RoadToCerulean
A Ordinary Kanto Lover
- 205
- Posts
- 8
- Years
- Route 1 (Kanto)
- Seen Apr 24, 2024
First, credit to Pokemon_XY for the original start menu clock routines.
Although this toturial is based on binary hacking, it benefits a lot from the decompilation projects (credit to pret) of FireRed, Emerald and Ruby. I made some modifications so that the menu clock features 12 hour format and week display.
Note: The time format supported in these routines is WEEK H:MM:SS AM/PM. I've added some comments into the codes (see the Emerald part) to make them clearer to read.
Upgraded Version of FireRed (Routine 1 only):
Emerald:
Ruby:
Screenshots (From left to right: FireRed, Emerald, Ruby):
Known Bugs:
Spoiler:
Time Box triggered along with the Start Menu
Preview: (Click to see the GIF animation)
View attachment 77173
The routines are only for FR. I haven't found any bugs in it. However, the CPU will run much more instructions so that it will be a bit (really?) slower when you open the 'pokemon', 'bag'..... menus.
1) Insert the RTC routine via the tool 'DNS'.
2) Insert these routines and do the byte changes:
Routine I:
Routine II:Spoiler:byte changes:
routine:Code:0x6F09C - 00 48 00 47 XX+1 XX XX 08 change all the 0x8750000 in the routine to the insert offset of the routine. change all the 0x8750001 in the routine to the insert offset + 1 of the routine.
Code:.thumb bl box_func ldr r1, =0x20370FF ldrb r0, [r1] add r0, #1 strb r0, [r1] mov r0, #0 add sp, sp, #0xC pop {r4, pc} .ltorg box_func: push {r4, lr} ldr r4, =0x2037101 ldr r0, =(0x8750000 + rbox_config) ldr r3, =0x8003ce5 bl call_r3 strb r0, [r4] ldr r3, =0x8003fa1 bl call_r3 ldrb r0, [r4] mov r1, #0 ldr r3, =0x80F6F1D bl call_r3 bl print_string ldr r0, =(0x8750001 + print_string) mov r1, #2 ldr r3, =0x807741D bl call_r3 ldr r1, =0x20370C0 strh r0, [r1] pop {r4, pc} .ltorg print_string: push {r4-r7, lr} sub sp, sp, #0xC ldr r0, =0x2021cd0 add r7, r0, #0 ldr r1, =0x300553c ldrb r5, [r1, #7] @minute ldrb r6, [r1, #8] @second ldrb r1, [r1, #6] @hour mov r2, #1 mov r3, #2 ldr r4, =0x8008E79 bl call_r4 bl go_padding ldr r0, =0x2021CF0 add r7, r0, #0 add r1, r5, #0 mov r2, #1 mov r3, #2 ldr r4, =0x8008e79 bl call_r4 bl go_padding ldr r0, =0x2021d04 add r7, r0, #0 add r1, r6, #0 mov r2, #1 mov r3, #2 ldr r4, =0x8008e79 bl call_r4 bl go_padding ldr r5, =0x2021D18 ldr r1, =(0x8750000 + string) add r0, r5, #0 ldr r3, =0x8008FCD bl call_r3 ldr r0, =0x2037101 ldrb r0, [r0] mov r1, #3 str r1, [sp] mov r1, #0xff str r1, [sp, #4] mov r1, #0 str r1, [sp, #8] mov r1, #2 add r2, r5, #0 mov r3, #4 ldr r4, =0x8002C49 bl call_r4 ldr r0, =0x2037101 ldrb r0, [r0] mov r1, #2 ldr r3, =0x8003F21 bl call_r3 add sp, sp, #0xC pop {r4-r7, pc} .ltorg go_padding: push {lr} ldrb r0, [r7] cmp r0, #0 bne back mov r0, #0xa1 strb r0, [r7] back: pop {pc} call_r3: bx r3 call_r4: bx r4 .align 2 rbox_config: .byte 0x0 @bg_id .byte 0x1 @x .byte 0x1 @y .byte 0xa @width .byte 0x2 @height .byte 0xf .hword 0x8 @tileset_ofs .word 0x8419f76 @pixels .align 2 string: .byte 0xce, 0xdd, 0xe1, 0xd9, 0xf0, 0xfd, 0x2, 0xf0, 0xfd, 0x3, 0xf0, 0xfd, 0x4, 0xff
Routine III:Spoiler:byte changes:
routine:Code:0x6EF1E - 00 00 00 49 08 47 YY+1 YY YY 08
Code:.thumb cmp r0, #1 beq safari ldr r0, =0x20370C0 ldrh r0, [r0] ldr r3, =0x8077509 bl call_r3 safari: ldr r4, =0x02037101 ldrb r0, [r4] mov r1, #0 ldr r3, =0x806ef29 call_r3: bx r3
Spoiler:byte changes:
routine:Code:0x6f4e8 - 00 48 00 47 ZZ+1 ZZ ZZ 08
Code:.thumb push {lr} ldr r0, =0x20370c0 ldrh r0, [r0] ldr r3, =0x8077509 bl call_r3 ldr r1, =0x20370F0 ldr r0, =0x806f5a5 str r0, [r1] mov r0, #0 pop {pc} call_r3: bx r3
Note: The time format supported in these routines is WEEK H:MM:SS AM/PM. I've added some comments into the codes (see the Emerald part) to make them clearer to read.
Upgraded Version of FireRed (Routine 1 only):
Spoiler:
Code:
@Change all 0x871B460 to where you insert your routine.
@Change all 0x871B461 to where you insert your routine plus 1.
.thumb
ldr r0, =0x0000406E
bl var_decrypt
ldrb r0, [r0]
cmp r0, #0x2
beq finish
bl box_func
finish:
ldr r1, =0x20370FF
ldrb r0, [r1]
add r0, #1
strb r0, [r1]
mov r0, #0
add sp, sp, #0xC
pop {r4, pc}
.ltorg
box_func:
push {r4, lr}
ldr r4, =0x2037101
ldr r0, =(0x871B460 + rbox_config)
ldr r3, =0x8003CE5
bl call_r3
strb r0, [r4]
ldr r3, =0x8003FA1
bl call_r3
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x80F6F1D
bl call_r3
bl print_string
ldr r0, =(0x871B461 + print_string)
mov r1, #2
ldr r3, =0x807741D
bl call_r3
ldr r1, =0x20370C0
strh r0, [r1]
pop {r4, pc}
.ltorg
print_string:
push {r4-r7, lr}
sub sp, sp, #0xC
ldr r0, =0x2021CD0
add r7, r0, #0
ldr r1, =0x300553C
ldrb r5, [r1, #7]
ldrb r6, [r1, #8]
ldrb r1, [r1, #6]
cmp r1, #0xC
bge pm_time
cmp r1, #0x0
bne am_time
add r1, #0xC
am_time:
mov r2, #1
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
ldr r0, =0x2021CF0
add r7, r0, #0
add r1, r5, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
ldr r0, =0x2021D04
add r7, r0, #0
add r1, r6, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
ldr r5, =0x2021D18
ldr r0, =0x3005541
ldrb r0, [r0]
cmp r0, #0x1
beq monday_am
cmp r0, #0x2
beq tuesday_am
cmp r0, #0x3
beq wednesday_am
cmp r0, #0x4
beq thursday_am
cmp r0, #0x5
beq friday_am
cmp r0, #0x6
beq saturday_am
sunday_am:
ldr r1, =(0x871B460 + sun_am)
b am_pm
monday_am:
ldr r1, =(0x871B460 + mon_am)
b am_pm
tuesday_am:
ldr r1, =(0x871B460 + tue_am)
b am_pm
wednesday_am:
ldr r1, =(0x871B460 + wed_am)
b am_pm
thursday_am:
ldr r1, =(0x871B460 + thu_am)
b am_pm
friday_am:
ldr r1, =(0x871B460 + fri_am)
b am_pm
saturday_am:
ldr r1, =(0x871B460 + sat_am)
b am_pm
pm_time:
cmp r1, #0xC
beq pm_time_2
sub r1, #0xC
pm_time_2:
mov r2, #1
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
ldr r0, =0x2021CF0
add r7, r0, #0
add r1, r5, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
ldr r0, =0x2021D04
add r7, r0, #0
add r1, r6, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008E79
bl call_r4
ldr r5, =0x2021D18
ldr r0, =0x3005541
ldrb r0, [r0]
cmp r0, #0x1
beq monday_pm
cmp r0, #0x2
beq tuesday_pm
cmp r0, #0x3
beq wednesday_pm
cmp r0, #0x4
beq thursday_pm
cmp r0, #0x5
beq friday_pm
cmp r0, #0x6
beq saturday_pm
sunday_pm:
ldr r1, =(0x871B460 + sun_pm)
b am_pm
monday_pm:
ldr r1, =(0x871B460 + mon_pm)
b am_pm
tuesday_pm:
ldr r1, =(0x871B460 + tue_pm)
b am_pm
wednesday_pm:
ldr r1, =(0x871B460 + wed_pm)
b am_pm
thursday_pm:
ldr r1, =(0x871B460 + thu_pm)
b am_pm
friday_pm:
ldr r1, =(0x871B460 + fri_pm)
b am_pm
saturday_pm:
ldr r1, =(0x871B460 + sat_pm)
b am_pm
am_pm:
add r0, r5, #0
ldr r3, =0x8008FCD
bl call_r3
ldr r0, =0x2037101
ldrb r0, [r0]
mov r1, #3
str r1, [sp]
mov r1, #0xff
str r1, [sp, #4]
mov r1, #0
str r1, [sp, #8]
mov r1, #2
add r2, r5, #0
mov r3, #4
ldr r4, =0x8002C49
bl call_r4
ldr r0, =0x2037101
ldrb r0, [r0]
mov r1, #2
ldr r3, =0x8003F21
bl call_r3
add sp, sp, #0xC
pop {r4-r7, pc}
.ltorg
call_r3:
bx r3
call_r4:
bx r4
var_decrypt:
ldr r1, vardecry
bx r1
.align 2
rbox_config: @struct WindowTemplate {
.byte 0x0 @u8 background_id,
.byte 0x1 @u8 tilemap_upperleft_x,
.byte 0x1 @u8 tilemap_upperleft_y,
.byte 0xC @u8 tilemap_width,
.byte 0x2 @u8 tilemap_height,
.byte 0xF @u8 paletteNum,
.hword 0x3C @u16 baseBlock
@}
.align 2
sun_am: .byte 0xCD, 0xCF, 0xC8, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
sun_pm: .byte 0xCD, 0xCF, 0xC8, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
mon_am: .byte 0xC7, 0xC9, 0xC8, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
mon_pm: .byte 0xC7, 0xC9, 0xC8, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
tue_am: .byte 0xCE, 0xCF, 0xBF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
tue_pm: .byte 0xCE, 0xCF, 0xBF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
wed_am: .byte 0xD1, 0xBF, 0xBE, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
wed_pm: .byte 0xD1, 0xBF, 0xBE, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
thu_am: .byte 0xCE, 0xC2, 0xCF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
thu_pm: .byte 0xCE, 0xC2, 0xCF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
fri_am: .byte 0xC0, 0xCC, 0xC3, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
fri_pm: .byte 0xC0, 0xCC, 0xC3, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
sat_am: .byte 0xCD, 0xBB, 0xCE, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
sat_pm: .byte 0xCD, 0xBB, 0xCE, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
.align 2
vardecry:
.word 0x0806E455
Spoiler:
Routine 1:
Routine 2:
Routine 3:
Spoiler:
Code:
@Routine 1 is to add an extra window and display a ticking clock when the start menu is opened.
@However, if we open the start menu in Safari Zone (and maybe in Battle Pyramid in Emerald as well)
@the clock window will overlap the original stat window.
@So we have to first check the flags that are set when the player enters such areas.
@Change all 0x89C4AF0 to where you insert Routine 1.
@Change all 0x89C4AF1 to where you insert Routine 1 plus 1.
@Change bytes at 0x809F926 to 00 00 00 48 00 47 EF+1 CD AB 08 after inserting.
@0x8ABCDEF is the address of Routine 1.
.thumb
ldr r3, =0x80FC0A1
bl call_r3
cmp r0, #0x1
beq finish @skip adding the clock frame if in safari zone
ldr r3, =0x81A9E41
bl call_r3
cmp r0, #0x1
beq finish @skip adding the clock frame if in battle pyramid
ldr r0, =0x0000406E
bl var_decrypt
bl box_func
finish: @Revives the code that are overwritten to redirect to Routine 1
ldr r1, =0x2037619
ldrb r0, [r1]
add r0, #1
strb r0, [r1]
mov r0, #0
add sp, sp, #0xC
pop {r4, pc}
.ltorg
@This part adds a window frame to the screen when the start menu is opened.
@You can modify the configurations in the "rbox_config" part near the end of this routine.
@So it is possible to put the clock frame at a different position to avoid overlapping
@when in the Safari Zone.
box_func:
push {r4, lr}
ldr r4, =0x203760C
ldr r0, =(0x89C4AF0 + rbox_config)
ldr r3, =0x8003381
bl call_r3 @call AddWindow()
strb r0, [r4]
ldr r3, =0x800378D
bl call_r3 @call PutWindowTilemap()
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x81973FD
bl call_r3 @call DrawStdWindowFrame()
bl print_string
ldr r0, =(0x89C4AF1 + print_string)
mov r1, #2
ldr r3, =0x80A8FB1
bl call_r3 @call CreateTask()
ldr r1, =0x20375E0
strh r0, [r1]
pop {r4, pc}
.ltorg
print_string:
push {r4-r7, lr}
sub sp, sp, #0xC
ldr r0, =0x2021CC4
add r7, r0, #0
ldr r0, =0x3000DC0 @C0 = year, C1 = mon, C2 = day,
@C3 = week, C4 = hour, C5 = min, C6 = sec
ldr r3, =0x802F289
bl call_r3 @updates date and time by calling RtcGetInfo()
ldr r1, =0x3000DC0
ldr r0, =0x2021CC4
ldrb r5, [r1, #5] @minute
ldrb r6, [r1, #6] @second
ldrb r1, [r1, #4] @hour
@The RTC time data in Ruby, Sapphire and Emerald are stored in faux decimals.
@For example, 12:34:07 is stored as 0x12 0x34 0x07, which are actually 18, 52 and 7 in decimal.
@So we have to convert the faux decimals into true decimals.
cmp r1, #0x20
blt h_ten_to_19
sub r1, r1, #0xC
b convert_minute
h_ten_to_19:
cmp r1, #0x10
blt convert_minute
sub r1, r1, #0x6
convert_minute:
cmp r5, #0x50 @80~89
blt m_forty_to_49
sub r5, r5, #0x1E @-30
b convert_second
m_forty_to_49:
cmp r5, #0x40 @64~73
blt m_thirty_to_39
sub r5, r5, #0x18 @-24
b convert_second
m_thirty_to_39:
cmp r5, #0x30 @48~57
blt m_twenty_to_29
sub r5, r5, #0x12 @-18
b convert_second
m_twenty_to_29:
cmp r5, #0x20 @32~41
blt m_ten_to_19
sub r5, r5, #0xC @-12
b convert_second
m_ten_to_19:
cmp r5, #0x10 @16~25
blt convert_second
sub r5, r5, #0x6 @-6
convert_second:
cmp r6, #0x50
blt s_forty_to_49
sub r6, r6, #0x1E
b twelve_hour
s_forty_to_49:
cmp r6, #0x40
blt s_thirty_to_39
sub r6, r6, #0x18
b twelve_hour
s_thirty_to_39:
cmp r6, #0x30
blt s_twenty_to_29
sub r6, r6, #0x12
b twelve_hour
s_twenty_to_29:
cmp r6, #0x20
blt s_ten_to_19
sub r6, r6, #0xC
b twelve_hour
s_ten_to_19:
cmp r6, #0x10
blt twelve_hour
sub r6, r6, #0x6
twelve_hour:
cmp r1, #0xC
bge pm_time @if hour >= 12 then jump to pm_time
cmp r1, #0x0
bne am_time
add r1, #0xC @if hour == 0 then hour = 12
@In this part, we convert time integers into strings based on padding.
@GBA supports 3 padding formats: ALIGN_LEFT = 0, ALIGN_RIGHT = 1 and LEADING_ZERO = 2.
@So we change the value of r2 to modify paddings.
@The following codes support H:MM:SS format.
@Therefore, the "padding" section in Pokemon_XY's routines is redundant and is omitted.
am_time:
mov r2, #1
mov r3, #2
ldr r4, =0x8008CC1
bl call_r4 @call ConvertIntToDecimalStringN()
ldr r0, =0x2021DC4
add r7, r0, #0
add r1, r5, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008CC1
bl call_r4
ldr r0, =0x2021EC4
add r7, r0, #0
add r1, r6, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008CC1
bl call_r4
ldr r5, =0x2021FC4
ldr r0, =0x3000DC3
@Convert week integer into week string
ldrb r0, [r0]
cmp r0, #0x1
beq monday_am
cmp r0, #0x2
beq tuesday_am
cmp r0, #0x3
beq wednesday_am
cmp r0, #0x4
beq thursday_am
cmp r0, #0x5
beq friday_am
cmp r0, #0x6
beq saturday_am
sunday_am:
ldr r1, =(0x89C4AF0 + sun_am)
b am_pm
monday_am:
ldr r1, =(0x89C4AF0 + mon_am)
b am_pm
tuesday_am:
ldr r1, =(0x89C4AF0 + tue_am)
b am_pm
wednesday_am:
ldr r1, =(0x89C4AF0 + wed_am)
b am_pm
thursday_am:
ldr r1, =(0x89C4AF0 + thu_am)
b am_pm
friday_am:
ldr r1, =(0x89C4AF0 + fri_am)
b am_pm
saturday_am:
ldr r1, =(0x89C4AF0 + sat_am)
b am_pm
pm_time:
cmp r1, #0xC
beq pm_time_2
sub r1, #0xC @if hour > 12 then hour -= 12
pm_time_2:
mov r2, #1
mov r3, #2
ldr r4, =0x8008CC1
bl call_r4
ldr r0, =0x2021DC4
add r7, r0, #0
add r1, r5, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008CC1
bl call_r4
ldr r0, =0x2021EC4
add r7, r0, #0
add r1, r6, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8008CC1
bl call_r4
ldr r5, =0x2021FC4
ldr r0, =0x3000DC3
ldrb r0, [r0]
cmp r0, #0x1
beq monday_pm
cmp r0, #0x2
beq tuesday_pm
cmp r0, #0x3
beq wednesday_pm
cmp r0, #0x4
beq thursday_pm
cmp r0, #0x5
beq friday_pm
cmp r0, #0x6
beq saturday_pm
sunday_pm:
ldr r1, =(0x89C4AF0 + sun_pm)
b am_pm
monday_pm:
ldr r1, =(0x89C4AF0 + mon_pm)
b am_pm
tuesday_pm:
ldr r1, =(0x89C4AF0 + tue_pm)
b am_pm
wednesday_pm:
ldr r1, =(0x89C4AF0 + wed_pm)
b am_pm
thursday_pm:
ldr r1, =(0x89C4AF0 + thu_pm)
b am_pm
friday_pm:
ldr r1, =(0x89C4AF0 + fri_pm)
b am_pm
saturday_pm:
ldr r1, =(0x89C4AF0 + sat_pm)
b am_pm
am_pm:
add r0, r5, #0
ldr r3, =0x8008EE1 @call StringExpandPlaceholders
bl call_r3
@This part configs how the time text string should be printed to the window.
ldr r0, =0x203760C
ldrb r0, [r0]
mov r1, #2
str r1, [sp]
mov r1, #0xff
str r1, [sp, #4]
mov r1, #0
str r1, [sp, #8]
mov r1, #1 @Change this value will change the font displayed in the box.
add r2, r5, #0
mov r3, #4
ldr r4, =0x80045D1
bl call_r4 @call AddTextPrinterParameterized
ldr r0, =0x203760C
ldrb r0, [r0]
mov r1, #2
ldr r3, =0x8003659 @call CopyWindowToVram
bl call_r3
add sp, sp, #0xC
pop {r4-r7, pc}
.ltorg
back_2:
pop {pc}
call_r3:
bx r3
call_r4:
bx r4
var_decrypt:
ldr r1, vardecry
bx r1
@The "pixel" word is redundant and is omitted.
.align 2
rbox_config: @struct WindowTemplate {
.byte 0x0 @ u8 background_id,
.byte 0x1 @ u8 tilemap_upperleft_x,
.byte 0x1 @ u8 tilemap_upperleft_y,
.byte 0xC @ u8 tilemap_width,
.byte 0x2 @ u8 tilemap_height,
.byte 0xF @ u8 paletteNum,
.hword 0x3C @ u16 baseBlock
@}
@String formats based on week days and AM/PM.
@In Emerald, byte 0x77 is an additional space character with width 0x6, the same as numbers,
@making it a better alternative of byte 0x00 the default space with width 0x3.
.align 2
sun_am: .byte 0xCD, 0xCF, 0xC8, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
sun_pm: .byte 0xCD, 0xCF, 0xC8, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
mon_am: .byte 0xC7, 0xC9, 0xC8, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
mon_pm: .byte 0xC7, 0xC9, 0xC8, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
tue_am: .byte 0xCE, 0xCF, 0xBF, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
tue_pm: .byte 0xCE, 0xCF, 0xBF, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
wed_am: .byte 0xD1, 0xBF, 0xBE, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
wed_pm: .byte 0xD1, 0xBF, 0xBE, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
thu_am: .byte 0xCE, 0xC2, 0xCF, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
thu_pm: .byte 0xCE, 0xC2, 0xCF, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
fri_am: .byte 0xC0, 0xCC, 0xC3, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
fri_pm: .byte 0xC0, 0xCC, 0xC3, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
sat_am: .byte 0xCD, 0xBB, 0xCE, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xBB, 0xC7, 0xFF
sat_pm: .byte 0xCD, 0xBB, 0xCE, 0x77, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x77, 0xCA, 0xC7, 0xFF
.align 2
vardecry:
.word 0x0809D649
Spoiler:
Code:
@Routine 2 removes the clock window when we exit the start menu.
@Changes bytes at 0x809F79C to 00 49 08 47 EF+1 CD AB 08 after inserting.
@0x8ABCDEF is the address of Routine 2.
.thumb
cmp r0, #1
beq safari
ldr r0, =0x20375E0
ldrh r0, [r0]
ldr r3, =0x80A909D
bl call_r3 @call DestroyTask()
safari:
ldr r4, =0x203760C
cmp r4, #0x1
bne r4_equals_2
add r4, r4, #0x1
r4_equals_2:
ldrb r0, [r4]
mov r1, #0
ldr r3, =0x809F785
call_r3:
bx r3
Spoiler:
Code:
@Routine 3 hides the clock window when we triggers the "save" option.
@Change bytes at 0x809FD0C to 00 48 00 47 EF+1 CD AB 08 after inserting.
@0x8ABCDEF is the address of Routine 3.
push {lr}
ldr r0, =0x20375E0
ldrh r0, [r0]
ldr r3, =0x80A909D
bl call_r3 @call DestroyTask()
ldr r1,=0x3005DF4
ldr r0,=0x809FE29
str r0,[r1]
mov r0,#0x0
pop {pc}
call_r3:
bx r3
Spoiler:
Routine 1:
Routine 2:
Routine 3:
Spoiler:
Code:
@Change all 0x86B0A00 into where you insert Routine 1.
@Change all 0x86B0A01 into where you insert Routine 1 plus 1.
@After inserting, change bytes at 0x80711E0 to 00 49 08 47 EF+1 CD AB 08.
@0x8ABCDEF is the address of Routine 1.
.thumb
ldr r3, =0x80C8185
bl call_r3
cmp r0,#0x0
beq out_of_safari_zone
ldr r3,=0x80710DD
bl call_r3
b finish
out_of_safari_zone:
ldr r0, =0x0000406E
bl var_decrypt
bl box_func
finish:
ldr r3,=0x80711E9
bx r3
@The Ruby version is simpler becase it calls fewer functions.
box_func:
push {r4, lr}
mov r0, #0x0 @left
mov r1, #0x0 @top
mov r2, #0xD @right
mov r3, #0x3 @bottom
ldr r4, =0x8071F09
bl call_r4 @call Menu_DrawStdWindowFrame()
bl print_string
ldr r0, =(0x86B0A01 + print_string)
mov r1, #2
ldr r3, =0x807AA89
bl call_r3
ldr r1, =0x202E8CC
strh r0, [r1]
pop {r4, pc}
.ltorg
print_string:
push {r4-r7, lr}
sub sp, sp, #0xC
ldr r0, =0x20231CC
add r7, r0, #0
ldr r0, =0x3000460
ldr r3, =0x80092B5
bl call_r3
ldr r1, =0x3000460
ldr r0, =0x20231CC
ldrb r5, [r1, #5]
ldrb r6, [r1, #6]
ldrb r1, [r1, #4]
cmp r1, #0x20
blt h_ten_to_19
sub r1, r1, #0xC
b convert_minute
h_ten_to_19:
cmp r1, #0x10
blt convert_minute
sub r1, r1, #0x6
convert_minute:
cmp r5, #0x50 @80~89
blt m_forty_to_49
sub r5, r5, #0x1E @-30
b convert_second
m_forty_to_49:
cmp r5, #0x40 @64~73
blt m_thirty_to_39
sub r5, r5, #0x18 @-24
b convert_second
m_thirty_to_39:
cmp r5, #0x30 @48~57
blt m_twenty_to_29
sub r5, r5, #0x12 @-18
b convert_second
m_twenty_to_29:
cmp r5, #0x20 @32~41
blt m_ten_to_19
sub r5, r5, #0xC @-12
b convert_second
m_ten_to_19:
cmp r5, #0x10 @16~25
blt convert_second
sub r5, r5, #0x6 @-6
convert_second:
cmp r6, #0x50
blt s_forty_to_49
sub r6, r6, #0x1E
b twelve_hour
s_forty_to_49:
cmp r6, #0x40
blt s_thirty_to_39
sub r6, r6, #0x18
b twelve_hour
s_thirty_to_39:
cmp r6, #0x30
blt s_twenty_to_29
sub r6, r6, #0x12
b twelve_hour
s_twenty_to_29:
cmp r6, #0x20
blt s_ten_to_19
sub r6, r6, #0xC
b twelve_hour
s_ten_to_19:
cmp r6, #0x10
blt twelve_hour
sub r6, r6, #0x6
twelve_hour:
cmp r1, #0xC
bge pm_time
cmp r1, #0x0
bne am_time
add r1, #0xC
am_time:
mov r2, #1
mov r3, #2
ldr r4, =0x8006BC5
bl call_r4
@bl go_padding_hmmss
ldr r0, =0x20232CC
add r7, r0, #0
add r1, r5, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8006BC5
bl call_r4
ldr r0, =0x20233CC
add r7, r0, #0
add r1, r6, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8006BC5
bl call_r4
ldr r5, =0x20234CC
ldr r0, =0x3000463
ldrb r0, [r0]
cmp r0, #0x1
beq monday_am
cmp r0, #0x2
beq tuesday_am
cmp r0, #0x3
beq wednesday_am
cmp r0, #0x4
beq thursday_am
cmp r0, #0x5
beq friday_am
cmp r0, #0x6
beq saturday_am
sunday_am:
ldr r1, =(0x86B0A00 + sun_am)
b am_pm
monday_am:
ldr r1, =(0x86B0A00 + mon_am)
b am_pm
tuesday_am:
ldr r1, =(0x86B0A00 + tue_am)
b am_pm
wednesday_am:
ldr r1, =(0x86B0A00 + wed_am)
b am_pm
thursday_am:
ldr r1, =(0x86B0A00 + thu_am)
b am_pm
friday_am:
ldr r1, =(0x86B0A00 + fri_am)
b am_pm
saturday_am:
ldr r1, =(0x86B0A00 + sat_am)
b am_pm
pm_time:
cmp r1, #0xC
beq pm_time_2
sub r1, #0xC
pm_time_2:
mov r2, #1
mov r3, #2
ldr r4, =0x8006BC5
bl call_r4
@bl go_padding_hmmss
ldr r0, =0x20232CC
add r7, r0, #0
add r1, r5, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8006BC5
bl call_r4
ldr r0, =0x20233CC
add r7, r0, #0
add r1, r6, #0
mov r2, #2
mov r3, #2
ldr r4, =0x8006BC5
bl call_r4
ldr r5, =0x20234CC
ldr r0, =0x3000463
ldrb r0, [r0]
cmp r0, #0x1
beq monday_pm
cmp r0, #0x2
beq tuesday_pm
cmp r0, #0x3
beq wednesday_pm
cmp r0, #0x4
beq thursday_pm
cmp r0, #0x5
beq friday_pm
cmp r0, #0x6
beq saturday_pm
sunday_pm:
ldr r1, =(0x86B0A00 + sun_pm)
b am_pm
monday_pm:
ldr r1, =(0x86B0A00 + mon_pm)
b am_pm
tuesday_pm:
ldr r1, =(0x86B0A00 + tue_pm)
b am_pm
wednesday_pm:
ldr r1, =(0x86B0A00 + wed_pm)
b am_pm
thursday_pm:
ldr r1, =(0x86B0A00 + thu_pm)
b am_pm
friday_pm:
ldr r1, =(0x86B0A00 + fri_pm)
b am_pm
saturday_pm:
ldr r1, =(0x86B0A00 + sat_pm)
b am_pm
am_pm:
add r0, r5, #0
ldr r3, =0x8006E45
bl call_r3
mov r1, #0x2
mov r2, #0x1
ldr r3, =0x8071E51
ldr r0, =0x20234CC
bl call_r3 @call Menu_PrintText
add sp, sp, #0xC
pop {r4-r7, pc}
.ltorg
go_padding_hmmss:
push {lr}
ldrb r0, [r7]
cmp r0, #0
bne back_2
mov r0, #0x0
strb r0, [r7]
back_2:
pop {pc}
call_r3:
bx r3
call_r4:
bx r4
var_decrypt:
ldr r1, vardecry
bx r1
.align 2
sun_am: .byte 0xCD, 0xCF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
sun_pm: .byte 0xCD, 0xCF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
mon_am: .byte 0xC7, 0xC9, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
mon_pm: .byte 0xC7, 0xC9, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
tue_am: .byte 0xCE, 0xCF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
tue_pm: .byte 0xCE, 0xCF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
wed_am: .byte 0xD1, 0xBF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
wed_pm: .byte 0xD1, 0xBF, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
thu_am: .byte 0xCE, 0xC2, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
thu_pm: .byte 0xCE, 0xC2, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
fri_am: .byte 0xC0, 0xCC, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
fri_pm: .byte 0xC0, 0xCC, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
sat_am: .byte 0xCD, 0xBB, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xBB, 0xC7, 0xFF
sat_pm: .byte 0xCD, 0xBB, 0x0, 0xFD, 0x2, 0xF0, 0xFD, 0x3, 0xF0, 0xFD, 0x4, 0x0, 0xCA, 0xC7, 0xFF
.align 2
vardecry:
.word 0x08069211
Spoiler:
Code:
@Changes bytes at 0x8071C30 to 00 49 08 47 EF+1 CD AB 08 after inserting.
@0x8ABCDEF is the address of Routine 2.
.thumb
ldr r0, =0x202E8CC
ldrh r0, [r0]
ldr r3, =0x807AB75
bl call_r3
ldr r3, =0x806553D
bl call_r3
ldr r3, =0x8072DED
bl call_r3
ldr r3, =0x8071C39
call_r3:
bx r3
Spoiler:
Code:
@Change bytes at 0x80714FC to 00 48 00 47 EF+1 CD AB 08 after inserting.
@0x8ABCDEF is the address of Routine 3.
.thumb
push {lr}
ldr r3, =0x8072DED
bl call_r3
ldr r0, =0x202E8CC
ldrh r0, [r0]
ldr r3, =0x807AB75
bl call_r3
ldr r1,=0x3004AE8
ldr r0,=0x80715A5
str r0,[r1]
mov r0,#0x0
pop {pc}
call_r3:
bx r3
Spoiler:
Known Bugs:
Spoiler:
- No fatal bugs found yet. But I haven't done thorough testing so some exceptions might still occur.
- Also, due to CPU consuming, when emulating with mGBA, the FireRed version would display "SUN 12:00:00 AM" and the Emerald version would display the last updated time when you exit "Option" for a split second.