is nestest infallible?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

is nestest infallible?

Post by Anes »

Im really pissed off. I tried making my emulator from scratch and i have a lot of errors.
nestest pass all official test, but blarrgs "vblank basics" throw me "way off" on vblank. My emu is waiting properly 20 * 341 cycles. I have debugged and tested. Im using a LUT of opcodes cycles to pass a RunPpu(int run_to). My frame is properly generating 89341 cycles.
Anyway, there are games that throw me visual errors.

Im asking if nestest.nes is confiable becouse al says "OK" and im thinking i have cpu errors. I have checked and rechecked my cpu code and it seems ok.

Im desperated.

The thing is that i don't want to emulate unofficial opcodes by now. And Blarrg's cpu test that test official opcodes use mmc3 (i think) and it's still unimplemented in my emu.
ANes
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: is nestest infallible?

Post by dougeff »

I believe the nestest just tests the CPU emulation.

Visual errors might be a PPU error. The NES has a lot of weird quirks on graphic rendering.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: is nestest infallible?

Post by Anes »

Yeah, i know. But it's the simplest thing.

Im putting my code of "RunPpuOff(int run_to)". Maybe someone can give me a hint.

Code: Select all

	void RunPpuOff(int run_to)
	{
		while (scanline <= 239)		//render
		{
			while (cc < 341)
			{
				if (scanline == 0 && cc == 0)
					nes_screen->Lock();
				if (cc >= 1 && cc <= 256)
					Multiplexer(0, 0);
				++cc;
				++ppu_run_to;
				if (ppu_run_to == run_to)
					return;
			}
			++scanline;
			cc = 0;
		}
		while (scanline == 240)							//dummy scanline
		{
			while (cc < 341)
			{
				++cc;
				++ppu_run_to;
				if (ppu_run_to == run_to)
					return;
			}
			++scanline;
			cc = 0;
		}
		while (scanline == 241)							//dummy scanline
		{
			while (cc < 341)
			{
				if (cc == 1)
				{
					on_vblank = 0x80;
					if (nmi_on_vblank)
						NmiPending(true);
				}

				++cc;
				++ppu_run_to;
				if (ppu_run_to == run_to)
					return;
			}
			++scanline;
			cc = 0;
		}
		while (scanline <= 260)							//vblank
		{
			while (cc < 341)
			{
				++cc;
				++ppu_run_to;
				if (ppu_run_to == run_to)
					return;
			}
			++scanline;
			cc = 0;
		}
		while (scanline <= 261)							//vblank
		{
			while (cc < 341)
			{
				if (cc == 1)
				{
					on_vblank = 0x00;
				}
				++cc;
				++ppu_run_to;
				if (ppu_run_to == run_to)
					return;
			}
			++scanline;
			cc = 0;
		}

		ppu_run_to = 0;
		scanline = 0;
	}
I know it's not the best code in the world, but maybe someone can tell me what can be wrong. I don't find any errors.
Im just starting from something simple. I thing this code should pass the error "ppu is way off".
ANes
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: is nestest infallible?

Post by Anes »

No help?

Oh my god
ANes
User avatar
Quietust
Posts: 1920
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: is nestest infallible?

Post by Quietust »

My advice would be to start looking here for other CPU test programs - nestest is known to not cover certain types of errors, and some of Blargg's individual CPU tests are more thorough.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
Anes
Posts: 702
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: is nestest infallible?

Post by Anes »

All links are broken.

I found blarrg's test in his github repository.
I can't find biskwit tests.
ANes
c3r34l
Posts: 1
Joined: Sat Feb 18, 2023 8:15 am

Re: is nestest infallible?

Post by c3r34l »

I also used nestest as a benchmark for developing my emulator, and I found that the interactive test suite (e.g. from loading & running it and using button controls to initiate the 'Run all tests' option) was unreliable -- I found that I would get inconsistent results depending on how I ran the tests, and in what order. There was also some weirdness in regards to illegal opcodes (it appeared to use a few even in the normal tests), and when tests did fail, the error codes & descriptions were not always helpful, or in some cases even misleading (I'd get an error code that didn't correspond to the test that was run).

To be fair, it is quite difficult to test a machine works properly when the test is running on the machine itself.

That said, the interactive mode is still a good smoke test. It's too bad there's no source code for it to shine some light on its quirks.

The real value of nestest is the 'automation' mode, and associated log file usually found with it (nestest.log), which is infallible, AFAIK. It can take a bit of work to implement a compatible logger, and it requires fudging the initial state a bit to match (ex: Stack pointer starts at $FD instead of $FF, it starts ~7 cycles in, PC starts at $C000, etc.), but it was only after rigging this up that I was able to find and correct the last few remaining bugs in my CPU implementation.

It's also the only way to really verify accurate cycle counts, especially for those tricky variable-cycle ones.

One word of advice I wish I had known before I did the work to implement a compatible logger: the status line on the right of the disassembly is the state of the system before executing the corresponding instruction on the left.

Re: Other test roms --

I was also a bit disheartened to find many of the download links for test roms on the wiki are dead. However, I've found a github repo that has most of the ones from the wiki + more: https://github.com/christopherpow/nes-test-roms

Maybe a mod can update the wiki with this link? I don't own the repo in question, but a mod could also make an official nesdev github account and fork the repo for free.
User avatar
org
Posts: 155
Joined: Tue Aug 07, 2012 12:27 pm

Re: is nestest infallible?

Post by org »

To check the 6502 I recommend looking at the Klaus Dormann tests: https://github.com/Klaus2m5/6502_65C02_functional_tests

They are well-proven and if your emulator passes them, it will give you a huge boost in confidence of what you have coded there :)
L. Spiro
Posts: 14
Joined: Sun Jan 29, 2023 11:27 pm

Re: is nestest infallible?

Post by L. Spiro »

https://github.com/TomHarte/ProcessorTe ... in/nes6502

There are 10,000 tests for every single opcode.

But frankly I don’t know that this is a CPU error. My CPU passes all CPU tests, including all 2,560,000 tests on that site, and still also fails Blargg’s PPU test.
Eventually I am going to ask for help with that here too, but for now I can only inform you that passing the PPU tests isn’t only a CPU issue; you need your CPU to be cycle-accurate so that it can properly count its cycles when it times its events, but most of the complications you will have will be on the PPU side. If you pass all of the tests in my link above then your CPU is known to be good, instruction-wise anyway. IRQ’s need other tests.

I also wait 20 scanlines from the start of v-blank until it ends and it is telling me I end v-blank 2 cycles early (or I start v-blank 2 cycles early or something—my v-blank is supposedly off by 2 CPU cycles, and, like you I have absolutely no clue why).


I can’t follow your code but I can see that it’s poorly structured. You shouldn’t have multiple exit points. While there are many valid ways to structure your PPU update, a good one that I recommend is to provide a function that simply ticks 1 cycle, then call it however many times you need in order to make a full PPU update. You’re going to be required to move everything to a single exit point anyway, because there has to be a per-cycle section of code reserved for handling the delayed register writes etc., which are necessary to pass Blargg’s tests.

“Rendering enabled” (either the background or the sprite flags set) is delayed by 1 cycle, for example.
Writes to your internal V loopy register via $2006 are delayed by 3 PPU cycles, as another example.
Your current architecture has absolutely no way to facilitate this, and it will become necessary for you to redo all of the code you posted above.

In order to pass Blargg tests you will also need to handle the special-case behavior caused by reading $2002 within a few cycles of v-blank.
You will also need to properly emulate the multi-NMI triggers causing by writes to $2000 during v-blank.

But the most important thing to do is refactor your PPU code entirely. Refactoring it later will only introduce more bugs and cause you to repeat your bug-squashing process, so do it now.


L. Spiro
Post Reply