Trackermodul-Engine (sehr einfach)

Diskussion zum Thema Programmierung unter DOS (Intel x86)
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

zatzen hat geschrieben:Ich dachte ja, die Lautstärken mit Shifting zu erledigen wäre ein super Trick
damit es schnell geht, aber würde es über Tabellen noch schneller gehen??
Naja, bei MIR geht es mit Tabellen ganz OK. Das liegt aber natürlich daran, daß ich da ganz anders vorgehe:
Meine Waves (und Samples) sind 4 bit und meine Lautstärken 0-15, also ebenfalls 4 bit.
Ich nehme das Wave/Sample (obere 4bit), AND Lautstärke (untere 4bit) und erhalte einen 8bit-Wert in AL.
dann führe ich den Befehl XLAT aus.

XLAT macht folgendes:
Es holt aus einer Tabelle, die an [BX+AL] steht steht einen Wert udn schreibt diesen wieder nach AL.
(Die Tabelle kann natürlich maximal 256 Bytes groß sein, weil ja AL...)
Da habe ich dann eine 256 Byte große vorberechnete Tabelle liegen, die den jeweiligen Sample*Lautstärke Werten entspricht.
Natürlich ginge so etwas auch mit einer Tabelle mit 8bit Samples und 8bit Lautstärken. Diese Tabelle wäre dann 64kB groß, die würde ich natürlich an eine /16 teilbare Adresse legen (so daß man ein Segmentregister genau darauf setzen kann).
Dann einfach BL auf den Sample (oder WAV) Wert und BH auf den Lautstärkenwert und schon kann man aus
mov AL,SEGMENT:[BX] den Ergebniswert holen - vorausgesetzt, da liegt natürlich eine vorberechnete Multiplikationstabelle. Nehmen wir an, man benutzt nur 64 mögliche Lautstärken (oder 65, wie in MODs) dann wäre die Multiplikationstabelle 16 kB groß.
Naja, und so weiter. Vielleicht hilft es ja.
Ich sagte ja, es gibt Gründe, wieso ich BX mag...
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Ich habe ja nur 8 verschiedene Lautstärken, zum einen um in den Patterns nicht mehr unterstützen zu müssen
und so maximal 3 Bit dafür zu brauchen, zum anderen war eben der Gedanke dabei, auf Tabellen verzichten
zu können und mit SAR oder SHL arbeiten zu können. Die Frage wäre also nur, was ist schneller, ein Speicher-
zugriff auf eine 8*256 = 2048 Byte große Tabelle oder ein SAR Befehl mit immediate...
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

zatzen hat geschrieben:Ich habe ja nur 8 verschiedene Lautstärken, zum einen um in den Patterns nicht mehr unterstützen zu müssen
und so maximal 3 Bit dafür zu brauchen, zum anderen war eben der Gedanke dabei, auf Tabellen verzichten
zu können und mit SAR oder SHL arbeiten zu können. Die Frage wäre also nur, was ist schneller, ein Speicher-
zugriff auf eine 8*256 = 2048 Byte große Tabelle oder ein SAR Befehl mit immediate...
Naja, wie Du ja weißt, gehe ich von anderen Voraussetzungen aus.
Erstens mische ich so, daß es am Ende "signed" ist - also ein Mittelsignal bei 128 und die Soundwellen sind ober - und unterhalb. (Ohne Tabellen wäre das bei mehreren Stimmen eklig zu programmieren.)
Zweitens benutze ich ja auch synthesizing (digitale Klangsynthese) - Samplenutzung ist bei mir ja nur "Nebenprodukt". D.h. ich benutze auch Hüllkurven (A-D-S-R).
Drittens wollte ich eine lineare Lautstärkesteigerung haben, keine logarithmische (wie in Deinem Fall).
Viertens müßte ich so ja intern mit 16bit arbeiten - das wollte ich von vornherein nicht.

Derzeitig bin ich übrigens auf der Suche nach einer möglichst gescheiten (d.h. einfachen und schnellen) Lösung für die Realisierung von Hochpaß und Tiefpass (also Filterprogrammierung).
Die Formeln die Leute da ins Netz posten mögen zwar mathematisch exakt sein, sind aber erstens zu kompliziert, um sie in ASM umzusetzen und dann immer noch Performance zu haben und zweitens bin ich mir sicher, daß es bei meiner geringen Klangweite sicher einfachere Methoden gibt.
Tiefpaß plane ich durch eine "Ringpuffer-Aufaddieren-Mittelwert" Methode. Ich vermute Hochpaß funktioniert so, daß man auf die o.g. einfache Art den Tiefpaß bildet und die Differenz zu den ursprünglichen Daten nimmt. Aber sicher bin ich mir nicht. Die ganze Theorie, die einem Leute für Klangfilterberechnung immer um die Ohren hauen sieht viel zu kompliziert aus, als daß es am Ende wirklich so einfach sein könnte.

In letzter Zeit bin ich leider immer so müde und erledigt - so daß ich leider schon seit einer Weile nichts mehr programmiert habe. Inzwischen weiß ich gar nicht, ob ich das unter diesen Umständen überhaupt noch als mein Hobby bezeichnen darf.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Ein ganz simpler Hochpass funktioniert über Delta Bildung, ist dann aber auch abhängig von der Samplerate.

Ansonsten hab ich in DOS Systemen keine wirklichen Filter gesehen. In der Wirklichkeit funktioniert das
elektronisch ja über Spulen und Kondensatoren, man könnte versuchen das Verhalten dieser Bauteile
nachzubilden, dürfte aber rechenintensiv sein. Aber ähnliches tun diese Plug-Ins und Soundbearbeitungs-
programme mit denen ich arbeite, allerdings ist das hier auch ein Rechner von 2011, und wie das so ist
mit Windows wirds schon wieder langsam knapp, je nachdem was man machen möchte. Medien mit HD Bild
und mehrspurige Soundmischungen mit (über-)CD Qualität fressen eben Ressourcen.

Ich habe gerade mal probiert, das mit dem größeren Puffer. Habe mal auf 2048 geändert, und es spielte noch
bis 3200 Cycles völlig flüssig. Damit dürfte ich den Tracker unterboten haben, denn seine Framerate ging
noch weiter in den Keller bzw. spielte er ja nur bis 4300 Cycles sauber.
Das heisst für mich jetzt, nochmal versuchen alle Routinen auszudünnen und zu optimieren die sich
um die Kernschleifen scharen.
Ich mach dann mal ne weitere Version fertig, falls es noch jemanden interessiert, diesmal mit Farbe und noch
der ein oder anderen Anzeige mehr - und dann wollte ich mal ne kleine Demo mit Grafik machen.
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Neue Version!
Und wahrscheinlich so erstmal die letzte von diesem Player...
http://www.zatzen.net/zsmp003b.zip

Neuerungen:
- Farbe
- Anzeige Event Flags Bytes vs. Pure Music Data
...daran kann ich mir noch überlegen ob es sich lohnen würde,
die Flags noch weiter zu komprimieren
- Patterns werden grafisch im Verlauf angezeigt
- Kanäle sind einzeln stummschaltbar
- Oszilloskop-Modus
- Animation mit Tänzer, kleine Demonstration der Sync-Möglichkeiten
indem man Samples ein Label gibt
- kein herumschwirrender Cursor mehr

Es sind ein paar neue Stücke dabei und auch ein paar der alten,
wegen der Samples-Labels. Die Dateien die bei der ersten Version
dabei waren sind noch kompatibel.

Die neue Version scheint so ersteinmal langsamer zu sein.
Das liegt an der Patternanzeige, die ich ersteinmal einfach mit
einzelnen write(...) Befehlen umgesetzt habe. Für einen ernsthaften
Release müsste ich das nochmal überarbeiten. Aber man kann sie abschalten.

Die Art des Players dient aber vor allem mir selbst als Informationsprogramm,
mit den ganzen Anzeigen, vor allem über die Patterndaten.
Letztendlich, in einer Anwendung wie ein Spiel, werden die meisten Informationen
gar nicht gebraucht, und es können viele Prozeduren und Variablen und deren
Zuweisungen aus der Player-Unit entfernt werden.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

zatzen hat geschrieben:Ein ganz simpler Hochpass funktioniert über Delta Bildung,
Also so wie ich es oben erwähnt habe?
zatzen hat geschrieben:ist dann aber auch abhängig von der Samplerate.
Inwiefern?
Ich meine: Die Samplerate habe ich ja sowieso als Wert, weil darauf basierend ja die Sounddaten generiert werden.
zatzen hat geschrieben:Ansonsten hab ich in DOS Systemen keine wirklichen Filter gesehen. In der Wirklichkeit funktioniert das
elektronisch ja über Spulen und Kondensatoren, man könnte versuchen das Verhalten dieser Bauteile
nachzubilden, dürfte aber rechenintensiv sein.
Naja, aber die C64-Emulatoren (vor allem VICE, dessen Emulation wirklich sehr präzise ist) emulieren auch die Filter
des SID. Also muß es ja irgendwie gehen. Mir geht es hauptsächlich darum, den Klang dadurch zu beeinflussen - vor allem Noise klingt besser, wenn man es noch Hoch/Tief-filtern kann.
zatzen hat geschrieben:Ich habe gerade mal probiert, das mit dem größeren Puffer. Habe mal auf 2048 geändert, und es spielte noch bis 3200 Cycles völlig flüssig. Damit dürfte ich den Tracker unterboten haben, denn seine Framerate ging
noch weiter in den Keller bzw. spielte er ja nur bis 4300 Cycles sauber.
Ja, das ist ja auch klar. Das, was "die Arbeit" macht, ist ja die Hauptschleife, die wird ja tausende Male durchlaufen. Je mehr die arbeitet, umso höher ist der Anteil "Sounddaten-Generieren" zu "Initialisieren".
Es geht ja auch darum: In einem SPIEL werden ja nicht nur Sounddaten generiert, sondern es muß auch Grafik generiert, sowie die Figuren gesteuert werden. Das braucht auch Zeit und muß sich diese mit dem Sound quasi "teilen".

Man könnte hier zwar "echtes" (präemptives) Multitasking versuchen, aber das bräuchte viel Power, Speicher usw und ist für ein einfaches Spiel in einem Singletasksystem wie "mit Kanonen auf Spatzen geschossen".
Ich persönlich wähle daher immer etwas, das dem kooperativen Multitasking entspricht: Es gibt eine Master-Hauptschleife, die das komplette Spiel hindurch läuft und immer "im Kreis" die verschiedenen Subroutinen aufruft - sobald dies nötig ist.
DIe "Nötigkeit" wird dabei für jede Subroutine mit einem Flag (bei mir ist es ein Counter) signalisiert.

Einfach ausgedrückt sieht das dann so aus (die Reihenfolge der Subroutinen kann dabei quasi "frei gewählt" werden) :
MASTERLOOPSTART
* Berechne_Grafik [auf nicht angezeigtem Bild, dann Bild_wechseln, mind. DoubleBuffer]
* Zähler_Steuerung>0 ? --> Zähler_Steuerung-1 und Berechne_Steuerung
* Zähler_Sound>0 ? --> Zähler_Sound-1 und Berechne_Sound [auf nicht gespieltem Pufferteil, dann Puffer wechseln, mind. DoubleBuffer]
* WARTEN! [siehe unten!]

MASTERLOOPEND

Wie erhöhen sich die Zähler? Beim Sound ist es einfach: Immer, wenn ein Pufferteil abgespielt ist, wird der nächste (dann schon neu generierte) begonnen, zusätzlich wird der Zähler_Sound um 1 erhöht. Der SoundBlaster erzeugt einen IRQ, wenn Puffer abgespielt, dieser kann dafür genutzt werden. Arbeitet man z.B. mit Speaker (und hat daher den Ticker auf mehrere tausend Hertz erhöht) setzt man Zähler_Sound dann auch, sobald man am Ende des aktuellen Teilpuffers ist und den nächsten beginnt. Achtung: Man prüft hier nie, ob im neuen Puffer schon valide Daten sind, man geht einfach davon aus!

Die Steuerung ist anders. Hier wird der Timer-IRQ bemüht, um Steuerdaten von Eingabegeräten zu "pollen". D.h. wenn ein Spiel mit z.B. 50 Hz läuft (d.h. 50 Steuerbefehle pro Sekunde erwartet werden) werden auch 50 Befehle pro Sekunde in einem Ringpuffer generiert (dies betrifft nur die Spielersteuerung), d.h. der Timer-IRQ wird dann auch 50 Hz gesetzt. (Man kann natürlich Speaker damit kombinieren. bei 14 kHz Speaker setzt man den Ticker auf 14000 Hz und zusätzlich zur "Soundausgabe" wird jedes 280. mal auch Steuerzustand geholt.

Das klingt komisch - aber so ist garantiert, daß - egal, wie schnell oder langsam der Rechner ist - das Spiel immer "gleich schnell" läuft (dann eben mit ruckeliger Grafik, wenn die Rechnerleistung nicht ausreicht).

Die Entscheidung, ob neue Grafik generiert werden muß, hängt normalerweise von der Bildwiederholfrequenz des Monitors ab - leider werfen nicht alle Grafikkarten einen IRQ, wenn ein Vertical Retrace auftritt. Außerdem kann es auf langsamen Maschinen passieren, daß die Leistung nicht ausreicht, um z.B. 70 Bilder pro Sekunde zu generieren (außerdem wären nur 50 nötig, wenn das Spielgeschehen sowieso nur mit 50 Hz gesteuert würde).

Hier kommt der o.g. WARTEN Teil zum Einsatz: Man kann hier auf den nächsten Vertikalen Retrace warten, dann den Zähler oder Flag für Grafik generieren auf 1 setzen und dann mit der Schleife fortfahren. Auf langsamen Maschinen verschwendet das aber unter Umständen noch mehr Zeit. Hier sollte man entweder wählbar machen, ob der VR abgewartet werden soll (schnelle Maschine) oder nicht (langsame Maschine) - oder, ob eine Selbstregulation (gibt es z.B. in meinem Spiel XPYDERZ) auch möglich ist. (Wenn ohne VR, tut "WARTEN" einfach nichts, sondern geht gleich zum Schleifenanfang zurück - da davon ausgegangen wird, daß die maximale FPS sowieso nie erreicht wird.)
Man könnte hier auch den Ticker mißbrauchen, um bei erreichen eines Ticks bei 50 Hz (oder 70 Hz oder was auch immer) das Flag für "Grafik benötigt" gesetzt wird.

Warum gehe ich so vor? Das Generieren der Grafik braucht meist mit Abstand die meiste Rechenzeit, somit baue ich alles "drumherum" auf. Irgendwann muß ein Bild generiert werden, daher steht dies gleich am Anfang der Schleife. Während das passier, läuft aber die ganze Zeit der Ticker (Timer-IRQ) mit, um entsprechend die anderen Zähler zu erhöhen, bzw der IRQ des SoundBlaster. Somit ist am Ende der Grafikberechnung klar, wieviele Steuer-Schritte nun gemacht werden müssen, um "die Grafik einzuholen" und ob inzwischen neue Sounddaten benötigt werden.

Und warum erzähle ich das? Nun - DAS ist der Grund, wieso der Soundpuffer nicht zu klein sein sollte - denn es könnte sonst passieren, daß neuer Sound benötigt wird, aber der Rechner noch mit der Berechnung der Grafik beschäftigt ist. Daher muß die Steuerung in einem Ringpuffer stattfinden und die Soundgenerierung quasi auch (auch wenn der "Ring" dort nur 2 Puffer enthalten könnte). Falls man Angst hat um die "Synchronität" des Sounds: Man kann ja auch statt z.B. 2 Puffer zu je 4 kB stattdessen z.B. 8 Puffer zu je 512 Byte nutzen - selbe Gesamtgröße, aber man ist "etwas synchroner".

Ganz synchron kann man sowieso nie werden, weil es ja immer Sounddatenpuffer sind und keine "Einzelbytes".
Wenn man einigermaßen irre ist, könnte man natürlich das Generieren der Grafik so gestalten, daß dieses "unterbrochen" werden kann. Dann könnte man auch auch langsamen Maschinen sehr kleine Puffer nehmen.
Die Grafik kann aber natürlich trotzdem erst umgeschaltet (auf das neue Bild) werden, wenn sie vollständig generiert wurde (Ruckeln kann man damit also nicht vermeiden.) Außerdem ist so eine "unterbrechbare Grafik-Generierung" natürlich etwas langsamer, weil sie etwas umständlicher zu programmieren ist und außerdem natürlich jeder Aufruf wieder den Init-Teil
abfertigen muß - und es dann auch einen "Exit"-Teil geben muß, um den Zustand (für die Unterbrechung) zu sichern. Daher habe ich mich da stets dagegen entschieden.

Und ja: Man kann nicht unendlich große Soundpuffer haben - erstens wird der Sound dann sehr unsynchron (bei Musik eher egal, bei Soundeffekten, die zum Spiel gehören eher nicht) und zweitens ist RAM ja nicht unendlich groß. - Also gibt es natürlich trotzdem eine Mindestleistung, die ein Rechner haben muß, damit das Spiel überhaupt läuft (dann eben mit ruckeliger Grafik). Bei der o.g. Vorgehensweise ist diese Mindestanforderung wirklich direkt abhängig davon, wie groß man die Ringpuffer für Steuerung und Sound anlegt.

Ich will mit diesem ganzen Redeschwall nur sagen: Wenn man den Puffer so klein wählt, daß man z.B. 50x pro Sekunde Sound generieren muß (weil Puffer in 1/50 Sekunde abgespielt ist) der Rechner aber zu langsam ist, um auch die Grafik mit 50 FPS zu berechnen, wird DER SOUND RUCKELN. (Grund: Rechner malt noch Grafik, Sound ist im Hintergrund schon abgelaufen und wird nicht neu erzeugt.) Und ruckeliger (stotternder) Sound ist schlimmer als ruckelige Grafik.

Wie gesagt: Dem könnte man entgehen, indem jeder einzelne Prozeß "unterbrechbar" ist (wie bei echtem - präemptivem - Multitasking) - nur dann muß erstens komplizierter programmiert werden (jede Subroutine braucht umfachgreicheren Eintritts-/Austritts-Code) und zweitens: Reicht die Rechnerleistung nicht, wird dann dennoch alles ruckeln.

Ich wähle die o.g. Methode aus, damit bei langsamer Maschine automatisch die FPS runtergehen - aber Steuerung und Sound "gleichschnell" bleiben. Anders ausgedrückt: Der Anteil der Gesamtleistung (Gesamtschleife), den Steuerung und Sound gegenüber Grafik zugewiesen bekommen, ist dann bei langsamen Maschinen höher.

Das ist wohl auch der Grund, wieso man bei Sound in Spielen/Demos auswählen kann/konnte, mit wieviel kHz der generiert werden soll - denn mehr kHz bei Sound erfordert natürlich mehr Daten pro Sekunde zu generieren - umso ruckeliger wird die Grafik bei langsamen Maschinen.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Ich muss gestehen dass die von dir beschriebenen Vorgehensweisen für mich noch etwas hoch sind -
mein letztes ernsthaftes Spiel war ja nur Kotzman II, und da hatte ich in den Leveln selbst keine
Musik und schon gar keine Sample-Musik, sondern nur Rechenzeit-freie AdLib-Effekte.
Auch die Grafik funktionierte ohne jegliches Puffern, jedes Sprite hatte einen schwarzen Rahmen
um sich herum um sich selbst wieder wegzu"radieren".
Grafik vor Hintergrund und die damit nötig werdende Pufferung, sowie Musik und Soundeffekte
parallel dazu sind für mich also eine neue Sache.
So werde ich ersteinmal versuchen, die Rechenanforderung für ein Spiel so gering zu halten,
dass es auf 486er Maschinen quasi monolithisch funktioniert, ohne dynamische Verwaltung
von Grafik und Ton, auch wenn man dabei mögliche Performance verschenkt.
Wie gesagt, für mich ist das etwas neues und ich freue mich ersteinmal darauf, überhaupt
ein nettes kleines Spiel zu haben mit Hintergrundmusik, Soundeffekten und Grafik mit Transparenz.
Auch freue ich mich, dass ich Assembler schon etwas besser beherrsche und mich damit
freier bewegen kann als früher.
Auch von Vertical Retrace habe ich viel gehört über die Jahre, und klar kann es nervig sein
wenn das Bild schwabbelt, aber das lasse ich erstmal auf mich zukommen.

Ich widme mich derzeit wieder ZVID.
Bisher waren die Schwächen noch:
1. Daten wurden den Decodier-Routinen mündchensmaß in einen Puffer vorkopiert, was die Performance
scmälerte. Das habe ich schon gefixt, die Daten werden jetzt direkt aus dem Stream verarbeitet.
2. Decodiert wird wiederum in einen (64 Byte) Zwischenpuffer, welcher dann erst an entsprechende Position
in den Zielpuffer kopiert wird. Da bin ich gerade dran, das zu ändern.
3. Bisher keine Sprungtabellen, sondern IF-Abfragen. So viele sind es aber nicht.

Am meisten dürfte im Moment noch Punkt 2 ausmachen.
Ich habe mit ZSM diese Aninmation mit der Ente (HIT_ANY) vertont, es ist eine Bildschirmfüllende
Animation, es läuft im Grunde schnell und flüssig, aber stellenweise stottert es wenn man die
Emulation auf 386SX Niveau einstellt. Ich werde das im ZVID Thread hochladen wenn ich den Viewer
optimiert habe.
mov ax, 13h
int 10h

while vorne_frei do vor;
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Zum Filtern:
Sicher gibt es da Algoritmen, die man auch in DOS umsetzen kann.
FFT Filter fallen mir da grade ein als Beispiel. Es ist nur so, dass soetwas für mich
ein Buch mit sieben Siegeln ist und dass ich softwaremäßig damit nur zu tun habe
im Rahmen von Windows, bei der Klangbearbeitung jenseits von Computerspiel-Niveau.

Delta-Hochpass wäre eben ganz einfach immer die Differenz zum Vorgänger-Sample bilden,
tiefe Töne kommen dann nicht mehr durch, ganz hohe aber besonders gut. Keine gute Methode,
aber eine sehr einfache.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

zatzen hat geschrieben:Ich muss gestehen dass die von dir beschriebenen Vorgehensweisen für mich noch etwas hoch sind -
mein letztes ernsthaftes Spiel war ja nur Kotzman II, und da hatte ich in den Leveln selbst keine
Musik und schon gar keine Sample-Musik, sondern nur Rechenzeit-freie AdLib-Effekte.
Naja, ich sage es mal so: Wir haben alle mal irgendwann angefangen zu programmieren.
Als ich meine ersten Spiele (in BASIC auf KC85 Rechnern) gebaut habe, habe ich die Steuerung der Figuren alle mit IF-Kaskaden gemacht und die Steuerung der Spielfigur wurde von getrennten, anderen Teilen realisiert als der Rest.
Inzwischen wird das alles eher generalisierter gemacht - aber da mußte ich auch erstmal drauf kommen.

Wenn man etwas gutes gemacht hat und es funktioniert, fragt man sich immer: "Das ist so einfach - wieso bin ich da nicht früher drauf gekommen?" Aber es ist eigentlich der gleiche Effekt wie bei Erfindungen von anderen: Sind die Erfindungen erstmal gemacht, denkt man: "Eigentlich logisch, hätte jeder drauf kommen können - sogar ich." Ist man aber nicht.

Wenn man daran denkt, daß Konrad Zuse 1939 das Patent für seinen Computer (der noch nicht mal Computer hieß) angemeldet hatte - und das Ding war quasi mechanisch... und heute schon irgendwelche Kids in einen Laden gehen und sich ein Wischhändi kaufen können, das eine Leistung und Speicher hat, für die man vor 50 Jahren einen Flugzeughangar voll Elektronik hätte stopfen müssen und selbst dann wäre das Ding nicht annähernd so schnell gewesen... - na egal.
zatzen hat geschrieben:Auch die Grafik funktionierte ohne jegliches Puffern, jedes Sprite hatte einen schwarzen Rahmen
um sich herum um sich selbst wieder wegzu"radieren".
Ja, ich weiß. Du erwähntest mal dergleichen.
Auf C64 konnte man sich ja auf die Hardware-Sprites verlassen - da mußte man keinen "Hintergrund löschen". Aber es gab von diesen Sprites nur 8 und die Größe war festgelegt. Mit Tricks (die aber wieder Rechenzeit/-leistung brauchten) konnte man hier die Sprites vervielfältigen. Außerdem hat man für kleinere Objekte (Projektile) ja wieder "Zeichen" benutzt, für die man natürlich wieder den Hintergrund sichern mußte. (Fast alle C64-Spiele sind in Textmode - aber die Textmodi des C64 sind etwas Besonderes. Die kann man auch auf "Multicolor" umschalten und die Zeichenmatrizen natürlich beliebig ändern. Und die Softscroll-Register für vertikal/horizontal sind ja auch sehr nützlich.)

Auf PC habe ich auch mit Textmode-Spielen angefangen (ich konnte zuerst nichts anderes). Aber bei PC-Grafikkarten hat man keinen Rasterzeilen-IRQ (fast nie) und der Multicolor-Mode, den die ETx000 Reihe hat, ist nicht überall gegeben. (Auf diese ganzen Sachen bin ich viel später gestoßen, als ich mich etwas tiefer mit VGA-Registern beschäftigt hatte.)

Sobald ich aber auf PC "Grafikmode" konnte, war für mich klar, daß ich ebenfalls eine "Umgebung" brauche, in der ich "freibewegliche" Sprites habe und "gekachelte" Levels. Also habe ich Zeug zusammengebaut, das genau das hat. Anders würde ich gar nicht mehr anfangen wollen, Spiele zu bauen. Und ja - ich hatte mich auch für einige Jahre in die Untiefen der 3D-Programmierung gestürzt, kann inzwischen auch so DOOM[tm]-artige Levels darstellen/durchlaufen und könnte somit auch ein 3D-Spiel schreiben (wenn ich die Zeit finden würde, Levels, Texturen, Figuren... Sounds... usw. zu kreieren).

Aber ich schaffe es ja seit Monaten (Jahren) nicht einmal, meine geplanten 2D-Spiele zu machen - obwohl ich quasi inzwischen so ziemlich alles dafür da habe, was ich brauche! Alles ist immer so zu 95% fertig, könnte aber schon verwendet werden. Aber 95% ist eben nicht 100% und ich will es immer "richtig machen". Geplant sind ein Raumschiff-Shooter (Shoot'em'up) und ein Jump'n'run-Arcade. Die Ideen dafür sind schon 13 Jahre (Jump'n'run) und 20 Jahre (Shoot'em'up, damals noch als Textmode geplant!) alt! Und vor 13 Jahren hätte das vielleicht noch irgendwen interessiert, da die Spiele auch unter MS-Windows noch lauffähig gewesen wären. Heutzutage sind es nicht so sehr die wirklichen SPIELER, sondern eher alte DOS-Enthusiasten, die sich Dinge wie "DOSbox" antun, um dann so alten Kram zu spielen. Aber selbst diese spielen wohl eher den richtigen alten Kram, d.h. das Zeug was wirklich "von damals" ist - als vielleicht ein neues Spiel (von 2016), das nur mit den Techniken "von damals" gemacht wurde und auch 1991 hätte programmiert werden können.

Und die jüngere Generation ist eher dem Modus, den mein Kumpel immer "Instant Gratification" nennt: Alles muß immer gleich und sofort und ohne die geringste Mühe und Anstrengung funktionieren. Ein Gerät, wo man nur über den Bildschirm tippen und wischen muß ohne über irgendetwas nachzudenken ist quasi die "plastikgewordene Manifestation" dieser Lebensart. (Endlich hatte Apple das geschafft, was sie schon jahrzehntelang wollten: User sollen überhaupt nicht nachdenken müssen. Das "Es gibt nur einen einzigen Button"-Gerät ist Wirklichkeit.)

Und auch wenn diese Leute vielleicht auch auf diesen "Retro-Zug" aufgesprungen sind und gern Spiele "wie damals" (Jump'n'run ö.ä.) spielen wollen - so etwas Anstrengendes wie sich einen Emulator herunterzuladen und sogar selbst EINRICHTEN zu müssen, würden sie dafür nie auf sich nehmen. Das grenzt ja an Nachdenken oder gar Arbeit! Man könnte blöderweise ja etwas dabei lernen! Am Ende sogar ein klein wenig mehr wissen als absolut überlebensnotwendig! So etwas kann man denen nicht antun! Wo es doch schließlich auch Retro-Jump'n'runs auf "gar-nicht-so-retro" Systemen gibt!

Und wenn diese angeblichen "Retro-Fans" mal ein Spiel oder Tool sehen, das nicht nur "wie retro" ist (aber 3D und mit 16 Mio. Farben angestrichen), sondern ein RICHTIGES Spiel von damals sehen:
- mit 256 Farben, 16 Farben, 4 Farben, 2 Farben
- mit Sound, der 4-stimmig, 3-stimmig, sogar 1-stimmig oder gar nicht vorhanden ist
- mit einen repetativen Spielprinzip, aber wirklich schweren Levels
dann können sie meist gar nicht glauben, daß es so etwas wirklich einmal gegeben hat und daß es Leute vor den Bildschirm gefesselt hat. Das ist so wie jemand, der Mittelalter-Märkte und Mittelalter-Filme und dergleichen mag... - würde der wohl versehentlich ins wirkliche Mittelalter fallen, wäre er wohl schnellstens auf der Suche nach einer Spitzhacke - um nach neuem Plutonium für seinen DeLorean zu graben...
zatzen hat geschrieben:Grafik vor Hintergrund und die damit nötig werdende Pufferung, sowie Musik und Soundeffekte
parallel dazu sind für mich also eine neue Sache.
Naja, auf dem PC bleiben einem nicht gerade viele Möglichkeiten. Selbst wenn die eigene Grafikkarte eventuell manche Effekte beherrscht, die man gut gebrauchen könnte, so ist und war der PC doch immer ein Elektronikpuzzle, bei dem man, vor allem, was Spieleentwicklung angeht, immer am besten gefahren, wenn man hier vom "kleinsten gemeinsamen Teiler" ausgeht und erst einmal quasi nur eine "Standard-Spielkiste" voraussetzt.

Seit es Multitasking und Systeme wie Windows gibt, hat man dieses Problem kompensiert, indem man softwareseitige Treiber liefert, damit sich Hardware an keinerlei Standards mehr halten müssen.

Auf einer DOS-Kiste (zumindest, wenn es eine ist, die zum Spielen gedacht ist), kann man (meines Erachtens) inzwischen davon ausgehen, daß mindestens eine VGA-Karte, sowie irgend etwas Soundblaster 2.0-kompatibles drinsteckt (und Tastatur und vielleicht 2-Tasten-Maus). Alles andere ist schon optional und Luxus.

ICH werde damit bei meiner Art zu programmieren schon größere Probleme haben:
1.) Meine größeren Spielprojekte erfordern alle schon mind. 386er (wegen Nutzung der 32bit-Register und Segmentregister FS/GS).
2.) Eine reine ISA-VGA ist VIEL ZU LANGSAM für erträgliches Vollbild-Scrolling bei quasi komplettem Bildaufbau für jedes Frame. Erklärung: Hatte mal eine reine VGA. Im schnellsten Modus (320x200) hatte sie einen Datendurchsatz von ca. 0,5 bis 0,6 MB/sek. Was bedeutet das? Naja. Geht man mal davon aus, daß man eine recht großzügige "Anzeige" ins Bild baut, die sich nicht immer ändert und man nutzt nur ca. 60000 statt der 64000 Pixel bei 320x200 (ist jetzt einfacher für das Rechenbeispiel) dann schafft man genau 10 FPS. Da kann die CPU noch so schnell sein! Diese 10 FPS erreicht man nicht einmal ganz, weil außer dem "Schaufeln der Pixel zur Grafikkarte" ja während der Spielschleife auch noch andere Dinge passieren müssen.
Und ja: Eine langsame Grafikkarte bremst die CPU herunter bei jedem Lese-/Schreibzugriff. Wieso? Nun ja, wenn man etwas an eine Speicherstelle schreibt, "wartet" die CPU, bis das auch wirklich passiert ist.

