Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 646
» Latest member: Luca1337
» Forum threads: 1,814
» Forum posts: 14,000

Full Statistics

Online Users
There are currently 100 online users.
» 0 Member(s) | 95 Guest(s)
Applebot, Bing, Facebook, Google, Twitter

Latest Threads
Top 10 Most Influential C...
Forum: Coding & Hacking General Discussion
Last Post: Vega
26 minutes ago
» Replies: 2
» Views: 7,333
Show Ice Cube on Online P...
Forum: Online Non-Item
Last Post: _Ro
7 hours ago
» Replies: 0
» Views: 24
CPU Control Cycler [Ro]
Forum: Offline Non-Item
Last Post: _Ro
7 hours ago
» Replies: 7
» Views: 992
Thunder Cloud Effect Modi...
Forum: Offline; Item
Last Post: JerryHatrick
Yesterday, 11:13 PM
» Replies: 11
» Views: 1,078
MKW Coder/Developer of th...
Forum: Coding & Hacking General Discussion
Last Post: Vega
Yesterday, 09:10 PM
» Replies: 10
» Views: 13,823
Make it to 10,000
Forum: General Discussion
Last Post: Vega
Yesterday, 08:15 PM
» Replies: 7,338
» Views: 5,670,076
Miniturbos and Inside Dri...
Forum: Coding & Hacking General Discussion
Last Post: JerryHatrick
Yesterday, 09:54 AM
» Replies: 1
» Views: 857
Code request???
Forum: Code Support / Help / Requests
Last Post: DrTap
01-09-2025, 06:06 PM
» Replies: 3
» Views: 4,953
CPUs/Online Players Have ...
Forum: Visual & Sound Effects
Last Post: Zeraora
01-09-2025, 02:26 AM
» Replies: 2
» Views: 501
Offline Hide and Seek
Forum: Code Support / Help / Requests
Last Post: FelX
01-08-2025, 03:43 PM
» Replies: 11
» Views: 743

 
  V-Report [Vega]; needs more testing and improvements
Posted by: Vega - 10-03-2021, 12:56 PM - Forum: Code Support / Help / Requests - Replies (2)

V-Report v0.1 [Vega]

So I threw this code into the Code Help/Support sub-forum because I'm too lazy to finish testing (lol). And this code is very un-optimized with some issues I'll explain later.

This is meant to replace any exception handlers you have. The code will create a report.txt file in your /shared2 directory of your NAND giving many details of your exception. If the crash is a DSI, ISI, Alignment, or Program exception, V-Report will attempt to generate a report on it.

It's designed to work for all Wii games. Thus, it's region free ofc, just slap the code on any game and you're good to go.

NOTE: This code easily exceeds the typical GCT limit, you need to add this code via main.dol patching of some sorts (i.e. Wiimm's wstrt or Joshua's GeckoLoader)

Video demo :



What's included in the report:

  • Address that CPU crashed on (also known as srr0)
  • Instruction at said Address
  • Type of Exception that occurred
  • Stack Trace
  • Callstack
  • GPRs
  • FPRs (stored as double precision via stfd)
  • Misc Registers (srr1, DAR, DSISR, LR, CTR, CR, XER, FPSCR, HID0, HID2, HID4, L2CR)

Equip this code with your other codes. Once a crash occurs and V-Report was successful generating a report, your screen will turn green, hard reboot your Wii, use some HBC app to view the /shared2/report.txt. If the screen is yellow, V-Report failed. Please note that the screen colors won't work on Dolphin, this is an issue with Dolphin, not the code. So as of right now, this code is only meant for real hardware use. It will still work on Dolphin, but your emulation will just freeze up and be glitchy, just stuck there until you shut it off.

---

Technical details/issues (noobs may not understand some of this)
First thing's first, some of the comments/notes on the sources may not be accurate, just an fyi, as I was constantly making small new changes along the way. V-Report functino pointer is saved into sprg3 (never used by any Wii game), and all the report data is stored in exception areas that are not hit by the string writes, in the gecko code handler itself (safe to do since we already crashed), and the unused Thermal interrupt.

V-Report can only fail in two main areas. The first is not being able to find the game's sprintf function. The second is some error return when fiddling with the IPC registers via my Universal IOS code.

The reason why I don't end the code off with something such as a OSFatal message, is because on some of my tests on diff Wii games, the game crashes on OSFatal! No idea why this is. Also tried some tests with OSReturnToMenu on certain tests, that would crash as well and that function literally takes zero args, you just call it.

A solution to all of this could be to write some code to setup the VI interface manually and eliminate all visual graphics and just have the console up and output printf messages on the TV screen, but that would NOT be a fun task.

Tests done so far:
DSI on PAL MKWii on real hardware
DSI on PAL MKWii on Dolphin
DSI on NTSC-U DBZ BT3 on Dolphin
DSI on NTSC-U Brawl on Dolphin

---

Planned improvements to V-Report (if I ever get around to it)
Mute the audio so the crash has no annoying noises (easy to do, just too lazy to work on this code lol)
Do something other than screen colors (custom console printf messages, hard to do)
Add more registers to the report such as all FPRs also being stored as paired singles (easy to do, just too lazy)

---

Without further a do, here's the code and the sources. Everything is licensed under GPLv2. A notice of the license is included in both sources.

Code creator: Vega
Code credits: Segher, Tmbinc, & Bushing (authors of the original ipc.c on WiiBrew)

Code:
06000300 00000024
7C1043A6 7C0802A6
7C1143A6 48000005
7C0902A6 7C1243A6
7C1342A6 7C0903A6
4E800420 00000000
06000400 00000024
7C1043A6 7C0802A6
7C1143A6 48000005
7C0902A6 7C1243A6
7C1342A6 7C0903A6
4E800420 00000000
06000600 00000024
7C1043A6 7C0802A6
7C1143A6 48000005
7C0902A6 7C1243A6
7C1342A6 7C0903A6
4E800420 00000000
06000700 00000024
7C1043A6 7C0802A6
7C1143A6 48000005
7C0902A6 7C1243A6
7C1342A6 7C0903A6
4E800420 00000000
C0000000 00000112
7C0802A6 48000875
7C1042A6 BC001700
7E9142A6 7EB242A6
7EC00026 7EE102A6
7F1A02A6 7F3B02A6
7F5302A6 7F7202A6
7F90FAA6 7FB8E2A6
7FD3FAA6 7FF9FAA6
BE800324 7FC802A6
480001F9 9421FF60
7C0802A6 900100A4
BF61008C 7C7B1B78
40860024 D8210028
562D5265 706F7274
20627920 56656761
206F6620 4D4B5769
692E636F 6D0A0A41
64647265 73732043
50552063 72617368
6564206F 6E202873
72723029 3A202530
38582049 6E737472
75637469 6F6E2040
20416464 72657373
3A202530 38580A0A
45786365 7074696F
6E205479 70653A20
25303858 0A0A4441
523A2025 30385820
44534953 52202530
38580A0A 53746163
6B205472 6163650A
41646472 65737320
4261636B 63686169
6E204C52 2D536176
65000A25 30385820
25303858 20253038
58000A0A 43616C6C
73746163 6B0A2530
38580A25 3038580A
25303858 0A253038
580A2530 3858000A
0A475052 733A0A72
25316420 25303858
0A722531 64202530
3858000A 72253164
20253038 580A7225
31642025 30385800
0A0A4650 52733A0A
66253164 20253038
58253038 580A6625
31642025 30385825
30385800 0A662531
64202530 38582530
38580A66 25316420
25303858 25303858
000A0A4D 6973633A
0A4C5220 25303858
0A435452 20253038
580A4352 20253038
580A7372 72312025
3038580A 58455220
25303858 000A4650
53435220 25303858
0A484944 30202530
38580A48 49443220
25303858 0A484944
34202530 38580A4C
32435220 25303858
002F7368 61726564
322F7265 706F7274
2E747874 00000000
7FE802A6 387F0220
64638000 7C7A03A6
7C7B02A6 5463045E
60632000 54630566
5463062C 7C7B03A6
4C000064 3FA08000
67FF8000 D83D1800
D83D1808 D85D1810
D87D1818 D89D1820
D8BD1828 D8DD1830
D8FD1838 D91D1840
D93D1848 D95D1850
D97D1858 D99D1860
D9BD1868 D9DD1870
D9FD1878 DA1D1880
DA3D1888 DA5D1890
DA7D1898 DA9D18A0
DABD18A8 DADD18B0
DAFD18B8 DB1D18C0
DB3D18C8 DB5D18D0
DB7D18D8 DB9D18E0
DBBD18E8 DBDD18F0
DBFD18F8 FC00048E
D801FFF8 8001FFFC
901D1900 63A50424
7C2A0B78 3C800001
38000005 7C0903A6
816A0000 818B0000
7C6B6050 7C032040
91450000 91650004
800A0004 90050008
38A5000C 4181000C
7D6A5B78 4200FFD4
63A30620 3A94FFFC
96830004 63A4042C
38000004 7C0903A6
84A4000C 2C050000
41820008 38A5FFFC
94A30004 4200FFEC
7DFFE4AA 3C00005F
6000F3FF 7C0903A6
63A33000 7CA3E4AA
7C057800 40820034
7C068000 4082002C
7C078800 40820024
7C089000 4082001C
7C099800 40820014
7C0AA000 4082000C
7C0BA800 41820010
38630004 4200FFC0
480002CC 7C6E1B78
38610040 54630034
7C7C1B78 389F001C
80BD0334 80C50000
57C7002E 811D033C
813D0340 7DC903A6
4E800421 7C7B1B78
63AF0420 3A000005
7C7BE214 389F00CE
84AF0004 84CF0004
84EF0004 7DC903A6
4E800421 2C030000
4180026C 7F7B1A14
3610FFFF 4082FFD4
7C7BE214 389F00DE
80BD0624 80DD0628
80FD062C 811D0630
813D0634 7DC903A6
4E800421 2C030000
41800234 7F7B1A14
7C7BE214 389F0103
38A00000 80DD1700
38E00001 811D1704
7DC903A6 4E800421
2C030000 41800208
7F7B1A14 63AF1704
3A00000F 3A200002
3A400003 7C7BE214
389F011F 7E258B78
84CF0004 7E479378
850F0004 7DC903A6
4E800421 2C030000
418001CC 7F7B1A14
3A310002 3A520002
3610FFFF 4082FFC8
7C7BE214 389F0134
38A00000 80DD1800
80FD1804 39000001
813D1808 815D180C
7DC903A6 4E800421
2C030000 41800188
7F7B1A14 63AF180C
3A00000F 3A200002
3A400003 7C7BE214
389F0158 7E258B78
84CF0004 84EF0004
7E489378 852F0004
854F0004 7DC903A6
4E800421 2C030000
41800144 7F7B1A14
3A310002 3A520002
3610FFFF 4082FFC0
7C7BE214 389F0175
80BD0324 80DD0328
80FD032C 811D0338
813D0330 7DC903A6
4E800421 2C030000
41800104 7F7B1A14
7C7BE214 389F01A9
80BD1900 80DD0344
80FD0348 811D034C
813D0350 7DC903A6
4E800421 2C030000
418000D4 7F7B1A14
38000013 7C0903A6
38000000 63A3207C
94030004 4200FFFC
387F01D9 63A42082
38000005 7C0903A6
84030004 94040004
4200FFF8 38000003
981D20C6 981D20C7
981D20C8 38600006
63A42020 38A00002
38C00009 63A72080
3900004C 4800008D
2C030000 41800068
38600001 63A42020
38BF01DD 38C00002
48000071 2C030000
4180004C 7C7A1B78
7C651B78 38600004
63A42020 7F86E378
7F67DB78 4800004D
2C030000 41800028
38600002 63A42020
7F45D378 48000035
2C030000 41800010
3C60CD80 3C000000
4800000C 3C60CD80
3C0000FF 6000FF01
90030024 7C0004AC
60000000 4BFFFFF8
9421FFF0 7C0802A6
90010014 BFC10008
7C7F1B78 7C9E2378
2C1F0001 41820034
2C1F0002 4182005C
2C1F0006 4182005C
7CC33378 7CE43B78
48000081 90BE0008
54C0007E 901E000C
90FE0010 480000B8
3865FFFF 38800000
38840001 8C030001
2C000000 4082FFF4
7CA32B78 4800004D
54A0007E 901E000C
90DE0010 48000088
90BE0008 48000080
7CE33B78 7D044378
48000029 90BE0008
90DE000C 54E0007E
901E0010 911E0014
5520007E 901E0018
915E001C 48000050
546B06FE 7C845A14
3884001F 5480D97E
7C0903A6 7C0018AC
38630020 4200FFF8
44000002 4E800020
546B06FE 7C845A14
3884001F 5480D97E
7C0903A6 7C001BAC
38630020 4200FFF8
4E800020 93FE0000
7FC3F378 38800020
4BFFFFA9 3CC0CD00
57C0007E 90060000
80060004 54000036
60000001 90060004
80060004 70000022
2C000022 40A2FFF4
80060004 54000036
60000002 90060004
3CA04000 90A60030
80060004 70000014
2C000014 40A2FFF4
80860008 2C040000
3860FFFB 41820038
3C648000 38800020
4BFFFF61 80060004
54000036 60000004
90060004 90A60030
80060004 54000036
60000008 90060004
807E0004 BBC10008
80010014 7C0803A6
38210010 4E800020
7D6802A6 556B007E
7D7343A6 7C0803A6
4E800020 00000000

