1 ###############################################################################
3 # Copyright (c) 2009, GraÅžvydas Ignotas
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.
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.
29 # --register-prefix-optional --bitwise-or
37 ##################################################
39 # Register and bitmask definitions #
41 ##################################################
43 .equ GFXDATA, 0xc00000
44 .equ GFXCNTL, 0xc00004
47 .equ VDP0_E_DISPLAY, 0x02
48 .equ VDP0_PLTT_FULL, 0x04
50 .equ VDP1_SMS_MODE, 0x80
51 .equ VDP1_E_DISPLAY, 0x40
59 .equ VDP12_SCREEN_V224, 0x00
60 .equ VDP12_SCREEN_V448, 0x04
61 .equ VDP12_PROGRESSIVE, 0x00
62 .equ VDP12_INTERLACED, 0x02
63 .equ VDP12_SCREEN_H256, 0x00
64 .equ VDP12_SCREEN_H320, 0x81
66 .equ VDP16_MAP_V32, 0x00
67 .equ VDP16_MAP_V64, 0x10
68 .equ VDP16_MAP_V128, 0x30
69 .equ VDP16_MAP_H32, 0x00
70 .equ VDP16_MAP_H64, 0x01
71 .equ VDP16_MAP_H128, 0x03
74 .equ MMODE_VAL_INPUT, 1
75 .equ MMODE_EDIT_VAL, 2
77 .equ MMODE_START_MENU, 4
78 .equ MMODE_GOTO_PREDEF, 5
79 .equ MMODE_JMP_ADDR, 6
81 .equ predef_addr_cnt, ((predef_addrs_end-predef_addrs)/4)
83 ##################################################
87 ##################################################
90 # Write val to VDP register reg
91 .macro write_vdp_r_dst reg val dst
92 move.w #((\reg << 8) + 0x8000 + \val),\dst
95 # Write val to VDP register reg, vdp addr in a3
96 .macro write_vdp_reg reg val
97 write_vdp_r_dst \reg, \val, (a3)
100 # Set up address in VDP, control port in dst
101 .macro VRAM_ADDR adr dst
102 move.l #(((0x4000 | (\adr & 0x3fff)) << 16) | (\adr >> 14)),\dst
106 # make VDP word from address adr and store in d0
107 .macro XRAM_ADDR_var adr
117 .macro VRAM_ADDR_var adr
123 .macro CRAM_ADDR_var adr
129 # convert tile coords in d0, d1 to nametable addr to a0
138 # check if some d-pad button (and modifier) is pressed
139 .macro do_dpad bit op val
147 # convert a6 to normal addr
149 .macro mk_a6_addr reg
157 .macro change_mode mode_new mode_back
159 or.w #(\mode_back<<11)|(\mode_new<<8),d7
162 .macro menu_text str x y pal
166 move.l #0x8000|(\pal<<13),d2
170 #################################################
174 #################################################
177 dc.w 0x0000,0x0eee,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
178 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
179 dc.w 0x0000,0x02e2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
180 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
181 dc.w 0x0000,0x0e44,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
182 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
183 dc.w 0x0000,0x044e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
184 dc.w 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
189 /* Y size link attr X */
190 dc.w 0; dc.b 0x05; dc.b 0; dc.w 0x6002; dc.w 0
194 dc.l 0x000000, 0x200000, 0x400000, 0xa00000, 0xa10000
195 dc.l 0xa11100, 0xa12000, 0xa13000, 0xa14000, 0xc00000
199 dc.l 0x000000, 0x7fffff
200 dc.l 0xe00000, 0xffffff
201 dc.l 0xa00000, 0xa100ff
202 dc.l 0xa11000, 0xa113ff
203 dc.l 0xa12000, 0xa120ff
204 dc.l 0xa13000, 0xa130ff
214 .ascii "Go to address\0"
216 .ascii "Go to (predef)\0"
218 .ascii "Jump to address\0"
220 .ascii "DTACK safety\0"
222 .ascii "DTACK err?\0"
224 .ascii "Exception \0"
226 ##################################################
230 ##################################################
233 # a6 = page_start[31:8]|cursor_offs[7:0]
234 # d7 = old_inputs[31:16]|edit_bytes[15:14]|g_mode_old[13:11]|g_mode[10:8]|irq_cnt[7:0]
235 # d6 = edit_word_save[31:15]|edit_done[7]|no_dtack_detect[4]|autorep_cnt[3:0]
237 # edit: edit_word[31:8]|edit_pos[4:2]|byte_cnt[1:0]
243 /* mask irqs during init */
270 move.b #0x40,(0xa10009).l
271 move.b #0x40,(0xa10003).l
276 /* Load color data */
279 moveq.l #(colors_end-colors)/2,d0
282 /* load font patterns */
285 VRAM_ADDR 0,(GFXCNTL)
297 rol.l #1,d1 /* fixup */
301 /* generate A layer map */
309 0: move.l #0x00000000,(a0)
315 /* generate B layer map */
320 0: move.l #0x00000000,(a0)
323 /* upload sprite data */
326 movea.l #sprite_data,a1
328 move.l #(sprite_data_end-sprite_data)/2-1,d3
332 /* wait for vsync before unmask */
347 /* wait a bit to avoid nested vint */
350 dbra d0,0b /* 10 cycles to go back */
355 ##################################################
363 /* let's hope VRAM is already set up.. */
371 ##################################################
375 # movem.l d0-d4/a0-a5,-(a7)
381 move.l (jumptab,pc,d0),a0
386 dc.l mode_edit_val /* edit val in editor */
389 dc.l mode_goto_predef
393 ##################### main #######################
396 /* assume we will hang */
407 move.l d0,a1 /* current addr */
410 add.b #27-1,d1 /* line where the cursor sits */
414 move.l #27-1,d5 /* line counter for dbra */
437 # unsafe or partially safe
440 swap d4 /* mask in upper word */
442 bne draw_row_hsafe_words_pre
444 draw_row_hsafe_bytes_pre:
449 draw_row_hsafe_bytes:
455 move.l #'?'|('?'<<16),(a0)
457 move.l #'?'|('?'<<16),(a0)
467 dbra d4,draw_row_hsafe_bytes
474 beq draw_cursor_unsafe_byte
475 bra draw_chars_hsafe_pre
477 draw_row_hsafe_words_pre:
482 draw_row_hsafe_words:
488 move.l #'?'|('?'<<16),(a0)
489 move.l #'?'|('?'<<16),(a0)
496 dbra d4,draw_row_hsafe_words
498 move.l #(' '<<16)|' ',(a0)
503 beq draw_cursor_unsafe_word
505 draw_chars_hsafe_pre:
515 move.l #'?'|('?'<<16),(a0)
516 bra draw_chars_hsafe_next
518 btst.l #15,d7 /* must perform correct read type */
519 bne 0f /* doing byte reads on security reg hangs */
546 draw_chars_hsafe_next:
548 dbra d4,draw_chars_hsafe
550 move.l #(' '<<16)|' ',(a0)
589 move.l #(' '<<16)|' ',(a0)
611 move.l #(' '<<16)|' ',(a0)
633 move.l #' '|(' '<<16),(a0)
634 move.l #' '|(' '<<16),(a0)
639 jsr get_input /* x0cbrldu x1sa00du */
641 btst.l #16+4,d0 /* A - scroll modifier */
644 do_dpad 16+0, sub, #0x0800
645 do_dpad 16+1, add, #0x0800
646 do_dpad 16+10, sub, #0xd800
647 do_dpad 16+11, add, #0xd800
654 do_dpad 0, subq, #0x0008
655 do_dpad 1, addq, #0x0008
676 btst.l #12,d0 /* B - switch byte/word mode */
679 add.w #0x4000,d7 /* changes between 01 10 */
682 sub.l d1,a6 /* make even, just in case */
685 btst.l #13,d0 /* C - edit selected byte */
688 change_mode MMODE_EDIT_VAL, MMODE_MAIN
689 write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
692 btst.l #5,d0 /* Start - menu */
696 change_mode MMODE_START_MENU, MMODE_MAIN
697 write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320 | VDP12_STE),(GFXCNTL)
701 # movem.l (a7)+,d0-d4/a0-a5
705 draw_cursor_unsafe_byte:
707 and.l #7,d0 /* byte offs */
710 add.b d1,d0 /* d0 *= 3 (chars) */
714 move.l #(0x2000|'?'|((0x2000|'?')<<16)),(a0)
718 jsr load_prepare /* restore a0 */
719 jmp draw_chars_hsafe_pre
721 draw_cursor_unsafe_word:
723 and.l #7,d0 /* byte offs */
725 lsr.b #1,d1 /* which word */
728 add.b d2,d1 /* num of chars to skip */
733 move.l #(0x2000|'?'|((0x2000|'?')<<16)),d0
739 jsr load_prepare /* restore a0 */
740 jmp draw_chars_hsafe_pre
745 and.l #7,d0 /* byte offs */
751 add.b d1,d0 /* d0 *= 3 (chars) */
759 jsr load_prepare /* restore a0 */
765 and.l #7,d0 /* byte offs */
767 lsr.b #1,d1 /* which word */
770 add.b d2,d1 /* num of chars to skip */
781 jsr load_prepare /* restore a0 */
786 #################### hedit #######################
790 bne mode_hedit_finish
792 /* read val to edit */
808 change_mode MMODE_VAL_INPUT, MMODE_EDIT_VAL
827 ##################### goto #######################
838 or.b #3,d5 /* 3 bytes */
840 change_mode MMODE_VAL_INPUT, MMODE_GOTO
860 ################### val edit #####################
864 movea.l #0xe000+14*2+11*64*2,a1
895 and.b #3,d3 /* edit field bytes */
913 lsr.b #1,d1 /* length in bytes */
917 and.b #7,d1 /* nibble to edit */
921 sub.b #1,d3 /* chars to shift out */
932 jsr get_input /* x0cbrldu x1sa00du */
939 add.b d1,d1 /* nibble count */
940 sub.b #1,d1 /* max n.t.e. val */
943 and.b #7,d2 /* nibble to edit */
955 lsl.l d1,d3 /* mask */
956 lsl.l d1,d4 /* what to add/sub */
1001 btst.l #4,d0 /* A - confirm */
1004 move.w d7,d1 /* back to prev mode */
1014 ################### start menu ###################
1021 menu_text txt_about, 13, 9, 1
1022 menu_text txt_goto, 13, 11, 0
1023 menu_text txt_goto_predef, 13, 12, 0
1024 menu_text txt_jmp_addr, 13, 13, 0
1025 menu_text txt_dtack, 13, 14, 0
1026 menu_text txt_a_confirm, 13, 16, 2
1028 /* dtack safety on/off */
1029 movea.l #0xe000+26*2+14*64*2,a0
1031 move.w #0x8000|'O',(a0)
1034 move.w #0x8000|'N',(a0)
1037 move.w #0x8000|'F',(a0)
1038 move.w #0x8000|'F',(a0)
1042 movea.l #0xe000+11*2+11*64*2,a0
1052 jsr get_input /* x0cbrldu x1sa00du */
1061 or.b #1,d2 /* up -1, down 1 */
1076 btst.l #4,d0 /* A - confirm */
1081 change_mode MMODE_GOTO, MMODE_MAIN
1088 change_mode MMODE_GOTO_PREDEF, MMODE_MAIN
1094 change_mode MMODE_JMP_ADDR, MMODE_MAIN
1114 movea.l #0xe000+10*2+8*64*2,a1
1128 ################### goto predef ##################
1132 movea.l #0xe000+14*2+8*64*2,a1
1133 move.l #predef_addr_cnt+2-1,d1
1145 /* draw addresses */
1146 movea.l #0xe000+17*2+9*64*2,a1
1148 move.w #predef_addr_cnt-1,d4
1154 jsr print_hex_preped
1159 movea.l #0xe000+15*2+9*64*2,a0
1168 jsr get_input /* x0cbrldu x1sa00du */
1175 or.b #1,d2 /* up -1, down 1 */
1179 move.b #predef_addr_cnt-1,d5
1181 cmp.b #predef_addr_cnt-1,d5
1188 btst.l #4,d0 /* A - confirm */
1196 jmp mode_goto_finish
1207 ##################### jmp ########################
1214 or.b #3,d5 /* 3 bytes */
1216 change_mode MMODE_VAL_INPUT, MMODE_JMP_ADDR
1221 write_vdp_r_dst 1,(VDP1_E_DISPLAY | VDP1_MODE5),(GFXCNTL) /* disable vint */
1226 # go back to main mode
1228 bclr.l #7,d6 /* not edited */
1229 change_mode MMODE_MAIN, MMODE_MAIN
1230 write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320),(GFXCNTL)
1234 #################################################
1236 # Initialize VDP registers #
1238 #################################################
1242 write_vdp_reg 0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
1243 write_vdp_reg 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_MODE5)
1244 write_vdp_reg 2,(0xe000 >> 10) /* Screen map a adress */
1245 write_vdp_reg 3,(0xe000 >> 10) /* Window address */
1246 write_vdp_reg 4,(0xc000 >> 13) /* Screen map b address */
1247 write_vdp_reg 5,(0xfc00 >> 9) /* Sprite address */
1249 write_vdp_reg 7,0 /* Backdrop color */
1250 write_vdp_reg 10,1 /* Lines per hblank interrupt */
1251 write_vdp_reg 11,0 /* 2-cell vertical scrolling */
1252 write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
1253 write_vdp_reg 13,(0x8000 >> 10) /* Horizontal scroll address */
1255 write_vdp_reg 16,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */
1257 write_vdp_reg 18,0xff
1261 # get mask of bits representing safe words
1262 # a1 - address to check
1263 # destroys d0-d2, strips upper bits from a1
1269 move.w #(safe_addrs_end - safe_addrs)/8-1,d2
1291 /* check for VDP address */
1296 bne addr_unsafe /* not vdp */
1305 blt addr_hsafe_3 /* data port */
1307 blt addr_safe /* below PSG */
1309 bge addr_safe /* above PSG */
1312 moveq.l #0,d0 /* skip line */
1316 moveq.l #3,d0 /* skip 2 words */
1326 # read single phase from controller
1331 move.b #0x40,(0xa10003)
1335 move.b (0xa10003),d0
1336 move.b #0x00,(0xa10003)
1339 move.b (0xa10003),d0
1344 eor.w d0,d1 /* changed btns */
1345 move.w d0,d7 /* old val */
1347 and.w d0,d1 /* what changed now */
1352 and.b #0x0f,d2 /* do autorepeat */
1363 # Prepare to write to VDP RAM @a0
1364 # sets a0 to VDP data port for convenience
1370 move.l d0,(GFXCNTL).l
1375 # Load color data from ROM
1377 # a1: color list address
1378 # d0: number of colors to load
1384 move.l d0,(GFXCNTL).l
1399 # d2 - tile_bits[15:11]
1424 # d3 - tile_bits[15:11]|digit_cnt[7:0]
1425 # destroys a0, preserves d3
1436 ror.l d0,d2 /* prep value */
1437 subq.l #1,d1 /* count */
1439 and.w #0xf800,d0 /* keep upper bits in d0 */
1452 dbra d1,_print_hex_loop
1457 # wait vertical sync
1468 #################################################
1472 #################################################
1480 # vim:filetype=asmM68k