Fun with CHR-ROM

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Fun with CHR-ROM
by on (#19626)
I've got this pattern table, and it looks like this in YY-Chr. Now, I put in in my NESASM program using

.bank 2
.org $0000
.incbin "parallax.chr"

Once I compile it, though, the palette dump I get from RockNES looks like this. Notice the squiggly line thingies at the top. Where are they coming from?

Also, I'm having problems with the name\attribute table. It seems as if the name and attribute tables are filled with $00. However, when I look at the dump from RockNES, the file seems intact! I write %10001000 to $2000, and the file is included in NESASM's bank 2 at $2000.

by on (#19627)
Nametables and attribute tables cannot be in CHR ROM unless you are using a specialized mapper - you must store it in your PRG ROM (i.e. banks 0/1) and then copy it into PPU memory.

I'm not sure what's going on with your tile corruption, though - are you using a special mapper?

by on (#19628)
Thanks for the info on the name and attribute tables. I'm using Mapper 0, so that can't be the problem. NESASM maybe?

by on (#19629)
So you can't read exactly what data is in the tiles unless you're using CHR RAM?

by on (#19630)
Celius wrote:
So you can't read exactly what data is in the tiles unless you're using CHR RAM?


Umm, yes you can...
Just because the tiles are in CHR-ROM doesn't mean you can't read them - set the VRAM address (via $2006) to point at tile data (PPU $0000-$1FFF) and read the data out of $2007.

by on (#19632)
But how would you do that if $2007 is one register, and there are 16 bytes to make up a tile?

by on (#19633)
Celius wrote:
But how would you do that if $2007 is one register, and there are 16 bytes to make up a tile?

One byte at a time.

First set the starting address:
Code:
  lda #addrhi
  sta PPUADDR
  lda #addrlo
  sta PPUADDR
  lda PPUDATA  ; load the PPU's read buffer

Then copy a 256-byte chunk from PPUDATA into increasing locations in RAM, and copy it back out to VRAM.

by on (#19635)
CHRROM is just readable, and CHRAM is both readable and writable. That remains true, even if CHROM is supposed to be read by the PPU it's still possible for the CPU to read it in VBlank (just remember that $2007 reads are buffered, exept for palette area !). Some games with limited PRGROM does this including Super Mairo Bros. 1 and several others (my game does that too, but I did it rather for fun because I'm not totally out of PRGROM).

Also, CHRRAM is supposed to be written to by the CPU and read by the PPU, but it's also possible to read it from the CPU. (Final Fantasy II does that to animate the water. However, Hanjuku Hero and Final Fantasy III animates the water in a similar way, but this time they improved the code to keep a copy of the water tiles in RAM, so that they have more VBlank time to do other things, on the other side of wasing a portion of RAM).

by on (#19732)
I'm getting glitched data in the name tables. Here's my code:

Code:
   lda #$20   ;Set $2007 to name tables
   ldx #$00
   sta $2006
   stx $2006

   lda #$90   ;start address at $9090
   sta $01
   sta $00   
   ldx #$04
   ldy #$FF

LoadNameTable:

   lda [00],y
   sta $2007
   dey
   bne LoadNameTable

VWait3:   
   lda $2002
   bpl VWait3
   
   dex
   beq PalletteStart   ;load pallette data
   inc $01
   ldy #$FF
   jmp LoadNameTable   

by on (#19750)
- Your code is somewhat confusing and not very well ordered, wich isn't a very good way to go
- Did you make sure to write #$00 to $2001 before doing all this ?
- It's a bad idea to "hardcore" your adress at $9090 in the code. You'd rather use a labed, and do something like the following :
Code:
lda #<Label
sta PointerL
lda #>Label
sta PointerH

lda [Pointer],Y

by on (#19755)
The code in the above box was copied incorrectly, so I fixed it up. Also, $2001 is zeroed out, as well as $2000. It still does not work. Anything else?

by on (#19758)
What your code does is copy data from $918f to $9090 BACKWARDS to $2007, then copy $928f to $9190 BACKWARDS, etc...
What you probably want is to do it forward.
You'd want to do something like that :
Code:
  ldx #$04
LoadLoop2
  ldy #$00
LoadLoop
  lda [Pointer], Y
  sta $2007
  iny
  bne LoadLoop
  dex
  bne LoadLoop2

by on (#19764)
your example copies the first 256 bytes over 4 times instead of the whole 1k.

Here's a quick fixup:

Code:
  ldx #$04
  ldy #$00   ; no need to put this in a LoadLoop2
                  ; as Y will be 0 when you DEX, and thus will be 0
                  ; everytime LoadLoop iterates
LoadLoop
  lda [Pointer], Y
  sta $2007
  iny
  bne LoadLoop
  inc PointerH    ; need this to advance forward 256 bytes in the source
  dex 
  bne LoadLoop



Also -- make sure you set the PPU address to increment by 1 after $2007 writes and not by 32, in addition to shutting the PPU off and all the other things mentioned.

by on (#19785)
Thanks Disch, your loop worked.