CPU/PPU sync approach

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
strat
Posts: 409
Joined: Mon Apr 07, 2008 6:08 pm
Location: Missouri

CPU/PPU sync approach

Post by strat »

This is my main emulation loop (CPU core is Marat Fayzullin's). It runs a scanline worth of cpu then draws a scanline. SMB seems to run fine and that's supposed to be the litmus test for new emulators, but Balloon Fight's scrolling (which uses timed code to set the scroll below the status bar) is off a few lines and Bomberman crashes right after starting the first level*. Burgertime also wouldn't run until the if/else condition below. Is this a sound approach or am I walking into a minefield of little bugs and crashes?

No apu emulation so if Bomberman uses an apu irq that would explain the crash.

I haven't tried the test roms yet.

Code: Select all

	Exec6502(&m6502,55);
	Exec6502(&m6502,58);
	cycles += 113

	if (sclines != 241) {
		Ppu_Render_Line(&sclines, &m6502);
	} else {
		ppu_run_info.vbl_bit = 0x80;
		Exec6502(&m6502,3);
		Ppu_Render_Line(&sclines, &m6502);
		if (ppu_run_info.bNmiFired) {
			Int6502(&m6502,INT_NMI);
			ppu_run_info.bNmiFired = 0;
		}
		Exec6502(&m6502,51);
		Exec6502(&m6502,58);
		cycles += 113;
		sclines++;
	}
	sclines++;
	if (262 == sclines) {
		sclines = 0;
	}
Sprite zero handling (in the loop to draw ppu pixels).

Code: Select all

	if (bSprHit && bSprZeroCheck) {
		uint32 cpu_cycles = fx / 3;
		Exec6502(m6502, cpu_cycles);
		ppu_run_info.spr_zero_bit = 0x40;
		Exec6502(m6502, 113-cpu_cycles);
		//(*cpu_sclines)++;  // buggy
		bSprZeroCheck = 0;
	}
Screenshot from 2022-08-30 21-36-23.png
Screenshot from 2022-08-30 21-36-23.png (4.56 KiB) Viewed 1294 times
Screenshot from 2022-08-30 21-36-55.png
Screenshot from 2022-08-30 21-36-55.png (5.12 KiB) Viewed 1294 times
Screenshot from 2022-08-30 21-37-52.png
Screenshot from 2022-08-30 21-37-52.png (5.83 KiB) Viewed 1294 times
User avatar
carmiker
Posts: 12
Joined: Wed Sep 16, 2020 4:16 am
Contact:

Re: CPU/PPU sync approach

Post by carmiker »

Seems like Sprite 0 Hit issues to me at first glance.

I recommend using a cycle stepped CPU core such as: https://github.com/floooh/chips/blob/ma ... ps/m6502.h

You could even just use this for testing against a faster one that is instruction stepped. However, I suspect in this case your issue is Sprite 0 Hit timing and you will need to consider pre-calculating that perhaps, and timing it to execute on the correct PPU cycle. Actually, it is much easier to write a cycle-stepped emulator if you want things to just work. The wiki has all the required details to write a cycle-stepped PPU.
strat
Posts: 409
Joined: Mon Apr 07, 2008 6:08 pm
Location: Missouri

Re: CPU/PPU sync approach

Post by strat »

Trying to make a cycle-stepped PPU, though it still uses the same CPU and runs the cpu cycles * 3 for each instruction. It's not clear to me how exactly the shift registers work with the palettes, so this is my code. On a scroll divisible by 8 it looks fine but as it scrolls the attributes become misaligned.

Code: Select all

	if (3 == ppu_run_info.cycles % 8) {

		uint16 attr_addr = 0x23C0 | (vreg & 0x0C00) | ((vreg >> 4) & 0x38) | ((vreg >> 2) & 0x07);
		attr_byte = ppu_run_info.ppumem[attr_addr];
		switch(ntbl_addr & 0x43) {
		case 0:
		case 1:
			attr_bits = attr_byte & 0x3; break;
		case 2:
		case 3:
			attr_bits = (attr_byte >> 2) & 0x3; break;
		case 0x40:
		case 0x41:
			attr_bits = (attr_byte >> 4) & 0x3; break;
		case 0x42:
		case 0x43:
			attr_bits = (attr_byte >> 6) & 0x3; break;
		}
	}
	
	if (!(ppu_run_info.cycles % 8) && ppu_run_info.cycles > 0) {
		Inc_Coarse_X(&ppu_run_info.vreg);
		curr_pal = attr_bits;
	}	
	
https://www.nesdev.org/w/images/default ... timing.png
Post Reply