Will sagen: Das was ich mache und in Xpyderz gemacht habe, erfordert eine Grafikkarte mit wesentlich mehr Power als eine normale VGA. Der Datendurchsatz ist ja nicht unbedingt die "Schuld" der VGA - aber so ein ISA-Port hat eben seine Grenzen...
zatzen hat geschrieben:So werde ich ersteinmal versuchen, die Rechenanforderung für ein Spiel so gering zu halten,
dass es auf 486er Maschinen quasi monolithisch funktioniert, ohne dynamische Verwaltung
von Grafik und Ton, auch wenn man dabei mögliche Performance verschenkt.
Ich verstehe nicht so ganz was Du damit meinst. Was ist die Alternative?
Ich meine: Damit in einem Spiel alles "gleichzeitig aussieht" muß ja immer im Wechsel Grafik und Ton erzeugt werden und auch die Usereingaben sollten ja zyklisch erfolgen, damit ein Spielfluß gegeben ist.
Wie hattest Du es denn in Kotzman II gelöst?
zatzen hat geschrieben:Wie gesagt, für mich ist das etwas neues und ich freue mich ersteinmal darauf, überhaupt
ein nettes kleines Spiel zu haben mit Hintergrundmusik, Soundeffekten und Grafik mit Transparenz.
Naja, das ist ja das, was wir ALLE wollen. Mir geht es ja prinzipiell auch um nichts anderes.
zatzen hat geschrieben:Auch freue ich mich, dass ich Assembler schon etwas besser beherrsche und mich damit
freier bewegen kann als früher.
Ja, es ist irgendwie ein befriedigendes/befreiendes Gefühl, wenn man irgendwann den Eindruck hat, daß man Ahnung hat von dem, was man tut. Ich kann mich auch noch an die schwierigen Anfänge erinnern - auch in BASIC, später dann in Pascal und dann auch in Assembler (bzw verschiedenen Assemblern): Zu Anfang war es oft ein haarsträubendes und zermürbendes "Ausprobieren". Ich muß zugeben, daß es Zeiten gab, wo mir eine bestimmte Formel für etwas einfach nicht einfallen wollte und dann habe ich so lange "an den Werten gedreht", bis es gepaßt hat. Aber es ist kein gutes Gefühl, wenn irgendwas "irgendwie funktioniert" und man selbst nicht nachvollziehen kann, wieso (bzw was man da angestellt hat). Ich kann es irgendwie nicht leiden, Codebereiche in meinem Programmcode zu haben, die "irgendwie gehen" und "Hauptsache nicht anfassen, damit es nicht auseinanderfällt" - aber muß leider sagen, daß es frühere Projekte von mir gibt, wo ich bestimmte Codeblöcke nie wieder anfassen will.
zatzen hat geschrieben:Auch von Vertical Retrace habe ich viel gehört über die Jahre, und klar kann es nervig sein
wenn das Bild schwabbelt, aber das lasse ich erstmal auf mich zukommen.
Naja, ruckelfreies Scrolling ist zwar schön - aber es ist auch schön, wenn es schon überhaupt erstmal scrollt.
Beim PC kann man sich ja nicht unbedingt auf eine einheitliche Wiederholfrequenz des Grafikaufbaus verlassen,
die 70Hz, die der MCGA (der beliebte Mode 13h, 320x200x256) hat, gelten für einen CRT. Auf TFT von Laptops
war der auf 60Hz eingestellt, wie jeder andere Mode. Ich weiß, daß man bei Turrican II für PC (DOS) die
Bildfrequenz sogar EINSTELLEN kann (zwischen 50 und 60 Hz in 1 Hz Schritten).

Aber weiß nicht, ob das auf allen Grafikkarten (auch neueren) noch funktionieren würde oder ob es da z.B.
bei TFT-Bildschirmen sowieso nicht geht...

Fakt ist, daß ich mich inzwischen nicht mehr auf die Bildwiederholfrequenz bei PCs verlasse, sondern das Bild
einfach refreshe, sobald Rechenleistung übrig ist und die "Spielfrequenz" noch nicht erreicht ist (man braucht
nicht 300x pro Sekunde das Bild refreshen, wenn das Spiel nur mit 50 Ticks/sek läuft).

Außerdem ist Scrolling ja an die Bewegung der Spielfigur gebunden (oder beim Raumschiffshooter automatisch
und gleichbleibend). Aber: Scrolling ist nur dann exakt ruckelfrei, wenn es genau synchron zur Bildwiederholfrequenz
des Monitors stattfindet UND nur dann flackerfrei, wenn das Umschalten zur neuen Seite in der Austastlücke (also in oder kurz nach dem Vertical Retrace, also dem Rücklauf des Rasterstrahls von rechts unten nach links oben) erfolgt.
Da der Vertical Retrace nur auf sehr wenigen Grafikkarten einen IRQ erzeugt (man sich darauf also nicht verlassen kann),
das WARTEN auf den VR aber wieder wertvolle Rechenzeit verschwendet, nutze ich das nur, wenn die Messungen ergeben,
daß die Maschine schnell genug ist und selbst dann nur zum Vermeiden des Flackerns, nicht für weiches Scrolling.

