From 611a58dcd2de03c9881a9d9d4f3c0ff5e024cfbf Mon Sep 17 00:00:00 2001 From: paulb-nl Date: Sun, 11 Apr 2021 15:50:47 +0200 Subject: [PATCH 1/2] CPU: Write on cycle T2&T3. (Fix Conker Pocket Tales glitches) --- rtl/T80/GBse.vhd | 10 ++++++++-- rtl/gb.v | 43 ++++++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/rtl/T80/GBse.vhd b/rtl/T80/GBse.vhd index bcd3ca0..9824ae0 100644 --- a/rtl/T80/GBse.vhd +++ b/rtl/T80/GBse.vhd @@ -77,7 +77,7 @@ use work.pReg_savestates.all; entity GBse is generic( - T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + T2Write : integer := 2; -- 0 => WR_n active in T3, 1 => WR_n active in T2, Other => WR_n active in T2+T3 IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle ); port( @@ -231,12 +231,18 @@ begin IORQ_n <= not IORQ; MREQ_n <= IORQ; end if; - else + elsif T2Write = 1 then if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then WR_n <= '0'; IORQ_n <= not IORQ; MREQ_n <= IORQ; end if; + else + if (TState = "001" or TState = "010") and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; end if; end if; if TState = "011" and Wait_n = '1' then diff --git a/rtl/gb.v b/rtl/gb.v index 79ef239..186f9e3 100644 --- a/rtl/gb.v +++ b/rtl/gb.v @@ -117,10 +117,10 @@ wire [4:0] Savestate_RAMRWrEn; localparam SAVESTATE_MODULES = 7; wire [63:0] SaveStateBus_wired_or[0:SAVESTATE_MODULES-1]; -wire [53:0] SS_Top; -wire [53:0] SS_Top_BACK; +wire [54:0] SS_Top; +wire [54:0] SS_Top_BACK; -eReg_SavestateV #(0, 31, 53, 0, 64'h0000000000800001) iREG_SAVESTATE_Top (clk_sys, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[6], SS_Top_BACK, SS_Top); +eReg_SavestateV #(0, 31, 54, 0, 64'h0000000000800001) iREG_SAVESTATE_Top (clk_sys, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[6], SS_Top_BACK, SS_Top); // include cpu reg boot_rom_enabled; @@ -263,6 +263,15 @@ always @ (posedge clk) begin reset_r <= reset; end +reg old_cpu_wr_n; + +assign SS_Top_BACK[54] = old_cpu_wr_n; + +always @(posedge clk_sys) begin + if(reset_ss) old_cpu_wr_n <= SS_Top[54]; // 1'b0 + else if (cpu_clken) old_cpu_wr_n <= cpu_wr_n; +end +wire cpu_wr_n_edge = ~(old_cpu_wr_n & ~cpu_wr_n); wire cpu_stop; @@ -328,7 +337,7 @@ always @(posedge clk_sys) begin cpu_speed <= SS_Top[3]; // 1'b0; prepare_switch <= SS_Top[4]; // 1'b0; end - else if (ce_2x && sel_key1 && !cpu_wr_n)begin + else if (ce_2x && sel_key1 && !cpu_wr_n_edge)begin prepare_switch <= cpu_do[0]; end @@ -343,7 +352,7 @@ end // -------------------------------------------------------------------- wire audio_rd = !cpu_rd_n && sel_audio; -wire audio_wr = !cpu_wr_n && sel_audio; +wire audio_wr = !cpu_wr_n_edge && sel_audio; gbc_snd audio ( .clk ( clk_sys ), @@ -384,7 +393,7 @@ link link ( .sel_sc(sel_sc), .sel_sb(sel_sb), - .cpu_wr_n(cpu_wr_n), + .cpu_wr_n(cpu_wr_n_edge), .sc_start_in(cpu_do[7]), .sc_int_clock_in(cpu_do[0]), @@ -417,7 +426,7 @@ assign SS_Top_BACK[6:5] = p54; always @(posedge clk_sys) begin if(reset_ss) p54 <= SS_Top[6:5]; //2'b00 for DMG, 2'b11 for CGB/SGB will be written by BIOS - else if(ce_cpu && sel_joy && !cpu_wr_n) p54 <= cpu_do[5:4]; + else if(ce_cpu && sel_joy && !cpu_wr_n_edge) p54 <= cpu_do[5:4]; end assign joy_do = { 2'b11, p54, joy_din }; @@ -438,7 +447,7 @@ always @(posedge clk_sys) begin FF73 <= SS_Top[42:35]; // 0; FF74 <= SS_Top[50:43]; // 0; FF75 <= SS_Top[53:51]; // 0; - end else if(ce_cpu && !cpu_wr_n) begin + end else if(ce_cpu && !cpu_wr_n_edge) begin if (sel_FF72) FF72 <= cpu_do; if (sel_FF73) FF73 <= cpu_do; if (sel_FF74) FF74 <= cpu_do; @@ -536,11 +545,11 @@ always @(negedge clk_sys) begin //negedge to trigger interrupt earlier end // cpu writes interrupt enable register - if(sel_ie && !cpu_wr_n) + if(sel_ie && !cpu_wr_n_edge) ie_r <= cpu_do; // cpu writes interrupt flag register - if(sel_if && !cpu_wr_n) + if(sel_if && !cpu_wr_n_edge) if_r <= cpu_do[4:0]; end @@ -559,7 +568,7 @@ timer timer ( .cpu_sel ( sel_timer ), .cpu_addr ( cpu_addr[1:0] ), - .cpu_wr ( !cpu_wr_n ), + .cpu_wr ( !cpu_wr_n_edge ), .cpu_di ( cpu_do ), .cpu_do ( timer_do ), @@ -595,7 +604,7 @@ video video ( .cpu_sel_reg ( sel_video_reg ), .cpu_sel_oam ( sel_video_oam ), .cpu_addr ( cpu_addr[7:0] ), - .cpu_wr ( !cpu_wr_n ), + .cpu_wr ( !cpu_wr_n_edge ), .cpu_di ( cpu_do ), .cpu_do ( video_do ), @@ -689,7 +698,7 @@ always @(posedge clk_sys) begin if(reset_ss) vram_bank <= SS_Top[22]; // 1'd0; else if (ce_cpu) begin - if((cpu_addr == 16'hff4f) && !cpu_wr_n && isGBC) + if((cpu_addr == 16'hff4f) && !cpu_wr_n_edge && isGBC) vram_bank <= cpu_do[0]; end end @@ -707,7 +716,7 @@ hdma hdma( // cpu register interface .sel_reg ( sel_hdma ), .addr ( cpu_addr[3:0] ), - .wr ( !cpu_wr_n ), + .wr ( !cpu_wr_n_edge ), .dout ( hdma_do ), .din ( cpu_do ), @@ -784,7 +793,7 @@ assign SS_Top_BACK[2:0] = iram_bank; always @(posedge clk_sys) begin if(reset_ss) iram_bank <= SS_Top[2:0]; // 3'd1; - else if(ce_cpu && sel_iram_bank && !cpu_wr_n) begin + else if(ce_cpu && sel_iram_bank && !cpu_wr_n_edge) begin if (cpu_do[2:0]==3'd0) // 0 -> 1; iram_bank <= 3'd1; else @@ -804,7 +813,7 @@ always @(posedge clk_sys) begin if(reset_ss) boot_rom_enabled <= SS_Top[23]; // 1'b1; else if (ce) begin - if((cpu_addr == 16'hff50) && !cpu_wr_n) + if((cpu_addr == 16'hff50) && !cpu_wr_n_edge) if ((isGBC && cpu_do[7:0]==8'h11) || (!isGBC && cpu_do[0])) boot_rom_enabled <= 1'b0; end @@ -830,7 +839,7 @@ assign is_hdma_cart_addr = (hdma_sel_rom || hdma_sel_cram); //rom or external ra assign cart_di = cpu_do; assign cart_addr = (isGBC&&hdma_rd&&is_hdma_cart_addr)?hdma_source_addr:(dma_rd&&is_dma_cart_addr)?dma_addr:cpu_addr; assign cart_rd = (isGBC&&hdma_rd&&is_hdma_cart_addr) || (dma_rd&&is_dma_cart_addr) || ((sel_rom || sel_cram) && !cpu_rd_n); -assign cart_wr = (sel_rom || sel_cram) && !cpu_wr_n && !hdma_rd; +assign cart_wr = (sel_rom || sel_cram) && !cpu_wr_n_edge && !hdma_rd; assign gbc_bios_addr = hdma_rd?hdma_source_addr[11:0]:cpu_addr[11:0]; From 5824708107b71e7c51aa1612bb5e0e773e2b6400 Mon Sep 17 00:00:00 2001 From: paulb-nl Date: Sun, 11 Apr 2021 15:53:21 +0200 Subject: [PATCH 2/2] PPU: adjust Vblank interrupt (Fix Altered Space glitches on DMG) --- rtl/video.v | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/rtl/video.v b/rtl/video.v index dfca28f..b374d3a 100644 --- a/rtl/video.v +++ b/rtl/video.v @@ -238,14 +238,14 @@ wire h_clk_en_neg = (lcd_on && h_div_cnt == 2'd2); wire hcnt_end = (h_cnt == 7'd113); wire vblank = (v_cnt >= 144); -reg vblank_l, vblank_t, vblank_ll; +reg vblank_l, vblank_t; reg end_of_line, end_of_line_l; reg lyc_match_l, lyc_match_t; assign SS_Video3_BACK[0] = vblank_l; assign SS_Video3_BACK[1] = end_of_line; assign SS_Video3_BACK[2] = end_of_line_l; -assign SS_Video3_BACK[3] = vblank_ll; +assign SS_Video3_BACK[3] = 0; assign SS_Video3_BACK[6] = vblank_t; always @(posedge clk) begin @@ -253,17 +253,14 @@ always @(posedge clk) begin vblank_l <= SS_Video3[0]; //1'b0; end_of_line <= SS_Video3[1]; //1'b0; end_of_line_l <= SS_Video3[2]; //1'b0; - vblank_ll <= SS_Video3[3]; //1'b0; vblank_t <= SS_Video3[6]; //1'b0; end else if (!lcd_on) begin vblank_l <= 1'b0; end_of_line <= 1'b0; end_of_line_l <= 1'b0; - vblank_ll <= 1'b0; vblank_t <= 1'b0; end else if (ce) begin vblank_l <= vblank_t; - vblank_ll <= vblank_l; if (h_clk_en_neg & hcnt_end) end_of_line <= 1'b1; @@ -273,9 +270,6 @@ always @(posedge clk) begin // It also makes the OAM interrupt at line 0 after Vblank a few cycles late. if (h_clk_en) begin vblank_t <= vblank; - if (vblank_t & ~vblank & ~isGBC) begin // DMG: vblank falling edge must be 1 cycle faster to pass some tests. - vblank_l <= vblank; - end end // end_of_line is active for 4 cycles if (h_clk_en_neg) begin @@ -325,7 +319,7 @@ always @(posedge clk) begin end wire int_lyc = (stat[6] & lyc_match_l); -wire int_oam = (stat[5] & end_of_line_l & (isGBC ? ~vblank_l : ~vblank_ll) ); +wire int_oam = (stat[5] & end_of_line_l & ~vblank_l); wire int_vbl = (stat[4] & vblank_l); wire int_hbl = (stat[3] & mode3_end_l & ~vblank_l); @@ -355,8 +349,12 @@ always @(posedge clk) begin end end +// DMG: STAT reads mode 0 for 1 Tcycle between Vblank and mode 2 +// but the interrupt signals of Vblank and mode 2 do overlap +wire mode_vblank = isGBC ? vblank_l : (vblank_l & vblank_t); + assign mode = - vblank_l ? 2'b01 : + mode_vblank ? 2'b01 : oam_eval_l ? 2'b10 : mode3_l & ~mode3_end ? 2'b11 : 2'b00;