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

Username
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 48
» Latest member: SwareJonge
» Forum threads: 945
» Forum posts: 1,705

Full Statistics

Online Users
There are currently 6 online users.
» 0 Member(s) | 5 Guest(s)
Google

Latest Threads
Air-O-Meter
Forum: Cheat Codes
Last Post: zak
Yesterday, 03:11 AM
» Replies: 3
» Views: 213
C++ Learning Center
Forum: Resources
Last Post: Phyz
12-09-2018, 03:41 PM
» Replies: 4
» Views: 84
Make it to 1000!
Forum: General Discussion
Last Post: zak
12-09-2018, 03:37 PM
» Replies: 164
» Views: 15,329
The "ASM Rampage" (what a...
Forum: Hacking General
Last Post: zak
12-08-2018, 05:38 PM
» Replies: 0
» Views: 43
WiiMod Update Thread
Forum: General Discussion
Last Post: Phyz
12-08-2018, 04:47 PM
» Replies: 12
» Views: 1,292
Speed Modifier
Forum: Cheat Codes
Last Post: zak
12-05-2018, 06:16 PM
» Replies: 1
» Views: 60
Tutorial on the 'BL Trick...
Forum: Guides/How-To's
Last Post: zak
12-05-2018, 02:52 AM
» Replies: 0
» Views: 61
Creating Loops (Pt. 2)
Forum: Guides/How-To's
Last Post: zak
12-04-2018, 06:31 PM
» Replies: 0
» Views: 43
Guide to perma patch ISO ...
Forum: Guides/How-To's
Last Post: xXCrazySniperXx
12-04-2018, 03:08 PM
» Replies: 3
» Views: 390
Creating Loops (Pt. 1)
Forum: Guides/How-To's
Last Post: zak
12-04-2018, 03:54 AM
» Replies: 0
» Views: 64

 
  The "ASM Rampage" (what a year)
Posted by: zak - 12-08-2018, 05:38 PM - Forum: Hacking General - No Replies

If anybody has been following my work as far as just creating Codes, they would know that I have been on an ASM 'Rampage'. Literally, every other day, I would create a new ASM code or a new ASM revision of an existing code.

As anyone can easily assume, this has wore me out, almost completely.

When the year started, I couldn't even imagine learning all this (expletive) and actually being semi decent at it. Before learning ASM, I did as much as any mkwii noobie could do as far as 'making' codes (nops, gecko pointer codes, gecko F6 type etc).

After learning ASM, I decided to exhaust all efforts for as long as possible to create code after code. Well, the steam has dissipated. I will no longer be actively making or attempting to make new codes and/or improve current codes. Currently, I am wrapping up optimizing some of my older codes, and that will be pretty much it (those threads will be modified later this year, once work obligations are out of the way). This isn't a retirement (ex: beg me back like every other mkwii noob does...) announcement, just a statement that please don't expect any more Codes. If something does intrigue me in the future, I will still throw some attempts at it, and try to make a new code if it doesn't require putting too much effort...

Anything I learned throughout my ASM journey, I have already posted in the Guides/How-To subforum. All the resources/info is out there for anyone who is willing to learn.

And finally....

This wouldn't have been possible without Star!! He put up with my (expletive), dealt with me, and got around my flaws. I was able to learn so much. Once again, thank you Star. I'm pretty sure Star is burnt out as well considering the amount of great codes he has made & released.

Also, thank you to everyone else who has helped along the way whether its code testing, discord stuff, helping on forums, etc.

Print this item

  C++ Learning Center
Posted by: Phyz - 12-06-2018, 05:24 AM - Forum: Resources - Replies (4)

Yo, so this is gonna be a thread going step-by-step throughout the process of C++. When it comes to Programming, I am an believer in "practice makes perfect", so we're gonna learn by completing practice problems. I will post links to all practice problems, and I will provide my own solutions with explanations of the new parts of C++ utilized in each program.

The structure of this guide will be:
----------
Chapter X

Practice Problem Link:

Problem Text:

New stuff covered:

Code: (This will include comments with why I used what)

Summary/Extra Problems: 
----------
This thread will be continuously edited for new chapters, unless Zak decides to make a new Topic for HBC dev/C++. 

Without any further a-do, here is

Chapter 1: "Hello World"



Problem Text: use either printf or cout to print the string  to stdout.


New stuff covered: Headers, Functions


Headers:
So a header is basically pre-written code that is compiled before any other code is ran. 
1. In this case iostream provides basic console input/output, and a few other things. 
2. cstudio on the other hand is used to communicate with other devices that the machine can use. ie. Mouse/Keyboard/etc.


Functions:
A function is a collection of statements that the compiler runs when called upon. 
1. "int". Here we define the function as needing to return an integer. Keep in mind that returning a value/string, is NOT the same as outputting to the console.
2. "main". In this case we have the loop "main" followed by brackets to symbolize where the function begins, but more impotently, where it ends. 
3. "printf("Hello, World!");". This simply prints what is within the quotations to the console.
4.  "return 0;". This simply returns an integer, which would signify that the function is over. 


Code:
#include <iostream>
#include <cstdio>
using namespace std;

int main() {
   printf("Hello, World!");
   return 0;
}


Summary/Extra Problems: So now you know what a header is, what a variable is, what a function is, and how to print stuff to the console!
Problem: Set 2 variables as integers (a and b), then have another integer variable © equal the sum of the two variables! (Do not have the user input to the console, just have the console output the number you desire! Hint: You may not be able to use a 'printf("")' on this one!
Leave your responses in the replies sections with the following format:
Extra Question 1 Code:
#include <iostream>
#include <cstdio>
using namespace std;

int main() {
 int a = 5;
 int b = 10;
 int c = a + b;
 << cout c;
}
-----------------------------------------------------------------------------------------

Chapter 2: "Input and Output"



Problem Text: (I am going to slightly modify this problem) Input 3 numbers to the console, and have their sum equal 10.
Note: This problem is different than the Extra Problem in Chapter 1 because the user in inserting their own numbers.


New stuff covered: cin, cout, and operands.


cin: cin is a fancy way of saying: Console "c" Input "in". Whenever you write "cin", you need to use ">>", which implies that the action is going to the console.


cout: This means: Console Output. Whenever you write "cout", you need to use "<<", which implies that the action is going out of the console.


operand: This is a fancy way of saying: + - * / etc. However, different programming languages use different operands for different functions. 
For a rather extensive list of operands for c++, visit: https://www.geeksforgeeks.org/operators-c-c/


Code:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;

int main() { // start our function
 int a; // define variable a
 int b; // define variable b
 int c; // define variable c

 cin >> a; // Have the user input a value for variable a
 cin >> b; // Have the user input a value for variable b
 cin >> c; // Have the user input a value for variable c
 int d = a + b + c; // Define variable b as an integer, and set it equal to the sum of a, b, and c
 cout << d; // Ouput variable d
 return 0;  // end the function
}


Summary/Extra Problems: So now you know how to get input from the user, and c++ operands!!!
Problem #2: Before you get input from the user, output text asking for the users first, second, and third number. When you print the sum of the 3 numbers print text that says: "The sum of your three numbers is X".
Problem #2 Code:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;

int main() { // start our function
 int a;     // define variable a
 int b;     // define variable b
 int c;     // define variable c
 printf("What is your first number?");
 cin >> a; // Have the user input a value for variable a
 printf("What is your second number?");
 cin >> b; // Have the user input a value for variable b
 printf("What is your third number?");
 cin >> c;          // Have the user input a value; for variable c
 int d = a + b + c; // Define variable b as an integer, and set it equal to the
                    // sum of a, b, and c
 printf("The sum of your three numbers is: ");
 cout << d; // Ouput variable d
 return 0;  // end the function
}
-----------------------------------------------------------------------------------------

Chapter 3: "Conditional Statements" 

Practice Problem Link: https://www.hackerrank.com/challenges/c-...se/problem

Problem Text: Give a positive integer denoting n, do the following:

1. If 1 =< n =< 9, then print the lowercase English word corresponding to the number (print "one" for 1, "two", for two, etc.

2. If n > 9, print "Greater than 9"

Constraints: 1 =< n =< 10^9

New stuff covered: if, else, and else-if

if: This means: "If (x) happens, then DO y.

example (not using c++ syntax): if the variable x = 1, then execute: x + 1.

else: This means: if (x) doesn't happen, then DO z.

example (not using c++ syntax): if the variable x does NOT = 1, then execute: x + 2.

(if-)else-if: This means: if (x) doesn't happen, but (a) does happen, then DO b.

example (not using c++ syntax): if the variable x does NOT = 1, but the variable x = 5, then execute: x + 7.

Code:

#include <bits/stdc++.h>

using namespace std;

int main() // Start of Function
{
 int n;    // Define n as an integer
 cin >> n; // Send input to the console
 cin.ignore(numeric_limits<streamsize>::max(), '\n');
 if (n == 1) { // If statement for 1
   printf("one");
 } else if (n == 2) { // If statement for 2
   printf("two");
 } else if (n == 3) { // If statement for 3
   printf("three");
 } else if (n == 4) { // If statement for 4
   printf("four");
 } else if (n == 5) { // If statement for 5
   printf("five");
 } else if (n == 6) { // If statement for 6
   printf("six");
 } else if (n == 7) { // If statement for 7
   printf("seven");
 } else if (n == 8) { // If statement for 8
   printf("eight");
 } else if (n == 9) { // If statement for 9
   printf("nine");
 } else if (n > 9) { // If statement for greater than 9
   printf("Greater than Nine!");
 }
 return 0;
}

Summary/Extra Problems: So you've learned about conditional statements. Now I want you to ask the user for their name and their birthday, as well as a friend of theirs' name and birthday. I then want you to compare their ages and print: "%their name%, is older than %your name% by %4 years%... or vic versa.
Sample input:
Tim
17
John
18
Sample Output:
John is older than Tim by 1 year(s)!

Problem #3 Code:
#include <bits/stdc++.h>
#include <iostream>
using namespace std;

int main() // Start of Function
{
char str [100]; // creating a string with the name "str"
cin >> str; // Asking the user for the value of the string
int a1;    // First Age input
cin >> a1; // Send input to the console
char stri [100]; // creating a string with the name "stri"
cin >> stri; //asking the user for the calue of the string
int a2;    // Second age input
cin >> a2; // Send input to the console
int dif; // declaring the variable for the difference in age.

cin.ignore(numeric_limits<streamsize>::max(), '\n');
if (a1 > a2) { // If statement for 1
   dif = a1 - a2; // getting the difference in age
  cout << str << " Is older than " << stri << " by " << dif << " year(s)" << endl; //output
} else if (a1 < a2) { // If statement for 2
   dif = a2 - a1; // getting the difference in age
  cout << stri << " Is older than " << str << " by " << dif << " year(s)" << endl; //ouput
} else if (a1 == a2) { // If statement for 3
  printf("You two are the same age!");
}
return 0;
}

-----------------------------------------------------------------------------------------

Chapter 4: "For Loops"

Practice Problem Link: https://www.hackerrank.com/challenges/c-...op/problem

Note: Before I even get started with this one, the practice problem provided by the site is explained HORRIBLY. I've taken a lot of math, and it still took me ages to solve the problem, and even after solving it... I'm not even sure I FULLY understand it.

Problem Text: (I am going to slightly modify this problem) Input 2 different numbers (at the same time) (The first number is ALWAYS smaller than the second). Then, if the first number is >= 9, run a loop that prints its written value up to nine. Afterwards, take the second number, and from (10 to the second number), loop and display if it is odd, or even.

Sample input:
3, 15
Sample output:
three
four
five
six
seven
eight
nine
even
odd
even
odd
even
odd

New stuff covered: for(a, b, c)

for(a;b; c):

a: Set a variable for the for loop. example: for(int i, ...
b: Set a parameter for which the loop runs. ie. i < 10... only run if integer i is less than 10: for(int i; i < 10 ...
c: How will you increment a? If a never goes beyond the parameters of b, then how will the loop stop? That's why you need c:
 for(int i; i < 10; i++)
Note: i++, just means that i will increase by 1 every time it loops. --i would make i decrease by 1 every time it loops. There are multiple ways to increment your variable.

Also, we need the "%" operand. This gives us the remainder of a division problem. For example: 10 % 5 = 0.        15 % 3 = 0.

Code:
#include <bits/stdc++.h>
#include <cstdio>
#include <iostream>
using namespace std;

int main() {
 int n = 10;
 int d;
 int i;
 int z;
 int y;

 cin >> y;
 z = y;
 cin >> i;
 d = i;

for (int z = y; z <= 9; z++)
  if (z == 1) {
    cout << "one" << endl;
  } else if (z == 2) {
    cout << "two" << endl;
  } else if (z == 3) {
    cout << "three" << endl;
  } else if (z == 4) {
    cout << "four" << endl;
  } else if (z == 5) {
    cout << "five" << endl;
  } else if (z == 6) {
    cout << "six" << endl;
  } else if (z == 7) {
    cout << "seven" << endl;
  } else if (z == 8) {
    cout << "eight" << endl;
  } else if (z == 9) {
    cout << "nine" << endl;
  }

for(int d = i; d >= n; n++)
   if (n % 2 == 0) {
   cout << "even" << endl;
   } else if (n % 2 != 0) {
   cout << "odd" << endl;
   }
}


There isn't going to be a BONUS problem this time, because if you could solve this problem, you're fine Smile
-----------------------------------------------------------------------------------------
Chapter 5: "Functions"

Practice Problem Link: https://www.hackerrank.com/challenges/c-tutorial-functions/problem

Problem Text: Create a function that inputs 4 numbers and outputs the largest number.

New stuff covered: Functions (kinda)

Function: A function is a just a collection of lines of code that can be called upon later.
Syntax:
int NAME_OF_FUNCTION(ELEMENT1, ELEMENT2, ETC){
     CODE
return 0;
}

Code:

#include <iostream>
#include <cstdio>
using namespace std;

int max(int a, int b, int c, int d){ //This is our function. It's named: max, and has 4 elements
   cin >> a; //input the value for int a
   cin >> b; // input the value for int b
   cin >> c; //input the value for int c
   cin >> d; // input the value for int d
   if (a > b and a > c and a > d){ //if statement to see if a is the largest number
       cout << a; //If it is the largest, output the value of a
   }
   if (b > a and b > c and b > d){ //if statement to see if b is the largest number
       cout << b; //If it is the largest, output the value of b
   }
   if (c > a and c > b and c > d) { //if statement to see if c is the largest number
     cout << c; // If it is the largest, output the value of c
   }
   if (d > a and d > b and d > c) { //if statement to see if d is the largest number
     cout << d; // If it is the largest, output the value of d
   }
   return 0; //Since I gave the function the int property, we must return a value. If this function was void, we wouldn't have to do this.
}
int main() {
   int z; // declare z
   z = max(0, 0, 0, 0); // set z equal to the result of the function.
}

-----------------------------------------------------------------------------------------

Print this item

  Speed Modifier
Posted by: SwareJonge - 12-05-2018, 03:27 PM - Forum: Cheat Codes - Replies (1)

Speed Modifier

NTSC-U
C257514C 00000004
C0041134 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2571CF4 00000004
C0091134 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257F0A4 00000004
C0051138 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257513C 00000004
C0041138 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2575360 00000004
C01E0108 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257551C 00000004
C0030004 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C25754F8 00000004
C0030014 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C258B988 00000004
C0230024 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C258B998 00000004
C0230028 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C258B9A8 00000004
C023002C 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C258B9B8 00000004
C0230030 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C258B968 0000001D
C0230018 3E80809C
82948F28 8294003C
82940000 82940000
82940000 A274000A
5673801E 2C130000
40820008 3E603F80
3E808170 92740000
3E600000 C3940000
EC3C0072 3E808160
3E6042D2 92740004
3E604296 92740008
3E604382 9274000C
3E604302 92740010
3E60491C 62734000
92740014 3E604302
92740018 60000000
C3D40004 EFDC07B2
3E60808A D3D312E8
C3D40008 EFDC07B2
D3D30FD8 C3D4000C
EFDC07B2 D3D310EC
C3D40010 EFDC07B2
D3D3114C C3D40014
EFDC07B2 D3D3115C
C3D40018 EFDC07B2
D3D30FE4 60000000
FFC0E890 3E600000
60000000 FF80E890
3A800000 60000000


PAL
C257B9B0 00000004
C00459F4 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2578558 00000004
C00959F4 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C25858C8 00000004
C00559F8 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257B9A0 00000004
C00459F8 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257BBC4 00000004
C01E0108 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257BD80 00000004
C0030004 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C257BD5C 00000004
C0030014 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C25921AC 00000004
C0230024 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C25921BC 00000004
C0230028 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C25921CC 00000004
C023002C 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C25921DC 00000004
C0230030 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C259218C 0000001D
C0230018 3E80809C
8294D6E8 8294003C
82940000 82940000
82940000 A274000A
5673801E 2C130000
40820008 3E603F80
3E808170 92740000
3E600000 C3940000
EC3C0072 3E808160
3E6042D2 92740004
3E604296 92740008
3E604382 9274000C
3E604302 92740010
3E60491C 62734000
92740014 3E604302
92740018 60000000
C3D40004 EFDC07B2
3E60808A D3D35DC0
C3D40008 EFDC07B2
D3D35AB0 C3D4000C
EFDC07B2 D3D35BC4
C3D40010 EFDC07B2
D3D35C24 C3D40014
EFDC07B2 D3D35C34
C3D40018 EFDC07B2
D3D35ABC 60000000
FFC0E890 3E600000
60000000 FF80E890
3A800000 60000000


NTSC-J
C257B330 00000004
C0044B54 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2577ED8 00000004
C0094B54 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2585248 00000004
C0054B58 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257B320 00000004
C0044B58 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257B544 00000004
C01E0108 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C257B700 00000004
C0030004 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C257B6DC 00000004
C0030014 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C2591B2C 00000004
C0230024 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2591B3C 00000004
C0230028 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2591B4C 00000004
C023002C 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2591B5C 00000004
C0230030 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2591B0C 0000001D
C0230018 3E80809C
8294C748 8294003C
82940000 82940000
82940000 A274000A
5673801E 2C130000
40820008 3E603F80
3E808170 92740000
3E600000 C3940000
EC3C0072 3E808160
3E6042D2 92740004
3E604296 92740008
3E604382 9274000C
3E604302 92740010
3E60491C 62734000
92740014 3E604302
92740018 60000000
C3D40004 EFDC07B2
3E60808A D3D34F20
C3D40008 EFDC07B2
D3D34C10 C3D4000C
EFDC07B2 D3D34D20
C3D40010 EFDC07B2
D3D34D84 C3D40014
EFDC07B2 D3D34D94
C3D40018 EFDC07B2
D3D34C1C 60000000
FFC0E890 3E600000
60000000 FF80E890
3A800000 60000000


NTSC-K
C2569A08 00000004
C0043E6C 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C25665B0 00000004
C0093E6C 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2573920 00000004
C0053E70 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C25699F8 00000004
C0043E70 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2569C1C 00000004
C01E0108 3E808170
C3940000 EC1C0032
FF80E890 3A800000
60000000 60000000
C2569DD8 00000004
C0030004 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C2569DB4 00000004
C0030014 3E808170
C3740000 EC1B0032
FF60E890 3A800000
60000000 60000000
C2580204 00000004
C0230024 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2580214 00000004
C0230028 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2580224 00000004
C023002C 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C2580234 00000004
C0230030 3E808170
C3940000 EC3C0072
FF80E890 3A800000
60000000 60000000
C25801E4 0000001D
C0230018 3E80809B
8294BD28 8294003C
82940000 82940000
82940000 A274000A
5673801E 2C130000
40820008 3E603F80
3E808170 92740000
3E600000 C3940000
EC3C0072 3E808160
3E6042D2 92740004
3E604296 92740008
3E604382 9274000C
3E604302 92740010
3E60491C 62734000
92740014 3E604302
92740018 60000000
C3D40004 EFDC07B2
3E608089 D3D34220
C3D40008 EFDC07B2
D3D33F10 C3D4000C
EFDC07B2 D3D34034
C3D40010 EFDC07B2
D3D34084 C3D40014
EFDC07B2 D3D34094
C3D40018 EFDC07B2
D3D33F1C 60000000
FFC0E890 3E600000
60000000 FF80E890
3A800000 60000000


Note: you need to edit the KMP of a SZS file to speed mod a track, you can do this with wszst:
wszst patch C:\Path\to\szs\file\Trackname.szs --speed-mod=factor
factor is a floating point value, For example: 1,2.
so normally you go 120 km/h with a shroom and with the speed mod 144 km/h

Code creator: MrBean35000vr
Code contributors: Geeh, MrEvil

Print this item

  Tutorial on the 'BL Trick' (ASM)
Posted by: zak - 12-05-2018, 02:52 AM - Forum: Guides/How-To's - No Replies

Efficiently Writing Long Strings Of Data to Memory ("BL Trick")

NOTICE: For coders who can already write loops but are dealing with a very large amounts of data that has to be written from 'scratch' before loading that data into a loop

There are multiple different ways to load/store large strings of data. Sometimes, a coder will push the stack, then use a lot of registers (up to r31) to write custom (from scratch) data to those registers. Then he/she will use a stmw (store multiple words) function to store a bunch of words at once to a final spot in memory. However, once a string of data gets too long, the stmw style of assembly will start to become inefficient/redundant...

Another not so efficient method, would be to use an empty spot in MKWii RAM. Write the string of data in the registers, store the data to the empty spot in memory. Then finally use a loop to load the custom string of data from the spot in RAM to another spot in memory

Too many unnecessary functions...

Before explaining what the BL Trick exactly is. Let's say we want to first custom write the following large string of data...

FFFF7777 AAAA1111 FFFF1111 22223333 44445555 66667777 88889999 AAAABBBB CCCCDDDD EEEEFFFF CCCC2222 11113333 

And our default list of instructions (first function is the default address)  is this...

80456CC0 lwz r4, 0 (r3)
80456CC4 stw r4, 0 (r5)
80456CC8 lwz r4, 0x4 (r3)
80456CCC stw r4, 0x4 (r5)
etc
etc til 10 words are loaded and stored.

Alright so a good way to make a code to manipulate what is written to r5, would be to write stuff to the address locations designated by r3, and let the game (on the following ASM functions), load the data from r3 into r4, then store it from r4 to r5.

r3 and r29 are both dynamic addresses, so we cannot simply write the memory address values for them in a plain sense.

Let's take a look of how an intermediate-level coder would attempt to write this assembly at code address 0x80456CC0...




##Setup a stmw function, write all the data from r20 through r31 beforehand, we obviously need to push the stack...##

stwu r1,-80(r1)
stmw r14,8(r1)

lis r20, 0xFFFF
ori r20, r20, 0x7777

lis r21, 0xAAAA
ori r21, r21, 0x1111

lis r22, 0xFFFF
ori r22, r22, 0x1111

lis r23, 0x2222
ori r23, r23, 0x3333

lis r24, 0x4444
ori r24, r24, 0x5555

lis r25, 0x6666
ori r25, r25, 0x7777

lis r26, 0x8888
ori r26, r26, 0x9999

lis r27, 0xAAAA
ori r27, r27, 0xBBBB

lis r28, 0xCCCC
ori r28, r28, 0xDDDD

lis r29, 0xEEEE
ori r29, r29, 0xFFFF

lis r30, 0xCCCC
ori r30, r30, 0x2222

lis r31, 0x1111
ori r31, r31, 0x3333

##Data writing is done, now write data to r3, to allow the game to normally load it into r4 then store it to r5##

stmw r20, 0 (r3)

##Now let the game do its work##

lmw r14,8(r1)
addi r1,r1,80

lwz r4, 0 (r3) #Default ASM




That snippet of code is very redundant. While the stmw is a good way to store data of consecutive registers to a spot in memory, there's a much more efficient way to write this assembly.

We do this with the BL Trick.

What we do on the BL Trick is setup a Branch & Link function right before our string of data. The label name for the BL function will be immediately after the string of data. We will write the string of data without using any registers. At this point you are probably saying "how is this possible?". 

Its possible due to what are called pseudo ops. Pseudo ops is a method to write strings of data in a spot of memory 100% manually without using functions w/ registers. To help you understand this more, we need to quickly talk about how Gecko (the universal code handler) applies your cheat codes from a GCT file.

When you have a cheat code on a GCT and the codes get hooked/loaded, what happens is that where ever your code address is.. a branch (backwards) function will jump to an early spot of memory (800022A8). At this point your ASM functions of that code are executed one address at a time. Then a branch (forewords) function will jump to where you left from (but one step later ofc).

For example:

We have this compiled code..
C24685A4 00000002
38600001 B06A0022
60000000 00000000

Here's what actually happens in the game when your ASM function gets called on...

Address     Instruction
804685A4   b => 0x800022A8
800022A8   li r5, 1
800022AC   sth r5, 0x22 (r10)
800022B0   nop
800022B4   b => 0x804685A8

And then you are back to your original routine at address 0x804685A8 and game continues as normal.

Objectively speaking, there is no such thing as an "Insert ASM" compiled code. You can't insert ASM into memory within memory itself. The code handler creates its own sub routine instead.

Going back to the BL Trick.. what we do is we write our string of data at the code handler's subroutine. Then we do some fancy Link Register stuff to point to the subroutine, then finally loading data into a loop to store it to r3.

First let's write our BL function. Obviously backup the original Link register beforehand...

mflr r11 #OG LR value backed up

bl our_link

The bl will make us jump to the our_link label and next address the bl function is stored in the Link Register.

Next, we will use the pseudo ops to write out our string of data. There are all kinds of pseudo ops. Let's go over a few...

.long - write a word of data in Hex
.llong - wirte a double word (back to back words) of data in Hex
.space X - X = bytes of zero to write
.string - write a string in plain text/ascii. Ascii will be auto converted to Hex when code is compiled.

We will be using .llong and .space for our assembly.

Before we start writing out our pseudo ops, lets think about our loop that we will use after the BL trick is done. Let's say our loop will be a 'subic.' type loop using the lwzu/stwu functions with increasing offsets of 0x4. Thus we need to compensate for this first offset of 0x4. We will need to write in a blank word of zeros first...

.space 4 #four bytes of zero written

Now we can finally write out our string of data....

.llong 0xFFFF7777AAAA1111
.llong 0xFFFF111122223333
.llong 0x4444555566667777
.llong 0x88889999AAAABBBB
.llong 0xCCCCDDDDEEEEFFFF
.llong 0xCCCC222211113333

Pseudo ops are completed. Keep in mind, every thing must be aligned by '4'. So lets pretend our '.space 4' op was a '.space 3', we would need to put a '.space 1' at the end for alignment purposes.

Next will be our label name. Then a mflr ASM function..

our_link:
mflr r12

What happens here is that the address in the code handler subroutine (immediately after the bl function) is moved from the link register to register 12. Register 12 now holds our loading address for the loop!

Now we can set up a simply bdnz type loop. The loading address is relative to r12, the storing address is relative to r3.

Let's setup the count register for the loop. Register 9 will be used...

li r9, 0xC #12 © words of data to be loaded then stored##

mtctr r9 #Move value of 0xC to the count register

We obviously need the address of r3 is be subtracted by 0x4 due to the stwu update function in our loop that will increase offset amount by 0x4. Let's use register 9 for that, we'll restore r9's original value after the loop is done (we will pretend r9's original value beforehand is 2).....

addi r9, r3, -0x4

Now for the loop!

loop_back:
lwzu r4, 0x4 (r12) #First word loaded is the 0xFFFF7777 from the first .llong psuedo op
stwu r4, 0x4 (r9) #r9 plus 0x4 is the address of r3 which is where we want our first word stored at
bdnz+ loop_back

Once the loop is over, restore the OG LR value, restore OG value of r9, and OG value of r3, execute the default ASM

li r9, 0x2 #lets pretend r9's OG value was 0x2 before we started using it as a countdown register
mtlr r11
lwz r4, 0 (r3)

Here's an overview of every ASM function we wrote:




mflr r11
bl our_link

.space 4
.llong 0xFFFF7777AAAA1111
.llong 0xFFFF111122223333
.llong 0x4444555566667777
.llong 0x88889999AAAABBBB
.llong 0xCCCCDDDDEEEEFFFF
.llong 0xCCCC222211113333

our_link:
mflr r12

li r9, 0xC
mtctr r9

addi r9, r3, 0x4

loop_back:
lwzu r4, 0x4 (r12) 
stwu r4, 0x4 (r9) 
bdnz+ loop_back

li r9, 0x2
mtlr r11
lwz r4, 0 (r3)




Comparison Length of Code / Conclusion

In our first example of the assembly, we did a redundant use of lis/ori with a stmw function. If we take the length of of the compiled code (as a C2 type), it is a total of 17 lines of compiled code.

The length of our improved (BL-trick) assembly is 14 lines of code. Thats 3 lines shorter than the original example.

So in conclusion, if you are dealing with large strings of data (around 5 words or more), you can probably shorten/optimize your code using the BL trick. Thanks for reading! Happy coding!

Print this item

  Creating Loops (Pt. 2)
Posted by: zak - 12-04-2018, 06:31 PM - Forum: Guides/How-To's - No Replies

Creating Loops Pt. 2

Part 2: Complex memcpy loops

NOTICE: This will be for veteran ASM coders, that are writing a code with multiple loops within...

If you have a very complex assembly code that has multiple loops. It may be best to use what are called memcpy loops. Instead of writing a bunch of separate loops, you will jump (call) to the game's built-in looping function every time a loop is needed to be executed.



Step 1. Backing up  Registers



The memcpy function makes use of the following registers: r0, r4, r5, r6. It would make sense to backup the original values of these registers beforehand. There are multiple ways to do that. Since a code that requires memcpy is already going to be very long and complex, you are probably already pushing the stack with this method HERE. You can push the stack, then move r0, r4 thru r6 to some upper registers for backup.

You can also use the following version of pushing the stack listed below to backup Registers 2 thru 31 (credits to Star for this snippet of code):

stwu r1,-0x80(r1)
stmw r2,8(r1)

...

lmw r2,8(r1)
addi r1,r1,0x80



Step 2. Preview of the memcpy loop function



In RAM, here are the following address with ASM functions of the memcpy loop function

80005F4C lbzu r0, 0x0001 (r4)
80005F50 stbu r0, 0x0001 (r6)
80005F54 subic r5, r5, 1
80005F58 bne+ -0xC ###if r5 not equal to zero, jump back to address 0x80005F4C###
80005F5C blr

As you can see, the memcpy function uses a 'subic.' type loop. You will also notice a blr function at the end. If you are reading this tutorial, you should already be able to understand the basic use of blr's.


Step 3. Setting up the appropriate Registers



Alright at this point r0, r4, r5, r6 should be backed up. 

We can tell that r4 represents to address to load data from. r0 is the regiser to temporarily hold said data. r6 is the register used for the storing address. r5 is used as the 'countdown' register telling the game how many times to execute the loop.

Let's say we have a string of data..

Address    Data
80002000 11112222
80002004 33334444
80002008 44445555
8000200C 66667777
80002010 88889999

We want to store these 5 words of data to the starting address of 81405000. Let's setup our loop...

lis r4, 0x8000
ori r4, r4, 0x19FC

Now we are going to set up the 'countdown' register which if r5 for memcpy. Memcpy uses lbzu & stbu instead of lwzu & stwu. Thus the offset value that memcpy uses for updating is 0x1 instead of 0x4. Therefore, we need to load the amount of bytes instead of words for register 5. 5 words of data is 20 bytes. 20 converted to Hex is 0x14. Load 0x14 into r5

li r5, 0x14

lis, r6, 0x8140
ori r6, r6, 0x4FFC

No need to edit in r0 ofc, as r0 will be the register used to temporarily hold the data for loading then storing.


Step 4. Calling the memcpy function



Alright our required registers are configured. Now let's call the loop function to get the loop going...

To call a function, we will set up a memory address value. That value will be the start of the memcpy, which is 0x80005F4C. We will use register 7 to set up this address.

lis r7, 0x8000
ori r7, r7, 0x5F4C

Next we need to move this address to the Link Register. You should always backup the original Link Register value first. Let's backup the OG Link Register value to register 8...

mflr r8

Now let's move r7 value (memcpy address) to the LR

mtlr r7

Time to call the function!!!

blr

Alright great, we are now at the first address of the memcpy function. But there's an issue. Can you figure it out?............Waits.....

The blr after our 'mtlr 7' is the issue. Let's pretend we continued on and did the memcpy loop. When the loop is finally done, it will (at address 0x80005F5C) call a blr. Well it will then jump back to 0x80005F4C, because that's the value that we currently have in the LR from the mtlr r7 function.

This will cause the loop to keep looping back forever... Thus, the game will freeze.


Step 5. Blrl



Welp blr won't work. So what can we do? We use the clever function blrl (Branch To Link Register Then Re-Link)

The blrl will branch to our link register address, and setup the LR to allow us to exit the loop once the memcpy's own blr is executed.

So instead of using blr, let's plug in a blrl instead. 

blrl

Before continuing, let's take a look at a portion of the game's memory pretending we are watching it step through function by function.. Obviously i will just throW in a list of random addresses..

800022C0 mtlr r7 #Moving memcpy address to LR
800022C4 blrl #Branch to memcpy then re-link (update LR) to address 0x800022C8
800022C8 stw r10, 0 (r29) #Random ASm placed here, has nothing to do with the loop.

So as our code is executing, we execute the blrl. At this point, we jump to the address in the LR (0x80005F4C), and at the same time the Link Register is now updated with the address 0x800022C8.

So once we execute the memcpy's own blr (once loop is done), we will be at address 0x800022C8 and the stw function will be executed (code continuing like normal)


Step 6. Conclusion



As you can see while this is complicated to setup. However, if you are using a lot of loops, this may come in handy and could shorten your overall length of code. Blrl is not really used in any mkwii codes, as its only needed in very complex function-jumping within a length ASM code.

Lets take a final look at all our instructions put together...

##some ASM here##

lis r4, 0x8000 #Set up 1st half address for updating Loading Adress
ori r4, r4, 0x19FC #Set 2nd half address for Loading Address

li r5, 0x14 #Load 0x14 into the 'countdown' register

lis, r6, 0x8140 #Set up 1st half address for updating Storing Address
ori r6, r6, 0x4FFC #Set up 2nd half address for updating Storing Address
 
lis r7, 0x8000 #Set up 1st half address of memcpy function
ori r7, r7, 0x5F4C #Set up 2nd half address of memcpy function
 
mflr r8 #Backup OG Link Register

mtlr r7 #Copy memcpy address to the Link Register

blrl #Branch to Link Register Then Re-Link! (we are now at memcpy, even though you cannot see it)

##some ASM here##

mtlr r8 #Restore OG LR's value



Thanks for reading! For a 'real word' example/demonstration. I took this code HERE and 'converted' it to call memcpy instead of writing a 'subic.' type loop from scratch.

(left address blank; using 01230123012301230123456789905 as the Mii Name)
C2000000 00000010
9421FF80 BC410008
7CE802A6 38C30067
48000045 00003000
31003200 33003000
31003200 33003000
31003200 33003000
31003200 33003000
31003200 33003400
35003600 37003800
39003900 30003500
00000000 7C8802A6
38A0003C 3D008000
61085F4C 7D0803A6
4E800021 7CE803A6
B8410008 38210080
8003006C 00000000

Source (using 01230123012301230123456789905 as the Mii Name):

####################
###START ASSEMBLY###
####################

#

####################
##Register Storage##
####################

stwu r1,-0x80(r1)
stmw r2,8(r1)

mflr r7 #Backup original Link Register into Register 7

################################################
##Address Config For Loop Mem Storage Location##
################################################

addi r6, r3, 0x0067 #Add 0x67 to value of r3 to setup proper address location in register 6 for upcoming memcpy loop

#########################################################
##Setup Loading Address Relative to the Program Counter##
#########################################################

##Following address after the 'bl' function will be stored in the link register##
##This will allow us to use it to later load the mii data into the loop##

bl link_label #branch to link_label, store address of link_label to the link register

################################
##Pseudo Ops (Mii Data Table)##
################################

##psuedo ops listed below are the mii data characters##
##Space value is for bytes of zeros##
##.llong is to put in a doubleword##
##.long is to put in a normal word##

##The .space 1 is put in because the first loaded address in the loop uses an offset of 0x1##
##So one bytes of zeros are needed to be added beforehand##

.space 1
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0034003500360037
.llong 0x0038003900390030
.long 0x00350000
.space 3

##The 0x0000 is added after the final ascii character to be used to tell the loop to stop loading data##
##The last .space 3 is for alignment reasons##

##############
##Link Label##
##############

##Now that we have our address that is at the start of the Mii Data table...##
##We want to move that address from the LR to r4 to begin loading data from it to the loop##

link_label:
mflr r4 #Move address that is 0x4 before the mii data from the link register to register 4

###########################
##Preparing Function Call##
###########################

li r5, 0x003C

lis r8, 0x8000
ori r8, r8, 0x5F4C
mtlr r8

####################################
##Calling Memcpy; Creating Re-Link##
####################################

blrl

###############################################
##Post Loop; Restore Original Register Values##
###############################################

mtlr r7 #Restore original Link Register

lmw r2,8(r1)
addi r1,r1,0x80

###############
##Default ASM##
###############

lwz r0, 0x006C (r3) #Default ASM

#

##################
###END ASSEMBLY###
##################

Code creator: zak
Code contributor(s): Star (used his Mii Extender code to setup a Write Breakpoint)

Print this item

  Creating Loops (Pt. 1)
Posted by: zak - 12-04-2018, 03:54 AM - Forum: Guides/How-To's - No Replies

Creating Loops (Pt. 1)


Part 1: Simple Loop Creation



This thread will teach a coder how to write basic loops in Power PC ASM.

For this tutorial, we have a string of data starting at memory address 0x80002000.

The string of data is this..

Address    Data
80002000 11112222
80002004 33334444
80002008 44445555
8000200C 66667777
80002010 88889999

The following string of data is a total of 5 words in length (or 10 halfwords, or 20 bytes)

We want to copy this data to starting memory address 0x81405000

When dealing with data longer than 64 bits in length (two words), it's best to copy the data via a loop instead of using load-store functions over and over again.

There are 3 types of loops:
The 'subic.' type loop
The 'bdnz' type loop
Call memcpy function loop (will not be covered in this thread, as it's vastly more complicated than the other 2 loops)

For both 'subic.' and 'bdnz' type loops, we will use load word update and store word update (can also be used for halfwords or bytes). If you are not familiar with this functions, view the simple asm reference page HERE (scroll down to lwzu & stwu)




Subic. Loop




The 'subic.' loop is the easiest loop to create in my opinion. You use an available register as a 'counter/countdown' tracker to tell the loop how many times to repeat. Once this 'countdown' register hits zero, the loop will stop. The amount in the countdown register you use is dependent on how many words/halfwords/bytes you are loading/storing. For this example, we will stick with words. Since we have 5 words total, we will load the value of 5 into our countdown register. Let's pretend our countdown register is register 14. Thus, let's load 0x5 into r14

li r14, 0x5

Our countdown register is set. Obviously we need to setup the proper memory locations for where we are loading data from, and where we are storing that data too. Let's say we want to use register 15 as the address we want to being loading the string of data from.  So...

lis r15, 0x8000
ori r15, r15, 0x2000

And we're good. Or are we??? Actually, this is not correct. When you execute a lwzu, you need to have some sort of offset so the address can be incremented every time the lwzu is executed. Since we are dealing with words, its pretty obvious that offset will be 0x4. So every time 0x4 is added to the address, we are at the next word in memory to load data from. 

But this is an issue if r15 is 80002000 as the first time the lwzu is executed, we will load from address 800020004 (incorrect). Thus we need to initially set our loading addresss just -0x4 away from 80002000 which is 800019FC. Let's fix r15

lis r15, 0x8000
ori r15, r15, 0x19FC

OK, now we must apply that same logic to the address where we first store the data to.... We will use r16 for our address for storing.

lis r16, 0x8140
ori r16, r16, 0x4FFC

Notice that 81404FFC is -0x4 from 81405000.

Alright perfect, we have our beginning loading and storing addresses. Our countdown register is set. Now before we start the loop we need a register to hold the data temporarily when loading/storing. We will use r17 for that... Ok now let's get this loop started, here's how it would be configured.

loop_back
lwzu r17, 0x0004 (r15)
stwu r17, 0x0004 (r16)
subic. r14, r14, 1
bne+ loop_back

As you can see with the 'subic.' function, r14 is subtracted by 0x1 every time the loop is executed. The 'subic.' has a Record function in itself. This record function is shortcut for cmpwi r14, 0x0.

Obviously, if r14 is not equal to 0, we will jump back to the start of the loop. Once r14 equals 0, we know that all 5 words of data are loaded and stored. Thus the jump to loop_back will not occur and the code will continue on.

Let's put all our functions together...

##some other ASM here##

li r14, 0x5

lis r15, 0x8000
ori r15, r15, 0x19FC

lis r16, 0x8140
ori r16, r16, 0x4FFC

loop_back:
lwzu r17, 0x0004 (r15)
stwu r17, 0x0004 (r16)
subic. r14, r14, 1
bne+ loop_back

##some other ASM here##

Alright, there you have it. A working model of the 'subic.' loop.




BDNZ Loop





The bdnz loop is a bit different. It requires the use of what is called the Count Register (CTR for short). The CTR is a register specifically designed to hold the countdown value of a loop. 

If we used this type of loop, we need to load our countdown value into r14 and then copy it to the CTR. Like this...

li r14, 0x5
mtctr r14

Alright, CTR has the value of 5. Of course, in this type of loop we don't need a 'subic.' function but the use of lwzu and stwu ASM functions are still required. Instead of there being a 'bne' to use as a conditional jump, we will use 'bdnz' instead.

bdnz some_label_here = Branch Decrement When Not Zero; This literally means, decrement (subtract) the CTR by 1, then branch to the desired label, if and only if the CTR is not equal to zero. 

Example of our first loop converted to a bdnz type....

##some other ASM here##

li r14, 0x5
mtctr r14

lis r15, 0x8000
ori r15, r15, 0x19FC

lis r16, 0x8140
ori r16, r16, 0x4FFC

loop_back:
lwzu r17, 0x0004 (r15)
stwu r17, 0x0004 (r16)
bdnz+ loop_back

##some other ASM here##



Conclusion




And there ya go. A guide on how to create simple loops in PPC ASM. To dive into the realm of complex memcpy loops please go to Part 2 - HERE

Print this item

  ASM Tips n Trix
Posted by: zak - 12-04-2018, 02:44 AM - Forum: Guides/How-To's - No Replies

ASM Tips n Trix

This thread will be a list of mini-guides/tips to help shorten or optimize your ASM codes. This is tailored towards a coder who recently started learning/utilizing ASM.




I. Using Offset Values to complete Memory Addresses

Let's say we want to load a word from the memory address 0x80001650. A beginner might write the following functions....

lis r12, 0x8000
ori r12, r12, 0x1650
lwz r11, 0 (r12)

This is not completely optimized. The use of the ori function is not needed. We can shorten this...

lis r12, 0x8000
lwz r11, 0x1650 (r12)

As you can see, the offset value was used to complete the 2nd half of the memory address. Keep in mind, you cannot exceed the value 0x7FFF for offsets, so this method won't work for a memory address such as 8045FFBF.




II. 'Register into a Register'

Let's say we have a code where we use Register 12 to load a word from and place it into Register 11...

lwz r11, 0x00AB (r12)

However, after this function, let's pretend we are no longer obligated to use Register 12. Well then there's no need to waste the use of Register 11, especially if we need that register for later. Therefore you should do this instead....

lwz r12, 0x00AB (r12)

Now we aren't wasting the use of Register 11.




III. Using a singular lis function for multiple loading/storing

Let's say we have the following functions...

lis r12, 0x8000
lwz r11, 0x1500 (r12)
lis r10, 0x8000
lwz r9, 0x1800 (r10)

We have a redundant ASM. We are executing the same lis function in two different registers. This is a waste of code. Use this instead...

lis r12, 0x8000
lwz r11, 0x1500 (r12)
lwz r9, 0x1800 (r12)

Now we saved the use of Register 10.




IV. Changing '3-Liner' stw-lwz ASM codes to 'Single Liner' li Type

We have the following list of functions..

li r5, 0xC
stw r5, 0x177B (r30)
lwz r5, 0x177B (r30)

This is redundant. There's no need to take our r5 value, store it to memory, and then immediately load it back from memory. Remove both the stw and lwz functions. You are left with this...

li r5, 0xC

In rare cases, some codes may require the stw-lwz functions back to back (like this code HERE). There's really no way (other than testing) to tell if a code stw-lwz won't work as a singular li function.




V. Optimizing Branch Routes

We have the following ASM...

cmpwi r21, 0x1
beq- the_label
b finish_code

the_label:
li r28, 0x14

finish_code:
stb r28, 0x2 (r30)

This is not fully optimized branch routing. There's no need to have two label names, you can do this instead...

cmpwi r21, 0x1
bne+ finish_code

li r28, 0x14

finish_code:
stb r28, 0x2 (r30)

As you can see if r21 is equal to one, it will continue down to the li function. This is more efficient that making two whole separate branch labels/routes.



VI. Avoiding Pushing/Popping the Stack

What some beginner coders will do (when needing extra registers in a code) is use the method of 'pushing/popping' the stack. Info for this is HERE. This will cause any code to naturally have more lines of compiled code. It is nice to have free registers, but if you are wanting to cut down the length of code, you should avoid the push/pop stack method.

We know Register's 11 and r12 are always free for use without restoration (99% of the time). You can also use a volatile register (r3 thru r10), and restore their original values at then end of your code. However, finding a volatile register to have the same value every time is the ASM function is executed (test this via a breakpoint over and over again), is actually rare.

Instead, you can use more registers (without restoring their original values), by looking ahead at further asm functions in comparison to your code's address. For example...let's say we have a code address of 0x80456000, and we have the following addresses plus ASM functions.

0x80456000 lwz r4, 0 (r5) #Default ASM
0x80456004 add r23, r6, r9
0x80456008 mflr r0
0x8045600C cmpwi r31, 0x1

If you have a code that is a loading type function (lwz, lhz etc) as the default address, and you are able to have the default asm at the end of the code, you can use r4 (for our example). r4 is free w/o restoration because it will get written to anyway.

r23 is also free, because it will get written to later. Same with r0. Obviously, we can't use r5, r6, r9, r31, because they are being used as variables for the functions. So even using them with restoring their original values is really not safe.

So with the functions listed above, our list of free registers would be r0, r4, r11, r12, and r23. Which will most likely be enough to not have to push/pop the stack.




VII. Optimizing conditions with the Record (dot) function

We have the following ASM...

lwz r5, 0xBAAE (r31)
add r6, r6, r5
cmpwi r6, 0x0
bne+ some_label

Certain ASM functions can have a dot (.) added to them. This is known as 'Record'. Record is a shortcut for cmpwi rD, 0x0. D = Whatever register you are using for the comparison. Please not that there's no way I can list all the functions that do or do not have the Record option. Refer to a full ASM handbook for assistance.

The add ASM function has the ability to add this Record feature. Like this...

lwz r5, 0xBAAE (r31)
add. r6, r6, r5
bne+ some_label

We now got rid of an unnecessary line of code.




VIII. Writing Activators/Deactivators within an ASM correctly

We have an ASM (NTSC-U code) where we will set a controller address (GCN), and we will load the button value (ZZZZ value; halfword) from the NTSC-U GCN contorller address. We want the use the Y button (0x0880 value) to jump to the_label in our ASM, so we have this snippet of code...

lis r12, 0x8034
lhz r11, 0x3E80 (r12)
cmpwi r11, 0x0880
beq- the_label

While this ASM will work, it will not allow a user to hold other buttons while pressing the Y button to get the ASM to jump to the_label within the code. In order for us to have this feature of being allowed to hold other buttons, we need to use what is called a Logical AND. Like this....

lis r12, 0x8034
lhz r11, 0x3E80 (r12)
and r11, r11, 0x0880
cmpwi r11, 0x0880
beq- the_label

Even though this snippet of code is one line longer, we now gain the ability to allow a user to hold other buttons while pressing the Y button.

Print this item

  Mii Name Extender (zak's version)
Posted by: zak - 12-03-2018, 05:19 PM - Forum: Incomplete/Outdated Codes - No Replies

Mii Name Extender (zak's version)

NOTE: Outdated by Star's version. Star's version is shorter and it's region free.

This code will allow you to put in a custom Mii name when online. Only you can see it. You also have the ability to extend the max length of the Mii name from 10 to 29 characters. If you don't want the max length, just fill in the unused values with 0's.

Also, this may not work on all MKW servers (such as Wiimmfi). There's no point adding button activators to this if the code isn't working on a particular MKW server as the ASM function gets called upon selecting your license during the MKWii main menu.

NTSC-U
C25DA7B0 0000000E
7C0802A6 39230066
48000045 0000XWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
00000000 7D8802A6
A56C0002 B5690002
2C0B0000 4082FFF4
7C0803A6 39200000
8003006C 00000000

PAL
C25FB094 0000000E
7C0802A6 39230066
48000045 0000XWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
00000000 7D8802A6
A56C0002 B5690002
2C0B0000 4082FFF4
7C0803A6 39200000
8003006C 00000000

NTSC-J
C25FA970 0000000E
7C0802A6 39230066
48000045 0000XWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
00000000 7D8802A6
A56C0002 B5690002
2C0B0000 4082FFF4
7C0803A6 39200000
8003006C 00000000

NTSC-K
C25E94B4 0000000E
7C0802A6 39230066
48000045 0000XWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
XWYZXWYZ XWYZXWYZ
00000000 7D8802A6
A56C0002 B5690002
2C0B0000 4082FFF4
7C0803A6 39200000
8003006C 00000000

XWYZ = Mii Character ASCII Value

Example ASCII Values:
0020 = Space
0041 = A
0061 = a
E017 = DSi Heart

Use 0000 for unfilled values if you don't want to use the full length of 29 characters.




Source (using 01230123012301230123456789905 as the Mii Name):

####################
###START ASSEMBLY###
####################

#

############################
##OG Link Register Storage##
############################

mflr r0 #Backup original Link Register into Register 0

################################################
##Address Config For Loop Mem Storage Location##
################################################

addi r9, r3, 0x0066 #Add 0x66 to value of r3 to setup proper address location in register to upcoming updating-loop

#########################################################
##Setup Loading Address Relative to the Program Counter##
#########################################################

##Following address after the 'bl' function will be stored in the link register##
##This will allow us to use it to later load the mii data into the loop##

bl link_label #branch to link_label, store address of link_label to the link register

################################
##Pseudo Ops (Mii Data Table)##
################################

##psuedo ops listed below are the mii data characters##
##Space value is for bytes of zeros##
##.llong is to put in a doubleword##
##.long is to put in a normal word##

##The .space 2 is put in because the first loaded address in the loop uses an offset of 0x2##
##So two bytes of zeros are needed to be added beforehand##

.space 2
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0030003100320033
.llong 0x0034003500360037
.llong 0x0038003900390030
.long 0x00350000
.space 2

##The 0x0000 is added after the final ascii character to be used to tell the loop to stop loading data##
##The last .space 2 is for alignment reasons##

##############
##Link Label##
##############

##Now that we have our address that is at the start of the Mii Data table...##
##We want to move that address from the LR to r12 to begin loading data from it to the loop##

link_label:
mflr r12 #Move address that is 0x4 before the mii data from the link register to register 12

############
##The LOOP##
############

loop_back:
lhzu r11, 0x0002 (r12) #Grab first mii data character halfword, then increment r12 address by 4 to grab next half word
sthu r11, 0x0002 (r9) #Store first mii data halfword to proper spot in memory, then increment r9 by 4 for when next character is stored
cmpwi r11, 0x0 
bne+ loop_back #If halfword is 0000 (null; provided by the code), we know to stop the loop and continue to next asm. if not equal to 0000, we start the loop over again

###############################################
##Post Loop; Restore Original Register Values##
###############################################

mtlr r0 #Restore original Link Register

li r9, 0x0 # Restore original value to r9 for game safety

###############
##Default ASM##
###############

lwz r0, 0x006C (r3) #Default ASM

#

##################
###END ASSEMBLY###
##################

Code creator: zak
Code contributor(s): Star (used his Mii Extender code to setup a Write Breakpoint)

Print this item

  Custom Friend Code Value For Friend Roster
Posted by: zak - 12-02-2018, 01:28 AM - Forum: Cheat Codes - No Replies

Custom Friend Code Value For Friend Roster

This code will allow you to put in a fully customized FC value for all friends of your friend roster. If you use the code without a full list of 30 friends, the rest of your list will be filled up with "?"'s for Mii images using the FC you put in the code.

NTSC-U
C25C57BC 00000004
3D80XXXX 618CWWWW
91840000 3D80YYYY
618CZZZZ 91840004
7C03002E 00000000

PAL
C25D28D8 00000004
3D80XXXX 618CWWWW
91840000 3D80YYYY
618CZZZZ 91840004
7C03002E 00000000

NTSC-J
C25D21B4 00000004
3D80XXXX 618CWWWW
91840000 3D80YYYY
618CZZZZ 91840004
7C03002E 00000000

NTSC-K
C25C0A74 00000004
3D80XXXX 618CWWWW
91840000 3D80YYYY
618CZZZZ 91840004
7C03002E 00000000

XXXXWWWWYYYYZZZZ = Desired FC value in Hex

Example: You want 0123-4567-8901 for the FC. The decimal value is 012345678901, put that number into a Dec to Hex converter. Hex value is 2DFDC1C35. Now fill in the missing zero's beforehand to get your 64 bit Hex value to put in code. Final XWYZ Hex value would be 00000002DFDC1C35.

Source:
lis r12, 0xXXXX #Load XXXX value into upper 16 bits of r12, lower 16 bits are cleared
ori r12, r12, 0xWWWW #Load WWWW value into lower 16 bits of r12
stw r12, 0 (r4) #Store the word of r12 to address of r4
lis r12, 0xYYYY #Load YYYY value into upper 16 bits of r12, lower 16 bits are cleared
ori r12, r12, 0xZZZZ #Load ZZZZ value into lower 16 bits of 12
stw r12, 0x0004 (r4) #Store the word of r12 to address of r4 plus offset of 0x4
lwzx r0, r3, r0 #Default ASM

Code creator: zak

Print this item

  Custom Globe Location For Friend Roster
Posted by: zak - 12-02-2018, 01:18 AM - Forum: Cheat Codes - No Replies

Custom Globe Location For Friend Roster

This code will allow you to put in any globe location value you want for all friends of your friend roster online.

NTSC-U
C25C57C4 00000003
7C600379 3D80ZZZZ
618Czzzz 9184007C
60000000 00000000

PAL
C25D28E0 00000003
7C600379 3D80ZZZZ
618Czzzz 9184007C
60000000 00000000

NTSC-J
C25D21BC 00000003
7C600379 3D80ZZZZ
618Czzzz 9184007C
60000000 00000000

NTSC-K
C25C0A7C 00000003
7C600379 3D80ZZZZ
618Czzzz 9184007C
60000000 00000000

ZZZZzzzz = Globe Location Value

Source:
or. r0, r3, r0 #Default ASM

lis r12, 0xZZZZ #Load ZZZZ value into upper 16 bits of Register 12, lower 16 bits are cleared

ori r12, r12, 0xzzzz #Load zzzz value into lower 16 bits of Register 12

stw r12, 0x007C (r4) #Store the word of Register 12 to address of Register 4 plus offset 0x7C

Code creator: zak

Print this item