1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
|
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.
## Contents
1. [Create a new WRAM byte](#1-create-a-new-wram-byte)
2. [Create color constants](#2-create-color-constants)
3. [Add the Color option](#3-add-the-color-option)
4. [Making the Pokédex load the color](#4-making-the-pok%C3%A9dex-load-the-color)
5. [Closing](#5-closing)
## 1. Create a new WRAM Byte
Edit [wram.asm](../blob/master/wram.asm):
```diff
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](../blob/master/engine/pokedex/pokedex.asm).
## 2. Create color constants
Now we need some constants that'll be used to figure out which color is selected. Edit [constants\wram_constants.asm](../blob/master/constants/wram_constants.asm):
```diff
; 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
```
## 3. Add the Color option
Edit [engine\pokedex\pokedex.asm](../blob/master/engine/pokedex/pokedex.asm).
```diff
; 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.
```diff
.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.
```diff
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.
```diff
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.
```diff
.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.
```asm
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.
```diff
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.
```asm
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.
```diff
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.
## 4. Making the Pokédex load the color
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](../blob/master/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`:
```diff
_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, .Red
+ ld a, PREDEFPAL_CGB_BADGE
+ ret
+
+.Red
+ ld a, PREDEFPAL_POKEDEX
+ ret
PokedexQuestionMarkPalette:
INCLUDE "gfx/pokedex/question_mark.pal"
```
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 your done.
## 5. Closing

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
|