"Double Dash!!" Speedometer [Sponge]
#1
"Double Dash!!" Speedometer [Sponge]

A remake of the speedometer from Mario Kart: Double Dash.

Preview:


I've aimed to make this behave and look accurate to the original game, although it's not perfect.

Stars and Bullet Bills both have unique color animations, this was inspired by CTGP-7.

File modifications are needed for this to work. A zip with assets will be provided so you can add them to your own game files.

I made this as a proof of concept. I'm certain this can be optimized in the future.

Note: This code uses addresses 0x80001610 through 0x8000161E. Ensure no other codes read or write to these addresses.

PAL
C2082358 0000001C
809E0000 9421FF70
D8210008 3D80809C
818C18F8 280C0000
418200BC 3C60809C
8063D728 88630B84
818C0020 5463103A
7D8C182E 818C0010
818C0010 C02C0024
FC200A10 FC20081C
D8210010 81810014
3CA07370 60A56565
80DEFFD8 7C053040
40820074 38A00030
88DEFFDF 38A50001
28050033 41810060
7C053040 4082FFF0
39000064 7D2C43D6
28050033 41820028
1D290064 7D496050
3900000A 7D2A43D6
28050032 4182001C
1D29000A 7D295050
4800001C 280C0063
41810014 4800000C
280C0009 41810008
3920000A 1D290860
7C844A14 C8210008
38210090 00000000
C2084628 00000040
80830000 9421FFA0
BDC10008 D8210008
7F0802A6 3D80809C
818C18F8 280C0000
418201CC 3DC0809C
81CED728 89CE0B84
818C0020 55CE103A
7D8C702E 818C0010
824C0010 826C001C
C0320024 FC200A10
FC20081C D8210010
82810014 3DC0645F
61CE626C 81FC00C0
7C0E7840 40820180
39C00030 89FC00C9
39CE0001 280E0037
4181016C 7C0E7840
4082FFF0 48000065
7F7F7FFF 00FFC3FF
55FF00FF AAFF00FF
FFFF00FF FFAA00FF
FF5400FF FF2200FF
00000000 FF80FEFF
FFBFC0FF FFDEA0FF
FFFE80FF FFDEA0FF
FFBFC0FF FF80FEFF
00000000 1E1D1EFF
E64129FF FFA829FF
FFC22BFF FFA829FF
E64129FF 1E1D1EFF
7E0802A6 81D3000C
75CE0800 3A100040
40820058 81D30008
75CE8000 3A10FFE0
40820048 81D30008
71CE0010 3A10FFE0
40820038 A1D20148
280E0000 4181002C
39C0000B 7DD473D6
39EFFFD0 7C0E7840
41800010 1DEF0004
7E30782E 48000090
82300000 48000088
3DC08000 61CE1610
39EFFFD0 7E2E78AE
28110000 40820008
7DF17B78 3AAE0008
7ED578AE 6AD60001
7ED579AE 8AEE0000
28170001 4080001C
28160001 40820014
3A31FFFF 28110000
41810008 3A200007
28110007 40820024
7C117840 4082001C
8ACE0000 3AD60001
28160004 41800008
3AC00000 9ACE0000
7E2E79AE 1E310004
7E30882E 92230000
92230004 92230008
9223000C 7F0803A6
C8210008 B9C10008
38210060 00000000
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
C285853C 00000018
9421FF80 7C0802A6
90010084 BC610008
7C6E1B78 48000039
7C641B78 48000045
7C651B78 48000051
7C661B78 48000065
7C671B78 7DC37378
3D80805C 618C2C60
7D8803A6 4E800021
48000064 7D8802A6
48000051 67616D65
5F696D61 67650000
7D8802A6 4800003D
73706565 646F6D65
74657200 7D8802A6
48000029 4374726C
53706565 646F6D65
7465725F 315F3000
7D8802A6 4800000D
00000000 00000000
7C6802A6 7D8803A6
4E800020 B8610008
80010084 7C0803A6
38210080 00000000
04857A28 60000000
04857A80 48000028

NTSC-U
C20822B8 0000001C
809E0000 9421FF70
D8210008 3D80809C
818CD110 280C0000
418200BC 3C60809C
80638F68 88630B84
818C0020 5463103A
7D8C182E 818C0010
818C0010 C02C0024
FC200A10 FC20081C
D8210010 81810014
3CA07370 60A56565
80DEFFD8 7C053040
40820074 38A00030
88DEFFDF 38A50001
28050033 41810060
7C053040 4082FFF0
39000064 7D2C43D6
28050033 41820028
1D290064 7D496050
3900000A 7D2A43D6
28050032 4182001C
1D29000A 7D295050
4800001C 280C0063
41810014 4800000C
280C0009 41810008
3920000A 1D290860
7C844A14 C8210008
38210090 00000000
C2084588 00000040
80830000 9421FFA0
BDC10008 D8210008
7F0802A6 3D80809C
818CD110 280C0000
418201CC 3DC0809C
81CE8F68 89CE0B84
818C0020 55CE103A
7D8C702E 818C0010
824C0010 826C001C
C0320024 FC200A10
FC20081C D8210010
82810014 3DC0645F
61CE626C 81FC00C0
7C0E7840 40820180
39C00030 89FC00C9
39CE0001 280E0037
4181016C 7C0E7840
4082FFF0 48000065
7F7F7FFF 00FFC3FF
55FF00FF AAFF00FF
FFFF00FF FFAA00FF
FF5400FF FF2200FF
00000000 FF80FEFF
FFBFC0FF FFDEA0FF
FFFE80FF FFDEA0FF
FFBFC0FF FF80FEFF
00000000 1E1D1EFF
E64129FF FFA829FF
FFC22BFF FFA829FF
E64129FF 1E1D1EFF
7E0802A6 81D3000C
75CE0800 3A100040
40820058 81D30008
75CE8000 3A10FFE0
40820048 81D30008
71CE0010 3A10FFE0
40820038 A1D20148
280E0000 4181002C
39C0000B 7DD473D6
39EFFFD0 7C0E7840
41800010 1DEF0004
7E30782E 48000090
82300000 48000088
3DC08000 61CE1610
39EFFFD0 7E2E78AE
28110000 40820008
7DF17B78 3AAE0008
7ED578AE 6AD60001
7ED579AE 8AEE0000
28170001 4080001C
28160001 40820014
3A31FFFF 28110000
41810008 3A200007
28110007 40820024
7C117840 4082001C
8ACE0000 3AD60001
28160004 41800008
3AC00000 9ACE0000
7E2E79AE 1E310004
7E30882E 92230000
92230004 92230008
9223000C 7F0803A6
C8210008 B9C10008
38210060 00000000
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
C2836AAC 00000018
9421FF80 7C0802A6
90010084 BC610008
7C6E1B78 48000039
7C641B78 48000045
7C651B78 48000051
7C661B78 48000065
7C671B78 7DC37378
3D80805B 618CA2CC
7D8803A6 4E800021
48000064 7D8802A6
48000051 67616D65
5F696D61 67650000
7D8802A6 4800003D
73706565 646F6D65
74657200 7D8802A6
48000029 4374726C
53706565 646F6D65
7465725F 315F3000
7D8802A6 4800000D
00000000 00000000
7C6802A6 7D8803A6
4E800020 B8610008
80010084 7C0803A6
38210080 00000000
04835F98 60000000
04835FF0 48000028

