ARTIKEL 5- Compilieren auf anderen Plattformen/Compilern ( Teil II )

von HypoThermia


Wenn du der Anleitung im ersten Teil dieses Artikels gefolgt bist, sollten die Q3Sourcen jetzt ordentlich auf der Virtual Machine laufen. Dieser Teil des Artikel erläutert, wie du den Code auf deiner Plattform zu Binaries compilierst.
Ich gehe davon aus, das du alle bisher nötigen Änderungen am Code in einem Extraverzeichnis unterhalb von \Quake3\source vorgenommen hast.

1. Die Binaries compilieren
Die Möglichkeit, Bytecode für die QVM zu compilieren, ist die minimale Voraussetzung, um vernünftig arbeiten zu können. Um dir die Arbeit aber um einiges zu erleichtern, solltest du es dir ermöglichen, Binaries aus den Q3Sourcen zu compilieren.
Wie du das anstellst ist stark Compiler- und Plattformabhängig. Für Kommandozeilen Tools solltest du Makefiles bereitstellen, die die Beziehung zwischen den Q3Sourcen und den compilierten Binaries definieren. Falls deine Plattform eine graphische Entwicklungsumgebung bietet, wäre eine Projektdatei wünschenswert.


1.1 Projektdateien
Die Projektdatei sollte sich als einzige ausserhalb deines Compilerverzeichnisses befinden. Genau wie das Microsoft Visual C++ Projekt sollte sich auch deines in \Quake3\source befinden. Wenn es ein Makefile ist, sollte sein Name auch darauf hinweisen (z.B. makefile.gcc.linux).
Der Aufwand, den du in das Verständnis der Header investiert hast, sollte sich nun auszahlen. Falls du irgendwelche Änderungen an den Sourcen vornehmen musstest, sollten sie keine Fehlermeldungen erzeugen. Versuche wieder, bereits definierte Konstanten (deiner Plattform) in den Q3Sourcen zu nutzen, um den Code zum laufen zu bringen.
Du wirst es nicht vermeiden können, dich intensiv mit den Tools deines Compilers vertraut zu machen.
Beachte, dass einige der Dateien aus source\game auch beim Erstellen von cgame und ui eingebunden werden.
Es wäre ausserdem von Vorteil, auch jede von deinem Compiler erzeugte Zwischendatei in deinem Compilerordner zu haben.
Beispiel:
Die Borland Tools nutzen eine Integrierte Entwicklungsumgebung (IDE). Jedes der drei Module muss zu einer Win32 DLL compiliert werden.
Microsoft nutzt WIN32 um Compilierung für Win32 anzuzeigen. Die Q3Sourcen-Header reagieren darauf, also muss es definiert werden.
Die Borland IDE erlaubt es, solche Variablen als Teil des Projektes zu definieren, ohne Änderungen an den Q3Sourcen vornehmen zu müssen. Das entspricht in etwa den -Dxxxx, die du an lcc.exe übergeben hast.
Die Borland Compiler setzen einen Unterstrich vor exportierte Funktionen. Das verträgt sich aber nicht mit Microsofts Namensgebung, also müssen alle exportierten Definitionen in den *.def Dateien folgendermassen verändert werden:

 

[EXPORTS]
vmMain=_vmMain
dllEntry=_dllEntry

 

Noch einmal, diese Dateien (für jedes Binary eine) gehören in den compilerspezifischen Ordner.


1.2 C_ONLY im Projekt verwenden
Es wird höchstwahrscheinlich nötig sein, folgende Definition für jedes Binary in das Projekt einzufügen:

#define C_ONLY

id hat einige Intel-optimierte Assemblerroutinen für die Performancekritischen Bereiche geschrieben. Falls sich diese nicht compilieren lassen, definiere diese Konstante.

1.3 Konstanten definieren
Wenn sich die Q3Sourcen bereits mit einem anderen Compiler auf deiner Plattform compilieren lassen, ist es sicher hilfreich, einige oder alle der von diesem Compiler benutzten Konstanten zu definieren. Deine Änderungen können dann darauf aufbauen.

1.4 system calls in die quake3.exe handhaben
WICHTIG: Eine entscheidende Compiler Option der Wintel Version ist "Datenstrukturen werden an 4-Byte Grenzen ausgerichtet". Ohne diese Option wird sich der Code unregelmässig und unvorhergesehen verhalten.
Die drei von dir erstellten Binaries entsprechen den drei Bytecode Dateien für die QVM. Auf der Wintel Plattform heissen sie qagamex86.dll, cgamex86.dll, and uix86.dll.
Für jede von ihnen muss eine Datei namens xx_syscalls.c eingebunden sein. Sie ermöglicht es dem Binary, auf stark optimierten Code innerhalb der quake3.exe zuzugreifen. Stelle sicher, dass QDECL definiert ist, damit die Schnittstelle zwischen dem Binary und der exe besteht. Die Definition von QDECL befindet sich in game\q_shared.h.
Falls das schief geht, wird das Spiel abstürzen.
Die Funktion dllEntry() nimmt die callback-Funktion in der quake.exe entgegen. Verwechsle sie nicht mit der Namensverwandten Funktion aus den Win32 DLLs, DllEntryPoint().

1.5 Versichere dich, dass Quake3 deine Binaries nutzen kann
Nur zwei Funktionen müssen für quake3.exe Sichtbar sein: vmMain() und dllEntry(). Prüfe, ob sie so von den Binaries exportiert werden, dass Quake3 sie sehen kann.


1.6 Nur zu Entwicklungszwecken
Erstelle den Server, Client und UI-Code nur zum Debuggen und testen. Veröffentlichen solltest du nur .qvm's.