Der Grund dafür ist, daß sonst die Scrollgeschwindigkeit (und damit die Spielgeschwindigkeit!) von der eingestellten
Bildwiederholrate des Grafikmodes abhängig wäre - und das kommt für mich nicht in Frage. Somit wird Scrolling auf
meinen PC-Spielen also immer irgendwie ruckeln.

Wie man auch leicht erkennen wird, ist ein 486er selbst mit PCI-Grafikkarte "gerade mal so" in der Lage, 70 Bilder pro
Sekunde zu berechnen - eine gescheite Berechnungsroutine (in Assembler!) vorausgesetzt.

Meine Routinen schaffen die gekachelten Levels (mit 16x16-Pixel Kacheln) im 1-Ebenen-Mode GERADE MAL SO ruckelfrei zu scrollen auf meinem 486er (X5, mit 133 MHz) mit PCI-Grafikarte (mit ca. 16 MB/sek Datendurchsatz). Und auch nur, wenn ich nicht zu viele Sprites anzeige. (Ich generiere die Grafik immer gleich in die Grafikkarte hinein, ohne Zwischenpuffer im RAM.)

Mein Mehrebenen-Mode (also wo ich mehrere Levelebenen transparent hintereinander unterschiedlich scrollen lassen kann) bringt das Ganze schon an seine Grenzen und darüber hinaus. Da hat mein 486er keine vollen FPS mehr - und mein 486er ist eine wahre Mördermaschine, das Motherboard ist das schnellste das ich je erlebt habe, die CPU ist eine 486 X5 (d.h. es ist ein 486er, der schon intern mit Pentium-Technologien gefertigt ist, aber in einen 486er-Slot paßt) und die Grafikkarte ist eben PCI - und Sound macht eine SB AWE 64. Das ist aber schon lange keine "Standard DOS-Kiste" mehr - für so etwas hätte man damals[tm] und früher(C) sicher mal so eben 5000 DM auf den Tresen gelegt - so etwas hätte damals wohl keiner für ein Spiel wie mein Xpyderz getan (d.h. diese Aufrüstung) - selbst wenn er das Geld gehabt hätte.

Leute im DOSforum haben mir ja schon mitgeteilt, daß Xpyderz auf einem 386er mit VGA (was ja die Mindestanforderung dafür ist) quasi fast unspielbar in den FPS runtergeht - selbst im LowRes Modus. Tja - was soll ich dazu sagen? Ich bin eben einfach noch zu schlecht.

Ich optimiere inzwischen aber eher auf "irgendwie einen mittleren Standard erreichen". Weil ich leider alleine entwickle, muß ich irgendwann mal einen "Baukasten aus Routinen" haben (so wie ich ihn habe), aus dem ich ein Spiel zusammenbauen kann. Und meine Level-/Sprite-Routinen sind an sich recht brauchbar, um ein Spiel damit zu bauen. Die könnte ich natürlich auch immer noch weiter und weiter optimieren - und wenn ich damit fertig bin, gefällt mir vielleicht wieder etwas an meinen Soundroutinen oder Steuerroutinen nicht und dann fange ich da auch wieder mit Optimieren an...

Irgendwann wenn ich 70 bin, schreibe ich dann vielleicht das beste und performanteste DOS-Spiel, das die Welt je erlebt hat - und es gibt auf der ganzen Welt noch 8 Rechner, auf denen das Spiel laufen kann - und alleine 5 davon stehen dann bei mir zu Hause... (und die restlichen 3 in Museen über die Welt verteilt - ausgeschaltet, mit einem "Bitte nicht berühren" Schild davor...)

Aber vielleicht will ich ja irgendwann nochmal ein Spiel fertigmachen, das ich selber noch spielen kann - bevor Gicht, Arthritis, Alzheimer oder Tod mich am Spielen hindern.
zatzen hat geschrieben:Ich widme mich derzeit wieder ZVID.
Bisher waren die Schwächen noch:
1. Daten wurden den Decodier-Routinen mündchensmaß in einen Puffer vorkopiert, was die Performance
scmälerte. Das habe ich schon gefixt, die Daten werden jetzt direkt aus dem Stream verarbeitet.
2. Decodiert wird wiederum in einen (64 Byte) Zwischenpuffer, welcher dann erst an entsprechende Position
in den Zielpuffer kopiert wird. Da bin ich gerade dran, das zu ändern.
3. Bisher keine Sprungtabellen, sondern IF-Abfragen. So viele sind es aber nicht.
Naja, hier ist sowieso die Lösung "die Mitte". Tabellen brauchen Speicher, komplexer Code braucht Rechenzeit. Den bestmöglichen Mittelweg zu finden, halte ich für den gescheitesten Ansatz. Und hier ist der Mensch jedem Compiler überlegen: Der Mensch weiß ja, was das Programm tun soll - d.h. welche Art Daten es erwartet, welche Art Daten am häufigsten auftreten werden usw.

Ich selbst z.B. habe bei einem bedingten Sprung immer im Hinterkopf, wie oft die eine oder andere Alternative zutrifft.
Und ich springe dann bei der selteneren Alternative. Sprünge kosten Zeit (leeren den Prefetch-Queue usw.) und bei bedingten Sprüngen passiert das ja nur, wenn die Bedingung erfüllt ist. Da die 80x86 CPUs freundlicherweise für (fast) jede Bedingung auch für die umgekehrte Bedingung einen Befehl bereitstellen, kann man hier dann leicht die umgekehrte Bedingung wählen.

Beispiel: Innerhalb einer Schleife passieren manchmal Dinge und manchmal nicht.
SCHLEIFENANFANG
Irgendwas1
Irgendwas2
Ding_Passiert? - Nein? Dann springe zu @Weiter
Lasse_Ding_Passieren
@Weiter:
Irgendwas3
SCHLEIFENENDE (Wenn noch nicht beendet, gehe zu Schleifenanfang)

Also wird jedesmal, wenn das Ding passiert, der Teil Lasse_Ding_Passieren ausgeführt (Kostet Zeit). Und jedesmal, wenn es nicht passiert, wird darüber gesprungen (Kostet auch Zeit).

Nehmen wir aber an, das Ding passiert recht selten, muß aber trotzdem immer abgefragt werden. Dann ist das meines Erachtens die bessere Variante:

SCHLEIFENANFANG
Irgendwas1
Irgendwas2
Ding_Passiert? - Ja? Dann springe zu @Passieren
@Weiter:
Irgendwas3
SCHLEIFENENDE (Wenn noch nicht beendet, gehe zu Schleifenanfang)
bla....
@Passieren:
Lasse_Ding_Passieren
Springe zu @Weiter

Somit hat man zwar, wenn es passiert, ZWEI Sprünge, aber wenn es nicht passiert, gar keinen Sprung!

Noch besser ist, das Ganze (wenn es möglich ist) an das Schleifenende zu verlagern, also "Irgendwas3" mit an den Anfang - dann geht nämlich das:

SCHLEIFENANFANG
Irgendwas1
Irgendwas2
Irgendwas3
Ding_Passiert? - Ja? Dann springe zu @Passieren
SCHLEIFENENDE (Wenn noch nicht beendet, springe zu SCHLEIFENANFANG)
bla...
@Passieren:
Lasse_Ding_Passieren
SCHLEIFENENDE (Wenn noch nicht beendet, springe zu SCHLEIFENANFANG)

D.h. es gibt zwei Schleifenenden, damit reduziert man aber die Anzahl Sprünge.
Auch eine lustige Lösung ist das:

Springe zu SCHLEIFENANFANG
@Passieren:
Lasse_Ding_Passieren
SCHLEIFENENDE (wenn beendet, springe zu @Raus)
SCHLEIFENANFANG
Irgendwas1
Irgendwas2
Irgendwas3
Ding_Passiert? Ja, gehe zu @Passieren
SCHLEIFENENDE (wenn nicht beendet, springe zu SCHLEIFENANFANG)
@Raus:

Es sind zwar mehr Sprünge, aber außerhalb der Schleife. Innerhalb ist es immer nur 1 Sprung.
Lasse_Ding_Passieren findet (sozusagen) auch am Ende der Schleife statt, wie man sieht:
Wenn das Ding nicht passiert, wird normal das Schleifenende abgefragt und wenn noch nicht erreicht, gibt es den Sprung zum Schleifenanfang. Wenn das Ding DOCH passiert, geht der Sprung zum @Passieren und läßt das Ding passieren, fragt auch ab, ob die Schleife beendet ist, aber springt nur in dem EINEN Fall (dem seltensten, nämlich wenn die Schleife durch ist) und ansonsten nicht - d.h. in dem Fall wird auf den Schleifenende-zu-Schleifenanfang-Sprung verzichtet, weil der Anfang direkt hinter dem Lasse_Ding_Passieren liegt - somit benutzt man einfach die natürliche Abfolge der Befehle dazu, auf diesen Sprung zu verzichten. Der einzige "Stunt" der dazu nötig ist, ist, am Anfang "in die Schleife hinein" (also an SCHLEIFENANFANG) zu springen. Witzigerweise ist dieser Sprung manchmal sogar doppelt nützlich - denn wenn jemand wie ich VOR der Schleife irgendwelchen Code INNERHALB der Schleife modifiziert hat, löscht dieser anfängliche Sprung praktischerweise gleich mal den Prefetch-Queue mit...

Das sind nur so Dinge, auf die ich über die Jahre im Programmieren mit Assembler ganz alleine gekommen bin. Und ich weiß nicht genau, wie z.B. eine Hochsprache eine IF-Abfrage innerhalb einer Schleife umsetzen würde - aber ich bin mir fast sicher: SO bestimmt nicht! Das zum Thema, daß Compiler besser optimieren als Menschen...
zatzen hat geschrieben:Am meisten dürfte im Moment noch Punkt 2 ausmachen.
Ja, wie ich schon sagte: Ich neige gern dazu, gleich alles direkt in den Grafikspeicher zu hauen. Das hat Vor- und Nachteile.
Die zwei Vorteile sind:
1.) Man schreibt nicht zweimal (einmal in einen Zwischenpuffer, einmal vom Zwischenpuffer in den Grafikspeicher).
2.) Man braucht nicht extra Speicher für den Zwischenpuffer.
Die zwei Nachteile sind:
1.) Man überschreibt im Grafikspeicher teilweise Daten, die man schon geschrieben hat (z.B. wenn man Sprites zeichnet vor bereits gezeichnete Hintergründe). Das ist insofern ein Nachteil, daß Speicherzugriffe auf Grafikspeicher langsamer sind als auf normalen RAM. Wenn man das Schreiben/Überschreiben im normalen RAM macht, wird alles, was dann im RAM (Zwischenpuffer) steht, nur einmal zum Grafikspeicher übertragen, das "überschriebene" wird also nicht übertragen.
2.) Man verzichtet auf den Vorteil des schnellen Kopierens mit REP Befehlen - denn für Ort-zu-Ort-Kopieren gibt es ja diese praktischen DS:[SI] -> ES:[DI] MOVs, mit CX als Zähler und REP... Besonders nützlich natürlich bei planarem Grafikspeicher (bei Mode-X müßte man etwas tricksen).
3.) Beim direkten Schreiben in den Grafikspeicher muß man zwingend mit mindestens 2 Bildschirmseiten arbeiten - auf VGA bleibt einem dafür nur der MODE-X, der aber nicht so planar ist, sondern eine etwas komische Speicheranordnung hat (weil er ja eigentlich ein "Hack" ist). Arbeitet man mit Puffern, so kann man auch den MCGA (320x200x256 Planar) benutzen, wenn das Kopieren einigermaßen fix geht.

Wieso arbeite ich trotzdem lieber mit direktem Schreiben in Grafikspeicher?
1.) Ich will einfach nicht so viel wertvollen RAM als zusätzlichen Puffer verschwenden.
2.) Ich will nicht auf 320x200 beschränkt sein - und 360x240 geht z.B. sowieso nur mit Mode-X.
3.) Sobald höhere (VESA) Modi hinzukommen, reicht der normale Heap sowieso nicht mehr für einen Zwischenpuffer aus. Alleine der (eher seltene) 640x400 (es gibt viel öfter den 640x480) braucht schon 256000 Bytes, der 640x480 schon 307200 Byte (300 kB!) - und im RealAddressMode (16bit-Mode) wäre bei über 64kB ja dann sowieso kein "planares" Arbeiten mehr möglich durch die nötigen Segmentwechsel. Da kann man auch gleich die "Banken" in der Grafikkarte wechseln... Und irgendwann wird dann Puffer-Kopieren auch langsamer als das, was durch das "Überschreiben von schon Geschriebenen" ansonsten verlorenginge. 300 kB kopiert auch so'n 486er ja nicht "mal eben so" - zumal, wenn er es vorher auch schon in einen extra RAM geschrieben hatte.

