palette corruption workaround documentation
This commit is contained in:
parent
547a7932aa
commit
2f5f1faa3f
|
@ -322,7 +322,7 @@ decay that OAM has.
|
|||
|
||||
## Sprite Number Encoding
|
||||
The sprite data in bank 1 is encoded. Except when #$fe, the first byte
|
||||
specifies the number of entries in the sprite. There there are that many groups
|
||||
specifies the number of entries in the sprite. Then there are that many groups
|
||||
of 4-bytes. Each #$4 bytes specify two tiles that are stacked vertically.
|
||||
Except when the first byte is #$80, these four bytes follow the PPU OAM byte
|
||||
specification. For details on this data structure,
|
||||
|
|
|
@ -1833,7 +1833,7 @@ sniper_attack_delay_tbl:
|
|||
; #$01 - number of bullets to shoot per attack - hiding rifle man
|
||||
; #$03 - number of bullets to shoot per attack - boss screen rifle man
|
||||
sniper_bullet_attack_count_tbl:
|
||||
.byte $03, $01,$03
|
||||
.byte $03,$01,$03
|
||||
|
||||
; rifle man - pointer 3
|
||||
sniper_routine_02:
|
||||
|
|
|
@ -177,7 +177,7 @@ handle_sound_slots:
|
|||
; * y - channel register offset, e.g. #$00 (pulse 1 channel), #$04 (pulse 2 channel), #$08 (triangle channel), #$0c (noise/dmc channel)
|
||||
@sound_slot_loop:
|
||||
stx SOUND_CURRENT_SLOT ; set the current sound slot to the current loop index
|
||||
sty SOUND_CHNL_REG_OFFSET ; set sound channel config register offset (#$00, #$04, $08, or #$0c)
|
||||
sty SOUND_CHNL_REG_OFFSET ; set sound channel config register offset (#$00, #$04, #$08, or #$0c)
|
||||
lda SOUND_CODE,x ; load sound code for sound slot
|
||||
beq @prep_next_loop ; prep to move to next sound slot, or exit if looped through all slots
|
||||
tay ; sound slot has a sound code, transfer sound code to offset register y
|
||||
|
@ -434,7 +434,7 @@ read_low_sound_cmd:
|
|||
pulse_sustain_note:
|
||||
tya ; transfer sound code read offset (#$00) to a
|
||||
pha ; backup y to the stack
|
||||
ldy SOUND_CHNL_REG_OFFSET ; load sound channel config register offset (#$00, #$04, $08, or #$0c)
|
||||
ldy SOUND_CHNL_REG_OFFSET ; load sound channel config register offset (#$00, #$04, #$08, or #$0c)
|
||||
sec ; set carry flag in preparation for subtraction
|
||||
sbc VIBRATO_DELAY,x ; negate vibrato duration (or #$100 - vibrato duration)
|
||||
; y - VIBRATO_DELAY,x --> #$00 - VIBRATO_DELAY,x
|
||||
|
@ -1266,7 +1266,7 @@ ldx_pulse_triangle_reg:
|
|||
; exit with x set to SOUND_CHNL_REG_OFFSET and the carry clear
|
||||
@clc_exit:
|
||||
clc ; clear carry to signal to update sound register
|
||||
ldx SOUND_CHNL_REG_OFFSET ; load sound channel config register offset (#$00, #$04, $08, or #$0c)
|
||||
ldx SOUND_CHNL_REG_OFFSET ; load sound channel config register offset (#$00, #$04, #$08, or #$0c)
|
||||
pla ; restore a from stack
|
||||
rts
|
||||
|
||||
|
@ -1332,7 +1332,7 @@ init_pulse_channel:
|
|||
tax
|
||||
lda SOUND_CODE,x
|
||||
beq sound_code_00 ; branch if sound code is #$00
|
||||
ldy SOUND_CHNL_REG_OFFSET ; load sound channel config register offset (#$00, #$04, $08, or #$0c)
|
||||
ldy SOUND_CHNL_REG_OFFSET ; load sound channel config register offset (#$00, #$04, #$08, or #$0c)
|
||||
jsr mute_unmute_pulse_channel ; mutes/unmutes pulse wave channel based on pause state
|
||||
ldx SOUND_CURRENT_SLOT ; load current sound slot
|
||||
rts
|
||||
|
@ -1484,8 +1484,8 @@ bank_1_unused_label_00:
|
|||
stx $e6
|
||||
lda $010a
|
||||
beq @pop_and_exit
|
||||
stx $010a ; set sound channel config register offset (#$00, #$04, $08, or #$0c)
|
||||
stx SOUND_CHNL_REG_OFFSET ; set sound channel config register offset (#$00, #$04, $08, or #$0c)
|
||||
stx $010a ; set sound channel config register offset (#$00, #$04, #$08, or #$0c)
|
||||
stx SOUND_CHNL_REG_OFFSET ; set sound channel config register offset (#$00, #$04, #$08, or #$0c)
|
||||
jsr init_pulse_channel
|
||||
|
||||
@pop_and_exit:
|
||||
|
|
|
@ -456,7 +456,7 @@ game_end_routine_04:
|
|||
beq load_credits_line_text ; always branch to draw blank line of tiles (ending_credits_00)
|
||||
|
||||
@draw_next_line:
|
||||
lda $42 ; load line credits text offset (initialized to 0 in level_routine_05 clear_memory_starting_a_x)
|
||||
lda $42 ; load line credits text offset (initialized to 0 in level_routine_05 clear_memory_starting_at_x)
|
||||
inc $42 ; increment credits line offset
|
||||
asl ; double since each entry is #$02 bytes
|
||||
tay
|
||||
|
|
|
@ -1187,13 +1187,14 @@ player_mode_1d_table:
|
|||
p2_game_over_status_tbl:
|
||||
.byte $01,$00
|
||||
|
||||
; clear memory addresses $0028 to $00f0 then CPU_SPRITE_BUFFER up to CPU_GRAPHICS_BUFFER
|
||||
; clear memory addresses $0028 to $00f0 then CPU_SPRITE_BUFFER up to CPU_GRAPHICS_BUFFER (not including) [$300-$700)
|
||||
clear_memory_3:
|
||||
ldx #$28
|
||||
|
||||
; clear x to #$f0 bytes
|
||||
; then clear CPU_SPRITE_BUFFER ($300) up to CPU_GRAPHICS_BUFFER ($700)
|
||||
clear_memory_starting_a_x:
|
||||
; clears memory [x-$f0) and [$300-$700]
|
||||
; input
|
||||
; * x - starting memory address to clear (inclusive)
|
||||
clear_memory_starting_at_x:
|
||||
lda #$00
|
||||
|
||||
@loop:
|
||||
|
@ -2653,13 +2654,14 @@ write_cpu_graphics_buffer_to_ppu:
|
|||
|
||||
@read_cpu_mem_to_ppu:
|
||||
lda $08 ; read previous high byte of PPU write address
|
||||
cmp #$3f ; compare $08 to #$3f
|
||||
bne @continue ; skip ahead if $08 is not equal to #$3f
|
||||
sta PPUADDR ; !(WHY?) the following code doesn't make sense to me
|
||||
lda #$00 ; it sets the PPUADDR to #$3f00, then #$0000
|
||||
sta PPUADDR ; but this is overwritten in the next few lines
|
||||
sta PPUADDR ; that would have been executed regardless of what $08 was
|
||||
sta PPUADDR ; this code seems to be able to be removed without issue !(WHY?)
|
||||
cmp #$3f ; compare $08 to #$3f (seeing if palette write)
|
||||
bne @continue ; skip ahead if $08 is not equal to #$3f (not writing palette)
|
||||
sta PPUADDR ; !(OBS) I think this is attempting to prevent the NTSC NES palette corruption bug
|
||||
lda #$00 ; the palette can get corrupted after writes to it
|
||||
; the workaround is to update the PPUADDR twice after writing to palette memory
|
||||
sta PPUADDR ; ref: https://www.nesdev.org/wiki/PPU_registers#Address_($2006)_%3E%3E_write_x2
|
||||
sta PPUADDR ; (1) set PPUADDR to $3f00, then (2) set PPUADDR outside palette memory (in this case $0000)
|
||||
sta PPUADDR ; these steps prevent palette corruption
|
||||
|
||||
; CPU address $cbe5
|
||||
@continue:
|
||||
|
@ -2787,10 +2789,12 @@ write_palette_colors_to_ppu:
|
|||
dex
|
||||
bne @loop
|
||||
lda #$3f
|
||||
sta PPUADDR ; set ppu write address to $3f00
|
||||
stx PPUADDR ; store low byte of $3f00
|
||||
stx PPUADDR ; be sure it wrote correctly
|
||||
stx PPUADDR ; be sure it wrote correctly
|
||||
sta PPUADDR ; !(OBS) I think this is attempting to prevent the NTSC NES palette corruption bug
|
||||
stx PPUADDR ; the palette can get corrupted after writes to it
|
||||
; the workaround is to update the PPUADDR twice after writing to palette memory
|
||||
; ref: https://www.nesdev.org/wiki/PPU_registers#Address_($2006)_%3E%3E_write_x2
|
||||
stx PPUADDR ; (1) set PPUADDR to $3f00, then (2) set PPUADDR outside palette memory (in this case $0000)
|
||||
stx PPUADDR ; these steps prevent palette corruption after writing to the palette memory
|
||||
stx NUM_PALETTES_TO_LOAD ; set number of palettes to load to #$3f
|
||||
; don't think this value is ever read when it's #$3f, overwritten later
|
||||
|
||||
|
@ -3231,7 +3235,7 @@ level_routine_05:
|
|||
lda P2_CURRENT_WEAPON ; current weapon code (player 2)
|
||||
sta $11 ; temporarily store current weapon in $11
|
||||
ldx #$40 ; x = #$40 (set to 30 for game over after lvl 1)
|
||||
jsr clear_memory_starting_a_x ; clear level header data, player data, sprite buffer, and super-tile buffer
|
||||
jsr clear_memory_starting_at_x ; clear level header data, player data, sprite buffer, and super-tile buffer (memory [$40-$f0) and [$300-$700])
|
||||
lda BOSS_DEFEATED_FLAG ; 0 = boss not defeated, 1 = boss defeated
|
||||
beq show_game_over_screen ; in level_routine_05 and boss wasn't defeated, game over
|
||||
; unless demo mode (shouldn't happen because demos don't reach end of level), then just set DEMO_LEVEL_END_FLAG and exit
|
||||
|
|
Loading…
Reference in New Issue