mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-01-27 12:21:44 +00:00
[NES] Game loader and compatibility improvements
Ignore dirty headers (Fantasy Zone now runs for example) Implement 4 screen mirroring for MMC3 (Gauntlet runs) Implement Mapper 206 (untested)
This commit is contained in:
@@ -20,8 +20,9 @@ module GameLoader(input clk, input reset,
|
||||
reg [21:0] bytes_left;
|
||||
|
||||
assign error = (state == 3);
|
||||
wire [7:0] prgrom = ines[4];
|
||||
wire [7:0] chrrom = ines[5];
|
||||
wire [7:0] prgrom = ines[4]; // Number of 16384 byte program ROM pages
|
||||
wire [7:0] chrrom = ines[5]; // Number of 8192 byte character ROM pages (0 indicates CHR RAM)
|
||||
wire has_chr_ram = (chrrom == 0);
|
||||
assign mem_data = indata;
|
||||
assign mem_write = (bytes_left != 0) && (state == 1 || state == 2) && indata_clk;
|
||||
|
||||
@@ -41,9 +42,25 @@ module GameLoader(input clk, input reset,
|
||||
chrrom <= 32 ? 5 :
|
||||
chrrom <= 64 ? 6 : 7;
|
||||
|
||||
wire [7:0] mapper = {ines[7][7:4], ines[6][7:4]};
|
||||
wire has_chr_ram = (chrrom == 0);
|
||||
assign mapper_flags = {16'b0, has_chr_ram, ines[6][0], chr_size, prg_size, mapper};
|
||||
// detect iNES2.0 compliant header
|
||||
wire is_nes20 = (ines[7][3:2] == 2'b10);
|
||||
// differentiate dirty iNES1.0 headers from proper iNES2.0 ones
|
||||
wire is_dirty = !is_nes20 && ((ines[8] != 0)
|
||||
|| (ines[9] != 0)
|
||||
|| (ines[10] != 0)
|
||||
|| (ines[11] != 0)
|
||||
|| (ines[12] != 0)
|
||||
|| (ines[13] != 0)
|
||||
|| (ines[14] != 0)
|
||||
|| (ines[15] != 0));
|
||||
|
||||
// Read the mapper number
|
||||
wire [7:0] mapper = {is_dirty ? 4'b0000 : ines[7][7:4], ines[6][7:4]};
|
||||
|
||||
// ines[6][0] is mirroring
|
||||
// ines[6][3] is 4 screen mode
|
||||
assign mapper_flags = {15'b0, ines[6][3], has_chr_ram, ines[6][0], chr_size, prg_size, mapper};
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
state <= 0;
|
||||
@@ -58,7 +75,8 @@ module GameLoader(input clk, input reset,
|
||||
ines[ctr] <= indata;
|
||||
bytes_left <= {prgrom, 14'b0};
|
||||
if (ctr == 4'b1111)
|
||||
state <= (ines[0] == 8'h4E) && (ines[1] == 8'h45) && (ines[2] == 8'h53) && (ines[3] == 8'h1A) && !ines[6][2] && !ines[6][3] ? 1 : 3;
|
||||
// Check the 'NES' header. Also, we don't support trainers.
|
||||
state <= (ines[0] == 8'h4E) && (ines[1] == 8'h45) && (ines[2] == 8'h53) && (ines[3] == 8'h1A) && !ines[6][2] ? 1 : 3;
|
||||
end
|
||||
1, 2: begin // Read the next |bytes_left| bytes into |mem_addr|
|
||||
if (bytes_left != 0) begin
|
||||
|
||||
@@ -251,7 +251,7 @@ module MMC2(input clk, input ce, input reset,
|
||||
assign chr_allow = flags[15];
|
||||
endmodule
|
||||
|
||||
// This mapper also handles mapper 119 and 47.
|
||||
// This mapper also handles mapper 47,118,119 and 206.
|
||||
module MMC3(input clk, input ce, input reset,
|
||||
input [31:0] flags,
|
||||
input [15:0] prg_ain, output [21:0] prg_aout,
|
||||
@@ -281,6 +281,9 @@ module MMC3(input clk, input ce, input reset,
|
||||
// TQROM maps 8kB CHR RAM
|
||||
wire TQROM = (flags[7:0] == 119);
|
||||
wire TxSROM = (flags[7:0] == 118); // Connects CHR A17 to CIRAM A10
|
||||
wire DxROM = (flags[7:0] == 206);
|
||||
|
||||
wire four_screen_mirroring = flags[16] | DxROM;
|
||||
|
||||
// Mapper 47 is a multicart that has 128k for each game. It has no RAM.
|
||||
wire mapper47 = (flags[7:0] == 47);
|
||||
@@ -384,16 +387,17 @@ module MMC3(input clk, input ce, input reset,
|
||||
wire [21:0] prg_aout_tmp = {3'b00_0, prgsel, prg_ain[12:0]};
|
||||
|
||||
assign {chr_allow, chr_aout} =
|
||||
(TQROM && chrsel[6]) ? {1'b1, 9'b11_1111_111, chrsel[2:0], chr_ain[9:0]} : // TQROM 8kb CHR-RAM
|
||||
(TQROM && chrsel[6]) ? {1'b1, 9'b11_1111_111, chrsel[2:0], chr_ain[9:0]} : // TQROM 8kb CHR-RAM
|
||||
(four_screen_mirroring && chr_ain[13]) ? {1'b1, 9'b11_1111_111, chr_ain[13], chr_ain[11:0]} : // DxROM 8kb CHR-RAM
|
||||
{flags[15], 4'b10_00, chrsel, chr_ain[9:0]}; // Standard MMC3
|
||||
|
||||
assign prg_is_ram = prg_ain >= 'h6000 && prg_ain < 'h8000 && ram_enable && !(ram_protect && prg_write);
|
||||
assign prg_allow = prg_ain[15] && !prg_write || prg_is_ram && !mapper47;
|
||||
wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
|
||||
assign prg_aout = prg_is_ram && !mapper47 ? prg_ram : prg_aout_tmp;
|
||||
assign prg_aout = prg_is_ram && !mapper47 && !DxROM ? prg_ram : prg_aout_tmp;
|
||||
assign vram_a10 = (TxSROM == 0) ? (mirroring ? chr_ain[11] : chr_ain[10]) :
|
||||
chrsel[7];
|
||||
assign vram_ce = chr_ain[13];
|
||||
assign vram_ce = chr_ain[13] && !four_screen_mirroring;
|
||||
endmodule
|
||||
|
||||
// MMC4 mapper chip. PRG ROM: 256kB. Bank Size: 16kB. CHR ROM: 128kB
|
||||
@@ -1837,6 +1841,7 @@ module MultiMapper(input clk, input ce, input ppu_ce, input reset,
|
||||
118, // TxSROM connects A17 to CIRAM A10.
|
||||
119, // TQROM uses the Nintendo MMC3 like other TxROM boards but uses the CHR bank number specially.
|
||||
47, // Mapper 047 is a MMC3 multicart
|
||||
206, // MMC3 w/o IRQ or WRAM support
|
||||
4: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq} = {mmc3_prg_addr, mmc3_prg_allow, mmc3_chr_addr, mmc3_vram_a10, mmc3_vram_ce, mmc3_chr_allow, mmc3_irq};
|
||||
|
||||
10: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow} = {mmc4_prg_addr, mmc4_prg_allow, mmc4_chr_addr, mmc4_vram_a10, mmc4_vram_ce, mmc4_chr_allow};
|
||||
|
||||
Reference in New Issue
Block a user