Pretty Speedometer [stebler]
#1
Pretty Speedometer 2.0 [stebler]

Features:
* Works on Dolphin without reducing image quality or performance (xfb hacks can stay enabled).
* Native look and feel.
* Supports both 16:9 and 4:3, as well as split-screen multiplayer.

Screenshot: [Image: iGN5EXz.png]

PAL:
C2857CA0 00000002
7C63F214 83E1001C
60000000 00000000
04857EDC 56B50630
C25E88F0 00000006
4E800421 80930000
3CA0636F 60A5696E
7C042800 40820014
3C804370 90830190
38800020 B0830198
60000000 00000000
C2857F4C 0000001A
72A00001 408200BC
7CA802A6 4800003D
4358C30C C30CC365
436CC365 436CC336
41D0C343 42DC42DC
C2D2C2D2 4398C366
C366C3A6 43ACC3A6
43ACC33E 41C8C347
42E642E6 C2E6C2E6
7C6802A6 88810016
3884FFCF 7C848A14
5484083C 7C632214
3C808038 80846000
80840058 1C84001C
7C632214 A0830000
B094001C A083000E
B0940020 807400BC
80630014 80630010
3C803E80 90830040
90830044 38800002
988300FC 3865006C
2C150000 4182000C
3865FF94 62B50001
7C6803A6 4E800020
98140081 38600208
60000000 00000000
C27ED1D8 00000021
887E0081 2C030000
408200F8 8BFE0190
3C60809C 8063D728
7C63FA14 88830B84
3C60809C 806318F8
80630020 5484103A
7C63202E 80630000
80630028 C0230020
38610008 3880000D
48000019 001A0800
00010030 0025002E
00320066 00000000
7CA802A6 4CC63242
3D808001 618C7814
7D8903A6 4E800421
38810010 387F0030
3CA0809C 80A5D728
1CDF00F0 7CA53214
80A500F4 2C050002
41820008 38650020
B064FFFE A0640000
2C030000 41820038
2C03002D 40820008
3860246D 2C03002E
40820008 3860246B
38A3FFD0 28050009
41810008 38652460
B0640000 38840001
4BFFFFC4 7FC3F378
38810008 38A00000
3D808063 618CDDB4
7D8903A6 4E800421
800100E4 00000000
C25F8C88 00000003
2C040000 4080000C
7C832378 4E800020
80A30010 00000000
045F8D08 7C832378
045F8D44 386DBFC4
045CDDAC 2C14FFFF
045CDDB0 4082000C

NTSC-U:
C2836210 00000002
7C63F214 83E1001C
60000000 00000000
0483644C 56B50630
C25D2204 00000006
4E800421 80930000
3CA0636F 60A5696E
7C042800 40820014
3C804370 90830190
38800020 B0830198
60000000 00000000
C28364BC 0000001A
72A00001 408200BC
7CA802A6 4800003D
4358C30C C30CC365
436CC365 436CC336
41D0C343 42DC42DC
C2D2C2D2 4398C366
C366C3A6 43ACC3A6
43ACC33E 41C8C347
42E642E6 C2E6C2E6
7C6802A6 88810016
3884FFCF 7C848A14
5484083C 7C632214
3C808038 80841C80
80840058 1C84001C
7C632214 A0830000
B094001C A083000E
B0940020 807400BC
80630014 80630010
3C803E80 90830040
90830044 38800002
988300FC 3865006C
2C150000 4182000C
3865FF94 62B50001
7C6803A6 4E800020
98140081 38600208
60000000 00000000
C27E392C 00000021
887E0081 2C030000
408200F8 8BFE0190
3C60809C 80638F68
7C63FA14 88830B84
3C60809C 8063D110
80630020 5484103A
7C63202E 80630000
80630028 C0230020
38610008 3880000D
48000019 001A0800
00010030 0025002E
00320066 00000000
7CA802A6 4CC63242
3D808001 618C6CB4
7D8903A6 4E800421
38810010 387F0030
3CA0809C 80A58F68
1CDF00F0 7CA53214
80A500F4 2C050002
41820008 38650020
B064FFFE A0640000
2C030000 41820038
2C03002D 40820008
3860246D 2C03002E
40820008 3860246B
38A3FFD0 28050009
41810008 38652460
B0640000 38840001
4BFFFFC4 7FC3F378
38810008 38A00000
3D808060 618CC994
7D8903A6 4E800421
800100E4 00000000
C25D83A4 00000003
2C040000 4080000C
7C832378 4E800020
80A30010 00000000
045D8424 7C832378
045D8460 386DBFC4
045C128C 2C14FFFF
045C1290 4082000C