Ja, ich weiß: Meine Programmiertechniken sind altmodisch - fast archaisch: Ich habe das alles dermaßen auf den 16bit-Mode (RealAddressMode) ausgelegt: Keinerlei Beachtung des Protected Mode, mit dem ich Zugriff auf großen planaren Speicher hätte, keinerlei Beachtung der Existenz von Speicher über 1 MB (oder 640 kB) außer per indirektem Zugriff durch HIMEM.SYS - als reinen "Lagerspeicher". Es gibt schon den reinen planaren 64bit-Mode und ich murks hier mit segmentbasiertem 16bit rum. Ist mir alles bewußt. Ich habe über die Jahre und Jahrzehnte jetzt viele Units gebaut und angehäuft, mit denen ich endlich etwas Sinnvolles machen könnte - da entscheidet sich die Industrie zum ersten Mal seit über 30 Jahren, den neuen CPU-Mode (64bit) nicht mehr abwärtskompatibel zu gestalten... Was soll ich dazu sagen?

Ich könnte natürlich "mit der Zeit gehen und immer das Neueste, was es gibt, direkt erlernen - aber ich lerne einfach zu langsam, um alles zu begreifen, und "irgendwie so halb" habe ich keine Lust. Wenn ich das machen wollte/sollte, könnte ich nur mit maschinenfernen Skripten arbeiten und ineffizienten Kram bauen, mit dem ich selbst nicht zufrieden wäre. Dann würde ich viele Spiele der Art "Tetris braucht Quadcore" schreiben, wo sich dann andere freuen, daß ich so viele Spiele rausbringe, ich selbst aber jedes meiner Erzeugnisse abgrundtief hassen würde. Mir geht und ging es ja immer eher um die Maschine - um das Programmieren an sich. Spiele sind quasi ein "Nebenprodukt" davon - auch wenn das jetzt seltsam klingt. Spiele sehe ich als eine programmiererische Herausforderung an, da sie Kenntnisse und Fähigkeiten auf vielen verschiedenen Gebieten erfordern - und dann auch noch die Fähigkeit, diese ganzen Einzelteile zu einem Gesamtwerk zu vereinigen, das insgesamt in den Speicher paßt und mit der vorhandenen Rechenleistung auskommt.

Aber aus vorhandenen Fertigteilen Spiele bauen - da entgeht mir ja das für mich Interessanteste: Die Programmierung. Wenn ich manche der vielen "Game-Maker" Spiele so sehe, die im Internet kursieren: Die verwenden eine fertige Engine, es gibt vorgefertigte Grafiken, sie brauchen nur irgendwelche Songs in MP3 oder Effekte in welchem Format auch immer nehmen, weil eine interne Engine die alle abspielen kann (macht ja nix, wenn das ganze Ding deshalb 120 MB groß wird...) das einzige, was sie selbst machen, ist die Levels zusammenzuklicken und eine lockere Geschichte drumherum zu bauen. Ja, auch das macht sicher Arbeit - aber das ist das an der ganzen Entwicklung für mich Uninteressanteste.

Vielleicht bin ich wirklich eher der Typ, der einen Game-Maker bauen sollte und den Rest anderen Leuten überlassen...
Andererseits gibt es ja bereits genügend Game-Maker - und die Sparte User, die so etwas heutzutage benutzt, hat sicher kein Interesse daran, einen Game-Maker für DOS-SPIELE haben zu wollen.
zatzen hat geschrieben:Ich habe mit ZSM diese Aninmation mit der Ente (HIT_ANY) vertont, es ist eine Bildschirmfüllende
Animation, es läuft im Grunde schnell und flüssig, aber stellenweise stottert es wenn man die
Emulation auf 386SX Niveau einstellt. Ich werde das im ZVID Thread hochladen wenn ich den Viewer
optimiert habe.
Cool. Freue mich schon darauf.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Eins Vorweg: Bei dem Gegrübel ob ein Spiel oder irgendwas im technischen Mantel von vor
25 Jahren sich lohnt oder gerechtfertigt ist, bin ich zu einen Schluss gekommen. Und zwar:
- Ich programmiere mit dem System, mit dem ich aufgewachsen bin,
und für das, was ich umsetzen möchte, genügt mir die Leistung.
- Ich will nichts verkaufen, also kann es mir egal sein wenn nicht
mehr als ein kleiner Kreis die Ergebnisse sehen will.
- DOS Programmierung macht mir mehr Spass, weil Assembler dort
noch Sinn macht, und man sich überhaupt Routinen selber schreibt
bei denen man sich in Windows vernünftigerweise nur fertigen,
von Experten geschriebenen Bibliotheken bedienen würde.
So wie ich es sehe besteht die Programmierung eines Spiels
in Windows lediglich aus objektorientierter Hochsprache.
- Als ich 9 war hatten wir den ersten PC, eine Art 286er mit 10 Mhz.
Da hatte man noch ein Gefühl dafür, dass die Software gut programmiert
war, denn wenn man da geschludert hätte wäre nichts gut gelaufen.
Und ich habe ja selber mit meinen eigenen ersten Gehversuchen in
BASIC ein Gefühl dafür bekommen, was ein 286er so kann.


Damit, dass mein Spiel "monolithisch" funktionieren soll und zwar bspw. ab einem 486er
meine ich, dass ein 486er Grundvoraussetzung sein soll, damit das Spiel keine Aussetzer
hat. Dynamisch angelegt könnte man es zwar auch auf einem 386er lauffähig halten, indem
man die Framerate drosselt sobald es eng wird mit dem Rechenaufwand, aber vorerst
würde ich eben einfach einen 486 voraussetzen und wer einen 386er hat, hat eben
"Pech gehabt", da ruckelt dann die Grafik und stottert auch der Ton, anstatt dass nur
die Grafik ruckelt.
Monolithisch also deshalb, weil ich einen 486er und schnelle VGA voraussetze, als Minimum,
und dann wäre garantiert dass das Spiel so flott läuft wie ein Konsolenspiel, ohne Ruckeln
oder sonstwas.
Bei Kotzman II hatte ich ja gar keinen Grafikpuffer und somit einen sehr geringen
Datendurchsatz, das Spiel funktioniert auch auf 286ern, wenn vielleicht stellenweise etwas
langsam. Also dort waren Themen wie Ruckeln gar nicht gegeben.

ZVID: Es ist schon merklich schneller, jetzt wo ich es umgeschrieben habe dass die Blöcke
direkt in den Ausgangspuffer (oder Video RAM) geschrieben werden. Allerdings ist die
Berechnung der Adressen noch umständlich, es werden erst mit MOD und DIV und zwei
SHL 3 aus dem Blockzähler für die ASM Routinen Koordinaten berechnet, und in den
Assembler Routinen dann unter Einsatz von MUL eine Adresse berechnet.
Das mache ich beides gleich mal raus, indem ich es durch Zähler ersetze.

Assembler: Ist schon fasznierend dass man da selbst tüfteln kann um die Performance
zu verbessern. Ich habe ja auch ein Assembler-Buch, und da stehen für jeden Befehl
auch die Takte drin, je nach Konstellation.
Aber gerade das mit Sprüngen ist mir erst jetzt bewusst geworden.

64 Bit-Cpus: Wenn man mal auf Youtube diverse "Let's Plays" verfolgt, dann trifft man da
nicht selten auch auf DOS Spiele aus den 90er Jahren. Somit ist da zumindest noch ein
gewisses Publikum, das den Emulator DOSBox bemüht. Mein letzter Pentium hat leider
vor ein paar Jahren auch schlapp gemacht, weshalb ich mich auch DOSBox bediene. Dann
habe ich noch einen Laptop, der kann noch DOS, allerdings keinen Soundblaster.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

zatzen hat geschrieben:Eins Vorweg: Bei dem Gegrübel ob ein Spiel oder irgendwas im technischen Mantel von vor
25 Jahren sich lohnt oder gerechtfertigt ist, bin ich zu einen Schluss gekommen. Und zwar:
- Ich programmiere mit dem System, mit dem ich aufgewachsen bin,
und für das, was ich umsetzen möchte, genügt mir die Leistung.
Ja, so geht es mir auch. Und ich versuche immer, die Leistung und Speicher, die nur wirklich benötigt wird,
vorauszusetzen, als immer mit der Monsterhardwarekeule draufzuhauen, nur weil man zu faul zum Optimieren ist.
zatzen hat geschrieben:- Ich will nichts verkaufen, also kann es mir egal sein wenn nicht
mehr als ein kleiner Kreis die Ergebnisse sehen will.
Ach, das Thema "Verkaufen" war für mich zu keiner Zeit jemals eine Option.
Ich finde es nur ein wenig schade, daß meine Spiele wohl nie von "Spielern" gespielt werden werden, sondern
eher von Leuten, die sich aus "Retro"-Gründen so Sachen ansehen oder vielleicht die Entwicklerleistung
würdigen o.ä. werden (weil DOS-Enthusiasten) - die aber das Spiel nicht "um das Spiels willen" spielen werden.
Das ist es, was ich meinte. (Hoffe, ich konnte das irgendwie verständlich machen.)
zatzen hat geschrieben:- DOS Programmierung macht mir mehr Spass, weil Assembler dort
noch Sinn macht, und man sich überhaupt Routinen selber schreibt
bei denen man sich in Windows vernünftigerweise nur fertigen,
von Experten geschriebenen Bibliotheken bedienen würde.
Naja, einerseits gibt es auch unter DOS (bzw auch unter vielen anderen OS)
fertig geschriebene Bibliotheken - andererseits ist das kein Grund, nicht selbst eine zu schreiben.
Und auch die unter Windows/Linux/wasweißich geschriebenen Bibliotheken wurden von irgendwem
geschrieben - und ab wann jemand ein "Experte" ist, ist sowieso eher subjektiv.
zatzen hat geschrieben:So wie ich es sehe besteht die Programmierung eines Spiels
in Windows lediglich aus objektorientierter Hochsprache.
Naja, man kann auch unter Windows und in jeder anderen Sprache und System immer auch in
Assembler programmieren - macht auch dort Programme schneller.... - ABER:
In Assembler geschriebene Programme oder Programmteile sind in der Regel nicht portierbar.
Wenn etwas nicht portierbar ist, bedeutet das im Umkehrschluß, daß das Programm oder der
Programmteil auf einem anderen System (wenn portiert werden soll), komplett neu geschrieben
werden müß. Egal ist das dann, wenn man sowieso nicht systemübergreifend programmieren will.
Leute, die mit Programmen und Programmierung/Softwareentwicklung allgemein Geld verdienen
wollen, wissen aber, daß portable Programme auf mehr Plattformen lauffähig gemacht werden
können - bei nur einmaliger Programmierung. Somit reduziert man die Mühe und maximiert den
Gewinn. Daß solche Programme oft nicht einmal ansatzweise die vorhandene Leistung der
entsprechenden Systeme richtig ausnutzen, liegt einfach in der Natur der Sache - und wird damit
kompensiert, indem man Leute, die sich nicht ständig neuere leistungsfähigere Systeme kaufen,
als dumm und rückständig beschimpft.
zatzen hat geschrieben:- Als ich 9 war hatten wir den ersten PC, eine Art 286er mit 10 Mhz.
Da hatte man noch ein Gefühl dafür, dass die Software gut programmiert
war, denn wenn man da geschludert hätte wäre nichts gut gelaufen.
So ist es. Und jedem, der sich Programmierer nennen will, würde ich immer wieder empfehlen,
immer mal wieder zu "den Basics" zurückzukehren, um von seinen abgehobenen systemfernen
Skripten mal wieder "in Maschinennähe" zu kommen - damit er ab und zu mal wieder ein Gefühl
für richtige Programmierung bekommt. Nur eine persönliche Meinung meinerseits - aber ich finde,
durch solche Sachen könnte so ineffizienter speicherfressender Mist, wie er heutzutage häufig anzutreffen
ist und auch noch als "der Weisheit letzten Schluß" bewundert wird, vermieden werden.