NTSC-J
C2082278 0000001C
809E0000 9421FF70
D8210008 3D80809C
818C0958 280C0000
418200BC 3C60809C
8063C788 88630B84
818C0020 5463103A
7D8C182E 818C0010
818C0010 C02C0024
FC200A10 FC20081C
D8210010 81810014
3CA07370 60A56565
80DEFFD8 7C053040
40820074 38A00030
88DEFFDF 38A50001
28050033 41810060
7C053040 4082FFF0
39000064 7D2C43D6
28050033 41820028
1D290064 7D496050
3900000A 7D2A43D6
28050032 4182001C
1D29000A 7D295050
4800001C 280C0063
41810014 4800000C
280C0009 41810008
3920000A 1D290860
7C844A14 C8210008
38210090 00000000
C2084548 00000040
80830000 9421FFA0
BDC10008 D8210008
7F0802A6 3D80809C
818C0958 280C0000
418201CC 3DC0809C
81CEC788 89CE0B84
818C0020 55CE103A
7D8C702E 818C0010
824C0010 826C001C
C0320024 FC200A10
FC20081C D8210010
82810014 3DC0645F
61CE626C 81FC00C0
7C0E7840 40820180
39C00030 89FC00C9
39CE0001 280E0037
4181016C 7C0E7840
4082FFF0 48000065
7F7F7FFF 00FFC3FF
55FF00FF AAFF00FF
FFFF00FF FFAA00FF
FF5400FF FF2200FF
00000000 FF80FEFF
FFBFC0FF FFDEA0FF
FFFE80FF FFDEA0FF
FFBFC0FF FF80FEFF
00000000 1E1D1EFF
E64129FF FFA829FF
FFC22BFF FFA829FF
E64129FF 1E1D1EFF
7E0802A6 81D3000C
75CE0800 3A100040
40820058 81D30008
75CE8000 3A10FFE0
40820048 81D30008
71CE0010 3A10FFE0
40820038 A1D20148
280E0000 4181002C
39C0000B 7DD473D6
39EFFFD0 7C0E7840
41800010 1DEF0004
7E30782E 48000090
82300000 48000088
3DC08000 61CE1610
39EFFFD0 7E2E78AE
28110000 40820008
7DF17B78 3AAE0008
7ED578AE 6AD60001
7ED579AE 8AEE0000
28170001 4080001C
28160001 40820014
3A31FFFF 28110000
41810008 3A200007
28110007 40820024
7C117840 4082001C
8ACE0000 3AD60001
28160004 41800008
3AC00000 9ACE0000
7E2E79AE 1E310004
7E30882E 92230000
92230004 92230008
9223000C 7F0803A6
C8210008 B9C10008
38210060 00000000
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
C2857BA8 00000018
9421FF80 7C0802A6
90010084 BC610008
7C6E1B78 48000039
7C641B78 48000045
7C651B78 48000051
7C661B78 48000065
7C671B78 7DC37378
3D80805C 618C25E0
7D8803A6 4E800021
48000064 7D8802A6
48000051 67616D65
5F696D61 67650000
7D8802A6 4800003D
73706565 646F6D65
74657200 7D8802A6
48000029 4374726C
53706565 646F6D65
7465725F 315F3000
7D8802A6 4800000D
00000000 00000000
7C6802A6 7D8803A6
4E800020 B8610008
80010084 7C0803A6
38210080 00000000
04857094 60000000
048570EC 48000028

NTSC-K
C20823B8 0000001C
809E0000 9421FF70
D8210008 3D80809B
818CFF38 280C0000
418200BC 3C60809B
8063BD68 88630B84
818C0020 5463103A
7D8C182E 818C0010
818C0010 C02C0024
FC200A10 FC20081C
D8210010 81810014
3CA07370 60A56565
80DEFFD8 7C053040
40820074 38A00030
88DEFFDF 38A50001
28050033 41810060
7C053040 4082FFF0
39000064 7D2C43D6
28050033 41820028
1D290064 7D496050
3900000A 7D2A43D6
28050032 4182001C
1D29000A 7D295050
4800001C 280C0063
41810014 4800000C
280C0009 41810008
3920000A 1D290860
7C844A14 C8210008
38210090 00000000
C2084688 00000040
80830000 9421FFA0
BDC10008 D8210008
7F0802A6 3D80809B
818CFF38 280C0000
418201CC 3DC0809B
81CEBD68 89CE0B84
818C0020 55CE103A
7D8C702E 818C0010
824C0010 826C001C
C0320024 FC200A10
FC20081C D8210010
82810014 3DC0645F
61CE626C 81FC00C0
7C0E7840 40820180
39C00030 89FC00C9
39CE0001 280E0037
4181016C 7C0E7840
4082FFF0 48000065
7F7F7FFF 00FFC3FF
55FF00FF AAFF00FF
FFFF00FF FFAA00FF
FF5400FF FF2200FF
00000000 FF80FEFF
FFBFC0FF FFDEA0FF
FFFE80FF FFDEA0FF
FFBFC0FF FF80FEFF
00000000 1E1D1EFF
E64129FF FFA829FF
FFC22BFF FFA829FF
E64129FF 1E1D1EFF
7E0802A6 81D3000C
75CE0800 3A100040
40820058 81D30008
75CE8000 3A10FFE0
40820048 81D30008
71CE0010 3A10FFE0
40820038 A1D20148
280E0000 4181002C
39C0000B 7DD473D6
39EFFFD0 7C0E7840
41800010 1DEF0004
7E30782E 48000090
82300000 48000088
3DC08000 61CE1610
39EFFFD0 7E2E78AE
28110000 40820008
7DF17B78 3AAE0008
7ED578AE 6AD60001
7ED579AE 8AEE0000
28170001 4080001C
28160001 40820014
3A31FFFF 28110000
41810008 3A200007
28110007 40820024
7C117840 4082001C
8ACE0000 3AD60001
28160004 41800008
3AC00000 9ACE0000
7E2E79AE 1E310004
7E30882E 92230000
92230004 92230008
9223000C 7F0803A6
C8210008 B9C10008
38210060 00000000
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
C28468FC 00000018
9421FF80 7C0802A6
90010084 BC610008
7C6E1B78 48000039
7C641B78 48000045
7C651B78 48000051
7C661B78 48000065
7C671B78 7DC37378
3D80805B 618C0CC4
7D8803A6 4E800021
48000064 7D8802A6
48000051 67616D65
5F696D61 67650000
7D8802A6 4800003D
73706565 646F6D65
74657200 7D8802A6
48000029 4374726C
53706565 646F6D65
7465725F 315F3000
7D8802A6 4800000D
00000000 00000000
7C6802A6 7D8803A6
4E800020 B8610008
80010084 7C0803A6
38210080 00000000
04845DE8 60000000
04845E40 48000028

Credits:
Stebler - 3rd and 4th ASM sources (Used in Pretty Speedometer)
Kazuki - 5th ASM Source (Modified source from KZ-RTD)

Quote:ASM 1: Change the loaded digit textures based on our current speed
Code:
#Inject at 0x80082358 PAL
#Inject at 0x800822B8 NTSC-U
#Inject at 0x80082278 NTSC-J
#Inject at 0x800823B8 NTSC-K

.set region, '' # Specify which region to compile for
.if    (region == 'P' || region == 'p') # RMCP
        .set RaceData, 0x809BD728
        .set PlayerHolder, 0x809C18F8
.elseif (region == 'E' || region == 'e' || region == 'U' || region == 'u') # RMCE
        .set RaceData, 0x809B8F68
        .set PlayerHolder, 0x809BD110
.elseif (region == 'J' || region == 'j') # RMCJ
        .set RaceData, 0x809BC788
        .set PlayerHolder, 0x809C0958
.elseif (region == 'K' || region == 'k') # RMCK
        .set RaceData, 0x809ABD68
        .set PlayerHolder, 0x809AFF38
.else # Invalid Region
        .abort
.endif

.macro pushStack
  stwu     r1, -0x90(r1)
  stfd     f1, 0x8(r1)
.endm

.macro popStack
  lfd     f1, 0x8(r1)
  addi     r1, r1, 0x90
.endm

.macro setPlayerBase
  lis     r12, PlayerHolder@ha
  lwz     r12, PlayerHolder@l(r12)
.endm

.macro setPlayerSlot
  lis     r3, RaceData@ha
  lwz     r3, RaceData@l(r3)
  lbz     r3, 0xB84(r3)
