Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #Very unoptimized code but frankly I am very lazy and I do not want to optimize this considering the use people will make of it.
- # inject at 8057c3a8 (PAL)
- # inject at 80575b44 (NTSC-U)
- # inject at 8057bd28 (NTSC-J)
- # inject at 8056a400 (NTSC-K)
- .set region, 'P'
- .if (region == 'P')
- .set swprintf, 0x80017814
- .set ScreenElement_setTextSrc, 0x805cdd00
- .set MtxtoEuler, 0x8022FB04
- .set CheckAreaIn, 0x805163f4
- .set Memset, 0x80006038
- .set RACEDATA, 0x809bd728
- .set MENUDATA, 0x809c1e38
- .set RACEINFO, 0x809bd730
- .set INPUTDATA, 0x809bd70c
- .set ITEMHOLDER, 0x809c3618
- .set KCLHOLDER, 0x809c27f8
- .set KMPHOLDER, 0x809BD6E8
- .set DEG2RAD, 0x808abaa4
- .set OFFSET, -0x5CF0
- .elseif (region == 'E')
- .set swprintf, 0x80016cb4
- .set ScreenElement_setTextSrc, 0x805c11e0
- .set MtxtoEuler, 0x8022F780
- .set CheckAreaIn, 0x80511F80
- .set Memset, 0x80006038
- .set RACEDATA, 0x809b8f68
- .set MENUDATA, 0x809bd508
- .set RACEINFO, 0x809B8F70
- .set INPUTDATA, 0x809b8f4c
- .set ITEMHOLDER, 0x809bee20
- .set KCLHOLDER, 0x809bdbb8
- .set KMPHOLDER, 0x809B8F28
- .set DEG2RAD, 0x808a5D24
- .set OFFSET, -0x5CF0
- .elseif (region == 'J')
- .set swprintf, 0x80017738
- .set ScreenElement_setTextSrc, 0x805cd5dc
- .set MtxtoEuler, 0x8022FA24
- .set CheckAreaIn, 0x80515D74
- .set Memset, 0x80006038
- .set RACEDATA, 0x809bc788
- .set MENUDATA, 0x809c0e98
- .set INPUTDATA, 0x809BC76C
- .set RACEINFO, 0x809BC790
- .set ITEMHOLDER, 0x809c2678
- .set KCLHOLDER, 0x809c1858
- .set KMPHOLDER, 0x809BC748
- .set DEG2RAD, 0x808AAC04
- .set OFFSET, -0x5CF0
- .elseif (region == 'K')
- .set swprintf, 0x8001787C
- .set ScreenElement_setTextSrc, 0x805BBCC0
- .set MtxtoEuler, 0x8022FE78
- .set CheckAreaIn, 0x80504414
- .set Memset, 0x80006038
- .set RACEDATA, 0x809abd68
- .set MENUDATA, 0x809B0478
- .set INPUTDATA, 0x809ABD4C
- .set RACEINFO, 0x809ABD70
- .set ITEMHOLDER, 0x809B1C58
- .set KCLHOLDER, 0x809B0E38
- .set KMPHOLDER, 0x809ABD28
- .set DEG2RAD, 0x80899f04
- .set OFFSET, -0x5CF0
- .set MENUDATA, 0x809b0478
- .set swprintf, 0x8001787c
- .set ScreenElement_setTextSrc, 0x805bbcc0
- .set OFFSET, -0x5CD0
- .else
- .err
- .endif
- # get the player index of the player on which the hooked function is working
- lis r31, RACEDATA@ha
- lwz r10, RACEINFO@l (r31)
- lwz r11, 0x28 (r10)
- cmpwi r11, 0 #If race has not started, do not display the panel; this avoid the panel warping in position
- beq- end
- lwz r11, 0x0 (r29)
- lwz r3, 0x0 (r11)
- lbz r3, 0x10 (r3)
- # get the player index from the first hud slot
- lwz r7, RACEDATA@l (r31)
- lbz r7, 0xb84 (r7)
- # if they don't match, the speedometer will not be updated
- cmpw r3, r7
- bne end
- # check if a single player gameplay screen is active
- lwz r4, MENUDATA@l (r31)
- lwz r3, 0x0 (r4)
- 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
- beq end
- found:
- lwz r28, 0x5c (r28)
- bl format
- .short 0x001a, 0x0800, 0x0001, 0x0030
- .short 0x001a, 0x0800, 0x0001, 0x0030 # bmg escape sequence for yellow text
- .llong 0x0052006500730070
- .llong 0x00610077006e0020
- .llong 0x00250032002e0030
- .llong 0x0066000a00430075
- .llong 0x0072004300500020
- .llong 0x0020002000200025
- .llong 0x0033002e00300066
- .llong 0x000a004300750072
- .llong 0x004b004300500020
- .llong 0x0020002000250032
- .llong 0x002e00300066000a
- .llong 0x0052006100630065
- .llong 0x0025002500200025
- .llong 0x0031002e00330066
- .llong 0x000a004900540050
- .llong 0x0054002000200020
- .llong 0x0020002000200020
- .llong 0x00250033002e0030
- .llong 0x0066000a00420069
- .llong 0x006c006c00200063
- .llong 0x0061006e00250073
- .llong 0x002000640072006f
- .llong 0x0070000a00250073
- .llong 0x002d007000720069
- .llong 0x006f007200690074
- .llong 0x0079000a004b0043
- .llong 0x004c0046006c0061
- .llong 0x0067002000250030
- .llong 0x00320078000a0056
- .llong 0x0061007200690061
- .llong 0x006e007400200020
- .llong 0x0025003000320078
- .llong 0x000a002500730020
- .llong 0x0054007200690063
- .llong 0x006b00610062006c
- .long 0x00650000
- .string "'t"
- .string "High"
- .string "Low"
- .string "Not"
- .string " "
- .align 2
- .short 0x001a, 0x0800, 0x0001, 0x0030
- .short 0x001a, 0x0800, 0x0001, 0x0030 # bmg escape sequence for yellow text
- .llong 0x0058002000250037
- .llong 0x002e00300066000a
- .llong 0x0059002000250037
- .llong 0x002e00300066000a
- .llong 0x005a002000250037
- .llong 0x002e00300066000a
- .llong 0x0072005800200025
- .llong 0x0037002e00300066
- .llong 0x000a007200590020
- .llong 0x00250037002e0030
- .llong 0x0066000a0072005a
- .llong 0x002000250037002e
- .llong 0x00300066000a0053
- .llong 0x0070006500650064
- .llong 0x002000250033002e
- .llong 0x00300066000a0041
- .llong 0x0052004500410020
- .llong 0x0025007300000000
- format:
- mflr r30
- lwz r5, INPUTDATA@l(r31)
- lbz r4, 0x3F(r4) #load active controller
- lhz r6, 0x4A (r5) #Previous Frame Input
- lhz r5, 0x32(r5) #Current Frame Input
- andc r5, r6, r5 #Check if Minus/Y has been pressed once
- andi. r6, r5, 0x1000
- cmpwi cr1, r4, 0x24
- bne+ cr1, check
- andi. r6, r5, 0x800
- check:
- lbz r4, 0x13F (r30) #Page Toggling
- beq+ compare
- addi r4, r4, 1
- cmpwi r4, 2
- ble+ compare
- li r4, 0
- compare:
- stb r4, 0x13F (r30)
- cmpwi r4, 2
- bne+ display
- li r5, 1 #"Page 3" = Panel disabled
- stb r5, 0x80 (r28)
- b end
- display:
- li r5, 0
- stb r5, 0x80 (r28)
- # prepare the arguments for swprintf 1
- lwz r29, 0x8 (r11)
- lwz r29, 0x90 (r29) #Prepare the pointers for position/speed load
- cmpwi r4, 0x1
- beq+ page2
- b next
- routine: #swprintf not enough int args, small routine to convert ints to floats
- xoris r3, r3, 0x8000
- stw r3, -0x4 (sp)
- lfd f6, -0x8 (sp)
- fsub f6, f6, f7
- blr
- next:
- #PAGE 1: f1 = Respawn/f2 = CP/f3 = CurrentKCP/f4 = race completion/f5 = ITPT/r6 = pointer to string/r7 = pointer to string/r8 = KCL Type/r9 = KCL Variant/r10 = pointer to string
- mr r5, r30 #For page 1, swprintf pointer to string
- lis r3, 0x4330
- stw r3, -0x8 (sp)
- lis r3, 0x8000
- stw r3, -0x4 (sp)
- lfd f7, -0x8 (sp) # load magic double into f7
- lwz r4, 0xC (r10)
- mulli r7, r7, 4
- lwzx r4, r4, r7 #My RACEINFO
- lbz r3, 0x21 (r4) #respawn
- bl routine
- fmr f1, f6
- lbz r3, 0xB (r4) #CP
- bl routine
- fmr f2, f6
- lbz r3, 0x27 (r4) #currentKCP
- bl routine
- fmr f3, f6
- lfs f4, 0xC (r4) #race completion
- lwz r3, ITEMHOLDER@l (r31)
- lwz r3, 0x14 (r3)
- lbz r3, 0x44 (r3) #ITPT
- bl routine
- fmr f5, f6
- lwz r6, KMPHOLDER@l (r31)
- lwz r4, 0x18 (r6)
- lwz r4, 0 (r4)
- mulli r3, r3, 4
- lwzx r4, r4, r3
- lwz r4, 0 (r4)
- lha r3, 0x12 (r4) #low prio and bill drop
- li r6, 0
- addi r7, r30, 0x12F #r7 = pointer to string for priority
- andi. r4, r3, 0x1
- beq+ priocheck
- addi r6, r30, 0x12C #r6 = pointer to string for bill dropping
- priocheck:
- andi. r4, r3, 0xA
- beq+ normal
- addi r7, r30, 0x134
- normal:
- addi r10, r30, 0x138
- lwz r3, KCLHOLDER@l (r31)
- lwz r3, 0x18 (r3)
- lbz r8, 0xF1 (r3) #KCL Type
- lbz r9, 0xF3 (r3) #KCL Variant
- cmpwi r8, 0x7 #Checks if trickable boost ramp/halfpipe KCL type
- beq- trickable
- cmpwi r8, 0x13
- beq- trickable
- cmpwi r8, 0x8
- beq- trickable
- lwz r3, 0x10 (r11)
- lwz r3, 0 (r3)
- lwz r3, 0x98 (r3)
- lwz r3, 0x1C (r3)
- lwz r3, 0x8 (r3)
- cmpwi r3, 0x9 #Convoluted check to see if trickable bit is set
- bne+ call
- trickable:
- addi r10, r30, 0x13C
- b call
- page2:
- #PAGE2: f1 = X/f2 = Y/f3 = Z/f4 = X rotation/f5 = Y rotation/f6 = Z rotation/f7 = speed/r6 = Pointer to AREA string
- lis r3, 0x8150
- ori r3, r3, 0x1500
- li r4, 0
- li r5, 0x50
- lis r12, Memset@h
- ori r12, r12, Memset@l
- mtctr r12
- bctrl #Clears the spot in memory where AREA string is stored
- lis r12, CheckAreaIn@h #Preparation of the AREA loop. This function uses a pointer to an AREA, a pointer to a point and checks if the point is inside the AREA
- ori r12, r12, CheckAreaIn@l
- mtctr r12
- lwz r6, KMPHOLDER@l (r31)
- lwz r6, 0x2C (r6)
- lhz r11, 0x4 (r6) #AreaCount = loop count
- lwz r6, 0x0010 (r6)
- subi r8, r3, 2 #Pointer to string
- li r10, 0
- li r12, 0 #r12 will count the number of AREAs the player is in
- looparea:
- lwz r4, 0x4 (r29)
- addi r4, r4, 0x68 #Adjusts the pointer for player's current position
- mulli r3, r10, 4
- lwzx r3, r6, r3 #INTO CURRENT AREA, also arg for the function below
- mr r9, r3
- bctrl
- cmpwi r3, 0 #If r3 = 0, the player is not in the AREA currently checked
- beq+ decrement
- #The string is entirely built manually. This is super convoluted and long, there is 100% a better way to do this but lazy
- cmpwi r12, 0 #If this is the first AREA the player is in, do not put a comma in the string
- beq- nocomma
- li r3, 0x2c #ASCII for Comma
- stb r3, 0x1 (r8)
- nocomma:
- addi r12, r12, 0x1
- lwz r3, 0x4 (r9) #for type and ID
- lbz r3, 0x1 (r3) #TYPE
- addi r3, r3, 0x30
- stb r3, 0x2 (r8)
- li r3, 0x28 #ASCII for "("
- stb r3, 0x3 (r8)
- lha r3, 0x44 (r9) #ID, the instructions after are used to separate each figure of the ID (for example 0x10 -> 1 and 0)
- srwi r5, r3, 0x4
- addi r5, r5, 0x30
- stb r5, 0x4 (r8) #Store upper half of the ID
- clrlwi r3, r3, 27
- addi r5, r3, 0x30
- cmpwi r3, 0xA
- blt+ small
- addi r5, r3, 0x37
- small:
- stb r5, 0x5 (r8) #Store Lower Half of the ID
- li r3, 0x29 #ASCII for ")"
- stbu r3, 0x6 (r8) #Store ")" and update the pointer for next iteration
- decrement:
- addi r10, r10, 1 #Loop until r10 = r11 = AREA Count
- cmplw r10, r11
- blt+ looparea
- #XYZ rot XYZ speed
- addi r3, r29, 0x9C #Adjusts r3 to point to the rotation Matrix in PlayerHolderPlayer
- lis r12, MtxtoEuler@h #Credits to Stebler for this function which converts a rotation Matrix to Euler Angles
- ori r12, r12, MtxtoEuler@l
- addi r4, sp, -0x100
- mtctr r12
- bctrl
- lwz r3, 0x4 (r29)
- lfs f1, 0x68 (r3) #Load the player's position
- lfs f2, 0x6c (r3)
- lfs f3, 0x70 (r3)
- lis r5, DEG2RAD@ha
- lfs f7, DEG2RAD@l (r5) #Load Deg2RAD constant
- fres f7, f7 #Invert it to RAD2Deg
- addi r4, sp, -0x100
- lfs f4, 0x0 (r4) #Load Euler Angles; X and Z hard to interpret but Y is the angle around the vertical axis
- lfs f5, 0x4 (r4)
- lfs f6, 0x8 (r4)
- fmuls f4, f4, f7 #Convert the Euler Angles to Degrees
- fmuls f5, f5, f7
- fmuls f6, f6, f7
- lfs f7, 0xE0 (r3) #XYZ Speed
- lis r6, 0x8150 #r6 = Pointer to AREA String
- ori r6, r6, 0x1500
- addi r5, r30, 0x140 #Adjusts pointer to swprintf string to format
- call:
- addi sp, sp, -0x200 #Call swprintf; very cautious with the buffer size but I had issues with buffer overflows and corrupted panels; difficult to know exactly how much I need considering the AREA string has a dynamic length
- addi r3, sp, 0x8
- li r4, 0x200
- crset 4 * cr1 + eq #Set cr1 so that swprintf handles the floats
- lis r12, swprintf@h
- ori r12, r12, swprintf@l
- mtctr r12
- bctrl
- addi r5, sp, 0x8
- addi r4, r5, 0xE # we do not want to process the bmg escape sequence
- # replace digits, dashes and dots with the timer versions
- loop:
- lhzu r3, 0x2 (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)
- b loop
- out:
- #size
- size:
- li r4, 77
- stw r4, 0x4 (r5)
- # set the position of the hud element
- lis r12, 0x4000
- lis r4, 0xC3A0
- lwz r30, OFFSET (r13) #r13 value to check if 4/3 or 16/9
- cmpwi r30, 1
- beq+ goodres
- lis r12, 0x4150
- lis r4, 0xC360
- goodres:
- stw r4, 0x4c (r28)
- stw r12, 0x50 (r28)
- # align the text to the right
- lwz r3, 0x114 (r28)
- lwz r7, 0x0 (r3)
- stb r4, 0x100 (r7)
- lis r12, 0x43B0
- stw r12, 0x50 (r7)
- lis r12, 0x4380
- stw r12, 0x4C (r7)
- li r4, 0
- lis r12, ScreenElement_setTextSrc@h #Call the function that will display the screenelement
- ori r12, r12, ScreenElement_setTextSrc@l
- mtctr r12
- bctrl
- end2:
- addi sp, sp, 0x200
- end:
- lwz r31, 0x7c (sp) # original instruction
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement