view menu.s68 @ 917:f057975212e9

Added button graphic for menu
author Michael Pavone <pavone@retrodev.com>
date Thu, 17 Dec 2015 20:41:43 -0800
parents c030e4af32b7
children a3b08915624b
line wrap: on
line source

	dc.l $0, start
	dc.l empty_handler
	dc.l empty_handler
	;$10
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$20
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$30
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$40
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$50
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$60
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$70
	dc.l int_4
	dc.l empty_handler
	dc.l int_6
	dc.l empty_handler
	;$80
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$90
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$A0
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$B0
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$C0
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$D0
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$E0
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	;$F0
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.l empty_handler
	dc.b "SEGA GENESIS    "
	dc.b "(c) 2015.JULY   "
	dc.b "Menu            "
	dc.b "                "
	dc.b "                "
	dc.b "Menu            "
	dc.b "                "
	dc.b "                "
	dc.b "MP BlstMenu-00", 0, 0
	dc.b "                "
	dc.l $0, rom_end-1, $FF0000, $FFFFFF
	dc.b "                "
	dc.b "                "
	dc.b "                "
	dc.b "                "
	dc.b "JUE "

;register addresses
VDP_DATA  equ $C00000
VDP_CTRL  equ $C00004
VDP_HV    equ $C00008
Z80_RAM   equ $A00000
IO_AREA   equ $A10000
PAD1_DATA equ (IO_AREA + 3)
PAD2_DATA equ (IO_AREA + 5)
EXT_DATA  equ (IO_AREA + 7)
PAD1_CTRL equ (IO_AREA + 9)
PAD2_CTRL equ (IO_AREA + 11)
EXT_CTRL  equ (IO_AREA + 13)

MODE_1   equ 0
MODE_2   equ 1
SCROLL_A equ 2
WINDOW   equ 3
SCROLL_B equ 4
SAT      equ 5
BG_COLOR equ 7
HINT     equ $A
MODE_3   equ $B
MODE_4   equ $C
HSCROLL  equ $D
AUTOINC  equ $F
SCROLL   EQU $10
WINDOW_H equ $11
WINDOW_V equ $12
DMALEN_L equ $13
DMALEN_H equ $14
DMASRC_L equ $15
DMASRC_M equ $16
DMASRC_H equ $17

VDP_VRAM_WRITE equ $40000000
VDP_CRAM_WRITE equ $C0000000
VDP_VSRAM_WRITE equ $40000010
VDP_DMA_FLAG equ $80

vdpregset macro
	move.w #(((\1) << 8) | $8000 | (\2)), (a1)
	endm

vdpreg macro
	dc.w (((\1) << 8) | $8000 | (\2))
	endm

;Writes a normal VDP command to the control port
;\1 - VDP address
;\2 - Access type
vdpaccess macro
	move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), (a1)
	endm

;Writes a DMA command to the control port
;\1 - Destination address
;\2 - Destination type
startdma macro
	move.l #(\2 | VDP_DMA_FLAG | (\1 << 16) & $3FFF0000 | (\1 >> 14) & 3), (a1)
	endm

DMA_SRC_68K  equ 0
DMA_SRC_VRAM equ $C0
DMA_SRC_FILL equ $80

dmasrc macro
	move.l #($95009600 + (\1) << 15 & $FF0000 + (\1) >> 9 & $FF), (a1)
	move.w #($9700 + (\1) >> 17 & $7F | (\2)), (a1)
	endm

dir_buffer equ $100000
menu_port  equ $180000

MAX_DISPLAY equ 24

	rsset $FFFF8000
x_pos         rs.w 1
base_cmd      rs.l 1
sprite_list   rs.l 160
page_index    rs.l MAX_DISPLAY+1
page_stack    rs.l 1
page_pointers rs.l 1024
mouse_sprite  rs.l 1
mouse_x       rs.w 1
num_sprites   rs.b 1
last_pad1     rs.b 1
last_pad2     rs.b 1
selected      rs.b 1
more_pages    rs.b 1
mouse_buf     rs.b 3
mouse_shown   rs.b 1
last_mbuttons rs.b 1


