mirror of
https://github.com/MiSTer-devel/Gameboy_MiSTer.git
synced 2026-04-19 03:04:09 +00:00
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
This commit is contained in:
127
Gameboy.sv
127
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;
|
||||
|
||||
30
rtl/gb.v
30
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),
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
52
rtl/video.v
52
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
|
||||
|
||||
470
sim/src/gameboy/mbc.sv
Normal file
470
sim/src/gameboy/mbc.sv
Normal file
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ^
|
||||
|
||||
Reference in New Issue
Block a user