Vor ein paar Tagen hat jemand den Kernalpatcher erwähnt womit man den RAM-Test aus dem originale C64-Kernal entfernen konnte.
Finde den beitrag leider nicht mehr.
Du bist in Begriff, Forum64 zu verlassen, um auf die folgende Adresse weitergeleitet zu werden:
Bitte beachte, dass wir für den Inhalt der Zielseite nicht verantwortlich sind und unsere Datenschutzbestimmungen dort keine Anwendung finden.
letzter Beitrag von strik am
Vor ein paar Tagen hat jemand den Kernalpatcher erwähnt womit man den RAM-Test aus dem originale C64-Kernal entfernen konnte.
Finde den beitrag leider nicht mehr.
Gute Frage,
jedoch hat die 1541 Ultiumate II Firmware die Antwort bereit:
für den Fall, dass wer Bedarf hat, der Quelltextauszug erläutert: Falls ab $fd6c (Position $1d6c in ROM Datei) die Hexwerte aus "fastresetOrg" stehen, so werden die ersten 22 davon durch die Werte aus "fastresetPatch" ersetzt. Falls nicht, ist das ROM zu dem Patch nicht kompatibel. Klappt neben CBM Kernal auch mit einigen anderen Kernals.
Sollte relativ leicht per Hexeditor manuell durchführbar sein.
für den Fall, dass wer Bedarf hat, der Quelltextauszug erläutert: Falls ab $fd6c (Position $1d6c in ROM Datei) die Hexwerte aus "fastresetOrg" stehen, so werden die ersten 22 davon durch die Werte aus "fastresetPatch" ersetzt. Falls nicht, ist das ROM zu dem Patch nicht kompatibel. Klappt neben CBM Kernal auch mit einigen anderen Kernals.
Nun ja, verglichen wird bei temp ab $1d6c, überschrieben aber bei kernel ab $1d6c. Zeigen temp und kernel auf den gleichen Speicherbereich? Ansonsten wird etwas anders verglichen als überschrieben wird.
Der gepatchte Code ist:
D.h., es wird getestet, ob ab $8000 RAM oder ROM ist. Ist es veränderbar, dann wird das BASIC-Ende auf $8000 gesetzt, sonst auf $A000.
Ist der Quelltext eigentlich C++ oder C? Bei C wären die Casts nämlich überflüssig und eher schlechter Stil, den vor allem C++ - Progammierer an den Tag legen (oder Leute, die noch K&R-C gelernt haben).
Ist der Quelltext eigentlich C++ oder C?
C++, wobei nicht die gesamte Standard Library verfügbar ist, da embedded Hardware. Und beim Compiler eher älter... muss auch mit den nicht mehr gearteten Xilinx Compiler laufen...
Also dass explizite Casts schlechter Stil seien höre ich zum ersten Mal. Ob sie an dieser Stelle speziell zum leichteren Verständnis beitragen ist aber eine andere Frage.
Nun ja, verglichen wird bei temp ab $1d6c, überschrieben aber bei kernel ab $1d6c. Zeigen temp und kernel auf den gleichen Speicherbereich? Ansonsten wird etwas anders verglichen als überschrieben wird.
Das nicht, aber direkt vorher wird ein
memcpy(kernal, temp, 8192); // as simple as that
gemacht, so dass im Endeffekt doch wieder das selbe verglichen wie geändert wird... "kernal" zeigt auf den Bereich im U64, den die Hardware nutzt beim Kernalzugriff. Unschönes C++ mit absoluten Adressen als Pointer, braucht esbei direktem Hardwarezugriff jedoch.
Also dass explizite Casts schlechter Stil seien höre ich zum ersten Mal.
Ein expliziter Cast kann Fehler verstecken. Sprich: Ein expliziter Cast sorgt dafür, dass der Compiler nicht warnt, wenn er das eigentlich sollte.
wird meistens ein Fehler sein. Der Cast sagt aber: "Ich weiß was ich tue, halt die Klappe."
In C sind void Pointer gerade eben mit der Eigenschaft eingeführt worden, kompatibel mit allen anderen Pointer-Typen zu Datentypen zu sein.
Aus dieem Grund warnt ein C-Compiler nicht, wenn ich einen Datenpointer auf void* zuweise (ohne Cast) oder einen (void*) Pointer auf einen anderen Datenpointer zuweise.
Daher ist
ein Ausdruck, den ein Compiler nicht anmeckern wird/sollte.
Genauso wenig:
Wie gesagt, genau dafür sind void-Pointer da. Sonst hätte man sie weglassen können und durch char* darstellen lassen können.
Da memcmp als Parameter void* erhält (genau: const void *), ist hier kein Cast notwendig. Wie oben gesagt, der Cast könnte hier eher eine notwendige Warnung unterdrücken (was ist, wenn ich memcmp einen Funktionspointer übergebe, was in C gar nicht garantiert ist?)
Leider hat Bjarne Stroustrup dies nicht verstanden, als er C++ entwickelt hat.
(Ja, ich weiß, darüber gibt es ellenlange Diskussionen, und es gibt Leute, die andere Meinung sind - auch z.B. MISRA-C).
Siehe auch z.B. https://stackoverflow.com/ques…-type-cast-a-void-pointer oder http://c-faq.com/ptrs/genericpp.html.
Das nicht, aber direkt vorher wird ein
memcpy(kernal, temp, 8192); // as simple as that
gemacht, so dass im Endeffekt doch wieder das selbe verglichen wie geändert wird...
Aua... Dann sollte er aber auch den gleichen Bereich vergleichen. Das mag im Endeffekt der gleiche Effekt sein, der Code "sieht aber falsch aus".
Dann sollte er aber auch den gleichen Bereich vergleichen. Das mag im Endeffekt der gleiche Effekt sein, der Code "sieht aber falsch aus".
Eigentlich vermeiden wir in der Firmware jedoch, auf von anderen Hardwareteilen zugegriffenen Speicherbereichen (der emulierte C64 greift auf den Bereich ab "kernal" direkt zu) mehr als notwendig zuzugreifen... ja, es gibt sogar einige memory mapped bereiche, die write only sind und gar bnicht korrekt gelesen werden können. Schreiben muss man aber in dem Bereich, den die Hardware auswertet... wenn ich Gideon riuchtig verstanden habe, ist der "RAM" dort bei *kernal von einem anderen Typ, nämlich memory mapped hardware (edit: im FPGA) und kein normaler Arbeitsspeicher...
Eigentlich vermeiden wir in der Firmware jedoch, auf von anderen Hardwareteilen zugegriffenen Speicherbereichen (der emulierte C64 greift auf den Bereich ab "kernal" direkt zu) mehr als notwendig zuzugreifen...
Ok, dann handelt es sich dabei also um eine Optimierung?
Dann würde ich das aber auch entsprechend kommentieren, damit ein unbedarfter Leser des Quellcodes (so wie ich gerade) den Sinn dahinter auch versteht und hier kein Versehen vermutet.
Mindestens eine Optimierung, um die Anforderungen an die FPGA Implementierung klein zu halten (jene musste sich ja durchaus schon mal an neues anpassen - z. B. als der Turbomodus kam). Wenn die noch mehr bringen sollte, umso besser... bei den 22 Bytes evtl. "zu viel" schreiben ist das mit der Sicht was anders, die Fähigkeit braucht es ja sowieso. Und 22 scgreibende Speicherzugriffe beim Kernalladen fallen zwirlich auch nicht wirklich ins Gewicht. Die hat also keiner wegoptimiert...
In C sind void Pointer gerade eben mit der Eigenschaft eingeführt worden, kompatibel mit allen anderen Pointer-Typen zu Datentypen zu sein.
Ok, da stimme ich Dir zu! Es klang so, als ob man explizite Casts generell weglassen solle, wenn sie implizit ohnehin passieren, was im Sinne der Lesbarkeit m.E. nicht unbedingt sinnvoll ist.
Irgendjemand hatte da einen fertigen Patcher geschrieben, den hätte ich eigentlich gerne.
Mit dem höher geschriebenen komme ich nicht so richtig klar
Hiernach den Speicherbereich $8000-$9FFF sichern und auf EPROM brennen.
Zeile 30 ändern auf:
Programm laufen lassen, dann:
POKE 43,0 : POKE 44,64 : POKE 45,0 : POKE 46, 96 : SAVE "KERNAL",8
Das setzt den BASIC-Anfang und das BASIC-Ende auf $4000/$6000, der SAVE speichert diesen Bereich dann auf Disk.
Ach ja, es werden natürlich C64-typisch 8194 Bytes gespeichert, die ersten beiden sind "00 40", da das Programm von $4000 weg gespeichert wurde. Beim Brennen am PC die ersten beiden Bytes natürlich wegschneiden.
Alles anzeigenZeile 30 ändern auf:
Programm laufen lassen, dann:
POKE 43,0 : POKE 44,64 : POKE 45,0 : POKE 46, 96 : SAVE "KERNAL",8
Das setzt den BASIC-Anfang und das BASIC-Ende auf $4000/$6000, der SAVE speichert diesen Bereich dann auf Disk.
Sollte man dann Zeile 10 nicht auch anpassen?
10 POKE 55,64:CLR:REM MAKE SURE WE DO NOT OVERWRITE THE KERNAL
die alte Zeile 10 schützt ja mit der Änderung von Zeile 30 den falschen Speicherbereich.
Wieso setzt du das Ziel nach $4000 und speicherst dann $4000-$5FFF? Das alte Ziel $8000 und dann $8000-$9FFF zu speichern wäre doch auch gegangen?
Man kann das Programm natürlich auch umschreiben, dass es gar nicht in den Speicher schreibt sondern direkt auf die Floppy. Dann kann man sogar beide Varianten (mit Ladeadresse/ohne Ladeadresse) umsetzen.