First Source (06 string writes)
Code:
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License 2.0 for more details.

#First Source (backup some things, call V-Report)

#START ASSEMBLY

#Write at all following addresses via 06 Gecko String Writes
#0x80000300; for DSI
#0x80000400; for ISI
#0x80000600; for Alignment
#0x80000700; for Program

#Backup r0
mtsprg0 r0

#Backup LR
mflr r0
mtsprg1 r0

#Do BL Trick to get Program Counter so V-Report can figure out what kind of exception occurred
bl getpc
getpc:

#Backup CTR
mfctr r0
mtsprg2 r0

#Get pointer to V-Report function; it's in sprg3
mfsprg3 r0

#Call V-Report!; pointer is already physical, good to go
mtctr r0
bctr

#END ASSEMBLY

Second Source (C0 code)
Code:
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License 2.0 for more details.

#============================

#Second Source (V-Report)

#START ASSEMBLY

#Put the entire code into one gigantic Brach-link table. We do this so the code doesn't have to reside in the unused EVA space via an 06 string write. Also the contents of a 06 string write are copy-pasted from the GCT to the designated hook address every frame. This will bog down on CPU preformance since the transfer of the 06-string write data occurs every frame.

#A better approach is to have our code within a C0 code but the C0 code will simply consist of storinig teh pointer to the codes contents at a spot in the EVA. This greatly helsp on CPU preofrmance and this mthod only tkes up one word of unused EVA space.

#First thing's first, backup C0 LR
mflr r0

#Create gignatic BL Trick
bl the_entire_code

########################################################

#The code itself

#Note
#r0 treated as literal 0; nice to use for physical work

#Variables
.set EVA_GPR, 0x1700 #Where GPRs are stored at
.set EVA_FPR, 0x1800 #Where FPRs are stored at
.set EVA_MISC, 0x324 #Where Misc registers are stored at
.set EVA_STACK_TRACE, 0x424 #Where the 5 rows Stack Trace contents are stored at
.set EVA_CALLSTACK, 0x624 #5 words of the call stack
#.set EVA_LR, EVA_MISC+0 #Not needed, just listed here for reference
.set EVA_CTR, EVA_MISC+4
.set EVA_CR, EVA_MISC+8
.set EVA_XER, EVA_MISC+12
.set EVA_srr0, EVA_MISC+16
.set EVA_srr1, EVA_MISC+20
.set EVA_DAR, EVA_MISC+24
.set EVA_DSISR, EVA_MISC+28
.set EVA_HID0, EVA_MISC+32
.set EVA_HID2, EVA_MISC+36
.set EVA_HID4, EVA_MISC+40
.set EVA_L2CR, EVA_MISC+44
.set EVA_FPSCR, EVA_FPR+256
.set HID0, 1008
.set HID2, 920
.set HID4, 1011
.set L2CR, 1017
.set DSISR, 12
.set DAR, 19

#Recover original r0
mfsprg0 r0

#Store every gpr starting to the unused thermal interrupt
stmw r0, EVA_GPR (r0)

#We cant store any FPRs in physical mode because...
#It will cause an FP unavailable exception due to MSR being set to 0x00001000 when the exception occured.

#Store misc other registers to the portion of the DSI vector that the 06 writes aren't using
#There are a crap ton more registers but honestly they having and will have nothing to do with execptions
mfsprg1 r20 #original LR
mfsprg2 r21 #original CTR
mfcr r22
mfxer r23
mfspr r24, srr0 #Address CPU crashed on
mfspr r25, srr1 #MSR value when crash occurred
mfspr r26, DAR
mfspr r27, DSISR
mfspr r28, HID0
mfspr r29, HID2
mfspr r30, HID4
mfspr r31, L2CR
stmw r20, EVA_MISC (r0)

#LR contains the exception type, place it in r30 since we need to use the Link Register now
mflr r30

#Make table
bl table
table_start:

#Search parameters for sprintf
sprintf_search_words:
.long 0x9421FF60      
.long 0x7C0802A6
.long 0x900100A4
.long 0xBF61008C
.long 0x7C7B1B78
.long 0x40860024
.long 0xD8210028

title:
.string "V-Report by Vega of MKWii.com\n\nAddress CPU crashed on (srr0): %08X\ Instruction @ Address: %08X\n\nException Type: %08X\n\nDAR: %08X DSISR %08X\n\nStack Trace\nAddress Backchain LR-Save"

stack_trace_row_string:
.string "\n%08X %08X %08X"

call_stack_start_string:
.string "\n\nCallstack\n%08X\n%08X\n%08X\n%08X\n%08X"

gpr_start_string:
.string "\n\nGPRs:\nr%1d %08X\nr%1d %08X"

gpr_string:
.string "\nr%1d %08X\nr%1d %08X"

fpr_start_string:
.string "\n\nFPRs:\nf%1d %08X%08X\nf%1d %08X%08X"

fpr_string:
.string "\nf%1d %08X%08X\nf%1d %08X%08X"

misc_start_string:
.string "\n\nMisc:\nLR %08X\nCTR %08X\nCR %08X\nsrr1 %08X\nXER %08X"

misc_final_string:
.string "\nFPSCR %08X\nHID0 %08X\nHID2 %08X\nHID4 %08X\nL2CR %08X"

file_path:
.string "/shared2/report.txt"

.align 2
table:
mflr r31 #Need to backup pointer to table for function calls

#Place start of virtual mode in r3

virtual_offset = end_physical - table_start
addi r3, r31, virtual_offset

#Make it virtual
oris r3, r3, 0x8000

#Place virtual address to jump to in srr0
mtspr srr0, r3

#We need to do some edits on the MSR (srr1). We need the following bits with the following settings..
#Remember you cannot edit the actual MSR register during an interrupt
#Bit 16 (EE aka External Interrupts) must be low
#Bit 18 (FP aka Floating Point Avialable) must be high
#Bit 20 (FE0 aka IEEE floating point exception mode 0) must be low
#Bit 23 (FE1 aka IEEE floating point exceptino mode 1) must be low
mfspr r3, srr1
rlwinm r3, r3, 0, 17, 15
ori r3, r3, 0x2000
rlwinm r3, r3, 0, 21, 19
rlwinm r3, r3, 0, 24, 22
mtspr srr1, r3

#Now finally ready to go to virtual mode!
rfi

#=======================

#Register notes
#r31 = Pointer to table (virtual)
#r30 = Exception Type
#r29 = 0x80000000
#r28 = Pointer to very start of 1st string
#r27 = Return Values of both sprintf calls added together
#r26 = fd
#r25 = 0x935E0000
#r18 = value for %1d
#r17 = secondary value for %1d
#r16 = loop tracker for sprintf loop writes
#r15 = temp addresses for the sprintfs
#r15 thru r22 = Search strings for sprinf/OShotreset; this is done before and after the group of sprintfs
#r14 = sprintf function address

#VIRTUAL MODE!
end_physical:

#Set r29, as 0x8000
lis r29, 0x8000

#Make r31 virtual
oris r31, r31, 0x8000

