byte mode, dtack safety
[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 .equ MMODE_MAIN,        0
49 .equ MMODE_VAL_INPUT,   1
50 .equ MMODE_EDIT_VAL,    2
51 .equ MMODE_GOTO,        3
52 .equ MMODE_START_MENU,  4
53 .equ MMODE_GOTO_PREDEF, 5
54
55 .equ predef_addr_cnt,   ((predef_addrs_end-predef_addrs)/4)
56
57 ##################################################
58 #                                                #
59 #                   MACROS                       #
60 #                                                #
61 ##################################################
62
63
64 # Write val to VDP register reg
65 .macro write_vdp_r_dst reg val dst
66         move.w #((\reg << 8) + 0x8000 + \val),\dst
67 .endm
68
69 # Write val to VDP register reg, vdp addr in a3
70 .macro write_vdp_reg reg val
71         write_vdp_r_dst \reg, \val, (a3)
72 .endm
73
74 /* For immediate addresses */
75 .macro VRAM_ADDR reg adr
76         move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
77 .endm
78
79 .macro CRAM_ADDR reg adr
80         move.l  #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
81 .endm
82
83
84 # make VDP word from address adr and store in d0
85 .macro XRAM_ADDR_var adr
86         move.l \adr,d0
87         lsl.l #8,d0
88         lsl.l #8,d0
89         rol.l #2,d0
90         lsl.b #2,d0
91         lsr.l #2,d0
92 .endm
93
94
95 .macro VRAM_ADDR_var adr
96         XRAM_ADDR_var \adr
97         or.l #0x40000000,d0
98 .endm
99
100
101 .macro CRAM_ADDR_var adr
102         XRAM_ADDR_var \adr
103         or.l #0xc0000000,d0
104 .endm
105
106
107 .macro VSCROLL_ADDR reg adr
108         move.l  #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg
109 .endm
110
111
112 .macro HSCROLL_ADDR reg adr
113         move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
114 .endm
115
116
117 # convert tile coords in d0, d1 to nametable addr to a0
118 .macro XY2NT
119         lsl.w           #6,d1
120         add.w           d1,d0
121         lsl.w           #1,d0
122         movea.l         #0xe000,a0
123         add.w           d0,a0
124 .endm
125
126 # check if some d-pad button (and modifier) is pressed
127 .macro do_dpad bit op val
128         btst.l          #\bit,d0
129         beq             0f
130         \op.l           \val,a6
131         bra             dpad_end
132 0:
133 .endm
134
135 # convert a6 to normal addr
136 #  destroys d0
137 .macro mk_a6_addr reg
138         move.l          a6,\reg
139         moveq.l         #0,d0
140         move.b          \reg,d0
141         lsr.l           #8,\reg
142         add.l           d0,\reg
143 .endm
144
145 .macro change_mode mode_new mode_back
146         and.w           #0xc0ff,d7
147         or.w            #(\mode_back<<11)|(\mode_new<<8),d7
148 .endm
149
150 .macro menu_text str x y pal
151         lea             \str,a0
152         move.l          #\x,d0
153         move.l          #\y,d1
154         move.l          #0x8000|(\pal<<13),d2
155         jsr             print
156 .endm
157
158 #################################################
159 #                                               #
160 #                    DATA                       #
161 #                                               #
162 #################################################
163
164 colors:
165         dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
166         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
167         dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
168         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
169         dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
170         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
171 colors_end:
172
173
174 sprite_data:
175         /*         Y        size     link          attr        X */
176         dc.w       0;  dc.b 0x05;  dc.b 0;  dc.w 0x6002;  dc.w 0
177 sprite_data_end:
178
179 predef_addrs:
180         dc.l 0x000000, 0x200000, 0x400000, 0xa00000, 0xa10000
181         dc.l 0xa11100, 0xa12000, 0xa13000, 0xc00000
182 predef_addrs_end:
183
184 safe_addrs:
185         dc.l 0x000000, 0x7fffff
186         dc.l 0xe00000, 0xffffff
187         dc.l 0xa00000, 0xa163ff         /* FIXME */
188         /* TODO: VDP */
189 safe_addrs_end:
190
191 txt_edit:
192         .ascii  "- edit -\0"
193 txt_a_confirm:
194         .ascii  "A-confirm\0"
195 txt_about:
196         .ascii  "hexed r1\0"
197 txt_goto:
198         .ascii  "Go to address\0"
199 txt_goto_predef:
200         .ascii  "Go to (predef)\0"
201 txt_dtack:
202         .ascii  "DTACK safety\0"
203
204 ##################################################
205 #                                                #
206 #               MAIN PROGRAM                     #
207 #                                                #
208 ##################################################
209
210 # global regs:
211 # a6 = page_start[31:8]|cursor_offs[7:0]
212 # d7 = old_inputs[31:16]|edit_bytes[15:14]|g_mode_old[13:11]|g_mode[10:8]|irq_cnt[7:0]
213 # d6 = edit_word_save[31:15]|edit_done[7]|no_dtack_detect[4]|autorep_cnt[3:0]
214 # d5 = main: tmp
215 #      edit: edit_word[31:8]|edit_pos[4:2]|byte_cnt[1:0]
216 #      menu: sel
217
218 .align 2
219
220 main:
221         /* mask irqs during init */
222         move.w          #0x2700,sr
223
224 .if 0
225         /* copy */
226         lea             (0,pc),a0
227         move.l          a0,d0
228         swap            d0
229         lsr.l           #4,d0
230         and.b           #0x0f,d0
231         cmp.b           #0,d0
232         bne             0f
233
234         move.w          #8000/2,d0
235         move.l          #0,a0
236         move.l          #0x400000,a1
237 1:
238         move.w          (a0)+,(a1)+
239         dbra            d0,1b
240 0:
241 .endif
242
243         movea.l         #0,a6
244         move.l          #0x8000,d7
245         moveq.l         #0,d6
246
247         /* Init pads */
248         move.b          #0x40,(0xa10009).l
249         move.b          #0x40,(0xa10003).l
250
251         /* Initialize VDP */
252         jsr             init_gfx
253
254         /* Load color data */
255         movea.l         #0,a0
256         movea.l         #colors,a1
257         moveq.l         #(colors_end-colors)/2,d0
258         jsr             load_colors
259
260         /* load patterns */
261         movea.l         #0,a0
262         movea.l         #font,a1
263         move.l          #128,d0
264         jsr             load_tiles
265
266         /* generate A layer map */
267         movea.l         #0xe000,a1
268         move.l          #28-1,d4
269 lmaploop0:
270         movea.l         a1,a0
271         jsr             load_prepare
272
273         move.l          #64/2-1,d3
274 0:      move.l          #0x00000000,(a0)
275         dbra            d3,0b
276
277         add.l           #64*2,a1
278         dbra            d4,lmaploop0
279
280         /* generate B layer map */
281         movea.l         #0xc000,a0
282         jsr             load_prepare
283
284         move.l          #64*28/2-1,d3
285 0:      move.l          #0x00000000,(a0)
286         dbra            d3,0b
287
288         /* upload sprite data */
289         movea.l         #0xfc00,a0
290         jsr             load_prepare
291         movea.l         #sprite_data,a1
292
293         move.l          #(sprite_data_end-sprite_data)/2-1,d3
294 0:      move.l          (a1)+,(a0)
295         dbra            d3,0b
296
297         move.w          #0x2000,sr
298
299 ##################################################
300
301 forever:
302         jsr             wait_vsync
303         bra             forever
304
305
306 VBL:
307         addq.b          #1,d7
308         movem.l         d0-d4/a0-a5,-(a7)
309
310         moveq.l         #0,d0
311         move.w          d7,d0
312         lsr.w           #6,d0
313         and.w           #0x1c,d0
314         move.l          (jumptab,pc,d0),a0
315         jmp             (a0)
316 jumptab:
317         dc.l            mode_main
318         dc.l            mode_val_input
319         dc.l            mode_edit_val   /* edit val in editor */
320         dc.l            mode_goto
321         dc.l            mode_start_menu
322         dc.l            mode_goto_predef
323         dc.l            mode_main
324         dc.l            mode_main
325
326 ##################### main #######################
327
328 mode_main:
329         clr.l           d1
330         move.l          a6,d0
331         move.b          d0,d1
332         lsr.l           #8,d0
333         move.l          d0,a1           /* current addr */
334         lsr.b           #3,d1
335         neg.b           d1
336         add.b           #27-1,d1        /* line where the cursor sits */
337         swap            d1
338
339         movea.l         #0xe002,a2
340         move.l          #27-1,d5        /* line counter for dbra */
341         or.l            d1,d5
342
343 draw_row:
344         move.l          a2,a0
345         jsr             load_prepare
346
347         btst.l          #15,d7
348         beq             0f
349         move.w          #' ',(a0)
350 0:
351         /* addr */
352         move.l          a1,d2
353         moveq.l         #6,d3
354         jsr             print_hex_preped
355
356         btst.l          #4,d6
357         bne             draw_row_safe
358
359         bsr             is_addr_safe
360         bne             draw_row_safe
361
362 # draw unreadable areas
363         btst.l          #15,d7
364         bne             draw_row_unsafe_words
365
366 draw_row_unsafe_bytes:
367         /* 8 bytes */
368         moveq.l         #8-1,d4
369 0:
370         move.w          #' ',(a0)
371         move.l          #'?'|('?'<<16),(a0)
372         dbra            d4,0b
373
374         move.w          #' ',(a0)
375
376         move.l          d5,d0
377         swap            d0
378         cmp.w           d5,d0
379         beq             draw_cursor_unsafe_byte
380         bra             draw_chars_unsafe
381
382 draw_row_unsafe_words:
383         /* 4 shorts */
384         moveq.l         #4-1,d4
385 0:
386         move.w          #' ',(a0)
387         move.l          #'?'|('?'<<16),(a0)
388         move.l          #'?'|('?'<<16),(a0)
389         dbra            d4,0b
390
391         move.l          #(' '<<16)|' ',(a0)
392
393         move.l          d5,d0
394         swap            d0
395         cmp.w           d5,d0
396         beq             draw_cursor_unsafe_word
397
398 draw_chars_unsafe:
399         move.l          #'?'|('?'<<16),(a0)
400         move.l          #'?'|('?'<<16),(a0)
401         move.l          #'?'|('?'<<16),(a0)
402         move.l          #'?'|('?'<<16),(a0)
403
404         move.l          #(' '<<16)|' ',(a0)
405         addq.l          #8,a1
406         add.w           #0x80,a2
407         dbra            d5,draw_row
408         bra             draw_status_bar
409
410
411 # normal draw
412 draw_row_safe:
413         btst.l          #15,d7
414         bne             draw_row_words
415
416 draw_row_bytes:
417         /* 8 bytes */
418         moveq.l         #2,d3
419         moveq.l         #8-1,d4
420 draw_bytes:
421         move.w          #' ',(a0)
422         move.b          (a1)+,d2
423         jsr             print_hex_preped
424         dbra            d4,draw_bytes
425
426         move.w          #' ',(a0)
427
428         move.l          d5,d0
429         swap            d0
430         cmp.w           d5,d0
431         beq             draw_cursor_byte
432         bra             draw_chars_pre
433
434 draw_row_words:
435         /* 4 shorts */
436         moveq.l         #4,d3
437         moveq.l         #4-1,d4
438 draw_words:
439         move.w          #' ',(a0)
440         move.w          (a1)+,d2
441         jsr             print_hex_preped
442         dbra            d4,draw_words
443
444         move.l          #(' '<<16)|' ',(a0)
445
446         move.l          d5,d0
447         swap            d0
448         cmp.w           d5,d0
449         beq             draw_cursor_word
450
451 draw_chars_pre:
452         /* 8 chars */
453         subq.l          #8,a1
454         moveq.l         #8-1,d4
455 draw_chars:
456         move.b          (a1)+,d0
457         move.b          d0,d1
458         sub.b           #0x20,d1
459         cmp.b           #0x60,d1
460         blo             0f
461         move.w          #'.',d0
462 0:
463         move.w          d0,(a0)
464         dbra            d4,draw_chars
465
466         move.l          #(' '<<16)|' ',(a0)
467
468         add.w           #0x80,a2
469         dbra            d5,draw_row
470
471 draw_status_bar:
472         /* status bar */
473         move.l          a2,a0
474         jsr             load_prepare
475
476         btst.l          #15,d7
477         beq             0f
478         move.w          #' ',(a0)
479 0:
480         mk_a6_addr      d2
481         move.l          #0x4006,d3
482         jsr             print_hex_preped
483         move.w          #' ',(a0)
484
485         /* handle input */
486         jsr             get_input               /* x0cbrldu x1sa00du */
487
488         btst.l          #16+4,d0                /* A - scroll modifier */
489         beq             input_noa
490
491         do_dpad         16+0,  sub, #0x0800
492         do_dpad         16+1,  add, #0x0800
493         do_dpad         16+10, sub, #0xd800
494         do_dpad         16+11, add, #0xd800
495 input_noa:
496         moveq.l         #0,d1
497         move.w          d7,d1
498         lsr.w           #7,d1
499         lsr.w           #7,d1
500
501         do_dpad         0,  subq, #0x0008
502         do_dpad         1,  addq, #0x0008
503         do_dpad         10, sub, d1
504         do_dpad         11, add, d1
505
506 dpad_end:
507         /* update addr */
508         move.l          a6,d1
509         cmp.b           #0xf0,d1
510         blo             0f
511         sub.l           #0xd800,a6
512         add.w           #0x00d8,a6
513         bra             1f
514 0:
515         cmp.b           #0xd8,d1
516         blo             1f
517         add.l           #0xd800,a6
518         sub.w           #0x00d8,a6
519 1:
520
521         /* other btns */
522         moveq.l         #0,d1
523         btst.l          #12,d0                  /* B - switch byte/word mode */
524         beq             input_nob
525         bclr.l          #15,d7
526         add.w           #0x4000,d7              /* changes between 01 10 */
527         move.l          a6,d1
528         and.l           #1,d1
529         sub.l           d1,a6                   /* make even, just in case */
530
531 input_nob:
532         btst.l          #13,d0                  /* C - edit selected byte */
533         beq             input_noc
534
535         change_mode     MMODE_EDIT_VAL, MMODE_MAIN
536         write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
537
538 input_noc:
539         btst.l          #5,d0                   /* Start - menu */
540         beq             input_nos
541
542         moveq.l         #0,d5
543         change_mode     MMODE_START_MENU, MMODE_MAIN
544         write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
545
546 input_nos:
547 vbl_end:
548         movem.l         (a7)+,d0-d4/a0-a5
549         rte
550
551
552 draw_cursor_unsafe_byte:
553         move.l          a6,d0
554         and.l           #7,d0           /* byte offs */
555         move.b          d0,d1
556         add.b           d0,d0
557         add.b           d1,d0           /* d0 *= 3 (chars) */
558         add.b           d0,d0
559         lea             (7*2,a2,d0),a0
560         jsr             load_prepare
561         move.l          #(0x2000|'?'|((0x2000|'?')<<16)),(a0)
562
563         move.l          a2,a0
564         add.w           #31*2,a0
565         jsr             load_prepare    /* restore a0 */
566         jmp             draw_chars_unsafe
567
568 draw_cursor_unsafe_word:
569         move.l          a6,d0
570         and.l           #7,d0           /* byte offs */
571         move.l          d0,d1
572         lsr.b           #1,d1           /* which word */
573         move.b          d1,d2
574         lsl.b           #2,d2
575         add.b           d2,d1           /* num of chars to skip */
576         add.b           d1,d1
577
578         lea             (8*2,a2,d1),a0
579         jsr             load_prepare
580         move.l          #(0x2000|'?'|((0x2000|'?')<<16)),d0
581         move.l          d0,(a0)
582         move.l          d0,(a0)
583
584         move.l          a2,a0
585         add.w           #29*2,a0
586         jsr             load_prepare    /* restore a0 */
587         jmp             draw_chars_unsafe
588
589
590 draw_cursor_byte:
591         move.l          a6,d0
592         and.l           #7,d0           /* byte offs */
593         move.w          #0x2002,d3
594
595         move.b          (-8,a1,d0),d2
596         move.b          d0,d1
597         add.b           d0,d0
598         add.b           d1,d0           /* d0 *= 3 (chars) */
599         add.b           d0,d0
600         lea             (7*2,a2,d0),a0
601         jsr             load_prepare
602         jsr             print_hex_preped
603
604         move.l          a2,a0
605         add.w           #31*2,a0
606         jsr             load_prepare    /* restore a0 */
607
608         jmp             draw_chars_pre
609
610 draw_cursor_word:
611         move.l          a6,d0
612         and.l           #7,d0           /* byte offs */
613         move.l          d0,d1
614         lsr.b           #1,d1           /* which word */
615         move.b          d1,d2
616         lsl.b           #2,d2
617         add.b           d2,d1           /* num of chars to skip */
618         add.b           d1,d1
619         move.w          #0x2004,d3
620
621         move.w          (-8,a1,d0),d2
622         lea             (8*2,a2,d1),a0
623         jsr             load_prepare
624         jsr             print_hex_preped
625
626         move.l          a2,a0
627         add.w           #29*2,a0
628         jsr             load_prepare    /* restore a0 */
629
630         jmp             draw_chars_pre
631
632
633 #################### hedit #######################
634
635 mode_edit_val:
636         btst.l          #7,d6
637         bne             mode_hedit_finish
638
639         /* read val to edit */
640         moveq.l         #0,d5
641         mk_a6_addr      d1
642         move.l          d1,a0
643         btst.l          #15,d7
644         bne             0f
645         move.b          (a0),d5
646         lsl.l           #8,d5
647         or.b            #1,d5
648         bra             1f
649 0:
650         move.w          (a0),d5
651         lsl.l           #8,d5
652         or.b            #2,d5
653 1:
654
655         change_mode     MMODE_VAL_INPUT, MMODE_EDIT_VAL
656         jmp             vbl_end
657
658 mode_hedit_finish:
659         /* write the val */
660         mk_a6_addr      d1
661         move.l          d1,a0
662         lsr.l           #8,d5
663
664         btst.l          #15,d7
665         bne             0f
666         move.b          d5,(a0)
667         bra             1f
668 0:
669         move.w          d5,(a0)
670 1:
671
672         bra             return_to_main
673
674 ##################### goto #######################
675
676 mode_goto:
677         btst.l          #7,d6
678         bne             mode_goto_finish
679
680         moveq.l         #0,d5
681         swap            d6
682         move.w          d6,d5
683         swap            d6
684         swap            d5
685         or.b            #3,d5           /* 3 bytes */
686         bclr.l          #7,d6
687         change_mode     MMODE_VAL_INPUT, MMODE_GOTO
688         jmp             vbl_end
689
690 mode_goto_finish:
691         lsr.l           #8,d5
692         move.l          d5,d0
693         move.l          d0,d1
694         and.l           #7,d1
695         and.b           #0xf8,d0
696         lsl.l           #8,d0
697         or.l            d1,d0
698         move.l          d0,a6
699
700         lsr.l           #8,d5
701         swap            d6
702         move.w          d5,d6
703         swap            d6
704
705         bra             return_to_main
706
707 ################### val edit #####################
708
709 mode_val_input:
710         /* frame */
711         movea.l         #0xe000+14*2+11*64*2,a1
712         moveq.l         #6-1,d1
713 0:
714         move.w          a1,a0
715         jsr             load_prepare
716         moveq.l         #11-1,d0
717 1:
718         move.w          #0,(a0)
719         dbra            d0,1b
720
721         add.w           #64*2,a1
722         dbra            d1,0b
723
724         /* text */
725         lea             txt_edit,a0
726         move.l          #15,d0
727         move.l          #11,d1
728         move.l          #0xc000,d2
729         jsr             print
730
731         lea             txt_a_confirm,a0
732         move.l          #15,d0
733         move.l          #15,d1
734         move.l          #0xc000,d2
735         jsr             print
736
737         /* edit field */
738         moveq.l         #0,d0
739         moveq.l         #0,d1
740         moveq.l         #0,d3
741         move.b          d5,d3
742         and.b           #3,d3           /* edit field bytes */
743
744         move.b          #19,d0
745         sub.b           d3,d0
746         move.b          #13,d1
747         move.l          d5,d2
748         lsr.l           #8,d2
749         add.b           d3,d3
750         or.w            #0x8000,d3
751         jsr             print_hex
752
753         /* current char */
754         moveq.l         #0,d0
755         moveq.l         #0,d1
756
757         and.w           #6,d3
758         move.b          #19,d0
759         move.b          d3,d1
760         lsr.b           #1,d1           /* length in bytes */
761         sub.b           d1,d0
762         move.b          d5,d1
763         lsr.b           #2,d1
764         and.b           #7,d1           /* nibble to edit */
765         add.b           d1,d0
766
767         sub.b           d1,d3
768         sub.b           #1,d3           /* chars to shift out */
769         lsl.b           #2,d3
770         add.b           #8,d3
771         move.l          d5,d2
772         lsr.l           d3,d2
773
774         move.b          #13,d1
775         move.w          #0xa001,d3
776         jsr             print_hex
777
778         /* handle input */
779         jsr             get_input       /* x0cbrldu x1sa00du */
780
781         move.w          d0,d1
782         and.w           #0x0f00,d1
783         beq             ai_no_dpad
784         move.b          d5,d1
785         and.b           #3,d1
786         add.b           d1,d1           /* nibble count */
787         sub.b           #1,d1           /* max n.t.e. val */
788         move.b          d5,d2
789         lsr.b           #2,d2
790         and.b           #7,d2           /* nibble to edit */
791
792         move.b          d0,d3
793         and.b           #3,d3
794         beq             ai_no_ud
795         moveq.l         #0,d3
796         moveq.l         #0,d4
797         move.b          #0xf,d3
798         move.b          #0x1,d4
799         sub.b           d2,d1
800         lsl.b           #2,d1
801         add.b           #8,d1
802         lsl.l           d1,d3           /* mask */
803         lsl.l           d1,d4           /* what to add/sub */
804         move.l          d5,d1
805         and.l           d3,d1
806         btst.l          #8,d0
807         beq             0f
808         add.l           d4,d1
809         bra             1f
810 0:
811         sub.l           d4,d1
812 1:
813         and.l           d3,d1
814         eor.l           #0xffffffff,d3
815         and.l           d3,d5
816         or.l            d1,d5
817         jmp             vbl_end
818
819 ai_no_ud:
820         btst.l          #10,d0
821         bne             0f
822         add.b           #1,d2
823         bra             1f
824 0:
825         sub.b           #1,d2
826 1:
827         cmp.b           #0,d2
828         bge             0f
829         move.b          d1,d2
830 0:
831         cmp.b           d1,d2
832         ble             0f
833         move.b          #0,d2
834 0:
835         and.b           #0xe3,d5
836         lsl.b           #2,d2
837         or.b            d2,d5
838         jmp             vbl_end
839
840 ai_no_dpad:
841         move.w          d0,d1
842         and.w           #0x1020,d1
843         beq             ai_no_sb
844
845         bra             return_to_main
846
847 ai_no_sb:
848         btst.l          #4,d0           /* A - confirm */
849         beq             ai_no_input
850         bset.l          #7,d6
851         move.w          d7,d1           /* back to prev mode */
852         and.w           #0x3800,d1
853         lsr.w           #3,d1
854         and.w           #0xc0ff,d7
855         or.w            d1,d7
856
857 ai_no_input:
858         jmp             vbl_end
859
860
861 ################### start menu ###################
862
863 mode_start_menu:
864         /* frame */
865         bsr             start_menu_box
866
867         /* text */
868         menu_text       txt_about,       13,  9, 1
869         menu_text       txt_goto,        13, 11, 0
870         menu_text       txt_goto_predef, 13, 12, 0
871         menu_text       txt_dtack,       13, 13, 0
872         menu_text       txt_a_confirm,   13, 15, 2
873
874         /* dtack safety on/off */
875         movea.l         #0xe000+26*2+13*64*2,a0
876         jsr             load_prepare
877         move.w          #0x8000|'O',(a0)
878         btst.l          #4,d6
879         bne             0f
880         move.w          #0x8000|'N',(a0)
881         bra             1f
882 0:
883         move.w          #0x8000|'F',(a0)
884         move.w          #0x8000|'F',(a0)
885 1:
886
887         /* cursor */
888         movea.l         #0xe000+11*2+11*64*2,a0
889         moveq.l         #0,d0
890         move.b          d5,d0
891         and.b           #3,d0
892         lsl.w           #7,d0
893         add.w           d0,a0
894         jsr             load_prepare
895         move.w          #'>',(a0)
896
897         /* input */
898         jsr             get_input       /* x0cbrldu x1sa00du */
899
900         move.w          d0,d1
901         and.w           #3,d1
902         beq             msm_no_ud
903         move.b          d5,d1
904         and.b           #3,d1
905         btst.l          #0,d0
906         sne             d2
907         or.b            #1,d2           /* up -1, down 1 */
908         add.b           d2,d1
909         cmp.b           #0,d1
910         bge             0f
911         move.b          #2,d1
912 0:
913         cmp.b           #2,d1
914         ble             0f
915         move.b          #0,d1
916 0:
917         and.b           #0xfc,d5
918         or.b            d1,d5
919         jmp             vbl_end
920
921 msm_no_ud:
922         btst.l          #4,d0           /* A - confirm */
923         beq             msm_no_a
924         move.b          d5,d1
925         and.b           #3,d1
926         bne             0f
927         change_mode     MMODE_GOTO, MMODE_MAIN
928         bsr             start_menu_box
929         jmp             vbl_end
930 0:
931         cmp.b           #1,d1
932         bne             0f
933         moveq.l         #0,d5
934         change_mode     MMODE_GOTO_PREDEF, MMODE_MAIN
935         bsr             start_menu_box
936         jmp             vbl_end
937 0:
938         cmp.b           #2,d1
939         bne             0f
940         bchg.l          #4,d6
941         jmp             vbl_end
942 0:
943
944 msm_no_a:
945         move.w          d0,d1
946         and.w           #0x3000,d1
947         beq             msm_no_bc
948         bra             return_to_main
949
950 msm_no_bc:
951         jmp             vbl_end
952
953 start_menu_box:
954         movea.l         #0xe000+10*2+8*64*2,a1
955         move.w          #9-1,d1
956 0:
957         move.w          a1,a0
958         jsr             load_prepare
959         move.w          #20-1,d0
960 1:
961         move.w          #0,(a0)
962         dbra            d0,1b
963
964         add.w           #64*2,a1
965         dbra            d1,0b
966         rts
967
968 ################### goto predef ##################
969
970 mode_goto_predef:
971         /* frame */
972         movea.l         #0xe000+14*2+8*64*2,a1
973         move.l          #predef_addr_cnt+2-1,d1
974 0:
975         move.w          a1,a0
976         jsr             load_prepare
977         moveq.l         #10-1,d0
978 1:
979         move.w          #0,(a0)
980         dbra            d0,1b
981
982         add.w           #64*2,a1
983         dbra            d1,0b
984
985         /* draw addresses */
986         movea.l         #0xe000+17*2+9*64*2,a1
987         lea             predef_addrs,a2
988         move.w          #predef_addr_cnt-1,d4
989         move.l          #0x8006,d3
990 mgp_da_loop:
991         move.w          a1,a0
992         jsr             load_prepare
993         move.l          (a2)+,d2
994         jsr             print_hex_preped
995         add.w           #64*2,a1
996         dbra            d4,mgp_da_loop
997
998         /* cursor */
999         movea.l         #0xe000+15*2+9*64*2,a0
1000         moveq.l         #0,d0
1001         move.b          d5,d0
1002         lsl.w           #7,d0
1003         add.w           d0,a0
1004         jsr             load_prepare
1005         move.w          #'>',(a0)
1006
1007         /* input */
1008         jsr             get_input       /* x0cbrldu x1sa00du */
1009
1010         move.w          d0,d1
1011         and.w           #3,d1
1012         beq             mgp_no_ud
1013         btst.l          #0,d0
1014         sne             d2
1015         or.b            #1,d2           /* up -1, down 1 */
1016         add.b           d2,d5
1017         cmp.b           #0,d5
1018         bge             0f
1019         move.b          #predef_addr_cnt-1,d5
1020 0:
1021         cmp.b           #predef_addr_cnt-1,d5
1022         ble             0f
1023         move.b          #0,d5
1024 0:
1025         jmp             vbl_end
1026
1027 mgp_no_ud:
1028         btst.l          #4,d0           /* A - confirm */
1029         beq             mgp_no_a
1030         moveq.l         #0,d0
1031         move.b          d5,d0
1032         lsl.w           #2,d0
1033         lea             predef_addrs,a0
1034         move.l          (a0,d0),d5
1035         lsl.l           #8,d5
1036         jmp             mode_goto_finish
1037
1038 mgp_no_a:
1039         move.w          d0,d1
1040         and.w           #0x3000,d1
1041         beq             mgp_no_bc
1042         bra             return_to_main
1043
1044 mgp_no_bc:
1045         jmp             vbl_end
1046
1047
1048 # go back to main mode
1049 return_to_main:
1050         bclr.l          #7,d6           /* not edited */
1051         change_mode     MMODE_MAIN, MMODE_MAIN
1052         write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320),(GFXCNTL)
1053         jmp             vbl_end
1054
1055
1056 #################################################
1057 #                                               #
1058 #         Initialize VDP registers              #
1059 #                                               #
1060 #################################################
1061
1062 init_gfx:
1063         move.l          #GFXCNTL,a3
1064         write_vdp_reg   0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
1065         write_vdp_reg   1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED)
1066         write_vdp_reg   2,(0xe000 >> 10)        /* Screen map a adress */
1067         write_vdp_reg   3,(0xe000 >> 10)        /* Window address */
1068         write_vdp_reg   4,(0xc000 >> 13)        /* Screen map b address */
1069         write_vdp_reg   5,(0xfc00 >>  9)        /* Sprite address */
1070         write_vdp_reg   6,0     
1071         write_vdp_reg   7,0                     /* Backdrop color */
1072         write_vdp_reg   10,1                    /* Lines per hblank interrupt */
1073         write_vdp_reg   11,0                    /* 2-cell vertical scrolling */
1074         write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
1075         write_vdp_reg   13,(0x8000 >> 10)       /* Horizontal scroll address */
1076         write_vdp_reg   15,2
1077         write_vdp_reg   16,(VDP16_MAP_V32 | VDP16_MAP_H64)      /* layer size */
1078         write_vdp_reg   17,0
1079         write_vdp_reg   18,0xff
1080         rts
1081
1082
1083 # determine if address packed in a6 is safe
1084 #  a1 - address to check
1085 #  destroys d0-d2, strips upper bits from a1
1086 is_addr_safe:
1087         move.l          a1,d1
1088         lsl.l           #8,d1
1089         lsr.l           #8,d1
1090         lea             safe_addrs,a1
1091         move.w          #(safe_addrs_end - safe_addrs)/8-1,d2
1092 0:
1093         move.l          (a1)+,d0
1094         cmp.l           d0,d1
1095         blt             1f
1096         move.l          (a1),d0
1097         cmp.l           d0,d1
1098         ble             addr_safe
1099 1:
1100         addq.l          #4,a1
1101         dbra            d2,0b
1102
1103 addr_unsafe:
1104         move.l          d1,a1
1105         moveq.l         #0,d0
1106         rts
1107
1108 addr_safe:
1109         move.l          d1,a1
1110         moveq.l         #1,d0
1111         rts
1112
1113
1114 # read single phase from controller
1115 #  #a0 - addr
1116 #  d0 - result
1117 #  destroys d1,d2
1118 get_input:
1119         move.b          #0x40,(0xa10003)
1120         nop
1121         nop
1122         nop
1123         move.b          (0xa10003),d0
1124         move.b          #0x00,(0xa10003)
1125         lsl.w           #8,d0
1126         nop
1127         move.b          (0xa10003),d0
1128         eor.w           #0xffff,d0
1129
1130         swap            d7
1131         move.w          d7,d1
1132         eor.w           d0,d1           /* changed btns */
1133         move.w          d0,d7           /* old val */
1134         swap            d7
1135         and.w           d0,d1           /* what changed now */
1136         bne             0f
1137
1138         addq.b          #1,d6
1139         move.b          d6,d2
1140         and.b           #0x0f,d2        /* do autorepeat */
1141         cmp.b           #9,d2
1142         bne             1f
1143         move.w          d0,d1
1144 0:
1145         and.b           #0xf0,d6
1146 1:
1147         swap            d0
1148         move.w          d1,d0
1149         rts
1150
1151 # Load tile data from ROM
1152 #  a0: VRAM base
1153 #  a1: pattern address
1154 #  d0: number of tiles to load
1155 #  destroys d1
1156
1157 load_tiles:
1158         move.l          d0,d1
1159         VRAM_ADDR_var   a0
1160         move.l          d0,(GFXCNTL).l
1161         
1162         move.l          #GFXDATA,a0
1163         lsl.w           #3,d1
1164         subq.l          #1,d1
1165 0:
1166         move.l          (a1)+,(a0)
1167         dbra            d1,0b
1168
1169         rts
1170
1171
1172 # Prepare to write to VDP RAM @a0
1173 # sets a0 to VDP data port for convenience
1174 #  a0: VRAM base
1175 #  destroys d0
1176
1177 load_prepare:
1178         VRAM_ADDR_var   a0
1179         move.l          d0,(GFXCNTL).l
1180         move.l          #GFXDATA,a0
1181         rts
1182
1183
1184 # Load color data from ROM
1185 #  a0: CRAM base
1186 #  a1: color list address
1187 #  d0: number of colors to load
1188 #  destroys d1
1189
1190 load_colors:
1191         move.l          d0,d1
1192         CRAM_ADDR_var   a0
1193         move.l          d0,(GFXCNTL).l
1194
1195         move.l          #GFXDATA,a0
1196         subq.w          #1,d1
1197 0:
1198         move.w          (a1)+,(a0)
1199         dbra            d1,0b
1200
1201         rts
1202
1203
1204 # print
1205 #  a0 - string
1206 #  d0 - x
1207 #  d1 - y 
1208 #  d2 - tile_bits[15:11]
1209 #  destroys a1
1210
1211 print:
1212         move.l          a0,a1
1213         XY2NT
1214         jsr             load_prepare
1215         move.l          d2,d0
1216         and.w           #0xf800,d0
1217
1218 _print_loop:
1219         move.b          (a1)+,d0
1220         beq             _print_end
1221
1222         move.w          d0,(a0)
1223         jmp             _print_loop
1224
1225 _print_end:
1226         rts
1227
1228
1229 # print_hex
1230 #  d0 - x
1231 #  d1 - y 
1232 #  d2 - value
1233 #  d3 - tile_bits[15:11]|digit_cnt[7:0]
1234 #  destroys a0, preserves d3
1235
1236 print_hex:
1237         XY2NT
1238         jsr             load_prepare
1239
1240 print_hex_preped:
1241         moveq.l         #0,d0
1242         move.b          d3,d0
1243         move.l          d0,d1
1244         lsl.b           #2,d0
1245         ror.l           d0,d2           /* prep value */
1246         subq.l          #1,d1           /* count */
1247         move.w          d3,d0
1248         and.w           #0xf800,d0      /* keep upper bits in d0 */
1249
1250 _print_hex_loop:
1251         rol.l           #4,d2
1252         move.b          d2,d0
1253         and.b           #0xf,d0
1254
1255         add.b           #'0',d0
1256         cmp.b           #'9',d0
1257         ble             0f
1258         addq.b          #7,d0
1259 0:
1260         move.w          d0,(a0)
1261         dbra            d1,_print_hex_loop
1262
1263         rts
1264
1265
1266 #################################################
1267 #                                               #
1268 #       Wait for next VBlank interrupt          #
1269 #                                               #
1270 #################################################
1271
1272 wait_vsync:
1273         move.b          d7,d0
1274 _wait_change:
1275         stop            #0x2000
1276         cmp.b           d7,d0
1277         beq             _wait_change
1278         rts
1279
1280
1281 #################################################
1282 #                                               #
1283 #                 RAM DATA                      #
1284 #                                               #
1285 #################################################
1286
1287 .bss
1288
1289 # nothing :)
1290
1291 .end
1292
1293 # vim:filetype=asmM68k