1
0
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:
Sebastien Delestaing
2016-09-09 17:05:04 +02:00
parent 53f21e9fad
commit 52ee9c65da
2 changed files with 33 additions and 10 deletions

View File

@@ -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

View File

@@ -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};