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