4db6e09f |
1 | ################################################## |
2 | # # |
3 | # Assemble with gas # |
4 | # --register-prefix-optional --bitwise-or # |
5 | # # |
6 | ################################################## |
7 | |
8 | .text |
9 | .globl main |
1286a1ba |
10 | .globl VBL |
4db6e09f |
11 | |
12 | ################################################## |
13 | # # |
14 | # Register and bitmask definitions # |
15 | # # |
16 | ################################################## |
17 | |
18 | .equ GFXDATA, 0xc00000 |
19 | .equ GFXCNTL, 0xc00004 |
20 | |
21 | .equ VDP0_E_HBI, 0x10 |
22 | .equ VDP0_E_DISPLAY, 0x02 |
23 | .equ VDP0_PLTT_FULL, 0x04 |
24 | |
25 | .equ VDP1_SMS_MODE, 0x80 |
26 | .equ VDP1_E_DISPLAY, 0x40 |
27 | .equ VDP1_E_VBI, 0x20 |
28 | .equ VDP1_E_DMA, 0x10 |
29 | .equ VDP1_NTSC, 0x00 |
30 | .equ VDP1_PAL, 0x08 |
31 | .equ VDP1_RESERVED, 0x04 |
32 | |
33 | .equ VDP12_SPR_SHADOWS, 0x08 |
34 | .equ VDP12_SCREEN_V224, 0x00 |
35 | .equ VDP12_SCREEN_V448, 0x04 |
36 | .equ VDP12_PROGRESSIVE, 0x00 |
37 | .equ VDP12_INTERLACED, 0x02 |
38 | .equ VDP12_SCREEN_H256, 0x00 |
39 | .equ VDP12_SCREEN_H320, 0x81 |
40 | |
41 | .equ VDP16_MAP_V32, 0x00 |
42 | .equ VDP16_MAP_V64, 0x10 |
43 | .equ VDP16_MAP_V128, 0x30 |
44 | .equ VDP16_MAP_H32, 0x00 |
45 | .equ VDP16_MAP_H64, 0x01 |
46 | .equ VDP16_MAP_H128, 0x03 |
47 | |
48 | |
49 | |
50 | ################################################## |
51 | # # |
52 | # MACROS # |
53 | # # |
54 | ################################################## |
55 | |
56 | |
57 | /* Write val to VDP register reg */ |
58 | .macro write_vdp_reg reg val |
59 | move.w #((\reg << 8) + 0x8000 + \val),(a3) |
60 | .endm |
61 | |
62 | |
63 | /* For immediate addresses */ |
64 | .macro VRAM_ADDR reg adr |
65 | move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg |
66 | .endm |
67 | |
68 | |
0fc4f06b |
69 | .macro CRAM_ADDR reg adr |
70 | move.l #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg |
71 | .endm |
72 | |
73 | |
74 | # make VDP word from address adr and store in d0 |
75 | .macro XRAM_ADDR_var adr |
570c4371 |
76 | move.l \adr,d0 |
0fc4f06b |
77 | lsl.l #8,d0 |
78 | lsl.l #8,d0 |
79 | rol.l #2,d0 |
80 | lsl.b #2,d0 |
81 | lsr.l #2,d0 |
4db6e09f |
82 | .endm |
83 | |
84 | |
0fc4f06b |
85 | .macro VRAM_ADDR_var adr |
86 | XRAM_ADDR_var \adr |
87 | or.l #0x40000000,d0 |
4db6e09f |
88 | .endm |
89 | |
90 | |
0fc4f06b |
91 | .macro CRAM_ADDR_var adr |
92 | XRAM_ADDR_var \adr |
93 | or.l #0xc0000000,d0 |
4db6e09f |
94 | .endm |
95 | |
96 | |
97 | .macro VSCROLL_ADDR reg adr |
98 | move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg |
99 | .endm |
100 | |
101 | |
102 | .macro HSCROLL_ADDR reg adr |
103 | move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg |
104 | .endm |
105 | |
106 | |
1286a1ba |
107 | # convert tile coords in d0, d1 to nametable addr to a0 |
108 | .macro XY2NT |
109 | lsl.w #6,d1 |
110 | add.w d1,d0 |
111 | lsl.w #1,d0 |
112 | movea.l #0xe000,a0 |
113 | add.w d0,a0 |
114 | .endm |
115 | |
4276cd7a |
116 | # check if some d-pad button (and modifier) is pressed |
117 | .macro do_dpad bit op opq val modval |
118 | btst.b #\bit,d0 |
119 | beq 1f |
120 | btst.b #4,d0 /* A pressed? */ |
121 | bne 0f |
122 | \opq.l #\val,a6 |
123 | bra input_end |
124 | 0: |
125 | \op.l #\modval,a6 |
126 | bra input_end |
127 | 1: |
128 | .endm |
129 | |
4db6e09f |
130 | ################################################# |
131 | # # |
132 | # DATA # |
133 | # # |
134 | ################################################# |
135 | |
136 | colors: |
4276cd7a |
137 | dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 |
138 | dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 |
139 | dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 |
140 | dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 |
141 | dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 |
142 | dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 |
570c4371 |
143 | colors_end: |
144 | |
4db6e09f |
145 | |
146 | sprite_data: |
147 | /* Y size link attr X */ |
570c4371 |
148 | dc.w 0; dc.b 0x05; dc.b 0; dc.w 0x6002; dc.w 0 |
4db6e09f |
149 | sprite_data_end: |
150 | |
4db6e09f |
151 | ################################################## |
152 | # # |
153 | # MAIN PROGRAM # |
154 | # # |
155 | ################################################## |
156 | |
570c4371 |
157 | .align 2 |
158 | |
4db6e09f |
159 | main: |
4276cd7a |
160 | /* mask irqs during init */ |
1286a1ba |
161 | move.w #0x2700,sr |
162 | |
163 | movea.l #0,a6 |
4276cd7a |
164 | moveq.l #0,d7 |
1286a1ba |
165 | |
166 | /* Init pads */ |
167 | move.b #0x40,(0xa10009).l |
168 | move.b #0x40,(0xa10003).l |
169 | |
4db6e09f |
170 | /* Initialize VDP */ |
171 | jsr init_gfx |
172 | |
173 | /* Load color data */ |
0fc4f06b |
174 | movea.l #0,a0 |
175 | movea.l #colors,a1 |
176 | moveq.l #(colors_end-colors)/2,d0 |
4db6e09f |
177 | jsr load_colors |
178 | |
179 | /* load patterns */ |
0fc4f06b |
180 | movea.l #0,a0 |
181 | movea.l #font,a1 |
182 | move.l #128,d0 |
4db6e09f |
183 | jsr load_tiles |
184 | |
185 | /* generate A layer map */ |
1286a1ba |
186 | movea.l #0xe000,a1 |
4db6e09f |
187 | move.l #28-1,d4 |
188 | lmaploop0: |
1286a1ba |
189 | movea.l a1,a0 |
4db6e09f |
190 | jsr load_prepare |
191 | |
570c4371 |
192 | move.l #64/2-1,d3 |
0fc4f06b |
193 | 0: move.l #0x00000000,(a0) |
4db6e09f |
194 | dbra d3,0b |
195 | |
1286a1ba |
196 | add.l #64*2,a1 |
4db6e09f |
197 | dbra d4,lmaploop0 |
198 | |
199 | /* generate B layer map */ |
0fc4f06b |
200 | movea.l #0xc000,a0 |
4db6e09f |
201 | jsr load_prepare |
202 | |
570c4371 |
203 | move.l #64*28/2-1,d3 |
0fc4f06b |
204 | 0: move.l #0x00000000,(a0) |
4db6e09f |
205 | dbra d3,0b |
206 | |
207 | /* upload sprite data */ |
0fc4f06b |
208 | movea.l #0xfc00,a0 |
4db6e09f |
209 | jsr load_prepare |
0fc4f06b |
210 | movea.l #sprite_data,a1 |
4db6e09f |
211 | |
212 | move.l #(sprite_data_end-sprite_data)/2-1,d3 |
0fc4f06b |
213 | 0: move.l (a1)+,(a0) |
4db6e09f |
214 | dbra d3,0b |
215 | |
1286a1ba |
216 | move.w #0x2000,sr |
570c4371 |
217 | |
4db6e09f |
218 | ################################################## |
219 | # # |
220 | # MAIN LOOP # |
221 | # # |
222 | ################################################## |
223 | |
1286a1ba |
224 | # global regs: |
4276cd7a |
225 | # a6 - page_start[31:8]|cursor_offs[7:0] |
226 | # d7 - byte_mode[0] |
1286a1ba |
227 | |
4db6e09f |
228 | forever: |
4db6e09f |
229 | |
4db6e09f |
230 | |
231 | jsr wait_vsync |
232 | bra forever |
233 | |
234 | |
235 | |
1286a1ba |
236 | VBL: |
237 | addq.l #1,(vtimer).l |
4276cd7a |
238 | movem.l d0-d6/a0-a5,-(a7) |
1286a1ba |
239 | |
240 | /* draw main stuff */ |
4276cd7a |
241 | clr.l d1 |
1286a1ba |
242 | move.l a6,d0 |
4276cd7a |
243 | move.b d0,d1 |
1286a1ba |
244 | lsr.l #8,d0 |
245 | move.l d0,a1 /* current addr */ |
4276cd7a |
246 | lsr.b #3,d1 |
247 | neg.b d1 |
248 | add.b #27-1,d1 /* line where the cursor sits */ |
249 | swap d1 |
1286a1ba |
250 | |
251 | movea.l #0xe004,a2 |
4276cd7a |
252 | move.l #27-1,d5 /* line counter for dbra */ |
253 | or.l d1,d5 |
1286a1ba |
254 | |
255 | draw_column: |
256 | move.l a2,a0 |
257 | jsr load_prepare |
258 | |
259 | /* addr */ |
260 | move.l a1,d2 |
261 | moveq.l #6,d3 |
262 | jsr print_hex_preped |
263 | |
264 | /* 4 shorts */ |
4276cd7a |
265 | moveq.l #4,d3 |
1286a1ba |
266 | moveq.l #4-1,d4 |
267 | draw_shorts: |
268 | move.w #' ',(a0) |
269 | move.w (a1)+,d2 |
1286a1ba |
270 | jsr print_hex_preped |
271 | dbra d4,draw_shorts |
272 | |
4276cd7a |
273 | move.l d5,d0 |
274 | swap d0 |
275 | cmp.w d5,d0 |
276 | beq draw_cursor |
277 | |
278 | draw_chars_pre: |
279 | move.l #(' '<<16)|' ',(a0) |
1286a1ba |
280 | |
281 | /* 8 chars */ |
282 | subq.l #8,a1 |
283 | moveq.l #8-1,d4 |
284 | draw_chars: |
285 | move.b (a1)+,d0 |
286 | move.b d0,d1 |
287 | sub.b #0x20,d1 |
288 | cmp.b #0x60,d1 |
289 | blo 0f |
290 | move.w #'.',d0 |
291 | 0: |
292 | move.w d0,(a0) |
293 | dbra d4,draw_chars |
294 | |
295 | add.w #0x80,a2 |
296 | dbra d5,draw_column |
297 | |
4276cd7a |
298 | /* status bar */ |
299 | movea.l #0xe004+64*2*27,a0 |
300 | jsr load_prepare |
301 | move.l a6,d2 |
302 | moveq.l #0,d3 |
303 | move.b d2,d3 |
304 | lsr.l #8,d2 |
305 | add.l d3,d2 |
306 | move.l #0x4006,d3 |
307 | jsr print_hex_preped |
308 | |
1286a1ba |
309 | /* handle input */ |
310 | jsr get_input /* x0cbrldu x1sa00du */ |
1286a1ba |
311 | |
4276cd7a |
312 | do_dpad 0, sub, subq, 0x0008, 0x0800 |
313 | do_dpad 1, add, addq, 0x0008, 0x0800 |
314 | do_dpad 10, sub, subq, 0x0001, 0xd800 |
315 | do_dpad 11, add, addq, 0x0001, 0xd800 |
316 | input_end: |
1286a1ba |
317 | |
4276cd7a |
318 | /* update addr */ |
319 | move.l a6,d0 |
320 | cmp.b #0xf0,d0 |
321 | blo 0f |
322 | sub.l #0xd800,a6 |
323 | add.w #0x00d8,a6 |
324 | bra 1f |
325 | 0: |
326 | cmp.b #0xe0,d0 |
327 | blo 1f |
328 | add.l #0xd800,a6 |
329 | sub.w #0x00d8,a6 |
330 | 1: |
1286a1ba |
331 | |
332 | end: |
4276cd7a |
333 | movem.l (a7)+,d0-d6/a0-a5 |
1286a1ba |
334 | rte |
335 | |
336 | |
4276cd7a |
337 | draw_cursor: |
338 | move.l a6,d0 |
339 | and.l #7,d0 /* byte offs */ |
340 | move.l d0,d1 |
341 | lsr.b #1,d1 /* which word */ |
342 | move.b d1,d2 |
343 | lsl.b #2,d2 |
344 | add.b d2,d1 /* num of chars to skip */ |
345 | lsl.b #1,d1 |
346 | |
347 | /* FIXME */ |
348 | move.w (-8,a1,d0),d2 |
349 | |
350 | lea (7*2,a2,d1),a0 |
351 | jsr load_prepare |
352 | |
353 | move.w #0x2004,d3 |
354 | jsr print_hex_preped |
355 | |
356 | move.l a2,a0 |
357 | add.w #26*2,a0 |
358 | jsr load_prepare /* restore a0 */ |
359 | |
360 | jmp draw_chars_pre |
361 | |
362 | |
4db6e09f |
363 | ################################################# |
364 | # # |
365 | # Initialize VDP registers # |
366 | # # |
367 | ################################################# |
368 | |
369 | init_gfx: |
370 | move.l #GFXCNTL,a3 |
570c4371 |
371 | write_vdp_reg 0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL) |
372 | write_vdp_reg 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED) |
4db6e09f |
373 | write_vdp_reg 2,(0xe000 >> 10) /* Screen map a adress */ |
374 | write_vdp_reg 3,(0xe000 >> 10) /* Window address */ |
375 | write_vdp_reg 4,(0xc000 >> 13) /* Screen map b address */ |
376 | write_vdp_reg 5,(0xfc00 >> 9) /* Sprite address */ |
377 | write_vdp_reg 6,0 |
570c4371 |
378 | write_vdp_reg 7,0 /* Backdrop color */ |
4db6e09f |
379 | write_vdp_reg 10,1 /* Lines per hblank interrupt */ |
380 | write_vdp_reg 11,0 /* 2-cell vertical scrolling */ |
570c4371 |
381 | write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320) |
382 | write_vdp_reg 13,(0x8000 >> 10) /* Horizontal scroll address */ |
4db6e09f |
383 | write_vdp_reg 15,2 |
570c4371 |
384 | write_vdp_reg 16,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */ |
4db6e09f |
385 | write_vdp_reg 17,0 |
386 | write_vdp_reg 18,0xff |
387 | rts |
388 | |
389 | |
1286a1ba |
390 | # read single phase from controller |
391 | # a0 - addr |
392 | # d0 - result |
393 | get_input: |
394 | move.b #0x40,(0xa10003) |
395 | nop |
396 | nop |
397 | nop |
398 | move.b (0xa10003),d0 |
399 | move.b #0x00,(0xa10003) |
400 | lsl.w #8,d0 |
401 | nop |
402 | move.b (0xa10003),d0 |
403 | eor.w #0xffff,d0 |
404 | # move.b #0x40,(0xa10003) |
405 | rts |
406 | |
0fc4f06b |
407 | # Load tile data from ROM |
408 | # a0: VRAM base |
409 | # a1: pattern address |
410 | # d0: number of tiles to load |
411 | # destroys d1 |
4db6e09f |
412 | |
413 | load_tiles: |
0fc4f06b |
414 | move.l d0,d1 |
415 | VRAM_ADDR_var a0 |
416 | move.l d0,(GFXCNTL).l |
4db6e09f |
417 | |
0fc4f06b |
418 | move.l #GFXDATA,a0 |
419 | lsl.w #3,d1 |
420 | subq.l #1,d1 |
421 | 0: |
422 | move.l (a1)+,(a0) |
423 | dbra d1,0b |
4db6e09f |
424 | |
425 | rts |
426 | |
427 | |
570c4371 |
428 | # Prepare to write to VDP RAM @a3 |
0fc4f06b |
429 | # sets a0 to VDP data port for convenience |
430 | # a0: VRAM base |
431 | # destroys d0 |
570c4371 |
432 | |
4db6e09f |
433 | load_prepare: |
0fc4f06b |
434 | VRAM_ADDR_var a0 |
435 | move.l d0,(GFXCNTL).l |
436 | move.l #GFXDATA,a0 |
4db6e09f |
437 | rts |
438 | |
439 | |
0fc4f06b |
440 | # Load color data from ROM |
441 | # a0: CRAM base |
442 | # a1: color list address |
443 | # d0: number of colors to load |
444 | # destroys d1 |
4db6e09f |
445 | |
446 | load_colors: |
0fc4f06b |
447 | move.l d0,d1 |
448 | CRAM_ADDR_var a0 |
449 | move.l d0,(GFXCNTL).l |
4db6e09f |
450 | |
0fc4f06b |
451 | move.l #GFXDATA,a0 |
452 | subq.w #1,d1 |
453 | 0: |
454 | move.w (a1)+,(a0) |
455 | dbra d1,0b |
4db6e09f |
456 | |
457 | rts |
458 | |
0fc4f06b |
459 | |
460 | # print |
461 | # a0 - string |
462 | # d0 - x |
463 | # d1 - y |
464 | # destroys a1 |
570c4371 |
465 | |
466 | print: |
0fc4f06b |
467 | move.l a0,a1 |
1286a1ba |
468 | XY2NT |
0fc4f06b |
469 | jsr load_prepare |
470 | moveq.l #0,d0 |
570c4371 |
471 | |
472 | _print_loop: |
0fc4f06b |
473 | move.b (a1)+,d0 |
570c4371 |
474 | beq _print_end |
475 | |
0fc4f06b |
476 | move.w d0,(a0) |
570c4371 |
477 | jmp _print_loop |
478 | |
479 | _print_end: |
480 | rts |
481 | |
4db6e09f |
482 | |
1286a1ba |
483 | # print_hex |
484 | # d0 - x |
485 | # d1 - y |
486 | # d2 - value |
4276cd7a |
487 | # d3 - digit_cnt[0:7]|tile_bits[11:15] |
488 | # destroys a0, preserves d3 |
1286a1ba |
489 | |
490 | print_hex: |
491 | XY2NT |
492 | jsr load_prepare |
493 | |
494 | print_hex_preped: |
4276cd7a |
495 | moveq.l #0,d0 |
496 | move.b d3,d0 |
497 | move.l d0,d1 |
1286a1ba |
498 | lsl.b #2,d0 |
499 | ror.l d0,d2 /* prep value */ |
4276cd7a |
500 | subq.l #1,d1 /* count */ |
501 | move.w d3,d0 |
502 | and.w #0xf800,d0 /* keep upper bits in d0 */ |
1286a1ba |
503 | |
504 | _print_hex_loop: |
505 | rol.l #4,d2 |
506 | move.b d2,d0 |
507 | and.b #0xf,d0 |
1286a1ba |
508 | |
509 | add.b #'0',d0 |
4276cd7a |
510 | cmp.b #'9',d0 |
511 | ble 0f |
512 | addq.b #7,d0 |
513 | 0: |
1286a1ba |
514 | move.w d0,(a0) |
4276cd7a |
515 | dbra d1,_print_hex_loop |
1286a1ba |
516 | |
517 | rts |
518 | |
519 | |
4db6e09f |
520 | ################################################# |
521 | # # |
522 | # Wait for next VBlank interrupt # |
523 | # # |
524 | ################################################# |
525 | |
526 | wait_vsync: |
527 | movea.l #vtimer,a0 |
528 | move.l (a0),a1 |
529 | _wait_change: |
530 | stop #0x2000 |
531 | cmp.l (a0),a1 |
532 | beq _wait_change |
533 | rts |
534 | |
535 | |
536 | ################################################# |
537 | # # |
538 | # RAM DATA # |
539 | # # |
540 | ################################################# |
541 | |
542 | .bss |
570c4371 |
543 | |
544 | # used by sega_gcc.s |
4db6e09f |
545 | .globl htimer |
546 | .globl vtimer |
547 | .globl rand_num |
548 | htimer: .long 0 |
549 | vtimer: .long 0 |
550 | rand_num: .long 0 |
570c4371 |
551 | |
552 | # |
4db6e09f |
553 | |
554 | .end |
555 | |
556 | # vim:filetype=asmM68k |