NTSC-J:
C285730C 00000002
7C63F214 83E1001C
60000000 00000000
04857548 56B50630
C25E81CC 00000006
4E800421 80930000
3CA0636F 60A5696E
7C042800 40820014
3C804370 90830190
38800020 B0830198
60000000 00000000
C28575B8 0000001A
72A00001 408200BC
7CA802A6 4800003D
4358C30C C30CC365
436CC365 436CC336
41D0C343 42DC42DC
C2D2C2D2 4398C366
C366C3A6 43ACC3A6
43ACC33E 41C8C347
42E642E6 C2E6C2E6
7C6802A6 88810016
3884FFCF 7C848A14
5484083C 7C632214
3C808038 80845980
80840058 1C84001C
7C632214 A0830000
B094001C A083000E
B0940020 807400BC
80630014 80630010
3C803E80 90830040
90830044 38800002
988300FC 3865006C
2C150000 4182000C
3865FF94 62B50001
7C6803A6 4E800020
98140081 38600208
60000000 00000000
C27EC844 00000021
887E0081 2C030000
408200F8 8BFE0190
3C60809C 8063C788
7C63FA14 88830B84
3C60809C 80630958
80630020 5484103A
7C63202E 80630000
80630028 C0230020
38610008 3880000D
48000019 001A0800
00010030 0025002E
00320066 00000000
7CA802A6 4CC63242
3D808001 618C7738
7D8903A6 4E800421
38810010 387F0030
3CA0809C 80A5C788
1CDF00F0 7CA53214
80A500F4 2C050002
41820008 38650020
B064FFFE A0640000
2C030000 41820038
2C03002D 40820008
3860246D 2C03002E
40820008 3860246B
38A3FFD0 28050009
41810008 38652460
B0640000 38840001
4BFFFFC4 7FC3F378
38810008 38A00000
3D808063 618CD420
7D8903A6 4E800421
800100E4 00000000
C25F8564 00000003
2C040000 4080000C
7C832378 4E800020
80A30010 00000000
045F85E4 7C832378
045F8620 386DBFC4
045CD688 2C14FFFF
045CD68C 4082000C

NTSC-K:
C2846060 00000002
7C63F214 83E1001C
60000000 00000000
0484629C 56B50630
C25D6A8C 00000006
4E800421 80930000
3CA0636F 60A5696E
7C042800 40820014
3C804370 90830190
38800020 B0830198
60000000 00000000
C284630C 0000001A
72A00001 408200BC
7CA802A6 4800003D
4358C30C C30CC365
436CC365 436CC336
41D0C343 42DC42DC
C2D2C2D2 4398C366
C366C3A6 43ACC3A6
43ACC33E 41C8C347
42E642E6 C2E6C2E6
7C6802A6 88810016
3884FFCF 7C848A14
5484083C 7C632214
3C808037 80844020
80840058 1C84001C
7C632214 A0830000
B094001C A083000E
B0940020 807400BC
80630014 80630010
3C803E80 90830040
90830044 38800002
988300FC 3865006C
2C150000 4182000C
3865FF94 62B50001
7C6803A6 4E800020
98140081 38600208
60000000 00000000
C27DB598 00000021
887E0081 2C030000
408200F8 8BFE0190
3C60809B 8063BD68
7C63FA14 88830B84
3C60809B 8063FF38
80630020 5484103A
7C63202E 80630000
80630028 C0230020
38610008 3880000D
48000019 001A0800
00010030 0025002E
00320066 00000000
7CA802A6 4CC63242
3D808001 618C787C
7D8903A6 4E800421
38810010 387F0030
3CA0809B 80A5BD68
1CDF00F0 7CA53214
80A500F4 2C050002
41820008 38650020
B064FFFE A0640000
2C030000 41820038
2C03002D 40820008
3860246D 2C03002E
40820008 3860246B
38A3FFD0 28050009
41810008 38652460
B0640000 38840001
4BFFFFC4 7FC3F378
38810008 38A00000
3D808062 618CC0CC
7D8903A6 4E800421
800100E4 00000000
C25E70A8 00000003
2C040000 4080000C
7C832378 4E800020
80A30010 00000000
045E7128 7C832378
045E7164 386DBFE4
045BBD6C 2C14FFFF
045BBD70 4082000C

Source code:
Code:
# inject at 80857ca0 (PAL)
# inject at 80836210 (NTSC-U)
# inject at 8085730c (NTSC-J)
# inject at 80846060 (NTSC-K)

add r3, r3, r30 # increase the control count by one speedometer per local player

lwz r31, 0x1c (r1) # original instruction
Code:
# replace at 80857edc (PAL)
# replace at 8083644c (NTSC-U)
# replace at 80857548 (NTSC-J)
# replace at 8084629c (NTSC-K)

# always create (at least) one CtrlRaceBattlePoint per player
# also reset the lsb which is used to know if the control is regular
rlwinm r21, r21, 0, 24, 24
Code:
# inject at 805e88f0 (PAL)
# inject at 805d2204 (NTSC-U)
# inject at 805e81cc (NTSC-J)
# inject at 805d6a8c (NTSC-K)

.set coin, 0x636f696e

bctrl # original instruction

lwz r4, 0x0 (r19) # get the brlyt name
lis r5, coin@h
ori r5, r5, coin@l
cmpw r4, r5 # check if it starts with "coin"
bne end # if not, we are done

# otherwise, patch the brlyt

# change the text pane size
lis r4, 0x4370 # 240.0f
stw r4, 0x190 (r3)

# change the maximum string size of the text pane
li r4, 0x20
sth r4, 0x198 (r3)

end:
Code:
# inject at 80857f4c (PAL)
# inject at 808364bc (NTSC-U)
# inject at 808575b8 (NTSC-J)
# inject at 8084630c (NTSC-K)

.set region, ''

.if (region == 'P')
    .set SystemManager_s_instance, 0x80386000
.elseif (region == 'E')
    .set SystemManager_s_instance, 0x80381c80
.elseif (region == 'J')
    .set SystemManager_s_instance, 0x80385980
.elseif (region == 'K')
    .set SystemManager_s_instance, 0x80374020
.else
    .err
.endif

andi. r0, r21, 0x1 # check if we are creating a custom control
bne end # if not, we are (almost) done

mflr r5 # backup the lr

bl positions
# 4:3 x
.short 0x4358 # 1/1: 216.0f
.short 0xc30c # 1/2: -140.0f
.short 0xc30c # 2/2: -140.0f
.short 0xc365 # 1/4: -229.0f
.short 0x436c # 2/4: 236.0f
.short 0xc365 # 3/4: -229.0f
.short 0x436c # 4/4: 236.0f

# 4:3 y
.short 0xc336 # 1/1: -182.0f
.short 0x41d0 # 1/2: 26.0f
.short 0xc343 # 2/2: -195.0f
.short 0x42dc # 1/4: 110.0f
.short 0x42dc # 2/4: 110.0f
.short 0xc2d2 # 3/4: -105.0f
.short 0xc2d2 # 4/4: -105.0f

# 16:9 x
.short 0x4398 # 1/1: 304.0f
.short 0xc366 # 1/2: -230.0f
.short 0xc366 # 2/2: -230.0f
.short 0xc3a6 # 1/4: -332.0f
.short 0x43ac # 2/4: 344.0f
.short 0xc3a6 # 3/4: -332.0f
.short 0x43ac # 4/4: 344.0f

# 16:9 y
.short 0xc33e # 1/1: -190.0f
.short 0x41c8 # 1/2: 25.0f
.short 0xc347 # 2/2: -199.0f
.short 0x42e6 # 1/4: 115.0f
.short 0x42e6 # 2/4: 115.0f
.short 0xc2e6 # 3/4: -115.0f
.short 0xc2e6 # 4/4: -115.0f
positions:
mflr r3

# compute the address
lbz r4, 0x8 + 0xe (r1)
subi r4, r4, 0x30 + 0x1
add r4, r4, r17
slwi r4, r4, 1
add r3, r3, r4
lis r4, SystemManager_s_instance@ha
lwz r4, SystemManager_s_instance@l (r4)
lwz r4, 0x58 (r4)
mulli r4, r4, 0x1c
add r3, r3, r4

# set the x position
lhz r4, 0x0 (r3)
sth r4, 0x1c (r20)

# set the y position
lhz r4, 0xe (r3)
sth r4, 0x20 (r20)

# access the layout
lwz r3, 0xbc (r20)
lwz r3, 0x14 (r3)
lwz r3, -0x4 + 0x14 (r3)

# set the scale
lis r4, 0x3e80
stw r4, -0x4 + 0x44 (r3)
stw r4, -0x4 + 0x48 (r3)

# align the text to the right
li r4, 0x2
stb r4, -0x4 + 0x100 (r3)

addi r3, r5, 0x6c # setup the lr to skip the creation of the CtrlRaceBattleAddPoint

cmpwi r21, 0x0 # check if the battle point controls are disabled
beq jump

subi r3, r5, 0x6c # setup the lr to create the second CtrlRaceBattlePoint
ori r21, r21, 0x1 # mark the custom control as created

jump:
mtlr r3
blr

end:
stb r0, 0x81 (r20) # mark the control as regular

li r3, 0x208 # original instruction
Code:
# inject at 807ed1d8 (PAL)
# inject at 807e392c (NTSC-U)
# inject at 807ec844 (NTSC-J)
# inject at 807db598 (NTSC-K)

.set region, ''

.if (region == 'P')
    .set swprintf, 0x80017814
    .set LayoutUIControl_setMessageAll, 0x8063ddb4
    .set RaceConfig_s_instance, 0x809bd728
    .set KartManager_s_instance, 0x809c18f8
.elseif (region == 'E')
    .set swprintf, 0x80016cb4
    .set LayoutUIControl_setMessageAll, 0x8060c994
    .set RaceConfig_s_instance, 0x809b8f68
    .set KartManager_s_instance, 0x809bd110
.elseif (region == 'J')
    .set swprintf, 0x80017738
    .set LayoutUIControl_setMessageAll, 0x8063d420
    .set RaceConfig_s_instance, 0x809bc788
    .set KartManager_s_instance, 0x809c0958
.elseif (region == 'K')
    .set swprintf, 0x8001787c
    .set LayoutUIControl_setMessageAll, 0x8062c0cc
    .set RaceConfig_s_instance, 0x809abd68
    .set KartManager_s_instance, 0x809aff38
.else
        .err
.endif

lbz r3, 0x81 (r30)
cmpwi r3, 0x0 # check if the control is custom
bne end # if not, we are done

# get the local player id
lbz r31, 0x190 (r30)

# get the player id
lis r3, RaceConfig_s_instance@ha
lwz r3, RaceConfig_s_instance@l (r3)
add r3, r3, r31
lbz r4, 0xb84 (r3)

# get the speed
lis r3, KartManager_s_instance@ha
lwz r3, KartManager_s_instance@l (r3)
lwz r3, 0x20 (r3)
slwi r4, r4, 2
lwzx r3, r3, r4
lwz r3, 0x0 (r3)
lwz r3, 0x28 (r3)
lfs f1, 0x20 (r3)

# format the string
addi r3, r1, 0x8
li r4, 0xd
bl format
.short 0x001a, 0x0800, 0x0001, 0x0030 # color
.string16 "%.2f"
.balign 4
format:
mflr r5
crset 4 * cr1 + eq

lis r12, swprintf@h
ori r12, r12, swprintf@l
mtctr r12
bctrl

addi r4, r1, 0x10

# change the color depending on the local player id and the team
addi r3, r31, 0x30
lis r5, RaceConfig_s_instance@ha
lwz r5, RaceConfig_s_instance@l (r5)
mulli r6, r31, 0xf0
add r5, r5, r6
lwz r5, 0xf4 (r5)
cmpwi r5, 0x2
beq no_team
addi r3, r5, 0x20
no_team:
sth r3, -0x2 (r4)

# replace digits, dashes and dots with the timer versions
loop:
lhz r3, 0x0 (r4)
cmpwi r3, 0x0
beq out

cmpwi r3, 0x2d
bne not_a_dash
li r3, 0x246d

not_a_dash:
cmpwi r3, 0x2e
bne not_a_dot
li r3, 0x246b

not_a_dot:
subi r5, r3, 0x30
cmplwi r5, 0x9
bgt not_a_digit
addi r3, r5, 0x2460

not_a_digit:
sth r3, 0x0 (r4)
addi r4, r4, 0x1
b loop

out:

# update the message
mr r3, r30
addi r4, r1, 0x8
li r5, 0x0

lis r12, LayoutUIControl_setMessageAll@h
ori r12, r12, LayoutUIControl_setMessageAll@l
mtctr r12
bctrl

end:
lwz r0, 0xe4 (r1) # original instruction
Code:
# inject at 805f8c88 (PAL)
# inject at 805d83a4 (NTSC-U)
# inject at 805f8564 (NTSC-J)
# inject at 805e70a8 (NTSC-K)

cmpwi r4, 0x0 # check if the message id is a pointer
bge end # is not, we are done

# otherwise return it as a slot
mr r3, r4
blr

end:
lwz r5, 0x10 (r3) # original instruction
Code:
# replace at 805f8d08 (PAL)
# replace at 805d8424 (NTSC-U)
# replace at 805f85e4 (NTSC-J)
# replace at 805e7128 (NTSC-K)

mr r3, r4 # if the slot is a pointer, return it as the message
Code:
# replace at 805f8d44 (PAL)
# replace at 805d8460 (NTSC-U)
# replace at 805f8620 (NTSC-J)
# replace at 805e7164 (NTSC-K)

.set region, ''

.if (region == 'P')
    .set offset, 0x403c
.elseif (region == 'E')
    .set offset, 0x403c
.elseif (region == 'J')
    .set offset, 0x403c
.elseif (region == 'K')
    .set offset, 0x401c
.else
    .err
.endif

# if the slot is a pointer, return a pointer to the attributes
# we have the wanted value somewhere in sdata2
subi r3, r13, offset
Code:
# replace at 805cddac (PAL)
# replace at 805c128c (NTSC-U)
# replace at 805cd688 (NTSC-J)
# replace at 805bbd6c (NTSC-K)

# only consider -1 as "no slot found"
cmpwi r20, -0x1
bne 0xc

Version 1.1:
Quote:NTSC-U:
c25ddb7c 00000008
80a30004 2c05000c
41820028 2c05000e
41820020 2c050012
41820018 2c050040
41820010 2c050042
41820008 48000008
38840001 7c852378
60000000 00000000
c2836a48 00000007
560004e7 40820030
806f0004 2c03000c
41820020 2c03000e
41820018 2c030012
41820010 2c030040
41820008 2c030042
4c421042 00000000
c25c1214 00000009
2c040000 4082003c
3d004330 91010070
91010078 7c721b78
3a600000 3f008089
3b18eed0 90a10020
38a00001 90a10010
3ca0805c 60a512e8
7ca803a6 4e800020
80040000 00000000
c2575b44 0000002c
48000019 001a0800
00010030 0025002e
00320066 00000000
807d0000 80630000
88630010 3c80809c
80848f68 88840b84
7c032000 40820120
3c60809c 8063d508
80630000 83830038
2c1c0000 40820044
8383003c 2c1c0000
40820038 83830040
2c1c0000 4082002c
83830050 2c1c0000
40820020 83830108
2c1c0000 40820014
83830110 2c1c0000
40820008 480000c8
3821ffd8 c03d0020
4cc63242 38610008
38800010 7ca802a6
3d808001 618c6cb4
7d8903a6 4e800421
38a10008 38850008
a0640000 2c030000
4182003c 2c03002d
40820008 3860246d
2c03002e 40820008
3860246b 2c030030
41800010 2c03003a
40800008 38632430
b0640000 38840001
4bffffc0 807c005c
3c8042f0 3cc08038
80c61c80 80c60058
2c060001 41820008
3c8041f0 9083004c
38800000 98830080
38c00002 80630114
80e30000 98c70100
3d80805c 618c11e0
7d8903a6 4e800421
38210028 83e1007c
60000000 00000000

PAL:
c260245c 00000008
80a30004 2c05000c
41820028 2c05000e
41820020 2c050012
41820018 2c050040
41820010 2c050042
41820008 48000008
38840001 7c852378
60000000 00000000
c28584d8 00000007
560004e7 40820030
806f0004 2c03000c
41820020 2c03000e
41820018 2c030012
41820010 2c030040
41820008 2c030042
4c421042 00000000
c25cdd34 00000009
2c040000 4082003c
3d004330 91010070
91010078 7c721b78
3a600000 3f008089
3b183e70 90a10020
38a00001 90a10010
3ca0805c 60a5de08
7ca803a6 4e800020
80040000 00000000
c257c3a8 0000002c
48000019 001a0800
00010030 0025002e
00320066 00000000
807d0000 80630000
88630010 3c80809c
8084d728 88840b84
7c032000 40820120
3c60809c 80631e38
80630000 83830038
2c1c0000 40820044
8383003c 2c1c0000
40820038 83830040
2c1c0000 4082002c
83830050 2c1c0000
40820020 83830108
2c1c0000 40820014
83830110 2c1c0000
40820008 480000c8
3821ffd8 c03d0020
4cc63242 38610008
38800010 7ca802a6
3d808001 618c7814
7d8903a6 4e800421
38a10008 38850008
a0640000 2c030000
4182003c 2c03002d
40820008 3860246d
2c03002e 40820008
3860246b 2c030030
41800010 2c03003a
40800008 38632430
b0640000 38840001
4bffffc0 807c005c
3c8042f0 3cc08038
80c66000 80c60058
2c060001 41820008
3c8041f0 9083004c
38800000 98830080
38c00002 80630114
80e30000 98c70100
3d80805c 618cdd00
7d8903a6 4e800421
38210028 83e1007c
60000000 00000000

