The NESDEV community has discussed the implementation of scanline detection, in-frame detection and other details. My mmc5 verilog has been able to make some games work properly, such as Metal Slader Glory.
For games in 8x16 sprite mode, some can be opportunistic to make the display look normal, but only half of sprite pattern table can be obtained (8K sprite pattern is actually used, while 4K can only be selected for speculation), such as Castlevania III, Gun Sight (no matter the display problem of sunk city in ex NT mode). The following two games of 8x16 SPR mode look normal:
Gradius AC2007_ op4 [h]
Gradius II AC Death20 [h]
The remaining key graphics technologies of mmc5 must be solved to emulate:
1. 8x16 spr mode
2. vsplit mode
3. ex-attr mode
The above three are based on the implementation of accurate PPU cycle counter. In the open source code of MISTER_NES, I intercepted a part and sorted it out as follows:
Code: Select all
// For NTSC only, the *last* cycle of odd frames is skipped.
// In Visual 2C02, the counter starts at zero and flips at scanline 256.
always_comb begin
case (sys_type)
2'b00,2'b11: begin // NTSC/Vs.
vblank_start_sl = 9'd241;
vblank_end_sl = 9'd260;
skip_en = 1'b1;
end
2'b01: begin // PAL
vblank_start_sl = 9'd241;
vblank_end_sl = 9'd310;
skip_en = 1'b0;
end
2'b10: begin // Dendy
vblank_start_sl = 9'd291;
vblank_end_sl = 9'd310;
skip_en = 1'b0;
end
endcase
end
wire skip_pixel = is_pre_render & ~even_frame_toggle & rendering_sr[3] & skip_en;
wire end_of_line = (cycle[8:3] == 42) & (cycle[3:0] == (skip_pixel ? 3 : 4));
// Set if the current line is line 0..239
always @(posedge clk) if (reset) begin
cycle <= 338;
end else if (ce) begin
// On a real AV famicom, the NMI even_odd_timing test fails with 09, this SR is to make that happen
rendering_sr <= {rendering_sr[2:0], in_frame};
cycle <= end_of_line ? 9'd0 : cycle + 9'd1;
end
Code: Select all
wire end_of_line = (cycle[8:3] == 42) & (cycle[3:0] ==3);
// Set if the current line is line 0..239
always @(posedge clk)
if (reset) begin
cycle <= 338;
end else if (ce) begin
// On a real AV famicom, the NMI even_odd_timing test fails with 09, this SR is to make that happen
cycle <= end_of_line ? 9'd0 : cycle + 9'd1;
end
Because 340 PPU cycles (0.. 339) are intercepted, the last cycle is ignored, so the head alignment must be synchronized. How to find the initial PPU cycle of each rendering line?
I think that once this problem is solved, the hardware emulation of mmc5 will be completed to 90%, only the last ex-attr may be a problem left over.
Finally, the parameters obtained by setting write breakpoints for some mmc5 games are sorted into a table:
Code: Select all
-MMC5 mapper, originally much complex bankswitching
-SPR Mode- -PRG Mode- -CHR Mode- -Ext RAM Mode- -Name----------------------
8x16 4x8 8x1 ex-attr* - Just Breed
8x16 4x8 8x1 ex-nt,vsplit* - Uchuu Keibitai SDF
8x16 4x8 8x1 ex-nt,3s - Gun Sight
8x16 16+8+8 8x1 ex-nt,3s - Castlevania III
8x8 4x8 8x1 ex-ram - Super Chinese 2 [T+ChS]
8x16 4x8 8x1 ex-ram - Hoshi no Kirby [T+ChS]
8x16 2x16 8x1 ex-ram - Gekikame Ninja Den [T+ChS]
8x8 4x8 8x1 ex-ram - Super Mario All-Stars NES [h]
8x16 2x16 8x1 ex-ram - Zelda - The Legend of Link [h]
8x8 4x8 8x1 none - Ultimate Mortal Kombat 3 [h]
8x8 4x8 2x4 ex-ram - Metal Slader Glory
8x8 16+8+8 2x4 ex-ram - Saint Seiya - Ougon Densetsu [T+ChS]
8x8 2x16 2x4 ex-ram - Grand Master [T+ChS]
8x16 4x8 4x2 none - Salamander AC Delta09a [h]
8x16 4x8 8x1 none - Gradius AC2007_op4 [h]
8x16 4x8 8x1 none - Gradius II AC Death20 [h]