(4.5.x) How to fix graphical glitches after warping WITHOUT buffer screens?

5kids2feed

Well-known member
I’m working on a little side project right now (arcade platformer module) and the way you jump from room to room is with the standard warp script that comes with NESMaker. It works all fine and dandy but I notice when I play my game that when I warp sometimes (maybe 1 to 3 times per full game) it’ll randomly leave a little graphical glitch on the next screen. Like half of one tile will be black for “no reason”… even when jumping from standard 8x8 tiles..

I could ultimately leave this in there and say it’s the beauty of the NES.. but if I could fix it, I would like to.

What’s the best way to handle this WITHOUT buffer screens? I have many rooms and that would require a lot of buffer screens.. plus I tested buffer screens out and the glitch still happens.

Is there something I can put with the warp code, post screen load, etc to help this issue out?

ThanksI
 
Last edited:

kevintron

Active member
Same boat following....I'm making a game in the maze module also 4.5.9. I got buffers and still some glitching. Character sprite occasionally still garbled after warp and random tile glitches. On the buffer screens I also just completely blackout the sprite and hud no extra hide hud past the into screen and I never use hide spite just match the background.
 

dale_coop

Moderator
Staff member
The romdom tile glitch... is caused by the handle path scripts. If you use paths in you game, there no real fix (yet). If you don't use the path tiles... there is a workaround for those tile glitches (commenting out lines in the doloadnametabledata.asm I can find you the line of interested)
 

dale_coop

