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