Add a new text scrolling speed - pret/pokecrystal GitHub Wiki
This tutorial details how to add an additional text speed option to the options screen. As an example we'll implement an option for instant text.
- Define wram constant
- Add instant text to options
- Fix text speed while holding A or B
- Fix
<SCROLL>command - (pokegold Only) Fix Loading
Edit constants/ram_constants.asm:
; wOptions1::
DEF TEXT_DELAY_MASK EQU %111
const_def 4
const NO_TEXT_SCROLL ; 4
const STEREO ; 5
const BATTLE_SHIFT ; 6
const BATTLE_SCENE ; 7
+DEF TEXT_DELAY_NONE EQU %000 ; 0
DEF TEXT_DELAY_FAST EQU %001 ; 1
DEF TEXT_DELAY_MED EQU %011 ; 3
DEF TEXT_DELAY_SLOW EQU %101 ; 5As you can see we defined TEXT_DELAY_NONE as 0, which will print all characters with 0 frame delay.
Edit engine/menus/options_menu.asm:
.Pointers:
dw Options_TextSpeed
...
const_def
const OPT_TEXT_SPEED_FAST ; 0
const OPT_TEXT_SPEED_MED ; 1
const OPT_TEXT_SPEED_SLOW ; 2
+ const OPT_TEXT_SPEED_NONE ; 3
Options_TextSpeed:
call GetTextSpeed
ldh a, [hJoyPressed]
bit D_LEFT_F, a
jr nz, .LeftPressed
bit D_RIGHT_F, a
jr z, .NonePressed
ld a, c ; right pressed
- cp OPT_TEXT_SPEED_SLOW
+ cp OPT_TEXT_SPEED_NONE
jr c, .Increase
...
.LeftPressed:
ld a, c
and a
jr nz, .Decrease
- ld c, OPT_TEXT_SPEED_SLOW + 1
+ ld c, OPT_TEXT_SPEED_NONE + 1This will make it cycleable in the options menu but it won't actually work quite yet. We still need to define its string and load the correct previous & next value into registers, otherwise it won't display the selected value correctly.
.Strings:
; entries correspond to OPT_TEXT_SPEED_* constants
dw .Fast
dw .Mid
dw .Slow
+ dw .None
.Fast: db "FAST@"
.Mid: db "MID @"
.Slow: db "SLOW@"
+.None: db "NONE@"
GetTextSpeed:
; converts TEXT_DELAY_* value in a to OPT_TEXT_SPEED_* value in c,
; with previous/next TEXT_DELAY_* values in d/e
ld a, [wOptions]
and TEXT_DELAY_MASK
cp TEXT_DELAY_SLOW
jr z, .slow
cp TEXT_DELAY_FAST
jr z, .fast
+ cp TEXT_DELAY_NONE
+ jr z, .none
; none of the above
ld c, OPT_TEXT_SPEED_MED
lb de, TEXT_DELAY_FAST, TEXT_DELAY_SLOW
ret
.slow
ld c, OPT_TEXT_SPEED_SLOW
- lb de, TEXT_DELAY_MED, TEXT_DELAY_FAST
+ lb de, TEXT_DELAY_MED, TEXT_DELAY_NONE
ret
.fast
ld c, OPT_TEXT_SPEED_FAST
- lb de, TEXT_DELAY_SLOW, TEXT_DELAY_MED
+ lb de, TEXT_DELAY_NONE, TEXT_DELAY_MED
+ ret
+
+.none
+ ld c, OPT_TEXT_SPEED_NONE
+ lb de, TEXT_DELAY_SLOW, TEXT_DELAY_FAST
retNote how lb de, <previous>, <next> correspond to the order defined with the OPT_TEXT_SPEED_<speed> constants. If your custom text speed is not 0 like mine you're done.
There are a few extra quirks to fix. When you hold the A or B buttons while text is scrolling it does so at TEXT_DELAY_FAST. Since our custom text speed is faster than that we need to make sure this doesn't happen.
Edit home/print_text.asm:
PrintLetterDelay::
...
; text speed
ld a, [wOptions]
and %111
+ jr z, .end
jr .updatedelayLastly, the <SCROLL> command, which is used when a stat is sharply raised or lowered (among a couple other cases), will cause the line to skip instantly, giving you no time to read it. We'll force a delay into it.
_ContText fallsthrough into _ContTextNoPause but it doesn't need the delay, so we'll replace the fallthrough with a jump
Edit home/text.asm:
_ContText::
...
call z, UnloadBlinkingCursor
- ; fallthrough
+ jr _ContTextNoPause.not_instant
_ContTextNoPause::
+ ld a, [wOptions]
+ and TEXT_DELAY_MASK
+ cp TEXT_DELAY_FAST
+ jr nz, .not_instant
+ ld c, 15
+ call DelayFrames
+.not_instant
push deAnd there you go.
Gold and Silver have a safety check in the routine for loading options ensuring the text delay is one of the valid amounts, but it was removed in Crystal for some reason. You'll have to adjust or disable it for this to work in pokegold.
Edit engine/menus/save.asm:
CheckTextDelay:
; Fix options if text delay is invalid
ld hl, wTextboxFlags
res TEXT_DELAY_F, [hl]
ld a, [wOptions]
and TEXT_DELAY_MASK
cp TEXT_DELAY_FAST
ret z
cp TEXT_DELAY_MED
ret z
cp TEXT_DELAY_SLOW
ret z
+ cp TEXT_DELAY_NONE
+ ret z
ld a, [wOptions]
and ~TEXT_DELAY_MASK
or (1 << FAST_TEXT_DELAY_F) | (1 << TEXT_DELAY_F)
ld [wOptions], a
retOr you can simply delete/comment out this routine and the calls to it in CheckPrimarySaveFile and CheckBackupSaveFile.