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.

Moderator: Moderators

Post Reply
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?
Attachments
pyl3_000.png
pyl3_000.png (6.45 KiB) Viewed 1514 times
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: 12427
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!
Post Reply