It is currently Mon Dec 11, 2017 11:37 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 58 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Fri Feb 19, 2016 1:47 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
This is really interesting/fun stuff but I'm expecting to have a brain meltdown anytime now. :)
I think I understand the basics more or less (probably a little more "less" :)) but the challenge here is to get it down in code. Where do you start? :) There are many things to think about but still it doesn't seem that it will require that much code in the end.
Perhaps the start is to have a small pixelbuffer (16-pixels or so) that you keep on filling/emptying... (?)

_________________
http://nes.goondocks.se/


Top
 Profile  
 
PostPosted: Fri Feb 19, 2016 2:02 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
I would stay start with the bare minimum. For me, that would be drawing BG only with no attributes. If you can wrap your head around the moving parts, it's not that hard:

The PPU typically has a 4-fetch pattern that spans 8 cycles total (each fetch is 2 cycles). Those fetches are:

A) Nametable byte (cycles 1,2)
B) Attribute byte (3,4)
C) CHR low byte (5,6)
D) CHR high byte (7,8)


- Nametable fetch reads a byte from the current scroll (current PPU address). That NT byte gets stored somewhere temporarily
- Attribute fetch read a byte -- but for now let's ignore it
- CHR low byte reads a byte based on the previously fetched NT byte. That byte gets moved into the "low shifter"
- CHR high byte reads the other CHR byte, moves it into a "high shifter"


So that's the fetch pattern. Then the rendering pattern is just pulling values from the shifters and outputting them.

When fineX = 0, you use the high bit of the shifter.
When fineX = 1, you use next to high bit
When fineX = 2, you use next to next to high bit
etc

Once you pull a value out of the shifter (no matter where you pulled it from), you shift it left.


1) So you pull out the appropriate bits from the low and high shifters
2) combine them to get your 2bpp color
3) which you would then combine with attributes (but don't worry about that for now)
4) which you would then prioritize with the sprite pixel (but don't worry about that for now)
5) Final value = the pixels you output


Top
 Profile  
 
PostPosted: Fri Feb 19, 2016 2:27 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
Hmm, But even in minimum state I need to deal with "FineY"-scroll and how to deal with fetching data from another name table (assuming xscroll>0).
?

_________________
http://nes.goondocks.se/


Top
 Profile  
 
PostPosted: Fri Feb 19, 2016 3:02 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
If you handle $2000/$2005/$2006 writes properly, and do the appropriate changes to the PPU addr to adjust the scroll during the frame... you need not concern yourself with the scroll. At least not for the NT fetch. The low 12 bits of the PPU address IS the scroll.

This handles coarse scroll:
Code:
NTbyte = ppuread( 0x2000 | (ppu_addr & 0x0FFF) );



Fine-Y is stored in bits 12-14 of the PPU address... and that is only used when fetching CHR:
Code:
 // bgpage = 0x0000 or 0x1000 depending on the state of $2000.4
finey = (ppu_addr >> 12) & 7;

CHR_low = ppuread( bgpage | (NTbyte << 4) | finey );
CHR_high = ppuread( bgpage | (NTbyte << 4) | finey | 8);


An Fine-X scroll determines which bit of the shifter to pull your pixel from.


Top
 Profile  
 
PostPosted: Sat Feb 20, 2016 5:06 am 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
What happens assuming x-scroll is something like, for example, 250? What happens with the vram_address then because if I just keeps incrementing it, it won't work properly. Will the vram_address magically "jump" to the next nametable? What will then happen at the next scanline?
Hope you get what I mean..

_________________
http://nes.goondocks.se/


Top
 Profile  
 
PostPosted: Sat Feb 20, 2016 6:06 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
oRBIT2002 wrote:
Will the vram_address magically "jump" to the next nametable?

Yes, the name table bit will toggle.

Quote:
What will then happen at the next scanline?

At the end of the visible scanline, the X part of the scroll is copied from the temp VRAM register, so the next scanline will start at the same X coordinate as the previous one.

If I'm not mistaken, this information is written in the diagram that was posted in this thread.

EDIT: Yes, the "hori(v) = hori(t)" box Indicates when the horizontal bits of the scroll are copied from T to V.


