Hello, Guest the thread was called1.8k times and contains 40 replays

last post from Frenetic at the

Programm von Cartridge ins RAM kopieren und starten

  • Ich hoffe ich frage nicht zum x-ten Mal etwas, das ich nur einfach nicht gefunden habe.


    Ich möchte _zunächst_ Folgendes tun:

    1) ein CBM80 Cartridge erzeugen, welches ein .PRG als "Nutzlast" gespeichert hat

    2) das PRG an seine Zieladresse kopieren (gehen wir mal von $0801 aus, d.h. ich könnte es, wenn ich es normal lade per "RUN" starten)

    3) RUN + RETURN in den Tastaturpuffer schreiben, damit's dann gestartet wird

    3) und dann eben das PRG ausführen


    1-3 funktionieren auch, aber wenn ich dann den Cartridge Code verlasse (jmp $fcf8) dann ist der Basic-Startup ($0801-$0802) natürlich weg.


    Ich habe gesehen, dass es eine Möglichkeit ist, den Basic-Pointer auf $8000+x zeigen zu lassen -- das ist aber keine Option.


    Im Easyflash-Loader, wenn ich es richtig verstanden habe, wird der CHRIN Vektor auf die Kopierroutine verbogen.


    Geht das auch ohne einen Umweg? Oder muss ich einen solchen Trick verwenden, um nach dem Basic Initialisieren alles richtig zu schreiben? (und wenn ja, was muss ich denn noch alles schreiben? auch $2b etc?)


    Für Tipps oder Links zu anderen Varianten wäre ich dankbar!

  • So ähnlich mache ich das in der Regel bei den RGCD-Compo-Beiträgen. Nur den Step mit RUN+RETURN kannst du weglassen, du kannst ja die Zieladresse direkt anspringen. Kein Grund, da über BASIC zu gehen.


    Aber Achtung: Das ROM überspringt einige Initialisierungen, wenn ein Cartridge erkannt wird. Da musst du ggf. ein paar Kernal-Routinen anspringen, um das nachzuholen.


    Bei meinem letzten Beitrag sah das so aus:

  • Danke für Dein Code Beispiel!

    Nur den Step mit RUN+RETURN kannst du weglassen, du kannst ja die Zieladresse direkt anspringen. Kein Grund, da über BASIC zu gehen.

    Das funktioniert aber nur, wenn ich die Zieladresse kenne, oder kann man auch ein Basic-Programm direkt starten?


    Ich habe (mangels besseren Wissens) den Weg über den CHRIN-Hook gewählt (ansonsten den Standard-Startup für Carts wie bei Dir) und die Kopierroutine nach $33c verlegt -- spricht da etwas dagegen (ist $400 eher zu empfehlen)?


    Zum Testen habe ich ein paar .PRGs probiert -- die haben auch alle funktioniert, nur eines >200 Blocks wollte nicht. Ich erinnere mich finster, dass große Programme immer speziell waren, auf was muss ich da achten?

  • Ich erinnere mich lückenhaft...


    Ich nutz bei sowas immer den Packer. Schreibe mein Programm normal für $080d, und packe es dann mit neuer, höherer Ladeadresse, zB. $0900. Dann habe ich im eigentliche Cartridge ASM Programm noch etwas Platz fürs Kopieren, evtl Text-Nachricht usw. und springe dann an die Startadresse des Packers, wo ich die gepackte Datei als !Bin eingebunden habe. Danach entpackt Exomizer die Datei ab $080d, entpackt als Bonus auch unter $d000 usw. und startet dann das Programm.


    * exomizer sfx $080d unpacked.prg -o "packed0900.prg" -x -Di_load_addr=$0900

  • Für eigene Programme habe ich auch den Exomizer verwendet, geht auch schön mit cc65 Resultaten.


    Ich möchte das allerdings jetzt für beliebige PRGs machen, die bspw. vom RasPiC64 von SD-Karte gelesen werden. Es tut soweit ja auch, was muss ich jetzt noch machen, damit ich unter $d000 kopieren kann? Reicht es dazu $01 zu sichern, zu verändern, dann kopieren und zurücksetzen?

  • EDIT: das Mist-Forum unterschlägt mal wieder neue Beiträge- ihr wart schon längst weiter... ich lass' es aber mal stehen...


    Die ganzen Inits des Kernal und Basic ausfüjren, prg runterkopieren, Nasic-Verkettung neu erstellen (setzt gleichzeitig etliche Pointer) und in den RUN-Befehl springen. Ggf. erst noch eine Rücksprungadresse auf den Stack werfen. Siehe c64 intern, c64 für Insider etc.


    Oder:


    Einen Modulgenerator nehmen, der per Definition genau so einen Startcode mitbringt und vor das Programm klebt.

  • Vielleicht hilft Dir ja meine Analyse des kleinen Basic-to-Cartrige Tools, über das ich mal gestolpert bin?

    Die habe ich gesehen und auch das zweite Dokument von dem Autor der Programme...


    Nasic-Verkettung neu erstellen (setzt gleichzeitig etliche Pointer) und in den RUN-Befehl springen

    geht das anders als die CHRIN-Trap, jmp $fcfe und dann in den Keyboard-Puffer schreiben?

  • So ähnlich mache ich das in der Regel bei den RGCD-Compo-Beiträgen. Nur den Step mit RUN+RETURN kannst du weglassen, du kannst ja die Zieladresse direkt anspringen. Kein Grund, da über BASIC zu gehen.


    Aber Achtung: Das ROM überspringt einige Initialisierungen, wenn ein Cartridge erkannt wird. Da musst du ggf. ein paar Kernal-Routinen anspringen, um das nachzuholen.


    Bei meinem letzten Beitrag sah das so aus: ...

    Der Einsprung in $080d geht davon aus, dass das den Einsprungpunkt als Maschinenprogramm auch gibt. Wenn es ein "nur" ein BASIC-Programm sein soll, muss man etwas mehr machen (sowas wie ein UNNEW und ein RUN). Bin gerade dabei das für Plain-BASIC zu adaptieren ...


    Aktuellere ACME-Versionen verwenden !pseudopc in Blocksyntax (nicht mehr mit !REALPC).


    Welche Adresse hat VIC.CONTROL_2?


    Der NMI-Vektor zeigt auf $8019, das ist mitten im AND-Befehl in Zeile 19. Könnte man ja auch auf $8009 zeigen lassen, oder?


    Die Kopierroutine könnte auch ohne extra Counter-Speicherstelle auskommen, wenn man Register y als Blockcounter verwendet ... (das aber nur der Eleganz wegen).

  • Die Kopierroutine könnte auch ohne extra Counter-Speicherstelle auskommen, wenn man Register y als Blockcounter verwendet ... (das aber nur der Eleganz wegen).

    na dann finde ich mein's noch eleganter extravaganter


    kommt natürlich daher, dass mein "Cartridge" bei $de00/$de01 bereitstellt, was als nächstes benötigt wird

  • Also jetzt hat es mit dem Basteln des Modul-Starters geklappt - ganz ohne Hilfsmittel wie Exomizer.


    Als Basis nahm ich das Beispiel von Edurion: Post #2

    Es macht die Initialisierung, löscht den Bildschirm und macht in implizites RUN (ohne über Tastaturpuffer oder so, direkt).

    Aufpassen muss man nur mit der Reihenfolge. Das Löschen des Screen, in dem ja das Programm selbst liegt, wird so angesprungen,

    das die finale Übergabe an den BASIC-Interpreter bereits am "Stack" liegt und so beim Rücksprung vom Screen-Löschen aufgerufen wird, während

    das Programm im Screen-Speicher ($0400) dann schon "weg" ist.

    Ich habe allerdings "nur" ein 8-KByte-Modul genommen, weil bei einem 16-K-Modul, hab ich es auf die schnelle nicht geschafft, statt des Moduls das BASIC wieder einzublenden.

    Erstellt mit ACME, mit dabei ist ein Makefile (unter Linux erstellt).

    Bauen mit "make", starten des Moduls im Emulator mit "make start".

    Das eigentliche Modul-Binary ist basicmodul.bin (das man so auf ein EPROM brennen könnte), das Tool cartconv wandelt es in das für VICE ladbare crt-Format.

    Das eingebettete BASIC-Programm ist basic.bas und wird mittels petcat in ein .prg umgewandelt.


    Verwendet werden petcat und cartconv, Programme, die bei VICE dabei sind.

    basicmodul.zip mit allen wesentlichen Dateien. ;)

  • ich klinke mich hier mal ein....

    Mit meinem aktuellen Projekt hab ich das folgende Problem:

    Der Code beginnt bei $8100.

    Es handelt sich um ein Programm welches letzendlich ein anderes Programm generiert dass im Rasterzeilen Interrupt läuft. Die IRQ Routine verlasse ich normal mit JMP $EA31 sodass der Rechner im Basicmodus weiterläuft mit meinem IRQ-Programm im Hintergrund.

    Das ganze soll nun vom Modul gestartet werden.

    In Vergangenheit hab ich mir da mal was aus dem C64-Intern Buch und Modulgeneratoren zusammengelogen ohne genau zu wissen was da genau passiert - das funktioniert hierbei aber leider nicht.

    Damals war es reines Assembler und $A000-$C000 war ausgeblendet.

    Hier mal wie ich es probiert habe:


    STX D016

    JSR FDA3

    JSR FD50

    JSF FD15

    JSR FFB5

    CLI

    JSR E453

    JSR E3BF

    LDX #FB

    TXS


    JMP mein Programm


    Ich hatte auch noch zusätzlich Basicstart auf $0801 und Ende auf $0803 gesetzt - funzt nicht.


    Wäre nett wenn mir da mal wer auf die Sprünge helfen könnte ^^

  • ich schau mir mal den Link von bigby genauer an. Muss ich mir nur erst übersetzen und dazu am Rechner sitzen. Am Smartphone ist das doof.

    Evtl. kann ich SYS $8100 + Return in den Tastaturpuffer schreiben....

  • Bis zum JMP mein Programm schaut es m. E. gut aus. Aber ich habe da so eine Ahnung. Wie endet dann "mein Programm"? Springt es gar mit RTS zurück? Das würde in die Hose gehen.

    Ich würde dafür sorgen, dass die die Interpreterschleife am Stack liegt und was auch immer gestartet wird, dann in die Interpreterschleife zurück kehrt (falls in im angesprungenen Programm nicht selbst in die Interpreterschleife gegangen wird).

    Code
    1. b_warm = $a7ae ; BASIC warm start/interpreter loop
    2. lda #>(b_warm-1)
    3. pha
    4. lda #<(b_warm-1)
    5. pha ; prepare execution as return address on stack
    6. jmp meinProgram ; start my program, maybe it ends with RTS ...
    7. ; in this case continue with b_warm ...
  • so. Ich hab das mal ähnlich gemacht wie bei dem link von bigby

    Die Idee mit dem Tastaturpuffer ist garnicht so blöd ;)

    Mit "Soft-Reset" Sys64738 macht der Kram schon mal was es soll 8)

    Morgen schauen wie sich das ganze mit Eprom verhält...

  • so. Ich hab das mal ähnlich gemacht wie bei dem link von bigby

    Die Idee mit dem Tastaturpuffer ist garnicht so blöd ;)

    Mit "Soft-Reset" Sys64738 macht der Kram schon mal was es soll 8)

    Morgen schauen wie sich das ganze mit Eprom verhält...

    Ich finde das auch gefinkelt. Dennoch war mir das immer ein Dorn im Auge, sich auf ein Feature zu verlassen, das zwar zugegebenermaßen einfach da ist, aber irgendwie ein Vehikel ist, wo man über die Autobahn zum Nachbarhaus 10 m entfernt fährt. Deswegen hat es mich auch gereizt "direkt" ein BASIC-Programm zu starten, ganz ohne Umweg. ;)

    Jetzt ist mir im Laufe dieses Threads noch immer nicht klar, ob denn nun ein Maschinencode per JMP gestartet werden soll oder tatsächlich ein BASIC-Programm laufen soll?

    Für letzteren Fall braucht man - um auf mein Beispiel zurück zu kommen - eigentlich nur das RUN-Kommando (das setzt aber nur den Interpreter-Kontext auf das aufzurufende Programm) aufzurufen, gefolgt vom Einstieg in die Interpreter-Schleife, die dann die eigentliche Abarbeitung auslöst. Details dazu findet man ja im bereits erwähnten Post #13. Im Gegensatz zum von Bigby erwähnten Verfahren, wird der BASIC-Code aus dem Modul an den "normal" Platz im RAM kopiert, sicherheitshalber neu verlinkt und das ROM schließlich deaktiviert. Damit fungiert das Modul eigentlich nur als "Lader" mit Autostart. :)

  • so. Ich hab das mal ähnlich gemacht wie bei dem link von bigby

    Die Idee mit dem Tastaturpuffer ist garnicht so blöd ;)

    Mit "Soft-Reset" Sys64738 macht der Kram schon mal was es soll 8)

    Morgen schauen wie sich das ganze mit Eprom verhält...

    So, mit Eprom funzt auch ^^

  • JeeK

    es kommt halt drauf an was du machen willst.

    Haste ein reines Assemblerprogramm welches ohne Interpreteroutinen auskommt kannste das machen wie in meinem Post#14.

    Musst halt vorher das Programm nach $0801 schieben.

    Alternativ funktioniert das tatsächlich dass du einfach RUN + Return in den Tastaturpuffer schiebst und das so ähnlich machst wie bei dem Link von bigby. Musst vorher aber ne 0 in $0800 schreiben - für alle Fälle.

    Zu beachten ist, dass dein Programm (falls es entpackt werden muss) nicht im Bereich $8000-$9FFF was macht, es sei denn du benutzt eine Karte die elektronisch abgeschaltet werden kann.


    Was ich bei dem Link nicht verstehe ist, dass der Basicanfang hinter $8000 gebogen wird und nachher wieder zurück.

    Das muss auch so funktionieren.