It is currently Tue Oct 17, 2017 7:04 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 30 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Mar 22, 2017 7:26 pm 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
So I've been reading Nerdy Nights and they have an example where they teach you how to use nametables. here is the code:
Code:
LoadBackground:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$20
  STA $2006             ; write the high byte of $2000 address
  LDA #$00
  STA $2006             ; write the low byte of $2000 address
  LDX #$00              ; start out at 0
LoadBackgroundLoop:
  LDA background, x     ; load data from address (background + the value in x)
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$80              ; Compare X to hex $80, decimal 128 - copying 128 bytes
  BNE LoadBackgroundLoop  ; Branch to LoadBackgroundLoop if compare was Not Equal to zero

What I don't understand about it is that all it says is LDA background,X. What address is background? Is it a variable because of sprite DMA? That would make sense if each individual X and Y position had its own memory address. And also, what is a High/Low latch?


Top
 Profile  
 
PostPosted: Wed Mar 22, 2017 7:45 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10047
Location: Rio de Janeiro - Brazil
DementedPurple wrote:
What I don't understand about it is that all it says is LDA background,X. What address is background?

It's a table in ROM where the data is copied from. You have to create this table yourself, it's just a sequence of tile indices:
Code:
background:
   .db $00, $02, $01, $10, $12, ...

The LDA $XXXX, X addressing mode can only access tables up to 256 bytes large though, so if you need to write more than that to a name table (a complete name table is 960 bytes) you will need to use pointers (LDA ($XX), Y, where the ZP position $XX contains the address of the table, and should be adjusted a few times during the transfer so that more than 256 bytes can be accessed).

Quote:
Is it a variable because of sprite DMA?

What? No sprites have nothing to do with the name tables.

Quote:
That would make sense if each individual X and Y position had its own memory address.

Each tile DOES have its own address, but even though the screen is 2D, memory is 1D. To find the address of a tile at position (X, Y) you need to use a little formula: address = Y * 32 + X. You can also think of the address in binary as having the following format: 0010NNYY YYYXXXXXX.

Quote:
And also, what is a High/Low latch?

To set the VRAM address, you write both the low and high bytes of the address to register $2006. This latch exists so the PPU knows whether you're writing the low or the high byte, otherwise it wouldn't be able to tell them apart. Reading $2002 resets the latch, letting the PPU know that the next $2006 write will contain the high byte of the VRAM address.


Top
 Profile  
 
PostPosted: Wed Mar 22, 2017 7:49 pm 
Offline
User avatar

Joined: Wed Oct 16, 2013 7:55 am
Posts: 130
Two separate things going on here:

1) Data table with indexed addressing.

In this sample code, `background` is the name of a table in memory. It's not a `variable`, because it's an address of ROM, which is not modifiable. Instead, this location in memory has a bunch of read-only data, and an amount of bytes equal to $80 is being read from that location and loaded into the PPU.

Let's say, for example, that `background` is pointing at the address $9123. Then the instruction:
LDA background,x
Will get the address at $9123+x and put it into the accumulator. The first time through the loop, X = 0, due to the LDX instead before the loop.

So:
LDA background,x
when X=0, loads A with the value in ROM at $9123

The next time through the loop, when X = 1,
LDA background,x
loads A with the value in ROM at $9124

and so on until X = $80.

This has nothing at all to do with sprite DMA, that's completely unrelated.

2) The high / low latch

The NES is an 8-bit machine, but its uses address spaces that are 16-bits, from $0000 to $ffff. In particular, the PPU has a 16-bit address space. This means that to create a pointer to the PPU's memory, addresses have to be created one byte at a time. When a byte is written to CPU's address $2006, this sets half of the PPU memory pointer. Which half it sets is based upon an internal flop called a "latch". When PPU_STATUS ($2002) is read, it resets the latch to "high", meaning the next write to $2006 will be the high byte of the ppu address, and this write will also flop the latch. The following write to $2006 will then be the low byte of the ppu address.

Stepping through this code a single instruction at a time:

Code:
  LDA $2002  -  latch=0, ppu_pointer=????
  LDA  #$20  -  latch=0, ppu_pointer=????
  STA $2006  -  latch=1, ppu_pointer=20??
  LDA  #$00  -  latch=1, ppu_pointer=20??
  STA $2006  -  latch=0, ppu_pointer=2000


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 7:33 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
Then how would we know what part of the ROM the name tables are pointing to?


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 7:48 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1771
Location: DIGDUG
Quote:
Then how would we know what part of the ROM the name tables are pointing to?


The nametables don't point to the ROM, or anything else.

The PPU has it's own RAM chip. The nametables are on that separate RAM chip. You have to transfer the data to it. (accessed with 2007 register).

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 7:54 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
Do I tell it where the Nametable ram is with the PPU control registers?


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 8:15 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1771
Location: DIGDUG
Now that is a good question.

