Source file: /~heha/hs/kcemu/[Download]kcemu_052.exe/SRC/KCSCR.ASM

;**********************************************************
;*
;*  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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded