8000 Consider using nestest for testing all instructions · Issue #1 · PyAndy/Py3NES · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Consider using nestest for testing all instructions #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DanTup opened this issue Jun 5, 2016 · 4 comments
Closed

Consider using nestest for testing all instructions #1

DanTup opened this issue Jun 5, 2016 · 4 comments

Comments

@DanTup
Copy link
DanTup commented Jun 5, 2016

There's a test rom called nestest listed on the NES Wiki Emulator Tests page. It's a sets of tests that can be run automatically (great for when you have no PPU) but also interactively once you have controller/PPU support.

You basically load the ROM and put the PC at 0xC000 and then execute, logging your PC (and registers) on every cycle and compare to a sample log. Docs are here.

I found it quite a quick way to verify/implement my instructions (I implemented it all in an automated test so Visual Studio key executing it every time I hit build; it only takes a few milliseconds).

Note: It does include all illegal opcodes too, so they seem to go on forever =D

@DanTup
Copy link
Author
DanTup commented Jun 6, 2016

Shame I wasn't watching this live to explain this better ;(

Here's the info I got from the nesdev forum when I tried to use nestest.

You'll eventually need to understand the iNES file format. For now, you can load 0x4000 bytes starting at offset 0x0010, and map that as ROM into both $8000-$BFFF and $C000-$FFFF of the emulated 6502's memory map. You can make an iNES parser once you start trying to actually run Concentration Room or Donkey Kong.

The 0xC000 wasn't very obvious on the page you loaded, but it's more obvious if you look at this map. I think for small carts 0x8000-0xBFFF and 0xC000-0xFFFF return the same data but bigger carts have different data in each.

My loading code looks a bit like this:

// Load the program data from the ROM
var romBytes = File.ReadAllBytes(RomFile);
var romData = new ArraySegment<byte>(romBytes, 0x0010, 0x4000).ToArray();

// Write into the correct memory location (write twice while we don't have a mapper)
ram.Write(0x8000, romData);
ram.Write(0xC000, romData);

You should add logging to output the PC at every tick then compare it to the left column of the sample log. When you get the wrong PC, review the previous entry from the same log. I actually logged all the registers too and compared them at the same time (note: the registers logged are the values before the instruction was executed).

I think it's worth getting nestest working sooner rather than later - it's so much easier to implement instructions when you can run the test and see if you get to the next instruction or not (and if logging registers, whether you set carry flag etc correctly). I went as far as automating the comparison to the sample log (or the columns I cared about) so I had instant feedback on build.

Note: Like you, I've never made an emulator before, so my knowledge is also very limited and maybe incorrect/incomplete in places! :D

@DanTup
Copy link
Author
DanTup commented Jun 14, 2016

Just catching up on what I missed this morning... Seems like good progress! :)

I was a little sceptical about the mixins at first (I've never actually used them) but they seem to be working well!

I've got a few tweaks in mind for my Chip-8 (which I made run in the browser!) which I might try and do this week, then back to DaNES!

Be prepared! nestest includes illegal (undocumented) opcodes, which many games used. Getting the whole thing to run through nestest correctly is going to be quite tedious for a while (over 200 instructions, took me a couple of evenings)!

Btw, at the end of the vid you were working on pushing the PC to the the stack - you were shifting by 8 and 16, but it should be 8 and 0 (else you're throwing away the low 8 bytes). But you'll need to truncate it though (eg. cast to byt/bitwise or with 0xFF/whatever). I created helpers to do conversions from my shorts to bytes and vice versa as it's used in quite a few places (I use this for reading absolutes, etc. too).

byte[] ToBytes(ushort value) => new[] { (byte)(value >> 8), (byte)value };
protected ushort FromBytes(byte b1, byte b2) => (ushort)(b1 | b2 << 8);

@PyAndy
Copy link
Owner
PyAndy commented Jun 27, 2016

Going to close this issue as the program now compares against NesTest log! Thanks for this suggestion @DanTup :)

@PyAndy PyAndy closed this as completed Jun 27, 2016
@DanTup
Copy link
Author
DanTup commented Jun 29, 2016

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0