The 2000 register selects a nametable (there are 4 nametables).
---- --00 = nametable 0
---- --01 = nametable 1

The scroll register (2005) tells the PPU where in the nametable to start rendering (ie, it shifts the nametable's position on the screen).

The 2006 shares bits with the 2005 register, so writing to 2006 (without then setting 2005 registers) will also shift the position of the screen. This is probably confusing...but it is common to rewrite the scroll registers every frame, even if they haven't changed, to make sure writes to the PPU don't screw up the scroll bits and misalign the screen.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 8:26 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
So how would I actually plot sprites?


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 8:44 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10047
Location: Rio de Janeiro - Brazil
Sprites have nothing to do with name tables. Name tables are used to draw backgrounds.

To draw sprites you have to fill a page of RAM worth of sprite attributes and then, during vblank, transfer that to the PPU using a sprite DMA.

To draw backgrounds you have to make sure that rendering is off (either by forcing it off or waiting for vblank) and copy the name table data to VRAM using registers $2006 (address) and $2007 (data). If your game uses a static background, normally you just have to copy 1024 bytes (960 tile indices + 64 attribute bytes) from ROM to VRAM with rendering disabled. But if you have scrolling levels, dynamic backgrounds, etc., then you need a more complex system to buffer the incremental changes to RAM and copy those to VRAM during vblank, respecting the limits of how much data can be transferred during the short vblank time.


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 8:47 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
So you pretty much would just write tile numbers to the PPU?


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 8:50 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19091
Location: NE Indiana, USA (NTSC)
To update nametables, you write bits 13-8 of the destination address to $2006, bits 7-0 of the destination address to $2006, and one or more tile numbers to $2007. Every time you write to $2007, the destination address increases by 1, causing tile numbers to be written from left to right. There's a setting in $2000 to make it increase by 32 instead, causing tile numbers to be written from top to bottom.


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 8:52 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10047
Location: Rio de Janeiro - Brazil
For backgrounds, yes. You also have attributes to worry about, they select which palette is used for each 16x16-pixel area of the screen, but you don't need to worry about creating this data manually if you use a program like NES Screen Tool. You can design your screens in it and export the data to be included in your ROM.


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 9:09 am 
Offline

Joined: Mon Jan 30, 2017 5:20 pm
Posts: 294
Location: Colorado USA
Could you maybe explain it in simpler terms?


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 9:31 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19091
Location: NE Indiana, USA (NTSC)
The following is long because "simpler terms" to express the same idea are often longer.

Coordinate pair (12, 10) means x=12 y=10, or 12 cells from the left and 10 cells from the top.

The video memory address of a nametable cell is the nametable's base address plus 32 times the Y coordinate plus the X coordinate.
For example, the video memory address of (12, 10) on the first nametable, whose base address is $2000, is
$2000 + 32 * Y + X
= $2000 + 32 * 10 + 12
= $2000 + 332
= $2000 + $14C
= $214C

To seek to $214C in video memory, write $21 to $2006 and then write $4C to $2006. Then write tile numbers to $2007. The first tile number you write to $2007 will then go to $214C, which corresponds to cell (12, 10).

If you continue to write tile numbers to $2007, where they go depends on the video memory increment, which can be +1 or +32. This depends on bit 2 of the last value written to $2000.

If bit 2 of $2000 is clear (0), the video memory increment is set to +1. This means successive tile numbers written to $2000 will appear to the right. To set the video memory increment to +1, write $80 to $2000. This means vblank NMI enabled (because bit 7 is set to 1) and video memory increment +1 (because bit 2 is clear to 0).

If the video memory increment is set to +1, and you seek to $214C and write three tile numbers, these tile numbers will be written to $214C, $214D, and $214E, which correspond to cell (12, 10) and the two cells to its right.

If bit 2 of $2000 is set (1), the video memory increment is set to +32. This means successive tile numbers written to $2000 will appear downward. To set the video memory increment to +32, write $84 to $2000. This means vblank NMI enabled (because bit 7 is set to 1) and video memory increment +32 (because bit 2 is set to 1).

If the video memory increment is set to +32, and you seek to $214C and write three tile numbers, these tile numbers will be written to $214C, $216C, and $218C, which correspond to cell (12, 10) and the two cells below it.


Top
 Profile  
 
PostPosted: Thu Mar 23, 2017 9:51 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1771
Location: DIGDUG
PPU addresses $2000-23ff represent nametable #0.

The last 64 bytes ($23c0-23ff) is called attribute table, and it's complicated, but it tells which parts of the screen (bg) should use which bg palette.

Just fill it with zero for now, and the whole screen will use the first palette (bg palette #0 = $3f00-3f03).

_________________
nesdoug.com -- blog/tutorial on programming for the NES


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users 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