Hello, Guest the thread was called1.5k times and contains 9 replays

last post from KiWi at the

Spiel im Kernal

  • Hallo,


    keine Ahnung ob das schon mal gemacht wurde. ich wollte mich in das CBM prg Studio einarbeiten und suchte eine Aufgabe.
    ich hatte mich immer schon gefragt, wie schwer es ist, ein Spiel aus einem 8k Modul anstelle des Kernals zu starten.
    Idee:
    Spiel suchen, was nur 8k Größe hat. Einfache Pack/Entroutine suchen/schreiben, um aus den 8k weniger zu machen.
    Dann einen Kernal-Loader schreiben, der das gepackte Image nach $8000 verschiebt und dann startet.
    Sollte ja nicht so schwer sein.


    Also los:
    ich entschied mich für Galaxian von Atari, weil ich Galaga Clones schon immer geliebt hae und es im gepackten Zustand 5kb groß war. Gute Chancen also!


    Als erstes musste ich aus dem CRT ein Binärfile machen. Danke Vice kein Thema, da Vice das Tool cartconv mitbringt:
    cartconv -t bin -i galaxian.crt -o galaxian.bin


    Dann kommt natürlich die Frage der Fragen: Was aus dem Kernal wird durch Galaxian aufgerufen. Die Frage ist wichtig,
    da der Kernal ja nicht mehr existiert.
    Um dies herauszubekommen habe ich das Binärfile durch den DA65 (der Disassambler des CC65) gejagt.
    Damit nicht zu großes Quatsch am Anfang entsteht, habe ich die ersten 18 Bytes gelöscht, da dort der Modulstart Header mit
    CBM80 und den Startvektoren zu finden ist.
    Das disassemblierte Programm (galaxian_dis.zip) sah dann so aus (nur der Anfang, unten das ganze File):






    Mich interessierten die Sprungadressen $EA7E und $FF81. Eine Suche im Quellcode ergab, dass $FF81 nur einmal und $EA7E zweimal aufgerufen wurde.
    Bei $EA7E handelt es sich um das Ende der Tastaturabfrage aus dem Kernal. Die muss ich ersetzen, da sie häufig aufgerufen wird.
    Bei $FF81 handelt es sich um den Einsprung in die Reset Initialisierungsroutine, die nur einmal am Anfang aufgerufen wird.


    Zum Glück ist der Code bei EA7E nur 9 Byte lang. Diese 9 Byte habe ich mir aus dem Ende des Images geklaut. Dort steht nur ein Copyright des Entwicklers.
    Sorry dafür 8o
    CodeEnde.JPG


    Neu:
    CodeEndeNeu.JPG


    Wenn man sich dann die Sprung-Orgi ab $FF81 ansieht, kam mir der Zweifel, ob ich das alles noch in den 8k unterbringen kann (und vor allem muss).
    Ich entschied mich daher zu erst es zu ignorieren.
    Stattdessen patchte ich im Binärfile die beiden Stellen mit dem EA7E Einsprung auf $FFF0. Das geht mit nem Hexeditor sehr einfach.


    Nun also zum Packen und Entpacken.
    In einem anderen Projekt hatte ich mal mit der RLE packmethode gearbeitet. Die ist eher für Grafik und nicht für Code geeignet,
    aber ich wollte mir nicht zu viel Arbeit machen.
    Unter RLE kann man sich Beispiel Code für CC65 inklusive C Code zum Packen und Entpacken herunterladen. Mit CC65 ud GCC schnell übersetzt
    hatte ich eine rlepack.exe und testete sie auf dem Galaxian Image. Es ergaben 7675 Bytes. Also noch über 400 bytes frei für die Entpack und ggf. Initialisierungroutine.
    Die Datei hängt im Anhang.galaxian_pacht2_rle.zip


    Der dann entstandene Code sah ungefähr so aus. galaxiankernal_asm.zip


    Der Code selber ist nicht groß (bitte nochmal auf die Erklärung zu initvic warten.

    Aus dem oben erwähnten RLE Toolkit habe ich die folgenden Anteile entnommen:

    So weit so gut. Aber es fehlte ja noch die Routine an $FF81.
    Ich schaute mir den Kernal Quellcode dazu an und entschied mich,
    erstmal nur die VIC Initialisierungsroutine aus $EAA0 zu nehmen.


    Fehlt noch das Einbinden des RLE gepackten Files und die Vektoren am Ende.


    Code
    1. incbin "galaxian_pacht2.rle"
    2. *=$FFFA
    3. BYTE $00,$E0,$00,$E0,$00,$E0


    Damit den neuen Kernal compilierrt und in VICE ausprobiert.
    HEUREKA es funktionierte!!!!!!!


    Es gab nur ein Problem. Das Spiel war links und rechts abgeschnitten. Was man dank schwarzem Hintergrund und Rahmen nicht sofort sehen konnte war,
    dass das Bild vertikal um 3 Pixel verschoben war. Als ich den Wert 9B aus der Initialisierungsroutine auf $98 geändert hatte. Sah alles gut aus.

    Code
    1. victable
    2. BYTE $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
    3. BYTE $00, $9B, $37, $00, $00, $00, $08, $00, $14, $0F, $00, $00, $00, $00, $00, $00
    4. BYTE $0E, $06, $01, $02, $03, $04, $00, $01, $02, $03, $04, $05, $06, $07

    Das so nun mit dem CBM prg Studio erzeugte File konnte (nach dem löschen der ersten (2 bytes) problemlos
    als Kernal im Vice eingebunden werden und startete Galaxian.


    Das war im Grunde einfacher als ich dachte. Zum Glück gab es nur wenige Sprünge in die Kernal Routinen.
    Ich denke mit einem besseren Pack Algorithmus könnte man noch mehr Platz sparen (ZIP schafft es ja den Code auf 5Kbytes zu schrumpfen). Da bliebe
    noch viel Platz für Kernal-Routinen.


    Mal sehen ob mich noch ein anderes Spiel reizt ;-)


    Der fertige "Kernal" ist dieser hier galaxian_in_the_kernal.zip



    EDIT: Da war noch Qautsch drin ! Musste daher den text noch mal anpassen.

  • Lustige Idee und sicher eine gute Möglichkeit, etwas zu lernen! Aber das Ergebnis ist wohl nur bedingt nützlich, weil ein Modul sich ja ohnehin als ROM einblendet und beim EInschalten gleich da ist. Oder übersehe ich einen Vorteil?

  • Ein Ultimax-Modul blendet so gut wie alles an RAM aus... Als Eprom gebrannt und in ein Ultimax-Modul verpackt wird es also kaum laufen.
    Was mir gerade die 1541 Ultimate II bestätigt hat. Nach Umwandlng in CRT mittels "cartconv -t ulti -i galaxiankernal.bin -o galaxiankernal.crt" habe ich das resultierende CRT mit der 1541 Ultimate II emulieren lassen, und es geht wie vermutet nicht.


    Nachtrag: Als Kernal eingebunden und nicht als Ultimax-Modul funktioniert es selbstverständlich. Aber deine letzte Antwort war ja "Ultimax Modul"

  • Nicht wirklich, da kann man auch das original CRT nach bin wandeln, die Startadresse $8000 voranstellen und flashen lassen. Als Startadresse gibt man $FCE2 an, und fertig. Der Superkernal kann schließlich auch Onefiler in den Slots unterbringen. :-)