Hey all, I've just been working on my first small project for a couple of weeks, following along with some tutorials for the basics, but have come up against what I imagine to be an issue for a fairly basic thing, and just can't work out what's wrong. Hoping that maybe some experts here could point me in the right direction.
I'm trying to create a simple background looping system which can dynamically load backgrounds into the PPU. I just have a single background at the moment, and have the game scrolling horizontally, loading in each column from the background data one by one as the horizontal scroll reaches it. The dynamic loading of columns works fine, after much work, but I still need to load in the initial background when the game starts. I tried to build a simple procedure which reuses my column loading procedure, simply looping through it 32 times (for 32 columns) before the PPU is then enabled.
When I implement this though, it seems to break everything, even the aforementioned column loading loop contained in my NMI handler. All I can seem to work out based on the FCEUX debugger is that the palette data seemingly gets overwritten, implying that my writes to the PPU are hitting addresses that they're not supposed to. I can't work out why though, as the initial background loading is using mostly the same code as the subsequent writes. Plus it seems to even break the column loop itself during NMI handling. I feel that it must be something simple, like I'm not setting the PPU up properly during the initial load, or misunderstanding what's actually happening under the hood. If anyone could take a look at my code and see if they notice what's wrong about the 'LoadBackground' procedure which would be breaking everything else, it would really help me out, as I've been at this for days now with no progress.
I've attached what I believe to be the relevant pieces of code (not every procedure). I've also left a comment in the code against a particular line in the 'LoadBackground' procedure which I've identified as the culprit that actually breaks everything; if I comment that line the background still doesn't load, but it doesn't break the rest of my game loop.
(I've also attached the full project, if needed)
I'm trying to create a simple background looping system which can dynamically load backgrounds into the PPU. I just have a single background at the moment, and have the game scrolling horizontally, loading in each column from the background data one by one as the horizontal scroll reaches it. The dynamic loading of columns works fine, after much work, but I still need to load in the initial background when the game starts. I tried to build a simple procedure which reuses my column loading procedure, simply looping through it 32 times (for 32 columns) before the PPU is then enabled.
When I implement this though, it seems to break everything, even the aforementioned column loading loop contained in my NMI handler. All I can seem to work out based on the FCEUX debugger is that the palette data seemingly gets overwritten, implying that my writes to the PPU are hitting addresses that they're not supposed to. I can't work out why though, as the initial background loading is using mostly the same code as the subsequent writes. Plus it seems to even break the column loop itself during NMI handling. I feel that it must be something simple, like I'm not setting the PPU up properly during the initial load, or misunderstanding what's actually happening under the hood. If anyone could take a look at my code and see if they notice what's wrong about the 'LoadBackground' procedure which would be breaking everything else, it would really help me out, as I've been at this for days now with no progress.
I've attached what I believe to be the relevant pieces of code (not every procedure). I've also left a comment in the code against a particular line in the 'LoadBackground' procedure which I've identified as the culprit that actually breaks everything; if I comment that line the background still doesn't load, but it doesn't break the rest of my game loop.
(I've also attached the full project, if needed)
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Procedure to Load Background Data into PPU Nametable;; - Loop through and draw 32 columns of tiles;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.proc LoadBackground lda #<BackgroundData sta SourceAddr ; lo-byte of source address to background data lo-byte lda #>BackgroundData sta SourceAddr+1 ; hi-byte of source address to background data hi-byte bit PPU_STATUS lda #$20 sta NewColAddr+1 ; hi-byte of PPU Address to $20 (first nametable) lda #$00 sta NewColAddr ; lo-byte of PPU Address to $00LoopBackgroundColumn: jsr DrawNewColumn ; draw a new column ;inc NewColAddr ; update PPU Address lo-byte to next column ; <- CURRENTLY BREAKS GAME PALETTE AND SUBSEQUENT COLUMN LOADING WHEN ENABLED lda Column cmp #0 ; if current column is 0 (wrapped around from 32) bne LoopBackgroundColumn ; Else: continue looping rts.endproc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reset Handler;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Reset: INIT_NESInitVariables: lda #0 sta Frame sta Clock60 ldx #0 lda SpriteData,x ; get Sprite Data at index 0 (y-position) sta YPos+1 ; store Sprite Data y-position in YPos pixels ldx #3 lda SpriteData,x ; get Sprite Data at index 3 (x-position) sta XPos+1 ; store Sprite Data x-position in XPos pixels lda #0 sta XScroll+1 sta XScroll sta Row sta Column lda #1 sta NewColumn ; setup to draw new column immediatelyMain: jsr LoadPalette ; load Palette Data jsr LoadSprites ; load Sprites lda #%00010100 ; disable NMI, Set Background to second Pattern Table sta PPU_CTRL jsr LoadBackground ; load initial Background DataEnablePPURendering: bit PPU_STATUS lda #%10010100 ; Enable NMI, Set Background to second Pattern Table sta PPU_CTRL lda #0 sta PPU_SCROLL sta PPU_SCROLL lda #%00011110 sta PPU_MASK ; Set PPU_MASK bits to show backgroundLoopForever: jmp LoopForever;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; NMI Handler;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;NMI: lda #$00 ; disable rendering sta PPU_MASKNewColumnCheck: lda NewColumn cmp #1 ; if new column flag set bne FinishColumn jsr DrawNewColumn ; If it is, proceed to draw a new column of tilesFinishColumn: jsr ScrollBackground jsr RefreshRendering jsr SetColumnAddresses rti;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Routine to draw a new column of tiles off-screen as we scroll horizontally;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;.proc DrawNewColumn PPU_SETADDR_VALUE NewColAddr ldx #$04 ldy ColumnColumnLoop: PPU_SETDATA_OFFSET (SourceAddr),y inc Row ; increment current row lda #30 cmp Row ; is current row last row beq FinishColumn ; Then: finish loop tya clc adc #32 ; add 32 to y-offset, to next row tay bcc ColumnLoop ; if y not exceed 256 and set Carry, continue loopNextBatch: inc SourceAddr+1 ; increment hi-byte of source, to next batch ldy Column ; reset y offset jmp ColumnLoop ; restart draw loopFinishColumn: lda Column clc adc #1 ; increment current column and #%00011111 ; drop left-most bit to clamp value to 32, wrap around to 0 sta Column rts.endproc
Statistics: Posted by EpicFlan — Tue Oct 29, 2024 4:44 pm — Replies 2 — Views 70