byte mode, edit mode wip
[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_STE,         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 val
118         btst.l          #\bit,d0
119         beq             0f
120         \op.l           \val,a6
121         bra             dpad_end
122 0:
123 .endm
124
125 #################################################
126 #                                               #
127 #                    DATA                       #
128 #                                               #
129 #################################################
130
131 colors:
132         dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
133         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
134         dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
135         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
136         dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
137         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
138 colors_end:
139
140
141 sprite_data:
142         /*         Y        size     link          attr        X */
143         dc.w       0;  dc.b 0x05;  dc.b 0;  dc.w 0x6002;  dc.w 0
144 sprite_data_end:
145
146 ##################################################
147 #                                                #
148 #               MAIN PROGRAM                     #
149 #                                                #
150 ##################################################
151  
152 .align 2
153
154 main:
155         /* mask irqs during init */
156         move.w          #0x2700,sr
157
158         movea.l         #0,a6
159         moveq.l         #0,d7
160         moveq.l         #0,d6
161
162         /* Init pads */
163         move.b          #0x40,(0xa10009).l
164         move.b          #0x40,(0xa10003).l
165
166         /* Initialize VDP */
167         jsr             init_gfx
168
169         /* Load color data */
170         movea.l         #0,a0
171         movea.l         #colors,a1
172         moveq.l         #(colors_end-colors)/2,d0
173         jsr             load_colors
174
175         /* load patterns */
176         movea.l         #0,a0
177         movea.l         #font,a1
178         move.l          #128,d0
179         jsr             load_tiles
180
181         /* generate A layer map */
182         movea.l         #0xe000,a1
183         move.l          #28-1,d4
184 lmaploop0:
185         movea.l         a1,a0
186         jsr             load_prepare
187
188         move.l          #64/2-1,d3
189 0:      move.l          #0x00000000,(a0)
190         dbra            d3,0b
191
192         add.l           #64*2,a1
193         dbra            d4,lmaploop0
194
195         /* generate B layer map */
196         movea.l         #0xc000,a0
197         jsr             load_prepare
198
199         move.l          #64*28/2-1,d3
200 0:      move.l          #0x00000000,(a0)
201         dbra            d3,0b
202
203         /* upload sprite data */
204         movea.l         #0xfc00,a0
205         jsr             load_prepare
206         movea.l         #sprite_data,a1
207
208         move.l          #(sprite_data_end-sprite_data)/2-1,d3
209 0:      move.l          (a1)+,(a0)
210         dbra            d3,0b
211
212         move.w          #0x2000,sr
213
214 ##################################################
215 #                                                #
216 #                 MAIN LOOP                      #
217 #                                                #
218 ##################################################
219
220 # global regs:
221 # a6 = page_start[31:8]|cursor_offs[7:0]
222 # d7 = old_inputs[31:16]|byte_mode[15]|g_mode[10:8]|irq_cnt[7:0]
223 # d6 = autorep_cnt[3:0]
224
225 forever:
226
227
228         jsr             wait_vsync
229         bra             forever
230         
231
232
233 VBL:
234         addq.b          #1,d7
235         movem.l         d0-d5/a0-a5,-(a7)
236
237         moveq.l         #0,d0
238         move.w          d7,d0
239         lsr.w           #6,d0
240         and.w           #0x1c,d0
241         move.l          (jumptab,pc,d0),a0
242         jmp             (a0)
243 jumptab:
244         dc.l            mode_main
245         dc.l            mode_edit
246         dc.l            mode_main
247         dc.l            mode_main
248         dc.l            mode_main
249         dc.l            mode_main
250         dc.l            mode_main
251         dc.l            mode_main
252
253 ##################### main #######################
254
255 mode_main:
256         clr.l           d1
257         move.l          a6,d0
258         move.b          d0,d1
259         lsr.l           #8,d0
260         move.l          d0,a1           /* current addr */
261         lsr.b           #3,d1
262         neg.b           d1
263         add.b           #27-1,d1        /* line where the cursor sits */
264         swap            d1
265
266         movea.l         #0xe004,a2
267         move.l          #27-1,d5        /* line counter for dbra */
268         or.l            d1,d5
269
270 draw_column:
271         move.l          a2,a0
272         jsr             load_prepare
273
274         /* addr */
275         move.l          a1,d2
276         moveq.l         #6,d3
277         jsr             print_hex_preped
278
279         /* 4 shorts */
280         moveq.l         #4,d3
281         moveq.l         #4-1,d4
282 draw_shorts:
283         move.w          #' ',(a0)
284         move.w          (a1)+,d2
285         jsr             print_hex_preped
286         dbra            d4,draw_shorts
287
288         move.l          d5,d0
289         swap            d0
290         cmp.w           d5,d0
291         beq             draw_cursor
292
293 draw_chars_pre:
294         move.l          #(' '<<16)|' ',(a0)
295
296         /* 8 chars */
297         subq.l          #8,a1
298         moveq.l         #8-1,d4
299 draw_chars:
300         move.b          (a1)+,d0
301         move.b          d0,d1
302         sub.b           #0x20,d1
303         cmp.b           #0x60,d1
304         blo             0f
305         move.w          #'.',d0
306 0:
307         move.w          d0,(a0)
308         dbra            d4,draw_chars
309
310         add.w           #0x80,a2
311         dbra            d5,draw_column
312
313         /* status bar */
314         movea.l         #0xe004+64*2*27,a0
315         jsr             load_prepare
316         move.l          a6,d2
317         moveq.l         #0,d3
318         move.b          d2,d3
319         lsr.l           #8,d2
320         add.l           d3,d2
321         move.l          #0x4006,d3
322         jsr             print_hex_preped
323
324         /* handle input */
325         jsr             get_input               /* x0cbrldu x1sa00du */
326
327         btst.l          #16+4,d0                /* A - scroll modifier */
328         beq             input_noa
329
330         do_dpad         16+0,  sub, #0x0800
331         do_dpad         16+1,  add, #0x0800
332         do_dpad         16+10, sub, #0xd800
333         do_dpad         16+11, add, #0xd800
334 input_noa:
335         moveq.l         #0,d1
336         btst.l          #15,d7
337         seq             d1
338         neg.b           d1                      /* 1 if word sel */
339         add.b           #1,d1
340
341         do_dpad         0,  subq, #0x0008
342         do_dpad         1,  addq, #0x0008
343         do_dpad         10, sub, d1
344         do_dpad         11, add, d1
345
346 dpad_end:
347         moveq.l         #0,d1
348         btst.l          #12,d0                  /* B - switch byte/word mode */
349         beq             input_nob
350         bchg.l          #15,d7
351         move.l          a6,d1
352         and.l           #1,d1
353         sub.l           d1,a6                   /* make even, just in case */
354
355 input_nob:
356         btst.l          #13,d0                  /* C - edit selected byte */
357         beq             input_noc
358 #       and.w           #0xf8ff,d7
359         or.w            #0x0100,d7              /* switch to edit mode */
360         write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE)
361
362 input_noc:
363         /* update addr */
364         move.l          a6,d0
365         cmp.b           #0xf0,d0
366         blo             0f
367         sub.l           #0xd800,a6
368         add.w           #0x00d8,a6
369         bra             1f
370 0:
371         cmp.b           #0xd8,d0
372         blo             1f
373         add.l           #0xd800,a6
374         sub.w           #0x00d8,a6
375 1:
376
377 vbl_end:
378         movem.l         (a7)+,d0-d5/a0-a5
379         rte
380
381
382 draw_cursor:
383         move.l          a6,d0
384         and.l           #7,d0           /* byte offs */
385         move.l          d0,d1
386         lsr.b           #1,d1           /* which word */
387         move.b          d1,d2
388         lsl.b           #2,d2
389         add.b           d2,d1           /* num of chars to skip */
390         lsl.b           #1,d1
391         move.w          #0x2004,d3
392
393         btst.l          #15,d7
394         beq             draw_cursor_word
395
396 draw_cursor_byte:
397         move.b          (-8,a1,d0),d2
398         and.b           #1,d0
399         lsl.b           #2,d0
400         add.b           d0,d1
401         subq.b          #2,d3
402         bra             0f
403
404 draw_cursor_word:
405         move.w          (-8,a1,d0),d2
406 0:
407         lea             (7*2,a2,d1),a0
408         jsr             load_prepare
409         jsr             print_hex_preped
410
411         move.l          a2,a0
412         add.w           #26*2,a0
413         jsr             load_prepare    /* restore a0 */
414
415         jmp             draw_chars_pre
416
417
418 ##################### edit #######################
419
420 mode_edit:
421         jmp             vbl_end
422
423
424 #################################################
425 #                                               #
426 #         Initialize VDP registers              #
427 #                                               #
428 #################################################
429
430 init_gfx:
431         move.l          #GFXCNTL,a3
432         write_vdp_reg   0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
433         write_vdp_reg   1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED)
434         write_vdp_reg   2,(0xe000 >> 10)        /* Screen map a adress */
435         write_vdp_reg   3,(0xe000 >> 10)        /* Window address */
436         write_vdp_reg   4,(0xc000 >> 13)        /* Screen map b address */
437         write_vdp_reg   5,(0xfc00 >>  9)        /* Sprite address */
438         write_vdp_reg   6,0     
439         write_vdp_reg   7,0                     /* Backdrop color */
440         write_vdp_reg   10,1                    /* Lines per hblank interrupt */
441         write_vdp_reg   11,0                    /* 2-cell vertical scrolling */
442         write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
443         write_vdp_reg   13,(0x8000 >> 10)       /* Horizontal scroll address */
444         write_vdp_reg   15,2
445         write_vdp_reg   16,(VDP16_MAP_V32 | VDP16_MAP_H64)      /* layer size */
446         write_vdp_reg   17,0
447         write_vdp_reg   18,0xff
448         rts
449
450
451 # read single phase from controller
452 #  #a0 - addr
453 #  d0 - result
454 #  destroys d1,d2
455 get_input:
456         move.b          #0x40,(0xa10003)
457         nop
458         nop
459         nop
460         move.b          (0xa10003),d0
461         move.b          #0x00,(0xa10003)
462         lsl.w           #8,d0
463         nop
464         move.b          (0xa10003),d0
465         eor.w           #0xffff,d0
466
467         swap            d7
468         move.w          d7,d1
469         eor.w           d0,d1           /* changed btns */
470         move.w          d0,d7           /* old val */
471         swap            d7
472         and.w           d0,d1           /* what changed now */
473         bne             0f
474
475         addq.b          #1,d6
476         move.b          d6,d2
477         and.b           #7,d2           /* do autorepeat every 8 frames */
478         cmp.b           #7,d2
479         bne             1f
480         move.w          d0,d1
481 0:
482         and.b           #0xf8,d6
483 1:
484         swap            d0
485         move.w          d1,d0
486         rts
487
488 # Load tile data from ROM
489 #  a0: VRAM base
490 #  a1: pattern address
491 #  d0: number of tiles to load
492 #  destroys d1
493
494 load_tiles:
495         move.l          d0,d1
496         VRAM_ADDR_var   a0
497         move.l          d0,(GFXCNTL).l
498         
499         move.l          #GFXDATA,a0
500         lsl.w           #3,d1
501         subq.l          #1,d1
502 0:
503         move.l          (a1)+,(a0)
504         dbra            d1,0b
505
506         rts
507
508
509 # Prepare to write to VDP RAM @a3
510 # sets a0 to VDP data port for convenience
511 #  a0: VRAM base
512 #  destroys d0
513
514 load_prepare:
515         VRAM_ADDR_var   a0
516         move.l          d0,(GFXCNTL).l
517         move.l          #GFXDATA,a0
518         rts
519
520
521 # Load color data from ROM
522 #  a0: CRAM base
523 #  a1: color list address
524 #  d0: number of colors to load
525 #  destroys d1
526
527 load_colors:
528         move.l          d0,d1
529         CRAM_ADDR_var   a0
530         move.l          d0,(GFXCNTL).l
531
532         move.l          #GFXDATA,a0
533         subq.w          #1,d1
534 0:
535         move.w          (a1)+,(a0)
536         dbra            d1,0b
537
538         rts
539
540
541 # print
542 #  a0 - string
543 #  d0 - x
544 #  d1 - y 
545 #  destroys a1
546
547 print:
548         move.l          a0,a1
549         XY2NT
550         jsr             load_prepare
551         moveq.l         #0,d0
552
553 _print_loop:
554         move.b          (a1)+,d0
555         beq             _print_end
556
557         move.w          d0,(a0)
558         jmp             _print_loop
559
560 _print_end:
561         rts
562
563
564 # print_hex
565 #  d0 - x
566 #  d1 - y 
567 #  d2 - value
568 #  d3 - digit_cnt[0:7]|tile_bits[11:15]
569 #  destroys a0, preserves d3
570
571 print_hex:
572         XY2NT
573         jsr             load_prepare
574
575 print_hex_preped:
576         moveq.l         #0,d0
577         move.b          d3,d0
578         move.l          d0,d1
579         lsl.b           #2,d0
580         ror.l           d0,d2           /* prep value */
581         subq.l          #1,d1           /* count */
582         move.w          d3,d0
583         and.w           #0xf800,d0      /* keep upper bits in d0 */
584
585 _print_hex_loop:
586         rol.l           #4,d2
587         move.b          d2,d0
588         and.b           #0xf,d0
589
590         add.b           #'0',d0
591         cmp.b           #'9',d0
592         ble             0f
593         addq.b          #7,d0
594 0:
595         move.w          d0,(a0)
596         dbra            d1,_print_hex_loop
597
598         rts
599
600
601 #################################################
602 #                                               #
603 #       Wait for next VBlank interrupt          #
604 #                                               #
605 #################################################
606
607 wait_vsync:
608         move.b          d7,d0
609 _wait_change:
610         stop            #0x2000
611         cmp.b           d7,d0
612         beq             _wait_change
613         rts
614
615
616 #################################################
617 #                                               #
618 #                 RAM DATA                      #
619 #                                               #
620 #################################################
621
622 .bss
623
624 # nothing :)
625
626 .end
627
628 # vim:filetype=asmM68k