1 ##################################################
4 # --register-prefix-optional --bitwise-or #
6 ##################################################
13 ##################################################
15 # Register and bitmask definitions #
17 ##################################################
19 .equ GFXDATA, 0xc00000
20 .equ GFXCNTL, 0xc00004
23 .equ VDP0_E_DISPLAY, 0x02
24 .equ VDP0_PLTT_FULL, 0x04
26 .equ VDP1_SMS_MODE, 0x80
27 .equ VDP1_E_DISPLAY, 0x40
32 .equ VDP1_RESERVED, 0x04
35 .equ VDP12_SCREEN_V224, 0x00
36 .equ VDP12_SCREEN_V448, 0x04
37 .equ VDP12_PROGRESSIVE, 0x00
38 .equ VDP12_INTERLACED, 0x02
39 .equ VDP12_SCREEN_H256, 0x00
40 .equ VDP12_SCREEN_H320, 0x81
42 .equ VDP16_MAP_V32, 0x00
43 .equ VDP16_MAP_V64, 0x10
44 .equ VDP16_MAP_V128, 0x30
45 .equ VDP16_MAP_H32, 0x00
46 .equ VDP16_MAP_H64, 0x01
47 .equ VDP16_MAP_H128, 0x03
50 .equ MMODE_VAL_INPUT, 1
51 .equ MMODE_EDIT_VAL, 2
53 .equ MMODE_START_MENU, 4
54 .equ MMODE_GOTO_PREDEF, 5
56 .equ predef_addr_cnt, ((predef_addrs_end-predef_addrs)/4)
58 ##################################################
62 ##################################################
65 # Write val to VDP register reg
66 .macro write_vdp_r_dst reg val dst
67 move.w #((\reg << 8) + 0x8000 + \val),\dst
70 # Write val to VDP register reg, vdp addr in a3
71 .macro write_vdp_reg reg val
72 write_vdp_r_dst \reg, \val, (a3)
75 /* For immediate addresses */
76 .macro VRAM_ADDR reg adr
77 move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
80 .macro CRAM_ADDR reg adr
81 move.l #(((0xc000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
85 # make VDP word from address adr and store in d0
86 .macro XRAM_ADDR_var adr
96 .macro VRAM_ADDR_var adr
102 .macro CRAM_ADDR_var adr
108 .macro VSCROLL_ADDR reg adr
109 move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + ((\adr >> 14) | 0x10)),\reg
113 .macro HSCROLL_ADDR reg adr
114 move.l #(((0x4000 + (\adr & 0x3fff)) << 16) + (\adr >> 14)),\reg
118 # convert tile coords in d0, d1 to nametable addr to a0
127 # check if some d-pad button (and modifier) is pressed
128 .macro do_dpad bit op val
136 # convert a6 to normal addr
138 .macro mk_a6_addr reg
146 .macro change_mode mode_new mode_back
148 or.w #(\mode_back<<11)|(\mode_new<<8),d7
151 .macro menu_text str x y pal
155 move.l #0x8000|(\pal<<13),d2
159 #################################################
163 #################################################
166 dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
167 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
168 dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
169 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
170 dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
171 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
172 dc.w 0x0000,0x044e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
173 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
178 /* Y size link attr X */
179 dc.w 0; dc.b 0x05; dc.b 0; dc.w 0x6002; dc.w 0
183 dc.l 0x000000, 0x200000, 0x400000, 0xa00000, 0xa10000
184 dc.l 0xa11100, 0xa12000, 0xa13000, 0xa14000, 0xc00000
188 dc.l 0x000000, 0x7fffff
189 dc.l 0xe00000, 0xffffff
190 dc.l 0xa00000, 0xa100ff
191 dc.l 0xa11000, 0xa113ff
192 dc.l 0xa12000, 0xa120ff
193 dc.l 0xa13000, 0xa130ff
203 .ascii "Go to address\0"
205 .ascii "Go to (predef)\0"
207 .ascii "DTACK safety\0"
209 .ascii "DTACK err?\0"
211 .ascii "Exception \0"
213 ##################################################
217 ##################################################
220 # a6 = page_start[31:8]|cursor_offs[7:0]
221 # d7 = old_inputs[31:16]|edit_bytes[15:14]|g_mode_old[13:11]|g_mode[10:8]|irq_cnt[7:0]
222 # d6 = edit_word_save[31:15]|edit_done[7]|no_dtack_detect[4]|autorep_cnt[3:0]
224 # edit: edit_word[31:8]|edit_pos[4:2]|byte_cnt[1:0]
230 /* mask irqs during init */
257 move.b #0x40,(0xa10009).l
258 move.b #0x40,(0xa10003).l
263 /* Load color data */
266 moveq.l #(colors_end-colors)/2,d0
275 /* generate A layer map */
283 0: move.l #0x00000000,(a0)
289 /* generate B layer map */
294 0: move.l #0x00000000,(a0)
297 /* upload sprite data */
300 movea.l #sprite_data,a1
302 move.l #(sprite_data_end-sprite_data)/2-1,d3
306 /* wait for vsync before unmask */
317 ##################################################
325 /* let's hope VRAM is already set up.. */
333 ##################################################
337 movem.l d0-d4/a0-a5,-(a7)
343 move.l (jumptab,pc,d0),a0
348 dc.l mode_edit_val /* edit val in editor */
351 dc.l mode_goto_predef
355 ##################### main #######################
358 /* assume we will hang */
369 move.l d0,a1 /* current addr */
372 add.b #27-1,d1 /* line where the cursor sits */
376 move.l #27-1,d5 /* line counter for dbra */
399 # unsafe or partially safe
402 swap d4 /* mask in upper word */
404 bne draw_row_hsafe_words_pre
406 draw_row_hsafe_bytes_pre:
411 draw_row_hsafe_bytes:
417 move.l #'?'|('?'<<16),(a0)
419 move.l #'?'|('?'<<16),(a0)
429 dbra d4,draw_row_hsafe_bytes
436 beq draw_cursor_unsafe_byte
437 bra draw_chars_hsafe_pre
439 draw_row_hsafe_words_pre:
444 draw_row_hsafe_words:
450 move.l #'?'|('?'<<16),(a0)
451 move.l #'?'|('?'<<16),(a0)
458 dbra d4,draw_row_hsafe_words
460 move.l #(' '<<16)|' ',(a0)
465 beq draw_cursor_unsafe_word
467 draw_chars_hsafe_pre:
477 move.l #'?'|('?'<<16),(a0)
478 bra draw_chars_hsafe_next
480 btst.l #15,d7 /* must perform correct read type */
481 bne 0f /* doing byte reads on security reg hangs */
508 draw_chars_hsafe_next:
510 dbra d4,draw_chars_hsafe
512 move.l #(' '<<16)|' ',(a0)
551 move.l #(' '<<16)|' ',(a0)
573 move.l #(' '<<16)|' ',(a0)
595 move.l #' '|(' '<<16),(a0)
596 move.l #' '|(' '<<16),(a0)
601 jsr get_input /* x0cbrldu x1sa00du */
603 btst.l #16+4,d0 /* A - scroll modifier */
606 do_dpad 16+0, sub, #0x0800
607 do_dpad 16+1, add, #0x0800
608 do_dpad 16+10, sub, #0xd800
609 do_dpad 16+11, add, #0xd800
616 do_dpad 0, subq, #0x0008
617 do_dpad 1, addq, #0x0008
638 btst.l #12,d0 /* B - switch byte/word mode */
641 add.w #0x4000,d7 /* changes between 01 10 */
644 sub.l d1,a6 /* make even, just in case */
647 btst.l #13,d0 /* C - edit selected byte */
650 change_mode MMODE_EDIT_VAL, MMODE_MAIN
651 write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
654 btst.l #5,d0 /* Start - menu */
658 change_mode MMODE_START_MENU, MMODE_MAIN
659 write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
663 movem.l (a7)+,d0-d4/a0-a5
667 draw_cursor_unsafe_byte:
669 and.l #7,d0 /* byte offs */
672 add.b d1,d0 /* d0 *= 3 (chars) */
676 move.l #(0x2000|'?'|((0x2000|'?')<<16)),(a0)
680 jsr load_prepare /* restore a0 */
681 jmp draw_chars_hsafe_pre
683 draw_cursor_unsafe_word:
685 and.l #7,d0 /* byte offs */
687 lsr.b #1,d1 /* which word */
690 add.b d2,d1 /* num of chars to skip */
695 move.l #(0x2000|'?'|((0x2000|'?')<<16)),d0
701 jsr load_prepare /* restore a0 */
702 jmp draw_chars_hsafe_pre
707 and.l #7,d0 /* byte offs */
713 add.b d1,d0 /* d0 *= 3 (chars) */
721 jsr load_prepare /* restore a0 */
727 and.l #7,d0 /* byte offs */
729 lsr.b #1,d1 /* which word */
732 add.b d2,d1 /* num of chars to skip */
743 jsr load_prepare /* restore a0 */
748 #################### hedit #######################
752 bne mode_hedit_finish
754 /* read val to edit */
770 change_mode MMODE_VAL_INPUT, MMODE_EDIT_VAL
789 ##################### goto #######################
800 or.b #3,d5 /* 3 bytes */
802 change_mode MMODE_VAL_INPUT, MMODE_GOTO
822 ################### val edit #####################
826 movea.l #0xe000+14*2+11*64*2,a1
857 and.b #3,d3 /* edit field bytes */
875 lsr.b #1,d1 /* length in bytes */
879 and.b #7,d1 /* nibble to edit */
883 sub.b #1,d3 /* chars to shift out */
894 jsr get_input /* x0cbrldu x1sa00du */
901 add.b d1,d1 /* nibble count */
902 sub.b #1,d1 /* max n.t.e. val */
905 and.b #7,d2 /* nibble to edit */
917 lsl.l d1,d3 /* mask */
918 lsl.l d1,d4 /* what to add/sub */
963 btst.l #4,d0 /* A - confirm */
966 move.w d7,d1 /* back to prev mode */
976 ################### start menu ###################
983 menu_text txt_about, 13, 9, 1
984 menu_text txt_goto, 13, 11, 0
985 menu_text txt_goto_predef, 13, 12, 0
986 menu_text txt_dtack, 13, 13, 0
987 menu_text txt_a_confirm, 13, 15, 2
989 /* dtack safety on/off */
990 movea.l #0xe000+26*2+13*64*2,a0
992 move.w #0x8000|'O',(a0)
995 move.w #0x8000|'N',(a0)
998 move.w #0x8000|'F',(a0)
999 move.w #0x8000|'F',(a0)
1003 movea.l #0xe000+11*2+11*64*2,a0
1013 jsr get_input /* x0cbrldu x1sa00du */
1022 or.b #1,d2 /* up -1, down 1 */
1037 btst.l #4,d0 /* A - confirm */
1042 change_mode MMODE_GOTO, MMODE_MAIN
1049 change_mode MMODE_GOTO_PREDEF, MMODE_MAIN
1069 movea.l #0xe000+10*2+8*64*2,a1
1083 ################### goto predef ##################
1087 movea.l #0xe000+14*2+8*64*2,a1
1088 move.l #predef_addr_cnt+2-1,d1
1100 /* draw addresses */
1101 movea.l #0xe000+17*2+9*64*2,a1
1103 move.w #predef_addr_cnt-1,d4
1109 jsr print_hex_preped
1114 movea.l #0xe000+15*2+9*64*2,a0
1123 jsr get_input /* x0cbrldu x1sa00du */
1130 or.b #1,d2 /* up -1, down 1 */
1134 move.b #predef_addr_cnt-1,d5
1136 cmp.b #predef_addr_cnt-1,d5
1143 btst.l #4,d0 /* A - confirm */
1151 jmp mode_goto_finish
1163 # go back to main mode
1165 bclr.l #7,d6 /* not edited */
1166 change_mode MMODE_MAIN, MMODE_MAIN
1167 write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320),(GFXCNTL)
1171 #################################################
1173 # Initialize VDP registers #
1175 #################################################
1179 write_vdp_reg 0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
1180 write_vdp_reg 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_E_DMA | VDP1_RESERVED)
1181 write_vdp_reg 2,(0xe000 >> 10) /* Screen map a adress */
1182 write_vdp_reg 3,(0xe000 >> 10) /* Window address */
1183 write_vdp_reg 4,(0xc000 >> 13) /* Screen map b address */
1184 write_vdp_reg 5,(0xfc00 >> 9) /* Sprite address */
1186 write_vdp_reg 7,0 /* Backdrop color */
1187 write_vdp_reg 10,1 /* Lines per hblank interrupt */
1188 write_vdp_reg 11,0 /* 2-cell vertical scrolling */
1189 write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
1190 write_vdp_reg 13,(0x8000 >> 10) /* Horizontal scroll address */
1192 write_vdp_reg 16,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */
1194 write_vdp_reg 18,0xff
1198 # get mask of bits representing safe words
1199 # a1 - address to check
1200 # destroys d0-d2, strips upper bits from a1
1206 move.w #(safe_addrs_end - safe_addrs)/8-1,d2
1228 /* check for VDP address */
1233 bne addr_unsafe /* not vdp */
1242 blt addr_hsafe_3 /* data port */
1244 blt addr_safe /* below PSG */
1246 bge addr_safe /* above PSG */
1249 moveq.l #0,d0 /* skip line */
1253 moveq.l #3,d0 /* skip 2 words */
1263 # read single phase from controller
1268 move.b #0x40,(0xa10003)
1272 move.b (0xa10003),d0
1273 move.b #0x00,(0xa10003)
1276 move.b (0xa10003),d0
1281 eor.w d0,d1 /* changed btns */
1282 move.w d0,d7 /* old val */
1284 and.w d0,d1 /* what changed now */
1289 and.b #0x0f,d2 /* do autorepeat */
1300 # Load tile data from ROM
1302 # a1: pattern address
1303 # d0: number of tiles to load
1309 move.l d0,(GFXCNTL).l
1321 # Prepare to write to VDP RAM @a0
1322 # sets a0 to VDP data port for convenience
1328 move.l d0,(GFXCNTL).l
1333 # Load color data from ROM
1335 # a1: color list address
1336 # d0: number of colors to load
1342 move.l d0,(GFXCNTL).l
1357 # d2 - tile_bits[15:11]
1382 # d3 - tile_bits[15:11]|digit_cnt[7:0]
1383 # destroys a0, preserves d3
1394 ror.l d0,d2 /* prep value */
1395 subq.l #1,d1 /* count */
1397 and.w #0xf800,d0 /* keep upper bits in d0 */
1410 dbra d1,_print_hex_loop
1415 #################################################
1417 # Wait for next VBlank interrupt #
1419 #################################################
1430 #################################################
1434 #################################################
1442 # vim:filetype=asmM68k