Shared Item Cheat Detection
#1
Shared Item Cheat Detection

This code will detect when a player tries to obtain a Shared Item, but the item they intend to cheat already has it's maximum amount in play. The code will also detect when a player obtains impossible item combinations. It will display the slot of the offending player in the milliseconds of the timer, accompanied by a value denoting the reason.

(NTSC-U)
C26593FC 00000006
9421FFB0 BDC10008
907C0008 3EE080A1
62F70024 3F008053
631810A0 92F80000
B9C10008 38210050
60000000 00000000
C265EE14 0000000C
9421FFB0 BDC10008
7F200026 8A430003
1D960004 3D8C8168
88030001 2C120000
41A20014 2C120001
41820018 2C120002
40A0001C 3BE00014
9BEC0193 48000014
3BE00057 9BEC0193
48000008 980C0193
7F2FF120 B9C10008
38210050 00000000
C265EE30 0000005C
9421FFB0 BDC10008
7F200026 7E8902A6
8A500013 1D960004
3D8C8168 88100011
2C120000 41A20014
2C120001 41820018
2C120002 40A0025C
3BE00014 9BEC0193
48000288 3BE00057
9BEC0193 3F008053
631810A0 3EE038A0
8A300012 2C110010
41820018 2C110011
41820010 2C110012
41820008 4800001C
2C000010 41820224
2C000011 4182021C
2C000012 41820214
3A60000C 7E6903A6
3DE08168 61EF0193
3DC08168 61CE0133
8AAF0000 2C150006
40A20014 8BEE0000
3BFF0001 9BEE0000
480000D8 2C150007
40A20014 8BEE0004
3BFF0001 9BEE0004
480000C0 2C150008
40A20014 8BEE0008
3BFF0001 9BEE0008
480000A8 2C150009
40A20014 8BEE000C
3BFF0001 9BEE000C
48000090 2C15000A
40A20014 8BEE0010
3BFF0001 9BEE0010
48000078 2C15000B
40A20014 8BEE0014
3BFF0001 9BEE0014
48000060 2C15000C
40A20014 8BEE0018
3BFF0001 9BEE0018
48000048 2C15000D
40A20014 8BEE001C
3BFF0001 9BEE001C
48000030 2C15000E
40A20014 8BEE0020
3BFF0001 9BEE0020
48000018 2C15000F
40A20010 8BEE0024
3BFF0001 9BEE0024
39EF0004 4200FF0C
2C000006 40A20014
8BEE0000 2C1F0003
408000E8 480000FC
2C000007 40A20014
8BEE0004 2C1F0001
408000D0 480000E4
2C000008 40A20014
8BEE0008 2C1F0001
408000B8 480000CC
2C000009 40A20014
8BEE000C 2C1F0003
408000A0 480000B4
2C00000A 40A20014
8BEE0010 2C1F0002
40800088 4800009C
2C00000B 40A20014
8BEE0014 2C1F0002
40800070 48000084
2C00000C 40A20014
8BEE0018 2C1F0001
40800058 4800006C
2C00000D 40A20014
8BEE001C 2C1F0001
40800040 48000054
2C00000E 40A20014
8BEE0020 2C1F0001
40800028 4800003C
2C00000F 40A20010
8BEE0024 2C1F0001
40800010 48000024
980C0193 48000034
62F70064 48000008
62F7012C 7EF7B214
3AF70001 92F80000
3BE00000 3A60000A
7E6903A6 9BEE0000
39CE0004 4200FFF8
7F2FF120 7E8903A6
B9C10008 38210050
60000000 00000000

(PAL)
C2661338 00000006
9421FFB0 BDC10008
907C0008 3EE080A1
62F70024 3F008053
63185BE8 92F80000
B9C10008 38210050
60000000 00000000
C265E18C 0000000C
9421FFB0 BDC10008
7F200026 8A430003
1D960004 3D8C8168
88030001 2C120000
41A20014 2C120001
41820018 2C120002
40A0001C 3BE00014
9BEC0193 48000014
3BE00057 9BEC0193
48000008 980C0193
7F2FF120 B9C10008
38210050 00000000
C265E1A8 0000005C
9421FFB0 BDC10008
7F200026 7E8902A6
8A500013 1D960004
3D8C8168 88100011
2C120000 41A20014
2C120001 41820018
2C120002 40A0025C
3BE00014 9BEC0193
48000288 3BE00057
9BEC0193 3F008053
63185BE8 3EE038A0
8A300012 2C110010
41820018 2C110011
41820010 2C110012
41820008 4800001C
2C000010 41820224
2C000011 4182021C
2C000012 41820214
3A60000C 7E6903A6
3DE08168 61EF0193
3DC08168 61CE0133
8AAF0000 2C150006
40A20014 8BEE0000
3BFF0001 9BEE0000
480000D8 2C150007
40A20014 8BEE0004
3BFF0001 9BEE0004
480000C0 2C150008
40A20014 8BEE0008
3BFF0001 9BEE0008
480000A8 2C150009
40A20014 8BEE000C
3BFF0001 9BEE000C
48000090 2C15000A
40A20014 8BEE0010
3BFF0001 9BEE0010
48000078 2C15000B
40A20014 8BEE0014
3BFF0001 9BEE0014
48000060 2C15000C
40A20014 8BEE0018
3BFF0001 9BEE0018
48000048 2C15000D
40A20014 8BEE001C
3BFF0001 9BEE001C
48000030 2C15000E
40A20014 8BEE0020
3BFF0001 9BEE0020
48000018 2C15000F
40A20010 8BEE0024
3BFF0001 9BEE0024
39EF0004 4200FF0C
2C000006 40A20014
8BEE0000 2C1F0003
408000E8 480000FC
2C000007 40A20014
8BEE0004 2C1F0001
408000D0 480000E4
2C000008 40A20014
8BEE0008 2C1F0001
408000B8 480000CC
2C000009 40A20014
8BEE000C 2C1F0003
408000A0 480000B4
2C00000A 40A20014
8BEE0010 2C1F0002
40800088 4800009C
2C00000B 40A20014
8BEE0014 2C1F0002
40800070 48000084
2C00000C 40A20014
8BEE0018 2C1F0001
40800058 4800006C
2C00000D 40A20014
8BEE001C 2C1F0001
40800040 48000054
2C00000E 40A20014
8BEE0020 2C1F0001
40800028 4800003C
2C00000F 40A20010
8BEE0024 2C1F0001
40800010 48000024
980C0193 48000034
62F70064 48000008
62F7012C 7EF7B214
3AF70001 92F80000
3BE00000 3A60000A
7E6903A6 9BEE0000
39CE0004 4200FFF8
7F2FF120 7E8903A6
B9C10008 38210050
60000000 00000000

(NTSC-J)
C26609A4 00000006
9421FFB0 BDC10008
907C0008 3EE080A1
62F70024 3F008053
63185568 92F80000
B9C10008 38210050
60000000 00000000
C265D7F8 0000000C
9421FFB0 BDC10008
7F200026 8A430003
1D960004 3D8C8168
88030001 2C120000
41A20014 2C120001
41820018 2C120002
40A0001C 3BE00014
9BEC0193 48000014
3BE00057 9BEC0193
48000008 980C0193
7F2FF120 B9C10008
38210050 00000000
C265D814 0000005C
9421FFB0 BDC10008
7F200026 7E8902A6
8A500013 1D960004
3D8C8168 88100011
2C120000 41A20014
2C120001 41820018
2C120002 40A0025C
3BE00014 9BEC0193
48000288 3BE00057
9BEC0193 3F008053
63185568 3EE038A0
8A300012 2C110010
41820018 2C110011
41820010 2C110012
41820008 4800001C
2C000010 41820224
2C000011 4182021C
2C000012 41820214
3A60000C 7E6903A6
3DE08168 61EF0193
3DC08168 61CE0133
8AAF0000 2C150006
40A20014 8BEE0000
3BFF0001 9BEE0000
480000D8 2C150007
40A20014 8BEE0004
3BFF0001 9BEE0004
480000C0 2C150008
40A20014 8BEE0008
3BFF0001 9BEE0008
480000A8 2C150009
40A20014 8BEE000C
3BFF0001 9BEE000C
48000090 2C15000A
40A20014 8BEE0010
3BFF0001 9BEE0010
48000078 2C15000B
40A20014 8BEE0014
3BFF0001 9BEE0014
48000060 2C15000C
40A20014 8BEE0018
3BFF0001 9BEE0018
48000048 2C15000D
40A20014 8BEE001C
3BFF0001 9BEE001C
48000030 2C15000E
40A20014 8BEE0020
3BFF0001 9BEE0020
48000018 2C15000F
40A20010 8BEE0024
3BFF0001 9BEE0024
39EF0004 4200FF0C
2C000006 40A20014
8BEE0000 2C1F0003
408000E8 480000FC
2C000007 40A20014
8BEE0004 2C1F0001
408000D0 480000E4
2C000008 40A20014
8BEE0008 2C1F0001
408000B8 480000CC
2C000009 40A20014
8BEE000C 2C1F0003
408000A0 480000B4
2C00000A 40A20014
8BEE0010 2C1F0002
40800088 4800009C
2C00000B 40A20014
8BEE0014 2C1F0002
40800070 48000084
2C00000C 40A20014
8BEE0018 2C1F0001
40800058 4800006C
2C00000D 40A20014
8BEE001C 2C1F0001
40800040 48000054
2C00000E 40A20014
8BEE0020 2C1F0001
40800028 4800003C
2C00000F 40A20010
8BEE0024 2C1F0001
40800010 48000024
980C0193 48000034
62F70064 48000008
62F7012C 7EF7B214
3AF70001 92F80000
3BE00000 3A60000A
7E6903A6 9BEE0000
39CE0004 4200FFF8
7F2FF120 7E8903A6
B9C10008 38210050
60000000 00000000

