News:

11 March 2016 - Forum Rules

Main Menu

Changing Background tiles

Started by HotCoffee, August 28, 2021, 07:30:23 AM

Previous topic - Next topic

HotCoffee

I'm trying to change the tiles of the background by writing to the PPU.
I wrote this code to change the first rows of tiles to the character "5":

 
LoadBackground2:
  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             
LoadBackgroundLoop2:
  LDA #$05   
  STA $2007             ; write to PPU
  INC $01
  LDA $01
  CMP #$00             
  BNE LoadBackgroundLoop2


This is the background:
https://imgur.com/a/OkzdGO5

This is the background after the code gets executed:
https://imgur.com/a/J5QRewK

I used a debugger to see what was going on and apperently it starts writing the correct tile but after a while it starts writing randomly to the background.

nesrocks

#1
Not sure what the problem is yet, but your code is loading 0 into X for nothing. It could be more optimized:

  LDX #$00     
  LDA #$05           
LoadBackgroundLoop2:
  STA $2007             ; write to PPU
  INX              
  BNE LoadBackgroundLoop2


I just tested this code in my source file and it does fill 1/4 of the background screen with tile 5.

You should set breakpoints to writes to 2006 and to 2007 and step through to see what else is messing things up.

note: If you want to update background graphics without turning off the screen you probably want to do this during vblank only. So do this at the start of NMI and make sure you don't write too many tiles or else it's gonna keep writing tiles after vblank is over and you don't want that.
If you don't mind turning off the screen to update the background tiles then it's advised to do so.

To turn off rendering:

  ldx #0
  stx _PPUCTRL_2000  ; disables NMI
  stx _PPUMASK_2001  ; disables rendering


https://wiki.nesdev.com/w/index.php?title=PPU_registers

HotCoffee

I tried moving the code to the start of NMI and I got this:

https://imgur.com/a/JRJPQrb

However when I changed the code to:



  LDX #$00     
  LDA #$05           
LoadBackgroundLoop2:
  STA $2007             ; write to PPU
  INX
  CPX #$80 
  BNE LoadBackgroundLoop2



It drew the tiles correctly:

https://imgur.com/a/IXOFZop

(those things at the center are sprites, they have nothing to do with it)

How can I fill 1/4 of the background correctly?


Cyneprepou4uk

#3
You cannot write as much data as you want into PPU inside NMI. Vblank time is very limited. With your current loop you have time for around 200 bytes. More than that, and you might end up with garbage on the screen.

If you want to write more, either disable rendering, or write data separately on different frames.

You can also improve your loop by using DEX + BNE instead of INX + CPX + BNE.




By the way, if you have a write to 4014 somewhere in NMI (which I assume you do, since you have sprites on the screen), that single write takes away time worth of at least 45 bytes, which leaves you with 155. But with an improved loop you can still manage to write about 190.


Cyneprepou4uk

No, I don't. With BPL you can't set initial X > 80.

nesrocks

Then it is exactly the same as the code I posted, I guess. I thought you wanted to optimize his code for 128 tiles.

Cyneprepou4uk

Yeah, same thing basically. But personally I prefer this

LDX #$10
LDA #$00
@loop:
STA $2007
DEX
BNE @loop


Over this

LDX #$F0
LDA #$00
@loop:
STA $2007
INX
BNE @loop

HotCoffee

I managed to correctly change tiles in the background by writing on different frames, thank you for your replies