NTSC-J:
c2601bd0 00000008
80a30004 2c05000c
41820028 2c05000e
41820020 2c050012
41820018 2c050040
41820010 2c050042
41820008 48000008
38840001 7c852378
60000000 00000000
c2857b44 00000007
560004e7 40820030
806f0004 2c03000c
41820020 2c03000e
41820018 2c030012
41820010 2c030040
41820008 2c030042
4c421042 00000000
c25cd610 00000009
2c040000 4082003c
3d004330 91010070
91010078 7c721b78
3a600000 3f008089
3b1834c0 90a10020
38a00001 90a10010
3ca0805c 60a5d6e4
7ca803a6 4e800020
80040000 00000000
c257bd28 0000002c
48000019 001a0800
00010030 0025002e
00320066 00000000
807d0000 80630000
88630010 3c80809c
8084c788 88840b84
7c032000 40820120
3c60809c 80630e98
80630000 83830038
2c1c0000 40820044
8383003c 2c1c0000
40820038 83830040
2c1c0000 4082002c
83830050 2c1c0000
40820020 83830108
2c1c0000 40820014
83830110 2c1c0000
40820008 480000c8
3821ffd8 c03d0020
4cc63242 38610008
38800010 7ca802a6
3d808001 618c7738
7d8903a6 4e800421
38a10008 38850008
a0640000 2c030000
4182003c 2c03002d
40820008 3860246d
2c03002e 40820008
3860246b 2c030030
41800010 2c03003a
40800008 38632430
b0640000 38840001
4bffffc0 807c005c
3c8042f0 3cc08038
80c65980 80c60058
2c060001 41820008
3c8041f0 9083004c
38800000 98830080
38c00002 80630114
80e30000 98c70100
3d80805c 618cd5dc
7d8903a6 4e800421
38210028 83e1007c
60000000 00000000

NTSC-K:
c25f087c 00000008
80a30004 2c05000c
41820028 2c05000e
41820020 2c050012
41820018 2c050040
41820010 2c050042
41820008 48000008
38840001 7c852378
60000000 00000000
c2846898 00000007
560004e7 40820030
806f0004 2c03000c
41820020 2c03000e
41820018 2c030012
41820010 2c030040
41820008 2c030042
4c421042 00000000
c25bbcf4 00000009
2c040000 4082003c
3d004330 91010070
91010078 7c721b78
3a600000 3f008088
3b182280 90a10020
38a00001 90a10010
3ca0805b 60a5bdc8
7ca803a6 4e800020
80040000 00000000
c256a400 0000002c
48000019 001a0800
00010030 0025002e
00320066 00000000
807d0000 80630000
88630010 3c80809b
8084bd68 88840b84
7c032000 40820120
3c60809b 80630478
80630000 83830038
2c1c0000 40820044
8383003c 2c1c0000
40820038 83830040
2c1c0000 4082002c
83830050 2c1c0000
40820020 83830108
2c1c0000 40820014
83830110 2c1c0000
40820008 480000c8
3821ffd8 c03d0020
4cc63242 38610008
38800010 7ca802a6
3d808001 618c787c
7d8903a6 4e800421
38a10008 38850008
a0640000 2c030000
4182003c 2c03002d
40820008 3860246d
2c03002e 40820008
3860246b 2c030030
41800010 2c03003a
40800008 38632430
b0640000 38840001
4bffffc0 807c005c
3c8042f0 3cc08037
80c64020 80c60058
2c060001 41820008
3c8041f0 9083004c
38800000 98830080
38c00002 80630114
80e30000 98c70100
3d80805b 618cbcc0
7d8903a6 4e800421
38210028 83e1007c
60000000 00000000

Source code:

Increment the child count of the single player gameplay screens other than time trial:
Code:
# inject at 8060245c (PAL)
# inject at 805ddb7c (NTSC-U)
# inject at 80601bd0 (NTSC-J)
# inject at 805f087c (NTSC-K)

lwz r5, 0x4 (r3)

cmpwi r5, 0xc # grand prix
beq increment

cmpwi r5, 0xe # 1 player offline vs
beq increment

cmpwi r5, 0x12 # 1 player battle
beq increment

cmpwi r5, 0x40 # 1 player ww/regional vs
beq increment

cmpwi r5, 0x42 # 1 player friend room vs
beq increment