(NTSC-K)
C264F650 00000006
9421FFB0 BDC10008
907C0008 3EE080A1
62F70024 3F008052
63183C40 92F80000
B9C10008 38210050
60000000 00000000
C264C4A4 0000000C
9421FFB0 BDC10008
7F200026 8A430003
1D960004 3D8C8168
88030001 2C120000
41A20014 2C120001
41820018 2C120002
40A0001C 3BE00014
9BEC0193 48000014
3BE00057 9BEC0193
48000008 980C0193
7F2FF120 B9C10008
38210050 00000000
C264C4C0 0000005C
9421FFB0 BDC10008
7F200026 7E8902A6
8A500013 1D960004
3D8C8168 88100011
2C120000 41A20014
2C120001 41820018
2C120002 40A0025C
3BE00014 9BEC0193
48000288 3BE00057
9BEC0193 3F008052
63183C40 3EE038A0
8A300012 2C110010
41820018 2C110011
41820010 2C110012
41820008 4800001C
2C000010 41820224
2C000011 4182021C
2C000012 41820214
3A60000C 7E6903A6
3DE08168 61EF0193
3DC08168 61CE0133
8AAF0000 2C150006
40A20014 8BEE0000
3BFF0001 9BEE0000
480000D8 2C150007
40A20014 8BEE0004
3BFF0001 9BEE0004
480000C0 2C150008
40A20014 8BEE0008
3BFF0001 9BEE0008
480000A8 2C150009
40A20014 8BEE000C
3BFF0001 9BEE000C
48000090 2C15000A
40A20014 8BEE0010
3BFF0001 9BEE0010
48000078 2C15000B
40A20014 8BEE0014
3BFF0001 9BEE0014
48000060 2C15000C
40A20014 8BEE0018
3BFF0001 9BEE0018
48000048 2C15000D
40A20014 8BEE001C
3BFF0001 9BEE001C
48000030 2C15000E
40A20014 8BEE0020
3BFF0001 9BEE0020
48000018 2C15000F
40A20010 8BEE0024
3BFF0001 9BEE0024
39EF0004 4200FF0C
2C000006 40A20014
8BEE0000 2C1F0003
408000E8 480000FC
2C000007 40A20014
8BEE0004 2C1F0001
408000D0 480000E4
2C000008 40A20014
8BEE0008 2C1F0001
408000B8 480000CC
2C000009 40A20014
8BEE000C 2C1F0003
408000A0 480000B4
2C00000A 40A20014
8BEE0010 2C1F0002
40800088 4800009C
2C00000B 40A20014
8BEE0014 2C1F0002
40800070 48000084
2C00000C 40A20014
8BEE0018 2C1F0001
40800058 4800006C
2C00000D 40A20014
8BEE001C 2C1F0001
40800040 48000054
2C00000E 40A20014
8BEE0020 2C1F0001
40800028 4800003C
2C00000F 40A20010
8BEE0024 2C1F0001
40800010 48000024
980C0193 48000034
62F70064 48000008
62F7012C 7EF7B214
3AF70001 92F80000
3BE00000 3A60000A
7E6903A6 9BEE0000
39CE0004 4200FFF8
7F2FF120 7E8903A6
B9C10008 38210050
60000000 00000000



Code:
#============================================================#
#                          Source                            #
#============================================================#

.globl shared_item_detection_reset_timer
shared_item_detection_reset_timer:

#============================================================#
#                    Local SELECT Record                     #
#============================================================#
# Original Address Ports:                                    #
# RMCE - 0x806593FC                                          #
# RMCP - 0x80661338                                          #
# RMCJ - 0x806609A4                                          #
# RMCK - 0x8064F650                                          #
#============================================================#

.set millisecondsDisplayAddress, 0
.set region, ''

.if (region == 'E' || region == 'e') # RMCE
millisecondsDisplayAddress = 0x805310A0
.elseif (region == 'P' || region == 'p') # RMCP
millisecondsDisplayAddress = 0x80535BE8
.elseif (region == 'J' || region == 'j') # RMCJ
millisecondsDisplayAddress = 0x80535568
.elseif (region == 'K' || region == 'k') # RMCK
millisecondsDisplayAddress = 0x80523C40
.else # Invalid Region
.abort
.endif

#============================================================#
#                   Registers & Offsets                      #
#------------------------------------------------------------#
# 8(r28) = NULL or Time of Sender                            #
#============================================================#
# r3  = NULL or Time of Sender                               #
# r23 = Modified Milliseconds Display Value                  #
# r24 = Milliseconds Display Address                         #
# r28 = Address to SELECT Record                             #
#============================================================#

# Function Prologue...
stwu r1, -80(r1) # Make space for 18 registers
stmw r14, 8(r1)  # Push r14-r31 onto the stack

# Original instruction
stw r3, 8(r28) # Store the word in r3 (NULL or Time of Sender) at the address in r28 offset by 8

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Reset the timer back to the default milliseconds after     #
# each race. If the timer was not changed, no harm done.     #
#                                                            #
# This instruction is only executed once before a race       #
# starts, so the timer will always be reset for a new race.  #
#============================================================#

lis r23, 0x80A1 # Set the higher 16 bits of r23 (Modified Milliseconds Display Value) to 0x38A0
ori r23, r23, 0x0024 # Set the lower 16 bits of r23 (Modified Milliseconds Display Value) to 0x0024

lis r24, millisecondsDisplayAddress@ha # Set the higher 16 bits of r24 (Milliseconds Display Address)
ori r24, r24, millisecondsDisplayAddress@l # Set the lower 16 bits of r24 (Milliseconds Display Address)

stw r23, 0(r24) # Store the word in r23 to the address in r24

# Function Epilogue...
lmw r14, 8(r1) # Pop r14-r31 off the stack
addi r1, r1, 80 # Release the space

~

.globl shared_item_detection_local_player
shared_item_detection_local_player:

#============================================================#
#                Local Player's ITEM Record                  #
#============================================================#
# Original Address Ports:                                    #
# RMCE - 0x8065EE14                                          #
# RMCP - 0x8065E18C                                          #
# RMCJ - 0x8065D7F8                                          #
# RMCK - 0x8064C4A4                                          #
#============================================================#

#============================================================#
#                   Registers & Offsets                      #
#------------------------------------------------------------#
# 0(r3) = Start time of Local Player's Item                  #
# 1(r3) = Local Player's Held Item                           #
# 2(r3) = Local Player's Trailed Item                        #
# 3(r3) = Local Player's Activation Mode                     #
#============================================================#
# r0  = Local Player's Held Item                             #
# r3  = Address to Local Player's ITEM Record                #
# r12 = Address to Local Player's Item Spy                   #
# r18 = Local Player's Activation Mode                       #
# r22 = Local Player's Slot                                  #
# r25 = Preserved Condition Register Value                   #
# r31 = Temporary Register                                   #
#============================================================#

# Function Prologue...
stwu r1, -80(r1) # Make space for 18 registers
stmw r14, 8(r1)  # Push r14-r31 onto the stack

mfcr r25 # Preserve the Condition Register in r25

lbz r18, 3(r3) # Load the byte at the address in r3 offset by 3 (Local Player's Activation Mode) and store it in r18

mulli r12, r22, 4 # Multiply the value in r22 (Local Player's Slot) by 4 and place the lower 32 bits of the result in r12
subis r12, r12, 32408 # Subtract the value in r12 by 32408, then shift r12 16 bits to the left and store the result in r12

# Original instruction
lbz r0, 1(r3) # Load the byte at the address in r3 offset by 1 (Local Player's Held Item) and store it in r0

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Find the Activation Mode of the Local Player.              #
#============================================================#

cmpwi cr0, r18, 0 # Compare the value in r18 (Local Player's Activation Mode) to 0
beq+ cr0, branch_handshake_stage_0 # Branch if equal
cmpwi cr0, r18, 1 # Compare the value in r18 (Local Player's Activation Mode) to 1
beq- cr0, branch_handshake_stage_1 # Branch if equal
cmpwi cr0, r18, 2 # Compare the value in r18 (Local Player's Activation Mode) to 2
bge+ cr0, branch_handshake_stage_2_or_greater # Branch if greater or equal

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Store the Local Player's Held Item to Item Spy.            #
#                                                            #
# To prevent false positives from occuring (Caused by the    #
# Item Value switching before the Activation Mode), store    #
# the No Item value to the Item Spy. The Local Player has No #
# Item in this mode.                                         #
#                                                            #
# Activation Mode:                                           #
# 0 - No Item                                                #
#============================================================#

branch_handshake_stage_0:

li r31, 0x14 # Load 0x14 into r31
stb r31, 0x193(r12) # Store the byte in r31 (No Item Value) to the address in r12 offset by 0x193

