Page 1 of 1

Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 2:19 am
by kocmoc
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)?

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 2:38 am
by koitsu
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

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 5:34 am
by Sumez
Basically, you write to the CHR-RAM in the same way you'd write to your nametables.

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 7:24 am
by kocmoc
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: Select all

    ; 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: Select all

;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 :(

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 7:41 am
by Kasumi
A tile is 16 bytes.
Tiles are stored at $0000-$1FFF

If you do this:

Code: Select all

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.

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 7:41 am
by kocmoc
sorry :
lda (src),y - is index ok, but from where (only zeropage - 0xFF size)?

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 7:49 am
by tepples
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: Select all

iny
bne :+
  ; The program counter gets here only if INY changed Y to $00
  inc src+1
:

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 7:55 am
by kocmoc
I seem to understand :(
CHR-ROM is 0-2000$
if not CHR-ROM, then we fill it with:

Code: Select all

  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?

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 8:07 am
by Kasumi
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: Select all

lda #$20
sta $2006
lda #$00
sta $2006
Because the first byte of the first nametable's address is $2000.
If you do

Code: Select all

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: Select all

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: Select all

 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: Select all

 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. 

Re: Use CHR without CHR-ROM

Posted: Mon Aug 20, 2018 8:19 am
by kocmoc

Code: Select all

  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: Select all

;index from CHR-RAM ($0-$2000)
I incorrectly explained this, sorry (I understand it).

Code: Select all

 ; 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! )

Re: Use CHR without CHR-ROM

Posted: Tue Aug 21, 2018 1:39 am
by Sumez
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.

Re: Use CHR without CHR-ROM

Posted: Tue Aug 21, 2018 2:08 am
by kocmoc
Okay, now I understand this completely.
Thank you! =)

Re: Use CHR without CHR-ROM

Posted: Tue Aug 21, 2018 7:23 am
by tokumaru
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.

Re: Use CHR without CHR-ROM

Posted: Wed Aug 22, 2018 2:02 am
by Sumez
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?

Re: Use CHR without CHR-ROM

Posted: Wed Aug 22, 2018 4:25 am
by tepples
Pin Bot and High Speed come to mind.