2. Modifikationen
Du wirst bemerken, dass die Q3Sourcen beim Compilieren einige Warnung produzieren. Schau dir an, ob sie unzusammenhängend sind. Normalerweise sollten sie das.
Da sich die Q3Sourcen bereits zu Bytecode compilieren liessen, sollten keine grossen Probleme auftauchen.
Achte bei notwendigen Codeänderungen auf Portabilität.
Falls sich plattformspezifischer Code nicht vermeiden lässt, schreibe ihn in eine eigene Datei in dem Compilerverzeichnis.


3. Erwartete Fehler
Einige Compiler interpretieren den C Standard strikter als andere. Falls möglich solltest du feststellen, ob sich dein Compiler in der erwarteten Weise verhält.


3.1 Einige Warnungen in den Q3Sourcen
id Software hat einige Programmierstile verwendet, die Warnungen auslösen können. Manche können ignoriert werden, andere solltest du überprüfen.
Fehler wie "Variable wird in Funktion xyz deklariert, aber nicht benutzt" kannst du ruhig ignorieren. Andererseits solltest du Fehlern wie "bei Konvertierung von x nach y können Informationen verloren gehen" auf den Zahn fühlen.
Eine weitere Warnung, die auftauchen könnte ist "mögliche fehlerhafte Zuweisung". Sie wird z.B. von folgendem Code erzeugt:

for( j = 0; control = controls[j]; j++ )

Irgendwo im Feld controls[] ist ein Element 0, das wird durch die vorherige Nutzung des Feldes garantiert. Die Zuweisung fungiert gleichzeitig als Schleifenbedingung. Sobald das ersten Element den Wert 0 hat, wird die Schleife abgebrochen. Man könnte es auch so schreiben:

for( j = 0; (control = controls[j])==0; j++ )

Du kannst auch diese Warnung ignorieren.


3.2 Prüfe deine Implementierung der math Bibliothek
Abhängig davon, wie deine math Bibliothek implementiert ist, wirst du sqrt:DOMAIN Fehler erhalten, wenn du cgame compilierst.
Das resultiert scheinbar aus einem Fehler in der Quake3.exe (v1.15c), der bewirkt, dass in den Q3Sourcen ein zu {0,0,0} senkrechter Vektor gesucht wird.
Die Behebung des Fehlers ist compilerabhängig. Du musst einen Weg finden, ihn abzufangen und zu ignorieren: sieh dir die Hilfedateien deines Compilers und seiner math Bibliothek an. Du solltest deine Lösung in den compilerabhängigen Dateien platzieren.
Der Bug offenbart sich beim Abspielen der demo001.dm3 mit "timedemo 1".
Beispiel: Mit der Borland math Implementierung entsteht dieser Fehler. Die Lösung ist einfach, diese Datei beim Erstellen von cgame mit "include" einzubinden.

 

  // borland_hack.c
  #include 
  int _RTLENTRY _EXPFUNC _matherr(struct exception* e) 
  {
  e->retval=1.0;
  return 1;
  }
        

 

4. Die Binaries testen
Verschiebe die erzeugten Binaries in den Ordner der quake3.exe und starte quake3.
Um sicherzustellen das die Binaries getestet werden, setze sv_pure auf 0.
Besonders wichtig ist das Testen der demo001.dm3 mit "timedemo 1". Wenn du einen sqrt:DOMAIN Fehler bekommst, musst du diesen Fehler deiner math Bibliothek abfangen.


5. Veröffentlichen deines Projektes
Wenn du dein Werk zur Veröffentlichung vorbereitest, solltest du versuchen die Änderungen an den Q3Sourcen so gering wie möglich zu halten. Es wird sicher nicht nötig sein das Schlachtermesser auszupacken und Unmengen an Änderungen über die Sourcen zu verteilen.


5.1 Nutze ein Extraverzeichnis für deine Arbeit
Die Organisation der Änderungen wird erheblich leichter, wenn du dir unter quake3\source ein eigenes Verzeichnis anlegst, um die zum Erstellen nötigen Dateien zu speichern.
Dadurch wird es erstens für mehrere Compiler möglich, mit der selben Sourcenversion zu arbeiten. Und zweitens bleiben die Verzeichnisse \game, \cgame und \ui sauber.
Die einzige Ausnahme bildet die Projektdatei, die du für Binaries auf deiner Plattform erstellt hast. Diese gehört in quake3\source und sollte einen sinnvollen, beschreibenden Namen haben.


5.2 Dokumentiere deine Änderungen
Es ist besser, die verwendeten Änderungen zu dokumentieren, und on anderen anwenden zu lassen, als veränderte Sourcen zu veröffentlichen. Auf diese Weise können sie viel sauberer in bestehende Projekte eingearbeitet werden.
Beispiel:
Öffne die Headerdatei game\q_shared.h, gehe zu Zeile 424, da sollte stehen:

float Q_crandom(int* seed);
  

füge folgendes direkt dahinter ein:

  #ifdef __BORLANDC__
  #ifdef random
  #undef random
  #endif
  #endif
  

Du solltest auch in Erwägung ziehen, DIFF Dateien zu Veröffentlichen.


5.3 Stelle deine Arbeit ins Internet
Dadurch können auch andere von deiner harten Arbeit profitieren. Melde dich bei Portalen, damit die gesamte Community von deiner Arbeit profitieren kann.


6. Glückwunsch !
Du hast die Q3Sourcen erfolgreich portiert.
Jetzt kannst du dich in die Sourcen graben, und deinen Mod entwickeln. Den Mod, auf den das Netz wartet !

<< zurück/back >>