diff --git a/Gameboy.sv b/Gameboy.sv index afcd9b2..a44641b 100644 --- a/Gameboy.sv +++ b/Gameboy.sv @@ -347,6 +347,7 @@ wire [14:0] cart1_addr; wire cart1_a15; wire cart1_rd; wire cart1_wr; +wire cart1_oe; wire [7:0] cart1_di; wire [7:0] cart1_do; wire [22:0] mbc1_addr; @@ -356,6 +357,7 @@ wire [14:0] cart2_addr; wire cart2_a15; wire cart2_rd; wire cart2_wr; +wire cart2_oe; wire [7:0] cart2_di; wire [7:0] cart2_do; wire [22:0] mbc2_addr; @@ -463,6 +465,7 @@ cart_top cart1 ( .cart_wr ( cart1_wr ), .cart_do ( cart1_do ), .cart_di ( cart1_di ), + .cart_oe ( cart1_oe ), .nCS ( gb1_nCS ), @@ -540,12 +543,13 @@ gb gb1 ( .joy_din ( joy1_do ), // interface to the "external" game cartridge - .cart_addr ( cart1_addr ), - .cart_a15 ( cart1_a15 ), + .ext_bus_addr( cart1_addr ), + .ext_bus_a15 ( cart1_a15 ), .cart_rd ( cart1_rd ), .cart_wr ( cart1_wr ), .cart_do ( cart1_do ), .cart_di ( cart1_di ), + .cart_oe ( cart1_oe ), .nCS ( gb1_nCS ), @@ -651,6 +655,7 @@ cart_top cart2 ( .cart_wr ( cart2_wr ), .cart_do ( cart2_do ), .cart_di ( cart2_di ), + .cart_oe ( cart2_oe ), .nCS ( gb2_nCS ), @@ -728,12 +733,13 @@ gb gb2 ( .joy_din ( joy2_do ), // interface to the "external" game cartridge - .cart_addr ( cart2_addr ), - .cart_a15 ( cart2_a15 ), + .ext_bus_addr( cart2_addr ), + .ext_bus_a15 ( cart2_a15 ), .cart_rd ( cart2_rd ), .cart_wr ( cart2_wr ), .cart_do ( cart2_do ), .cart_di ( cart2_di ), + .cart_oe ( cart2_oe ), .nCS ( gb2_nCS ), diff --git a/rtl/cart.v b/rtl/cart.v index 854f482..8da9596 100644 --- a/rtl/cart.v +++ b/rtl/cart.v @@ -12,6 +12,7 @@ module cart_top ( input cart_wr, output [7:0] cart_do, input [7:0] cart_di, // data from cpu to cart + output cart_oe, input nCS, @@ -151,8 +152,10 @@ mappers mappers ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe ( cart_oe ), .rom_di ( rom_di ), .rom_do ( rom_do ), @@ -377,7 +380,6 @@ assign ram_mask_file = // 0 - no ram assign has_save = mbc_battery && (cart_ram_size > 0 || mbc2 || mbc7 || tama); // Up to 8kb * 16banks of Cart Ram (128kb) - dpram #(16) cram_l ( .clock_a (clk_sys), .address_a (cram_addr[16:1]), diff --git a/rtl/gb.v b/rtl/gb.v index 4de024c..7433a72 100644 --- a/rtl/gb.v +++ b/rtl/gb.v @@ -34,12 +34,13 @@ module gb ( // cartridge interface // can adress up to 1MB ROM - output [14:0] cart_addr, - output cart_a15, + output [14:0] ext_bus_addr, + output ext_bus_a15, output cart_rd, output cart_wr, input [7:0] cart_do, output [7:0] cart_di, + input cart_oe, // WRAM or Cart RAM CS output nCS, @@ -120,14 +121,17 @@ wire [7:0] Savestate_RAMReadData_WRAM, Savestate_RAMReadData_VRAM, Savestate_RAM wire [19:0] Savestate_RAMAddr; wire [4:0] Savestate_RAMRWrEn; -localparam SAVESTATE_MODULES = 7; +localparam SAVESTATE_MODULES = 8; wire [63:0] SaveStateBus_wired_or[0:SAVESTATE_MODULES-1]; wire [54:0] SS_Top; wire [54:0] SS_Top_BACK; - 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); +wire [10:0] SS_Top2; +wire [10:0] SS_Top2_BACK; +eReg_SavestateV #(0, 38, 10, 0, 64'h0000000000000000) iREG_SAVESTATE_Top2 (clk_sys, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[7], SS_Top2_BACK, SS_Top2); + // include cpu reg boot_rom_enabled; @@ -150,19 +154,32 @@ wire sel_zpram = (cpu_addr[15:7] == 9'b111111111) && // 127 bytes zero pageram a (cpu_addr != 16'hffff); wire sel_audio = (cpu_addr[15:8] == 8'hff) && // audio reg ff10 - ff3f and ff76/ff77 PCM12/PCM34 (undocumented registers) ((cpu_addr[7:5] == 3'b001) || (cpu_addr[7:4] == 4'b0001) || (cpu_addr[7:0] == 8'h76) || (cpu_addr[7:0] == 8'h77)); - +wire sel_ext_bus = sel_rom | sel_cram | sel_iram; + +wire sel_boot_rom, sel_boot_rom_cgb; + // unused cgb registers wire sel_FF72 = isGBC && cpu_addr == 16'hff72; // unused register, all bits read/write wire sel_FF73 = isGBC && cpu_addr == 16'hff73; // unused register, all bits read/write wire sel_FF74 = isGBC && isGBC_game && (cpu_addr == 16'hff74); // unused register, all bits read/write, only in CGB mode wire sel_FF75 = isGBC && cpu_addr == 16'hff75; // unused register, bits 4-6 read/write - -//DMA can select from $0000 to $F100 + +wire ext_bus_wram_sel, ext_bus_cram_sel, ext_bus_rom_sel; +wire ext_bus_rd, ext_bus_wr; +wire [7:0] ext_bus_di; +wire cart_sel; + + +// From Game Boy: Complete Technical Reference: +// DMA register value, Selected bus, Asserted CS: +// 0x00-0x7F, external bus, external ROM (A15) +// 0x80-0x9F, video RAM bus, video RAM (MCS) +// 0xA0-0xFF, external bus, external RAM (CS) wire [15:0] dma_addr; -wire dma_sel_rom = !dma_addr[15]; // lower 32k are rom -wire dma_sel_cram = dma_addr[15:13] == 3'b101; // 8k cart ram at $a000 -wire dma_sel_vram = dma_addr[15:13] == 3'b100; // 8k video ram at $8000 -wire dma_sel_iram = (dma_addr[15:8] >= 8'hC0 && dma_addr[15:8] <= 8'hF1); // 8k internal ram at $c000 +wire dma_sel_rom = ~dma_addr[15]; // lower 32k are rom +wire dma_sel_vram = dma_addr[15:13] == 3'b100; // 8k video ram at $8000-$9FFF +wire dma_sel_ext_bus = ~dma_sel_vram; // WRAM or Cart ROM/RAM +wire dma_sel_ext_ram = ~dma_sel_rom; // External RAM CS //CGB wire sel_vram_bank = (cpu_addr==16'hff4f); @@ -177,6 +194,7 @@ wire [15:0] hdma_source_addr; wire hdma_sel_rom = !hdma_source_addr[15]; // lower 32k are rom wire hdma_sel_cram = hdma_source_addr[15:13] == 3'b101; // 8k cart ram at $a000 wire hdma_sel_iram = hdma_source_addr[15:13] == 3'b110; // 8k internal ram at $c000-$dff0 +wire hdma_sel_ext_bus = hdma_sel_rom | hdma_sel_cram | hdma_sel_iram; // the boot roms sees a special $42 flag in $ff50 if it's supposed to to a fast boot @@ -209,7 +227,7 @@ wire [7:0] sb_o; wire [7:0] timer_do; wire [7:0] video_do; wire [7:0] audio_do; -wire [7:0] rom_do; +wire [7:0] bios_do; wire [7:0] vram_do; wire [7:0] vram1_do; wire [7:0] zpram_do; @@ -237,11 +255,10 @@ wire [7:0] cpu_di = sel_video_reg?video_do: // video registers (sel_video_oam&&oam_cpu_allow)?video_do: // video object attribute memory sel_audio?audio_do: // audio registers - sel_rom?rom_do: // boot rom + cartridge rom - sel_cram?rom_do: // cartridge ram + sel_boot_rom?bios_do: // boot rom + sel_ext_bus?ext_bus_di: // wram + cartridge rom/ram (sel_vram&&vram_cpu_allow)?(isGBC&&vram_bank)?vram1_do:vram_do: // vram (GBC bank 0+1) sel_zpram?zpram_do: // zero page ram - sel_iram?iram_do: // internal ram sel_ie?ie_r: // interrupt enable register sel_FF72?FF72: // unused register, all bits read/write sel_FF73?FF73: // unused register, all bits read/write @@ -592,8 +609,9 @@ timer timer ( // cpu tries to read or write the lcd controller registers wire [12:0] video_addr; wire video_rd, dma_rd; -wire [7:0] dma_data = dma_sel_iram?iram_do:dma_sel_vram?(isGBC&&vram_bank)?vram1_do:vram_do:cart_do; +wire [7:0] dma_data = dma_sel_ext_bus ? ext_bus_di : + (isGBC & vram_bank) ? vram1_do : vram_do; video video ( .reset ( reset_ss ), @@ -650,14 +668,9 @@ video video ( wire cpu_wr_vram = sel_vram && !cpu_wr_n && vram_cpu_allow; wire hdma_rd; -wire is_hdma_cart_addr; -wire [7:0] vram_di = (hdma_rd&&isGBC)? - hdma_sel_iram?iram_do: - is_hdma_cart_addr?cart_do: - 8'hFF: - cpu_do; - +wire [7:0] vram_di = (hdma_rd & isGBC) ? ext_bus_di : cpu_do; + wire vram_wren = video_rd?1'b0:!vram_bank&&((hdma_rd&&isGBC)||cpu_wr_vram); wire vram1_wren = video_rd?1'b0:vram_bank&&((hdma_rd&&isGBC)||cpu_wr_vram); @@ -764,22 +777,13 @@ dpram #(7) zpram ( ); // -------------------------------------------------------------------- -// ------------------------ 8k/32k(GBC) internal ram ----------------- +// -------------------------- 8k/32k(GBC) work ram ------------------- // -------------------------------------------------------------------- -wire cpu_wr_iram = sel_iram && !cpu_wr_n; -wire iram_wren = (dma_rd&&dma_sel_iram)||(isGBC&&hdma_rd&&hdma_sel_iram)?1'b0:cpu_wr_iram; +wire iram_wren = ext_bus_wram_sel & ext_bus_wr; +wire [14:0] iram_addr = (ext_bus_addr[12]) ? { iram_bank, ext_bus_addr[11:0] } // bank 1-7 $D000-DFFF + : { 3'd0, ext_bus_addr[11:0] }; // bank 0 $C000-CFFF -wire [14:0] iram_addr = (isGBC&&hdma_rd&&hdma_sel_iram)? //hdma transfer? - (hdma_source_addr[12])?{iram_bank,hdma_source_addr[11:0]}: //bank 1-7 D000-DFFF - {3'd0,hdma_source_addr[11:0]}: //bank 0 - (dma_rd&&dma_sel_iram)? //dma transfer? - (dma_addr[12])?{iram_bank,dma_addr[11:0]}: //bank 1-7 - {3'd0,dma_addr[11:0]}: //bank 0 - //cpu - (cpu_addr[12])?{iram_bank,cpu_addr[11:0]}: //bank 1-7 - {3'd0,cpu_addr[11:0]}; //bank 0 - dpram #(15) iram ( .clock_a (clk_cpu), .address_a (iram_addr), @@ -837,35 +841,15 @@ wire [15:0] boot_rom_addr = (isGBC && hdma_rd) ? hdma_source_addr : cpu_addr; // 0- FF bootrom 1st part //100-1FF Cart Header //200-8FF bootrom 2nd part -wire boot_rom_cgb_sel = isGBC && (boot_rom_addr[15:8] >= 8'h02 && boot_rom_addr[15:8] <= 8'h08); -wire boot_rom_sel = boot_rom_enabled && (!boot_rom_addr[15:8] || boot_rom_cgb_sel); +assign sel_boot_rom_cgb = isGBC && (boot_rom_addr[15:8] >= 8'h02 && boot_rom_addr[15:8] <= 8'h08); +assign sel_boot_rom = boot_rom_enabled && (!boot_rom_addr[15:8] || sel_boot_rom_cgb); -assign rom_do = ~boot_rom_sel ? cart_do : - isGBC ? gbc_bios_do : - isSGB ? boot_rom_sgb_do : - fast_boot ? fast_boot_rom_do : boot_rom_do; - - -wire is_dma_cart_addr = (dma_sel_rom || dma_sel_cram); //rom or external ram -assign is_hdma_cart_addr = (hdma_sel_rom || hdma_sel_cram); //rom or external ram - -assign cart_di = cpu_do; - -wire [15:0] cart_addr_i = (isGBC&&hdma_rd&&is_hdma_cart_addr)?hdma_source_addr:(dma_rd&&is_dma_cart_addr)?dma_addr:cpu_addr; - -// External A15 is not directly connected to internal A15. It does not go low when accessing the boot rom. -assign cart_a15 = cart_addr_i[15] | boot_rom_sel; -assign cart_addr = cart_addr_i[14:0]; - -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_edge && !hdma_rd; - -assign nCS = ~( (sel_cram | sel_iram) | (dma_rd & (dma_sel_cram | dma_sel_iram)) | (isGBC & hdma_rd & (hdma_sel_cram | hdma_sel_iram)) ); +assign bios_do = isGBC ? gbc_bios_do : + isSGB ? boot_rom_sgb_do : + fast_boot ? fast_boot_rom_do : boot_rom_do; assign gbc_bios_addr = boot_rom_addr[11:0]; -assign DMA_on = (hdma_active && is_hdma_cart_addr) || (dma_rd && is_dma_cart_addr); - boot_rom boot_rom ( .addr ( cpu_addr[7:0] ), .clk ( clk_sys ), @@ -884,6 +868,66 @@ boot_rom_sgb boot_rom_sgb ( .data ( boot_rom_sgb_do) ); +// -------------------------------------------------------------------- +// ------------------ External bus (WRAM, Cartridge) ------------------ +// -------------------------------------------------------------------- + +// Emulate cartridge open bus behavior. +// Some games read from Cart RAM while it is disabled or not present and +// expect to read the previous ROM byte instead of $FF otherwise they freeze. +// Ex. Tokyo Disneyland - Fantasy Tour (in Minnie's house) and +// Daiku no Gen-san - Kachikachi no Tonkachi ga Kachi (Stage 1-4) + +reg [7:0] open_bus_data; +reg [2:0] open_bus_cnt; + +assign SS_Top2_BACK[ 7: 0] = open_bus_data; +assign SS_Top2_BACK[10: 8] = open_bus_cnt; + +always @(posedge clk_sys) begin + if(reset_ss) begin + open_bus_data <= SS_Top2[ 7: 0]; // 8'd0; + open_bus_cnt <= SS_Top2[10: 8]; // 3'd0; + end else if (ce) begin + open_bus_data <= ext_bus_di; + if (ext_bus_wram_sel | (cart_sel & cart_oe) ) begin + open_bus_cnt <= 0; + end else if (~&open_bus_cnt) begin + open_bus_cnt <= open_bus_cnt + 1'b1; + if (open_bus_cnt == 3'd4) open_bus_data <= 8'hFF; // Slow pull-up + end + end +end + +assign cart_di = cpu_do; + +wire hdma_read_ext_bus = (isGBC & hdma_rd & hdma_sel_ext_bus); +wire dma_read_ext_bus = (dma_rd & dma_sel_ext_bus); + +assign nCS = ~( hdma_read_ext_bus ? (hdma_sel_cram | hdma_sel_iram) : dma_read_ext_bus ? dma_sel_ext_ram : (sel_cram | sel_iram) ); + +wire [15:0] ext_bus_i = hdma_read_ext_bus ? hdma_source_addr : dma_read_ext_bus ? dma_addr : cpu_addr; + +// External A15 is not directly connected to internal A15. It does not go low when accessing the boot rom. +assign ext_bus_a15 = ext_bus_i[15] | sel_boot_rom; +assign ext_bus_addr = ext_bus_i[14:0]; + +assign ext_bus_rd = hdma_read_ext_bus | dma_read_ext_bus | (sel_ext_bus & ~cpu_rd_n); +assign ext_bus_wr = (sel_ext_bus & ~cpu_wr_n_edge) & ~hdma_read_ext_bus & ~dma_read_ext_bus; + +assign ext_bus_wram_sel = ~nCS & ext_bus_addr[14]; +assign ext_bus_cram_sel = ~nCS & ~ext_bus_addr[14]; +assign ext_bus_rom_sel = ~ext_bus_a15; + +assign ext_bus_di = ext_bus_wram_sel ? iram_do : + (cart_sel & cart_oe) ? cart_do : open_bus_data; + +assign cart_sel = ext_bus_rom_sel | ext_bus_cram_sel; +assign cart_rd = cart_sel & ext_bus_rd; +assign cart_wr = cart_sel & ext_bus_wr; + +assign DMA_on = cart_sel & (hdma_active | dma_rd); + // -------------------------------------------------------------------- // ------------------------ savestates ------------------------- // -------------------------------------------------------------------- @@ -904,8 +948,9 @@ assign Savestate_CRAMAddr = Savestate_RAMAddr; assign Savestate_CRAMRWrEn = Savestate_RAMRWrEn[4]; assign Savestate_CRAMWriteData = Savestate_RAMWriteData; -wire [63:0] SaveStateBus_Dout = SaveStateBus_wired_or[0] | SaveStateBus_wired_or[1] | SaveStateBus_wired_or[2] | SaveStateBus_wired_or[3] | - SaveStateBus_wired_or[4] | SaveStateBus_wired_or[5] | SaveStateBus_wired_or[6] | SaveStateExt_Dout; +wire [63:0] SaveStateBus_Dout = SaveStateBus_wired_or[0] | SaveStateBus_wired_or[1] | SaveStateBus_wired_or[2] | SaveStateBus_wired_or[3] | + SaveStateBus_wired_or[4] | SaveStateBus_wired_or[5] | SaveStateBus_wired_or[6] | SaveStateBus_wired_or[7] | + SaveStateExt_Dout; wire sleep_rewind, sleep_savestates; diff --git a/rtl/mappers/gb_camera.v b/rtl/mappers/gb_camera.v index 88761bb..6fd231e 100644 --- a/rtl/mappers/gb_camera.v +++ b/rtl/mappers/gb_camera.v @@ -17,9 +17,12 @@ module gb_camera ( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + inout cart_oe_b, + input cram_rd, input [7:0] cram_di, inout [7:0] cram_do_b, inout [16:0] cram_addr_b, @@ -32,6 +35,7 @@ module gb_camera ( wire [22:0] mbc_addr; wire [7:0] cram_do; wire [16:0] cram_addr; +wire cart_oe; wire ram_enabled; wire has_battery; wire [15:0] savestate_back; @@ -39,6 +43,7 @@ wire [15:0] savestate_back; assign mbc_addr_b = enable ? mbc_addr : 23'hZ; assign cram_do_b = enable ? cram_do : 8'hZ; assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign cart_oe_b = enable ? cart_oe : 1'hZ; assign ram_enabled_b = enable ? ram_enabled : 1'hZ; assign has_battery_b = enable ? has_battery : 1'hZ; assign savestate_back_b = enable ? savestate_back : 16'hZ; @@ -47,7 +52,7 @@ assign savestate_back_b = enable ? savestate_back : 16'hZ; reg [5:0] rom_bank_reg; reg [3:0] ram_bank_reg; -reg ram_enable; +reg ram_write_en; reg cam_en; assign savestate_back[ 5: 0] = rom_bank_reg; @@ -55,23 +60,23 @@ assign savestate_back[ 8: 6] = 0; assign savestate_back[12: 9] = ram_bank_reg; assign savestate_back[ 13] = 0; assign savestate_back[ 14] = cam_en; -assign savestate_back[ 15] = ram_enable; +assign savestate_back[ 15] = ram_write_en; always @(posedge clk_sys) begin if(savestate_load & enable) begin rom_bank_reg <= savestate_data[ 5: 0]; //6'd1; ram_bank_reg <= savestate_data[12: 9]; //4'd0; cam_en <= savestate_data[ 14]; //1'b0; - ram_enable <= savestate_data[ 15]; //1'b0; + ram_write_en <= savestate_data[ 15]; //1'b0; end else if(~enable) begin rom_bank_reg <= 6'd1; ram_bank_reg <= 4'd0; cam_en <= 1'b0; - ram_enable <= 1'b0; + ram_write_en <= 1'b0; end else if(ce_cpu) begin if (cart_wr & ~cart_a15) begin case(cart_addr[14:13]) - 2'b00: ram_enable <= (cart_di[3:0] == 4'ha); //RAM enable/disable + 2'b00: ram_write_en <= (cart_di[3:0] == 4'ha); //RAM write enable/disable 2'b01: rom_bank_reg <= cart_di[5:0]; //write to ROM bank register 2'b10: begin if (cart_di[4]) begin @@ -99,7 +104,9 @@ assign mbc_addr = { 3'b000, rom_bank_m, cart_addr[13:0] }; // 16k ROM Bank 0-63 assign cram_do = cam_en ? 8'h00 : cram_di; // Reading from RAM or CAM is always enabled assign cram_addr = { ram_bank, cart_addr[12:0] }; +assign cart_oe = (cart_rd & ~cart_a15) | cram_rd; + assign has_battery = 1; -assign ram_enabled = ~cam_en & ram_enable; // Writing RAM +assign ram_enabled = ~cam_en & ram_write_en; // Writing RAM endmodule \ No newline at end of file diff --git a/rtl/mappers/huc1.v b/rtl/mappers/huc1.v index bc01cfb..4ac872b 100644 --- a/rtl/mappers/huc1.v +++ b/rtl/mappers/huc1.v @@ -17,9 +17,12 @@ module huc1 ( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + inout cart_oe_b, + input cram_rd, input [7:0] cram_di, inout [7:0] cram_do_b, inout [16:0] cram_addr_b, @@ -33,12 +36,14 @@ wire [22:0] mbc_addr; wire ram_enabled; wire [7:0] cram_do; wire [16:0] cram_addr; +wire cart_oe; wire has_battery; wire [15:0] savestate_back; assign mbc_addr_b = enable ? mbc_addr : 23'hZ; assign cram_do_b = enable ? cram_do : 8'hZ; assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign cart_oe_b = enable ? cart_oe : 1'hZ; assign ram_enabled_b = enable ? ram_enabled : 1'hZ; assign has_battery_b = enable ? has_battery : 1'hZ; assign savestate_back_b = enable ? savestate_back : 16'hZ; @@ -86,12 +91,14 @@ wire [5:0] rom_bank = (~cart_addr[14]) ? 6'd0 : rom_bank_reg; wire [5:0] rom_bank_m = rom_bank & rom_mask[5:0]; //64 assign mbc_addr = { 3'b000, rom_bank_m, cart_addr[13:0] }; // 16k ROM Bank 0-63 -assign ram_enabled = ~ir_en & has_ram; // 0xC0 is no light detected -assign cram_do = ir_en ? 8'hC0 : ram_enabled ? cram_di : 8'hFF; +assign cram_do = ir_en ? 8'hC0 : cram_di; assign cram_addr = { 2'b00, ram_bank, cart_addr[12:0] }; + +assign cart_oe = (cart_rd & ~cart_a15) | (cram_rd & (ir_en | ram_enabled)); + +assign ram_enabled = ~ir_en & has_ram; assign has_battery = 1; - endmodule \ No newline at end of file diff --git a/rtl/mappers/huc3.v b/rtl/mappers/huc3.v index 2fcbaa5..9cc3696 100644 --- a/rtl/mappers/huc3.v +++ b/rtl/mappers/huc3.v @@ -26,8 +26,10 @@ module huc3 ( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + inout cart_oe_b, input nCS, @@ -44,6 +46,7 @@ wire [22:0] mbc_addr; wire ram_enabled; wire [7:0] cram_do; wire [16:0] cram_addr; +wire cart_oe; wire has_battery; wire [63:0] savestate_back; @@ -51,9 +54,12 @@ reg [31:0] RTC_timestampOut; reg [47:0] RTC_savedtimeOut; wire RTC_inuse = 1; +wire is_cram_addr = ~nCS & ~cart_addr[14]; + assign mbc_addr_b = enable ? mbc_addr : 23'hZ; assign cram_do_b = enable ? cram_do : 8'hZ; assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign cart_oe_b = enable ? cart_oe : 1'hZ; assign ram_enabled_b = enable ? ram_enabled : 1'hZ; assign has_battery_b = enable ? has_battery : 1'hZ; assign savestate_back_b = enable ? savestate_back : 64'hZ; @@ -163,7 +169,7 @@ always @(posedge clk_sys) begin rtc_index <= 8'd0; rtc_flags <= 4'd0; rtc_out <= 4'd0; - end else if(ce_cpu & cart_wr & ~nCS & ~cart_addr[14]) begin // $A000-BFFF + end else if(ce_cpu & cart_wr & is_cram_addr) begin // $A000-BFFF if (mode == 4'hB) begin if (cart_di[7:4] == 4'd1) begin case(rtc_index) @@ -233,10 +239,13 @@ always @* begin end assign mbc_addr = { 2'b00, rom_bank_m, cart_addr[13:0] }; // 16k ROM Bank 0-127 -assign ram_enabled = (mode == 4'hA) & has_ram; // RAM write enable assign cram_do = cram_do_r; assign cram_addr = { 2'b00, ram_bank, cart_addr[12:0] }; + +assign cart_oe = cart_rd & (~cart_a15 | is_cram_addr); + +assign ram_enabled = (mode == 4'hA) & has_ram; // RAM write enable assign has_battery = has_ram; diff --git a/rtl/mappers/mappers.v b/rtl/mappers/mappers.v index 9b6061e..41bb32a 100644 --- a/rtl/mappers/mappers.v +++ b/rtl/mappers/mappers.v @@ -52,8 +52,10 @@ module mappers( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + output cart_oe, input [7:0] rom_di, output [7:0] rom_do, @@ -83,6 +85,7 @@ tri0 [15:0] savestate_back_b; tri0 [63:0] savestate_back2_b; tri0 [7:0] cram_wr_do_b; tri0 cram_wr_b; +tri0 cart_oe_b; tri0 [31:0] RTC_timestampOut_b; tri0 [47:0] RTC_savedtimeOut_b; tri0 RTC_inuse_b; @@ -91,6 +94,7 @@ tri0 RTC_inuse_b; wire ce = speed ? ce_cpu2x : ce_cpu; wire no_mapper = ~(mbc1 | mbc2 | mbc3 | mbc5 | mbc6 | mbc7 | mmm01 | huc1 | huc3 | gb_camera | tama | rocket | sachen); wire rom_override = (rocket); +wire cart_oe_override = (mbc3 | mbc7 | huc1 | huc3 | gb_camera | tama); mbc1 map_mbc1 ( .enable ( mbc1 ), @@ -186,8 +190,10 @@ mbc3 map_mbc3 ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe_b ( cart_oe_b ), .nCS ( nCS ), @@ -286,8 +292,10 @@ mbc7 map_mbc7 ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe_b ( cart_oe_b ), .nCS ( nCS ), @@ -353,9 +361,12 @@ huc1 map_huc1 ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe_b ( cart_oe_b ), + .cram_rd ( cram_rd ), .cram_di ( cram_di ), .cram_do_b ( cram_do_b ), .cram_addr_b ( cram_addr_b ), @@ -393,8 +404,10 @@ huc3 map_huc3 ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe_b ( cart_oe_b ), .nCS ( nCS ), @@ -426,9 +439,12 @@ gb_camera map_gb_camera ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe_b ( cart_oe_b ), + .cram_rd ( cram_rd ), .cram_di ( cram_di ), .cram_do_b ( cram_do_b ), .cram_addr_b ( cram_addr_b ), @@ -459,8 +475,10 @@ tama map_tama ( .cart_mbc_type ( cart_mbc_type ), + .cart_rd ( cart_rd ), .cart_wr ( cart_wr ), .cart_di ( cart_di ), + .cart_oe_b ( cart_oe_b ), .cram_rd ( cram_rd ), .cram_di ( cram_di ), @@ -538,7 +556,7 @@ sachen map_sachen ( .has_battery_b ( has_battery_b ) ); -assign { cram_do, ram_enabled } = { cram_do_b, ram_enabled_b }; +assign { cram_do } = { cram_do_b }; assign { savestate_back, savestate_back2 } = { savestate_back_b, savestate_back2_b }; assign { RTC_timestampOut, RTC_savedtimeOut, RTC_inuse } = { RTC_timestampOut_b, RTC_savedtimeOut_b, RTC_inuse_b }; assign { cram_wr_do, cram_wr } = { cram_wr_do_b, cram_wr_b }; @@ -546,6 +564,8 @@ assign { cram_wr_do, cram_wr } = { cram_wr_do_b, cram_wr_b }; assign mbc_addr = no_mapper ? {8'd0, cart_addr[14:0]} : mbc_addr_b; assign cram_addr = no_mapper ? {4'd0, cart_addr[12:0]} : cram_addr_b; assign has_battery = no_mapper ? (cart_mbc_type == 8'h09) : has_battery_b; +assign ram_enabled = no_mapper ? has_ram : ram_enabled_b; assign rom_do = rom_override ? rom_do_b : rom_di; +assign cart_oe = cart_oe_override ? cart_oe_b : ((cart_rd & ~cart_a15) | (cram_rd & ram_enabled)); endmodule \ No newline at end of file diff --git a/rtl/mappers/mbc3.v b/rtl/mappers/mbc3.v index af7981e..137afb9 100644 --- a/rtl/mappers/mbc3.v +++ b/rtl/mappers/mbc3.v @@ -30,8 +30,10 @@ module mbc3 ( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + inout cart_oe_b, input nCS, @@ -47,9 +49,11 @@ module mbc3 ( wire [22:0] mbc_addr; wire [7:0] cram_do; wire [16:0] cram_addr; +wire cart_oe; wire ram_enabled; wire has_battery; wire [15:0] savestate_back; +wire is_cram_addr = ~nCS & ~cart_addr[14]; reg [31:0] RTC_timestampOut; reg [47:0] RTC_savedtimeOut; @@ -58,6 +62,7 @@ reg RTC_inuse; assign mbc_addr_b = enable ? mbc_addr : 23'hZ; assign cram_do_b = enable ? cram_do : 8'hZ; assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign cart_oe_b = enable ? cart_oe : 1'hZ; assign ram_enabled_b = enable ? ram_enabled : 1'hZ; assign has_battery_b = enable ? has_battery : 1'hZ; assign savestate_back_b = enable ? savestate_back : 16'hZ; @@ -134,8 +139,10 @@ end assign cram_do = cram_do_r; assign cram_addr = { 1'b0, mbc3_ram_bank, cart_addr[12:0] }; +assign cart_oe = cart_rd & (~cart_a15 | (is_cram_addr & mbc_ram_enable & (mbc3_mode | has_ram)) ); + assign has_battery = (cart_mbc_type == 8'h0F || cart_mbc_type == 8'h10 || cart_mbc_type == 8'h13); -assign ram_enabled = mbc_ram_enable & has_ram; +assign ram_enabled = mbc_ram_enable & ~mbc3_mode & has_ram; ///////////////////////////// RTC /////////////////////////////// reg [2:0] rtc_index; @@ -214,7 +221,7 @@ always @(posedge clk_sys) begin RTC_inuse <= 1'b1; - end else if(ce_cpu && cart_wr && ~nCS && ~cart_addr[14] && mbc3_mode == 1'b1) begin // setting RTC registers from game + end else if(ce_cpu && cart_wr && is_cram_addr && mbc3_mode == 1'b1) begin // setting RTC registers from game case (rtc_index) 0: begin diff --git a/rtl/mappers/mbc7.v b/rtl/mappers/mbc7.v index 0a974fd..308c0d4 100644 --- a/rtl/mappers/mbc7.v +++ b/rtl/mappers/mbc7.v @@ -24,8 +24,10 @@ module mbc7 ( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + inout cart_oe_b, input nCS, @@ -44,16 +46,19 @@ module mbc7 ( wire [22:0] mbc_addr; wire [7:0] cram_do; wire [16:0] cram_addr; +wire cart_oe; wire ram_enabled; wire has_battery; wire [15:0] savestate_back; wire [63:0] savestate_back2; wire [7:0] cram_wr_do; wire cram_wr; +wire is_cram_addr = ~nCS & ~cart_addr[14]; assign mbc_addr_b = enable ? mbc_addr : 23'hZ; assign cram_do_b = enable ? cram_do : 8'hZ; assign cram_addr_b = enable ? cram_addr : 17'hZ; +assign cart_oe_b = enable ? cart_oe : 1'hZ; assign ram_enabled_b = enable ? ram_enabled : 1'hZ; assign has_battery_b = enable ? has_battery : 1'hZ; assign savestate_back_b = enable ? savestate_back : 16'hZ; @@ -71,6 +76,7 @@ reg accel_latched; reg eeprom_di, eeprom_clk, eeprom_cs; wire ram_reg_en = ram_enable1 & ram_enable2; +wire ram_reg_sel = is_cram_addr & ~cart_addr[12]; // $A000-AFFF assign savestate_back[ 6: 0] = rom_bank_reg; assign savestate_back[ 7] = ram_enable1; @@ -108,7 +114,7 @@ always @(posedge clk_sys) begin 2'b10: ram_enable2 <= (cart_di == 8'h40); //RAM enable/disable endcase end - if (ram_reg_en & ~nCS & ~cart_addr[14] & ~cart_addr[12]) begin // A000-AFFF + if (ram_reg_en & ram_reg_sel) begin case(cart_addr[7:4]) 0: if (cart_di == 8'h55) begin accel_latched <= 1'b0; @@ -155,7 +161,7 @@ eeprom93LC56 eeprom( reg [7:0] cram_do_r; always @* begin cram_do_r = 8'hFF; - if (ram_reg_en & ~cart_addr[12]) begin // cram_rd & A000-AFFF + if (ram_reg_en & ram_reg_sel) begin case(cart_addr[7:4]) 2: cram_do_r = accelerometer_x[ 7:0]; 3: cram_do_r = accelerometer_x[15:8]; @@ -180,6 +186,8 @@ assign mbc_addr = { 2'b00, rom_bank_m, cart_addr[13:0] }; // 16k ROM Bank 0-511 assign cram_do = cram_do_r; assign cram_addr = { 9'd0, cram_addr_e }; +assign cart_oe = cart_rd & (~cart_a15 | (ram_reg_en & ram_reg_sel)); + assign has_battery = 1; assign ram_enabled = 0; // EEPROM diff --git a/rtl/mappers/tama.v b/rtl/mappers/tama.v index c2655ce..e9cd823 100644 --- a/rtl/mappers/tama.v +++ b/rtl/mappers/tama.v @@ -18,8 +18,10 @@ module tama ( input [7:0] cart_mbc_type, + input cart_rd, input cart_wr, input [7:0] cart_di, + inout cart_oe_b, input nCS, @@ -44,6 +46,7 @@ wire has_battery; wire [63:0] savestate_back; wire [7:0] cram_wr_do; wire cram_wr; +wire cart_oe; assign mbc_addr_b = enable ? mbc_addr : 23'hZ; assign cram_do_b = enable ? cram_do : 8'hZ; @@ -53,6 +56,7 @@ assign has_battery_b = enable ? has_battery : 1'hZ; assign savestate_back_b = enable ? savestate_back : 64'hZ; assign cram_wr_do_b = enable ? cram_wr_do : 8'hZ; assign cram_wr_b = enable ? cram_wr : 1'hZ; +assign cart_oe_b = enable ? cart_oe : 1'hZ; // --------------------- CPU register interface ------------------ // https://gbdev.gg8.se/forums/viewtopic.php?id=469 @@ -321,6 +325,8 @@ assign cram_wr_do = reg_data_in; assign cram_do = { 4'hF, cram_do_r }; assign cram_addr = { 12'd0, reg_addr }; +assign cart_oe = (cart_rd & ~cart_a15) | (cram_rd & ~cart_addr[0]); + assign has_battery = 1; assign ram_enabled = 0; diff --git a/rtl/reg_savestates.vhd b/rtl/reg_savestates.vhd index 92dbcf0..f744393 100644 --- a/rtl/reg_savestates.vhd +++ b/rtl/reg_savestates.vhd @@ -38,7 +38,8 @@ package pReg_savestates is constant REG_SAVESTATE_Wave1_GBC : regmap_type := ( 35, 63, 0, 1, x"FF00FF00FF00FF00"); constant REG_SAVESTATE_Wave2_GBC : regmap_type := ( 36, 63, 0, 1, x"FF00FF00FF00FF00"); - constant REG_SAVESTATE_Top : regmap_type := ( 31, 53, 0, 1, x"0000000000800001"); + constant REG_SAVESTATE_Top : regmap_type := ( 31, 54, 0, 1, x"0000000000800001"); + constant REG_SAVESTATE_Top2 : regmap_type := ( 38, 10, 0, 1, x"0000000000000000"); constant REG_SAVESTATE_Ext : regmap_type := ( 32, 15, 0, 1, x"0000000000000001"); constant REG_SAVESTATE_Ext2 : regmap_type := ( 37, 63, 0, 1, x"0000000000000000");