*
* 6569mono.i - Schnellere VIC-Emulation (Amiga monochrom)
*
* Copyright (C) 1994-1996 by Christian Bauer
*

*
* Anmerkungen:
* ------------
*
* Funktionsweise:
*  - Die monochrome Emulation arbeitet nicht mit einer Chunky-Bitmap,
*    sondern schreibt die rohen Grafikdaten direkt in eine Amiga-Bitplane
*  - Farbwerte werden ignoriert, der Hintergrund ist immer schwarz, die
*    Grafik immer weiß, ebenso bei den Sprites. Eine Ausnahme bildet die
*    Rahmenfarbe: Sie ist immer weiß, außer wenn der Rahmen schwarz ist
*


*
* Definitionen
*

BytesPerLine	= DisplayX/8	;Anzahl Bytes pro Zeile in einer Bitplane

*
* Makros
*

; Sprite darstellen
FDoSprite	MACRO	;Nummer
		moveq	#\1,d6		;d6: Spritenummer
		btst	d6,SPRITEON(a4)	;Wird das Sprite dargestellt?
		beq	\@1$

		move.l	MATRIXBASE(a4),a0
		moveq	#0,d0
		move.b	$03f8+\1(a0),d0	;d0: Datenzeiger
		move.w	MC\1(a4),d1	;d1: MC
		move.w	SPRX\1(a4),d5	;d5: X-Koordinate
		bsr	FDrawSprite
\@1$
		ENDM


**
** Eine Rasterzeile ausführen (monochrom)
**
** d7: Rasterzeilenzähler
** a4: Zeiger auf VIC-Register
** a5: Zeiger auf das Ziel im Bildschirmspeicher
**

AmigaMono6569

*
* "Bad Lines"-Videomatrixzugriff:
* 40 Bytes aus Videomatrix und Farb-RAM lesen und zwischenspeichern
*

		tst.b	BADLINEENABLE(a4) ;War das DEN-Bit in Rasterzeile $30 gesetzt?
		beq	FNoBadLine

		cmp.w	#FirstDMALine,d7 ;Innerhalb des DMA-Bereiches?
		blo	FNoBadLine
		cmp.w	#LastDMALine,d7
		bhi	FNoBadLine

		move.b	d7,d0		;Ja, stimmen die unteren Bits
		and.b	#7,d0		;der Rasterzeile mit dem Y-Scroll
		cmp.b	YSCROLL+1(a4),d0 ;überein?
		bne	FNoBadLine

FIsBadLine	st.b	BADLINE(a4)	;Ja, Bad Line
		move.w	VCCOUNT(a4),d2	;d2: VC Videomatrix-Zähler

		move.l	MATRIXBASE(a4),a0 ;Videomatrixbasis holen
		add.w	d2,a0		;Videomatrixzähler dazunehmen

		lea	MatrixLine,a1	;Nur Videomatrix-Zeile lesen
		movem.l	(a0)+,d0-d6	;40 Bytes kopieren
		movem.l	d0-d6,(a1)
		movem.l	(a0)+,d0-d2
		movem.l	d0-d2,28(a1)

		clr.w	RC(a4)		;RC zurücksetzen
		clr.b	DISPLAYOFF(a4)	;Darstellung anschalten

		move.w	BadLineCycles,CyclesLeft ;Andere Anzahl Zyklen
FNoBadLine

*
* Oberen und unteren Rahmen handhaben
*

		cmp.w	DYSTOP(a4),d7	;Unteres Ende des Fensters erreicht
		bne	1$		; -> Rahmen einschalten
		st.b	BORDERON(a4)
		bra	FTBBorderDraw

1$		btst	#4,CTRL1(a4)	;Rahmen nur abschalten, wenn DEN-Bit gesetzt
		beq	FTBBorderDone
		cmp.w	DYSTART(a4),d7	;Oberes Ende des Fensters erreicht
		bne	FTBBorderDone	; -> Rahmen abschalten
		clr.b	BORDERON(a4)
		bra	FTBNoBorder

