; Septic's Demoskola - Lektion 2 : Copper Madness
; Skriven av Vicious / Septic 18 April 1993

DisableCache=1	; En etta betyder att funktionen är på!
DisableMotor=1

	section	Lektion2,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	#%1000001010000000,$dff096	; Endast Copper DMA är på!
	;	  S    NDBCBSD
	;	  E    aMPOLPS
	;	  T    sALPTRK
	;	       t
	;              y

	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		; Vänta på en speciell strålposition
	bsr.w	ClrBars		; Rensa gamla rasterbalkar
	bsr.s	SwingBars	; Sätt ut de nya balkarna!
	btst	#6,$bfe001	; Testa vänster musknapp!
	bne.s	main

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

sync:	move.l	$dff004,d0	; Hämta strålens position
	and.l	#$1ff00,d0	; Maska bort horisontella positionen
	lsr.l	#8,d0		; Shifta ner till lägsta bitarna
	cmp.w	#$f0,d0		; Kolla om det är rätt vertikal position
	bne.s	sync
	rts

TableCounter:
	dc.l	0

SwingBars:
	movem.l	d0-a6,-(sp)
	lea.l	CopperBarGfx(pc),a0	; Här har vi färgerna på balkarna
	lea.l	bars+14(pc),a1		; Här ska vi flytta in balkarna
	lea.l	SineTable(pc),a2	; Pekare till sinustabellen
	move.l	#3,d0			; Tjockleken på minsta balken

	moveq	#5,d7			; Sätt ut 6 balkar (6-1 för DBF-loop)
.get:	move.l	tablecounter(pc),d1	; Hämta offset för sinustabellen
	addq.l	#4,tablecounter		; och öka den sen till nästa longword
	move.l	(a2,d1.w),d2		; Hämta sinusvärde till D2
	bpl.s	.notneg			; Branch if PLus...Hoppa om D2 inte
					; är negativt.
	move.l	#0,TableCounter		; Nollställ tabell-offset-pekaren
	bra.s	.get			; om vi är i slutet på sinustabellen.
.notneg:
	asl.l	#3,d2			; Multiplicera d2 med 8 (eller som
					; jag gör här: skifta d2 tre steg
					; åt vänster vilket är snabbare)
					; eftersom färgvärdena ligger med
					; ett mellanrum på 8 bytes i copper-
					; listan!
	bsr.s	MoveBar			; Flytta in balken i copperlistan
	addq.l	#1,d0			; Öka på tjockleken, så att vi nästa
					; gång inte hämtar för lite färgdata
					; från copperbalk-grafiken...
	addq.l	#4,d1			; Vi ökar också på sinuspekaren
					; så att vi hamnar på nästa longword
					; i tabellen...
.get2:	move.l	(a2,d1.w),d2		; Här hämtar vi sinusvärde igen...
	bpl.s	.notneg2		; Och hoppar om det är positivt
	moveq.l	#0,d1			; Annars nollställer vi offseten....
	bra.s	.get2
.notneg2:
	dbf	d7,.notneg		; Loopa tillbaka för mer balkar

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

MoveBar:
	movem.l	d0/a1,-(sp)
.movit:	move.w	(a0)+,(a1,d2.w)		; Flytta in färgkod i copperlistan
	lea.l	8(a1),a1		; Öka copperlist-pekaren med 8
	dbf	d0,.movit		; Loopa det antal gånger som
					; tjockleken anger...
	movem.l	(sp)+,d0/a1
	rts

ClrBars:
	movem.l	d0-a6,-(sp)
	lea.l	bars(pc),a0		; Vi ställer in A0 på våra balkar
					; i copperlistan
	move.l	#$5807fffe,d0		; Sätter första wait-koden i D0
	move.l	#$01800000,d1		; Och koden för att byta bakgrunds-
					; färg till svart i D1
	move.l	#($a8)-1,d7		; Vår lista är $A8*2 longwords...
.setup:	move.l	d0,(a0)+		; Skriv in waitkod i coperlistan
	move.l	d1,(a0)+		; och skriv in "byt-bakgrundsfärg"-kod
	add.l	#$01000000,d0		; Öka waitkod så att den väntar på
					; nästa vertikala rad
	dbf	d7,.setup		; Loopa...
	movem.l	(sp)+,d0-a6
	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!


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

copper:
	dc.w	$008e,$2c81	; De här sakerna ska vi gå igenom närmare
	dc.w	$0090,$2cc1	; i lektionen om bitplansgrafik!
	dc.w	$0092,$0038
	dc.w	$0094,$00d0
	dc.w	$0100,$0200
	dc.w	$0102,$0000
	dc.w	$0104,$0000
	dc.w	$0108,$0000
	dc.w	$010a,$0000

	; Detta är den översta, gröna copperbalken!
	; Först väntar vi på en rad, sen byter vi bakgrundsfärg och så
	; upprepar vi detta hela tiden för att åstadkomma en "balk"...
	dc.w	$4f07,$fffe,$0180,$0c0	; Rad $4f, kolumn $07, bakgrund $0c0
	dc.w	$5007,$fffe,$0180,$0e0	; Rad $50, kolumn $07, bakgrund $0e0
	dc.w	$5107,$fffe,$0180,$0f0	; osv....
	dc.w	$5207,$fffe,$0180,$0d0
	dc.w	$5307,$fffe,$0180,$0b0
	dc.w	$5407,$fffe,$0180,$090
	dc.w	$5507,$fffe,$0180,$070
	dc.w	$5607,$fffe,$0180,$040
	dc.w	$5707,$fffe,$0180,$000	; Sist sätter vi svart bakgrund igen

bars:	blk.w	$a8*4,0		; Här reserverar vi plats i copperlistan för
				; våra röda copperbars som ska röra på sig.

	dc.w	$ffdf,$fffe	; Vänta på "PAL"-läge...Dvs där den vertikala
				; positionen $00 går över till att bli $100
				; så att vi kan ha coppergrafik på rad 256 och
				; neråt....(Notera att 256 är hårdvaru-
				; koordinater i det här sammanhanget och
				; egentligen motsvarar skärmkoordinaten
				; 256 - 44 = 212)

	dc.w	$0107,$fffe,$0180,$0c0	; Här gör vi vår andra gröna balk...
	dc.w	$0207,$fffe,$0180,$0e0
	dc.w	$0307,$fffe,$0180,$0f0
	dc.w	$0407,$fffe,$0180,$0d0
	dc.w	$0507,$fffe,$0180,$0b0
	dc.w	$0607,$fffe,$0180,$090
	dc.w	$0707,$fffe,$0180,$070
	dc.w	$0807,$fffe,$0180,$040
	dc.w	$0907,$fffe,$0180,$000

	dc.w	$ffff,$fffe		; Slut på copperlistan!

; Detta är "grafiken" till våra copperbalkar...Egentligen är det en massa
; färgkoder som vi skriver in i copperlistan.
CopperBarGfx:
	; Bar 1 (Smalast)
	dc.w	$700
	dc.w	$800
	dc.w	$500
	dc.w	$000

	; Bar 2
	dc.w	$800
	dc.w	$900
	dc.w	$700
	dc.w	$400
	dc.w	$000

	; Bar 3
	dc.w	$900
	dc.w	$a00
	dc.w	$800
	dc.w	$600
	dc.w	$300
	dc.w	$000

	; Bar 4
	dc.w	$b00
	dc.w	$c00
	dc.w	$a00
	dc.w	$800
	dc.w	$600
	dc.w	$300
	dc.w	$000

	; Bar 5
	dc.w	$c00
	dc.w	$e00
	dc.w	$d00
	dc.w	$b00
	dc.w	$900
	dc.w	$700
	dc.w	$400
	dc.w	$000

	; Bar 6 (Tjockast)
	dc.w	$c00
	dc.w	$e00
	dc.w	$f00
	dc.w	$d00
	dc.w	$b00
	dc.w	$900
	dc.w	$700
	dc.w	$400
	dc.w	$000

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

; Sinustabell, skapad med Sine Creator v1.10 (gjord av mig själv)! Verkligen
; ett måste när man ska göra demos!

SineTable:
	dc.w	0,0,0,0,0,1,2,3,3,4,6,7
	dc.w	8,10,11,13,15,17,19,21,23,25,28,30
	dc.w	33,35,38,40,43,46,49,52,55,58,61,64
	dc.w	67,70,73,76,80,83,86,89,92,95,98,101
	dc.w	104,107,110,113,116,119,121,124,127,129,132,134
	dc.w	136,138,140,142,144,146,148,149,151,152,153,155
	dc.w	156,156,157,158,159,159,159,159,159,159,159,159
	dc.w	158,158,157,156,156,155,153,152,151,149,148,146
	dc.w	144,142,140,138,136,134,131,129,126,124,121,119
	dc.w	116,113,110,107,104,101,98,95,92,89,86,83
	dc.w	79,76,73,70,67,64,61,58,55,52,49,46
	dc.w	43,40,38,35,32,30,27,25,23,21,19,17
	dc.w	15,13,11,10,8,7,6,4,3,2,2,1
	dc.w	0,0,0
	dc.l	-1
