Seite 2 von 2

Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Fr 12. Jan 2024, 10:35
von DOSferatu
@zatzen:
Ja, innerhalb der ISR vom Ticker sollte man nicht allzuviel machen.
Den Ticker benutze ich auch nur so: Ich erhöhe irgendwelche Zähler, setze Flags, o.ä. - Die eigentlichen Dinge werden dann in der Hauptschleife ausgeführt - die prüfen, ob ein Flag gesetzt, ein Zähler einen Wert über-/unterlaufen hat usw. - D.h. den Ticker nutze ich dann mehr dazu, daß nicht eine Funktion vor der anderen "davonläuft".

Man kann natürlich auch einige einfache Dinge innerhalb des Tickers machen - beispielsweise fülle ich im Ticker den "Steuerpuffer" für Figuren - damit ich genau so viele Steuerbefehle (gedrückte Tasten-/Kombis) kriege wie ich Steuerschritte in der Figuren-/Spiel-Steuerung habe. Und natürlich, wenn ich DIgi-Sound über PC-Speaker abspiele, da ist das ohne Ticker quasi nicht möglich (außer wenn man außer Soundabspielen nichts weiter machen will).

Und wegen Unterstützung: Windows XP (32bit) unterstützt auch den Sound-Blaster.
Wie schonmal erwähnt: In C:\WINDOWS\System32\autoexec.nt einfach sowas schreiben wie:
SET BLASTER=A220 I5 D1 T2
oder ähnliches - je nachdem, was man haben will. Und der supportet dann die entsprechende SB, d.h. er erkennt die Portzugriffe und spielt es dann auf der Soundhardware/Soundtreiber ab, der installiert ist. D.h. die NTVDM (das ist das Ding in 32bit-Windows, das die 16bit-Programme ("DOS", Realmode) ausführt) tut dann so, als wäre die Soundkarte im System, die dem BLASTER Wert entspricht. - Funktioniert bei mir seit Jahren tadellos.

Ich hab's noch nicht mit AdLib probiert - aber eine SB enthält ja auch die Funktionalität der AdLib-Karten. Könnte also sein, daß auch das ganze AdLib-Zeug dann mit funktioniert.

(Auch das ganze Ticker-Zeug funktioniert übrigens unter Windows - außer wenn man die Tickerfrequenz über 1000 Hz stellt.)

Windows XP war nicht umsonst so beliebt und wurde viel länger supportet als vorgesehen:
Das beste aus allen Welten: Die Forschrittlichkeit der NT-Linie, die Einfachheit der Win9x Linie, die Abwärtskompatibilität zu alten 16bit-Windows und zu DOS. Wenn DOS-Programme unter WinXP laufen, Zugriff auf INTs, die dann lange FIlenamen ermöglichen (lesend/schreibend). DIe Zwischenablage von Windows kann man von DOS aus nutzen (Bei Win9x einfach so, für WinXP hat einer n Treiber gebaut, seitdem kann ich das auch direkt zwischen DOS und Windows benutzen.)

Schon wieder zu viel Text meinerseits. Und ja, ich weiß: Du magst die ganze alte DOS-Hardware: VGA, AdLib, SoundBlaster, Keyboard - aber aus irgendwelchen Gründen den Timer nicht. Ich wollt auch nicht damit nerven, nur 'n paar vielleicht nützliche Informationen streuen.

OPL2 vs. OPL3 Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Fr 12. Jan 2024, 12:45
von wobo
OPL3 braucht nur 0,28 Mikrosekunden Wartezeit nach einem Schreibzugriff, das ist alles.
Vielleicht ist OPL3 Hardware aber auch als AdLib konfiguriert entsprechend schnell, so dass ich das per Konfiguration einstellen würde, wie lang gewartet werden muss.
Ja. Zumindest, was man so immer wieder lesen kann, z.B. hier
http://www.fit.vutbr.cz/~arnost/opl/opl3.html

OPL3 braucht eben viel weniger Wartezyklen als OPL2, egal in welchem Mode der OPL3 betrieben wird. Du kannst also einen klassischen 9-Stimmen-OPL2-Player schreiben, und bei Vorhandensein eines OPL3 dann die schnelleren Ausgaberoutinen für den OPL3 verwenden.