FTBBorderDone	tst.b	BORDERON(a4)	;Rahmen an?
		beq	FTBNoBorder

FTBBorderDraw	move.l	CURRENTA5(a4),a0 ;Ja, Rahmen malen

		tst.b	$20(a4)		;Jede Farbe außer schwarz wird als weiß dargestellt
		beq	FTBBorderBlack

		moveq	#-1,d0		;Rahmen weiß
		move.w	#BytesPerLine/4-1,d1
FTBBorderLoop	move.l	d0,(a0)+
		dbra	d1,FTBBorderLoop
		bra	FVICIncA5	;Sonst nix

FTBBorderBlack	move.w	#BytesPerLine/4-1,d1 ;Rahmen schwarz
FTBBlackLoop	clr.l	(a0)+
		dbra	d1,FTBBlackLoop
		bra	FVICIncA5	;Sonst nix
FTBNoBorder

*
* Inhalt des Fensters: Darstellung eingeschaltet?
*

		lea	4(a5),a1	;a1: Ziel in Bildschirmspeicher
		lea	MatrixLine,a2	;a2: Zeichencodes

		tst.b	DISPLAYOFF(a4)	;$3FFF darstellen?
		bne	FShow3FFF

		move.l	DisplayProc,a0	;Nein, Routine entsprechend
		jmp	(a0)		;dem Darstellungsmodus anspringen

*
* Standard-Text: Zeichendaten holen und darstellen
*

FTextStd	add.w	#40,VCCOUNT(a4)	;VC erhöhen (wird nicht verwendet)

		move.l	CHARBASE(a4),a0	;a0: Zeichengeneratorbasis
		add.w	RC(a4),a0	;RC dazunehmen

		clr.b	4(a5)		;Hintergrund, wenn XScroll>0

		moveq	#0,d3		;XScroll holen
		move.w	XSCROLL(a4),d3
		beq	FTextNoScroll

; Schleife für 40 Zeichen
		moveq	#9,d1		;d1: 4-Zeichen-Zähler
		moveq	#0,d0
FCharLoop	move.b	(a2)+,d0	;Grafikdaten von 4 Zeichen lesen
		move.w	(a0,d0.w*8),d2
		move.b	(a2)+,d0
		move.b	(a0,d0.w*8),d2
		swap	d2
		move.b	(a2)+,d0
		move.w	(a0,d0.w*8),d2
		move.b	(a2)+,d0
		move.b	(a0,d0.w*8),d2
		bfins	d2,(a1){d3:32}	;und in den Bildschirm schreiben
		addq.w	#4,a1		;Zielzeiger erhöhen
		dbra	d1,FCharLoop
		bra	FDoSprites

; Schleife für 40 Zeichen, kein XScroll
FTextNoScroll	moveq	#9,d1		;d1: 4-Zeichen-Zähler
		moveq	#0,d0
FNCharLoop	move.b	(a2)+,d0	;Grafikdaten von 4 Zeichen lesen
		move.w	(a0,d0.w*8),d2
		move.b	(a2)+,d0
		move.b	(a0,d0.w*8),d2
		swap	d2
		move.b	(a2)+,d0
		move.w	(a0,d0.w*8),d2
		move.b	(a2)+,d0
		move.b	(a0,d0.w*8),d2
		move.l	d2,(a1)+	;und in den Bildschirm schreiben
		dbra	d1,FNCharLoop
		bra	FDoSprites

*
* Standard-BitMap: Grafikdaten holen und darstellen
*

