Ok, I watched fox's video, and it did help, I did see that it needed two 8 digit numbers to be entered as a simple write code, but what do I do when the base address isn't the 80000000?
The code's actual memory address is 815DBB77, the value I want is 00000063, and in order to do a 32 bit write, I have to prefix the address with 04, and with a 80000000 address, it's all fine and dandy to put 04(remaining 6 digits of address) because the base address is 80000000 and if it were 80000000 the code would be 045DBB77 00000063, but how do I write the code for a base address of 81000000?
I am a bit of a novice at this as I got my gecko just today, but I have been successfully poking my way through many games with great results, it's only when I go to create the GCT codes that I get stumped. I'd like to be able to share these with the community and the only way I can is if I actually learn how to write these as codes instead of just memory addresses and values.
Thanks in advance for any help the community can give, I'm sorry the tutorials and videos don't seem clear enough for me.
Edit-
I have had experience with poking and finding memory addresses and pointers using pc game cheat programs all the way back to DOS, but I never needed to do more than poke specific addresses with a value and haven't had a chance to learn alot about other aspects of it.
ba is masked with 0xFE000000 when you use it, so you can't set ba to 0x81000000 because it will mask the 1. When your address is in the 0x81 range, you need to use the 05 code-type instead of the 04 code-type. 05 writes to ba + 0x01000000 + address.
If you need to touch mem2 (0x90-0x93), you need to use the 40 42 code-type to set the ba to whatever. If you need to touch 0x91 or 0x93, you ALSO need to use the 05 code-type. After using a 40 42 code-type to adjust the ba, you need to use the E0 codetype (E0000000 80008000) to fix the ba, or you'll screw the next code up.
The whole masking and needing to use the 05 code-type isn't necessary if you use the po instead. The po can be set to anything, even 0x810123456.
http://wiird.l0nk.org/codetypes.html (http://wiird.l0nk.org/codetypes.html)
I find the page on code types difficult to peruse, it almost seems as if someone intentionally obfuscated the material, but since I have taken some programming courses, I realize it's not, it's just that the person who wrote it didn't write it for beginners but for people who are used to it.
When you mention code types, you're saying 04, 05, and 40, but I am having difficulty understanding the code types page and am not making the connection. It's not that I'm retarded, but I may be a little slow :rolleyes:
I can make the connection better with examples.
Can you give me an example of using the 40 code type to set the ba?
Can you tell me specifically where on the code types page to find the 05 code type?
And the 05 code type is the 32 bit write that automatically starts with 81000000?
The memory addresses and the values I am poking are:
815DBB77 63
815DBB7B 63
815DBB7F 63
815DBB83 63
815DBB87 63
815DBB8B 63
815DBB8F 63
That sets the items in nsmb wii to 99 for each, but I have to poke each one manually. So for making it a gct code, I'll need to use the 05 code to show that I am starting with a base address of 81000000 and writing a 32 bit value correct? So my codes will look like this:
055DBB77 00000063
055DBB7B 00000063
055DBB7F 00000063
055DBB83 00000063
055DBB87 00000063
055DBB8B 00000063
055DBB8F 00000063
How would I go about turning that into a pointer?
I appreciate any help and apologize if I seem to be trying to make it too simple to be accurate, once I get a bit of a foothold, I should be able to learn on my own better.
Re: code types doc, yeah, it's a little obtuse at times. There are a few sections that could use some serious re-wording, and now that you mention it, I don't see 01/03/05 code types in the doc. =( It's also missing 11, 13, and 15, which use the po instead of ba.
-----
You are (almost) correct in your examples. Poking 815DBB77 to 0x63 would be accomplished by 015DBB77 00000063. How do I know this? Look at the alignment of the memory you're writing to. By alignment, I mean take the address and apply the mask 0x00000003; 815DBB77 & 00000003 = 0x3, which is an odd number, meaning you are writing to an 8-bit memory location. If the result was 0x1, you are still writing to an odd number, so it's still 8-bit. If the result was 0x2, you are writing to half-way between the word boundaries, so you're writing half-words, or 16-bits. If the result was 0x0, then you are aligned to the word boundary, i.e. 32-bits.
04/05/14/15 code types are 32-bit writes that always write on word boundaries, which means they must be aligned at 32 bits, which means the two LSBits of the address you're writing to must be 0.
02/03/12/13 code types are 16-bit writes that write on half-word boundaries, which means they must be aligned to 16 bits, so the LSBit must be 0.
00/01/10/11 code types are 8-bit writes that write on byte boundaries, so the address can be anything.
note you could write to the 16- or 8-bits that are on the word boundary, so just because your mask result is 0x0 does not mean you aren't doing 16- or 8-bit writes
---
Note that the ba is never actually 0x81000000. It's still 0x80000000, but the additional 0x01000000 comes from the 01/03/05 code types. You actually *can't* set the ba to 0x81000000 because it ignores the LSBit of the MSByte. So ba can be 0x8000000, 0x82000000, 0x84000000, 0x86000000, etc, but not 0x81000000, 0x83000000, etc.
Actually, that right there is a lie, because MEM1 ends at 0x81800000, but I hope you get the point. So, if you are writing a code for a MEM1 address with the ba, then there's no reason to use the 40 42 code type to set ba.
Now, if you were using MEM2...let's say your address was 915DBB74 instead. (Notice how I changed it to be word-aligned so I can use 32-bit writes; do NOT use this example, it's just to illustrate 40 42 code type)
4000000042000000 90000000 # load ba with 0x90000000
055DBB74 00000063 # write 0x00000063 to ba + 0x01000000 + 0x005DBB74
E0000000 80008000 # set ba back to 0x80000000
---
Digest this, then come back and we'll talk a bit about pointers.
Thank you very much, you're helping alot by filling in what the code types sheet is missing, and it's making a lot more sense now. I will digest this, and hopefully I will be able to learn a bit about pointers and begin tinkering with them before I run into trouble and have to call for help :)
Edit-
About the alignment,
apply the mask 0x00000003; 815DBB77 & 00000003 = 0x3
I understand that odd numbers means the address starts between words, but what exactly does applying the mask mean? the number plus 3 = 3 is what that seems to be saying, but it's probably because i'm a bit rusty on my data structures and I'm having trouble understanding LSBits. I don't want to tire you out or anything, from what you've told me I should be able to learn a lot more without any more help, I just would like to understand exactly what you meant by that.
Masking was just a way for me to describe the important bits. Mask stands for bit mask (http://en.wikipedia.org/wiki/Mask_%28computing%29). In programming, we use bit masks to isolate the bits that we're interested in. We use the logical AND operation to do masking (see "masking bits to 0" in the wiki article). In this case, we're isolating the two Least Significant Bits (http://en.wikipedia.org/wiki/Least_significant_bit) (LSBits) of the Least Significant Byte (LSByte) - that is, if you convert the hexadecimal address to binary, the two bits alllll the way on the right. These bits can be used to determine the data's alignment.
The address 815DBB77 in hex = 10000001010111011011101101110111 in binary. (Now you see why we use hex, lol). ANDing with the mask 0x00000003 = 00000000000000000000000000000011 will give us the last two bits of the address, which are 11, so the data is aligned on an 8-bit boundary.
If the last two bits were 01, it's still an 8-bit boundary. 10 would be a 16-bit boundary. 00 would be a 32-bit boundary. Since hex is just compressed binary, you're really only interested in the last hex digit. 0, 4, 8, and C are word-aligned; 2, 6, A, and E are hword-aligned; 1, 3, 5, 7, 9, B, D, and F are byte-aligned.
Alignment is only important because the hardware cannot under any circumstances do anything across word boundaries in a single instruction. Let's say you wanted to write to 16-bit values at 815DBB76 and 815DBB78. A 32-bit write could conceivably write to both memory addresses. However, they're on different sides of the word boundary, so you will need two separate writes. However, 815DBB76 and 815DBB74 are part of the same word (remember, word = 32 bits) in memory, so you could write to both at the same time.
EDIT:
Look in Memory Viewer (image from Romaap's tutorial)
(http://i108.photobucket.com/albums/n31/Romaap/1rightclickbreakpoint.jpg)
See how everything is organized in groups of 8 hex digits with spaces between each group? Each of these groups is a word of memory. A single instruction can only touch one group of 8 digits at a time. If you wanted to read or write data across one of the "spaces", you would need to use two separate instructions. So writing 32-bits to 80A79900 is okay; writing 32-bits to 80A79902 is not, because half of the write is on one side of a word boundary, and half is on the other. This is why 32-bit writes will always end with an address that is a multiple of 4.
Thank you very much, I understand it a lot better now.
I will try to learn more on my own, and if I hit a snag, I'll definitely ask for help :)
That's not what the 40 codetype does, the 40 codetype is like the base address version of 48 it sets the value at the address specified as the base address
the 42 codetype is what's used to set the base address to the address you specifiy
$&#$ me, you're right wiiztec. This is what I get for doing way too many asm codes. I saw "load into base address" and I thought load like load word, not load like dereference...
I'll edit my post to fix it.
Why is it correct to use the 05 code type with the ba=90000000 as you mention below, but it's not correct to use 055DBB77 00000063 to write 63 to 815DBB77?
Quote4000000042000000 90000000 # load ba with 0x90000000
055DBB74 00000063 # write 0x00000063 to ba + 0x01000000 + 0x005DBB74
E0000000 80008000 # set ba back to 0x80000000
Quote from: live2play on March 17, 2010, 06:29:33 PM
Why is ... it not correct to use 055DBB77 00000063 to write 63 to 815DBB77?
Quote42000000 90000000 # load ba with 0x90000000
055DBB74 00000063 # write 0x00000063 to ba + 0x01000000 + 0x005DBB74
E0000000 80008000 # set ba back to 0x80000000
The reason is called
alignment. I suggest re-reading the thread, as it discusses alignment in detail, but maybe a picture will help.
(http://i45.photobucket.com/albums/f60/deadcatx2/WiiRd/alignment.png)
Notice how the row is composed of four groups of four bytes separated by a red line. Memory is arranged in "words" - groups of 4 bytes. Each row is four words, each word is separated by red lines. Your 055DBB77 00000063 would be writing 4 bytes across a word boundary (the red line), which is forbidden.
An instruction is only allowed to touch one "word" of memory at a time. In my example, I wrote 4 bytes to 0x905DBB74. The address 0x905DBB74 is "word aligned", meaning that it's a multiple of 0x4 (i.e. the address ends in 0x0, 0x4, 0x8, or 0xC), so all 4 of the bytes I'm writing do not cross any word boundaries.
0x815DBB77 is not word aligned (it does not end in 0/4/8/C). If you write 4 bytes to address 0x815DBB77, you will be writing 1 byte to the end of the word at 0x815DBB74, and three bytes to the beginning of the word at 0x815DBB78.
Thanks! A picture is worth a thousand words.
This is how you would do it
015DBB77 00000063
So, is the following summary correct?
Memory addresses that end in…
0, 4, 8, and C are word-aligned (32-bit) and you should use the appropriate 32-bit WiiRD code type
2, 6, A, and E are hword-aligned (16-bit) and you should use the appropriate 16-bit WiiRD code type
1, 3, 5, 7, 9, B, D, and F are byte-aligned (8-bit) and you should use the appropriate 8-bit WiiRD code type
...almost. To be 100% correct, *all* addresses are byte-aligned - 0-F.
All *even* addresses are hword-aligned - 0/2/4/6/8/A/C/E.
You can write a byte anywhere without crossing a red line. You can write an hword at any even address and you won't cross a red line.
I am not 100% sure, but while it may be *possible* to read or write two bytes at an odd address without crossing a red line (1/5/9/D), I have never seen this in all of the ASM code I've looked at and I would not bet any money on the ability to do such a read/write.
Thanks! Is it true to state the following?
You should never use a WiiRD code type for a 32-bit write to memory addresses that end with 2, 6, A, and E and you should never use a WiiRD code type for a 16-bit write to memory addresses that end with 1, 3, 5, 7, 9, B, D, and F.
Quote from: live2play on March 17, 2010, 09:56:32 PMYou should never use a WiiRD code type for a 32-bit write to memory addresses that end with 2, 6, A, and E and you should never use a WiiRD code type for a 16-bit write to memory addresses that end with 1, 3, 5, 7, 9, B, D, and F.
What you say is all correct, but not the whole story.
1) Not just WiiRD, but the PowerPC processor inside the Wii cannot do unaligned memory accesses.
2) This applies not only to writes, but reads as well. Any memory access must be aligned.
3) Not only can 32-bit memory accesses never end in 2/6/A/E, but they cannot ever be 1/3/5/7/9/B/D/F either. In other words, they must end in 0/4/8/C, which is a multiple of 4, which is how many bytes a word is.