It is currently Fri Oct 20, 2017 9:11 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 74 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
PostPosted: Thu Aug 08, 2013 9:25 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10064
Location: Rio de Janeiro - Brazil
Zepper wrote:
Avoid technical or low level things. He's writing an emulator.

Well, he did ask how the PPU does it, and that's how... I can't lie to him, or even dumb it down. But I didn't provide any details either, or said that he should emulate this control line.

Quote:
You should trap reads by LDA $2007 instruction, and writes by STA $2007.

You and tepples are talking about LDA and STA like those are the ONLY instructions that can access $2007. Personally, I think that might confuse the OP. Several instructions (with different addressing modes!) can write/read to/from memory, and all of them can access $2007... no reason to hide that from him.


Top
 Profile  
 
PostPosted: Thu Aug 08, 2013 11:09 pm 
Offline
User avatar

Joined: Sat Jan 03, 2009 3:28 pm
Posts: 59
Location: Oregon
Zepper wrote:
tokumaru wrote:
Dartht33bagger wrote:
1. How does the PPU know if $2007 wants a read or a write? Does the CPU write a nonzero value for a write and a zero value for a read?

What? Where did you get this zero/non-zero idea from? Like 3gengames said, one of the CPU pins indicates whether it's trying to read or write data, and the PPU uses that to tell reads and writes apart.


Avoid technical or low level things. He's writing an emulator.

How does the PPU know if $2007 wants a read or a write?
- Firstly, you need the CPU 6502 program code. You should trap reads by LDA $2007 instruction, and writes by STA $2007. Look for LDA/STA timing diagram. Easy.


This is exactly what I needed. I didn't know that reading $2007 would tell the PPU to read data for the CPU. I was thinking that reading $2007 would just give you the back the data that you wrote to $2007 in the past.


Top
 Profile  
 
PostPosted: Fri Aug 09, 2013 7:55 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
tokumaru wrote:
Zepper wrote:
Avoid technical or low level things. He's writing an emulator.

Well, he did ask how the PPU does it, and that's how... I can't lie to him, or even dumb it down. But I didn't provide any details either, or said that he should emulate this control line.


He asked for an easy PPU read/write... in an emulation point of view.

Quote:
You and tepples are talking about LDA and STA like those are the ONLY instructions that can access $2007. Personally, I think that might confuse the OP. Several instructions (with different addressing modes!) can write/read to/from memory, and all of them can access $2007... no reason to hide that from him.


That's obvious. I gave a quick example, since I mentioned to check the instruction timing, where occurs reads or writes.


Top
 Profile  
 
PostPosted: Fri Aug 09, 2013 10:32 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10064
Location: Rio de Janeiro - Brazil
Zepper wrote:

You know it's obvious, and I know it's obvious... but does he? :wink:


Top
 Profile  
 
PostPosted: Fri Aug 09, 2013 1:02 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
tokumaru wrote:
Zepper wrote:

You know it's obvious, and I know it's obvious... but does he? :wink:


I don't know. I suppose he has 6502 emulation working, but I can't answer by him. -_-;;


Top
 Profile  
 
PostPosted: Sun Aug 11, 2013 3:29 pm 
Offline
User avatar

Joined: Sat Jan 03, 2009 3:28 pm
Posts: 59
Location: Oregon
My 6502 emulator is working correctly :)

A few more questions for you guys. I'm having a hard time figuring out how a 8x8 tile is rendered in a scanline. From my understand of how the PPU renders a background pixel from this diagram, it goes something like this:

1. Fetch name table byte
2. Fetch attribute table byte two cycles later
3. Fetch lower background byte two cycles later
4. Fetch upper background byte two cycles later
5. 8 cycles after the first fetch, the attribute byte and the two background tile bytes are loaded into shift registers.

Now the PPU shifts the registers every cycle and created a pixel from the four bits it fetches from the shift registers. That's great and it makes sense. The part that confuses me is how I'm supposed to draw a 8x8 tile in a scanline. Does only the top 8x1 pixels in a tile get rendered on the first scanline? Does the PPU switch between many different tiles on the first scanline and then come back to the same tiles when it needs to draw the next scanline?

Also, almost everything about scrolling makes sense to me but this line:

Quote:
The low 3 bits of X and Y sent to $2005 are the fine pixel offset within the 8x8 tile. The X component goes into the separate x register, which just selects one of 8 pixels coming out of a set of shift registers.


How exactly does it "select" the pixel coming out of the shift register?


Top
 Profile  
 
PostPosted: Sun Aug 11, 2013 3:44 pm 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19107
Location: NE Indiana, USA (NTSC)
Dartht33bagger wrote:
The part that confuses me is how I'm supposed to draw a 8x8 tile in a scanline. Does only the top 8x1 pixels in a tile get rendered on the first scanline?

Yes. Each scanline covers 34 tiles, and only a sliver of each tile gets rendered.

Quote:
Does the PPU switch between many different tiles on the first scanline and then come back to the same tiles when it needs to draw the next scanline?

Yes. It normally* visits a particular set of 34 tiles eight times.

Quote:
Quote:
The low 3 bits of X and Y sent to $2005 are the fine pixel offset within the 8x8 tile. The X component goes into the separate x register, which just selects one of 8 pixels coming out of a set of shift registers.

How exactly does it "select" the pixel coming out of the shift register?

With these:
ImageImage
ImageImage

The eight pixels coming out of the shift register are fed into a set of 8-to-1 multiplexers indexed by the three bits of fine X scroll.


* The top and bottom row of tiles in a scrolled screen may be visited fewer than eight times, as are many tiles that form part of a raster effect.


Top
 Profile  
 
PostPosted: Mon Aug 12, 2013 2:21 am 
Offline
User avatar

Joined: Sat Jan 03, 2009 3:28 pm
Posts: 59
Location: Oregon
I'm really close to understanding how this all works now. Two final questions (hopefully).

1. When the attribute shift registers are filled, the attribute byte fetched is fed through a 4 to 1 mux that selects two bits in the attribute byte based on bit 1 of coarse X and coarse Y. The two bits that are selected by the mux are used to fill the entirety of the two attribute shift registers, correct?

For example, say my attribute byte is 11100100. Then lets say bit 1 of coarse X is 1 and bit 1 of course Y is 0. That would make my mux choose 01 from the attribute byte, which would make my two attribute shift registers look like this: 01010101. Is this a correct understand of the process?

2. How are the pattern table addresses created? I know how to find the nametable address and read a byte from that location, which will give me a value of up to $FF. Then I check the PPU register status to see what pattern table the background is held in. If it's held in the second table, I add $1000. That's fine.

