RE: Pretty Speedometer [stebler] - jawa - 10-12-2023
(02-09-2021, 04:39 PM)Melg Wrote: Yes you can change it to display anything really. For example this is a debug panel code I made for CT authors and testers:
This code essentially patches setTextsrc to display any arbitrary string if you call it with r4=0.
The easy way (but not the shortest) to do it is just to change the ASM contents of the last code. You need to call swprintf with the string of your choice. It uses the standard C printf formatting.
The arguments for swprintf are:
r6 through r10 are your integer/pointer to char arguments (%d %c in the string)
f1 through f8 are your float arguments (%f in the string)
So you'd replace the original string by the one of your choice, eg:
Code: .string16 "Integer1 %3d Integer2 %1d \a Float1 %3.0f"
And there before swprintf gets called, you load your arguments:
Code: lwz r6, 0x21 (r3)
lbz r7, 0x30 (r3)
lfs f1, 0x90 (r3)
This specific example would draw on the screen
Code: Integer1 r6 Integer2 r7
Float1 f1
You can also hook at a different instruction, format your string (by calling swprintf and then making any modification to the string you'd want) there and then call setTxtsrc there, if your arguments loading is easier at that instruction.
I cannot find this cheat code anywhere online. Do you still have it?
RE: Pretty Speedometer [stebler] - Cealgair - 10-13-2023
There is a very similar code here: https://mariokartwii.com/showthread.php?tid=2049&pid=10779#pid10779
RE: Pretty Speedometer [stebler] - Vega - 08-10-2024
Here's the older speedometer displaying live margin vs ghost if anyone wants it. Was requested some days ago for this, might as well post it on the forums. It's specifically based off the configurable XYZ speedometer on page 8 here -> https://mariokartwii.com/showthread.php?tid=1730&pid=11158#pid11158
Video - https://www.youtube.com/watch?v=Xie6dnohKDw
Live Margin [Stebler, Vega, Gearworks]
Shows Time Delta vs Ghost at all times. Does the Marign diff than how the Game does it for lap crossings. To disable the lap margin text, apply with Diamonds code - https://mariokartwii.com/showthread.php?tid=1625
PAL (too lazy to assemble for all 4 regions; configured using XYZ speed for time delta with text on bottom right)
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
C2597820 0000004E
38E00000 3F4042F0
3F6041F0 3FC0C35C
3FE03F80 807C0000
80630000 88630010
3C80809C 8084D728
88840B84 7C032000
40A20238 3C60809C
80631E38 80630000
83A30038 2C1D0000
40820040 83A3003C
2C1D0000 40820034
83A30040 2C1D0000
40820028 83A30050
2C1D0000 4082001C
83A30108 2C1D0000
40820010 83A30110
2C1D0000 418201E4
4800002D 001A0800
00010030 0025002E
00330066 00000000
42700000 40200000
001A0800 00010021
221E0000 3D80809C
818CD6E8 818C0020
C1AC0010 3D60809C
816BD730 816B000C
814B0000 C16A000C
ED6B0372 812B0004
C189000C ED8C0372
FF8B6040 39000000
409D0008 39000001
3C60809C 806318F8
80630020 5508103A
7C63402E 80630000
80630008 80630090
80830004 E0630018
C0830020 E0240068
C0440070 2C070000
41820010 EC000028
10210460 10630460
10211828 EC422028
10210072 10210854
EC2208BA FC200834
EC200830 7CA802A6
C1A50014 EDA10372
C0050018 FC8D0040
3821FF00 40A4000C
38A5001C 48000094
409D000C 118B6420
116C64E0 EC4C5828
EC226824 38000030
419D0008 38000021
98050007 4CC63242
38610008 38800100
3D808001 618C7814
7D8903A6 4E800421
38A10008 3881000E
A4640002 2C030000
41820040 2C03002D
41820024 2C03002E
41820024 28030030
41A0FFE0 28030039
41A1FFD8 38632430
48000010 3860246D
48000008 3860246B
B0640000 4BFFFFBC
807D005C 3CC08038
80C66000 80C60058
2C060001 93C30050
93E30058 41A2000C
9363004C 48000008
9343004C 38800000
98830080 38C00002
80630114 80E30000
98C70100 3D80805C
618CDD00 7D8903A6
4E800421 38210100
39610100 00000000
Source for the 4th ASM code only:
Code: #Address Ports
#Inject at 80597820 (PAL)
#Inject at 80590FFC (NTSC-U)
#Inject at 805971A0 (NTSC-J)
#Inject at 80585878 (NTSC-K)
#Region Compilation Setting & Assembler Directives
.set region, ''
.if (region == 'p')
.set ptr_raceData, 0x809bd728
.set ptr_menuData, 0x809c1e38
.set swprintf, 0x80017814
.set ptr_unk, 0x80386000
.set ScreenElement_setTextSrc, 0x805cdd00
.set racedirector, 0x809BD730
.set kmpinfo, 0x809BD6E8
.set PlayerHolder, 0x809C18F8
.elseif (region == 'e')
.set ptr_raceData, 0x809b8f68
.set ptr_menuData, 0x809bd508
.set swprintf, 0x80016cb4
.set ptr_unk, 0x80381c80
.set ScreenElement_setTextSrc, 0x805c11e0
.set racedirector, 0x809B8F70
.set kmpinfo, 0x809B8F28
.set PlayerHolder, 0x809BD110
.elseif (region == 'j')
.set ptr_raceData, 0x809bc788
.set ptr_menuData, 0x809c0e98
.set swprintf, 0x80017738
.set ptr_unk, 0x80385980
.set ScreenElement_setTextSrc, 0x805cd5dc
.set racedirector, 0x809BC790
.set kmpinfo, 0x809BC748
.set PlayerHolder, 0x809C0958
.elseif (region == 'k')
.set ptr_raceData, 0x809abd68
.set ptr_menuData, 0x809b0478
.set swprintf, 0x8001787c
.set ptr_unk, 0x80374020
.set ScreenElement_setTextSrc, 0x805bbcc0
.set racedirector, 0x809ABD70
.set kmpinfo, 0x809ABD28
.set PlayerHolder, 0x809AFF38
.else
.err
.endif
#Register Safety Notes
#r0, r3 thru r12 safe, r26 thru r31 safe
#f0 thru 13, and f29 safe
#LR and CTR safe
#Set User config registers
li r7, 0 #0 = XYZ Speed, #1 = XY Speed
lis r26, 0x42F0 #Set widescreen X position
lis r27, 0x41F0 #Set 4:3 X position
lis r30, 0xC35C #Set Y position
lis r31, 0x3F80 #Set Scale
#Get Slot that code is currently hooked on. Then get your Slot value. Make sure they are equal
lwz r3, 0 (r28) #r28 is Player Data ptr
lwz r3, 0 (r3)
lbz r3, 0x10 (r3)
lis r4, ptr_raceData@ha
lwz r4, ptr_raceData@l (r4)
lbz r4, 0x0B84 (r4)
cmpw r3, r4 #If slots don't match, skip code
bne+ end
#Check if a single player gameplay screen is active, keep pointer in r29 for later use
lis r3, ptr_menuData@ha
lwz r3, ptr_menuData@l (r3)
lwz r3, 0 (r3)
lwz r29, 0x38 (r3) # grand prix
cmpwi r29, 0
bne- found
lwz r29, 0x3C (r3) # time trial
cmpwi r29, 0
bne- found
lwz r29, 0x40 (r3) # 1 player offline vs
cmpwi r29, 0
bne- found
lwz r29, 0x50 (r3) # 1 player battle
cmpwi r29, 0
bne- found
lwz r29, 0x108 (r3) # 1 player ww/regional vs
cmpwi r29, 0
bne- found
lwz r29, 0x110 (r3) # 1 player friend room vs
cmpwi r29, 0
beq- end
#Single Player screen is active!
#Create the string via BL Trick
found:
bl format
.short 0x001A, 0x0800, 0x0001, 0x0030 #Bmg escape sequence for yellow text
.short 0x0025, 0x002E, 0x0033, 0x0066 #16-bit ascii for %.3f
.long 0 #Because below float EA must be div'd by 4
.float 60.0 #For time delta calculation, might as well put it here
.float 2.5 #Limit for infi text
infi_text:
.short 0x001A, 0x0800, 0x0001, 0x0021 #Bmg escape sequence for yellow text
.short 0x221E, 0x0000 #inf symbol
.align 2
format:
#Get Course Length
lis r12, kmpinfo@ha
lwz r12, kmpinfo@l (r12)
lwz r12, 0x20 (r12)
lfs f13, 0x10 (r12)
#Get level 2 ptr from race director
lis r11, racedirector@ha
lwz r11, racedirector@l (r11)
lwz r11, 0xC (r11)
#Get slot 0's (human's) race distance
lwz r10, 0 (r11)
lfs f11, 0xC (r10) #slot 0 race completion
fmuls f11, f11, f13
#Get slot 1's (CPU's) race distance
lwz r9, 0x4 (r11)
lfs f12, 0xC (r9) #slot 1 race completion
fmuls f12, f12, f13
#See who's ahead.
#We need speed from person behind
fcmpo cr7, f11, f12
li r8, 0 #Default slot value 0
ble- cr7, 0x8 #If ghost is equal or ahead, take this branch, we need slot0's speed
li r8, 1
#Get Player Data ptr based on slot
lis r3, PlayerHolder@ha
lwz r3, PlayerHolder@l (r3)
lwz r3, 0x0020 (r3)
slwi r8, r8, 2 #mulli by 4
lwzx r3, r3, r8
lwz r3, 0 (r3) #r3 is Player Data ptr
#Get Player's current and prev XYZs
lwz r3, 0x8 (r3)
lwz r3, 0x90 (r3) #r3 is base pointer nearby prev XYZ
lwz r4, 0x4 (r3) #r4 is base pointer nearby current XYZ
psq_l f3, 0x18 (r3), 0, 0 #old XY
lfs f4, 0x20 (r3) #old Z
psq_l f1, 0x68 (r4), 0, 0 #new XY
lfs f2, 0x70 (r4) #new Z
#Check for XYZ vs XZ
cmpwi r7, 0
beq- skip_xz_adjustments
#Null out both Y Values
#Merge old X with new Y values back together in their respective original FPRs
fsubs f0, f0, f0 #Subtract FPR by itself to make it Null
ps_merge01 f1, f1, f0 #Merge in nulled out Y value f1 ps1
ps_merge01 f3, f3, f0 #Merge in nulled out Y value to f3 ps1
#Do the formula: sqrt{[(x2 - x1)^2] + [(y2 - y1)^2] + [(z2 - z1)^2]}
#X2 = f1 ps0
#X1 = f3 ps0
#Y2 = f1 ps1
#Y1 = f3 ps1
#Z2 = f2 ps0
#Z1 = f2 ps0
skip_xz_adjustments:
ps_sub f1, f1, f3
fsubs f2, f2, f4
ps_mul f1, f1, f1
ps_sum0 f1, f1, f1, f1
fmadds f1, f2, f2, f1
frsqrte f1, f1
fres f1, f1 #Speed now in f1 as units/frame
#Change Speed from Units/Frame to Units/Second
mflr r5
lfs f13, 0x14 (r5)
fmuls f13, f1, f13
#Is u/s less than 2.5? If so, print blue "inf" no matter what
lfs f0, 0x18 (r5)
fcmpo cr1, f13, f0
addi sp, sp, -0x100 #Don't wanna deal with readding sp for inf route, just do it no matter what
bge+ cr1, NON_INFI
#Adjust r5 for inf and skip time delta calc and skip ascii reformatting
addi r5, r5, 0x1C
b out
#Do Time Delta Formula
#Time Delta = (FD-SD)/SDSlotSpeed
#FD = 1st place distance
#SD = 2nd place distance
NON_INFI:
ble- cr7, 0xC #Branch if Ghost is ahead of Human or equal to
ps_merge00 f12, f11, f12 #Swap f11 and f12 ps0's
ps_merge11 f11, f12, f12
fsubs f2, f12, f11
fdivs f1, f2, f13 #f1 arg now complete for swprintf
#Change font color to blue if Ghost is ahead of Human
li r0, 0x30 #yellow
bgt- cr7, 0x8
li r0, 0x21 #light blue
stb r0, 0x7 (r5)
#Set non-float args of swprintf, call it
#f1 speed
#r3 where to dump (dest addr)
#r4 length
#r5 source addr (already set)
crset 4*cr1+eq #Makes swprintf execute faster by providing an accurate branch route regarding float processing
addi r3, sp, 0x8
li r4, 0x100
lis r12, swprintf@h
ori r12, r12, swprintf@l
mtctr r12
bctrl
#Preset r5 for later func call and preset r4 for ascii conversion loop
addi r5, sp, 0x8 #r5 arg; Beginning of the formatted string
addi r4, sp, 0xE #We do not want to process the bmg escape sequence
#The Timer uses special 16-bit ascii symbols in place of typical 16-bit ascii symbols for digits, dashes, and dots. Adjust the symbols.
loop:
lhzu r3, 0x2 (r4)
cmpwi r3, 0
beq- out
cmpwi r3, 0x2D
beq- dash
cmpwi r3, 0x2E
beq- dot
cmplwi r3, 0x30
blt- loop
cmplwi r3, 0x39
bgt- loop
addi r3, r3, 0x2430 #Update digits (0 thru 9)
b write_new_ascii
dash:
li r3, 0x246D
b write_new_ascii
dot:
li r3, 0x246B
write_new_ascii:
sth r3, 0 (r4)
b loop
#Ascii symbol reformatting complete
out:
lwz r3, 0x5C (r29) #r3 arg
#Find out if widescreen or not, apply X and Y screen pos
lis r6, ptr_unk@ha
lwz r6, ptr_unk@l (r6)
lwz r6, 0x58 (r6)
cmpwi r6, 1
stw r30, 0x50 (r3) #Write Y pos
stw r31, 0x58 (r3) #Write Scale, fyi stmw is slow
beq+ widescreen
stw r27, 0x4C (r3) #Write 4:3 X pos
b make_visible
widescreen:
stw r26, 0x4C (r3) #Write 16:9 X pos
#Make the element visible, align text to right, call func to display it on screen
make_visible:
li r4, 0
stb r4, 0x80 (r3)
li r6, 2 #Side note: Use 0 to align left, be sure to update your X measurements correctly (neg/inverse them)
lwz r3, 0x114 (r3)
lwz r7, 0 (r3)
stb r6, 0x100 (r7)
lis r12, ScreenElement_setTextSrc@h
ori r12, r12, ScreenElement_setTextSrc@l
mtctr r12
bctrl
#Recover sp
addi sp, sp, 0x100
#The end (original instruction)
end:
addi r11, sp, 0x100
|