#Backup floats and fpscr to the System Management interrupt, high chance this is unused, but it doesn't matter regardless, lul
stfd f1, EVA_FPR (r29)
stfd f1, EVA_FPR+8 (r29)
stfd f2, EVA_FPR+16 (r29)
stfd f3, EVA_FPR+24 (r29)
stfd f4, EVA_FPR+32 (r29)
stfd f5, EVA_FPR+40 (r29)
stfd f6, EVA_FPR+48 (r29)
stfd f7, EVA_FPR+56 (r29)
stfd f8, EVA_FPR+64 (r29)
stfd f9, EVA_FPR+72 (r29)
stfd f10, EVA_FPR+80 (r29)
stfd f11, EVA_FPR+88 (r29)
stfd f12, EVA_FPR+96 (r29)
stfd f13, EVA_FPR+104 (r29)
stfd f14, EVA_FPR+112 (r29)
stfd f15, EVA_FPR+120 (r29)
stfd f16, EVA_FPR+128 (r29)
stfd f17, EVA_FPR+136 (r29)
stfd f18, EVA_FPR+144 (r29)
stfd f19, EVA_FPR+152 (r29)
stfd f20, EVA_FPR+160 (r29)
stfd f21, EVA_FPR+168 (r29)
stfd f22, EVA_FPR+176 (r29)
stfd f23, EVA_FPR+184 (r29)
stfd f24, EVA_FPR+192 (r29)
stfd f25, EVA_FPR+200 (r29)
stfd f26, EVA_FPR+208 (r29)
stfd f27, EVA_FPR+216 (r29)
stfd f28, EVA_FPR+224 (r29)
stfd f29, EVA_FPR+232 (r29)
stfd f30, EVA_FPR+240 (r29)
stfd f31, EVA_FPR+248 (r29)
mffs f0
stfd f0, -0x8 (sp)
lwz r0, -0x4 (sp)
stw r0, EVA_FPSCR (r29) #EVA_FPR+256

#========================

#Store Stack Trace (not this isnt the Call Stack)
#Address; Backchain; LR Save
#Store EVA Pointer to store at the space intended for Stack Trace contents (5 rows max output)
ori r5, r29, EVA_STACK_TRACE

#Make a copy of the sp for initial 'Address' value in Stack Trace output
mr 10, sp

#Stack sizes are never this large, this is our upper bound size limit check
lis r4, 0x0001

#Set max loop of 5
li r0, 5
mtctr r0

#Call stack search loop
trace_loop:
lwz r11, 0 (r10)
lwz r12, 0 (r11)
sub r3, r12, r11

#Check for upper bound on stack size limit
cmplw r3, r4

#Stack is valid, add on new stack trace row below
stw r10, 0 (r5) #Address
stw r11, 0x4 (r5) #Backchain
lwz r0, 0x4 (r10) #Load LR Save
stw r0, 0x8 (r5) #Store LR Save

#Increment r5 to point to next stack trace row
addi r5, r5, 0xC

#Do branch now based on cmpwi results
bgt- stack_trace_complete #If branching on this, that means we stored the last addr

#Follow further into the stack trace
mr r10, r11
bdnz+ trace_loop

stack_trace_complete:

#=====================

#Store Callstack (5 max)
#Callstack format...(just like Dolphin)
#addr = ... fyi the 1st addr is just LR-4.
#addr = ... fyi this is just the stack trace's 2nd LR-Save - 4
#addr = ... stack trace's 3rd LR-Save - 4
ori r3, r29, EVA_CALLSTACK-4

#Get top of call stack (OG Link Register - 4)
addi r20, r20, -4 #OG LR still residing in r20
stwu r20, 0x4 (r3)

#Loop to load 2nd thru 5th LR-Save of Stack trace, minus 4 on it, then store
ori r4, r29, EVA_STACK_TRACE+8

#Loop of 4
li r0, 4
mtctr r0

callstack_loop:
lwzu r5, 0xC (r4)
cmpwi r5, 0 #If an LR-save was null, call stack addr was null ofc
beq- no_minus_four
subi r5, r5, 4
no_minus_four:
stwu r5, 0x4 (r3)
bdnz+ callstack_loop

#==============================

#Attempt to find the game's sprintf function
lswi r15, r31, 28 #Load the sprintf search string into r5 thru r11, thank you lswi

#5FF3FF words from 0x80003000 to 0x817FFFFC
lis r0, 0x5F
ori r0, r0, 0xF3FF
mtctr r0
ori r3, r29, 0x3000

find_sprintf:
lswi r5, r3, 28
cmpw r5, r15
bne- decrement_sprintf_search
cmpw r6, r16
bne- decrement_sprintf_search
cmpw r7, r17
bne- decrement_sprintf_search
cmpw r8, r18
bne- decrement_sprintf_search
cmpw r9, r19
bne- decrement_sprintf_search
cmpw r10, r20
bne- decrement_sprintf_search
cmpw r11, r21
beq- found_sprintf
decrement_sprintf_search:
addi r3, r3, 4
bdnz+ find_sprintf
b HUGE_ERROR

#Found it! store in r14
found_sprintf:
mr r14, r3

#Call sprintf for 1st string
#r3 = arg to dump shit to
#r4 = pointer to string that needs formatting
#r5+ = args
title_string_offset = title - table_start
#We need to make sure r3 will end up being 0x20 (32) byte aligned, later for ISFS_Write

#Increment sp by 0x40 then clear last 5 bits, so we have a 32-byte aligned r3 arg
addi r3, sp, 0x40
clrrwi r3, r3, 5

we_are_aligned:
mr r28, r3 #Backup for the write buffer input on ISFS_Write
addi r4, r31, title_string_offset #Points to start of string in the table
lwz r5, EVA_srr0 (r29) #Load srr0's original value (address CPU crashed on)
lwz r6, 0 (r5) #Load srr0's address's instruction
clrrwi r7, r30, 8 #Clear out last byte, r7 will ontain 0x300, 0x400, 0x600, or 0x700
lwz r8, EVA_DAR (r29) #Load DAR's value
lwz r9, EVA_DSISR (r29) #Load DSISR's value
mtctr r14
bctrl

#Backup value of bytes written into r27, ISFS Write will need it later
mr r27, r3

#====================

#Sprintf loop for the 5 stack trace rows

#Setup loop first laod address
ori r15, r29, EVA_STACK_TRACE-4

#Set loop amount; need to use a GVR due to function call within loop
li r16, 5

#Set macro to get the sprintf string offset in our table
stack_trace_string_offset = stack_trace_row_string - table_start

stack_trace_sprintf_loop:
add r3, r27, r28 #Add return value to r27 to keep movign the sprintf dump location properly further down in memory
addi r4, r31, stack_trace_string_offset
lwzu r5, 0x4 (r15)
lwzu r6, 0x4 (r15)
lwzu r7, 0x4 (r15)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3
subic. r16, r16, 1
bne+ stack_trace_sprintf_loop

#==================

#sprintf for call_stack_start_string
call_stack_string_offset = call_stack_start_string - table_start
add r3, r27, r28 #Update r3 to move further down in memory to keep dumping
addi r4, r31, call_stack_string_offset
lwz r5, EVA_CALLSTACK (r29)
lwz r6, EVA_CALLSTACK+4 (r29)
lwz r7, EVA_CALLSTACK+8 (r29)
lwz r8, EVA_CALLSTACK+12 (r29)
lwz r9, EVA_CALLSTACK+16 (r29)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3

#==================

#1st GPR sprintf (its 'title' aka gpr_start_string)
gpr_title_string_offset = gpr_start_string - table_start
add r3, r27, r28 #Keep updating dump spot
addi r4, r31, gpr_title_string_offset
li r5, 0
lwz r6, EVA_GPR (r29)
li r7, 1
lwz r8, EVA_GPR+4 (r29)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3

#===================

#Sprintf loop for the rest of the GPRs

#Set Loop first load address
ori r15, r29, EVA_GPR+4

#Set loop amount
li r16, 15 #30 gprs left, can only do 2 at a time

#Set the initial %1d's (starts at 3 and 4, cuz 1 and 2 already done)
li r17, 2
li r18, 3

#macro to set r4
gpr_loop_string_offset = gpr_string - table_start

gpr_sprintf_loop:
add r3, r27, r28 #Keep updating dump spot
addi r4, r31, gpr_loop_string_offset
mr r5, r17
lwzu r6, 0x4 (r15)
mr r7, r18
lwzu r8, 0x4 (r15)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3
#Update the %1d's
addi r17, r17, 2
addi r18, r18, 2
subic. r16, r16, 1
bne+ gpr_sprintf_loop

#====================

#1st FPR sprintf (its 'title' aka fpr_start_string)
fpr_title_string_offset = fpr_start_string - table_start
add r3, r27, r28 #Keep updating dump spot
addi r4, r31, fpr_title_string_offset
li r5, 0
lwz r6, EVA_FPR (r29)
lwz r7, EVA_FPR+4 (r29)
li r8, 1
lwz r9, EVA_FPR+8 (r29)
lwz r10, EVA_FPR+12 (r29)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3

#====================

#sprintf loop for rest of FPRs

#Setup loop first laod address
ori r15, r29, EVA_FPR+12

fpr_loop_string_offset = fpr_string - table_start

#Set loop amount
li r16, 15 #Can only do 2 fprs at a time cuz they are 16 hex digits in length

#Set the initial %1d's (starts at 3 and 4, cuz 1 and 2 already done)
li r17, 2
li r18, 3

fpr_sprintf_loop:
add r3, r27, r28 #Keep updating dump spot
addi r4, r31, fpr_loop_string_offset
mr r5, r17
lwzu r6, 0x4 (r15)
lwzu r7, 0x4 (r15)
mr r8, r18
lwzu r9, 0x4 (r15)
lwzu r10, 0x4 (r15)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3
#Update the %1d's
addi r17, r17, 2
addi r18, r18, 2
subic. r16, r16, 1
bne+ fpr_sprintf_loop

#=======================

#sprint for first 'half' of misc registers
misc_title_string_offset = misc_start_string - table_start
add r3, r27, r28 #Keep updating dump spot
addi r4, r31, misc_title_string_offset
lwz r5, EVA_MISC (r29) #EVA_LR
lwz r6, EVA_CTR (r29)
lwz r7, EVA_CR (r29)
lwz r8, EVA_srr1 (r29)
lwz r9, EVA_XER (r29)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3

