-##################################################
-# #
-# Assemble with gas #
-# --register-prefix-optional --bitwise-or #
-# #
-##################################################
+###############################################################################
+#
+# Copyright (c) 2009, GraÅžvydas Ignotas
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the organization nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Assemble with gas
+# --register-prefix-optional --bitwise-or
+#
+
+.equ USE_VINT, 0
+.equ COPY_TO_EXP, 1
+.equ RELOCATE_TO_RAM, 1
.text
.globl main
.equ MMODE_START_MENU, 4
.equ MMODE_GOTO_PREDEF, 5
.equ MMODE_JMP_ADDR, 6
+.equ MMODE_DUMP, 7
.equ predef_addr_cnt, ((predef_addrs_end-predef_addrs)/4)
# Set up address in VDP, control port in dst
.macro VRAM_ADDR adr dst
- move.l #(((0x4000 | (\adr & 0x3fff)) << 16) | (\adr >> 14)),\dst
+ move.l #(0x40000000 | ((\adr & 0x3fff) << 16) | (\adr >> 14)),\dst
+.endm
+
+.macro VSRAM_ADDR adr dst
+ move.l #(0x40000010 | ((\adr & 0x3fff) << 16) | (\adr >> 14)),\dst
.endm
or.w #(\mode_back<<11)|(\mode_new<<8),d7
.endm
+# destroys a0,d0-d2
.macro menu_text str x y pal
- lea \str,a0
+ lea (\str,pc),a0
move.l #\x,d0
move.l #\y,d1
move.l #0x8000|(\pal<<13),d2
dc.l 0xa13000, 0xa130ff
safe_addrs_end:
+transfer_mode:
+ dc.l 0x000000 /* 1 for recv */
+transfer_addr:
+ dc.l 0x000000
+transfer_len:
+ dc.l 0x000800
+
txt_edit:
.ascii "- edit -\0"
txt_a_confirm:
.ascii "A-confirm\0"
txt_about:
- .ascii "hexed r1\0"
+ .ascii "hexed r2\0"
txt_goto:
.ascii "Go to address\0"
txt_goto_predef:
.ascii "Go to (predef)\0"
txt_jmp_addr:
.ascii "Jump to address\0"
+txt_dump:
+ .ascii "Transfer\0"
txt_dtack:
.ascii "DTACK safety\0"
+txt_ready_send:
+ .ascii "Ready to send\0"
+txt_ready_recv:
+ .ascii "Ready to recv\0"
+txt_working:
+ .ascii "Working.. \0"
txt_dtack_err:
.ascii "DTACK err?\0"
txt_exc:
/* mask irqs during init */
move.w #0x2700,sr
-.if 0
- /* copy */
- lea (0,pc),a0
- move.l a0,d0
- swap d0
- lsr.l #4,d0
- and.b #0x0f,d0
- cmp.b #0,d0
+.if COPY_TO_EXP
+ /* copy to expansion device if magic number is set */
+ move.l #0x400000,a1
+ cmp.w #0x1234,(a1)
bne 0f
- move.w #8000/2,d0
move.l #0,a0
- move.l #0x400000,a1
+ move.w #0x2000/8-1,d0
+1:
+ move.l (a0)+,(a1)+
+ move.l (a0)+,(a1)+
+ dbra d0,1b
+0:
+.endif
+
+.if RELOCATE_TO_RAM
+ /* we could be relocated by 32x or something else, adjust start addr */
+ lea (pc),a0
+ move.l a0,d0
+ and.l #0xff0000,d0
+ move.l d0,a0
+
+ /* copy, assume 8K size */
+ move.l #0xFF0100,a1
+ move.w #0x2000/8-1,d0
+1:
+ move.l (a0)+,(a1)+
+ move.l (a0)+,(a1)+
+ dbra d0,1b
+
+ /* copy test code */
+ lea (test_code,pc),a0
+ move.l #0xffc000,a1
+ move.w #(test_code_end - test_code)/2-1,d0
1:
move.w (a0)+,(a1)+
dbra d0,1b
+
+ lea (0f,pc),a0
+ move.l a0,d0
+ and.l #0x00ffff,d0
+ add.l #0xFF0100,d0
+ move.l d0,a0
+
+ /* patch test code */
+ move.l #0xffc000,a1
+ add.w #(test_code_ret_op-test_code+2),a1
+ move.l a0,(a1)
+
+ jmp (a0)
0:
.endif
/* Initialize VDP */
jsr init_gfx
+ /* Clear h/v scroll */
+ movea.l #GFXDATA,a0
+ VRAM_ADDR 0x8000,(GFXCNTL)
+ move.l #0,(a0)
+ VSRAM_ADDR 0,(GFXCNTL)
+ move.l #0,(a0)
+
/* Load color data */
movea.l #0,a0
- movea.l #colors,a1
+ lea (colors,pc),a1
moveq.l #(colors_end-colors)/2,d0
jsr load_colors
/* load font patterns */
- lea GFXDATA,a0
- lea font,a1
+ movea.l #GFXDATA,a0
+ lea (font,pc),a1
VRAM_ADDR 0,(GFXCNTL)
move.w #128*8,d3
font_loop:
/* upload sprite data */
movea.l #0xfc00,a0
jsr load_prepare
- movea.l #sprite_data,a1
+ lea (sprite_data,pc),a1
move.l #(sprite_data_end-sprite_data)/2-1,d3
0: move.l (a1)+,(a0)
dbra d3,0b
+.if USE_VINT
/* wait for vsync before unmask */
- move.l #GFXCNTL,a3
+ jsr wait_vsync_poll
+
+ /* wait a bit to avoid nested vint */
+ move.w #20,d0
0:
- move.w (a3),d0
- and.b #8,d0
- nop
- nop
- beq 0b
+ dbra d0,0b /* 10 cycles to go back */
- move.w #0x2000,sr
+ /* enable and unmask vint */
+ write_vdp_r_dst 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_MODE5),(GFXCNTL)
+ move.w #0x2000,sr
+.endif
##################################################
forever:
+.if USE_VINT
jsr wait_vsync
+.else
+ jsr wait_vsync_poll
+ jsr VBL
+.endif
bra forever
INT:
/* let's hope VRAM is already set up.. */
- lea txt_exc,a0
+ lea (txt_exc,pc),a0
move.l #9,d0
move.l #27,d1
move.l #0xe000,d2
move.w d7,d0
lsr.w #6,d0
and.w #0x1c,d0
- move.l (jumptab,pc,d0),a0
+ lea (jumptab,pc,d0),a0
jmp (a0)
jumptab:
- dc.l mode_main
- dc.l mode_val_input
- dc.l mode_edit_val /* edit val in editor */
- dc.l mode_goto
- dc.l mode_start_menu
- dc.l mode_goto_predef
- dc.l mode_jmp_addr
- dc.l mode_main
+ bra mode_main
+ bra mode_val_input
+ bra mode_edit_val /* edit val in editor */
+ bra mode_goto
+ bra mode_start_menu
+ bra mode_goto_predef
+ bra mode_jmp_addr
+ bra mode_transfer
##################### main #######################
mode_main:
/* assume we will hang */
- lea txt_dtack_err,a0
+ lea (txt_dtack_err,pc),a0
move.l #9,d0
move.l #27,d1
move.l #0xe000,d2
input_nos:
vbl_end:
# movem.l (a7)+,d0-d4/a0-a5
+.if USE_VINT
rte
+.else
+ rts
+.endif
draw_cursor_unsafe_byte:
move.l a2,a0
add.w #31*2,a0
jsr load_prepare /* restore a0 */
- jmp draw_chars_hsafe_pre
+ bra draw_chars_hsafe_pre
draw_cursor_unsafe_word:
move.l a6,d0
move.l a2,a0
add.w #29*2,a0
jsr load_prepare /* restore a0 */
- jmp draw_chars_hsafe_pre
+ bra draw_chars_hsafe_pre
draw_cursor_byte:
add.w #31*2,a0
jsr load_prepare /* restore a0 */
- jmp draw_chars_pre
+ bra draw_chars_pre
draw_cursor_word:
move.l a6,d0
add.w #29*2,a0
jsr load_prepare /* restore a0 */
- jmp draw_chars_pre
+ bra draw_chars_pre
#################### hedit #######################
1:
change_mode MMODE_VAL_INPUT, MMODE_EDIT_VAL
- jmp vbl_end
+ bra vbl_end
mode_hedit_finish:
/* write the val */
or.b #3,d5 /* 3 bytes */
bclr.l #7,d6
change_mode MMODE_VAL_INPUT, MMODE_GOTO
- jmp vbl_end
+ bra vbl_end
mode_goto_finish:
lsr.l #8,d5
dbra d1,0b
/* text */
- lea txt_edit,a0
+ lea (txt_edit,pc),a0
move.l #15,d0
move.l #11,d1
move.l #0xc000,d2
jsr print
- lea txt_a_confirm,a0
+ lea (txt_a_confirm,pc),a0
move.l #15,d0
move.l #15,d1
move.l #0xc000,d2
eor.l #0xffffffff,d3
and.l d3,d5
or.l d1,d5
- jmp vbl_end
+ bra vbl_end
ai_no_ud:
btst.l #10,d0
and.b #0xe3,d5
lsl.b #2,d2
or.b d2,d5
- jmp vbl_end
+ bra vbl_end
ai_no_dpad:
move.w d0,d1
or.w d1,d7
ai_no_input:
- jmp vbl_end
+ bra vbl_end
################### start menu ###################
menu_text txt_goto, 13, 11, 0
menu_text txt_goto_predef, 13, 12, 0
menu_text txt_jmp_addr, 13, 13, 0
- menu_text txt_dtack, 13, 14, 0
- menu_text txt_a_confirm, 13, 16, 2
+ menu_text txt_dump, 13, 14, 0
+ menu_text txt_dtack, 13, 15, 0
+ menu_text txt_a_confirm, 13, 17, 2
/* dtack safety on/off */
- movea.l #0xe000+26*2+14*64*2,a0
+ movea.l #0xe000+26*2+15*64*2,a0
jsr load_prepare
move.w #0x8000|'O',(a0)
btst.l #4,d6
movea.l #0xe000+11*2+11*64*2,a0
moveq.l #0,d0
move.b d5,d0
- and.b #3,d0
+ and.b #7,d0
lsl.w #7,d0
add.w d0,a0
jsr load_prepare
and.w #3,d1
beq msm_no_ud
move.b d5,d1
- and.b #3,d1
+ and.b #7,d1
btst.l #0,d0
sne d2
or.b #1,d2 /* up -1, down 1 */
add.b d2,d1
cmp.b #0,d1
bge 0f
- move.b #3,d1
+ move.b #4,d1
0:
- cmp.b #3,d1
+ cmp.b #4,d1
ble 0f
move.b #0,d1
0:
- and.b #0xfc,d5
+ and.b #0xf8,d5
or.b d1,d5
- jmp vbl_end
+ bra vbl_end
msm_no_ud:
btst.l #4,d0 /* A - confirm */
beq msm_no_a
move.b d5,d1
- and.b #3,d1
+ and.b #7,d1
bne 0f
change_mode MMODE_GOTO, MMODE_MAIN
bsr start_menu_box
- jmp vbl_end
+ bra vbl_end
0:
cmp.b #1,d1
bne 0f
moveq.l #0,d5
change_mode MMODE_GOTO_PREDEF, MMODE_MAIN
bsr start_menu_box
- jmp vbl_end
+ bra vbl_end
0:
cmp.b #2,d1
bne 0f
change_mode MMODE_JMP_ADDR, MMODE_MAIN
bsr start_menu_box
- jmp vbl_end
+ bra vbl_end
0:
cmp.b #3,d1
bne 0f
+ change_mode MMODE_DUMP, MMODE_MAIN
+ bsr start_menu_box
+ bra vbl_end
+0:
+ cmp.b #4,d1
+ bne 0f
bchg.l #4,d6
- jmp vbl_end
+ bra vbl_end
0:
msm_no_a:
bra return_to_main
msm_no_bc:
- jmp vbl_end
+ bra vbl_end
start_menu_box:
movea.l #0xe000+10*2+8*64*2,a1
- move.w #10-1,d1
+ move.w #11-1,d1
0:
move.w a1,a0
jsr load_prepare
/* draw addresses */
movea.l #0xe000+17*2+9*64*2,a1
- lea predef_addrs,a2
+ lea (predef_addrs,pc),a2
move.w #predef_addr_cnt-1,d4
move.l #0x8006,d3
mgp_da_loop:
ble 0f
move.b #0,d5
0:
- jmp vbl_end
+ bra vbl_end
mgp_no_ud:
btst.l #4,d0 /* A - confirm */
moveq.l #0,d0
move.b d5,d0
lsl.w #2,d0
- lea predef_addrs,a0
+ lea (predef_addrs,pc),a0
move.l (a0,d0),d5
lsl.l #8,d5
- jmp mode_goto_finish
+ bra mode_goto_finish
mgp_no_a:
move.w d0,d1
bra return_to_main
mgp_no_bc:
- jmp vbl_end
+ bra vbl_end
##################### jmp ########################
or.b #3,d5 /* 3 bytes */
bclr.l #7,d6
change_mode MMODE_VAL_INPUT, MMODE_JMP_ADDR
- jmp vbl_end
+ bra vbl_end
mode_jmp_finish:
lsr.l #8,d5
move.l d5,a0
jmp (a0)
+################### transfer #####################
+
+mode_transfer:
+ move.b #0x40,(0xa1000b).l
+ move.b #0x40,(0xa10005).l
+
+ move.l (transfer_mode,pc),d0
+ tst.l d0
+ bne 0f
+ lea (txt_ready_send,pc),a0
+ bra 1f
+0:
+ lea (txt_ready_recv,pc),a0
+1:
+ move.l #13,d0
+ move.l #13,d1
+ move.l #0x8000,d2
+ jsr print
+
+wait_tl_low0:
+ move.b (0xa10005),d0
+ btst.b #4,d0
+ bne wait_tl_low0
+
+ menu_text txt_working, 13, 13, 0
+
+ lea 0xa10005,a1
+ move.l (transfer_addr,pc),a0
+ move.l (transfer_len,pc),d2
+
+ move.l (transfer_mode,pc),d0
+ tst.l d0
+ bne transfer_recv
+
+transfer_send:
+ move.b #0x4f,(0xa1000b).l
+
+tr_send_loop:
+ move.b (a0),d1
+ and.b #0x0f,d1
+
+wait_tl_low1:
+ move.b (a1),d0
+ btst.b #4,d0
+ bne wait_tl_low1
+
+ move.b d1,(a1) /* clears TH and writes data */
+
+ move.b (a0)+,d1
+ lsr.b #4,d1
+ bset.b #6,d1 /* prepare TH */
+
+wait_tl_hi1:
+ move.b (a1),d0
+ btst.b #4,d0
+ beq wait_tl_hi1
+
+ move.b d1,(a1)
+ subq.l #1,d2
+ bne tr_send_loop
+
+ move.b #0,(0xa1000b).l
+ bra return_to_main
+
+transfer_recv:
+ move.b #0,(a1) /* clear TH */
+
+tr_recv_loop:
+wait_tl_low2:
+ move.b (a1),d0
+ btst.b #4,d0
+ bne wait_tl_low2
+
+ move.b #0x40,(a1) /* set TH */
+ move.b d0,d1
+ and.b #0x0f,d1
+
+wait_tl_hi2:
+ move.b (a1),d0
+ btst.b #4,d0
+ beq wait_tl_hi2
+
+ move.b #0,(a1) /* clear TH */
+ lsl.b #4,d0
+ or.b d0,d1
+ move.b d1,(a0)+
+
+ subq.l #1,d2
+ bne tr_recv_loop
+
+ move.b #0,(0xa1000b).l
+ bra return_to_main
+
# go back to main mode
return_to_main:
bclr.l #7,d6 /* not edited */
change_mode MMODE_MAIN, MMODE_MAIN
write_vdp_r_dst 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320),(GFXCNTL)
- jmp vbl_end
+ bra vbl_end
#################################################
init_gfx:
move.l #GFXCNTL,a3
write_vdp_reg 0,(VDP0_E_DISPLAY | VDP0_PLTT_FULL)
- write_vdp_reg 1,(VDP1_E_VBI | VDP1_E_DISPLAY | VDP1_MODE5)
+ write_vdp_reg 1,(VDP1_E_DISPLAY | VDP1_MODE5)
write_vdp_reg 2,(0xe000 >> 10) /* Screen map a adress */
write_vdp_reg 3,(0xe000 >> 10) /* Window address */
write_vdp_reg 4,(0xc000 >> 13) /* Screen map b address */
write_vdp_reg 5,(0xfc00 >> 9) /* Sprite address */
write_vdp_reg 6,0
write_vdp_reg 7,0 /* Backdrop color */
- write_vdp_reg 10,1 /* Lines per hblank interrupt */
- write_vdp_reg 11,0 /* 2-cell vertical scrolling */
- write_vdp_reg 12,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
- write_vdp_reg 13,(0x8000 >> 10) /* Horizontal scroll address */
- write_vdp_reg 15,2
- write_vdp_reg 16,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */
- write_vdp_reg 17,0
- write_vdp_reg 18,0xff
+ write_vdp_reg 0x0a,1 /* Lines per hblank interrupt */
+ write_vdp_reg 0x0b,0 /* 2-cell vertical scrolling */
+ write_vdp_reg 0x0c,(VDP12_SCREEN_V224 | VDP12_SCREEN_H320)
+ write_vdp_reg 0x0d,(0x8000 >> 10) /* Horizontal scroll address */
+ write_vdp_reg 0x0e,0
+ write_vdp_reg 0x0f,2
+ write_vdp_reg 0x10,(VDP16_MAP_V32 | VDP16_MAP_H64) /* layer size */
+ write_vdp_reg 0x11,0
+ write_vdp_reg 0x12,0
rts
move.l a1,d1
lsl.l #8,d1
lsr.l #8,d1
- lea safe_addrs,a1
+ lea (safe_addrs,pc),a1
move.w #(safe_addrs_end - safe_addrs)/8-1,d2
0:
move.l (a1)+,d0
beq _print_end
move.w d0,(a0)
- jmp _print_loop
+ bra _print_loop
_print_end:
rts
rts
-# wait vertical sync
+# wait vertical sync interrupt
wait_vsync:
move.b d7,d0
rts
+# wait vsync start (polling)
+# destroys a0,d0
+
+wait_vsync_poll:
+ move.l #GFXCNTL,a0
+0:
+ move.w (a0),d0
+ and.b #8,d0
+ nop
+ nop
+ bne 0b
+0:
+ move.w (a0),d0
+ and.b #8,d0
+ nop
+ nop
+ beq 0b
+ rts
+
+
+test_code:
+ nop
+
+test_code_ret_op:
+ jmp 0x123456 /* will be patched */
+test_code_end:
+
#################################################
# #
# RAM DATA #