int_6:
	dmasrc sprite_list, DMA_SRC_68K
	;set DMA length
	move.l #$94009300, d0
	moveq #0, d1
	move.b num_sprites.w, d1
	add.w d1, d1
	add.w d1, d1
	move.b d1, d0
	swap d0
	lsr.w #8, d1
	move.b d1, d0
	move.l d0, (a1)
	startdma $C000, VDP_VRAM_WRITE

	;read gamepad/mouse in port 1
	lea PAD1_DATA, a2

	bsr io_read

	cmp.b #3, d2
	beq .mouse

	move.b last_pad1.w, d1
	eor.b d0, d1
	and.b d0, d1
	move.b d0, last_pad1.w

	bsr handle_pad_buttons

	bra pad2
.mouse
	bsr handle_mouse

pad2:
	;read gamepad/mouse in port 2
	lea PAD2_DATA, a2

	bsr io_read

	cmp.b #3, d2
	beq .mouse

	move.b last_pad2.w, d1
	eor.b d0, d1
	and.b d0, d1
	move.b d0, last_pad2.w

	bsr handle_pad_buttons
	rte
.mouse
	bsr handle_mouse
	rte


;d0 = SACBRLUD
;d1 = newly pressed buttons
handle_pad_buttons:
	moveq #16, d2
	btst #1, d1
	bne down
	btst #0, d1
	bne up
	btst #3, d1
	bne right
	btst #2, d1
	bne left
	btst #7, d1
	bne select_entry
	btst #5, d1
	bne select_entry
handle_done:
	rts

down:
	;check if we are already at the bottom of the page
	moveq #1, d0
	add.b (selected).w, d0
	move.w d0, d1
	add.w d0, d0
	add.w d0, d0
	lea page_index.w, a2
	tst.l (0, a2, d0.w)
	beq handle_done
	move.b d1, (selected).w

	add.w d2, (sprite_list).w
	add.w d2, (sprite_list+8).w
	rts
up:
	;check if we are already at the top of the page
	move.b (selected).w, d0
	beq handle_done
	subq #1, d0
	move.b d0, (selected).w

	sub.w d2, (sprite_list).w
	sub.w d2, (sprite_list+8).w
	rts

right:
	;check that we have another page to go to
	tst.b more_pages.w
	beq handle_done
	;switch to the next page
	move.l page_stack.w, a6
	move.l (-4, a6), a6

	addq #6, a7
	bra render_page

left:
	move.l page_stack.w, a5
	;check if we're already on the first page
	cmp.l #(page_pointers+8), a5
	beq handle_done
	;switch to previous page
	lea (-12, a5), a5
	move.l (a5)+, a6
	move.l a5, page_stack.w

	addq #6, a7
	bra render_page

select_entry:
	moveq #0, d0
	move.b (selected).w, d0
	add.w d0, d0
	add.w d0, d0
	lea page_index.w, a2
	move.l (0, a2, d0.w), a2
	tst.b (-1, a2)
	bne enter_dir
	;regular file
	lea menu_port+8, a3
	move.l a2, (a3)
	rts
enter_dir:
	lea menu_port+4, a3
	move.l a2, (a3)
.wait_complete
	tst.w (a3)
	bne .wait_complete
	addq #6, a7
	bra menu_start

handle_mouse:
	move.b last_mbuttons.w, d4
	eor.b d3, d4
	and.b d3, d4
	move.b d3, last_mbuttons.w

	move.b d0, d2
	or.b d1, d2
	beq .no_mouse_move


	tst.b mouse_shown.w
	bne .skip_show_check

	moveq #0, d2
	move.b num_sprites.w, d2
	move.w d2, d4
	lsl.w #3, d4
	lea sprite_list.w, a2
	move.b d2, (-5, a2, d4.w)
	lea (0, a2, d4.w), a2
	move.l a2, mouse_sprite.w
	move.l #$01000500, (a2)+
	move.w #$8083, (a2)
	move.w #$100, mouse_x.w
	addq #1, d2
	move.b d2, num_sprites.w

	move.b #1, mouse_shown.w

.skip_show_check
	neg.w d1
	move.l mouse_sprite.w, a2
	add.w d1, (a2)
	add.w d0, mouse_x.w
	move.w mouse_x.w, d0
	asr.w #1, d0
	move.w d0, (6, a2)
	move.w (a2), d1
	cmp.w #272, d1
	blo .done
	cmp.w #655, d1
	bhi .done
	and.w #$FFF0, d1
	subq #8, d1
	move.w d1, (sprite_list).w
	move.w d1, (sprite_list+8).w

	sub.w #264, d1
	lsr.w #4, d1
	move.b d1, selected.w