#=======================

#final sprintf, the second 'half' of misc registers
misc_final_string_offset = misc_final_string - table_start
add r3, r27, r28 #Keep updating dump spot
addi r4, r31, misc_final_string_offset
lwz r5, EVA_FPSCR (r29)
lwz r6, EVA_HID0 (r29)
lwz r7, EVA_HID2 (r29)
lwz r8, EVA_HID4 (r29)
lwz r9, EVA_L2CR (r29)
mtctr r14
bctrl
cmpwi r3, 0
blt- HUGE_ERROR
#Update total bytes of formatted string for later use of ISFS_Write
add r27, r27, r3

#r27 now contains grant total of byte lenght of entire formatted string!

#========================

#Create report.txt (ios_ioctl using /dev/fs fd)

#IOS_Ioctl createFile structure (size 0x4C)
#0x0 (word) = Owner ID
#0x4 (halfword) = Group ID
#0x6 thru 0x45 = file path/name ; it's last byte must be null
#0x46 = Owner Permissions
#0x47 = Group Permissions
#0x48 = Other Permissions
#0x49 = u8 attributes
#0x4A & 0x4B = ??? (always appears to be null)

#Setup the IOCTL structure
#Transfer file name to it
#set all other value
#80002080 is where the structure is at
#First, null it all out
li r0, 0x13 #0x4C bytes is 0x13 (19) words
mtctr r0

li r0, 0

ori r3, r29, 0x207C

null_loop_ioctl:
stwu r0, 0x4 (r3)
bdnz+ null_loop_ioctl

#Transfer file name
file_path_offset = file_path - table_start
addi r3, r31, file_path_offset-4 #Need minus four for first iternation of loop's lwzu instruction
ori r4, r29, 0x2082 #-4 for stwu

#Lenght of file name/path (includes null byte at end) is exactly 5 words
li r0, 5
mtctr r0

file_name_transfer:
lwzu r0, 0x4 (r3)
stwu r0, 0x4 (r4)
bdnz+ file_name_transfer

#Complete rest of ioctl structure
li r0, 3
stb r0, 0x20C6 (r29)
stb r0, 0x20C7 (r29)
stb r0, 0x20C8 (r29)

#Note: There should be no need to null out the ios_structure. Universal ios places all the values in that structure, any unused values shouldn't have be null before any IPC fiddling, and the second half 0x20 bytes of the structure is completely ignored by IOS. Only putting this note here, just in case I am wrong and in the future ppl encounter bugs in this code, this may be the reason.

#=======================================

#Create the File!
#r3 = universal ios command
#r4 = 32 byte aligned pointer to the ios_structure
#r5 = fd of /dev/fs; always 2
#r6 = ioctl no. ; this is 9
#r7 = pointer to input buffer; must be 32 byte aligned, this is NOT the pointer to the ios_structure
#r8 = size of inpute buffer; 0x4C
li r3, 6 #ioctl command for universal ios
ori r4, r29, 0x2020
li r5, 2 #fd for /dev/fs, it's the same for every wii game
li r6, 9
ori r7, r29, 0x2080
li r8, 0x4C
bl universal_ios_function
cmpwi r3, 0
blt- HUGE_ERROR

#Open report.txt
#r3 = universal ios command
#r4 = 32 byte aligned pointer to the ios_structure
#r5 = pointer to file path
#r6 = permissions
li r3, 1
ori r4, r29, 0x2020
addi r5, r31, file_path_offset
li r6, 2
bl universal_ios_function
cmpwi r3, 0
blt- HUGE_ERROR

#Write to report.txt
#r3 = universal ios command
#r4 = 32 byte aligned pointer to the ios_structure
#r5 = fd
#r6 = pointer to stuff that will be written; must be 32-byte aligned
#r7 = amount of bytes to write
mr r26, r3 #Backup the returned fd for ISFS_Close afterwards
mr r5, r3 #fd needs to be in r5 for universal ios
li r3, 4 #ios_write for universal ios
ori r4, r29, 0x2020
mr r6, r28 #Backed up from earlier for sprintf r3 arg
mr r7, r27 #Backed up from earlier; return values added together from both sprintf calls
bl universal_ios_function
cmpwi r3, 0
blt- HUGE_ERROR

#Close report.txt
#r3 = universal ios command
#r4 = 32 byte aligned pointer to the ios_structure
#r5 = fd
li r3, 2 #ios_close for universal ios
ori r4, r29, 0x2020 #pointer to ios_structure; 32-byte aligned
mr r5, r26 #fd
bl universal_ios_function
cmpwi r3, 0
blt- HUGE_ERROR

#============================

#THE END!!!!
#We were sucessful, make the screen green
#Set green color (0,0)
lis r3, 0xCD80
lis r0, 0x0000 #li r0, 0 will work too, fyi
b update_vi

#Couldn't find sprintf or an ios error occurred, set screen to yellow
HUGE_ERROR:
lis r3, 0xCD80
lis r0, 0x00FF

update_vi:
ori r0, r0, 0xFF01 #Full brightness and flip enable bit high
stw r0, 0x0024 (r3)

loop_forever:
sync
nop
b loop_forever


#===========================

#Universal IOS; slightly modified, certain things not needed were commented out

#Start Assembly

#Prologue
universal_ios_function:
stwu sp, -0x0010 (sp)
mflr r0
stw r0, 0x0014 (sp)
stmw r30, 0x8 (sp)

#Disable External Interrupts; NOT NEEDED, interrupts already been disabled
#mfmsr r0
#rlwinm r11, r0, 0, 17, 15 #Flip off 'Allow interrupts' bit
#mtmsr r11 #Update MSR
#rlwinm r12, r0, 17, 31, 31 #Backup modified MSR state

#Backup 1st two Args
mr r31, r3
mr r30, r4

#r5 thru r8 remain untouched before final subroutine involving IPC, no need to back up them
#r9 and r10 remain untouched the entire time, no need to back them up

#Determine what IOS command is being utilized
cmpwi r31, 1
beq- universal_open
cmpwi r31, 2
beq- universal_close
#cmpwi r31, 5 #NOT NEEDED
#beq- universal_seek
cmpwi r31, 6
beq- universal_ioctl
#cmpwi r31, 7 #NOT NEEDED
#beq- universal_ioctlv

#Read/Write is being used; Note, only write is being used
#universal_readwrite: #the check below for read vs write not needed
#r5 = fd
#r6 = Input/Output Buffer
#r7 = Size

#Check if read (invalidate) or write (flush), adjust cache accordingly for IOS's 2nd arg
mr r3, r6 #still need these two instructions for the r3 and r4 arg setup for the flush
mr r4, r7
#cmpwi r31, 3 #Checks not needed!
#beq- its_read

#IOS_Write is being used, flush the input buffer
bl data_cache_flush
#b done_with_cache #With the read stuff being commented, no point having this as it just branches to very next instruction

#IOS_Read is being used, invalidate the output buffer; NOT NEEDED!!!!!!!!!!!!!!!!
#its_read:
#bl data_cache_invalidate

#Store fd, and other args to IOS structure; any mem pointer that is sent will be sent physically
#done_with_cache: #label name NOT needed
stw r5, 0x8 (r30)
clrlwi r0, r6, 1
stw r0, 0xC (r30)
stw r7, 0x10 (r30)

#Prep IOS structure, run IPC
b flush_ios_structure_then_run_ipc

#IOS_Open
universal_open:
#r5 = Pointer
#r6 = Permissions

#Figure out file path byte length
addi r3, r5, -1
li r4, 0 #Use r3 for counter for upcoming subroutine call (has 1 arg)
file_path_counter:
addi r4, r4, 1
lbzu r0, 0x1 (r3)
cmpwi r0, 0
bne+ file_path_counter

#Flush file path; r4 already set
mr r3, r5
bl data_cache_flush

#Store args to IOS structure; any mem pointer that is sent will be sent physically
clrlwi r0, r5, 1
stw r0, 0xC (r30) #No fd to store at 0x8
stw r6, 0x10 (r30)

#Prep IOS structure, run IPC
b flush_ios_structure_then_run_ipc

#IOS_Close
universal_close:
#r5 = fd
#Store fd to IOS structure
stw r5, 0x8 (r30)

#Prep IOS structure, run IPC
b flush_ios_structure_then_run_ipc

#IOS_Seek; NOT NEEDED!!!!!!!!!!!!!!!!!!!!!
#universal_seek:
#r5 = fd
#r6 = Offset from Location Mode
#r7 = Location Mode

#Store fd and other args to IOS structure
#stw r5, 0x8 (r30)
#stw r6, 0xC (r30)
#stw r7, 0x10 (r30)
#b flush_ios_structure_then_run_ipc

#IOS_Ioctl
universal_ioctl:
#r5 = fd
#r6 = ioctl_no
#r7 = inbuf
#r8 = size of inbuf
#r9 = outbuf
#r10 = size of outbuf

#Flush Input Buffer
mr r3, r7
mr r4, r8
bl data_cache_flush

#Invalidate Output Buffer; NOT NEEDED!!!!!!!!!!!! our ioctl for createfile has no output buffer!
#mr r3, r9
#mr r4, r10
#bl data_cache_invalidate

#Store fd and other args to IOS structure; any mem pointer that is sent will be sent physically
stw r5, 0x8 (r30)
stw r6, 0xC (r30)
clrlwi r0, r7, 1
stw r0, 0x10 (r30)
stw r8, 0x14 (r30)
clrlwi r0, r9, 1
stw r0, 0x18 (r30)
stw r10, 0x1C (r30)
b flush_ios_structure_then_run_ipc

#IOS_Ioctlv; NOT NEEDED!!!!!!!!!!!!!!!!!!!!!!!!!!
#universal_ioctlv:
#r5 = fd
#r6 = ioctl_no
#r7 = number of input buffers
#r8 = number of output buffers
#r9 = pointer to Vector table

#Flush entire Vector Table
#mr r3, r9
#add r4, r7, r8 #Input + Output Buffers
#bl data_cache_flush

#Store fd and other args to IOS structure; any mem pointer that is sent will be sent physically
#stw r5, 0x8 (r30)
#stw r6, 0xC (r30)
#stw r7, 0x10 (r30)
#stw r8, 0x14 (r30)
#clrlwi r0, r9, 1
#stw r0, 0x18 (r30)
#b flush_ios_structure_then_run_ipc

