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

Bekanntes Mitglied
Okay, nach näherer Analyse lag es gar nicht am 32 Bit wchar sondern an einer C++ Problematik (die seltsamerweise bei 16 Bit wchars nicht auftrat).

Ich habe eine Klasse Control, die enthält:

void SetText(const String*);
virtual void SetText(const String&) {};

Abgeleitet davon:

Klasse Button:

void SetText(const String& string);

Nun habe ich im Python->C++ Interface (schon auf C++ Seite) den Code:

control->SetText(string);

Hierbei ist string ein lokaler Pointer.

Effekt:

VOR control->SetText(string); ist string ein korrekter wstring mit 32 Bit wchars
IN SetText in der Button-Klasse (direkt erste Zeiile der Methode) ist der string broken.
NACH SetText in der aufrufenden Methode ist der String wieder korrekt.

Wenn ich nun die Zeile durch

control->Settext(*string);

ersetze, dann geht der String nicht kaputt. Das Display ist zwar immer noch kaputt (SINGL statt SINGLEPLAYER bei manchen Strings auch falsche Zeichen nach 5-6 Zeichen etc.). Aber vermute es gibt weiter hinten in der Aufrufreihenfolge weitere analoge Probleme.

Hat jemand eine Idee ?

Falls nicht bleibt

a) Alles auf 16 Bit Wchars umschreiben (sehr aufwendig)
b) Alle pointer-Übergaben der Strings durch Referenzen ersetzen (wie oben angedeutet).

Seltsam immer noch dass es nur bei 32 Bit wchars passiert... und nur beim 68k-Compile...

Okay, was auch schief geht ist hier

