This tutorial is for how to add a new Pack pocket. As an example, we'll add a Berry Pocket.
## Contents
1. [Define pocket-related constants](#1-define-pocket-related-constants)
2. [Give the pocket a name](#2-give-the-pocket-a-name)
3. [Update the item types](#3-update-the-item-types)
4. [Update the Pack graphics](#4-update-the-pack-graphics)
5. [Add space in WRAM for the new pocket](#5-add-space-in-wram-for-the-new-pocket)
6. [Initialize the new WRAM](#6-initialize-the-new-wram)
7. [Update `HasNoItems` and `CheckRegisteredItem` to check the new pocket](#7-update-hasnoitems-and-checkregistereditem-to-check-the-new-pocket)
8. [Update standard inventory routines](#8-update-standard-inventory-routines)
9. [Update the Pack engine](#9-update-the-pack-engine)
10. [Update the Crystal-only Pack engine](#10-update-the-crystal-only-pack-engine)
11. [Update Kurt's Apricorn script](#11-update-kurts-apricorn-script)
12. [Fix build errors](#12-fix-build-errors)
## 1. Define pocket-related constants
Edit [constants/item_data_constants.asm](../blob/master/constants/item_data_constants.asm):
```diff
; item types
const_def 1
const ITEM ; 1
const KEY_ITEM ; 2
const BALL ; 3
const TM_HM ; 4
+ const BERRIES ; 5
...
; pack pockets
const_def
const ITEM_POCKET ; 0
const BALL_POCKET ; 1
const KEY_ITEM_POCKET ; 2
const TM_HM_POCKET ; 3
+ const BERRY_POCKET ; 4
NUM_POCKETS EQU const_value
MAX_ITEMS EQU 20
MAX_BALLS EQU 12
MAX_KEY_ITEMS EQU 25
MAX_PC_ITEMS EQU 50
+MAX_BERRIES EQU 17
```
Notice that the "item types" constants are in a different order than the "pack pockets" constants. So don't mix them up. Also we name the item type "`BERRIES`" because "`BERRY`" is an item, so don't mix those up either.
The `MAX_*` constants are the storage capacities of their respective pockets. We defined `MAX_BERRIES` as 17 because there are 17 items that will go in the Berry pocket, as we'll see later; that way you can conveniently carry one stack of each Berry. (Likewise, `MAX_BALLS` is 12, and 12 items belong in the Ball pocket.)
## 2. Give the pocket a name
Edit [data/items/pocket_names.asm](../blob/master/data/items/pocket_names.asm):
```diff
ItemPocketNames:
; entries correspond to item type constants
dw .Item
dw .Key
dw .Ball
dw .TM
+ dw .Berry
.Item: db "ITEM POCKET@"
.Key: db "KEY POCKET@"
.Ball: db "BALL POCKET@"
.TM: db "TM POCKET@"
+.Berry: db "BERRY POCKET@"
```
The phrase "`the BERRY POCKET.`" has to fit on one line for the message "*PLAYER* put the *ITEM* in the *POCKET*." So a pocket name can be up to 13 characters long, plus a "@" at the end.
## 3. Update the item types
Edit [data/items/attributes.asm](../blob/master/data/items/attributes.asm), changing the relevant items' types from `ITEM` to `BERRIES`:
- `BERRY`
- `GOLD_BERRY`
- `PSNCUREBERRY`
- `PRZCUREBERRY`
- `BURNT_BERRY`
- `ICE_BERRY`
- `BITTER_BERRY`
- `MINT_BERRY`
- `MIRACLEBERRY`
- `MYSTERYBERRY`
- `RED_APRICORN`
- `BLU_APRICORN`
- `YLW_APRICORN`
- `GRN_APRICORN`
- `WHT_APRICORN`
- `BLK_APRICORN`
- `PNK_APRICORN`
Note that all of these items have the `CANT_SELECT` property. The only items without it are `BICYCLE`, `ITEMFINDER`, `OLD_ROD`, `GOOD_ROD`, and `SUPER_ROD`, which are all Key Items. I haven't tried creating a non–Key Item that can be registered to the Select button, but suspect that it would cause glitches.
## 4. Update the Pack graphics
Edit [gfx/pack/pack.png](../blob/master/gfx/pack/pack.png):

Edit [gfx/pack/pack_f.png](../blob/master/gfx/pack/pack_f.png):

And edit [gfx/pack/pack_menu.png](../blob/master/gfx/pack/pack_menu.png):

The pack.png and pack_f.png graphics are in this order, from top to bottom: Key Items, Items, TM/HM, Balls. We've split the Ball pocket in half and turned the right half into a Berry pocket, with its graphic appended to the bottom of the image. (Note that this doesn't match the order of either set of constants. We'll see later that the offsets of each pocket's individual picture are hard-coded in a table, not calculated directly from a constant.)
The pack_menu.png graphic is a set of 80 tiles in no particular order, except for the 20 sequential tiles that form the "`◀▶ POCKET ▼▲ ITEMS`" header. We've added the new "Berries" subtitle sequentially, but that's just to be neat; we'll see later that the individual tiles of the subtitles are all hard-coded, so you can fit them into any of the unused tiles in the original:

## 5. Add space in WRAM for the new pocket
Edit [wram.asm](../blob/master/wram.asm):
```diff
wPCItemsCursor:: db
wPartyMenuCursor:: db
wItemsPocketCursor:: db
wKeyItemsPocketCursor:: db
wBallsPocketCursor:: db
wTMHMPocketCursor:: db
+wBerryPocketCursor:: db
wPCItemsScrollPosition:: db
wPartyMenuScrollPosition:: db ; unused
wItemsPocketScrollPosition:: db
wKeyItemsPocketScrollPosition:: db
wBallsPocketScrollPosition:: db
wTMHMPocketScrollPosition:: db
+wBerryPocketScrollPosition:: db
...
+wDudeNumBerries::
wDudeNumKeyItems:: db ; d292
wDudeKeyItems:: ds 18
wDudeKeyItemsEnd:: db
...
wCmdQueue:: ds CMDQUEUE_CAPACITY * CMDQUEUE_ENTRY_SIZE
- ds 40
...
wNumBalls:: db ; d8d7
wBalls:: ds MAX_BALLS * 2 + 1 ; d8d8
wBallsEnd::
+wNumBerries:: db
+wBerries:: ds MAX_BERRIES * 2 + 1
+wBerriesEnd::
```
Every pocket has a wNamePocketCursor
and a wNamePocketScrollPosition
byte for scrolling through it, a wNumNames
byte that stores how many items are in it, and a wNames
–wNamesEnd
array for storing its items. `wTMsHMs` and `wKeyItems` are special, but normal item-storage pockets like `wItems` and `wBalls` have two bytes per possible item (one for the ID, one for the quantity) plus a byte for the end-of-list marker.
`wDudeNumBerries` just shares space with `wDudeNumKeyItems` because the catch tutorial dude only shows his Item and Ball pockets. It's probably possible to remove the data and code for his Key Item pocket entirely, but that's beyond the scope of this tutorial, and not necessary unless you really need some extra space.
Speaking of extra space: we used a total of 37 more WRAM bytes for the Berry pocket's data. Its WRAM bank has barely any free space left, so in general you'll need to remove as many bytes as you add. There was an unused `ds 40` that conveniently saved 40 bytes. If you want larger pockets and need to free up more space, shortly below the pockets is an unused `ds 13`, then `ds 49` after the wMapNameSceneID
bytes, then `ds 100` after the wTrainerFightCount
bytes, and a `ds 23` after `wPhoneList`. Any of those can be reduced to make more room for Pack pockets (or for more map scene IDs, or extending `wEventFlags` if you raise `NUM_EVENTS`, or so on).
## 6. Initialize the new WRAM
Edit [engine/menus/intro_menu.asm](../blob/master/engine/menus/intro_menu.asm):
```diff
ld hl, wNumItems
call .InitList
ld hl, wNumKeyItems
call .InitList
ld hl, wNumBalls
call .InitList
+
+ ld hl, wNumBerries
+ call .InitList
ld hl, wNumPCItems
call .InitList
```
As the `.InitList` comment explains, this "loads 0 in the count and −1 in the first item slot."
## 7. Update `HasNoItems` and `CheckRegisteredItem` to check the new pocket
Edit [engine/pokemon/mon_menu.asm](../blob/master/engine/pokemon/mon_menu.asm) (or [engine/menus/start_menu.asm](../blob/master/engine/menus/start_menu.asm) in older versions of pokecrystal):
```diff
HasNoItems:
ld a, [wNumItems]
and a
ret nz
ld a, [wNumKeyItems]
and a
ret nz
ld a, [wNumBalls]
and a
ret nz
+ ld a, [wNumBerries]
+ and a
+ ret nz
ld hl, wTMsHMs
ld b, NUM_TMS + NUM_HMS
.loop
ld a, [hli]
and a
jr nz, .done
dec b
jr nz, .loop
scf
ret
.done
and a
ret
```
Now edit [engine/overworld/select_menu.asm](../blob/master/engine/overworld/select_menu.asm):
```diff
.Pockets:
; entries correspond to *_POCKET constants
dw .CheckItem
dw .CheckBall
dw .CheckKeyItem
dw .CheckTMHM
+ dw .CheckBerry
...
.CheckBall:
ld hl, wNumBalls
+.StandardCheck:
call .CheckRegisteredNo
jr nc, .NoRegisteredItem
inc hl
ld e, a
ld d, 0
add hl, de
add hl, de
call .IsSameItem
jr c, .NoRegisteredItem
ret
+
+.CheckBerry:
+ ld hl, wNumBerries
+ jr .StandardCheck
```
There's no such thing as a Ball or Berry that can be registered, so I haven't actually tested this code; if there's a bug with the built-in handling of registered Balls, it will also apply to Berries. You're better off leaving Key Items as the only type that can be registered.
## 8. Update standard inventory routines
Edit [engine/items/items.asm](../blob/master/engine/items/items.asm). Four routines here need updating, so let's take them one by one.
Edit `_ReceiveItem`:
```diff
_ReceiveItem::
...
.Pockets:
; entries correspond to item types
dw .Item
dw .KeyItem
dw .Ball
dw .TMHM
+ dw .Berry
...
.Ball:
ld hl, wNumBalls
jp PutItemInPocket
+
+.Berry:
+ ld hl, wNumBerries
+ jp PutItemInPocket
```
Edit `_TossItem`:
```diff
_TossItem::
...
.Pockets:
; entries correspond to item types
dw .Item
dw .KeyItem
dw .Ball
dw .TMHM
+ dw .Berry
.Ball:
ld hl, wNumBalls
jp RemoveItemFromPocket
+
+.Berry:
+ ld hl, wNumBerries
+ jp RemoveItemFromPocket
```
Edit `_CheckItem`:
```diff
_CheckItem::
...
.Pockets:
; entries correspond to item types
dw .Item
dw .KeyItem
dw .Ball
dw .TMHM
+ dw .Berry
.Ball:
ld hl, wNumBalls
jp CheckTheItem
+
+.Berry:
+ ld hl, wNumBerries
+ jp CheckTheItem
```
And edit `GetPocketCapacity`:
```diff
GetPocketCapacity:
ld c, MAX_ITEMS
ld a, e
cp LOW(wNumItems)
jr nz, .not_bag
ld a, d
cp HIGH(wNumItems)
ret z
.not_bag
ld c, MAX_PC_ITEMS
ld a, e
cp LOW(wNumPCItems)
jr nz, .not_pc
ld a, d
cp HIGH(wNumPCItems)
ret z
.not_pc
+ ld c, MAX_BERRIES
+ ld a, e
+ cp LOW(wBerries)
+ jr nz, .not_berries
+ ld a, d
+ cp HIGH(wNumBerries)
+ ret z
+
+.not_berries
ld c, MAX_BALLS
ret
```
In most of these cases we just based the Berry pocket case on the Ball pocket case. The TM/HM and Key Item pockets are special, and the Item pocket is sometimes treated as a "default" case with different handling. But the Ball pocket is non-default and just stores regular items, so it's safe to copy.
## 9. Update the Pack engine
We've saved editing the longest file for last: [engine/items/pack.asm](../blob/master/engine/items/pack.asm). Let's go over it piece by piece. (Don't worry, a lot of it is just copy+pasting chunks of code with the word "Berry" substituted for "Ball" or "Item".)
```diff
; Pack.Jumptable and BattlePack.Jumptable indexes
const_def
const PACKSTATE_INITGFX ; 0
const PACKSTATE_INITITEMSPOCKET ; 1
const PACKSTATE_ITEMSPOCKETMENU ; 2
const PACKSTATE_INITBALLSPOCKET ; 3
const PACKSTATE_BALLSPOCKETMENU ; 4
const PACKSTATE_INITKEYITEMSPOCKET ; 5
const PACKSTATE_KEYITEMSPOCKETMENU ; 6
const PACKSTATE_INITTMHMPOCKET ; 7
const PACKSTATE_TMHMPOCKETMENU ; 8
+ const PACKSTATE_INITBERRYPOCKET
+ const PACKSTATE_BERRYPOCKETMENU
const PACKSTATE_QUITNOSCRIPT ; 9
const PACKSTATE_QUITRUNSCRIPT ; 10
```
These are jumptable indexes. Jumptables are a common design pattern you'll see for interfaces with a lot of different states and transitions between states, like the Pokédex and Pokégear. In general, there's a table of pointers corresponding to these index constants, and each pointer is to a different subroutine. Control jumps to whichever pointer corresponds to the value in `wJumptableIndex`, which usually starts at 0. Each subroutine can change `wJumptableIndex`, often by incrementing it to automatically reach the next state in the table, or by setting particular values depending on which buttons are pressed.
Notice the pattern to this table: for each pocket, there's a `PACKSTATE_INIT*POCKET` state followed by a `PACKSTATE_*POCKETMENU` state. They happen to be in the same order as the `*_POCKET` constants, although that isn't actually significant; all that matters is that the default pocket be the first one (since the `PACKSTATE_INITGFX` state increments `wJumptableIndex` and advances to the next state, which should thus be the default pocket's `INIT` state).
```diff
Pack:
...
.Jumptable:
; entries correspond to PACKSTATE_* constants
dw .InitGFX ; 0
dw .InitItemsPocket ; 1
dw .ItemsPocketMenu ; 2
dw .InitBallsPocket ; 3
dw .BallsPocketMenu ; 4
dw .InitKeyItemsPocket ; 5
dw .KeyItemsPocketMenu ; 6
dw .InitTMHMPocket ; 7
dw .TMHMPocketMenu ; 8
+ dw .InitBerryPocket
+ dw .BerryPocketMenu
dw Pack_QuitNoScript ; 9
dw Pack_QuitRunScript ; 10
```
Here's the first jumptable corresponding to those constants. It's the "core" jumptable for when you enter the Pack via the Start Menu.
```diff
.KeyItemsPocketMenu:
...
- ld b, PACKSTATE_INITBALLSPOCKET ; left
+ ld b, PACKSTATE_INITBERRYPOCKET ; left
ld c, PACKSTATE_INITTMHMPOCKET ; right
call Pack_InterpretJoypad
ret c
call .ItemBallsKey_LoadSubmenu
ret
...
.InitBallsPocket:
ld a, BALL_POCKET
ld [wCurPocket], a
call ClearPocketList
call DrawPocketName
call WaitBGMap_DrawPackGFX
call Pack_JumptableNext
ret
.BallsPocketMenu:
ld hl, BallsPocketMenuHeader
call CopyMenuHeader
ld a, [wBallsPocketCursor]
ld [wMenuCursorPosition], a
ld a, [wBallsPocketScrollPosition]
ld [wMenuScrollPosition], a
call ScrollingMenu
ld a, [wMenuScrollPosition]
ld [wBallsPocketScrollPosition], a
ld a, [wMenuCursorY]
ld [wBallsPocketCursor], a
ld b, PACKSTATE_INITITEMSPOCKET ; left
- ld c, PACKSTATE_INITKEYITEMSPOCKET ; right
+ ld c, PACKSTATE_INITBERRYPOCKET ; right
call Pack_InterpretJoypad
ret c
call .ItemBallsKey_LoadSubmenu
ret
+
+.InitBerryPocket:
+ ld a, BERRY_POCKET
+ ld [wCurPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.BerryPocketMenu:
+ ld hl, BerryPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBerryPocketCursor]
+ ld [wMenuCursorPosition], a
+ ld a, [wBerryPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wBerryPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wBerryPocketCursor], a
+ ld b, PACKSTATE_INITBALLSPOCKET ; left
+ ld c, PACKSTATE_INITKEYITEMSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call .ItemBallsKey_LoadSubmenu
+ ret
```
We're doing two things here.
One, we insert the Berry pocket in-between the Ball and Key Item pockets. Originally you can scroll left and right through the pockets in order: Items ↔ Balls ↔ Key Items ↔ TM/HM ↔ Items again. This is done by explicitly hard-coding each pocket's left and right ones. So the Berry pocket just had to be coded in.
Two, we actually write the subroutines that we just added pointers to in the jumptable. Really they're just copy+pasted from the Ball pocket's subroutines, but with "Berry" substituted for "Ball". (As we discussed earlier, the Ball pocket is safe to use as a base, since it stores regular items and isn't a default like the Items pocket.)
```diff
BattlePack:
...
.Jumptable:
; entries correspond to PACKSTATE_* constants
dw .InitGFX ; 0
dw .InitItemsPocket ; 1
dw .ItemsPocketMenu ; 2
dw .InitBallsPocket ; 3
dw .BallsPocketMenu ; 4
dw .InitKeyItemsPocket ; 5
dw .KeyItemsPocketMenu ; 6
dw .InitTMHMPocket ; 7
dw .TMHMPocketMenu ; 8
+ dw .InitBerryPocket
+ dw .BerryPocketMenu
dw Pack_QuitNoScript ; 9
dw Pack_QuitRunScript ; 10
```
This is another jumptable, but for using the Pack during battle. Again, we add pointers for the Berry pocket, and will next have to define them.
```diff
.KeyItemsPocketMenu:
...
- ld b, PACKSTATE_INITBALLSPOCKET ; left
+ ld b, PACKSTATE_INITBERRYPOCKET ; left
ld c, PACKSTATE_INITTMHMPOCKET ; right
call Pack_InterpretJoypad
ret c
call ItemSubmenu
ret
...
.InitBallsPocket:
ld a, BALL_POCKET
ld [wCurPocket], a
call ClearPocketList
call DrawPocketName
call WaitBGMap_DrawPackGFX
call Pack_JumptableNext
ret
.BallsPocketMenu:
ld hl, BallsPocketMenuHeader
call CopyMenuHeader
ld a, [wBallsPocketCursor]
ld [wMenuCursorPosition], a
ld a, [wBallsPocketScrollPosition]
ld [wMenuScrollPosition], a
call ScrollingMenu
ld a, [wMenuScrollPosition]
ld [wBallsPocketScrollPosition], a
ld a, [wMenuCursorY]
ld [wBallsPocketCursor], a
ld b, PACKSTATE_INITITEMSPOCKET ; left
- ld c, PACKSTATE_INITKEYITEMSPOCKET ; right
+ ld c, PACKSTATE_INITBERRYPOCKET ; right
call Pack_InterpretJoypad
ret c
call ItemSubmenu
ret
+
+.InitBerryPocket:
+ ld a, BERRY_POCKET
+ ld [wCurPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+.BerryPocketMenu:
+ ld hl, BerryPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBerryPocketCursor]
+ ld [wMenuCursorPosition], a
+ ld a, [wBerryPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wBerryPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wBerryPocketCursor], a
+ ld b, PACKSTATE_INITBALLSPOCKET ; left
+ ld c, PACKSTATE_INITKEYITEMSPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call ItemSubmenu
+ ret
```
Just like before, we insert the Berry pocket between the Ball and Key Item pockets, and base the Berry pocket's subroutines on the pre-existing Ball pocket ones.
```diff
DepositSellPack:
...
.Jumptable:
; entries correspond to *_POCKET constants
dw .ItemsPocket
dw .BallsPocket
dw .KeyItemsPocket
dw .TMHMPocket
+ dw .BerryPocket
...
.BallsPocket:
ld a, BALL_POCKET
call InitPocket
ld hl, PC_Mart_BallsPocketMenuHeader
call CopyMenuHeader
ld a, [wBallsPocketCursor]
ld [wMenuCursorPosition], a
ld a, [wBallsPocketScrollPosition]
ld [wMenuScrollPosition], a
call ScrollingMenu
ld a, [wMenuScrollPosition]
ld [wBallsPocketScrollPosition], a
ld a, [wMenuCursorY]
ld [wBallsPocketCursor], a
ret
+
+.BerryPocket:
+ ld a, BERRY_POCKET
+ call InitPocket
+ ld hl, PC_Mart_BerryPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBerryPocketCursor]
+ ld [wMenuCursorPosition], a
+ ld a, [wBerryPocketScrollPosition]
+ ld [wMenuScrollPosition], a
+ call ScrollingMenu
+ ld a, [wMenuScrollPosition]
+ ld [wBerryPocketScrollPosition], a
+ ld a, [wMenuCursorY]
+ ld [wBerryPocketCursor], a
+ ret
```
Here's a jumptable for when the Pack is opened to deposit or sell an item; it has entries for each individual pocket, less complicated than the previous jumptables with their intermediate `INIT` states. As usual, we just look at how the other pockets work and do what they do but with the word "Berry" in the right places.
```diff
.d_left
ld a, [wJumptableIndex]
dec a
- maskbits NUM_POCKETS
+ cp -1
+ jr nz, .left_ok
+ ld a, NUM_POCKETS - 1
+.left_ok
ld [wJumptableIndex], a
push de
ld de, SFX_SWITCH_POCKETS
call PlaySFX
pop de
scf
ret
.d_right
ld a, [wJumptableIndex]
inc a
- maskbits NUM_POCKETS
+ cp NUM_POCKETS
+ jr nz, .right_ok
+ xor a
+.right_ok
ld [wJumptableIndex], a
push de
ld de, SFX_SWITCH_POCKETS
call PlaySFX
pop de
scf
ret
```
This is somewhat tricky to notice. Here the code is decrementing or incrementing `wJumptableIndex` (that is, subtracting or adding 1) when you press Left or Right. But doing that can go beyond the valid range, since it might decrement the minimum or increment the maximum. When there were only four pockets, they neatly took up two bits, so a bitmask could be used to efficiently clamp them within the valid range. But five pockets requires more explicit checks so that the minimum and maximum values (0 and `NUM_POCKETS` − 1) wrap around.
```diff
TutorialPack:
...
.dw
; entries correspond to *_POCKET constants
dw .Items
dw .Balls
dw .KeyItems
dw .TMHM
+ dw .Berries
...
.Balls:
ld a, BALL_POCKET
ld hl, .BallsMenuHeader
jr .DisplayPocket
.BallsMenuHeader:
db MENU_BACKUP_TILES ; flags
menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
dw .BallsMenuData
db 1 ; default option
.BallsMenuData:
db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
db 5, 8 ; rows, columns
db 2 ; horizontal spacing
dbw 0, wDudeNumBalls
dba PlaceMenuItemName
dba PlaceMenuItemQuantity
dba UpdateItemDescription
+
+.Berries:
+ ld a, BERRY_POCKET
+ ld hl, .BerriesMenuHeader
+ jr .DisplayPocket
+
+.BerriesMenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .BerriesMenuData
+ db 1 ; default option
+
+.BerriesMenuData:
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wDudeNumBerries
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
```
Another jumptable, this time used by the catch tutorial dude. Once again, we just add an entry to the jumptable for the Berry pocket and base its code and data on whatever the Ball pocket does.
```diff
PackGFXPointers:
dw PackGFX + (15 tiles) * 1 ; ITEM_POCKET
dw PackGFX + (15 tiles) * 3 ; BALL_POCKET
dw PackGFX + (15 tiles) * 0 ; KEY_ITEM_POCKET
dw PackGFX + (15 tiles) * 2 ; TM_HM_POCKET
+ dw PackGFX + (15 tiles) * 4 ; BERRY_POCKET
```
This is a table of pointers to the individual highlighted pocket pictures in pack.png and pack_f.png. Remember how they were out of order compared to the constants? That's why this table is necessary. For example, the first (#0) picture was of the Key Item pocket, and `KEY_ITEM_POCKET` is 2, so the third (#2) entry here points to the first picture. Anyway, all we have to do is add a pointer for the Berry pocket again.
```diff
.tilemap
; ITEM_POCKET
db $00, $04, $04, $04, $01 ; top border
db $06, $07, $08, $09, $0a ; Items
db $02, $05, $05, $05, $03 ; bottom border
; BALL_POCKET
db $00, $04, $04, $04, $01 ; top border
db $15, $16, $17, $18, $19 ; Balls
db $02, $05, $05, $05, $03 ; bottom border
; KEY_ITEM_POCKET
db $00, $04, $04, $04, $01 ; top border
db $0b, $0c, $0d, $0e, $0f ; Key Items
db $02, $05, $05, $05, $03 ; bottom border
; TM_HM_POCKET
db $00, $04, $04, $04, $01 ; top border
db $10, $11, $12, $13, $14 ; TM/HM
db $02, $05, $05, $05, $03 ; bottom border
+; BERRY_POCKET
+ db $00, $04, $04, $04, $01 ; top border
+ db $1a, $1b, $1c, $1d, $1e ; Berries
+ db $02, $05, $05, $05, $03 ; bottom border
```
These are tilemaps for the pocket name labels in pack_menu.png. Each one is three rows of five tiles each, with tile indexes starting at 0. Take a look at pack_menu.png and notice how the hexadecimal indexes here correspond to tiles that form sensible pictures.
```diff
BallsPocketMenuHeader:
db MENU_BACKUP_TILES ; flags
menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
dw .MenuData
db 1 ; default option
.MenuData:
db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
db 5, 8 ; rows, columns
db SCROLLINGMENU_ITEMS_QUANTITY ; item format
dbw 0, wNumBalls
dba PlaceMenuItemName
dba PlaceMenuItemQuantity
dba UpdateItemDescription
PC_Mart_BallsPocketMenuHeader:
db MENU_BACKUP_TILES ; flags
menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
dw .MenuData
db 1 ; default option
.MenuData:
db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags
db 5, 8 ; rows, columns
db SCROLLINGMENU_ITEMS_QUANTITY ; item format
dbw 0, wNumBalls
dba PlaceMenuItemName
dba PlaceMenuItemQuantity
dba UpdateItemDescription
+
+BerryPocketMenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData:
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP | STATICMENU_CURSOR ; flags
+ db 5, 8 ; rows, columns
+ db SCROLLINGMENU_ITEMS_QUANTITY ; item format
+ dbw 0, wNumBerries
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+
+PC_Mart_BerryPocketMenuHeader:
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+
+.MenuData:
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags
+ db 5, 8 ; rows, columns
+ db SCROLLINGMENU_ITEMS_QUANTITY ; item format
+ dbw 0, wNumBerries
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
```
We saw `BallsPocketMenuHeader` used in the subroutines for the Start Menu Pack and the battle Pack, and `PC_Mart_BallsPocketMenuHeader` in the subroutine for the Pack when depositing or selling. Here they're finally being defined. And since we created the corresponding names `BerryPocketMenuHeader` and `PC_Mart_BerryPocketMenuHeader`, they need defining too; as usual, we can just copy whatever the Ball pocket does and substitute "Berry" for "Ball".
## 10. Update the Crystal-only Pack engine
Edit [engine/items/pack_kris.asm](../blob/master/engine/items/pack_kris.asm):
```diff
PackFGFXPointers:
dw PackFGFX + (15 tiles) * 1 ; ITEM_POCKET
dw PackFGFX + (15 tiles) * 3 ; BALL_POCKET
dw PackFGFX + (15 tiles) * 0 ; KEY_ITEM_POCKET
dw PackFGFX + (15 tiles) * 2 ; TM_HM_POCKET
+ dw PackFGFX + (15 tiles) * 4 ; BERRY_POCKET
```
This is just like `PackGFXPointers`, but for the Crystal-only girl's Pack.
## 11. Update Kurt's Apricorn script
If you did not change the Apricorns' pocket, then skip this step.
Kurt's script to turn Apricorns into Balls assumes they're still in the Item pocket. Fixing this is thankfully quick and easy. Edit [engine/events/kurt.asm](../blob/master/engine/events/kurt.asm). There are *five* places in the code where we need to do this:
```diff
- ld hl, wNumItems
+ ld hl, wNumBerries
```
1. `Kurt_GetQuantityOfApricorn`
2. `Kurt_GiveUpSelectedQuantityOfSelectedApricorn`
3. `Kurt_GetAddressOfApricornQuantity`
4. `Kurt_GetRidOfItem`
5. `Kurt_GetRidOfItem.okay`
Just use your text editor to find all five occurrences of "`wNumItems`" in the file, and make that one-line change to all of them.
## 12. Fix build errors
We're almost finished, but if you run `make` now, it gives an error:
```
error: engine/items/pack.asm(1243) : Value must be 8-bit
```
Line 1243 of [engine/items/pack.asm](../blob/master/engine/items/pack.asm) is `jr .DisplayPocket`.
So, `jr` and `jp` both jump to the given label. But `jp` encodes the full two-byte address of the label, while `jr` saves a byte by encoding a one-byte distance to jump. That means it can only reach −128 to 127 bytes away from its own location. Some of the code we added must have made `.DisplayPocket` more than 128 bytes away from this `jr` instruction. Anyway, the solution is simple: change it to `jp`.
```diff
TutorialPack:
...
.Items:
xor a ; ITEM_POCKET
ld hl, .ItemsMenuHeader
- jr .DisplayPocket
+ jp .DisplayPocket
```
(If you're adding more pockets, you might have more errors like this.)
We're finally done!

There are many other pockets you could add. Gen 4 had Medicine, Mail, and Battle pockets; there could also be a separate pocket for held items, or for a new type of item entirely.