;**********************************************************
;*
;* Bitmap-Interface für KC-Emulator und alle KC-Typen
;*
;*****
;Folgende Beschränkungen gelten für alle KC's und auch den User-KC's:
;24 statische Farben 0..23,
;8 animierbare Farben 24..31
;Windows-Pixmapgröße max. 128K
;Das dürfte wirklich für alle existierenden Z80-Computer reichen!
;Registerbelegung:
; es: Adreßbereich KC
; ds: restliche Daten (Windows automatisches Datensegment [HInstance])
; si: Z80-Instruktionszeiger ("program counter" PC)
;
IDEAL
%TITLE "KCEMU DrawBitmap library"
model small, pascal
P286
warn pro ;Protected-Mode-Fehler anmeckern
extrn MemKCSel: Word ;KC-Selektor
extrn InUpdate: Byte:160 ;Bitfeld der Update-Regionen
extrn BlinkFarben: Byte:8 ;8 Blinkfarbpaare
extrn __ahincr: Proc ;Selektor-Inkrement (Offset als Konstante)
extrn hDisplay: Word ;Bitmap-Selektor
extrn DisplaySize: DWord ;Bitmap-Größe (für Blink_GC)
extrn hCharMap: Word; ;Zeichenbildtabellen-Selektor
extrn KC4Port84H: Byte ;Register für Bankauswahl und HRG
extrn KC4Port88H: Byte ;Register für Z9001-20-Zeilen-Modus und Border
extrn KCIRM: DWord ;Zeiger auf KC85/4-Bildspeicher
extrn Blinken: Byte ;Boolean-Schalter
extrn GC_ShortCircuit: Byte ;Boolean-Schalter
extrn Foreground: Byte ;Boolean-Schalter
extrn Test8086: Byte ;Ergebnis des CPU-Tests (Unit SYSTEM)
extrn GetAnimIdx: Word; ;Prozedur-Zeiger
extrn Regions: Word ;Klötzchenregion-Zähler
extrn MainWnd: Word ;Hauptfenster
extrn hPal: Word; ;Paletten-Handle
extrn InvalidateRect: FAR ;Windows-Funktion
extrn AnimatePalette: FAR ;Windows-Funktion
extrn ChrBox: DWord ;Zeichenzelle in Bildschirm-Pixeln
extrn PixBox: Word ;8x8-Zelle in Bildschirm-Pixeln
extrn Palette: DWord:33 ;die beiden Header-Words mitgezählt
;*** allgemein ***
public Blink_GC ;Garbage Collection für User-KC
public GetBlinkFarbe ;Freie Blinkfarbe beschaffen, für User-KC
public Animate ;Nach Wechsel von [Foreground] aufzurufen
public InvalWnd ;ganze Bitmap invalidieren
public Inval8x8 ;Klötzchen inval., für Vollgrafik-Systeme
; (das Zeichenraster [ChrBox] muß nicht zwangsläufig 8x8 sein [WordPro!])
public InvalChrBox ;Klötzchen inval., für Textbildschirme
;*** KC85/2,3,4 ***
public GetAnimIdx3 ;Umrechnung Farbbyte+Foreground->PalIndex
public IRM_Access3 ;schließt KC85/2 ein
public IRM_Update3
public IRM_Access4
public IRM_Update4
;*** KC85/1, Z1013 ***
public GetAnimIdx7
public IRM_Access1
public IRM_Update1
public IRM_Access7
public IRM_Update7
public IRM_Access9
public IRM_Update9
CODESEG
;**************************
;****************************************************
;*** Allgemeine Routinen (Invalidieren und Blinken***
;****************************************************
proc Blink_GC
;{Garbage Collection für BlinkFarben: Durchbrowst die Pixmap
; nach Einträgen zwischen 24 und 31 und entfernt Fehlreferenzen
; aus BlinkFarben[]. Sind alle Farben in Beschlag, dann CY=1.
; PE: CLD! VR: BX,CX}
push ax es si
mov bx,[word LOW DisplaySize]
cmp [word HIGH DisplaySize],0 ;darf maximal 1 sein!
mov es,[hDisplay]
jz @@0
xor bx,bx ;>64K: zuerst eine "volle" Runde
@@0: xor si,si
mov ah,0FFh ;{Alles frei...}
@@l: seges lodsb ;{Byte laden}
sub al,24
cmp al,8
jnc @@no ;{keine Blinkfarbe}
mov cl,al
mov al,not 1
rol al,cl
and ah,al ;{Bitstelle ist NICHT mehr frei}
@@no: dec bx
jnz @@l
or si,si
jnz @@w ;{in 2. Runde raus! (SI<>0)}
mov bx,es
add bx,offset __ahincr
mov es,bx
mov bx,[word LOW DisplaySize]
or bx,bx ;{Neuer Zähler für den Rest (KC85/3: 16K}
jnz @@l ;durchlaufen falls genau 64K
@@w:
pop si es
cmp ah,1 ;{Null? (Alle 8 Indizes in Beschlag?)}
jc @@e ;ja, kann nichts machen
lea bx,[BlinkFarben]
@@l2: shr ah,1 ;{Bit ausschieben}
jnc @@used
mov [byte bx],0
@@used: inc bx
or ah,ah ;{Noch freie Bits? (und CY löschen!)}
jnz @@l2
@@e: pop ax
ret
endp Blink_GC
;**************************
proc GetBlinkFarbe
;{PE: AL=(unverändertes) Farbattribut; PA:AL=Palettenindex; VR: AL}
;{Funktioniert für alle KC durch Funktionszeiger für GetAnimIdx}
push bx cx
mov bx,offset BlinkFarben-1
mov cx,8
@@l1: inc bx
cmp [bx],al ;{Gleichen Eintrag suchen}
loopnz @@l1
jz @@f_e ;{Gleichen Eintrag gefunden!}
@@try: mov bx,offset BlinkFarben-1
mov cx,8
@@l2: inc bx
cmp [byte bx],0 ;{Freien Eintrag suchen}
loopnz @@l2
jz @@f_f ;{Freien Eintrag gefunden!}
cmp [GC_ShortCircuit],0
jnz @@sc
call Blink_GC ;{"Garbage Collection" aufrufen}
mov [GC_ShortCircuit],1
jnc @@try ;{Wenn neue freie Einträge gefunden}
@@sc: stc
jmp @@e ;{Fehler, nicht-blinkende Farben nehmen}
@@f_f: mov [bx],al ;{Farbe allozieren}
;{Neu allozierte Farbe muß nun auch (einzeln) animiert werden!}
pusha
push es
push ds
pop es
cmp [Foreground],0
call [GetAnimIdx] ;{liefert AL zwischen 0 und 23}
xor ah,ah ;{auf AX erweitern}
sub bx,offset BlinkFarben-24
mov di,bx ;{Index der animierten Farbe (24..31}
push [hPal] ;AnimatePalette()-Aufruf vorbereiten
push di ;{Paletten-Index}
push 1 ;{genau 1 Farbe}
push ds
lea si,[Palette+4]
shl di,2 ;{*sizeof(LongInt)}
add di,si ;{Zieladresse für Farb-Kopieren}
push di ;Adresse des TPaletteEntry-Eintrags
shl al,2
add si,ax ;{Quelladresse}
cld
movsw
movsb ;{3 Farbbytes kopieren}
call AnimatePalette
pop es
popa
@@f_e: sub bx,offset BlinkFarben-24 ;{CLC}
mov al,bl ;{aus BX=Zeiger Palettenindex machen}
@@e: pop cx bx
ret
endp GetBlinkFarbe
;**************************
proc Animate
cld
push ds
pop es
lea bx,[BlinkFarben] ;Quelladresse
lea di,[Palette+4+24*4] ;laufende Zieladresse
mov cx,8
@@l: mov al,[bx]
cmp [Foreground],0
call [GetAnimIdx]
xor ah,ah
shl al,2
lea si,[Palette+4]
add si,ax
movsw
movsb
inc di ;peFlags übergehen
inc bx ;nächste Blinkfarbe
loop @@l
push [hPal]
push 24
push 8
push ds
push offset Palette+4+24*4
call AnimatePalette
ret
endp Animate
;**************************
proc InvalWnd
;{PE: -, PA: -, VR: alle außer DS,SI,SP,BP}
xor ax,ax
push [MainWnd]
push ax ax ;{lpRect=NIL}
push ax ;{fErase=FALSE}
call InvalidateRect
push ds
pop es
mov di,offset InUpdate
mov cx,length InUpdate/2 ;SIZE würde hier 1 liefern
mov ax,0FFFFh
cld
rep stosw ;{FillChar: Alles in Update-Region}
ret
endp InvalWnd
proc MakeBXAL
;erstellt für den am 286er fehlenden Befehl BTS [InUpdate],bx
;eine Bitmaske in AL und Byte-Adresse in BX
;PE: BX=Bit-Nummer; PA: BX=Adresse, AL=Maske, Z=1: Bit=0; VR: CL
mov cl,bl
and cl,7
mov al,1
shl al,cl ;{AL=Bitmaske}
shr bx,3 ;{BX nun max. 124}
add bx,offset InUpdate
test [bx],al
ret
endp MakeBXAL
;**************************
proc Inval8x8
;{Invaliditiert Bildschirm-Bereich 8x8-Pixel-Schritten
; PE: DL=Zeile(Y), DH=Spalte(X) (also gerade andersherum als im PC-BIOS)
; BX=eindeutiger Bit-Bezeichner für InUpdate-BitArray
; VR: BX,CL,Flags}
cmp [Test8086],2 ;{386er?}
jc @@286
P386
BTS [word InUpdate],bx
jnc @@w
@@e: ret
P286
@@286: call MakeBXAL
jnz @@e
or [bx],al ;{Bit setzen}
@@w: pusha
push es
mov si,[PixBox]
mov di,si
jmp InvalXY
endp Inval8x8
;**************************
proc InvalChrBox
;{dieselbe Routine wie oben, jedoch in Zeichenzellen statt 8x8}
cmp [Test8086],2 ;{386er?}
jc @@286
P386
BTS [word InUpdate],bx
jnc @@w
@@e: ret
P286
@@286: call MakeBXAL
jnz @@e
or [bx],al ;{Bit setzen}
@@w: pusha
push es
mov si,[word LOW ChrBox] ;X
mov di,[word HIGH ChrBox] ;Y
InvalXY: dec [Regions]
jnz @@w1
call InvalWnd
jmp @@ex
@@w1: mov ax,di
imul dl ;{AX=R.top}
add di,ax ;{eine Zeichenhöhe dazu gibt R.bottom}
push di ;{R.bottom}
xchg bx,ax ;{R.top retten}
mov ax,si
imul dh ;{AX=R.left}
add si,ax ;{eine Zeichenbreite dazu gibt R.right}
push si ;{R.right}
push bx ;{R.top}
push ax ;{R.left}
mov ax,sp ;{SS:AX=Adresse von TRect}
push [MainWnd]
push ss ax ;{auf dem Stack liegendes TRect}
push 0
call InvalidateRect ;{modifiziert ES!}
add sp,8 ;{TRect entfernen}
@@ex: pop es
popa
ret
endp InvalChrBox
;**************************************
;*** Routinen für KC85/2, /3 und /4 ***
;**************************************
proc GetAnimIdx3
;{PE: AL=Farbbyte, Z=1: HFarbe, Z=0: VFarbe gewünscht;
; PA: AL=Index als Blinkfarbe (0..23)
; VR: AL, Flags}
jnz @@fg
and al,7
ret
@@fg: shr al,3
and al,0Fh
add al,8
ret
endp
proc GetVFarbe
;Gemeinsame Routine für KC85/3 und 4 wegen gleichem Farbbyte-Aufbau.
;Keine Verwendung für den KC85/4-HRG-Modus
;{PE: CL=Pixelbyte (KC85/4), <>0 (andere KCs),
; AL=Farbattribut; PA: AL=Palettenindex für VFarbe; VR: AL,Flags}
;{N: HFarbe ist stets AL and 7}
cmp al,80h ;{Blinkbit?}
jbe @@nb ;{wenn kein Blinkbit oder schwarz auf schwarz}
cmp [Blinken],0
jz @@nb ;{wenn global ausgeschaltet}
cmp al,0C0h ;{Auch schwarz auf schwarz?}
je @@nb
or cl,cl ;{Bits gesetzt? (am /3 immer)}
je @@nb ;{nein-auch nicht blinken lassen!}
call GetBlinkFarbe
jnc @@e
@@nb: shr al,3
and al,0Fh
add al,8 ;{VFarbe für KC85/2,3,4}
@@e: ret
endp GetVFarbe
proc adr2pixcolxy
;{PE: BX=Schreibadresse,
; PA: SI=Pixeladresse, DI=Farbadresse, DX=Spalte(X), CX=Zeile(Y),
; AL=0 (DEBUG: kein Update), 1 (Pixel-Update), 4(Farb-Update)}
mov di,bx
mov si,bx
xor ch,ch
xor dh,dh
xor al,al ;{Fehler-Code}
sub bh,0B2h
IFDEF DEBUG
jnc @@err
ENDIF
add bh,2
jc @@cr
add bh,8
jc @@cl
add bh,8
jc @@pr
add bh,20h
IFDEF DEBUG
jnc @@err
ENDIF
;{PE: Pixeladresse links}
@@pl: mov dl,bl
and dl,1Fh ;{H}
add bx,bx
mov cl,bh
shr bh,2
or bh,50h
mov di,bx
stc
rcr di,1 ;{Farbadresse fertig!}
shl bx,4
and bh,0FCh
and cl,03h
or cl,bh ;{V}
mov al,1
ret
;{PE: Pixeladresse rechts}
@@pr: mov dl,bl
and dl,7
or dl,20h ;{H}
add bx,bx
mov ax,bx ;{AH enthält: V7 V6 V1 V0, AL: V3 V2 V5 V4}
shr bh,2
shr bx,1
or bh,0B0h
mov di,bx ;{Farbadresse fertig!}
mov bx,ax
shl bx,4
and bh,0CCh
and ax,0330h
or al,ah
or al,bh
mov cl,al ;{V}
mov al,1
ret
;{PE: Farbadresse links}
@@cl: mov dl,bl
and dl,01Fh ;{H}
shl bx,5
mov cl,bh
and cl,0FCh ;{V}
shr bx,4
shr bl,1
add bh,bh
or bh,80h
mov si,bx ;{Pixeladresse fertig!}
mov al,4
ret
;{PE: Farbadresse rechts}
@@cr:
mov dl,bl
and dl,7
or dl,20h ;{H}
add bx,bx
mov cl,bl ;{V4 und V5 bit-richtig!}
shr bl,1 ;{V1 und V0 =0 setzen!}
add bh,bh
or bh,0A0h
mov si,bx ;{Pixeladresse fertig!}
shl bx,5
and bh,0FCh
and cl,30h
or cl,bh ;{V}
mov al,4
;{PE: fehlerhafte Adresse}
@@err: ret
endp adr2pixcolxy
;**************************
proc IRM_Access3
;{PE: BX=Schreibadresse, ES=MemKCSel (ES:BX bereits geschrieben)
; PA: -, VR: Flags}
pusha
call adr2pixcolxy ;{4 Parameter ausrechnen}
IFDEF DEBUG
or al,al
jz @@e
ENDIF
push ax ;{Zeilen retten}
pusha
mov dh,dl
mov dl,cl
mov bx,dx
shr bx,3
shr dl,3 ;{Y}
call Inval8x8 ;{Aktualisieren lassen}
popa
not cl ;{Zeile stürzen für DIB}
mov ax,cx
add ax,ax
add ax,ax ;{Spalte*4}
add ax,cx ;{*5}
shl ax,3 ;{*40}
add ax,dx ;{Zeile*40+Spalte}
mov dx,[hDisplay]
shl ax,3 ;{Pixel-Adresse, wird CY richtig gesetzt??}
jnc @@1
add dx,offset __ahincr
@@1: ;{DX:AX nun Adresse in Pixmap}
pop cx ;{Zeilenzahl in CL}
cld
;{Hauptschleife mit: DX:AX (temp.alias ES:DI)=Windows-DIB-Adresse,
; AL=Akku, BL=Pixelbyte, BH=VFarbe, AH=HFarbe, CH=Bitmaske, CL=Schleifenzähler,
; ES:SI=KC-Pixel-Adresse, ES:DI=KC-Farb-Adresse}
mov bh,[es:di] ;{Farb-Byte}
xchg di,ax ;{DI nun Bitmap-Adresse}
mov al,bh
call GetVFarbe ;{CL trickreicherweise immer <>0}
xchg ah,al ;{VFarbe nach AH}
and bh,7 ;{HFarbe}
@@l2: mov bl,[es:si] ;{Pixel-Byte}
push es
mov es,dx ;{Segment-"Umschaltung"}
mov ch,80h ;{Start mit Bit 7}
@@l1: test bl,ch
mov al,bh ;{HFarbe?}
jz @@hf
mov al,ah ;{nimm VFarbe!}
@@hf: stosb ;{Pixel setzen, kein Segmentüberlauf
shr ch,1 ; (außer am Ende)}
jnz @@l1
pop es
dec cl
jz @@e ;{fertig, nicht mehr rechnen}
dec di ;{"Anlauf" nehmen gegen Segmentüberlauf}
sub di,320+7 ;{Pixel pro Zeile + 1 Byte - 1 Bit}
jnc @@3
sub dx,offset __ahincr
@@3: add si,80h ;{nächste KC-Pixelzeile (Farbe bleibt)}
jmp @@l2
@@e:
popa
ret
endp IRM_Access3
;**************************
proc IRM_Access4
;{PE: BX=Schreibadresse, (ES:BX bereits geschrieben)
; PA: -, VR: Flags}
pusha
push es
sub bh,80h
IFDEF DEBUG
cmp bh,28h
jnc @@e ;{BH=X, BL=Y}
ENDIF
mov si,bx ;{KC-Adresse retten}
les di,[KCIRM]
mov [es:di+bx],al ;{in den 10-K-Spiegel schreiben}
mov al,[KC4Port84H]
and al,5 ;{Anzeige und Zugriff verschieden?}
jpo @@e ;{ja (unpaarig) - raus!}
;{Test auf InUpdate und Aufruf von InvalidateRect}
mov dx,bx
shr bx,3 ;{Unterste Bits (X) uninteressant!}
shr dl,3 ;{nun DL=Y, DH=X}
call Inval8x8
mov dx,si
not dl ;{Zeile stürzen für DIB}
mov bl,dh
xor bh,bh ;{BX=Spalte(X)}
xor dh,dh ;{DX=Zeile(Y), gestürzt}
mov di,dx
add di,di
add di,di ;{Spalte*4}
add di,dx ;{*5}
shl di,3 ;{*40}
add di,bx ;{Zeile*40+Spalte}
mov dx,[hDisplay]
shl di,3 ;{Pixel-Adresse, CY ist das letzte Bit}
jnc @@1
add dx,offset __ahincr
@@1: ;{DX:DI nun Adresse in Pixmap}
cld
;{Hauptschleife mit: DX:DI=Windows-DIB-Adresse,
; AL=Akku, CL=Pixelbyte, CH=HFarbe, AH=VFarbe, BH=Bitmaske,
; SI=KC-Pixel-Adresse, [KC4Pixel], [KC4Color]: Basiszeiger}
mov al,[KC4Port84H]
and ax,1
ror ax,1 ;{0 oder 8000h}
add si,ax
mov cl,[es:si] ;{Pixel-Byte}
mov al,[es:si+4000h];{Farb-Byte}
mov ch,al
mov es,dx ;{hDisplay-Segment}
test [KC4Port84H],8 ;{HRG-Modus? (Bit invertiert!)}
mov bh,80h ;{Start mit Bit 7}
jz @@hrg
call GetVFarbe ;{CL enthält Pixel-Byte}
mov ah,al
and ch,7 ;{HFarbe}
@@l1: test cl,bh
mov al,ch ;{HFarbe?}
jz @@hf
mov al,ah ;{nimm VFarbe!}
@@hf: stosb ;{Pixel setzen}
shr bh,1
jnz @@l1
@@e: pop es
popa
ret
@@hrg: ;{im HRG-Modus liefern die Pixel-Bits den Rot- und die Farb-Bits
; den Türkis-Anteil - beide zusammen weiß}
@@l2: mov al,8 ;{Vordergrundfarbe Schwarz}
test cl,bh
jz @@p0
or al,2 ;{Vordergrundfarbe Rot}
@@p0: test ch,bh
jz @@c0
or al,5 ;{Vordergrundfarbe Türkis oder Weiß}
@@c0: stosb
shr bh,1
jnz @@l2
pop es
popa
ret
endp IRM_Access4
;**************************
proc IRM_Update4
;{Routine für die Umschaltung der KC85/4-Bildseite oder -Auflösung,
; dafür mehr als sonst auf Geschwindigkeit getrimmt}
;{PE: -, PA: -, VR: Flags}
pusha
cld
push es
mov bh,[KC4Port84H]
ror bh,1 ;{Bit7 je nach Anzeige-Bild}
mov si,[word HIGH KCIRM]
mov dx,[hDisplay]
xor di,di ;{fangen unten links an}
mov bl,0FFh
@@ll0: and bh,80h ;{entsprechende KC-Adresse}
@@ll: ;{ES:DI nun Adresse in Pixmap}
;{Hauptschleife mit: DX:DI=Windows-DIB-Adresse, SI=[KCIRM]
; AL=Akku(VFarbe), AH=Bitmaske, BL=Zeile, BH=Spalte (+80h),
; CL=Pixelbyte, CH=HFarbe, [KC4Pixel], [KC4Color]: Basiszeiger}
mov es,si
mov cl,[es:bx] ;{Pixel-Byte}
mov ch,[es:bx+4000h];{Farb-Byte}
mov es,dx
test [KC4Port84H],8 ;{HRG-Modus? (Bit invertiert!)}
mov ah,80h ;{Start mit Bit 7}
jz @@hrg
mov al,ch
and ch,7 ;{HFarbe}
call GetVFarbe
@@l1: test cl,ah
jnz @@vf
xchg al,ch
stosb ;{HFarbe setzen}
xchg ch,al
shr ah,1 ;{Doppelt zur Sprungvermeidung}
jnz @@l1
jmp @@w
@@vf: stosb ;{VFarbe setzen}
@@w1: shr ah,1
jnz @@l1
jmp @@w
@@hrg: ;{im HRG-Modus liefern die Pixel-Bits den Rot- und die Farb-Bits
; den Türkis-Anteil - beide zusammen weiß. Blinken gibt's nicht}
@@l2: mov al,8 ;{Vordergrundfarbe Schwarz}
test cl,ah
jz @@p0
or al,2 ;{Vordergrundfarbe Rot}
@@p0: test ch,ah
jz @@c0
or al,5 ;{Vordergrundfarbe Türkis oder Weiß}
@@c0: stosb
shr ah,1
jnz @@l2
@@w: or di,di
jnz @@ni
add dx,offset __ahincr
mov es,dx ;{nächstes Segment}
@@ni: inc bh ;{X - nach rechts}
mov al,bh
and al,7Fh
cmp al,40
jc @@ll
sub bl,1 ;{Y - nach oben}
jnc @@ll0
ToInvalWnd:
call InvalWnd
pop es
@@e: popa
ret
endp
;**************************
proc IRM_Update3
;{PE: -, PA: -, VR: Flags}
;Langsame Variante, da nur bei Emulator-Start oder -Resume gerufen
pusha
push es
mov cx,0A00h
mov bx,0A800h
mov di,offset IRM_Access3
ToUpdate: mov es,[MemKCSel]
@@l: mov al,[es:bx]
call di
inc bx
loop @@l
jmp ToInvalWnd
endp IRM_Update3
;***********************************
;*** Routinen für Z9001 und KC87 ***
;***********************************
proc GetAnimIdx7
;{PE: AL=Farbbyte, Z=1: HFarbe, Z=0: VFarbe gewünscht;
; PA: AL=Index als Blinkfarbe (0..23)
; VR: AL, Flags}
jz @@bg
shr al,4
@@bg: and al,7
ret
endp
proc CalcZ24
;{rechnen: Adr=((23-Y)*8+7)*40+X, aufgelöst: Adr=7640-Y*320+X}
shl dl,3 ;{Pixelzeilen}
mov ax,40*256+24*8-1;{DIB-Adresse berechnen, =40*y+x}
sub al,dl ;{Pixelzeile stürzen, z.B. 0->191}
mul ah
add al,dh ;{X dazu}
adc ah,0 ;{AX ist Offset}
ret
endp CalcZ24
proc CalcZ20
;{rechnen: Adr=((19-Y)*10+8)*40+X, aufgelöst: Adr=7920-Y*400+X}
mov bl,dh
mov bh,0
mov al,-25
imul dl
shl ax,4 ;schneller als mul dx,-400
add ax,bx
add ax,7920
ret
endp CalcZ20
;**************************
proc IRM_Access1
;{PE: BX=Schreibadresse, (ES:BX bereits geschrieben), AL=Zeichen
; PA: -, VR: Flags}
pusha
mov ch,al ;{Zeichen retten}
sub bh,0ECh
IFDEF DEBUG
cld
cmp bh,04h
jnc @@e
ENDIF
mov ax,bx
mov cl,40
div cl ;{AH=ZeichenSpalte, AL=ZeichenZeile}
test [KC4Port88H],4
jz @@z24 ;{normaler 24-Zeilen-Modus}
cmp al,20
jnc @@e
xchg ax,dx
push es
call InvalChrBox ;{mit DH=X und DL=Y}
call CalcZ20
jmp @@w20
@@z24:
cmp al,24 ;{24. oder 25. Zeile?}
jnc @@e ;{Ja-raus (kein Zugriff)}
xchg ax,dx ;{DH=Spalte(X), DL=Zeile(Y)}
;{Test auf InUpdate und Aufruf von InvalidateRect}
push es
call InvalChrBox ;{mit DH=X und DL=Y}
call CalcZ24
@@w20: mov es,[hDisplay]
xchg ax,di ;{ES:DI: fertig ist die DIB-Adresse!}
mov cl,0
shr cx,5 ;{Zeichencode in Position bringen}
push ds
mov ds,[hCharMap]
mov si,cx ;{und DS:SI zeigt auf Zeichenbildtabelle}
;{Hauptschleife mit: ES:DI=Windows-DIB-Adresse, DS:SI=Zeichenbild,
; CX=Schleifenzähler}
mov cx,8
@@l: movsb
sub di,1+40 ;{DIB ist "verkehrtherum"}
loop @@l
pop ds
pop es
@@e: popa
ret
endp IRM_Access1
proc GetVFarbeZ
;{PE: CL=Zeichencode (20h verhindert Blinken), AL=Farbattribut
; PA: AL=Palettenindex für VFarbe; VR: AL,CH,Flags}
;{N: HFarbe ist AL and 7}
cmp al,80h ;{Blinkbit?}
jbe @@nb ;{wenn kein Blinkbit oder schwarz auf schwarz}
cmp [Blinken],0
jz @@nb ;{wenn global ausgeschaltet}
cmp cl,20h ;{Leerzeichen?}
je @@nb ;{Auch nicht blinken!}
mov ch,al
shr ch,4
xor ch,al
and ch,7 ;{Grauer Adler auf grauem Grund?}
jz @@nb
call GetBlinkFarbe
jnc @@e
@@nb: shr al,4
and al,7
@@e: ret
endp GetVFarbeZ
proc CalcZ7
;Hilfsroutine für IRM_Access7
;PE: AX=Monochrom-Bitmap-Adresse, SI=Z9001-Zugriffsadresse AND 3FFh
;PA: ES:DI=DIB-Adresse, SI=Zeichentabellen-Offset,
; BH=VFarbe (0..7 oder 24..31), AH=HFarbe(0..7)
shl ax,3
xchg ax,di ;{DI ist Offset}
mov cl,[es:si+0EC00h] ;{ASCII}
mov al,[es:si+0E800h] ;{Farbe}
mov es,[hDisplay] ;{ES:DI: fertig ist die DIB-Adresse!}
mov ah,al
and ah,7 ;{8 Hintergrundfarben}
call GetVFarbeZ ;{AL->Index (unter Verwendung von CL)}
mov ch,0
shl cx,3 ;{Zeichencode in Position bringen}
mov si,cx ;{und (DS:)SI zeigt auf Zeichenbildtabelle}
mov bh,al
ret
endp CalcZ7
proc StosZ
;gemeinsame Zeichenschreibroutine
mov cl,8
@@lx2: mov ch,80h
lodsb ;{Zeichentabellen-Zugriff}
mov bl,al
@@lx: test bl,ch ;{Pixel gesetzt}
mov al,ah
jz @@x1 ;{nein, HFarbe verwenden}
mov al,bh
@@x1: stosb
shr ch,1 ;{Nächstes Bit}
jnz @@lx
sub di,8+320 ;{DIB ist "verkehrtherum"}
loop @@lx2 ;{CH ist hier Null!}
ret
endp StosZ
;**************************
proc IRM_Access7
;{PE: BX=Schreibadresse, (ES:BX bereits geschrieben), AL=Zeichen oder Farbcode
; PA: -, VR: Flags
;FARBBYTE:
; Bit 7: 1=Blinken
; Bit 6..4: Vordergrundfarbe B-G-R
; Bit 3: frei
; Bit 2..0: Hintergrundfarbe B-G-R
;BILDSCHIRMRAND UND ZEILENUMSTELLUNG
; Port 136 (88h):
; Bit 5..3: Bildrandfarbe B-G-R (wird später via WM_NCPaint emuliert)
; Bit 2: 1=20-Zeilen-Modus mit 8x10-Zeichenzellen}
pusha
IFDEF DEBUG
cld
sub bh,0E8h
cmp bh,08h
jnc @@e
ENDIF
and bh,3 ;{auf Pixeladresse}
mov si,bx ;{Adresse retten}
mov ax,bx
mov cl,40
div cl ;{AH=ZeichenSpalte, AL=ZeichenZeile}
test [KC4Port88H],4
jz @@z24 ;{normaler 24-Zeilen-Modus}
cmp al,20
jnc @@e
xchg ax,dx
push es
call InvalChrBox ;{mit DH=X und DL=Y}
call CalcZ20
add ax,40 ;Korrektur, um Leerzeile mit HFarbe zu füllen
call CalcZ7 ;Weitere Vorbereitungen
push ds
mov ds,[hCharMap]
;{Hauptschleife mit: ES:DI=Windows-DIB-Adresse, DS:SI=Zeichenbild, AH=HFarbe
; BH=VFarbe, BL=Bits, CH=Maske, CL=Schleifenzähler}
mov al,ah
mov cx,4 ;{Word-Zähler}
rep stosw ;{Obere leere Zeile füllen}
sub di,8+320
call StosZ
mov cl,4
mov al,ah
rep stosw ;{Untere leere Zeile füllen}
jmp @@w20
@@z24:
cmp al,24 ;{24. oder 25. Zeile?}
jnc @@e ;{Ja-raus}
xchg ax,dx ;{DH=Spalte(X), DL=Zeile(Y)}
;{Test auf InUpdate und Aufruf von InvalidateRect}
push es
call InvalChrBox
call CalcZ24
call CalcZ7
push ds
mov ds,[hCharMap]
;{Hauptschleife mit: ES:DI=Windows-DIB-Adresse, DS:SI=Zeichenbild, AH=HFarbe
; BH=VFarbe, BL=Bits, CH=Maske, CL=Schleifenzähler}
call StosZ
@@w20: pop ds
pop es
@@e: popa
ret
endp IRM_Access7
;**************************
proc IRM_Update1
;{PE: -, PA: -, VR: Flags}
;Langsame Variante, jedoch mit Anpassung an 20/24-Zeilen-Modus
pusha
push es
;ACHTUNG-beim IRM_Access1 erfolgt nicht das Löschen der Freizeilen zwischen
;den Zeilen, deshalb muß hier im 20-Zeilen-Modus die Bitmap gelöscht werden!
test [KC4Port88H],4
jz @@0
mov es,[hDisplay]
xor ax,ax
mov di,ax
mov cx,200*40/2
cld
rep stosw ;{Speicher löschen wegen Freizeilen}
@@0: mov di,offset IRM_Access1
ToUpdZ:
mov cx,40*24
test [KC4Port88H],4
jz @@1
mov cx,40*20 ;Anzahl Zeichen
ToUZ1013:
@@1: mov bx,0EC00h ;Zeichenspeicher (auch bei Z1013!)
jmp ToUpdate
endp IRM_Update1
;**************************
proc IRM_Update7
;{PE: -, PA: -, VR: Flags}
;Langsame Variante, jedoch mit Anpassung an 20/24-Zeilen-Modus
pusha
push es
mov di,offset IRM_Access7
jmp ToUpdZ ;weiter wie bei Update1
endp IRM_Update7
;**************************
;*** Routinen für Z1013 ***
;**************************
proc IRM_Access9
;{PE: BX=Schreibadresse, (ES:BX bereits geschrieben), AL=Zeichen
; PA: -, VR: Flags}
pusha
mov ch,al ;{Zeichen retten}
sub bh,0ECh
IFDEF DEBUG
cmp bh,04h
jnc @@e
ENDIF
mov dx,bx
shl dx,3
shr dl,3
mov di,dx
xchg dl,dh ;{DL=Zeile(Y), DH=Spalte(X)}
;{Test auf InUpdate und Aufruf von InvalidateRect}
push es
call InvalChrBox
xor di,1FE0h ;{Zeile stürzen für DIB}
mov es,[hDisplay] ;{ES:DI: fertig ist die DIB-Adresse!}
mov cl,0
ror cx,5 ;{Zeichen 'runterholen und *8}
push ds
mov ds,[hCharMap]
mov si,cx ;{und DS:SI zeigt auf Zeichenbildtabelle}
;{Hauptschleife mit: ES:DI=Windows-DIB-Adresse, DS:SI=Zeichenbild,
; CX=Schleifenzähler}
cld
mov cx,8
@@l: movsb
sub di,1+32 ;{DIB ist "verkehrtherum"}
loop @@l
pop ds
pop es
@@e: popa
ret
endp IRM_Access9
;**************************
proc IRM_Update9
;{PE: -, PA: -, VR: Flags}
pusha
push es
mov di,offset IRM_Access9
mov cx,32*32
jmp ToUZ1013
endp IRM_Update9
END
Detected encoding: OEM (CP437) | 1
|
|