; Septic's Demoskola - Lektion 6 : Sprites (Attached)
; Skriven av Vicious / Septic 15 Juni 1993

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

	section	Lektion6,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	#%1000001110100000,$dff096	; Sprite-DMA påslagen!
	;	  S    NDBCBSD
	;	  E    aMPOLPS
	;	  T    sALPTRK
	;	       t
	;              y

	bsr.w	SetSpritePointers
	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:
	move.l	#$f0,d1
	bsr.s	sync
	bsr.w	SineSwing
	bsr.s	SpriteMove
	btst	#6,$bfe001	; Testa vänster musknapp!
	bne.s	main

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

SpriteMove:
	movem.l	d0-a6,-(sp)
	lea.l	Spr1a(pc),a0
	lea.l	Dir1(pc),a2

	move.l	#4*2-1,d7

.movva:	move.l	(a0)+,a1	; Peka på sprite
	move.b	(a2),d0		; Hämta riktning
	add.b	d0,1(a1)	; Adda på riktning
	cmp.b	#$d8,1(a1)	; Kolla höger vägg
	bne.s	.rightok	; Hoppa om vi inte nått den
	neg.b	d0		; Annars negerar vi riktningen
.rightok:cmp.b	#$40,1(a1)	; Kolla vänster vägg på samma sätt
	bne.s	.leftok
	neg.b	d0
.leftok:move.b	d0,(a2)+	; Skriv tillbaka riktningen
	dbf	d7,.movva	; Loopa tillbaka

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

SprSin1:dc.l	Ysin		; Sinuspekare...Pekar lite olika
SprSin2:dc.l	Ysin+20		; i tabellen för att boxarna inte ska
SprSin3:dc.l	Ysin+14		; studsa samtidigt.
SprSin4:dc.l	Ysin+40
Spr1a:	dc.l	Sprite1a	; Pekare på spritedatan.
Spr1b:	dc.l	Sprite1b
Spr2a:	dc.l	Sprite2a
Spr2b:	dc.l	Sprite2b
Spr3a:	dc.l	Sprite3a
Spr3b:	dc.l	Sprite3b
Spr4a:	dc.l	Sprite4a
Spr4b:	dc.l	Sprite4b
Dir1:	dc.b	1		; Riktningar...
	dc.b	1
Dir2:	dc.b	-1
	dc.b	-1
Dir3:	dc.b	2
	dc.b	2
Dir4:	dc.b	-2
	dc.b	-2

SineSwing:
	movem.l	d0-a6,-(sp)
	lea.l	SprSin1(pc),a0
	lea.l	Spr1a(pc),a2

	move.l	#4-1,d7
.getit:
	move.l	(a0),a1		; Peka i sinustabellen
	move.l	(a2)+,a3	; Peka på sprite
	move.l	(a2)+,a4	; Och på spriten som e attachad till den

	cmp.w	#-1,(a1)	; Kolla om vi är i slutet på sinustabellen
	bne.s	.notend
	move.l	#Ysin,a1	; I så fall börjar vi om från början
.notend:
	move.w	(a1)+,d0	; Hämta sinusvärde
	move.l	a1,(a0)+	; Skriv tillbaka sinuspekare
	move.b	d0,(a3)		; Sätt sinusvärde i spritens kontroll WORD
	move.b	d0,(a4)		;  "     "    "   "   "  "    "   "    "
	add.l	#16,d0		; Addera spritens höjd för att få den
				; vertikala stop positionen.
	move.b	d0,2(a3)	; Skriv vertikal stop position till
	move.b	d0,2(a4)	; spritarnas kontroll WORD.

	dbf	d7,.getit	; Loopa!

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

SetBplPtr:
	movem.l	d0-a6,-(sp)
	lea.l	EmptyBitplane,a0
	move.l	a0,d0
	lea.l	bplptr+2,a1
	move.w	d0,4(a1)
	swap	d0
	move.w	d0,(a1)
	movem.l	(sp)+,d0-a6
	rts

SetSpritePointers:
	movem.l	d0-a6,-(sp)
	lea.l	sprptr+2,a1

	lea.l	sprite1a,a0
	bsr.s	.setit

	lea.l	sprite1b,a0
	bsr.s	.setit

	lea.l	sprite2a,a0
	bsr.s	.setit

	lea.l	sprite2b,a0
	bsr.s	.setit

	lea.l	sprite3a,a0
	bsr.s	.setit

	lea.l	sprite3b,a0
	bsr.s	.setit

	lea.l	Sprite4a,a0
	bsr.s	.setit

	lea.l	Sprite4b,a0
	bsr.s	.setit

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

.setit:	move.l	a0,d0
	move.w	d0,4(a1)
	swap	d0
	move.w	d0,(a1)
	lea.l	8(a1),a1
	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
				; 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,$0038	; DDFSTRT
	dc.w	$0094,$00d8	; DDFSTOP
	dc.w	$0100,$1200	; BPLCON0
	dc.w	$0102,$0000	; BPLCON1
	dc.w	$0104,$0000	; BPLCON2
	dc.w	$0108,$ffd6	; BPLMOD1 (Negativ den här gången!)
	dc.w	$010a,$ffd6	; BPLMOD2 (Läs längre ner...)

; Här är de 8 spritepekarna, som vi ställer in med rutinen
; SetSpritePointers...
SprPtr:
	dc.w	$0120,$0000,$0122,$0000,$0124,$0000,$0126,$0000
	dc.w	$0128,$0000,$012a,$0000,$012c,$0000,$012e,$0000
	dc.w	$0130,$0000,$0132,$0000,$0134,$0000,$0136,$0000
	dc.w	$0138,$0000,$013a,$0000,$013c,$0000,$013e,$0000

