Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 439
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon zatzen » Do 6. Feb 2020, 21:52

Hallo Thomas!

Während der Programmlaufzeit die Uhr "Up to Date" halten fühlt sich für mich einfach irgendwie besser an, und es sind ja auch nur ein paar Zeilen Code mehr. Es könnte ja auch sein, dass man Highscores oder sonstiges speichert, und dann ist es irgendwie schöner, wenn Datum und Uhrzeit der Dateien stimmen.

Und ja genau, meine Unit bietet beides, so wie es in Basic war und aber auch so, dass nur ein Flag gesetzt wird und Du dann in der Hauptschleife btplay_playtick (entspricht der Basic Gosub BT.Play, habe es playtick genannt weil pro Aufruf einen 50 Hz Tick weitergegangen wird) "selber" aufrufst, wenn btplay_next_tick = true. Diese Boolean-Variable kannst Du auch als Flag nutzen wann es im Spiel weitergehen soll. Wenn Du die Musik lieber "im Hintergrund" hast und trotzdem noch eine Flag-Variable haben willst, muss man das in der introut_playtick nur ergänzen (mov btplay_next_tick, 1).
Der Grund warum man so eine Abspielroutine in die Hauptschleife verlegen könnte wäre der, dass die Routine ein "wenig" lang ist für ne ISR, daher war ja auch meine Intention das ganze durch Assembler wenigstens etwas zu verkürzen und zu beschleunigen. Bis jetzt sind die IF-Kaskaden und die Variablenzuweisungen da drin noch 1:1 vom Original übernommen, aber insofern schon optimiert, dass die Offsets für die Array-Zugriffe nicht immer wieder neu berechnet werden und überhaupt etwas intelligenter mit den Registerinhalten umgegangen wird.

Ja, Set/GetIntVec schreibt/liest nur je einen Pointer an ner Adresse, wäre blöd gewesen dafür extra die Unit DOS zu brauchen.
DOSferatu
DOS-Übermensch
Beiträge: 1172
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon DOSferatu » Do 6. Feb 2020, 21:58

Naja, INT-Vektoren setzen/holen ist ja wohl total einfach. Geht in Pascal oder Assembler. Man sollte nur beim Setzen vorher CLI und nachher STI machen (damit während des Setzens nicht der Interrupt zuschlägt).
Und wo die Vektoren liegen, dürfte ja wohl klar sein: Ganz vorne. (also bei $0000:$0000 bis $0000:$03FF)
In Pascal also:

Code: Alles auswählen

var INTVEC:array{0..255]of Pointer absolute $0000:$0000;

und damit holen/setzen.

in Assembler (mit Pascal-Header) zB sowas:

Code: Alles auswählen

funktion SetGetVec(IntNr:byte;NewVec:Pointer):Pointer; assembler;
asm
pushf
cli
push ES
xor BX,BX
mov ES,BX
mov BL,IntNr
shl BX,2
mov AX,ES:[BX]
mov DX,ES:word ptr[BX+2]
db $66;mov CX,word ptr NewVec
db $67;jcxz @NoSet
db $66;mov ES:[BX],CX
@NoSet:
pop ES
popf
end;

Setzt einen neuen Vektor(wenn er nicht NIL (also 0:0) ist und gibt jederzeit den alten zurück.
Macht also beides gleichzeitig und beides kann "ignoriert" werden. Wenn man nur Vektor holen will:

Code: Alles auswählen

OldVector:=GetSetVec(Nr,NIL);

Wenn man nur Vektor setzen will:

Code: Alles auswählen

GetSetVec(Nr,OwnVector);

Wenn man beides will:

Code: Alles auswählen

OldVector:=GetSetVec(Nr,OwnVector);

Wie wär's damit?
(Hab ich nur mal fix zusammengetackert.)
Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 439
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon zatzen » Do 6. Feb 2020, 22:24

Eine sehr elegante Funktion. Könnte in Zukunft bei mir Einzug halten als Ersatz für das was Pascal bietet.
Aber ich hab eben nur erstmal eine Umgehung der DOS-Unit gesucht und es für den Timer hardgecodet:

Code: Alles auswählen

procedure set_timer_vec(p: pointer); assembler;
asm
   xor ax, ax; mov es, ax
   db 66h; mov ax, word ptr p
   cli; db 66h; mov es:[32], ax; sti
end;

Und so ähnlich für's "getten".
In der Get-Routine wird noch abgefragt, ob schonmal gegettet wurde und dann eben nicht mehr, sonst verliert man hinterher das Original.

EDIT: JCXZ, hatte ich schon ganz vergessen weil ich es in Loops nie brauchte. Damit kann ich ja die Sprungkaskaden von BTPLAY noch etwas optimieren. Dieses db 067h ist das richtig davor? Oder doch db 066h? Also weil man ECX will...
Benutzeravatar
Thomas
BIOS-Flasher
Beiträge: 381
Registriert: Mi 22. Jun 2016, 12:29
Wohnort: Nähe von Limburg / Lahn
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon Thomas » Fr 7. Feb 2020, 11:38

Zatzen hat geschrieben:Es könnte ja auch sein, dass man Highscores oder sonstiges speichert, und dann ist es irgendwie schöner, wenn Datum und Uhrzeit der Dateien stimmen.

Ist ein stichfestes Argument das ich total außen vor gelassen habe.
Zatzen hat geschrieben:Der Grund warum man so eine Abspielroutine in die Hauptschleife verlegen könnte wäre der, dass die Routine ein "wenig" lang ist für ne ISR, daher war ja auch meine Intention das ganze durch Assembler wenigstens etwas zu verkürzen und zu beschleunigen. Bis jetzt sind die IF-Kaskaden und die Variablenzuweisungen da drin noch 1:1 vom Original übernommen, aber insofern schon optimiert, dass die Offsets für die Array-Zugriffe nicht immer wieder neu berechnet werden und überhaupt etwas intelligenter mit den Registerinhalten umgegangen wird.

Klar, Optimierung ist immer gut aber um diese Jagd nach dem Topspeed nachzuvollziehen, fehlt mir die nötige Kenntnis. Ich kenne bisher nur Basic, bzw. Habe damit mein erstes, großes Programm geschrieben und wenn meine Grafik 30FPS stemmt trotz der "langsamen" Musik Abspielroutinen, denke ich mir, langt doch. Klar, knapperer Code bringt auch immer weniger Speicherhunger mit sich.
zatzen hat geschrieben:Ja, Set/GetIntVec schreibt/liest nur je einen Pointer an ner Adresse, wäre blöd gewesen dafür extra die Unit DOS zu brauchen.

DAS stimmt allerdings.

Dosferatu hat geschrieben:Naja, INT-Vektoren setzen/holen ist ja wohl total einfach.

Stimmt, sagte ich bereits.
Dosferatu hat geschrieben:Und wo die Vektoren liegen, dürfte ja wohl klar sein: Ganz vorne. (also bei $0000:$0000 bis $0000:$03FF)

Ja, ist auch klar.
Dosferatu hat geschrieben:Wie wär's damit?
(Hab ich nur mal fix zusammengetackert.)

Super. Praktische, kleine Routine.

zatzen hat geschrieben:Dieses db 067h ist das richtig davor? Oder doch db 066h? Also weil man ECX will...

En waaaas? :shock:
Ein bisschen DOS kann oft mehr als ein Haufen Fenster.

Gigabyte GA-586HX, P54C 100@75MHz, 24MB RAM, AVGA3-22-1M ISA, RTL8029AS PCI, Goldstar Prime 2 ISA, MA5ASOUND, Dreambl. X2 DB, HD 4x2GB, 48x CD, 3,5" Floppy, 2xRS232, 1xPar., PS/2 Maus
Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 439
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon zatzen » Fr 7. Feb 2020, 18:56

Thomas hat geschrieben:Klar, Optimierung ist immer gut aber um diese Jagd nach dem Topspeed nachzuvollziehen, fehlt mir die nötige Kenntnis. Ich kenne bisher nur Basic, bzw. Habe damit mein erstes, großes Programm geschrieben und wenn meine Grafik 30FPS stemmt trotz der "langsamen" Musik Abspielroutinen, denke ich mir, langt doch. Klar, knapperer Code bringt auch immer weniger Speicherhunger mit sich.

Wirklich wichtig ist Geschwindigkeit z.B. bei Sprite-Routinen. Wie nötig das mit der Übersetzung der Player Routinen nach Assembler war sei mal dahingestellt, aber es gibt mir ein besseres Gefühl wenn das möglichst knapp gehalten wird, und ich habe das einfach mal aus einem Idealismus heraus gemacht, auch weil ich eine Weile lang nicht mehr programmiert habe, hatte einfach Lust drauf. Als ich zuletzt in echtem Dos programmiert habe hatte ich einen Pentium 200 MMX, der frisst sich natürlich so ziemlich durch alles schnell durch, und so ist es keine Kunst für so einen ein Spiel zu schreiben das performt.

So ein db 66h im Assembler-Code ist ein Operand-Size Prefix. In Pascal sind erstmal alle Zugriffe auf 16 Bit Daten ausgelegt. Will ich jetzt aber ein 32 Bit Register verwenden (also z.B. ECX statt CX), muss ich vor einer entsprechenden Anweisung ein db 66h schreiben. Also man könnte es so erklären, "db 66h; mov ax, 0" entspricht letztlich "mov eax, 0". Der integrierte Assembler von Pascal kennt eax, ebx, ecx usw. nicht, daher muss man das so machen.
Benutzeravatar
Thomas
BIOS-Flasher
Beiträge: 381
Registriert: Mi 22. Jun 2016, 12:29
Wohnort: Nähe von Limburg / Lahn
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon Thomas » Fr 7. Feb 2020, 19:38

Aaah ok, alles klar. Ein workaround sozusagen. Stimmt, nur 286 kompatibel, da war etwas.
Idealismus find ich Klasse. Ich mein, ich wollte das ja auch nicht kritisieren, es kam nur so ehrgeizig rüber. Ich will halt kein professionelles DOS Spiel machen wie es seiner Zeit zB von LucasArts kam.
Danke für die Aufklärung.
Ein bisschen DOS kann oft mehr als ein Haufen Fenster.

Gigabyte GA-586HX, P54C 100@75MHz, 24MB RAM, AVGA3-22-1M ISA, RTL8029AS PCI, Goldstar Prime 2 ISA, MA5ASOUND, Dreambl. X2 DB, HD 4x2GB, 48x CD, 3,5" Floppy, 2xRS232, 1xPar., PS/2 Maus
DOSferatu
DOS-Übermensch
Beiträge: 1172
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon DOSferatu » Sa 8. Feb 2020, 02:20

Kurze Erklärung: Bei JECXZ (im Gegensatz zu JCXZ) würde man ja Präfix $66 erwarten, das stimmt. Aber bei DIESEM EINEN Befehl hat intel sich damals wohl für $67 entschieden - keine Ahnung wieso, aber es ist definitiv so - vielleicht, weil es ein Sprung ist, vielleicht weils der einzige bedingte Sprung ist, der nicht auf ein Flag, sondern ein generelles Register reagiert... keine Ahnung. Aber für Wandlung von JCXZ in JECXZ muß es definitiv mit Präfix $67 erfolgen.
(Als es damals, wo ich das ausprobiert habe, mit db $66 nicht ging, war ich schon davon ausgegangen, daß es unter 16bit gar nicht möglich ist, damit auf ECX zu reagieren. Dann hatte ich recherchiert und das mit der $67 herausgefunden.)

Achja, noch was:
1. Ich finds schade, daß man damit nur auf =0, aber nicht auf <>0 prüfen kann.
2. Bei dem Befehl muß man beachten, daß es von dem Befehl (JCXZ/JECXZ) NUR eine SHORT JMP Variante gibt (also max. -128 bis +127 Bytes vor/nach dem Befehl), d.h. kein NEAR JMP (-32768..+32767).

Noch etwas zu CALLs (weil die Frage aufkam): CALLs im gleichen ASM-Block sind (außer wenn anders angegeben) immer NEAR. Und die NEAR brauchen auch maximal ne Handvoll Zyklen (auf 486er z.B. 3, auf 386er ein paar mehr). Mehr Zyklen brauchen schon FAR CALLs. Die meisten werden für so Taskwechsel gebraucht (klar). Aber sowas machen wir ja nicht unter 16bit-DOS.
Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 439
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon zatzen » Sa 8. Feb 2020, 19:56

Ich habe gestern den Code aktualisiert mit ein paar JCXZ hier und da, und da ist mir das mit dem Short Jump auch begegnet, es gab einen "Fehler beim erzeugen des Codes". Habe ich mir dann aber gedacht dass eben nur short jumps möglich sind.
Danke für die Erklärung mit den CALLs und dem 67h, letzteres ist ja etwas verwirrend das es ja eigentlich ein Address Size Prefix ist.
Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 439
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon zatzen » Do 13. Feb 2020, 23:37

Ich habe eine neue Version: http://www.zatzen.net/btp11.zip

Ich hatte Lust, nochmal etwas an der Komprimierung der Patterns zu ändern.
Vorher war es ja so, dass ich einfach pro Pattern für jede Zeile ein Bit hatte, das angab ob die Zeile genutzt wird oder nicht. Also für 64 Zeilen 64 Bits, macht 8 Byte. Dadurch musste das Auslesen auch sequentiell erfolgen. Ich habe das jetzt auf den ersten Blick etwas komplizierter gemacht, aber letztlich ist es zum einen deutlich effektiver und man hat sozusagen "Random Access", wodurch sich das Auslesen der Patterns vereinfacht.

Nur falls Dich das näher interessiert:
Die neue Kompression greift umso stärker, je redundanter die Inhalte sind. Die Redundanzen werden rausgekürzt und die Ereignisse (also Byte-Triplets) in einer Tabelle gehalten. Das ergibt z.B. oft so um die 16 verschiedene Zeileneinträge pro Pattern. Manchmal mehr, manchmal aber auch nur eine Hihat, das wird dann besonders klein. Um richtig aus so einer Tabelle zu lesen braucht man jetzt noch pro Zeile, also 64x, eine Referenz in die Tabelle, und die muss jeweils nur so viel Bits haben wie zur Indizierung in die Tabelle nötig. Also wenn die Tabelle 9-16 Positionen hat dann braucht man 4 Bit, hat die Tabelle aber z.B. nur 2 Einträge (wie o.g. Beispiel mit Hihat) dann reicht 1 Bit. Also ergeben sich z.B. für ein Pattern mit 16 verschiedenen Ereignissen 3 x 16 + 0,5 (4 Bit) x 64 Zeilen = 80 Bytes, im Vergleich zu 192. Bei nur zwei verschiedenen Ereignissen ergibt sich 3 x 2 + 1/8 x 64 = 14 Byte statt 192. Grenzwertig wird es wenn es auf die 32 verschiedenen Ereignisse zugeht, dann haben wir 3 x 32 + 5/8 x 64 = 96 + 40 = 136 ... aber es lohnt sich noch. Bei 64 verschiedenen Ereignissen kann man natürlich nicht mehr komprimieren, allerdings noch für den Fall 33 verschiedene Ereignisse, 33 * 3 + 6/8 x 64 = 99 + 48 = 147 und noch ein bisschen weiter. Worst case wäre 64 verschiedene, dann haben wir 192 + 48 Byte, also 48 mehr, kommt aber eigentlich nie vor. Dann braucht es noch zwei Offsets und eine Information über die Bitbreite, das sind pro Pattern 5 Bytes.

So, aber ich denke das genügt jetzt auch, Deine Stage-Musik braucht als PCS jetzt nur noch 3476 Bytes auf dem Heap.

Von den Instrumenten werden auch nur noch die benötigten geladen.

Und ich habe hier und da noch etwas optimiert, und die Interrupt-Player-Routine setzt auch die Flag-Variable, so dass man ein Spiel danach takten könnte, auch wenn die Musik "von selbst" spielt.

Ich empfehle jedenfalls, im Endergebnis PCS Dateien (oder nenne sie wie Du willst) zu nutzen, weil die Konvertierung spürbar langsam ist ("loadmod" konvertiert ja beim Laden in das komprimierte Format, weil der Player dafür ausgelegt ist), und wie gehabt, load_pcs zu nutzen und loadmod nicht, erzeugt deutlich weniger Kompilat.
Benutzeravatar
Thomas
BIOS-Flasher
Beiträge: 381
Registriert: Mi 22. Jun 2016, 12:29
Wohnort: Nähe von Limburg / Lahn
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon Thomas » Fr 14. Feb 2020, 00:01

Ja super!
Damit ich das richtig verstehe: Ich baue mir wie gehabt mein Mod und wenn es fertig ist lasse ich deinen Konvertierer darüber laufen damit ich das gewünschte PCS erhalte? Muss ja so sein da der Tracker noch kein PCS kann.

zatzen hat geschrieben:Von den Instrumenten werden auch nur noch die benötigten geladen.

Gute Idee aber leider unnötig. Wenn man im Tracker Instrumente erstellt, sie aber im Mod nicht nutzt, speichert der Tracker die nicht mit ab.
Ein bisschen DOS kann oft mehr als ein Haufen Fenster.

Gigabyte GA-586HX, P54C 100@75MHz, 24MB RAM, AVGA3-22-1M ISA, RTL8029AS PCI, Goldstar Prime 2 ISA, MA5ASOUND, Dreambl. X2 DB, HD 4x2GB, 48x CD, 3,5" Floppy, 2xRS232, 1xPar., PS/2 Maus
Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 439
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon zatzen » Fr 14. Feb 2020, 00:28

Ja genau, ein MOD (oder PIS) fertig machen und zu PCS konvertieren.

Instrumente: Damit meinte ich, dass nur so viel Speicher reserviert wird wie benötigt, um die Anzahl der Instrumente zu halten. Vorher hatte ich das statisch auf 32 Instrumente gemacht, weil Instrument 32 (Stille) im Player benötigt wird. Hab ich jetzt anders gelöst.
Benutzeravatar
Thomas
BIOS-Flasher
Beiträge: 381
Registriert: Mi 22. Jun 2016, 12:29
Wohnort: Nähe von Limburg / Lahn
Kontaktdaten:

Re: Allgemeine Hilfestellung zum Programmieren unter DOS gesucht

Beitragvon Thomas » Fr 14. Feb 2020, 06:18

Ach so, ja jetzt hab ich es verstanden. Cool.
Ein bisschen DOS kann oft mehr als ein Haufen Fenster.

Gigabyte GA-586HX, P54C 100@75MHz, 24MB RAM, AVGA3-22-1M ISA, RTL8029AS PCI, Goldstar Prime 2 ISA, MA5ASOUND, Dreambl. X2 DB, HD 4x2GB, 48x CD, 3,5" Floppy, 2xRS232, 1xPar., PS/2 Maus

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste