1 |
; Rolling image on copperbars-1
|
2 |
|
3 |
DMACONR EQU $dff002
|
4 |
ADKCONR EQU $dff010
|
5 |
INTENAR EQU $dff01c
|
6 |
INTREQR EQU $dff01e
|
7 |
|
8 |
DMACON EQU $dff096
|
9 |
ADKCON EQU $dff09e
|
10 |
INTENA EQU $dff09a
|
11 |
INTREQ EQU $dff09c
|
12 |
|
13 |
incdir "windows:amigavikke/"
|
14 |
|
15 |
; Optimizations could easily be made to the small/tight loops in the code by using
|
16 |
; incremental addressing (An)+ or decremental addressing -(An) and REPT <n> / ERPT
|
17 |
|
18 |
init:
|
19 |
; store hardware registers, store view- and copperaddresses, load blank view,
|
20 |
; wait 2x for top of frame, own blitter, wait for blitter and forbid multitasking!
|
21 |
; all this just to be able to exit gracely
|
22 |
|
23 |
; store data in hardwareregisters ORed with $8000
|
24 |
; (bit 15 is a write-set bit when values are written back into the system)
|
25 |
move.w DMACONR,d0
|
26 |
or.w #$8000,d0
|
27 |
move.w d0,olddmareq
|
28 |
move.w INTENAR,d0
|
29 |
or.w #$8000,d0
|
30 |
move.w d0,oldintena
|
31 |
move.w INTREQR,d0
|
32 |
or.w #$8000,d0
|
33 |
move.w d0,oldintreq
|
34 |
move.w ADKCONR,d0
|
35 |
or.w #$8000,d0
|
36 |
move.w d0,oldadkcon
|
37 |
|
38 |
move.l $4,a6 ; execBase ==> a6
|
39 |
move.l #gfxname,a1 ; pointer to gfxname ==> a1 : used in openLibrary
|
40 |
moveq #0,d0 ; d0 = 0 any version of graphics.library will do
|
41 |
jsr -552(a6) ; d0 = openLibrary(a1,d0)
|
42 |
move.l d0,gfxbase ; store the returned pointer ==> gfxbase
|
43 |
move.l d0,a6 ; d0 ==> a6 : a6 used as addressing base below
|
44 |
move.l 34(a6),oldview ; store old Viewport
|
45 |
move.l 38(a6),oldcopper ; store old Copperlist
|
46 |
|
47 |
move.l #0,a1
|
48 |
jsr -222(a6) ; LoadView
|
49 |
jsr -270(a6) ; WaitTOF
|
50 |
jsr -270(a6) ; WaitTOF
|
51 |
jsr -456(a6) ; OwnBlitter
|
52 |
jsr -228(a6) ; WaitBlit
|
53 |
move.l $4,a6
|
54 |
jsr -132(a6) ; Forbid
|
55 |
|
56 |
; end exit gracely preparations!
|
57 |
|
58 |
; clear Bitplanes from garbage
|
59 |
; very slow routine! should be done with the Blitter, or unrolled loop
|
60 |
move.w #320/8*200/4,d0 ; d0 is a counter for number of longwords to get cleared
|
61 |
move.l #bpl0,a0 ; bpl0 => a0
|
62 |
move.l #bpl1,a1 ; bpl1 => a1
|
63 |
screen_clear:
|
64 |
move.l #0,(a0)+ ; #0 => (a0), and increment a0 to next longword (a0=a0+4)
|
65 |
move.l #0,(a1)+ ; #0 => (a1), and increment a1 to next longword (a1=a1+4)
|
66 |
subq.w #1,d0
|
67 |
bne screen_clear
|
68 |
|
69 |
; copy bitmap to bitplanes
|
70 |
move.w #320/8*94/4,d0
|
71 |
move.l #bpl0,a0 ; bpl0 => a0
|
72 |
move.l #bpl1,a1 ; bpl1 => a1
|
73 |
move.l #img_av,a6
|
74 |
add.l #2,a6
|
75 |
copy_img:
|
76 |
move.l 320/8*94(a6),(a1)+ ; bpl1
|
77 |
move.l (a6)+,(a0)+ ; bpl0
|
78 |
subq.w #1,d0
|
79 |
bne copy_img
|
80 |
|
81 |
; setup display-HW to show 320x200px w/ 2 bitplanes, with 0 horizontal scroll and 0 modulos
|
82 |
move.w #$2200,$dff100 ; 2 bitplane lowres
|
83 |
move.w #$0000,$dff102 ; horizontal scroll 0
|
84 |
move.w #$0000,$dff108 ; odd modulo 0
|
85 |
move.w #$0000,$dff10a ; even modulo 0
|
86 |
move.w #$2c81,$dff08e ; DIWSTRT - topleft corner (2c81)
|
87 |
move.w #$f4d1,$dff090 ; DIVSTOP - bottomright corner (f4d1)
|
88 |
move.w #$0038,$dff092 ; DDFSTRT - max overscan $0018 ; standard 0038 & 00d0
|
89 |
move.w #$00d0,$dff094 ; DDFSTOP - max overscan $00d8 ; max os: 368x283px in PAL
|
90 |
move.w #%1000010111000000,DMACON ; DMA set ON
|
91 |
move.w #%0000000000111111,DMACON ; DMA set OFF
|
92 |
move.w #%1100000000000000,INTENA ; IRQ set ON
|
93 |
move.w #%0011111111111111,INTENA ; IRQ set OFF
|
94 |
|
95 |
|
96 |
mainloop:
|
97 |
; increase framecounter by 1
|
98 |
move.l frame,d0
|
99 |
addq.l #1,d0
|
100 |
move.l d0,frame
|
101 |
|
102 |
|
103 |
; make copperlist
|
104 |
; doubblebuffering of copperlists, defined at copper1 and copper2,
|
105 |
; chosen by LSB in framecounter copper (and a6) will hold the address
|
106 |
; to the copperlist we will write to (not the one currently in use)
|
107 |
and.l #1,d0
|
108 |
bne usecopper2
|
109 |
move.l #copper1,a6
|
110 |
bra usecopper1
|
111 |
usecopper2:
|
112 |
move.l #copper2,a6
|
113 |
usecopper1:
|
114 |
move.l a6,copper
|
115 |
|
116 |
|
117 |
; *********************************************************
|
118 |
;
|
119 |
; 32px high copperbars for rolling (p=32*pi ==> p~100 ==> image should be ~ 100px high (here 94px)
|
120 |
;
|
121 |
; *********************************************************
|
122 |
|
123 |
clr.l d1 ; d1 = 0
|
124 |
move.w cbar_img_line1,d1 ; startingline index ==> d1
|
125 |
add.w #40,d1 ; d1 = d1 + 40 (320px/8 = 40 bytes)
|
126 |
cmp.w #94/2*40,d1 ; compare if larger than half the height of the image
|
127 |
bcs .10
|
128 |
sub.w #94/2*40,d1 ; if it is, then subract the overgoing part from it
|
129 |
.10:
|
130 |
move.w d1,cbar_img_line1 ; store new startingline index for next frame
|
131 |
|
132 |
; if all copperbars below would have the same startingline in the image every bar
|
133 |
; would look the same, except for the background color.
|
134 |
; by chaning the startingline we get a "waggling" effect between the copperbarimages
|
135 |
|
136 |
; 1st bar
|
137 |
move.l d1,d3 ; startingline in image ==> d3
|
138 |
add.l #40*2,d3 ; add 2 lines to d3
|
139 |
move.l #$2c,d2 ; starting scanline ==> d2
|
140 |
move.l #cbar3,a0 ; colortable ==> a0
|
141 |
jsr make_Copper_roller ; Jump to SubRoutine (RTS will get back here)
|
142 |
|
143 |
; 2nd bar
|
144 |
move.l d3,d1
|
145 |
add.l #40*4,d3 ; add 4 lines to d3
|
146 |
move.l #$2c+$20,d2
|
147 |
move.l #cbar2,a0
|
148 |
jsr make_Copper_roller
|
149 |
|
150 |
; 3rd bar
|
151 |
move.l d3,d1
|
152 |
add.l #40*6,d3 ; add 6 lines to d3
|
153 |
move.l #$2c+$40,d2
|
154 |
move.l #cbar3,a0
|
155 |
jsr make_Copper_roller
|
156 |
|
157 |
; 4th bar
|
158 |
move.l d3,d1
|
159 |
add.l #40*8,d3 ; add 8 lines to d3
|
160 |
move.l #$2c+$60,d2
|
161 |
move.l #cbar2,a0
|
162 |
jsr make_Copper_roller
|
163 |
|
164 |
; 5th bar
|
165 |
move.l d3,d1
|
166 |
add.l #40*10,d3 ; add 10 lines to d3
|
167 |
move.l #$2c+$80,d2
|
168 |
move.l #cbar3,a0
|
169 |
jsr make_Copper_roller
|
170 |
|
171 |
|
172 |
; end of copperlist (copperlist ALWAYS ends with WAIT $fffffffe)
|
173 |
move.l #$fffffffe,(a6)+ ; end copperlist
|
174 |
|
175 |
testMouseButton:
|
176 |
; if mousebutton/joystick 1 or 2 pressed then exit
|
177 |
btst.b #6,$bfe001
|
178 |
beq exit
|
179 |
btst.b #7,$bfe001
|
180 |
beq exit
|
181 |
|
182 |
; display is ready,
|
183 |
; or atleast we have done everything we wanted and the copper continues on its own
|
184 |
; we have to wait for Vertical Blanking before making the next frame
|
185 |
|
186 |
waitVB:
|
187 |
move.l $dff004,d0
|
188 |
and.l #$1ff00,d0
|
189 |
cmp.l #300<<8,d0
|
190 |
bne waitVB
|
191 |
|
192 |
; use next copperlist
|
193 |
; as we are using doubblebuffering on copperlists we now take the new one into use
|
194 |
move.l copper,d0
|
195 |
move.l d0,$dff080
|
196 |
bra mainloop
|
197 |
|
198 |
exit:
|
199 |
; exit gracely - reverse everything done in init
|
200 |
move.w #$7fff,DMACON ; set bits[0,14] = 0 (bit15 is a set/clear bit)
|
201 |
move.w olddmareq,DMACON ; and set bits[0,14] as they were at init
|
202 |
move.w #$7fff,INTENA ; set bits[0,14] = 0 (bit15 is a set/clear bit)
|
203 |
move.w oldintena,INTENA ; and set bits[0,14] as they were at init
|
204 |
move.w #$7fff,INTREQ ; set bits[0,14] = 0 (bit15 is a set/clear bit)
|
205 |
move.w oldintreq,INTREQ ; and set bits[0,14] as they were at init
|
206 |
move.w #$7fff,ADKCON ; set bits[0,14] = 0 (bit15 is a set/clear bit)
|
207 |
move.w oldadkcon,ADKCON ; and set bits[0,14] as they were at init
|
208 |
|
209 |
move.l oldcopper,$dff080 ; load old Copperlist
|
210 |
; graphics.library calls
|
211 |
move.l gfxbase,a6 ; gfxBase ==> a6
|
212 |
move.l oldview,a1 ; oldView ==> a1 (used in LoadView)
|
213 |
jsr -222(a6) ; LoadView : load back the view at start of program
|
214 |
jsr -270(a6) ; WaitTOF : Wait for Top Of Frame to get everything synced up
|
215 |
jsr -270(a6) ; WaitTOF : (2 times for interlaced screens)
|
216 |
jsr -228(a6) ; WaitBlit : wait for Blitter to finish running task (if any)
|
217 |
jsr -462(a6) ; DisownBlitter : release Blitter to system
|
218 |
; exec.library calls
|
219 |
move.l $4,a6 ; execBase ==> a6
|
220 |
move.l gfxbase,a1 ; gfxBase ==> a1 (used in closeLibrary)
|
221 |
jsr -414(a6) ; closeLibrary : close graphics.library
|
222 |
jsr -138(a6) ; Permit multitasking
|
223 |
|
224 |
; end program
|
225 |
rts
|
226 |
|
227 |
; subroutines
|
228 |
|
229 |
make_Copper_roller:
|
230 |
; bitplane 0
|
231 |
move.l #bpl0,d0
|
232 |
add.l d1,d0 ; add startingline index to address
|
233 |
move.w #$00e2,(a6)+ ; LO-bits of start of bitplane
|
234 |
move.w d0,(a6)+ ; go into $dff0e2
|
235 |
swap d0
|
236 |
move.w #$00e0,(a6)+ ; HI-bits of start of bitplane
|
237 |
move.w d0,(a6)+ ; go into $dff0e0
|
238 |
|
239 |
; bitplane 1
|
240 |
move.l #bpl1,d0
|
241 |
add.l d1,d0 ; add startingline index to address
|
242 |
move.w #$00e6,(a6)+ ; LO-bits of start of bitplane
|
243 |
move.w d0,(a6)+ ; go into $dff0e6
|
244 |
swap d0
|
245 |
move.w #$00e4,(a6)+ ; HI-bits of start of bitplane
|
246 |
move.w d0,(a6)+ ; go into $dff0e4
|
247 |
|
248 |
;move.l #cbar2,a0
|
249 |
move.l #cbar_c1,a1
|
250 |
move.l #cbar_c2,a2
|
251 |
move.l #cbar_c3,a3
|
252 |
move.l #shift1,a4
|
253 |
move.l #$0007fffe,d1 ; this is just a template for copper WAIT-instruction
|
254 |
; to this template we need to add the vertical-position
|
255 |
; into bits [24,31], 07 is the horizontal-position
|
256 |
lsl.l #8,d2 ; d2 = d2 * 2^8 (shift bits 8 steps left)
|
257 |
lsl.l #8,d2 ; d2 = d2 * 2^8 (8 is max shift, so therefore 3 times)
|
258 |
lsl.l #8,d2 ; d2 = d2 * 2^8 ==> all-in-all d2 = d2 * 2^24
|
259 |
; *2^24 could be made faster, but as this isn't timecritical
|
260 |
; it isn't done here (this part is ran only once/bar/frame)
|
261 |
add.l d2,d1 ; add d2 to d1 = add vertical-position to the template
|
262 |
; Copper WAIT <$Yy07>,<$fffe>: V:$Yy & H:$07 & mask:$fffe
|
263 |
moveq #32,d0
|
264 |
loop_cbar1:
|
265 |
move.l d1,(a6)+ ; copper WAIT
|
266 |
move.w #$0180,(a6)+ ; color0-
|
267 |
move.w (a0)+,(a6)+ ; value
|
268 |
move.w #$0182,(a6)+ ; color1-
|
269 |
move.w (a1)+,(a6)+ ; value
|
270 |
move.w #$0184,(a6)+ ; color2-
|
271 |
move.w (a2)+,(a6)+ ; value
|
272 |
move.w #$0186,(a6)+ ; color3-
|
273 |
move.w (a3)+,(a6)+ ; value
|
274 |
move.w #$0102,(a6)+ ; h-shift-
|
275 |
move.w (a4)+,(a6)+ ; value
|
276 |
add.l #1<<24,d1 ; here the optimization continues,
|
277 |
; we know that the verticalvalues are in bits[24,31],
|
278 |
; so we add 1*2^24 to get to the next line
|
279 |
subq #1,d0
|
280 |
bne loop_cbar1
|
281 |
|
282 |
rts ; end subroutine and get back to main code
|
283 |
|
284 |
|
285 |
|
286 |
; *******************************************************************************
|
287 |
; *******************************************************************************
|
288 |
; DATA
|
289 |
; *******************************************************************************
|
290 |
; *******************************************************************************
|
291 |
|
292 |
|
293 |
; storage for 32-bit addresses and data
|
294 |
CNOP 0,4
|
295 |
oldview: dc.l 0
|
296 |
oldcopper: dc.l 0
|
297 |
gfxbase: dc.l 0
|
298 |
frame: dc.l 0
|
299 |
copper: dc.l 0
|
300 |
|
301 |
; storage for 16-bit data
|
302 |
CNOP 0,4
|
303 |
olddmareq: dc.w 0
|
304 |
oldintreq: dc.w 0
|
305 |
oldintena: dc.w 0
|
306 |
oldadkcon: dc.w 0
|
307 |
|
308 |
CNOP 0,4
|
309 |
; storage for 8-bit data and text
|
310 |
gfxname: dc.b 'graphics.library',0
|
311 |
|
312 |
CNOP 0,4
|
313 |
cbar1: dc.w $000,$100,$200,$300,$400,$500,$600,$700,$800,$900,$a00,$b00,$c00,$d00,$e00,$f00,$f00,
|
314 |
$e00,$d00,$c00,$b00,$a00,$900,$800,$700,$600,$500,$400,$300,$200,$100,$000
|
315 |
cbar2: dc.w $000,$101,$202,$303,$404,$505,$606,$707,$808,$909,$a0a,$b0b,$c0c,$d0d,$e0e,$f0f,$f0f,
|
316 |
$e0e,$d0d,$c0c,$b0b,$a0a,$909,$808,$707,$606,$505,$404,$303,$202,$101,$000
|
317 |
cbar3: dc.w $000,$001,$002,$003,$004,$005,$006,$007,$008,$009,$00a,$00b,$00c,$00d,$00e,$00f,$00f,
|
318 |
$00e,$00d,$00c,$00b,$00a,$009,$008,$007,$006,$005,$004,$003,$002,$001,$000
|
319 |
|
320 |
cbar_c1: dc.w $000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,
|
321 |
$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000,$000
|
322 |
cbar_c2: dc.w $000,$100,$200,$300,$400,$500,$600,$700,$800,$900,$A00,$B00,$C00,$D00,$E00,$F00,$F00,
|
323 |
$E00,$D00,$C00,$B00,$A00,$900,$800,$700,$600,$500,$400,$300,$200,$100,$000
|
324 |
cbar_c3: dc.w $000,$110,$220,$330,$440,$550,$660,$770,$880,$990,$AA0,$BB0,$CC0,$DD0,$EE0,$FF0,$FF0,
|
325 |
$EE0,$DD0,$CC0,$BB0,$AA0,$990,$880,$770,$660,$550,$440,$330,$220,$110,$000
|
326 |
shift1: dc.w $00,$55,$77,$99,$AA,$BB,$CC,$DD,$DD,$EE,$EE,$EE,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$EE,
|
327 |
$EE,$EE,$DD,$DD,$CC,$BB,$AA,$99,$77,$55,$00
|
328 |
cbar_img_line1: dc.w 0
|
329 |
|
330 |
|
331 |
|
332 |
Section ChipRAM,Data_c
|
333 |
|
334 |
; bitplanes aligned to 32-bit
|
335 |
CNOP 0,4
|
336 |
bpl0: blk.b 320/8*250,0
|
337 |
bpl1: blk.b 320/8*250,0
|
338 |
|
339 |
; datalists aligned to 32-bit
|
340 |
CNOP 0,4
|
341 |
copper1:
|
342 |
dc.l $ffffffe ; CHIPMEM!
|
343 |
blk.l 1023,0 ; CHIPMEM!
|
344 |
CNOP 0,4
|
345 |
copper2:
|
346 |
dc.l $ffffffe ; CHIPMEM!
|
347 |
blk.l 1023,0 ; CHIPMEM!
|
348 |
|
349 |
CNOP 0,4
|
350 |
img_av: incbin "av.raw"
|
|