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