; ----------------------------------------------
;     GRSTRING.INC
; ----------------------------------------------
;     Include-Datei zur Ausgabe von Text
;     in den EGA/VGA-Grafikmodes 10h und 12h
; ----------------------------------------------

BIOSSeg      equ  0040h
GRC          equ   3CEh
GRSeg        equ  0A000h
INT43h       equ    43h shl 2
LineLength   equ    80
PointsOfs    equ    85h

OUTDX   macro X           ; Makro zur Ausgabe
                          ; eines Wortes an
        mov ax,X          ; den Port in DX
        out dx,ax
        endm
; ----------------------------------------------

        .DATA             ; Beginn des Daten-
                          ; Segments

Color    db 0             ; Variable der Sub-
                          ; routine GRString
Func     db 0
Points   dw 0
TabSeg   dw 0
VAddr    dw 0
; ----------------------------------------------

         .CODE            ; Beginn des Code-
                          ; Segments
; ==============================================
; Subroutine GRString: Ausgabe eines Strings im
;                      Grafikmode
;           ax:    X-Grafikkordinate
;           bx:    Y-Grafikkordinate
;           dh:    Farbe
;           dl:    Funktion
;                  0: Normal
;                  1: Kursiv (max H”he: 17 Pts.)
;           es:si: Zeiger auf String, letztes
;                  Zeichen muá 00h sein
; ==============================================
GRString proc near
        mov [Func],dl     ; Funktion zwi-
                          ; schenspeichern
        push ax           ; X retten

        mov ah,dh
        xor al,al
        mov dx,GRC        ; Graphics Controller
                          ; programmieren
        out dx,ax         ; Farbe in das
                          ; Set/Reset Register
        OUTDX 0F01h       ; Enable Set Reset
                          ; Register
        OUTDX 0003h       ; Data Rotate/
                          ; Function
                          ; Select Register
        mov ax,LineLength ; Offset im Video-
                          ; speicher berechnen:
        mul bx            ; Adr = Y * 80
                          ; Byte/Line
        pop bx
        mov ch,bl
        and ch,00000111b  ; Anzahl der hori-
                          ; zontalen Shifts
        mov cl,3
        shr bx,cl         ; Adr = Adr + X div 8
        mov cl,ch
        xor ch,ch
        add ax,bx
        mov [VAddr],ax    ; Offset im Video-
                          ; speicher ablegen
        push ds           ; Datensegment retten
        mov ax,BIOSSeg    ; BIOS-Datensegment
        mov bx,INT43h     ; Offset des INT 43h-
                          ; Vektors
        mov ds,ax
        mov dl,ds:[PointsOfs]; H”he der aktu-
                          ; ellen Zeichenmatrix
        xor ax,ax         ; aus der Video
                          ; Display Data Area
        mov ds,ax
        lds di,ds:[bx]    ; Zeiger DS:DI auf
                          ; aktuellen Font
        mov bx,ds         ; laut INT 43h
        pop ds
        mov [TabSeg],bx   ; ermittelte Werte
                          ; zwischenspeichern
        mov byte ptr [Points],dl
        cmp [Func],1      ; Kursiv ?
        jnz NextChr2
        add cl,dl         ; JA: Versatz fr
                          ; oberste Scan Line
        dec cl
NextChr2:
; ==============================================
        push ds           ; „uáere Schleife fr
                          ; n„chstes Zeichen
        push es
        pop ds
        cld
        lodsb             ; n„chstes ASCII-
                          ; Zeichen auf String
        pop ds
        or al,al          ; Endmarke 00h ge-
                          ; funden?
        jnz NoEnd         ; NEIN => Rausspringen
        jmp Raus          ; JA => Rausspringen
NoEnd:  push [VAddr]      ; Adresse und Versatz
                          ; fr n„chstes
        push cx           ; Zeichen retten
        xor ah,ah
        mov bx,[Points]
        mul bx            ; Eintrag in Matrizen-
                          ; tabelle berechnen
        push bx
        mov bx,ax
NextLine:
; ----------------------------------------------
        push ds           ; innere Schleife fr
                          ; n„chste Scan Line
        mov ax,TabSeg
        mov ds,ax         ; n„chste Scan Line
                          ; des Zeichens aus der
        mov ah,[di+bx]    ; Tabelle holen
        pop ds
        inc bx            ; Zeiger bx erh”hen
        push bx           ; Register fr das Be-
                          ; schreiben des Video-
        push di           ; speichers retten
        xor bx,bx
        push cx
        and cx,0FFh       ; LSB extrahieren
        jz Weiter         ; Verschiebung = 0 ?
Rotate: shr ax,1          ; Bitmuster pixelweise
                          ; horz. verschieben
        rcr bx,1
        loop Rotate
Weiter: mov ch,al         ; 2. Byte zwischen-
                          ; speichern
        mov al,8          ; Bit Mask Register des
                          ; Graphic-Controllers
        mov dx,GRC        ; programmieren
        out dx,ax
        mov di,[VAddr]
        push ds
        mov ax,GRSeg      ; Segment des Video-
                          ; speichers im Grafik-
        mov ds,ax         ; mode herstellen
        mov cl,[di]       ; Pixel des linken
                          ; Byte setzen
        mov [di],cl
        mov al,8          ; Bit Mask Register
                          ; adressieren
        IRP n,<ch,bh,bl>  ; die restlichen
                          ; 3 Byte schreiben
           inc di         ; Videospeicheradresse
                          ; des Bytes
           mov ah,&n
           or ah,ah       ; Pixel setzen ?
           jz Zero&n
           out dx,ax      ; JA: Bitmaske in
                          ; Graphic Controller
           mov cl,[di]    ; Pixel dieser Scan-
                          ; Line setzen
           mov [di],cl
Zero&n     label near
        endm
        add di,LineLength - 3
                          ; Adresse fur n„chste
        pop ds            ; Scan Line berechnen
        mov [VAddr],di    ; und ablegen
        pop cx
        cmp [Func],1      ; Kursiv ?
        jnz Norm
        dec cl            ; JA: Versatz verrin-
                          ; gern
Norm:   pop di            ; Register wieder her-
                          ; stellen
        pop bx
        pop ax
        dec ax
        jz NextChr1       ; letzte Scan Line er-
                          ; reicht?
        push ax           ; NEIN => weiter zur
                          ; n„chsten Scan Line
        jmp NextLine      ; Sprung zum Schlei-
                          ; fenanfang
; ----------------------------------------------
NextChr1:
        pop cx            ; Versatz der obersten
                          ; Scan Line
        pop ax            ; Adresse im Video
                          ; speicher fr n„chs-
        inc ax            ; tes Zeichen erh”hen
        mov [VAddr],ax
        jmp NextChr2      ; Sprung zum
                          ; Schleifenanfang
; ==============================================
Raus:                     ; Standardwerte fr
                          ; den Graphics Contr.
        OUTDX 0000h       ; Set/Reset Register
        OUTDX 0F01h       ; Enable Set Reset Re-
                          ; gister
        OUTDX 0003h       ; Data Rotate/Function
                          ; Select Register
        OUTDX 0FF08h      ; Bit Mask Register
        ret
GRString endp