Power64 bietet ein Monitor/Debugger der vollständig auf der Macintosh Seite der Emulation arbeitet. Somit ist es möglich den Zustand des C64 zu untersuchen und zu verändern, ohne auch nur ein Byte des C64 RAM zu benutzen. Der Debugger ist für C64 Programme vollkommen unsichtbar.
Um den Monitor Debugger zu starten, wählen Sie Ablage/Monitor/Debugger(Cmd-G). Es erscheint ein Textfester, in dem Sie Kommandos eingeben können und die Ausgaben erscheinen (eine Liste der unterstützten Kommandos folgt unten).
Normalerweise analysiert der Debugger den Zustand des C64. Durch das Kommando 'z' (siehe unten) ist es aber auch möglich ein Diskettenlaufwerk zu bearbeiten.
Um ein Kommando auszuführen geben Sie es in einer Zeile ein, und drücken Sie <Return>. Sie können auch alte Kommandos 'recyclen' indem Sie den Cursor wieder über das alte Kommando stellen und noch einmal <Return> drücken, indem Sie Cut & Paste verwenden oder indem Sie mit Ctrl-Cursor in der Liste der zuletzt genutzten Befehle blättern.
Um den Inhalt des RAM zu verändern ist es geschickt zunächst ein Kommando zu verwenden, das den alten Inhalt in angenehmer Form darstellt (etwa das 'm' Kommando) und dann diesen Output zu modifizieren. Wenn nun in der veränderten Zeile <Return> gedrückt wird, wird der neue Inhalt in den Speicher des C64 geschrieben.
Die Ausgabe aller Kommandos läßt sich mit der Leer- und der Return Taste steuern. Während mit der Leertaste wird genau eine weitere Zeile ausgegeben wird, wird nach einen Druck auf Return so lange Output generiert, bis wieder eine Taste gedrückt wird. Mit Escape wird ein Kommando abgebrochen. Die Kommandos 'm', 'k', 'n', 'b' und 'y' lassen sich mit den Cursortasten noch genauer kontrollieren. Cursor runter gibt, wie die Leertaste, die folgende Zeile aus. Cursor rauf gibt die Zeile, vor der aktuellen Zeile aus, und Cursor links/rechts liefert die aktuelle Zeile +/- 1 Byte.
Die meisten Kommandos erwarten numerische Parameter, die in einer C-ähnlichen Syntax angegeben werden können. Numerische Konstanten können entweder in hexadezimaler Notation (ohne Präfix, oder mit Präfix '0x' oder '$'), dezimal (Präfix '#') oder binär (Präfix '%') angegeben werden. Weiters sind die Werte der CPU Register unter den Bezeichnungen 'rA', 'rX', 'rY', 'PC' und 'SP' (inkl. $0100 Offset)) und der Inhalt des RAM (per 'RAM[xxxx]' oder 'RAMb[xxxx]' für 8 Bit Zugriff oder 'RAMw[xxxx]' für 16 Bit Zugriff) verfügbar. MEM[xxxx] funktioniert genauso wie RAM[xxxx] nimmt aber auf die aktuelle Speicherkonfiguration Rücksicht. Daher wirkt MEM[xxxx] manchmal auf RAM, manchmal auf ROM und manchmal auf I/O Chips. Statt MEM[xxxx] kann auch PEEK(yyyy) verwendet werden, wobei die Adresse dann aber, wie in BASIC, dezimal anzugeben ist.Die Registernamen und Speicherreferenzen können noch mit dem Suffix 's' oder 'u' versehen werden (etwa 'rAs', 'rXu', RAMwu[xxxx]) um vorzeichenbehaftete und vorzeichenlose Werte zu unterscheiden (Voreinstellung: vorzeichenlos).
Alle Werte können mit den Operatoren '+', '-', '*', '/', '<<', '>>', '&', '^', '|', '~', '-' verknüpft werden. Alle Operationen werden dabei in vorzeichenbehafteter 32-Bit Arithmetik ausgeführt. Beachten Sie, daß (im Unterschied zu C) die Shift Operatoren eine höhere Präzedenz haben als '+', '-', '*' und '/' (Ich halte die Semantik von C für in diesem Punkt höchst unglücklich). Natürlich läßt sich die Reihenfolge der Auswertung über Klammern beliebig steuern.
Der Debugger unterstützt folgende Kommandos (Parameter in Klammern sind optional):
a StartAddr - Assembler
Assembliere Code ab Adresse StartAddr. Alle Konstanten und Adressen müssen in hexadezimaler Schreibweise angegeben werden. Illegale Opcodes sind erlaubt. Eine leere Zeile beendet die Assemblierung.
b StartAddr (EndAddr) - Binary Memory Dump
Zeigt den Inhalt des Speichers von StartAddr bis EndAddr in binärer Schreibweise. Gesetzte Bits werden durch '*' dargestellt, nicht gesetzte durch '.'. So läßt sich die Bitmap eines Zeichensatzes bequem untersuchen. Änderungen der Speichers sind durch Überschreiben der Daten und Abschluß mit <Return> möglich.
c StartAddr EndAddr CompareAddr - Compare Memory - Speichervergleich
Vergleiche den Inhalt des Speicherbereichs von StartAddr bis EndAddr mit dem Speicherinhalt des Bereichs ab CompareAddr. Identische und unterschiedliche Bereiche werden gemeldet. Identische Bereiche, die kleiner als 3 Byte sind, und von unterschiedlichen Bereichen umgeben sind, werden als Artefakte angesehen und werden nicht gemeldet. Dies reduziert die Anzahl der gemeldeten Blöcke und erhöht somit die Übersichtlichkeit.
d StartAddr (EndAddr) - Disassemble
Disassembliert den Speicherbereich von StartAddr bis EndAddr. Änderungen des Programms sind durch das Überschreiben der Befehle und ein abschließendes <Return> möglich.
f StartAddr EndAddr Bytes - Find
Sucht nach einer Folge von Bytes im Speicher. Die Bytes müssen in hexadezimaler Schreibweise angegeben werden. Es ist möglich '?' als Platzhalter für eine beliebige Hexziffer zu verwenden. Alternativ kann statt den Bytes auch eine Zeichenkette angegeben werden, nach der gesucht werden soll. Diese Zeichenkette wird ohne Unterscheidung von Groß-/Kleinschreibung, ASCII/Bildschirmkodierung und normaler/inverser Darstellung gesucht.
Beispiele: f a000 a080 43 42 ?d f e000 f000 "Commodore"
fa StartAddr EndAddr SearchAddr - Find Address
Sucht alle Referenzen auf die absolute Adresse SearchAddr im Programm von StartAddr bis EndAddr. Auch hier ist es möglich '?' als Platzhalter für eine beliebige Hexziffer zu verwenden.
Beispiel: fa e000 ffff d0?? - sucht im Kernal ROM alle Zugriffe auf den VIC.
fp StartAddr EndAddr Value - Find Poke
Sucht jene Stelle, an der ein bestimmter Wert (etwa die Anzahl der verbliebenen Leben, das aktuelle Energieniveau oder der Punktestand) im Speicher abgelegt ist. Wenn statt der StartAddr EndAddr (gemeinsam) + als Adressbereich verwendet wird, so such fp in den Ergebnissen der vorherigen Suche.
Die korrekte Verwendung von Find Poke soll anhand eines Beispiels illustriert werden. Nehmen wir an, wir wollen herausfinden, wo Serpentine die Anzahl der verbleibenden Leben speichert. Nach dem Programmstart haben wir 5 Leben, also suchen wir mit fp 0800 2A00 5. Es gibt viele Treffer - Zu viele um sie von Hand zu untersuchen. Wir spielen weiter, bis wir ein Leben verlieren und suchen nun (mit 4 verbleibenden Leben) mit fp + 4 nach der korrekten Stelle, aber es gibt leider keine Treffer - Pech gehabt ;(. Vielleicht zählt Serpentine bei der Anzahl restlichen Leben das aktuelle Leben nicht mit. Also ein neues Spiel starten und mit fp 0800 2A00 4 suchen. Nach dem nächsten Tod in den obigen Ergebnissen mit fp + 3 suchen und 'Voila', wir haben einen einzigen Treffer ($0924). Auch bei anderen Programmen gibt es meistens nur sehr wenige Treffer, die sich dann von Hand weiter untersuchen lassen. Wir können nun mit m 0924 den aktuellen Wert betrachten und verändern, oder mit fa 0800 2a00 0924 alle Stellen im Programmcode suchen, an denen Serpentine auf die aktuelle Anzahl der Leben zugreift (um dann dort passende Patches anzubringen).
Achtung: fp ist ein sehr mächtiger, aber auch trickreicher Befehl der nur für erfahrene Benutzer gedacht ist. Es gibt sehr viele verschiedene Arten wie ein Wert gespeichert sein kann. Die 'Off-by-One' Problematik wurde oben geschildert, es könnte aber auch sein, dass das Spiel die Nummer des aktuellen Lebens und nicht die Anzahl der restlichen Leben speichert. Manche Spiele vergeben auch für kleine Erfolge immer gleiche ein Vielfaches von 100 Punkten. Es ist sinnlos, die letzten beiden Nullen zu speichern und das Spiel kann (muss aber nicht) darauf verzichten. Insgesamt kann man sagen, dass viel Geduld und geschicktes Raten erforderlich sind um den fp Befehl erfolgreicht zu verwenden. fp sucht die Daten im Binärformat (Big- und Little-Endian), als BCD-Zahlen (Big- und Little-Endian), in ASCII Darstellung und als BASIC Float Variable.
g (RegPC) - Go
Fährt mit der Ausführung des C64 an de Adresse RegPC (Default: Aktueller PC) fort. Das Debuggerfenster wird dabei nicht geschlossen.
h - Help
Zeigt eine kurze Zusammenfassung alle Debugger-Befehle.
l (LoadAddr) - Load Data
Lädt Daten von der Mac Festplatte (*.C64, *.CBM, *.PRG oder *.P00 Dateien) in das C64 RAM. Üblicherweise werden die Daten an die in der Datei vorgesehenen Adresse geladen, doch ist es auch möglich eine andere LoadAddr vorzugeben. Die gewünschte Datei wird über einen Mac Dateiauswahldialog bestimmt.
lr LoadAddr - Load Raw Data.
Lädt rohe Daten von der Mac Festplatte in das C64 RAM. Dabei wird der gesamte (!) Inhalt der Datei ins RAM geholt, inklusive des Headers einer *.P00 Datei und den zwei führenden Adressbytes. Daher ist es erforderlich die LoadAddr bei lr Befehl unbedingt explizit anzugeben. Die gewünschte Datei wird über einen Mac Dateiauswahldialog bestimmt.
k StartAddr (EndAddr) - PETASCII Memory Dump
Zeigt den Inhalt des Speichers von StartAddr bis EndAddr als Folge von PETASCII Zeichen. Änderungen der Speichers sind durch Überschreiben der Daten und Abschluß mit <Return> möglich.
m StartAddr (EndAddr) - Hex/PETASCII Memory Dump
Zeigt den Inhalt des Speichers von StartAddr bis EndAddr als hexadezimale Zahlen und als PETASCII Zeichen. Änderungen der Speichers sind durch Überschreiben der hexadezimalen Zahlen und Abschluß mit <Return> möglich.
n StartAddr (EndAddr) - Screen Code Dump
Zeigt den Inhalt des Speichers von StartAddr bis EndAddr als Folge von Bildschirmcodes. Änderungen der Speichers sind durch Überschreiben der Daten und Abschluß mit <Return> möglich.
o StartAddr EndAddr Data - Occupy Memory (memset)
Füllt den Speicher von StartAddr bis EndAddr mit dem Wert Data.
p ("FileName") - Reset Log File
Schließt das aktuelle Log Datei und öffnet eine neue mit dem angegebenen Dateinamen (Default: "C64 Monitor - tt.mm.jjjj" im Drucker Ordner). Die Ausgabe jedes beliebigen Kommandos kann in die Log Datei umgelenkt werden, indem das Kommando in Großbuchstaben geschrieben wird.
r - Show CPU Registers
Zeigt den aktuellen Inhalt der CPU Register an. Änderungen sind durch Überschreiben der Werte und Abschluß mit <Return> möglich.
s StartAddr EndAddr - Save Data
Sichert den Speicherbereich von StartAddr bis EndAddr auf der Mac Festplatte. Die Datei wird über einen Macintosh Dateiauswahldialog bestimmt. Je nach Extension wird die Datei entweder als *.C64 oder *.P00 Datei geschrieben. Wenn Sie den gleichen Bereich speichern wollen, den Sie zuvor geladen haben, ist es nicht erforderlich StartAddr und EndAddr anzugeben.
sr StartAddr EndAddr - Save Raw Data
Sichert den Speicherbereich von StartAddr bis EndAddr auf der Mac Festplatte. Nur der Speicherinhalt, aber keine Headerinformation, wird geschrieben. Die Datei wird über einen Macintosh Dateiauswahldialog bestimmt.
t (RegPC) - Trace Program
Das C64 Programm an Adresse RegPC (Default: aktueller PC) wird im Einzelschrittmodus abgearbeitet. Nach jedem Befehl wird der Zustand der CPU ausgegeben und Power64 wartet auf eine Taste. Mit der Leertaste wird ein weiterer M6510 Befehl abgearbeitet. Nach einem Druck auf die <Return>-Taste arbeitet Power64 im beschleunigten Einzelschrittmodus. Alle Informationen werden ausgegeben, aber Power64 wartet nicht jedesmal auf einen Tastendruck. Mit 'J' wird der Rest des aktuellen Unterprogramms auf einen Schlag abgearbeitet. 'S' führt die aktuelle Codezeile (ein einfacher Befehl oder ein Unterprogramm) aus. 'L' führt das Programm bis zum Erreichen jener Scanline, die zuletzt mit dem Kommando 'tl' verwendet wurde, aus. Per 'G' wird der Einzelschrittmodus beendet und das Programm wieder mit voller Geschwindigkeit ausgeführt.
tb (Addr (Cnt)) (!) - Set/Show/Clear Breakpoints
Ohne Parameter zeigt tb die Liste aller gesetzten Breakpoints. Wenn nur eine Adresse angegeben ist, setzt Power64 an dieser Stelle einen Breakpoint. Jedes mal, wenn der C64 den Breakpoint erreicht, wird in den Einzelschrittmodus geschaltet. Wenn neben der Adresse noch ein Cnt Wert angegeben wird, wird nur einmal, beim dem Cnt-ten erreichen des Breakpoints, in den Einzelschrittmodus gewechselt, danach ist der Breakpoint automatisch gelöscht. Um einen Breakpoint einzeln zu löschen verwenden Sie tb Addr!. Mit tb ! werden alle Breakpoints auf einmal gelöscht.
Die speziellen Schlüsselwörter IRQ, NMI und RESET können verwendet statt einer Addr verwendet werden um einen Breakpoint beim Erreichen einer dieser Exceptions zu setzen.
Anmerkung: Breakpoints funktionieren bei selbstmodifizierendem Code nicht immer korrekt.
tl (Scanline (RegPC)) - Trace to Scanline
Das C64 Programm an Adresse RegPC (Default: aktueller PC) wird ausgeführt, bis der VIC die angegebene Scanline (Default: gleicher Wert, wie beim letzten tl) erreicht hat. Danach wird in den Einzelschrittmodus gewechselt. Diese Funktion ist sehr nützlich zur Fehlersuche bei Raster-Interrupt Routinen.
tq (Cnt (RegPC)) - Trace Quick
Cnt Befehle des C64 Programms ab RegPC (Default: aktueller PC) werden schnell abgearbeitet. Dann wird in den Einzelschrittmodus gewechselt. So lassen sich viele Iterationen einer Schleife abarbeiten, ohne jeden einzelnen Schritt zu beobachten.
v vic - View VIC
Zeigt den Zustand des Video Chips VIC (VideoIC) in bequem lesbarer Form an.
v sid - View SID
Zeigt den Zustand des Sound Chips SID (Sound Interface Device) in bequem lesbarer Form an.
v cia1 | cia2 - View CIA1 or CIA2
Zeigt den Zustand des Timer und I/O Chips CIA 1 (Complex Interface Adapters) oder CIA 2 in bequem lesbarer Form (inklusive interner Schattenregister) an.
v ram - View Memory Configuration
Zeigt die Speicherkonfiguration in bequem lesbarer Form an.
w StartAddr EndAddr DestAddr - Write (Copy) Memory
Der Speicherbereich von StartAddr bis EndAddr wird in den Speicherbereich ab DestAddr kopiert. Dies funktioniert auch dann korrekt, wenn Quell- und Zielbereich überlappen (oder sogar identisch sind - etwa beim Kopieren des ROM ins RAM)
x - Exit/Quit Monitor
Schließt das Debuggerfenster
y StartAddr (EndAddr) - Sprite Dump
Zeigt den Inhalt des Speichers von StartAddr bis EndAddr in binärer Schreibweise mit 3 Byte pro Zeile. Gesetzte Bits werden durch '*' dargestellt, nicht gesetzte durch '.'. So lassen sich die Bitmaps von Sprites bequem untersuchen. Änderungen der Speichers sind durch Überschreiben der Daten und Abschluß mit <Return> möglich.
z DeviceNumber - Select Device
Der Debugger kann nicht nur für den C64, sondern auch für die angeschlossenen Diskettenlaufwerke genutzt werden. Über DeviceNumber 8-11 lassen sich die Laufwerke auswählen; Alle anderen Werte wählen den Commodore64.
$ HexExpr - Berechnet den Wert eines Ausdrucks in Hexdarstellung
# DezimalExpr - Berechnet den Wert eines Ausdrucks in Dezimaldarstellung
% BinärExpr - Berechnet den Wert eines Ausdrucks in Binärdarstellung
? Expr
Berechnet der Wert des Ausdrucks Expr und stellt ihn in dezimaler und hexadezimaler Schreibweise dar.
Setzt den Wert einer Speicherstelle. Dabei wird im Gegensatz zu allen anderen Monitorbefehlen die Adresse und der neue Wert als dezimale Zahl, oder als dezimaler Ausdruck angegeben, so wie das auch im C64 BASIC üblich ist. So lassen sich Cheat-POKEs bequem in ein laufendes Programm eingeben.
SYS DezimalAddr - Programm starten
Wie Go, aber mit einer dezimalen Adresse à la BASIC.
Die Ausgabe aller Kommandos kann auch (zusätzlich zur Ausgabe auf dem Bildschirm) in einem Logfile gesichert werden indem der Kommandoname in Großbuchstaben geschrieben wird. Das Logfile wird im Drucker Ordner (Details siehe Kapitel 5.15: Drucker) angelegt und trägt üblicherweise den Namen "C64 Monitor - tt.mm.jjjj". Über das Kommando 'p' kann ein anderer Dateiname bestimmt werden.