Mii Tag Name Changer
#1
For this code I want to move the Mii Name by a certain amount of digits to add a tagname (I don't really know what it is called, the clan name thing). I have looked at Anarion's Mii Name Changer Code https://mkwii.com/showthread.php?tid=838 and noticed that you store the Mii Name to the memory location stated at  register 30 using the lis and ori functions at r4. But then I don't understand what happens next. Would you say I am not quite ready to make a code yet an should reread the ASM tutorials or is it the case that I just need some practice?

It seems to me that you are storing the mii name to many different addresses after the original value in r30 like a RAM write code, but then you store the address at r30 to r4 but it seems to me that you didn't change that address. That is the confusing part. As you can probably tell I'm not a natural at this kinda stuff I have to do something many times for it to sink in.
Reply
#2
Q - Would you say I am not quite ready to make a code yet an should reread the ASM tutorials or is it the case that I just need some practice?

A- I say you are ready. When learning any ASM to make codes, you will hit a lot of mental barriers per say. You will get stuck on a specific step for a while, then sort of out of nowhere, you will get a lightbulb-over-your-head moment. Then realize that the step you were on was actually easy. I personally got stuck on so many tasks when Star was teaching me ASM over a year ago.

Here's my attempt to explain each step of the source for you and why certain instructions+values were written. Read through this slowly.

Mii Names are done in ASCII. Look up ASCII to hex/hex to ASCII converter. Example: 0x30 equals 0

However with MKWii (to incorporate Japanese letters, and special symbols), the game uses 16 bit ASCII (halfwords) instead of 8 bit (bytes).

What does this mean? 0x0030 = 0 (Each ASCII Mii name character is a halfword in length)

Source (0123456789 used as the Mii Name):

So the Mii name in hex for the source is this 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039

Each two ASCII characters take one word of space in memory. The whole Mii name is 5 words in length



Here's the source with better notes....

lis r4, 0x0030 #As you can see we first set the very first ASCII character of the name. We set this to the upper 16 bits of the register, because we want to store one word at a time to keep this code efficient instead of storing halfword after halfword

ori r4, r4, 0x0031 #Next we set the next ASCII character in the same register. Now r4 = 00300031
stw r4, 0x2 (r30) #r30 is like our memory pointer, it is in reference to where in dynamic memory we have to store our ASCII characters to, it's r30 due to the default instruction (founded by the Read BP) below. We store 00300031 to dynamic memory.

lis r4, 0x0032 #Now we continue to set the 3rd ASCII character, we can use r4 again because we already stored the previous two characters
ori r4, r4, 0x0033 #For 4th ASCII character
stw r4, 0x6 (r30) #Store 3rd & 4th ASCII characters to dynamic memory. Notice how the offset value in this stw instruction is bumped up to 0x6 instead of being 0x2? That's because we already stored the first word. A word is 4 bytes in length. So we increase the offset by 0x4 everytime we store a new word for the Mii name

lis r4, 0x0034 
ori r4, r4, 0x0035 
stw r4, 0xA (r30) #0x6 + 0x4 = 0xA

lis r4, 0x0036 
ori r4, r4, 0x0037 
stw r4, 0xE (r30) #0xA + 0x4 = 0xE

lis r4, 0x0038 
ori r4, r4, 0x0039 
stw r4, 0x12 (r30)  #0xE + 0x4 = 0x12

lhz r4, 0 (r30) #Default instruction; At this point you are probably confused why the default instruction loads the halfword value with no offset. Well with Mii data, there is a halfword (0x2) of other data that comes before the start of the mii name. In this instruction the game is loading all the Mii data. Thus it starts at the very beginning of the data. 




r30 directly points to that beginning. So the start of the mii name is 0x2 in reference to r30. Hence why the very first stw instruction above is stw r4, 0x2 (r30)

In regards to register safety: we can use r4, because a value is loaded into it anyway by the default instruction at the very end of the source.

Visual example: Launch Dolphin. Go to Options, then Hotkey settings. Under General tab, set an unused key (I use '9') for Toggle Pause. Go to Debugging tab, set an unused key (I use 'M') for Step Into. Save and close window.

You're PAL right? Apply the PAL code in the cheat manager of your dolphin. Launch the game, the moment it launches to the wii remote boot strap screen, pause the emulation (using w/e hotkey you set for Toggle Pause). Set an Instruction BP to 800C6DD8. I can't exactly remember, but I think the address will break after the wii remote screen, or right before you see the licenses.

The game will pause due to the BP. You are at the code's address (but there's a branch instruction instead of the default instruction). Open up Aldelaro5's ram viewer. Make sure you can see the Code View, Registers, and the RAM viewer all at once. Now, press your hotkey for Step-Into. You will branch to an area in memory around 0x800022A0 (can't exactly remember). You are at the subroutine that the gecko code handler has created for the ASM code. Now to step to each next instruction, just press your hotkey again. And watch the registers, plus the RAM viewer while you are stepping. 

