Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/coolgirl-multicart/coolgirl-famicom-multicart.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2020-09-14 17:59:51 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2020-09-14 23:21:08 +0300
commit5b61c22343f5ba627988cb60aaa22f5adbb08bce (patch)
treed1abca6f26c7a1855b0453e182501298e74df82b
parent5635058f3006ace7786e13f4a98143009a9364df (diff)
Huge optimization
-rw-r--r--mappers.vh466
1 files changed, 245 insertions, 221 deletions
diff --git a/mappers.vh b/mappers.vh
index 8515c1d..c489917 100644
--- a/mappers.vh
+++ b/mappers.vh
@@ -27,55 +27,89 @@
reg four_screen = 0;
reg lockout = 0;
- // some common registers for all mappers
- reg [7:0] r0 = 0;
- reg [7:0] r1 = 0;
- reg [7:0] r2 = 0;
- reg [7:0] r3 = 0;
- reg [7:0] r4 = 0;
- reg [7:0] r5 = 0;
-
/*
reg [7:0] mul1;
reg [7:0] mul2;
wire [15:0] mul = mul1*mul2;
*/
-
- // for scanline-based interrupts
- reg [7:0] irq_scanline_counter = 0;
- reg [1:0] a12_low_time = 0;
- reg irq_scanline_reload = 0;
- reg [7:0] irq_scanline_latch = 0;
- reg irq_scanline_reload_clear = 0;
- reg irq_scanline_enabled = 0;
- reg irq_scanline_value = 0;
- reg irq_scanline_ready = 0;
- reg irq_scanline_out = 0;
- // for MMC5
- reg irq_scanline2_enabled = 0;
- reg [7:0] irq_scanline2_line = 0;
- reg irq_scanline2_out = 0;
- reg irq_scanline2_clear = 0;
- // current scanline counter
- reg [7:0] scanline = 0;
- reg [3:0] ppu_rd_hi_time = 0;
- reg new_screen = 0;
- reg new_screen_clear = 0;
- reg [1:0] ppu_nt_read_count;
-
- // for CPU-based interrupts
- reg [15:0] irq_cpu_value = 0;
- reg irq_cpu_out = 0;
- reg [3:0] irq_cpu_control = 0;
- reg [15:0] irq_cpu_latch = 0;
- reg [6:0] vrc4_irq_prescaler = 0;
- reg [1:0] vrc4_irq_prescaler_counter = 0;
+ // IRQ stuff
+ assign irq = (mmc3_irq_out | mmc5_irq_out | mapper18_irq_out | mapper65_irq_out | vrc4_irq_cpu_out | vrc3_irq_cpu_out | fme7_irq_out | mapper42_irq_out) ? 1'b0 : 1'bZ;
+ // for scanline-based interrupts, counts A12 rises after long A12 falls (MMC3)
+ reg mmc3_irq_enabled = 0; // register to enable/disable counter
+ reg [7:0] mmc3_irq_latch = 0; // stores counter reload latch value
+ reg [7:0] mmc3_irq_counter = 0; // counter itself (downcounting)
+ reg [1:0] a12_low_time = 0; // counts how long A12 is low
+ reg mmc3_irq_reload = 0; // flag to reload counter from latch
+ reg mmc3_irq_reload_clear = 0; // flag to clear reload flag
+ reg mmc3_irq_ready = 0; // stores 1 when IRQ is ready (enabled and non-zero)
+ reg mmc3_irq_out = 0; // stores 1 when IRQ is triggered
+ // scanline counter, counts dummy PPU reads
+ reg [3:0] ppu_rd_hi_time = 0; // counts how log there is no reads from PPU to detect v-blank
+ reg [1:0] ppu_nt_read_count; // nametable read counter
+ reg [7:0] scanline = 0; // current scanline
+ reg new_screen = 0; // stores 1 when v-blank detected ("in frame" flag)
+ reg new_screen_clear = 0; // flag to clear new_screen flag
+ // for scanline-based interrupts, counts dummy PPU reads (MMC5)
+ reg mmc5_irq_enabled = 0; // register to enable/disable counter
+ reg [7:0] mmc5_irq_line = 0; // scanline on which IRQ will be triggered
+ reg mmc5_irq_ack = 0; // flag to acknowledge IRQ
+ reg mmc5_irq_out = 0; // stores 1 when IRQ is triggered
+ // for mapper #18
+ reg [15:0] mapper18_irq_value = 0; // counter itself (upcounting/downcounting depends on mapper)
+ reg [3:0] mapper18_irq_control = 0; // IRQ settings
+ reg [15:0] mapper18_irq_latch = 0; // stores counter reload latch value
+ reg mapper18_irq_out = 0;
+ // for mapper #65
+ reg mapper65_irq_enabled = 0;
+ reg [15:0] mapper65_irq_value = 0; // counter itself (upcounting/downcounting depends on mapper)
+ reg [15:0] mapper65_irq_latch = 0; // stores counter reload latch value
+ reg mapper65_irq_out = 0;
+ // for Sunsoft FME-7
+ reg fme7_irq_enabled = 0; // register to enable/disable IRQ
+ reg fme7_counter_enabled = 0; // register to enable/disable counter
+ reg [15:0] fme7_irq_value = 0; // counter itself (downcounting)
+ reg fme7_irq_out = 0; // stores 1 when IRQ is triggered
+ // for VRC4 CPU-based interrupts
+ reg [7:0] vrc4_irq_cpu_value = 0; // counter itself (upcounting)
+ reg [2:0] vrc4_irq_cpu_control = 0; // IRQ settings
+ reg [7:0] vrc4_irq_cpu_latch = 0; // stores counter reload latch value
+ reg [6:0] vrc4_irq_prescaler = 0; // prescaler counter for VRC4
+ reg [1:0] vrc4_irq_prescaler_counter = 0; // prescaler cicles counter for VRC4
+ reg vrc4_irq_cpu_out = 0; // stores 1 when IRQ is triggered
+ // for VRC3 CPU-based interrupts
+ reg [15:0] vrc3_irq_cpu_value = 0; // counter itself (upcounting/downcounting depends on mapper)
+ reg [3:0] vrc3_irq_cpu_control = 0; // IRQ settings (individual for different mappers)
+ reg [15:0] vrc3_irq_cpu_latch = 0; // stores counter reload latch value
+ reg vrc3_irq_cpu_out = 0; // stores 1 when IRQ is triggered
+ // for mapper #42 (only Baby Mario)
+ reg mapper42_irq_enabled = 0; // register to enable/disable counter
+ reg [14:0] mapper42_irq_value = 0; // counter itself (upcounting)
+ wire mapper42_irq_out = mapper42_irq_value[14] & mapper42_irq_value[13];
+
+ // Mapper specific stuff
// for MMC2/MMC4
reg ppu_latch0 = 0;
reg ppu_latch1 = 0;
- reg ppu_mapper_163_latch = 0;
-
+ // for MMC1
+ reg [5:0] mmc1_load_register;
+ // for MMC3
+ reg [2:0] mmc3_internal;
+ // for mapper #69
+ reg [3:0] mapper69_internal;
+ // for mapper #90
+ reg mapper90_xor;
+ // for mapper #112
+ reg [2:0] mapper112_internal;
+ // for mapper #163
+ reg mapper_163_latch;
+ reg [7:0] mapper163_r0;
+ reg [7:0] mapper163_r1;
+ reg [7:0] mapper163_r2;
+ reg [7:0] mapper163_r3;
+ reg [7:0] mapper163_r4;
+ reg [7:0] mapper163_r5;
+ // to block two writes in a row
reg writed;
wire cpu_data_out_enabled;
@@ -85,11 +119,11 @@
(
((mapper == 0) && (cpu_addr_in[14:12] == 3'b101)) ? {8'b10000000, new_dendy} :
(USE_MAPPER_163 && (mapper == 6'b000110) && ({cpu_addr_in[14:12],cpu_addr_in[10:8]} == 6'b101001)) ?
- {1'b1, r2 | r0 | r1 | ~r3} :
+ {1'b1, mapper163_r2 | mapper163_r0 | mapper163_r1 | ~mapper163_r3} :
(USE_MAPPER_163 && (mapper == 6'b000110) && ({cpu_addr_in[14:12],cpu_addr_in[10:8]} == 6'b101101)) ?
- {1'b1, r5[0] ? r2 : r1} :
+ {1'b1, mapper163_r5[0] ? mapper163_r2 : mapper163_r1} :
(USE_MAPPER_005 && (mapper == 6'b001111) && (cpu_addr_in[14:0] == 15'h5204)) ?
- {1'b1, irq_scanline2_out, ~new_screen, 6'b000000} :
+ {1'b1, mmc5_irq_out, ~new_screen, 6'b000000} :
(USE_MAPPER_036 && mapper == 6'b011101 && {cpu_addr_in[14:13], cpu_addr_in[8]} == 3'b101) ? // Need by Strike Wolf, being simplified mapper, this cart still uses some TCX mapper features andrely on it
{1'b1, 2'b00, prg_bank_a[3:2], 4'b00} :
//(USE_MAPPER_090_MUL && (mapper == 6'b001101) && (cpu_addr_in[14:0] == 15'h5800)) ? {1'b1, mul[7:0]} :
@@ -167,7 +201,7 @@
) : ( // chr_mode[1]
(USE_MAPPER_163 && chr_mode[0]) ? (
// 001 - Mapper #163 special
- {ppu_mapper_163_latch, ppu_addr_in[11:10]}
+ {mapper_163_latch, ppu_addr_in[11:10]}
) : (
// 000 - 0x2000(A)
{chr_bank_a[7:3], ppu_addr_in[12:10]}
@@ -175,8 +209,6 @@
)
);
- assign irq = (irq_scanline_out | irq_scanline2_out | irq_cpu_out) ? 1'b0 : 1'bZ;
-
// for VRC
wire vrc_2b_hi = cpu_addr_in[1] | cpu_addr_in[3] | cpu_addr_in[5] | cpu_addr_in[7];
wire vrc_2b_low = cpu_addr_in[0] | cpu_addr_in[2] | cpu_addr_in[4] | cpu_addr_in[6];
@@ -184,103 +216,96 @@
always @ (negedge m2)
begin
// IRQ for VRC4
- if (USE_MAPPER_021_022_023_025 & USE_VRC4_INTERRUPTS & (mapper == 6'b011000) & (irq_cpu_control[1]))
+ if (USE_MAPPER_021_022_023_025 & USE_VRC4_INTERRUPTS & (mapper == 6'b011000) & (vrc4_irq_cpu_control[1]))
begin
// Cycle mode without prescaler is not used by any games? It's missed in fceux source code.
- if (irq_cpu_control[2]) // cycle mode
+ if (/*vrc4_irq_cpu_control[2]*/ 0) // cycle mode
begin
- irq_cpu_value[7:0] = irq_cpu_value[7:0] + 1'b1; // just count IRQ value
- if (irq_cpu_value[7:0] == 0)
+ vrc4_irq_cpu_value[7:0] = vrc4_irq_cpu_value[7:0] + 1'b1; // just count IRQ value
+ if (vrc4_irq_cpu_value[7:0] == 0)
begin
- irq_cpu_out = 1;
- irq_cpu_value[7:0] = irq_cpu_latch[7:0];
+ vrc4_irq_cpu_out = 1;
+ vrc4_irq_cpu_value[7:0] = vrc4_irq_cpu_latch[7:0];
end
end else begin // scanline mode
vrc4_irq_prescaler = vrc4_irq_prescaler + 1'b1; // count prescaler
if ((vrc4_irq_prescaler_counter[1] == 0 && vrc4_irq_prescaler == 114) || (vrc4_irq_prescaler_counter[1] == 1 && vrc4_irq_prescaler == 113)) // 114, 114, 113
begin
- irq_cpu_value[7:0] = irq_cpu_value[7:0] + 1'b1;
+ vrc4_irq_cpu_value[7:0] = vrc4_irq_cpu_value[7:0] + 1'b1;
vrc4_irq_prescaler = 0;
vrc4_irq_prescaler_counter = vrc4_irq_prescaler_counter + 1'b1;
if (vrc4_irq_prescaler_counter == 2'b11) vrc4_irq_prescaler_counter = 2'b00;
- if (irq_cpu_value[7:0] == 0)
+ if (vrc4_irq_cpu_value[7:0] == 0)
begin
- irq_cpu_out = 1;
- irq_cpu_value[7:0] = irq_cpu_latch[7:0];
+ vrc4_irq_cpu_out = 1;
+ vrc4_irq_cpu_value[7:0] = vrc4_irq_cpu_latch[7:0];
end
end
end
end
// IRQ for VRC3
- if (USE_MAPPER_073 & (mapper == 6'b010011) & (irq_cpu_control[1]))
+ if (USE_MAPPER_073 & (mapper == 6'b010011) & (vrc3_irq_cpu_control[1]))
begin
- if (irq_cpu_control[2])
+ if (vrc3_irq_cpu_control[2])
begin // 8-bit mode
- irq_cpu_value[7:0] = irq_cpu_value[7:0] + 1'b1;
- if (irq_cpu_value[7:0] == 0)
+ vrc3_irq_cpu_value[7:0] = vrc3_irq_cpu_value[7:0] + 1'b1;
+ if (vrc3_irq_cpu_value[7:0] == 0)
begin
- irq_cpu_out = 1;
- irq_cpu_value[7:0] = irq_cpu_latch[7:0];
+ vrc3_irq_cpu_out = 1;
+ vrc3_irq_cpu_value[7:0] = vrc3_irq_cpu_latch[7:0];
end
end else begin // 16-bit mode
- irq_cpu_value[15:0] = irq_cpu_value[15:0] + 1'b1;
- if (irq_cpu_value[15:0] == 0)
+ vrc3_irq_cpu_value[15:0] = vrc3_irq_cpu_value[15:0] + 1'b1;
+ if (vrc3_irq_cpu_value[15:0] == 0)
begin
- irq_cpu_out = 1;
- irq_cpu_value[15:0] = irq_cpu_latch[15:0];
+ vrc3_irq_cpu_out = 1;
+ vrc3_irq_cpu_value[15:0] = vrc3_irq_cpu_latch[15:0];
end
end
end
// IRQ for Sunsoft FME-7
- if (USE_MAPPER_069 & (mapper == 6'b011001) & (irq_cpu_control[1]))
+ if (USE_MAPPER_069 & (mapper == 6'b011001) & fme7_counter_enabled)
begin
- if ((irq_cpu_value[15:0] == 0) & irq_cpu_control[0]) irq_cpu_out = 1;
- irq_cpu_value[15:0] = irq_cpu_value[15:0] - 1'b1;
- end
-
+ if ((fme7_irq_value[15:0] == 0) & fme7_irq_enabled) fme7_irq_out = 1;
+ fme7_irq_value[15:0] = fme7_irq_value[15:0] - 1'b1;
+ end
// Mapper #18 - Sunsoft-2
if (USE_MAPPER_018 && mapper == 6'b000111)
begin
- if (irq_cpu_control[0])
+ if (mapper18_irq_control[0])
begin
- if (irq_cpu_control[3])
- begin
- if (irq_cpu_value[3:0] == 0) irq_cpu_out = 1;
- irq_cpu_value[3:0] = irq_cpu_value[3:0] - 1'b1;
- end else if (irq_cpu_control[2]) begin
- if (irq_cpu_value[7:0] == 0) irq_cpu_out = 1;
- irq_cpu_value[7:0] = irq_cpu_value[7:0] - 1'b1;
- end else if (irq_cpu_control[1]) begin
- if (irq_cpu_value[11:0] == 0) irq_cpu_out = 1;
- irq_cpu_value[11:0] = irq_cpu_value[11:0] - 1'b1;
- end else begin
- if (irq_cpu_value[15:0] == 0) irq_cpu_out = 1;
- irq_cpu_value[15:0] = irq_cpu_value[15:0] - 1'b1;
- end
+ reg carry;
+ {carry, mapper18_irq_value[3:0]} = {1'b0, mapper18_irq_value[3:0]} - 1'b1;
+ if (!mapper18_irq_control[3])
+ {carry, mapper18_irq_value[7:4]} = {1'b0, mapper18_irq_value[7:4]} - carry;
+ if (!mapper18_irq_control[3] && !mapper18_irq_control[2])
+ {carry, mapper18_irq_value[11:8]} = {1'b0, mapper18_irq_value[11:8]} - carry;
+ if (!mapper18_irq_control[3] && !mapper18_irq_control[2] && !mapper18_irq_control[1])
+ {carry, mapper18_irq_value[15:12]} = {1'b0, mapper18_irq_value[15:12]} - carry;
+ mapper18_irq_out = mapper18_irq_out | carry;
end
end
// Mapper #65 - Irem's H3001
if (USE_MAPPER_065 && mapper == 6'b001110)
begin
- if (irq_cpu_control[0])
+ if (mapper65_irq_enabled)
begin
- if (irq_cpu_value[15:0] > 0)
+ if (mapper65_irq_value[15:0] != 0)
begin
- irq_cpu_value[15:0] = irq_cpu_value[15:0] - 1'b1;
- if (irq_cpu_value[15:0] == 0) irq_cpu_out = 1;
+ mapper65_irq_value[15:0] = mapper65_irq_value[15:0] - 1'b1;
+ if (mapper65_irq_value[15:0] == 0) mapper65_irq_out = 1;
end
end
end
// IRQ for mapper #42
- if (USE_MAPPER_042 & USE_MAPPER_042_INTERRUPTS & (mapper == 6'b010111) & (irq_cpu_control[0]))
+ if (USE_MAPPER_042 & USE_MAPPER_042_INTERRUPTS & (mapper == 6'b010111) & mapper42_irq_enabled)
begin
- irq_cpu_value[14:0] = irq_cpu_value[14:0] + 1'b1;
- irq_cpu_out = irq_cpu_value[14] & irq_cpu_value[13];
+ mapper42_irq_value[14:0] = mapper42_irq_value[14:0] + 1'b1;
end
if (cpu_rw_in == 1) // read
@@ -324,9 +349,9 @@
begin
if (cpu_addr_in[14:0] == 15'h5101)
begin
- if ((r4 != 0) && (cpu_data_in == 0))
- r5[0] = ~r5[0];
- r4 = cpu_data_in;
+ if ((mapper163_r4 != 0) && (cpu_data_in == 0))
+ mapper163_r5[0] = ~mapper163_r5[0];
+ mapper163_r4 = cpu_data_in;
end else if ((cpu_addr_in[14:0] == 15'h5100) && (cpu_data_in == 6))
begin
prg_mode[0] = 0;
@@ -336,16 +361,16 @@
2'b10: begin
prg_mode[0] = 1;
prg_bank_a[7:6] = cpu_data_in[1:0];
- r0 = cpu_data_in;
+ mapper163_r0 = cpu_data_in;
end
2'b00: begin
prg_mode[0] = 1;
prg_bank_a[5:2] = cpu_data_in[3:0];
chr_mode[0] = cpu_data_in[7];
- r1 = cpu_data_in;
+ mapper163_r1 = cpu_data_in;
end
- 2'b11: r2 = cpu_data_in;
- 2'b01: r3 = cpu_data_in;
+ 2'b11: mapper163_r2 = cpu_data_in;
+ 2'b01: mapper163_r3 = cpu_data_in;
endcase
end
end
@@ -415,13 +440,13 @@
chr_bank_h = cpu_data_in;
if (cpu_addr_in[14:0] == 15'h5203)
begin
- irq_scanline2_line = cpu_data_in;
- irq_scanline2_clear = 1;
+ mmc5_irq_line = cpu_data_in;
+ mmc5_irq_ack = 1;
end
if (cpu_addr_in[14:0] == 15'h5204)
begin
- irq_scanline2_enabled = cpu_data_in[7];
- //irq_scanline2_clear = 1;
+ mmc5_irq_enabled = cpu_data_in[7];
+ //mmc5_irq_ack = 1;
end
end
@@ -562,17 +587,17 @@
5'b10101: chr_bank_g[7:4] = cpu_data_in[3:0]; // $D001
5'b10110: chr_bank_h[3:0] = cpu_data_in[3:0]; // $D002
5'b10111: chr_bank_h[7:4] = cpu_data_in[3:0]; // $D003
- 5'b11000: irq_cpu_latch[3:0] = cpu_data_in[3:0]; // $E000
- 5'b11001: irq_cpu_latch[7:4] = cpu_data_in[3:0]; // $E001
- 5'b11010: irq_cpu_latch[11:8] = cpu_data_in[3:0]; // $E002
- 5'b11011: irq_cpu_latch[15:12] = cpu_data_in[3:0]; // $E003
+ 5'b11000: mapper18_irq_latch[3:0] = cpu_data_in[3:0]; // $E000
+ 5'b11001: mapper18_irq_latch[7:4] = cpu_data_in[3:0]; // $E001
+ 5'b11010: mapper18_irq_latch[11:8] = cpu_data_in[3:0]; // $E002
+ 5'b11011: mapper18_irq_latch[15:12] = cpu_data_in[3:0]; // $E003
5'b11100: begin // $F000
- irq_cpu_value[15:0] = irq_cpu_latch[15:0];
- irq_cpu_out = 0;
+ mapper18_irq_value[15:0] = mapper18_irq_latch[15:0];
+ mapper18_irq_out = 0; // ack
end
5'b11101: begin // $F001
- irq_cpu_control[3:0] = cpu_data_in[3:0];
- irq_cpu_out = 0;
+ mapper18_irq_control[3:0] = cpu_data_in[3:0];
+ mapper18_irq_out = 0;
end
5'b11110: mirroring = cpu_data_in[1:0] ^ {1'b0, ~cpu_data_in[1]}; // $F002
5'b11111: ; // $F003 - sound
@@ -636,19 +661,19 @@
end
if ({cpu_addr_in[14:12], cpu_addr_in[1:0]} == 5'b10101) // $D001
mirroring = cpu_data_in[1:0];
- if (/*USE_MAPPER_090_INTERRUPTS &&*/ cpu_addr_in[14:12] == 3'b100) // $C00x
+ if (cpu_addr_in[14:12] == 3'b100) // $C00x
begin
case (cpu_addr_in[2:0])
- 3'b000: irq_scanline_enabled = cpu_data_in[0];
+ 3'b000: mmc3_irq_enabled = cpu_data_in[0];
3'b001: ;
- 3'b010: irq_scanline_enabled = 0;
- 3'b011: irq_scanline_enabled = 1;
+ 3'b010: mmc3_irq_enabled = 0;
+ 3'b011: mmc3_irq_enabled = 1;
3'b100: ;
3'b101: begin
- irq_scanline_latch = cpu_data_in ^ r0;
- irq_scanline_reload = 1;
+ mmc3_irq_latch = cpu_data_in ^ mapper90_xor;
+ mmc3_irq_reload = 1;
end
- 3'b110: r0 = cpu_data_in;
+ 3'b110: mapper90_xor = cpu_data_in;
3'b111: ;
endcase
end
@@ -661,15 +686,15 @@
6'b000000: prg_bank_a[5:0] = cpu_data_in[5:0]; // $8000
6'b001001: mirroring = {1'b0, cpu_data_in[7]}; // $9001, mirroring
6'b001011: begin
- irq_cpu_control[0] = cpu_data_in[7]; // $9003, enable IRQ
- irq_cpu_out = 0;
+ mapper65_irq_enabled = cpu_data_in[7]; // $9003, enable IRQ
+ mapper65_irq_out = 0; // ack
end
6'b001100: begin
- irq_cpu_value[15:0] = {r0, r1}; // $9004, IRQ reload
- irq_cpu_out = 0;
+ mapper65_irq_value = mapper65_irq_latch; // $9004, IRQ reload
+ mapper65_irq_out = 0; // ack
end
- 6'b001101: r0 = cpu_data_in; // $9005, IRQ high value
- 6'b001110: r1 = cpu_data_in; // $9006, IRQ low value
+ 6'b001101: mapper65_irq_latch[15:8] = cpu_data_in; // $9005, IRQ high value
+ 6'b001110: mapper65_irq_latch[7:0] = cpu_data_in; // $9006, IRQ low value
6'b010000: prg_bank_b[5:0] = cpu_data_in[5:0]; // $A000
6'b011000: chr_bank_a = cpu_data_in; // $B000
6'b011001: chr_bank_b = cpu_data_in; // $B001
@@ -685,51 +710,50 @@
// Mapper #1 - MMC1
/*
- r0 - load register
- flag0 - 16KB of WRAM (SOROM)
+ flag0 - 16KB of PRG RAM (SOROM)
*/
if (mapper == 6'b010000)
begin
if (cpu_data_in[7] == 1) // reset
begin
- r0[5:0] = 6'b100000;
+ mmc1_load_register[5:0] = 6'b100000;
prg_mode = 3'b000; // 0x4000 (A) + fixed last (C)
prg_bank_c[4:0] = 5'b11110;
end else begin
- r0[5:0] = {cpu_data_in[0], r0[5:1]};
- if (r0[0] == 1)
+ mmc1_load_register[5:0] = {cpu_data_in[0], mmc1_load_register[5:1]};
+ if (mmc1_load_register[0] == 1)
begin
case (cpu_addr_in[14:13])
2'b00: begin // $8000-$9FFF
- if (r0[4:3] == 2'b11)
+ if (mmc1_load_register[4:3] == 2'b11)
begin
prg_mode = 3'b000; // 0x4000 (A) + fixed last (C)
prg_bank_c[4:0] = 5'b11110;
- end else if (r0[4:3] == 2'b10)
+ end else if (mmc1_load_register[4:3] == 2'b10)
begin
prg_mode = 3'b001; // fixed first (C) + 0x4000 (A)
prg_bank_c[4:0] = 5'b00000;
end else
prg_mode = 3'b111; // 0x8000 (A)
- if (r0[5])
+ if (mmc1_load_register[5])
chr_mode = 3'b100;
else
chr_mode = 3'b000;
- mirroring[1:0] = r0[2:1] ^ 2'b10;
+ mirroring[1:0] = mmc1_load_register[2:1] ^ 2'b10;
end
2'b01: begin // $A000-$BFFF
- chr_bank_a[6:2] = r0[5:1];
- prg_bank_a[5] = r0[5]; // for SUROM, 512k PRG support
- prg_bank_c[5] = r0[5]; // for SUROM, 512k PRG support
+ chr_bank_a[6:2] = mmc1_load_register[5:1];
+ prg_bank_a[5] = mmc1_load_register[5]; // for SUROM, 512k PRG support
+ prg_bank_c[5] = mmc1_load_register[5]; // for SUROM, 512k PRG support
end
- 2'b10: chr_bank_e[6:2] = r0[5:1]; // $C000-$DFFF
+ 2'b10: chr_bank_e[6:2] = mmc1_load_register[5:1]; // $C000-$DFFF
2'b11: begin
- prg_bank_a[4:1] = r0[4:1]; // $E000-$FFFF
- sram_enabled = ~r0[5];
+ prg_bank_a[4:1] = mmc1_load_register[4:1]; // $E000-$FFFF
+ sram_enabled = ~mmc1_load_register[5];
end
endcase
- r0[5:0] = 6'b100000;
- if (flags[0]) // 16KB of WRAM
+ mmc1_load_register[5:0] = 6'b100000;
+ if (flags[0]) // 16KB of PRG RAM
begin
if (chr_mode[2])
sram_page = {1'b1, ~chr_bank_a[6]}; // page #2 is battery backed
@@ -770,19 +794,19 @@
if (USE_MAPPER_073 && mapper == 6'b010011)
begin
case (cpu_addr_in[14:12])
- 3'b000: irq_cpu_latch[3:0] = cpu_data_in[3:0]; // $8000-$8FFF
- 3'b001: irq_cpu_latch[7:4] = cpu_data_in[3:0]; // $9000-$9FFF
- 3'b010: irq_cpu_latch[11:8] = cpu_data_in[3:0]; // $A000-$AFFF
- 3'b011: irq_cpu_latch[15:12] = cpu_data_in[3:0]; // $B000-$BFFF
+ 3'b000: vrc3_irq_cpu_latch[3:0] = cpu_data_in[3:0]; // $8000-$8FFF
+ 3'b001: vrc3_irq_cpu_latch[7:4] = cpu_data_in[3:0]; // $9000-$9FFF
+ 3'b010: vrc3_irq_cpu_latch[11:8] = cpu_data_in[3:0]; // $A000-$AFFF
+ 3'b011: vrc3_irq_cpu_latch[15:12] = cpu_data_in[3:0]; // $B000-$BFFF
3'b100: begin // $C000-$CFFF
- irq_cpu_out = 0; // ack
- irq_cpu_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack
- if (irq_cpu_control[1]) // if E is set
- irq_cpu_value[15:0] = irq_cpu_latch[15:0]; // reload with latch
+ vrc3_irq_cpu_out = 0; // ack
+ vrc3_irq_cpu_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack
+ if (vrc3_irq_cpu_control[1]) // if E is set
+ vrc3_irq_cpu_value[15:0] = vrc3_irq_cpu_latch[15:0]; // reload with latch
end
3'b101: begin // $D000-$DFFF
- irq_cpu_out = 0; // ack
- irq_cpu_control[1] = irq_cpu_control[0];
+ vrc3_irq_cpu_out = 0; // ack
+ vrc3_irq_cpu_control[1] = vrc3_irq_cpu_control[0];
end
3'b110: ; // $E000-$EFFF
3'b111: prg_bank_a[3:1] = cpu_data_in[2:0]; // $F000-$FFFF
@@ -791,7 +815,6 @@
// Mapper #4 - MMC3/MMC6
/*
- r0[2:0] - internal register
flag0 - TxSROM
flag1 - mapper #189
flag2 - mapper #206 (disable most features)
@@ -800,7 +823,7 @@
begin
case ({cpu_addr_in[14:13], cpu_addr_in[0]})
3'b000: begin // $8000-$9FFE, even
- r0[2:0] = cpu_data_in[2:0];
+ mmc3_internal[2:0] = cpu_data_in[2:0];
if ((!USE_MAPPER_189 | ~flags[1]) & (!USE_MAPPER_206 | ~flags[2])) // disabled for mappers #189 & #206
begin
if (cpu_data_in[6])
@@ -817,7 +840,7 @@
end
end
3'b001: begin // $8001-$9FFF, odd
- case (r0[2:0])
+ case (mmc3_internal[2:0])
3'b000: chr_bank_a = cpu_data_in;
3'b001: chr_bank_c = cpu_data_in;
3'b010: chr_bank_e = cpu_data_in;
@@ -830,22 +853,21 @@
end
3'b010: if (!USE_MAPPER_206 | ~flags[2]) // disabled for mapper #206
mirroring = {1'b0, cpu_data_in[0]}; // $A000-$BFFE, even (mirroring)
- 3'b100: irq_scanline_latch = cpu_data_in; // $C000-$DFFE, even (IRQ latch)
- 3'b101: irq_scanline_reload = 1; // $C001-$DFFF, odd
- 3'b110: irq_scanline_enabled = 0; // $E000-$FFFE, even
+ 3'b100: mmc3_irq_latch = cpu_data_in; // $C000-$DFFE, even (IRQ latch)
+ 3'b101: mmc3_irq_reload = 1; // $C001-$DFFF, odd
+ 3'b110: mmc3_irq_enabled = 0; // $E000-$FFFE, even
3'b111: if (!USE_MAPPER_206 | ~flags[2]) // disabled for mapper #206
- irq_scanline_enabled = 1; // $E001-$FFFF, odd
+ mmc3_irq_enabled = 1; // $E001-$FFFF, odd
endcase
end
// Mapper #112
- // r0[2:0] - internal register
if (USE_MAPPER_112 && (mapper == 6'b010101))
begin
case (cpu_addr_in[14:13])
- 2'b00: r0[2:0] = cpu_data_in[2:0]; // $8000-$9FFF
+ 2'b00: mapper112_internal[2:0] = cpu_data_in[2:0]; // $8000-$9FFF
2'b01: begin // $A000-$BFFF
- case (r0[2:0])
+ case (mapper112_internal[2:0])
3'b000: prg_bank_a[5:0] = cpu_data_in[5:0];
3'b001: prg_bank_b[5:0] = cpu_data_in[5:0];
3'b010: chr_bank_a = cpu_data_in;
@@ -883,10 +905,10 @@
if (USE_MAPPER_048_INTERRUPTS)
begin
case ({cpu_addr_in[14:13], cpu_addr_in[1:0]})
- 4'b1000: irq_scanline_latch = ~cpu_data_in; // $C000, IRQ latch
- 4'b1001: irq_scanline_reload = 1; // $C001, IRQ reload
- 4'b1010: irq_scanline_enabled = 1; // $C002, IRQ enable
- 4'b1011: irq_scanline_enabled = 0; // $C003, IRQ disable & ack
+ 4'b1000: mmc3_irq_latch = ~cpu_data_in; // $C000, IRQ latch
+ 4'b1001: mmc3_irq_reload = 1; // $C001, IRQ reload
+ 4'b1010: mmc3_irq_enabled = 1; // $C002, IRQ enable
+ 4'b1011: mmc3_irq_enabled = 0; // $C003, IRQ disable & ack
endcase
end
end
@@ -900,10 +922,9 @@
3'b100: prg_bank_6000[3:0] = cpu_data_in[3:0]; // $E000, PRG Reg (8k @ $6000)
3'b101: mirroring = {1'b0, cpu_data_in[3]}; // Mirroring
3'b110: if (USE_MAPPER_042_INTERRUPTS) begin
- irq_cpu_control[0] = cpu_data_in[1];
- if (!irq_cpu_control[0]) begin
- irq_cpu_out = 0;
- irq_cpu_value = 0;
+ mapper42_irq_enabled = cpu_data_in[1];
+ if (!mapper42_irq_enabled) begin
+ mapper42_irq_value = 0;
end
end
endcase
@@ -978,20 +999,20 @@
if (cpu_addr_in[14:12] == 3'b111)
begin
case ({flags[0] ? vrc_2b_low : vrc_2b_hi, flags[0] ? vrc_2b_hi : vrc_2b_low})
- 2'b00: irq_cpu_latch[3:0] = cpu_data_in[3:0]; // IRQ latch low
- 2'b01: irq_cpu_latch[7:4] = cpu_data_in[3:0]; // IRQ latch hi
+ 2'b00: vrc4_irq_cpu_latch[3:0] = cpu_data_in[3:0]; // IRQ latch low
+ 2'b01: vrc4_irq_cpu_latch[7:4] = cpu_data_in[3:0]; // IRQ latch hi
2'b10: begin // IRQ control
- irq_cpu_out = 0; // ack
- irq_cpu_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack
- if (irq_cpu_control[1]) begin // if E is set
+ vrc4_irq_cpu_out = 0; // ack
+ vrc4_irq_cpu_control[2:0] = cpu_data_in[2:0]; // mode, enabled, enabled after ack
+ if (vrc4_irq_cpu_control[1]) begin // if E is set
vrc4_irq_prescaler_counter = 2'b00; // reset prescaler
vrc4_irq_prescaler = 0;
- irq_cpu_value[7:0] = irq_cpu_latch[7:0]; // reload with latch
+ vrc4_irq_cpu_value[7:0] = vrc4_irq_cpu_latch[7:0]; // reload with latch
end
end
2'b11: begin // IRQ ack
- irq_cpu_out = 0;
- irq_cpu_control[1] = irq_cpu_control[0];
+ vrc4_irq_cpu_out = 0;
+ vrc4_irq_cpu_control[1] = vrc4_irq_cpu_control[0];
end
endcase
end
@@ -1004,10 +1025,10 @@
*/
if (USE_MAPPER_069 && mapper == 6'b011001)
begin
- if (cpu_addr_in[14:13] == 2'b00) r0[3:0] = cpu_data_in[3:0];
+ if (cpu_addr_in[14:13] == 2'b00) mapper69_internal[3:0] = cpu_data_in[3:0];
if (cpu_addr_in[14:13] == 2'b01)
begin
- case (r0[3:0])
+ case (mapper69_internal[3:0])
4'b0000: chr_bank_a = cpu_data_in; // CHR0
4'b0001: chr_bank_b = cpu_data_in; // CHR1
4'b0010: chr_bank_c = cpu_data_in; // CHR2
@@ -1022,11 +1043,11 @@
4'b1011: prg_bank_c[5:0] = cpu_data_in[5:0]; // PRG3
4'b1100: mirroring[1:0] = cpu_data_in[1:0]; // mirroring
4'b1101: begin
- irq_cpu_control[1:0] = {cpu_data_in[7], cpu_data_in[0]}; // IRQ control
- irq_cpu_out = 0; // ack
+ {fme7_counter_enabled, fme7_irq_enabled} = {cpu_data_in[7], cpu_data_in[0]}; // IRQ control
+ fme7_irq_out = 0; // ack
end
- 4'b1110: irq_cpu_value[7:0] = cpu_data_in; // IRQ low
- 4'b1111: irq_cpu_value[15:8] = cpu_data_in; // IRQ high
+ 4'b1110: fme7_irq_value[7:0] = cpu_data_in; // IRQ low
+ 4'b1111: fme7_irq_value[15:8] = cpu_data_in; // IRQ high
endcase
end
end
@@ -1072,29 +1093,31 @@
end // romsel
end // write
- // for MMC5
- if (USE_MAPPER_005 && mapper == 6'b001111 && romsel && cpu_addr_in[14:0] == 15'h5204) // write or read
- irq_scanline2_clear = 1;
-
+
// some IRQ stuff
- if (irq_scanline_reload_clear)
- irq_scanline_reload = 0;
- if (irq_scanline2_clear && ~irq_scanline2_out)
- irq_scanline2_clear = 0;
- end
-
- // Fire scanline IRQ if counter is zero
- // BUT doesn't fire it when it's zero end reenabled
- always @ (*)
- begin
- if (!irq_scanline_enabled)
+ // for MMC3
+ if (mmc3_irq_reload_clear)
+ mmc3_irq_reload = 0;
+
+ if (!mmc3_irq_enabled)
+ begin
+ mmc3_irq_ready = 0;
+ mmc3_irq_out = 0;
+ end else if (mmc3_irq_enabled && mmc3_irq_counter != 0)
+ begin
+ // Fire scanline IRQ if counter is zero
+ // BUT doesn't fire it when it's zero end reenabled
+ mmc3_irq_ready = 1;
+ end
+ else if (mmc3_irq_ready && mmc3_irq_counter == 0)
begin
- irq_scanline_ready = 0;
- irq_scanline_out = 0;
- end else if (irq_scanline_enabled && !irq_scanline_value)
- irq_scanline_ready = 1;
- else if (irq_scanline_ready && irq_scanline_value)
- irq_scanline_out = 1;
+ mmc3_irq_out = 1;
+ end
+ // for MMC5
+ if (USE_MAPPER_005 && romsel && cpu_addr_in[14:0] == 15'h5204) // write or read
+ mmc5_irq_ack = 1;
+ if (mmc5_irq_ack && ~mmc5_irq_out)
+ mmc5_irq_ack = 0;
end
// IRQ counter
@@ -1102,18 +1125,15 @@
begin
if (a12_low_time == 3)
begin
- if ((irq_scanline_reload && !irq_scanline_reload_clear) || (irq_scanline_counter == 0))
+ if ((mmc3_irq_reload && !mmc3_irq_reload_clear) || (mmc3_irq_counter == 0))
begin
- irq_scanline_counter = irq_scanline_latch;
- if (irq_scanline_reload) irq_scanline_reload_clear = 1;
- end else
- irq_scanline_counter = irq_scanline_counter - 1'b1;
- if (irq_scanline_counter == 0 && irq_scanline_enabled)
- irq_scanline_value = 1;
- else
- irq_scanline_value = 0;
+ mmc3_irq_counter = mmc3_irq_latch;
+ if (mmc3_irq_reload) mmc3_irq_reload_clear = 1;
+ end else begin
+ mmc3_irq_counter = mmc3_irq_counter - 1'b1;
+ end
end
- if (!irq_scanline_reload) irq_scanline_reload_clear = 0;
+ if (!mmc3_irq_reload) mmc3_irq_reload_clear = 0;
end
// A12 must be low for 3 rises of M2
@@ -1134,8 +1154,10 @@
if (new_screen_clear) new_screen = 0;
end else if (ppu_rd_hi_time < 4'b1111)
begin
+ // Counting how long there is no PPU reads
ppu_rd_hi_time = ppu_rd_hi_time + 1'b1;
end else begin
+ // Too long, v-blank detected
new_screen = 1;
end
end
@@ -1143,13 +1165,13 @@
// Scanline counter
always @ (negedge ppu_rd_in)
begin
- if (irq_scanline2_clear) irq_scanline2_out = 0;
+ if (mmc5_irq_ack) mmc5_irq_out = 0;
if (~new_screen && new_screen_clear) new_screen_clear = 0;
if (new_screen & ~new_screen_clear)
begin
scanline = 0;
new_screen_clear = 1;
- ppu_mapper_163_latch = 0;
+ mapper_163_latch = 0;
end else
if (ppu_addr_in[13:12] == 2'b10)
begin
@@ -1158,12 +1180,14 @@
ppu_nt_read_count = ppu_nt_read_count + 1'b1;
end else begin
scanline = scanline + 1'b1;
- if (irq_scanline2_enabled && scanline == irq_scanline2_line+1)
- irq_scanline2_out = 1;
+ if (mmc5_irq_enabled && scanline == mmc5_irq_line+1)
+ mmc5_irq_out = 1;
if (scanline == 129)
- ppu_mapper_163_latch = 1;
+ mapper_163_latch = 1;
end
- end else ppu_nt_read_count = 0;
+ end else begin
+ ppu_nt_read_count = 0;
+ end
end
// for MMC2/MMC4