Page 1 of 1

Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 1:15 am
by Eisetley
I'm working on a simple, non-scrolling, NROM game that will have just a few screens and I'm trying to figure out a decent way to load a background. I RLE'd the title screen using just notepad and now I'm trying to load it, but the whole screen is blue.
Screen data (left value is tile number, right is the amount):

Code: Select all

titlescrn:
	.db $24,$8c
        .db $c3,$01
        .db $c4,$01
        .db $c5,$01
        .db $c6,$01
        .db $c7,$01
        .db $c8,$01
        .db $c9,$01
        .db $ca,$01
        .db $cb,$01
        .db $24,$17
        .db $d3,$01
        .db $d4,$01
        .db $d5,$01
        .db $d6,$01
        .db $d7,$01
        .db $d8,$01
        .db $d9,$01
        .db $da,$01
        .db $db,$01
        .db $24,$14
        .db $e0,$01
        .db $e1,$01
        .db $e2,$01
        .db $e3,$01
        .db $e4,$01
        .db $e5,$01
        .db $e6,$01
        .db $e7,$01
        .db $e8,$01
        .db $e9,$01
        .db $ea,$01
        .db $eb,$01
        .db $ec,$01
        .db $ed,$01
        .db $ee,$01
        .db $ef,$01
        .db $24,$10
        .db $f0,$01
        .db $f1,$01
        .db $f2,$01
        .db $f3,$01
        .db $f4,$01
        .db $f5,$01
        .db $f6,$01
        .db $f7,$01
        .db $f8,$01
        .db $f9,$01
        .db $fa,$01
        .db $fb,$01
        .db $fc,$01
        .db $fd,$01
        .db $fe,$01
        .db $ff,$01
        .db $24,$d2
        .db $01,$01
        .db $19,$01
        .db $15,$01
        .db $0a,$01
        .db $22,$01
        .db $0e,$01
        .db $1b,$01
        .db $24,$19
        .db $02,$01
        .db $19,$01
        .db $15,$01
        .db $0a,$01
        .db $22,$01
        .db $0e,$01
        .db $1b,$01
        .db $1c,$01
        .db $24,$FF
        .db $24,$4E
        .db $0a,$01
        .db $15,$01
        .db $19,$01
        .db $11,$01
        .db $0a,$01
        .db $24,$01
        .db $18,$01
        .db $18,$01
        .db $24,$47
        ;;;attr
        .db $00,$0A
        .db $50,$01
        .db $55,$01
        .db $55,$01
        .db $51,$01
        .db $10,$01
        .db $00,$0B
        .db $40,$01
        .db $50,$02
        .db $00,$23
        .db $25 ;$25 = end of room

Code: Select all

backgrounds_lo: .dl titlescrn
backgrounds_hi: .dh titlescrn
Loading code:

Code: Select all

LoadBackground:
;Turn off NMI and rendering
   LDA #%00000000
   STA PPU_CtrlA
   STA PPU_CtrlB
   LDA PPU_CtrlB ;reading $2002 clears write pair for $2005/2006


   LDA #$20
   STA PPU_Addr
   LDA #$00
   STA PPU_Addr

   LDX BackgroundToLoad
   LDA backgrounds_lo, x
   STA BackgroundAddress
   LDA backgrounds_hi, x
   STA BackgroundAddress + 1
   LDY #$00
LoadBackgroundLoopA:
   LDA (BackgroundAddress), y
   CMP #$25
   BEQ LoadBackgroundLoopEnd
   INY
   LDX (BackgroundAddress), y
LoadBackgroundLoopB:
   STA PPU_Write
   DEX
   BNE LoadBackgroundLoopB
   INY
   JMP LoadBackgroundLoopA

LoadBackgroundLoopEnd:

 ;Reset Scroll
   LDA #$00
   STA PPU_Scroll
   STA PPU_Scroll
   INC BackgroundLoadingStatus
RTS
Another thing is updating a certain part of the background. Should I just decompress all the background data into ram first instead of running the code above, and then load a whole background every time a change is made?

Re: Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 3:34 am
by dougeff
LDX (BackgroundAddress), y

This isn't a valid indirect mode (only LDA can do indirect modes). This should give an error when trying to assemble...

What assembler are you using?

Re: Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 3:41 am
by Eisetley
ASM6
Should I use LDA (BackgroundAddress), y->TAX?

Re: Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 3:51 am
by dougeff
Probably yes.

If that doesn't work, open the file in an emulator with a debugger. Make sure the correct values are loading to the PPU.

Re: Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 5:52 am
by Sumez
Eisetley wrote:ASM6
Should I use LDA (BackgroundAddress), y->TAX?
Just remember to move it up before your "actual" LDA, to preserve the A register :)

Re: Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 6:24 am
by Eisetley
Sure, it works now. Turns out LDA (address) + something doesn't work either, so I had to manipulate Y.

Code: Select all

LoadBackgroundLoopA:
   INY
   LDA (BackgroundAddress), y
   TAX
   DEY
   LDA (BackgroundAddress), y
   CMP #$25
   BEQ LoadBackgroundLoopEnd
LoadBackgroundLoopB:
   STA PPU_Write
   DEX
   BNE LoadBackgroundLoopB
   INY
   INY
   JMP LoadBackgroundLoopA
Still, I don't know how to do updates on a chosen tile, first decompress whole screen somewhere in ram and load whole 1024 bytes of background + attributes every time I want to change something (even if it's only a single tile)?

Re: Uncompressing background, updating individual BG tiles.

Posted: Tue Aug 07, 2018 8:26 am
by tokumaru
Eisetley wrote:Turns out LDA (address) + something doesn't work either, so I had to manipulate Y.
Yup. LDA Absolute+Offset works because the address is calculated at assembly time, but with indirect addressing the address is calculated at run time, so you're limited by what the CPU can do.
Still, I don't know how to do updates on a chosen tile, first decompress whole screen somewhere in ram and load whole 1024 bytes of background + attributes every time I want to change something (even if it's only a single tile)?
It's definitely possible to update any number of bytes you want, just not from an RLE stream, since those don't typically allow for random access. If you want to read partial chunks off of an RLE stream, you'll need to break the stream in smaller pieces and create a list of pointers to the individual pieces.

Anyway, once you do know where to read the data from, you can calculate the target name table address using the following formula: Base OR (Y * 32) OR X.

Something like this should work for calculating the Target address dynamically at run time:

Code: Select all

  lda TileY
  asl
  asl
  asl
  asl
  rol TargetAddress+1
  asl
  rol TargetAddress+1
  ora TileX
  sta TargetAddress+0
  lda TargetAddress+1
  and #%00000011
  ora Base
  sta TargetAddress+1
TileX and TileY are 5-bit values (0 to 31) and Base is one of $20, $24, $28 or $2C, depending on which name table you're targeting. Then you can just write TargetAddress to register $2006 and set its value as the starting point for the transfer, instead of always starting from $2000.