b end

increment:
addi r4, r4, 0x1

end:
mr r5, r4 # original instruction
Add the "GHOST DATA CANNOT BE SAVED" element to single player gameplay screens other than time trial:
Code:
# inject at 808584d8 (PAL)
# inject at 80836a48 (NTSC-U)
# inject at 80857b44 (NTSC-J)
# inject at 80846898 (NTSC-K)

rlwinm. r0, r16, 0x0, 19, 19 # original instruction
bne end

lwz r3, 0x4 (r15)

cmpwi r3, 0xc # grand prix
beq invert

cmpwi r3, 0xe # 1 player offline vs
beq invert

cmpwi r3, 0x12 # 1 player battle
beq invert

cmpwi r3, 0x40 # 1 player ww/regional vs
beq invert

cmpwi r3, 0x42 # 1 player friend room vs

invert:
crnot 4 * cr0 + eq, 4 * cr0 + eq

end:
Extend the setTextSrc method to load text from an arbitrary string instead of a bmg, if the argument in r4 is null:
Code:
# inject at 805cdd34 (PAL)
# inject at 805c1214 (NTSC-U)
# inject at 805cd610 (NTSC-J)
# inject at 805bbcf4 (NTSC-K)

.set region, ''

.if (region == 'P')
        .set ptr_consts, 0x80893e70
        .set target, 0x805cde08
.elseif (region == 'E')
        .set ptr_consts, 0x8088eed0
        .set target, 0x805c12e8
.elseif (region == 'J')
        .set ptr_consts, 0x808934c0
        .set target, 0x805cd6e4
.elseif (region == 'K')
        .set ptr_consts, 0x80882280
        .set target, 0x805bbdc8
.else
        .err
.endif

# check if custom text is enabled
cmpwi r4, 0x0
bne end

# some registers are initialized in the middle of the bmg loading stuff we are skipping, so we have
# to do it here instead
lis r8, 0x4330
stw r8, 0x70 (r1)
stw r8, 0x78 (r1)
mr r18, r3
li r19, 0x0
lis r24, ptr_consts@ha
addi r24, r24, ptr_consts@l

# load the custom string
stw r5, 0x20 (r1)
li r5, 0x1
stw r5, 0x10 (r1)

# jump to the end of the bmg loading stuff
lis r5, target@h
ori r5, r5, target@l
mtlr r5
blr

end:
lwz r0, 0x0 (r4) # original instruction
Make the element visible, and set its value to the current speed:
Code:
# inject at 8057c3a8 (PAL)
# inject at 80575b44 (NTSC-U)
# inject at 8057bd28 (NTSC-J)
# inject at 8056a400 (NTSC-K)

.set region, ''

.if (region == 'P')
        .set ptr_raceData, 0x809bd728
        .set ptr_menuData, 0x809c1e38
        .set swprintf, 0x80017814
        .set ptr_unk, 0x80386000
        .set ScreenElement_setTextSrc, 0x805cdd00
.elseif (region == 'E')
        .set ptr_raceData, 0x809b8f68
        .set ptr_menuData, 0x809bd508
        .set swprintf, 0x80016cb4
        .set ptr_unk, 0x80381c80
        .set ScreenElement_setTextSrc, 0x805c11e0
.elseif (region == 'J')
        .set ptr_raceData, 0x809bc788
        .set ptr_menuData, 0x809c0e98
        .set swprintf, 0x80017738
        .set ptr_unk, 0x80385980
        .set ScreenElement_setTextSrc, 0x805cd5dc
.elseif (region == 'K')
        .set ptr_raceData, 0x809abd68
        .set ptr_menuData, 0x809b0478
        .set swprintf, 0x8001787c
        .set ptr_unk, 0x80374020
        .set ScreenElement_setTextSrc, 0x805bbcc0
.else
        .err
.endif

bl format

.short 0x001a, 0x0800, 0x0001, 0x0030 # bmg escape sequence for yellow text
.string16 "%.2f\0"

format:

# get the player index of the player on which the hooked function is working
lwz r3, 0x0 (r29)
lwz r3, 0x0 (r3)
lbz r3, 0x10 (r3)

# get the player index from the first hud slot
lis r4, ptr_raceData@ha
lwz r4, ptr_raceData@l (r4)
lbz r4, 0xb84 (r4)

# if they don't match, the speedometer will not be updated
cmpw r3, r4
bne end

# check if a single player gameplay screen is active
lis r3, ptr_menuData@ha
lwz r3, ptr_menuData@l (r3)
lwz r3, 0x0 (r3)