However, I see that on the wiki, the valid pattern table address are from $0000-$0FF7 and $1000-$1FF7. How are these addresses made? The only way I could think of it happening is shifting the byte read from the nametable to the left 4 bits and then adding fine x scroll to the address (since fine x scroll can't be larger than 7).


Top
 Profile  
 
PostPosted: Mon Aug 12, 2013 6:12 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1389
Dartht33bagger wrote:
For example, say my attribute byte is 11100100. Then lets say bit 1 of coarse X is 1 and bit 1 of course Y is 0. That would make my mux choose 01 from the attribute byte, which would make my two attribute shift registers look like this: 01010101. Is this a correct understand of the process?


No - one shift register will get filled with 1s and the other will get filled with 0s.

Dartht33bagger wrote:
2. How are the pattern table addresses created? I know how to find the nametable address and read a byte from that location, which will give me a value of up to $FF. Then I check the PPU register status to see what pattern table the background is held in. If it's held in the second table, I add $1000. That's fine.

However, I see that on the wiki, the valid pattern table address are from $0000-$0FF7 and $1000-$1FF7. How are these addresses made? The only way I could think of it happening is shifting the byte read from the nametable to the left 4 bits and then adding fine x scroll to the address (since fine x scroll can't be larger than 7).


It does indeed shift the nametable byte to the left 4 bits, but it adds the fine Y scroll to the address, not the fine X scroll (why would it add fine X scroll when each byte represents one scanline?). Also, remember that the PPU fetches two pattern bytes per tile, where the second one is simply the first one plus 8 (and contains the upper color bits for that tile).

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
PostPosted: Thu Aug 15, 2013 2:28 am 
Offline
User avatar

Joined: Sat Jan 03, 2009 3:28 pm
Posts: 59
Location: Oregon
So I've gotten the background part of my ppu written and I'm trying to test it, but I'm failing miserably. I'm just trying to get one frame rendered at the very least. Right now, I'm not even reaching any of my PPU functions because $2000 stays 0x00 and $2001 stays 0x10. I know my CPU works because it passed the nestest.nes log (well, at least up until the illegal opcodes kicked in), but my cpu gets stuck in a loop as well.

So I'm thinking at this point I'm missing something important about how the system starts up. I've read the power up states for both the PPU and the CPU on the wiki, but I'm having a hard time understanding how the system starts up. I know the system boots up, the program counter is set to the reset vector, and then the PPU does something for a certain amount of cycles before telling the CPU that it's clear to go.

How exactly does the "handshake" between the PPU and the CPU occur? Is the PPU rendering frames at this point? Do NMIs occur at this point, or do they wait until the handshake is complete?


Top
 Profile  
 
PostPosted: Thu Aug 15, 2013 3:14 am 
Offline
User avatar

Joined: Fri Mar 08, 2013 9:55 pm
Posts: 349
Location: Linköping, Sweden
Dartht33bagger wrote:
So I've gotten the background part of my ppu written and I'm trying to test it, but I'm failing miserably. I'm just trying to get one frame rendered at the very least. Right now, I'm not even reaching any of my PPU functions because $2000 stays 0x00 and $2001 stays 0x10. I know my CPU works because it passed the nestest.nes log (well, at least up until the illegal opcodes kicked in), but my cpu gets stuck in a loop as well.

So I'm thinking at this point I'm missing something important about how the system starts up. I've read the power up states for both the PPU and the CPU on the wiki, but I'm having a hard time understanding how the system starts up. I know the system boots up, the program counter is set to the reset vector, and then the PPU does something for a certain amount of cycles before telling the CPU that it's clear to go.

How exactly does the "handshake" between the PPU and the CPU occur? Is the PPU rendering frames at this point? Do NMIs occur at this point, or do they wait until the handshake is complete?


The CPU and PPU run in isolation and only interact via reads/writes from the CPU and NMIs from the PPU. On the NES, the PPU always starts at (0,0) in this diagram on power-up and reset (I think the reset button on the Famicom doesn't reset the PPU, so there it could start anywhere within the frame). The PPU is always "running", so there's nothing special that needs to be done to get it going.

The only complication is that certain registers won't work (are zeroed out) until the PPU has run for one frame. On startup, you'll see games e.g. polling the VBlank flag in $2002 in a loop to determine when the PPU is safe to use. I don't know of any games that depend on certain PPU regs not working on start-up though, so you can safely treat all PPU regs as working right away when starting out.

If you haven't done so already, I'd recommend implementing CPU tracing so you can see what your emulator is doing. On startup you should get something like the following (taken from Donkey Kong):

Code:
C79E: sei
C79F: cld
C7A0: lda #$10
C7A2: sta $2000
C7A5: ldx #$FF
C7A7: txs     
C7A8: lda $2002 <-+
C7AB: and #$80    | VBlank flag polling loop
C7AD: beq $C7A8 --+


Once you get that, you can then see that the PPU register accesses in that code are handled as expected, using your favourite debugging method.


Top
 Profile  
 
PostPosted: Thu Aug 15, 2013 7:32 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10064
Location: Rio de Janeiro - Brazil
Dartht33bagger wrote:
How exactly does the "handshake" between the PPU and the CPU occur?

Are you setting bit 7 of $2002 to indicate that VBlank has started? The PPU needs about a frame to become stable after power up, so all games will wait 2 or 3 frames by polling this flag before doing anything else. If you are not consistently setting/clearing the flag games will get stuck in this wait loop.

Quote:
Is the PPU rendering frames at this point?

The PPU is always rendering something. Even if background and sprites are disabled, it will render the background color.

Quote:
Do NMIs occur at this point, or do they wait until the handshake is complete?

NMIs will only occur if bit 7 of $2000 is set. Most games will only enable NMIs after everything is stable and initialized. It should be possible to have them enabled right from the start though.


Top
 Profile  
 
PostPosted: Mon Aug 19, 2013 10:04 pm 
Offline
User avatar

Joined: Sat Jan 03, 2009 3:28 pm
Posts: 59
Location: Oregon
Another question about rendering turned on/off. If background rendering is turned off, does the ppu still go through the attribute/nametable/tile fetch and all that, or does the ppu just idle and render pixels from whatever pallete value is at $3F00?


Top
 Profile  
 
PostPosted: Mon Aug 19, 2013 10:11 pm 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19107
Location: NE Indiana, USA (NTSC)
Dartht33bagger wrote:
If background rendering is turned off, does the ppu still go through the attribute/nametable/tile fetch and all that

Yes, so long as sprite rendering is turned on. If at least one of background rendering and sprite rendering is turned on, all the background processing still happens. The background pixels are just replaced with 0 before they hit the compositor (the part of the PPU where the pixels from the sprite unit and background unit are combined). In my block diagram, this replacement with 0 happens in the D-shaped AND gates just to the left of the compositor. This results in display of the color at $3F00 unless an opaque sprite is in the way.

If both background and sprite rendering are turned off, the output is the color at $3F00, unless the VRAM address is in $3F00-$3FFF in which case the output is the color at the VRAM address.


Top
 Profile  
 
PostPosted: Tue Aug 20, 2013 2:38 am 
Offline
User avatar

Joined: Sat Jan 03, 2009 3:28 pm
Posts: 59
Location: Oregon
So I've spent about 8 hours debugging now and I'm kind of stuck. I'm currently just trying to render the background before I move onto sprites, and everything looks like it *should* be working correctly in my code. The screen shows a different story, though. I'm using Donkey Kong as a test game and I'm getting black, orange and gray bars on the screen. Does anyone have any idea why this is happening? I can't seem to pinpoint the issue since my cpu seems to be filling VRAM correctly, and my PPU is reading from valid addresses.


Attachments:
Nesemu.png
Nesemu.png [ 16.37 KiB | Viewed 1445 times ]
Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 74 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Majestic-12 [Bot] and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group