;-----------------------------------------------------------------------------
;     Panning fr Turbo Pascal 4.0/5.x und EGA/VGA                 release 1.0
;     Copyright (c) Ingo Eickmann, 1989                               11/05/89
;-----------------------------------------------------------------------------

PAGE 65,132
TITLE Panning

   BufferLength    equ  4Ch            ; Eintrag im Systemsegment (s. Tabelle)
   Columns         equ  4Ah            ; Eintrag im Systemsegment (s. Tabelle)
   CRTC            equ  63h            ; Eintrag im Systemsegment (s. Tabelle)
   EGABase         equ  0A000h         ; Segment des Grafikvideospeichers
   GraphicColNorm  equ  640            ; alte Aufl”sung (X) des Grafikmode 12h
   GraphicRowNorm  equ  480            ; alte Aufl”sung (Y) des Grafikmode 12h
   PixelPerChar    equ  9              ; fr VGA, HGC und EGA mono Mode,
                                       ; 8 fr alle anderen EGA Modes
   Rows_m1         equ  84h            ; Eintrag im Systemsegment (s. Tabelle)
   SLinesPerChar   equ  85h            ; Eintrag im Systemsegment (s. Tabelle)
   TextColNorm     equ  80             ; alte Aufl”sung (X) des Textmode 3
   TextRowNorm     equ  25             ; alte Aufl”sung (Y) des Textmode 3

if1
   VertRet macro n                     ; Vertical Retrace (Bit 3) im
           local Loco                  ; Input Status Register 1 abfragen und
           Loco: in al,dx              ; auf  0 (nz: No Vertical Retrace)
                 test al,00001000b     ; bzw. 1 ( z: Vertical Retrace)
                 j&n Loco              ; warten.
           endm
;-----------------------------------------------------------------------------
SetPanning macro                       ; Programmierung der CRTC und Attribute
              mov bl,al                ; Controller Register
              mov dx,es:[CRTC]
              add dl,6                 ; ermitteln des CRTC Status Registers
              VertRet nz               ; auf das Ende eines Vert.Retrace warten
              VertRet z                ; auf den Anfang eines Horz. Ret. warten
              cli
              sub dl,6                 ; CRTC Address Register
              mov al,12
              out dx,ax                ; Start Address (High) belegen
              inc al
              mov ah,bl
              out dx,ax                ; Start Address (Low) belegen
              mov ah,ch
              mov al,8
              out dx,ax                ; Preset Row Scan Register belegen
              mov dl,0C0h              ; Horizontal Pixel Panning Register
              mov al,33h               ; im Attribute Controller adressieren
              out dx,al
              mov al,bh
              out dx,al                ; Horz. Pixel Panning Register belegen
              sti
              mov al,1                 ; Return Value fr function:Boolean:=.t.
           endm
;-----------------------------------------------------------------------------
MExpandText macro PX,PY,ETRaus         ; Erweiterung der Aufl”sung
              xor al,al                ; im Textmode 3
              mov bx,TextColNorm
              cmp bx,PX                ; Aufl”sung in X-Richtung zul„ssig?
              jge ETRaus               ;   NEIN ==> Raus
              mov bx,TextRowNorm
              cmp bx,PY                ; Aufl”sung in Y-Richtung zul„ssig?
              jge ETRaus               ;   NEIN ==> Raus
              mov ax,PX
              mov bx,PY
              mul bx                   ; Anzahl der Character pro erweiterter
              mov cx,ax                ; Bildschirmseite
              dec ax
              and ax,8000h
              or  dx,ax                ; Anzahl der Character > 8000h ?
              jnz ETRaus               ;   JA ==> Raus
              dec bx
              or  bh,bh                ; Anzahl der Textzeilen > 256 ?
              jnz ETRaus               ;   JA ==> Raus
              mov es:[BufferLength],cx ; neue Gr”áe der Bildschirmseite
              mov ax,PX                ; speichern (s. Tabelle)
              mov es:[Columns],ax      ; Anzahl der Spalten und (Zeilen - 1)
              mov es:[Rows_m1],bl      ; im Systemsegment ablegen
              shr ax,1                 ; Worte pro Textzeile
              mov ah,al
              mov al,19
              mov dx,es:[CRTC]         ; Offset Register des CRTC neu
              out dx,ax                ; programmieren
              mov al,1                 ; Return Value fr function:Boolean:=.t.
            endm
;-----------------------------------------------------------------------------
MPanText macro Px,Py,PTRaus            ; angezeigtes Window durch die absoluten
        local noPT,Not9,Tokay          ; Pixelkoordinaten der linken oberen
              mov ax,PX                ; Ecke festlegen
              xor dx,dx
              mov cx,PixelPerChar      ; X-Pixelkoordinate in Columns umrechnen
              div cx
              mov bh,dl                ; bh: Pixel Pan Value
              mov bl,al                ; bl: Char Offset in Row
              dec bh                   ; ************************
              jge Not9                 ; *** Entf„llt fr EGA ***
              mov bh,8                 ; ************************
        Not9: add ax,TextColNorm
              cmp ax,es:[Columns]      ; rechter Rand der Bildschirmseite durch
              jg  noPT                 ; Window berschritten? - JA ==> Raus
              mov ax,PY
              xor dx,dx
              mov cx,es:[SLinesPerChar]
              div cx                   ; Y-Pixelkoordinate in Rows umrechnen
              or  dh,ah                ; Anzahl der Textzeilen zul„ssig?
              jz  Tokay                ;   JA ==> Okay
        noPT: xor al,al                ; Return Value fr function:Boolean:=.f.
              jmp PTRaus               ; Raussprung
       Tokay: mov ch,dl                ; ch: Preset Scan Line
              mov cl,al                ; cl: Row Offset
              add ax,TextRowNorm-1
              cmp ax,es:[Rows_m1]      ; unterer Rand der Bildschirmseite durch
              jg  noPT                 ; Window berschritten? - JA ==> Raus
              mov al,cl                ; Startadresse berechnen:
              xor ah,ah
              mul word ptr es:[Columns] ;         Zeilenzahl * Zeilenl„nge
              xor dx,dx                 ;    +          Offset in der Zeile
              mov dl,bl                 ;   -------------------------------
              add ax,dx                 ;   Startadresse fr den CRTC in AX

              SetPanning               ; Programmierung des CRTC und
         endm                          ; des Attribute Controllers
;-----------------------------------------------------------------------------
MExpandGraphic macro PX,PY,EGRaus      ; Erweiterung der Aufl”sung im
                 xor al,al             ; Grafikmode 12h
                 mov bx,GraphicColNorm
                 cmp bx,PX             ; Aufl”sung in X-Richtung zul„ssig?
                 jg  EGRaus            ;   NEIN ==> Raus
                 mov bx,PY
                 cmp bx,GraphicRowNorm ; Aufl”sung in Y-Richtung zul„ssig?
                 jl  EGRaus            ;   NEIN -> Raus
                 mov ax,PX             ; Berechnung des Speicherbedarfs fr
                 mov cl,4              ; die angeforderte Aufl”sung
                 shr ax,cl             ; durch 8 teilen und nach rechts shiften
                 mul bx
                 dec ax
                 and ax,8000h
                 or  dx,ax             ; Speicherbedarf > 65536 Bytes / Map ?
                 jnz EGRaus            ;   JA ==> Raus
                 mov ax,PX
                 mov xGMax,ax          ; neue Aufl”sung im Datensegment ablegen
                 mov yGMax,bx
                 shr ax,cl             ; Words pro Pixelzeile
                 mov ah,al
                 mov al,19
                 mov dx,es:[CRTC]      ; Offset Register des CRTC neu
                 out dx,ax             ; programmieren
                 mov al,1              ; Return Value fr function:Boolean:=.t.
               endm
;-----------------------------------------------------------------------------
MPanGraphic macro PX,PY,PGRaus         ; angezeigtes Window durch die absoluten
           local noPG,Gokay            ; Pixelkoordinaten der linken oberen
                 mov ax,PX             ; Ecke festlegen
                 mov bx,ax
                 add bx,GraphicColNorm
                 cmp bx,xGMax          ; rechter Rand der Bildschirmseite durch
                 jg  noPG              ; Window berschritten? - JA ==> Raus
                 xor dx,dx
                 mov cx,8              ; 8 Pixel / Byte bei Grafikmodus 12h
                 div cx
                 mov bh,dl             ; Pixel Pan Value
                 mov bl,al             ; Char Offset in Row
                 mov ax,PY
                 mov cx,ax
                 add cx,GraphicRowNorm
                 cmp cx,yGMax          ; unterer Rand der Bildschirmseite durch
                 jle Gokay             ; Window berschritten? - No ==> Okay
           noPG: xor al,al             ; Return Value fr function:Boolean:=.f.
                 jmp PGRaus            ; Raussprung
          Gokay: mov dx,xGMax          ; Startadresse berechnen:
                 mov cl,3              ;   Zeilenzahl * Zeilenl„nge in Bytes
                 shr dx,cl
                 mov cx,dx
                 mul cx
                 xor ch,ch             ; ch:=0 fr Addition und Preset Row Scan
                 mov cl,bl             ; cx: Row Offset
                 add ax,cx             ; Offset in der Zeile addieren
                 SetPanning            ; Programmierung des CRTC und AttribCtrl
            endm
