Erstellt: 4. Mai 2014 (zuletzt geändert: 1. November 2021)

Ein EPROM „brennen“

Ab auf den Chip

C64 Studio & AMCE

Ich möchte den Start der diesjährigen „C64 16KB Cartridge Game Development Competition“ von RGCD zum Anlass nehmen, um mal tatsächlich ein EPROM zu „bruzzeln“.
Vielleicht habt ihr ja Lust an der obigen Competition teilzunehmen (als Preis winkt u. a. eine 1541 Ultimate II), dann solltet ihr euren Beitrag auf jeden Fall auch unter realen Bedingungen testen. Also euer Spiel als Modul an einem echten C64 betreiben.
(Keine Angst: Falls ihr keinen EPROM-Brenner besitzt, aber unbedingt teilnehmen möchtet, auch RGCD bietet Unterstützung beim Test auf realer Hardware an. Aber dann braucht ihr eigentlich auch gar nicht weiterlesen, hier geht es schließlich hauptsächlich ums Brennen.)

Was wird benötigt?
  • Ein Modul erstellen wird für den Programmierteil vorausgesetzt.
  • SD2IEC
    oder eine andere Möglichkeit ein Programm vom PC zum C64 zu übertragen
  • ein 8KB großes EPROM (2764)
  • EPROM-Brenner
    Ich habe mich hier für den bekannten TINY-EPROMMER entschieden, da man diesen auch heute noch mit standard Komponenten nachbauen kann.
  • „Trägerplatine“ für das fertige EPROM (z. B. REX-9502 DUO-EPROM)
  • Löschgerät für EPROMs (zumindest falls ihr ein EPROM häufiger beschreiben wollt)

Falls euch die Programmierung nicht interessiert, könnt ihr auch direkt zum Brennen springen.

Was soll aufs EPROM?

Ich möchte dieses Mal ein vorhandenes Programm auf ein Modul packen. Meine Wahl fiel auf den CBM-FileBrowser, den ich für das SD2IEC verwende.

Ein Problem ist natürlich der Umstand, dass der CBM-FileBrowser nicht für den Modulspeicherbereich ab $8000 entwickelt wurde. Wir können ihn also nicht einfach aufs Modul packen und starten. Entweder wir besorgen uns den Quellcode und passen diesen für den Modulbetrieb an oder wir machen es uns einfach.

Ich bin für die zweite Möglichkeit 😉 .

Das Programm erstellen

Der einfache Weg besteht nun darin, dass wir das Programm vom Modul in den eigentlich vorgesehenen Speicherbereich zurück kopieren und dort starten. Beginnen wir also mit unserem Progrämmchen.

