GoldSrc debuggen

Author: TheTinySteini

Tja, es kommt spät, aber immerhin: Ein Tutorial über das Debuggen von Half-Life. Ich denke mal, es sollte sich mittlerweile rumgesprochen haben, dass man serverseitig mit ALERT() Debugmeldungen in der Konsole erzeugen kann. Vielleicht nicht mehr ganz so bekannt sind die Möglichkeiten von ALERT. Wichtig sind zum Beispiel die Werte at_console und at_aiconsole für den ersten Parameter. Ersterer wird ziemlich häufig benutzt, letzterer vor allem im AI-Code (wie der Name schon sagt). Durch die beiden verschiedenen Werte kann man sich ganz einfach verschiedene Debug-Levels zusammenbasteln. Denn während die at_console-Meldungen schon angezeigt werden, wenn man HL mit -dev startet oder developer 1 in der Konsole eingibt, werden die at_aiconsole erst dann ausgegeben, wenn man developer 2 eingibt. Valve hat davon schon ziemlichen Gebrauch gemacht. Startet mal ne Map mit ein paar Monstern und gebt dann developer 2 ein - da erfährt man so ziemlich alles, was die Monster gerade anstellen (vor allem aber, woran sie gerade gescheitert sind).

Clientseitig gibt es gEngfuncs.Con_Printf bzw. gEngfuncs.Con_DPrintf, die beide ähnlich wie ALERT( at_console, … ) funktionieren. Ihr solltet euch am besten in der client.dll ein Makro basteln, mit dem ihr ALERT auf gEngfuncs.Con_Printf mappt, denn ALERT ist doch deutlich kürzer zu tippen =).

Die weiteren Parameter von Con_Printf bzw. ALERT sollten wir auch nochmal kurz ansprechen. Zuerst einmal übergebt ihr natürlich einen Text. Also etwa so:

ALERT( at_console, "--- Debug Checkpoint\n" );
gEngfuncs.Con_Printf( "--- Debug Checkpoint\n" );

Beachtet unbedingt das \n am Ende, sonst wird die nächste Meldung in der gleichen Zeile direkt angehängt - und das wird dann ziemlich unübersichtlich. Viel nützlicher sind allerdings noch diese Sonderzeichen:

%s - String-Platzhalter %d - Integer-Platzhalter %f - Float-Platzhalter Es gibt noch mehr (etwa %c für Chars), aber das waren die wichtigsten. Statt %d kann man zwar auch %i schreiben, aber %i sollte nicht mehr verwendet werden. So, wie setzt man diese Platzhalter nun ein? Ganz einfach:

int iHealth = 56;
float flSpeed = 95.564;
szName = "Enemy";
ALERT( at_console, "Name: %s, Health: %d, Speed: %.2f\n", szName, iHealth, flSpeed );

Wie ihr seht, muss man bloß die Platzhalter an die entsprechenden Stellen im Text einsetzen und dann die Variablen in der richtigen Reihenfolge hinter den String schreiben.

Euch ist aufgefallen, dass ich statt %f %.2f geschrieben hab? Damit kann man die Anzeigegenauigkeit einschränken. Denn in HL enthalten floats oft sehr krumme Zahlen, sowas wie 1.93568234. Soviel Genauigkeit braucht man aber bei der Anzeige meist nicht, es ist im Gegenteil oft störend. Deswegen kann man mit dem Punkt und der Zahl angeben, wieviele Nachkommastellen angezeigt werden sollen. %.2f würde also 1.93 anzeigen, %.4f 1.9356. Nice to know =)

Gut, ihr wisst jetzt, wie man sich Debug-Messages ausgeben lassen kann. Zum Beispiel kann man ganz einfach überprüfen, ob an bestimmten Stellen tatsächlich die Zahlen ankommen, die man erwartet. Oder ob man mit dem richtigen Spielerpointer arbeitet. Es gibt viele Möglichkeiten, aber leider ein Problem: Was ist, wenn HL abstürzt, in den Launcher oder auf den Desktop zurückgeht? Dann kann man die Messages ja nicht lesen, weil sie, kaum ausgegeben, auch schon wieder verschwunden sind. Für solche Fälle ist es sinnvoll, HL mit dem Parameter -condebug zu starten. Ihr findet dann in eurem Mod-Verzeichnis eine Datei namens qconsole.log (hehe, wofür das Q wohl steht? ;-). Diese Datei enthält alle Konsolenmeldungen des letzten HL-Starts im Textformat. Wenn's euch also zu schnell ging oder die Messages gar nicht erst sichtbar wurden, dann könnt ihr sie hier in Ruhe nachlesen. In dem Zusammenhang noch eine nützliche Funktion, die vielleicht nicht alle kennen: Man kann in der HL-Konsole mit Shift-BildAuf und Shift-BildAb durch die Meldungen scrollen, wenn allerdings auch nur in gewissen Grenzen (etwa 2 Bildschirmseiten).

