It is currently Mon Oct 15, 2018 10:37 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Use CHR without CHR-ROM
PostPosted: Mon Aug 20, 2018 2:19 am 
Offline
User avatar

Joined: Mon Aug 20, 2018 2:09 am
Posts: 9
Location: Rus (PAL)
Hello!
I'm new to programming for nes.
It seems that everything is clear, except for one thing: if the game does not use CHR-ROM (only PRG-ROM), how does the game determine where to get the tiles/sprites (respectively for $2007/$2004)?


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 2:38 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3629
Location: Mountain View, CA
The location is the same whether you're using CHR-ROM or CHR-RAM (i.e. PRG-ROM only): the pattern table data (for tiles/sprites) is located at $0000-0FFF and $1000-1FFF in PPU memory space. That's 8KBytes total (4KBytes per pattern table).

That region of PPU memory spaceis mapped (via hardware/address lines) to CHR on the cartridge -- which is either CHR-ROM or CHR-RAM.

With CHR-ROM, the pattern tables are thus what's contained in the CHR-ROM IC / mask ROM itself.

With CHR-RAM, the pattern tables are thus RAM, and it's up to 6502 code located in PRG to populate the pattern tables with data.

Details: https://wiki.nesdev.com/w/index.php/CHR_ROM_vs._CHR_RAM


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 5:34 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 768
Location: Denmark (PAL)
Basically, you write to the CHR-RAM in the same way you'd write to your nametables.


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 7:24 am 
Offline
User avatar

Joined: Mon Aug 20, 2018 2:09 am
Posts: 9
Location: Rus (PAL)
I understand correctly:
If the cartridge has a CHR-ROM, then CHR-RAM (0 - $2000) is filled with the data index from the CHR-ROM, but if the cartridge does not have a CHR-ROM, then the CHR-RAM is filled with data! (and not index) PRG-ROM?
I better give an example ((I do not understand how to draw a tile on an index without CHR-ROM, what indexes are associated with PRG-ROM memory?):
my test code:
Code:
    ; load tiles
    lda #$20
    sta $2006
    lda #$00
    sta $2006 ; address first the page (ok)

    ldx #0
    ldy #0
    load_tile_next:

    lda #1; this index of data from the CHR-ROM (e.g. how here is first sign) (ok, e.g. data quad: .dw $FF00 .dw $FF00 .dw $FF00 .dw $FF00 .dw $FF00 .dw $FF00 .dw $FF00 .dw $FF00)
    sta $2007
;.......

from link on nesdev forum (above):
Code:
;Switching to CHR RAM
 lda #<mytiles_chr  ; load the source address into a pointer in zero page(why zero page?
                           ; .segment "RODATA" - is zero page?
                           ; mytiles_chr: .incbin "mytiles.chr")
  sta src
  lda #>mytiles_chr
  sta src+1

  ldy #0       ; starting index into the first page
  sty PPUMASK  ; turn off rendering just in case
  sty PPUADDR  ; load the destination address into the PPU (why zero, if the initial address of the first page is 2000?)
  sty PPUADDR
  ldx #32      ; number of 256-byte pages to copy
loop:
  lda (src),y  ; copy one byte (here copying data (tile), not INDEX!, why?) (no ok, i.e. need copying 16 bytes for one tile?.... wtf I confused %)
  sta PPUDATA

Sorry for stupid questions :(


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 7:41 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1250
A tile is 16 bytes.
Tiles are stored at $0000-$1FFF

If you do this:
Code:
lda #0
sta $2006
sta $2006
;The address that $2007 will write to is now the first byte of the first tile
ldx #16;Get set up to write 16 bytes
loop:
sta $2007
dex
bne loop

You have just written all 16 bytes of tile 0 with index 0. So the address of any given tile on the PPU is 16*tileNumber. The index you use to refer to it after you copy it is whereever you copied it to.

So say you had 8KB of CHR data in your ROM. (In your PRG ROM, not your CHR ROM which CHR RAM doesn't have.) If you set address $0000 with $2006 and then wrote that CHR data from your PRG ROM byte by byte into $2007, you'd use all the same exact indices for each tile as you would if you were on CHR ROM on NROM with the same data in your CHR ROM bank. You can find code that copies 8KB of CHR data to RAM on this page: https://wiki.nesdev.com/w/index.php/CHR ... to_CHR_RAM Edit: Oh you already found that >_> Sorry.

_________________
https://kasumi.itch.io/indivisible


Last edited by Kasumi on Mon Aug 20, 2018 7:41 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 7:41 am 
Offline
User avatar

Joined: Mon Aug 20, 2018 2:09 am
Posts: 9
Location: Rus (PAL)
sorry :
lda (src),y - is index ok, but from where (only zeropage - 0xFF size)?


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 7:49 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
The variable src has to be in zero page, but the data it points to need not be. Consider these conditions:

  • src is a symbol for address $0008
  • The value at $0008 is $AB
  • The value at $0009 is $89
  • The value in Y is $20

Then the instruction lda (src),y will do this:

  1. Read the address whose low byte is in $0008 and whose high byte is in $0009, which is $89AB.
  2. Add the value in Y to this address. Adding $20 to $89AB produces $89CB.
  3. Copy the value in the resulting address to A.

When Y overflows from $FF to $00, use that as signal to increase the high byte of the pointer by 1 so that you can read the next 256 bytes of data:
Code:
iny
bne :+
  ; The program counter gets here only if INY changed Y to $00
  inc src+1
:


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 7:55 am 
Offline
User avatar

Joined: Mon Aug 20, 2018 2:09 am
Posts: 9
Location: Rus (PAL)
I seem to understand :(
CHR-ROM is 0-2000$
if not CHR-ROM, then we fill it with:
Code:
  lda #$0 ; data
  ldx #$0 ; address
  stx $2006
  stx $2006

 ; pseudo code
  all_data:
      sta $2007 ; save tile/sprite
      bne all_data ; till $40 * $10 =  first page tile/sprite
      bne all_data ; till $40 * $10 =  second page tile/sprite (1 page + 2 page = $2000)

  ; after, we use as usually
  lda #$20
  sta $2006
  sta $2006 ; e.g. first page
  sta $2007 ; index from CHR-RAM ($0-$2000)


I right?


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 8:07 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1250
Not quite. So you have to load both bytes of the address then write them.
For instance, to setup the first byte of the first nametable, you'd do
Code:
lda #$20
sta $2006
lda #$00
sta $2006

Because the first byte of the first nametable's address is $2000.
If you do
Code:
lda #$20
  sta $2006
  sta $2006 ; e.g. first page

like in your example, you're writing to $2020.
The reason you can do
Code:
lda #$00
sta $2006
sta $2006

For the first byte of CHR RAM is just because both bytes of the address happen to be the same.

Code:
 index from CHR-RAM ($0-$2000)

No, just the tile number. Each tile in the nametable is one byte, so you can only use values from $00-$FF, not $0000-$1FFF.

CHR RAM doesn't change how you deal with nametables at all. Edit for clarity: It just means you have to write the tiles themselves (which the nametables draw) to $0000-$1FFF. You can sort of think of it like CHR ROM automatically copies the tile data to $0000-$1FFF on boot. CHR RAM doesn't, so you have to do this step. After the copy is done, everything for nametables is the same for both CHR RAM and CHR ROM.

The copy code in your example would also only write exactly one byte to CHR RAM. (Which you may know because you marked it as psuedo code. If so, ignore below)
Code:
 lda #$0 ; data;The Zero flag is set, because lda affects the zero flag and zero got loaded.
  ldx #$0 ; address;The zero flag is set, because ldx affects the zero flag and zero got loaded.
  stx $2006;This does not affect the zero flag so it's still set
  stx $2006;This does not affect the zero flag so it's still set

 ; pseudo code
  all_data:
      sta $2007 ; save tile/sprite;This does not affect the zero flag, so it's still set
      bne all_data ;So this will never branch
      bne all_data ;and this will never branch
;So that single write to $2007 is all that happens.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Mon Aug 20, 2018 8:19 am 
Offline
User avatar

Joined: Mon Aug 20, 2018 2:09 am
Posts: 9
Location: Rus (PAL)
Code:
  lda #$20
  sta $2006
  sta $2006 ; e.g. first page

I understand it.
This, just be short (sorry that without explanation, I meant writing in any position on the first page).
Code:
;index from CHR-RAM ($0-$2000)

I incorrectly explained this, sorry (I understand it).
Code:
 ; pseudo code

Yes, this is pseudocode, I understand it too.

I'm just stupid and forgot that the tile on the Vpages is shown from $0 to $2000 (we can manually fill it on the fly, not only from the CHR-ROM).
It's simple ...

I really thank you all for your help! )


Top
 Profile  
 
PostPosted: Tue Aug 21, 2018 1:39 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 768
Location: Denmark (PAL)
kocmoc wrote:
I understand correctly:
If the cartridge has a CHR-ROM, then CHR-RAM (0 - $2000) is filled with the data index from the CHR-ROM, but if the cartridge does not have a CHR-ROM, then the CHR-RAM is filled with data! (and not index) PRG-ROM?

No, that's not how it works. The cartridge has a chip with graphics data and that can either be a ROM chip or a RAM chip. Never both.

If it's a ROM chip, the data is programmed into the chip, and can't be changed as the game is running. Basically the graphics is a part of the game as it is produced.
(you can change the graphics made available with the CHR ROM using a mapper chip, but don't worry about that right now)

If it's a RAM chip, it's empty when the game starts (or rather, has "random" data in it), and your program will have to fill it with data before the NES can display anything. The advantage here is that you can put anything into CHR-RAM, and alter it based on game logic.
The advantage to ROM is that the data is available and accessible instantly and you never have to "load data".

I absolutely recommend starting out making something using CHR-ROM before you even worry about CHR-RAM existing.


Top
 Profile  
 
PostPosted: Tue Aug 21, 2018 2:08 am 
Offline
User avatar

Joined: Mon Aug 20, 2018 2:09 am
Posts: 9
Location: Rus (PAL)
Okay, now I understand this completely.
Thank you! =)


Top
 Profile  
 
PostPosted: Tue Aug 21, 2018 7:23 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10892
Location: Rio de Janeiro - Brazil
Sumez wrote:
The cartridge has a chip with graphics data and that can either be a ROM chip or a RAM chip. Never both.

Actually, there are cartridges with both CHR-ROM and CHR-RAM, but that's a very rare occurrence and hardly anyone would have a user for this.

For beginners, CHR-ROM is simpler, because the tiles are just there, ready to be used. For more advanced projects, there are times when one or the other is more convenient, depending on how dynamic the graphics are and how fast you need to change them.


Top
 Profile  
 
PostPosted: Wed Aug 22, 2018 2:02 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 768
Location: Denmark (PAL)
How does that even work?
I can get the use for using mappers on CHR-RAM (which to my knowledge hasn't been done for some reason?), but combining CHR-ROM and RAM sounds weird. What games do it? Licensed ones?


Top
 Profile  
 
PostPosted: Wed Aug 22, 2018 4:25 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20656
Location: NE Indiana, USA (NTSC)
Pin Bot and High Speed come to mind.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Gilbert, Google Adsense [Bot] 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