.no_mouse_move
	btst #0, d4
	bne select_entry
.done
	rts
int_4:
empty_handler:
	rte

id_lookup:
	dc.b $0, $1, $4, $5
	dc.b $2, $3, $6, $7
	dc.b $8, $9, $C, $D
	dc.b $A, $B, $E, $F

io_read:
	;read TH=1
	move.b (a2), d0
	;read TH=0
	move.b #0, (a2)
	nop
	nop
	move.b (a2), d1
	;reset TH to 1
	move.b #$40, (a2)

	moveq #0, d2   ;4

	;calculate Mega Drive peripheral ID
	move.b d1, d2  ;4
	lsr.b #1, d2   ;8, 12
	or.b d1, d2    ;4, 16
	and.b #5, d2   ;8, 24

	move.b d0, d3  ;4
	add.b d3, d3   ;4, 8
	or.b d0, d3    ;4, 12
	and.b #$A, d3  ;8, 20

	or.b d3, d2    ;4
	move.b (id_lookup, pc, d2.w), d2 ;14


	cmp.b #$3, d2
	beq .mouse

	cmp.b #$D, d2
	bne .not_pad

	and.b #$3F, d0
	and.b #$30, d1
	add.b d1, d1
	add.b d1, d1
	or.b d1, d0
	not.b d0
	rts
.not_pad:
	moveq #0, d0
	rts

.mouse:

	move.b #$60, (a2)
	move.b #$60, (PAD1_CTRL-PAD1_DATA, a2)
	move.b #$60, (a2)

	moveq #$f, d4
wait_hi_init:
	btst #4, (a2)
	beq wait_hi_init
	nop
	nop
	move.b #$20, (a2)
	nop
	nop
	moveq #$f, d4
	move.b #0, (a2)
.wait_lo
	btst #4, (a2)
	bne .wait_lo
	moveq #$f, d4
	move.b #$20, (a2)
.wait_hi
	btst #4, (a2)
	beq .wait_hi

	lea mouse_buf.w, a3
	move.l a3, a4
	moveq #2, d3
	moveq #0, d0
loop:
	moveq #$f, d4
	move.b #0, (a2)
.wait_lo
	btst #4, (a2)
	bne .wait_lo
	move.b (a2), d0
	lsl.b #4, d0
	moveq #$f, d4
	move.b #$20, (a2)
.wait_hi
	btst #4, (a2)
	beq .wait_hi
	move.b (a2), d1
	and.b #$f, d1
	or.b d1, d0
	move.b d0, (a3)+

	dbra d3, loop

	;end request
	move.b #$60, (a2)


	;massage data
	moveq #0, d1
	move.b d0, d1
	move.b (a4)+, d3
	move.b (a4), d0

	btst #4, d3
	beq xpos
	or.w #$FF00, d0
xpos
	btst #5, d3
	beq ypos
	or.w #$FF00, d1
ypos
	;set port config back to normal controller mode
	move.b #$40, (PAD1_CTRL-PAD1_DATA, a2)
	rts



initial_regs:
	vdpreg MODE_2, $4    ;Mode 5, everything turned off
	vdpreg MODE_1, $4
	vdpreg SCROLL_A, $20 ;Scroll a table $8000
	vdpreg SCROLL_B, $05 ;Scroll b table $A000
	vdpreg SAT, $60      ;SAT table $C000
	vdpreg BG_COLOR, 0
	vdpreg HINT, $FF
	vdpreg MODE_3, 0     ;full screen scroll
	vdpreg MODE_4, $87   ;40 cell mode, double-res interlace
	vdpreg HSCROLL, 0
	vdpreg AUTOINC, 2
	vdpreg SCROLL, 1     ;64x32 scroll size
end_initial_regs

start:
	lea $FF0000, a0
	moveq #0, d0
	move.w #($10000/8 - 1), d1
.clearloop:
	move.l d0, (a0)+
	move.l d0, (a0)+
	dbra d1, .clearloop

	lea $C00000, a0
	lea $C00004, a1

	moveq #(end_initial_regs-initial_regs-1), d0
	lea initial_regs.w, a2
.regloop
	move.w (a2)+, (a1)
	dbra d0, .regloop

	vdpaccess $0, VDP_CRAM_WRITE
	move.w #$020, (a0)
	move.w #$EEE, (a0)
	move.w #$222, (a0)

	;init scroll table
	vdpaccess $0, VDP_VRAM_WRITE
	move.w #0, (a0)
	move.w #4, (a0)

	;load tiles
	vdpaccess $800, VDP_VRAM_WRITE
	lea font(pc), a2
	move.w #((cursorend-font)/4 - 1), d0
tloop:
	move.l (a2)+, (a0)
	dbra d0, tloop


	;setup SAT
	;;vdpaccess $C000, VDP_VRAM_WRITE

	lea sprite_list.w, a2
	;left arrow
	move.l #$01080501, (a2)+
	move.l #$807F0086, (a2)+

	;right arrow
	move.l #$01080500, (a2)+
	move.l #$887F01AA, (a2)+
	move.b #2, num_sprites.w

menu_start:
	lea page_pointers.w, a5
	lea dir_buffer, a6
	move.l a6, (a5)+
	move.l a5, page_stack.w
	lea menu_port, a2
	move.l a6, (a2)

wait_complete:
	tst.w (a2)
	bne wait_complete

render_page:
	;clear name tables
	vdpaccess $8000, VDP_VRAM_WRITE
	moveq #32, d0
	swap d0
	move.b #32, d0
	move.w #(64*64-1), d1
ploop:
	move.l d0, (a0)
	dbra d1, ploop

	move.l #$40860002, d3
	move.l d3, (a1)
	move.l d3, base_cmd.w

	move.b #0, more_pages.w
	lea page_index.w, a3
	moveq #MAX_DISPLAY-1, d7
file_loop:
	tst.b (a6)+
	beq done_files
	addq #1, a6 ;TODO: Do something with directory flag

	;skip over entries starting with a dot except ..
	cmp.b #$2E, (a6)
	bne normal
	cmp.b #$2E, (1, a6)
	beq normal
	addq #1, a6
.skip_loop:
	tst.b (a6)+
	bne .skip_loop
	addq #1, d7
	move.l a6, d6
	bra skip
normal:
	;save entry pointer to page index
	move.l a6, (a3)+
	;print name on screen
	moveq #0, d0
	bsr print_string
	move.l a6, d6

	lea Newline(pc), a6
	bsr print_string

skip:
	;word align pointer
	addq #1, d6
	and.w #$FFFE, d6
	move.l d6, a6

	dbra d7, file_loop
	tst.b (a6)
	beq done_files
	move.b #1, more_pages.w
done_files:
	move.l page_stack.w, a5
	move.l a6, (a5)+
	move.l a5, page_stack.w

	;null terminate page_index
	moveq #0, d0
	move.l d0, (a3)

	;setup gamepads
	move.b #$40, PAD1_CTRL
	move.b #$40, PAD2_CTRL

	move.w #$8174, (a1) ;enable display, vertical interrupts, DMA


wait_forever
	stop #2500
	bra wait_forever

Newline:
	dc.b $A, 0

	align 1

;Prints a null terminated string
;a6 - pointer to string
;a0 - VDP data port
;d0 - base tile attribute
;
;Clobbers: d1.w, d2.w, d3.l
print_string:
	lea widths(pc), a5
	move.w x_pos.w, d2
	move.l base_cmd.w, d3
.loop
	moveq #0, d1
	move.b (a6)+, d1
	beq .end
	cmp.b #$A, d1
	beq .newline
	tst.b (-32, a5, d1.w)
	beq .narrow
	add.w d0, d1
	move.w d1, (a0)
	addq #2, d2
	bra .loop
.narrow
	add.w d0, d1
	move.w d1, (a0)
	addq #1, d2
	move.l d2, d1
	;switch to other plane
	and.w #$FFFE, d1
	swap d1
	eor.l #$20000000, d3
	add.l d3, d1
	move.l d1, (a1)
	bra .loop
.newline
	moveq #0, d2
	;switch back to plane A
	and.l #$DFFFFFFF, d3
	;skip to next row
	add.l #$00800000, d3
	move.l d3, (a1)
	bra .loop
.end
	move.w d2, x_pos.w
	move.l d3, base_cmd.w
	rts

	align 1
font:
	incbin font_interlace_variable.tiles
fontend
arrow:
	incbin arrow.tiles
arrowend:
cursor:
	incbin cursor.tiles
cursorend:
button:
	incbin button.tiles
buttonend:

widths:
	dc.b 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1
	dc.b 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0
	dc.b 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1
	dc.b 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
	dc.b 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1

rom_end: