JamesNES
Well-known member
This is something I wanted a while back but didn't know how to do. It's for if you want to say, change the palette of a monster block after it's disappeared to match the grass or something like that.
I don't have any experience at all with NES Maker's scrolling modules so I'm not sure how this'd work on them, but for single screen games it's all good.
I've made two versions, one which change all four palettes in an attribute grid, and the second one will change just one of the four. They take an X and Y argument, and the palette you want to switch it to (ie 0 to 3).
You might want to check this out first for an idea on how attributes work:
NESdev PPU attribute tables
So the first one works like this, and can be run from any bank:
So this changes the top two to be palette 0 and the bottom two to be palette 1.
The second one has to be run from the static bank as it needs to look up from bank 16 which palettes the other tiles have.
This changes tile 8,6 to use palette 1.
There's bound to be a less wordy way for this one, and it'll be better as a subroutine, but it works. Hope this helps someone!
I don't have any experience at all with NES Maker's scrolling modules so I'm not sure how this'd work on them, but for single screen games it's all good.
I've made two versions, one which change all four palettes in an attribute grid, and the second one will change just one of the four. They take an X and Y argument, and the palette you want to switch it to (ie 0 to 3).
You might want to check this out first for an idea on how attributes work:
NESdev PPU attribute tables
So the first one works like this, and can be run from any bank:
Code:
ChangeFourPalettes #$08, #$06, #%01010000
So this changes the top two to be palette 0 and the bottom two to be palette 1.
Code:
MACRO ChangeFourPalettes arg0, arg1, arg2
;;arg0 = x
;;arg1 = y
;;arg2 = new palettes for this quadrant
;; 7654 3210
; |||| ||++- Color bits 3-2 for top left quadrant of this byte
; |||| ++--- Color bits 3-2 for top right quadrant of this byte
; ||++------ Color bits 3-2 for bottom left quadrant of this byte
; ++-------- Color bits 3-2 for bottom right quadrant of this byte
LDA camScreen
AND #%00000001
BEQ +leftNametable
LDA #$27
STA temp
JMP +gotNT
+leftNametable
LDA #$23
STA temp
+gotNT
LDA arg1
LSR
ASL
ASL
ASL
STA tempB
LDA arg0
lsr
CLC
ADC tempB
CLC
ADC #$C0
STA tempC
LDY maxScrollOffsetCounter
LDA temp
STA scrollUpdateRam,y
INY
LDA tempC
STA scrollUpdateRam,y
INY
LDA arg2
STA scrollUpdateRam,y
INY
STY maxScrollOffsetCounter
LDA updateScreenData
ORA #%0000100
STA updateScreenData
ENDM
The second one has to be run from the static bank as it needs to look up from bank 16 which palettes the other tiles have.
Code:
ChangeSinglePalette #$08, #$06, #$01
This changes tile 8,6 to use palette 1.
Code:
MACRO ChangeSinglePalette arg0, arg1, arg2
;arg0 = x
;arg1 = y
;arg2 = palette to swap to, 0-3
LDA camScreen
AND #%00000001
BEQ +leftNametable
LDA #$27
STA temp
JMP +gotNT
+leftNametable
LDA #$23
STA temp
+gotNT
LDA arg1
LSR
ASL
ASL
ASL
STA tempB
LDA arg0
lsr
CLC
ADC tempB
sta tempA
CLC
ADC #$C0
STA tempC
;;now to get the original attribute value for this
SwitchBank #$16
LDA camScreen
LSR
LSR
LSR
LSR
LSR
sta temp1
LDA camScreen
tay
LDA warpMap
AND #%00000001
BEQ +loadAttFromMap1table
;;;load from map 2 table
LDA AttributeTables_Map2_Lo,y
STA temp16
LDA AttributeTables_Map2_Hi,y
STA temp16+1
LDA arg0_hold
CLC
ADC #$08
STA arg0_hold
JMP +GotAttLoadPointer
+loadAttFromMap1table:
LDA AttributeTables_Map1_Lo,y
STA temp16
LDA AttributeTables_Map1_Hi,y
STA temp16+1
+GotAttLoadPointer:
;;now (temp16) holds the address of the nametable to be loaded.
ReturnBank
SwitchBank temp1
LDA tempA
tay
LDA (temp16),y ;;got the attribute value
STA tempD
;;now which quadrant is it
LDA arg0
AND #%00000001
BNE +rightHand
;;left side
;;top or bottom
LDA arg1
AND #%00000001
BNE +bottom
;;top left
LDA tempD
AND #%11111100
ORA arg2
STA tempD
JMP +done
+bottom
;bottom left
LDA arg2
ASL
ASL
ASL
ASL
ASL
ASL
STA arg2_hold
LDA tempD
AND #%11001111
ORA arg2_hold
STA tempD
JMP +done
+rightHand
LDA arg1
AND #%00000001
BNE +bottom
;;top right
LDA arg2
ASL
ASL
STA arg2_hold
LDA tempD
AND #%11110011
ORA arg1_hold
STA tempD
JMP +done
+bottom
;bottom right
LDA arg2
ROR
ROR
ROR
STA arg2_hold
LDA tempD
AND #%00111111
ORA arg2_hold
STA tempD
+done
LDY maxScrollOffsetCounter
LDA temp
STA scrollUpdateRam,y
INY
LDA tempC
STA scrollUpdateRam,y
INY
LDA tempD
STA scrollUpdateRam,y
INY
STY maxScrollOffsetCounter
LDA updateScreenData
ORA #%0000100
STA updateScreenData
ENDM
There's bound to be a less wordy way for this one, and it'll be better as a subroutine, but it works. Hope this helps someone!