93f6a2be4176b65c9c05051dc45245db9d451eac
[megadrive.git] / hexed / hexed.s
1 ##################################################
2 #                                                #
3 # Assemble with gas                              #
4 #   --register-prefix-optional --bitwise-or      #
5 #                                                #
6 ##################################################
7
8 .text
9 .globl main
10 .globl VBL
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
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
76         move.l \adr,d0
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
82 .endm
83
84
85 .macro VRAM_ADDR_var adr
86         XRAM_ADDR_var \adr
87         or.l #0x40000000,d0
88 .endm
89
90
91 .macro CRAM_ADDR_var adr
92         XRAM_ADDR_var \adr
93         or.l #0xc0000000,d0
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
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
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
130 #################################################
131 #                                               #
132 #                    DATA                       #
133 #                                               #
134 #################################################
135
136 colors:
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
143 colors_end:
144
145
146 sprite_data:
147         /*         Y        size     link          attr        X */
148         dc.w       0;  dc.b 0x05;  dc.b 0;  dc.w 0x6002;  dc.w 0
149 sprite_data_end:
150
151 ##################################################
152 #                                                #
153 #               MAIN PROGRAM                     #
154 #                                                #
155 ##################################################
156  
157 .align 2
158
159 main:
160         /* mask irqs during init */
161         move.w          #0x2700,sr
162
163         movea.l         #0,a6
164         moveq.l         #0,d7
165
166         /* Init pads */
167         move.b          #0x40,(0xa10009).l
168         move.b          #0x40,(0xa10003).l
169
170         /* Initialize VDP */
171         jsr             init_gfx
172
173         /* Load color data */
174         movea.l         #0,a0
175         movea.l         #colors,a1
176         moveq.l         #(colors_end-colors)/2,d0
177         jsr             load_colors
178
179         /* load patterns */
180         movea.l         #0,a0
181         movea.l         #font,a1
182         move.l          #128,d0
183         jsr             load_tiles
184
185         /* generate A layer map */
186         movea.l         #0xe000,a1
187         move.l          #28-1,d4
188 lmaploop0:
189         movea.l         a1,a0
190         jsr             load_prepare
191
192         move.l          #64/2-1,d3
193 0:      move.l          #0x00000000,(a0)
194         dbra            d3,0b
195
196         add.l           #64*2,a1
197         dbra            d4,lmaploop0
198
199         /* generate B layer map */
200         movea.l         #0xc000,a0
201         jsr             load_prepare
202
203         move.l          #64*28/2-1,d3
204 0:      move.l          #0x00000000,(a0)
205         dbra            d3,0b
206
207         /* upload sprite data */
208         movea.l         #0xfc00,a0
209         jsr             load_prepare
210         movea.l         #sprite_data,a1
211
212         move.l          #(sprite_data_end-sprite_data)/2-1,d3
213 0:      move.l          (a1)+,(a0)
214         dbra            d3,0b
215
216         move.w          #0x2000,sr
217
218 ##################################################
219 #                                                #
220 #                 MAIN LOOP                      #
221 #                                                #
222 ##################################################
223
224 # global regs:
225 # a6 - page_start[31:8]|cursor_offs[7:0]
226 # d7 - byte_mode[0]
227
228 forever:
229
230
231         jsr             wait_vsync
232         bra             forever
233         
234
235
236 VBL:
237         addq.l          #1,(vtimer).l
238         movem.l         d0-d6/a0-a5,-(a7)
239
240         /* draw main stuff */
241         clr.l           d1
242         move.l          a6,d0
243         move.b          d0,d1
244         lsr.l           #8,d0
245         move.l          d0,a1           /* current addr */
246         lsr.b           #3,d1
247         neg.b           d1
248         add.b           #27-1,d1        /* line where the cursor sits */
249         swap            d1
250
251         movea.l         #0xe004,a2
252         move.l          #27-1,d5        /* line counter for dbra */
253         or.l            d1,d5
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 */
265         moveq.l         #4,d3
266         moveq.l         #4-1,d4
267 draw_shorts:
268         move.w          #' ',(a0)
269         move.w          (a1)+,d2
270         jsr             print_hex_preped
271         dbra            d4,draw_shorts
272
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)
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
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
309         /* handle input */
310         jsr             get_input               /* x0cbrldu x1sa00du */
311
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:
317
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:
331
332 end:
333         movem.l         (a7)+,d0-d6/a0-a5
334         rte
335
336
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
363 #################################################
364 #                                               #
365 #         Initialize VDP registers              #
366 #                                               #
367 #################################################
368
369 init_gfx:
370         move.l          #GFXCNTL,a3
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)
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     
378         write_vdp_reg   7,0                     /* Backdrop color */
379         write_vdp_reg   10,1                    /* Lines per hblank interrupt */
380         write_vdp_reg   11,0                    /* 2-cell vertical scrolling */
381         write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
382         write_vdp_reg   13,(0x8000 >> 10)       /* Horizontal scroll address */
383         write_vdp_reg   15,2
384         write_vdp_reg   16,(VDP16_MAP_V32 | VDP16_MAP_H64)      /* layer size */
385         write_vdp_reg   17,0
386         write_vdp_reg   18,0xff
387         rts
388
389
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
407 # Load tile data from ROM
408 #  a0: VRAM base
409 #  a1: pattern address
410 #  d0: number of tiles to load
411 #  destroys d1
412
413 load_tiles:
414         move.l          d0,d1
415         VRAM_ADDR_var   a0
416         move.l          d0,(GFXCNTL).l
417         
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
424
425         rts
426
427
428 # Prepare to write to VDP RAM @a3
429 # sets a0 to VDP data port for convenience
430 #  a0: VRAM base
431 #  destroys d0
432
433 load_prepare:
434         VRAM_ADDR_var   a0
435         move.l          d0,(GFXCNTL).l
436         move.l          #GFXDATA,a0
437         rts
438
439
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
445
446 load_colors:
447         move.l          d0,d1
448         CRAM_ADDR_var   a0
449         move.l          d0,(GFXCNTL).l
450
451         move.l          #GFXDATA,a0
452         subq.w          #1,d1
453 0:
454         move.w          (a1)+,(a0)
455         dbra            d1,0b
456
457         rts
458
459
460 # print
461 #  a0 - string
462 #  d0 - x
463 #  d1 - y 
464 #  destroys a1
465
466 print:
467         move.l          a0,a1
468         XY2NT
469         jsr             load_prepare
470         moveq.l         #0,d0
471
472 _print_loop:
473         move.b          (a1)+,d0
474         beq             _print_end
475
476         move.w          d0,(a0)
477         jmp             _print_loop
478
479 _print_end:
480         rts
481
482
483 # print_hex
484 #  d0 - x
485 #  d1 - y 
486 #  d2 - value
487 #  d3 - digit_cnt[0:7]|tile_bits[11:15]
488 #  destroys a0, preserves d3
489
490 print_hex:
491         XY2NT
492         jsr             load_prepare
493
494 print_hex_preped:
495         moveq.l         #0,d0
496         move.b          d3,d0
497         move.l          d0,d1
498         lsl.b           #2,d0
499         ror.l           d0,d2           /* prep value */
500         subq.l          #1,d1           /* count */
501         move.w          d3,d0
502         and.w           #0xf800,d0      /* keep upper bits in d0 */
503
504 _print_hex_loop:
505         rol.l           #4,d2
506         move.b          d2,d0
507         and.b           #0xf,d0
508
509         add.b           #'0',d0
510         cmp.b           #'9',d0
511         ble             0f
512         addq.b          #7,d0
513 0:
514         move.w          d0,(a0)
515         dbra            d1,_print_hex_loop
516
517         rts
518
519
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
543
544 # used by sega_gcc.s
545 .globl htimer
546 .globl vtimer
547 .globl rand_num
548 htimer:         .long 0
549 vtimer:         .long 0
550 rand_num:       .long 0
551
552 #
553
554 .end
555
556 # vim:filetype=asmM68k