Graphical In-Game Item Spy Offline [Vega]
NOTE: It's recommended to also include this code to eliminate frame flickers -> https://mkwii.com/showthread.php?tid=1530
Works Offline only.
This code will place a graphical image on the bottom on your screen. The screen will contain the held items (in inventory) of every player in the race. The listing of the items will be ordered by the player slot number. The items presented will be shown in their hex value...
Hex Item Image Values:
00 - Green Shell / No Player on Slot
01 - Red Shell
02 - Banana
03 - Fib
04 - Shroom
05 - Triple Shrooms
06 - Bomb
07 - Blue Shell
08 - Shock
09 - Star
0A - Golden
0B - Mega
0C - Blooper
0D - Pow
0E - TC
0F - Bill
10 - Triple Greens
11 - Triple Reds
12 - Triple Nanas
14 - No Item / No Item Available
NOTE: This code makes use of the following memory addresses...
0x80001500 thru 0x80001518
0x81500000 thru 0x8150002F
0x81510000 thru 0x81510003
Make sure no other codes in your GCT/Cheat-Manager are using those addresses.
NTSC-U
C200A3F0 00000007
9421FF80 BC610008
806DA358 80630044
80630000 3D808002
618C23E0 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C2009640 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C0ECC
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C0ECC
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1DF0
7D8803A6 4E800021
61CC1DD0 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C278EEF8 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
PAL
C200A430 00000007
9421FF80 BC610008
806DA360 80630044
80630000 3D808002
618C2480 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C2009680 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C1A2C
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C1A2C
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1E90
7D8803A6 4E800021
61CC1E70 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C2797F04 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
NTSC-J
C200A38C 00000007
9421FF80 BC610008
806DA360 80630044
80630000 3D808002
618C23A0 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C20095DC 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C1950
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C1950
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1DB0
7D8803A6 4E800021
61CC1D90 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C2797570 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
NTSC-K
C200A538 00000007
9421FF80 BC610008
806DA380 80630044
80630000 3D808002
618C24E0 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C2009788 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C1A94
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C1A94
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1EF0
7D8803A6 4E800021
61CC1ED0 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C27862C4 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
List of Sources:
1st ASM (When Game loads StaticR.rel, Get Render Mode & Call Direct Print Setup Frame Buffer)
#~~~~~~~~~~~~~~~~#
# START ASSEMBLY #
#~~~~~~~~~~~~~~~~#
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Register Notes: #
# No need to backup r0 or LR #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#~~~~~~~~~~~~~~~~~~~~~#
# Macros & Statements #
#~~~~~~~~~~~~~~~~~~~~~#
.macro push_stack
stwu r1, -0x80 (r1)
stmw r3, 0x8 (r1)
.endm
.macro pop_stack
lmw r3, 0x8 (r1)
addi r1, r1, 0x80
.endm
.macro call_link address
lis r12, \address@h
ori r12, r12, \address@l
mtlr r12
blrl
.endm
.macro default_instruction
lwz r0, 0x0014 (r1)
.endm
.set region, '' #Must set region value, or else source will not compile
.if (region == 'E' || region == 'e') # RMCE
.set nw4r_db_DirectPrint_SetupFB, 0x800223E0
.elseif (region == 'P' || region == 'p') # RMCP
.set nw4r_db_DirectPrint_SetupFB, 0x80022480
.elseif (region == 'J' || region == 'j') # RMCJ
.set nw4r_db_DirectPrint_SetupFB, 0x800223A0
.elseif (region == 'K' || region == 'k') # RMCK
.set nw4r_db_DirectPrint_SetupFB, 0x800224E0
.else # Invalid Region
.abort
.endif
#~~~~~~~~~~~~~~~~~~~~~~~#
# Start Register Safety #
#~~~~~~~~~~~~~~~~~~~~~~~#
push_stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Get Render Mode (RKSystem->mpVideo()->pRenderMode) #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
.if (region == 'E' || region == 'e') # RMCE
lwz r3, -0x5CA8(r13)
.elseif (region == 'P' || region == 'p') # RMCP
lwz r3, -0x5CA0(r13)
.elseif (region == 'J' || region == 'j') # RMCJ
lwz r3, -0x5CA0(r13)
.elseif (region == 'K' || region == 'k') # RMCK
lwz r3, -0x5C80(r13)
.endif
lwz r3, 0x0044(r3)
lwz r3, 0x0 (r3)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Call nw4r::db: DirectPrint_SetupFB #
# r3 = Render Mode #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
call_link nw4r_db_DirectPrint_SetupFB
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# End Register Safety; Default Instruction #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
pop_stack
default_instruction
#
#~~~~~~~~~~~~~~#
# END ASSEMBLY #
#~~~~~~~~~~~~~~#
==========
2nd ASM Source:
#~~~~~~~~~~~~~~~~#
# START ASSEMBLY #
#~~~~~~~~~~~~~~~~#
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Register Notes: #
# No need to backup r0 or LR #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Memory Address Notes: #
# 0x80001500 thru 0x80001512 - Formatted 1st Half of String #
# 0x80001512 - Null Byte appended from 1st Call of Sprintf #
# 0x80001512 thru 0x80001517 - Formatted 2nd Half of String #
# 0x80001518 - Null Byte appneded from 2nd Call of Sprintf #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#~~~~~~~~~~~~~~~~~~~~~#
# Macros & Statements #
#~~~~~~~~~~~~~~~~~~~~~#
.macro push_stack
stwu r1, -0x80 (r1)
stmw r3, 0x8 (r1)
.endm
.macro pop_stack
lmw r3, 0x8 (r1)
addi r1, r1, 0x80
.endm
.macro call_link address
lis r12, \address@h
ori r12, r12, \address@l
mtlr r12
blrl
.endm
.macro call_nw4r address
ori r12, r14, \address@l
mtlr r12
blrl
.endm
.macro default_instruction
lwz r12, 0x0 (r3)
.endm
.set region, '' #Must set region value, or else source will not compile
.if (region == 'E' || region == 'e') # RMCE
.set sprintf, 0x80010ECC
.set nw4r_db_DirectPrint_Printf, 0x1DF0
.set nw4r_db_DirectPrint_StoreCache, 0x1DD0
.elseif (region == 'P' || region == 'p') # RMCP
.set sprintf, 0x80011A2C
.set nw4r_db_DirectPrint_Printf, 0x1E90
.set nw4r_db_DirectPrint_StoreCache, 0x1E70
.elseif (region == 'J' || region == 'j') # RMCJ
.set sprintf, 0x80011950
.set nw4r_db_DirectPrint_Printf, 0x1DB0
.set nw4r_db_DirectPrint_StoreCache, 0x1D90
.elseif (region == 'K' || region == 'k') # RMCK
.set sprintf, 0x80011A94
.set nw4r_db_DirectPrint_Printf, 0x1EF0
.set nw4r_db_DirectPrint_StoreCache, 0x1ED0
.else # Invalid Region
.err
.endif
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check to See if a Race is Active: #
# Load Status Word from Mem 81 #
# If not zero, we know to execute the Draw Code #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
lis r12, 0x8151
lwz r12, 0x0 (r12)
cmpwi r12, 0x0
beq- dont_execute
#~~~~~~~~~~~~~~~~~~~~~~~#
# Start Register Safety #
#~~~~~~~~~~~~~~~~~~~~~~~#
push_stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Sprintf #1 #
# r3 = Address Pointer to Dump Formatted String #
# r4 = Address Pointer to String that needs Formatting #
# r5 thru r10 = Non Float Format Args #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
bl printf_string
.llong 0x2530325820253032 #1st String for 1st Sprintf - "%02X %02X %02X %02X %02X %02X "
.llong 0x5820253032582025
.llong 0x3032582025303258
.llong 0x2025303258200000
printf_string:
mflr r4
li r5, 0x20
stb r5, 0x1D (r4) #This is needed because the final 0x20 gets nulled out for second sprintf, so we always need to 'recover' it before first sprintf
mr r29, r4 #Backup String Address Pointer to r29
lis r30, 0x8150
lswi r5, r30, 24 #Load the first 6 slot Item Words into r5 - r10
lis r3, 0x8000 #Set Address to Dump String To
ori r3, r3, 0x1500
addi r31, r3, 0x0012 #First Formatted String Ends at 0x80001512 (null), so add 0x18 to r3 for start of 2nd string on 2nd call of sprintf. Put result in r31 for global variable storage thru function calls
call_link sprintf
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check Sprintf #1 Return Value #
# If negative, error occured #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
cmpwi r3, 0x0
blt- _error
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Sprintf #2 #
# r3 = Address Pointer to Dump Formatted String #
# r4 = Address Pointer to String that needs Formatting #
# r5 thru r10 = Non Float Format Args #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
mr r4, r29 #Move backed up string address pointer to r4
li r5, 0x0
stb r5, 0x1D (r4) #The space in the ASCII string near the end is not needed, null it out, string is now ready for 2nd call of sprintf
mr r3, r31 #2nd String will be dumped to exactly where null byte of 1st string of ended at
addi r30, r30, 0x18 #Add 0x18 to r30, now address points to beginning of second half of the 12 player item slot listing
lswi r5, r30, 24 #Load slot's 7 - 12 Item Words into r5 - r10
call_link sprintf
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check Sprintf #2 Return Value #
# If negative, error occured #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
cmpwi r3, 0x0
blt- _error
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# DirectPrint Printf & Store Cache #
# Purpose: Draw on Screen #
# r3 = X coordinate (starts far left) #
# r4 = Y coordinate (starts at very top) #
# r5 = 0 No Wrap; 1 Wrap #
# r6 = Address Pointer to String that will be Drawn on Screen #
# r7 thru r10 printf format args #
# f1 thru f13 printf float format args #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
li r3, 0x30
li r4, 0xDA
li r5, 0x1
addi r6, r31, -0x12 #Make r6 have 0x80001500, beginning of entire formatted string
lis r14, 0x8002 #For nw4r macro
call_nw4r nw4r_db_DirectPrint_Printf
call_nw4r nw4r_db_DirectPrint_StoreCache
#~~~~~~~~~~~~~~~~~~~~~#
# End Register Safety #
#~~~~~~~~~~~~~~~~~~~~~#
_error:
pop_stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# dont_execute label; Default Instruction #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
dont_execute:
default_instruction
#
#~~~~~~~~~~~~~~#
# END ASSEMBLY #
#~~~~~~~~~~~~~~#
==========
3rd ASM:
lwz r0, 0x8C (r29) #Default Instruction, r0 holds current Player/CPU's Held Item
mulli r12, r27, 0x4 #Multiple Player Slot value in r27 by 0x4, put result in r12
addis r12, r12, 0x8150 #Add 0x8150 to upper 16 bits of r12. The player slot will increment/separate the address by 0x4 depending on slot value
stw r0, 0x0 (r12) #Store current Player/CPU's Held Item value to address of r12
lis r11, 0x8151 #Set 1st Half Address for Race-Status Word Check
stw r29, 0x0 (r11) #We need anything not zero at 0x81510000, store 29 to that spot
Code creator: Vega
Code credits: Star & RiiDefi (Draw Text to Screen Code); Bully (Item Spy ASM)
NOTE: It's recommended to also include this code to eliminate frame flickers -> https://mkwii.com/showthread.php?tid=1530
Works Offline only.
This code will place a graphical image on the bottom on your screen. The screen will contain the held items (in inventory) of every player in the race. The listing of the items will be ordered by the player slot number. The items presented will be shown in their hex value...
Hex Item Image Values:
00 - Green Shell / No Player on Slot
01 - Red Shell
02 - Banana
03 - Fib
04 - Shroom
05 - Triple Shrooms
06 - Bomb
07 - Blue Shell
08 - Shock
09 - Star
0A - Golden
0B - Mega
0C - Blooper
0D - Pow
0E - TC
0F - Bill
10 - Triple Greens
11 - Triple Reds
12 - Triple Nanas
14 - No Item / No Item Available
NOTE: This code makes use of the following memory addresses...
0x80001500 thru 0x80001518
0x81500000 thru 0x8150002F
0x81510000 thru 0x81510003
Make sure no other codes in your GCT/Cheat-Manager are using those addresses.
NTSC-U
C200A3F0 00000007
9421FF80 BC610008
806DA358 80630044
80630000 3D808002
618C23E0 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C2009640 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C0ECC
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C0ECC
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1DF0
7D8803A6 4E800021
61CC1DD0 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C278EEF8 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
PAL
C200A430 00000007
9421FF80 BC610008
806DA360 80630044
80630000 3D808002
618C2480 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C2009680 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C1A2C
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C1A2C
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1E90
7D8803A6 4E800021
61CC1E70 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C2797F04 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
NTSC-J
C200A38C 00000007
9421FF80 BC610008
806DA360 80630044
80630000 3D808002
618C23A0 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C20095DC 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C1950
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C1950
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1DB0
7D8803A6 4E800021
61CC1D90 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C2797570 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
NTSC-K
C200A538 00000007
9421FF80 BC610008
806DA380 80630044
80630000 3D808002
618C24E0 7D8803A6
4E800021 B8610008
38210080 80010014
60000000 00000000
C2009788 0000001D
3D808151 818C0000
2C0C0000 418200D0
9421FF80 BC610008
48000025 25303258
20253032 58202530
32582025 30325820
25303258 20253032
58200000 7C8802A6
38A00020 98A4001D
7C9D2378 3FC08150
7CBEC4AA 3C608000
60631500 3BE30012
3D808001 618C1A94
7D8803A6 4E800021
2C030000 41800060
7FA4EB78 38A00000
98A4001D 7FE3FB78
3BDE0018 7CBEC4AA
3D808001 618C1A94
7D8803A6 4E800021
2C030000 41800030
38600030 388000DA
38A00001 38DFFFEE
3DC08002 61CC1EF0
7D8803A6 4E800021
61CC1ED0 7D8803A6
4E800021 B8610008
38210080 81830000
60000000 00000000
C27862C4 00000004
801D008C 1D9B0004
3D8C8150 900C0000
3D608151 93AB0000
60000000 00000000
List of Sources:
1st ASM (When Game loads StaticR.rel, Get Render Mode & Call Direct Print Setup Frame Buffer)
#~~~~~~~~~~~~~~~~#
# START ASSEMBLY #
#~~~~~~~~~~~~~~~~#
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Register Notes: #
# No need to backup r0 or LR #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#~~~~~~~~~~~~~~~~~~~~~#
# Macros & Statements #
#~~~~~~~~~~~~~~~~~~~~~#
.macro push_stack
stwu r1, -0x80 (r1)
stmw r3, 0x8 (r1)
.endm
.macro pop_stack
lmw r3, 0x8 (r1)
addi r1, r1, 0x80
.endm
.macro call_link address
lis r12, \address@h
ori r12, r12, \address@l
mtlr r12
blrl
.endm
.macro default_instruction
lwz r0, 0x0014 (r1)
.endm
.set region, '' #Must set region value, or else source will not compile
.if (region == 'E' || region == 'e') # RMCE
.set nw4r_db_DirectPrint_SetupFB, 0x800223E0
.elseif (region == 'P' || region == 'p') # RMCP
.set nw4r_db_DirectPrint_SetupFB, 0x80022480
.elseif (region == 'J' || region == 'j') # RMCJ
.set nw4r_db_DirectPrint_SetupFB, 0x800223A0
.elseif (region == 'K' || region == 'k') # RMCK
.set nw4r_db_DirectPrint_SetupFB, 0x800224E0
.else # Invalid Region
.abort
.endif
#~~~~~~~~~~~~~~~~~~~~~~~#
# Start Register Safety #
#~~~~~~~~~~~~~~~~~~~~~~~#
push_stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Get Render Mode (RKSystem->mpVideo()->pRenderMode) #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
.if (region == 'E' || region == 'e') # RMCE
lwz r3, -0x5CA8(r13)
.elseif (region == 'P' || region == 'p') # RMCP
lwz r3, -0x5CA0(r13)
.elseif (region == 'J' || region == 'j') # RMCJ
lwz r3, -0x5CA0(r13)
.elseif (region == 'K' || region == 'k') # RMCK
lwz r3, -0x5C80(r13)
.endif
lwz r3, 0x0044(r3)
lwz r3, 0x0 (r3)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Call nw4r::db: DirectPrint_SetupFB #
# r3 = Render Mode #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
call_link nw4r_db_DirectPrint_SetupFB
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# End Register Safety; Default Instruction #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
pop_stack
default_instruction
#
#~~~~~~~~~~~~~~#
# END ASSEMBLY #
#~~~~~~~~~~~~~~#
==========
2nd ASM Source:
#~~~~~~~~~~~~~~~~#
# START ASSEMBLY #
#~~~~~~~~~~~~~~~~#
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Register Notes: #
# No need to backup r0 or LR #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Memory Address Notes: #
# 0x80001500 thru 0x80001512 - Formatted 1st Half of String #
# 0x80001512 - Null Byte appended from 1st Call of Sprintf #
# 0x80001512 thru 0x80001517 - Formatted 2nd Half of String #
# 0x80001518 - Null Byte appneded from 2nd Call of Sprintf #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
#~~~~~~~~~~~~~~~~~~~~~#
# Macros & Statements #
#~~~~~~~~~~~~~~~~~~~~~#
.macro push_stack
stwu r1, -0x80 (r1)
stmw r3, 0x8 (r1)
.endm
.macro pop_stack
lmw r3, 0x8 (r1)
addi r1, r1, 0x80
.endm
.macro call_link address
lis r12, \address@h
ori r12, r12, \address@l
mtlr r12
blrl
.endm
.macro call_nw4r address
ori r12, r14, \address@l
mtlr r12
blrl
.endm
.macro default_instruction
lwz r12, 0x0 (r3)
.endm
.set region, '' #Must set region value, or else source will not compile
.if (region == 'E' || region == 'e') # RMCE
.set sprintf, 0x80010ECC
.set nw4r_db_DirectPrint_Printf, 0x1DF0
.set nw4r_db_DirectPrint_StoreCache, 0x1DD0
.elseif (region == 'P' || region == 'p') # RMCP
.set sprintf, 0x80011A2C
.set nw4r_db_DirectPrint_Printf, 0x1E90
.set nw4r_db_DirectPrint_StoreCache, 0x1E70
.elseif (region == 'J' || region == 'j') # RMCJ
.set sprintf, 0x80011950
.set nw4r_db_DirectPrint_Printf, 0x1DB0
.set nw4r_db_DirectPrint_StoreCache, 0x1D90
.elseif (region == 'K' || region == 'k') # RMCK
.set sprintf, 0x80011A94
.set nw4r_db_DirectPrint_Printf, 0x1EF0
.set nw4r_db_DirectPrint_StoreCache, 0x1ED0
.else # Invalid Region
.err
.endif
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check to See if a Race is Active: #
# Load Status Word from Mem 81 #
# If not zero, we know to execute the Draw Code #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
lis r12, 0x8151
lwz r12, 0x0 (r12)
cmpwi r12, 0x0
beq- dont_execute
#~~~~~~~~~~~~~~~~~~~~~~~#
# Start Register Safety #
#~~~~~~~~~~~~~~~~~~~~~~~#
push_stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Sprintf #1 #
# r3 = Address Pointer to Dump Formatted String #
# r4 = Address Pointer to String that needs Formatting #
# r5 thru r10 = Non Float Format Args #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
bl printf_string
.llong 0x2530325820253032 #1st String for 1st Sprintf - "%02X %02X %02X %02X %02X %02X "
.llong 0x5820253032582025
.llong 0x3032582025303258
.llong 0x2025303258200000
printf_string:
mflr r4
li r5, 0x20
stb r5, 0x1D (r4) #This is needed because the final 0x20 gets nulled out for second sprintf, so we always need to 'recover' it before first sprintf
mr r29, r4 #Backup String Address Pointer to r29
lis r30, 0x8150
lswi r5, r30, 24 #Load the first 6 slot Item Words into r5 - r10
lis r3, 0x8000 #Set Address to Dump String To
ori r3, r3, 0x1500
addi r31, r3, 0x0012 #First Formatted String Ends at 0x80001512 (null), so add 0x18 to r3 for start of 2nd string on 2nd call of sprintf. Put result in r31 for global variable storage thru function calls
call_link sprintf
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check Sprintf #1 Return Value #
# If negative, error occured #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
cmpwi r3, 0x0
blt- _error
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Sprintf #2 #
# r3 = Address Pointer to Dump Formatted String #
# r4 = Address Pointer to String that needs Formatting #
# r5 thru r10 = Non Float Format Args #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
mr r4, r29 #Move backed up string address pointer to r4
li r5, 0x0
stb r5, 0x1D (r4) #The space in the ASCII string near the end is not needed, null it out, string is now ready for 2nd call of sprintf
mr r3, r31 #2nd String will be dumped to exactly where null byte of 1st string of ended at
addi r30, r30, 0x18 #Add 0x18 to r30, now address points to beginning of second half of the 12 player item slot listing
lswi r5, r30, 24 #Load slot's 7 - 12 Item Words into r5 - r10
call_link sprintf
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Check Sprintf #2 Return Value #
# If negative, error occured #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
cmpwi r3, 0x0
blt- _error
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# DirectPrint Printf & Store Cache #
# Purpose: Draw on Screen #
# r3 = X coordinate (starts far left) #
# r4 = Y coordinate (starts at very top) #
# r5 = 0 No Wrap; 1 Wrap #
# r6 = Address Pointer to String that will be Drawn on Screen #
# r7 thru r10 printf format args #
# f1 thru f13 printf float format args #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
li r3, 0x30
li r4, 0xDA
li r5, 0x1
addi r6, r31, -0x12 #Make r6 have 0x80001500, beginning of entire formatted string
lis r14, 0x8002 #For nw4r macro
call_nw4r nw4r_db_DirectPrint_Printf
call_nw4r nw4r_db_DirectPrint_StoreCache
#~~~~~~~~~~~~~~~~~~~~~#
# End Register Safety #
#~~~~~~~~~~~~~~~~~~~~~#
_error:
pop_stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# dont_execute label; Default Instruction #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
dont_execute:
default_instruction
#
#~~~~~~~~~~~~~~#
# END ASSEMBLY #
#~~~~~~~~~~~~~~#
==========
3rd ASM:
lwz r0, 0x8C (r29) #Default Instruction, r0 holds current Player/CPU's Held Item
mulli r12, r27, 0x4 #Multiple Player Slot value in r27 by 0x4, put result in r12
addis r12, r12, 0x8150 #Add 0x8150 to upper 16 bits of r12. The player slot will increment/separate the address by 0x4 depending on slot value
stw r0, 0x0 (r12) #Store current Player/CPU's Held Item value to address of r12
lis r11, 0x8151 #Set 1st Half Address for Race-Status Word Check
stw r29, 0x0 (r11) #We need anything not zero at 0x81510000, store 29 to that spot
Code creator: Vega
Code credits: Star & RiiDefi (Draw Text to Screen Code); Bully (Item Spy ASM)