Porting mmc5 PPU cycle counter from mister_nes

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by lidnariq »

I think you have to do that for the MMC5's "is_rendering" flag anyway. Yes, you could probably use that.
User avatar
aquasnake
Posts: 515
Joined: Fri Sep 13, 2019 11:22 pm

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by aquasnake »

There should be two ways to detect the end of the scanline(or the start of the next scanline):

1. Consecutive detection of two reads on the same PPU address. This requires monitoring all PPU address lines. Here, PPU cycle should be 337-340. After the detection, PPU cycle is at 0.

2. Consecutive detection of 3 reads when ppu_a13=1 & ppu_A12 = 0, it is not required to monitor all PPU addresses. Here PPU cycle should be 337-340, 1. (when PPU cycle is 0, all address lines remain the same as PPU cycle 337-340 at the end of the last scanline, /ppu_rd or /ppu_wr signal is not generated, so the detection is ignored. When the next scan line PPU cycle is 1, the NT byte of the first tile is detected, accumulating to 3 times). After the detection, PPU cycle is at 1
User avatar
aquasnake
Posts: 515
Joined: Fri Sep 13, 2019 11:22 pm

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by aquasnake »

During PPU cycle 1-256, the bg tiles are rendered. Each tile needs to be read four times. A total of four bytes are read in,the first byte is nametable, the second is attribute, the third and fourth are pixel bitmap bytes(8x2bit). Eight PPU cycles are a group, and a row of eight pixels of a tile is displayed. Therefore, we can detect 8 PPU cycles as a time unit, and dynamically switch the bank for each row of each tile. 8 pixels are 2 bytes. This kind of switching is not completely accessing on random address, but can only get the offset address in the pattern table by calculating the ID in the nametable and combining with the current scanline number.

If you replace the nametable byte and tile byte (# 0, # 2, # 3 bytes) in 8 PPU cycles, it is vsplit mode. Here the substitution is by bankswitching.
If you replace the attribute byte (# 1 byte) in 8 PPU cycles, it is the ex-attr mode. Here is the real data bus hijacking.

Based on the rendering mode of visible scanline buffer, the final display will delay one scanline.
The BG or SPR tiles of the current line will be filled in the shift register and displayed on the next scanline. So the first line will appear garbage
Last edited by aquasnake on Tue Feb 23, 2021 9:53 pm, edited 1 time in total.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by lidnariq »

aquasnake wrote: Tue Feb 23, 2021 12:45 am There should be two ways to detect the end of the scanline(or the start of the next scanline):

1. Consecutive detection of two reads on the same PPU address. This requires monitoring all PPU address lines. Here, PPU cycle should be 337-340. After the detection, PPU cycle is at 0.
No, this won't work. During the sprite slivers, the internal PPU address multiplexers aren't driven for the the nametable fetches, and they often show the same address for both the nametable and attribute table fetches.
User avatar
aquasnake
Posts: 515
Joined: Fri Sep 13, 2019 11:22 pm

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by aquasnake »

lidnariq wrote: Tue Feb 23, 2021 1:18 pm
aquasnake wrote: Tue Feb 23, 2021 12:45 am There should be two ways to detect the end of the scanline(or the start of the next scanline):

1. Consecutive detection of two reads on the same PPU address. This requires monitoring all PPU address lines. Here, PPU cycle should be 337-340. After the detection, PPU cycle is at 0.
No, this won't work. During the sprite slivers, the internal PPU address multiplexers aren't driven for the the nametable fetches, and they often show the same address for both the nametable and attribute table fetches.
N8 flash cart detects two 3(it matters) reads on the same address, and the counter is reset and synchronized.

Code: Select all

	always @(negedge ppu_oe)
	begin
		
		ppu_addr_eq <= last_ppu_addr == ppu_addr;
		
		if(last_ppu_addr == ppu_addr & ppu_addr_eq)
		begin
			line_ctr <= 0;
		end
			else
		line_ctr <= line_ctr + 1;
	
		if(line_ctr == 170-1)ppu_line_strobe <= !ppu_line_strobe;
		
		last_ppu_addr <= ppu_addr;
		
		
		if(nt_ce)ppu_nt_strobe <= !ppu_nt_strobe;
	end
Last edited by aquasnake on Wed Feb 24, 2021 11:58 pm, edited 1 time in total.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by lidnariq »

I don't know how (edit: only 2 reads) could possibly work. We've measured that all the name+attribute table fetches during sprite slivers are regularly from the same address:
viewtopic.php?p=113288#p113288
User avatar
aquasnake
Posts: 515
Joined: Fri Sep 13, 2019 11:22 pm

Re: Porting mmc5 PPU cycle counter from mister_nes

Post by aquasnake »

I have verified two implementations, listening to 3 or 4 consecutive reads of $2000 - $2fff. If it's four times, it doesn't need to compare the same address, just need to count, which can simplify the physical logic implementation.

The 8x16 sprite mode(12KB pattern) has also worked, but "Salamander AC Delta09a [h]" running on my hardware shows the jitter of the status bar. I don't know whether it's an issue of my scanline counter or the hacked ROM itself.

For judging sprite refresh time, I use the simplest expression:
wire spr_fetch = ppu_cycle_div2[7]; // fetch sprite pattern between 128..159 cycles

Thanks to NESDEV community for reference, thank you all guys.
Post Reply