From 31563c2ef64eebcac9864c2af01decac43c7df67 Mon Sep 17 00:00:00 2001 From: RobertPeip <53250236+RobertPeip@users.noreply.github.com> Date: Wed, 6 Jan 2021 08:33:24 +0100 Subject: [PATCH] improved rewind capture performance (#127) fixed random fastforward crash fixed fastforward Video glitches(HDMA) added fastforward toggle (short button press) added savestate OSD entry and multiple slots using keyboard(F1-F4) add MBC detection and address translation to simulation --- Gameboy.sv | 127 +++++++++- rtl/gb.v | 30 ++- rtl/gb_savestates.vhd | 16 +- rtl/speedcontrol.vhd | 18 +- rtl/video.v | 52 ++-- sim/src/gameboy/mbc.sv | 470 +++++++++++++++++++++++++++++++++++++ sim/src/tb/sdram_model.vhd | 25 +- sim/src/tb/tb.vhd | 85 +++++-- sim/vcom_all.bat | 1 + 9 files changed, 750 insertions(+), 74 deletions(-) create mode 100644 sim/src/gameboy/mbc.sv diff --git a/Gameboy.sv b/Gameboy.sv index 3e797ef..af0ed49 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -150,7 +150,7 @@ assign AUDIO_MIX = status[8:7]; // 0 1 2 3 // 01234567890123456789012345678901 // 0123456789ABCDEFGHIJKLMNOPQRSTUV -// XXXXXXXXXXXXXXXXXXXXX XXXXX +// XXXXXXXXXXXXXXXXXXXXX XXXXXXX `include "build_id.v" localparam CONF_STR = { @@ -170,6 +170,9 @@ localparam CONF_STR = { "h2RA,Save Backup RAM;", "OD,Autosave,Off,On;", "-;", + "h3RS,Save state (Alt-F1);", + "h3RT,Restore state (F1);", + "-;", "O34,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];", "OIK,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", "O5,Stabilize video(buffer),Off,On;", @@ -185,6 +188,16 @@ localparam CONF_STR = { "-;", "R0,Reset;", "J1,A,B,Select,Start,FastForward,SaveState,LoadState,Rewind;", + "I,", + "Save to state 1,", + "Restore state 1,", + "Save to state 2,", + "Restore state 2,", + "Save to state 3,", + "Restore state 3,", + "Save to state 4,", + "Restore state 4,", + "Rewinding...;", "V,v",`BUILD_DATE }; @@ -219,6 +232,7 @@ wire [15:0] ioctl_dout; reg ioctl_wait; wire [15:0] joystick_0, joystick_1, joystick_2, joystick_3; +wire [10:0] ps2_key; wire [7:0] filetype; @@ -263,7 +277,7 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io .buttons(buttons), .status(status), - .status_menumask({sav_supported,|tint,gg_available}), + .status_menumask({cart_ready,sav_supported,|tint,gg_available}), .direct_video(direct_video), .gamma_bus(gamma_bus), .forced_scandoubler(forced_scandoubler), @@ -271,7 +285,12 @@ hps_io #(.STRLEN($size(CONF_STR)>>3), .WIDE(1)) hps_io .joystick_0(joystick_0), .joystick_1(joystick_1), .joystick_2(joystick_2), - .joystick_3(joystick_3) + .joystick_3(joystick_3), + + .ps2_key(ps2_key), + + .info_req(ss_info_req), + .info(ss_info) ); /////////////////////////////////////////////////// @@ -287,7 +306,7 @@ wire [23:0] sdram_addr = cart_download? ioctl_addr[24:1]: {2'b00, mbc_bank, cart wire sdram_oe = ~cart_download & cart_rd & ~cram_rd; wire sdram_we = cart_download & dn_write; wire sdram_refresh_force; -wire sdram_autorefresh = !fastforward; +wire sdram_autorefresh = !ff_on; assign SDRAM_CKE = 1; @@ -577,6 +596,8 @@ wire [1:0] lcd_mode; wire lcd_on; wire lcd_vsync; +wire HDMA_on; + assign AUDIO_S = 0; wire reset = (RESET | status[0] | buttons[1] | cart_download | bk_loading); @@ -628,7 +649,9 @@ gb gb ( .lcd_mode ( lcd_mode ), .lcd_on ( lcd_on ), .lcd_vsync ( lcd_vsync ), + .speed ( speed ), + .HDMA_on ( HDMA_on ), // serial port .sc_int_clock2(sc_int_clock_out), @@ -645,9 +668,12 @@ gb gb ( .gg_available(gg_available), // savestates - .save_state (joystick_0[9]), - .load_state (joystick_0[10]), + .cart_ram_size (cart_ram_size), + .save_state (ss_save), + .load_state (ss_load), + .savestate_number(ss_base), .sleep_savestate (sleep_savestate), + .state_loaded (ss_loaded), .SaveStateExt_Din (SaveStateBus_Din), .SaveStateExt_Adr (SaveStateBus_Adr), @@ -810,6 +836,7 @@ wire ce_cpu, ce_cpu2x; wire cart_act = cart_wr | cart_rd; wire fastforward = joystick_0[8] && !ioctl_download && !OSD_STATUS; +wire ff_on; wire sleep_savestate; @@ -821,15 +848,48 @@ end speedcontrol speedcontrol ( .clk_sys (clk_sys), - .speed (speed), .pause (paused), - .speedup (fastforward), + .speedup (fast_forward), .cart_act (cart_act), + .HDMA_on (HDMA_on), .ce (ce_cpu), .ce_2x (ce_cpu2x), - .refresh (sdram_refresh_force) + .refresh (sdram_refresh_force), + .ff_on (ff_on) ); +///////////////////////////// Fast Forward Latch ///////////////////////////////// + +reg fast_forward; +reg ff_latch; + +always @(posedge clk_sys) begin : ffwd + reg last_ffw; + reg ff_was_held; + longint ff_count; + + last_ffw <= fastforward; + + if (fastforward) + ff_count <= ff_count + 1; + + if (~last_ffw & fastforward) begin + ff_latch <= 0; + ff_count <= 0; + end + + if ((last_ffw & ~fastforward)) begin // 32mhz clock, 0.2 seconds + ff_was_held <= 0; + + if (ff_count < 3200000 && ~ff_was_held) begin + ff_was_held <= 1; + ff_latch <= 1; + end + end + + fast_forward <= (fastforward | ff_latch); +end + ///////////////////////////// savestates ///////////////////////////////// wire [63:0] SaveStateBus_Din; @@ -866,6 +926,55 @@ ddram ddram .ch1_ready(ss_ack) ); +// saving with keyboard/OSD/gamepad +wire pressed = ps2_key[9]; +wire [7:0] code = ps2_key[7:0]; + +reg [1:0] ss_base = 0; +reg [7:0] ss_info; +reg ss_save, ss_load, ss_info_req; +wire ss_loaded; +always @(posedge clk_sys) begin + reg old_state; + reg alt = 0; + reg [1:0] old_st; + reg [1:0] old_st_joy; + + old_state <= ps2_key[10]; + + if(cart_ready) begin + if(old_state != ps2_key[10]) begin + case(code) + 'h11: alt <= pressed; + 'h05: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 0; end // F1 + 'h06: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 1; end // F2 + 'h04: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 2; end // F3 + 'h0C: begin ss_save <= pressed & alt; ss_load <= pressed & ~alt; ss_base <= 3; end // F4 + endcase + end + + old_st_joy <= joystick_0[10:9]; + if(old_st_joy[0] ^ joystick_0[9]) ss_save <= joystick_0[9]; + if(old_st_joy[1] ^ joystick_0[10]) ss_load <= joystick_0[10]; + if(joystick_0[10:9]) ss_base <= 0; + + old_st <= status[29:28]; + if(old_st[0] ^ status[28]) ss_save <= status[28]; + if(old_st[1] ^ status[29]) ss_load <= status[29]; + if(status[29:28]) ss_base <= 0; + + if(ss_load | ss_save) ss_info <= 7'd1 + {ss_base, ss_load}; + ss_info_req <= (ss_loaded | ss_save); + + // rewind info + if (status[27] & joystick_0[11]) begin + ss_info_req <= 1'b1; + ss_info <= 7'd9; + end + + end +end + ///////////////////////////// GBC BIOS ///////////////////////////////// wire [7:0] bios_do; diff --git a/rtl/gb.v b/rtl/gb.v index 4b81fab..bd06856 100644 --- a/rtl/gb.v +++ b/rtl/gb.v @@ -58,6 +58,7 @@ module gb ( input [3:0] joy_din, output speed, //GBC + output HDMA_on, input gg_reset, input gg_en, @@ -72,9 +73,12 @@ module gb ( output serial_data_out, // savestates - input save_state, - input load_state, - output sleep_savestate, + input [7:0] cart_ram_size, + input save_state, + input load_state, + input [1:0] savestate_number, + output sleep_savestate, + output state_loaded, output [63:0] SaveStateExt_Din, output [9:0] SaveStateExt_Adr, @@ -233,7 +237,7 @@ wire clk_cpu = clk_sys & ce_cpu; wire cpu_clken = !(isGBC && hdma_active) && ce_cpu; //when hdma is enabled stop CPU (GBC) reg reset_r = 1; -reg reset_ss = 1; +wire reset_ss; //sync reset with clock always @ (posedge clk) begin @@ -566,11 +570,11 @@ video video ( .dma_rd ( dma_rd ), .dma_addr ( dma_addr ), .dma_data ( dma_data ), - - .Savestate_OAMRAMAddr (Savestate_RAMAddr[7:0]), - .Savestate_OAMRAMRWrEn (Savestate_RAMRWrEn[2]), - .Savestate_OAMRAMWriteData (Savestate_RAMWriteData), - .Savestate_OAMRAMReadData (Savestate_RAMReadData_ORAM), + + .Savestate_OAMRAMAddr (Savestate_RAMAddr[7:0]), + .Savestate_OAMRAMRWrEn (Savestate_RAMRWrEn[2]), + .Savestate_OAMRAMWriteData (Savestate_RAMWriteData), + .Savestate_OAMRAMReadData (Savestate_RAMReadData_ORAM), .SaveStateBus_Din (SaveStateBus_Din ), .SaveStateBus_Adr (SaveStateBus_Adr ), @@ -675,6 +679,8 @@ hdma hdma( .SaveStateBus_Dout (SaveStateBus_wired_or[2]) ); +assign HDMA_on = hdma_active; + // -------------------------------------------------------------------- // -------------------------- zero page ram --------------------------- // -------------------------------------------------------------------- @@ -823,13 +829,15 @@ gb_savestates gb_savestates ( .reset_in (reset_r), .reset_out (reset_ss), - //.load_done (load_done), + .load_done (state_loaded), .save (savestate_savestate), .load (savestate_loadstate), .savestate_address (savestate_address), .savestate_busy (savestate_busy), + .cart_ram_size (cart_ram_size), + .lcd_vsync (lcd_vsync), .BUS_Din (SaveStateBus_Din), @@ -867,7 +875,7 @@ gb_statemanager #(58720256, 33554432) gb_statemanager ( .rewind_on (rewind_on), .rewind_active (rewind_active), - .savestate_number (1'b0), + .savestate_number (savestate_number), .save (save_state), .load (load_state), diff --git a/rtl/gb_savestates.vhd b/rtl/gb_savestates.vhd index 90cee83..caaa610 100644 --- a/rtl/gb_savestates.vhd +++ b/rtl/gb_savestates.vhd @@ -18,6 +18,8 @@ entity gb_savestates is savestate_address : in integer; savestate_busy : out std_logic; + cart_ram_size : in std_logic_vector(7 downto 0); + lcd_vsync : in std_logic; BUS_Din : out std_logic_vector(BUS_buswidth-1 downto 0) := (others => '0'); @@ -60,13 +62,13 @@ architecture arch of gb_savestates is constant SAVETYPESCOUNT : integer := 5; signal savetype_counter : integer range 0 to SAVETYPESCOUNT; type t_savetypes is array(0 to SAVETYPESCOUNT - 1) of integer; - constant savetypes : t_savetypes := + signal savetypes : t_savetypes := ( 32768, -- RAM 16384, -- VRAM 160, -- OAM 128, -- ZeroPage - 131072 -- Saveram + 131072 -- Saveram -> overwritten depending on cart_ram_size ); type tstate is @@ -126,6 +128,14 @@ begin --if (reset_in = '1') then -- header_amount <= (others => '0'); --end if; + + case (cart_ram_size) is + when x"00" => savetypes(4) <= 512; -- for MBC2 + when x"01" => savetypes(4) <= 2048; -- 2 KByte + when x"02" => savetypes(4) <= 8192; -- 8 KByte + when x"03" => savetypes(4) <= 32768; -- 32 KByte + when others => savetypes(4) <= 131072; -- 128 KByte + end case; case state is @@ -133,7 +143,7 @@ begin savetype_counter <= 0; if (reset_in = '1') then reset_out <= '1'; - BUS_rst <= '1'; + BUS_rst <= '1'; elsif (save = '1') then state <= SAVE_WAITVSYNC; header_amount <= header_amount + 1; diff --git a/rtl/speedcontrol.vhd b/rtl/speedcontrol.vhd index aa62228..97649dd 100644 --- a/rtl/speedcontrol.vhd +++ b/rtl/speedcontrol.vhd @@ -6,13 +6,14 @@ entity speedcontrol is port ( clk_sys : in std_logic; - speed : in std_logic; pause : in std_logic; speedup : in std_logic; cart_act : in std_logic; + HDMA_on : in std_logic; ce : out std_logic := '0'; ce_2x : buffer std_logic := '0'; - refresh : out std_logic := '0' + refresh : out std_logic := '0'; + ff_on : out std_logic := '0' ); end entity; @@ -63,7 +64,7 @@ begin state <= PAUSED; unpause_cnt <= 0; end if; - elsif (speedup = '1' and pause = '0') then + elsif (speedup = '1' and pause = '0' and HDMA_on = '0' and clkdiv = "000") then state <= FASTFORWARDSTART; fastforward_cnt <= 0; else @@ -92,17 +93,19 @@ begin when FASTFORWARDSTART => if (fastforward_cnt = 15) then state <= FASTFORWARD; + ff_on <= '1'; else fastforward_cnt <= fastforward_cnt + 1; end if; when FASTFORWARD => - if (pause = '1' or speedup = '0') then + if (pause = '1' or speedup = '0' or HDMA_on = '1') then state <= FASTFORWARDEND; fastforward_cnt <= 0; - end if; - - if (cart_act = '1' and cart_act_1 = '0') then + if (clkdiv(0) = '1') then + clkdiv <= "100"; + end if; + elsif (cart_act = '1' and cart_act_1 = '0') then state <= RAMACCESS; sdram_busy <= 1; elsif (cart_act = '0' and refreshcnt = 0) then @@ -121,6 +124,7 @@ begin when FASTFORWARDEND => if (fastforward_cnt = 15) then state <= NORMAL; + ff_on <= '0'; else fastforward_cnt <= fastforward_cnt + 1; end if; diff --git a/rtl/video.v b/rtl/video.v index 07be306..67e1580 100644 --- a/rtl/video.v +++ b/rtl/video.v @@ -362,7 +362,6 @@ generate end endgenerate -integer ii=0; always @(posedge clk) begin if(reset) begin @@ -383,24 +382,39 @@ always @(posedge clk) begin obpi_ai <= SS_Video2[ 45]; // 1'b0; lyc <= SS_Video2[53:46]; // 8'h00; - for (ii=0;ii<8;ii=ii+1)begin - bgpd[ii*8+0] <= SS_BPAL[ii][ 7: 0]; //8'h00; - bgpd[ii*8+1] <= SS_BPAL[ii][15: 8]; //8'h00; - bgpd[ii*8+2] <= SS_BPAL[ii][23:16]; //8'h00; - bgpd[ii*8+3] <= SS_BPAL[ii][31:24]; //8'h00; - bgpd[ii*8+4] <= SS_BPAL[ii][39:32]; //8'h00; - bgpd[ii*8+5] <= SS_BPAL[ii][47:40]; //8'h00; - bgpd[ii*8+6] <= SS_BPAL[ii][55:48]; //8'h00; - bgpd[ii*8+7] <= SS_BPAL[ii][63:56]; //8'h00; - obpd[ii*8+0] <= SS_OPAL[ii][ 7: 0]; //8'h00; - obpd[ii*8+1] <= SS_OPAL[ii][15: 8]; //8'h00; - obpd[ii*8+2] <= SS_OPAL[ii][23:16]; //8'h00; - obpd[ii*8+3] <= SS_OPAL[ii][31:24]; //8'h00; - obpd[ii*8+4] <= SS_OPAL[ii][39:32]; //8'h00; - obpd[ii*8+5] <= SS_OPAL[ii][47:40]; //8'h00; - obpd[ii*8+6] <= SS_OPAL[ii][55:48]; //8'h00; - obpd[ii*8+7] <= SS_OPAL[ii][63:56]; //8'h00; - end + bgpd[ 0] <= SS_BPAL[0][ 7: 0]; bgpd[16] <= SS_BPAL[2][ 7: 0]; bgpd[32] <= SS_BPAL[4][ 7: 0]; bgpd[48] <= SS_BPAL[6][ 7: 0]; //8'h00; + bgpd[ 1] <= SS_BPAL[0][15: 8]; bgpd[17] <= SS_BPAL[2][15: 8]; bgpd[33] <= SS_BPAL[4][15: 8]; bgpd[49] <= SS_BPAL[6][15: 8]; //8'h00; + bgpd[ 2] <= SS_BPAL[0][23:16]; bgpd[18] <= SS_BPAL[2][23:16]; bgpd[34] <= SS_BPAL[4][23:16]; bgpd[50] <= SS_BPAL[6][23:16]; //8'h00; + bgpd[ 3] <= SS_BPAL[0][31:24]; bgpd[19] <= SS_BPAL[2][31:24]; bgpd[35] <= SS_BPAL[4][31:24]; bgpd[51] <= SS_BPAL[6][31:24]; //8'h00; + bgpd[ 4] <= SS_BPAL[0][39:32]; bgpd[20] <= SS_BPAL[2][39:32]; bgpd[36] <= SS_BPAL[4][39:32]; bgpd[52] <= SS_BPAL[6][39:32]; //8'h00; + bgpd[ 5] <= SS_BPAL[0][47:40]; bgpd[21] <= SS_BPAL[2][47:40]; bgpd[37] <= SS_BPAL[4][47:40]; bgpd[53] <= SS_BPAL[6][47:40]; //8'h00; + bgpd[ 6] <= SS_BPAL[0][55:48]; bgpd[22] <= SS_BPAL[2][55:48]; bgpd[38] <= SS_BPAL[4][55:48]; bgpd[54] <= SS_BPAL[6][55:48]; //8'h00; + bgpd[ 7] <= SS_BPAL[0][63:56]; bgpd[23] <= SS_BPAL[2][63:56]; bgpd[39] <= SS_BPAL[4][63:56]; bgpd[55] <= SS_BPAL[6][63:56]; //8'h00; + bgpd[ 8] <= SS_BPAL[1][ 7: 0]; bgpd[24] <= SS_BPAL[3][ 7: 0]; bgpd[40] <= SS_BPAL[5][ 7: 0]; bgpd[56] <= SS_BPAL[7][ 7: 0]; //8'h00; + bgpd[ 9] <= SS_BPAL[1][15: 8]; bgpd[25] <= SS_BPAL[3][15: 8]; bgpd[41] <= SS_BPAL[5][15: 8]; bgpd[57] <= SS_BPAL[7][15: 8]; //8'h00; + bgpd[10] <= SS_BPAL[1][23:16]; bgpd[26] <= SS_BPAL[3][23:16]; bgpd[42] <= SS_BPAL[5][23:16]; bgpd[58] <= SS_BPAL[7][23:16]; //8'h00; + bgpd[11] <= SS_BPAL[1][31:24]; bgpd[27] <= SS_BPAL[3][31:24]; bgpd[43] <= SS_BPAL[5][31:24]; bgpd[59] <= SS_BPAL[7][31:24]; //8'h00; + bgpd[12] <= SS_BPAL[1][39:32]; bgpd[28] <= SS_BPAL[3][39:32]; bgpd[44] <= SS_BPAL[5][39:32]; bgpd[60] <= SS_BPAL[7][39:32]; //8'h00; + bgpd[13] <= SS_BPAL[1][47:40]; bgpd[29] <= SS_BPAL[3][47:40]; bgpd[45] <= SS_BPAL[5][47:40]; bgpd[61] <= SS_BPAL[7][47:40]; //8'h00; + bgpd[14] <= SS_BPAL[1][55:48]; bgpd[30] <= SS_BPAL[3][55:48]; bgpd[46] <= SS_BPAL[5][55:48]; bgpd[62] <= SS_BPAL[7][55:48]; //8'h00; + bgpd[15] <= SS_BPAL[1][63:56]; bgpd[31] <= SS_BPAL[3][63:56]; bgpd[47] <= SS_BPAL[5][63:56]; bgpd[63] <= SS_BPAL[7][63:56]; //8'h00; + + obpd[ 0] <= SS_OPAL[0][ 7: 0]; obpd[16] <= SS_OPAL[2][ 7: 0]; obpd[32] <= SS_OPAL[4][ 7: 0]; obpd[48] <= SS_OPAL[6][ 7: 0]; //8'h00; + obpd[ 1] <= SS_OPAL[0][15: 8]; obpd[17] <= SS_OPAL[2][15: 8]; obpd[33] <= SS_OPAL[4][15: 8]; obpd[49] <= SS_OPAL[6][15: 8]; //8'h00; + obpd[ 2] <= SS_OPAL[0][23:16]; obpd[18] <= SS_OPAL[2][23:16]; obpd[34] <= SS_OPAL[4][23:16]; obpd[50] <= SS_OPAL[6][23:16]; //8'h00; + obpd[ 3] <= SS_OPAL[0][31:24]; obpd[19] <= SS_OPAL[2][31:24]; obpd[35] <= SS_OPAL[4][31:24]; obpd[51] <= SS_OPAL[6][31:24]; //8'h00; + obpd[ 4] <= SS_OPAL[0][39:32]; obpd[20] <= SS_OPAL[2][39:32]; obpd[36] <= SS_OPAL[4][39:32]; obpd[52] <= SS_OPAL[6][39:32]; //8'h00; + obpd[ 5] <= SS_OPAL[0][47:40]; obpd[21] <= SS_OPAL[2][47:40]; obpd[37] <= SS_OPAL[4][47:40]; obpd[53] <= SS_OPAL[6][47:40]; //8'h00; + obpd[ 6] <= SS_OPAL[0][55:48]; obpd[22] <= SS_OPAL[2][55:48]; obpd[38] <= SS_OPAL[4][55:48]; obpd[54] <= SS_OPAL[6][55:48]; //8'h00; + obpd[ 7] <= SS_OPAL[0][63:56]; obpd[23] <= SS_OPAL[2][63:56]; obpd[39] <= SS_OPAL[4][63:56]; obpd[55] <= SS_OPAL[6][63:56]; //8'h00; + obpd[ 8] <= SS_OPAL[1][ 7: 0]; obpd[24] <= SS_OPAL[3][ 7: 0]; obpd[40] <= SS_OPAL[5][ 7: 0]; obpd[56] <= SS_OPAL[7][ 7: 0]; //8'h00; + obpd[ 9] <= SS_OPAL[1][15: 8]; obpd[25] <= SS_OPAL[3][15: 8]; obpd[41] <= SS_OPAL[5][15: 8]; obpd[57] <= SS_OPAL[7][15: 8]; //8'h00; + obpd[10] <= SS_OPAL[1][23:16]; obpd[26] <= SS_OPAL[3][23:16]; obpd[42] <= SS_OPAL[5][23:16]; obpd[58] <= SS_OPAL[7][23:16]; //8'h00; + obpd[11] <= SS_OPAL[1][31:24]; obpd[27] <= SS_OPAL[3][31:24]; obpd[43] <= SS_OPAL[5][31:24]; obpd[59] <= SS_OPAL[7][31:24]; //8'h00; + obpd[12] <= SS_OPAL[1][39:32]; obpd[28] <= SS_OPAL[3][39:32]; obpd[44] <= SS_OPAL[5][39:32]; obpd[60] <= SS_OPAL[7][39:32]; //8'h00; + obpd[13] <= SS_OPAL[1][47:40]; obpd[29] <= SS_OPAL[3][47:40]; obpd[45] <= SS_OPAL[5][47:40]; obpd[61] <= SS_OPAL[7][47:40]; //8'h00; + obpd[14] <= SS_OPAL[1][55:48]; obpd[30] <= SS_OPAL[3][55:48]; obpd[46] <= SS_OPAL[5][55:48]; obpd[62] <= SS_OPAL[7][55:48]; //8'h00; + obpd[15] <= SS_OPAL[1][63:56]; obpd[31] <= SS_OPAL[3][63:56]; obpd[47] <= SS_OPAL[5][63:56]; obpd[63] <= SS_OPAL[7][63:56]; //8'h00; end else if (ce_cpu) begin if(cpu_sel_reg && cpu_wr) begin diff --git a/sim/src/gameboy/mbc.sv b/sim/src/gameboy/mbc.sv new file mode 100644 index 0000000..d0e4f03 --- /dev/null +++ b/sim/src/gameboy/mbc.sv @@ -0,0 +1,470 @@ +module mbc +( + input clk_sys, + input clkram, + input reset, + input ce_cpu2x, + + input [15:0] cart_addr, + input cart_rd, + input cart_wr, + output [7:0] cart_do, + input [7:0] cart_di, + + output reg [7:0] cart_ram_size, + output is_gbc, + + input sleep_savestate, + + input [63:0] SaveStateBus_Din, + input [9:0] SaveStateBus_Adr, + input SaveStateBus_wren, + input SaveStateBus_rst, + output [63:0] SaveStateBus_Dout, + input savestate_load, + + input [19:0] Savestate_CRAMAddr, + input Savestate_CRAMRWrEn, + input [7:0] Savestate_CRAMWriteData, + output [7:0] Savestate_CRAMReadData +); + + +/////////////////////////////////////////////////// + + +// http://fms.komkon.org/GameBoy/Tech/Carts.html + +// 32MB SDRAM memory map using word addresses +// 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 D +// 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 S +// ------------------------------------------------- +// 0 0 0 0 X X X X X X X X X X X X X X X X X X X X X up to 2MB used as ROM (MBC1-3), 8MB for MBC5 +// 0 0 0 0 R R B B B B B C C C C C C C C C C C C C C MBC1 ROM (R=RAM bank in mode 0) + +wire [6:0] mbc1_rom_bank_mode; +wire [8:0] rom_mask; +wire [3:0] ram_mask; + +reg mbc_ram_enable; +reg mbc1_mode; +reg mbc3_mode; +reg [8:0] mbc_rom_bank_reg; +reg [3:0] mbc_ram_bank_reg; //0-15 + +reg [7:0] cart_logo_check = 8'd0; +reg [2:0] cart_logo_idx = 3'd0; +wire mbc1m = &cart_logo_check; + +// 0x0000-0x3FFF = Bank 0 +wire [8:0] mbc_rom_bank = (cart_addr[15:14] == 2'b00) ? 9'd0 : mbc_rom_bank_reg; + +// mask address lines to enable proper mirroring +wire [6:0] mbc1_rom_bank = mbc1_rom_bank_mode & rom_mask[6:0]; //128 +wire [6:0] mbc2_rom_bank = mbc_rom_bank[6:0] & rom_mask[6:0]; //16 +wire [6:0] mbc3_rom_bank = mbc_rom_bank[6:0] & rom_mask[6:0]; //128 +wire [8:0] mbc5_rom_bank = mbc_rom_bank & rom_mask; //480 + +// extract header fields extracted from cartridge +// during download +wire [7:0] cart_mbc_type; +reg [7:0] cart_rom_size; +reg [7:0] cart_cgb_flag; +reg [7:0] cart_sgb_flag; +reg [7:0] cart_old_licensee; +reg [15:0] cart_logo_data[0:7]; + +// RAM size +assign ram_mask = // 0 - no ram + (cart_ram_size == 1)?4'b0000: // 1 - 2k, 1 bank + (cart_ram_size == 2)?4'b0000: // 2 - 8k, 1 bank + (cart_ram_size == 3)?4'b0011: // 3 - 32k, 4 banks + 4'b1111; // 4 - 128k 16 banks + +// ROM size +assign rom_mask = // 0 - 2 banks, 32k direct mapped + (cart_rom_size == 1)? 9'b000000011: // 1 - 4 banks = 64k + (cart_rom_size == 2)? 9'b000000111: // 2 - 8 banks = 128k + (cart_rom_size == 3)? 9'b000001111: // 3 - 16 banks = 256k + (cart_rom_size == 4)? 9'b000011111: // 4 - 32 banks = 512k + (cart_rom_size == 5)? 9'b000111111: // 5 - 64 banks = 1M + (cart_rom_size == 6)? 9'b001111111: // 6 - 128 banks = 2M + (cart_rom_size == 7)? 9'b011111111: // 7 - 256 banks = 4M + (cart_rom_size == 8)? 9'b111111111: // 8 - 512 banks = 8M + (cart_rom_size == 82)?9'b001111111: //$52 - 72 banks = 1.1M + (cart_rom_size == 83)?9'b001111111: //$53 - 80 banks = 1.2M + (cart_rom_size == 84)?9'b001111111: + 9'b001111111; //$54 - 96 banks = 1.5M + +wire mbc1 = (cart_mbc_type == 1) || (cart_mbc_type == 2) || (cart_mbc_type == 3); +wire mbc2 = (cart_mbc_type == 5) || (cart_mbc_type == 6); +//wire mmm01 = (cart_mbc_type == 11) || (cart_mbc_type == 12) || (cart_mbc_type == 13) || (cart_mbc_type == 14); +wire mbc3 = (cart_mbc_type == 15) || (cart_mbc_type == 16) || (cart_mbc_type == 17) || (cart_mbc_type == 18) || (cart_mbc_type == 19); +//wire mbc4 = (cart_mbc_type == 21) || (cart_mbc_type == 22) || (cart_mbc_type == 23); +wire mbc5 = (cart_mbc_type == 25) || (cart_mbc_type == 26) || (cart_mbc_type == 27) || (cart_mbc_type == 28) || (cart_mbc_type == 29) || (cart_mbc_type == 30); +//wire tama5 = (cart_mbc_type == 253); +//wire tama6 = (cart_mbc_type == ???); +//wire HuC1 = (cart_mbc_type == 254); +//wire HuC3 = (cart_mbc_type == 255); + +// --------------------------------------------------------------- +// ----------------------------- MBC1 ---------------------------- +// --------------------------------------------------------------- + +wire [9:0] mbc1_addr = {2'b00, mbc1_rom_bank, cart_addr[13]}; // 16k ROM Bank 0-127 or MBC1M Bank 0-63 + +wire [9:0] mbc2_addr = {2'b00, mbc2_rom_bank, cart_addr[13]}; // 16k ROM Bank 0-15 + +wire [9:0] mbc3_addr = {2'b00, mbc3_rom_bank, cart_addr[13]}; // 16k ROM Bank 0-127 + +wire [9:0] mbc5_addr = { mbc5_rom_bank, cart_addr[13]}; // 16k ROM Bank 0-480 (0h-1E0h) + +// https://forums.nesdev.com/viewtopic.php?p=168940#p168940 +// https://gekkio.fi/files/gb-docs/gbctr.pdf +// MBC1 $6000 Mode register: +// 0: Bank2 ANDed with CPU A14. Bank2 affects ROM 0x4000-0x7FFF only +// 1: Passthrough. Bank2 affects ROM 0x0000-0x3FFF, 0x4000-0x7FFF, RAM 0xA000-0xBFFF +wire [1:0] mbc1_bank2 = mbc_ram_bank_reg[1:0] & {2{cart_addr[14] | mbc1_mode}}; + +// -------------------------- RAM banking ------------------------ + +wire [1:0] mbc1_ram_bank = mbc1_bank2 & ram_mask[1:0]; +wire [1:0] mbc3_ram_bank = mbc_ram_bank_reg[1:0] & ram_mask[1:0]; +wire [3:0] mbc5_ram_bank = mbc_ram_bank_reg & ram_mask; + +// -------------------------- ROM banking ------------------------ + +// MBC1: 4x32 16KByte banks, MBC1M: 4x16 16KByte banks +assign mbc1_rom_bank_mode = mbc1m ? { 1'b0, mbc1_bank2, mbc_rom_bank[3:0] } + : { mbc1_bank2, mbc_rom_bank[4:0] }; + +// in mode 0 map memory at A000-BFFF +// in mode 1 map rtc register at A000-BFFF +//wire [6:0] mbc3_ram_bank_addr = { mbc3_mode?2'b00:mbc3_ram_bank_reg, mbc3_rom_bank_reg}; + +wire mbc_battery = (cart_mbc_type == 8'h03) || (cart_mbc_type == 8'h06) || (cart_mbc_type == 8'h09) || (cart_mbc_type == 8'h0D) || + (cart_mbc_type == 8'h10) || (cart_mbc_type == 8'h13) || (cart_mbc_type == 8'h1B) || (cart_mbc_type == 8'h1E) || + (cart_mbc_type == 8'h22) || (cart_mbc_type == 8'hFF); + +// --------------------- CPU register interface ------------------ + +wire [15:0] SS_Ext; +wire [15:0] SS_Ext_BACK; + +assign SS_Ext_BACK[ 8: 0] = mbc_rom_bank_reg; +assign SS_Ext_BACK[12: 9] = mbc_ram_bank_reg; +assign SS_Ext_BACK[ 13] = mbc1_mode; +assign SS_Ext_BACK[ 14] = mbc3_mode; +assign SS_Ext_BACK[ 15] = mbc_ram_enable; + +always @(posedge clk_sys) begin + if(savestate_load) begin + mbc_rom_bank_reg <= SS_Ext[ 8: 0]; //5'd1; + mbc_ram_bank_reg <= SS_Ext[12: 9]; //4'd0; + mbc1_mode <= SS_Ext[ 13]; //1'b0; + mbc3_mode <= SS_Ext[ 14]; //1'b0; + mbc_ram_enable <= SS_Ext[ 15]; //1'b0; + end else if(reset) begin + mbc_rom_bank_reg <= 5'd1; + mbc_ram_bank_reg <= 4'd0; + mbc1_mode <= 1'b0; + mbc3_mode <= 1'b0; + mbc_ram_enable <= 1'b0; + end else if(ce_cpu2x) begin + + //write to ROM bank register + if(cart_wr && (cart_addr[15:13] == 3'b001)) begin + if(~mbc5 && cart_di[6:0]==0) //special case mbc1-3 rombank 0=1 + mbc_rom_bank_reg <= 5'd1; + else if (mbc5) begin + if (cart_addr[13:12] == 2'b11) //3000-3FFF High bit + mbc_rom_bank_reg[8] <= cart_di[0]; + else //2000-2FFF low 8 bits + mbc_rom_bank_reg[7:0] <= cart_di[7:0]; + end else + mbc_rom_bank_reg <= {2'b00,cart_di[6:0]}; //mbc1-3 + end + + //write to RAM bank register + if(cart_wr && (cart_addr[15:13] == 3'b010)) begin + if (mbc3) begin + if (cart_di[3]==1) + mbc3_mode <= 1'b1; //enable RTC + else begin + mbc3_mode <= 1'b0; //enable RAM + mbc_ram_bank_reg <= {2'b00,cart_di[1:0]}; + end + end else + if (mbc5)//can probably be simplified + mbc_ram_bank_reg <= cart_di[3:0]; + else + mbc_ram_bank_reg <= {2'b00,cart_di[1:0]}; + end + + // MBC1 ROM/RAM Mode Select + if(mbc1 && cart_wr && (cart_addr[15:13] == 3'b011)) + mbc1_mode <= cart_di[0]; + + //RAM enable/disable + if(ce_cpu2x && cart_wr && (cart_addr[15:13] == 3'b000)) + mbc_ram_enable <= (cart_di[3:0] == 4'ha); + end +end + +wire [9:0] mbc_bank = + mbc1?mbc1_addr: // MBC1, 16k bank 0, 16k bank 1-127 + ram + mbc2?mbc2_addr: // MBC2, 16k bank 0, 16k bank 1-15 + ram + mbc3?mbc3_addr: + mbc5?mbc5_addr: +// tama5?tama5_addr: +// HuC1?HuC1_addr: +// HuC3?HuC3_addr: + {8'd0, cart_addr[14:13]}; // no MBC, 32k linear address + +wire isGBC_game = (cart_cgb_flag == 8'h80 || cart_cgb_flag == 8'hC0); +wire isSGB_game = (cart_sgb_flag == 8'h03 && cart_old_licensee == 8'h33); + +assign is_gbc = isGBC_game; + +reg [127:0] palette = 128'h828214517356305A5F1A3B4900000000; + +// MBC1M detect +//always @(posedge clk_sys) begin +// if(~old_downloading & downloading) begin +// cart_logo_idx <= 3'd0; +// cart_logo_check <= 8'd0; +// end +// +// if(cart_download & ioctl_wr) begin +// case(ioctl_addr) +// 'h142: cart_cgb_flag <= ioctl_dout[15:8]; +// 'h146: {cart_mbc_type, cart_sgb_flag} <= ioctl_dout; +// 'h148: { cart_ram_size, cart_rom_size } <= ioctl_dout; +// 'h14a: { cart_old_licensee } <= ioctl_dout[15:8]; +// endcase +// +// //Store cart logo data +// if (ioctl_addr >= 'h104 && ioctl_addr <= 'h112) begin +// cart_logo_data[cart_logo_idx] <= ioctl_dout; +// cart_logo_idx <= cart_logo_idx + 1'b1; +// end +// +// // MBC1 Multicart detect: Compare 8 words of logo data at second 256KByte bank +// if (ioctl_addr >= 'h40104 && ioctl_addr <= 'h40112) begin +// cart_logo_check[cart_logo_idx] <= (ioctl_dout == cart_logo_data[cart_logo_idx]); +// cart_logo_idx <= cart_logo_idx + 1'b1; +// end +// +// end +// +// if (palette_download & ioctl_wr) begin +// palette[127:0] <= {palette[111:0], ioctl_dout[7:0], ioctl_dout[15:8]}; +// end +//end + +wire [7:0] sdram_do; + +wire [23:0] sdram_addr = {1'b0, mbc_bank, cart_addr[12:0]}; + +sdram_model sdram_model +( + clkram, + sdram_addr, + cart_rd, + sdram_do, + cart_cgb_flag, + cart_sgb_flag, + cart_mbc_type, + cart_rom_size, + cart_ram_size, + cart_old_licensee +); + + +//TODO: e.g. output and read timer register values from mbc3 when selected +reg cart_ready = 1; + +wire cram_rd; +wire [7:0] cram_do; + +assign cart_do = + ~cart_ready ? + 8'h00 : + cram_rd ? + cram_do : sdram_do; +// cart_addr[0] ? +// sdram_do[15:8]: +// sdram_do[7:0]; + + +reg isGBC = 0; +//always @(posedge clk_sys) if(reset) begin +// if(status[15:14]) isGBC <= status[15]; +// else if(cart_download) isGBC <= !filetype[7:4]; +//end + + +///////////////////////////// savestates ///////////////////////////////// + +eReg_SavestateV #(0, 32, 15, 0, 64'h0000000000000001) iREG_SAVESTATE_Ext (clk_sys, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_Dout, SS_Ext_BACK, SS_Ext); + +///////////////////////// BRAM SAVE/LOAD ///////////////////////////// + +//wire [16:0] bk_addr = {sd_lba[7:0],sd_buff_addr}; +//wire bk_wr = sd_buff_wr & sd_ack; +//wire [15:0] bk_data = sd_buff_dout; +//wire [15:0] bk_q; +//assign sd_buff_din = bk_q; + +wire [16:0] cram_addr = sleep_savestate ? Savestate_CRAMAddr[16:0]: + mbc1? {2'b00,mbc1_ram_bank, cart_addr[12:0]}: + mbc3? {2'b00,mbc3_ram_bank, cart_addr[12:0]}: + mbc5? {mbc5_ram_bank, cart_addr[12:0]}: + {4'd0, cart_addr[12:0]}; + +wire [7:0] cram_q_h; +wire [7:0] cram_q_l; +wire [7:0] cram_q = cram_addr[0] ? cram_q_h : cram_q_l; + +assign cram_do = + mbc_ram_enable ? + ((cart_addr[15:9] == 7'b1010000) && mbc2) ? + {4'hF,cram_q[3:0]} : // 4 bit MBC2 Ram needs top half masked. + mbc3_mode ? + 8'h0: // RTC mode + cram_q : // Return normal value + 8'hFF; // Ram not enabled + + +reg read_low = 0; +always @(posedge clk_sys) begin + read_low <= cram_addr[0]; +end + +assign Savestate_CRAMReadData = read_low ? cram_q_h : cram_q_l; + +wire is_cram_addr = (cart_addr[15:13] == 3'b101); +assign cram_rd = cart_rd & is_cram_addr; +wire cram_wr = sleep_savestate ? Savestate_CRAMRWrEn : cart_wr & is_cram_addr; + +wire [7:0] cram_di = sleep_savestate ? Savestate_CRAMWriteData : cart_di; + +// Up to 8kb * 16banks of Cart Ram (128kb) + +dpram #(16) cram_l ( + .clock_a (clk_sys), + .address_a (cram_addr[16:1]), + .wren_a (cram_wr & ~cram_addr[0]), + .data_a (cram_di), + .q_a (cram_q_l), + + .clock_b (clk_sys), + .address_b (16'd0), + .wren_b (1'b0), + .data_b (8'b0) + + //.clock_b (clk_sys), + //.address_b (bk_addr[15:0]), + //.wren_b (bk_wr), + //.data_b (bk_data[7:0]), + //.q_b (bk_q[7:0]) +); + +dpram #(16) cram_h ( + .clock_a (clk_sys), + .address_a (cram_addr[16:1]), + .wren_a (cram_wr & cram_addr[0]), + .data_a (cram_di), + .q_a (cram_q_h), + + .clock_b (clk_sys), + .address_b (16'd0), + .wren_b (1'b0), + .data_b (8'b0) + + //.clock_b (clk_sys), + //.address_b (bk_addr[15:0]), + //.wren_b (bk_wr), + //.data_b (bk_data[15:8]), + //.q_b (bk_q[15:8]) +); + +//wire downloading = cart_download; + +//reg bk_ena = 0; +//reg new_load = 0; +//reg old_downloading = 0; +//reg sav_pending = 0; +//wire sav_supported = (mbc_battery && (cart_ram_size > 0 || mbc2) && bk_ena); +// +//always @(posedge clk_sys) begin +// old_downloading <= downloading; +// if(~old_downloading & downloading) bk_ena <= 0; +// +// //Save file always mounted in the end of downloading state. +// if(downloading && img_mounted && !img_readonly) bk_ena <= 1; +// +// if (old_downloading & ~downloading & sav_supported) +// new_load <= 1'b1; +// else if (bk_state) +// new_load <= 1'b0; +// +// if (cram_wr & ~OSD_STATUS & sav_supported) +// sav_pending <= 1'b1; +// else if (bk_state) +// sav_pending <= 1'b0; +//end +// +//wire bk_load = status[9] | new_load; +//wire bk_save = status[10] | (sav_pending & OSD_STATUS & status[13]); +//reg bk_loading = 0; +//reg bk_state = 0; + +// RAM size +wire [7:0] ram_mask_file = // 0 - no ram + (mbc2)?8'h01: // mbc2 512x4bits + (cart_ram_size == 1)?8'h03: // 1 - 2k, 1 bank sd_lba[1:0] + (cart_ram_size == 2)?8'h0F: // 2 - 8k, 1 bank sd_lba[3:0] + (cart_ram_size == 3)?8'h3F: // 3 - 32k, 4 banks sd_lba[5:0] + 8'hFF; // 4 - 128k 16 banks sd_lba[7:0] 1111 + +//always @(posedge clk_sys) begin +// reg old_load = 0, old_save = 0, old_ack; +// +// old_load <= bk_load; +// old_save <= bk_save; +// old_ack <= sd_ack; +// +// if(~old_ack & sd_ack) {sd_rd, sd_wr} <= 0; +// +// if(!bk_state) begin +// if(bk_ena & ((~old_load & bk_load) | (~old_save & bk_save))) begin +// bk_state <= 1; +// bk_loading <= bk_load; +// sd_lba <= 32'd0; +// sd_rd <= bk_load; +// sd_wr <= ~bk_load; +// end +// if(old_downloading & ~downloading & |img_size & bk_ena) begin +// bk_state <= 1; +// bk_loading <= 1; +// sd_lba <= 0; +// sd_rd <= 1; +// sd_wr <= 0; +// end +// end else begin +// if(old_ack & ~sd_ack) begin +// +// if(sd_lba[7:0]>=ram_mask_file) begin +// bk_loading <= 0; +// bk_state <= 0; +// end else begin +// sd_lba <= sd_lba + 1'd1; +// sd_rd <= bk_loading; +// sd_wr <= ~bk_loading; +// end +// end +// end +//end + +endmodule diff --git a/sim/src/tb/sdram_model.vhd b/sim/src/tb/sdram_model.vhd index e3e0493..4d13868 100644 --- a/sim/src/tb/sdram_model.vhd +++ b/sim/src/tb/sdram_model.vhd @@ -8,10 +8,16 @@ use tb.globals.all; entity sdram_model is port ( - clk : in std_logic; - cart_addr : in std_logic_vector(15 downto 0); - cart_rd : in std_logic; - cart_do : out std_logic_vector(7 downto 0) + clk : in std_logic; + cart_addr : in std_logic_vector(23 downto 0); + cart_rd : in std_logic; + cart_do : out std_logic_vector(7 downto 0); + cart_cgb_flag : out std_logic_vector(7 downto 0); + cart_sgb_flag : out std_logic_vector(7 downto 0); + cart_mbc_type : out std_logic_vector(7 downto 0); + cart_rom_size : out std_logic_vector(7 downto 0); + cart_ram_size : out std_logic_vector(7 downto 0); + cart_old_licensee : out std_logic_vector(7 downto 0) ); end entity; @@ -72,7 +78,14 @@ begin wait until rising_edge(clk); wait until rising_edge(clk); cart_do <= std_logic_vector(to_unsigned(data(to_integer(unsigned(cart_addr))), 8)); - end if; + end if; + + cart_cgb_flag <= std_logic_vector(to_unsigned(data(16#143#), 8)); + cart_sgb_flag <= std_logic_vector(to_unsigned(data(16#146#), 8)); + cart_mbc_type <= std_logic_vector(to_unsigned(data(16#147#), 8)); + cart_rom_size <= std_logic_vector(to_unsigned(data(16#148#), 8)); + cart_ram_size <= std_logic_vector(to_unsigned(data(16#149#), 8)); + cart_old_licensee <= std_logic_vector(to_unsigned(data(16#14B#), 8)); COMMAND_FILE_ACK_1 <= '0'; if COMMAND_FILE_START_1 = '1' then @@ -102,7 +115,7 @@ begin COMMAND_FILE_ACK_1 <= '1'; end if; - + end process; diff --git a/sim/src/tb/tb.vhd b/sim/src/tb/tb.vhd index 3514832..dd9a1a4 100644 --- a/sim/src/tb/tb.vhd +++ b/sim/src/tb/tb.vhd @@ -31,6 +31,7 @@ architecture arch of etb is signal ce_2x : std_logic := '1'; signal speed : std_logic; + signal HDMA_on : std_logic; signal command_in : std_logic; signal command_out : std_logic; @@ -62,7 +63,7 @@ architecture arch of etb is signal pixel_out_data : std_logic_vector(14 downto 0); signal pixel_out_we : std_logic := '0'; - signal is_CGB : std_logic := '0'; + signal is_CGB : std_logic; signal sleep_savestate : std_logic; @@ -97,6 +98,20 @@ architecture arch of etb is signal GB_SaveState : std_logic_vector(Reg_GB_SaveState.upper downto Reg_GB_SaveState.lower) := (others => '0'); signal GB_LoadState : std_logic_vector(Reg_GB_LoadState.upper downto Reg_GB_LoadState.lower) := (others => '0'); + -- savestates + signal cart_ram_size : std_logic_vector(7 downto 0); + + signal Savestate_CRAMAddr : std_logic_vector(19 downto 0); + signal Savestate_CRAMRWrEn : std_logic; + signal Savestate_CRAMWriteData : std_logic_vector(7 downto 0); + signal Savestate_CRAMReadData : std_logic_vector(7 downto 0); + + signal SaveStateExt_Din : std_logic_vector(63 downto 0); + signal SaveStateExt_Adr : std_logic_vector(9 downto 0); + signal SaveStateExt_wren : std_logic; + signal SaveStateExt_rst : std_logic; + signal SaveStateExt_Dout : std_logic_vector(63 downto 0); + signal SaveStateExt_load : std_logic; begin @@ -115,23 +130,14 @@ begin port map ( clk_sys => clksys, - speed => speed, pause => sleep_savestate, speedup => '1', cart_act => cart_act, + HDMA_on => HDMA_on, ce => ce, ce_2x => ce_2x ); - isdram_model : entity tb.sdram_model - port map - ( - clk => clkram, - cart_addr => cart_addr, - cart_rd => cart_rd, - cart_do => cart_do - ); - igb : entity gameboy.gb port map ( @@ -173,6 +179,7 @@ begin joy_din => "1111", speed => speed, --GBC + HDMA_on => HDMA_on, gg_reset => reset, gg_en => '0', @@ -186,17 +193,24 @@ begin serial_data_in => '0', serial_data_out => open, + cart_ram_size => cart_ram_size, save_state => GB_SaveState, load_state => GB_LoadState, sleep_savestate => sleep_savestate, + savestate_number => 0, - SaveStateExt_Din => open, - SaveStateExt_Adr => open, - SaveStateExt_wren => open, - SaveStateExt_rst => open, - SaveStateExt_Dout => (63 downto 0 => '0'), + SaveStateExt_Din => SaveStateExt_Din, + SaveStateExt_Adr => SaveStateExt_Adr, + SaveStateExt_wren => SaveStateExt_wren, + SaveStateExt_rst => SaveStateExt_rst, + SaveStateExt_Dout => SaveStateExt_Dout, + SaveStateExt_load => SaveStateExt_load, + + Savestate_CRAMAddr => Savestate_CRAMAddr, + Savestate_CRAMRWrEn => Savestate_CRAMRWrEn, + Savestate_CRAMWriteData => Savestate_CRAMWriteData, + Savestate_CRAMReadData => Savestate_CRAMReadData, - Savestate_CRAMReadData => (7 downto 0 => '0'), SAVE_out_Din => SAVE_out_Din, SAVE_out_Dout => SAVE_out_Dout, @@ -209,6 +223,39 @@ begin rewind_active => '0' ); + + imbc : entity gameboy.mbc + port map + ( + clk_sys => clksys, + clkram => clkram, + reset => reset, + ce_cpu2x => ce_2x, + + cart_addr => cart_addr, + cart_rd => cart_rd, + cart_wr => cart_wr, + cart_do => cart_do, + cart_di => cart_di, + + cart_ram_size => cart_ram_size, + is_gbc => is_CGB, + + sleep_savestate => sleep_savestate, + + SaveStateBus_Din => SaveStateExt_Din, + SaveStateBus_Adr => SaveStateExt_Adr, + SaveStateBus_wren => SaveStateExt_wren, + SaveStateBus_rst => SaveStateExt_rst, + SaveStateBus_Dout => SaveStateExt_Dout, + savestate_load => SaveStateExt_load, + + Savestate_CRAMAddr => Savestate_CRAMAddr, + Savestate_CRAMRWrEn => Savestate_CRAMRWrEn, + Savestate_CRAMWriteData => Savestate_CRAMWriteData, + Savestate_CRAMReadData => Savestate_CRAMReadData + ); + ch1_addr <= SAVE_out_Adr(25 downto 0) & "0"; ch1_din <= SAVE_out_Din; ch1_req <= SAVE_out_ena; @@ -259,7 +306,7 @@ begin address => gbc_bios_addr, data => gbc_bios_do ); - + process(clksys) begin if rising_edge(clksys) then @@ -292,7 +339,7 @@ begin when others => pixel_out_data <= "00000" & "00000" & "11111"; end case; else - pixel_out_data <= lcd_data; + pixel_out_data <= lcd_data(4 downto 0) & lcd_data(9 downto 5) & lcd_data(14 downto 10); end if; end if; diff --git a/sim/vcom_all.bat b/sim/vcom_all.bat index 9bb5642..3a1b8e9 100644 --- a/sim/vcom_all.bat +++ b/sim/vcom_all.bat @@ -50,6 +50,7 @@ vlog -sv -quiet -work sim/gameboy ^ ../rtl/gb.v vlog -sv -quiet -work sim/gameboy ^ +src/gameboy/mbc.sv ^ src/gameboy/cheatcodes.sv vcom -quiet -work sim/gameboy ^