Skip to content

Instantly share code, notes, and snippets.

@ISSOtm
Last active April 4, 2020 15:47
Show Gist options
  • Save ISSOtm/eb1a61206c3fe26425e7988575b638d0 to your computer and use it in GitHub Desktop.
Save ISSOtm/eb1a61206c3fe26425e7988575b638d0 to your computer and use it in GitHub Desktop.
Palette loading and fading routines for the Game Boy Color
Fadeout::
xor a
ld [wFadeCount], a
ld a, [wFadeSpeed]
add a, a
jr c, FadeOutToBlack
FadeOutToWhite:
ld a, [wFadeSpeed]
and $7F
jr z, .maxSpeed
ld b, a
.delayFade
rst waitVBlank
dec b
jr nz, .delayFade
.maxSpeed
rst waitVBlank
ld hl, wBGPalettes
ld c, rBGPI & $FF
.nextPaletteSet
ld a, $80
ld [$FF00+c], a
inc c
ld b, 4 * 8
.onePalette
push bc
ld a, [wFadeCount]
ld b, a
ld a, [hli]
add a, b
cp $1F
jr c, .notWhiteC
ld a, $1F
.notWhiteC
ld c, a
ld a, [hli]
add a, b
cp $1F
jr c, .notWhiteE
ld a, $1F
.notWhiteE
ld e, a
ld a, [hli]
add a, b
cp $1F
jr c, .notWhiteD
ld a, $1F
.notWhiteD
ld d, a
call PaletteCommon_Custom
ld b, a
.waitVRAM1
rst isVRAMOpen
jr nz, .waitVRAM1
ld a, b
pop bc
ld [$FF00+c], a
ld a, e
and $03
rl d
and a
rl d
or d
ld d, a
.waitVRAM2
rst isVRAMOpen
jr nz, .waitVRAM2
ld a, d
ld [$FF00+c], a
dec b
jr nz, .onePalette
inc c
ld a, c
cp rOBPI & $FF
jr z, .nextPaletteSet
ld a, [wFadeCount]
inc a
ld [wFadeCount], a
cp $20
jr nz, FadeOutToWhite
ret
FadeOutToBlack:
ld a, [wFadeSpeed]
and $7F
jr z, .maxSpeed
ld b, a
.delayFade
rst waitVBlank
dec b
jr nz, .delayFade
.maxSpeed
rst waitVBlank
ld hl, wBGPalettes
ld c, rBGPI & $FF
.nextPaletteSet
ld a, $80
ld [$FF00+c], a
inc c
ld b, 4 * 8
.onePalette
push bc
ld a, [wFadeCount]
ld b, a
ld a, [hli]
sub b
jr nc, .notWhiteC
xor a
.notWhiteC
ld c, a
ld a, [hli]
sub b
jr nc, .notWhiteE
xor a
.notWhiteE
ld e, a
ld a, [hli]
sub b
jr nc, .notWhiteD
xor a
.notWhiteD
ld d, a
call PaletteCommon_Custom
ld b, a
.waitVRAM1
rst isVRAMOpen
jr nz, .waitVRAM1
ld a, b
pop bc
ld [$FF00+c], a
ld a, e
and $03
rl d
and a
rl d
or d
ld d, a
.waitVRAM2
rst isVRAMOpen
jr nz, .waitVRAM2
ld a, d
ld [$FF00+c], a
dec b
jr nz, .onePalette
inc c
ld a, c
cp rOBPI & $FF
jr z, .nextPaletteSet
ld a, [wFadeCount]
inc a
ld [wFadeCount], a
cp $20
jr nz, FadeOutToBlack
ret
Fadein::
ld a, $1F
ld [wFadeCount], a
ld a, [wFadeSpeed]
add a, a
jr c, FadeInToBlack
FadeInToWhite:
ld a, [wFadeSpeed]
and $7F
jr z, .maxSpeed
ld b, a
.delayFade
rst waitVBlank
dec b
jr nz, .delayFade
.maxSpeed
rst waitVBlank
ld hl, wBGPalettes
ld c, rBGPI & $FF
.nextPaletteSet
ld a, $80
ld [$FF00+c], a
inc c
ld b, 4 * 8
.onePalette
push bc
ld a, [wFadeCount]
ld b, a
ld a, [hli]
add a, b
cp $1F
jr c, .notWhiteC
ld a, $1F
.notWhiteC
ld c, a
ld a, [hli]
add a, b
cp $1F
jr c, .notWhiteE
ld a, $1F
.notWhiteE
ld e, a
ld a, [hli]
add a, b
cp $1F
jr c, .notWhiteD
ld a, $1F
.notWhiteD
ld d, a
call PaletteCommon_Custom
ld b, a
.waitVRAM1
rst isVRAMOpen
jr nz, .waitVRAM1
ld a, b
pop bc
ld [$FF00+c], a
ld a, e
and $03
rl d
and a
rl d
or d
ld d, a
.waitVRAM2
rst isVRAMOpen
jr nz, .waitVRAM2
ld a, d
ld [$FF00+c], a
dec b
jr nz, .onePalette
inc c
ld a, c
cp rOBPI & $FF
jr z, .nextPaletteSet
ld a, [wFadeCount]
dec a
ld [wFadeCount], a
inc a
jr nz, FadeInToWhite
ret
FadeInToBlack:
ld a, [wFadeSpeed]
and $7F
jr z, .maxSpeed
ld b, a
.delayFade
rst waitVBlank
dec b
jr nz, .delayFade
.maxSpeed
rst waitVBlank
ld hl, wBGPalettes
ld c, rBGPI & $FF
.nextPaletteSet
ld a, $80
ld [$FF00+c], a
inc c
ld b, 4 * 8
.onePalette
push bc
ld a, [wFadeCount]
ld b, a
ld a, [hli]
sub b
jr nc, .notWhiteC
xor a
.notWhiteC
ld c, a
ld a, [hli]
sub b
jr nc, .notWhiteE
xor a
.notWhiteE
ld e, a
ld a, [hli]
sub b
jr nc, .notWhiteD
xor a
.notWhiteD
ld d, a
call PaletteCommon_Custom
ld b, a
.waitVRAM1
rst isVRAMOpen
jr nz, .waitVRAM1
ld a, b
pop bc
ld [$FF00+c], a
ld a, e
and $03
rl d
and a
rl d
or d
ld d, a
.waitVRAM2
rst isVRAMOpen
jr nz, .waitVRAM2
ld a, d
ld [$FF00+c], a
dec b
jr nz, .onePalette
inc c
ld a, c
cp rOBPI & $FF
jr z, .nextPaletteSet
ld a, [wFadeCount]
dec a
ld [wFadeCount], a
inc a
jr nz, FadeInToBlack
ret
GrayOutPicture::
ld hl, wBGPalettes
rst $00
ld c, rBGPI & $FF
.palettesLoop
ld a, $80
ld [$FF00+c], a
inc c
ld b, 8
.loop
ld d, 4
.oneColor
ld a, [hli]
ld e, a
ld a, [hli]
add a, e
ld e, a
ld a, [hli]
add a, e
ld e, 0
cp 3
jr c, .divEnd
.divideBy3
inc e
sub 3
jr c, .divEnd
jr nz, .divideBy3
.divEnd
push de
ld a, e
rrca
rrca
rrca
and $E0
or e
ld d, a
.waitVRAM1
rst isVRAMOpen
jr nz, .waitVRAM1
ld a, d
ld [$FF00+c], a
ld a, e
rlca
rlca
and $7C
ld d, a
ld a, e
and $18
rrca
rrca
rrca
or d
ld d, a
.waitVRAM2
rst isVRAMOpen
jr nz, .waitVRAM2
ld a, d
pop de
ld [$FF00+c], a
dec d
jr nz, .oneColor
dec b
jr nz, .loop
inc c
ld a, c
cp $6C
jr nz, .palettesLoop
ret
; Initializes OBJ palette #a with the struct pointed to by hl
; Struct is the same as BG palette, without first 3 color bytes (bcuz transparent, lel)
LoadOBJPalette::
ld d, h
ld e, l
ld c, a
push af
push hl
call SaveCurRAMBank
ld a, 1
call SwitchRAMBanks
ld h, d
ld l, e
ld d, wOBJPalettes >> 8
ld a, c
ld b, a
add a, a
add a, b
add a, a
add a, a
add a, wOBJPalettes & $FF + 3
ld e, a
ld c, 9
.copy
ld a, [hli]
and $1F
ld [de], a
inc de
dec c
jr nz, .copy
call RestoreRAMBank
pop hl
ld b, 3
.waitVRAM
rst isVRAMOpen
jr nz, .waitVRAM
pop af
add a, a
add a, a
inc a ; [add a, 2], globally
add a, a
or $80 ; Enable auto-increment
ld [rOBPI], a
.writeByte
call PaletteCommon
ld [rOBPD], a
ld a, e
and $03
rl d
and a ; Clear carry
rl d
or d ; Mix 2/5 G and B
ld [rOBPD], a
dec b
jr nz, .writeByte
ret
; Initializes BG palete #a (whose ID is a) with the 3*4 bytes at hl (RGB RGB RGB RGB)
; Applies a change to adjust to GBA screen if needed (checking hIsGBA)
; hl points to last byte, zeroes b, a equals last written byte, destroys de and c
LoadBGPalette::
ld d, h
ld e, l
ld c, a
push af
push hl
call SaveCurRAMBank
ld a, 1
call SwitchRAMBanks
ld h, d
ld l, e
ld d, wBGPalettes >> 8
ld a, c
ld b, a
add a, a
add a, b
add a, a
add a, a
ld e, a
ld c, 12
.copy
ld a, [hli]
and $1F
ld [de], a
inc de
dec c
jr nz, .copy
call RestoreRAMBank
pop hl
.waitVRAM
rst isVRAMOpen
jr nz, .waitVRAM
ld b, 4
pop af
add a, a
add a, a
add a, a
or $80 ; Enable auto-increment
ld [rBGPI], a
.writeByte
call PaletteCommon
ld [rBGPD], a
ld a, e
and $03
rl d
and a ; Clear carry
rl d
or d ; Mix 2/5 G and B
ld [rBGPD], a
dec b
jr nz, .writeByte
ret
PaletteCommon::
; We need to mix all three colors together, making sure they are all in range $00-$1F
ld a, [hli]
and $1F
ld c, a
ld a, [hli]
and $1F
ld e, a
ld a, [hli]
and $1F
ld d, a
PaletteCommon_Custom: ; Call with colors in c and de
ldh a, [hIsGBA]
and a
ld a, c
jr z, .notGBA
; Adjust all three palettes, using the formula "GBAPal = GBCPal / 2 + $10"
; Carry is clear from previous "and a"
rra
add a, $10
ld c, a ; Preserve this palette for later recovery
ld a, e ; Load middle color
; Carry can't be set
rra
add a, $10
ld e, a
ld a, d
; Same
rra
add a, $10
ld d, a
; Restore
ld a, c
.notGBA
ld c, a
ld a, e
rrca
rrca
rrca
ld e, a
and $e0
or c ; Mix R and 3/5 G
ld c, a
.waitVRAM
rst isVRAMOpen
jr nz, .waitVRAM
ld a, c
ret
; Reloads palettes from WRAM
; Use for example after GrayOutPicture
ReloadPalettes::
ld a, $80
ld [rBGPI], a
ld hl, wBGPalettes
.reloadBGPalettes
call PaletteCommon
ld [rBGPD], a
ld a, e
and $03
rl d
and a
rl d
or d
ld [rBGPD], a
ld a, l
cp wOBJPalettes & $FF
jr nz, .reloadBGPalettes
ld a, $80
ld [rOBPI], a
.reloadOBJPalettes
call PaletteCommon
ld [rOBPD], a
ld a, e
and $03
rl d
and a
rl d
or d
ld [rOBPD], a
ld a, l
cp wPalettesEnd & $FF
jr nz, .reloadOBJPalettes
ret
DefaultPalette::
db $1F, $1F, $1F
GrayPalette::
db $15, $15, $15 ; These 3 are shared by Default- and GrayPalette
db $0A, $0A, $0A
db $00, $00, $00
InvertedPalette::
db $00, $00, $00 ; Shared with GrayPalette
db $0A, $0A, $0A
db $15, $15, $15
PlayerPalette:: ; Sprite palette : 3 colors
db $1F, $1F, $1F
db $00, $00, $00
db $00, $00, $00
; A few map palettes
GrassPalette::
db $04, $1A, $00 ; "Fill" color
db $00, $14, $00 ; Green life stuff
db $0C, $08, $00 ; Wood
db $00, $00, $00 ; Black
HousePalette::
db $04, $1A, $00 ; Grass color (behind roof)
db $1C, $0C, $00 ; Wall
db $1C, $10, $08 ; Roof
db $00, $00, $00 ; Edges
DoorWindowPalette::
db $1C, $0C, $00 ; Wall
db $0C, $08, $00 ; Wood
db $18, $1B, $18 ; Window
db $00, $00, $00 ; Edges
WaterPalette::
db $08, $18, $18 ; Water
db $04, $14, $18 ; Ripples
db $0C, $08, $00 ; Wood
db $00, $00, $00 ; Ropes
; Use to declare a palette buffer in RAM
struct_pal: MACRO
w\1Palette\2_color0:: ds 3
w\1Palette\2_color1:: ds 3
w\1Palette\2_color2:: ds 3
w\1Palette\2_color3:: ds 3
ENDM
SECTION "Fade vars", WRAM0 ; Or WRAMX, who cares
; Fadeout/Fadein will wait (this & $7F)+1 frames between each step of the fade
; If bit 7 is reset, fade will be from/to white, otherwise black
wFadeSpeed::
ds 1
; Counter for palette fade effect
wFadeCount::
ds 1
; !!! MAKE SURE THIS IS 256-BYTE ALIGNED !!!
SECTION "Palettes", WRAM0[$C000] ; Or WRAMX, again who cares
; Contains all loaded BG palettes in uncompressed format
; Used for fadeout/fadein
wBGPalettes::
struct_pal BG,0
struct_pal BG,1
struct_pal BG,2
struct_pal BG,3
struct_pal BG,4
struct_pal BG,5
struct_pal BG,6
struct_pal BG,7
; Contains all loaded OBJ palettes in uncompressed format
; Used for fadeout/fadein
wOBJPalettes::
struct_pal OBJ,0
struct_pal OBJ,1
struct_pal OBJ,2
struct_pal OBJ,3
struct_pal OBJ,4
struct_pal OBJ,5
struct_pal OBJ,6
struct_pal OBJ,7
wPalettesEnd::
SECTION "Console type", HRAM
hIsGBA::
ds 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment