I'm creating a NES emulator.

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

I'm creating a NES emulator.

Post by LordEmilio »

Hello,

My name is Matthias, and I'm making a NES emulator coded in Visual Basic .NET (please don't judge me :mrgreen: ).

I always was very interested in emulation since I discovered it back in 2006, and even wanted to create my own one.

After 15 years of testing, experimentations, accumulation of knowledge, and all of this, I then achieved the first Alpha of a nearly working NES CPU.

The project is named JadeNES, after someone's name I talk with. However, I am not able to test the CPU in depth, thus I am hesitating of writing the next parts of the project, like the PPU. If you guys could help me solve this issue.

In fact, I'm afraid this project is encountering the same problems than an old project I've been working on a few years ago, concerning the Program Counter registry (PC). :?

My project is only based on documentations available on the Internet (NESDev, y0shi, etc.), plus I've read a few emulators' source code to learn how their code acts, in order to adapt the documentation to the right dev language syntax. Despite that, I've never copied a single line of code from their projects, and credited them in the "About" dialog box as inspiration projects.

I can send the source code of the NES core from my project, on the forum, if someone is ready to help me. Or even add me on Discord to discuss about my project. :) I'm seeking help on the NESDev forum, because not a lot of people are helping me these days about this emu.

Best regards everybody. :wink:
User avatar
Individualised
Posts: 309
Joined: Mon Sep 05, 2022 6:46 am

Re: I'm creating a NES emulator.

Post by Individualised »

We can't really help you if you don't tell us what your problem is. It's good online etiquette to describe your problem in your first post, you don't need to ask first.

(Also, this is probably more suitable for the NESemdev sub-forum.)
Fiskbit
Posts: 890
Joined: Sat Nov 18, 2017 9:15 pm

Re: I'm creating a NES emulator.

Post by Fiskbit »

We have a lot of test ROMs linked on the wiki that may be of use to you. Probably the most relevant to you at this stage is nestest, which tests the CPU and I believe can be run without a PPU.
User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

Re: I'm creating a NES emulator.

Post by LordEmilio »

Actually, the problem is that I've already implemented some features, though I'm not sure about the CPU loop.

You know, when the PC register goes crazy, it sometimes happen on poorly written emulators, and points to weird memory spaces.

I think these actual NES test ROMs might help me finding if the program counter registry and memory readings are correct.

Thanks a lot.

See you next time!
User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

Re: I'm creating a NES emulator.

Post by LordEmilio »

I'm back after a few tests,

I downloaded the dummy read test ROM, and launched it under my emulator. :D

See : viewtopic.php?p=31629

So, in conclusion, how this test ROM works is basically setting the X register to 7, and Y to 255. And then, it decreases Y in a loop.

The signed processor status flag is set when Y < 128. When Y equals 0, it decrements X once, and assigns 255 to Y to start from the top.

When X equals 0, it ends up this loop, sets X to 255 and Y to 0. Is it right, or is there something wrong in this 6502 execution? :|

See you later! :wink:
Fiskbit
Posts: 890
Joined: Sat Nov 18, 2017 9:15 pm

Re: I'm creating a NES emulator.

Post by Fiskbit »

You should start specifically with nestest. It can run without a PPU. The dummy reads test gives results visually and with a tone, but you don't have a PPU nor APU.

Edit: Actually, even better might be instr_test_v5, though the download link on the wiki is down right now. I think this is the one I remember people using most.
User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

Re: I'm creating a NES emulator.

Post by LordEmilio »

Thank U.
User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

Re: I'm creating a NES emulator.

Post by LordEmilio »

Hey guys I'm back for another question,

I don't get something about how CPU memory banks work.

When the Program Counter reads data from the upper banks, it directly reads from $C000 to $7FFF (Bank 1), and from $8000 to $FFFF (Bank 2).

However, I thought those addresses were used for MMC access, but I don't know a lot about it. Whenever the ROM mapper is greater than 0, are those memory addresses just used for MMC bank switching ?

I've checked BasicNES' source code, and it's even weirder, it uses 4 memory banks, with a total size of 8KB each :

Code: Select all

Case &H6000& To &H7FFF&: Read6502 = bank6(Address And &H1FFF&)
Case &H8000& To &H9FFF&: Read6502 = bank8(Address And &H1FFF&)
Case &HA000& To &HBFFF&: Read6502 = bankA(Address And &H1FFF&)
Case &HC000& To &HDFFF&: Read6502 = bankC(Address And &H1FFF&)
Case &HE000& To &HFFFF&: Read6502 = bankE(Address And &H1FFF&)
I thought the NES used 16KB memory banks for the program ROMs. What is this odd tinkering?

Thanks in advance.
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: I'm creating a NES emulator.

Post by Quietust »

LordEmilio wrote: Tue Oct 04, 2022 3:55 pm I thought the NES used 16KB memory banks for the program ROMs. What is this odd tinkering?
The NES does not have any concept of bank sizes built into it, aside from the 8KB memory regions dedicated to internal RAM ($0000-$1FFF) and the PPU I/O ports ($2000-$3FFF). The only thing that's required is that the cartridge respond to reads from $FFFC-$FFFD (to provide the RESET vector) as well as whatever address said RESET vector happens to point at.

Some cartridges use 32KB banks, some use 16KB banks, some use 8KB, and a select few use even smaller banks than that. Most emulators will adopt a certain minimum bank size to accomodate the vast majority of cartridges - BasicNES seems to have chosen 8KB, while some other emulators use 4KB in order to support banked NSF playback.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

Re: I'm creating a NES emulator.

Post by LordEmilio »

Okay then. Thanks again.

I have yet another question, I don't know when the PPU redraws a scanline on screen, is it like every 30 instructions executed?

Plus I saw that even while the PPU draws a scanline, it can execute a single CPU instruction.

Is it linked to the VBlank instruction, or NMI interruption, or something like that?

Thanks in advance.

LordEmilio
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: I'm creating a NES emulator.

Post by Quietust »

LordEmilio wrote: Fri Oct 07, 2022 2:30 pm I have yet another question, I don't know when the PPU redraws a scanline on screen, is it like every 30 instructions executed?

Plus I saw that even while the PPU draws a scanline, it can execute a single CPU instruction.

Is it linked to the VBlank instruction, or NMI interruption, or something like that?
I have to say, I'm a bit puzzled as to how exactly you came to that conclusion.

The PPU runs completely independently of the CPU - its clock speed is about 3 times as fast, and it takes 341 cycles to output a single scanline worth of video. Meanwhile, the CPU will have executed exactly 113+2/3 cycles, which could be anywhere from 16 to 57 instructions depending on what was being executed.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: I'm creating a NES emulator.

Post by tokumaru »

The PPU and the CPU run in parallel with each other, each one doing its own thing independently.

The PPU is 3 times faster than the CPU (in NTSC), and outputs 1 pixel per cycle. Out of the 341 cycles of one scanline, 256 pixels are output, and the remaining 85 cycles are spent during overscan (border) and hblank (the time it takes for a CRT TV's electron gun to move from the right edge of the screen back to the left edge for the next scanline). After 240 scanlines, vblank starts - this is the period between one frame and the next, when the electron gun goes back to the top of the screen and the PPU doesn't access VRAM, leaving it free for the CPU to use. This process is repeated indefinitely, as long as rendering is enabled. If rendering is disabled, the PPU still goes through the whole process of drawing a picture, but it doesn't access VRAM to do it, it just draws a blank image.

While the PPU is doing all that, the CPU is busy fetching instructions from memory and executing them. Instructions can take from 2 to 7 cycles to execute, so like Quietust said, there can be 16 to 56 instructions being executed each scanline.

Emulators generally can't make the two chips run in parallel like on actual hardware, so they usually alternate between the two, giving each one the opportunity to catch up with the other. The more frequently you switch between the two chips, the more accurate your emulator is going to be, but also slower.
User avatar
LordEmilio
Posts: 18
Joined: Sat Oct 01, 2022 11:39 am

Re: I'm creating a NES emulator.

Post by LordEmilio »

Hello fellows,

I've added the PPU writing/reading routines through $2000 - $2007 registers, and the video memory routines (accessing CHR-RAM, reading or writing Name Tables, NES bg/fg palettes), and tried to begin writing a scanline-based rendering, which is only rendering the background from the Name Tables stored in memory, handling mirroring and scrolling.

However, on some games, the PC register sometimes gets funky values, like $0 or other addresses located at $8000-$FFFF leading to unknown opcode errors. I don't know what's happening.

Image

Hence, all I'm getting on screen is a black screen, or a grey screen in some cases, as if the PPU was drawing empty tiles with the 0x0 NES color palette (which is actually grey). I don't know where it comes from, maybe some instructions are missing or badly implemented. Finding where the mistake is will take time, as my project is partially based on other's emulators source code, and sometimes I've just read how they do the work, along with the NES documentation, and wrote approximatively the same code.

Where to even start? :? I'm a bit confused.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: I'm creating a NES emulator.

Post by tokumaru »

One thing that helps in these cases is to run the game in an emulator that can write trace logs (e.g. Mesen, FCEUX) and then have your own emulator output a log in the exact same format, so you can then compare the files and see exactly where your emulator is doing something it shouldn't.
User avatar
Quietust
Posts: 1918
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: I'm creating a NES emulator.

Post by Quietust »

You should probably start by adding a CPU trace log of some sort - each time it executes an instruction, write a line to a text file indicating the exact details of that instruction (i.e. the address, the opcode bytes, a text representation of the instruction, and the contents of all CPU registers at the time).

Basically, you want it to produce something like this:

Code: Select all

C5F5  A2 00     LDX #$00                        A:00 X:00 Y:00 P:24 SP:FD
C5F7  86 00     STX $00 = 00                    A:00 X:00 Y:00 P:26 SP:FD
C5F9  86 10     STX $10 = 00                    A:00 X:00 Y:00 P:26 SP:FD
C5FB  86 11     STX $11 = 00                    A:00 X:00 Y:00 P:26 SP:FD
C5FD  20 2D C7  JSR $C72D                       A:00 X:00 Y:00 P:26 SP:FD
C72D  EA        NOP                             A:00 X:00 Y:00 P:26 SP:FB
C72E  38        SEC                             A:00 X:00 Y:00 P:26 SP:FB
C72F  B0 04     BCS $C735                       A:00 X:00 Y:00 P:27 SP:FB
C735  EA        NOP                             A:00 X:00 Y:00 P:27 SP:FB
C736  18        CLC                             A:00 X:00 Y:00 P:27 SP:FB
C737  B0 03     BCS $C73C                       A:00 X:00 Y:00 P:26 SP:FB
C739  4C 40 C7  JMP $C740                       A:00 X:00 Y:00 P:26 SP:FB
C740  EA        NOP                             A:00 X:00 Y:00 P:26 SP:FB
That way, you can read through the instruction sequence and identify exactly where and why things went wrong.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
Post Reply