; Septic's Demoskola - Lektion 7 : Blitter (scroll)
; Skriven av Vicious / Septic - 23 Juli 1993

DisableCache=1	; En nolla betyder att funktionen är avstängd...
DisableMotor=1

	section	Lektion7,code_c

j:	movem.l	d0-a6,-(sp)

	bsr.w	INIT
	tst.l	gfxbase		; Kolla om vi hittade gfx.library
	beq.s	error		; Nepp...Då hoppar vi ut...

	move.w	#%1000011111000000,$dff096	; Vår lilla DMA
	;	  S    NDBCBSD
	;	  E    aMPOLPS
	;	  T    sALPTRK
	;	       t
	;              y

	bsr.w	setbplptr

	move.l	#copper,$dff080	; Nu sätter vi vår egen copperlista
	move.w	d0,$dff088	; Och tvingar den att börja direkt...

main:
	bsr.s	sync
	bsr.s	scrolltext	; Hoppa till scrolltext-rutinen!
	btst	#6,$bfe001	; Testa vänster musknapp!
	bne.s	main

xit:	bsr.w	UnINIT
error:	movem.l	(sp)+,d0-a6
	rts

; Syncroniserings rutin
sync:	move.l	$dff004,d0
	and.l	#$1ff00,d0
	lsr.l	#8,d0
	cmp.w	#$f0,d0		; Kolla om rasterrad=$f0
	bne.s	sync
	rts

ScrollCounter:
	dc.w	1

ScrollText:
	movem.l	d0-a6,-(sp)
	subq.w	#1,scrollcounter
	bne.s	.NoNewChar
	move.w	#8,scrollcounter
	bsr.s	NewChar
.NoNewChar:
	bsr.s	ScrollIt
	movem.l	(sp)+,d0-a6
	rts

ScrollIt:
	btst	#6,$dff002
	bne.s	ScrollIt
	lea.l	screen+2,a0		; Source
	lea.l	screen,a1		; Destination
	move.w	#$c000+srca!dest!a,$dff040	; BLTCON0
	move.w	#0,$dff042		; BLTCON1
	move.l	#$ffffffff,$dff044	; BLTAxWM
	move.l	a0,$dff050		; BLTAPT
	move.l	a1,$dff054		; BLTDPT
	move.w	#$0,$dff064		; BLTAMOD
	move.w	#$0,$dff066		; BLTDMOD
	move.w	#((32*4)+8)*64+23,$dff058	; BLTSIZE
	rts

NewChar:
	move.l	textptr(pc),a0
	moveq	#0,d0
	move.b	(a0)+,d0
	bne.s	.notzero
	move.l	#text,textptr
	bra.s	newchar
.notzero:
	move.l	a0,textptr
	sub.b	#32,d0
	moveq	#0,d1
	divu	#10,d0		; Dela med 10 eftersom det är 10 bokstäver
				; på varje fontrad.
	move.w	d0,d1		; D1 innehåller nu raden
	mulu	#40*32,d1	; Mulla med 40*32 eftersom fontbilden är
				; 40 bytes bred och varje bokstav är
				; 32 pixlar hög.
	clr.w	d0
	swap	d0		; och D0 X offseten
	asl.w	#2,d0		; Mulla med 4 för att få rätt offset
				; för en 32 pixels font...

	lea.l	font,a0
	add.l	d0,a0
	add.l	d1,a0
	lea.l	screen+46,a1

	moveq	#4-1,d6
.nxtbpl:moveq	#32-1,d7
.nxtrow:move.l	(a0),(a1)
	add.l	#40,a0
	add.l	#48,a1
	dbf	d7,.nxtrow
	add.l	#(40*192)-(40*32),a0
	dbf	d6,.nxtbpl
	rts

; Detta är initialiserings-rutinen....
AttnFlags=296
INIT:
	movem.l	d0-a6,-(sp)
	bsr.w	FetchVBR

	move.l	$4.w,a6
	jsr	-132(a6)	; Forbid - Stäng av multitasking

 IFNE DisableCache		; Kolla om den här rutinen ska vara med...
	cmp.w	#36,20(a6)	; Disable Cache funkar bara på KS2.0++
	bcs.s	.not20		; Om lägre än 2.0 så hoppar vi vidare...
	move.l	#$00003818,d0	; Har inte kunnat testa de här siffrorna
	move.l	#$80003b1b,d1	; men det ska förmodligen funka :-)
	jsr	-648(a6)	; CacheControl()
	lea.l	OldCache(pc),a0
	move.l	d0,(a0)
