Adding Attributes Causes Background to Shift

A place for your artistic side. Discuss techniques and tools for pixel art on the NES, GBC, or similar platforms.
Tompis1995
Posts: 34
Joined: Fri Feb 22, 2019 10:05 am

Adding Attributes Causes Background to Shift

Post by Tompis1995 »

The next step to my Press Your Luck simulation is to add "background colors" to each square. However, whenever I try to assign the attributes to the PPU register, this happens in the picture shown. What's up with that?
You do not have the required permissions to view the files attached to this post.
Tompis1995
Posts: 34
Joined: Fri Feb 22, 2019 10:05 am

Re: Adding Attributes Causes Background to Shift

Post by Tompis1995 »

and here's the code for reference:

Code: Select all

input_control:
.include "controller.s"

boardSound:
	.include "PYL_Board_Sound.s"
	
palettePointer:
	.res 1
	
board7attributes:
	.include "pyl_board7_attributes.s"

.segment "RODATA"
	Palette:
		.byte $0f,$16,$12,$30,$0f,$16,$06,$20,$0f,$16,$28,$20,$0f,$16,$2a,$20
		.byte $0f,$16,$12,$30,$0f,$16,$06,$20,$0f,$16,$28,$20,$0f,$16,$2a,$20
		
ReferenceSquareY:		;Reference Square is the top right square
	.byte $0d,$0d,$0d,$0d,$0d,$0d,$15,$1d,$25,$2d,$35,$35,$35,$35,$35,$35
	.byte $2d,$25,$1d,$15
ReferenceSquareX:
	.byte $08,$10,$18,$20,$28,$30,$30,$30,$30,$30,$30,$28,$20,$18,$10,$08
	.byte $08,$08,$08,$08
SquareTileOrder:
	.byte $7C,$80,$80,$80,$80,$78,$79,$79,$79,$79,$75,$77,$77,$77,$77,$76
	.byte $7E,$7E,$7E,$7E
PredefinedPattern:
	.byte $03,$10,$0d,$0a,$12,$08,$06,$0e,$07,$05,$0f,$0b,$11,$02,$0c
	.byte $01,$09,$04,$05,$12,$0b,$0d,$03,$06,$0f,$07,$01,$09,$0e,$10 
	.byte $0a,$02,$04,$0c,$11,$08,$0b,$06,$0a,$0c,$01,$04,$0e,$10,$02 
	.byte $09,$11,$08,$0d,$0f,$03,$07,$12,$05,$11,$0a,$0f,$0d,$02,$08 
	.byte $12,$10,$0c,$03,$05,$0b,$07,$04,$01,$09,$0e,$06,$12,$10,$08 
	.byte $05,$0b,$09,$02,$0d,$11,$07,$04,$0f,$0c,$08,$06,$03,$01,$0e
	

	
	;Milestone reached: ALWAYS put screen data LAST in RODATA to avoid interference with the PPU from other data.
	
boardScreens:
	.include "pyl_board7.s"
	.include "pyl_board8.s"
	.include "pyl_board9.s"

.segment "HEADER"
	.byte "NES"
	.byte $1a
	.byte $02
	.byte $01
	.byte %00000000
	.byte $00
	.byte $00
	.byte $00
	.byte $00
	.byte $00, $00, $00, $00, $00
	
.segment "STARTUP"

.segment "ZEROPAGE"	
	
	UpperRow:
	.res 1
	
	BottomRow:
	.res 1
	
	RightColumn:
	.res 1
	
	LeftColumn:
	.res 1
	
	TopLeftCorner:	; Top left corner of the ring of lights
	.res 1
	
	TopRightCorner:	; Top right corner of the ring of lights
	.res 1
	
	BottomLeftCorner:
	.res 1
	
	BottomRightCorner:
	.res 1

	SDCC:	; SDCC = Square Drawing Cycle Counter
	.res 1
	
	SOX:	; SOX = Square Offset X
	.res 1
	
	SOY:	; SOY = Square Offset Y
	.res 1
	
	timer:	; amount of time before the next screen becomes lit
	.res 1
	
	patternCounter:	; amount of bytes from the beginning of the pre-defined spin pattern
	.res 1
	
	chosenSquare:		; uniquely identifies each space on the board by number
	.res 1
	
	screen_switcher:	; changes the prizes and dollar amounts on every space
	.res 1
	
	board_hits:			; counts how many times the ring of lights have changed position since the last screen switch
	.res 1
	
	stopped:
	.res 1
	
	stopWhammySound:
	.res 1
	
	blink_delay:
	.res 1
	
	number_of_blinks:
	.res 1
	
	big_bucks_flag:
	.res 1
	
	whammy_sound_counter:
	.res 1
	
	bgPointer:
	.res 1
	
.segment "CODE"
	WaitForVBlank:		; Don't do anything until the screen finishes drawing.
	:
		BIT $2002
		BPL :-
		RTS
	
	Restart:		; Clear all data from RAM
		SEI
		CLD
		LDX #$40
		STX $4017
		LDX #$FF
		TXS
		INX
		STX $2000
		STX $2001
		STX $4010
		JSR WaitForVBlank
		
	ClearMemory:
		LDA #$00
		STA $0000, x
		STA $0100, x
		STA $0200, x
		STA $0400, x
		STA $0500, x
		STA $0600, x
		STA $0700, x
		STA $0300, x
		INX
		BNE ClearMemory
		JSR WaitForVBlank
		

	
	Main:
	lda #$00
	sta blink_delay
	jsr activate_sound_registers
		LightSpriteTiles:
		LDA #$7C
		STA TopLeftCorner
		LDA #$80
		STA UpperRow
		LDA #$78
		STA TopRightCorner
		LDA #$79
		STA RightColumn
		LDA #$75
		STA BottomRightCorner
		LDA #$77
		STA BottomRow
		LDA #$76
		STA BottomLeftCorner
		LDA #$7E
		STA LeftColumn
		
		LoadPalette:
			LDA #$3f
			STA $2006
			LDA #$00
			STA $2006
			LDX #$00
			:
			LDA Palette, x
			STA $2007
			INX 
			CPX #$20
			BNE :-
		
		LoadSprites:
		lda #<pyl_board7
			sta bgPointer
			lda #>pyl_board7
			sta bgPointer+1
			LDA #$20
			STA $2006
			LDA #$20
			STA $2006
			LDX #$00
			LDY #$00
		:
			LDA (bgPointer), y
			STA $2007
			INY
			BNE :-
			INX
			INC bgPointer+1
			CPX #4
			BNE :-
			
		LoadAttributes:
			LDA #$23
			STA $2006             ; write the high byte of $23C0 address
			LDA #$C0
			STA $2006             ; write the low byte of $23C0 address
			LDX #$00  
			:
			LDA pyl_board7_attributes, x
			STA $2007
			INX
			CPX #$3f
			BNE :-
			
					
			LDA #%10001000
			STA $2000
			LDA #%00011000
			STA $2001
	
	Loop:
	JMP Loop
	
	
	
	GenerateRandomNumber:
	lda patternCounter
	cmp #$50
	bne chooseSquare
	lda #$00
	sta patternCounter
	
	chooseSquare:
	ldx patternCounter
	lda PredefinedPattern, x
	sta chosenSquare
	rts
	
	
	VerifyGeneratedNumber:
	lda chosenSquare
	cmp #2
	bpl :+
	LDA #$00
	STA SOX
	STA SOY
	rts
	
	:
	cmp #3
	bpl :+
	LDA #$28
	STA SOX
	LDA #$00
	STA SOY
	rts
	
	:
	cmp #4
	bpl :+
	LDA #$50
	STA SOX
	LDA #$00
	STA SOY
	rts
	
	:
	cmp #5
	bpl :+
	LDA #$78
	STA SOX
	LDA #$00
	STA SOY
	rts

	:
	cmp #6
	bpl :+
	LDA #$A0
	STA SOX
	LDA #$00
	STA SOY
	rts
	
	:
	cmp #7
	bpl :+
	LDA #$C8
	STA SOX
	LDA #$00
	STA SOY
	rts
	
	:
	cmp #8
	bpl :+
	LDA #$C8
	STA SOX
	LDA #$28
	STA SOY
	rts
	
	:
	cmp #9
	bpl :+
	LDA #$C8
	STA SOX
	LDA #$50
	STA SOY
	rts
	
	:
	cmp #10
	bpl :+
	LDA #$C8
	STA SOX
	LDA #$78
	STA SOY
	rts
	
	:
	cmp #11
	bpl :+
	LDA #$C8
	STA SOX
	LDA #$A0
	STA SOY
	rts
	
	:
	cmp #12
	bpl :+
	LDA #$A0
	STA SOX
	LDA #$A0
	STA SOY
	rts
	
	:
	cmp #13
	bpl :+
	LDA #$78
	STA SOX
	LDA #$A0
	STA SOY
	rts
	
	:
	cmp #14
	bpl :+
	LDA #$50
	STA SOX
	LDA #$A0
	STA SOY
	rts
	
	:
	cmp #15
	bpl :+
	LDA #$28
	STA SOX
	LDA #$A0
	STA SOY
	rts
	
	:
	cmp #16
	bpl :+
	LDA #$00
	STA SOX
	LDA #$A0
	STA SOY
	rts
	
	:
	cmp #17
	bpl :+
	LDA #$00
	STA SOX
	LDA #$78
	STA SOY
	rts
	
	:
	cmp #18
	bpl :+
	LDA #$00
	STA SOX
	LDA #$50
	STA SOY
	rts
	
	:
	LDA #$00
	STA SOX
	LDA #$28
	STA SOY
	rts
	
	DrawSquare:
	LDA ReferenceSquareY, x
	CLC
	ADC SOY
	sta $200, y
	lda SquareTileOrder, x
	sta $201, y
	lda #$00
	sta $202, y
	lda ReferenceSquareX, x
	clc
	adc SOX
	sta $203, y
	inx
	iny
	iny
	iny
	iny
	cpx #$14	; amount of time needed to complete drawing the ring of lights
	bne DrawSquare
	RTS
	
	CheckTimer:
	LDA timer
	cmp #$0d
	bne skip
	lda #$00
	sta timer

	JSR GenerateRandomNumber
	JSR VerifyGeneratedNumber
	LDX #$00
	LDY #$00
	JSR DrawSquare
	inc patternCounter
	inc board_hits
	lda board_hits
	cmp #$03
	bne :+
	lda #$00
	sta board_hits
	jsr switchScreens
	:
	rts
	skip:
	inc timer
	rts
	
	switchScreens:
	inc screen_switcher
	:
	lda screen_switcher
	cmp #$03
	bpl restartScreenSwitcher
	cmp #$02
	bne :+
	jsr switch2Screen3
	:
	lda screen_switcher
	cmp #$01
	bne :+
	jsr switch2Screen2
	:
	lda screen_switcher
	cmp #$00
	bne :+
	jsr switch2Screen1
	:
	rts
	restartScreenSwitcher:
	lda #$00
	sta screen_switcher
	jmp :----
	
	switch2Screen1:
			lda $2002
			lda #$00
			sta $2000
			sta $2001
			lda #<pyl_board7
			sta bgPointer
			lda #>pyl_board7
			sta bgPointer+1
			LDA #$20
			STA $2006
			LDA #$20
			STA $2006
			LDX #$00
			LDY #$00
		:
			LDA (bgPointer), y
			STA $2007
			INY
			BNE :-
			INX
			INC bgPointer+1
			CPX #4
			BNE :-
			
			LDA #%10001000
			STA $2000
			LDA #%00011000
			STA $2001
		rts
		
		switch2Screen2:
			lda $2002
			lda #$00
			sta $2000
			sta $2001
			lda #<pyl_board8
			sta bgPointer
			lda #>pyl_board8
			sta bgPointer+1
			LDA #$20
			STA $2006
			LDA #$20
			STA $2006
			LDX #$00
			LDY #$00
		:
			LDA (bgPointer), y
			STA $2007
			INY
			BNE :-
			INX
			INC bgPointer+1
			CPX #4
			BNE :-
			
			LDA #%10001000
			STA $2000
			LDA #%00011000
			STA $2001
		rts
		
			switch2Screen3:
			lda $2002
			lda #$00
			sta $2000
			sta $2001
			lda #<pyl_board9
			sta bgPointer
			lda #>pyl_board9
			sta bgPointer+1
			LDA #$20
			STA $2006
			LDA #$20
			STA $2006
			LDX #$00
			LDY #$00
		:
			LDA (bgPointer), y
			STA $2007
			INY
			BNE :-
			INX
			INC bgPointer+1
			CPX #4
			BNE :-
			
			LDA #%10001000
			STA $2000
			LDA #%00011000
			STA $2001
		rts
	
	a_button_pressed:
	lda #$01
	sta stopped
	rts
	
	
	VBlank:
	jsr LatchController
	lda stopped
	cmp #$01
	bne :+
	jsr detectSpace
	jsr blink_lights
	inc blink_delay
	rti
	:
	JSR CheckTimer
	jsr play_sound
	lda #$00
	sta $2003
	lda #$02
	sta $4014
	RTI
	
	blink_lights:
	lda blink_delay
	cmp #$0c
	bne :+
	lda #$00
	sta blink_delay
	lda number_of_blinks
	cmp #$00
	beq lights_on
	cmp #$01
	beq lights_off
	cmp #$02
	beq lights_on
	cmp #$03
	beq lights_off
	cmp #$04
	beq lights_on
	cmp #$05
	beq lights_off
	cmp #$06
	beq lights_on
	cmp #$07
	beq lights_off
	cmp #$08
	beq lights_on
	cmp #$09
	beq lights_off
	cmp #$0a
	beq lights_on
	cmp #$0b
	beq lights_off
	cmp #$0c
	beq lights_on
	cmp #$0d
	beq lights_off
	cmp #$0e
	beq lights_on
	:
	rts
	lights_on:
	lda #%00011000
	sta $2001
	inc number_of_blinks
	rts
		lights_off:
	lda #%00001000
	sta $2001
	inc number_of_blinks
	rts
	
	spin_again:
	lda #$00
	sta stopped
	lda #$00
	sta number_of_blinks
	sta blink_delay
	sta stopWhammySound
	sta whammy_sound_counter
	lda #$0f
	sta $4015
	rts
	
	detectSpace:
	lda screen_switcher
	cmp #$00
	beq screen1Spaces
	cmp #$01
	beq screen2Spaces
	cmp #$02
	beq screen3Spaces
	
	screen1Spaces:
	lda chosenSquare
	cmp #3
	bne :+
	jmp	playWhammySound
	:
	cmp #12
	bne :+ 
	jmp	playWhammySound
	:
	rts
	
	screen2Spaces:
	lda chosenSquare
	cmp #5
	bne :+
	jmp playWhammySound
	:
	cmp #9
	bne :+
	jmp playWhammySound
	:
	cmp #11
	bne :+
	jmp playWhammySound
	:
	rts
	
	screen3Spaces:
	lda chosenSquare
	cmp #1
	bne :+
	jmp playWhammySound
	:
	cmp #7
	bne :+ 
	jmp playWhammySound
	:
	cmp #14
	bne :+
	jmp playWhammySound
	:
	cmp #17
	bne :+
	jmp playWhammySound
	:
	rts
	
	playWhammySound:
	lda stopWhammySound
	cmp #$01
	beq :+
	cmp #$02
	beq :+++
	
ldy #$00
lda #$0f ; $00-$0F are playback speeds
sta $4010
lda #$40
sta $4011
lda #<((whammy_sound2 - whammy_sound1) / 16)
sta $4013
lda #<((whammy_sound1 - $C000) / 64)
sta $4012
lda #%00010000
sta $4015
inc stopWhammySound
:
lda whammy_sound_counter
cmp #$30
beq :+
inc whammy_sound_counter
rts
:
lda #$00
sta $4015 ;Milestone reached: When using DMC samples that are longer than can be taken by the APU, when you want to transition to the next sample, disable the APU status ($4015) first.
ldy #$00
lda #$0f ; $00-$0F are playback speeds
sta $4010
lda #$40
sta $4011
lda #<((whammy_end - whammy_sound2) / 16)
sta $4013
lda #<((whammy_sound2 - $C000) / 64)
sta $4012
lda #%00010000
sta $4015
inc stopWhammySound
:
rts


	
.segment "VECTORS"
	.word VBlank
	.word Restart
	.word 0
	
.segment "SAMPLES"
	whammy_sound1:
	.incbin "whammyhq1.dmc"
	whammy_sound2:
	.incbin "whammyhq2.dmc"
	whammy_end:
	

.segment "CHARS"
	.incbin "pyl.chr"
	
User avatar
tokumaru
Posts: 12673
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Adding Attributes Causes Background to Shift

Post by tokumaru »

Typically, when the scroll is messed up, it's because the scroll wasn't set before the picture started rendering. Every time you manipulate the video memory using $2006/$2007, the scroll position is affected, and you have to set it back to the position you want rendering to start from.

Skimming through your code, I don't see any $2005 writes at all. Games usually write to $2005 (twice - once for the X scroll and once for the Y scroll) and $2000 (to select a name table) every frame, after all video updates and before rendering starts.
Tompis1995
Posts: 34
Joined: Fri Feb 22, 2019 10:05 am

Re: Adding Attributes Causes Background to Shift

Post by Tompis1995 »

tokumaru wrote: Sun Jan 01, 2023 6:05 pm Typically, when the scroll is messed up, it's because the scroll wasn't set before the picture started rendering. Every time you manipulate the video memory using $2006/$2007, the scroll position is affected, and you have to set it back to the position you want rendering to start from.

Skimming through your code, I don't see any $2005 writes at all. Games usually write to $2005 (twice - once for the X scroll and once for the Y scroll) and $2000 (to select a name table) every frame, after all video updates and before rendering starts.
Ah, thanks! That did the trick!