endif

data segment word public
          xGMax dw 0                   ; neue Grafikaufl”sung fr ExpandGraphic
          yGMax dw 0
data ends

code segment word public 'CODE'
     assume cs:code,ds:data

IRP fname,<ExpandText,PanText,ExpandGraphic,PanGraphic>
   ;--------------------------------------------------------------------------
   ; function &fname(PX,PY: Integer):Boolean;
   ;--------------------------------------------------------------------------
   public &fname
   &fname proc far

   PY equ [bp+6]                       ; die Parameter liegen in umgekehrter
   PX equ [bp+8]                       ; Reihenfolge auf dem Stack
            push bp                    ; Kopf der Funktionsaufrufe
            mov  bp,sp
            push es
            mov  ax,40h                ; Segmentregister ES auf
            mov  es,ax                 ; Systemsegment setzen
            mov  al,ah                 ; function:Boolean:=.f. setzen
            mov  bx,PX
            or   bx,PY                 ; ist ein Parameter negativ?
            jge  MJP&fname             ;   NEIN ==> Macro
            jmp  Raus&fname            ;   JA   ==> Raus
MJP&fname:  M&fname PX,PY,Raus&fname   ; Makro der Funktion
Raus&fname: pop  es                    ; Raussprung
            pop  bp
            ret  4                     ; 2 Intergerwerte belegten 4 Bytes
   &fname endp                         ; zus„tzlich auf dem Stack
endm

;-----------------------------------------------------------------------------
; procedure ExpandPutPixel(PX,PY,Color: Integer);
;-----------------------------------------------------------------------------
public ExpandPutPixel                  ; Pixel im erweiterten Grafikmodus
ExpandPutPixel proc far                ; setzen

   Color equ [bp+6]
   PY    equ [bp+8]                    ; die Parameter liegen in umgekehrter
   PX    equ [bp+10]                   ; Reihenfolge auf dem Stack
              push bp                  ; Kopf der Procedure
              mov  bp,sp
              push es
              mov  dx,3CEh             ; Adresse des Graphic Controllers
              mov  ax,Color            ; Die Pixelfarbe ..
              xor  ah,ah
              xchg ah,al               ; .. selektiert im Set-/Reset-Register
              out  dx,ax               ;    das Beschreiben der Maps
              mov  ax,0F01h            ; Alle 4 Set-/Reset-Register werden
              out  dx,ax               ; zum Beschreiben der Maps zugelassen
              mov  ax,3                ; Data Rotate Register mit Rot. Count 0
              out  dx,ax               ; und keine Farbmodifikation belegen
              mov  al,8                ; Bit Mask Register vorab anw„hlen
              out  dx,al
              mov  cx,PX               ; Ist X-Koordinate innerhalb des
              mov  ax,xGMax            ; virtuellen Bildes?
              cmp  ax,cx
              jle  EPRaus              ;   NEIN ==> Raus
              and  cl,7                ; Bit Maske ermitteln
              mov  al,10000000b
              shr  al,cl
              inc  dx                  ; und im Bit Mask Register ablegen
              out  dx,al
              mov  bx,PY               ; Ist Y-Koordinate innerhalb des
              mov  cx,yGMax            ; virtuellen Bild?
              cmp  bx,cx
              jge  EPRaus              ;   NEIN ==> Raus
              mov  ax,xGMax            ; Adresse im Videospeicher berechnen:
              mov  cl,3
              shr  ax,cl               ;   Y * X-Aufl”sung / 8 Pixel/Byte
              push dx
              mul  bx
              pop  dx
              mov  bx,PX               ;              +  X / 8 Pixel/Byte
              shr  bx,cl
              add  ax,bx
              mov  bp,ax
              mov  ax,EGABase          ; Segment des Videospeichers im
              mov  es,ax               ; Grafikmode 12h
              mov  al,es:[bp]          ; Lese- und Schreiboperation mit
              mov  es:[bp],al          ; dieser Speicherstelle ausfhren
      EPRaus: mov  al,0FFh             ; Alle Bits der im Bit Mask Register
              out  dx,al               ; wieder zulassen
              dec  dx
              mov  ax,1                ; Set-/Reset-Register zurcksetzen
              out  dx,ax
              pop  es                  ; verwendete Register wieder herstellen
              pop  bp
              ret  6                   ; 3 Integer-Parameter belegten 6 Bytes
ExpandPutPixel endp                    ; zus„tzlich auf dem Stack

code ends                              ; MS-C: Segmentname code in _TEXT „ndern
     end