#Subroutine for data cache flush
data_cache_flush:
rlwinm r11, r3, 0, 27, 31
add r4, r4, r11
addi r4, r4, 31
rlwinm r0, r4, 27, 5, 31
mtctr r0
flush_loop:
dcbf 0, r3
addi r3, r3, 32 #Move on to next cache block (each block is 0x20 in size)
bdnz+ flush_loop
sc #Update HID0
blr

#Subroutine for data cache invalidate
data_cache_invalidate:
rlwinm r11, r3, 0, 27, 31
add r4, r4, r11
addi r4, r4, 31
rlwinm r0, r4, 27, 5, 31
mtctr r0
inval_loop:
dcbi 0, r3
addi r3, r3, 32 #Move on to next cache block (each block is 0x20 in size)
bdnz+ inval_loop
blr

#Flush first 0x20 bytes of IOS structure
flush_ios_structure_then_run_ipc:
stw r31, 0 (r30) #Store IOS command
mr r3, r30
li r4, 0x20
bl data_cache_flush

#Run the IPC Engine

#Set Hollywood IPC/IRQ upper 16 bits
lis r6, 0xCD00 #You think this would be 0xCD80, but this is how Wii games do it.

#Send IOS structure pointer (physical) to IPC_PPCMSG
clrlwi r0, r30, 1
stw r0, 0 (r6)

#Tell IPC_PPCCTRL to execute command; do NOT modify the IY1 and IY2 bits.
lwz r0, 0x4 (r6)
clrrwi r0, r0, 4
ori r0, r0, 0x0001
stw r0, 0x4 (r6)

#Wait for Starlet to acknowledge our command
check_for_acknowledge:
lwz r0, 0x4 (r6)
andi. r0, r0, 0x22 #Check if IY2 and Y2 bits were flipped high by Starlet
cmpwi r0, 0x22
bne- check_for_acknowledge

#Starlet has acknowledged, rewrite Acknowledge bit flipped high to clear it
#Then disable IRQ-30, and now wait for Starlet to execute the command & have pointer (physical IOS structure) avialable in IPC_ARMMSG
lwz r0, 0x4 (r6)
clrrwi r0, r0, 4
ori r0, r0, 0x0002
stw r0, 0x4 (r6)

lis r5, 0x4000 #Keep value in r5 for later secondary use
stw r5, 0x30 (r6)

check_if_executed:
lwz r0, 0x4 (r6)
andi. r0, r0, 0x14
cmpwi r0, 0x14
bne- check_if_executed

#Check if pointer is available in IPC_ARMMSG
lwz r4, 0x8 (r6) #Using r4 due to upcoming addis instruction
cmpwi r4, 0
li r3, -5
beq- restore_interrupts #No pointer, somehow a different IPC call was being done during our work?

#Turn IOS structure pointer back to virtual, then invalidate the first 0x20 bytes
addis r3, r4, 0x8000 #Could also just use mr r4, r30 here, w/e works
li r4, 0x20
bl data_cache_invalidate

#Starlet has executed our command, rewrite Execute bit flipped high to clear it
#Then disable IRQ-30 one more time, is is needed or else next IOS call keep IPC_PPCCTRL at 0x31 forever...
lwz r0, 0x4 (r6)
clrrwi r0, r0, 4
ori r0, r0, 0x0004
stw r0, 0x4 (r6)
stw r5, 0x30 (r6)

#Set IPC_PPCMSG X bits to relaunch
lwz r0, 0x4 (r6)
clrrwi r0, r0, 4
ori r0, r0, 0x0008
stw r0, 0x4 (r6)

#Put return value into r3
lwz r3, 0x4 (r30)

#Restore External Interrupts; NOT NEEDED!!!! leave the branch label destination though
restore_interrupts:
#cmpwi r12, 0
#mfmsr r4
#beq- clear_bit
#ori r0, r4, 0x8000 #Flip on 'Allow Interrupts' bit
#b skip_clear_bit
#clear_bit:
#rlwinm r0, r4, 0, 17, 15
#skip_clear_bit:
#mtmsr r0

#Epilogue; r3 contains return value
epilogue:
lmw r30, 0x8 (sp)
lwz r0, 0x0014 (sp)
mtlr r0
addi sp, sp, 0x0010
blr

#

#########################################

the_entire_code:
mflr r11

#Store physical pointer in sprg3, no standard vector exceptions use this spare register, and afaik there's no reason for any game to use this register in any non-exception use.
clrlwi r11, r11, 1
mtsprg3 r11


#Recover C0 LR
mtlr r0
#blr #end C0

#END EVERYTHING!

Print this item

  [Request] Miis as CPUs in Mission Mode
Posted by: JimmyKazakhstan - 09-30-2021, 01:09 AM - Forum: Code Support / Help / Requests - Replies (2)

Hi! I've been using Mission Mode to record some footage for a video I'm making. I've found it to be a quick and easy way to rid the race of all other CPUs without having to use a large assortment of codes. 

It's possible to load a Mii as the character used in the mission itself, but adding Miis as CPUs causes the game to crash. So I was wondering if this could be fixed with a code.

Could a code be made that allows Miis from the user's console to be loaded as CPUs in Missions?
Perhaps it could allow the user to set the index of the mii from their console they want loaded over certain CPUs, would this be possible to make a code for?

This would help so much!

Print this item

  Items On Minimap [stebler]
Posted by: stebler - 09-26-2021, 03:10 PM - Forum: Visual & Sound Effects - Replies (1)

Items On Minimap [stebler]

Warning: this code gives a tactical advantage and as such using it in worldwides or regionals can get you banned.

Screenshot: [Image: dEapUsn.png]

PAL:
c2858194 00000005
3c60809c 80633618
80830244 80840000
a0840008 80630248
7c641a14 1c6301b4
386301a4 00000000
c27ea450 00000005
3b5b0001 3ca0809c
80a53618 80c50244
80c60000 a0c60008
80a50248 7ca62a14
7f5a2a14 00000000
c27ea6e0 00000023
4e800421 3b400000
3af801a4 3b200000
7ee3bb78 3d808063
618cd798 7d8903a6
4e800421 3c60808d
60633900 90770000
7f03c378 3b9c0001
7f84e378 7ee5bb78
3d808063 618cd278
7d8903a6 4e800421
38610020 92e30000
3cc0808a 60c49477
60c59482 60c69491
38e00000 3d80805c
618c2c60 7d8903a6
4e800421 7ee3bb78
3ca0808a 60a49477
60a5a007 3d808063
618cd9c0 7d8903a6
4e800421 9b570081
9b370082 3cc0808a
60c3f7c0 48000015
000c182c 604c5820
7840848c 689c9000
7c8802a6 7c84d0ae
7ca32214 7ee3bb78
60c4a7c8 3d808063
618ce0f0 7d8903a6
4e800421 3af701b4
3b390001 3c60809c
80633618 1c9a0024
7c632214 80630050
7c191800 4180ff0c
3b5a0001 2c1a000f
4180fefc 00000000
c27eaca8 00000010
4e800421 807f016c
2c030000 4182006c
807f0198 388000a0
988300b8 3c804140
9083004c 90830050
38600001 987f0080
3c60809c 80633618
889f0081 1c840024
7c632214 80830058
88bf0082 7c052000
40800028 38800000
989f0080 8063004c
54a4103a 7c63202e
38830044 7ca464aa
389f019c 7ca465aa
60000000 00000000


NTSC-U:
c2836704 00000005
3c60809c 8063ee20
80830244 80840000
a0840008 80630248
7c641a14 1c6301b4
386301a4 00000000
c27e0ba4 00000005
3b5b0001 3ca0809c
80a5ee20 80c50244
80c60000 a0c60008
80a50248 7ca62a14
7f5a2a14 00000000
c27e0e34 00000023
4e800421 3b400000
3af801a4 3b200000
7ee3bb78 3d808060
618cc378 7d8903a6
4e800421 3c60808c
6063ead0 90770000
7f03c378 3b9c0001
7f84e378 7ee5bb78
3d808060 618cbe58
7d8903a6 4e800421
38610020 92e30000
3cc0808a 60c43d4f
60c53d5a 60c63d69
38e00000 3d80805b
618ca2cc 7d8903a6
4e800421 7ee3bb78
3ca0808a 60a43d4f
60a546df 3d808060
618cc5a0 7d8903a6
4e800421 9b570081
9b370082 3cc0808a
60c38d00 48000015
000c182c 604c5820
7840848c 689c9000
7c8802a6 7c84d0ae
7ca32214 7ee3bb78
60c44e48 3d808060
618cccd0 7d8903a6
4e800421 3af701b4
3b390001 3c60809c
8063ee20 1c9a0024
7c632214 80630050
7c191800 4180ff0c
3b5a0001 2c1a000f
4180fefc 00000000
c27e13fc 00000010
4e800421 807f016c
2c030000 4182006c
807f0198 388000a0
988300b8 3c804140
9083004c 90830050
38600001 987f0080
3c60809c 8063ee20
889f0081 1c840024
7c632214 80830058
88bf0082 7c052000
40800028 38800000
989f0080 8063004c
54a4103a 7c63202e
38830044 7ca464aa
389f019c 7ca465aa
60000000 00000000


NTSC-J:
c2857800 00000005
3c60809c 80632678
80830244 80840000
a0840008 80630248
7c641a14 1c6301b4
386301a4 00000000
c27e9abc 00000005
3b5b0001 3ca0809c
80a52678 80c50244
80c60000 a0c60008
80a50248 7ca62a14
7f5a2a14 00000000
c27e9d4c 00000023
4e800421 3b400000
3af801a4 3b200000
7ee3bb78 3d808063
618cce04 7d8903a6
4e800421 3c60808d
60632a50 90770000
7f03c378 3b9c0001
7f84e378 7ee5bb78
3d808063 618cc8e4
7d8903a6 4e800421
38610020 92e30000
3cc0808a 60c485d7
60c585e2 60c685f1
38e00000 3d80805c
618c25e0 7d8903a6
4e800421 7ee3bb78
3ca0808a 60a485d7
60a59167 3d808063
618cd02c 7d8903a6
4e800421 9b570081
9b370082 3cc0808a
60c3e920 48000015
000c182c 604c5820
7840848c 689c9000
7c8802a6 7c84d0ae
7ca32214 7ee3bb78
60c49928 3d808063
618cd75c 7d8903a6
4e800421 3af701b4
3b390001 3c60809c
80632678 1c9a0024
7c632214 80630050
7c191800 4180ff0c
3b5a0001 2c1a000f
4180fefc 00000000
c27ea314 00000010
4e800421 807f016c
2c030000 4182006c
807f0198 388000a0
988300b8 3c804140
9083004c 90830050
38600001 987f0080
3c60809c 80632678
889f0081 1c840024
7c632214 80830058
88bf0082 7c052000
40800028 38800000
989f0080 8063004c
54a4103a 7c63202e
38830044 7ca464aa
389f019c 7ca465aa
60000000 00000000