void Button::SetText(const String& string)
{
outputRawWString2(string);
outputStringAddress2(string,"After SetText");
Text = string;
fprintf(stdout,"Now!aaaa!!\n");
outputRawWString2(Text); // A
outputRawWString2(string); // B
...

Der mit A gekennzeichnete Text ist kaputt, der mit B gekenntzeichnete Text ist in Ordnung. Irgendwie wird hier nicht richtig kopiert.

Text ist in der Klasse als

String Text;

definiert, wobei String ein typedef auf wcstring ist.

Wenn ich in dem letzten Beispiel statt "Text = string;"

ein

"
Text.clear();
Text.reserve(string.size());
for (size_t i = 0; i < string.size(); ++i) {
Text.push_back(string); // Manually copy each character
}"

mache, dann wird der String korrekt kopiert (display ist immer noch falsch, aber ich vermute bis zum Display gibt es weitere Assignments, und es scheint dass das Assignment die Probleme auslöst).

Also doch Compilerbug ? ^^




Danke schonmal!

Gruß,
Steffen
 
Zuletzt bearbeitet:

MrFlay

Kult Mitglied
Hallo, mir ist das alles etwas wirr. Teilweise widersprichst Du dir auch selbst. Wir hatten ja schon geklärt, dass es kein Compilerbug ist. Die Umstellung von 32bit auf 16bit wchar_t brachte ja bereits eine sichtbare Verbesserung. Vielleicht solltest Du das Problem Schritt für Schritt angehen. Du musst darauf achten, dass Systemfunktionen entweder auf 16bit oder auf 32bit laufen, und dass sauber voneinander trennen. Versuche mal nur einen String zu bauen, der so ist, dass er überall korrekt angezeigt und bearbeitet wird. Mit Referenzen muss man aufpassen. Der Vorteil ist, dass man nur einmal Speicher braucht. Der Nachteil ist, dass man diesen bis zum Ende des Programmes bereitstellen muss. Reiche ich irgendwo eine Referenz weiter muss geklärt werden wer den Speicher aufräumt. Wenn hinterher irgendwo ein "delete" kommt, dann bemerkt die Referenz-Kopie das nicht. Es kracht dann sobald man diese Referenz nochmal nutzt. Verwende am besten einen Debugger bzw. ein Tool (GDB, MungWall, Enforcer) und vollziehe genau nach, warum und wo es kracht.
 

MagicSN

Bekanntes Mitglied
Also, vielleicht habe ich am Anfang auch aus dem beobachteten Verhalten teils falsche Schlüsse gezogen. Das was nun "definitiv" der Fall ist ist folgendes. Was Compilerbug angeht, das was ich als erstes als Compilerbug vermutete war ein Irrtum, aber es scheint möglicherweise ein ANDERER Compilerbug vorhanden zu sein (da es sich anders verhält als wenn man auf PPC compiliert). Der scheinbare Widerspruch ergibt sich daraus, dass einiges was ich geschrieben habe sich auf den 16 Bit Compile anders sich auf den 32 bit Compile bezieht, und das wohl verwirrend ist.

Auch habe ich in den ersten Posts (wo es noch mehr Probleme gab, etwa Crashes und falsche Positionierung am Bildschirm) noch eine andere Version des Compilers für 68k verwendet. Mit der älteren Version des 68k-Compilers sind nun einige dieser Probleme weg (außer die noch beschriebenen), sprich wir hatten es zumindest teilweise DEFINITIV mit Compilerbug-Problematiken zu tun.

Ich habe zwei Compiles, im einen habe ich mit 16 Bit Compiliert, im anderen mit 32 Bit (also jeweils komplett):

16 Bit:

- Mit neuem Compiler kommen die Texte "richtig", aber die Formatanweisungen wereden (logischerweise, weil der Code hier weiterhin 32 Bit Logik verwendet) falsch interpretiert und kommen als "Text" rüber

32 Bit:

- Hier verhält es sich so wie in meinem letzten Post beschrieben. Das passiert NUR wenn 68k Compile. Im OS4 Compile oder WarpOS Compile passiert das nicht.

Insbesondere dieses Problem

"
Effekt:

VOR control->SetText(string); ist string ein korrekter wstring mit 32 Bit wchars
IN SetText in der Button-Klasse (direkt erste Zeiile der Methode) ist der string broken.
NACH SetText in der aufrufenden Methode ist der String wieder korrekt.
"

Wie soll man das außer mit "Compilerbug" erklären ?

Meine Vermutung ist diese Sache mit dem
"
Ich habe eine Klasse Control, die enthält:

void SetText(const String*);
virtual void SetText(const String&) {};

Abgeleitet davon:

Klasse Button:

void SetText(const String& string);"

dass da also in der Button-Klasse kein SetText mit Pointer vorhanden ist der 68k-Compiler anders handhabt als der PPC-Compiler. Aber es geht ja nicht nur da drum, selbst wenn ich die Aufrufe mit Pointer durch welche mit *string (dereferenziert) ersetze, gibt es beim OUTPUT immer noch Probleme.

Im Prinzip muss ich nun entscheiden, ob ich versuche die 32 Bit Variante zu "reparieren" oder den Code so umschreibe, dass er statt 32 Bit 16 Bit (da müsste man dann vieles an wchar Funktionen von Hand neu schreiben schätze ich) einsetzt.

Gruß,
Steffen
 

MrFlay

Kult Mitglied
Welchen Compiler verwendest Du genau und auf welchem System compilierst Du für 68k?
 

MrFlay

Kult Mitglied
VOR control->SetText(string); ist string ein korrekter wstring mit 32 Bit wchars
IN SetText in der Button-Klasse (direkt erste Zeiile der Methode) ist der string broken.
NACH SetText in der aufrufenden Methode ist der String wieder korrekt.

Was bedeutet "string broken" genau? Woran machst Du das fest?
Auch dass kann damit zusammenhängen wo und wie Du den Speicher verwaltet hast. Gleiche Library, wenn nicht, werden beide mit dem Flag "-fshort-wchar" kompiliert? Gib Dir an beiden Stellen mal "sizeof(wchar_t)" aus um dies zu prüfen.
 

MrFlay

Kult Mitglied
Nachtrag: Du sagst "gibt es beim OUTPUT immer noch Probleme". Wie gibst Du es aus? Ist die Ausgabefunktion eine ABI-Funktion (16Bit oder 32Bit)?
 

MagicSN

Bekanntes Mitglied
Auf 68k habe ich drei Compiler, alle "Bebbo" Compiler.

Ein "älterer" (genaue Versionsnummer müsste ich raussuchen), der recht zuverlässig tut (GemRB-spezifisch gibts da zumindest keine Crashes mehr dann, auch der Sin-Compile funktioniert mit dem "fast" - ein Texturemapper baut noch murx bei 68k bei dem)
Den aktuellsten 6.50b Bebbo Compiler - führt dazu, wenn man GemRB compiled - ohne jegliche Änderung des Codes - dass es alle möglichen Crashes gibt, daher bin ich da wieder zu dem älteren Compiler zurückgegangen
gcc11 (oder wars 13 ? Bin grad nicht zu hause) - crasht direkt beim Starten weg, habs mir nun nicht näher angeschaut, nachdem der "ältere" 6.50b wesentlich stabiler läuft (was GemRB angeht)

Wie ich das mit dem "String broken" festmache - dass 5 Zeichen oder so korrekt im Memory stehen und danach nur Datenmüll. Daran mache ich das fest. Und wie gesagt, Daten sind in Ordnung vor Paramterübergabe. Dann in der Aufgerufenen Funktion in dem Parameter kaputt. Und dann nach Verlassen der Funktion in der übergebenen Variable wieder in Ordnung. Und wenn man statt per Pointer per Referenz übergibt, sind die Daten auch in der Funktion in Ordnung (die Ausgabe auf der GUI ist immer noch broken, aber ich glaube da gibts einfach noch mindestens eine weitere Stelle wo etwas wie bei dem erwähnten Funktionsaufruf passiert).

Beim Output da meine ich das Darstellen in der GUI. Das läuft über den Font-Renderer von GemRB, der intern ne Menge wchar Zeugs macht.

Und wie gesagt ich hab da nun zwei Compiles

a) 16 Bit

Text kommt richtig, kein Datenmüll. Aber eben weil das wchar-Handling nicht richtig ist (der verwendet ja intern wchar 32 Bit Befehle) landen dann Formatanweisungen als Text auf dem Bildschirm und so was. Sprich falls ich diesen Pfad weiterverfolge müsste ich alle wchar Funktionen auf "eigene" Funktionen die mit wchar 16 Bit klarkommen umschreiben

b) 32 Bit

Hier tritt wie gesagt an verschiedenen Stellen bei Parameterübergabe der "Datenmülleffekt" auf

Gruß,
Steffen
 
Oben