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

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 404
» Latest member: Shutaura
» Forum threads: 1,418
» Forum posts: 7,578

Full Statistics

Online Users
There are currently 53 online users.
» 2 Member(s) | 49 Guest(s)
Bing, Google

Latest Threads
Make it to 10,000
Forum: General Discussion
Last Post: Fzerowii
1 hour ago
» Replies: 2,263
» Views: 1,181,509
Wii & Dolphin Desync
Forum: Code Support / Help / Requests
Last Post: Seeky
1 hour ago
» Replies: 1
» Views: 10
Battle Scorestreaks [Shut...
Forum: Incomplete & Outdated Codes
Last Post: Shutaura
5 hours ago
» Replies: 0
» Views: 12
POW Graphic Mode Modifier...
Forum: Visual & Sound Effects
Last Post: Jerma
Yesterday, 04:26 AM
» Replies: 3
» Views: 1,934
Change combo after track ...
Forum: Code Support / Help / Requests
Last Post: Jerma
Yesterday, 01:10 AM
» Replies: 7
» Views: 3,595
Allow THP 1.0 [TheLordScr...
Forum: Misc/Other
Last Post: TheLordScruffy
11-26-2021, 09:35 PM
» Replies: 0
» Views: 77
I make a wave with the ca...
Forum: Hacking General Discussion
Last Post: WhatisLoaf
11-25-2021, 03:33 PM
» Replies: 2
» Views: 95
Hello !
Forum: Introductions
Last Post: Fzerowii
11-25-2021, 03:20 PM
» Replies: 2
» Views: 143
Pretty Speedometer [stebl...
Forum: Visual & Sound Effects
Last Post: stebler
11-23-2021, 07:03 AM
» Replies: 64
» Views: 33,897
Guide For Calling Functio...
Forum: Power PC Assembly
Last Post: Vega
11-22-2021, 11:02 PM
» Replies: 6
» Views: 6,278

 
  [Request] Code that removes regional button
Posted by: Joeblase - 08-09-2021, 02:47 AM - Forum: Code Support / Help / Requests - No Replies

https://mkwii.com/showthread.php?tid=994...ide+option Just this but it removes the regional button.

Print this item

  Your Own Shock Zaps You [stebler]
Posted by: Vega - 08-09-2021, 12:03 AM - Forum: Online; Item - No Replies

Your Own Shock Zaps You [stebler]

If you use a Shock, you will be zapped too.

NTSC-U
047A91FC 60000000

PAL
047B7C5C 60000000

NTSC-J
047B72C8 60000000

NTSC-K
047A601C 60000000

#beq- branch is nop'd

Code Creator: stebler

Print this item

  Activate Bullet Bill at Anytime [Vega]
Posted by: Vega - 08-08-2021, 12:44 PM - Forum: Offline; Item - Replies (2)

Activate Bullet Bill at Anytime [Vega]

This code will allow you to press your desired button(s) on your controller to activate the Bullet Bill whenever you want. There is offline version and online version of the code. The online version is untested, can somebody test please? =p.

  • Q (PAL only) 5 for GCN; 4 for Non-GCN
  • S (Offline version of code only) = Slot (0 for yourself)
  • XXXX = Controller Address
  • ZZZZ = Button to Activate (use Wavebird ZZZZ values if using GCN!!)

Link to thread of XXXX and ZZZZ values - https://mkwii.com/showthread.php?tid=44

FINAL NOTE: Regarding the offline version, if you want everybody to all be in a Bill at once, replace "2C1B000S" with "48000008", this gets rid of the Player Slot check.

Video demo - https://www.youtube.com/watch?v=ijF5DqakGdI

Code creator: Vega
Code credits: Stebler (player.h)

Offline version~

NTSC-U
C278EEF8 00000015
4800004D 8078EEFC
8078895C 80788964
8078898C 807889BC
807889C4 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA0807D 63BD68BC
7FA903A6 7D6802A6
3D808034 A18CXXXX
718CZZZZ 41A20014
2C1B000S 40A2000C
394B002C 48000008
394B0014 396BFFFC
39200006 7D2903A6
852A0004 850B0004
91280000 7C00406C
7C0004AC 7C0047AC
4C00012C 4200FFE4
801D008C 00000000

PAL
C2797F04 00000015
4800004D 80797F08
80791968 80791970
80791998 807919C8
807919D0 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA0807A 63BD9AFC
7FA903A6 7D6802A6
3D80803Q A18CXXXX
718CZZZZ 41A20014
2C1B000S 40A2000C
394B002C 48000008
394B0014 396BFFFC
39200006 7D2903A6
852A0004 850B0004
91280000 7C00406C
7C0004AC 7C0047AC
4C00012C 4200FFE4
801D008C 00000000

NTSC-J
C2797570 00000015
4800004D 80797574
80790FD4 80790FDC
80791004 80791034
8079103C 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA0807A 63BD9168
7FA903A6 7D6802A6
3D808034 A18CXXXX
718CZZZZ 41A20014
2C1B000S 40A2000C
394B002C 48000008
394B0014 396BFFFC
39200006 7D2903A6
852A0004 850B0004
91280000 7C00406C
7C0004AC 7C0047AC
4C00012C 4200FFE4
801D008C 00000000

NTSC-K
C27862C4 00000015
4800004D 807862C8
8077FD28 8077FD30
8077FD58 8077FD88
8077FD90 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA08079 63BD7EBC
7FA903A6 7D6802A6
3D808033 A18CXXXX
718CZZZZ 41A20014
2C1B000S 40A2000C
394B002C 48000008
394B0014 396BFFFC
39200006 7D2903A6
852A0004 850B0004
91280000 7C00406C
7C0004AC 7C0047AC
4C00012C 4200FFE4
801D008C 00000000



Online version (untested)~

NTSC-U
C278EEF8 00000017
4800004D 8078EEFC
8078895C 80788964
8078898C 807889BC
807889C4 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA0807D 63BD68BC
7FA903A6 7D6802A6
3D808034 A18CXXXX
718CZZZZ 41A20020
3D40809C 814A8F68
894A0B84 7C0AD800
40A2000C 394B002C
48000008 394B0014
396BFFFC 39200006
7D2903A6 852A0004
850B0004 91280000
7C00406C 7C0004AC
7C0047AC 4C00012C
4200FFE4 801D008C
60000000 00000000

PAL
C2797F04 00000017
4800004D 80797F08
80791968 80791970
80791998 807919C8
807919D0 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA0807A 63BD9AFC
7FA903A6 7D6802A6
3D80803Q A18CXXXX
718CZZZZ 41A20020
3D40809C 814AD728
894A0B84 7C0AD800
40A2000C 394B002C
48000008 394B0014
396BFFFC 39200006
7D2903A6 852A0004
850B0004 91280000
7C00406C 7C0004AC
7C0047AC 4C00012C
4200FFE4 801D008C
60000000 00000000

NTSC-J
C2797570 00000017
4800004D 80797574
80790FD4 80790FDC
80791004 80791034
8079103C 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA0807A 63BD9168
7FA903A6 7D6802A6
3D808034 A18CXXXX
718CZZZZ 41A20020
3D40809C 814AC788
894A0B84 7C0AD800
40A2000C 394B002C
48000008 394B0014
396BFFFC 39200006
7D2903A6 852A0004
850B0004 91280000
7C00406C 7C0004AC
7C0047AC 4C00012C
4200FFE4 801D008C
60000000 00000000

NTSC-K
C27862C4 00000017
4800004D 807862C8
8077FD28 8077FD30
8077FD58 8077FD88
8077FD90 2C000014
7C0320AE 83C60014
83A60018 7FACEB78
7D8903A6 48000084
38000001 3BC00000
3FA08079 63BD7EBC
7FA903A6 7D6802A6
3D808033 A18CXXXX
718CZZZZ 41A20020
3D40809B 814ABD68
894A0B84 7C0AD800
40A2000C 394B002C
48000008 394B0014
396BFFFC 39200006
7D2903A6 852A0004
850B0004 91280000
7C00406C 7C0004AC
7C0047AC 4C00012C
4200FFE4 801D008C
60000000 00000000



List of Sources:

Offline version~
Code:
#START ASSEMBLY

#Address Ports
#NTSC-U = 8078EEF8
#PAL = 80797F04
#NTSC-J = 80797570
#NTSC-K = 807862C4

.set region, ''

.if (region == 'E')
        .set address1, 0x8078EEFC
        .set address2, 0x8078895C
        .set address3, 0x80788964
        .set address4, 0x8078898C
        .set address5, 0x807889BC
        .set address6, 0x807889C4
        .set regdepinstruction1, 0x3FA0807D
        .set regdepinstruction2, 0x63BD68BC
.elseif (region == 'P')
        .set address1, 0x80797F08
        .set address2, 0x80791968
        .set address3, 0x80791970
        .set address4, 0x80791998
        .set address5, 0x807919c8
        .set address6, 0x807919d0
        .set regdepinstruction1, 0x3FA0807A
        .set regdepinstruction2, 0x63BD9AFC
.elseif (region == 'J')
        .set address1, 0x80797574
        .set address2, 0x80790FD4
        .set address3, 0x80790FDC
        .set address4, 0x80791004
        .set address5, 0x80791034
        .set address6, 0x8079103C
        .set regdepinstruction1, 0x3FA0807A
        .set regdepinstruction2, 0x63BD9168
.elseif (region == 'K')
        .set address1, 0x807862C8
        .set address2, 0x8077FD28
        .set address3, 0x8077FD30
        .set address4, 0x8077FD58
        .set address5, 0x8077FD88
        .set address6, 0x8077FD90
        .set regdepinstruction1, 0x3FA08079
        .set regdepinstruction2, 0x63BD7EBC
.else
        .err
.endif

#Setup Lookup Table
bl table
.long address1
.long address2
.long address3
.long address4
.long address5
.long address6
.long 0x2C000014 #Default Instructions
.long 0x7c0320ae
.long 0x83c60014
.long 0x83a60018
.long 0x7faceb78
.long 0x7d8903a6
.long 0x48000084 #New Instructions
.long 0x38000001
.long 0x3BC00000
.long regdepinstruction1 #Region dependent instruction for setting the address in the CTR to bl to
.long regdepinstruction2
.long 0x7FA903A6
table:
mflr r11

#Check Controller
lis r12, 0x8035 #PAL GCN Y Button used for compilation, adjust this for your needs
lhz r12, 0xFFFF8200 (r12)
andi. r12, r12, 0x0800
beq+ deactivate_code

#Check Slot
cmpwi r27, 0 #Slot 0 (yourself) used for compilation, adjust this for your needs; #change to b 0x8 to skip slot check and make everybody use a Bill
bne+ deactivate_code #1 out of 12 possible, hence most likely branch

#Activate Code!
addi r10, r11, 0x2C #Point to -0x4 before 1st new instruction
b write_instructions

#Deactivate Code
deactivate_code:
addi r10, r11, 0x14 #Point to -0x4 before 1st Default Instruction

#Write Instructions; setup Loop
write_instructions:
addi r11, r11, -4 #Point to a word before the table for upcoming updating loop
li r9, 6 #6 for 6 instructions to write
mtctr r9

#Loop
loop:
lwzu r9, 0x4 (r10) #Load instruction
lwzu r8, 0x4 (r11) #Load instruction's address
stw r9, 0 (r8) #Write it!

#Clear cache so instructions update instantly
dcbst 0, r8
sync
icbi 0, r8
isync

#Decrement Loop
bdnz+ loop

#Default Instruction
lwz r0, 0x008C (r29)

#END ASSEMBLY



Online version~
Code:
#START ASSEMBLY

#Address Ports
#NTSC-U = 8078EEF8
#PAL = 80797F04
#NTSC-J = 80797570
#NTSC-K = 807862C4

.set region, ''

.if (region == 'E')
        .set ptr_raceData, 0x809b8f68
        .set address1, 0x8078EEFC
        .set address2, 0x8078895C
        .set address3, 0x80788964
        .set address4, 0x8078898C
        .set address5, 0x807889BC
        .set address6, 0x807889C4
        .set regdepinstruction1, 0x3FA0807D
        .set regdepinstruction2, 0x63BD68BC
.elseif (region == 'P')
        .set ptr_raceData, 0x809bd728
        .set address1, 0x80797F08
        .set address2, 0x80791968
        .set address3, 0x80791970
        .set address4, 0x80791998
        .set address5, 0x807919c8
        .set address6, 0x807919d0
        .set regdepinstruction1, 0x3FA0807A
        .set regdepinstruction2, 0x63BD9AFC
.elseif (region == 'J')
        .set ptr_raceData, 0x809bc788
        .set address1, 0x80797574
        .set address2, 0x80790FD4
        .set address3, 0x80790FDC
        .set address4, 0x80791004
        .set address5, 0x80791034
        .set address6, 0x8079103C
        .set regdepinstruction1, 0x3FA0807A
        .set regdepinstruction2, 0x63BD9168
.elseif (region == 'K')
        .set ptr_raceData, 0x809abd68
        .set address1, 0x807862C8
        .set address2, 0x8077FD28
        .set address3, 0x8077FD30
        .set address4, 0x8077FD58
        .set address5, 0x8077FD88
        .set address6, 0x8077FD90
        .set regdepinstruction1, 0x3FA08079
        .set regdepinstruction2, 0x63BD7EBC
.else
        .err
.endif

#Setup Lookup Table
bl table
.long address1
.long address2
.long address3
.long address4
.long address5
.long address6
.long 0x2C000014 #Default Instructions
.long 0x7c0320ae
.long 0x83c60014
.long 0x83a60018
.long 0x7faceb78
.long 0x7d8903a6
.long 0x48000084 #New Instructions
.long 0x38000001
.long 0x3BC00000
.long regdepinstruction1 #Region dependent instruction for setting the address in the CTR to bl to
.long regdepinstruction2
.long 0x7FA903A6
table:
mflr r11

#Check Controller
lis r12, 0x8035 #PAL GCN Y Button used for compilation, adjust this for your needs
lhz r12, 0xFFFF8200 (r12)
andi. r12, r12, 0x0800
beq+ deactivate_code

#Make sure your slot is the one being executed
lis r10, ptr_raceData@ha
lwz r10, ptr_raceData@l (r10)
lbz r10, 0x0B84 (r10)
cmpw r10, r27
bne+ deactivate_code #1 out of 12 possible, hence most likely branch

#Activate Code!
addi r10, r11, 0x2C #Point to -0x4 before 1st new instruction
b write_instructions

#Deactivate Code
deactivate_code:
addi r10, r11, 0x14 #Point to -0x4 before 1st Default Instruction

#Write Instructions; setup Loop
write_instructions:
addi r11, r11, -4 #Point to a word before the table for upcoming updating loop
li r9, 6 #6 for 6 instructions to write
mtctr r9

#Loop
loop:
lwzu r9, 0x4 (r10) #Load instruction
lwzu r8, 0x4 (r11) #Load instruction's address
stw r9, 0 (r8) #Write it!

#Clear cache so instructions update instantly
dcbst 0, r8
sync
icbi 0, r8
isync

#Decrement Loop
bdnz+ loop

#Default Instruction
lwz r0, 0x008C (r29)

#END ASSEMBLY

Print this item

  What is the code to disable TC glitch?
Posted by: Kaguya - 08-08-2021, 12:24 PM - Forum: Code Support / Help / Requests - Replies (2)

What is the code to disable TC glitch?

Print this item

  If anyone has any knowledge, please let me know.
Posted by: Kaguya - 08-08-2021, 09:53 AM - Forum: Code Support / Help / Requests - Replies (6)

Can everyone, including the person who used shock, make a code that is affected by Shock?

Print this item

  Extended Performance Monitor [stebler]
Posted by: stebler - 08-07-2021, 08:38 AM - Forum: Visual & Sound Effects - No Replies

Extended Performance Monitor [stebler]

This displays the game's built-in (from the EGG library) performance monitor and adds an additional bar to it.

Overview of mkw's main loop:
1. Wait on the video interface to make sure we are at the beginning of a frame.
2. Call SceneManager::draw, which will traverse the game engine's hierarchy and call the draw method of every element, which will send commands to the GPU.
3. While the GPU is processing commands, call SceneManager::calc, which will traverse the game engine's hierarchy the same way and call the calc method of every element, which will update their respective internal state for the next frame.
4. Wait for everything to complete.

What the bars measure:
Red: total frame time.
Green: SceneManager::draw.
Blue: time spent by the GPU.
Pink (custom bar): SceneManager::calc.

WIP decompilation of ProcessMeter: https://github.com/stblr/mkw/commit/868e...2806904e2d

Credits: chadderz, riidefi (documentation), Bean (previous performance monitor code).

Screenshot:
[Image: JCO3mTG.png]

PAL:
040092b8 38600180
c2238a7c 0000000a
3c80802a 60843d60
909e0154 3c80ff50
6084ffff 909e0168
3c804040 909e016c
3c803f80 909e0170
38800000 989e0174
387e0060 389e0158
3d80800a 618cef80
7d8903a6 4e800421
7fc3f378 00000000
c200960c 00000004
80750050 81830048
818c0038 7d8903a6
4e800421 81950000
60000000 00000000
c200962c 00000004
4e800421 80750050
81830048 818c0040
7d8903a6 4e800421
60000000 00000000
c200968c 00000004
4e800421 80750050
81830048 818c0044
7d8903a6 4e800421
60000000 00000000
c2009700 00000004
9bf5006b 80750050
38630154 81830000
818c0010 7d8903a6
4e800421 00000000
c2009764 00000004
80750050 38630154
81830000 818c0014
7d8903a6 4e800421
2c180000 00000000
c20097a4 00000004
4e800421 80750050
81830048 818c003c
7d8903a6 4e800421
60000000 00000000
04238f34 60000000
0423910c 48000120


NTSC-U:
04009278 38600180
c22386f8 0000000a
3c808029 6084f9f8
909e0154 3c80ff50
6084ffff 909e0168
3c804040 909e016c
3c803f80 909e0170
38800000 989e0174
387e0060 389e0158
3d80800a 618ceee0
7d8903a6 4e800421
7fc3f378 00000000
c20095cc 00000004
80750050 81830048
818c0038 7d8903a6
4e800421 81950000
60000000 00000000
c20095ec 00000004
4e800421 80750050
81830048 818c0040
7d8903a6 4e800421
60000000 00000000
c200964c 00000004
4e800421 80750050
81830048 818c0044
7d8903a6 4e800421
60000000 00000000
c20096c0 00000004
9bf5006b 80750050
38630154 81830000
818c0010 7d8903a6
4e800421 00000000
c2009724 00000004
80750050 38630154
81830000 818c0014
7d8903a6 4e800421
2c180000 00000000
c2009764 00000004
4e800421 80750050
81830048 818c003c
7d8903a6 4e800421
60000000 00000000
04238bb0 60000000
04238d88 48000120


NTSC-J:
04009214 38600180
c223899c 0000000a
3c80802a 60843700
909e0154 3c80ff50
6084ffff 909e0168
3c804040 909e016c
3c803f80 909e0170
38800000 989e0174
387e0060 389e0158
3d80800a 618ceea0
7d8903a6 4e800421
7fc3f378 00000000
c2009568 00000004
80750050 81830048
818c0038 7d8903a6
4e800421 81950000
60000000 00000000
c2009588 00000004
4e800421 80750050
81830048 818c0040
7d8903a6 4e800421
60000000 00000000
c20095e8 00000004
4e800421 80750050
81830048 818c0044
7d8903a6 4e800421
60000000 00000000
c200965c 00000004
9bf5006b 80750050
38630154 81830000
818c0010 7d8903a6
4e800421 00000000
c20096c0 00000004
80750050 38630154
81830000 818c0014
7d8903a6 4e800421
2c180000 00000000
c2009700 00000004
4e800421 80750050
81830048 818c003c
7d8903a6 4e800421
60000000 00000000
04238e54 60000000
0423902c 48000120


NTSC-K:
04009408 38600180
c2238df0 0000000a
3c808029 60841d60
909e0154 3c80ff50
6084ffff 909e0168
3c804040 909e016c
3c803f80 909e0170
38800000 989e0174
387e0060 389e0158
3d80800a 618cefe0
7d8903a6 4e800421
7fc3f378 00000000
c2009714 00000004
80750050 81830048
818c0038 7d8903a6
4e800421 81950000
60000000 00000000
c2009734 00000004
4e800421 80750050
81830048 818c0040
7d8903a6 4e800421
60000000 00000000
c2009794 00000004
4e800421 80750050
81830048 818c0044
7d8903a6 4e800421
60000000 00000000
c2009808 00000004
9bf5006b 80750050
38630154 81830000
818c0010 7d8903a6
4e800421 00000000
c200986c 00000004
80750050 38630154
81830000 818c0014
7d8903a6 4e800421
2c180000 00000000
c20098ac 00000004
4e800421 80750050
81830048 818c003c
7d8903a6 4e800421
60000000 00000000
042392a8 60000000
04239480 48000120


Source code:

Code:
# replace at 800092b8 (PAL)

# increase the size of ProcessMeter to store an additional CpuMonitor
li r3, 0x180
Code:
# inject at 80238a7c (PAL)

# set the vtable
.set CpuMonitor_vtable, 0x802a3d60
lis r4, CpuMonitor_vtable@h
ori r4, r4, CpuMonitor_vtable@l
stw r4, 0x154 + 0x0 (r30)

# set the color
.set color, 0xff50ffff # pink: rgba(255, 80, 255, 255)
lis r4, color@h
ori r4, r4, color@l
stw r4, 0x154 + 0x4 + 0x10 (r30)

# set the y position
.set posY, 0x40400000 # 3.0f
lis r4, posY@h
stw r4, 0x154 + 0x4 + 0x14 (r30)

# set the y dimension
.set dimY, 0x3f800000 # 1.0f
lis r4, dimY@h
stw r4, 0x154 + 0x4 + 0x18 (r30)

# set the flags
li r4, 0 # none
stb r4, 0x154 + 0x4 + 0x1c (r30)

# add it to the list
.set List_Append, 0x800aef80
addi r3, r30, 0x60 # the list
addi r4, r30, 0x154 + 0x4 # the bar
lis r12, List_Append@h
ori r12, r12, List_Append@l
mtctr r12
bctrl

mr r3, r30 # original instruction
Code:
# inject at 8000960c (PAL)

# call ProcessMeter::measureBeginFrame after Display::beginFrame
lwz r3, 0x50 (r21)
lwz r12, 0x48 (r3)
lwz r12, 0x38 (r12)
mtctr r12
bctrl

lwz r12, 0x0 (r21) # original instruction
Code:
# inject at 8000962c (PAL)

bctrl # original instruction

# call ProcessMeter::measureBeginRender after Display::beginRender and before SceneManager::draw
lwz r3, 0x50 (r21)
lwz r12, 0x48 (r3)
lwz r12, 0x40 (r12)
mtctr r12
bctrl
Code:
# inject at 8000968c (PAL)

bctrl # original instruction

# call ProcessMeter::measureEndRender after ProcessMeter::draw and before Display::endRender
lwz r3, 0x50 (r21)
lwz r12, 0x48 (r3)
lwz r12, 0x44 (r12)
mtctr r12
bctrl
Code:
# inject at 80009700 (PAL)

stb r31, 0x6b (r21) # original instruction

# start the timer of the custom CPU monitor before SceneManager::calc
lwz r3, 0x50 (r21)
addi r3, r3, 0x154
lwz r12, 0x0 (r3)
lwz r12, 0x10 (r12)
mtctr r12
bctrl
Code:
# inject at 80009764 (PAL)

# stop the timer of the custom CPU monitor after SceneManager::calc
lwz r3, 0x50 (r21)
addi r3, r3, 0x154
lwz r12, 0x0 (r3)
lwz r12, 0x14 (r12)
mtctr r12
bctrl

cmpwi r24, 0x0 # original instruction
Code:
# inject at 800097a4 (PAL)

bctrl # original instruction

# call ProcessMeter::endFrame after Display::endFrame
lwz r3, 0x50 (r21)
lwz r12, 0x48 (r3)
lwz r12, 0x3c (r12)
mtctr r12
bctrl
Code:
# replace at 80238f34 (PAL)

nop # prevent the game from hiding the bars
Code:
# replace at 8023910c (PAL)

b 0x120 # hide the ugly element on the left

Print this item

  How to change a word in mem90?
Posted by: jawa - 08-06-2021, 09:44 AM - Forum: Code Support / Help / Requests - Replies (2)

I know how to access/change values in mem80. Is mem90 accessed the same way as mem80?

Print this item

  [Request] Random Track Music
Posted by: Yuri Bacon - 08-06-2021, 06:02 AM - Forum: Code Support / Help / Requests - Replies (4)

There is already a code that can randomize the track .szs itself made by CLF78 (https://mkwii.com/showthread.php?tid=165...76#pid7976). A similar code that could let you give tracks multiple .brstm files and pick them at random every time you race them would be pretty cool for adding custom music to your own game, not limiting you to hearing the same song every time.

Print this item

  [REQUEST] How to get the profile address of the current player?
Posted by: Wiimm - 08-04-2021, 01:12 PM - Forum: Code Support / Help / Requests - Replies (3)

For a LE-CODE cheat code I need a function to get the address of the profile (save data) of the current player. Alternatively it is ok to get the index of the current player, because I know how to get the address by index:

ADDRESS := [809BD748] + INDEX * 0x93f0 (PAL)

Print this item

  Paired Singles
Posted by: Vega - 08-02-2021, 11:15 PM - Forum: Power PC Assembly - No Replies

Paired Singles



Chapter 1: Intro

Paired Singles are probably the most strenuous aspect of PPC Assembly to understand.

First thing's first, you have to already know the basics of PPC ASM, able to make codes, and you already understand the fundamentals of Floating Points + FPRs. I have a great tutorial covering Floats which you can find HERE. Read that first before coming back here.



Chapter 2: Paired Singles in a FPR 

With normal floating point instructions, you have only been working with the first 64-bit segment.  This first segment which all normal floating point instructions work on is known as Paired Single 0 (or ps0 for short). The second segment is Paired Single 1 (ps1). Paired Single instructions utilize both ps0 and ps1 simultaneously, and the floats in ps0 & ps1 can only be of single precision. Hence the term Paired Singles (a pair of single precision floats). Using paired single instructions when a double precision float is present in an FPR will cause undefined behavior/results and could lead to an exception.



Chapter 3: Paired Singles in Memory

Since the values in ps0 and ps1 are single precision, each paired single (if stored/loaded to/from memory) is a word value.

Example: You have this value in f1 - C06C800000000000 4170000000000000
  • ps0 = C06C800000000000
  • ps1 = 4170000000000000

If this paired single value was stored to memory, it will be shown as 0xC36400004B800000
  • 0xC3640000 is the ps0 value
  • 0x4B800000 is the ps1 value

It's important to understand that paired singles are always two words in memory linked together as a double word.



Chapter 4: Storing/Loading

Here are some basic instructions for loading and storing paired singles.

psq_l fD, VALUE (rA), W, I
#VALUE is signed

The above example will load the paired single value located at rA+VALUE into fD. The single precision floating point value located at rA+VALUE will be loaded in ps0 and the single precision floating point value located at rA+VALUE+4 will be loaded into ps1.

psq_st fD, VALUE (rA), W, I
#VALUE is signed

The above is a basic paired single storing instruction. Value of ps0 is stored to memory location rA+VALUE and the value of ps1 is stored at rA+VALUE+4.

VALUE is NOT a 16-bit signed range. For paired single loading/storing instructions it's actually a 12-bit signed range (0xFFFFF800 thru 0x000007FF). If this range isn't followed, your compiler will throw an error.

Note: The format I have shown above for the two instructions is the format that all PPC compilers use. For whatever reason, Dolphin (in Code view) uses a slightly different format.

What are the W and I values?
W can only be two values. 0 or 1. If W is 1 then ps1 of the FPR is always loaded/stored as the floating point value of 1 (0x3FF0000000000000) regardless what is in the fpr/memory beforehand. If W is 0, then the loading/storing of ps1 acts normally.

The I value represents which Graphics Quantization Register (GQR) will be used. To keep things simple for now, for basic loading/storing of paired singles, simply set the I value to 0. This will be fine for most Wii games. More information covering the nitty gritty of GQRs will be discussed later in Chapter 8.



Chapter 5: Basic Math & Single Parameter Instructions

Like floating point instructions, there are plenty of instructions for paired single instructions for all sorts of math.


ps_add fD, fA, fB
#fA ps0 + fB ps0 = fD ps0
#fA ps1 + fB ps1 = fD ps1

Other math instructions:
ps_sub (subtracting)
ps_mul (multiplying)
ps_div (dividing)

You also have some basic single parameter instructions...

ps_mr fD, fA
#fA ps0's value is copied to fD ps0
#fB ps1's value is copied to fD ps1

ps_abs fD, fA
#absolute value of fA ps0 is placed into fD ps0
#absolute value of fA ps1 is palced into fD ps1

ps_nabs fD, fA
#same as ps_abs but using negative absolute value instead

ps_neg fD, fA
#fA ps0 (if positive) is changed to its negative value (i.e. 1 to -1), result placed in fD ps0. If negative, then the value it changed to positive (i.e. -1 to 1). Same effects will obviously also apply to fA ps1 and result will be placed into fD ps1.



Chapter 6: Comparisons

ps_cmpo is the instruction for ordered paired single comparisons. There is also the ps_cmpu instruction for unordered comparisons.

The difference between ordered and unordered comparisons is how the FPSCR (floating point status control register) is modified when a NaN (not a number) is present in the comparison. Thus, in simple terms if you have no idea about what I just stated, stick with ordered comparisons only (ps_cmpo).

There are two types of ordered comparisons. One for ps0 and one for ps1

ps_cmpo0 crf, fD, fA
#fD ps0's value is compared to fA ps0's value

ps_cmpo1 crf, fD, fA
#fD ps1's value is compared to fA ps1's value

Just like with floating point instructions, you need to specify the condition register field. To keep it simple, use cr1.

Example comparison:
#Let's say f3 ps1 has the value of 1.0 in decimal form, and f0 ps1 has the value of 3.5 in decimal form.

Code:
ps_cmpo1 cr1, f3, f0
bgt- some_label

In the above source, the branch would NOT be taken because 1.0 is less then 3.5.



Chapter 7: Other Instructions

Paired Singles has some nifty instructions to move values across the paired single segments. There are 4 different instructions you can use.

ps_merge00 fD, fA, fB
#fA ps0 is copied to fD ps0. fB ps0 is copied to fD ps1

ps_merge01 fD, fA, fB
#fA ps0 is copied to fD ps0. fB ps1 is copied to fD ps1

ps_merge10 fD, fA, fB
#fA ps1 is copied to fD ps0. fB ps0 is copied to fD ps1

ps_merge11 fD, fA, fB
#fA ps1 is copied to fD ps0. fB ps1 is coped to fD ps1

You can use ps_merge10 to swap the ps values within an FPR. This could come in handy for you.

Example (swap the ps values of f0)~

Code:
ps_merge10 f0, f0, f0


Here are two instructions that allows you to do basic addition across the paired single segments. Obviously if the value(s) are negative, the instructions can be used as subtraction instead.

ps_sum0 fD, fA, fC, fB
#fA ps0 + fB ps1 = fD ps0
#fC ps1 = fD ps1

ps_sum1 fD, fA, fC, fB
#fA ps0 + fB ps1 = fD ps1
#fC ps0 = fD ps0

Here's an example of adding ps0 and ps1 of an FPR together and having the result stored back in ps0 of the same FPR. This could be useful for something such as writing some source involving basic Trigonometry. We'll use f5 for the following example.

Code:
ps_sum0 f5, f5, f5, f5

If for w/e reason you wanted the result in ps1 of f5, just use ps_sum1 instead.



Chapter 8: Scaling, Quantization, and the GQRs

When a paired single load instruction of any type is executed, this is known as Dequantization (or Dequantizing). If it's a paired single store instruction of any type, it is known as Quantization (or Quantizing). Quantizaton/Dequantization is just a fancy term for taking integer values and having them in a scale (or range) that can be converted back to or from a float value.

The use of Scaling allows you to have integer values (no larger than halfwords) in memory and utilize them as floating points (by a specified range) in the paired single segments of an FPR.

Revisiting Chapter 4 regarding the paired single loading/storing instructions, the I value stands for which Graphics Quantization Register (GQR) to use. There are 8 total GQRs. The I value can be any number from 0 to 7.

Each GQR is 32 bits of data. You can modify a GQR to effect how scaling is done during quantization and/or dequantization. Wii Games will usually set the all the GQR values during its early boot sequence. You can modify any GQR value but be sure to restore its value at some point later in your source/code.

You can write a value to the GQR's via the mtspr instruction. Here are the spr numbers for the GQRs
  • 912 = GQR0
  • 913 = GQR1
  • 914 = GQR2
  • 915 = GQR3
  • 916 = GQR4
  • 917 = GQR5
  • 918 = GQR6
  • 919 = GQR7

To write a register value to the GQR...
mtspr XXX, rD
#XXX = GQR's spr number, rD contains the value to copy to the GQR

To backup the value of a GQR to a register...
mfspr rD, XXX
#rD is the register where the GQR's value will be copied to, XXX = GQR's spr number

Structure of GQR:
  • Bits 0 & 1 = Unused
  • Bits 2 thru 7 = Scale Value for Dequantization; 6 bit value (L_Scale)
  • Bits 8 thru 12 = Unused
  • Bits 13 thru 15 = Dequantization Type; 3 bit value (L_Type)
  • Bits 16 & 17 = Unused
  • Bits 18 thru 23 = Scale Value for Quantization; 6 bit value (R_Scale)
  • Bits 24 thru 28 = Unused
  • Bits 29 thru 31 = Quantization Type; 3 bit value (R_Type)

L_Type and R_Type can only be 4 different values.
  • 0x0 = Float (no scaling)
  • 0x4 = Unsigned Byte
  • 0x5 = Unsigned Halfword
  • 0x6 = Signed Byte
  • 0x7 = Signed Halfword

L_Scale & R Scale structure:
This is a value (anywhere from 0x00 to 0x3F) that is plugged into the following formula:

2^scale = DQ (dequant/quant value)

During Dequantization:
Integer value (determined by L_Type) in memory is divided by DQ, that result is converted to a single precision float, and placed into its paired single segment of the FPR.

During Quantization:
Single precision float value of the paired single segment converted to its integer value (determined by R_Type), that result is multiplied by DQ, and placed into memory.

Confused? Yeah I don't blame you. Let's go over an example use of scaling.

Let's say you are making a code for your game that will utilize the GCN C stick values. You find where these values are in memory. There's a byte value for the X axis and a byte value right next to it for the Y axis. You move the sticks around and have come to the conclusion of the following ranges...

X axis range:
0x80 (furthest left) thru 0x00 (neutral) thru 0x7F (furthest right)

Y axis range:
0x80 (furthest down) thru 0x00 (neutral) thru 0x7F (furthest up)

Thus the two bytes are signed. We want to load these two byte values and scale them to floating points so we can preform quicker and more complex math on them compared to using normal integer instructions.

First we need to setup GQR7. The L_Type and R_Type will be set to 0x6 (signed byte). Now for L_Scale and R_Scale, what value do we use? Well the range of 0x00 thru 0xFF is a total of 256 unique values. A byte is 8 bits. If you preform the Scale equation of 2^8, you get a total of 256, matching the 256 unique values. So L_Scale and R_Scale will be 0x08. Now let's write the GQR7.

Code:
lis r0, 0x0806 #Assuming r0 is safe for use in this example source
ori r0, r0, 0x0806
mtspr 919, r0 #Write new value to GQR7

GQR7 is set, let's load the two bytes into the paired segments of an FPR. We will use f18 as an example. The bytes are located at r9 + 0x0088.

Code:
psq_l f18, 0x0088 (r9), 0, 7

Let's assume during the load, the X axis was a value of 0x00 (neutral) and the Y axis was 0xEF (sligthly down). f18 would have a value of...
  • ps0 (X axis) 0x0000000000000000
  • ps1 (Y axis) 0xBFB1000000000000

Convert these to decimal and you get 0.0, & -0.06640625

Scaling uses a range of -0.5 to 0.5 for signed bytes/halfwords and a range of 0.0 to 1.0 for unsigned (logical) bytes/halfwords. The ranges will be correct in response to your integers as long as you set the scale values correctly and you know the ranges of the integers beforehand.

Let's say we load them again but at a different point in time. X axis is 0x7F (max right), and Y axis is 0x33 (moderate up). f18 would have a value of...
  • ps0 (X axis) 0x3FDFC00000000000
  • ps1 (Y axis) 0x3FC9800000000000

Convert those to decimal and you get 0.49609375, & 0.19921875. If you are wondering why 0x7F didn't convert to 0.5 (max float) that's because 0x00 (0.0) is a possible value in the range and has to be accounted for. If any of the stick integer values were 0x80, that would result in -0.5.

If you were using something such as Halfword values where they had a range of 0x0000 thru 0xFFFF (65536 total possible values), you would use the scale formula of 2^16. 16 for 16 bits (halfword)



Chapter 9: Going back over normal Float Instructions in regards to ps1

When working in the past with normal float instructions, your only concern was what was in ps0. However it's important to note that a lot of normal float instructions (mostly single precision float instructions) effect ps1 as well. Having this knowledge can help you optimize a source by using normal float instructions along with your paired single instructions.

Load Floating Single (lfs)~
Whenever an lfs instruction is executed, the single precision float that is loaded into ps0, is also loaded into ps1. Thus ps0 and ps1 are now the same value.

Example: r31's value is a memory address points to the word value of 0x3F800000; load that value as single precision float into f0

Code:
lfs f0, 0 (r31)

After the instruction has executed, both ps0 and ps1 of the FPR are now 0x3FF000000000000.

---

Store floating single (stfs)~
Even though this is obvious, but it might as well be stated that the stfs instruction only stores ps0's value to memory.

---

Single Precision Floating Point Math~
ALL math based single precision floating point instructions will only use the ps0 values of the source registers for the calculation, but the destination register will have the result be placed in both ps0 and ps1.

---

fres (can only be used on single precision floats)~
fres will use the ps0 values of the source register for the calculation. Destination register will have the result placed in both ps0 & ps1.

---

All other instructions that work on (or can work on) single floats (frsp, fmr, etc) only produce a result in ps0 while ps1 will be left undefined.

Shoutout to CLF78 for help with the contents in this Chapter!



Chapter 10: Dolphin Inaccuracies

Something you should know...

Dolphin actually displays the FPRs incorrectly. An FPR is actually just one 64 bit segment. The second segment you see on Dolphin doesn't actually exist on the Wii's hardware.

On real hardware, Single Precision floats take up just 32 bits of data in the FPR, thus these single precision floats are in their word form (like what you see in memory). Double Precision floats are still 64 bits of data, thus they take up the entire FPR.

For whatever reason, the Devs of Dolphin made the FPRs be displayed as two 64 bit segments and have any single precision floats be displayed in 64-bit form. Paired Singles are two single precision floats, and in Dolphin, the first float in the first 64 bit segment and the second float is in the other 64 bit segment.

What occurs on real hardware regarding Paired Singles is the the 64-bit FPR is split in two halves. The upper 32 bits is the first paired single while the lower 32 bits is the second.

Thus this inaccuracy of the FPRs can allow a coder to write up source to manipulate the incorrect outputs of instructions such as using fmr with a double precision float and messing with the destination register ps1's leftover value, which would have been erased/replaced when done on real hardware.

It's nothing to worry about though as replicating this 'bug' can only be done with poorly handwritten assembly. Thus the quirky FPR usage by Dolphin won't cause any issues at all running your Wii games.

For more info about this 'bug', here's a small write up with a demo code + source - https://mkwii.com/showthread.php?tid=1886



Chapter 11: Real World Example; Conclusion

Still confused by Paired Singles? Or not sure how some of these instructions can optimize one of your sources? It may be best to look at a real code (not some source example) that uses multiple different types of paired single instructions where using such instructions improves that source from just using plain jane floating point instructions.

Here is an MKWii code I have created that fits such requirements - https://mkwii.com/showthread.php?tid=1260

Summary of the code:
  • Purpose is to allow the user to spin the WiFi globe in the direction depending on their analog stick
  • Analog Stick X and Y values reside in memory as a paired single and work in a value range of -1 to 1.
  • Longitude and Latitude of the globe resides in memory as a paired single.
  • Load the Longitude & Latitude and update its values depending on the Analog Stick X and Y current values

Print this item