b branch_finished

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# This code will not detect if the Local Player is using the #
# Shared Item code. This is done to avoid doubling the       #
# code's length for little reason.                           #
#                                                            #
# To prevent false positives from occuring (Caused by the    #
# Item Value switching before the Activation Mode), store    #
# garbage to the Item Spy.                                   #
#                                                            #
# Handshake Value:                                           #
# 1 - Item Local Player wants                                #
#============================================================#

branch_handshake_stage_1:

li      r31, 0x57 # Load 0x57 into r31
stb r31, 0x193(r12) # Store the byte in r31 to the address in r12 offset by 0x193

b branch_finished

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Store the Local Player's Held Item to Item Spy.            #
#                                                            #
# Activation Modes >= 2 mean the Item the Local Player will  #
# receive is confirmed.                                      #
#                                                            #
# Activation Mode:                                           #
# 2 - Item Local Player will receive                         #
# 3 - ?                                                      #
# 4 - Ready to fire Triple Items                             #
# 5 - ?                                                      #
# 6 - Ready to fire Item                                     #
# 7 - No Item Available                                      #
#============================================================#

branch_handshake_stage_2_or_greater:

stb r0, 0x193(r12) # Store the byte in r0 (Player's Held Item) to the address in r12 offset by 0x193

branch_finished:

mtcr r25 # Restore the Condition Register from r25

lmw r14, 8(r1) # Pop r14-r31 off the stack
addi r1, r1, 80 # Release the space

~

.globl shared_item_detection_player
shared_item_detection_player:

#============================================================#
#                   Players ITEM Record                      #
#============================================================#
# Original Address Ports:                                    #
# RMCE - 0x8065EE30                                          #
# RMCP - 0x8065E1A8                                          #
# RMCJ - 0x8065D814                                          #
# RMCK - 0x8064C4C0                                          #
#============================================================#

.set millisecondsDisplayAddress, 0
.set region, ''

.if (region == 'E' || region == 'e') # RMCE
millisecondsDisplayAddress = 0x805310A0
.elseif (region == 'P' || region == 'p') # RMCP
millisecondsDisplayAddress = 0x80535BE8
.elseif (region == 'J' || region == 'j') # RMCJ
millisecondsDisplayAddress = 0x80535568
.elseif (region == 'K' || region == 'k') # RMCK
millisecondsDisplayAddress = 0x80523C40
.else # Invalid Region
.abort
.endif

#============================================================#
#                   Registers & Offsets                      #
#------------------------------------------------------------#
# 16(r16) = Start time of Item                               #
# 17(r16) = Held Item                                        #
# 18(r16) = Trailed Item                                     #
# 19(r16) = Activation Mode                                  #
#============================================================#
# r0  = Player's Held Item                                   #
# r12 = Address to Player's Item Spy                         #
# r14 = Address to # of Items in play                        #
# r15 = Address to all Players Item Spy                      #
# r16 = Address to ITEM Record                               #
# r17 = Player's Trailed Item                                #
# r18 = Player's Activation Mode                             #
# r19 = Count Register Value                                 #
# r20 = Preserved Count Register Value                       #
# r21 = nth Player's Item                                    #
# r22 = Player's Slot                                        #
# r23 = Modified Milliseconds Display Value                  #
# r24 = Milliseconds Display Address                         #
# r25 = Preserved Condition Register Value                   #
# r31 = Temporary Register                                   #
#============================================================#

# Function Prologue...
stwu r1, -80(r1) # Make space for 18 registers
stmw r14, 8(r1)  # Push r14-r31 onto the stack

mfcr r25 # Preserve the Condition Register in r25
mfctr   r20 # Preserve the Count Register in r20

lbz r18, 19(r16) # Load the byte at the address in r16 offset by 19 (Player's Activation Mode) and store it in r18

mulli r12, r22, 4 # Multiply the value in r22 (Player's Slot) by 4 and place the lower 32 bits of the result in r12
subis r12, r12, 32408 # Subtract the value in r12 by 32408, then shift r12 16 bits to the left and store the result in r12

# Original instruction
lbz r0, 17(r16) # Load the byte at the address in r16 offset by 17 (Player's Held Item) and store it in r0

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Find the Activation Mode of the Player.                    #
#============================================================#

cmpwi cr0, r18, 0 # Compare the value in r18 (Player's Activation Mode) to 0
beq+ cr0, branch_handshake_stage_0 # Branch if equal
cmpwi cr0, r18, 1 # Compare the value in r18 (Player's Activation Mode) to 1
beq- cr0, branch_handshake_stage_1 # Branch if equal
cmpwi cr0, r18, 2 # Compare the value in r18 (Player's Activation Mode) to 2
bge+ cr0, branch_handshake_stage_2_or_greater # Branch if greater than or equal

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Store the Player's Held Item to Item Spy.                  #
#                                                            #
# To prevent false positives from occuring (Caused by the    #
# Item Value switching before the Activation Mode), store    #
# the No Item value to the Item Spy. The Player has No Item  #
# in this mode.                                              #
#                                                            #
# Activation Mode:                                           #
# 0 - No Item                                                #
#============================================================#

branch_handshake_stage_0:

li r31, 0x14 # Load 0x14 into r31
stb r31, 0x193(r12) # Store the byte in r31 (No Item Value) to the address in r12 offset by 0x193

b branch_finished

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Detect Players trying to obtain impossible Shared Items    #
# using a variety of methods.                                #
#                                                            #
# To prevent false positives from occuring (Caused by the    #
# Item Value switching before the Activation Mode), store    #
# garbage to the Item Spy.                                   #
#                                                            #
# Handshake Value:                                           #
# 1 - Item Player wants                                      #
#============================================================#

branch_handshake_stage_1:

li      r31, 0x57 # Load 0x57 into r31
stb r31, 0x193(r12) # Store the byte in r31 (Garbage Item Value) to the address in r12 offset by 0x193

lis r24, millisecondsDisplayAddress@ha # Set the higher 16 bits of r24 (Milliseconds Display Address)
ori r24, r24, millisecondsDisplayAddress@l # Set the lower 16 bits of r24 (Milliseconds Display Address)

lis r23, 0x38A0 # Set the higher 16 bits of r23 (Modified Milliseconds Display Value) to 0x38A0

lbz r17, 18(r16) # Load the byte at the address in r16 offset by 18 (Player's Trailed Item) and store it in r17

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Check the if the current Player has impossible             #
# Items trailing them, according to their current Item.      #
#                                                            #
# It is impossible for a Player to obtain another set of     #
# Triple Items if they are currently trailing a set.         #
#============================================================#

cmpwi cr0, r17, 0x10 # Compare the value in r17 (Player's Trailed Item) to 0x10 (Triple Green Shells)
beq- cr0, branch_impossible_trailed_items_check # Branch if equal
cmpwi cr0, r17, 0x11 # Compare the value in r17 (Player's Trailed Item) to 0x11 (Triple Red Shells)
beq- cr0, branch_impossible_trailed_items_check # Branch if equal
cmpwi cr0, r17, 0x12 # Compare the value in r17 (Player's Trailed Item) to 0x12 (Triple Bananas)
beq- cr0, branch_impossible_trailed_items_check # Branch if equal

b branch_skip_impossible_trailed_items_check

branch_impossible_trailed_items_check:

cmpwi cr0, r0, 0x10 # Compare the value in r0 (Player's Held Item) to 0x10 (Triple Green Shells)
beq- cr0, branch_impossible_triple_item_combination_detected # Branch if equal
cmpwi cr0, r0, 0x11 # Compare the value in r0 (Player's Held Item) to 0x11 (Triple Red Shells)
beq- cr0, branch_impossible_triple_item_combination_detected # Branch if equal
cmpwi cr0, r0, 0x12 # Compare the value in r0 (Player's Held Item) to 0x12 (Triple Bananas)
beq- cr0, branch_impossible_triple_item_combination_detected # Branch if equal

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Store the amount of each Item currently in play,           #
# not including the Player's pending Item.                   #
#                                                            #
# => If a Player has an Item Value not listed below, nothing #
# is done.                                                   #
#                                                            #
# => If there are less than 12 Players in the room, the      #
# extra slots in memory will have a value of 0.              #
#============================================================#

branch_skip_impossible_trailed_items_check:

li r19, 12 # Load 12 into r19 (Count Register Loop Amount)
mtctr r19 # Move r19 into the Count Register

lis r15, 0x8168 # Set the higher 16 bits of r15 (Address to all Player's Items) to 0x8168
ori r15, r15, 0x0193 # Set the lower 16 bits of r15 (Address to all Player's Items) to 0x0193

lis r14, 0x8168 # Set the higher 16 bits of r14 (Address to number of items in play) to 0x8168
ori r14, r14, 0x0133 # Set the lower 16 bits of r14 (Address to number of items in play) to 0x0133

branch_item_amount_loop:

lbz r21, 0(r15) # Load the byte at the address in r15 (nth Player's Item) and store it in r21

cmpwi cr0, r21, 0x6 # Compare the value in r21 (nth Player's Item) to 0x6 (Bob-omb)
bne+ cr0, branch_item_not_bob_omb # Branch if not equal
lbz r31, 0(r14) # Load the byte at the address in r14 (Number of Bob-ombs in play) and store it in r31
addi r31, r31, 1 # Add 1 to r31 (Number of Bob-ombs in play) and store the result in r31
stb r31, 0(r14) # Store the byte in r31 (Number of Bob-ombs in play) to the address in r14
b branch_item_found # Branch to check the next player since we found the item this player is holding

branch_item_not_bob_omb:

cmpwi cr0, r21, 0x7
bne+ cr0, branch_item_not_blue_shell
lbz r31, 4(r14)
addi r31, r31, 1
stb r31, 4(r14)
b branch_item_found

branch_item_not_blue_shell:

cmpwi cr0, r21, 0x8
bne+ cr0, branch_item_not_lightning
lbz r31, 8(r14)
addi r31, r31, 1
stb r31, 8(r14)
b branch_item_found

branch_item_not_lightning:

cmpwi cr0, r21, 0x9
bne+ cr0, branch_item_not_star
lbz r31, 12(r14)
addi r31, r31, 1
stb r31, 12(r14)
b branch_item_found

branch_item_not_star:

cmpwi cr0, r21, 0xA
bne+ cr0, branch_item_not_golden_mushroom
lbz r31, 16(r14)
addi r31, r31, 1
stb r31, 16(r14)
b branch_item_found

branch_item_not_golden_mushroom:

cmpwi cr0, r21, 0xB
bne+ cr0, branch_item_not_mega_mushroom
lbz r31, 20(r14)
addi r31, r31, 1
stb r31, 20(r14)
b branch_item_found

branch_item_not_mega_mushroom:

cmpwi cr0, r21, 0xC
bne+ cr0, branch_item_not_blooper
lbz r31, 24(r14)
addi r31, r31, 1
stb r31, 24(r14)
b branch_item_found

branch_item_not_blooper:

cmpwi cr0, r21, 0xD
bne+ cr0, branch_item_not_pow_block
lbz r31, 28(r14)
addi r31, r31, 1
stb r31, 28(r14)
b branch_item_found

branch_item_not_pow_block:

cmpwi cr0, r21, 0xE
bne+ cr0, branch_item_not_thunder_cloud
lbz r31, 32(r14)
addi r31, r31, 1
stb r31, 32(r14)
b branch_item_found

branch_item_not_thunder_cloud:

cmpwi cr0, r21, 0xF
bne+ cr0, branch_item_not_bullet_bill
lbz r31, 36(r14)
addi r31, r31, 1
stb r31, 36(r14)

branch_item_not_bullet_bill:

branch_item_found:

addi r15, r15, 4 # Add 4 to r15 (Address to all Player's items) and store the result in r15
bdnz+ branch_item_amount_loop # Branch and decrement the Count Register while not zero

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Now that we have the amount of each Item in play,          #
# we can compare them to their hardcoded limits.             #
#                                                            #
# If the amount in play is equal (or greater) to the max,    #
# the current Player must be trying to cheat one. This is    #
# because they are trying obtain one when the game would     #
# not normally allow it due to hardcoded limits.             #
#                                                            #
# This is possible because during Activation Mode 1, the     #
# Player will report the Item they would like to receive as  #
# their Held Item.                                           #
#                                                            #
# => If the Player's Held Item is not listed below, nothing  #
# will happen.                                               #
#============================================================#

cmpwi cr0, r0, 0x6 # Compare the value in r0 (Player's Held Item) to 0x6 (Bob-omb)
bne+ cr0, branch_not_checking_bob_omb_limit # Branch if not equal
lbz r31, 0(r14) # Load the byte at the address in r14 (Number of Bob-ombs in play) and store it in r31
cmpwi cr0, r31, 3 # Compare the value in r31 (Number of Bob-ombs in play) to 0x3 (Max Number of Bob-ombs)
bge- cr0, branch_impossible_shared_item_detected # Branch if greater than or equal
b branch_impossible_shared_item_not_detected # Branch if the Item will not break any rules

branch_not_checking_bob_omb_limit:

cmpwi cr0, r0, 0x7
bne+ cr0, branch_not_checking_blue_shell_limit
lbz r31, 4(r14)
cmpwi cr0, r31, 1
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_blue_shell_limit:

cmpwi cr0, r0, 0x8
bne+ cr0, branch_not_checking_lightning_limit
lbz r31, 8(r14)
cmpwi cr0, r31, 1
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_lightning_limit:

cmpwi cr0, r0, 0x9
bne+ cr0, branch_not_checking_star_limit
lbz r31, 12(r14)
cmpwi cr0, r31, 3
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_star_limit:

cmpwi cr0, r0, 0xA
bne+ cr0, branch_not_checking_golden_mushroom_limit
lbz r31, 16(r14)
cmpwi cr0, r31, 2
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_golden_mushroom_limit:

cmpwi cr0, r0, 0xB
bne+ cr0, branch_not_checking_mega_mushroom_limit
lbz r31, 20(r14)
cmpwi cr0, r31, 2
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_mega_mushroom_limit:

