Ich will hier mal eine Idee vorstellen, die ich für mein "Stoneage64" Spiel umgesetzt habe, und eventuell "fortspinnen"...
Vorher aber zum Hintergrund: Der SID leidet ja am vermutlich allseits bekannten ADSR-Bug: Wenn man einen neuen Ton (gate-bit) startet, ist der Hüllkurven-Generator noch in "irgendeinem" Zustand, was dann herauskommt ist mehr zufällig als sonst was (man kann es ganz sicher berechnen, und frühe Composer haben sich ja damit herumgeschlagen, ihre "Instrumente" so zu bauen, dass das irgendwie passt und nach was klingt). Man hat dann herausgefunden, dass man als Workaround "gate" mehrere Frames auf 0 lassen kann (quasi eine Mikro-Pause) und so lange ADSR auch auf 0000 lässt. Danach startet es wieder sauber. Der Workaround nennt sich "Hard Restart".
Nun gibt es ja auch die "moderne" Form das "Hard Restart", bei der ADSR während der Pause (2 Frames) auf einen anderen Wert (oft 0F00) gesetzt wird, gefolgt von einem Frame mit aktiviertem Test-Bit und den tatsächlichen ADSR-Werten des Instruments. Was da intern im SID passiert weiß ich nicht (kann vielleicht ein SID Experte erklären), aber Resultat ist, dass man auf die Art ungeahnt "scharfe" Starts von Sounds hinbekommt, insbesondere für glaubwürdige Drums natürlich sehr hilfreich. Der Pferdefuß dabei: DAS funktioniert nur mit "PAL-Timing" (also 50 SID-Writes pro Sekunde) korrekt.
Sollte ich bis hierhin Mist verzapft haben, bitte gerne korrigieren.
Nun zur Idee: Warum nicht auch auf einer NTSC-Maschine diese Technik anwenden, und die Musik "einfach" mit "PAL-Timing" abspielen? Da ich oft meinen eigenen Player-Code (also keinen Tracker) verwende, war es in der Tat nicht SO kompliziert:
Der eigentliche Player schreibt in Shadow-Register, wird wie gehabt ein mal pro Frame aufgerufen, wertet aber zusätzlich ein Flag aus, in dem steht, ob die zuletzt berechneten Werte schon "rausgeschrieben" wurden. Wenn nicht, tut er nichts:
Dazu gibt es eine Routine nur fürs rausschreiben der Shadow-Register, die wird 5 mal pro Frame aufgerufen, und zwar an Raster-Positionen, die auf NTSC gleich weit voneinander entfernt sind. DIE hat einen Counter, so dass sie nur bei jedem 5. Aufruf etwas tut:
Das einzige was dann noch nötig ist: NTSC detecten, wenn auf NTSC, den Counter per self-mod so erhöhen, dass die Routine nur bei jedem 6. Aufruf etwas tut (also hier: lda #5; sta so_count).
Das ganze funktioniert wirklich hervorragend ... kostet natürlich ein wenig zusätzlich "rastertime".
Ich habe mich nun gefragt, ob es sich lohnen könnte, so etwas auch um das "übliche" Interface (ne play-routine die eben einmal pro Frame aufgerufen wird und "alles" macht) herum zu basteln? Das würde natürlich NOCH mehr extra Rastertime kosten, aber vielleicht könnte es im ein oder anderen Fall lohnenswert sein? Allzu komplex sollte das nicht werden, man nutzt im Prinzip den Code oben, "wrappt" aber die originale Play-Routine so, dass die Writes im RAM statt in den echten Registern landen, dann kann man sie direkt danach woanders hin kopieren und mit snd_out schließlich ausgeben. Man könnte damit aber im Tracker seiner Wahl Musik schreiben, die EIGENTLICH nur für PAL ist, und trotzdem auf NTSC verwenden ...