Wir OpenAccess-User kennen ja alle das Problem:
Wenn man oavision in der NTVDM unter windows startet, dann geht die CPU-Last auf 100% und oa tut solange nix, bis man PAUSE + ENTER drückt, dann startet es. Ein lästiges Problem, was leider auch im dosemu unter Linux auftritt. Der Workaround mit PAUSE+RETURN geht zwar unter Windows, unter Linux über ein Terminal funktioniert das mit dem Pause aber leider nicht mehr.
Grund genug, das Problem zu analysieren und zu beheben.
Ich habe mich also mit meinem Debugger mal auf die Suche gemacht und bin dabei auf folgende Schleife gestoßen, in die ich eigentlich immer reingekommen bin. Ich habe sie rudimentär kommentiert, damit man hoffentlich auch als Assembler-Unkundiger ungefähr versteht was hier los ist:
Code:
cs:1B28 BB0100 mov bx,0001
cs:1B2B 32E4 xor ah,ah
cs:1B2D CD1A int 1A ; Get System Time
cs:1B2F 52 push dx
cs:1B30 8BC3 mov ax,bx
cs:1B32 B9F10A mov cx,0AF1
cs:1B35 E2FE loop 1B35 ; AF1mal einfach hier loopen
cs:1B37 48 dec ax
cs:1B38 75F8 jne 1B32 ; Schleife je nach Systemtime
cs:1B3A 32E4 xor ah,ah
cs:1B3C CD1A int 1A ; Nochmal systemtime holen
cs:1B3E 59 pop cx
cs:1B3F 3D0100 cmp ax,0001 ; Mitternacht vergangen?
cs:1B42 74E4 je 1B28 ; ..dann nochmal
cs:1B44 2BD1 sub dx,cx ; Differenz errechnen
cs:1B46 83FA02 cmp dx,0002
cs:1B49 7307 jnb 1B52 ; >=2, dann ok
cs:1B4B F8 clc
cs:1B4C 43 inc bx
cs:1B4D 73DC jnb 1B2B
cs:1B4F BBFFFF mov bx,FFFF ; Return -1, Fehlgeschlagen
cs:1B52 36891E3219 mov ss:[1932],bx
cs:1B57 CB retf ; Und Ende
Aufgefallen ist mir, dass, sobald ich in den Debugger reingebreakt bin und dann den Programmfluss fortgesetzt habe, OA relativ schnell da war. Nur wenn mans einfach so aufgerufen hat wieder die hohe CPU-Auslastung. Denkt man dann an den Workaround mit PAUSE+ENTER wird einem schnell klar, was hier abläuft: Drückt man PAUSE, hält man temporär den Programmfluss an, drückt man eine beliebige Taste setzt man ihn wieder fort. Durch das kurzfristige Anhalten bewirkt man, dass zwischen den beiden "Get System Time" - Aufrufen eine Unterbrechung entsteht. Wenn wir dann noch die Geschwindigkeit heutiger Rechner und der Rechner vergleichen, für die OA entwickelt wurde kommt man zu dem Schluss: Die Differenz ist auf modernen Systemen und in der VDM ziemlich lange <2, was bewirkt, dass die Funktion sehr lange loopt.
Das Umgehen des Problems ist dann auch schnell mit einem 1-Byte-Patch getan:
PHP-Code:
1) Open Access IV beenden
2) Öffnet die OA4.SPI oder die CMP.SPI je nachdem was ihr patchem wollt
mit einem Texteditor der auch HEX Suche kann.
3) Sucht nach: 3D 01 00 74 E4 2B D1 83 FA 02 und ändert den Wert
ganz hinten von 02 auf 00
Update 28.11.2008:
Das Ganze funktioniert übrigens auch für die Runtime CMP.SPI. Der Patcher berücksichtigt nun auch die Runtime. Assembler-Sourcecode vom Patcher gibt's auf Anfrage...
Doch halt! Update 07.12.2008:
Wie Leser Gerd unten richtig bemerkt hat, funktioniert dann das Music-Kommando nicht mehr richtig, da die verbleibende Wartezeit 1 ist!
Für einene saubereren Workaround also bitte
unten meinen Artikel lesen.
Ich habe meinen angehängten Patcher in patch.zip entsprechend auf die neue Methode aktualisiert, dieser Patch überspringt nicht nur die lästige Warteroutine am Programmanfang sondern korrigiert auch das Timing-Verhalten.
Bitte vor dem Patchen die OA4.SPI sichern, sicher ist sicher...!
Beim Debuggen ist mir dann auch aufgefallen, warum oa4.exe im Vergleich mit oavision relativ langsam läuft:
OA4 verwendet zur optimierten Bildschirmausgabe Informationen über den Vertical Retrace aus dem VGA I/O Port 3DAh. Dies funktioniert zwar auf einer echten VGA-Karte sehr schnell, wenn man das Ding allerdings in der NTVDM laufen lässt kann man den I/O Port nicht direkt abfragen und die VDM muss das Syncen übernehmen, was sehr langsam ist. Daher die verzögerte Ausgabe. Wen's interessiert kann sich
The vertical retrace durchlesen. OAVISION verwendet hingegen einen Videotreiber, welcher die Ansteuerung übernimmt und da fällt das Ganze dann weg.
Der Code ist im Prinzip folgender:
Code:
cs:2BEA BADA03 mov dx,03DA ; I/O Port 03DA
cs:2BED 2E8B0E202C mov cx,cs:[2C20]
cs:2BF2 AD lodsw
cs:2BF3 8BD8 mov bx,ax
cs:2BF5 EC in al,dx ; Einlesen
cs:2BF6 D0D8 rcr al,1 ; Sync?
cs:2BF8 72FB jb 2BF5 ; Nein, dann nochmal.
cs:2BFA EC in al,dx
cs:2BFB D0D8 rcr al,1
cs:2BFD 73FB jnb 2BFA
Wer auch dieses "Problemchen" beheben will: Es reicht, den Sprung in der ersten einfach
einfach auszuNOPpen.
Also für die Hexeditor-Benutzer: Suche nach
und ersetze die zwei folgenden Bytes
durch
.
Bequemer geht's wieder mit angehängtem Patch vdmpatch.zip. Auf einem echten DOS-System bringt dieser Patch aber eher Nachteile, also nur für Benutzer interessant, die OA4 in einer VDM z.B. unter Windows oder Linux betreiben.
Nachdem man das Problem mit oavision ja umschiffen kann ist der Patch wahrscheinlich hauptsächlich für Benutzer der Runtime CMP.SPI interessant.
Update 04.12.2008:
Asche auf mein Haupt! Der alte Patcher hatte einen Fehler und hat die falschen Bytes an die falsche Stelle gepatcht.. Sowas Dummes, ist mir erst jetzt aufgefallen. Ich habe den vdmpatch.zip aktualisiert, jetzt sollte es passen. Als Entschädigung kann er dafür auch OA3 patchen.
Einen weiteren Tip gibt's dann zum Abschluss noch für die Verwendung von OA4 mit Dosemu:
Leider verbraucht das Programm 100% CPU-Leistung in dosemu, weil es ja für dne Realmode ausgelegt ist und daher die CPU normalerweise für sich beanspruchen und schön die Tastatur pollen kann. Nachdem das aber doch einiges an Saft verbraucht und eigentlich nicht nötig ist gibt's auch dafür nen schönen Workaround (ist nicht von mir, aber die Idee ist gut):
auslast.zip
Einfach die auslast.com vor dem Start von OA ausführen. Das Ding hängt sich in den Tastaturinterrupt 0x16 als TSR hinein und setzt ein paar
Release Current Virtual Machine Time-Slice Kommandos ab, was die VM zwingt, den Timeslice aufzugeben. Das funzt auch im dosemu, nicht nur unter Windows (dort hat man das Problem ja nicht) und senkt die CPU-Last merklich.
Soda, genug OA-Optimierung für heute
EDIT: Die Patcher findet ihr im Download Bereich !