*=$8000
 !word start                        ;ab $8000 RESET-Vector
 !word start                        ;ab $8002 NMI-Vector   
 !byte $c3, $c2, $cd
 !text "80"                         ;ab $8004 CBM80 (die Buchstaben müssen
                                    ;invertiert, die Zahlen 'normal' sein!
 
start                               ;Einsprung

Wir beginnen mit dem bekannten Modulkopf, hier starten wir bei einem RESET oder NMI den CBM-FileBrowser. Der Kopf ist soweit bekannt und wir machen nun hinter start mit unserer Initialisierung weiter…

 ldx #$00
 stx $d016                          ;VIC aktivieren
 jsr $fda3                          ;Init CIA
 jsr $fd50                          ;RAM testen / löschen
 jsr $fd15                          ;Init Kernal Vektoren
 jsr $ff5B                          ;Init VIC
 jsr $e453                          ;BASIC-RAM Vektoren intialisieren
 jsr $e3bf                          ;Haupt-BASIC-RAM Initialisierung
 ldx #$fb                           ;Stack für BASIC 
 txs                                ;vorbereiten

Bis zum jsr $ff5b kennen wir das auch schon. Danach initialisieren wir aber noch das BASIC und sorgen dafür, dass der Stack korrekt gesetzt ist, damit auch ein Rücksprung zum BASIC klappt (schließlich wollen wir den CBM-FileBrowser bei Bedarf auch verlassen können).

Wir möchten ja gleich den CBM-FileBrowser vom Modul in den C64 Speicher kopieren. Die Kopier-Routine (Loader), die gleich zum Einsatz kommt, wird sich selbst ändern, dies ist natürlich im Modulspeicher nicht möglich. Also brauchen wir noch eine kleine Kopierfunktion, die den Loader in den Hauptspeicher kopiert. Dabei darf es natürlich nicht zu Überschneidungen mit dem Zielspeicher des CBM-FileBrowser kommen.

 ldx #filestart-loader-1            ;Größe des 'Loaders' ermitteln und als Schleifenzähler verwenden
nextLoaderByte                      
 lda loader,X                       ;Byte holen
 sta LOADERADDR,X                   ;und kopieren
 sta $D020                          ;etwas Blinken...
 dex                                ;Schleifenzähler verringern
 bpl nextLoaderByte                 ;solange positiv nächstes Byte
 jmp LOADERADDR                     ;'Loader' starten

Unser Loader startet beim gleichnamigen Label und erstreckt sich bis zum Beginn des CBM-FileBrowsers, der ab filestart eingebunden wird. Das X-Register dient als Schleifenzähler. Da wir solange kopieren, bis X positiv ist, verringern wir die Anzahl noch um eins. Dann holen wir uns ein Byte der Loader-Funktion in den Akku und kopieren es nach LOADERADDR. Über diese Konstante legen wir das Ziel für den Loader fest. Um die erwähnte Überschneidung zu vermeiden, können wir diesen z. B. in den Bildschimspeicher kopieren. Fügt also am Programmbeginn die Zeile LOADERADDR=$0400 ein. Den Akkuwert verwenden wir ebenfalls, um zur optischen Kontrolle den Rahmen blinken zulassen. Dann wird X verringert und wie erwähnt, wiederholen wir die Schleife solange X positiv ist. Zum Schluß springen wir zum Loader, der sich nun ja an der Adresse LOADERADDR befindet.

Kümmern wir uns jetzt noch um den eigentlichen Loader.

loader
 ldx #32                            ;Pagezähler (32 * 256 = 8192)
 ldy #0                             ;Schleifenzähler für die Bytes
nextProgByte
 lda filestart,Y                    ;Byte holen
 sta $0801,Y                        ;zum Ziel kopieren
 sta $d020                          ;blinken...
 dey                                ;Byte Zähler verringer
 bne nextProgByte                   ;solange nicht 0 nochmal
 inc LOADERADDR+6                   ;sonst MSB der Quelle erhöhen
 inc LOADERADDR+9                   ;und MSB des Ziels erhöhen
 dex                                ;Pagezähler verringern
 bne nextProgByte                   ;solange nicht 0 wiederholen
 cli                                ;Interrupts freigeben
 lda #$08                           ;Device-ID auf 8
 sta $ba                            ;setzen
 jmp 2061                           ;kopiertes Programm starten

Unser ROM wird gleich exakt 8192 Bytes groß sein. Daher initialisieren wir das X-Register, mit dem wir die Pages zählen, mit 32 (8192 / 256 = 32). Das Y-Register nutzen wir, um die 256 Bytes je Page zu verarbeiten. Dann holen wir uns ein Byte von filestart und kopieren es an die original Ladeadresse des CBM-FileBrowsers, also nach $0801. Die Ladeadresse findet ihr zur Not auch in den ersten beiden Bytes der fb64.prg-Datei. Auch hier nutzen wir das eben kopierte Byte, um den Rahmen blinken zulassen. Dies wiederholen wir solange, bis Y = 0 ist. Dann wird die Quell- filestart und Zieladresse $0801 beim lda und sta um eine Page erhöht. Dabei müssen wir beachten, dass sich der Loader nun ja an einer anderen Stelle im Speicher befindet!
Wir können also nicht die Label loader oder nextProgByte als Basis für Adressberechnung bei den beiden inc-Befehlen nehmen, sondern müssen die in LOADERADDR hinterlegte nehmen! Bei den Bedingten-Sprüngen können wir aber die eben erwähnten Label nutzen, da diese die relative Adressierung verwenden.
Anschließend verringern wir noch das X-Register und springen, solange X nicht 0 ist, wieder nach nextProgByte. Da wir den CBM-FileBrowser vom Modul starten, ist evtl. die aktuelle Geräte-Id nicht gesetzt. Der Browser zeigt dann erstmal nichts an und wir müssten dann durch Tastendruck auf die Floppy umschalten. Um gleich mit der richtigen Geräteadresse zu starten laden wir diese in den Akku und schreiben sie nach $ba (hier merkt sich der C64 die aktuelle Geräteadresse). Ihr könnt hier natürlich auch eine andere Id hinterlegen, aber bei mir läuft das SD2IEC mit der ID 8. Zum Schluß springen wir direkt zum Start des CBM-FileBrowsers. Die Adresse 2061 (hier ausnahmsweise mal dezimal angegeben!) findet ihr, wenn ihr den CBM-FileBrowser ladet und euch vor dem Start die BASIC-Startzeile mit LIST anschaut 1 SYS2061.

Falls noch nicht geschehen, kopiert den CBM-FileBrowser fb64.prg ins Projekt-Verzeichnis, damit wir den jetzt einfach einbinden können.

filestart
 !bin "fb64.prg",,2
 !fill $2000-(*-$8000),$ff

Mit der letzten Zeile füllen wir den Rest (bis 8192 Bytes erreicht sind) noch mit $ff auf. Dazu berechnen wir den bisher verbrauchten Platz vom Modulbeginn $8000 bis zum Ende des CBM-FileBrowser und ziehen diesen Wert von 8192 (oder $2000) ab. Nun wissen wir, wie oft wir $ff einfügen müssen.

LOADERADDR          = $0400         ;Hier den Loader ablegen

*=$8000
 !word start                        ;ab $8000 RESET-Vector
 !word start                        ;ab $8002 NMI-Vector   
 !byte $c3, $c2, $cd
 !text "80"                         ;ab $8004 CBM80 (die Buchstaben müssen
                                    ;invertiert, die Zahlen 'normal' sein!
 
start                               ;Einsprung
 ldx #$00
 stx $d016                          ;VIC aktivieren
 jsr $fda3                          ;Init CIA
 jsr $fd50                          ;RAM testen / löschen
 jsr $fd15                          ;Init Kernal Vektoren
 jsr $ff5B                          ;Init VIC
 jsr $e453                          ;BASIC-RAM Vektoren intialisieren
 jsr $e3bf                          ;Haupt-BASIC-RAM Initialisierung
 ldx #$fb                           ;Stack für BASIC 
 txs                                ;vorbereiten
 
 ldx #filestart-loader-1            ;Größe des 'Loaders' ermitteln und als Schleifenzähler verwenden
nextLoaderByte                      
 lda loader,X                       ;Byte holen
 sta LOADERADDR,X                   ;und kopieren
 sta $D020                          ;etwas Blinken...
 dex                                ;Schleifenzähler verringern
 bpl nextLoaderByte                 ;solange positiv nächstes Byte
 jmp LOADERADDR                     ;'Loader' starten



loader
 ldx #32                            ;Pagezähler (32 * 256 = 8192)
 ldy #0                             ;Schleifenzähler für die Bytes
nextProgByte
 lda filestart,Y                    ;Byte holen
 sta $0801,Y                        ;zum Ziel kopieren
 sta $d020                          ;blinken...
 dey                                ;Byte Zähler verringer
 bne nextProgByte                   ;solange nicht 0 nochmal
 inc LOADERADDR+6                   ;sonst MSB der Quelle erhöhen
 inc LOADERADDR+9                   ;und MSB des Ziels erhöhen
 dex                                ;Pagezähler verringern
 bne nextProgByte                   ;solange nicht 0 wiederholen
 cli                                ;Interrupts freigeben
 lda #$08                           ;Device-ID auf 8
 sta $ba                            ;setzen
 jmp 2061                           ;kopiertes Programm starten



filestart
 !bin "fb64.prg",,2
 !fill $2000-(*-$8000),$ff

Das Programm können wir nun mit VICE testen. Nach dem Start geschieht freilich erstmal nichts, aber ein RESET oder ein Druck auf die RESTORE-Taste startet den CBM-FileBrowser.

Unser Modul läuft mit VICE.
Unser Modul läuft mit VICE.

So weit, so gut. Da alles funktioniert, können wir nun unser erstelltes Programm auf ein EPROM brennen. Einen Punkt möchte ich noch anmerken. Je nach Software für den Brenner (erst recht, falls ihr nicht am C64, sondern am PC eurer EPROM erstellt) kann es notwendig sein, die Ladeadresse zu entfernen. Die Ladeadresse könnt ihr z. B. mit einem Hex-Editor löschen oder ihr steuert dies einfach über den Assembler. Beim C64 Studio und ACME gebt ihr einfach die Direktive !to „eprom.bin“,plain zu Beginn des Quellcodes ein, dann erhaltet ihr eine Datei ohne Ladeadresse.

Für die Software des TINY-EPROMMERs können wir unser erstelltes Programm aber ganz normal (inkl. Ladeadresse) verwenden. Ich habe das obige Programm unter dem Namen EPROM mit ins D64-Image der TINY-Software gepackt und auf die SD-Karte für das SD2IEC kopiert.

Brennen

Natürlich könnt ihr EPROMs auch direkt am PC brennen, für das echte Retrofeeling wollen wir dies aber an einem guten alten C64 machen. Wer mit dem Programmieren nichts am Hut hat, der findet hier ein D64-Image mit der Software für den TINY-EPROMMER und dem oben erstellten Programm.

Der TINY-EPROMMER wird in den User-Port des C64 gesteckt und benötigt zusätzlich eine Verbindung zu den Joystick-Ports (keine Angst, die sind durchgeschliffen).

Der TINY-Eprommer
Der TINY-EPROMMER

Außerdem braucht wir jetzt noch ein 8KB großes EPROM vom Typ 2764. Den Typ findet ihr normalerweise auf dem EPROM-Gehäuse.

EPROM Typ (hier 2764)
EPROM-Typ (hier 2764)
TINY am C64
TINY-EPROMMER am C64

Sehr wichtig ist, dass ihr aufs richtige Einsetzen des EPROMs achtet!
Falls es verkehrt eingesetzt wird, besteht die Gefahr, dass ihr es zerstört!!!

Das EPROM verfügt über eine Kerbe an der schmalen Seite, die euch dabei hilft, die richtige Richtung zu ermitteln. Durch die Kerbe wisst ihr, wo sich der erstes Pin befindet (PIN-1). Wie ihr seht muss bei meiner Version des TINY-EPROMMERs, das EPROM mit der Kerbe nach links zeigen. Ob das immer der Fall ist kann ich nicht sagen, da es auch viele selbstgebaute TINY-EPROMMER gibt. Dort könnte das Layout der Platine und somit evlt. die Richtung für das EPROM abweichen.

Auf die richtige Ausrichtung des EPROMMs achten!
Auf die richtige Ausrichtung des EPROMMs achten!

Nun könnt ihr die TINY-Software laden und starten. Nach kurzer Zeit begrüßt euch das Hauptmenü.

TINY-Software
TINY-Software

Als Erstes sollten wir mit ‚F3‘ = TYP/ALLGORITHMUS WAEHLEN den richtigen EPROM-Typ und den Brennalgorithmus wählen.
Auch dies ist wieder sehr wichtig! Die EPROMs müssen mit verschiedenen Spannungen gebrannt werden. Eine zu niedrige Spannung führt nur zu einem Fehlschlag beim Brennen, eine zu hohe wird aber evtl. das EPROM zerstören! Falls ihr euch nicht sicher seid, findet ihr hin und wieder die Spannung auf dem EPROM, sonst hilft nur ein Blick ins zugehörige Datenblatt. Die Standardtypen (wie unser 2764) sind aber vorgegeben.

EPROM-Typ und Algorithmus
EPROM-Typ und Algorithmus

Bestätigt den richtigen Typ und die Spannung mit RETURN. Danach kommt ihr zur Auswahl des Brennalgorithmus. Wie ihr an den Namen erkennen könnt, bestimmt dieser wie schnell das EPROM gebrannt wird. Kommt es zu Problemen, dann solltet ihr einen langsameren Algorithmus wählen. Ich entscheide mich hier für den Mittelweg FAST & SECURE. Bestätigt ihr auch dies, dann landet ihr wieder im Hauptmenü.
Ganz unten findet ihr zur Kontrolle den aktuell gewählten EPROM-Typ, die Spannung und den Algorithums.

EPROM_008Da man dem EPROM nicht ansieht, ob es leer ist, sollten wir dies zur Sicherheit mit ‚F2‘ = EPROM LEERTEST überprüfen. Bei einem leeren EPROM liefern alle Speicherstellen $ff zurück (daher habe ich mich oben auch zum Auffüllen mit diesem Wert entschieden). Bestätigt die Abfrage und nach wenigen Sekunden erhaltet ihr das Ergebnis.

Der Leertest.
Der Leertest.

Sollte das EPROM nicht gelöscht sein, dann müsst ihr entweder ein anderes nehmen oder es mit dem hoffentlich vorhandenen EPROM-Löschgerät löschen.

Für das Löschen ist es wichtig, dass das Sichtfenster des EPROMs offen ist (siehe weiter oben)! Nur dann kommt das UV-Licht durch und kann den Baustein löschen.
Entfernt vor dem Löschen also evtl. vorhandene Aufkleber!

Sobald wir ein leeres EPROM haben, müssen wir das Programm, das aufs EPROM soll, in den Speicher laden. Wechselt dazu mit ‚F5‘ = FILES/DIREKTORY zum Disketten-Menü…

Disketten-Menü
Disketten-Menü

… und wählt dort ‚F5‘ = PROGRAMM LADEN aus. Gebt dann den Dateinamen (bei mir EPROM) ein und wählt oder bestätigt die Geräteadresse (meistens kann wohl die 8 stehen bleiben). Danach folgt eine Abfrage wo ihr das Programm im Speicher ablegen möchtet. Wie ihr dem Bild (s. unten) entnehmen könnt dürfen wir ab $3000 etwas ablegen, gebt also 3000 ein und bestätigt die folgende Abfrage mit Ja. Das Programm wird eingeladen und ihr seht zur Kontrolle wo es endet. Hier für unser Beispiel ist es, wie erwartet, $4fff (8192 BYTES).

Das Programm in den C64-Speicher laden.
Das Programm in den C64-Speicher laden.

Drückt, wie angezeigt, eine Taste, um zum Disketten-Menü zurückzukehren. Von dort geht es mit ‚F1‘ = ZURUECK wieder ins Hauptmenü.

Jetzt soll aber endlich der „Brenner“ anspringen. Im Hauptmenü wechseln wir mit ‚F1‘ = EPROM BRENNEN das Menü.

'Brenn'-Menü
‚Brenn‘-Menü

Da wir unser eben in den Speicher geladenes Programm „brennen“ wollen, wählen wir hier ‚F3‘ = SPEICHERINHALT BRENNEN aus. Wir werden dann nach dem Beginn und Ende des Speicherbereichs gefragt. Hier geben wir die vom Laden bekannten Werte 3000 und 4fff ein. Da man ein EPROM auch in Etappen befüllen kann, müssen wir jetzt noch die Start- und Endadresse für das EPROM festlegen. Wir überschreiben alles vom Anfang und geben daher 0000 als Anfangsadresse und 1fff als Endadresse ein.

Stimmen alle Angaben?
Stimmen alle Angaben?

Kontrolliert eure Angaben, stimmt alles (vorallem Typ und Spannung) dann startet das Brennen mit Ja. Während der EPROMMer seine Arbeit verrichtet, leuchtet die rote LED.

Der Brenner brennt.
Der Brenner brennt.

So bald der Brennvorgang abgeschlossen ist, informiert euch die Software darüber.

FERTIG!
FERTIG!

Um sicherzugehen, dass der EPROM-Inhalt mit unserem Programm übereinstimmt, kehrt ins Hauptmenü zurück und wählt den Punkt ‚F6‘ = EPROM VERIFY an. Gebt wieder die bekannten Adressen ein und die Software vergleicht den C64-Speicher mit dem EPROM sobald, ihr die Abfrage mit Ja bestätigt. Nach kurzer Zeit solltet ihr das Ergebnis sehen.

Speicherbereiche vergleichen ... erfolgreich!
Speicherbereiche vergleichen … erfolgreich!

Sollte es hier zu einem Fehler kommen, dann müsst ihr das EPROM löschen und ggf. mit anderen Einstellungen nochmal erstellen. Kommt es wiederholt zu Problemen mit einem EPROM-Baustein, dann ist dieser evtl. defekt.

Das EPROM ist fertig!

Um das eben erstellte EPROM zu testen, steckt es auf eine Trägerkarte (z. B. eine REX 9502). Achtet auch hier wieder darauf, dass es richtig eingesetzt wird! Dazu gibt es eine Kerbe auf dem Sockel, dort muss dann also auch die Kerbe des EPROMs hin.

Kerbe auf Kerbe
Kerbe auf Kerbe

Stöpselt nun die Modulplatine in den C64.

Das EPROM auf einer Modulplatine im C64.
Das EPROM auf einer Modulplatine im C64.

Aktiviert die Platine (richtigen Steckplatz wählen 1 oder 2 und Schalter von AUS auf EIN) und drückt RESET, schon startet der CBM-FileBrowser.

Der CBM-Filebrowser
Der CBM-FileBrowser

Nun solltet ihr über alle Infos verfügen, um standard Module zu erstellen und z. B. an der „C64 16KB Cartridge Game Development Competition“ teilnehmen zu können. Es gibt allerdings noch weitere Themen wie z. B. Bankswitching (um größere EPROMs zu nutzen) oder was man beim Tausch von C64-ROMs durch EPROMs beachten muss.

Die Software unterscheidet sich natürlich von Brenner zu Brenner. Aber prinzipell bieten alle ähnliche Funktionen.

Wer den Aufwand mit einem EPROM-Brenner scheut, der kann natürlich auch über andere Wege seine Module testen. Dazu eignen sich z. B. das Retro Replay, ein Easy Flash oder natürlich das Turbo Chameleon 64.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (3 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


Zurück

2 Gedanken zu „Ein EPROM „brennen““

  1. Super Anleitung! Vielen Dank…
    Versuche das Spiel “Mega Phoenix” auf ein EPROM zu bringen und hab deinen Code dafür angepasst. Leider funktioniert das nicht und ich weiß nicht wieso. Die Datei ist 28KB groß und soll auf einen 27256 EPROM. Geändert hab ich im “loader” den Pagezähler von 32 auf 128. Die Einsprungadresse bei Phoenix ist ebenfalls $0801 und der Basiccode zum Programmstart ist SYS2059, was ich im Code ebenfalls auf “jmp 2059” geändert habe.
    incbin “phoenix.prg”,2
    dummy=fileend-$8000
    dummy=$8000-dummy
    BYTES $FF*dummy
    wurden auch noch angepasst. Dann im HEX-Editor die Einsprungadresse aus dem erzeugten PRG gelöscht und per PC gebrannt.
    Hast du einen Tipp, wo der Fehler liegen könnte???

    1. Ich vermisse das „Bankswitching“ (es wird zwar von mir im Beitrag erwähnt, ich bin aber nicht weiter darauf eingegangen). Der C64 „sieht“ nur max. 16kb des Moduls aufeinmal. Du brauchst also eine Trägerplatine, die ein 32kb-EPROM aufnehmen kann und eine elektronische Umschaltung („Bankswitching“) ermöglicht, um auf mehr als 16kb zugreifen zu können. Dann muss man die Kopierroutine entsprechend anpassen, sodass erst 16kb kopiert werden, dann die Bank umschalten und die zweiten 16kb kopieren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Protected by WP Anti Spam