summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Add-a-new-Pack-pocket.md510
1 files changed, 500 insertions, 10 deletions
diff --git a/Add-a-new-Pack-pocket.md b/Add-a-new-Pack-pocket.md
index 20ca578..6a655e5 100644
--- a/Add-a-new-Pack-pocket.md
+++ b/Add-a-new-Pack-pocket.md
@@ -13,6 +13,7 @@ This tutorial is for how to add a new Pack pocket. As an example, we'll add a Be
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. [Fix build errors](#11-fix-build-errors)
## 1. Define pocket-related constants
@@ -76,7 +77,7 @@ The phrase "`the BERRY POCKET.`" has to fit on one line for the message "*PLAYER
## 3. Update the item types
-Edit the types in [data/items/attributes.asm](../blob/master/data/items/attributes.asm), changing the relevant items from `ITEM` to `BERRIES`:
+Edit [data/items/attributes.asm](../blob/master/data/items/attributes.asm), changing the relevant items' types from `ITEM` to `BERRIES`:
- `BERRY`
- `GOLD_BERRY`
@@ -96,7 +97,7 @@ Edit the types in [data/items/attributes.asm](../blob/master/data/items/attribut
- `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.
+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
@@ -113,9 +114,9 @@ And edit [gfx/pack/pack_menu.png](../blob/master/gfx/pack/pack_menu.png):
![gfx/pack/pack_menu.png](screenshots/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 Balls 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.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:
+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:
![gfx/pack/pack_menu.png](screenshots/unused-pack_menu-tiles.png)
@@ -169,7 +170,7 @@ Every pocket has a <code>w<i>Name</i>PocketCursor</code> and a <code>w<i>Name</i
`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 <code>w<i>MapName</i>SceneID</code> bytes, then "`ds 100`" after the <code>w<i>Trainer</i>FightCount</code> 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).
+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 <code>w<i>MapName</i>SceneID</code> bytes, then `ds 100` after the <code>w<i>Trainer</i>FightCount</code> 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
@@ -196,7 +197,7 @@ Edit [engine/menus/intro_menu.asm](../blob/master/engine/menus/intro_menu.asm):
As the `.InitList` comment explains, this "loads 0 in the count and −1 in the first item slot."
-## 7. Update `HasNoItems` to check the new pocket
+## 7. Update `HasNoItems` and `CheckRegisteredItem` to check the new pocket
Edit [engine/menus/start_menu.asm](../blob/master/engine/menus/start_menu.asm):
@@ -261,7 +262,7 @@ Now edit [engine/overworld/select_menu.asm](../blob/master/engine/overworld/sele
+ 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.
+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
@@ -379,14 +380,477 @@ In most of these cases we just based the Berry pocket case on the Ball pocket ca
## 9. Update the Pack engine
-Edit [engine/items/pack.asm](../blob/master/engine/items/pack.asm). This will take a while. My own procedure was to carefully go down the file, noticing repetitive lines that handle each pocket case by case, and adding similar cases for the Berry pocket. There are also a few tricky parts where the code is optimized for having exactly four pockets (a nice round power of 2), so adding a fifth needs some extra code.
+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.
-TODO
+```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
+```
+
+TODO: Explain.
+
+```diff
+ Pack: ; 10000
+ ...
+
+ .Jumptable: ; 10030 (4:4030)
+ ; 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
+```
+
+TODO: Explain.
+
+```diff
+ .KeyItemsPocketMenu: ; 100a6 (4:40a6)
+ ...
+- 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: ; 10186 (4:4186)
+ ld a, BALL_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+ .BallsPocketMenu: ; 10198 (4:4198)
+ ld hl, BallsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBallsPocketCursor]
+ ld [wMenuCursorBuffer], 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 [wCurrPocket], a
++ call ClearPocketList
++ call DrawPocketName
++ call WaitBGMap_DrawPackGFX
++ call Pack_JumptableNext
++ ret
++
++.BerryPocketMenu:
++ ld hl, BerryPocketMenuHeader
++ call CopyMenuHeader
++ ld a, [wBerryPocketCursor]
++ ld [wMenuCursorBuffer], 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
+```
+
+TODO: Explain.
+
+```diff
+ BattlePack: ; 10493
+ ...
+
+ .Jumptable: ; 104c3 (4:44c3)
+ ; 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
+```
+
+TODO: Explain.
+
+```diff
+ .KeyItemsPocketMenu: ; 10539 (4:4539)
+ ...
+- ld b, PACKSTATE_INITBALLSPOCKET ; left
++ ld b, PACKSTATE_INITBERRYPOCKET ; left
+ ld c, PACKSTATE_INITTMHMPOCKET ; right
+ call Pack_InterpretJoypad
+ ret c
+ call ItemSubmenu
+ ret
+
+ ...
+
+ .InitBallsPocket: ; 10594 (4:4594)
+ ld a, BALL_POCKET
+ ld [wCurrPocket], a
+ call ClearPocketList
+ call DrawPocketName
+ call WaitBGMap_DrawPackGFX
+ call Pack_JumptableNext
+ ret
+
+ .BallsPocketMenu: ; 105a6 (4:45a6)
+ ld hl, BallsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBallsPocketCursor]
+ ld [wMenuCursorBuffer], 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 [wCurrPocket], a
++ call ClearPocketList
++ call DrawPocketName
++ call WaitBGMap_DrawPackGFX
++ call Pack_JumptableNext
++ ret
++
++.BerryPocketMenu:
++ ld hl, BerryPocketMenuHeader
++ call CopyMenuHeader
++ ld a, [wBerryPocketCursor]
++ ld [wMenuCursorBuffer], 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
+```
+
+TODO: Explain.
+
+```diff
+ DepositSellPack: ; 106be
+ ...
+
+ .Jumptable: ; 106d1 (4:46d1)
+ ; entries correspond to *_POCKET constants
+ dw .ItemsPocket
+ dw .BallsPocket
+ dw .KeyItemsPocket
+ dw .TMHMPocket
++ dw .BerryPocket
+
+ ...
+
+ .BallsPocket: ; 1073b (4:473b)
+ ld a, BALL_POCKET
+ call InitPocket
+ ld hl, PC_Mart_BallsPocketMenuHeader
+ call CopyMenuHeader
+ ld a, [wBallsPocketCursor]
+ ld [wMenuCursorBuffer], 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 [wMenuCursorBuffer], a
++ ld a, [wBerryPocketScrollPosition]
++ ld [wMenuScrollPosition], a
++ call ScrollingMenu
++ ld a, [wMenuScrollPosition]
++ ld [wBerryPocketScrollPosition], a
++ ld a, [wMenuCursorY]
++ ld [wBerryPocketCursor], a
++ ret
+```
+
+TODO: Explain.
+
+```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
+```
+
+TODO: Explain.
+
+```diff
+ TutorialPack: ; 107bb
+ ...
+
+ .dw ; 107e1 (4:47e1)
+ ; entries correspond to *_POCKET constants
+ dw .Items
+ dw .Balls
+ dw .KeyItems
+ dw .TMHM
++ dw .Berries
+
+ ...
+
+ .Balls: ; 1083b (4:483b)
+ ld a, BALL_POCKET
+ ld hl, .BallsMenuHeader
+ jr .DisplayPocket
+
+ ; 10842 (4:4842)
+ .BallsMenuHeader: ; 0x10842
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .BallsMenuData
+ db 1 ; default option
+ ; 0x1084a
+
+ .BallsMenuData: ; 0x1084a
+ 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
+ ; 1085a
++
++.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
++; 0x107f7
++
++.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
+```
+
+TODO: Explain.
+
+```diff
+ PackGFXPointers: ; 108cc
+ 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
+ ; 108d4
+```
+
+TODO: Explain.
+
+```diff
+ .tilemap ; 109e1
+ ; 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
+ ; 10a1d
+```
+
+TODO: Explain.
+
+```diff
+ BallsPocketMenuHeader: ; 0x10aaf
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+ ; 0x10ab7
+
+ .MenuData: ; 0x10ab7
+ 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, wNumBalls
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+ ; 10ac7
+
+ PC_Mart_BallsPocketMenuHeader: ; 0x10ac7
+ db MENU_BACKUP_TILES ; flags
+ menu_coords 7, 1, SCREEN_WIDTH - 1, TEXTBOX_Y - 1
+ dw .MenuData
+ db 1 ; default option
+ ; 0x10acf
+
+ .MenuData: ; 0x10acf
+ db STATICMENU_ENABLE_SELECT | STATICMENU_ENABLE_LEFT_RIGHT | STATICMENU_ENABLE_START | STATICMENU_WRAP ; flags
+ db 5, 8 ; rows, columns
+ db 2 ; horizontal spacing
+ dbw 0, wNumBalls
+ dba PlaceMenuItemName
+ dba PlaceMenuItemQuantity
+ dba UpdateItemDescription
+ ; 10adf
++
++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 2 ; horizontal spacing
++ 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 2 ; horizontal spacing
++ dbw 0, wNumBerries
++ dba PlaceMenuItemName
++ dba PlaceMenuItemQuantity
++ dba UpdateItemDescription
+```
+
+TODO: Explain.
## 10. Update the Crystal-only Pack engine
-Edit [engine/items/pack_kris.asm](../blob/master/engine/items/pack_kris.asm).
+Edit [engine/items/pack_kris.asm](../blob/master/engine/items/pack_kris.asm):
```diff
PackFGFXPointers: ; 48e93
@@ -399,6 +863,32 @@ Edit [engine/items/pack_kris.asm](../blob/master/engine/items/pack_kris.asm).
This is just like `PackGFXPointers`, but for the Crystal-only girl's Pack.
+
+## 11. 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: ; 107bb
+ ...
+
+ .Items: ; 107e9 (4:47e9)
+ xor a ; ITEM_POCKET
+ ld hl, .ItemsMenuHeader
+- jr .DisplayPocket
++ jp .DisplayPocket
+```
+
We're finally done!
![Screenshot](screenshots/berry-pocket.png)
+
+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.