home *** CD-ROM | disk | FTP | other *** search
- ;****************************************
- ;* VGALOAD.ASM
- ;*
- ;* Syntax: VGALOAD dateiname [/A] [/E] [/Wnn]
- ;*
- ;* Bedeutung der Parameter: /A: Bildschirm am Anfang eingeschaltet lassen
- ;* /E: Bildschirm am Ende eingeschaltet lassen
- ;* /W: nach Laden und Anzeige des Bildes
- ;* nn Sekunden warten
- ;*
- ;****************************************
-
- ;*** Makro zum Lesen von Zeichen aus Parameterzeile
-
- getpar macro
- local mac002 ;Lokale Sprungmarke definieren
-
- mov al,ds:anzpar ;Anzahl Zeichen in Parameterzeile holen
- mov ah,00 ;auf 16 Bit bringen
- cmp si,ax ;Zeiger in Parameterzeile mit Anzahl vgl.
- stc ;Ende signalisieren
- je mac002 ;Ende erreicht
- mov al,parzeil[si] ;noch kein Ende: Zeichen nach al holen
- inc si ;Zeiger in Parameterzeile erhöhen
- clc ;Carry-Flag löschen -> Ende nicht erreicht
- mac002:
- endm ;Ende des Makros
-
- ;*** Konstanten
-
- anzpar equ offset 80h ;PSP Offset 80h: Länge der Parameterzeile
- parzeil equ offset 82h ;PSP Offset 81h: Parameterzeile
- ; (eigentlich 81h, dort aber Leerzeichen)
- video equ 0a000h ;Segment-Adresse des Video-RAMs
- pufflen equ 1024 ;Größe des Puffers beim Dateilesen
- stdmod equ 7 ;Standard-Text-Modus für Fehlermeldungen
-
- code segment para 'CODE'
-
- org 100h ;256 Byte für PSP reservieren
-
- assume cs:code, ds:code, es:code, ss:code
-
- main proc near ;Hauptprogramm
-
- start: jmp start1 ;Variablenbereich überspringen
-
- ;*** Variablen
-
- handle dw (?) ;DOS-Datei-Handle
- pag db 0 ;Nummer des Video-RAM-Segments
- kennung db (?) ;Kennungsbyte für Wiederholungen
- zaehler equ this word ;Zähler beim Dekomprimieren
- anz_l db (?) ;dessen Low-Byte
- anz_h db (?) ;dessen High-Byte
- wdhflag db 0 ;Flag/Status beim Lesen von Wiederholungen
- ; 0: Normal, keine Wdh. lesen
- ; 1: Low-Byte d. Anzahl d. Wdh. lesen
- ; 2: dto. High-Byte
- ; 3: zu wiederholendes Byte lesen
- endeflg db 0 ;Flag für Dateiende
- openflg db 0 ;Flag für Datei geöffnet ja/nein
- para_a db 0 ;Schalter für Parameter "A":
- ; Bildschirm am Anfang eingeschaltet lassen
- para_e db 0 ;Schalter für Parameter "E":
- ; Bildschirm am Ende eingeschaltet lassen
- para_w db 0 ;Schalter für Parameter "W":
- ; Nach Anzeige gewisse Zeit warten
- pause dw 0 ;Länge der Pause für Parameter "W"
- anzahl dw (?) ;Anzahl der gelesenen Zeichen im Puffer
- altmode db (?) ;Video-Modus bei Einsprung
- altint equ this dword ;Adresse für alten Interrupt-Vektor
- altinto dw (?) ;dessen Offset-Adresse
- altints dw (?) ;dessen Segment-Adresse
- fehler dw 0 ;Fehlercode bei Programmende (ERRORLEVEL)
- err_tab equ this word ;Tabelle mit Zeigern auf Fehlermeldungen
- dw 0 ;kein Fehler, Dummy
- dw meld1 ;File-Sharing nicht möglich
- dw meld2 ;Datei nicht gefunden
- dw meld3 ;zu viele geöffnete Dateien
- dw meld4 ;Zugriff verweigert
- dw meld5 ;unerwartetes Dateiende
- dw meld6 ;Bildüberlauf, Datei zu lang
- dw meld7 ;unbekannter Fehler
- dw meld8 ;Dateiname fehlt
- dw meld9 ;ungültige Parameterzeile
-
- adjust db 0,1,2,2,3,4,7 ;Abgleichungstabelle für DOS-Fehlernummern
- db 7,7,7,7,7,4
-
- sec_t10 dw 0, 182, 364 ;Sekunden-Zehner-Tabelle
- dw 546, 728, 910
- dw 1092,1274,1456
- dw 1638,1820
- sec_t1 dw 0, 18, 36, 55 ;Sekunden-Einer-Tabelle
- dw 73, 91,109,127
- dw 146,164,182
- puffer db pufflen dup (?) ;Puffer beim Dateilesen
-
- filenam db 80 dup (0) ;Name der zu lesenden Datei
-
- ;*** Fehlermeldungen
-
- meld1: db "File-Sharing ist nicht möglich!",13,10,13,10,"$"
- meld2: db "Datei nicht gefunden!",13,10,13,10,"$"
- meld3: db "Zu viele Dateien geöffnet!",13,10,13,10,"$"
- meld4: db "Zugriff verweigert!",13,10,13,10,"$"
- meld5: db "Unerwartetes Dateiende!",13,10,13,10,"$"
- meld6: db "Datei zu lang, Bildüberlauf!",13,10,13,10,"$"
- meld7: db "Fehler! Ursache unklar!",13,10,13,10,"$"
- meld8: db "Dateiname fehlt!",13,10,13,10,"$"
- meld9: db "ungültige Parameterzeile!",13,10,13,10,"$"
-
- ;*** Code-Beginn
-
- start1 label near ;eigentlicher Programm-Start
-
- ;*** Parameterzeile analysieren
-
- mov si,0 ;Zeiger in Parameterzeile initialisieren
-
- ;*** Dateinamen holen
-
- mov di,0 ;Zeiger in Zielbereich für Dateinamen init.
- mov bx,8 ;Fehlernummer initialisieren
-
- get_n0: getpar ;Zeichen aus Parameterzeile holen
- jc readerr ;Ende vorzeitig erreicht
-
- cmp al,32 ;Leerzeichen überlesen
- je get_n0
-
- get_n1: mov filenam[di],al ;Zeichen in Dateinamen übernehmen
- inc di ;Zeiger in Dateinamen erhöhen
- getpar ;Zeichen aus Parameterzeile holen
- jnc cont1 ;Ende der Parameterzeile noch nicht erreicht
- jmpopen:jmp open ;Sprung zum Öffnen der Datei
-
- cont1: cmp al,32 ;Zeichen mit Leerzeichen vgl.
- jne get_n1 ;kein Leerzeichen, dann aufnehmen
-
- mov bx,9 ;Fehlernummer initialisieren
-
- get_p0: getpar ;Parameter-Behandlung
- jc jmpopen ;Ende der Parameterzeile erreicht
- cmp al,32 ;Leerzeichen überlesen
- je get_p0
-
- cmp al,"/" ;handelt es sich um Parameterangabe ?
- jne readerr ;nein, dann Fehler
-
- getpar ;Parameter-Buchstaben einlesen
- jc readerr ;nicht gefunden, also Fehler
-
- cmp al,"a" ;Test auf Schalter "A"
- je set_p1 ;ggf. setzen
- cmp al,"A" ;dto. Großschreibung
- je set_p1
-
- cmp al,"e" ;Test auf Schalter "E"
- je set_p2 ;ggf. setzen
- cmp al,"E" ;dto. Großschreibung
- je set_p2
-
- cmp al,"w" ;Test auf Schalter "W"
- je get_pw0 ;ggf. weiter einlesen
- cmp al,"W" ;dto. Großschreibung
- je get_pw0
-
- readerr:mov fehler,bx ;Fehlernummer setzen
- jmp errausg ;Fehlermeldung ausgeben
-
- set_p1: mov para_a,1 ;Schalter "A" setzen
- jmp short get_p0 ;weiter einlesen
-
- set_p2: mov para_e,1 ;Schalter "E" setzen
- jmp short get_p0 ;weiter einlesen
-
- get_pw0:mov para_w,1 ;Schalter "W" setzen
- mov bp,sec_t10 ;Zeiger auf Sekunden-Zehner-Tabelle setzen
- mov pause,0 ;Pausenlänge initialisieren
- mov cx,2 ;Schleifen-Zähler
-
- get_pw1:getpar ;1. Ziffer lesen
- jc readerr ;vorzeitiges Ende, also Fehler
- sub al,"0" ;Test auf Ziffer
- js readerr ;kleiner als 0, also Fehler
- cmp al,9 ;größer als 9
- jg readerr ;ja, also Fehler
- shl al,1 ;mit 2 multiplizieren (Wortzugriff)
- mov ah,0 ;auf 16 Bit bringen
- mov di,ax ;ins Index-Register übertragen
- mov ax,pause ;bisherige Pausenlänge nach AX
- add ax,[bp+di] ;Pausenlänge aufsummieren
- mov pause,ax ;Ergebnis zurückschreiben
- mov bp,sec_t1 ;Zeiger auf Sekunden-Einer-Tabelle setzen
- loop get_pw1 ;Schleifenende
- jmp get_p0 ;weiter einlesen
-
- ;*** Datei öffnen
-
- open: mov ah,3dh ;DOS-Fkt. 3dh: Datei öffnen (Handle)
- mov al,0 ;Zugriffsmodus 0: Lesen
- mov dx,offset filenam;Adresse des Dateinamens
- int 21h ;Öffnen ausführen
- jc doserr ;bei Fehlern Abbruch
-
- mov handle,ax ;DOS-Handle merken
- mov openflg,1 ;Flag für Datei geöffnet setzen
-
- ;*** bisherigen Video-Modus holen
-
- mov ah,0fh ;Funktion 0fh: Video-Informationen liefern
- int 10h ;ausführen
- mov altmode,al ;Video-Modus merken
-
- ;*** Video-Modus setzen
-
- mov ah,0 ;Funktion 0: Modus setzen
- mov al,30h ;Modus 30h: 800*600 P., 256 Farben aus 256K
- int 10h ;ausführen
-
- ;*** Bildschirm abschalten
-
- mov al,para_a ;Abschalten unterbunden ?
- jne skipoff ;ggf. überspringen
-
- mov dx,3c4h ;DX auf TS Index Register
- mov al,1 ;Index 1 -> TS Mode
- out dx,al ;TS Mode adressieren
- mov dx,3c5h ;Port-Adresse indexed TS Register nach DX
- in al,dx ;TS-Mode holen
- and al,11011111b ;Bit 5 löschen (Screen Off Bit)
- out dx,al ;zurückschreiben
- skipoff:
-
- ;*** Paletten-Register und Kennzeichen laden
-
- mov ah,3fh ;DOS-Fkt. 3fh: Datei lesen (Handle)
- mov bx,handle ;DOS-Handle holen
- mov cx,3*256+3 ;Anzahl der zu lesenden Zeichen:
- ; 256 Farbwerte à 3 Byte,
- ; 1 Byte Paging Mode,
- ; 1 Byte Color Page,
- ; 1 Byte Kennzeichen für Wdh.
- mov dx,offset puffer;Zielbereich für Daten
- int 21h ;Daten lesen
- jnc ok2 ;kein Fehler, dann weiter
-
- doserr: mov di,ax ;Fehlernummer nach di
- cmp di,12 ;Vergleich mit größter bekannter Fehlernr.
- jbe bekannt ;bekannter Fehler, dann weiter
- mov ax,7 ;sonst Nummer für unbekannten Fehler
- jmp close
- bekannt:mov al,adjust[di] ;abgeglichene Fehlernummer nach AL
- mov ah,0 ;auf 16 Bit bringen
- jmp close ;Fehlermeldung, Ende
-
- ok2: cmp ax,3*256+3 ;Kontrolle, ob alle Zeichen gelesen
- je palette ;ok, dann Paletten-Register setzen
- mov ax,5 ;sonst Fehler: Unerwartetes Dateiende
- jmp close ;Fehlermeldung, Datei schließen, Ende
-
- ;*** Paletten-Register setzen
-
- palette:mov ah,10h ;Fkt. 10h: Paletten-Register bearbeiten
- mov al,12h ;Sub-Fkt. 12h: Gruppe von Farb-Reg. setzen
- push ds ;ES:DX = Zeiger auf Tabelle mit Farbwerten
- pop es ;DS nach ES kopieren
- mov dx,offset puffer;Offset der Tabelle nach DX
- mov bx,0 ;Start bei Farb-Register 0
- mov cx,256 ;256 Register setzen
- int 10h ;ausführen
-
- ;*** Paging Mode setzen
-
- mov ah,10h ;Fkt. 10h: Paletten-Register bearbeiten
- mov al,13h ;Sub-Fkt. 13h: Color-Page bearbeiten
- mov bl,0 ;Select Paging Mode
- mov bh,puffer[3*256];Modus aus Lesepuffer holen
- int 10h ;setzen
-
- ;*** Color Page setzen
-
- mov ah,10h ;Fkt. 10h: Paletten-Register bearbeiten
- mov al,13h ;Sub-Fkt. 13h: Color-Page bearbeiten
- mov bl,1 ;Select Page
- mov bh,puffer[3*256+1];Seite aus Lesepuffer holen
- int 10h ;setzen
-
- ;*** Kennzeichen für Wiederholungen setzen
-
- mov al,puffer[3*256+2];Kennzeichen aus Lesepuffer holen
- mov kennung,al ;und merken
-
- ;*** Initialisierungen
-
- mov di,0 ;Offset in Video-Segment
- mov ax,video ;ES auf Startadresse Video-RAM setzen
- mov es,ax
-
- ;*** erstes Video-RAM-Segment selektieren
-
- mov dx,3cdh ;DX auf Segment-Select-Register setzen
- in al,dx ;einlesen
- and al,11111000b ;Write-Segment-Pointer (Bit 0-2) auf 0
- out dx,al ;und zurückschreiben
-
- ;*** Puffer füllen / laden
-
- loadpuf:mov ah,3fh ;DOS-Fkt. 3fh: Datei lesen (Handle)
- mov bx,handle ;DOS-Handle holen
- mov cx,pufflen ;Anz. d. zu lesenden Zeichen auf Pufferlänge
- mov dx,offset puffer;Zielbereich für Daten ist Puffer
- int 21h ;Datei lesen
- jc doserr ;bei Fehlern Abbruch
-
- cmp ax,pufflen ;Puffer voll, d.h. noch nicht eof?
- je skip1 ;ja, dann weiter
-
- mov endeflg,1 ;sonst Ende-Flag setzen
-
- skip1: mov anzahl,ax ;Anzahl der gelesenen Zeichen merken
-
- mov si,0 ;Index in Puffer auf 0
-
- test_i: cmp si,anzahl ;Puffer komplett ausgelesen?
- jne read ;nein, dann weiter auslesen
-
- cmp endeflg,1 ;Ende der Datei erreicht?
- jne loadpuf ;nein, dann erneut Puffer füllen/laden
-
- mov ax,0 ;kein Fehler
- jmp close ;Datei schließen, Ende
-
- ;*** Puffer auslesen
-
- read: mov al,puffer[si] ;Byte[Index] holen
-
- cmp wdhflag,0 ;wird gerade eine Wiederholung gelesen?
- je normal ;nein, dann Byte normal behandeln
-
- cmp wdhflag,1 ;wurde Low-Byte d. Anz. d. Wdh. gelesen?
- je lies_l ;ja
-
- cmp wdhflag,2 ;wurde High-Byte d. Anz. d. Wdh. gelesen?
- je lies_h ;ja
-
- ;*** Byte-Wiederholung
-
- poke0: mov es:[di],al ;Byte in Video-RAM schreiben
- inc di ;Offset in Video-Segment erhöhen
- jnz test_z ;Ende Segment nocht nicht erreicht
- inc pag ;Nummer des Video-RAM-Segments erhöhen
- cmp pag,8 ;letztes Segment überschritten?
- jb segok0 ;nein, dann weiter
-
- mov ax,6 ;sonst Fehler: Bildüberlauf
- jmp close ;Datei schließen, Ende
-
- segok0: push ax ;AX-Register sichern
- mov dx,3cdh ;DX auf Segment-Select-Register setzen
- in al,dx ;einlesen
- and al,11111000b ;Write-Segment-Pointer zunächst init.
- or al,pag ;dann Nr. des Video-RAM-Segments odern
- out dx,al ;zurückschreiben
- pop ax ;AX-Register wiederherstellen
-
- test_z: dec zaehler ;Zähler für Wiederholungen vermindern
- jne poke0 ;Ende noch nicht erreicht, Schleife
- mov wdhflag,0 ;sonst Flag für Wdh. löschen
- jmp short i_plus ;nächstes Byte lesen
-
- ;*** keine Wiederholung zu lesen
-
- normal: cmp al,kennung ;Kennzeichen für Wiederholung gelesen?
- je kenn ;ja, dann Kennung setzen
-
- poke: mov es:[di],al ;Byte in Video-RAM schreiben
-
- inc di ;Offset in Video-Segment erhöhen
- jnz i_plus ;Ende Segment noch nicht erreicht
-
- inc pag ;sonst Nummer des Video-RAM-Segments erhöhen
- cmp pag,8 ;letztes Segment überschritten?
- jb segok ;nein, in Ordnung
-
- mov ax,6 ;sonst Fehler: Bildüberlauf
- jmp close ;Datei schließen, Ende
-
- segok: mov dx,3cdh ;DX auf Segment-Select-Register
- in al,dx ;einlesen
- and al,11111000b ;Write-Segment-Pointer zunächst init.
- or al,pag ;dann Nummer des Video-RAM-Segments odern
- out dx,al ;und zurückschreiben
-
- ;*** Index erhöhen
-
- i_plus: inc si ;Index in Lese-Puffer erhöhen
- jmp test_i ;auf Ende testen
-
- ;*** Wiederholung wurde gelesen
-
- lies_l: mov anz_l,al ;Low-Byte der Anzahl der Wdh. merken
- mov wdhflag,2 ;Kennzeichen weiterzählen
- jmp short i_plus ;weiterlesen
-
- lies_h: mov anz_h,al ;High-Byte der Anzahl der Wdh. merken
- mov wdhflag,3 ;Kennzeichen weiterzählen
- jmp short i_plus ;weiterlesen
-
- ;*** Kennzeichen wurde gelesen/erkannt
-
- kenn: mov wdhflag,1 ;Kennzeichen für Wiederholungen setzen
- jmp short i_plus ;weiterlesen
-
- ;*** Datei schließen
-
- close: mov fehler,ax ;Fehlernummer merken
-
- mov al,openflg ;Dateischließen erforderlich?
- je skip_cl ;nein, Schließen überspringen
-
- mov ah,3eh ;DOS-Fkt. 3eh: Datei schließen (Handle)
- mov bx,handle ;DOS-Handle holen
- int 21h ;Datei schließen
-
- skip_cl:cmp fehler,0 ;ist ein Fehler aufgetreten?
- je show ;nein, Bildschirm einschalten
-
- ;*** auf Video-Textmodus umschalten
-
- mov ah,0 ;Funktion 0: Modus setzen
- mov al,stdmod ;Video-Modus für Fehlermeldungen holen
- int 10h ;ausführen
-
- ;*** Fehlermeldung ausgeben
-
- errausg:mov ax,fehler ;Fehlernummer nach AX
- shl ax,1 ;mit 2 multiplizieren (Wort-Zugriff)
- mov si,ax ;Ergebnis ins Index-Register
- mov dx,err_tab[si] ;Offset der Fehlermeldung nach DX
- mov ah,09h ;DOS-Fkt. 09h: Zeichenkette ausgeben
- int 21h ;Fehlermeldung ausgeben
- jmp short ende ;zum Programm-Ende
-
- ;*** Bildschirm einschalten
-
- show: mov dx,3c4h ;DX auf TS Index Register
- mov al,1 ;Index auf 1 -> TS Mode
- out dx,al ;TS-Mode adressieren
- mov dx,3c5h ;Port-Adresse indexed TS Register nach DX
- in al,dx ;TS-Mode holen
- or al,00100000b ;Bit 5 setzten (Screen Off Bit)
- out dx,al ;zurückschreiben
-
- ;*** Warteschleife
-
- mov al,para_w ;Warten erwünscht ?
- je exit ;nein, dann Aussprung
-
- mov ah,35h ;DOS-Fkt. 35h: Interrupt-Vektor holen
- mov al,1ch ;Interrupt 1ch: Periodischer Interrupt
- int 21h ;bisherige Interrupt-Adresse holen
- mov altints,es ;Segmentadresse merken
- mov altinto,bx ;Offsetadresse merken
- mov ah,25h ;DOS-Fkt. 25h: Interrupt-Vektor setzen
- mov al,1ch ;Interrupt 1ch: Periodischer Interrupt
- mov dx,offset waitint;Offsetadresse des Pausen-Interrupts
- int 21h ;Interrupt-Vektor setzen
- warten: mov ax,pause ;Pausenzähler testen
- jne warten ;noch nicht null, weiter warten
- mov ah,25h ;Interrupt 25h: Interrupt-Vektor setzen
- mov ah,1ch ;Interrupt 1ch: Periodischer Interrupt
- push ds ;Datensegmentregister retten
- mov dx,altinto ;Vektor wiederherstellen (Offset)
- mov ax,altints ;Vektor wiederherstellen (Segment)
- mov ds,ax
- int 21h ;alten Interrupt-Vektor wiederherstellen
- pop ds ;Datensegmentregister wiederherstellen
-
- ;*** Bildschirm zurückschalten
-
- exit: mov al,para_e ;Zurückschalten unterbunden ?
- jne ende ;ggf. Bildschirmmodus unverändert lassen
-
- mov ah,0 ;Funktion 0: Modus setzen
- mov al,altmode ;Video-Modus bei Einsprung holen
- int 10h ;ausführen
-
- ;*** Programm beenden
-
- ende: mov ah,4ch ;DOS-Fkt. 4ch: Programm beenden
- mov ax,fehler ;Fehler-Code für ERRORLEVEL holen
- int 21h ;Programm beenden
-
- main endp
-
- ;*** Warte-Interrupt für Pause nach Anzeige eines Bildes
- ;*** vermindert bei jedem Aufruf den Pausenzähler "pause",
- ;*** das Hauptprogramm wartet, bis dieser Zähler Null erreicht
-
- waitint proc far ;Prozedur-Beginn
-
- pushf ;Flags sichern - Interrupt simulieren
- call cs:[altint] ;bisherigen Interrupt ausführen
-
- dec cs:pause ;Pausenzähler vermindern
-
- iret ;Interrupt beenden
-
- waitint endp ;Prozedur-Ende
-
- code ends ;Code-Ende
- end main