This is called step-by-step testing, which is a very good visual aid to debug/analyze an ASM Code.

Hopefully this will help you  Smile And then you can work on the code you described.
Reply
#3
(08-04-2019, 01:34 PM)zak Wrote: Q - Would you say I am not quite ready to make a code yet an should reread the ASM tutorials or is it the case that I just need some practice?

A- I say you are ready. When learning any ASM to make codes, you will hit a lot of mental barriers per say. You will get stuck on a specific step for a while, then sort of out of nowhere, you will get a lightbulb-over-your-head moment. Then realize that the step you were on was actually easy. I personally got stuck on so many tasks when Star was teaching me ASM over a year ago.

Here's my attempt to explain each step of the source for you and why certain instructions+values were written. Read through this slowly.

Mii Names are done in ASCII. Look up ASCII to hex/hex to ASCII converter. Example: 0x30 equals 0

However with MKWii (to incorporate Japanese letters, and special symbols), the game uses 16 bit ASCII (halfwords) instead of 8 bit (bytes).

What does this mean? 0x0030 = 0 (Each ASCII Mii name character is a halfword in length)

Source (0123456789 used as the Mii Name):

So the Mii name in hex for the source is this 0030 0031 0032 0033 0034 0035 0036 0037 0038 0039

Each two ASCII characters take one word of space in memory. The whole Mii name is 5 words in length



Here's the source with better notes....

lis r4, 0x0030 #As you can see we first set the very first ASCII character of the name. We set this to the upper 16 bits of the register, because we want to store one word at a time to keep this code efficient instead of storing halfword after halfword

ori r4, r4, 0x0031 #Next we set the next ASCII character in the same register. Now r4 = 00300031
stw r4, 0x2 (r30) #r30 is like our memory pointer, it is in reference to where in dynamic memory we have to store our ASCII characters to, it's r30 due to the default instruction (founded by the Read BP) below. We store 00300031 to dynamic memory.

lis r4, 0x0032 #Now we continue to set the 3rd ASCII character, we can use r4 again because we already stored the previous two characters
ori r4, r4, 0x0033 #For 4th ASCII character
stw r4, 0x6 (r30) #Store 3rd & 4th ASCII characters to dynamic memory. Notice how the offset value in this stw instruction is bumped up to 0x6 instead of being 0x2? That's because we already stored the first word. A word is 4 bytes in length. So we increase the offset by 0x4 everytime we store a new word for the Mii name

lis r4, 0x0034 
ori r4, r4, 0x0035 
stw r4, 0xA (r30) #0x6 + 0x4 = 0xA

lis r4, 0x0036 
ori r4, r4, 0x0037 
stw r4, 0xE (r30) #0xA + 0x4 = 0xE

lis r4, 0x0038 
ori r4, r4, 0x0039 
stw r4, 0x12 (r30)  #0xE + 0x4 = 0x12

lhz r4, 0 (r30) #Default instruction; At this point you are probably confused why the default instruction loads the halfword value with no offset. Well with Mii data, there is a halfword (0x2) of other data that comes before the start of the mii name. In this instruction the game is loading all the Mii data. Thus it starts at the very beginning of the data. 




r30 directly points to that beginning. So the start of the mii name is 0x2 in reference to r30. Hence why the very first stw instruction above is stw r4, 0x2 (r30)

In regards to register safety: we can use r4, because a value is loaded into it anyway by the default instruction at the very end of the source.

Visual example: Launch Dolphin. Go to Options, then Hotkey settings. Under General tab, set an unused key (I use '9') for Toggle Pause. Go to Debugging tab, set an unused key (I use 'M') for Step Into. Save and close window.

You're PAL right? Apply the PAL code in the cheat manager of your dolphin. Launch the game, the moment it launches to the wii remote boot strap screen, pause the emulation (using w/e hotkey you set for Toggle Pause). Set an Instruction BP to 800C6DD8. I can't exactly remember, but I think the address will break after the wii remote screen, or right before you see the licenses.

The game will pause due to the BP. You are at the code's address (but there's a branch instruction instead of the default instruction). Open up Aldelaro5's ram viewer. Make sure you can see the Code View, Registers, and the RAM viewer all at once. Now, press your hotkey for Step-Into. You will branch to an area in memory around 0x800022A0 (can't exactly remember). You are at the subroutine that the gecko code handler has created for the ASM code. Now to step to each next instruction, just press your hotkey again. And watch the registers, plus the RAM viewer while you are stepping. 

This is called step-by-step testing, which is a very good visual aid to debug/analyze an ASM Code.

Hopefully this will help you  Smile And then you can work on the code you described.

Great, thank you so much!!
Reply
#4
After a lot of head scratching I have still got no further. I am having difficulty trying to move the current Mii name data to a place where I can manipulate it. I get it is the value stored at register 30 but that address is dynamic and therefore always changing. I wish to move the current data then shift it enough to allow space for the tagname. Any ideas?
Reply
#5
You will need to do this...

Create a loop counting the amount of bytes in length of your entire clan tag is (ex: TC* = 3 ascii chars = 3 halfwords = 6 bytes)

let's say you use r10 for the loop counter. r10 would be 6

Next, you need to set another loop using the 0x6 as a countdown tool (either using a subic. type loop, or bdnz/ctr type loop). This loop will load each byte of the mii name and restore it 0x6 further in memory.

You will need to implement some check to make sure the mii name won't go past 10 characters

Once is Mii name is restored, simply store the clan tag at the beginning (0x2 in reference to r30)

In the source I made for the NoSSL code, i used what you need - https://mkwii.com/showthread.php?tid=56&...ght=no+ssl

For the NoSSL code, change the code's address to the PAL shared item address (0x807BA164), set an Instruction BP on it like how i taught you. then step thru the source. (go to offline race, either your or CPU hit box, BP will occur). write down any notes that you need when stepping thru

For more info on loops - https://mkwii.com/showthread.php?tid=975
Reply
#6
You need a bp right before the codes loop after you step, once after the first BP is set due to box pickup.

-Zak
Reply
#7
Ty Dorian for relaying my message.

Here's a better explanation

You can't step thru the entire code cuz it scans all of mem80 so it would take literally days to step thru.

So after ur shared item code address BP. Just step once. You are at the codes subroutine. Then u need to set a second BP

The second BP you set is for 'the_loop' (2nd loop listed) of the NoSSL source. Right after the Li r3, 0

After u set the 2nd BP, resume emulation. The game will then stop at the 2nd BP. Now u can finally do normal step by stepping.
Reply
#8
Woah, my mind is blown.
Reply
#9
You've probably noticed by now, that while ASM itself is pretty much all simple instructions (add, multiply, branch, compare, subtract, etc), putting various instructions together to preform a designated task can be quite the challenge.

I've already recommended doing step-by-step testing to help you understand more. Another thing you can do is take a look at some of my older/simpler ASM writes. Those ASM codes are much easier to understand. 

Here's a quick source I typed up, I didn't bother analyzing anything on Dolphin. This will give you an idea of how to start writing ASM and an idea of how to make the loops I was talking about earlier.



First thing's first, we need an area of memory for the user to fill in the name/clan tag they want. We will set a limit of 3 ASCII characters on it. We need a space in memory that never gets written to. An area of memory that fulfills this requirement is the Exception Vectors Areahttp://mkwii.com/showthread.php?tid=1106

Considering 3 MKWii ASCII characters is 6 bytes of length, let's use memory addresses 0x80000A00 thru 0x800000A05. We can let the user set this value via two gecko-type RAM writes. We can load the values from the Exception Vector Area with the ASM code later. We cannot use a singular 32 bit (word) RAM write, because 6 bytes is more than a word in length.

RAM Writes
04000A00 XXXXYYYY
02000A04 0000ZZZZ

These RAM Writes will write the word XXXXYYYY at addresses 0x80000A00 thru A03. And halfword ZZZZ at 0x80000A04 thru A05.

--

Alright now onto the ASM code itself. Similar to the Mii name changer code, we will have the default instruction at the end, so it allows the game to load the new mii name (after changes were made) and allows us to use register 4 safely.

As per Register Safety protocol - HERE , we can always use r11 and r12. So we already have 3 registers at our disposal. However, to not worry about register safety, we will use what is called stack pushing/popping. Instructions to do this are also explained in the protocol thread..

Onto the source...

First thing's first, lets push the stack so we can freely use r14 thru r31.

stwu r1,-80(r1) # make space for 18 registers
stmw r14,8(r1) # push r14-r31 onto the stack


