More issues changing background tiles

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

More issues changing background tiles

Post by battagline »

So I'm trying to create an asteroid out of background tiles and I'm running into issues where garbage is showing up in my background under certain conditions.

If I write 4 or 5 tiles to the background everything is fine. I am trying to copy over 4 entire rows of tiles starting with the top left corner of my large asteroid. (this isn't meant to be a long term solution, just a test)

Code: Select all

    lda PPU_STATUS        ; PPU_STATUS = $2002
    lda #$21

    sta PPU_ADDR          ; PPU_ADDR = $2006
    lda #$08
    sta PPU_ADDR          ; PPU_ADDR = $2006

    @render_loop:
        lda asteroid_background,x ;#LARGE_ASTEROID_SPRITE_START
        sta PPU_DATA    

        inx
        cpx #40   ; I've been playing with this number
    bne @render_loop
If I tweak the cpx at the bottom to have #4 or #5 in it, the copy works fine. If I have #40 or #50 I get garbage all over the background.

I also tried something roughly like this (killed the code so this isn't exactly what I was testing).

Code: Select all

    lda PPU_STATUS        ; PPU_STATUS = $2002
    lda #$21

    sta PPU_ADDR          ; PPU_ADDR = $2006
    lda #$08
    sta PPU_ADDR          ; PPU_ADDR = $2006

    @render_loop:
        lda asteroid_background,x ;#LARGE_ASTEROID_SPRITE_START
        sta PPU_DATA    

        inx
        cpx #4
    bne @render_loop


    lda PPU_STATUS        ; PPU_STATUS = $2002
    lda #$21

    sta PPU_ADDR          ; PPU_ADDR = $2006
    lda #$28
    sta PPU_ADDR          ; PPU_ADDR = $2006

    @render_loop_2:
        lda asteroid_background,x ;#LARGE_ASTEROID_SPRITE_START
        sta PPU_DATA    

        inx
        cpx #4  
    bne @render_loop_2


This also gives me garbage in my background.

Do I have too much code in my nmi? Or am I fundamentally doing this the wrong way?

Thanks
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: More issues changing background tiles

Post by koitsu »

Two immediate causes I can think of:

1. Exhausted available time in NMI -- Mesen makes figuring this out quite a bit easier than others; Lua scripts may be involved, otherwise breakpoints and staring at CPU cycle counters in the emulator
2. Nuances related to https://wiki.nesdev.com/w/index.php/PPU_scrolling -- this page will probably destroy your soul, but it matters tremendously WRT $2000 / $2002 / $2005 / $2006.

What I've said here probably does not help you at all, so I'm questioning even clicking Submit at this point.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Re: More issues changing background tiles

Post by Kasumi »

You have about 2270 cycles after the NMI happens to safely write things to $2007 (PPU_DATA ) (and $4014 for the sprite DMA).

I realize you've said this isn't your exact code. But I notice it doesn't initialize X. If X was already 40 before you started, one of the loops would run 256 times.

Another weird thing is you're saying you want to write four rows of tiles, but a row is only 32 tiles long, not 40 which might be part of the problem. (The screen is 256 pixels across. Divide that by 8 to get 32.)

Looking at the loop:

Code: Select all

@render_loop:
        lda asteroid_background,x ;4 cycles
        sta PPU_DATA;4 cycles   

        inx;2 cycles
        cpx #40;2 cycles
        bne @render_loop;3 cycles (for all but one loop)
So 15 cycles for 39 of these loops, 14 cycles for one of them. That's only 599 cycles. But if you do it four times, that's 2396 cycles. You'd be over time. Also remember that sprite DMA takes 513ish cycles. So if you copied and pasted the above loop 4 times, and sprite DMA'd you'd be at 2909 cycles. Way over.

So
1. Make sure you're initializing X before each loop starts.
2. Rows are 32 tiles not 40.
3. Even with 32 tile rows, loops like this will be too slow to do 4 loops with a DMA.

You can unroll your loops. (You always know you'll be writing 32 tiles, so:

Code: Select all

ldx #0
lda asteroid_background,x ;4 cycles
sta PPU_DATA ;1 write
inx
lda asteroid_background,x ;4 cycles
sta PPU_DATA ;2 writes
inx
lda asteroid_background,x ;4 cycles
sta PPU_DATA ;3 writes
;etc
Which is only 10 cycles per byte rather than 15. That's 320 cycles per row. 4 times is 1280 cycles. + 513 (sprite DMA) is 1793 cycles.

Doing 4 rows in a single NMI is usually pretty tight without doing some trickier things, though. Because writing rows/sprite DMA is not all the logic it will end up containing.

edit: Actually, it's worth noting you can't cpx the same number if you copy and paste multiple row loops.
If you have this:

Code: Select all

@render_loop:
        lda asteroid_background,x ;#LARGE_ASTEROID_SPRITE_START
        sta PPU_DATA   

        inx
        cpx #4
    bne @render_loop
X is 4 at the bottom.
if you then do this (without changing X)

Code: Select all

 @render_loop_2:
        lda asteroid_background,x ;#LARGE_ASTEROID_SPRITE_START
        sta PPU_DATA   

        inx
        cpx #4 
    bne @render_loop_2
X starts at 4. So the loop with run 256 times. But if you do a ldx #0 beforehand, it will just load the same data.

But there's very little reason to have two loops if you're writing contiguous rows.

Just change the cpx to change the number of bytes.

Code: Select all

        ldx #0
@render_loop:
        lda asteroid_background,x ;#LARGE_ASTEROID_SPRITE_START
        sta PPU_DATA   

        inx
        cpx #64;Just change this number
    bne @render_loop
Edit: Changed 256 tiles across to 256 pixels.
Last edited by Kasumi on Fri Oct 19, 2018 10:29 am, edited 1 time in total.
User avatar
battagline
Posts: 152
Joined: Wed Sep 05, 2018 11:13 am
Location: Colorado
Contact:

Re: More issues changing background tiles

Post by battagline »

Thanks guys. I broke it up so that it rendered a little bit at a time over several frames and it seems to be working(ish) now. Still having issues, but at least they are different issues.

Thanks again
A few of my web games
https://www.embed.com
Or if you're bored at work
https://www.classicsolitaire.com
Post Reply