NTSC-K:
c2846554 00000005
3c60809b 80631c58
80830244 80840000
a0840008 80630248
7c641a14 1c6301b4
386301a4 00000000
c27d8810 00000005
3b5b0001 3ca0809b
80a51c58 80c50244
80c60000 a0c60008
80a50248 7ca62a14
7f5a2a14 00000000
c27d8aa0 00000023
4e800421 3b400000
3af801a4 3b200000
7ee3bb78 3d808062
618cbab0 7d8903a6
4e800421 3c60808c
60631d98 90770000
7f03c378 3b9c0001
7f84e378 7ee5bb78
3d808062 618cb590
7d8903a6 4e800421
38610020 92e30000
3cc08089 60c478d7
60c578e2 60c678f1
38e00000 3d80805b
618c0cc4 7d8903a6
4e800421 7ee3bb78
3ca08089 60a478d7
60a58467 3d808062
618cbcd8 7d8903a6
4e800421 9b570081
9b370082 3cc08089
60c3dc20 48000015
000c182c 604c5820
7840848c 689c9000
7c8802a6 7c84d0ae
7ca32214 7ee3bb78
60c48c28 3d808062
618cc408 7d8903a6
4e800421 3af701b4
3b390001 3c60809b
80631c58 1c9a0024
7c632214 80630050
7c191800 4180ff0c
3b5a0001 2c1a000f
4180fefc 00000000
c27d9068 00000010
4e800421 807f016c
2c030000 4182006c
807f0198 388000a0
988300b8 3c804140
9083004c 90830050
38600001 987f0080
3c60809b 80631c58
889f0081 1c840024
7c632214 80830058
88bf0082 7c052000
40800028 38800000
989f0080 8063004c
54a4103a 7c63202e
38830044 7ca464aa
389f019c 7ca465aa
60000000 00000000


Source code:

Code:
# inject at 80858194 (PAL)
# inject at 80836704 (NTSC-U)
# inject at 80857800 (NTSC-J)
# inject at 80846554 (NTSC-K)

.set region, ''

.if (region == 'P')
    .set ItemDirector_staticInstance, 0x809c3618
.elseif (region == 'E')
    .set ItemDirector_staticInstance, 0x809bee20
.elseif (region == 'J')
    .set ItemDirector_staticInstance, 0x809c2678
.elseif (region == 'K')
    .set ItemDirector_staticInstance, 0x809b1c58
.else
    .err
.endif


lis r3, ItemDirector_staticInstance@ha
lwz r3, ItemDirector_staticInstance@l (r3)
lwz r4, 0x244 (r3)
lwz r4, 0x0 (r4) # first object of last item type
lhz r4, 0x8 (r4) # global id
lwz r3, 0x248 (r3) # number of objects of last item type
add r3, r4, r3 # maximum number of items

mulli r3, r3, 0x1b4 # one CtrlRace2DMapObject per item
addi r3, r3, 0x1a4 # size of expanded CtrlRace2DMap
Code:
# inject at 807ea450 (PAL)
# inject at 807e0ba4 (NTSC-U)
# inject at 807e9abc (NTSC-J)
# inject at 807d8810 (NTSC-K)

.set region, ''

.if (region == 'P')
    .set ItemDirector_staticInstance, 0x809c3618
.elseif (region == 'E')
    .set ItemDirector_staticInstance, 0x809bee20
.elseif (region == 'J')
    .set ItemDirector_staticInstance, 0x809c2678
.elseif (region == 'K')
    .set ItemDirector_staticInstance, 0x809b1c58
.else
    .err
.endif

addi r26, r27, 1 # original instruction

lis r5, ItemDirector_staticInstance@ha
lwz r5, ItemDirector_staticInstance@l (r5)
lwz r6, 0x244 (r5)
lwz r6, 0x0 (r6) # first object of last item type
lhz r6, 0x8 (r6) # global id
lwz r5, 0x248 (r5) # number of objects of last item type
add r5, r6, r5 # maximum number of items

add r26, r26, r5 # number of children
Code:
# inject at 807ea6e0 (PAL)
# inject at 807e0e34 (NTSC-U)
# inject at 807e9d4c (NTSC-J)
# inject at 807d8aa0 (NTSC-K)

.set region, ''

.if (region == 'P')
    .set ControlLoader_load, 0x805c2c60
    .set UIControl_insertChild, 0x8063d278
    .set LayoutUIControl_ct, 0x8063d798
    .set LayoutUIControl_setPictureSourceLayout, 0x8063d9c0
    .set LayoutUIControl_setPicture, 0x8063e0f0
    .set str_game_image, 0x808a9477
    .set str_map_start_line, 0x808a9482
    .set str_start_line, 0x808a9491
    .set str_item, 0x808aa007
    .set str_race_null, 0x808aa7c8
    .set str_kame_green, 0x808af7c0
    .set CtrlRace2DMapObject_vt, 0x808d3900
    .set ItemDirector_staticInstance, 0x809c3618
.elseif (region == 'E')
    .set ControlLoader_load, 0x805ba2cc
    .set UIControl_insertChild, 0x8060be58
    .set LayoutUIControl_ct, 0x8060c378
    .set LayoutUIControl_setPictureSourceLayout, 0x8060c5a0
    .set LayoutUIControl_setPicture, 0x8060ccd0
    .set str_game_image, 0x808a3d4f
    .set str_map_start_line, 0x808a3d5a
    .set str_start_line, 0x808a3d69
    .set str_item, 0x808a46df
    .set str_race_null, 0x808a4e48
    .set str_kame_green, 0x808a8d00
    .set CtrlRace2DMapObject_vt, 0x808cead0
    .set ItemDirector_staticInstance, 0x809bee20
.elseif (region == 'J')
    .set ControlLoader_load, 0x805c25e0
    .set UIControl_insertChild, 0x8063c8e4
    .set LayoutUIControl_ct, 0x8063ce04
    .set LayoutUIControl_setPictureSourceLayout, 0x8063d02c
    .set LayoutUIControl_setPicture, 0x8063d75c
    .set str_game_image, 0x808a85d7
    .set str_map_start_line, 0x808a85e2
    .set str_start_line, 0x808a85f1
    .set str_item, 0x808a9167
    .set str_race_null, 0x808a9928
    .set str_kame_green, 0x808ae920
    .set CtrlRace2DMapObject_vt, 0x808d2a50
    .set ItemDirector_staticInstance, 0x809c2678
.elseif (region == 'K')
    .set ControlLoader_load, 0x805b0cc4
    .set UIControl_insertChild, 0x8062b590
    .set LayoutUIControl_ct, 0x8062bab0
    .set LayoutUIControl_setPictureSourceLayout, 0x8062bcd8
    .set LayoutUIControl_setPicture, 0x8062c408
    .set str_game_image, 0x808978d7
    .set str_map_start_line, 0x808978e2
    .set str_start_line, 0x808978f1
    .set str_item, 0x80898467
    .set str_race_null, 0x80898c28
    .set str_kame_green, 0x8089dc20
    .set CtrlRace2DMapObject_vt, 0x808c1d98
    .set ItemDirector_staticInstance, 0x809b1c58
.else
    .err
.endif


bctrl # original instruction

li r26, 0 # item type
addi r23, r24, 0x1a4 # current control (CtrlRace2DMapObject)

item_type_loop:
li r25, 0 # object index

object_loop:
mr r3, r23 # current control

lis r12, LayoutUIControl_ct@h
ori r12, r12, LayoutUIControl_ct@l
mtctr r12
bctrl

lis r3, CtrlRace2DMapObject_vt@h
ori r3, r3, CtrlRace2DMapObject_vt@l
stw r3, 0x0 (r23)

mr r3, r24 # this (CtrlRace2DMap)
addi r28, r28, 1
mr r4, r28 # child index
mr r5, r23 # current control

lis r12, UIControl_insertChild@h
ori r12, r12, UIControl_insertChild@l
mtctr r12
bctrl

addi r3, r1, 0x20 # ControlLoader (can be safely reused)
stw r23, 0x0 (r3)

lis r6, str_start_line@h # optimize common upper part
ori r4, r6, str_game_image@l # directory name
ori r5, r6, str_map_start_line@l # control file name
ori r6, r6, str_start_line@l # "section 3" name
li r7, 0x0 # animations

lis r12, ControlLoader_load@h
ori r12, r12, ControlLoader_load@l
mtctr r12
bctrl

mr r3, r23 # current control
lis r5, str_item@h # optimize common upper part
ori r4, r5, str_game_image@l # directory name
ori r5, r5, str_item@l # layout file name

lis r12, LayoutUIControl_setPictureSourceLayout@h
ori r12, r12, LayoutUIControl_setPictureSourceLayout@l
mtctr r12
bctrl

stb r26, 0x81 (r23) # store the item type
stb r25, 0x82 (r23) # store the object index

# get the item picture name
lis r6, str_kame_green@h
ori r3, r6, str_kame_green@l
bl trick
.byte 0x00 # 0x0 -> kame_green
.byte 0x0c # 0x1 -> kame_red
.byte 0x18 # 0x2 -> banana
.byte 0x2c # 0x3 -> kinoko
.byte 0x60 # 0x4 -> star
.byte 0x4c # 0x5 -> kame_wing
.byte 0x58 # 0x6 -> thunder
.byte 0x20 # 0x7 -> dummybox
.byte 0x78 # 0x8 -> kinoko_big
.byte 0x40 # 0x9 -> bomb_hei
.byte 0x84 # 0xa -> gesso
.byte 0x8c # 0xb -> pow
.byte 0x68 # 0xc -> GoldenKinoko
.byte 0x9c # 0xd -> killer
.byte 0x90 # 0xe -> thunder_c
.balign 0x4
trick:
mflr r4
lbzx r4, r4, r26
add r5, r3, r4

