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
|
This tutorial is for how to add a fourth page to Pokémon stats. As an example, we'll make an orange page after the pink, green, and blue ones.
(The code for this feature was adapted from [i-am-the-pokeman](https://github.com/i-am-the-pokeman/pokecrystal-4th-stat-screen/).)
## Contents
1. [Define the fourth page's colors](#1-define-the-fourth-pages-colors)
2. [Load and apply the fourth page's palette](#2-load-and-apply-the-fourth-pages-palette)
3. [Display the fourth page's content](#3-display-the-fourth-pages-content)
4. [Account for the shifted page indexes](#4-account-for-the-shifted-page-indexes)
5. [Show Caught Data on the fourth page](#5-show-caught-data-on-the-fourth-page)
## 1. Define the fourth page's colors
Edit [gfx/stats/pages.pal](../blob/master/gfx/stats/pages.pal):
```diff
; pink
RGB 31, 31, 31
RGB 31, 19, 31
RGB 31, 15, 31
RGB 00, 00, 00
; green
RGB 31, 31, 31
RGB 21, 31, 14
RGB 17, 31, 00
RGB 00, 00, 00
; blue
RGB 31, 31, 31
RGB 17, 31, 31
RGB 17, 31, 31
RGB 00, 00, 00
+; orange
+ RGB 31, 31, 31
+ RGB 30, 24, 16
+ RGB 30, 22, 12
+ RGB 00, 00, 00
```
And edit [gfx/stats/stats.pal](../blob/master/gfx/stats/stats.pal):
```diff
; pink
RGB 31, 19, 31
; green
RGB 21, 31, 14
; blue
RGB 17, 31, 31
+; orange
+ RGB 30, 24, 16
```
`RGB` colors define 5-bit red, green, and blue channels, each from 0 to 31. (On a PC, typically 8-bit color channels go from 0 to 255, or in hex 00 to FF. Just multiply or divide by 8 to convert between them; e.g. `RGB 30, 24, 16` looks like [#F0C080](https://www.color-hex.com/color/F0C080).)
Both of these files sort the pages in order from left to right.
## 2. Load and apply the fourth page's palette
Edit [engine/gfx/cgb_layouts.asm](../blob/master/engine/gfx/cgb_layouts.asm):
```diff
_CGB_StatsScreenHPPals:
ld de, wBGPals1
ld a, [wCurHPPal]
ld l, a
ld h, $0
add hl, hl
add hl, hl
ld bc, HPBarPals
add hl, bc
call LoadPalette_White_Col1_Col2_Black ; hp palette
ld a, [wCurPartySpecies]
ld bc, wTempMonDVs
call GetPlayerOrMonPalettePointer
call LoadPalette_White_Col1_Col2_Black ; mon palette
ld hl, ExpBarPalette
call LoadPalette_White_Col1_Col2_Black ; exp palette
ld hl, StatsScreenPagePals
ld de, wBGPals1 palette 3
- ld bc, 3 palettes ; pink, green, and blue page palettes
+ ld bc, 4 palettes ; pink, green, blue, and orange page palettes
ld a, BANK(wBGPals1)
call FarCopyWRAM
call WipeAttrmap
hlcoord 0, 0, wAttrmap
lb bc, 8, SCREEN_WIDTH
ld a, $1 ; mon palette
call FillBoxCGB
hlcoord 10, 16, wAttrmap
ld bc, 10
ld a, $2 ; exp palette
call ByteFill
- hlcoord 13, 5, wAttrmap
+ hlcoord 11, 5, wAttrmap
lb bc, 2, 2
ld a, $3 ; pink page palette
call FillBoxCGB
- hlcoord 15, 5, wAttrmap
+ hlcoord 13, 5, wAttrmap
lb bc, 2, 2
ld a, $4 ; green page palette
call FillBoxCGB
- hlcoord 17, 5, wAttrmap
+ hlcoord 15, 5, wAttrmap
lb bc, 2, 2
ld a, $5 ; blue page palette
call FillBoxCGB
+
+ hlcoord 17, 5, wAttrmap
+ lb bc, 2, 2
+ ld a, $6 ; orange page palette
+ call FillBoxCGB
call ApplyAttrmap
call ApplyPals
ld a, $1
ldh [hCGBPalUpdate], a
ret
StatsScreenPagePals:
INCLUDE "gfx/stats/pages.pal"
StatsScreenPals:
INCLUDE "gfx/stats/stats.pal"
```
Here we load the new fourth palette, and change where the palettes are applied to the screen. The pink, green, and blue page icons are going to shift left to make room for a fourth orange icon.
## 3. Display the fourth page's content
Edit [engine/pokemon/stats_screen.asm](../blob/master/engine/pokemon/stats_screen.asm):
```diff
- const_def 1
- const PINK_PAGE ; 1
- const GREEN_PAGE ; 2
- const BLUE_PAGE ; 3
-NUM_STAT_PAGES EQU const_value + -1
+ const_def
+ const PINK_PAGE ; 0
+ const GREEN_PAGE ; 1
+ const BLUE_PAGE ; 2
+ const ORANGE_PAGE ; 3
+NUM_STAT_PAGES EQU const_value
```
Instead of three constants from 1 to 3, we'll use four constants from 0 to 3. We're not using 1 to 4, because 4 in binary is %100, and these values need to fit in two bits.
```diff
StatsScreenMain:
xor a
ld [wJumptableIndex], a
-; ???
- ld [wStatsScreenFlags], a
- ld a, [wStatsScreenFlags]
- and ~STAT_PAGE_MASK
- or PINK_PAGE ; first_page
- ld [wStatsScreenFlags], a
+ ld [wStatsScreenFlags], a ; PINK_PAGE
.loop
ld a, [wJumptableIndex]
and ~(1 << 7)
ld hl, StatsScreenPointerTable
rst JumpTable
call StatsScreen_WaitAnim ; check for keys?
ld a, [wJumptableIndex]
bit 7, a
jr z, .loop
ret
StatsScreenMobile:
xor a
ld [wJumptableIndex], a
- ???
- ld [wStatsScreenFlags], a
- ld a, [wStatsScreenFlags]
- and ~STAT_PAGE_MASK
- or PINK_PAGE ; first_page
- ld [wStatsScreenFlags], a
+ ld [wStatsScreenFlags], a ; PINK_PAGE
.loop
farcall Mobile_SetOverworldDelay
ld a, [wJumptableIndex]
and ~(1 << 7)
ld hl, StatsScreenPointerTable
rst JumpTable
call StatsScreen_WaitAnim
farcall MobileComms_CheckInactivityTimer
jr c, .exit
ld a, [wJumptableIndex]
bit 7, a
jr z, .loop
.exit
ret
```
This code was a bit messy and redundant, but the intended effect is to start at the pink page. We changed its index from 1 to 0, so that needed updating.
```diff
StatsScreen_JoypadAction:
...
.a_button
ld a, c
- cp BLUE_PAGE ; last page
+ cp ORANGE_PAGE ; last page
jr z, .b_button
.d_right
inc c
- ld a, BLUE_PAGE ; last page
+ ld a, ORANGE_PAGE ; last page
cp c
jr nc, .set_page
ld c, PINK_PAGE ; first page
jr .set_page
.d_left
+ ld a, c
dec c
+ and a ; cp PINK_PAGE ; first page
jr nz, .set_page
- ld c, BLUE_PAGE ; last page
+ ld c, ORANGE_PAGE ; last page
jr .set_page
.done
ret
.set_page
ld a, [wcf64]
and %11111100
or c
ld [wcf64], a
ld h, 4
call StatsScreen_SetJumptableIndex
ret
```
Pressing left and right navigates between the pages, wrapping around the ends if necessary. The orange page is last, not the blue page any more, and some logic also needed updating since a page index of 0 is now possible.
```diff
StatsScreen_PlacePageSwitchArrows:
- hlcoord 12, 6
+ hlcoord 10, 6
ld [hl], "◀"
hlcoord 19, 6
ld [hl], "▶"
ret
```
The arrow left of the page icons needs shifting further left to make room for a fourth icon.
```diff
StatsScreen_LoadGFX:
...
.PageTilemap:
ld a, [wStatsScreenFlags]
maskbits NUM_STAT_PAGES
- dec a
ld hl, .Jumptable
rst JumpTable
ret
.Jumptable:
; entries correspond to *_PAGE constants
dw LoadPinkPage
dw LoadGreenPage
dw LoadBluePage
+ dw LoadOrangePage
...
+LoadOrangePage:
+ ld de, HelloWorldString
+ hlcoord 1, 9
+ call PlaceString
+ ret
+
+HelloWorldString:
+ db "Hello world!@"
+
IDNoString:
db "<ID>№.@"
OTString:
db "OT/@"
```
This is where we display the actual content of the orange page (as well as another adjustment to account for the pink page's new index 0). This example will just say ["Hello world!"](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program)
```diff
StatsScreen_LoadPageIndicators:
+ hlcoord 11, 5
+ ld a, $36 ; " " " "
+ call .load_square
hlcoord 13, 5
ld a, $36 ; first of 4 small square tiles
call .load_square
hlcoord 15, 5
ld a, $36 ; " " " "
call .load_square
hlcoord 17, 5
ld a, $36 ; " " " "
call .load_square
ld a, c
- cp GREEN_PAGE
- ld a, $3a ; first of 4 large square tiles
- hlcoord 13, 5 ; PINK_PAGE (< GREEN_PAGE)
- jr c, .load_square
- hlcoord 15, 5 ; GREEN_PAGE (= GREEN_PAGE)
- jr z, .load_square
- hlcoord 17, 5 ; BLUE_PAGE (> GREEN_PAGE)
+ cp PINK_PAGE
+ hlcoord 11, 5
+ jr z, .load_highlighted_square
+ cp GREEN_PAGE
+ hlcoord 13, 5
+ jr z, .load_highlighted_square
+ cp BLUE_PAGE
+ hlcoord 15, 5
+ jr z, .load_highlighted_square
+ ; must be ORANGE_PAGE
+ hlcoord 17, 5
+.load_highlighted_square
+ ld a, $3a ; first of 4 large square tiles
.load_square
push bc
ld [hli], a
inc a
ld [hld], a
ld bc, SCREEN_WIDTH
add hl, bc
inc a
ld [hli], a
inc a
ld [hl], a
pop bc
ret
```
The current page's icon is shown larger than the rest. Apart from changing their coordinates, we also need to update the logic. With only three pages, a single less/equal/greater comparison to the middle page's index was enough to tell which one to highlight, but four pages need more thorough checking.
## 4. Account for the shifted page indexes
Edit [engine/gfx/color.asm](../blob/master/engine/gfx/color.asm):
```diff
LoadStatsScreenPals:
call CheckCGB
ret z
ld hl, StatsScreenPals
ld b, 0
- dec c
add hl, bc
add hl, bc
ldh a, [rSVBK]
push af
ld a, BANK(wBGPals1)
ldh [rSVBK], a
ld a, [hli]
ld [wBGPals1 palette 0], a
ld [wBGPals1 palette 2], a
ld a, [hl]
ld [wBGPals1 palette 0 + 1], a
ld [wBGPals1 palette 2 + 1], a
pop af
ldh [rSVBK], a
call ApplyPals
ld a, $1
ret
```
This function used to adjust the page index in `c` from 1–3 to 0–2. Now that indexes are 0–3, they don't need adjustment.
Now we have a fourth stats page in-game!

## 5. Show Caught Data on the fourth page
This is an alternative `loadOrangePage`, as opposed to the "Hello world!" example earlier. It displays the Caught Location (or "UNKNOWN"), the caught Time (or a blank row if the Caught Location was unknown) as well as the level the Pokémon was met at (or "???").
```diff
+LoadOrangePage:
+ call .placeCaughtLocation
+ ld de, MetAtMapString
+ hlcoord 1, 9
+ call PlaceString
+ call .placeCaughtLevel
+ ret
+
+.placeCaughtLocation
+ ld a, [wTempMonCaughtLocation]
+ and CAUGHT_LOCATION_MASK
+ jr z, .unknown_location
+ cp LANDMARK_EVENT
+ jr z, .unknown_location
+ cp LANDMARK_GIFT
+ jr z, .unknown_location
+ ld e, a
+ farcall GetLandmarkName
+ ld de, wStringBuffer1
+ hlcoord 2, 10
+ call PlaceString
+ ld a, [wTempMonCaughtTime]
+ and CAUGHT_TIME_MASK
+ ret z ; no time
+ rlca
+ rlca
+ dec a
+ ld hl, .times
+ call GetNthString
+ ld d, h
+ ld e, l
+ call CopyName1
+ ld de, wStringBuffer2
+ hlcoord 2, 11
+ call PlaceString
+ ret
+
+.unknown_location:
+ ld de, MetUnknownMapString
+ hlcoord 2, 10
+ call PlaceString
+ ret
+
+.times
+ db "MORN@"
+ db "DAY@"
+ db "NITE@"
+
+.placeCaughtLevel
+ ; caught level
+ ; Limited to between 1 and 63 since it's a 6-bit quantity.
+ ld a, [wTempMonCaughtLevel]
+ and CAUGHT_LEVEL_MASK
+ jr z, .unknown_level
+ cp CAUGHT_EGG_LEVEL ; egg marker value
+ jr nz, .print
+ ld a, EGG_LEVEL ; egg hatch level
+
+.print
+ ld [wTextDecimalByte], a
+ hlcoord 3, 13
+ ld de, wTextDecimalByte
+ lb bc, PRINTNUM_LEFTALIGN | 1, 3
+ call PrintNum
+ ld de, MetAtLevelString
+ hlcoord 1, 12
+ call PlaceString
+ hlcoord 2, 13
+ ld [hl], "<LV>"
+ ret
+
+.unknown_level
+ ld de, MetUnknownLevelString
+ hlcoord 2, 12
+ call PlaceString
+ ret
+
+MetAtMapString:
+ db "MET AT:@"
+
+MetUnknownMapString:
+ db "UNKNOWN@"
+
+MetAtLevelString:
+ db "MET LEVEL:@"
+MetUnknownLevelString:
+ db "???@"
```
|