Moderator
Staff member
Try replacing your doLoadNametableData.asm (in "GameEngineData\Routines\BASE_4_5\Game\Subroutines\") with that one, you should have less tile glitches:

Code:
doLoadNametableData:
    ;;; currently, arg0_hold has the bank data
    ;;; arg1_hold has the screen index, if it is needed.
    ;;; arg2_hold has screen bits.
        ;;; bit 0 = overworld (0) underworld (1)
        ;;; bit 1 = metaTable (0) 8x8 table (1)
        ;arg0 = screen bank
    ;arg3_hold = columns to load
    ;arg4_hold = rows to load
    ;arg5_hold = start position hi
    ;arg6_hold = start position lo
    ;arg7_hold = start column   
    
    ;;; decreasing arg3_holder / arg4_holder will track if there are more columns/rows to load.  If zero, that part is done.
    LDA arg6_hold
    STA pointer
    LDA arg5_hold
    STA pointer+1
    
    LDA arg3_hold
    STA tempB ; we will use tempB to hold the number of columns
            ; so when we start a new row, we can return to the proper number of columns.
    ;;; now we can use the (pointer) to know the PPU address to write the nametable.
    ;;; whilte (temp16) denotes where the nametable data is being pulled from.

    SwitchBank arg0_hold;temp

        LDY arg7_hold ;;; in what column should the nametable begin?
        loop_LoadNametableMeta:
            bit $2002
            LDA pointer+1
            STA $2006
            LDA pointer
            STA $2006
            LDA (temp16),y
            STA temp
                ;;; now we have to do an evaluation, to compare this to potential "blank" values and paths.
            JSR doGetSingleMetaTileValues
            JSR doDrawSingleMetatile
        doneDrawingThisMetatile:
            INY
            DEC tempB ;; is a surrogate for columns
            LDA tempB
            BEQ doneWithMetaTileColumn
                LDA pointer
                CLC
                ADC #$02
                STA pointer
                JMP loop_LoadNametableMeta   
            doneWithMetaTileColumn:
                DEC arg4_hold
                LDA arg4_hold
                BEQ noMoreMetaTilesToLoad   
                    CMP #$08
                    BNE dontWaitFrame
                        JSR doWaitFrame
                    dontWaitFrame
                    LDA arg3_hold
                    STA tempB ;; resets the amount of columns.
                    ;;;;; calculate based on the number of columns drawn
                    ;;;;; where the "beginning of the column" should be,
                    ;;;;; and skip down to the next free line.
                    ASL
                    STA tempC ;
                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    LDA pointer
                    CLC
                    ADC #$02
                    SEC
                    SBC tempC
                    clc
                    adc #$40
                    STA pointer
                    LDA pointer+1
                    ADC #$00
                    STA pointer+1
                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    ;;; now, calculate where y should read from
                    ;;; based on the number of columns being drawn.
                    TYA
                    CLC
                    ADC #$10
                    SEC
                    SBC arg3_hold
                    TAY
                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    JMP loop_LoadNametableMeta
                                    
                    
        noMoreMetaTilesToLoad:
    
    ReturnBank
    RTS
    
    
    
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

doGetSingleMetaTileValues:
    STA temp
    
    LDA screenLoadTemps
    AND #%10000000
    BNE notPath
    LDA temp
;    CMP #BLANK_TILE ;; solid BLACK translate.
    CMP #$f5
    BEQ isBlankTile
    CMP #$FD
    BEQ isBlankTile ;isFDtile ;; solid "RED" translate
    CMP #$FE
    BEQ isBlankTile ;isFEtile ;; solid "GREEN" translate
    CMP #$FF
    BEQ isBlankTile ;isFFtile ;; solid "BLACK" translate
    JMP notBlankTile
isBlankTile:
    ;;; it was a blank tile.  They are all now blank tiles
    STA updateTile_00
    STA updateTile_01
    STA updateTile_02
    STA updateTile_03
    RTS
    
notBlankTile:

    ;;;; check for screen modes.
    LDA tileLayout
    CLC                ;; dale_coop
    CMP #%01000000
    BEQ checkForPathUpdates
    CMP #%01100000
    BEQ checkForPathUpdates1
    ;;;; THIS DOES NOT USE PATHS!!!
    ;;;; so just restore the temp value and proceed with metaTiles as if it wasn't a path value.
    LDA temp
    JMP notPath
    RTS
    
checkForPathUpdates1:
;;;;; THIS MODE USES ONLY THE FIRST TWO "paths" AS PATHS.
    LDA temp
    CLC            ;; dale_coop
    CMP #$A0
    BEQ doPathUpdate
    CMP #$B0
    BEQ doPathUpdate
    JMP notPath
    
checkForPathUpdates:
;;;;;; THIS MODE USES ALL FOUR "paths" AS PATHS.
    
    LDA temp
    CLC            ;; dale_coop
    CMP #$80
    BEQ doPathUpdate
    CMP #$90
    BEQ doPathUpdate
    CMP #$A0
    BEQ doPathUpdate
    CMP #$B0
    BEQ doPathUpdate
    JMP notPath
    
doPathUpdate:
    
    ;; now we have to do evaluations of other tiles around us to know
    ;; exactly what to draw here.
    JSR handlePath
    RTS
notPath:
    LDA temp            ;; dale_coop
    STA updateTile_00
    INC temp
    LDA temp
    STA updateTile_01
    ;;; now, what we need is a row down from our current position...updateNT_pointer
    ;;; and temp, increased to its next row.
    CLC
    ADC #$0f
    STA temp
    STA updateTile_02
    INC temp
    LDA temp
    STA updateTile_03
    RTS
    
doDrawSingleMetatile:
    bit $2002
    LDA pointer+1
    STA $2006
    LDA pointer
    STA $2006

    LDA updateTile_00
    STA $2007  ;write 1
    LDA updateTile_01
    STA $2007 ;; write 2

    ;;; now, what we need is a row down from our current position...pointer
    ;;; and temp, increased to its next row.
    bit $2002
    LDA pointer+1
    STA $2006
    
    LDA pointer
    CLC
    ADC #$20 ;; dont store it into pointer
            ;; because then it will be easy to just add 2 to
            ;; for the next place to write.
    STA $2006

    ;; now get the tile
    LDA updateTile_02
    STA $2007 ; write 3
    LDA updateTile_03
    STA $2007 ; write 4
    RTS
    
    
    
    
    
    
    
    
    
    
    
    
    
    
handlePath:
    TXA
    PHA
    TYA
    PHA

    .include SCR_HANDLE_PATHS

    
    PLA
    TAY
    PLA
    TAX
    
    RTS

(Can't promise if will fix every glitch, but sure reduce them)
 

dale_coop

Moderator
Staff member
This script should work with paths, too.
just a few minors modifications (cf my "dale_coop" comments in the script)
 

kevintron

Active member
Awesome! If understand right I just need to use the 2 path part since that's all I have loaded. Then I comment out the part about 4 paths and the part in non blank title 4 paths. Then I only need the one CheckForPathUpdate and just rename the 2 path to that.
Thankyou again!
 

vufka

New member
Hi all. This thread is referenced a lot and I do believe it is very useful. But I wanted to chime in with something I noticed in my current game. I don't know what exactly triggers the issue but I believe it is this: if you are switching your first (universal) palette colour between warps and (maybe) using the LR platform module, you may still experience graphical glitches after a warp. They look like the wrong tiles are loaded for your Player but moving corrects them. I have implemented the fix above and still experience this. My fix, for now, is to avoid causing the issue in the first place - I was getting it between cut scenes and gameplay, so I make sure my final cutscene has the same first colour in the palette as the screen being warped to.
 

mouse spirit

Well-known member
Hi all. This thread is referenced a lot and I do believe it is very useful. But I wanted to chime in with something I noticed in my current game. I don't know what exactly triggers the issue but I believe it is this: if you are switching your first (universal) palette colour between warps and (maybe) using the LR platform module, you may still experience graphical glitches after a warp. They look like the wrong tiles are loaded for your Player but moving corrects them. I have implemented the fix above and still experience this. My fix, for now, is to avoid causing the issue in the first place - I was getting it between cut scenes and gameplay, so I make sure my final cutscene has the same first colour in the palette as the screen being warped to.
Is it messing up the graphics ,or just the colors? If it's the colors,maybe reset to the correct pallettes at the start of a screen.
Also maybe put some more buffers (wait frames,not buffer screens) in there. They are only each for fractions of a second I think.
 
Top Bottom