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