4db6e09f |
1 | ################################################## |
2 | # # |
3 | # Assemble with gas # |
4 | # --register-prefix-optional --bitwise-or # |
5 | # # |
6 | ################################################## |
7 | |
8 | .text |
9 | .globl main |
10 | |
11 | ################################################## |
12 | # # |
13 | # Register and bitmask definitions # |
14 | # # |
15 | ################################################## |
16 | |
17 | .equ GFXDATA, 0xc00000 |
18 | .equ GFXCNTL, 0xc00004 |
19 | |
20 | .equ VDP0_E_HBI, 0x10 |
21 | .equ VDP0_E_DISPLAY, 0x02 |
22 | .equ VDP0_PLTT_FULL, 0x04 |
23 | |
24 | .equ VDP1_SMS_MODE, 0x80 |
25 | .equ VDP1_E_DISPLAY, 0x40 |
26 | .equ VDP1_E_VBI, 0x20 |
27 | .equ VDP1_E_DMA, 0x10 |
28 | .equ VDP1_NTSC, 0x00 |
29 | .equ VDP1_PAL, 0x08 |
30 | .equ VDP1_RESERVED, 0x04 |
31 | |
32 | .equ VDP12_SPR_SHADOWS, 0x08 |
33 | .equ VDP12_SCREEN_V224, 0x00 |
34 | .equ VDP12_SCREEN_V448, 0x04 |
35 | .equ VDP12_PROGRESSIVE, 0x00 |
36 | .equ VDP12_INTERLACED, 0x02 |
37 | .equ VDP12_SCREEN_H256, 0x00 |
38 | .equ VDP12_SCREEN_H320, 0x81 |
39 | |
40 | .equ VDP16_MAP_V32, 0x00 |
41 | .equ VDP16_MAP_V64, 0x10 |
42 | .equ VDP16_MAP_V128, 0x30 |
43 | .equ VDP16_MAP_H32, 0x00 |
44 | .equ VDP16_MAP_H64, 0x01 |
45 | .equ VDP16_MAP_H128, 0x03 |
46 | |
47 | |
48 | |
49 | ################################################## |
50 | # # |
51 | # MACROS # |
52 | # # |
53 | ################################################## |
54 | |
55 | |
56 | /* Write val to VDP register reg */ |
57 | .macro write_vdp_reg reg val |
58 | move.w #((\reg << 8) + 0x8000 + \val),(a3) |
59 | .endm |
60 | |
61 | |
62 | /* For immediate addresses */ |
63 | .macro VRAM_ADDR reg adr |
64 | move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg |
65 | .endm |
66 | |
67 | |
570c4371 |
68 | # make VDP word from address adr to d0 |
69 | # destroys d7 |
70 | .macro VRAM_ADDR_var adr |
71 | move.l \adr,d0 |
4db6e09f |
72 | move.l \adr,d7 |
570c4371 |
73 | and.w #0x3fff,d0 |
4db6e09f |
74 | lsr.w #7,d7 |
75 | lsr.w #7,d7 |
570c4371 |
76 | add.w #0x4000,d0 |
77 | lsl.l #7,d0 |
78 | lsl.l #7,d0 |
79 | lsl.l #2,d0 |
80 | or.l d7,d0 |
4db6e09f |
81 | .endm |
82 | |
83 | |
84 | .macro CRAM_ADDR reg adr |
85 | move.l #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg |
86 | .endm |
87 | |
88 | |
89 | /* For indirect (variable) addresses */ |
90 | .macro CRAM_ADDR_var reg adr |
91 | move.l \adr,d6 |
92 | move.l \adr,d7 |
93 | and.w #0x3fff,d6 |
94 | lsr.w #7,d7 |
95 | lsr.w #7,d7 |
96 | add.w #0xc000,d6 |
97 | lsl.l #7,d6 |
98 | lsl.l #7,d6 |
99 | lsl.l #2,d6 |
100 | or.l d7,d6 |
101 | move.l d6,\reg |
102 | .endm |
103 | |
104 | |
105 | .macro VSCROLL_ADDR reg adr |
106 | move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg |
107 | .endm |
108 | |
109 | |
110 | .macro HSCROLL_ADDR reg adr |
111 | move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg |
112 | .endm |
113 | |
114 | |
115 | ################################################# |
116 | # # |
117 | # DATA # |
118 | # # |
119 | ################################################# |
120 | |
121 | colors: |
570c4371 |
122 | dc.w 0x0000,0x0eee |
123 | colors_end: |
124 | |
125 | # pattern: |
4db6e09f |
126 | |
127 | |
128 | sprite_data: |
129 | /* Y size link attr X */ |
570c4371 |
130 | dc.w 0; dc.b 0x05; dc.b 0; dc.w 0x6002; dc.w 0 |
4db6e09f |
131 | sprite_data_end: |
132 | |
570c4371 |
133 | hello: |
134 | .ascii "hello world" |
4db6e09f |
135 | |
136 | ################################################## |
137 | # # |
138 | # MAIN PROGRAM # |
139 | # # |
140 | ################################################## |
141 | |
570c4371 |
142 | .align 2 |
143 | |
4db6e09f |
144 | main: |
145 | /* Initialize VDP */ |
146 | jsr init_gfx |
147 | |
148 | /* Load color data */ |
149 | movea.l #0,a3 |
570c4371 |
150 | movea.l #colors,a4 |
151 | moveq.l #(colors_end-colors)/2,d4 |
4db6e09f |
152 | jsr load_colors |
153 | |
154 | /* load patterns */ |
155 | movea.l #0,a3 |
570c4371 |
156 | movea.l #font,a4 |
157 | move.l #128,d4 |
4db6e09f |
158 | jsr load_tiles |
159 | |
160 | /* generate A layer map */ |
570c4371 |
161 | movea.l #0xe000,a6 |
4db6e09f |
162 | move.l #28-1,d4 |
163 | lmaploop0: |
164 | movea.l a6,a3 |
165 | jsr load_prepare |
166 | |
570c4371 |
167 | move.l #64/2-1,d3 |
168 | 0: move.l #0x00000000,(a3) |
4db6e09f |
169 | dbra d3,0b |
170 | |
171 | add.l #64*2,a6 |
172 | dbra d4,lmaploop0 |
173 | |
174 | /* generate B layer map */ |
570c4371 |
175 | movea.l #0xc000,a3 |
4db6e09f |
176 | jsr load_prepare |
177 | |
570c4371 |
178 | move.l #64*28/2-1,d3 |
179 | 0: move.l #0x00000000,(a3) |
4db6e09f |
180 | dbra d3,0b |
181 | |
182 | /* upload sprite data */ |
183 | movea.l #0xfc00,a3 |
184 | jsr load_prepare |
185 | movea.l #sprite_data,a0 |
186 | |
187 | move.l #(sprite_data_end-sprite_data)/2-1,d3 |
188 | 0: move.l (a0)+,(a3) |
189 | dbra d3,0b |
190 | |
191 | jsr wait_vsync |
192 | |
570c4371 |
193 | movea.l #hello,a0 |
194 | moveq.l #1,d0 |
195 | moveq.l #1,d1 |
196 | jsr print |
197 | |
4db6e09f |
198 | ################################################## |
199 | # # |
200 | # MAIN LOOP # |
201 | # # |
202 | ################################################## |
203 | |
204 | forever: |
4db6e09f |
205 | |
4db6e09f |
206 | |
207 | jsr wait_vsync |
208 | bra forever |
209 | |
210 | |
211 | |
212 | ################################################# |
213 | # # |
214 | # Initialize VDP registers # |
215 | # # |
216 | ################################################# |
217 | |
218 | init_gfx: |
219 | move.l #GFXCNTL,a3 |
570c4371 |
220 | write_vdp_reg 0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL) |
221 | write_vdp_reg 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED) |
4db6e09f |
222 | write_vdp_reg 2,(0xe000 >> 10) /* Screen map a adress */ |
223 | write_vdp_reg 3,(0xe000 >> 10) /* Window address */ |
224 | write_vdp_reg 4,(0xc000 >> 13) /* Screen map b address */ |
225 | write_vdp_reg 5,(0xfc00 >> 9) /* Sprite address */ |
226 | write_vdp_reg 6,0 |
570c4371 |
227 | write_vdp_reg 7,0 /* Backdrop color */ |
4db6e09f |
228 | write_vdp_reg 10,1 /* Lines per hblank interrupt */ |
229 | write_vdp_reg 11,0 /* 2-cell vertical scrolling */ |
570c4371 |
230 | write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320) |
231 | write_vdp_reg 13,(0x8000 >> 10) /* Horizontal scroll address */ |
4db6e09f |
232 | write_vdp_reg 15,2 |
570c4371 |
233 | write_vdp_reg 16,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */ |
4db6e09f |
234 | write_vdp_reg 17,0 |
235 | write_vdp_reg 18,0xff |
236 | rts |
237 | |
238 | |
239 | |
240 | ################################################# |
241 | # # |
242 | # Load tile data from ROM # |
243 | # # |
244 | # Parameters: # |
245 | # a3: VRAM base # |
246 | # a4: pattern address # |
247 | # d4: number of tiles to load # |
570c4371 |
248 | # Destroys a2,d0,d7... # |
4db6e09f |
249 | # # |
250 | ################################################# |
251 | |
252 | load_tiles: |
253 | move.l #GFXCNTL,a2 |
570c4371 |
254 | VRAM_ADDR_var a3 |
4db6e09f |
255 | move.l d0,(a2) |
256 | lsl #3,d4 |
257 | |
258 | move.l #GFXDATA,a3 |
259 | subq.l #1,d4 |
260 | _copy_tile_data: |
261 | move.l (a4)+,(a3) |
262 | dbra d4,_copy_tile_data |
263 | |
264 | rts |
265 | |
266 | |
570c4371 |
267 | # Prepare to write to VDP RAM @a3 |
268 | # a3: VRAM base |
269 | # a3 set to VDP data port for convenience |
270 | # destroys a2,d0,d7 |
271 | |
4db6e09f |
272 | load_prepare: |
273 | move.l #GFXCNTL,a2 |
570c4371 |
274 | VRAM_ADDR_var a3 |
4db6e09f |
275 | move.l d0,(a2) |
276 | move.l #GFXDATA,a3 |
277 | |
278 | rts |
279 | |
280 | |
4db6e09f |
281 | ################################################# |
282 | # # |
283 | # Load color data from ROM # |
284 | # # |
285 | # Parameters: # |
286 | # a3: CRAM base # |
287 | # a4: color list address # |
288 | # d4: number of colors to load # |
289 | # # |
290 | ################################################# |
291 | |
292 | load_colors: |
293 | move.l #GFXCNTL,a2 |
294 | CRAM_ADDR_var d0,a3 |
295 | move.l d0,(a2) |
296 | |
297 | move.l #GFXDATA,a3 |
298 | subq.w #1,d4 |
299 | _copy_color_data: |
300 | move.w (a4)+,(a3) |
301 | dbra d4,_copy_color_data |
302 | |
303 | rts |
304 | |
570c4371 |
305 | ################################################# |
306 | ## |
307 | ## print |
308 | # a0 - string |
309 | # d0 - x |
310 | # d1 - y |
311 | |
312 | print: |
313 | lsl.w #6,d1 |
314 | add.w d1,d0 |
315 | movea.l #0xe000,a6 |
316 | lsl.w #1,d0 |
317 | add.w d0,a6 |
318 | moveq.l #0,d1 |
319 | |
320 | _print_loop: |
321 | move.b (a0)+,d1 |
322 | beq _print_end |
323 | |
324 | move.l a6,a3 |
325 | jsr load_prepare |
326 | move.w d1,(a3) |
327 | addq.l #2,a6 |
328 | jmp _print_loop |
329 | |
330 | _print_end: |
331 | rts |
332 | |
4db6e09f |
333 | |
334 | ################################################# |
335 | # # |
336 | # Wait for next VBlank interrupt # |
337 | # # |
338 | ################################################# |
339 | |
340 | wait_vsync: |
341 | movea.l #vtimer,a0 |
342 | move.l (a0),a1 |
343 | _wait_change: |
344 | stop #0x2000 |
345 | cmp.l (a0),a1 |
346 | beq _wait_change |
347 | rts |
348 | |
349 | |
350 | ################################################# |
351 | # # |
352 | # RAM DATA # |
353 | # # |
354 | ################################################# |
355 | |
356 | .bss |
570c4371 |
357 | |
358 | # used by sega_gcc.s |
4db6e09f |
359 | .globl htimer |
360 | .globl vtimer |
361 | .globl rand_num |
362 | htimer: .long 0 |
363 | vtimer: .long 0 |
364 | rand_num: .long 0 |
570c4371 |
365 | |
366 | # |
4db6e09f |
367 | |
368 | .end |
369 | |
370 | # vim:filetype=asmM68k |