Top
 Profile  
 
PostPosted: Sat Feb 20, 2016 10:02 am 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
oRBIT: You might want to read some docs on how scrolling actually works on the NES:

http://wiki.nesdev.com/w/index.php/PPU_scrolling


EDIT:

The thing to note is that the NES doesn't really have an X scroll or a Y scroll... or even a nametable select. It just has a PPU address, and a "temporary" PPU address: Often referred to as "loopy v" and "loopy t" respectively (since they were identified/coined in loopy's scroll doc) -- or just "v" and "t".

If you look at that wiki page... notice how $2005 and $2006 change the exact same var ("t"), just in different ways.


Top
 Profile  
 
PostPosted: Sat Feb 20, 2016 2:58 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
i think I've got it a little bit wrong again.. According to the PPU diagram it fetches tiles all the time (and not really pixel by pixel as I thought and discovered when doing the math...). Correct me if I am wrong.

You learn and discover something new everyday obviously. :)

_________________
http://nes.goondocks.se/


Top
 Profile  
 
PostPosted: Sat Feb 20, 2016 6:01 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
The PPU performs 4 fetches for a single tile:

- Nametable byte
- Attribute byte
- CHR low
- CHR high

Each of these fetches takes 2 cycles... resulting in 8 cycles total for an 8x1 pixel image.
That 4-fetch pattern is repeated several times throughout the scanline. You can think of this fetch process of "loading" the image, but not actually drawing it.


In addition to fetching, it's also outputting pixels. 1 pixel per cycle means that it'll take 8 cycles to draw an 8x1 image.

So it takes 8 cycles to LOAD an 8x1 image.
And it takes 8 cycles to DRAW an 8x1 image.

So graphics are loaded and drawn at more or less the same speed... just with a slight delay between when they're loaded and when they're actually drawn.


Top
 Profile  
 
PostPosted: Sat Feb 20, 2016 6:47 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
Disch wrote:
So graphics are loaded and drawn at more or less the same speed...

Not only at the same speed, but also at the same TIME. As it fetches data for future pixels, it also draws pixels using data that was fetched before.


Top
 Profile  
 
PostPosted: Sun Feb 21, 2016 12:39 am 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
The pieces are finally starting to fit together(in my head).. :)

_________________
http://nes.goondocks.se/


Top
 Profile  
 
PostPosted: Sun Feb 21, 2016 6:40 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
oRBIT2002 wrote:
The pieces are finally starting to fit together(in my head).. :)


Good. To be better, please, the wiki must be updated in order to make it easier to understand.


Top
 Profile  
 
PostPosted: Sun Feb 21, 2016 12:58 pm 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
Here's tonights first result of "Mario Bros" titlescreen with a pixelrenderer ("tilerender" should be more appropriate but still.. :) )
It's buggy of course, but I'm still pretty proud I got this far. :D
Now lets see if we can fix some bugs...


Attachments:
File comment: "Mario Bros" titlescreen (buggy)
mb.png
mb.png [ 33.26 KiB | Viewed 963 times ]

_________________
http://nes.goondocks.se/
Top
 Profile  
 
PostPosted: Sun Feb 21, 2016 1:17 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19334
Location: NE Indiana, USA (NTSC)
The first step toward fixing it is logging which addresses the PPU is reading and seeing whether the log makes sense. For example, the first row of a title screen nametable is likely to be blank, and the first 20 accesses might look like this:
Code:
     nt   attr tiledata
321: 2000 23C0 0240 0248  (starting in pre-render pre-roll)
329: 2001 23C0 0240 0248
  1: 2002 23C0 0240 0248  (first fetch of new line, for third column)
  9: 2003 23C0 0240 0248
 17: 2004 23C1 0240 0248

What do you get?


Top
 Profile  
 
PostPosted: Mon Feb 22, 2016 4:13 am 
Offline
User avatar

Joined: Sun Mar 19, 2006 3:06 am
Posts: 584
Location: Gothenburg/Sweden
My vram-address is way off, so something is going on here...

_________________
http://nes.goondocks.se/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 58 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Yahoo [Bot], zxbdragon and 5 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