; Septic's Demoskola - Lektion 3 : Bitplansgrafik (Hires+Interlace)
; Skriven av Vicious / Septic 22 Maj 1993

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

Width=640
Height=512
Bitplan=4

	section	Lektion4,code_c

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

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

	move.w	#%1000001110000000,$dff096	; Vår lilla DMA...Notera
	;	  S    NDBCBSD			; att BPL-dma nu är på!
	;	  E    aMPOLPS
	;	  T    sALPTRK
	;	       t
	;              y

	bsr.w	setbplptr	; Ställ in bitplanspekare
	bsr.w	setcolours	; Sätt rätta färger i DestCols

	; Här ställer vi in lite pekare i coppern som möjliggör
	; automatisk interlace-flip.
	lea.l	xtracopper,a0
	lea.l	xtrapekareB+2,a1
	move.l	a0,d0
	move.w	d0,4(a1)
	swap	d0
	move.w	d0,(a1)

	lea.l	xtracopper2,a0
	lea.l	xtrapekareA+2,a1
	move.l	a0,d0
	move.w	d0,4(a1)
	swap	d0
	move.w	d0,(a1)

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

main:
	move.l	#$80,d1
	bsr.s	sync

	lea.l	destcols,a0	; Vi fejdar från svart orignal palette
	lea.l	cols,a1		; till destcols-färgerna.
	move.l	#16,d0		; 16 färger.
	move.l	#2,d1		; Hastighet 2.
	bsr.w	fade

	btst	#6,$bfe001	; Testa vänster musknapp!
	bne.s	main

	move.l	#16*3,d7
DownFade:
	move.l	#$80,d1
	bsr.s	sync
	lea.l	blackcols,a0
	lea.l	cols,a1
	move.l	#16,d0
	move.l	#2,d1
	bsr.w	fade
	dbf	d7,downfade

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

; Raster line in D1
sync:	move.l	$dff004,d0
	and.l	#$1ff00,d0
	lsr.l	#8,d0
	cmp.w	d1,d0
	bne.s	sync
	rts

; Den här rutinen sätter bitplanspekarna i coppern.
SetBplPtr:
	movem.l	d0-a6,-(sp)
	lea.l	picture,a0	; Peka på bilden.
	move.l	a0,d0		; Flytta över pekaren till D0 så att vi
				; kan använda kommandot SWAP senare...
	lea.l	bplptrA+2,a1	; Peka i copperlistan där vi ska skriva
				; in bitplanen.
	lea.l	bplptrB+2,a2	; Och peka här oxo!
	moveq	#Bitplan-1,d7	; Antal bitplan minus ett.
.SetPtrs:
	move.l	d0,d1
	add.l	#80,d1		; Adda 40 bytes
	move.w	d0,4(a1)	; Flytta de lägsta 16 bitarna till coppern.
	move.w	d1,4(a2)
	swap	d0		; Swappa de 16 lägsta bitarna i D0 med de
				; 16 högsta.
	swap	d1
	move.w	d0,(a1)		; Flytta in de 16 högsta bitarna av
				; bitplanspekaren i coppern.
	move.w	d1,(a2)
	swap	d0		; Och swappa tillbaka de 16 högsta och 16
				; lägsta bitarna i D0.

	add.l	#(width/8)*height,d0	; Lägg till storleken på ett
					; bitplan till D0 så att vi får
					; reda på var nästa bitplan börjar.
	lea.l	8(a1),a1		; Öka A1 med 8. Går snabbare än
					; ADD.L #8,A1...
	lea.l	8(a2),a2
	dbf	d7,.setptrs		; Loopa tillbaka!

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

; Den här rutinen sätter bildens färger i coppern.
SetColours:
	movem.l	d0-a6,-(sp)
	lea.l	picture,a0			; Peka på bilden.
	add.l	#((width/8)*height)*bitplan,a0	; Och lägg till hela bild-
						; storleken så att vi
						; hamnar i slutet på bilden
						; där vi har lagrat
						; färgerna.

	lea.l	destcols+2,a1	; Peka på destinations-färglistan.
	moveq	#(2^bitplan)-1,d7	; 2^Bitplan minus ett för loopen.
.setcols:
	move.w	(a0)+,(a1)	; Flytta ett färgvärde till coppern.
	lea.l	4(a1),a1	; Öka på A1 med 4.
	dbf	d7,.setcols	; Loopa...
	movem.l	(sp)+,d0-a6
	rts

