finalize for release
[megadrive.git] / hexed / hexed.s
1 ###############################################################################
2 #
3 # Copyright (c) 2009, GraÅžvydas Ignotas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #     * Redistributions of source code must retain the above copyright
9 #       notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above copyright
11 #       notice, this list of conditions and the following disclaimer in the
12 #       documentation and/or other materials provided with the distribution.
13 #     * Neither the name of the organization nor the
14 #       names of its contributors may be used to endorse or promote products
15 #       derived from this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 # DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #
28 # Assemble with gas
29 #   --register-prefix-optional --bitwise-or
30 #
31
32 .text
33 .globl main
34 .globl INT
35 .globl VBL
36
37 ##################################################
38 #                                                #
39 #        Register and bitmask definitions        #
40 #                                                #
41 ##################################################
42
43 .equ GFXDATA,           0xc00000
44 .equ GFXCNTL,           0xc00004
45
46 .equ VDP0_E_HBI,        0x10
47 .equ VDP0_E_DISPLAY,    0x02 
48 .equ VDP0_PLTT_FULL,    0x04 
49
50 .equ VDP1_SMS_MODE,     0x80
51 .equ VDP1_E_DISPLAY,    0x40
52 .equ VDP1_E_VBI,        0x20
53 .equ VDP1_E_DMA,        0x10
54 .equ VDP1_NTSC,         0x00
55 .equ VDP1_PAL,          0x08
56 .equ VDP1_MODE5,        0x04
57
58 .equ VDP12_STE,         0x08
59 .equ VDP12_SCREEN_V224, 0x00
60 .equ VDP12_SCREEN_V448, 0x04
61 .equ VDP12_PROGRESSIVE, 0x00
62 .equ VDP12_INTERLACED,  0x02
63 .equ VDP12_SCREEN_H256, 0x00
64 .equ VDP12_SCREEN_H320, 0x81
65
66 .equ VDP16_MAP_V32,     0x00
67 .equ VDP16_MAP_V64,     0x10
68 .equ VDP16_MAP_V128,    0x30
69 .equ VDP16_MAP_H32,     0x00
70 .equ VDP16_MAP_H64,     0x01
71 .equ VDP16_MAP_H128,    0x03
72
73 .equ MMODE_MAIN,        0
74 .equ MMODE_VAL_INPUT,   1
75 .equ MMODE_EDIT_VAL,    2
76 .equ MMODE_GOTO,        3
77 .equ MMODE_START_MENU,  4
78 .equ MMODE_GOTO_PREDEF, 5
79 .equ MMODE_JMP_ADDR,    6
80
81 .equ predef_addr_cnt,   ((predef_addrs_end-predef_addrs)/4)
82
83 ##################################################
84 #                                                #
85 #                   MACROS                       #
86 #                                                #
87 ##################################################
88
89
90 # Write val to VDP register reg
91 .macro write_vdp_r_dst reg val dst
92         move.w #((\reg << 8) + 0x8000 + \val),\dst
93 .endm
94
95 # Write val to VDP register reg, vdp addr in a3
96 .macro write_vdp_reg reg val
97         write_vdp_r_dst \reg, \val, (a3)
98 .endm
99
100 # Set up address in VDP, control port in dst
101 .macro VRAM_ADDR adr dst
102         move.l #(((0x4000 | (\adr & 0x3fff)) << 16) | (\adr >> 14)),\dst
103 .endm
104
105
106 # make VDP word from address adr and store in d0
107 .macro XRAM_ADDR_var adr
108         move.l \adr,d0
109         lsl.l #8,d0
110         lsl.l #8,d0
111         rol.l #2,d0
112         lsl.b #2,d0
113         lsr.l #2,d0
114 .endm
115
116
117 .macro VRAM_ADDR_var adr
118         XRAM_ADDR_var \adr
119         or.l #0x40000000,d0
120 .endm
121
122
123 .macro CRAM_ADDR_var adr
124         XRAM_ADDR_var \adr
125         or.l #0xc0000000,d0
126 .endm
127
128
129 # convert tile coords in d0, d1 to nametable addr to a0
130 .macro XY2NT
131         lsl.w           #6,d1
132         add.w           d1,d0
133         lsl.w           #1,d0
134         movea.l         #0xe000,a0
135         add.w           d0,a0
136 .endm
137
138 # check if some d-pad button (and modifier) is pressed
139 .macro do_dpad bit op val
140         btst.l          #\bit,d0
141         beq             0f
142         \op.l           \val,a6
143         bra             dpad_end
144 0:
145 .endm
146
147 # convert a6 to normal addr
148 #  destroys d0
149 .macro mk_a6_addr reg
150         move.l          a6,\reg
151         moveq.l         #0,d0
152         move.b          \reg,d0
153         lsr.l           #8,\reg
154         add.l           d0,\reg
155 .endm
156
157 .macro change_mode mode_new mode_back
158         and.w           #0xc0ff,d7
159         or.w            #(\mode_back<<11)|(\mode_new<<8),d7
160 .endm
161
162 .macro menu_text str x y pal
163         lea             \str,a0
164         move.l          #\x,d0
165         move.l          #\y,d1
166         move.l          #0x8000|(\pal<<13),d2
167         jsr             print
168 .endm
169
170 #################################################
171 #                                               #
172 #                    DATA                       #
173 #                                               #
174 #################################################
175
176 colors:
177         dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
178         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
179         dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
180         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
181         dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
182         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
183         dc.w 0x0000,0x044e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
184         dc.w    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
185 colors_end:
186
187
188 sprite_data:
189         /*         Y        size     link          attr        X */
190         dc.w       0;  dc.b 0x05;  dc.b 0;  dc.w 0x6002;  dc.w 0
191 sprite_data_end:
192
193 predef_addrs:
194         dc.l 0x000000, 0x200000, 0x400000, 0xa00000, 0xa10000
195         dc.l 0xa11100, 0xa12000, 0xa13000, 0xa14000, 0xc00000
196 predef_addrs_end:
197
198 safe_addrs:
199         dc.l 0x000000, 0x7fffff
200         dc.l 0xe00000, 0xffffff
201         dc.l 0xa00000, 0xa100ff
202         dc.l 0xa11000, 0xa113ff
203         dc.l 0xa12000, 0xa120ff
204         dc.l 0xa13000, 0xa130ff
205 safe_addrs_end:
206
207 txt_edit:
208         .ascii  "- edit -\0"
209 txt_a_confirm:
210         .ascii  "A-confirm\0"
211 txt_about:
212         .ascii  "hexed r1\0"
213 txt_goto:
214         .ascii  "Go to address\0"
215 txt_goto_predef:
216         .ascii  "Go to (predef)\0"
217 txt_jmp_addr:
218         .ascii  "Jump to address\0"
219 txt_dtack:
220         .ascii  "DTACK safety\0"
221 txt_dtack_err:
222         .ascii  "DTACK err?\0"
223 txt_exc:
224         .ascii  "Exception \0"
225
226 ##################################################
227 #                                                #
228 #               MAIN PROGRAM                     #
229 #                                                #
230 ##################################################
231
232 # global regs:
233 # a6 = page_start[31:8]|cursor_offs[7:0]
234 # d7 = old_inputs[31:16]|edit_bytes[15:14]|g_mode_old[13:11]|g_mode[10:8]|irq_cnt[7:0]
235 # d6 = edit_word_save[31:15]|edit_done[7]|no_dtack_detect[4]|autorep_cnt[3:0]
236 # d5 = main: tmp
237 #      edit: edit_word[31:8]|edit_pos[4:2]|byte_cnt[1:0]
238 #      menu: sel
239
240 .align 2
241
242 main:
243         /* mask irqs during init */
244         move.w          #0x2700,sr
245
246 .if 0
247         /* copy */
248         lea             (0,pc),a0
249         move.l          a0,d0
250         swap            d0
251         lsr.l           #4,d0
252         and.b           #0x0f,d0
253         cmp.b           #0,d0
254         bne             0f
255
256         move.w          #8000/2,d0
257         move.l          #0,a0
258         move.l          #0x400000,a1
259 1:
260         move.w          (a0)+,(a1)+
261         dbra            d0,1b
262 0:
263 .endif
264
265         movea.l         #0,a6
266         move.l          #0x8000,d7
267         moveq.l         #0,d6
268
269         /* Init pads */
270         move.b          #0x40,(0xa10009).l
271         move.b          #0x40,(0xa10003).l
272
273         /* Initialize VDP */
274         jsr             init_gfx
275
276         /* Load color data */
277         movea.l         #0,a0
278         movea.l         #colors,a1
279         moveq.l         #(colors_end-colors)/2,d0
280         jsr             load_colors
281
282         /* load font patterns */
283         lea             GFXDATA,a0
284         lea             font,a1
285         VRAM_ADDR       0,(GFXCNTL)
286         move.w          #128*8,d3
287 font_loop:
288         moveq.l         #8-1,d2
289         moveq.l         #0,d1
290         move.b          (a1)+,d0
291 0:
292         lsr.b           #1,d0
293         roxl.l          #1,d1
294         ror.l           #5,d1
295         dbra            d2,0b
296
297         rol.l           #1,d1           /* fixup */
298         move.l          d1,(a0)
299         dbra            d3,font_loop
300
301         /* generate A layer map */
302         movea.l         #0xe000,a1
303         move.l          #28-1,d4
304 lmaploop0:
305         movea.l         a1,a0
306         jsr             load_prepare
307
308         move.l          #64/2-1,d3
309 0:      move.l          #0x00000000,(a0)
310         dbra            d3,0b
311
312         add.l           #64*2,a1
313         dbra            d4,lmaploop0
314
315         /* generate B layer map */
316         movea.l         #0xc000,a0
317         jsr             load_prepare
318
319         move.l          #64*28/2-1,d3
320 0:      move.l          #0x00000000,(a0)
321         dbra            d3,0b
322
323         /* upload sprite data */
324         movea.l         #0xfc00,a0
325         jsr             load_prepare
326         movea.l         #sprite_data,a1
327
328         move.l          #(sprite_data_end-sprite_data)/2-1,d3
329 0:      move.l          (a1)+,(a0)
330         dbra            d3,0b
331
332         /* wait for vsync before unmask */
333         move.l          #GFXCNTL,a3
334 0:
335         move.w          (a3),d0
336         and.b           #8,d0
337         nop
338         nop
339         bne             0b
340 0:
341         move.w          (a3),d0
342         and.b           #8,d0
343         nop
344         nop
345         beq             0b
346
347         /* wait a bit to avoid nested vint */
348         move.w          #20,d0
349 0:
350         dbra            d0,0b           /* 10 cycles to go back */
351
352         /* enable vint */
353         move.w          #0x2000,sr
354
355 ##################################################
356
357 forever:
358         jsr             wait_vsync
359         bra             forever
360
361
362 INT:
363         /* let's hope VRAM is already set up.. */
364         lea             txt_exc,a0
365         move.l          #9,d0
366         move.l          #27,d1
367         move.l          #0xe000,d2
368         jsr             print
369         bra             forever
370
371 ##################################################
372
373 VBL:
374         addq.b          #1,d7
375 #       movem.l         d0-d4/a0-a5,-(a7)
376
377         moveq.l         #0,d0
378         move.w          d7,d0
379         lsr.w           #6,d0
380         and.w           #0x1c,d0
381         move.l          (jumptab,pc,d0),a0
382         jmp             (a0)
383 jumptab:
384         dc.l            mode_main
385         dc.l            mode_val_input
386         dc.l            mode_edit_val   /* edit val in editor */
387         dc.l            mode_goto
388         dc.l            mode_start_menu
389         dc.l            mode_goto_predef
390         dc.l            mode_jmp_addr
391         dc.l            mode_main
392
393 ##################### main #######################
394
395 mode_main:
396         /* assume we will hang */
397         lea             txt_dtack_err,a0
398         move.l          #9,d0
399         move.l          #27,d1
400         move.l          #0xe000,d2
401         jsr             print
402
403         moveq.l         #0,d1
404         move.l          a6,d0
405         move.b          d0,d1
406         lsr.l           #8,d0
407         move.l          d0,a1           /* current addr */
408         lsr.b           #3,d1
409         neg.b           d1
410         add.b           #27-1,d1        /* line where the cursor sits */
411         swap            d1
412
413         movea.l         #0xe002,a2
414         move.l          #27-1,d5        /* line counter for dbra */
415         or.l            d1,d5
416
417 draw_row:
418         move.l          a2,a0
419         jsr             load_prepare
420
421         btst.l          #15,d7
422         beq             0f
423         move.w          #' ',(a0)
424 0:
425         /* addr */
426         move.l          a1,d2
427         moveq.l         #6,d3
428         jsr             print_hex_preped
429
430         btst.l          #4,d6
431         bne             draw_row_safe
432
433         bsr             get_safety_mask
434         cmp.b           #0xf,d0
435         beq             draw_row_safe
436
437 # unsafe or partially safe
438 draw_row_hsafe:
439         move.l          d0,d4
440         swap            d4              /* mask in upper word */
441         btst.l          #15,d7
442         bne             draw_row_hsafe_words_pre
443
444 draw_row_hsafe_bytes_pre:
445         /* 8 bytes */
446         moveq.l         #2,d3
447         move.w          #3,d4
448
449 draw_row_hsafe_bytes:
450         move.w          #' ',(a0)
451         move.b          d4,d0
452         add.b           #16,d0
453         btst.l          d0,d4
454         bne             0f
455         move.l          #'?'|('?'<<16),(a0)
456         move.w          #' ',(a0)
457         move.l          #'?'|('?'<<16),(a0)
458         bra             1f
459 0:
460         move.b          (0,a1),d2
461         jsr             print_hex_preped
462         move.w          #' ',(a0)
463         move.b          (1,a1),d2
464         jsr             print_hex_preped
465 1:
466         addq.l          #2,a1
467         dbra            d4,draw_row_hsafe_bytes
468
469         move.w          #' ',(a0)
470
471         move.l          d5,d0
472         swap            d0
473         cmp.w           d5,d0
474         beq             draw_cursor_unsafe_byte
475         bra             draw_chars_hsafe_pre
476
477 draw_row_hsafe_words_pre:
478         /* 4 shorts */
479         moveq.l         #4,d3
480         move.w          #3,d4
481
482 draw_row_hsafe_words:
483         move.w          #' ',(a0)
484         move.b          d4,d0
485         add.b           #16,d0
486         btst.l          d0,d4
487         bne             0f
488         move.l          #'?'|('?'<<16),(a0)
489         move.l          #'?'|('?'<<16),(a0)
490         bra             1f
491 0:
492         move.w          (a1),d2
493         jsr             print_hex_preped
494 1:
495         addq.l          #2,a1
496         dbra            d4,draw_row_hsafe_words
497
498         move.l          #(' '<<16)|' ',(a0)
499
500         move.l          d5,d0
501         swap            d0
502         cmp.w           d5,d0
503         beq             draw_cursor_unsafe_word
504
505 draw_chars_hsafe_pre:
506         subq.l          #8,a1
507         move.w          #3,d4
508         moveq.l         #0,d0
509
510 draw_chars_hsafe:
511         move.b          d4,d0
512         add.b           #16,d0
513         btst.l          d0,d4
514         bne             0f
515         move.l          #'?'|('?'<<16),(a0)
516         bra             draw_chars_hsafe_next
517 0:
518         btst.l          #15,d7          /* must perform correct read type */
519         bne             0f              /* doing byte reads on security reg hangs */
520         move.b          (0,a1),d0
521         lsl.l           #8,d0
522         move.b          (1,a1),d0
523         bra             1f
524 0:
525         move.w          (a1),d0
526 1:
527         ror.l           #8,d0
528         move.b          d0,d1
529         sub.b           #0x20,d1
530         cmp.b           #0x60,d1
531         blo             0f
532         move.b          #'.',d0
533 0:
534         move.w          d0,(a0)
535
536         move.b          #0,d0
537         rol.l           #8,d0
538         move.b          d0,d1
539         sub.b           #0x20,d1
540         cmp.b           #0x60,d1
541         blo             0f
542         move.b          #'.',d0
543 0:
544         move.w          d0,(a0)
545
546 draw_chars_hsafe_next:
547         addq.l          #2,a1
548         dbra            d4,draw_chars_hsafe
549
550         move.l          #(' '<<16)|' ',(a0)
551         add.w           #0x80,a2
552         dbra            d5,draw_row
553         bra             draw_status_bar
554
555
556 # normal draw
557 draw_row_safe:
558         btst.l          #15,d7
559         bne             draw_row_words
560
561 draw_row_bytes:
562         /* 8 bytes */
563         moveq.l         #2,d3
564         moveq.l         #8-1,d4
565 draw_bytes:
566         move.w          #' ',(a0)
567         move.b          (a1)+,d2
568         jsr             print_hex_preped
569         dbra            d4,draw_bytes
570
571         move.w          #' ',(a0)
572
573         move.l          d5,d0
574         swap            d0
575         cmp.w           d5,d0
576         beq             draw_cursor_byte
577         bra             draw_chars_pre
578
579 draw_row_words:
580         /* 4 shorts */
581         moveq.l         #4,d3
582         moveq.l         #4-1,d4
583 draw_words:
584         move.w          #' ',(a0)
585         move.w          (a1)+,d2
586         jsr             print_hex_preped
587         dbra            d4,draw_words
588
589         move.l          #(' '<<16)|' ',(a0)
590
591         move.l          d5,d0
592         swap            d0
593         cmp.w           d5,d0
594         beq             draw_cursor_word
595
596 draw_chars_pre:
597         /* 8 chars */
598         subq.l          #8,a1
599         moveq.l         #8-1,d4
600 draw_chars:
601         move.b          (a1)+,d0
602         move.b          d0,d1
603         sub.b           #0x20,d1
604         cmp.b           #0x60,d1
605         blo             0f
606         move.w          #'.',d0
607 0:
608         move.w          d0,(a0)
609         dbra            d4,draw_chars
610
611         move.l          #(' '<<16)|' ',(a0)
612
613         add.w           #0x80,a2
614         dbra            d5,draw_row
615
616
617 draw_status_bar:
618         /* status bar */
619         move.l          a2,a0
620         jsr             load_prepare
621
622         btst.l          #15,d7
623         beq             0f
624         move.w          #' ',(a0)
625 0:
626         mk_a6_addr      d2
627         move.l          #0x4006,d3
628         jsr             print_hex_preped
629
630         /* clear error */
631         moveq.l         #5-1,d0
632 0:
633         move.l          #' '|(' '<<16),(a0)
634         move.l          #' '|(' '<<16),(a0)
635         dbra            d0,0b
636
637
638         /* handle input */
639         jsr             get_input               /* x0cbrldu x1sa00du */
640
641         btst.l          #16+4,d0                /* A - scroll modifier */
642         beq             input_noa
643
644         do_dpad         16+0,  sub, #0x0800
645         do_dpad         16+1,  add, #0x0800
646         do_dpad         16+10, sub, #0xd800
647         do_dpad         16+11, add, #0xd800
648 input_noa:
649         moveq.l         #0,d1
650         move.w          d7,d1
651         lsr.w           #7,d1
652         lsr.w           #7,d1
653
654         do_dpad         0,  subq, #0x0008
655         do_dpad         1,  addq, #0x0008
656         do_dpad         10, sub, d1
657         do_dpad         11, add, d1
658
659 dpad_end:
660         /* update addr */
661         move.l          a6,d1
662         cmp.b           #0xf0,d1
663         blo             0f
664         sub.l           #0xd800,a6
665         add.w           #0x00d8,a6
666         bra             1f
667 0:
668         cmp.b           #0xd8,d1
669         blo             1f
670         add.l           #0xd800,a6
671         sub.w           #0x00d8,a6
672 1:
673
674         /* other btns */
675         moveq.l         #0,d1
676         btst.l          #12,d0                  /* B - switch byte/word mode */
677         beq             input_nob
678         bclr.l          #15,d7
679         add.w           #0x4000,d7              /* changes between 01 10 */
680         move.l          a6,d1
681         and.l           #1,d1
682         sub.l           d1,a6                   /* make even, just in case */
683
684 input_nob:
685         btst.l          #13,d0                  /* C - edit selected byte */
686         beq             input_noc
687
688         change_mode     MMODE_EDIT_VAL, MMODE_MAIN
689         write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
690
691 input_noc:
692         btst.l          #5,d0                   /* Start - menu */
693         beq             input_nos
694
695         moveq.l         #0,d5
696         change_mode     MMODE_START_MENU, MMODE_MAIN
697         write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
698
699 input_nos:
700 vbl_end:
701 #       movem.l         (a7)+,d0-d4/a0-a5
702         rte
703
704
705 draw_cursor_unsafe_byte:
706         move.l          a6,d0
707         and.l           #7,d0           /* byte offs */
708         move.b          d0,d1
709         add.b           d0,d0
710         add.b           d1,d0           /* d0 *= 3 (chars) */
711         add.b           d0,d0
712         lea             (7*2,a2,d0),a0
713         jsr             load_prepare
714         move.l          #(0x2000|'?'|((0x2000|'?')<<16)),(a0)
715
716         move.l          a2,a0
717         add.w           #31*2,a0
718         jsr             load_prepare    /* restore a0 */
719         jmp             draw_chars_hsafe_pre
720
721 draw_cursor_unsafe_word:
722         move.l          a6,d0
723         and.l           #7,d0           /* byte offs */
724         move.l          d0,d1
725         lsr.b           #1,d1           /* which word */
726         move.b          d1,d2
727         lsl.b           #2,d2
728         add.b           d2,d1           /* num of chars to skip */
729         add.b           d1,d1
730
731         lea             (8*2,a2,d1),a0
732         jsr             load_prepare
733         move.l          #(0x2000|'?'|((0x2000|'?')<<16)),d0
734         move.l          d0,(a0)
735         move.l          d0,(a0)
736
737         move.l          a2,a0
738         add.w           #29*2,a0
739         jsr             load_prepare    /* restore a0 */
740         jmp             draw_chars_hsafe_pre
741
742
743 draw_cursor_byte:
744         move.l          a6,d0
745         and.l           #7,d0           /* byte offs */
746         move.w          #0x2002,d3
747
748         move.b          (-8,a1,d0),d2
749         move.b          d0,d1
750         add.b           d0,d0
751         add.b           d1,d0           /* d0 *= 3 (chars) */
752         add.b           d0,d0
753         lea             (7*2,a2,d0),a0
754         jsr             load_prepare
755         jsr             print_hex_preped
756
757         move.l          a2,a0
758         add.w           #31*2,a0
759         jsr             load_prepare    /* restore a0 */
760
761         jmp             draw_chars_pre
762
763 draw_cursor_word:
764         move.l          a6,d0
765         and.l           #7,d0           /* byte offs */
766         move.l          d0,d1
767         lsr.b           #1,d1           /* which word */
768         move.b          d1,d2
769         lsl.b           #2,d2
770         add.b           d2,d1           /* num of chars to skip */
771         add.b           d1,d1
772         move.w          #0x2004,d3
773
774         move.w          (-8,a1,d0),d2
775         lea             (8*2,a2,d1),a0
776         jsr             load_prepare
777         jsr             print_hex_preped
778
779         move.l          a2,a0
780         add.w           #29*2,a0
781         jsr             load_prepare    /* restore a0 */
782
783         jmp             draw_chars_pre
784
785
786 #################### hedit #######################
787
788 mode_edit_val:
789         btst.l          #7,d6
790         bne             mode_hedit_finish
791
792         /* read val to edit */
793         moveq.l         #0,d5
794         mk_a6_addr      d1
795         move.l          d1,a0
796         btst.l          #15,d7
797         bne             0f
798         move.b          (a0),d5
799         lsl.l           #8,d5
800         or.b            #1,d5
801         bra             1f
802 0:
803         move.w          (a0),d5
804         lsl.l           #8,d5
805         or.b            #2,d5
806 1:
807
808         change_mode     MMODE_VAL_INPUT, MMODE_EDIT_VAL
809         jmp             vbl_end
810
811 mode_hedit_finish:
812         /* write the val */
813         mk_a6_addr      d1
814         move.l          d1,a0
815         lsr.l           #8,d5
816
817         btst.l          #15,d7
818         bne             0f
819         move.b          d5,(a0)
820         bra             1f
821 0:
822         move.w          d5,(a0)
823 1:
824
825         bra             return_to_main
826
827 ##################### goto #######################
828
829 mode_goto:
830         btst.l          #7,d6
831         bne             mode_goto_finish
832
833         moveq.l         #0,d5
834         swap            d6
835         move.w          d6,d5
836         swap            d6
837         swap            d5
838         or.b            #3,d5           /* 3 bytes */
839         bclr.l          #7,d6
840         change_mode     MMODE_VAL_INPUT, MMODE_GOTO
841         jmp             vbl_end
842
843 mode_goto_finish:
844         lsr.l           #8,d5
845         move.l          d5,d0
846         move.l          d0,d1
847         and.l           #7,d1
848         and.b           #0xf8,d0
849         lsl.l           #8,d0
850         or.l            d1,d0
851         move.l          d0,a6
852
853         lsr.l           #8,d5
854         swap            d6
855         move.w          d5,d6
856         swap            d6
857
858         bra             return_to_main
859
860 ################### val edit #####################
861
862 mode_val_input:
863         /* frame */
864         movea.l         #0xe000+14*2+11*64*2,a1
865         moveq.l         #6-1,d1
866 0:
867         move.w          a1,a0
868         jsr             load_prepare
869         moveq.l         #11-1,d0
870 1:
871         move.w          #0,(a0)
872         dbra            d0,1b
873
874         add.w           #64*2,a1
875         dbra            d1,0b
876
877         /* text */
878         lea             txt_edit,a0
879         move.l          #15,d0
880         move.l          #11,d1
881         move.l          #0xc000,d2
882         jsr             print
883
884         lea             txt_a_confirm,a0
885         move.l          #15,d0
886         move.l          #15,d1
887         move.l          #0xc000,d2
888         jsr             print
889
890         /* edit field */
891         moveq.l         #0,d0
892         moveq.l         #0,d1
893         moveq.l         #0,d3
894         move.b          d5,d3
895         and.b           #3,d3           /* edit field bytes */
896
897         move.b          #19,d0
898         sub.b           d3,d0
899         move.b          #13,d1
900         move.l          d5,d2
901         lsr.l           #8,d2
902         add.b           d3,d3
903         or.w            #0x8000,d3
904         jsr             print_hex
905
906         /* current char */
907         moveq.l         #0,d0
908         moveq.l         #0,d1
909
910         and.w           #6,d3
911         move.b          #19,d0
912         move.b          d3,d1
913         lsr.b           #1,d1           /* length in bytes */
914         sub.b           d1,d0
915         move.b          d5,d1
916         lsr.b           #2,d1
917         and.b           #7,d1           /* nibble to edit */
918         add.b           d1,d0
919
920         sub.b           d1,d3
921         sub.b           #1,d3           /* chars to shift out */
922         lsl.b           #2,d3
923         add.b           #8,d3
924         move.l          d5,d2
925         lsr.l           d3,d2
926
927         move.b          #13,d1
928         move.w          #0xa001,d3
929         jsr             print_hex
930
931         /* handle input */
932         jsr             get_input       /* x0cbrldu x1sa00du */
933
934         move.w          d0,d1
935         and.w           #0x0f00,d1
936         beq             ai_no_dpad
937         move.b          d5,d1
938         and.b           #3,d1
939         add.b           d1,d1           /* nibble count */
940         sub.b           #1,d1           /* max n.t.e. val */
941         move.b          d5,d2
942         lsr.b           #2,d2
943         and.b           #7,d2           /* nibble to edit */
944
945         move.b          d0,d3
946         and.b           #3,d3
947         beq             ai_no_ud
948         moveq.l         #0,d3
949         moveq.l         #0,d4
950         move.b          #0xf,d3
951         move.b          #0x1,d4
952         sub.b           d2,d1
953         lsl.b           #2,d1
954         add.b           #8,d1
955         lsl.l           d1,d3           /* mask */
956         lsl.l           d1,d4           /* what to add/sub */
957         move.l          d5,d1
958         and.l           d3,d1
959         btst.l          #8,d0
960         beq             0f
961         add.l           d4,d1
962         bra             1f
963 0:
964         sub.l           d4,d1
965 1:
966         and.l           d3,d1
967         eor.l           #0xffffffff,d3
968         and.l           d3,d5
969         or.l            d1,d5
970         jmp             vbl_end
971
972 ai_no_ud:
973         btst.l          #10,d0
974         bne             0f
975         add.b           #1,d2
976         bra             1f
977 0:
978         sub.b           #1,d2
979 1:
980         cmp.b           #0,d2
981         bge             0f
982         move.b          d1,d2
983 0:
984         cmp.b           d1,d2
985         ble             0f
986         move.b          #0,d2
987 0:
988         and.b           #0xe3,d5
989         lsl.b           #2,d2
990         or.b            d2,d5
991         jmp             vbl_end
992
993 ai_no_dpad:
994         move.w          d0,d1
995         and.w           #0x1020,d1
996         beq             ai_no_sb
997
998         bra             return_to_main
999
1000 ai_no_sb:
1001         btst.l          #4,d0           /* A - confirm */
1002         beq             ai_no_input
1003         bset.l          #7,d6
1004         move.w          d7,d1           /* back to prev mode */
1005         and.w           #0x3800,d1
1006         lsr.w           #3,d1
1007         and.w           #0xc0ff,d7
1008         or.w            d1,d7
1009
1010 ai_no_input:
1011         jmp             vbl_end
1012
1013
1014 ################### start menu ###################
1015
1016 mode_start_menu:
1017         /* frame */
1018         bsr             start_menu_box
1019
1020         /* text */
1021         menu_text       txt_about,       13,  9, 1
1022         menu_text       txt_goto,        13, 11, 0
1023         menu_text       txt_goto_predef, 13, 12, 0
1024         menu_text       txt_jmp_addr,    13, 13, 0
1025         menu_text       txt_dtack,       13, 14, 0
1026         menu_text       txt_a_confirm,   13, 16, 2
1027
1028         /* dtack safety on/off */
1029         movea.l         #0xe000+26*2+14*64*2,a0
1030         jsr             load_prepare
1031         move.w          #0x8000|'O',(a0)
1032         btst.l          #4,d6
1033         bne             0f
1034         move.w          #0x8000|'N',(a0)
1035         bra             1f
1036 0:
1037         move.w          #0x8000|'F',(a0)
1038         move.w          #0x8000|'F',(a0)
1039 1:
1040
1041         /* cursor */
1042         movea.l         #0xe000+11*2+11*64*2,a0
1043         moveq.l         #0,d0
1044         move.b          d5,d0
1045         and.b           #3,d0
1046         lsl.w           #7,d0
1047         add.w           d0,a0
1048         jsr             load_prepare
1049         move.w          #'>',(a0)
1050
1051         /* input */
1052         jsr             get_input       /* x0cbrldu x1sa00du */
1053
1054         move.w          d0,d1
1055         and.w           #3,d1
1056         beq             msm_no_ud
1057         move.b          d5,d1
1058         and.b           #3,d1
1059         btst.l          #0,d0
1060         sne             d2
1061         or.b            #1,d2           /* up -1, down 1 */
1062         add.b           d2,d1
1063         cmp.b           #0,d1
1064         bge             0f
1065         move.b          #3,d1
1066 0:
1067         cmp.b           #3,d1
1068         ble             0f
1069         move.b          #0,d1
1070 0:
1071         and.b           #0xfc,d5
1072         or.b            d1,d5
1073         jmp             vbl_end
1074
1075 msm_no_ud:
1076         btst.l          #4,d0           /* A - confirm */
1077         beq             msm_no_a
1078         move.b          d5,d1
1079         and.b           #3,d1
1080         bne             0f
1081         change_mode     MMODE_GOTO, MMODE_MAIN
1082         bsr             start_menu_box
1083         jmp             vbl_end
1084 0:
1085         cmp.b           #1,d1
1086         bne             0f
1087         moveq.l         #0,d5
1088         change_mode     MMODE_GOTO_PREDEF, MMODE_MAIN
1089         bsr             start_menu_box
1090         jmp             vbl_end
1091 0:
1092         cmp.b           #2,d1
1093         bne             0f
1094         change_mode     MMODE_JMP_ADDR, MMODE_MAIN
1095         bsr             start_menu_box
1096         jmp             vbl_end
1097 0:
1098         cmp.b           #3,d1
1099         bne             0f
1100         bchg.l          #4,d6
1101         jmp             vbl_end
1102 0:
1103
1104 msm_no_a:
1105         move.w          d0,d1
1106         and.w           #0x3000,d1
1107         beq             msm_no_bc
1108         bra             return_to_main
1109
1110 msm_no_bc:
1111         jmp             vbl_end
1112
1113 start_menu_box:
1114         movea.l         #0xe000+10*2+8*64*2,a1
1115         move.w          #10-1,d1
1116 0:
1117         move.w          a1,a0
1118         jsr             load_prepare
1119         move.w          #20-1,d0
1120 1:
1121         move.w          #0,(a0)
1122         dbra            d0,1b
1123
1124         add.w           #64*2,a1
1125         dbra            d1,0b
1126         rts
1127
1128 ################### goto predef ##################
1129
1130 mode_goto_predef:
1131         /* frame */
1132         movea.l         #0xe000+14*2+8*64*2,a1
1133         move.l          #predef_addr_cnt+2-1,d1
1134 0:
1135         move.w          a1,a0
1136         jsr             load_prepare
1137         moveq.l         #10-1,d0
1138 1:
1139         move.w          #0,(a0)
1140         dbra            d0,1b
1141
1142         add.w           #64*2,a1
1143         dbra            d1,0b
1144
1145         /* draw addresses */
1146         movea.l         #0xe000+17*2+9*64*2,a1
1147         lea             predef_addrs,a2
1148         move.w          #predef_addr_cnt-1,d4
1149         move.l          #0x8006,d3
1150 mgp_da_loop:
1151         move.w          a1,a0
1152         jsr             load_prepare
1153         move.l          (a2)+,d2
1154         jsr             print_hex_preped
1155         add.w           #64*2,a1
1156         dbra            d4,mgp_da_loop
1157
1158         /* cursor */
1159         movea.l         #0xe000+15*2+9*64*2,a0
1160         moveq.l         #0,d0
1161         move.b          d5,d0
1162         lsl.w           #7,d0
1163         add.w           d0,a0
1164         jsr             load_prepare
1165         move.w          #'>',(a0)
1166
1167         /* input */
1168         jsr             get_input       /* x0cbrldu x1sa00du */
1169
1170         move.w          d0,d1
1171         and.w           #3,d1
1172         beq             mgp_no_ud
1173         btst.l          #0,d0
1174         sne             d2
1175         or.b            #1,d2           /* up -1, down 1 */
1176         add.b           d2,d5
1177         cmp.b           #0,d5
1178         bge             0f
1179         move.b          #predef_addr_cnt-1,d5
1180 0:
1181         cmp.b           #predef_addr_cnt-1,d5
1182         ble             0f
1183         move.b          #0,d5
1184 0:
1185         jmp             vbl_end
1186
1187 mgp_no_ud:
1188         btst.l          #4,d0           /* A - confirm */
1189         beq             mgp_no_a
1190         moveq.l         #0,d0
1191         move.b          d5,d0
1192         lsl.w           #2,d0
1193         lea             predef_addrs,a0
1194         move.l          (a0,d0),d5
1195         lsl.l           #8,d5
1196         jmp             mode_goto_finish
1197
1198 mgp_no_a:
1199         move.w          d0,d1
1200         and.w           #0x3000,d1
1201         beq             mgp_no_bc
1202         bra             return_to_main
1203
1204 mgp_no_bc:
1205         jmp             vbl_end
1206
1207 ##################### jmp ########################
1208
1209 mode_jmp_addr:
1210         btst.l          #7,d6
1211         bne             mode_jmp_finish
1212
1213         moveq.l         #0,d5
1214         or.b            #3,d5           /* 3 bytes */
1215         bclr.l          #7,d6
1216         change_mode     MMODE_VAL_INPUT, MMODE_JMP_ADDR
1217         jmp             vbl_end
1218
1219 mode_jmp_finish:
1220         lsr.l           #8,d5
1221         write_vdp_r_dst 1,(VDP1_E_DISPLAY | VDP1_MODE5),(GFXCNTL)       /* disable vint */
1222         move.l          d5,a0
1223         jmp             (a0)
1224
1225
1226 # go back to main mode
1227 return_to_main:
1228         bclr.l          #7,d6           /* not edited */
1229         change_mode     MMODE_MAIN, MMODE_MAIN
1230         write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320),(GFXCNTL)
1231         jmp             vbl_end
1232
1233
1234 #################################################
1235 #                                               #
1236 #         Initialize VDP registers              #
1237 #                                               #
1238 #################################################
1239
1240 init_gfx:
1241         move.l          #GFXCNTL,a3
1242         write_vdp_reg   0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
1243         write_vdp_reg   1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_MODE5)
1244         write_vdp_reg   2,(0xe000 >> 10)        /* Screen map a adress */
1245         write_vdp_reg   3,(0xe000 >> 10)        /* Window address */
1246         write_vdp_reg   4,(0xc000 >> 13)        /* Screen map b address */
1247         write_vdp_reg   5,(0xfc00 >>  9)        /* Sprite address */
1248         write_vdp_reg   6,0     
1249         write_vdp_reg   7,0                     /* Backdrop color */
1250         write_vdp_reg   10,1                    /* Lines per hblank interrupt */
1251         write_vdp_reg   11,0                    /* 2-cell vertical scrolling */
1252         write_vdp_reg   12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
1253         write_vdp_reg   13,(0x8000 >> 10)       /* Horizontal scroll address */
1254         write_vdp_reg   15,2
1255         write_vdp_reg   16,(VDP16_MAP_V32 | VDP16_MAP_H64)      /* layer size */
1256         write_vdp_reg   17,0
1257         write_vdp_reg   18,0xff
1258         rts
1259
1260
1261 # get mask of bits representing safe words
1262 #  a1 - address to check
1263 #  destroys d0-d2, strips upper bits from a1
1264 get_safety_mask:
1265         move.l          a1,d1
1266         lsl.l           #8,d1
1267         lsr.l           #8,d1
1268         lea             safe_addrs,a1
1269         move.w          #(safe_addrs_end - safe_addrs)/8-1,d2
1270 0:
1271         move.l          (a1)+,d0
1272         cmp.l           d0,d1
1273         blt             1f
1274         move.l          (a1),d0
1275         cmp.l           d0,d1
1276         ble             addr_safe
1277 1:
1278         addq.l          #4,a1
1279         dbra            d2,0b
1280
1281         move.l          d1,a1
1282
1283         moveq.l         #0x0c,d0
1284         cmp.l           #0xa14000,d1
1285         beq             gsm_rts
1286
1287         moveq.l         #0x08,d0
1288         cmp.l           #0xa14100,d1
1289         beq             gsm_rts
1290
1291         /* check for VDP address */
1292         move.l          d1,d0
1293         swap            d0
1294         and.b           #0xe0,d0
1295         cmp.b           #0xc0,d0
1296         bne             addr_unsafe     /* not vdp */
1297
1298         move.l          d1,d0
1299         and.l           #0x0700e0,d0
1300         bne             addr_unsafe
1301
1302         move.l          d1,d0
1303         and.b           #0x1f,d0
1304         cmp.b           #0x04,d0
1305         blt             addr_hsafe_3    /* data port */
1306         cmp.b           #0x10,d0
1307         blt             addr_safe       /* below PSG */
1308         cmp.b           #0x18,d0
1309         bge             addr_safe       /* above PSG */
1310
1311 addr_unsafe:
1312         moveq.l         #0,d0           /* skip line */
1313         rts
1314
1315 addr_hsafe_3:
1316         moveq.l         #3,d0           /* skip 2 words */
1317         rts
1318
1319 addr_safe:
1320         move.l          d1,a1
1321         moveq.l         #0xf,d0
1322 gsm_rts:
1323         rts
1324
1325
1326 # read single phase from controller
1327 #  #a0 - addr
1328 #  d0 - result
1329 #  destroys d1,d2
1330 get_input:
1331         move.b          #0x40,(0xa10003)
1332         nop
1333         nop
1334         nop
1335         move.b          (0xa10003),d0
1336         move.b          #0x00,(0xa10003)
1337         lsl.w           #8,d0
1338         nop
1339         move.b          (0xa10003),d0
1340         eor.w           #0xffff,d0
1341
1342         swap            d7
1343         move.w          d7,d1
1344         eor.w           d0,d1           /* changed btns */
1345         move.w          d0,d7           /* old val */
1346         swap            d7
1347         and.w           d0,d1           /* what changed now */
1348         bne             0f
1349
1350         addq.b          #1,d6
1351         move.b          d6,d2
1352         and.b           #0x0f,d2        /* do autorepeat */
1353         cmp.b           #9,d2
1354         bne             1f
1355         move.w          d0,d1
1356 0:
1357         and.b           #0xf0,d6
1358 1:
1359         swap            d0
1360         move.w          d1,d0
1361         rts
1362
1363 # Prepare to write to VDP RAM @a0
1364 # sets a0 to VDP data port for convenience
1365 #  a0: VRAM base
1366 #  destroys d0
1367
1368 load_prepare:
1369         VRAM_ADDR_var   a0
1370         move.l          d0,(GFXCNTL).l
1371         move.l          #GFXDATA,a0
1372         rts
1373
1374
1375 # Load color data from ROM
1376 #  a0: CRAM base
1377 #  a1: color list address
1378 #  d0: number of colors to load
1379 #  destroys d1
1380
1381 load_colors:
1382         move.l          d0,d1
1383         CRAM_ADDR_var   a0
1384         move.l          d0,(GFXCNTL).l
1385
1386         move.l          #GFXDATA,a0
1387         subq.w          #1,d1
1388 0:
1389         move.w          (a1)+,(a0)
1390         dbra            d1,0b
1391
1392         rts
1393
1394
1395 # print
1396 #  a0 - string
1397 #  d0 - x
1398 #  d1 - y 
1399 #  d2 - tile_bits[15:11]
1400 #  destroys a1
1401
1402 print:
1403         move.l          a0,a1
1404         XY2NT
1405         jsr             load_prepare
1406         move.l          d2,d0
1407         and.w           #0xf800,d0
1408
1409 _print_loop:
1410         move.b          (a1)+,d0
1411         beq             _print_end
1412
1413         move.w          d0,(a0)
1414         jmp             _print_loop
1415
1416 _print_end:
1417         rts
1418
1419
1420 # print_hex
1421 #  d0 - x
1422 #  d1 - y 
1423 #  d2 - value
1424 #  d3 - tile_bits[15:11]|digit_cnt[7:0]
1425 #  destroys a0, preserves d3
1426
1427 print_hex:
1428         XY2NT
1429         jsr             load_prepare
1430
1431 print_hex_preped:
1432         moveq.l         #0,d0
1433         move.b          d3,d0
1434         move.l          d0,d1
1435         lsl.b           #2,d0
1436         ror.l           d0,d2           /* prep value */
1437         subq.l          #1,d1           /* count */
1438         move.w          d3,d0
1439         and.w           #0xf800,d0      /* keep upper bits in d0 */
1440
1441 _print_hex_loop:
1442         rol.l           #4,d2
1443         move.b          d2,d0
1444         and.b           #0xf,d0
1445
1446         add.b           #'0',d0
1447         cmp.b           #'9',d0
1448         ble             0f
1449         addq.b          #7,d0
1450 0:
1451         move.w          d0,(a0)
1452         dbra            d1,_print_hex_loop
1453
1454         rts
1455
1456
1457 # wait vertical sync
1458
1459 wait_vsync:
1460         move.b          d7,d0
1461 _wait_change:
1462         stop            #0x2000
1463         cmp.b           d7,d0
1464         beq             _wait_change
1465         rts
1466
1467
1468 #################################################
1469 #                                               #
1470 #                 RAM DATA                      #
1471 #                                               #
1472 #################################################
1473
1474 .bss
1475
1476 # nothing :)
1477
1478 .end
1479
1480 # vim:filetype=asmM68k