mr r3, r23
ori r4, r6, str_race_null@l

lis r12, LayoutUIControl_setPicture@h
ori r12, r12, LayoutUIControl_setPicture@l
mtctr r12
bctrl

addi r23, r23, 0x1b4 # move to the next control

addi r25, r25, 1 # increment the object index
lis r3, ItemDirector_staticInstance@ha
lwz r3, ItemDirector_staticInstance@l (r3)
mulli r4, r26, 0x24
add r3, r3, r4
lwz r3, 0x48 + 0x8 (r3) # maximum number of objects of the current type
cmpw r25, r3
blt object_loop

addi r26, r26, 1 # increment the item type
cmpwi r26, 15
blt item_type_loop
Code:
# inject at 807eaca8 (PAL)
# inject at 807e13fc (NTSC-U)
# inject at 807ea314 (NTSC-J)
# inject at 807d9068 (NTSC-K)

.set region, ''

.if (region == 'P')
    .set ItemDirector_staticInstance, 0x809c3618
.elseif (region == 'E')
    .set ItemDirector_staticInstance, 0x809bee20
.elseif (region == 'J')
    .set ItemDirector_staticInstance, 0x809c2678
.elseif (region == 'K')
    .set ItemDirector_staticInstance, 0x809b1c58
.else
    .err
.endif

bctrl # original instruction

# only proceed if we have a picture source layout
lwz r3, 0x16c (r31)
cmpwi r3, 0x0
beq end

# set the opacity of the pane
lwz r3, 0x198 (r31)
li r4, 0xa0
stb r4, 0xb8 (r3)

# set the size of the pane
lis r4, 0x4140 # 12.0f
stw r4, 0x4c (r3)
stw r4, 0x50 (r3)

# hide the control
li r3, 1
stb r3, 0x80 (r31)

lis r3, ItemDirector_staticInstance@ha
lwz r3, ItemDirector_staticInstance@l (r3)
lbz r4, 0x81 (r31) # item type
mulli r4, r4, 0x24
add r3, r3, r4
lwz r4, 0x48 + 0x10 (r3) # current number of objects of this type

lbz r5, 0x82 (r31) # object index
cmpw r5, r4
bge end

# show the control
li r4, 0
stb r4, 0x80 (r31)

lwz r3, 0x48 + 0x4 (r3) # object array
slwi r4, r5, 2
lwzx r3, r3, r4 # object

# copy the item object position to the control
addi r4, r3, 0x44
lswi r5, r4, 0xc
addi r4, r31, 0x19c
stswi r5, r4, 0xc

end:

Print this item

  Race with Ghost Mii [Diamond]
Posted by: Diamond - 09-18-2021, 04:20 PM - Forum: Time Trials & Battle - No Replies

Allows you to race with the ghost of RKGBuffer[0]'s mii in RaceData

NTSC-U
C25CB450 0000000C
7C7E1B78 3D80809C
816C8F70 2C0B0000
40820040 3D80809C
806CD508 3D80809C
816C8F68 38AB242C
A16B23F0 2C0B524B
40820020 80630098
38630188 38800000
3D80805D 618C9D2C
7D8903A6 4E800421
7FC3F378 80030094
60000000 00000000
04524EFC 41820094

PAL
C25E1230 0000000C
7C7E1B78 3D80809C
816CD730 2C0B0000
40820040 3D80809C
806C1E38 3D80809C
816CD728 38AB242C
A16B23F0 2C0B524B
40820020 80630098
38630188 38800000
3D80805F 618CA610
7D8903A6 4E800421
7FC3F378 80030094
60000000 00000000
04529370 41820094

NTSC-J
C25E0B08 0000000C
7C7E1B78 3D80809C
816CC790 2C0B0000
40820040 3D80809C
806C0E98 3D80809C
816CC788 38AB242C
A16B23F0 2C0B524B
40820020 80630098
38630188 38800000
3D80805F 618C9EEC
7D8903A6 4E800421
7FC3F378 80030094
60000000 00000000
04528CF0 41820094

NTSC-K
C25CF3C8 0000000C
7C7E1B78 3D80809B
816CBD70 2C0B0000
40820040 3D80809B
806C0478 3D80809B
816CBD68 38AB242C
A16B23F0 2C0B524B
40820020 80630098
38630188 38800000
3D80805E 618C8A30
7D8903A6 4E800421
7FC3F378 80030094
60000000 00000000
04517394 41820094

Print this item

  CPU Temperature Shenanigans
Posted by: Vega - 09-15-2021, 05:49 PM - Forum: Code Support / Help / Requests - No Replies

I'll try to keep this somewhat short w/o rambling.

I wanted to make a code to read Broadway's CPU temp
All 3 thermal registers are set to always be null in Broadway (they are on disabled on purpose, specifically stated so in the manual)
Can only read Broadway CPU temp with separate device sending amps to the diode and reading the returned voltage
Broadway Manual makes absolutely zero mention of a Thermal Interrupt routine
But the Thermal Interrupt is present at 0x1700
The Interrupt is unused though from my limited tests
Still somehow the Wii knows to shut itself off when I disable the Fan (via code) and the Wii gets too hot (40ish minutes on MKW TT mode)

So anyway.... on the Gamecube console, all the Thermal Registers are used. Thus we can get the Gekko CPU temp.

I have a GC but no cables!

Anyway here is a snippet of source to read Gekko's temp. It "works" on Dolphin, meaning when I place in fake bit values for the read-only bits, the code responds correctly to values of those read-only bits.

Code 

Code:
#Temperature Read code crap, works on Dolphin when you simulate fake THRM register bit responses on the read-only bits
#Wont work on Wii, intended for GC, not tested on real hardware

#SPR list
#1020 = THRM1
#1021 = THRM2
#1022 = THRM3 (the TAU aka Thermal Assist Unit)

#TAU is currently running, disable it. Clear any previous data.
li r0, 0
mtspr 1022, r0

#We want to use TAU in single mode, disable usage of THRM2
#Clear the V (SPR valid) bit; bit 31
#I might be able to just write null to the register to disable it, but it may cause a program exception due to possibly writing new values to the read-only bits. Play it safe.
mfspr r0, 1021
rlwinm r0, r0, 0, 0, 30
mtspr 1021, r0

#Prepare THRM1
#Enable it (V high)
#Disable Thermal Interrupts (TIE low)
#Set initial threshold of 0x40 degress celisus (bits 2 thru 8)
#Clear TID bit so when TIN is high, we know above threshold, and when TIN is low we below it
mfspr r0, 1020
andis. r0, r0, 0xC000 #Clear everything out but the read-only bits
oris r0, r0, 0x2000 #Bits 2 thru 8 are set to value of 0x40
ori r0, r0, 0x0001 #Flip V (spr valid) bit high
mtspr 1020, r0

#Prepare THRM3
#Enable it (E bit high)
#Don't have any calibration set
#Set timer cycles to max (0x1FFF); the more cycles, the more accurate the reading; bits 18 thru 30 all high
li r0, 0x3FFF

#Start the TAU!
mtspr 1022, r0

#The most you can poll is 5 times, due to temperature readings being in 4*C increments. Poll 5 times for the highest accuracy.
#Set loop to 5
li r0, 5
mtctr r0

#Set initial threshold increment/decrement value (0x20)
li r5, 0x40 #Will be halved before first iteration, hence why we first set it to 0x40

#Temperature Check Loop
loop:

#Read THRM1
mfspr r3, 1020

#Temp is above threshold when following bits are this.. (combo only correct when TID is set to 0)
#TIN = 1
#TIV = 1

#Temp is below threshold when bits are this (only correct when TID is set to 0)
#TIN = 0
#TIV = 1

#Check if TIV is high (valid)
#This tells temperature has crossed the threshold
andis. r0, r3, 0x4000
beq- loop

#Temperature has crossed threshold, figure out if it crossed above or below (check TIN bit)
andis. r0, r3, 0x8000

#Extract the threshold from THRM1 and right align it, divide r5 by 2, adjust current threshold by new amount in r5
rlwinm r4, r3, 9, 25, 31
srwi r5, r5, 1

#Now branch
beq- lower_threshold

#Temperature is above threshold; raise it
add r0, r4, r5
b decrement_loop

#Temperature is below threshold; lower it
lower_threshold:
subf r0, r5, r4 #Equivalent to sub r0, r4, r5

#Place in new threshold value, update THRM1, decrement Loop
decrement_loop:
rlwimi r3, r0, 23, 2, 8 #Shift r0's value (new threshold) to be in bits 2 thru 8; then replace those bits into r3 while leaving all other r3's bits alone
mtspr 1020, r3
bdnz+ loop

#Loop is over, place latest iteration of r4 as the result; is this even accurate, lol?
mr r3, r4


If somebody can use devkitpro to compile a GC-specific dol file for a program that simply printf's the temperature, that would be appreciated.

Print this item

  CPU bot[Dea]
Posted by: Dea00 - 09-15-2021, 09:45 AM - Forum: Offline Non-Item - Replies (19)

CPU bot[Dea]

Works every game mode but offline only.

NTSC-J
C252EEB8 00000003
801E0018 2C000000
40820008 38000001
60000000 00000000
C27258DC 00000003
80630038 2C030000
40820008 38600001
60000000 00000000

NTSC-U
C252A9F0 00000003
801E0018 2C000000
40820008 38000001
60000000 00000000
C2721E40 00000003
80630038 2C030000
40820008 38600001
60000000 00000000

PAL(untested)
C252F538 00000003
801E0018 2C000000
40820008 38000001
60000000 00000000
C2726270 00000003
80630038 2C030000
40820008 38600001
60000000 00000000

NTSC-K(untested)
C251D590 00000003
801E0018 2C000000
40820008 38000001
60000000 00000000
C2714618 00000003
80630038 2C030000
40820008 38600001
60000000 00000000

Reference https://youtu.be/PuNHqc29_u4

Print this item

  How to find the code for size, color, speed, etc.
Posted by: Takamura - 09-02-2021, 01:01 PM - Forum: Code Support / Help / Requests - Replies (4)

