Zitat
Vernunftmensch: Du hast die Unterbrechungsbehandlung offensichtlich ohne sie zu verstehen übernommen. Du brauchst ja gar keine zwei verschiedenen Rasterzeilen für die Unterbrechung und das mit dem `zaehler` ist ein hässlicher Hack, weil die Unterbrechungsbehandlung für die Timer-Unterbrechung und zweimal pro Frame für durch eine Rasterzeile ausgeführt wird. Du rufst die Abspielroutine an der falschen Stelle auf.
Ja, ich klaue mir alles zusammen. Manchmal denke ich nur nach, wenn es nicht funtioniert. Hier z.B. nicht. Kannst Du mir bitte die einfachere Routine posten, die Du meinst?
Zitat
Und das mit `MEM` könnte gefährlich werden.
Wie wir Kölner sagen: Es hätt noch immer jutgegangen. 
Zitat
A) Ich bin mir ziemlich sicher Du verwendest das Wort ”rekursiv” falsch. Und solche Lader gibt es sehr wahrscheinlich nicht. Wie willst Du zuverlässig Code und Daten trennen? Insbesondere wenn der Code sich selbst modifiziert und dadurch im Grunde beides ist. Und in den Daten, die sowohl als Operanden von Befehlen, als auch ”frei” in den reinen Datenbereichen vorkommen können, müsstest Du dann die Adressen identifizieren können, die angepasst werden müssen. Wobei die auch erst durch Berechnungen mit Werten entstehen könnten.
Wunder verbringen die alle nicht. Aber vieles wird genau richtig disassembliert. Aber vieles auch nicht, hast Du auch Recht.
Zitat
Wenn Du einen allgemeinen SID-Player wie Sidplay 64 schreiben möchtest, und dafür C einsetzen willst, würde ich eher das Hauptprogramm in C schreiben und dann einen Lader+Player in Assembler für mehrere Positionen im RAM oder besser noch frei in 256-Byte-Schritten verschiebbar, der am Ende das Hauptprogramm wieder nachläd falls das von den Musikdaten oder beim Abspielen überschrieben worden sein sollte. Es gibt SIDs die wirklich viel Speicher benötigen, weil sie zum Beispiel Sampledaten enthalten oder die Initialisierungsroutine die Playerroutine und die Daten erst einmal quer über den ganzen Speicher verteilt. So ein Song muss nicht in dem Bereich bleiben, in den er geladen wurde!
Sidplay 64 runtergeladen als .d64, seltsam, aber da sind keine SID-Dateien bei, nur PRG-Dateien. Seltsam.
Ok, also bei cc65 ist ein Programm namens overlaydemo.c bei und die zugehörige*.cfg. Es wird gezeigt, wie man Segmente mehrfach beschreibt in c und wie man in der cfg erklärt, daß er alle Versionen in eigende Dateien beim Linken schreibt. Im Programm lädt er dann drei versch. Versionen ein und desselben Segments nach und ruft jeweils daraus eine Beispielprozedur. Da könnte man was von machen.
Wenn ich höre, daß manche SIDs unkontrolliert Speicher benutzen außerhalb der Grenzen wird mir gruselig. :-S
Zitat
B) Man muss den Ladecode ausserhalb des Bereichs ablegen der durch das neue Programm belegt wird [1]_. Und dann kann man einfach laden und den geladenen Code mit den entsprechenden Aufrufen starten. Also entweder eine Assemblersequenz, die ein RUN ”nachbaut” oder direkt an die Startadresse springen, falls das nachgeladene Programm kein BASIC-Programm ist und die Startadresse bekannt ist.
Für diesen Fall jetzt wahrscheinlich nicht so wichtig, aber man kann mit cc65 auch ”overlays” schreiben, in dem man in der Linker-Konfiguration mehrere Speicherbereiche mit den selben Adressen definiert und diese in verschiedene Dateien schreiben lässt und mit ``Bitte melde dich an, um diesen Link zu sehen.``-Anweisungen dann Funktionen und Daten gezielt in für diese Bereiche definierte Segmente platziert. Auf diese Weise kann man nachladbare Teilprogramme realisieren.
.. [1] Das ist nicht ganz korrekt: Man könnte auch die Startadresse - 1 des nachzuladenen Maschinespracheprogramms auf dem (Hardware)Stack ablegen wenn die eigentliche Laderoutine tatsächlich der allerletzte Aufruf aus dem Code ist, der durch das Laden überschrieben wird.
Ich habe da schon eine Idee. Die Programmversion, die bis auf die Startinitialisierung mit Code am Ende ist, die kann ja den Anfang mit dem zweiten Programm laden, das am Anfang allen Code hat. Das könnte wie Du sagst schief gehen, aber ich ziele sowieso nur auf die gutartigen SIDs ab...
Zitat
C) Ja natürlich. Beispielsweise die Lade-, Initialisierungs-, und Abspieladressen und die Quelle des Timings (Rasterzeile, CIA-Timer, Init macht was eigenes).
Ich meinte die hier ganz unteren ab flags....
typedef struct // all values big-endian
{
char id[4]; // 'PSID' (ASCII)
uint8_t version[2]; // 0x0001 or 0x0002
uint8_t data[2]; // 16-bit offset to binary data in file
uint8_t load[2]; // 16-bit C64 address to load file to
uint8_t init[2]; // 16-bit C64 address of init subroutine
uint8_t play[2]; // 16-bit C64 address of play subroutine
uint8_t songs[2]; // number of songs
uint8_t start[2]; // start song out of [1..256]
uint8_t speed[4]; // 32-bit speed info
// bit: 0=50 Hz, 1=CIA 1 Timer A (default: 60 Hz)
char name[32]; // ASCII strings, 31 characters long and
char author[32]; // terminated by a trailing zero
char released[32]; //
uint8_t flags[2]; // only version 0x0002
uint8_t relocStartPage; // only version 0x0002B
uint8_t relocPages; // only version 0x0002B
uint8_t reserved[2]; // only version 0x0002
} psidHeader;
Alles anzeigen
cbm_load ("fire",8,NULL); (um in irgendsoein Beispielsprogramm zu springen)
//__asm__ ("jmp $07ff");
//__asm__ ("jmp $0801");
__asm__ ("jmp $????");
Wie bekomme ich leicht raus, wo die main-Funktion beginnt?
Also einfacher als das:
__asm__ ("jmp $c00a");
rausgeholt durch anfrage in fire.c:
__asm__ ("lda #<(%v)",main);
__asm__ ("sta %v", oben);
__asm__ ("lda #>(%v)",main);
__asm__ ("sta %v",unten);
gotoxy (1,1);
cprintf ("fire %x:%x ",oben, unten);
while (!kbhit()) {};
return 1;
Alles anzeigen
Sehe gerade, daß das zu Problemen führen könnte, weil wohl aus START_UP erst nach Säuberungen in main gesprungen wird.....