Mercurial > repos > blastem
view menu.s68 @ 1971:80920c21bb52
Add an event log soft flush and call it twice per frame in between hard flushes to netplay latency when there are insufficient hardware updates to flush packets in the middle of a frame
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 08 May 2020 11:40:30 -0700 |
parents | 7f4fac75b484 |
children |
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 "JU " ;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 ifeq NARG-2 move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), (a1) else move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), \3 endif 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 load_rom_port equ (menu_port+2*4) lock_on_port equ (menu_port+8*4) 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 menu_functions rs.l 1 cursor_show_fun rs.l 1 special_click rs.l 1 rom_load_addr rs.l 1 mouse_x rs.w 1 selection_top rs.w 1 selection_bot rs.w 1 selection_mask 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 num_menu rs.b 1 num_slots rs.b 1 port_off 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 move.w (menu_port+4*7), d0 btst #0, d0 bne show_pause_menu ;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: tst.b num_menu.w bne handle_buttons_menu tst.b num_slots.w bne handle_buttons_save moveq #16, d2 btst #3, d1 bne right btst #2, d1 bne left buttons_no_leftright btst #1, d1 bne down btst #0, d1 bne up btst #7, d1 bne select_entry btst #5, d1 bne select_entry handle_done: rts handle_buttons_menu moveq #48, d2 bra buttons_no_leftright handle_buttons_save moveq #32, d2 bra buttons_no_leftright down: ;check if we are already at the bottom of the page moveq #1, d0 add.b (selected).w, d0 tst.b num_menu.w bne .menu tst.b num_slots.w bne .slots move.w d0, d1 add.w d1, d1 add.w d1, d1 lea page_index.w, a2 tst.l (0, a2, d1.w) beq handle_done .do_move move.b d0, (selected).w add.w d2, (sprite_list).w add.w d2, (sprite_list+8).w rts .menu: cmp.b num_menu.w, d0 beq handle_done bra .do_move .slots: cmp.b num_slots.w, d0 beq handle_done bra .do_move 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 tst.b num_menu.w bne .select_menu_button tst.b num_slots.w bne .select_save_slot lea page_index.w, a2 move.l (0, a2, d0.w), a2 tst.b (-1, a2) bne enter_dir ;regular file move.l rom_load_addr.w, a3 move.l a2, (a3) addq #6, a7 bra show_pause_menu .select_menu_button: movea.l menu_functions.w, a2 move.l (0, a2, d0.w), a2 addq #6, a7 jmp (a2) .select_save_slot: lea menu_port, a3 moveq #0, d0 move.b port_off.w, d0 add.w d0, a3 move.b selected.w, d0 move.l d0, (a3) addq #6, a7 jmp show_pause_menu 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 #$00EA0500, (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 move.l cursor_show_fun.w, d2 beq .skip_show_check move.l d2, a2 jsr (a2) .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 selection_top.w, d1 blo .done cmp.w selection_bot.w, d1 bhi .special_click tst.b num_menu.w bne .handle_menu tst.b num_slots.w bne .handle_slots 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 bra .normal_click .handle_menu ;TODO: FIXME and.w #$FFF0, d1 moveq #0, d0 move.w d1, d0 sub.w selection_top.w, d0 divu.w #48, d0 swap d0 tst.w d0 beq .no_adjust cmp.w #16, d0 bne .round_up swap d0 sub.w #16, d1 bra .set_cursor_pos .round_up swap d0 addq #1, d0 add.w #16, d1 bra .set_cursor_pos .no_adjust swap d0 .set_cursor_pos move.w d1, (sprite_list).w move.w d1, (sprite_list+8).w move.b d0, selected.w bra .normal_click .handle_slots and.w #$FFE0, d1 subq #8, d1 move.w d1, (sprite_list).w move.w d1, (sprite_list+8).w sub.w #264, d1 lsr.w #5, d1 move.b d1, selected.w .normal_click btst #0, d4 bne select_entry .done rts .no_mouse_move tst.b mouse_shown bne .skip_show_check rts .special_click: btst #0, d4 beq .done move.l special_click.w, d2 beq .done move.l d2, a2 jmp (a2) 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 topcorner equ (button-font)/64 + 32 topmiddle equ topcorner+1 botcorner equ topmiddle+1 botmiddle equ botcorner+1 horiz_flip equ $800 vert_flip equ $1000 ; draws a button ; d0.w - x in cells ; d1.w - y in cells ; d2.w - width in cells ; ; clobbers a6 draw_button: ;multiply x by 2 add.w d0, d0 ;multiply y by 128 lsl.w #7, d1 add.w d1, d0 add.w #$A000, d0 move.w d0, d1 and.w #$3FFF, d0 rol.w #2, d1 and.w #3, d1 ori.w #(VDP_VRAM_WRITE >> 16), d0 swap d0 move.w d1, d0 move.l d0, (a1) move.w d2, d1 ;top left corner move.w #topcorner, (a0) subq #3, d1 bmi .notopmiddle .toploop: ;top middle move.w #topmiddle, (a0) dbra d1, .toploop .notopmiddle ;top right corner move.w #(topcorner | horiz_flip), (a0) ;go to next row in name table add.l #((2*64) << 16), d0 move.l d0, (a1) ;bottom left corner move.w #botcorner, (a0) subq #3, d2 bmi .nomiddlebot .botloop: ;bottom middle move.w #botmiddle, (a0) dbra d2, .botloop .nomiddlebot ;bottom right corner move.w #(botcorner | horiz_flip), (a0) rts ;a5 - menu pointer ;d6 - initial Y position of menu draw_menu: moveq #0, d7 moveq #0, d5 ;clear out save slot state move.b d5, num_slots.w ;clear out event handlers move.l d5, cursor_show_fun.w move.l d5, special_click.w ;select first item move.b d7, selected.w ;save menu pointer for second pass movea.l a5, a4 ;adjust arrow mask move.w #$FFE0, selection_mask.w .lenloop tst.b (a5) beq .lendone addq #1, d5 movea.l a5, a6 bsr strlen cmp.w d7, d0 blo .nochange move.w d0, d7 .nochange lea (1, a5, d0.w), a5 bra .lenloop .lendone addq #2, d7 move.b d5, num_menu.w ;calculate X position move.w d7, d4 lsr.w #1, d4 moveq #20, d5 sub.w d4, d5 ;calculate left arrow X move.w d5, d4 lsl.w #3, d4 add.w #(128-24), d4 move.w d4, (sprite_list+6).w ;calculate right arrow x move.w d7, d3 lsl.w #3, d3 add.w d3, d4 add.w #32, d4 move.w d4, (sprite_list+6+8).w ;update left arrow Y move.w d6, d4 lsl.w #4, d4 add.w #256, d4 move.w d4, (sprite_list).w move.w d4, (sprite_list+8).w ;update mouse top limit move.w d4, selection_top.w ;restore menu pointer movea.l a4, a5 .drawloop tst.b (a5) beq .done ;x pos move.w d5, d0 ;y pos move.w d6, d1 ;width move.w d7, d2 bsr draw_button movea.l a5, a6 bsr strlen movea.l a5, a6 lea (1, a5, d0.w), a5 ;x pos move.w d7, d1 lsr.w #1, d1 add.w d5, d1 lsr.w #1, d0 sub.w d0, d1 ;y pos move.w d6, d2 ;base attribute move.w #$206B, d0 bsr print_string_fixed addq #3, d6 bra .drawloop .done ;update mouse bottom limit lsl.w #4, d6 add.w #224, d6 move.w d6, selection_bot.w rts clear_screen: ;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 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 #$400, (a0) move.w #$EEE, (a0) move.w #$222, (a0) ;init scroll table vdpaccess $0, VDP_VRAM_WRITE move.w #0, (a0) move.w #0, (a0) ;load tiles vdpaccess $800, VDP_VRAM_WRITE lea font(pc), a2 move.w #((buttonend-font)/4 - 1), d0 tloop: move.l (a2)+, (a0) dbra d0, tloop move.w #((fontfixedend-fontfixed)/4 - 1), d0 dtloop: move.l (a2)+, d1 move.l d1, (a0) move.l d1, (a0) dbra d0, dtloop ;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 show_main_menu: bsr clear_screen ;init vertical scroll RAM vdpaccess $0, VDP_VSRAM_WRITE move.w #-4, (a0) move.w #0, (a0) moveq #8, d6 move.l #main_menu_func, menu_functions.w lea main_menu(pc), a5 bsr draw_menu bra gamepad_setup show_pause_menu: bsr clear_screen ;init vertical scroll RAM vdpaccess $0, VDP_VSRAM_WRITE move.w #-4, (a0) move.w #0, (a0) moveq #8, d6 move.l #pause_menu_func, menu_functions.w lea pause_menu(pc), a5 bsr draw_menu bra gamepad_setup lock_on: move.l #lock_on_port, rom_load_addr.w bra menu_common menu_start: move.l #load_rom_port, rom_load_addr.w menu_common: moveq #0, d0 ;init vertical scroll RAM vdpaccess $0, VDP_VSRAM_WRITE move.w d0, (a0) move.w d0, (a0) ;reset arrow position move.w #$0108, sprite_list.w move.w #$0108, (sprite_list + 8).w move.w #$0086, (sprite_list + 6).w move.w #$01AA, (sprite_list + 6 + 8).w ;reset selection move.b d0, selected.w ;reset special click handler move.l d0, special_click.w 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: bsr clear_screen ;clear menu state move.b #0, num_menu.w move.w #272, selection_top.w move.w #655, selection_bot.w move.w #$FFF0, selection_mask.w ;init scroll table vdpaccess $0, VDP_VRAM_WRITE move.w #0, (a0) move.w #4, (a0) 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) tst.b mouse_shown beq .no_mouse tst.b more_pages.w beq .no_next_page ;draw Next button moveq #30, d0 moveq #26, d1 moveq #6, d2 bsr draw_button ;base attribute move.w #$206B, d0 ;x pos moveq #32, d1 ;y pos moveq #26, d2 lea next_str(pc), a6 bsr print_string_fixed .no_next_page cmp.l #(page_pointers+8), a5 beq .no_prev_page ;draw Prev button moveq #3, d0 moveq #26, d1 moveq #6, d2 bsr draw_button ;base attribute move.w #$206B, d0 ;x pos moveq #5, d1 ;y pos moveq #26, d2 lea prev_str(pc), a6 bsr print_string_fixed .no_prev_page move.l #0, cursor_show_fun.w bra .done_page_buttons .no_mouse move.l #show_prev_next_buttons, cursor_show_fun.w .done_page_buttons move.l #handle_prev_next_click, special_click.w gamepad_setup: ;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 handle_prev_next_click: ;make sure we're actually low enough cmp.w #663, d1 bls .no_prev_page tst.b more_pages.w beq .no_next_page cmp.w #373, d0 blo .no_next_page cmp.w #419, d0 bhi .no_next_page ;switch to the next page move.l page_stack.w, a6 move.l (-4, a6), a6 add.w #10, a7 bra render_page .no_next_page cmp.l #(page_pointers+8), a5 beq .no_prev_page cmp.w #157, d0 blo .no_prev_page cmp.w #203, d0 bhi .no_prev_page ;switch to previous page lea (-12, a5), a5 move.l (a5)+, a6 move.l a5, page_stack.w add.w #10, a7 bra render_page .no_prev_page rts show_prev_next_buttons: movem.l d0-d2/a6, -(a7) tst.b more_pages.w beq .no_next_page ;draw Next button moveq #30, d0 moveq #26, d1 moveq #6, d2 bsr draw_button ;base attribute move.w #$206B, d0 ;x pos moveq #32, d1 ;y pos moveq #26, d2 lea next_str(pc), a6 bsr print_string_fixed .no_next_page cmp.l #(page_pointers+8), a5 beq .no_prev_page ;draw Prev button moveq #3, d0 moveq #26, d1 moveq #6, d2 bsr draw_button ;base attribute move.w #$206B, d0 ;x pos moveq #5, d1 ;y pos moveq #26, d2 lea prev_str(pc), a6 bsr print_string_fixed .no_prev_page move.l #0, cursor_show_fun.w movem.l (a7)+, d0-d2/a6 rts show_about: bsr clear_screen moveq #1, d7 lea about_text(pc), a6 ;base attribute move.w #$006B, d0 .loop tst.b (a6) beq .done ;x pos moveq #1, d1 ;y pos move.w d7, d2 bsr print_string_fixed addq #1, d7 bra .loop .done moveq #8, d6 move.l #about_menu_func, menu_functions.w lea about_menu(pc), a5 bsr draw_menu .wait stop #$2500 bra .wait exit: move.l #1, menu_port+12 bra exit resume: move.l #2, menu_port+12 bra show_pause_menu show_save_slots: move.w #(256+26), sprite_list.w move.w #(256+26), (sprite_list+8).w move.w #(128+8), (sprite_list+6).w move.w #(128+320-24), (sprite_list+6+8).w move.w #(256+32), selection_top.w move.b #0, selected.w move.b #0, num_menu.w lea dir_buffer, a6 lea menu_port+16, a3 move.l a6, (a3) .waitdone: tst.w (a3) bne .waitdone bsr clear_screen moveq #0, d0 moveq #0, d6 moveq #2, d7 .slotloop tst.b (a6) beq .done addq #1, d6 moveq #4, d1 move.w d7, d2 bsr print_string_fixed addq #2, d7 bra .slotloop .done lsl.w #4, d7 add.w #248, d7 move.w d7, selection_bot.w move.b d6, num_slots.w rts save_state: move.b #(5*4), port_off.w bsr show_save_slots .wait stop #$2500 bra .wait load_state: move.b #(6*4), port_off.w bsr show_save_slots .wait stop #$2500 bra .wait next_str: dc.b "Next", 0 prev_str: dc.b "Prev", 0 about_text: dc.b "BlastEm v0.6.3-pre", 0 dc.b "Copyright 2011-2019 Michael Pavone", 0 dc.b " ", 0 dc.b "BlastEm is a high performance, open", 0 dc.b "source (GPLv3) Genesis/Megadrive", 0 dc.b "emulator.",0 dc.b " ", 0 dc.b " ", 0 dc.b " ", 0 dc.b " ", 0 dc.b " --- Special Thanks ---", 0 dc.b " ", 0 dc.b "Nemesis: Documentatino and test ROMs", 0 dc.b "Charles MacDonald: Documentation", 0 dc.b "Eke-Eke: Documentation", 0 dc.b "Bart Trzynadlowski: Documentation", 0 dc.b "KanedaFR: Hosting the best Sega forum", 0 dc.b "Titan: Awesome demos and documentation", 0 dc.b "flamewing: BCD info and test ROM", 0 dc.b "r57shell: Opcode size test ROM", 0 dc.b "micky: Testing", 0 dc.b "Sasha: Testing", 0 dc.b "lol-frank: Testing", 0 dc.b "Sik: Testing", 0 dc.b "Tim Lawrence : Testing", 0 dc.b "ComradeOj: Testing", 0 dc.b "Vladikcomper: Testing", 0 dc.b 0 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 ;Prints a null-terminated string with a fixed width font ;a6 - pointer to string ;a0 - VDP data port ;d0 - base tile attribute ;d1 - x col ;d2 - y col ; print_string_fixed: ;multiply x by 2 add.w d1, d1 ;multiply y by 128 lsl.w #7, d2 add.w d2, d1 add.w #$8000, d1 move.w d1, d2 and.w #$3FFF, d1 rol.w #2, d2 and.w #3, d2 ori.w #(VDP_VRAM_WRITE >> 16), d1 swap d1 move.w d2, d1 move.l d1, (a1) .loop moveq #0, d1 move.b (a6)+, d1 beq .end add.w d0, d1 move.w d1, (a0) bra .loop .end rts ;Returns string length in d0 ;a6 - pointer to string strlen: moveq #-1, d0 .loop addq #1, d0 tst.b (a6)+ bne .loop 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: fontfixed: incbin font.tiles fontfixedend: 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 main_menu: dc.b "Load ROM", 0 dc.b "About", 0 dc.b "Exit", 0 dc.b 0 align 1 main_menu_func: dc.l menu_start dc.l show_about dc.l exit about_menu: dc.b "Return", 0 dc.b 0 align 1 about_menu_func: dc.l show_main_menu pause_menu: dc.b "Resume", 0 dc.b "Load ROM", 0 dc.b "Lock On", 0 dc.b "Save State", 0 dc.b "Load State", 0 dc.b "Exit", 0 dc.b 0 align 1 pause_menu_func dc.l resume dc.l menu_start dc.l lock_on dc.l save_state dc.l load_state dc.l exit rom_end: