$2002 reads

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
been_jamin
Posts: 5
Joined: Wed Jan 18, 2017 7:54 pm

$2002 reads

Post by been_jamin » Wed Jan 18, 2017 8:03 pm

I have just finished programming the NES processor in C, and was reading http://wiki.nesdev.com/w/index.php/PPU_ ... #PPUSTATUS for information about the PPU so I can begin programming it. There it says that the VBlank bit gets reset after every read from the $2002 status register. I had already programmed my entire cpu with a structure similar to this:
read = cpu->memory[memlocation];
Anyways, now I would hate to have to replace all of that code, so is there any way that I could get around this? And are there other registers like this that reset when you read them?

Thanks in advance!

PS included my cpu code just in case any of you need it.
Attachments
6502.c
(46.36 KiB) Downloaded 252 times

User avatar
tokumaru
Posts: 12059
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: $2002 reads

Post by tokumaru » Wed Jan 18, 2017 8:12 pm

This is a characteristic of the PPU, not the CPU. The CPU just goes "hey, whatever hardware is answering for memory location $2002, give me the byte corresponding to this location". The PPU then raises a hand and goes "that's be me, let me prepare the data for you", and as it serves the data, it happens to clear that specific flag as part of its internal logic. This doesn't concern the CPU at all.

EDIT: You can't simply use an array when accessing registers, because memory mapped registers are very different from plain memory. You probably need a method to handle memory accesses instead, and this method will take care of selecting what part of the system will respond depending on the address being accessed. Maybe other emulator authors will give you better tips on how to emulate the memory map of the NES than I can.
Last edited by tokumaru on Wed Jan 18, 2017 8:18 pm, edited 2 times in total.

User avatar
mikejmoffitt
Posts: 1352
Joined: Sun May 27, 2012 8:43 pm

Re: $2002 reads

Post by mikejmoffitt » Wed Jan 18, 2017 8:16 pm

Think of a fetch from an address as an opaque function. Memory is mapped to the address space as you'd expect, but other devices are mapped that way as well.

Code: Select all

read = system_read(address);
system_read would then be responsible for returning data from RAM, or info from the PPU (and acting on certain reads like $2002), or even returning the appropriate data for an open-bus situation.

Functions like system_read and system_write would trigger much of the "glue" holding the CPU, PPU, and peripherals.

been_jamin
Posts: 5
Joined: Wed Jan 18, 2017 7:54 pm

Re: $2002 reads

Post by been_jamin » Wed Jan 18, 2017 8:19 pm

Right, but just reading straight from the register using an array like the way I said is problematic still because now I have no way of telling when the cpu reads from $2002, right? Is there any way I can avoid having to rewrite so much of my code?

User avatar
mikejmoffitt
Posts: 1352
Joined: Sun May 27, 2012 8:43 pm

Re: $2002 reads

Post by mikejmoffitt » Wed Jan 18, 2017 8:21 pm

Precisely. That's why you will want to abstract all reads and writes from the CPU address space, so these cases can be handled.

User avatar
tokumaru
Posts: 12059
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: $2002 reads

Post by tokumaru » Wed Jan 18, 2017 8:29 pm

Instead of accessing the "memory" array directly, you should call a "read" function, that will handle all the interactions between the different parts of the system. CPU, PPU, APU, RAM, ROM, mappers... all of them are mapped to the same address space, and simply accessing an array will not trigger all the consequences of accessing them.

been_jamin
Posts: 5
Joined: Wed Jan 18, 2017 7:54 pm

Re: $2002 reads

Post by been_jamin » Wed Jan 18, 2017 8:32 pm

Oh, and one more question: The reads that reset the register include reads performed by indirect addressing etc. right?

User avatar
tokumaru
Posts: 12059
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: $2002 reads

Post by tokumaru » Wed Jan 18, 2017 8:38 pm

Yes. From the point of view of the hardware, it doesn't matter how the read came to be: if the address of the register ended up on the address bus, and the read signal was asserted, the PPU will respond to it.

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Re: $2002 reads

Post by Disch » Wed Jan 18, 2017 10:44 pm

If you want some ideas:

I have a 'Cpu' class and a 'Bus' class. When reading/writing, the Cpu class will call into the Bus class which will actually perform the read/write.

Other parts of the system can hook into the Bus by adding callbacks for a specific range of addresses. So your PPU can tell the Bus that it wants callbacks for all addresses in the $2000-3FFF range. Then, when the CPU reads/writes those addresses, the bus checks to see what callbacks are assigned to them, and calls them.

been_jamin
Posts: 5
Joined: Wed Jan 18, 2017 7:54 pm

Re: $2002 reads

Post by been_jamin » Fri Jan 20, 2017 11:53 pm

Welp, going pure C for pure speed. So using classes won't work, but I'll definitely think about making a Bus structure. Thanks!

User avatar
Disch
Posts: 1849
Joined: Wed Nov 10, 2004 6:47 pm

Re: $2002 reads

Post by Disch » Sat Jan 21, 2017 1:30 am

if C just replace 'class' with 'struct'.

C++ is basically just C with goodies.

Post Reply