*** Fading routine - Coded by Vicious of Septic ***
; A0 - Original colours
; A1 - Copper list colours
; D0 - Nr of colours
; D1 - Speed (0=fastest)

FADE:
	movem.l	d0-a6,-(sp)
	tst.w	fadecount
	beq.s	.WaitOk
	sub.w	#1,FadeCount
	bra.s	.out
.WaitOk:move.w	d1,FadeCount	; Set new wait
	lea.l	2(a0),a0
	lea.l	2(a1),a1
	bsr.s	.StepFade
.out:	movem.l	(sp)+,d0-a6
	rts

.StepFade:
	subq.l	#1,d0
.nxtval:moveq	#2,d1		; Red+Green+Blue
	move.w	#1,d4
	move.w	#$f,d5
.nxtrgb:move.w	(a0),d2		; Hämta destinations färg.
	move.w	(a1),d3		; Hämta nuvarande färg.
	and.w	d5,d2
	and.w	d5,d3
	cmp.w	d2,d3
	beq.s	.valmatch
	cmp.w	d2,d3
	bmi.s	.ValLo
	sub.w	d4,d3
	bra.s	.valok
.ValLo:	add.w	d4,d3
.valok:	not.w	d5
	and.w	d5,(a1)
	not.w	d5
	or.w	d3,(a1)
.valmatch:
	asl.w	#4,d4
	asl.w	#4,d5
	dbf	d1,.nxtrgb
	lea.l	4(a0),a0
	lea.l	4(a1),a1
	dbf	d0,.nxtval
	rts

FadeCount:
	dc.w	0

; 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
				; av AsmOne 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!


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

copper:
	dc.w	$008e,$2c81	; DIWSTRT
	dc.w	$0090,$2cc1	; DIWSTOP
	dc.w	$0092,$003c	; DDFSTRT
	dc.w	$0094,$00d4	; DDFSTOP
	dc.w	$0100,$c204	; BPLCON0 (4 bpl, Hires och Interlace!)
	dc.w	$0102,$0000	; BPLCON1
	dc.w	$0104,$0000	; BPLCON2
	dc.w	$0108,$0050	; BPLMOD1
	dc.w	$010a,$0050	; BPLMOD2

	; Alla 16 färger!
Cols:	dc.w	$0180,$0,$0182,$0,$0184,$0,$0186,$0
	dc.w	$0188,$0,$018a,$0,$018c,$0,$018e,$0
	dc.w	$0190,$0,$0192,$0,$0194,$0,$0196,$0
	dc.w	$0198,$0,$019a,$0,$019c,$0,$019e,$0

	dc.w	$008a,$0000	; CopJmp2

XtraCopper:
xtrapekareA:
	dc.w	$0084,$0000
	dc.w	$0086,$0000

	; Alla 6 bitplanspekarna!
bplptrA:dc.w	$00e0,$0000,$00e2,$0000,$00e4,$0000,$00e6,$0000
	dc.w	$00e8,$0000,$00ea,$0000,$00ec,$0000,$00ee,$0000
	dc.w	$00f0,$0000,$00f2,$0000,$00f4,$0000,$00f6,$0000

	dc.w	$ffff,$fffe

XtraCopper2:
xtrapekareB:
	dc.w	$0084,$0000
	dc.w	$0086,$0000

	; Alla 6 bitplanspekarna!
bplptrB:dc.w	$00e0,$0000,$00e2,$0000,$00e4,$0000,$00e6,$0000
	dc.w	$00e8,$0000,$00ea,$0000,$00ec,$0000,$00ee,$0000
	dc.w	$00f0,$0000,$00f2,$0000,$00f4,$0000,$00f6,$0000

	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

BlackCols:
	dc.w	$0180,$0,$0182,$0,$0184,$0,$0186,$0
	dc.w	$0188,$0,$018a,$0,$018c,$0,$018e,$0
	dc.w	$0190,$0,$0192,$0,$0194,$0,$0196,$0
	dc.w	$0198,$0,$019a,$0,$019c,$0,$019e,$0

DestCols:
	dc.w	$0180,$0,$0182,$0,$0184,$0,$0186,$0
	dc.w	$0188,$0,$018a,$0,$018c,$0,$018e,$0
	dc.w	$0190,$0,$0192,$0,$0194,$0,$0196,$0
	dc.w	$0198,$0,$019a,$0,$019c,$0,$019e,$0

	; Här laddar vi in vår bild.
	section	Bild,data_c
Picture:
	incbin	'ram:SplashII.raw'
