From 9c065aba10fca5a6730b3ebb903d2d7690997040 Mon Sep 17 00:00:00 2001 From: Eugene Lozovoy Date: Fri, 19 Jan 2024 13:29:59 +0300 Subject: [PATCH] implement fast forward --- README.md | 1 + cpld/rtl/cpu.sv | 7 ++++ cpld/rtl/magic.sv | 12 +++++-- cpld/rtl/ps2.v | 3 ++ cpld/rtl/top.sv | 9 ++++-- rom_src/config.asm | 1 + rom_src/main.asm | 80 ++++++++++++++++++++++++++-------------------- 7 files changed, 73 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index b1dfe1f..5bcaa85 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Sega gamepad support will be available starting from PCB rev.D (or Rev.C with sl | Button | Function | | - | - | | F1 | Pause | +| F2 | Fast forward | | F5 | Magic button | | F10 | Reboot | | F12 | Reboot | diff --git a/cpld/rtl/cpu.sv b/cpld/rtl/cpu.sv index 5fc6426..6853a5a 100644 --- a/cpld/rtl/cpu.sv +++ b/cpld/rtl/cpu.sv @@ -16,6 +16,7 @@ module cpu( input [2:0] ram_page128, input machine_t machine, input turbo_t turbo, + input fastforward, input hold, input ext_wait_cycle1, input ext_wait_cycle2, @@ -90,7 +91,13 @@ localparam INT_L_S128 = 6'd36; localparam INT_V_PENT = 239; localparam INT_H_PENT = 322; localparam INT_L_PENT = 6'd32; +localparam INT_V_FF1 = 0; +localparam INT_V_FF2 = 106; +localparam INT_V_FF3 = 212; +localparam INT_H_FF = 0; wire int_begin = + (fastforward)? + (vc == INT_V_FF1 || vc == INT_V_FF2 || vc == INT_V_FF3) && hc == INT_H_FF : (machine == MACHINE_S48)? vc == INT_V_S48 && hc == INT_H_S48 : (machine == MACHINE_S128 || machine == MACHINE_S3)? diff --git a/cpld/rtl/magic.sv b/cpld/rtl/magic.sv index f339251..ed8894b 100644 --- a/cpld/rtl/magic.sv +++ b/cpld/rtl/magic.sv @@ -14,6 +14,7 @@ module magic( input magic_button, input pause_button, + input fastforward_button, input div_paged, input basic48_paged, @@ -40,7 +41,8 @@ module magic( output reg sd_indication_en, output reg bright_boost, output reg zxkit1, - output reg joy_a_up + output reg joy_a_up, + output reg fastforward ); localparam magic_on_start = 1'b1; @@ -63,7 +65,7 @@ always @(posedge clk28 or negedge rst_n) begin opcode_is_reading <= 0; end else begin - if ((magic_button || pause_button) && n_int == 1'b1 && n_int_next == 1'b0) begin + if ((magic_button || pause_button || fastforward_button) && n_int == 1'b1 && n_int_next == 1'b0) begin if (!magic_mode) n_nmi <= 1'b0; magic_mode <= 1'b1; @@ -136,6 +138,7 @@ always @(posedge clk28 or negedge rst_n) begin magic_reboot <= 0; magic_beeper <= 0; rom_wren <= 0; + fastforward <= 0; end else if (config_cs && bus.wr) case (bus.a[15:8]) 8'h01: {rom_wren, magic_reboot, magic_beeper} <= bus.d[2:0]; @@ -154,11 +157,12 @@ always @(posedge clk28 or negedge rst_n) begin 8'h0E: autoturbo_en <= bus.d[0]; 8'h0F: zxkit1 <= bus.d[0]; 8'h10: joy_a_up <= bus.d[0]; + 8'h11: fastforward <= bus.d[0]; endcase end reg config_rd; -wire [7:0] config_data = {4'b0000, div_paged, 1'b1, pause_button, magic_button}; +wire [7:0] config_data = {4'b0000, div_paged, fastforward_button, pause_button, magic_button}; always @(posedge clk28 or negedge rst_n) begin if (!rst_n) config_rd <= 0; @@ -189,6 +193,8 @@ end always @(posedge clk28 or negedge rst_n) begin if (!rst_n) turbo <= TURBO_NONE; + else if (fastforward) + turbo <= TURBO_14; else if (autoturbo_en && div_paged && !magic_map) turbo <= TURBO_14; else if (autoturbo_en && |portfe_noturbo) diff --git a/cpld/rtl/ps2.v b/cpld/rtl/ps2.v index 0f1e13c..4abd27d 100644 --- a/cpld/rtl/ps2.v +++ b/cpld/rtl/ps2.v @@ -16,6 +16,7 @@ module ps2#( output reg key_magic, output reg key_reset, output reg key_pause, + output reg key_fastforward, output reg joy_up, output reg joy_down, output reg joy_left, @@ -57,6 +58,7 @@ always @(posedge clk or negedge rst_n) begin is_ext <= 0; key_magic <= 0; key_pause <= 0; + key_fastforward <= 0; {joy_up, joy_down, joy_left, joy_right, joy_fire} <= 0; {key2_a, key2_b, key2_c, key2_d, key2_e, key2_f, key2_g, key2_h, key2_i, key2_j, key2_k, key2_l, key2_m, key2_n} <= 0; {key2_o, key2_p, key2_q, key2_r, key2_s, key2_t, key2_u, key2_v, key2_w, key2_x, key2_y, key2_z, key2_0, key2_1} <= 0; @@ -137,6 +139,7 @@ always @(posedge clk or negedge rst_n) begin `PS2_PGDN: key2_pgdn <= is_press; `PS2_F1: key_pause <= is_press; + `PS2_F2: key_fastforward <= is_press; `PS2_F5: key_magic <= is_press; `PS2_F10: key_reset0 <= is_press; `PS2_F12: key_reset0 <= is_press; diff --git a/cpld/rtl/top.sv b/cpld/rtl/top.sv index cbc3f84..2950eb5 100644 --- a/cpld/rtl/top.sv +++ b/cpld/rtl/top.sv @@ -109,6 +109,7 @@ wire joy_a_up; wire div_map; wire div_mapram; wire basic48_paged; +wire fastforward; /* CPU BUS */ @@ -230,7 +231,7 @@ rgb rgb0( /* PS/2 KEYBOARD */ wire [4:0] ps2_kd; -wire ps2_key_magic; +wire ps2_key_magic, ps2_key_fastforward; wire ps2_joy_up, ps2_joy_down, ps2_joy_left, ps2_joy_right, ps2_joy_fire; `ifndef REV_C ps2 #(.CLK_FREQ(28_000_000)) ps2_0( @@ -243,6 +244,7 @@ ps2 #(.CLK_FREQ(28_000_000)) ps2_0( .key_magic(ps2_key_magic), .key_reset(ps2_key_reset), .key_pause(ps2_key_pause), + .key_fastforward(ps2_key_fastforward), .joy_up(ps2_joy_up), .joy_down(ps2_joy_down), .joy_left(ps2_joy_left), @@ -338,6 +340,7 @@ cpu cpu0( .machine(machine), .video_contention(video_contention), .turbo(turbo), + .fastforward(fastforward), .hold(mem_wait), .ext_wait_cycle2(ay_ext_wait_cycle2 | div_ext_wait_cycle2), @@ -389,6 +392,7 @@ magic magic0( .magic_button(~n_magic || joy_mode || ps2_key_magic), .pause_button(ps2_key_pause || joy_start), + .fastforward_button(ps2_key_fastforward), .div_paged(div_map && !div_mapram), .basic48_paged(basic48_paged), @@ -415,7 +419,8 @@ magic magic0( .sd_indication_en(sd_indication_en), .bright_boost(bright_boost), .zxkit1(zxkit1), - .joy_a_up(joy_a_up) + .joy_a_up(joy_a_up), + .fastforward(fastforward) ); diff --git a/rom_src/config.asm b/rom_src/config.asm index f427842..46ab376 100644 --- a/rom_src/config.asm +++ b/rom_src/config.asm @@ -46,6 +46,7 @@ bright DB BRIGHT_DEFAULT autoturbo DB 0 zxkit1 DB 0 joy_a_up DB 0 +fastforward DB 0 ENDS STRUCT CFGEXT_T diff --git a/rom_src/main.asm b/rom_src/main.asm index 46b7702..d891a15 100644 --- a/rom_src/main.asm +++ b/rom_src/main.asm @@ -56,6 +56,8 @@ startup_handler: call detect_external_bdi call check_custom_rom .warm_boot: + xor a + ld (cfg_saved.fastforward), a call load_config call init_cpld call save_initialized @@ -80,15 +82,18 @@ nmi_handler: ld (var_magic_enter_cnt), a ld (var_magic_leave_cnt), a .key_wait_loop: - call check_entering_pause ; A[1] == 1 if pause button is pressed - bit 1, a ; ... - jp nz, .enter_pause ; ... + xor a ; + in a, (#ff) ; + bit 2, a ; A[2] == 1 if fastforward button is pressed + jr nz, .enter_fastforward ; ... + bit 1, a ; A[1] == 1 if pause button is pressed + jr nz, .enter_pause ; ... call delay_10ms ; call check_entering_menu ; A == 1 if we are entering menu, A == 2 if we are leaving to... - bit 0, a ; ...default nmi handler, A == 0 otherwise - jp nz, .enter_menu ; ... - bit 1, a ; ... - jr z, .key_wait_loop ; ... + cp 1 ; ...default nmi handler, A == 0 otherwise + jr z, .enter_menu ; ... + cp 2 ; ... + jr nz, .key_wait_loop ; ... .leave_no_key: xor a ; disable border ld bc, #01ff ; ... @@ -96,10 +101,14 @@ nmi_handler: ld bc, #00ff ; ... in a, (c) ; if divmmc paged - just do retn bit 3, a ; ... - jr nz, exit_with_ret ; ... + jp nz, exit_with_ret ; ... ld hl, #0066 ; otherwise jump to default nmi handler - jr exit_with_jp ; ... + jp exit_with_jp ; ... +.enter_fastforward: + ld hl, nmi_fastforward + ld (var_main_fun), hl + jr .enter .enter_pause: ld hl, nmi_pause ld (var_main_fun), hl @@ -231,6 +240,8 @@ load_user_config: .quirks: ; some options shouldn't be saved by user, so we just overwrite them from default config ld a, (CFG_DEFAULT.ay) ; AY should be disabled only by detect_external_ay ld (cfg_saved.ay), a ; ... + ld a, (CFG_DEFAULT.fastforward) + ld (cfg_saved.fastforward), a ret ; OUT - A = 1 if error, 0 if ok @@ -420,13 +431,6 @@ check_custom_rom: ret -; OUT - A bit 1 if we are entering pause, 0 otherwise -check_entering_pause: - xor a ; read pause key state in bit 1 of #00FF port - in a, (#ff) ; ... - ret - - ; OUT - A = 1 if we are entering menu, A = 2 if we are leaving menu, A = 0 otherwise ; OUT - F - garbage check_entering_menu: @@ -458,6 +462,10 @@ check_entering_menu: ; OUT - AF - garbage ; OUT - BC - garbage delay_10ms: + ld c, 7*4 + ld a, (cfg.fastforward) + or a + jr nz, .loop ld c, 7 ld a, (cfg.clock) or a @@ -624,8 +632,18 @@ bootmenu: ld hl, menuboot call menu_init call menu_input_loop - call wait_for_keys_release - ret + jp wait_for_keys_release + + +nmi_fastforward: + ld a, (cfg.fastforward) + xor 1 + ld (cfg.fastforward), a + ld bc, #11ff + out (c), a + ei + halt + jp wait_for_keys_release nmi_pause: @@ -639,19 +657,7 @@ nmi_pause: ld a, (var_exit_flag) or a jr z, .loop -.wait_for_pause_key_release: - xor a ; read magic/pause keys state from port #00FF - in a, (#ff) ; ... - and #03 ; ... - jr nz, .wait_for_pause_key_release - ei ; second read to fix start button bouncing on 8bitdo gamepad - halt ; ... -.wait_for_pause_key_release2: - xor a ; read magic/pause keys state from port #00FF - in a, (#ff) ; ... - and #03 ; ... - jr nz, .wait_for_pause_key_release2 - ret + jp wait_for_keys_release nmi_menu: @@ -674,8 +680,7 @@ nmi_menu: call menu_init .loop: call menu_input_loop - call wait_for_keys_release - ret + jp wait_for_keys_release menu_input_loop: @@ -697,6 +702,9 @@ menu_input_loop: wait_for_keys_release: + ld b, 2 ; second attempt to fix start button bouncing on 8bitdo gamepad +.attempt: + push bc .loop: ei halt @@ -704,10 +712,12 @@ wait_for_keys_release: xor a or b jr nz, .loop - xor a ; read magic/pause keys state from port #00FF + xor a ; read magic/pause/fastforward keys state from port #00FF in a, (#ff) ; ... - and #03 ; ... + and #07 ; ... jr nz, .loop + pop bc + djnz .attempt ret