; Vi måste ha ett bitplan påslaget för att spritarna ska synas...Därför
; gör jag ett litet trick, och använder negativ modulo, vilket gör att
; raden i EmptyBitplane visas över hela skärmen, och vi behöver alltså inte
; ha en helt ren skärm utan det räcker med en enda rad.

bplptr:	dc.w	$00e0,$0000,$00e2,$0000

	dc.w	$0180,$0000

	; Alla 16 färger till spritarna!
Cols:	dc.w	$01a0,$000,$01a2,$ff0,$01a4,$dd0,$01a6,$bb0
	dc.w	$01a8,$990,$01aa,$870,$01ac,$660,$01ae,$440
	dc.w	$01b0,$00f,$01b2,$00d,$01b4,$00c,$01b6,$00a
	dc.w	$01b8,$009,$01ba,$007,$01bc,$006,$01be,$004

	dc.w	$ee07,$fffe,$0180,$84f	; Skapa ett golv
	dc.w	$ef07,$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

EmptyBitplane:
	blk.l	40,0	; En tom rad som visas över hela skärmen.

Sprite1a:
	dc.w	$a0a0,$b080
	dc.w	$fffe,$fffe,$8002,$fffe,$bffa,$c006,$a00a,$c006
	dc.w	$afea,$cfe6,$a82a,$cfe6,$abaa,$cc66,$aaaa,$cc66
	dc.w	$abaa,$cc66,$a82a,$cfe6,$afea,$cfe6,$a00a,$c006
	dc.w	$bffa,$c006,$8002,$fffe,$fffe,$fffe,$0000,$0000
	dc.w	0,0

Sprite1b:
	dc.w	$a0a0,$b080
	dc.w	$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe
	dc.w	$f01e,$fffe,$f01e,$fffe,$f01e,$fffe,$f01e,$fffe
	dc.w	$f01e,$fffe,$f01e,$fffe,$f01e,$fffe,$fffe,$fffe
	dc.w	$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$0000,$0000
	dc.w	0,0

Sprite2a:
	dc.w	$a080,$b080
	dc.w	$fffe,$fffe,$8002,$fffe,$bffa,$c006,$a00a,$c006
	dc.w	$afea,$cfe6,$a82a,$cfe6,$abaa,$cc66,$abaa,$cc66
	dc.w	$abaa,$cc66,$a82a,$cfe6,$afea,$cfe6,$a00a,$c006
	dc.w	$bffa,$c006,$8002,$fffe,$fffe,$fffe,$0000,$0000
	dc.w	0,0

Sprite2b:
	dc.w	$a080,$b080
	dc.w	$fffe,$0000,$fffe,$0000,$fffe,$0000,$fffe,$0000
	dc.w	$f01e,$0000,$f01e,$0000,$f01e,$0000,$f01e,$0000
	dc.w	$f01e,$0000,$f01e,$0000,$f01e,$0000,$fffe,$0000
	dc.w	$fffe,$0000,$fffe,$0000,$fffe,$0000,$0000,$0000
	dc.w	0,0

Sprite3a:
	dc.w	$90c0,$a080
	dc.w	$fffe,$fffe,$8002,$fffe,$bffa,$c006,$a00a,$c006
	dc.w	$afea,$cfe6,$a82a,$cfe6,$abaa,$cc66,$aaaa,$cc66
	dc.w	$abaa,$cc66,$a82a,$cfe6,$afea,$cfe6,$a00a,$c006
	dc.w	$bffa,$c006,$8002,$fffe,$fffe,$fffe,$0000,$0000
	dc.w	0,0

Sprite3b:
	dc.w	$90c0,$a080
	dc.w	$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe
	dc.w	$f01e,$fffe,$f01e,$fffe,$f01e,$fffe,$f01e,$fffe
	dc.w	$f01e,$fffe,$f01e,$fffe,$f01e,$fffe,$fffe,$fffe
	dc.w	$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$0000,$0000
	dc.w	0,0

Sprite4a:
	dc.w	$e060,$f080
	dc.w	$fffe,$fffe,$8002,$fffe,$bffa,$c006,$a00a,$c006
	dc.w	$afea,$cfe6,$a82a,$cfe6,$abaa,$cc66,$abaa,$cc66
	dc.w	$abaa,$cc66,$a82a,$cfe6,$afea,$cfe6,$a00a,$c006
	dc.w	$bffa,$c006,$8002,$fffe,$fffe,$fffe,$0000,$0000
	dc.w	0,0

Sprite4b:
	dc.w	$e060,$f080
	dc.w	$fffe,$0000,$fffe,$0000,$fffe,$0000,$fffe,$0000
	dc.w	$f01e,$0000,$f01e,$0000,$f01e,$0000,$f01e,$0000
	dc.w	$f01e,$0000,$f01e,$0000,$f01e,$0000,$fffe,$0000
	dc.w	$fffe,$0000,$fffe,$0000,$fffe,$0000,$0000,$0000
	dc.w	0,0

Ysin:
	dc.w	140,140,141,142,144,146,149,152,156,160,164,169
	dc.w	174,180,185,191,198,204,210,217,223,217,210,204
	dc.w	197,191,185,179,174,169,164,160,155,152,149,146
	dc.w	144,142,140
	dc.w	-1