cmpwi cr0, r0, 0xC
bne+ cr0, branch_not_checking_blooper_limit
lbz r31, 24(r14)
cmpwi cr0, r31, 1
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_blooper_limit:

cmpwi cr0, r0, 0xD
bne+ cr0, branch_not_checking_pow_block_limit
lbz r31, 28(r14)
cmpwi cr0, r31, 1
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_pow_block_limit:

cmpwi cr0, r0, 0xE
bne+ cr0, branch_not_checking_thunder_cloud_limit
lbz r31, 32(r14)
cmpwi cr0, r31, 1
bge- cr0, branch_impossible_shared_item_detected
b branch_impossible_shared_item_not_detected

branch_not_checking_thunder_cloud_limit:

cmpwi cr0, r0, 0xF
bne+ cr0, branch_not_checking_bullet_bill_limit
lbz r31, 36(r14)
cmpwi cr0, r31, 1
bge- cr0, branch_impossible_shared_item_detected

branch_not_checking_bullet_bill_limit:

b branch_impossible_shared_item_not_detected

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Store the Player's Held Item to Item Spy.                  #
#                                                            #
# Activation Modes >= 2 mean the Item the Player will        #
# receive is confirmed.                                      #
#                                                            #
# Activation Mode:                                           #
# 2 - Item Player will receive                               #
# 3 - ?                                                      #
# 4 - Ready to fire Triple Items                             #
# 5 - ?                                                      #
# 6 - Ready to fire Item                                     #
# 7 - No Item Available                                      #
#============================================================#

branch_handshake_stage_2_or_greater:

stb r0, 0x193(r12) # Store the byte in r0 (Player's Held Item) to the address in r12 offset by 0x193

b branch_finished

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# The first digit of the milliseconds will denote the        #
# detection reason. The last two digits will denote the      #
# Player's Slot (01-12).                                     #
#                                                            #
# Possible Detection Reasons:                                #
# 1SS - Impossible Shared Item Detected                      #
# 3SS - Impossible Triple Item Combination Detected          #
#============================================================#

branch_impossible_shared_item_detected:

ori r23, r23, 100 # Set the lower 16 bits of r23 (Modified Milliseconds Display Value) to 100

b branch_modify_timer

branch_impossible_triple_item_combination_detected:

ori r23, r23, 300 # Set the lower 16 bits of r23 (Modified Milliseconds Display Value) to 300

branch_modify_timer:

add r23, r23, r22 # Add the value in r22 (Player's Slot) to the value in r23 (Modified Milliseconds Display Value) and store the result in r23
addi r23, r23, 1 # Add 1 (Have the milliseconds display 1-12 rather than 0-11 for the Player's Slot) to r23 and store the result in r23
stw r23, 0(r24) # Store the word in r23 to the address in r24 (Milliseconds Display Address)

#============================================================#
#                         Purpose                            #
#------------------------------------------------------------#
# Clear the amount of Items in play.                         #
#============================================================#

branch_impossible_shared_item_not_detected:

li r31, 0 # Load 0 into r31

li r19, 10 # Load 10 into r19 (Count Register Loop Amount)
mtctr r19 # Move r19 into the Count Register

branch_clear_item_amount_loop:

stb r31, 0(r14) # Store the byte in r31 (00) to the address in r14 (Number of n in play)
addi r14, r14, 4 # Add 4 to r14 and store the result in r14

bdnz+ branch_clear_item_amount_loop # Branch and decrement the Count Register while not zero

branch_finished:

# Function Epilogue...
mtcr r25 # Restore the Condition Register from r25
mtctr r20 # Restore the Count Register from r20

lmw r14, 8(r1) # Pop r14-r31 off the stack
addi r1, r1, 80 # Release the space



Notes:
- If a detection occurs, the milliseconds will return to normal when the next race begins.
- This code relies on a specific value in the ITEM Packet. Due to the nature of how network traffic is sent, it is recommended to have all P2P connections set up (NATNEG complete).

Code Creator: Star
Code Credits: mdmwii (Item Warning), Bully@WiiPlaza (USB Gecko Item Spy, Millisecond Display Modifier)
Reply
#2
Nice work!
Reply
#3
Update: After debugging the code, I was able to identify the cause of the false positives and remedy the issue.

Technical: I assumed a Player's Held Item and Activation Mode would be updated in parallel. However, a Player's Item Value may update before their Activation Mode. This would cause their Item in the Item Spy to be updated with the Item they want to receive before they reached Activation Mode 1, where the code would stop updating the Item Spy. This resulted in an extra Item of the one they want to receive being added to the Item Spy. In turn, this caused false positives since the Item Count was incorrect. To fix this, the code now overwrites the Item Values with Non-Item Values while in Activation Modes 0 & 1.
[Image: M8Vn0Cu.png]
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)