Family BASIC palette change

Started by P, August 18, 2015, 11:29:04 am

Previous topic - Next topic


August 18, 2015, 11:29:04 am Last Edit: August 21, 2015, 01:55:09 am by P
After discussing some Family BASIC with zmaster18, the fact that it can only use number of predefined palettes using CGSET was mentioned. So I felt like making a subroutine that lets you create your own palette.

Here's the subroutine and a random palette that I made up:

vblank_wait: ;palette can only be changed in a vblank
 bit $2002
 bpl vblank_wait

 lda $2002 ;read $2002 to reset high/low latch
 lda #$3F ;palette starts at VRAM $3F00
 sta $2006
 lda #$00
 sta $2006

 ldx #$00 ;set loop counter to 0
 lda palette_data, X ;load new palette data + X
 sta $2007 ;write data to PPU $3F00, $3F01 and so on
 cpx #$20 ;32 colours total in palette
 bne @loop

 ;BG palette:     00                01                10                11
 .db $0F,$16,$10,$03,  $0F,$01,$21,$31,  $0F,$07,$27,$28,  $0F,$07,$29,$19
 ;$16 = red

 ;Sprite palette: 00                01                10                11
 .db $0F,$02,$25,$38,  $0F,$16,$38,$30,  $0F,$01,$21,$31,  $0F,$00,$10,$30

It has red colour ($16) in the place where Family BASIC default palette has its white colour used for the text. So all text will become red if this subroutine works.

After assembling:

code (will be placed at &H6FC0):
2C 02 20 10 FB AD 02 20
A9 3F 8D 06 20 A9 00 8D
06 20 A2 00 BD E0 6F 8D <- E0 6F is the location of the palette data (backwards)
07 20 E8 E0 20 D0 F5 60

palette data (will be placed at &H6FE0):
0F 16 10 03 0F 01 21 31 0F 07 27 28 0F 07 29 19
0F 02 25 38 0F 16 38 30 0F 01 21 31 0F 00 10 30

The code happens to be exactly 32 byte and the BG and sprite palettes together are also 32 byte so we have a total of 64 (&H40 in hexadecimal) byte to POKE, easy to count. User RAM ends right before &H7000 (in V3) so  &H7000 - &H40 = &H6FC0 is where we want to put it.

And finally the Family BASIC (V3) code. I used a technique I found, to insert "&H" in a loop while poking the data. Since BASIC code is stored as text, this saves a lot of memory.

40 POKEI,VAL("&H"+A$)
70 DATA 2C,02,20,10,FB,AD,02,20,A9,3F,8D,06,20,A9,00,8D,06,20,A2,00,BD,E0,6F,8D,07,20,E8,E0,20,D0,F5,60
90 DATA 0F,16,10,03,0F,01,21,31,0F,07,27,28,0F,07,29,19,0F,02,25,38,0F,16,38,30,0F,01,21,31,0F,00,10,30

Hopefully I didn't make any mistakes. But it seems to work (text became red at least).

Here's all possible hex values for all colours the Famicom provides (just remember that the actual colours differs from TV to TV).

Note that 0D is a forbidden black colour since it glitches on certain TVs, so never use that colour. Use 0F for black instead.
Edit: Actually it's best to not use any of the four colours in the xD scale (0D, 1D, 2D or 3D). If you fade any of these colours by keep subtracting them with &H10 they will eventually become the forbidden 0D.
Edit: Although it may not look like it in this picture, 2D and 3D are very similar to 00 and 10, so there's no reason to use them anyway. 1D looks dark grey in the picture but this colour and all the blacks from 0E to 3F are all identical too 0F, so no reason to use any of these either. In the end 0F is the only colour you need in the last three collumns (0D-3F).
Finally the two whites 20 and 30 are also actually identical (most games use 30 as white but Rockman uses 20 for his eyes for some reason).


This is very handy for making a game that requires many pallet changes. This way, you can change your pallets on the fly without having to type in long pallet defining commands each time you switch. Very clever P!

So you can have your 3 groups of 4 pallets for sprites and 2 groups of 4 pallets for background tiles. Before with the PALETB and PALETS command, you could only have 1 group of 4 pallets for each.

This can make your game very colorful! The more colors the better  8)


August 18, 2015, 01:10:52 pm #2 Last Edit: August 19, 2015, 02:57:57 am by P
Yeah run the code somewhere early in your program and you can change any colour in the palette again later in the program, by just poking in any valid number of colour codes into &H6FE0-&H6FFF (for example poke &H16 into &H6FF1 to change the sprite palette's second colour into red) then use CALL&H6FC0 again to rewrite the palette with the changes.

I forgot pre-V3 version! In pre-V3, user RAM upper limit is &H77FF so change all instances of 6F to 77 in the code including the machine code subroutine:

20 FORI=&H77C0TO&H77FF
40 POKEI,VAL("&H"+A$)
60 CALL&H77C0
70 DATA 2C,02,20,10,FB,AD,02,20,A9,3F,8D,06,20,A9,00,8D,06,20,A2,00,BD,E0,77,8D,07,20,E8,E0,20,D0,F5,60
90 DATA 0F,16,10,03,0F,01,21,31,0F,07,27,28,0F,07,29,19,0F,02,25,38,0F,16,38,30,0F,01,21,31,0F,00,10,30

Post Merge: August 18, 2015, 01:45:11 pm

LOL nevermind I checked PALET and it has full control of your palette. My subroutine is useless!

PALETS 0,&H16,&H16,&H16,&H16
This changes all four colours in the sprite palette's set 0 to red. This also makes the backdrop red (since the first colour in either palette controls the backdrop colour).

PALETB 3,&H0F,&H16,&H19,&H12
This changes four colours in the BG palette's set 3 to black, red, green and blue.

You can change any number of colours you want using the PALET command.

Well I guess it was fun to try this technique of poking hexadecimal numbers.


I thought your program allowed you to modify the pallets defined in CGSET! So with the regular PALETB/S command, you only get 1 group to edit. I thought your code allowed you have more than 1 group.


August 18, 2015, 03:38:43 pm #4 Last Edit: August 18, 2015, 03:44:04 pm by P
No I just load 32 arbitrary bytes into $3F00-$3F1F (where the palettes that is currently displayed is stored). This is essentially what the PALET command is doing, although it only changes 4 palette entries at a time, while my routine changes all 32 palette entries at once (PALET needs to run 8 times to update the whole palette). Needless to say I didn't know/remember about that command.

I suppose the predefined palette data that CGSET loads, is in ROM and can't be touched.

QuoteI thought your code allowed you have more than 1 group.

You can have as many groups as you want as long as you can store them somewhere (ROM or RAM). It's just data, it only gets meaning when you write it to $3F00-$3F1F using either PALET, CGSET or my useless subroutine.

Easiest way to see what's happening is loading V3 in Nintendulator and open the video debugging window and see all changes in real-time. There you will see the whole 32 byte palette space in $3F00-$3F1F. Hover the mouse over the palette entries to see their colour code ($00-$3F), VRAM address ($3F00-$3F1F), group number (0-3 called offset in Nintendulator) and whether they belong to the BG or sprite palette.
Then try changing each palette entry with the PALET command or try swapping the whole palette using the CGSET command while the video window is open so you can see all changes.


Why not control palletes by machine code subroutines and do not use PALET etc at all?  ???
I don't buy, sell or trade at moment.
But my question is how hackers at that time were able to hack those games?(c)krzy


Yeah you could do that of course. But my routine takes up a bit of memory.


Not really. 64 bytes only, you can easily hide under the REM in the first line, remove exceeded code and, when you do listing, start it from the next line.
I don't buy, sell or trade at moment.
But my question is how hackers at that time were able to hack those games?(c)krzy


August 20, 2015, 04:15:04 pm #8 Last Edit: August 21, 2015, 11:56:25 am by P
Oh yeah I remember something about using REM lines for data. But still I'm not sure how it would be more effective than just using PALET? I guess it's faster since it's not BASIC and you can rewrite anywhere from 1 to 32 colours at a time, unlike PALET that always seems to write 4 colours at a time.

Edit: Oh yeah I put a vblank wait in the beginning of the subroutine, so the program needs to wait for the next frame before it can write the palette (how else am I supposed to make sure it's in vblank?) so I guess it's not faster than PALET at all. You can tell because the screen flickers when you use CALL. I guess it's not very suitable for games unless you have some specific needs.

Also note that what you write to the first colour in each of the four BG palettes doesn't matter at all since they are overwritten when it writes the first colours in the the four sprite palettes. This is because these colours are mirrors of each other (what you write in one, is also written in the other). If you want to change the backdrop colour, change the first colour in the sprite palette, not in the BG palette.

BTW I added some more notes at the end of the first post.