Customizable Pokédex Color - pret/pokecrystal GitHub Wiki
Ever wanted the color of your Pokédex to be something besides red? This is rather simple to implement in pokecrystal. All that's needed is a WRAM byte, and reworking some already existing code.
- Create a new WRAM byte
- Create color constants
- Add the Color option
- Making the Pokédex load the color
- Closing
Edit ram/wram.asm:
wPokegearFlags::
; bit 0: map
; bit 1: radio
; bit 2: phone
; bit 3: expn
; bit 7: on/off
db
wRadioTuningKnob:: db
wLastDexMode:: db
- ds 1
+wCurPokedexColor:: db ; current dex color
wWhichRegisteredItem:: db
wRegisteredItem:: db
To start we create a WRAM byte. wLastDexMode
has room after it and is also used by engine\pokedex\pokedex.asm.
Now we need some constants that'll be used to figure out which color is selected. Edit constants\wram_constants.asm:
; wCurDexMode::
const_def
const DEXMODE_NEW
const DEXMODE_OLD
const DEXMODE_ABC
const DEXMODE_UNOWN
+; wPokedexColor
+ const_def
+ const DEXCOLOR_RED
+ const DEXCOLOR_BLUE
+ const DEXCOLOR_PURPLE
+ const DEXCOLOR_BROWN
+ const DEXCOLOR_GREEN
+ const DEXCOLOR_PINK
+ const DEXCOLOR_YELLOW
+ const DEXCOLOR_CYAN
+ const DEXCOLOR_GRAY
+ const DEXCOLOR_MEWTWO
; wMonType::
const_def
const PARTYMON ; 0
const OTPARTYMON ; 1
const BOXMON ; 2
const TEMPMON ; 3
const WILDMON ; 4
Edit engine\pokedex\pokedex.asm.
; Pokedex_RunJumptable.Jumptable indexes
const_def
const DEXSTATE_MAIN_SCR
const DEXSTATE_UPDATE_MAIN_SCR
const DEXSTATE_DEX_ENTRY_SCR
const DEXSTATE_UPDATE_DEX_ENTRY_SCR
const DEXSTATE_REINIT_DEX_ENTRY_SCR
const DEXSTATE_SEARCH_SCR
const DEXSTATE_UPDATE_SEARCH_SCR
const DEXSTATE_OPTION_SCR
const DEXSTATE_UPDATE_OPTION_SCR
const DEXSTATE_SEARCH_RESULTS_SCR
const DEXSTATE_UPDATE_SEARCH_RESULTS_SCR
const DEXSTATE_UNOWN_MODE
const DEXSTATE_UPDATE_UNOWN_MODE
+ const DEXSTATE_COLOR_OPTION
+ const DEXSTATE_UPDATE_COLOR_OPTION
const DEXSTATE_EXIT
First is to create the const
DEXSTATEs that'll be used to determine the Color options screen.
.Jumptable:
; entries correspond to DEXSTATE_* constants
dw Pokedex_InitMainScreen
dw Pokedex_UpdateMainScreen
dw Pokedex_InitDexEntryScreen
dw Pokedex_UpdateDexEntryScreen
dw Pokedex_ReinitDexEntryScreen
dw Pokedex_InitSearchScreen
dw Pokedex_UpdateSearchScreen
dw Pokedex_InitOptionScreen
dw Pokedex_UpdateOptionScreen
dw Pokedex_InitSearchResultsScreen
dw Pokedex_UpdateSearchResultsScreen
dw Pokedex_InitUnownMode
dw Pokedex_UpdateUnownMode
+ dw Pokedex_InitColorOption
+ dw Pokedex_UpdateColorOption
dw Pokedex_Exit
And to create the jumptable data for those screens.
Pokedex_InitOptionScreen:
xor a
ldh [hBGMapMode], a
call ClearSprites
call Pokedex_DrawOptionScreenBG
call Pokedex_InitArrowCursor
- ; point cursor to the current dex mode (modes == menu item indexes)
- ld a, [wCurDexMode]
ld [wDexArrowCursorPosIndex], a
call Pokedex_DisplayModeDescription
call WaitBGMap
ld a, SCGB_POKEDEX_SEARCH_OPTION
call Pokedex_GetSGBLayout
call Pokedex_IncrementDexPointer
ret
This is to make sure the options menu starts at the top of the screen whenever the player enters it. Otherwise it'd begin at the second option.
Pokedex_UpdateOptionScreen:
...
.NoUnownModeArrowCursorData:
- db D_UP | D_DOWN, 3
- dwcoord 2, 4 ; NEW
- dwcoord 2, 6 ; OLD
- dwcoord 2, 8 ; ABC
+ db D_UP | D_DOWN, 4
+ dwcoord 2, 3 ; NEW
+ dwcoord 2, 4 ; OLD
+ dwcoord 2, 5 ; ABC
+ dwcoord 2, 6 ; COLOR
.ArrowCursorData:
- db D_UP | D_DOWN, 4
- dwcoord 2, 4 ; NEW
- dwcoord 2, 6 ; OLD
- dwcoord 2, 8 ; ABC
- dwcoord 2, 10 ; UNOWN
+ db D_UP | D_DOWN, 5
+ dwcoord 2, 3 ; NEW
+ dwcoord 2, 4 ; OLD
+ dwcoord 2, 5 ; ABC
+ dwcoord 2, 6 ; COLOR
+ dwcoord 2, 7 ; UNOWN
Here we're adding the color option to the cursor jumptable. You may notice that the dwcoord
are changed as well. This is because in order to fit an extra option on the screen, along with a description of said option, we need to remove the space between each option.
.MenuActionJumptable:
dw .MenuAction_NewMode
dw .MenuAction_OldMode
dw .MenuAction_ABCMode
+ dw .MenuAction_ColorOption
dw .MenuAction_UnownMode
...
+.MenuAction_ColorOption
+ call Pokedex_BlackOutBG
+ ld a, DEXSTATE_COLOR_OPTION
+ ld [wJumptableIndex], a
+ ret
.MenuAction_UnownMode:
call Pokedex_BlackOutBG
ld a, DEXSTATE_UNOWN_MODE
ld [wJumptableIndex], a
ret
Adding the Color option to the .MenuActionJumptable
. As you can see, the menu action is a copy of the Unown Dex action, but it takes us to the color option instead.
Pokedex_InitColorOption:
xor a
ldh [hBGMapMode], a
call ClearSprites
call Pokedex_DrawColorScreenBG
call Pokedex_InitArrowCursor
ld a, [wCurPokedexColor]
ld [wDexArrowCursorPosIndex], a
call WaitBGMap
ld a, SCGB_POKEDEX_SEARCH_OPTION
call Pokedex_GetSGBLayout
jp Pokedex_IncrementDexPointer
Here is the actual color option screen code, that should be placed after Pokedex_UnownModeUpdateCursorGfx
. It's a modified version of Pokedex_InitOptionScreen
that will also remember the cursor's location on the screen.
Pokedex_DrawOptionScreenBG:
call Pokedex_FillBackgroundColor2
hlcoord 0, 2
lb bc, 8, 18
call Pokedex_PlaceBorder
hlcoord 0, 12
lb bc, 4, 18
call Pokedex_PlaceBorder
hlcoord 0, 1
ld de, .Title
call Pokedex_PlaceString
- hlcoord 3, 4
- ld de, .Modes
- call PlaceString
+ hlcoord 3, 3
+ ld de, .NewMode
+ call PlaceString
+ hlcoord 3, 4
+ ld de, .OldMode
+ call PlaceString
+ hlcoord 3, 5
+ ld de, .AtoZMode
+ call PlaceString
+ hlcoord 3, 6
+ ld de, .Color
+ call PlaceString
ld a, [wUnlockedUnownMode]
and a
ret z
- hlcoord 3, 10
+ hlcoord 3, 7
ld de, .UnownMode
call PlaceString
ret
.Title:
db $3b, " OPTION ", $3c, -1
-.Modes:
- db "NEW #DEX MODE"
- next "OLD #DEX MODE"
- next "A to Z MODE"
- db "@"
-
+.NewMode:
+ db "NEW #DEX MODE@"
+
+.OldMode:
+ db "OLD #DEX MODE@"
+
+.AtoZMode:
+ db "A to Z MODE@"
+
+.Color:
+ db "#DEX COLOR@"
+
.UnownMode:
db "UNOWN MODE@"
This is where we add the text displayed by the Pokédex in the options menu. We had to change it from .Modes
since it would force there to be a space between each line of the options, this way we guarantee that each line will be uniform.
Pokedex_DrawColorScreenBG:
call Pokedex_FillBackgroundColor2
hlcoord 0, 2
lb bc, 14, 18
call Pokedex_PlaceBorder
hlcoord 0, 1
ld de, .Title
call Pokedex_PlaceString
hlcoord 3, 3
ld de, .Red
call Pokedex_PlaceString
hlcoord 3, 4
ld de, .Blue
call Pokedex_PlaceString
hlcoord 3, 5
ld de, .Purple
call Pokedex_PlaceString
hlcoord 3, 6
ld de, .Brown
call Pokedex_PlaceString
hlcoord 3, 7
ld de, .Green
call Pokedex_PlaceString
hlcoord 3, 8
ld de, .Pink
call Pokedex_PlaceString
hlcoord 3, 9
ld de, .Yellow
call Pokedex_PlaceString
hlcoord 3, 10
ld de, .Cyan
call Pokedex_PlaceString
hlcoord 3, 11
ld de, .Gray
call Pokedex_PlaceString
hlcoord 3, 12
ld de, .Mewtwo
jp Pokedex_PlaceString
.Title:
db $3b, " COLORS ", $3c, -1
.Red
db "RED ", $4f, -1
.Blue
db "BLUE ", $4f, -1
.Purple
db "PURPLE ", $4f, -1
.Brown
db "BROWN ", $4f, -1
.Green
db "GREEN ", $4f, -1
.Pink
db "PINK ", $4f, -1
.Yellow
db "YELLOW ", $4f, -1
.Cyan
db "CYAN ", $4f, -1
.Gray
db "GRAY ", $4f, -1
.Mewtwo
db "MEWTWO ", $4f, -1
Pokedex_UpdateColorOption:
ld de, .ArrowCursorData
call Pokedex_MoveArrowCursor
ld hl, hJoyPressed
ld a, [hl]
and SELECT | B_BUTTON
jr nz, .return_to_main_screen
ld a, [hl]
and A_BUTTON
jr nz, .do_menu_action
ret
.ArrowCursorData:
db D_UP | D_DOWN, 10
dwcoord 2, 3 ; Red
dwcoord 2, 4 ; Blue
dwcoord 2, 5 ; Purple
dwcoord 2, 6 ; Brown
dwcoord 2, 7 ; Green
dwcoord 2, 8 ; Pink
dwcoord 2, 9 ; Yellow
dwcoord 2, 10 ; Cyan
dwcoord 2, 11 ; Gray
dwcoord 2, 12 ; Mewtwo
.do_menu_action
ld a, [wDexArrowCursorPosIndex]
ld hl, .MenuActionJumptable
call Pokedex_LoadPointer
jp hl
.return_to_main_screen
call Pokedex_BlackOutBG
ld a, DEXSTATE_MAIN_SCR
ld [wJumptableIndex], a
ret
.MenuActionJumptable:
dw .MenuAction_Red
dw .MenuAction_Blue
dw .MenuAction_Purple
dw .MenuAction_Brown
dw .MenuAction_Green
dw .MenuAction_Pink
dw .MenuAction_Yellow
dw .MenuAction_Cyan
dw .MenuAction_Gray
dw .MenuAction_Mewtwo
.MenuAction_Red
ld b, DEXCOLOR_RED
jr .ChangeColor
.MenuAction_Blue
ld b, DEXCOLOR_BLUE
jr .ChangeColor
.MenuAction_Purple
ld b, DEXCOLOR_PURPLE
jr .ChangeColor
.MenuAction_Brown
ld b, DEXCOLOR_BROWN
jr .ChangeColor
.MenuAction_Green
ld b, DEXCOLOR_GREEN
jr .ChangeColor
.MenuAction_Pink
ld b, DEXCOLOR_PINK
jr .ChangeColor
.MenuAction_Yellow
ld b, DEXCOLOR_YELLOW
jr .ChangeColor
.MenuAction_Cyan
ld b, DEXCOLOR_CYAN
jr .ChangeColor
.MenuAction_Gray
ld b, DEXCOLOR_GRAY
jr .ChangeColor
.MenuAction_Mewtwo
ld b, DEXCOLOR_MEWTWO
.ChangeColor:
ld a, [wCurPokedexColor]
cp b
jr z, .skip_changing_color
ld a, b
ld [wCurPokedexColor], a
.skip_changing_color
call Pokedex_BlackOutBG
ld a, DEXSTATE_COLOR_OPTION
ld [wJumptableIndex], a
ret
This should be placed immediately after .UnownMode
. This is the bread and butter of the color options screen. So let's break it down into its parts:
Pokedex_DrawColorScreenBG
is actually what creates the color option screen. It's a copy of the already used Pokedex_DrawOptionScreenBG
, just adjusted to what we need. Pokedex_UpdateColorOption
is similarly a copy of Pokedex_UpdateOptionScreen
, but modified to remove the extra window at the bottom, since the colors don't really need descriptions. Also it uses the same button actions as that screen. This is optional, but the reason we've added the Poké Ball symbol beside each color option is because that is the only use of the lighter color in the palette, and will give the player an additional idea of what the color will look like on a whole, without having to completely leave the menu.
Now the .MenuActionJumptable
is a copy of the same one used by the options screen to update the Pokédex mode it's in, but modified in a way that it loads wCurPokedexColor
we created earilier with one of the corresponding palettes and then updates the screen so to apply the color.
Pokedex_DisplayModeDescription:
xor a
ldh [hBGMapMode], a
hlcoord 0, 12
lb bc, 4, 18
call Pokedex_PlaceBorder
ld a, [wDexArrowCursorPosIndex]
ld hl, .Modes
call Pokedex_LoadPointer
ld e, l
ld d, h
hlcoord 1, 14
call PlaceString
ld a, $1
ldh [hBGMapMode], a
ret
.Modes:
dw .NewMode
dw .OldMode
dw .ABCMode
+ dw .Color
dw .UnownMode
.NewMode:
db "<PK><MN> are listed by"
next "evolution type.@"
.OldMode:
db "<PK><MN> are listed by"
next "official type.@"
.ABCMode:
db "<PK><MN> are listed"
next "alphabetically.@"
+.Color:
+ db "Change the color"
+ next "of the border.@"
.UnownMode:
db "UNOWN are listed"
next "in catching order.@"
And finally this adds a description for our new Pokédex menu option.
Now that everything's set up on the Pokédex side, we need it to actually load the correct color. Doing some digging reveals that what we need is located in engine\gfx\cgb_layouts.asm.
Searching the file for the default Pokédex color (PREDEFPAL_POKEDEX
) will show it in _CGB_Pokedex
, _CGB_PokedexSearchOption
, and _CGB_PokedexUnownMode
:
_CGB_Pokedex:
ld de, wBGPals1
- ld a, PREDEFPAL_POKEDEX
+ call CheckPokedexColor
call GetPredefPal
call LoadHLPaletteIntoDE ; dex interface palette
ld a, [wCurPartySpecies]
cp $ff
jr nz, .is_pokemon
ld hl, PokedexQuestionMarkPalette
call LoadHLPaletteIntoDE ; green question mark palette
jr .got_palette
...
+CheckPokedexColor:
+ ld a, [wCurPokedexColor]
+ cp DEXCOLOR_BLUE
+ jr nz, .Purple
+ ld a, PREDEFPAL_TRADE_TUBE
+ ret
+
+.Purple
+ cp DEXCOLOR_PURPLE
+ jr nz, .Brown
+ ld a, PREDEFPAL_RB_PURPLEMON
+ ret
+
+.Brown
+ cp DEXCOLOR_BROWN
+ jr nz, .Green
+ ld a, PREDEFPAL_RB_BROWNMON
+ ret
+
+.Green
+ cp DEXCOLOR_GREEN
+ jr nz, .Pink
+ ld a, PREDEFPAL_RB_GREENMON
+ ret
+
+.Pink
+ cp DEXCOLOR_PINK
+ jr nz, .Yellow
+ ld a, PREDEFPAL_RB_PINKMON
+ ret
+
+.Yellow
+ cp DEXCOLOR_YELLOW
+ jr nz, .Cyan
+ ld a, PREDEFPAL_RB_YELLOWMON
+ ret
+
+.Cyan
+ cp DEXCOLOR_CYAN
+ jr nz, .Gray
+ ld a, PREDEFPAL_RB_CYANMON
+ ret
+
+.Gray
+ cp DEXCOLOR_GRAY
+ jr nz, .Mewtwo
+ ld a, PREDEFPAL_CGB_BADGE
+ ret
+
+.Mewtwo
+ cp DEXCOLOR_MEWTWO
+ jr nz, .Red
+ ld a, PREDEFPAL_DIPLOMA
+ ret
+
+.Red
+ ld a, PREDEFPAL_POKEDEX
+ ret
PokedexQuestionMarkPalette:
INCLUDE "gfx/pokedex/question_mark.pal"
...
_CGB_PokedexUnownMode:
ld de, wBGPals1
- ld a, PREDEFPAL_POKEDEX
+ call CheckPokedexColor
...
_CGB_PokedexSearchOption:
ld de, wBGPals1
- ld a, PREDEFPAL_POKEDEX
+ call CheckPokedexColor
...
We replaced the inital load of PREDEFPAL_POKEDEX
with CheckPokedexColor
that finds the correct color and sets it. Do this for the other two mentioned locations and you're done.
The palettes I used were the unused palettes of the original Pokémon sprites in Red/Blue, but you can use any palette you like. This also has freed up some space on the options screen to allow for other Pokédex modes in addition to what's already there!
TODO: Cursor color