.not20:
 ENDC

	lea.l	gfxname(pc),a1
	jsr	-408(a6)	; OldOpenLibrary() - Funkar lika bra som
	tst.l	d0		; valiga openlibrary() om man inte behöver
	beq.w	noGfx		; öppna en speciell version...
	move.l	d0,GfxBase
	move.l	d0,a6
	jsr	-456(a6)	; Ownblitter - Ska vi använda blittern måste
				; vi se till att vi får ta den...
	jsr	-228(a6)	; Och det är lika bra att vänta på den oxå!
				; Det gör vi med WaitBlit()
	sub.l	a1,a1
	jsr	-222(a6)	; Loadview - Nu kysser vi copperlistan adjö!
	jsr	-270(a6)	; WaitTOF - Vänta tills vi med säkerhet kan
	jsr	-270(a6)	; installera våra egna saker...WaitTOF ska
				; enligt Commodore helst köras två gånger!
	lea.l	oldintena(pc),a1
	move.w	$dff01c,(a1)+	; Spara gamla interrupt statusen
	move.w	$dff002,(a1)	; Spara gammal DMA
	move.w	#$7fff,d0
	move.w	d0,$dff09a	; INTENA
	move.w	d0,$dff096	; DMACON - Vi rensar gammal skit...

 IFNE DisableMotor		; Kolla om vi ska kötta av drivemotorn...
	move.b	#-1,$bfd100	; Den här lilla kodsnutten är inte direkt
	nop			; snäll men bör fungera ändå. Det värsta
	nop			; som kan hända är att driven fortsätter
	move.b	#$81,$bfd100	; att vara på.
	nop			; Mer om denna lilla snutt kommer när jag
	nop			; tar upp HW-trackloading! Tills dess får
	move.b	#-1,$bfd100	; ni svälja den utan förklaring...
 ENDC
	movem.l	(sp)+,d0-a6
	rts

NoGFX:	move.l	$4.w,a6
	jsr	-138(a6)	; Permit multitasking...
	movem.l	(sp)+,d0-a6
	rts

; Denna rutin sätter upp systemet igen...
UNINIT:
	movem.l	d0-a6,-(sp)
	move.w	oldintena(pc),d0
	or.w	#$8000,d0		; Så bitarna sätts och inte rensas
	move.w	d0,$dff09a
	move.w	olddmacon(pc),d0
	or.w	#$8000,d0
	move.w	d0,$dff096

	move.l	gfxbase(pc),a6
	jsr	-228(a6)	; Waitblit()
	jsr	-462(a6)	; DisOwnBlit()

	lea.l	intname(pc),a1	; Nu måste vi öppna Intuition
	move.l	$4.w,a6
	jsr	-408(a6)	; OldOpenlibrary
	move.l	d0,a2
	tst.l	d0		; Kolla om intuition gick att öppna....
	beq.s	.closegfx	; Hoppa om det inte gick...

	lea.l	34(a2),a1	; Fetcha Viewporten!
	move.l	gfxbase(pc),a6
	jsr	-222(a6)	; Loadviewa in den riktiga viewporten!
	move.l	$26(a6),$dff080	; Och restora gamla copperlistorna...
	move.l	$30(a6),$dff084

	move.l	a2,a1
	move.l	$4.w,a6
	jsr	-414(a6)	; Stäng intuition

.closegfx:
	move.l	$4.w,a6
	move.l	gfxbase(pc),a1
	jsr	-414(a6)	; och stäng också graphics.library...

 IFNE DisableCache
; Nu sätter vi på cache-minnet igen...
	cmp.w	#36,20(a6)	; Kolla version igen...Verkligen dumt
	bcs.s	.not20		; om det skulle ändra sig under programmets
				; gång! :-)))
	move.l	oldcache(pc),d0
	moveq	#-1,d1
	jsr	-648(a6)	; CacheControl()
.not20:
 ENDC
	jsr	-138(a6)	; Permit multitasking

	movem.l	(sp)+,d0-a6
	rts

; Den här rutinen hämtar VBR, vilket är en offset till vektorområdet
; på högre processorer än 68000. På en vanlig 68000 är VBR alltid 0.
FetchVBR:
	move.l	a6,-(sp)
	move.l	$4.w,a6			; Hämta exec
	sub.l	a0,a0			; Nollställ a0
	btst	#0,Attnflags+1(a6)	; Kolla om 68010++
	beq.s	.Lower
	move.l	a5,-(sp)
	lea.l	.getVBR(pc),a5
	jsr	-30(a6)		; Vi måste hämta VBR i supervisor mode
	move.l	(sp)+,a5
.lower:	move.l	(sp)+,a6
	rts

.GetVBR:movem.l	a0/a1,-(sp)
	lea.l	MyVBR(pc),a1	; Här ska vi skriva in VBRen.
	dc.l	$4e7a8801	; Detta är egentligen instruktionen
				; MOVEC VBR,A0 men eftersom äldre versioner
				; inte stödjer den instruktionen gjorde jag
				; ett litet specialtrick här...
	move.l	a0,(a1)
	movem.l	(sp)+,a0/a1
	rte			; Återvänd från supervisor...

MyVBR:	dc.l	0		; Här lägger vi VBR!


SetBplPtr:
	movem.l	d0-a6,-(sp)
	lea.l	screen,a0
	move.l	a0,d0
	lea.l	bplptr+2(pc),a0
	moveq	#4-1,d7
.setbpl:move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	lea.l	8(a0),a0
	add.l	#48*32,d0
	dbf	d7,.setbpl
	movem.l	(sp)+,d0-a6
	rts

************* COPPER ************

copper:
	dc.w	$008e,$8061	; DIWSTRT
	dc.w	$0090,$b0e1	; DIWSTOP
	dc.w	$0092,$0028	; DDFSTRT
	dc.w	$0094,$00d8	; DDFSTOP
	dc.w	$0100,$4200	; BPLCON0
	dc.w	$0102,$0000	; BPLCON1
	dc.w	$0104,$0000	; BPLCON2
	dc.w	$0108,$0002	; BPLMOD0
	dc.w	$010a,$0002	; BPLMOD1

	; Bitplanspekare
bplptr:	dc.w	$00e0,$0000,$00e2,$0000,$00e4,$0000,$00e6,$0000
	dc.w	$00e8,$0000,$00ea,$0000,$00ec,$0000,$00ee,$0000

	; Fontens färger (sparat i en IFF2RAW konverterare)
fontcols:
	dc.w	$0180,$0000,$0182,$0a9b,$0184,$0435,$0186,$0546
	dc.w	$0188,$0657,$018a,$0768,$018c,$0879,$018e,$098a
	dc.w	$0190,$0324,$0192,$0bac,$0194,$0cbd,$0196,$0dce
	dc.w	$0198,$0edf,$019a,$0fef,$019c,$006f,$019e,$000a

	dc.w	$7e07,$fffe,$0180,$fff
	dc.w	$7f07,$fffe,$0180,$006

	dc.w	$a007,$fffe
	dc.w	$0108,$ff72,$010a,$ff72	; Här sätter jag negativ modulo
					; och gör därmed så att Amigan
					; visar rad för rad uppåt igen
					; så att bilden blir uppochnervänd
					; och så har vi enkelt skapat en
					; komprimerad spegeleffekt.

	; Fontfärger i spegeln, eftersom de ska vara lite mörkare...
mirrorcols:
	dc.w	$0180,$0004,$0182,$0657,$0184,$0001,$0186,$0102
	dc.w	$0188,$0213,$018a,$0324,$018c,$0435,$018e,$0546
	dc.w	$0190,$0000,$0192,$0768,$0194,$0879,$0196,$098a
	dc.w	$0198,$0a9b,$019a,$0bab,$019c,$002b,$019e,$0006

	dc.w	$b107,$fffe,$0180,$fff
	dc.w	$b207,$fffe,$0180,$000

	dc.w	$ffff,$fffe

gfxname:dc.b	'graphics.library',0
intname:dc.b	'intuition.library',0
	even
gfxbase:dc.l	0
oldintena:
	dc.w	0
olddmacon:
	dc.w	0
OldCache:
	dc.l	0
TextPtr:dc.l	text

	; Vår lilla scrolltext...Endast stora bokstäver.
Text:
	DC.B	'TJOSAN I STUGAN!   DETTA %R LEKTION 7 I DEMOSKOLAN '
	DC.B	'SOM VISAR HUR MAN KAN G+RA EN SCROLLANDE TEXT '
	DC.B	'MED BLITTERN!   KASTA ALDRIG GRUS P& EN KINESISK '
	DC.B	'RISPLOCKARE!   CYNEZ! - VICIOUS/SEPTIC    (MYCKET '
	DC.B	'MUMSIGA SVULLNA L%BBIGA OCH BIGGA TACKNINGAR TILL '
	DC.B	'SQUEALER/SEPTIC F+R DEN H%R FONTEN!)        '
	dc.b	0

	section	scr,data_c
screen:	ds.b	48*32*4
	ds.b	48*8		; (Just Safety)

	section	fontie,data_c
Font:	incbin	'bbsfont.raw'


; Blitter MINTERM data
DEST =	$100
SRCC =	$200
SRCB =	$400
SRCA =	$800

ABC =	$80
ABNC =	$40
ANBC =	$20
ANBNC =	$10
NABC =	$8
NABNC =	$4
NANBC =	$2
NANBNC =	$1

A = ABC!ABNC!ANBC!ANBNC
B = ABC!ABNC!NABC!NABNC
C = ABC!ANBC!NABC!NANBC

NA = (~A)&$FF
NB = (~B)&$FF
NC = (~C)&$FF

