Aktuelles
AmigaPortal.de

Wir würden uns freuen, dich als neues Mitglied begrüßen zu können. Melde dich noch heute an und werde Teil einer freundlichen Community deren gemeinsames Hobby der "AMIGA" ist. Hier kannst du dich in einer gemütlichen Atmosphäre mit anderen Usern zu vielen interessanten Themen rege austauschen oder andere an deinen Erfahrungen teilhaben lassen. Wir wünschen dir viel Spaß hier auf AmigaPortal.de

Baldur's Gate (GemRB) 68k - Info Update

MagicSN

Kult Mitglied
Hallo!

Dank eines Spenders, der die Entwicklung von Python 68k bezahlt, habe ich inzwischen eine frühe Alpha-Version von Python 2.7 für 68k (ist noch keine volle Version - nur was für GemRB nötig ist - und nahezu ungetestet).

GemRB kommt inzwischen bis ins Hauptmenu, und auch die Intros werden schon abgespielt. Fühlt sich soweit alles flott an (allerdings hab ichs bisher auch nur unter UAE laufen lassen).

Nun der Haken - alle Buttontexte sind vollkommen kaputt, und man kommt daher auch nicht ins Spiel rein (kann aber bissl was im Menu klicken), vermutlich wegen der Buttontexte (da prüft irgendwas auf den Text "OK" oder so wass in der Art).

Das Problem ist, dass der 68k gcc scheinbar eine kaputte Implementierung von wchar (Wide Chars) hat. Der andere gcc den ich habe hat noch katastrophalere Ergebnisse.

Ich bin derzeit dabei GemRB 0.8.7 von Wide Char auf char * umzuschreiben, um dieses Problem zu lösen. Ich bin zuversichtlich, dass ich das hinkriege, aber es ist dennoch ein größerer Aufwand, dieses Umschreiben.

68k ist halt einfach nicht so weit entwickelt (aus Entwickler-Sicht, also was Libraries und Entwicklertools angeht) wie etwa AmigaOS4 oder WarpOS.

Aber es ist auf jeden Fall ein Schritt voran. Das Python-Problem scheint soweit gelöst zu sein (obs noch Bugs gibt wird man noch sehen, nachdem das wchar Problem gelöst ist, dass man also das Spiel ordentlich bedienen kann um richtig testen zu können.

Es ist aber in jedem Fall klar - finanziell rechnet sich das eher nicht, der Aufwand ist einfach gigantisch aber ich mach weiter !!!
Und hoffe, es wird dann ein paar Verkäufe geben ;-)

Gruß,
Steffen
 

MrFlay

Kult Mitglied
Klingt interessant! Was ist denn das Ziel dieses Projektes? Es unter Amiga 68k lauffähig zu bekommen? Was währen die dann Systemanforderungen?
Der 68k gcc ist da nicht wirklich kaputt, wenn Du den Unterschied zwischen gcc und VS meinst (gcc wchar_t 32bit und VS wchar_t 16bit). Im gcc kannst Du dieses Verhalten auch erzwingen mir "-fshort-wchar", das erleichtert Dir vielleicht die Arbeit etwas. Vielleicht wär es aber besser gleich char16_t zu verwenden und eigene Hilfsfunktionen zu implementieren, weil die Surrorgatepaare ja auch Probleme bereiten können.
 

MagicSN

Kult Mitglied
Ja, es soll genau so wie die AmigaOS4 und WarpOS Versionen laufen. Wird dann ebenso bei Alinea kaufbar sein (19,95 EUR).

Was die Mindest-Systemanforderungen angeht, kann ich derzeit natürlich nur die Kristallkugel bemühen sozusagen ^^ Aber ich tippe mal dass es unter PiStorm und Pi5+AmiKit beiden läuft. So wie die Videosequenzen liefen und die Menubedienung, würde ich mal RATEN dass auch ein Pi3 ausreichen sollte. Mit etwas Glück auch ein Vampire. Aber das ist nun alles nur geraten, weil ins eigentliche Spiel komme ich noch nicht rein (nur so GUI zum Charerstellen und so bisher).

Dass es auf etwas "niedrigerem" als einem Vampire läuft, halte ich für unwahrscheinlich bis unmöglich.

Sobald ich genaueres weiß, werde ich da natürlich Bescheid geben.

Danke für Deine Erläuterungen zu wchar. Das mit dem wchar 32 Bit klingt schon ziemlich nach dem Verhalten das ich beobachtet habe. Das werde ich ausprobieren, vielen Dank für die Hinweise, wenn das funktioniert könnte mir das eine Menge Arbeit sparen! Interessant ist aber, dass unter OS4 und WarpOS (oder bei Compilern dafür) der gcc da scheinbar schon per Default 16 Bit wchar zu nehmen scheint.
 
Zuletzt bearbeitet:

MagicSN

Kult Mitglied
Ok das hat geholfen. Aber irgendwas ist noch bei den Positionierungen kaputt (aber die Texte werden schonmal richtig geladen jetzt). Und bei einem Dialog schmeißt er dann ne Assertion (aber habe zumindest die genaue Stelle, wo es schief läuft).

Vielen Dank, Du hast sehr weitergeholfen!
 

MagicSN

Kult Mitglied
Hab momentan mal die Assertions rausgemacht, dann scheint die GUI weitgehend zu tun. Es gibt aber wohl weitere wchar Probleme. Hier ist ein wenig Code mit debug output:

for (size_t i = 0; i < string->length(); i++) {
wchar_t ch = string->at(i);
fprintf(stderr, " char[%zu] = '%lc' (0x%x)\n", i, ch, ch);
}
fprintf(stderr,"%d\n",L'.');
free(str);

if (dirs == false) {

size_t pos = string->find_last_of(L'.');

Der "string" oben ist "Barde.chr", man sieht auch durch den printf-loop dass ein Zeichen 46 (0x2e), also der . ist. Der Output von L'.' ist ebenfalls 46. Dennoch liefert string->find_last_of(L'.') als Rückgabewert -1. Also doch ein Problem in der wchar Implementierung ? (An der Stelle hier kann ichs natürlich durch was anderes ersetzen, aber kann natürlich an verschiedenen Stellen Probleme geben - habe tatsächlich noch ne weitere Stelle wo etwas ähnliches schief läuft.

Hast Du da ne Idee ? (Und ja, compiliere nun mit -fshort-wchar.

Verbleibende Probleme derzeit:

- Einige "Listen" (etwa beim Import) sind leer (das liegt an der Sache wo ich das Codebeispiel geposted habe gerade)
- Eintippen vom Charakternamen tut nicht (scheint auch ein wchar-Problem zu sein, habs mir noch nicht genauer angeschaut)
- Positionierung des Texts in den Buttons ist "manchmal" falsch. Wenn man dann einen Button im Screen drückt korrigiert er die Positionierung (noch nicht näher debugged, dieses Phänomen)
- Crash wenn man dann tatsächlich das Spiel startet (glaube ich hatte bei der OS4 Version am Anfang was ähnliches, kann mich nicht mehr erinnern wie ich es gelöst habe, denke das hat nix mit wchar zu tun, muss ich näher debuggen, kümmere mich aber erstmal um diese wchar Sachen
- Wenn man bei der Charaktererschaffung was zusammenklickt, fehlen immer die \n's also der ganze Charbeschreibungstext ist so zusammengeschrieben ohne Zeilenenden (könnte was ähnliches wie das mit dem L'.' sein evtl muss ich mir aber noch näher ansehen.

Gruß,
Steffen
 

MagicSN

Kult Mitglied
Inzwischen:

- Import tut (aber beim letzten Item macht der Font Renderer den letzten Buchstaben weg ^^)
- Tatsächlich ins Spiel tut nun meistens. 3D Engine läuft (auf dem UAE etwa 30 fps, Speed Data zu realen Amigas kommen bald.
- Savegames tun noch nicht
- Crashes, Crashes, Crashes (ich glaub alle was zu tun mit dem wchar Schrott Außerdem wird SEHR viel Text schrottig/falsch/gar nicht angezeigt. Also noch viel zu tun. Werde es demnächst noch mit ner anderen Compilerversion versuchen ob da das wchar Geraffel besser tut, falls nicht muss ich wirklich jede Codestelle einzeln fixen. Scheinbar sind alle "find" und ähnliche Sachen von wstring kaputt. Siehe mein Beispiel oben. Hab noch ein zweites wo ich einen L"\n" suche der definitiv im String enthalten ist die Suchfunktion von wstring aber sagt "nein ist keiner drin". Broken. Mein Eindruck ist sobald in irgendner Form diese "L"-Notation involviert ist, gehts kaputt ^^ Und die wird SEEEEHR viel verwendet.

Hab nun etwa so was gemacht

#ifdef AMIGA
String s2;
FormatFPSString(s2,frames);
fps->Print( fpsRgn, s2, palette,
IE_FONT_ALIGN_LEFT | IE_FONT_ALIGN_MIDDLE | IE_FONT_SINGLE_LINE );
#else
fps->Print( fpsRgn, String(fpsstring), palette,
IE_FONT_ALIGN_LEFT | IE_FONT_ALIGN_MIDDLE | IE_FONT_SINGLE_LINE );
#endif

fpsstring ist dabei L"%.3f fps" und s2 ist so was

void FormatFPSString(String& out, double fps) {
char temp[64];
std::snprintf(temp, sizeof(temp), "%.3f fps", fps);

// Clear output string
out.clear();

// Convert char* to wchar_t manually
for (const char* p = temp; *p; ++p) {
out.push_back(static_cast<wchar_t>(*p));
}
}

Da bau ich also quasi den wstring von Hand zusammen aus nem char *, unter Vermeidung der Funktionen von wstring/wchar aus der Linkerlib. Weil die tun nicht.

Ist natürlich ne Höllenarbeit jede Stelle, wo irgendwie das L-zeugs verwendet wird, anzupassen...
 

MagicSN

Kult Mitglied
Auf einem pi4 lief es auch mit 30 fps aber nur beim disablen von Audio. Audio zerstört die fps rate auf dem pi4 komplett (1 fps). Aber denke das liegt dran dass mit dem compiler den ich derzeit nehmen muss bei GemRB 68k softfloat genommen werden muss und ohne fastmath. Hoffe sobald das mit nem stabileren gcc compilierbar ist das besser geht ;)
 

MrFlay

Kult Mitglied
Du schreibst immer wieder, dass der wchar_t im GCC kaputt ist, dass ist aber nicht der Fall.
Es ist nur eine Definitionsfrage ob wchar_t 16bit ist, oder eben 32bit.

Im obigen Beispiel verwendest Du einen "string", welchen Typ hat der denn und wie wird der Konstruktor aufgerufen?
In welchem Format sind denn Deine Quelltexte abgespeichert?
 

MrFlay

Kult Mitglied
Noch einen Nachtrag: Bei "free(str)" bekomme ich eine Gänsehaut. :eek:
std::string und auch std::wstring (nicht ANSI C, sondern C++), brauchen ja gar kein malloc und free.
Diese "Stringklasse" sieht mir irgendwie "selbstgeklöppelt" aus. Wenn die natürlich char statt wchar_t verarbeitet, dann kein ein L'.' ja gar nicht gehen.
Aber das kann ich alles nur schwer einschätzen mit so wenig Informationen darüber.
 

MagicSN

Kult Mitglied
Hallo!

String ist ein typedef auf wstring.

Und ich habs wie gesagt explizit getestet. Etwa so:

#define WHITESPACE_STRING L"\n\t\r "

if (std::wstring(WHITESPACE_STRING).find(L'\n') == std::wstring::npos) { fprintf(stderr, "L'\\n' is NOT in WHITESPACE_STRING!\n"); } else { fprintf(stderr, "L'\\n' IS in WHITESPACE_STRING.\n"); }

Es erfolgte die Ausgabe "IS NOT IN WHITESPACE_STRING".

Derselbe Code mit gcc für OS4 oder WarpOS oder MorphOS compiliert ergibt keine solchen Probleme. Das Problem tritt nur beim Compile für 68k auf.

Ich habe verschiedene solche Stellen in dem Code festgestellt. An einer Stelle wird etwa ein String (wstring) auf L"." getestet. Wenn man in einer Loop die einzelnen Charakter ausgibt, findet man raus dass "." definitiv enthalten ist. Die find Methode sagt aber nein.

Gruß,
Steffen
 

MrFlay

Kult Mitglied
Okay, jetzt ist der Fehler klar. Was du versuchst wird so nicht klappen. ;)
Konnte es jetzt auch unter Linux nachstellen (mit einem modernen Compiler).
Ich hoffe ich kann es erklären. Das Flag "-fshort-wchar" gilt natürlich nur für deinen eigenen Code.
Alles andere ist ja ohne dieses Flag compiliert.
Wenn Du jetzt die Standard Library verwendest (wstring, wprintf etc), dann ist die natürlich nocht mit 32Bit wchar_t erstellt worden.
Das hat also nichts damit zu tun, dass der Compiler irgendwie kaputt wäre.
 

MrFlay

Kult Mitglied
Um portabel zu sein nutze besser char16_t, char32_t mit u"foo.bar" bzw U"foo.bar". Falls das nicht geht, dann musst Du einen eigenen Wrapper schreiben für die Standard-Library-Funktionen.
 

MagicSN

Kult Mitglied
Das mit dem free ist übrigens der "ursprüngliche" char * der gefreed wird, nicht der String (die engine holt sich einen char * aus nem Datenfile raus, konvertiert den dann in ein wstring, und arbeitet dann mit dem wstring weiter).
 

MrFlay

Kult Mitglied
Das wird noch klappen, aber sobald du "find" nutzt aus der Standard-Library, dann kracht es, weil die eben nicht mit 16Bit compiliert wurde.
 

MagicSN

Kult Mitglied
Um portabel zu sein nutze besser char16_t, char32_t mit u"foo.bar" bzw U"foo.bar". Falls das nicht geht, dann musst Du einen eigenen Wrapper schreiben für die Standard-Library-Funktionen.
Ich würde gern vermeiden einen Code, der auf x verschiedenen Systemen läuft, und den ich vielleicht mal auf ne aktuellere Version updaten möchte massiv abzuändern, das ist mein Dilemma. Und auf OS4 MorphOS und WarpOS funktioniert das ja alles ohne Änderungen. Nur unter 68k macht es Probleme.

Wie gesagt - der Code ist nicht von mir. Das ist unmodifiziert der Code der GemRB Engine:

char * str = ConvertCharEncoding(name, core->SystemEncoding, core->TLKEncoding.encoding.c_str());
String* string = StringFromCString(str);
free(str);

if (dirs == false) {
size_t pos = string->find_last_of(L'.');
if (pos == String::npos || (type == DIRECTORY_CHR_SOUNDS && pos-- == 0)) {
delete string;
continue;
}
string->resize(pos);
}
strings.push_back(*string);
delete string;

Das StringFromCString ist dort so gemacht:

String* StringFromCString(const char* string)
{
// if multibyte is false this is basic expansion of cstring to wchar_t
// the only reason this is special, is because it allows characters 128-256.
return StringFromEncodedData((ieByte*)string, core->TLKEncoding);
}

und

static String* StringFromEncodedData(const ieByte* string, const EncodingStruct& encoded)
{
if (!string) return NULL;

bool convert = encoded.widechar || encoded.multibyte;
// assert that its something we know how to handle
// TODO: add support for other encodings?
assert(!convert || (encoded.widechar || encoded.encoding == "UTF-8"));

size_t len = strlen((char*)string);
String* dbString = new String();
dbString->reserve(len);
size_t dbLen = 0;
for(size_t i=0; i<len; ++i) {
ieWord currentChr = string;
// we are assuming that every multibyte encoding uses single bytes for chars 32 - 127
if(convert && (i+1 < len) && (currentChr >= 128 || currentChr < 32)) {
// this is a double byte char, or a multibyte sequence
ieWord ch = 0;
if (encoded.encoding == "UTF-8") {
size_t nb = 0;
if (currentChr >= 0xC0 && currentChr <= 0xDF) {
/* c0-df are first byte of two-byte sequences (5+6=11 bits) */
/* c0-c1 are noncanonical */
nb = 2;
} else if (currentChr >= 0xE0 && currentChr <= 0XEF) {
/* e0-ef are first byte of three-byte (4+6+6=16 bits) */
/* e0 80-9f are noncanonical */
nb = 3;
} else if (currentChr >= 0xF0 && currentChr <= 0XF7) {
/* f0-f7 are first byte of four-byte (3+6+6+6=21 bits) */
/* f0 80-8f are noncanonical */
nb = 4;
} else if (currentChr >= 0xF8 && currentChr <= 0XFB) {
/* f8-fb are first byte of five-byte (2+6+6+6+6=26 bits) */
/* f8 80-87 are noncanonical */
nb = 5;
} else if (currentChr >= 0xFC && currentChr <= 0XFD) {
/* fc-fd are first byte of six-byte (1+6+6+6+6+6=31 bits) */
/* fc 80-83 are noncanonical */
nb = 6;
} else {
Log(WARNING, "String", "Invalid UTF-8 character: %x", currentChr);
continue;
}

ch = currentChr & ((1 << (7 - nb)) - 1);
while (--nb)
ch <<= 6, ch |= string[++i] & 0x3f;
} else {
ch = (string[++i] << 8) + currentChr;
}
dbString->push_back(ch);
} else {
dbString->push_back(currentChr);
}
++dbLen;
}

// we dont always use everything we allocated.
// realloc in this case to avoid static anylizer warnings about "garbage values"
// since this realloc always truncates it *should* be quick
dbString->resize(dbLen);
return dbString;
}
 

MagicSN

Kult Mitglied
Das wird noch klappen, aber sobald du "find" nutzt aus der Standard-Library, dann kracht es, weil die eben nicht mit 16Bit compiliert wurde.
Ah. Ja, hatte auch schon so was vermutet, dass das das Problem sein könnte. Unter OS4 usw. verwende ich auch 32 Bit, das ist wohl der unterschied. Aber wenn ich dort nicht auf 16 Bit wechsle, ist in den Strings nur Blödsinn (immer nach dem fünften Charakter gehts schief, hatten wir ja oben diskutiert).
 

MrFlay

Kult Mitglied
Wenn Du aus "size_t pos = string->find_last_of(L'.');" ein size_t pos = string->find_last_of(u'.'); machst, dann wandelt er schon mal nicht in 32bit sondern korrekt in 16bit um.
 

MrFlay

Kult Mitglied
Geht es nur um die Funktion ConvertCharEncoding? Wenn ja, dann würde ich die durch eine korrigierte Version ersetzen.
 

MagicSN

Kult Mitglied
Nicht nur. Das Zeugs wird "all over the place" verwendet.

Ich vermute jetzt eigentlich dass eigentlich richtig wäre 32 Bit zu verwenden (so wirds etwa auch im OS4 Compile, und im WarpOS Compile genommen - und glaube auch im MorphOS Compile, letzterer nicht von mir). Also ohne die Option -fshort-wchar.

Das merkwürdige ist nur (daher hab ich ja dann -fshort-wchar genommen wie Du geschrieben hattest) dass unter 68k mit 32 Bit folgender Effekt auftrat:

Bei der Konvertierung von char * nach wstring (s.o.) waren dann die ersten 5 Zeichen z.B. 002e für den . und ab dem fünften Zeichen wurden es dann statt dessen irgendwelche riesigen Zahlen (Unicode ?) In der GUI hatte das den Effekt, dass immer nur die ersten 5 Zeichen zu sehen waren. Im OS4/WarpOS Compile passierte das nicht (und der Font/GUI-Code ist ohne jegliche Codeänderung, direkter Recompile).

Da stand dann z.B. statt "SINGLEPLAYER" im Menu nur noch "SINGL" da er dann bei den "Riesenzahlen" abbrach irgendwie.

Sprich das vernünftigste wäre vermutlich wenn man irgendwie das mit den 32 Bit wchars hinkriegt. Falls nicht wäre wohl das was Du in Deinem letzten Post geschrieben hast das vernünftigste.

Danke für alle Deine Tipss jedenfalls mal, hatte bisher noch nix mit wchar zu tun ^^

Gruß,
Steffen
 

MagicSN

Kult Mitglied
Ich denke ich hab’s nun kapiert der Key dürfte sein wieder auf 32 Bit wchar zurück und dann schauen warum das Wstring encoding bloedsinn macht Danke für Deine Hilfe!
 
Oben