Next, let's grab the user's name/clan tag from the Exception Vector Area. We need to set a register to represent the beginning memory address of where the name/clan tag is. Let's use r14 for that...

lis r14, 0x8000 #Set upper 16 bits of r14 to 0x8000
ori r14, r14, 0x0A00 #Set lower 16 bits of r14 to 0x0A00

The ori is an unneeded instruction (there's a more optimized way to do this), but since you are a beginner let's keep it simple

lwz r15, 0 (r14) #The user's XXXXYYYY value is now in r15
lhz r16, 0x4 (r14) #User's ZZZZ value is now in r16

Alright at this point, we need to load our current Mii name and re-store back into dynamic memory (6 bytes further). We can't store the mii tag first, because we will lose part of our Mii name.

Now it's time for a loop. If you had read the Loop Pt1 thread, you will know we need to make our first loading loop address -0x4 in reference of what word we wanna load first.

Mii name starts at 0x2 in reference to r30. So.... 0x2 minus 0x4 = negative 0x2. Let's use r17 for that

addi r17, r30, -0x2

#r17 is set. Now we need a storing address. We need to store every Mii name word 0x6 further. But at the same time we need to account for the 0x4 margin. 

So r30 + 0x2 = Where Mii name begins....
Thus 0x2 + 0x6 is 0x8 = Where we want Mii name to start at due to clan tag being added later..
0x8 - 0x4 for the 0x4 margin...So 0x4 is the value we need to add to r30...

addi r18, r30, 0x4 

#r18 is now set to the loop's first storing address

We will use r19 as the register to hold each Mii word that is loaded and re-stored. We want this loop to only execute 5 times, since we are dealing with 5 total words. Let's use r20 to keep track of this...

li r20, 5 #Set r20 to 5

Let's start the loop!!

the_loop: #You need to label the loop. ASM tutorial teaches you how to set label names
lwzu r19, 0x4 (r17)
stwu r19, 0x4 (r18)
subic. r20, r20, 1
bne+ the_loop

This loop will execute only 5 times. At this point the Mii name has been re-stored! Let's add the Mii clan tag...

stw r14, 0x2 (r30)
sth r15, 0x6 (r30)

We are done! Let's pop the stack to recover r14 thru r31's values. And finish it off with the default instruction...

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


lhz r4, 0 (r30) #Default Instruction




Entire Source put together...

stwu r1,-80(r1) # make space for 18 registers
stmw r14,8(r1) # push r14-r31 onto the stack

lis r14, 0x8000 #Set upper 16 bits of r14 to 0x8000
ori r14, r14, 0x0A00 #Set lower 16 bits of r14 to 0x0A00
lwz r15, 0x0 (r14) #The user's XXXXYYYY value is now in r15
lhz r16, 0x4 (r14) #User's ZZZZ value is now in r16

addi r17, r30, -0x2 #Sets Loop 1st loading address
addi r18, r30, 0x4 #sets Loop 1st storing address
li r20, 5 #Set r20 to 5, how many times the loop will execute

the_loop:
lwzu r19, 0x4 (r17)
stwu r19, 0x4 (r18)
subic. r20, r20, 1
bne+ the_loop

stw r14, 0x2 (r30) #Store Clan Tag
sth r15, 0x6 (r30)

lmw r14,8(r1) # pop r14-r31 off the stack
addi r1,r1,80 # release the space
lhz r4, 0 (r30) #Default Instruction


Conclusion

Code compiled with RAM writes added (PAL)..
04000A00 XXXXYYYY
02000A04 0000ZZZZ
C20C6DD8 0000000A
9421FFB0 BDC10008
3DC08000 61CE0A00
81EE0000 A20E0004
3A3EFFFE 3A5E0004
3A800005 86710004
96720004 3694FFFF
4082FFF4 91DE0002
B1FE0006 B9C10008
38210050 A09E0000
60000000 00000000


This code WILL fail. There is no check for...
If user uses a tag less than 6 bytes in size.
If user's mii name (with assumed added tag) will exceed 10 characters
If user's original mii name exceeds 10 characters, which wouldn't even allow any tag to be added

Those are features you will need to add yourself to the ASM. Get your ASM fully working first before begin concerned w/ optimization. Good luck!    Smile
Reply
#10
Now things are starting to make at least some sense. ASM is definitely way more complicated when applying it to an actual code. Thank you for your very comprehensive, detailed answers you have been providing, the time and effort you put into them is greatly appreciated.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)