.endm


  lwz     r4, 0(r30) # Default instruction

  pushStack

  setPlayerBase
 
  cmplwi     r12, 0
  beq     end

  setPlayerSlot

  lwz     r12, 0x0020(r12) # Load Word from 1st Level Pointer
  slwi     r3, r3, 2 # Shift the bits of r3 by 2 to the left. This is the same as multiplying by 0x4.
  lwzx     r12, r12, r3 # Load into 2nd Level Pointer
  lwz     r12, 0x0010(r12) # Load into 3rd Level Pointer
  lwz     r12, 0x0010(r12) # Load into 4th Level Pointer
  lfs     f1, 0x0024(r12) # Load the speed value
  fabs     f1, f1 # Handle negatives
  fctiw     f1, f1 # Convert to int
  stfd     f1, 0x10(r1)
  lwz     r12, 0x14(r1) # Load the speed value as an int
  lis     r5, 0x7370
  ori     r5, r5, 0x6565 # Load part of the digit string
  lwz     r6, -0x28(r30)
  cmplw     r5, r6 # Check if the loaded texture is related to the digits
  bne     end
  li    r5, 0x30
  lbz     r6, -0x21(r30)
 
  digitLoop:
  addi     r5, r5, 1
  cmplwi     r5, 0x33
  bgt     end # Exit the code as we're not dealing with the digits
  cmplw     r5, r6
  bne     digitLoop # Loop if the texture name doesn't match
  li    r8, 100
  divw     r9, r12, r8
  cmplwi     r5, 0x33
  beq     showHundred
  mulli     r9, r9, 100
  sub     r10, r12, r9
  li    r8, 10
  divw     r9, r10, r8
  cmplwi     r5, 0x32
  beq     showTens
  mulli     r9, r9, 10
  sub     r9, r10, r9
  b        skipHide # Don't hide the ones digit, it's always shown

  showHundred:
  cmplwi     r12, 0x63 # Hide the hundreds digit if your speed is below 100
  bgt     skipHide
  b         hideDigit
 
  showTens:
  cmplwi     r12, 0x9 # Hide the tens digit if your speed is below 10
  bgt     skipHide
 
  hideDigit:
  li    r9, 0xa
 
  skipHide:
  mulli     r9, r9, 0x860
  add     r4, r4, r9

  end:
 
  popStack

ASM 2: Update block color based on speed and status effects
Code:
#Inject at 0x80084628 PAL
#Inject at 0x80084588 NTSC-U
#Inject at 0x80084548 NTSC-J
#Inject at 0x80084688 NTSC-K

.set colorEVA, 0x80001610
.set region, '' # Specify which region to compile for
.if    (region == 'P' || region == 'p') # RMCP
        .set RaceData, 0x809BD728
        .set PlayerHolder, 0x809C18F8
.elseif (region == 'E' || region == 'e' || region == 'U' || region == 'u') # RMCE
        .set RaceData, 0x809B8F68
        .set PlayerHolder, 0x809BD110
.elseif (region == 'J' || region == 'j') # RMCJ
        .set RaceData, 0x809BC788
        .set PlayerHolder, 0x809C0958
.elseif (region == 'K' || region == 'k') # RMCK
        .set RaceData, 0x809ABD68
        .set PlayerHolder, 0x809AFF38
.else # Invalid Region
        .abort
.endif

.macro     pushStack
  stwu    r1, -0x60(r1)
  stmw    r14, 0x8(r1)
  stfd     f1, 0x8(r1)
  mflr    r24
.endm

.macro     popStack
  mtlr    r24
  lfd     f1, 0x8(r1)
  lmw        r14, 0x8(r1)
  addi    r1, r1, 0x60
.endm

.macro     setPlayerBase
  lis     r12, PlayerHolder@ha
  lwz     r12, PlayerHolder@l(r12)
.endm

.macro     setPlayerSlot
  lis     r14, RaceData@ha
  lwz     r14, RaceData@l(r14)
  lbz     r14, 0xB84(r14)
.endm


  lwz     r4, 0(r3) # Default instruction

  pushStack

  setPlayerBase
 
  cmplwi     r12, 0
  beq     end

  setPlayerSlot
 
  lwz     r12, 0x0020 (r12) # Load Word from 1st Level Pointer
  slwi     r14, r14, 2 # Shift the bits of r14 by 2 to the left. This is the same as multiplying by 0x4.
  lwzx     r12, r12, r14 # Load into 2nd Level Pointer
  lwz     r12, 0x0010(r12) # Load into 3rd Level Pointer
  lwz     r18, 0x0010(r12) # Load into PlayerSub10
  lwz     r19, 0x001c(r12) # Load into PlayerSub1c
  lfs     f1, 0x0024 (r18) # Load the speed value
  fabs     f1, f1 # Handle negatives
  fctiw     f1, f1 # Convert to int
  stfd     f1, 0x10(r1)
  lwz     r20, 0x14(r1) # Load the speed value as an int
  lis     r14, 0x645f
  ori     r14, r14, 0x626c # Load part of the block string
  lwz     r15, 0xC0(r28)
  cmplw     r14, r15 # Check if the loaded texture is related to the blocks
  bne     end
  li    r14, 0x30
  lbz     r15, 0xc9(r28)
 
  blockLoop:
  addi     r14, r14, 1
  cmplwi     r14, 0x37
  bgt     end # Exit the code as we're not dealing with the blocks
  cmplw     r14, r15
  bne     blockLoop # Loop if the texture name doesn't match

  bl    storeColors # Do the bl trick to store the colors and load them later on

  .long     0x7F7F7FFF
  .long     0x00FFC3FF
  .long     0x55FF00FF
  .long     0xAAFF00FF
  .long     0xFFFF00FF
  .long     0xFFAA00FF
  .long     0xFF5400FF
  .long     0xFF2200FF
  .long     0x00000000
  .long     0xFF80FEFF
  .long     0xFFBFC0FF
  .long     0xFFDEA0FF
  .long     0xFFFE80FF
  .long     0xFFDEA0FF
  .long     0xFFBFC0FF
  .long     0xFF80FEFF
  .long     0x00000000
  .long     0x1E1D1EFF
  .long     0xE64129FF
  .long     0xFFA829FF
  .long     0xFFC22BFF
  .long     0xFFA829FF
  .long     0xE64129FF
  .long     0x1E1D1EFF

  storeColors:
  mflr     r16

  lwz     r14, 0xc(r19)
  andis.     r14, r14, 0x0800
  addi     r16, r16, 0x40
  bne     beginCycling # Point towards Bullet Bill color set and begin cycling colors

  lwz     r14, 0x8(r19)
  andis.     r14, r14, 0x8000
  subi     r16, r16, 0x20
  bne     beginCycling # Point towards Star color set and begin cycling colors

  lwz     r14, 0x8(r19)
  andi.     r14, r14, 0x10
  subi     r16, r16, 0x20
  bne     beginCycling # Start cycling regular colors if we're in a cannon...

  lhz     r14, 0x148(r18)
  cmplwi     r14, 0
  bgt     beginCycling # ...or if we have offroad invincibility

  li         r14, 11 # Load normal behavior otherwise
  divw     r14, r20, r14
  subi     r15, r15, 0x30
  cmplw     r14, r15 # Double Dash lights up one block around every 11 units. Here we compare the current block relative to the speed and grey it out if we aren't going fast enough.
  blt     greyBlock
  mulli     r15, r15, 0x4
  lwzx     r17, r16, r15 # Load color based on current speed
  b        storeColor

  greyBlock:
  lwz     r17, 0(r16)
  b        storeColor

  beginCycling:
  lis     r14, colorEVA@ha
  ori     r14, r14, colorEVA@l
  subi     r15, r15, 0x30
  lbzx     r17, r14, r15
  cmplwi     r17, 0
  bne     validColor
  mr    r17, r15 # Required as the cycles will start at the wrong color due to blank EVA

  validColor:
  addi     r21, r14, 0x8
  lbzx     r22, r21, r15
  xori     r22, r22, 1
  stbx     r22, r21, r15 # Store the bit for later use
  lbz     r23, 0(r14)
  cmplwi     r23, 1 # Required for "four frame" behavior
  bge     colorFreeze
  cmplwi     r22, 0x1 # Double Dash only updates the color every second frame, so we compare against the bit we flipped
  bne     colorFreeze
  subi     r17, r17, 1
  cmplwi     r17, 0
  bgt     colorFreeze # Reset to the end of the colors if we hit 0
  li    r17, 7

  colorFreeze:
  cmplwi     r17, 0x7 # Check if we're loading the final color in the set...
  bne     fourFrameSkip
  cmplw     r17, r15 # ...and if we're referencing the final block, if not skip the "four frame" behavior
  bne     fourFrameSkip
  lbz     r22, 0x0(r14)
  addi     r22, r22, 1
  cmplwi     r22, 4 # Double Dash will also delay color updates for four frames if said two conditions above are met, so we make a counter and reset it once the four frames have finished
  blt     fourFrameStore
  li    r22, 0

  fourFrameStore:
  stb     r22, 0(r14)

  fourFrameSkip:
  stbx     r17, r14, r15 # Store value for later use
  mulli     r17, r17, 0x4
  lwzx     r17, r16, r17 # Load up the color based on the current value

  storeColor:
  stw     r17, 0(r3)
  stw     r17, 0x4(r3)
  stw    r17, 0x8(r3)
  stw    r17, 0xc(r3)
 
  end:

  popStack

