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