Es wird ja immer wieder behauptet, die modernen Sprachen und Compiler sind so gut, daß ein Mensch
sie nicht mehr übertreffen könne. Wenn ich dann aber sehe, wie z.B. dieser hochgelobte DotNet-Kram
performt (bzw NICHT performt), dann würde ich da gerne mal ein paar Argumente von den betreffenden
Leuten dazu hören - das wäre sicher spannend...
zatzen hat geschrieben:Und ich habe ja selber mit meinen eigenen ersten Gehversuchen in
BASIC ein Gefühl dafür bekommen, was ein 286er so kann.
Meine BASIC-Zeiten waren auf den KC85-Rechnern (DDR-Rechner) und auf C64. Auf PC habe ich nie BASIC
programmiert, da hatte ich gleich mit Pascal angefangen. Das lag u.a. auch daran, daß dieser "Informatik"-
Unterricht, den wir hatten, auch in Pascal lief. (Zu der Zeit war ich schon ca. 6 Jahre mit anderen Rechnern
unterwegs.)
zatzen hat geschrieben:Damit, dass mein Spiel "monolithisch" funktionieren soll und zwar bspw. ab einem 486er
meine ich, dass ein 486er Grundvoraussetzung sein soll, damit das Spiel keine Aussetzer
hat. Dynamisch angelegt könnte man es zwar auch auf einem 386er lauffähig halten, indem
man die Framerate drosselt sobald es eng wird mit dem Rechenaufwand, aber vorerst
würde ich eben einfach einen 486 voraussetzen und wer einen 386er hat, hat eben
"Pech gehabt", da ruckelt dann die Grafik und stottert auch der Ton, anstatt dass nur
die Grafik ruckelt.
Naja, hatte ja bereits mal erwähnt, daß ich z.B. nicht mit dem Soundframeticker ein Spiel timen würde.
Und selbst bei 486ern gibt es ja auch eine ganze Bandbreite von möglichen MHz-Raten bei CPUs und auch
bei Grafikkarten sind nicht alle auch wirklich schnell, da gibt es auch ziemliche "Krücken".

Mein Credo war ja von jeher, dem "Rechner-Wettrüsten" entgegenzuwirken und auch auf "LowEnd"-Maschinen
noch lauffähige Software zu produzieren. Daß es natürlich IMMER eine Untergrenze geben wird, ist klar.
Bei einem gedachten Spielinhalt und einer bestimmten festgelegten Mindestqualität von Grafik und Sound ist
eben trotzdem eine technische Untergrenze gegeben, unter der gar nichts mehr funktionieren würde.

Wenn man das auf PC nicht will, kann man nur 8086er-Spiele programmieren - dann natürlich aber auch nur
solche, die mit 4,77 MHz CPU, Original VGA (bzw Original Hercules-Karte) auskommen...
Hier muß wohl jeder selbst sehen, wo er die Untergrenze für seine Spiele legen will.

Daß der 386er meine Untergrenze (zumindest bei größeren Projekten) ist, liegt weniger daran, daß die Performance
meiner Spiele so ist, daß ein 386er für 100% Leistung ausreicht - sondern eher an der Verwendung von 32bit Registern
und erweiterten Segmentregistern (FS/GS) - was jeder 286er und darunter mit Absturz (bzw Fehler-INTs) quittieren
würde. "Lauffähigkeit auf 386ern mit VGA" meiner Spiele bedeutet dabei nur, daß die Software dort läuft ohne
abzustürzen - jedoch nicht zwangsläufig auch mit voller Performance.

Da gibt es dann auch weiterhin ein Optimum und Maximum. Selbst auf meinem 486er läuft Xpyderz nicht mit
absoluter Höchstperformance. Aber in Xpyderz gibt es ja auch 8-Wege-Scrolling und bis zu 1600 freibeweigliche
Objekte (Sprites), die im ganzen Spielfeld (auch den gerade nicht sichtbaren Bereichen) agieren und interagieren
(Kollisionsabfrage!) - da bin ich schon froh, daß es auf meinem 486er so vergleichsweise gut performt.
zatzen hat geschrieben:Monolithisch also deshalb, weil ich einen 486er und schnelle VGA voraussetze, als Minimum,
und dann wäre garantiert dass das Spiel so flott läuft wie ein Konsolenspiel, ohne Ruckeln
oder sonstwas.
Naja, das setze ich eher als "Optimum" voraus. Erklärung: Ich benutze absichtlich keine 486er-Opcodes
(obwohl ich es könnte), um die Mindestanforderung 386er nicht zu überschreiten. Der 486er ist für meine
Spiele als eher ein "386er, nur schneller".
zatzen hat geschrieben:Bei Kotzman II hatte ich ja gar keinen Grafikpuffer und somit einen sehr geringen
Datendurchsatz, das Spiel funktioniert auch auf 286ern, wenn vielleicht stellenweise etwas
langsam. Also dort waren Themen wie Ruckeln gar nicht gegeben.
Da Kotzman II nicht scrollte, nehme ich an, daß wirklich nur die beweglichen Objekte bewegt wurden
und somit eine geringere Datenmenge dauernd zu übertragen war - es wurde also nicht jedes Frame das
komplette Bild neu gezeichnet.
zatzen hat geschrieben:ZVID: Es ist schon merklich schneller, jetzt wo ich es umgeschrieben habe dass die Blöcke
direkt in den Ausgangspuffer (oder Video RAM) geschrieben werden. Allerdings ist die
Berechnung der Adressen noch umständlich, es werden erst mit MOD und DIV
Ich hoffe, Du benutzt hier Assembler - wo DIV und MOD quasi mit demselben Befehl abgearbeitet werden
(Ergebnis und Divisionsrest werden beide gespeichert, in verschiedenen Registern). In Hochsprachen gibt
es DIV und MOD Befehle, jeder der beiden führt die gleiche Division aus - der erste wirft den Rest weg,
der zweite das Ergebnis... Wenn man das erstmal weiß, findet man es ärgerlich, nicht wahr?
zatzen hat geschrieben:und zwei SHL 3 aus dem Blockzähler für die ASM Routinen Koordinaten berechnet, und in den
Assembler Routinen dann unter Einsatz von MUL eine Adresse berechnet.
Das mache ich beides gleich mal raus, indem ich es durch Zähler ersetze.
Ja, kleinere Multiplikationen kann man z.B. durch Tabellen ersetzen.
zatzen hat geschrieben:Assembler: Ist schon fasznierend dass man da selbst tüfteln kann um die Performance
zu verbessern. Ich habe ja auch ein Assembler-Buch, und da stehen für jeden Befehl
auch die Takte drin, je nach Konstellation.
Ja, in ASM86FAQ.TXT stehen auch die Takte drin. Für alle Rechner von Pentium, 486er, 386er, 286er und 8086er -
außerdem (wo nötig) auch noch getrennt für RM und PM. Ebenfalls auch noch, welche Flags sich ändern und in welcher
Weise. Bei manchen "komplexeren" Befehlen auch nochmal in "Pseudo-Code", was diese ausführen und in welchen
Schritten.
Sehr nützliches Nachschlagewerk - unbedingt zu empfehlen für jeden ASM-Programmierer.
zatzen hat geschrieben:Aber gerade das mit Sprüngen ist mir erst jetzt bewusst geworden.
Naja, in manchen so "Lern"-Büchern werden so "interne" Sachen gar nicht so erwähnt. Zu Anfang neigt man in
ASM dazu, andauernd haufenweise Sprünge einzubauen (ja, ging mir anfangs auch so). Das liegt einfach daran, daß
man von Hochsprachen diese ganzen IF-Kaskaden so gewöhnt war, daß man dies Vorgehensweise insinktiv in Assembler
irgendwie "nachbaut". Daß man in Assembler oft andere, viel bessere Möglichkeiten hat, wird einem erst später klar.

Für den Assembler-Anfänger ist das nur so "Hochsprache, nur schneller und mit anderen Befehlen". Man fängt erst nach einer Weile an, darüber nachzudenken, was der Kram, den man so macht, ganz direkt mit/in der CPU anrichtet.
zatzen hat geschrieben:64 Bit-Cpus: Wenn man mal auf Youtube diverse "Let's Plays" verfolgt, dann trifft man da
nicht selten auch auf DOS Spiele aus den 90er Jahren.
Naja, das liegt an der derzeit allerorts umhergreifenden Retro-Welle. Das ist (meiner Meinung nach) eher eine Art
"Modeerscheinung". Heute ist man "cool", wenn man retro mag...
zatzen hat geschrieben:Somit ist da zumindest noch ein gewisses Publikum, das den Emulator DOSBox bemüht.
Mein letzter Pentium hat leider vor ein paar Jahren auch schlapp gemacht, weshalb ich mich auch DOSBox bediene.
Dann habe ich noch einen Laptop, der kann noch DOS, allerdings keinen Soundblaster.
DOSbox ist für mich lediglich die letzte Instanz. Wenn es auf allem anderen läuft, teste ich, ob es auch in DOSbox
läuft. Was ich nie wollen würde: Irgendwann mal ein DOS-Programm schreiben, das zwar in DOSbox lauffähig ist,
aber nicht mehr auf einer echten DOS-Maschine.

Um das nicht falsch zu verstehen: Ich respektiere DOSbox - die Entwickler haben da wirklich großartiges geleistet -
auch für DOS und dessen Fans, aber auch, um die vielfältig vorhandene Software "am Leben zu erhalten".
Aber: Bewiesen, ob etwas gut ist und funktioniert, ist Software erst, wenn sie sich auf der wahren Hardware
bewiesen hat.
Benutzeravatar
zatzen
DOS-Guru
Beiträge: 518
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von zatzen »

Um meinem Ziel eines Spiels etwas näher zu kommen habe ich mir ein wenig
Gedanken gemacht und dabei entschieden, dass ich kein Scrolling machen möchte.
Ich würde es eher ähnlich Kotzman II halten, nur mit Hintergrundgrafiken und
dass sich die erkundbare Welt auch vertikal erstreckt. So ähnlich wie bei
Cauldron II. Natürlich muss dann nicht alles nach Dungeon aussehen, man
kann ja auch eine "Oberwelt" erschaffen.
Lediglich würde ich eben kein Scrolling verwenden - möglicherweise aber,
wie es in manchen Spielen, wie beim alten NES Zelda der Fall ist, ein
schnelles "Einschieben" des anderen Bildschirms, ohne dass währenddessen
etwas passiert.

Dieses "überall hingehen können wo man will", also eine Welt in allen
Himmelsrichtungen erkunden, das hat mich als Kind fasziniert und war
der Grund, warum ich auf dem Nintendo Zelda haben wollte, obwohl
ich damit nervlich total überfordert war.

Grundsätzlich bin ich aber nach wie vor von der Idee begeistert, ein Spiel
als "Modul" aufzuziehen, ich will ja nicht sagen Game-Maker, denn so simpel
wäre meiner nicht zu bedienen.
Aber ich würde mich wohl auf dieses "Dungeon" Jump&Run Genre festlegen,
und dass ich sozusagen einen Player oder sagen wir eine generelle Engine
habe, die nur noch Daten braucht. Sicherlich kommt es einem erstmal
sehr wirr vor wenn man dran denkt wie man Cutscenes reinbringen will
oder überhaupt die ganzen verschiedenen Möglichkeiten an Waffen etc.
Aber man muss auch irgendwo mal Grenzen setzen.
Für Lucasarts Spiele gibt es ja ScummVM, und der Vorteil davon ist,
das es portierbar ist. So wäre mein System mit entsprechend
angepasstem "Player" auch portierbar, falls sich überhaupt mal
jemand dafür interessieren sollte.

ZVID habe ich übrigens soweit fertig optimiert, es kann jetzt auch
spiegeln, aber da jetzt noch Clipping zu integrieren wäre sehr schwierig.
Vielleicht siehst du das anders, aber mir erscheint das so komplex,
dass ich meine, der Aufwand lohnt sich nicht.
Daher würde ich es nur für die Hintergründe nutzen und mir für die
Sprites etwas anderes ausdenken.

Ansonsten programmiere ich eigentlich nur für mich selbst, naja immerhin
habe ich wenigstens einen Freund den das auch begeistert (auch wenn er
selbst kaum Ahnung vom Programmieren hat) - er möchte gern mal ein
personalisiertes Spiel für einen anderen Freund machen, mehr als Gag.
So ein Modulsystem wo man sich nur auf Grafik, Leveldesign und Sound
konzentrieren muss erniedrigt zumindest für mich die Hürde, ein Spiel
zu machen. Oder anders gesagt, ich kann mich beim Programmieren einer
solche Engine besser auf die Optimierung konzentrieren, als wenn
ich alles hardcoden muss. Naja, denke ich zumindest.
Werde ich ja sehen.

Jedenfalls motiviert mich, dass mein ZSM Player so schön funktioniert.
mov ax, 13h
int 10h

while vorne_frei do vor;
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

zatzen hat geschrieben:Um meinem Ziel eines Spiels etwas näher zu kommen habe ich mir ein wenig Gedanken gemacht und dabei entschieden, dass ich kein Scrolling machen möchte.
Naja, ich habe auf dem PC auch noch kein "echtes" Scrolling realisiert. Bei Xpyderz zeichne ich einfach jedes Frame komplett neu.
Es gäbe ja auch die Möglichkeit, die Fähigkeiten der VGA richtig auszureizen und mit den Softscroll-Registern (horizontal) bzw dem Bildschirmposition (Start-) register (vertikal) herumzuspielen. Dann müßte man die Scanlinie 8 Pixel breiter machen und den "gesamten" Bildbereich 8 Pixel höher. Aber in dem Fall könnte man eine generalisiertere Block-Pixel-Routine benutzen, die auf "ganze 8" ausgelegt ist.

Man kann natürlich auch die Scanlinie ganz breit machen, dann könnte man im Mode-X (320x200) einen 1280x200 breiten Level darstellen. Oder man läßt sie bei 200 - mit den Y-Positionsregistern (bzw Bildstart) wäre das Level dann 320x800. Oder man macht beides in Kombination, jeweils die Hälfte - und hätte ein 640x400 Pixel Level, das man innerhalb des 320x200 Fensters beliebig hin und her scrollen könnte. Dann müßte man die "Sprites" eben mit "Setzen und Löschen" machen, aber bräuchte ansonsten nie das Level immer wieder zeichnen, außer wenn sich etwas ändert.
Ich selbst benutze eher Double- oder Triple- Buffering: Ich zeichne jedesmal das komplette Bild neu (im gerade nicht angezeigten Grafikkartenspeicherbereich) und schalte dann auf das Bild um...
(So handhabe ich es auch mit dem Sound.)
zatzen hat geschrieben:Ich würde es eher ähnlich Kotzman II halten, nur mit Hintergrundgrafiken und dass sich die erkundbare Welt auch vertikal erstreckt. So ähnlich wie bei Cauldron II. Natürlich muss dann nicht alles nach Dungeon aussehen, man kann ja auch eine "Oberwelt" erschaffen.
Lediglich würde ich eben kein Scrolling verwenden - möglicherweise aber, wie es in manchen Spielen, wie beim alten NES Zelda der Fall ist, ein schnelles "Einschieben" des anderen Bildschirms, ohne dass währenddessen etwas passiert.
Ja, so geht es natürlich auch. Naja, wie gesagt, die Wahl der Mittel ist stets dem Programmierer überlassen. Auch gegen ein Spiel mit festen Bildschirmen ist nichts einzuwenden. Technische Dinge wie Scrolling sind es nicht, an dem ich Spielspaß bemesse.

Anmerkung dazu:
Mein C64-Spiel "Rockus" ist auch ein Jump&Run ohne Scrolling. Die Screens werden weitergeschaltet. (9 Level mit je 3 Unterleveln, jedes mit 16 Bildschirmen - also insgesamt 432 Levelseiten).
Jedes der 9 "Hauptlevel" hatte andere Musik und andere Grafik.
Es gab immer 32 Blocks (immer aus 4 "Zeichen" zusammengesetzt, also 16x16 Pixel, bzw 8x16, weil im Multicolor die Pixel doppelt breit sind). Jeder Screen hatte 20x10 Blocks.
Ich hatte das mit dem Scrolling damals irgendwie noch nicht so richtig drauf und war auf C64 im Assembler noch eher Anfänger - das Ganze ist eher viel Basic mit wenigen Assembler-Subroutinen.
Falls Du es mal sehen willst, ist im C64/Spiele Bereich auf meiner Website. Läuft auch auf C64-Emulatoren.
zatzen hat geschrieben:Dieses "überall hingehen können wo man will", also eine Welt in allen Himmelsrichtungen erkunden, das hat mich als Kind fasziniert und war der Grund, warum ich auf dem Nintendo Zelda haben wollte, obwohl ich damit nervlich total überfordert war.
Ja, und inzwischen gibt es dieses "überall hingehen können" sogar auch im 3D-Bereich. Ich frage mich da immer wieder, wo die Leute die ganzen Daten dafür speichern...
zatzen hat geschrieben:Grundsätzlich bin ich aber nach wie vor von der Idee begeistert, ein Spiel als "Modul" aufzuziehen, ich will ja nicht sagen Game-Maker, denn so simpel wäre meiner nicht zu bedienen.
Im Gegensatz zu meinen Anfängen (als ich noch keine richtigen Konzepte hatte und immer eher so "drauflos programmiert" habe) bin ich inzwischen ein großer Freund modularer Programmierung. (Außer vielleicht bei ganz winzigen Projekten - minimalen Kommandozeilentools oder so,)

Bei größeren Projekten kommt man meiner Meinung nach um modularen Aufbau gar nicht herum - sonst verliert man sich wirklich hoffnungslos im Chaos.

Ich bin ganz froh, daß ich inzwischen viele nützliche "Units" gebaut habe, die ich zu einem Programm/Projekt "zusammenschrauben" kann. Auch für das Programm selbst schreibe ich dann oft noch eine "spezialisierte" Unit, falls das Programm/Spiel besondere Dinge benötigt, die ich noch nicht in einer Unit habe, weil sie z.B. zu speziell auf das Spiel bezogen wären. Im "Hauptprogramm" habe ich dann quasi nur noch die "Hauptschleife", die die ganzen Sachen immer wieder zyklisch abarbeitet und die bei Bedarf die "Kommunikation" zwischen den einzelnen Unterprogrammen (falls erforderlich) regelt.

Ob man das ganze nun in einen Game-Maker packt oder nicht, wäre nur noch eine Frage, ob man die entsprechenden Tools/Oberflächen dafür auch noch bauen will - oder ob man ohne Game-Maker quasi das Spiel selbst "zusammenschraubt".

Zumindest teilweise wird man aber wohl IMMER auf Game-Maker-artige Dinge zurückgreifen: Wer will heutzutage schon noch wirklich Levels als irgendwelche Zahlenkolonnen in Hex-Editoren oder ähnlichem eingeben? Und wer wird schon Sprites in Datenform entwickeln? Oder wer wird Musiken in reiner Datenform für einen Player in die Konsole hacken? Aber das ist dann eben einfach eine Definitionsfrage, ab wann ist es ein Game-Maker und ab wann nur ein Haufen Tools?

Beispiele aus meinem eigenen Entwicklungsbereich:
* TheGame3 ist ein Tool um Levels, Levelgrafiken und Sprites zu erstellen, ebenfalls um "Spawnpunkte" der Sprites im Level festzulegen. Es legt aber NICHT die Bewegungen oder Reaktionen der Sprites fest - maximal kann man den Sprites einen "Typ" zuweisen.
-> Dazu gehört dann ARCADE01 - eine Unit mit einer Sammlung von Subroutinen, die Levels und Sprites darstellen kann.

* GS2ASM ist ein Tool, um Sprite- (also Figuren)- Bewegungen zu steuern, Kollisionen abzufragen und darauf zu reagieren, ebenfalls natürlich mit Spielerdaten (Boni, Waffen, etc. pp.). Damit gibt man aber die Daten nur ein - in einer Assembler-ähnlichen Programmiersprache. Das Ergebnis ist dann ein Block von Daten, quasi ein Programm in Bytecode. (Ich hatte immer mal ein BASIC-Frontend dazu angedacht, aber ich komme einfach zu nichts. Dieser Job, den ich habe, kostet mich viel Lebenszeit und Kraft. Ich rechne auch schon gar nicht mehr damit, daß irgend jemand anderes jemals eines meiner Tools benutzen wird - da wäre es mir um den Aufwand eines Frontends, das ich vielleicht selbst gar nicht nutze, doch etwas zu schade.)
-> Dazu gehört dann GAMESYS2 - das ist ein großer in 100% Assembler gebauter Klotz, der diese "Sprache" interpretiert und ausführt, sozusagen ein Bytecode-Interpreter.

* prISM ist das neue Tool, um Musiken/Soundeffekte zu erstellen, es ist eine Art "Pseudo-Tracker" - weil es eben nicht wie ein normaler Tracker arbeitet. Die Musikdaten sind quasi auch wie eine Art "Programm": seriell hintereinander angeordnet die Noten (inkl. Abspiellängen), aber zusätzlich unterstützt mit vielen Hilfsbefehlen, die man nutzen KANN, aber nicht MUß.
-> Dazu gehört ISM - das ist ebenfalls ein großer in 100% Assembler gebauter Klotz, der die Musikdaten quasi in "Wave-Daten" (in einem Puffer, optimalerweise mind. Double-Buffering) wandelt, also in etwas, das von einer Soundhardware abgespielt werden kann.

Es gibt natürlich noch ein paar andere Tools:
* PI, ein Malprogramm - um z.B. Sprites und Levelelemente zu zeichnen. Diese können dann mit TheGame3 "ausgeschnitten" werden.
* Wav2Smp, um WAVs in Samples im ISM-Format (*.SMP) zu wandeln, mit diversen Vorgaben, sowie das Frontend dazu: SndCheck, in dem man das WAV vorher beschneiden, anhören und auf die richtige Referenztonhöhe stellen kann.
Es gibt noch viele kleine ebenfalls nützliche Tools, die man alle u.a. auch für die Spieleprogrammierung nutzen könnte und kann.

Und selbstverständlich könnte man jetzt quasi "um die Tools herum" so einen Maker basteln, der diese aufruft, die Daten quasi zwischen diesen "vermittelt" und ein Endergebnis erstellt - nur, damit es dann nach außen wie ein "Game-Maker" aussieht. Aber bisher habe ich den Aufwand dafür immer gescheut: Das verbraucht nur zusätzlichen Speicherplatz, den man dann nicht mehr für die Grafik/Sound/Level-Daten u.ä. frei hätte und alles nur, damit man so ein schickes "Gesamtkonzept" hat, das nach Game-Maker aussieht. Ich habe das Problem, daß ich sowieso schon zu nichts komme und froh bin, daß ich das, was ich bisher habe, schon geschafft habe. Mit anderen Worten: Es wäre auch schön, endlich mal wieder ein Spiel zu programmieren/entwickeln - nicht nur die Tools dazu...
zatzen hat geschrieben:Aber ich würde mich wohl auf dieses "Dungeon" Jump&Run Genre festlegen, und dass ich sozusagen einen Player oder sagen wir eine generelle Engine habe, die nur noch Daten braucht.
Prinzipiell wäre es für mich wohl kein Problem mehr, so einen "Spiel-Klotz" zu erstellen, der quasi nur noch Daten braucht. Allerdings muß ja sowieso auch jemand die Daten machen - die sind ja nicht "einfach so da". - Und da kommen wir dann wieder dazu, daß man sich in der Welt der Editoren aufhält, um die Daten zu erstellen - ob es nun ein ganzes Game-Maker-Paket ist oder eine Sammlung von Tools.

So ein "Spiel-Klotz" (also eine EXE, die eben mit verschiedenen Daten laufen könnte) ist technisch zwar machbar - allerdings ist man dann jederzeit auf die fest definierten Dinge beschränkt, die die EXE supportet. Das kann man zwar auch ausweiten "bis zur Unendlichkeit und noch viel weiter"[tm] - muß aber, realistisch gesehen, natürlich immer berücksichtigen, daß Speicher und Rechenleistung keine unendlich vorhandenen Ressourcen sind und daher immer Einschränkungen hingenommen werden müssen.

Der kleine Vorteil, wenn man keinen "Spiel-Klotz", sondern ein "programmiertes" Spiel hat, ist der, daß man selbst festlegen kann, ob und wieviele Ressourcen den jeweiligen "Diensten" (Grafik, Sound, Steuerung, Sonstiges wie Zwischenanimationen u.ä.) zugewiesen werden. Das gibt einem bei der Art des Spiels mehr Handlungsspielraum. (Weglassen schafft Speicher/Rechenzeit. In generalisierten Routinen sind eben dann auch Dinge enthalten, die man vielleicht gar nicht braucht - und die dann Speicher belegen, den man lieber für Grafikdaten oder Samples verwendet hätte.)
zatzen hat geschrieben:Sicherlich kommt es einem erstmal sehr wirr vor wenn man dran denkt wie man Cutscenes reinbringen will oder überhaupt die ganzen verschiedenen Möglichkeiten an Waffen etc.
Naja, es ist alles nur immer eine Frage, wo man es speichert und wie man es abspielt. Verschiedene Waffen sind meiner Meinung nach ein eher kleines Problem. In Xpyderz kostet es mich nur recht wenig Aufwand, eine neue Waffe einzubauen, weil ich das Ganze schon so aufgebaut hatte - und das, obwohl Xpyderz "hard-coded" ist (also kein Bytecode. Damals gab es zwar schon ARCADE01, aber noch kein GameSys2).