ASM 3: Increment the child count of the single player gameplay screens other than time trial (by Stebler)
Code:
#Inject at 0x8060245C PAL
#Inject at 0x805DDB7C NTSC-U
#Inject at 0x80601BD0 NTSC-J
#Inject at 0x805F087C NTSC-K

  lwz r5, 0x4 (r3)

  cmpwi r5, 0xc # Grand Prix
  beq increment

  cmpwi r5, 0xe # 1P offline VS
  beq increment

  cmpwi r5, 0x12 # 1P Battle
  beq increment

  cmpwi r5, 0x40 # 1P Worldwide/Regional VS
  beq increment

  cmpwi r5, 0x42 # 1P Friend Room VS
  beq increment

  b end

  increment:
  addi r4, r4, 0x1

  end:
  mr r5, r4 # Original instruction

ASM 4: Add the "GHOST DATA CANNOT BE SAVED" element to single player gameplay screens other than time trial (by Stebler)
Code:
#Inject at 0x808584D8 PAL
#Inject at 0x80836A48 NTSC-U
#Inject at 0x80857B44 NTSC-J
#Inject at 0x80846898 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 # 1P offline VS
  beq invert

  cmpwi r3, 0x12 # 1P Battle
  beq invert

  cmpwi r3, 0x40 # 1P Worldwide/Regional VS
  beq invert

  cmpwi r3, 0x42 # 1P Friend Room VS

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

  end:

ASM 5: Load our custom control instead of the ghost message control (by Kazuki)
Code:
#Inject at 0x8085853C PAL
#Inject at 0x80836AAC NTSC-U
#Inject at 0x80857BA8 NTSC-J
#Inject at 0x808468FC NTSC-K

.macro pushStack
  stwu sp, -0x80 (sp)
  mflr r0
  stw r0, 0x84 (sp)
  stmw r3, 8 (sp)
.endm

.macro popStack
  lmw r3, 8 (sp)
  lwz r0, 0x84 (sp)
  mtlr r0
  addi sp, sp, 0x80
.endm


.set region, '' # Specify which region to compile for

.if    (region == 'P' || region == 'p') # RMCP
    .set LayoutUIControl__setMessageAll, 0x8063DDB4
    .set ControlLoader__Load, 0x805C2C60
.elseif (region == 'E' || region == 'e' || region == 'U' || region == 'u') # RMCE
    .set LayoutUIControl__setMessageAll, 0x8060C994
    .set ControlLoader__Load, 0x805BA2CC
.elseif (region == 'J' || region == 'j') # RMCJ
    .set LayoutUIControl__setMessageAll, 0x8063D420
    .set ControlLoader__Load, 0x805C25E0
.elseif (region == 'K' || region == 'k') # RMCK
    .set LayoutUIControl__setMessageAll, 0x8062C0CC
    .set ControlLoader__Load, 0x805B0CC4
.else # Invalid Region
        .abort
.endif

  pushStack
 
  mr r14, r3
  bl get_data0 # Use the bl trick throughout to grab the string data we need
  mr r4, r3
  bl get_data1
  mr r5, r3
  bl get_data2
  mr r6, r3
  bl get_data3
  mr r7, r3
  mr r3, r14
  lis r12, ControlLoader__Load@h
  ori r12, r12, ControlLoader__Load@l # Call a function to load the speedometer control instead of the ghost message control
  mtlr r12
  blrl
  b end

  get_data0:
  mflr r12
  bl blTrickCommonEnd
  .string "game_image"
  .balign 4

  get_data1:
  mflr r12
  bl blTrickCommonEnd
  .string "speedometer"
  .balign 4

  get_data2:
  mflr r12
  bl blTrickCommonEnd
  .string "CtrlSpeedometer_1_0"
  .balign 4

  get_data3:
  mflr r12
  bl blTrickCommonEnd
  .long 0
  .long 0

  blTrickCommonEnd:
  mflr r3
  mtlr r12
  blr

  end:
 
  popStack


Attached Files
.zip   Double_Dash_Speedometer.zip (Size: 8.15 KB / Downloads: 88)
Reply


Messages In This Thread
"Double Dash!!" Speedometer [Sponge] - by Sponge - 03-12-2024, 02:23 PM

Forum Jump:


Users browsing this thread: 3 Guest(s)