I understand that the value is floating point, but changing the floating point value from one end is inefficient, so please let me know if you have any technique.

Print this item

  MKW LAN Mod Guide [w/ USB Loading & Gecko Codes]
Posted by: Yuri Bacon - 08-31-2021, 11:17 AM - Forum: Other - Replies (12)

Ramble-y Preamble: Feel Free to Skip

So, I had a MKW LAN party late last year using DWC emulator, and while it went great, I don't think I'll ever bother to set up (or maintain/keep around) DWC emulator again, since its honestly kind of a pain in the ass, and it doesn't seem to have been maintained in a few years now, so it'll only continue to be more and more of a pain in the ass as time goes on.

So, I wanted to find a better solution that wasn't "Fuck it, I'mma just use Wiimmfi", so I turned my attention back to the MKW LAN mod made by Chadderz and MrBean35000vr. The reasons I hadn't used it then were pretty simple: I couldn't USB Load with it (big deal breaker, this game is like $40 a pop!), I couldn't run any Gecko codes with it (I need my 150cc), and it doesn't work in Dolphin (which is through no fault of the mod as far as I know, its an issue with Dolphin, sadly). Well, I managed to find solutions to both how to USB load it, and how to run Gecko codes alongside the LAN mod, making it much easier to set up a LAN party without nearly as much fuss.

I set to work first to figure out how to get it to USB load. I already knew it couldn't be ISO patched at all, and while its not impossible for BrainSlug module support to be added into a USB loader directly, no one has done it. I've got to use the BrainSlug boot.dol no way around it. Well, it just so happens I lucked, out: You can go into your game settings and simply enable alternate dol and place the BSlug .dol according, and the USB loader will load BrainSlug, and then BrainSlug will load its modules and then the game .dol like a charm. I can't believe I didn't think to do that before, but now I don't have to worry about spending tons to get 6 copies of Mario Kart Wii.

The biggest effort I had to put in was not having Gecko Codes of course. The first thing I tried was turning on Ocarina codes in USB Loader GX, and no dice. Nothing changed. In the same vein as the last problem, I also tried to see if I could get BrainSlug to load GeckoOS or the other way around, and then load into the game, but I just couldn't find any way to do this. Finally, I simply tried to patch the codes into the game's main.dol with wstrt, and again nothing. Nothing changed at all even though no vanilla dol was available! Well, I guess BrainSlug just wacks off extra hooks or something, and there ain't much to change about that.

If I'm getting cheats to run with the LAN Mod, its going to be in BSlug module form. Originally I had no clue how to pull off making a Gecko codehandler module, and in this guide's original form I had instead just figured out how to do basic RAM writes directly to convert basic 00/02/04 codes into stand alone modules. For what it was worth, it did its job fine enough, but it left ASM/C2 codetypes unusable, and still had a lot to be desired tho. Thankfully InvoxiPlayGames dropped me some great info in this thread, and helped me out in Discord DMs, and I was able to make a complete Gecko codehandler module that loads GCTs right from the SD card. Its ended up being really simple (much simplier than coverting codes into modules lol), and it works for any game too. I can't really say I can take credit for it though, IPG basically make the code for me, and while I managed to figure out a good bit of it on my own before that I wouldn't have gotten anywhere without her, so big shout outs to InvoxiPlayGames!

I've left the old code conversion modules I made in the post below, if you happen to be interested for whatever reason.



MKW LAN Mod: Pros & Cons, Requirements

Requirements:
* All Wiis will need to have the homebrew channel installed (and cIOS if you plan to use a USB loader). Check out https://wii.guide/ for a good tutorial on Wii, and https://wiiu.hacks.guide/ on Wii U.
* You'll need at least half as many Wiis as you do players (you can have 1 or 2 players per Wii), 1 TV per Wii, 1 controller per player, and a router to network them all together. If you're at a huge event (tournament, convention, etc) you might want to be mindful of all the wireless talk around and use ethernet if you can, but otherwise Wifi works just fine.

Pros:
+ Simple, easy
+ Doesn't require any extra computers, just Wiis
+ Can be used with a USB loader and Gecko codes, for custom tracks and more

Cons:
- Can't use Dolphin (emulator bug)
- Can't invite remote players, if the whole gang can't be there in person
- Does not support NTSC-K (intentional crash)

If you know your way around Linux, got an extra computer/VPS/Rasberry Pi, and want to suppliment your Wiis with PCs running Dolphin and/or want to invite remote friends to join in, you'd be better off using DWC Emulator (or if you're not good with Linux, saying fuck it and using Wiimmfi).

If you just want simple and easy, and you've got enough Wiis, this is the guide for you.



Tutorial: How to get set up and running

0) Ensure you have a disc copy of MKW, or have a WBFS of the game on your USB and ready to rock for each Wii (U) console you will be using. You can use discs and WBFSs in any mixture, you just need 1 per Wii. Every following step will focus on just one Wii, repeat for each Wii.

1) Download the MKW LAN mod from here: http://www.chadsoft.co.uk/downloads/LAN_MKW_v0.9.zip

2) Copy the contents of the release folder to the root of your SD card.

2.1) If you are USB Loading, you will need to make a copy of the boot.dol file in the /apps/brainslug folder and move/rename to the appropriate location to use it as an alternate dol. For USB Loader GX, you should rename boot.dol to RMCE01.dol (for NTSC-U, use RMCP01 for PAL, and RMCJ01 for NTSC-J) and put it on the root of your USB or SD card.

3) If you want to use Gecko Codes (ex: Force 150cc in Friend Rooms), download the attached files on this post for a zip folder containing a Gecko codehandler BrainSlug module, and copy the contents to the root of the SD card (you should have 4 new .mod files in /bslug/modules). Then just make a GCT of all the codes you want to use (https://mkwii.com/gct) and copy it to /codes/RMCE01.gct (RMCP01 for PAL, RMCJ01 for JP). You only need to make the GCT once, you can copy the same GCT for every Wii.

4) Once you have everything copied over, insert your SD card (and USB) into your Wii and turn it on. If you are playing on a disc, you can just launch BrainSlug from the homebrew channel. BrainSlug will now load all your modules and boot the game. This Wii is now ready to go, rinse and repeat this process for all Wiis.

4.1) If you are USB loading, launch your USB loader, and turn "alternate dol" on, then launch the game. You should see BrainSlug appear and start loading modules. It should boot into the game once it is done. This Wii is now ready.

Pro tip: BrainSlug modules are loaded entirely into RAM, so once the game boots you can remove the SD card and reuse it on the next Wii!

5) Now that all the Wiis are ready, if they are all set up on the same network, you should be able to hit 1 or 2 player LAN Multiplayer on all of them, have one of them open a room, and the rest of them can check the friends list and join the host. Thats it! Its time to play!



Misc Notes

Just some useful observations that I honestly don't know where to put.

1) The Gecko codehandler module I made and provided in this post has a GCT limit much lower than you'd normally expect out of other codehandlers. Your GCT can only be about ~230 lines long or 1880 bytes long. Any longer, and you'll get a crash on the strap screen. I'm honestly not entirely sure what the issue is, since I swapped the USB Gecko modules codehandler with JoshuaMKW's full codehandler, which is supposed to do up to 450 codes. Source code is provided with the Gecko codehandler module, so if you think you can extend/increase the modules GCT space before it crashs, feel free to give it a crack.

TL;DR: Keep your GCT under 230 lines of gecko codes. This shouldn't be too hard to do, so long as you stay away from MrBean's item rain code (or other obscenely long codes). That thing is 201 lines alone! Yeesh!

2) Despite being able to use alternate dol in USB Loader GX to load BrainSlug and then load into the WBFS, trying to load into BrainSlug from Riivolution just results in a crash. BrainSlug seems to shake off hooks or something as it boots, which includes ingoring sections of the dol it is booting. Even tho you can inject a GCT directly into MKW's dol file with wstrt, it does nothing after BrainSlug boots it. This is probably due to how BrainSlug modules work, being relocatable ELF files in a similar way to how StaticR.rel works, and Brainslug ends up dropping the dol section with the GCT. Due to the above two factors combined, you won't be able to use an Riivolution mod packs you already have with the LAN mod. InvoxiPlayGames does have a Emvolution module that reads game files off the SD card similar to Riivolution, but it currently requires you complie the module yourself to use your own list of file replacements, so I wouldn't recommend it for casual player. A modded WBFS works better, since a lot of mods out there provide a pre-made WBFS, but most all mod packs now a days both use some Gecko code or another somewhere, and usually embed it into the game dol, so even with a pre-made WBFS, you'll still be missing the critical Gecko codes other parts of the mod may rely on if launched with BrainSlug.

TL;DR: While its possible to play with custom tracks using this guide, its beyond the scope of this guide to help you do that. If you don't have the tech know how to do it, tehn you should just use CTGP instead. It has the LAN Mod built in, and you get access to all of CTGP's usual features. All you have to do is install CTGP and change your online setting from Wiimmfi to LAN in the CTGP channel. This will mean you'll need a real disc for every Wii though, so I hope your wallet is ready.



Conclusion: Thanks to all you dedicated modders

Honestly, I already put all my words (too many words!) into the rest of this thread, so I don't have too much more to say. A massive thanks and shout out to all the dedicated modders out there that have done so much to learn and document so much stuff about the Wii and modding it, Mario Kart Wii and how it works, as well as mod the game to hell and back with ASM cheat codes, custom tracks, and just tons of insane work I can't even begin to mention like the LAN Mod this guide is about, and all the tools and info out there to be find and used. I wouldn't have been able to do any of it if I didn't have all this stuff to use as a foundation. Thank you all so much!

I'd especially like to give a shout out to InvoxiPlayGames, thank you so much for the help with making a Gecko codehandler BrainSlug module!



Attached Files
.zip   Gecko Codehandler BrainSlug Module.zip (Size: 40.02 KB / Downloads: 57)
Print this item

  How to overwrite a function; for example memcpy?
Posted by: jawa - 08-29-2021, 07:11 PM - Forum: Code Support / Help / Requests - Replies (2)

Cool Cool

Print this item

  Hello!
Posted by: Takamura - 08-19-2021, 03:32 PM - Forum: Introductions - Replies (8)

Hello! I would like to make various codes for NSMBWii and MKWii. I will post using Google Translate, which can be annoying, but thank you!

Print this item