Du bist bei den erweiterten Modi des OPL3 (siehe Link oben) auch nicht gezwungen, diese in Stereo zu verwenden. Beim OPL3 kannst du für jeden Kanal einstellen, ob er links, rechts oder zentriert ist. Du könntest also auch einen 18-Stimmen-OPL2-Track in Mono abspielen.

Ein OPL3-Stück, das den 4-Operatoren-Mode benutzt habe ich übrigens hier gefunden
https://www.youtube.com/watch?v=01TXqmPN520

Du musst also jetzt nicht extra für mich noch einen OPL3-Tracker mit 4-Operatoren-Mode schreiben :-)

Einen Disclaimer noch: Ich habe nie selbst etwas für den OPL3 programmiert, sondern das nur vorgehabt und mit deswegen durch ein paar Doks gewühlt (ist allerdings schon Jahre her). Ich kann also nicht wirklich helfen, und nur auf die Links verweisen!

Übrigens, vielleicht was für die Admins:
Während ich hier schrieb, schrieb auch DOSferatu was, und als ich meine Nachricht abgesendet hatte war sie einfach weg.
Das ist leider schon seit meiner Anmeldung vor 10 Jahren so. Ist mir auch oft passiert, wenn ich mit einer Antwort zu lange gebraucht habe, weil ich zu lange an ihr herumgefeilt habe.

Wenn ich nicht wirklich ganz schnell eine q&d-reply hier im Forum mache, erstelle ich die Antworten immer extern mit einem Texteditor und copy&paste dann.

Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Fr 12. Jan 2024, 16:20
von zatzen
@DOSferatu:
Ist doch gut, ich hab es gerne gelesen!

Den Ticker benutze ich auch aktuell deshalb nicht, weil ich die Sache zuletzt schlichtweg nicht zum Laufen gebracht habe (Absturz) und erstmal keine Nerven hatte das hinzukriegen. Deshalb ja: Evtl. später.

Die andere Seite mit dem Ticker-Problem, bezieht sich auf die Sache mit der variablen Framerate. Diese möchte ich lieber, wenn möglich, "monolithisch konstant" halten, da sich dann sehr vieles einfacher gestaltet. Man verschenkt dabei natürlich potentielle Performance, hier würde ich dann aber erstmal damit leben können, dass etwa ein Spiel einen 486-100 braucht was sonst auch, allerdings öfters "ruckelnd", auf einem 486-25 laufen würde.
Vielleicht fällt es mir aber leichter, wenn ich eine variable Framerate ersteinmal in einer technischen Umgebung zu realisieren versuche, die keinen digitalen Audiopuffer "im Hintergrund" erzeugen muss. Sondern eben AdLib und One-Shot-DMA Einzelsounds. Das könnte mir das Brett vorm Kopf in der Angelegenheit nehmen. Ich habe das "Problem", dass ich alles immer wirklich verstehen und mir selber autodidaktisch erarbeiten muss. Ich denke, das wäre hier für mich ersteinmal der richtige Weg.

Mein Lieblings-"Feature" von DOS ist VGA bzgl. vielmehr MCGA.
Einfach Daten in die Adresse - zack, Grafik auf dem Bildschirm.
Ich programmiere unregelmäßig aber gerne, und ich lerne langsam und stetig dazu. Aber ich versuche nicht, zielstrebig ein "Profi" zu werden, etwa um, wie es vor 30 Jahren vielleicht sinnvoll gewesen wäre, bahnbrechende Software rauszubringen, d.h. von der technischen Seite her, die Hardware maximal auszreizen.
Daher ist für mich der echte VGA Modus und dessen Programmierung nach wie vor ersteinmal ein Buch mit sieben Siegeln.

MCGA scheint zudem irgendwie ein Standard gewesen zu sein, sehr viele Spiele, gerade auch die "ganz großen", nutzten diesen Modus wenn ich das nicht falsch beobachtet habe.

