forked from uhef/amiga-assembly-crashcourse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
blit_bad.s
255 lines (224 loc) · 6.9 KB
/
blit_bad.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
; adapted from https://github.com/alpine9000/amiga_examples
include "include/registers.i"
include "hardware/dmabits.i"
include "hardware/intbits.i"
LVL3_INT_VECTOR equ $6c
PLAYFIELD_WIDTH equ 640
PLAYFIELD_HEIGHT equ 200
PLAYFIELD_WIDTH_BYTES equ (PLAYFIELD_WIDTH/8)
PLAYFIELD_BIT_DEPTH equ 3
PLAYFIELD_RES equ 8 ; 8=lo resolution, 4=hi resolution
RASTER_X_START equ $81 ; hard coded coordinates from hardware manual
RASTER_Y_START equ $2c
SCREEN_WIDTH equ 320
SCREEN_HEIGHT equ 256
RASTER_X_STOP equ RASTER_X_START+SCREEN_WIDTH
RASTER_Y_STOP equ RASTER_Y_START+SCREEN_HEIGHT
;bra entry
setup:
; copied from reactor source.asm - is it needed?
; maybe only needed if want to exit back to workbench
move.l $4,a6
move.l #gfxname,a1
moveq #0,d0
jsr -552(a6)
move.l d0,gfxbase
move.l d0,a6
;move.l 34(a6),oldview
;move.l 38(a6),oldcopper
move.l #0,a1
jsr -222(a6) ; LoadView
jsr -270(a6) ; WaitTOF
jsr -270(a6) ; WaitTOF
move.l $4,a6
jsr -132(a6) ; Forbid
entry:
;; custom chip base globally in a6
lea CUSTOM,a6
move #$7ff,DMACON(a6) ; disable all dma
move #$7fff,INTENA(a6) ; disable all interrupts
include "out/image-palette.s"
;; set up playfield
move.w #(RASTER_Y_START<<8)|RASTER_X_START,DIWSTRT(a6)
move.w #((RASTER_Y_STOP-256)<<8)|(RASTER_X_STOP-256),DIWSTOP(a6)
move.w #(RASTER_X_START/2-PLAYFIELD_RES),DDFSTRT(a6)
move.w #(RASTER_X_START/2-PLAYFIELD_RES)+(8*((SCREEN_WIDTH/16)-1)),DDFSTOP(a6)
;move.w #$0038,DDFSTRT(a6)
;move.w #$00d0,DDFSTOP(a6)
; the $200 enables coolor
move.w #(PLAYFIELD_BIT_DEPTH<<12)|$200,BPLCON0(a6)
move.w #$0000,BPLCON1(a6) ; no scroll
move.w #$003f,BPLCON2(a6) ; priority
move.w #PLAYFIELD_WIDTH_BYTES-TC_WIDTH_BYTES,BLTDMOD(a6) ;D modulo
; using vertical memory arrangement- 640x600
move.w #(PLAYFIELD_WIDTH-SCREEN_WIDTH)/8,BPL1MOD(a6)
; move.w #PLAYFIELD_WIDTH_BYTES*PLAYFIELD_BIT_DEPTH-PLAYFIELD_WIDTH_BYTES,BPL2MOD(a6)
move.w #(PLAYFIELD_WIDTH-SCREEN_WIDTH)/8,BPL2MOD(a6)
;; poke bitplane pointers in copper list
bra skip_bpl
;lea bitplanes(pc),a1
lea copper(pc),a2
moveq #PLAYFIELD_BIT_DEPTH-1,d0
.bitplaneloop:
move.l a1,d1
move.w d1,2(a2)
swap d1
move.w d1,6(a2)
; lea PLAYFIELD_WIDTH_BYTES(a1),a1 ; bit plane data is interleaved
add.l #(PLAYFIELD_WIDTH_BYTES*PLAYFIELD_HEIGHT),a1 ; bit plane data is not interleaved
addq #8,a2
dbra d0,.bitplaneloop
skip_bpl:
; modify bitplane data for debug
bra skip_modify_bpl
move.l #$fa0,d0
move.l #bitplanes,a1
.drawbpl:
move.l d0,(a1)
add.l #4,a1
dbra d0,.drawbpl
skip_modify_bpl:
;; install copper list, then enable dma and selected interrupts
;lea copper(pc),a0
;move.l a0,COP1LC(a6)
;move.w COPJMP1(a6),d0
; MASTER = DMAEN
; RASTER = BPLEN
; TODO(lucasw) what does ! mean below - if it means negate, then why not leave
; out that entirely?
;move.w #(DMAF_BLITTER|DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a6)
; 8 BPLEN
; 7 COPEN
; 6 BLTEN
; 5 SPREN
; fedcba9876543210
move.w #%1000000111000000,DMACON(a6)
move.w #%0000000000111111,DMACON(a6)
; INTF_EXTR - is that needed?
;move.w #(INTF_SETCLR|INTF_INTEN|INTF_EXTER),INTENA(a6)
move.w #%1100000000000000,INTENA(a6) ; IRQ set ON
move.w #%0011111111111111,INTENA(a6) ; IRQ set OFF
jsr doblit
.mainLoop:
; vertical blank is happening at start of main loop,
; but with enough code here need to know when it is over
; alternate bitplane register loading, has to be done during every vertical blank
; by cpu or copper, so using cpu here
;bpl_set:
move.l #bitplanes,BPL1PT(a6)
move.l #bitplanes+16000,BPL2PT(a6)
move.l #bitplanes+32000,BPL3PT(a6)
move.l #bitplanes,BPL4PT(a6)
move.l #bitplanes+16000,BPL5PT(a6)
move.l #bitplanes+32000,BPL6PT(a6)
;skip_bpl_set:
; cycle background color to see something happening
add.l #1,frame
move.l frame,d0
lsr.l #3,d0
and.l #$0fff,d0
move.w d0,COLOR00(a6)
move.w #$02a,d0 ;wait for EOFrame
bsr.s waitRaster
;bsr.s wait_vertical_blank
bra .mainLoop
; VPOSR is in registers.i but is defined as vposr, which I can't find
VPOSRb EQU $004
wait_vertical_blank:
move.l CUSTOM+VPOSRb,d0
and.l #$1ff00,d0
; this waits for line 300?
cmp.l #300<<8,d0
bne wait_vertical_blank
waitRaster: ;wait for rasterline d0.w. Modifies d0-d2/a0.
move.l #$1ff00,d2
lsl.l #8,d0
and.l d2,d0
lea CUSTOM+VPOSRb,a0
.wr: move.l (a0),d1
and.l d2,d1
cmp.l d1,d0
bne.s .wr
rts
blitWait:
tst DMACONR(a6) ;for compatibility
.waitblit:
btst #6,DMACONR(a6)
bne.s .waitblit
rts
TC_WIDTH equ 32
TC_HEIGHT equ 32
TC_WIDTH_BYTES equ TC_WIDTH/8
TC_WIDTH_WORDS equ TC_WIDTH/16
TC_XPOS equ 16
TC_YPOS equ 16
TC_XPOS_BYTES equ (TC_XPOS)/8
;; BLTCON? configuration
;; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node011C.html
;; blitter logic function minterm truth table
;; fill in D column for desired function
;; A B C D
;; - - - -
;; 0 0 0 0
;; 0 0 1 0
;; 0 1 0 0
;; 0 1 1 0
;; 1 0 0 1
;; 1 0 1 1
;; 1 1 0 1
;; 1 1 1 1
;;
;; then read D column from bottom up = 11110000 = $f0
;; this is used in the LF? bits
BLIT_LF_MINTERM equ $f0
BLIT_A_SOURCE_SHIFT equ 0
BLIT_DEST equ $100
BLIT_SRCC equ $200
BLIT_SRCB equ $400
BLIT_SRCA equ $800
BLIT_ASHIFTSHIFT equ 12 ;Bit index of ASH? bits
BLIT_BLTCON1 equ 0 ;BSH?=0, DOFF=0, EFE=0, IFE=0, FCI=0, DESC=0, LINE=0
doblit:
movem.l d0-a6,-(sp)
bsr blitWait
move.w #(BLIT_SRCA|BLIT_DEST|BLIT_LF_MINTERM|BLIT_A_SOURCE_SHIFT<<BLIT_ASHIFTSHIFT),BLTCON0(A6)
move.w #BLIT_BLTCON1,BLTCON1(a6)
move.l #$ffffffff,BLTAFWM(a6) ;no masking of first/last word
move.w #0,BLTAMOD(a6) ;A modulo=bytes to skip between lines
move.w #PLAYFIELD_WIDTH_BYTES-TC_WIDTH_BYTES,BLTDMOD(a6) ;D modulo
move.l #tc,BLTAPTH(a6) ;source graphic top left corner
;move.l #bitplanes+TC_XPOS_BYTES+(PLAYFIELD_WIDTH_BYTES*PLAYFIELD_BIT_DEPTH*TC_YPOS),BLTDPTH(a6) ;destination top left corner
move.l #bitplanes+TC_XPOS_BYTES+(PLAYFIELD_WIDTH_BYTES*TC_YPOS),BLTDPTH(a6) ;destination top left corner
move.w #(TC_HEIGHT*PLAYFIELD_BIT_DEPTH)<<6|(TC_WIDTH_WORDS),BLTSIZE(a6) ;rectangle size, starts blit
movem.l (sp)+,d0-a6
rts
copper:
;; bitplane pointers must be first else poking addresses will be incorrect
dc.w BPL1PTL,0
dc.w BPL1PTH,0
dc.w BPL2PTL,0
dc.w BPL2PTH,0
dc.w BPL3PTL,0
dc.w BPL3PTH,0
dc.w BPL4PTL,0
dc.w BPL4PTH,0
dc.w BPL5PTL,0
dc.w BPL5PTH,0
dc.l $fffffffe
CNOP 0,4
frame:
dc.l 0
CNOP 0,4
; because of the Section below, all the memory below will also be in ChipRAM
gfxbase: dc.l 0 ; TODO(lucasw) moved this from other misc register above, does it matter?
gfxname:
dc.b 'graphics.library',0
Section ChipRAM,Data_c
CNOP 0,4
bitplanes:
incbin "gimp/sky.data.raw"
;incbin "gimp/mountains.data.raw"
CNOP 0,4
tc:
incbin "gimp/explosion.data.raw"
CNOP 0,4