Kommen wir aber nun zum „richtigen“ Debuggen mit dem MSVC++ Debugger. Um die damit verbundenen Möglichkeiten zu nutzen, solltet ihr allerdings schonmal mit dem Debugger gearbeitet haben, eine genaue Erklärung würde dieses Tutorial vermutlich mehrere 100 Seiten lang machen (mal davon abgesehen, dass ich selber nur die wichtigsten Sachen kann ;-). Ich beschränke mich hier darauf, zu erklären, wie man den Debugger überhaupt für HL konfiguriert (und andersrum).

Zuerst müsst ihr den Arbeitsbereich laden, den ihr debuggen wollt. Stellt nun die aktive Konfiguration auf „Debug“ - dazu geht ihr auf „Erstellen→Aktive Konfiguration festlegen…“ und wählt dann im Fenster die Konfiguration, die auf „Win32 Debug“ endet. Klickt auf OK, und drückt dann ALT-F7. Es öffnen sich jetzt die Projekt-Eigenschaften. Klickt im rechten Teil auf den Kartenreiter „Debug“. Nun müsst ihr ein paar Eintragungen tätigen. Unter „Ausführbares Programm für Debug-Sitzung“ wählt ihr eure hl.exe, unter „Arbeitsverzeichnis“ tragt ihr euer HL-Verzeichnis ein (das, wo die hl.exe drin ist). Bei „Programmargumente“ könnt ihr eure Startparameter angeben, also etwa “-game euermod -dev -toconsole -condebug“. Wählt jetzt unter „Kategorie“ den Punkt „Zusätzliche DLLs“. Nun klickt ihr doppelt auf den blauen Balken, so dass ein Textfenster und daneben ein Button mit drei Punkten erscheint. Klickt auf den Button und wählt die dll aus, die ihr debuggen möchtet. So, nun nur noch OK drücken und fertig.

Wenn's mit dem Debuggen losgehen soll, braucht ihr nun nur noch F5 zu drücken, MSVC++ kompiliert dann die DLL und startet danach Half-Life. Ihr solltet HL allerdings in den Optionen noch auf Window-Mode („Run in Window“) stellen, die Maus-Sperre deaktivieren („Use Mouse“ sollte nicht angekreuzt sein), und eine relativ kleine Auflösung wählen. Oft reicht schon 320*240. Denn dummerweise bleibt das HL-Window meist im Vordergrund, wenn der Debugger anspringt. Und ihr habt kaum eine Chance das Fenster zu verschieben, ihr müsst also durch die niedrige Auflösung dafür sorgen, dass ihr möglichst viel Fläche für den Debugger zur Verfügung habt.

Falls HL crasht und ihr irgendwo mitten in Assembler-Code landet, dann versucht, ob ihr mit der Aufrufliste (ALT-7) feststellen könnt, welche eurer Funktionen zuletzt aufgerufen wurde. Ihr könnt dann per Doppelklick dorthinwechseln und z.B. einen Breakpoint setzen.

Aber nun kommen wir schon in die richtig umfangreichen Gefilde, da hilft eigentlich sowieso nur noch eins: Ausprobieren. Und wenn ihr schon in die verzweifelte Lage kommt, HL mit MSVC++ debuggen zu müssen, dann wird euch eh nicht mehr sehr viel schiefgehen können =)

Ok, ich hoffe es hat euch geholfen, Credits gehen an Adrian „Pink“ Finol, der auf Wavelength die Grundlagen für den letzten Teil geschrieben hat.

Anmerkung

Dieses Tutorial stammt aus der ehemaligen Sammlung des resourcecode.de und konnte dank der freundlichen Zustimmung des Autors in das thewall-Wiki übertragen werden.

Die Verwendung aller Dokumente einschließlich der Abbildungen ausschließlich zu nichtkommerziellen Zwecken. Verbreitung des Dokuments auf Speichermedien, (insbesondere auf CD-ROMs als Beilage zu Zeitschriften und Magazinen oder sog. "Mission-Packs" etc.) ist untersagt.
 
goldsrc/coding/debugging.txt · Zuletzt geändert: 2010/08/05 16:59 von Adrian_Broher