Pretty Speedometer [stebler]
#1
Pretty Speedometer [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.

Limitations:
* Doesn't work in split-screen multiplayer.
* In time trials, it replaces the "GHOST DATA CANNOT BE SAVED" element.

Code credits: the Dossun team for some menu and screen symbols.

Screenshot: [Image: 1zhbexx.png]

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: 1 Guest(s)