Mit GS2ASM/GameSys2 wird das Ganze jetzt noch einen Zacken einfacher: Alles "was sich bewegt", kann generalisiert abgearbeitet werden, Darstellung und Steuerung von Sprites laufen in unterschiedlichen Programmteilen ab. Ob ein Objekt eine Waffe, der Spieler, ein Feind, ein Bonus o.ä. ist, ist nur eine Sache von Typen oder Flags, die man selbst setzen kann. Und da GameSys2 bereits eingebaute Mechanismen zur Kollisionsabfrage (und Reaktion darauf) enthält, erübrigt sich hier eine Menge manueller Aufwand und "drumherumprogrammieren".
zatzen hat geschrieben:Aber man muss auch irgendwo mal Grenzen setzen. Für Lucasarts Spiele gibt es ja ScummVM, und der Vorteil davon ist, das es portierbar ist.
Ja, aber auch ScummVM ist beschränkt auf alles, was es "bis dato" unterstützt. Die Scumm-Engine ist von den Machern immer weiterentwickelt worden und ScummVM muß alle Features supporten, damit es funktioniert. Wenn Lucas-Arts ein neues Spiel herausbringen würde mit neuen Features einer erweiterten Scumm, müßten auch die Entwickler der ScummVM die entsprechenden Features wieder einbauen, damit das entsprechende Spiel läuft. Es gibt gerade in diesem "Skript"-Bereich selten etwas, das derart "allgemein" gehalten wurde, daß es mit jeder Neuerung "einfach so" zurechtkommt.

Im Gegensatz zu anderen spielte für mich Portierbarkeit bei der Entwicklung meiner Programme immer eine untergeordnete - oder besser: nicht vorhandene - Rolle. Sollte ich z.B. wirklich mal eines meiner Spiele vom PC auf C64 portieren wollen, würde auf C64 so ziemlich alles "hardcoded" werden und alle Daten würden sehr rigoros konvertiert werden müssen. Anders wäre eine annehmbare Lösung für mich nicht denkbar. Aus finanziellen Gründen werden Portierungen heutzutage allzuoft "generalisiert" gemacht - ohne Ausnutzung systemisch gegebener Besonderheiten, das schränkt Performance und Möglichkeiten - im Klartext: die Qualität - portierter Programme/Spiele oft viel mehr ein als es nötig wäre.
zatzen hat geschrieben:So wäre mein System mit entsprechend angepasstem "Player" auch portierbar, falls sich überhaupt mal jemand dafür interessieren sollte.
Naja, das träfe auf viele Sachen zu. Ein Programm-Klotz mit Daten-Klotz (also beides getrennt, bzw. trennbar) wäre natürlich ideal zur Portierung. Man emuliert dann nur den Programm-Klotz (also das Programm, das die Routinen zur Steuerung, Soundausgabe, Grafikanzeige usw. enthält) und kann mit unverändertem Daten-Klotz portieren.
Der kleine Nachteil ist (wie erwähnt) lediglich, daß eventuelle Vorteile, die aus bestimmten Eigenheiten des Entwicklungssystems entstehen (z.B. x86 PC mit VGA und SB) auf anderen Systemen mit fremder Technik nicht mehr zum Tragen kommen, da es dann hier sein kann, daß Daten, deren Format für x86 CPUs, VGAs und SBs in exzellenter Form vorliegen, auf einer VM dann eventuell aufwendig für die Fremdhardware gewandelt und an diese übergeben werden müßten, die die Daten vielleicht in einem anderen Format erwartet. Dinge wie diese sind ja unter anderem der Grund, wieso Emulatoren oft das Vielfache (100-1000 fache) der Leistung des Originalgeräts benötigen, um dessen Spiele in Echtzeit darzustellen.
zatzen hat geschrieben:ZVID habe ich übrigens soweit fertig optimiert, es kann jetzt auch spiegeln, aber da jetzt noch Clipping zu integrieren wäre sehr schwierig.
Ich weiß nicht, was Du in diesem Zusammenhang mit Clipping meinst. Betrifft das das "Verhalten am Bildrand" (z.B. bei halb-gescrollten "Kacheln")? Wie oben erwähnt gäbe es hier auch die Möglichkeit, die Besonderheiten der VGA-Register auszunutzen. Da könnte ich helfen - besonders mit diesem Kram kenne ich mich inzwischen ziemlich gut aus.
zatzen hat geschrieben:Vielleicht siehst du das anders, aber mir erscheint das so komplex, dass ich meine, der Aufwand lohnt sich nicht.
Daher würde ich es nur für die Hintergründe nutzen und mir für die Sprites etwas anderes ausdenken.
Achso. Naja, ich weiß nicht genau, was Du meinst. Also für etwas, das keine Animation ist, sondern etwas interaktives, sind so "Delta-Film" artige Animationsformate meiner bescheidenen Meinung nach eher weniger geeignet. Da müßte man jede mögliche Bewegung und jeden möglichen Weg schon vorberechnen und quasi als "Film" abspeichern - allein beim Gedanken an die (selbst mit guten Packverfahren) zu erwartende schiere Datenmenge stehen mir die Haare zu Berge.
Für Zwischensequenzen dagegen - vor allem, wenn es "schön" sein soll - also nicht nur "Sprite hampelt vor fixem Hintergrund herum", sondern eher, daß sich alles miteinander ergänzt - wären so Animationsformate wie eben ZVID dagegen ideal.
Ich finde es nur etwas schade, daß Du Dich hier auf diese statische 8:8:4-Palette beschränken willst - da gäbe es auch andere Möglichkeiten.
zatzen hat geschrieben: Ansonsten programmiere ich eigentlich nur für mich selbst, naja immerhin habe ich wenigstens einen Freund den das auch begeistert (auch wenn er selbst kaum Ahnung vom Programmieren hat) ...
Naja, mich z.B. begeistert es IMMER, wenn auch andere Leute heutzutage privat programmieren - und ganz besonders, wenn es sich dabei nicht nur um Skripten oder Batch-schreiben oder HTML, sondern wirkliche nativ auf CPU ausführbare Dinge handelt.
zatzen hat geschrieben: ... er möchte gern mal ein personalisiertes Spiel für einen anderen Freund machen, mehr als Gag.
Naja, wenn man sieht, was für einen Aufwand es macht, selbst ein recht simples Spiel zu bauen, das auch wirklich als Spiel bezeichnet werden kann, dann sollte man, wenn es "nur als Gag" ist, schon ziemlich viele vorgefertigte Sachen (Subroutinen/Bibliotheken/Units, wie auch immer man es nennen will) haben, aus denen man schöpfen kann. Für "nur als Gag" würde ein so "aus der Kalten heraus"-Projekt wohl am Ende wahrscheinlich länger brauchen, als der Gag lustig ist. An so einer Stelle wäre natürlich ein generalisierter Ansatz von Vorteil.
zatzen hat geschrieben:So ein Modulsystem wo man sich nur auf Grafik, Leveldesign und Sound konzentrieren muss erniedrigt zumindest für mich die Hürde, ein Spiel zu machen. Oder anders gesagt, ich kann mich beim Programmieren einer solche Engine besser auf die Optimierung konzentrieren, als wenn ich alles hardcoden muss. Naja, denke ich zumindest. Werde ich ja sehen.
Ja, sehe ich ja genauso. Deshalb arbeite ich ja auch modular. Ich hatte allerdings auch schonmal angedacht eine Art "eierlegende Wollmilchsau"-EXE aus meinen Units zu erstellen, die dann einen Datenblock nachladen (oder anlinken) kann, der dann das komplette Spiel (also alle Daten) enthält - quasi das, was Dir wahrscheinlich auch vorschwebt. Aber, wie bereits mehrfach erwähnt: Auch diese Daten müßten ja erstmal entwickelt werden. Ich bin ja leider auch eher so ein "Engine-Bastler" als ein Spiele-Macher.
zatzen hat geschrieben:Jedenfalls motiviert mich, dass mein ZSM Player so schön funktioniert.
Ja, wenn man mal wieder etwas zum Funktionieren gebracht hat, das motiviert natürlich zum Weitermachen - ist besser als das ewige Debuggen von irgendwelchem Kram, den man "kaputtoptimiert" hat oder so. Manchmal habe ich schon Zeug einfach nochmal bei Null angefangen, wenn ich gemerkt habe, daß ich ständig dabei bin, mein eigenes Zeug zu "workarounden" - und habe es dann gleich richtig gemacht. Aber wenn so ein mühsam erstelltes Ding endlich auch mal tut, was es soll, das ist (um es mit den Manta-Fahrern zu sagen) "wie wennze fliechst".

Als ich damals meine 3D-Engine gebaut habe und ich dann irgendwann damit durch Doom-Level laufen konnte (mit Wand/Boden/Deckentexturen und Beleuchtung! sowie ein paar Gimmicks wie z.B. eine Kamera) - da hab ich so im übertragenen Sinne gedacht "SEHT HER: ICH BIN BATMAN! NUR NOCH COOLER!"
Ja, ich weiß: In Wirklichkeit bin ich ein Freak...

Btw: In nicht allzuferner Zeit werde ich dann mal mein prISM (der "Pseudo-Tracker", siehe oben) der Öffentlichkeit zugänglich machen. Ein paar kleine Funktionen fehlen noch, aber im Großen und Ganzen ist es fertig. Vielleicht bekommt ja doch mal irgendwer Lust, sich damit am Komponieren zu versuchen...
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Trackermodul-Engine (sehr einfach)

Beitrag von DOSferatu »

Hallo, Zatzen!
Ich habe da mal eine technische Frage:
Ich löse im Interrupt, den der Soundblaster wirft (wenn er mit dem Puffer fertig ist) das Abspielen des neuen Puffers aus.
(Selbstredend arbeite ich mit Doublebuffer, also der Puffer, der gerade gespielt wird, ist schon fertig berechnet und der neue wird erst berechnet, wenn er im anderen angefangen hat zu spielen.)
Ich benutze DMA-Modus $48.

Bei höheren Frequenzen habe ich aber trotzdem so ein Klicken beim Pufferwechsel. Kennst Du das Problem? Wie kann das verhindert werden?
wobo
DOS-Guru
Beiträge: 613
Registriert: So 17. Okt 2010, 14:40

Re: Trackermodul-Engine (sehr einfach)

Beitrag von wobo »

DOSferatu hat geschrieben:Hallo, Zatzen!
Ich habe da mal eine technische Frage:
Ich löse im Interrupt, den der Soundblaster wirft (wenn er mit dem Puffer fertig ist) das Abspielen des neuen Puffers aus.
(Selbstredend arbeite ich mit Doublebuffer, also der Puffer, der gerade gespielt wird, ist schon fertig berechnet und der neue wird erst berechnet, wenn er im anderen angefangen hat zu spielen.)
Ich benutze DMA-Modus $48.

Bei höheren Frequenzen habe ich aber trotzdem so ein Klicken beim Pufferwechsel. Kennst Du das Problem? Wie kann das verhindert werden?
Du weisst, dass bei den alten Soundblastern (SB 20, SB PRO und kombatible) mit DSP Versionen 2.00-3.99 grundsätzlich der DMA - Autoinit mode ($48) nur bis Frequenzen bis 22kHz funktioniert? Erst ab DSP Version 4.xx ist laut Creative die Unterstützung von Frequenzen > 22 kHz vorgesehen. Alte Soundblaster - jedenfalls DSP Vers. 2.01-3.01 - können Frequenzen > 22 khz nur im besonderen HighSpeed-DMA-Mode. (Meiner Erfahrung nach können die meisten kompatiblen Soundblaster Pro, die nicht von Creative sind, ab DSP Ver. 3.02 auch Frequenzen > 22khz im standard DMA Autoinit mode (alles ditto für standard DMA single cycle)).

Du weisst, dass der DMA - Controller nur physikalisch seitenübergreifend arbeiten kann, d.h. dass er Daten nur entweder innerhalb der ersten 64kb, der zweiten 64kb, der dritten 64kb usw. übertragen kann? Die Segmentierungstechnik der 8086 cpu kann der DMA controller gerade nicht. Ich habe da bisher keine andere Lösung gefunden, als diejenige, dass ich einen doppelt so grossen Speicherbereich allokiere, als ich ihn eigentlich für double buffering benötige und dann den Beginn des Buffers innerhalb des allokierten Bereichs so wähle, dass eben keine Überschreitung einer 64k-Grenze stattfinden kann.
Antworten