lwz r28, 0x38 (r3) # grand prix
cmpwi r28, 0x0
bne found

lwz r28, 0x3c (r3) # time trial
cmpwi r28, 0x0
bne found

lwz r28, 0x40 (r3) # 1 player offline vs
cmpwi r28, 0x0
bne found

lwz r28, 0x50 (r3) # 1 player battle
cmpwi r28, 0x0
bne found

lwz r28, 0x108 (r3) # 1 player ww/regional vs
cmpwi r28, 0x0
bne found

lwz r28, 0x110 (r3) # 1 player friend room vs
cmpwi r28, 0x0
bne found

b end

found:

# allocate stack memory:
# * 0x8 needed by swprintf
# * 0x20 for the formatted string
addi r1, r1, -0x28

# prepare the arguments for swprintf
lfs f1, 0x20 (r29)
crset 4 * cr1 + eq
addi r3, r1, 0x8
li r4, 0x10
mflr r5

lis r12, swprintf@h
ori r12, r12, swprintf@l
mtctr r12
bctrl

addi r5, r1, 0x8 # beginning of the formatted string
addi r4, r5, 0x8 # we do not want to process the bmg escape sequence

# replace digits, dashes and dots with the timer versions
loop:
lhz r3, 0x0 (r4)
cmpwi r3, 0x0
beq out

cmpwi r3, 0x2d
bne not_a_dash
li r3, 0x246d

not_a_dash:
cmpwi r3, 0x2e
bne not_a_dot
li r3, 0x246b

not_a_dot:
cmpwi r3, 0x30
blt not_a_digit
cmpwi r3, 0x3a
bge not_a_digit
addi r3, r3, 0x2430

not_a_digit:
sth r3, 0x0 (r4)
addi r4, r4, 0x1
b loop

out:

lwz r3, 0x5c (r28)

# set the position of the hud element
lis r4, 0x42f0 # 120.0f for 16:9
lis r6, ptr_unk@ha
lwz r6, ptr_unk@l (r6)
lwz r6, 0x58 (r6)
cmpwi r6, 0x1
beq widescreen
lis r4, 0x41f0 # 30.0f for 4:3
widescreen:
stw r4, 0x4c (r3)

# make the element visible
li r4, 0x0
stb r4, 0x80 (r3)

# align the text to the right
li r6, 0x2
lwz r3, 0x114 (r3)
lwz r7, 0x0 (r3)
stb r6, 0x100 (r7)

lis r12, ScreenElement_setTextSrc@h
ori r12, r12, ScreenElement_setTextSrc@l
mtctr r12
bctrl

addi r1, r1, 0x28

end:
lwz r31, 0x7c (r1) # original instruction
Reply
#2
Cannot overstate how useful this is going to be. Finally dolphin users will have a nice looking som, and this'll also help distributions that do not want to use CT-code. Amazing job and already a contender for code of the year in...January.
Reply
#3
(01-16-2021, 09:58 PM)Melg Wrote: Cannot overstate how useful this is going to be. Finally dolphin users will have a nice looking som, and this'll also help distributions that do not want to use CT-code. Amazing job and already a contender for code of the year in...January.

This!

2021 Code of the Year
Reply
#4
OMG this is great
Discord: Alina.#6309
Twitter: @RMCW01

[Image: Screenshot_2021-02-15_184623.png]
Reply
#5
The code has been updated with correct right-alignment instead of padding zeros, and some slight latency improvements.
Reply
#6
Really Nice Code. Will is be possible to change the color of it ?
Reply
#7
(01-17-2021, 06:04 PM)Optllizer Wrote: Really Nice Code. Will is be possible to change the color of it ?

Yes, you can do this by replacing 00010030 with 000100xx where xx is 00 for gray, 01 for red, 02 for white, etc. You can find the full color list here.
Reply
#8
Video of the code in action

Reply
#9
[Image: Dolphin_2021-01-18_17_24_02.png?width=828&height=433]
NTSC-K shows a bunch of blocks , just letting know
Discord : Kozue#0007
[Image: RMCJ01_2021-01-11_15-23-53.png]

Best time on PS4 Controller
Reply
#10
(01-18-2021, 10:27 PM)Again Wrote: [Image: Dolphin_2021-01-18_17_24_02.png?width=828&height=433]
NTSC-K shows a bunch of blocks , just letting know
I updated a new version that hopefully fixes the bug (the code was using snprintf instead of swprintf), can you test it?
Reply


Forum Jump:


Users browsing this thread: 9 Guest(s)