FBitMapStd	move.l	BITMAPBASE(a4),a0 ;a0: Bitmap-Basis
		move.w	VCCOUNT(a4),d0	;VC holen
		lsl.w	#3,d0		;*8
		add.w	RC(a4),d0	;RC dazunehmen
		add.w	d0,a0		;und zur Bitmap-Basis dazunehmen

		add.w	#40,VCCOUNT(a4)	;VC erhöhen

		clr.b	4(a5)		;Hintergrund, wenn XScroll>0

		moveq	#0,d3		;XScroll holen
		move.w	XSCROLL(a4),d3
		beq	FBitMapNoScroll

; Schleife für 40 Bytes
		moveq	#9,d1		;d1: 4-Zeichen-Zähler
FBitMapLoop	move.w	(a0),d2		;4 Bytes Grafikdaten lesen
		move.b	8(a0),d2
		swap	d2
		move.w	16(a0),d2
		move.b	24(a0),d2
		bfins	d2,(a1){d3:32}	;und in den Bildschirm schreiben
		addq.w	#4,a1		;Zielzeiger erhöhen
		lea	32(a0),a0	;Quellzeiger erhöhen
		dbra	d1,FBitMapLoop
		bra	FDoSprites

; Schleife für 40 Bytes, kein XScroll
FBitMapNoScroll	moveq	#9,d1		;d1: 4-Zeichen-Zähler
FNBitMapLoop	move.w	(a0),d2		;4 Bytes Grafikdaten lesen
		move.b	8(a0),d2
		swap	d2
		move.w	16(a0),d2
		move.b	24(a0),d2
		move.l	d2,(a1)+	;und in den Bildschirm schreiben
		lea	32(a0),a0	;Quellzeiger erhöhen
		dbra	d1,FNBitMapLoop
		bra	FDoSprites

*
* Ungültiger Darstellungsmodus: Schwarzen Bildschirm anzeigen
*

FBlackScreen	add.w	#40,VCCOUNT(a4)	;VC erhöhen

		moveq	#9,d0		;40 Zeichen schwarz
1$		clr.l	(a1)+
		dbra	d0,1$
		bra	FDoSprites

*
* $3FFF darstellen
*

FShow3FFF	tst.b	$21(a4)		;Wenn der Hintergrund schwarz ist, sieht man nichts
		beq	FInvis3FFF

		moveq	#0,d3		;XScroll holen
		move.w	XSCROLL(a4),d3

		clr.b	4(a5)		;Hintergrund, wenn X-Scroll>0

		btst	#6,CTRL1(a4)
		bne	11$
		move.w	#$3fff,d0	;Byte bei $3FFF lesen
		bra	12$
11$		move.w	#$39ff,d0	;ECM: Byte bei $39FF lesen
12$		bsr	GetPhysical

		move.w	(a0),d0		;Byte als Langwort lesen
		move.b	(a0),d0
		swap	d0
		move.w	(a0),d0
		move.b	(a0),d0
		not.l	d0		;und invertieren

; Zeile schreiben
		moveq	#9,d1		;d0: 4-Zeichen-Zähler
FLoop3FFF	bfins	d0,(a1){d3:32}	;In den Bildschirm schreiben
		addq.w	#4,a1		;Zielzeiger erhöhen
		dbra	d1,FLoop3FFF
		bra	FDoSprites

; Hintergrund schwarz: 3FFF unsichtbar
FInvis3FFF	moveq	#9,d1		;d0: 4-Zeichen-Zähler
FLoop3FFFInvis	clr.l	(a1)+		;In den Bildschirm schreiben
		dbra	d1,FLoop3FFFInvis

*
* Sprites
*

FDoSprites	tst.b	SPRITEON(a4)	;Ist überhaupt ein Sprite z.Z. sichtbar?
		beq	FDrawLRBorder	;Ja, dann Sprites malen
		tst.w	SpritesOn	;Sprite-Darstellung angeschaltet?
		beq	FDrawLRBorder

*
* Mindestens ein Sprite ist sichtbar, Sprites malen
*

		move.l	d7,-(sp)
		FDoSprite 7
		FDoSprite 6
		FDoSprite 5
		FDoSprite 4
		FDoSprite 3
		FDoSprite 2
		FDoSprite 1
		FDoSprite 0
		move.l	(sp)+,d7

*
* Linken und rechten Rahmen zeichnen
*

; 40-Spalten-Rahmen
FDrawLRBorder	move.l	CURRENTA5(a4),a0

		tst.b	$20(a4)
		beq	FLRBorderBlack

		moveq	#-1,d0
		move.l	d0,(a0)		;Links: $00..$17
		move.l	d0,44(a0)	;Rechts: $158..$16f

; 38-Spalten-Rahmen
		tst.b	IS38COL(a4)
		beq	1$
		move.b	d0,4(a0)	;Links: $18..$1e
		move.b	d0,43(a0)	;Rechts: $14f..$157
1$		bra	FVICNext

; Schwarzer Rahmen
FLRBorderBlack	clr.l	(a0)		;40-Spalten
		clr.l	44(a0)
		tst.b	IS38COL(a4)	;38-Spalten
		beq	1$
		clr.b	4(a0)
		clr.b	43(a0)
1$

*
* Ende einer sichtbaren Zeile: Zeiger in Bitmap erhöhen
*

FVICNext
FVICIncA5	lea	BytesPerLine(a5),a5
		move.l	a5,CURRENTA5(a4)

*
* Zurück zur Haupt-Routine
*

		bra	VICIncRC


**
** Ein Sprite zeichnen (monochrom)
** d0.l: Spritedatenzeiger
** d1.w: MC
** d5.w: X-Koordinate
** d6.l: Spritenummer (0..7)
**

		CNOP	0,4
FDrawSprite	lsl.w	#6,d0		;Datenzeiger*64
		add.w	d1,d0		;MC dazunehmen
		bsr	GetPhysical	;a0: Spritedaten

		move.w	d5,d0		;X-Koordinate
		lsr.w	#3,d0		;Pixel in Bytes umrechnen
		lea	1(a5,d0.w),a1	;a1: Ziel im Bildschirmspeicher

		btst	d6,MXE(a4)	;X-expandiert?
		bne	FSprExp

		cmp.w	#$180-24,d5	;Sprite horizontal sichtbar?
		bhs	FSpriteDone

; Standard-Sprite
		and.w	#7,d5		;d5: Bit-Shift

		move.l	(a0),d0		;Sprite-Daten lesen,
		clr.b	d0		; auf 24 Bit beschränken
		lsr.l	d5,d0		; verschieben
		or.l	d0,(a1)		; und in den Bildschirm schreiben
FSpriteDone	rts

; X-expandiertes Sprite
FSprExp		cmp.w	#$180-48,d5	;Sprite horizontal sichtbar?
		bhs	FSpriteDone

		move.l	(a0),d0		;Sprite-Daten lesen
		lea	ExpTable,a0	; und expandieren (3 Bytes -> 3 Worte)
		moveq	#0,d1
		rol.l	#8,d0
		move.b	d0,d1
		move.w	(a0,d1.w*2),d2
		swap	d2
		rol.l	#8,d0
		move.b	d0,d1
		move.w	(a0,d1.w*2),d2
		moveq	#0,d3
		rol.l	#8,d0
		move.b	d0,d1
		move.w	(a0,d1.w*2),d3
		swap	d3

		and.w	#7,d5		;d5: Bit-Shift
		bne	1$
		or.l	d2,(a1)+	;Kein Shift, in den Bildschirm schreiben
		or.l	d3,(a1)
		rts

1$		subq.w	#1,d5		;Daten verschieben
2$		lsr.l	#1,d2
		roxr.l	#1,d3
		dbra	d5,2$

		or.l	d2,(a1)+	;und in den Bildschirm schreiben
		or.l	d3,(a1)
		rts

*
* Tabelle zum X-expandieren von Sprites
*

		CNOP	0,4
ExpTable	INCBIN	"ExpTable.bin"
