Add a new Unown form - pret/pokecrystal GitHub Wiki
This tutorial is for how to add a new Unown form. As an example, we'll add the ! and ? forms introduced in Gen 3.
Contents
- Define a Unown form constant
- Design its sprites and animation
- Include and point to the sprite and animation data
- Change how DVs determine forms to make them all available
- Make room for it in the Pokédex WRAM
- Create a Unown font character for the new form
- Define its Unown Mode word
- Update Unown Mode to make room for the new form
- Allow the new form to be unlocked in the wild
- Correct the Research Center computer
- Fix bank overflow errors
1. Define a Unown form constant
Edit constants/pokemon_constants.asm:
; Unown forms
; indexes for:
; - UnownWords (see data/pokemon/unown_words.asm)
; - UnownPicPointers (see data/pokemon/unown_pic_pointers.asm)
; - UnownAnimationPointers (see gfx/pokemon/unown_anim_pointers.asm)
; - UnownAnimationIdlePointers (see gfx/pokemon/unown_idle_pointers.asm)
; - UnownBitmasksPointers (see gfx/pokemon/unown_bitmask_pointers.asm)
; - UnownFramesPointers (see gfx/pokemon/unown_frame_pointers.asm)
const_def 1
const UNOWN_A ; 1
...
const UNOWN_Z ; 26
+ const UNOWN_EXCLAMATION ; 27
+ const UNOWN_QUESTION ; 28
- NUM_UNOWN EQU const_value + -1 ; 26
+ NUM_UNOWN EQU const_value + -1 ; 28
2. Design its sprites and animation
Create gfx/pokemon/unown_exclamation/front.png:
And gfx/pokemon/unown_exclamation/back.png:
Then create gfx/pokemon/unown_question/front.png:
And gfx/pokemon/unown_question/back.png:
front.png is a vertical strip of unique animation frames. Frames are all the same size, 40x40 pixels, since that's the size of all the other Unown forms. back.png is always 48x48. Both sprites have to use the same four colors: white, black, and the same two hues as every other Unown.
Now create gfx/pokemon/unown_exclamation/anim.asm:
+ frame 0, 09
+ frame 1, 09
+ frame 2, 09
+ frame 3, 05
+ frame 2, 05
+ frame 4, 05
+ frame 1, 05
+ frame 1, 05
+ endanim
And gfx/pokemon/unown_exclamation/anim_idle.asm:
+ frame 0, 18
+ setrepeat 2
+ frame 5, 05
+ frame 0, 05
+ dorepeat 2
+ endanim
Then create gfx/pokemon/unown_question/anim.asm:
+ frame 0, 09
+ setrepeat 3
+ frame 1, 05
+ frame 2, 05
+ frame 1, 05
+ frame 0, 05
+ dorepeat 2
+ endanim
And finally gfx/pokemon/unown_question/anim_idle.asm:
+ frame 0, 13
+ setrepeat 2
+ frame 3, 05
+ frame 0, 05
+ dorepeat 2
+ endanim
anim.asm defines the main sprite animation sequence; anim_idle.asm defines an extra one that gets played in some contexts (notably not when a Pokémon is encountered in battle). A full description of the animation script commands is at docs/pic_animations.md.
These animations were designed by SCMidna. But you're more likely to have a single static front sprite than a whole animated sequence of frames. In that case, you can save the one sprite as front.png (so it will be a single square frame, not a vertical strip of them), and just put endanim
as the full contents of anim.asm and anim_idle.asm.
When you make
the ROM, a number of sprite-related files will be automatically generated for you. For more information on that, see the tutorial for how to add a new Pokémon.
3. Include and point to the sprite and animation data
Edit data/pokemon/unown_pic_pointers.asm:
UnownPicPointers::
; entries correspond to Unown letters, two apiece
dba_pic UnownAFrontpic
dba_pic UnownABackpic
...
dba_pic UnownZFrontpic
dba_pic UnownZBackpic
+ dba_pic UnownExclamationFrontpic
+ dba_pic UnownExclamationBackpic
+ dba_pic UnownQuestionFrontpic
+ dba_pic UnownQuestionBackpic
We have to use dba_pic
here instead of a standard dba
—declaring the bank and address of each label—because of this design flaw. I strongly recommend removing the whole FixPicBank
routine from engine/gfx/load_pics.asm, including all four calls to it in that file, and just using dba
here; then you'll be able to INCBIN
sprites in arbitrary banks.
Edit gfx/pics.asm:
SECTION "Pics 19", ROMX
-; Seems to be an accidental copy of the previous bank
-
-INCBIN "gfx/pokemon/spinarak/back.2bpp.lz"
-...
-INCBIN "gfx/pokemon/unown_r/back.2bpp.lz"
+UnownExclamationFrontpic: INCBIN "gfx/pokemon/unown_exclamation/front.animated.2bpp.lz"
+UnownExclamationBackpic: INCBIN "gfx/pokemon/unown_exclamation/back.2bpp.lz"
+UnownQuestionFrontpic: INCBIN "gfx/pokemon/unown_question/front.animated.2bpp.lz"
+UnownQuestionBackpic: INCBIN "gfx/pokemon/unown_question/back.2bpp.lz"
(If you don't fix the dba_pic
design flaw, you'll have to put your sprites in the "Pics N" sections, which are compatible with dba_pic
. "Pics 19" isn't used for anything useful—all its contents are unused duplicates of "Pics 18"—and it has a whole bank to itself, so it's the easiest place to start adding new sprites. (The other sections, includng "Pics 20" through "Pics 24", have limited remaining space since they already contain some sprites and/or share their banks with other sections.) But if you have a lot of new sprites to add, you risk overflowing the banks, and it's hard to fit sprites within fixed bank limits. By using just dba
, you can create new sections with a few sprites each, that will automatically be placed wherever they can fit in the ROM.)
Anyway, edit gfx/pokemon/unown_anim_pointers.asm:
UnownAnimationPointers:
dw UnownAAnimation
...
dw UnownZAnimation
+ dw UnownExclamationAnimation
+ dw UnownQuestionAnimation
Edit gfx/pokemon/unown_anims.asm:
UnownAnimations: ; used only for BANK(UnownAnimations)
UnownAAnimation: INCLUDE "gfx/pokemon/unown_a/anim.asm"
...
UnownZAnimation: INCLUDE "gfx/pokemon/unown_z/anim.asm"
+UnownExclamationAnimation: INCLUDE "gfx/pokemon/unown_exclamation/anim.asm"
+UnownQuestionAnimation: INCLUDE "gfx/pokemon/unown_question/anim.asm"
Edit gfx/pokemon/unown_idle_pointers.asm:
UnownAnimationIdlePointers:
dw UnownAAnimationIdle
...
dw UnownZAnimationIdle
+ dw UnownExclamationAnimationIdle
+ dw UnownQuestionAnimationIdle
Edit gfx/pokemon/unown_idles.asm:
UnownAAnimationIdle: INCLUDE "gfx/pokemon/unown_a/anim_idle.asm"
...
UnownZAnimationIdle: INCLUDE "gfx/pokemon/unown_z/anim_idle.asm"
+UnownExclamationAnimationIdle: INCLUDE "gfx/pokemon/unown_exclamation/anim_idle.asm"
+UnownQuestionAnimationIdle: INCLUDE "gfx/pokemon/unown_question/anim_idle.asm"
Edit gfx/pokemon/unown_bitmask_pointers.asm:
UnownBitmasksPointers:
dw UnownABitmasks
...
dw UnownZBitmasks
+ dw UnownExclamationBitmasks
+ dw UnownQuestionBitmasks
Edit gfx/pokemon/unown_bitmasks.asm:
UnownABitmasks: INCLUDE "gfx/pokemon/unown_a/bitmask.asm"
...
UnownZBitmasks: INCLUDE "gfx/pokemon/unown_z/bitmask.asm"
+UnownExclamationBitmasks: INCLUDE "gfx/pokemon/unown_exclamation/bitmask.asm"
+UnownQuestionBitmasks: INCLUDE "gfx/pokemon/unown_question/bitmask.asm"
Edit gfx/pokemon/unown_frame_pointers.asm:
UnownFramesPointers:
dw UnownAFrames
...
dw UnownZFrames
+ dw UnownExclamationFrames
+ dw UnownQuestionFrames
Finally, edit gfx/pokemon/unown_frames.asm:
UnownsFrames: ; used only for BANK(UnownsFrames)
UnownAFrames: INCLUDE "gfx/pokemon/unown_a/frames.asm"
...
UnownZFrames: INCLUDE "gfx/pokemon/unown_z/frames.asm"
+UnownExclamationFrames: INCLUDE "gfx/pokemon/unown_exclamation/frames.asm"
+UnownQuestionFrames: INCLUDE "gfx/pokemon/unown_question/frames.asm"
4. Change how DVs determine forms to make them all available
Edit engine/gfx/load_pics.asm:
GetUnownLetter:
; Return Unown letter in wUnownLetter based on DVs at hl
; Take the middle 2 bits of each DV and place them in order:
; atk def spd spc
; .ww..xx. .yy..zz.
; atk
ld a, [hl]
and %01100000
sla a
ld b, a
; def
ld a, [hli]
and %00000110
swap a
srl a
or b
ld b, a
; spd
ld a, [hl]
and %01100000
swap a
sla a
or b
ld b, a
; spc
ld a, [hl]
and %00000110
srl a
or b
-; Divide by 10 to get 0-25
+; Divide by 9 to get 0-28
ldh [hDividend + 3], a
xor a
ldh [hDividend], a
ldh [hDividend + 1], a
ldh [hDividend + 2], a
- ld a, $ff / NUM_UNOWN + 1
+ ld a, 9
ldh [hDivisor], a
ld b, 4
call Divide
-; Increment to get 1-26
+; Increment to get 1-29
ldh a, [hQuotient + 3]
inc a
+; The valid range is 1-28, so use UNOWN_E (5) instead of 29
+ cp NUM_UNOWN + 1
+ jr c, .valid
+ ld a, UNOWN_E
+.valid
ld [wUnownLetter], a
ret
The comments in GetUnownLetter
already describe how it works; as you can see, we've changed it to allow 28 possible values instead of 29. Before, Unown A to Y each had a 10/256 chance of appearing, and Unown Z only had a 6/256 chance (assuming wild DVs are perfectly random). Now, Unown A to Z, as well as ! and ?, all have a 9/256 chance of appearing—except for Unown E, which has a 13/256 chance because the routine defaults to it for the invalid 29th Unown.
Of course, the choice to give Unown E a boost is arbitrary. I picked it because E is the most common English letter; you could pick a different one, or try distributing the invalid cases more fairly to give four different forms a 10/256 chance; or completely revamp how forms are determined. The important thing is that every form needs to be available, and invalid forms should be impossible.
5. Make room for it in the Pokédex WRAM
Edit wram.asm:
- ds 22
+ ds 20
wPokedexCaught:: flag_array NUM_POKEMON ; de99
wEndPokedexCaught::
wPokedexSeen:: flag_array NUM_POKEMON ; deb9
wEndPokedexSeen::
wUnownDex:: ds NUM_UNOWN ; ded9
wUnlockedUnowns:: db ; def3
wFirstUnownSeen:: db
This WRAM bank is very close to being full. Since wUnownDex
has grown by 2 bytes, we need to remove 2 bytes elsewhere. Luckily there are 22 unused bytes nearby.
6. Create a Unown font character for the new form
Edit gfx/font/unown_font.png:
We've added the ! and ? characters after Z and before ◆. This font gets used by the Unown Mode for the Pokédex.
7. Define its Unown Mode word
Edit data/pokemon/unown_words.asm:
UnownWords:
; entries correspond to UNOWN_* form constants
dw UnownWordA
...
dw UnownWordZ
+ dw UnownWordExclamation
+ dw UnownWordQuestion
UnownWordA: unownword "ANGRY"
...
UnownWordZ: unownword "ZOOM"
+UnownWordExclamation: unownword "(((((" ; "!!!!!" since "Z" + 1 == "("
+UnownWordQuestion: unownword ")))))" ; "?????" since "Z" + 2 == ")"
The valid characters here correspond to the ones in gfx/font/unown_font.png: A to Z, plus the new ! and ?. You could also use ":"
("Z"
+ 3) for ◆, but that's meant to be the cursor, not for words.
"!!!!!" and "?????" are the words from the Unown Report in HG/SS.
8. Update Unown Mode to make room for the new form
This is the default Unown Mode Pokédex:
It has room to add one more Unown form in the bottom-right, but for two, we'll also have to widen it a little.
Edit engine/pokedex/pokedex.asm:
Pokedex_UnownModePlaceCursor:
ld a, [wDexCurUnownIndex]
- ld c, $5a ; diamond cursor
+ ld c, $5c ; diamond cursor
...
Pokedex_DrawUnownModeBG:
call Pokedex_FillBackgroundColor2
hlcoord 2, 1
- lb bc, 10, 13
+ lb bc, 10, 14
call Pokedex_PlaceBorder
hlcoord 2, 14
- lb bc, 1, 13
+ lb bc, 1, 14
call Pokedex_PlaceBorder
hlcoord 2, 15
ld [hl], $3d
- hlcoord 16, 15
+ hlcoord 17, 15
ld [hl], $3e
hlcoord 6, 5
call Pokedex_PlaceFrontpicAtHL
ld de, 0
ld b, 0
- ld c, 26
+ ld c, NUM_UNOWN
.loop
ld hl, wUnownDex
add hl, de
ld a, [hl]
and a
jr z, .done
push af
ld hl, UnownModeLetterAndCursorCoords
rept 4
add hl, de
endr
ld a, [hli]
ld h, [hl]
ld l, a
pop af
add $40 - 1 ; Unown A
ld [hl], a
inc de
inc b
dec c
jr nz, .loop
.done
ld a, b
ld [wDexUnownCount], a
ret
UnownModeLetterAndCursorCoords:
; entries correspond to Unown forms
; letter, cursor
dwcoord 4,11, 3,11 ; A
dwcoord 4,10, 3,10 ; B
dwcoord 4, 9, 3, 9 ; C
dwcoord 4, 8, 3, 8 ; D
dwcoord 4, 7, 3, 7 ; E
dwcoord 4, 6, 3, 6 ; F
dwcoord 4, 5, 3, 5 ; G
dwcoord 4, 4, 3, 4 ; H
dwcoord 4, 3, 3, 2 ; I
dwcoord 5, 3, 5, 2 ; J
dwcoord 6, 3, 6, 2 ; K
dwcoord 7, 3, 7, 2 ; L
dwcoord 8, 3, 8, 2 ; M
dwcoord 9, 3, 9, 2 ; N
dwcoord 10, 3, 10, 2 ; O
dwcoord 11, 3, 11, 2 ; P
dwcoord 12, 3, 12, 2 ; Q
dwcoord 13, 3, 13, 2 ; R
- dwcoord 14, 3, 15, 2 ; S
- dwcoord 14, 4, 15, 4 ; T
- dwcoord 14, 5, 15, 5 ; U
- dwcoord 14, 6, 15, 6 ; V
- dwcoord 14, 7, 15, 7 ; W
- dwcoord 14, 8, 15, 8 ; X
- dwcoord 14, 9, 15, 9 ; Y
- dwcoord 14,10, 15,10 ; Z
+ dwcoord 14, 3, 14, 2 ; S
+ dwcoord 15, 3, 16, 2 ; T
+ dwcoord 15, 4, 16, 4 ; U
+ dwcoord 15, 5, 16, 5 ; V
+ dwcoord 15, 6, 16, 6 ; W
+ dwcoord 15, 7, 16, 7 ; X
+ dwcoord 15, 8, 16, 8 ; Y
+ dwcoord 15, 9, 16, 9 ; Z
+ dwcoord 15,10, 16,10 ; !
+ dwcoord 15,11, 16,11 ; ?
...
Pokedex_LoadUnownFont:
ld a, BANK(sScratch)
call OpenSRAM
ld hl, UnownFont
ld de, sScratch + $188
ld bc, 39 tiles
ld a, BANK(UnownFont)
call FarCopyBytes
ld hl, sScratch + $188
- ld bc, 27 tiles
+ ld bc, (NUM_UNOWN + 1) tiles
call Pokedex_InvertTiles
ld de, sScratch + $188
ld hl, vTiles2 tile $40
- lb bc, BANK(Pokedex_LoadUnownFont), 27
+ lb bc, BANK(Pokedex_LoadUnownFont), NUM_UNOWN + 1
call Request2bpp
call CloseSRAM
ret
First of all, notice that we had to add 2 to the value of the "diamond cursor" tile because we added two characters in front of it in gfx/font/unown_font.png.
As for Pokedex_DrawUnownModeBG
, our edits do three things:
- one, widen the interface;
- two, define coordinates for the letter and cursor at new positions for ! and ? (and adjust the positions for S to Z to accomodate the wider interface);
- three, change some hard-coded constants to depend on
NUM_UNOWN
(this was already done in pokecrystal as of July 19, 2018).
9. Allow the new form to be unlocked in the wild
There are four chambers in the Ruins of Alph with puzzles of Kabuto, Omanyte, Aerodactyl, and Ho-Oh; solving each one unlocks a set of more Unown forms to be available in the wild. You could simply add the new forms to one of their four sets, but this step will show you how to add a fifth set.
Edit constants/engine_flags.asm:
; wUnlockedUnowns
const ENGINE_UNLOCKED_UNOWNS_A_TO_K
const ENGINE_UNLOCKED_UNOWNS_L_TO_R
const ENGINE_UNLOCKED_UNOWNS_S_TO_W
const ENGINE_UNLOCKED_UNOWNS_X_TO_Z
- const ENGINE_UNLOCKED_UNOWNS_UNUSED_4
+ const ENGINE_UNLOCKED_UNOWNS_EXCLAMATION_QUESTION
const ENGINE_UNLOCKED_UNOWNS_UNUSED_5 ; 30
const ENGINE_UNLOCKED_UNOWNS_UNUSED_6
const ENGINE_UNLOCKED_UNOWNS_UNUSED_7
Edit data/engine_flags.asm:
; unown sets (see data/wild/unlocked_unowns.asm)
engine_flag wUnlockedUnowns, 0 ; A-K
engine_flag wUnlockedUnowns, 1 ; L-R
engine_flag wUnlockedUnowns, 2 ; S-W
engine_flag wUnlockedUnowns, 3 ; X-Z
- engine_flag wUnlockedUnowns, 4 ; unused
+ engine_flag wUnlockedUnowns, 4 ; !-?
engine_flag wUnlockedUnowns, 5 ; unused ; $30
engine_flag wUnlockedUnowns, 6 ; unused
engine_flag wUnlockedUnowns, 7 ; unused
Edit data/wild/unlocked_unowns.asm:
UnlockedUnownLetterSets:
; entries correspond to wUnlockedUnowns bits
dw .Set_A_K ; ENGINE_UNLOCKED_UNOWNS_A_TO_K
dw .Set_L_R ; ENGINE_UNLOCKED_UNOWNS_L_TO_R
dw .Set_S_W ; ENGINE_UNLOCKED_UNOWNS_S_TO_W
dw .Set_X_Z ; ENGINE_UNLOCKED_UNOWNS_X_TO_Z
+ dw .Set_Exclamation_Question ; ENGINE_UNLOCKED_UNOWNS_EXCLAMATION_QUESTION
.End
.Set_A_K:
unown_set A, B, C, D, E, F, G, H, I, J, K
.Set_L_R:
unown_set L, M, N, O, P, Q, R
.Set_S_W:
unown_set S, T, U, V, W
.Set_X_Z:
unown_set X, Y, Z
+.Set_Exclamation_Question:
+ unown_set EXCLAMATION, QUESTION
Finally, edit maps/RuinsOfAlphInnerChamber.asm:
RuinsOfAlphInnerChamberStatue:
+ checkflag ENGINE_UNLOCKED_UNOWNS_EXCLAMATION_QUESTION
+ iftrue .already_unlocked
+ readvar VAR_UNOWNCOUNT
+ ifless 26, .dont_unlock
+ opentext
+ writetext RuinsOfAlphInnerChamberStatueText
+ waitbutton
+ writetext RuinsOfAlphInnerChamberStatueUnlockText
+ waitbutton
+ closetext
+ pause 30
+ earthquake 30
+ showemote EMOTE_SHOCK, PLAYER, 20
+ pause 30
+ playsound SFX_STRENGTH
+ earthquake 50
+ setflag ENGINE_UNLOCKED_UNOWNS_EXCLAMATION_QUESTION
+ jumptext RuinsOfAlphStrangePresenceText
+
+.already_unlocked
+.dont_unlock
jumptext RuinsOfAlphInnerChamberStatueText
RuinsOfAlphStrangePresenceText:
text "There is a strange"
line "presence here…"
done
...
RuinsOfAlphInnerChamberStatueText:
text "It's a replica of"
line "an ancient #-"
cont "MON."
done
+
+RuinsOfAlphInnerChamberStatueUnlockText:
+ text "…The statue is"
+ line "shaking!"
+ done
The simple method would be to just edit data/wild/unlocked_unowns.asm and add EXCLAMATION
and QUESTION
to one of the four existing sets. This demonstrates which other files need editing to add a fifth set.
We've also invented an event in the Ruins of Alph: if you talk to one of the statues after catching 26 different Unown, there will be an earthquake and the final set will be unlocked. (I copied the earthquake code from the wall-opening script in maps/RuinsOfAlphKabutoChamber.asm.)
10. Correct the Research Center computer
Edit maps/RuinsOfAlphResearchCenter.asm:
RuinsOfAlphResearchCenterComputerText_GotAllUnown:
text "Mystery #MON"
line "Name: UNOWN"
- para "A total of 26"
+ para "A total of 28"
line "kinds found."
done
11. Fix bank overflow errors
We're done adding the Unown forms, but make
won't compile the ROM:
error: Unable to place 'Pics 2' (ROMX section) at $40A8 in bank $49
But we didn't change anything in "Pics 2", so why is this happening?
As defined in pokecrystal.link, the "Unown Pic Pointers" and "Pics 2" sections are both in bank $49:
ROMX $49
org $4000
"Unown Pic Pointers"
"Pics 2"
It turns out that adding the new dba_pic
s to the UnownPicPointers
table was a little too much data for that bank. To fix this, we'll need to move some data out of bank $49. "Unown Pic Pointers" has to be as large as it is, but "Pics 2" is an arbitrary set of sprites, so we can move one of those.
Edit gfx/pics.asm again:
SECTION "Pics 2", ROMX
BlastoiseFrontpic: INCBIN "gfx/pokemon/blastoise/front.animated.2bpp.lz"
RapidashFrontpic: INCBIN "gfx/pokemon/rapidash/front.animated.2bpp.lz"
MeganiumFrontpic: INCBIN "gfx/pokemon/meganium/front.animated.2bpp.lz"
NidoqueenFrontpic: INCBIN "gfx/pokemon/nidoqueen/front.animated.2bpp.lz"
HitmonleeFrontpic: INCBIN "gfx/pokemon/hitmonlee/front.animated.2bpp.lz"
ScizorFrontpic: INCBIN "gfx/pokemon/scizor/front.animated.2bpp.lz"
BeedrillFrontpic: INCBIN "gfx/pokemon/beedrill/front.animated.2bpp.lz"
ArcanineFrontpic: INCBIN "gfx/pokemon/arcanine/front.animated.2bpp.lz"
TyranitarFrontpic: INCBIN "gfx/pokemon/tyranitar/front.animated.2bpp.lz"
MoltresFrontpic: INCBIN "gfx/pokemon/moltres/front.animated.2bpp.lz"
ZapdosFrontpic: INCBIN "gfx/pokemon/zapdos/front.animated.2bpp.lz"
ArbokFrontpic: INCBIN "gfx/pokemon/arbok/front.animated.2bpp.lz"
MewtwoFrontpic: INCBIN "gfx/pokemon/mewtwo/front.animated.2bpp.lz"
FearowFrontpic: INCBIN "gfx/pokemon/fearow/front.animated.2bpp.lz"
CharizardFrontpic: INCBIN "gfx/pokemon/charizard/front.animated.2bpp.lz"
-QuilavaFrontpic: INCBIN "gfx/pokemon/quilava/front.animated.2bpp.lz"
...
SECTION "Pics 19", ROMX
UnownExclamationFrontpic: INCBIN "gfx/pokemon/unown_exclamation/front.animated.2bpp.lz"
UnownExclamationBackpic: INCBIN "gfx/pokemon/unown_exclamation/back.2bpp.lz"
UnownQuestionFrontpic: INCBIN "gfx/pokemon/unown_question/front.animated.2bpp.lz"
UnownQuestionBackpic: INCBIN "gfx/pokemon/unown_question/back.2bpp.lz"
+QuilavaFrontpic: INCBIN "gfx/pokemon/quilava/front.animated.2bpp.lz"
Now we're done!
You can add even more than 28 Unown forms, but the Unown mode interface will need redesigning to accomodate them. For example, here's a version that fits 33 forms:
All you have to do is:
- Edit
Pokedex_DrawUnownModeBG
in engine/pokedex/pokedex.asm to change where the UI elements are drawn, and - Edit
_CGB_PokedexUnownMode
in engine/gfx/cgb_layouts.asm to align the Unown sprite's palette with its new position (if that changed).