Also... Solange ich hier etwas 100% alleine mache, erwarte ich von mir auch gar nicht, dass es etwas weltbewegendes wird. Für sowas bräuchte man eben ein Team, wo sich jeder mit seinen Stärken einbringen kann.
Dass sowas im Hobby-Bereich meist nicht funktioniert weil irgendwer irgendwann einfach keinen Bock mehr hat und dann aussteigt, davon hattest Du erzählt, und das ist nachvollziehbar.

Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Fr 12. Jan 2024, 16:47
von zatzen
@wobo:

Das ist doch eine tolle Sache, dass ein OPL3 auch für OPL2 nur 0.28 µs Wartezeit braucht.
Vielleicht, bzw. wahrscheinlich, kann man eine OPL3 Karte sogar automatisch erkennen.
Eine AdLib lässt sich auch erkennen, das wusste ich bisher nicht - weil man ja einfach in 388h und 389h "reinballern" kann, ohne dass es schadet, wenn keine AdLib installiert ist.

OPL3 Stereo: Nach meiner Erfahrung kann man einstellen, ob links, rechts oder auf beiden Seiten. Das ist "tontechnisch" ein wenig anders als eine richtige links-rechts-Verteilung, weil nur links oder nur rechts effektiv 6 dB leiser ist als "beide Seiten". Man kann so arbeiten, aber es wirkt immer ein wenig so, als wenn was kaputt ist, wenn man einen Klang nur einseitig benutzt.

18 Stimmen... Also, das kann sinnvoll sein, je nachdem mit welcher musikalischen Philosophie man da rangeht, mein Tracker soll neben der "komischen" Instrumentendefinition aber auch relativ einfach und übersichtlich für Anfänger werden.
Vielleicht bekomme ich 9 Kanäle gleichzeitig im Textmodus 80x50 nebeneinander dargestellt.
Ich kann hier ja noch ein bisschen ausholen:
Es ist ohne weiteres möglich, mit dem klassischen Amiga-MOD Format, mit 4 Kanälen, tolle Musik zu machen. Dabei hat Sample-Musik allerdings ein Ass im Ärmel: Samples können auch direkt ganze Akkorde, 3- oder 4-Klänge sein.
Bei AdLib hat man das so nicht, braucht also für adäquate Möglichkeiten 3 Kanäle + weitere 3-4 Kanäle für Akkorde. Das ist aber so klein Problem, denn das sind ja nur 6-7 benötigte Kanäle, da ist man mit 9 Kanälen gegenüber MOD sogar noch besser dran.
Noch krasser wird das "genug Kanäle haben", wenn man mit dem C64 oder Nintendo NES vergleicht. Der SID hat nur 3 Kanäle, NES vielleicht vier, wenn man Noise und PCM rauslässt, wobei letzteres kaum benutzt wird.

Ürbigens kann man AdLib ja auch auf 6 Kanäle + Drums schalten. Letztere klingen zwar irgendwie "billig", aber irgendwie doch manchmal gerade deshalb ganz nett. Ich denke, ich werde diese Option im Tracker ermöglichen.

4-Operatoren-Mode: Ja, die Klänge klingen irgendwie frischer, für mich aber immer noch typisch nach FM. Ich werd einfach mal sehen ob ich ungewöhnliche Sounds aus der AdLib rauskriege. Und wenn nicht: Dann hab ich eben einen eigenen AdLib-Tracker, den ich selber wenigstens perfekt bedienen kann, und es wäre mein erster, der auf einem Kanal jederzeit die Instrumente wechseln kann, und Effekte wie Portamento oder Arpeggio hat.

Auch wenn Du selber nichts für OPL3 programmiert hast: Du hast schon sehr geholfen mit dem Fakt, dass eine OPL3 Hardware kaum Waitstate braucht!

Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Di 23. Jan 2024, 17:19
von zatzen
Kleines Update:

Ich habe eine Ansteuerung über 0388h und 0389h mit nur einmal 0388h lesen nach Zugriff auf 0389h versucht - es ist fehlerhaft, zumindest in DosBox. Daher muss ich bei 6x bzw. 36x 0388h lesen bleiben.
Dadurch ergeben sich nun rund 33000 mögliche Registerzugriffe pro Sekunde. Das klingt erstmal viel, ob sich das mit meinem Vorhaben verträgt, bleibt abzuwarten.
Ich möchte ja, je nach Geschwindigkeitseinstellung, 50x pro Sekunde etwas an den Operatoren verändern. Im Extremfall könnten das geschätzt um die 200 Zugriffe, x 9 = 1800 Zugriffe sein - das könnte knapp werden, da diese Zugriffe vielmehr innerhalb von nur ein paar Millisekunden stattfinden müssen, da bei 50 Hz ja insgesamt nur ein Spielraum von 20 ms gegeben ist.

Also, schneller Zugriff über die Ports 038xh funktioniert schonmal nicht. In meiner DosBox ist BLASTER auf T6, also SB16 konfiguriert, demnach sollte OPL3 also vorhanden sein, und das wurde über die inoffizielle Erkennungmethode auch erkannt.
Ich denke ich werde es mal über die Ports 220h - 223h probieren - da bestehen für mich allerdings noch Unklarheiten.

Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Di 23. Jan 2024, 23:22
von zatzen
So, komisch, diesmal hat es geklappt über Ports 388/89h, quasi ohne Wartezyklen, vielleicht war mir noch ein Fehler unterlaufen. Jedenfalls habe ich auch Zugriff über Ports 220/21h wenn OPL3 erkannt wird, und es klingt genauso wie über die klassischen AdLib Ports. Das ist schonmal eine gute technische Basis.
Sollte es technisch bei einer OPL3 Hardware keinen Unterschied zwischen der Basis 388h und 220h geben, wäre die Ansteuerung über 388h natürlich einfacher umzusetzen, und das wird auch empfohlen.

Vielleicht sieht noch jemand grundsätzliche Optimierungsmöglichkeiten meiner derzeitigen Output-Routine:

Code: Alles auswählen

procedure write_reg; assembler;
(* AH: Data, AL: Reg *)
asm
  mov dx, oplbase
  out dx, al

  test dx, 080h
  jnz @opl2   (* jump to @opl2 if base is 388, not 220, 240 or 260 *)

  mov al, ah
  inc dx
  out dx, al
  dec dx
  in al, dx

  ret

  @opl2:

  (* delay for base/status register *)
  in al, dx; ... (-> 6x unrolled!)

  mov al, ah
  inc dx
  out dx, al
  dec dx

  (* delay for data register *)
  in al, dx; ... (-> 35x unrolled!)
end;
EDIT: Mir ist erstmal schon eingefallen, dass ich einfach Bit 7 von der Basis "TESTen" kann, dieses steht nämlich nur, wenn die Basis 388h ist und nicht 220, 240 oder 260. Da muss ich gar nicht noch zusätzlich den Boolean-Status "opl3_present" prüfen.

Und noch ein EDIT:
Ich werde das ganze über Codemodifikation lösen.
So kann die Routine dann immediates statt Speicherzugriffe nutzen, ein TEST und ein Sprung fallen weg, und ich verwende MOVs statt INC/DEC, so dass die Routine nur die Register AL und DX ändert und die Flags nicht beeinflusst.

Re: "Kompilierung" von Grafik zu Assembler-Code, für maximale Geschwindigkeit?

Verfasst: Fr 4. Apr 2025, 10:35
von zatzen
Ich möchte nochmal konkret auf das eigentliche Thema hier zurückkommen.

Kurz zum Thema AdLib:
Ich habe schon ernsthaft vor, einen Tracker zu schreiben, mit diesen Besonderheiten wie der Möglichkeit, mit 50 Hz beliebige Parameter der Operatoren zu ändern, und somit komplexere und ungewöhnliche Sounds zu erzeugen, was in der Instrumentendefinition konfiguriert wird, so dass man dann ganz unkompliziert mit diesen komplexen Sounds Musik machen kann.

Über eine Sache bin ich etwas unschlüssig:
Die Lautstärkeparameter der AdLib-Karte werden über 63 Stufen definiert, und zwar sind diese logarithmisch ausgelegt und es handelt sich um Dämpfung, nicht um Lautstärke. Sprich, 63 ist extrem leise, 0 ist maximal laut.
Als pragmatisch würde ich es eher ansehen, wenn ich diese 63 Stufen auf tatsächliche Lautstärkeangaben umarrangiere.
Hier würden sich 16 Werte anbieten, das logarithmische würde ich rausnehmen, so dass man nun die Lautstärke linear mit Werten von 0-15 angeben kann.
Das wäre datenmäßig schön kompakt und ließe sich als Hex-Wert einstellig darstellen.
EDIT: 0-31 linear "gemappt" wäre wohl trotz allem besser, für eine feinere Auflösung.
Das muss ich mal in der Praxis entscheiden.



Ok, nun noch der Hintergrund zu der Idee mit Grafik zu Maschinencode umwandeln:

1995 habe ich dieses Spiel "Kotzman II" programmiert. Hier mal ein Youtube-Link dazu: https://youtu.be/wzOFciAlYcY

Es ist in QuickBASIC gemacht und Bzgl. der Grafik habe ich da nur die vorhandenen Bordmittel verwendet, also einfach PUT.
PUT kann keine Transparenz, kein Clipping und kein Spiegeln.
Ich habe es damals so gemacht, dass jedes Sprite einen Rahmen von einem Pixel Dicke hat, in schwarz, und die Sprites bewegen sich alle nur um jeweils einen Pixel, somit radieren sie sich selber aus. Ich brauchte also keinen Grafik-Puffer, es wurde direkt in den Grafikspeicher geschrieben.
Zudem da ich nicht wusste wie man in Basic den Heap nutzen kann, habe ich die komplette Grafik im Datensegment untergebracht, d.h. die Grafik belegte weniger als 64 K.

Das waren also die grafischen Bedingungen.

Ausgehend davon bringt die Idee der Maschinencode-Kompilierung der Grafikdaten unter den obigen bescheidenen Voraussetzungen diese Vorteile:
- Hintergrund möglich, da der Rahmen um die Sprites jetzt nicht mehr nicht schwarz sein muss, sondern mit einem entsprechenden Bereich eines Hintergrundbildes gefüllt werden kann
- Trotzdem viel schneller als das PUT von Basic, da ca. 95% der Daten nicht erst gelesen werden müssen, sondern direkt im Maschinencode definiert sind, und da dieser Code "unrolled" ist, fallen auch die nötigen Takte für Zählregister weg

Einen Nachteil hat es: Die Daten blähen sich ca. um den Faktor 4 auf - bei < 64K aber weniger ein Problem.
ca. 256K (Sprites) + 64K (Hintergrundbild) = 320 K kann man noch gut auf dem Heap unterbringen, zumindest wenn ich nicht vorhabe, das Spiel großartig mit Digi-Sound auszustatten.

Also, auf diese Weise könnte ich, mit einer abgwandelten Engine, dieses Spiel um Hintergrundgrafik erweitern und dabei sogar noch performanter machen.

Sprites auf den Bildschirm bringen läuft hier ähnlich ab wie der Aufruf einer BIOS-Funktion:
- ein paar Register konfigurieren (z.B. x/y oder direkt Adresse in Form von z.B. x + 320 * y)
- per CALL die Routine des entsprechenden Sprites auf dem Heap aufrufen

Dass mich das begeistern kann liegt daran, dass ich auf einem 286er mit programmieren angefangen habe, und bei meinen eigenen Spielen schon merkte, wie der in Hochsprachen an seine Grenzen kam.
Insofern hat Assembler immer noch eine große Faszination, leider heute eher obsolet, wo alles vielmehr nur noch mit nem Haufen Bibliotheken gescripted wird und man trotzdem nicht merkt wie langsam das eigentlich performt - weil die Rechner eben super schnell sind.
Und, das muss mal wohl auch sehen: 64 Bit Assembler ist, was ich davon gesehen habe, "unmenschlich" komplex, z.B. irgendwie 150 Varianten von MOV, was auch immer. Da ist es wohl wirklich klüger, wenn man das einem Compiler überlässt.