home *** CD-ROM | disk | FTP | other *** search
- ; ***********************************************************
- ; * Programmname : HERCUTIL.ASM *
- ; * Inhalt : Routinen zur Ermittlung des Grafikmodus *
- ; * und der aktiven Grafikseite bei einer *
- ; * Hercules-Karte *
- ; * Programmiert : Chr. Monien *
- ; * : (c) Verlag Heinz Heise Redaktion c't *
- ; * ------------------------------------------------------- *
- ; * Assemblierung: MASM HERCUTIL.ASM; *
- ; ***********************************************************
-
- STATUS EQU 03BAH ; Display-Status-Port
- INDEX EQU 03B4H ; Index-Register
- LPSET EQU 03B9H ; LP-FlipFlop setzen (Schreiben)
- LPRESET EQU 03BBH ; LP-FlipFlop löschen (Schreiben)
-
- VRETRACE EQU 128 ; Bit für VRETRACE
- HRETRACE EQU 1 ; Bit für HRETRACE
- PIXEL EQU 8 ; Bit für Pixeldaten
-
- PUFFERLEN EQU 20 ; Länge der Zeile in Wörtern
- THRESHOLD EQU 2000 ; Schwellwert für Grafikmodus
-
- PUBLIC TESTGRAPH ; Adressen für TP zugänglich machen
- PUBLIC GETPAGE ; Achtung! NEAR-Prozeduren, nicht im
- ; INTERFACE-Teil einer Unit deklarieren!
-
- CODE SEGMENT BYTE PUBLIC
- ASSUME CS:CODE, DS:NOTHING, ES:NOTHING
- PHERC PROC NEAR
-
- PUFFER DW PUFFERLEN DUP (?,?) ; Puffer anlegen (2 Zeilen)
-
- ;------------------------------------------------------------------------
- ;-- TESTGRAPH ermittelt die Position des LightPens in der 340. Zeile
- ;-- und vergleicht das Ergebnis mit einem Schwellwert, der
- ;-- zur Unterscheidung von Grafik- und Textmodus dient.
- ;-- Aufruf von Turbo-PASCAL: function TestGraph: boolean;
- TESTGRAPH:
- CLI ; bitte keine Interrupts
- MOV AH,VRETRACE ; auf vertikalen Strahlrücklauf warten
- CALL WAIT_RETRACE
- MOV CX,340 ; Zähler für Zeilen
- MOV AH,HRETRACE ; auf horizontalen Strahlrücklauf warten
- @L1:
- CALL WAIT_RETRACE
- LOOP @L1 ; solange bis Zeile 340 erreicht ist
- CALL GETLPPOS ; LightPen-Position lesen
- CMP AX,THRESHOLD ; Textspeicher überschritten ?
- MOV AL,0
- JNA @L2 ; Nein, FALSE zurück
- INC AL ; TRUE zurück
- @L2:
- STI ; Interrupts erlauben
- RET
-
- ;------------------------------------------------------------------------
- ;-- WAIT_RETRACE wartet auf eine positive Flanke der vertikalen bzw.
- ;-- horizontalen Synchronisationssignale.
- ;-- Eingabe : AH= 080H Warten auf VRETRACE
- ;-- AH= 001H Warten auf HRETRACE
- ;-- Ausgabe : keine
- WAIT_RETRACE:
- MOV DX,STATUS
- @L3: ; Loop, solange Bit gesetzt
- IN AL,DX
- TEST AL,AH
- JNE @L3
- @L4: ; Loop, solange Bit gelöscht
- IN AL,DX
- TEST AL,AH
- JE @L4
- RET
-
- ;------------------------------------------------------------------------
- ;-- GETLPPOS liest aus den Registern 16 und 17 des CRTC 6845 die
- ;-- aktuelle Position des LightPens
- ;-- Eingabe: keine
- ;-- Ausgabe: AX= Offsetadresse des LightPens
- GETLPPOS:
- MOV DX,LPRESET ; Reset und Set des LightPen-FlipFlops
- OUT DX,AL
- MOV DL,LOW LPSET
- OUT DX,AL
-
- MOV AL,16 ; Register 16 (High-Byte) auslesen
- MOV DL,LOW INDEX
- OUT DX,AL
- INC DX
- IN AL,DX
- MOV AH,AL
-
- MOV AL,17 ; Register 17 (Low-Byte) auslesen
- DEC DX
- OUT DX,AL
- INC DX
- IN AL,DX
- RET
-
- ;------------------------------------------------------------------------
- ;-- GETPAGE ermittelt die aktuelle Bildschirmseite im Grafikmodus,
- ;-- indem der Pixeldatenstrom zum Anfang des Bildes geprüft
- ;-- wird. Dazu werden Teile der ersten Zeile von beiden Seiten
- ;-- gespeichert und mit 0 (Seite 0, Segment B000h) bzw. 1
- ;-- (Seite 1, Segment B800h) aufgefüllt, um eindeutige Ergeb-
- ;-- nisse zu erzielen. Nach dem Test wird der alte Bildkontext
- ;-- wieder hergestellt.
- ;-- Aufruf von Turbo-PASCAL: function GetPage: byte;
- GETPAGE:
- PUSH DS ; Segmentreg. retten
- PUSH ES
- CLD ; aufsteigend zählen
- MOV CX,PUFFERLEN ; Länge steht immer in CX
- CALL SAVE_LINE ; Zeilen sichern und auf Seite 0 Zeile löschen
- ; bzw. auf Seite 1 setzen
-
- MOV DX,STATUS ; Statusport wird abgefragt
- CLI ; bitte nicht stören
- @L5:
- IN AL,DX ; auf vertikalen Strahlrücklauf warten
- TEST AL,VRETRACE
- JNE @L5
- @L6:
- IN AL,DX ; auf Ausgabe der 1. Zeile warten
- TEST AL,HRETRACE
- JNE @L6
-
- IN AL,DX ; Pixeldatum gibt Auskunft über Bildschirmseite
- AND AL,PIXEL
- SHR AL,1 ; auf Bit-Position 0 verschieben
- SHR AL,1
- SHR AL,1
-
- STI ; Interrupts wieder freigeben
-
- CALL RESTORE_LINE ; Originalzustand der Zeilen wiederherstellen
- POP ES ; Register wiederherstellen
- POP DS
- RET
-
- ;------------------------------------------------------------------------
- ;-- SAVE_LINE speichert jeweils die erste Zeile von beiden Grafikseiten
- ;-- und belegt diese Zeilen mit 0 (Seite 0) bzw. FFFFh
- ;-- (Seite 1)
- ;-- Eingabe: CX= Länge der Zeile in Wörtern
- SAVE_LINE:
- PUSH CS ; ES= CS
- POP ES
- XOR AX,AX ; Zeile mit 0 auffüllen
- MOV SI,0B000H ; Segment von Seite 0
- MOV DI,OFFSET PUFFER ; Ziel ist der Puffer
- CALL SAVE
- NOT AX ; Zeile mit 1 auffüllen
- MOV SI,0B800H ; Segment von Seite 1
- SAVE:
- MOV DS,SI ; DS mit Bildschirm-Segment laden
- XOR SI,SI ; Offset ist 0
- PUSH CX ; Anzahl in CX retten
- @L7:
- MOVSW ; Bildkontext speichern
- MOV WORD PTR DS:[SI-2],AX; Zeile mit AX laden
- LOOP @L7 ; bis Puffer voll
- POP CX ; CX wieder vom Stack holen
- RET
-
- ;------------------------------------------------------------------------
- ;-- RESTORE_LINE stellt den alten Bildschirminhalt wieder her.
- ;-- Eingabe: CX= Länge der Zeile in Wörtern
- RESTORE_LINE:
- PUSH CS ; DS= CS
- POP DS
- MOV DI,0B000H ; Segment von Seite 0
- MOV SI,OFFSET PUFFER ; Quelle ist der Puffer
- CALL RESTORE
- MOV DI,0B800H ; Segemnt von Seite 1
- RESTORE:
- MOV ES,DI ; ES mit Bildschirm-Segemnt laden
- XOR DI,DI ; Offset ist 0
- PUSH CX ; Anzahl in CX retten
- REP MOVSW ; Bildkontext wieder auf den Bildschirm
- POP CX ; CX wieder vom Stack nehmen
- RET
-
- PHERC ENDP
- CODE ENDS
- END
-
-