Ok, how would you use two addresses in an ASM code. I now start my code by loading the main address ( e.g ammo)
lis r5, 0x8000
ori r5, r5, 0x0001
Now, what if I was making a code that use two different addresses from totally different areas (like 80B5EF76 and 80FF590F). In the compiler I use, you can only use 1 main address.
Would I use a pointer offset with the first address (r5)?
Are you trying to make a C0 code?
Well, no. In fact, that's new to me!
I was just curious, and would like to see how to do it. Could you also explain the difference between a C2 and C0 code?
C2 hooks into an ASM address and writes in a non conditional branch to where your C2 code is stored in RAM then at the end of your C2 code it automatically jumps to the line after the one that was hooked, so C2 codes only run when the original ASM instruction would run
C0 is an ASM code that runs every frame
Ok, so I think I should leave that until I'm a bit more experienced.
So how would you use two addresses?
Anyone?
I don't get what you mean by two addresses
I think they're mixing it up. There are 2 different "addresses" you could be talking about.
One is the address you set in the compiler, eg 0x80000000
The other addresses are the ones you use in your code, and you can have as many of these as you want.
But how does
lis r22, 0x8097
ori r22, r22, 0x0001
become an address unless specified in the Main address in the compiler.
Couldn't that just be read as a value of something (Money)? How does the CPU know this is an address?
You're right, it could be a value, like money. It could be a floating point value. It could be four characters from a string. (well, almost)
The biggest clue that it's an address is the fact that...well...it's a legal MEM1 address.
The CPU will know it's an address, because some instruction after those ones will use r22 in parentheses. e.g. lbz r3,0(r22). I used Load Byte and Zero because your address, being odd, is byte-aligned.
If r22 0(r22) does not have a valid address, the CPU will lock up. If this were Windows, you would probably see something like exception 0xC0000005 - access violation.
EDIT: it's not just r22, but the sum of the offset and r22, that must be a valid memory address.
Oh! Thank you! I thought you'd use for 80000001 and 80000002;
lwz r22, 1(r5)
(If 80000001 was in r5).
You shouldn't really do that. You need to watch out for alignment.
Computers have data stored in various sizes. We refer to them as a byte (8-bits), half-word (16-bits), or word (32-bits).
If an address reads or writes a word, then it must be word aligned. That is, the address must be divisible by 4. So you can't lwz the address 80000001, or 80000002, or 80000003. But you can 80000000, 80000004, 80000008, etc.
lhz/sth must be half-word aligned; the address should be divisible by 2. So you can't lhz 80000001, 80000003, 80000005, but you can 80000000, 80000002, 80000004.
lbz/stb can be byte aligned. That is, the address can be any value.
Ok, I understand what you have said. I've learnt so much these past few weeks.
Going back to the C0 Codetype thing, how do you make one? Does it depend on how you start it, or how you write it?
I think a C0 code might be a bit too much for you right now. You should really try to write some simple ASM patches; e.g. nop'ing the stw to provide infinite xyz or something similar. Once you understand how ASM executes, then maybe you could consider writing a C2 code. Once you can do a C2 code, then maybe you could do a C0 code.
C0 codes are like C2 codes that run in the code handler. C2 codes are multiple ASM instructions that are executed at a specified address, thanks to some tricky branches that the code handler writes for you. Simple ASM patches are a single ASM instruction that replaces another. So you may see why you want to start simpler first.
I know BASIC Asm; I can change values like in ammo or money, or Health. Just about. But I prefer making these codes 'longer', they're more spread out and easier to read:
Address: 802BEF10
lis r5, 0x802B
ori r5, r5, 0xEF10
lwz r29, 0(r5)
cmpwi r29, 200
ble LowAmmo
bgt HighAmmo
LowAmmo:
addi r29, r29, 100
cmpwi r29, 200
ble LowAmmo
b End
HighAmmo:
subi r29, r29, 100
cmpwi r29, 200
bgt HighAmmo
End:
stw r29, 0(r5)
I originally made this code to test to see if I understood Labels, which is why what it does is kinda stupid.
Huh, not too bad...that looks like a C0 code, except that I wouldn't use r29. In general, avoid using registers above r12, because they are non-volatile. However, you can use a stack frame to preserve their contents if you really want to use them.
Part of the problem is that registers in the code handler can change depending on the version. So, you should really create a stack frame before using *any* registers (volatile or not), push them onto the stack, do your work, pop the registers back off the stack, and remove the stack frame.
However, if you know you're using a recent-ish version of Gecko OS, and you don't mind not being able to work on all versions, then you can use a few registers that are known safe for certain versions. I know this list works for 1.9.3.1
from http://wiird.l0nk.org/forum/index.php/topic,5622.msg48854.html#msg48854
r0 safe
r1 Stack pointer
r2 Table of Contents (TOC) pointer
r3 safe
r4 not safe
r5 safe
r6 ba
r7 gr addresses
r8 code execution status
r9 safe
r10 safe
r11 safe
r12 safe
r13 not safe (reserved)
r14 not safe
r15 code line address
r16 po
r17-31 unknown
Ok, use any of the registers written in blue in your post.
I thought that was a C2 code, I haven't put it through the compiler yet though. I'm starting to look for addresses in games which allow you to make 'easy' codes. I'm not having much luck though...
That list is ONLY for C0 codes and ONLY for certain versions of the code handler. It is NOT for C2 codes, and if you're writing a real code that you want to distribute you should make something that works for all versions, because that list is different for some other builds of Gecko OS.
C2 code register safety is governed by an ENTIRELY different set of rules, because your code will run "in the game" instead of "in the code handler".
http://wiird.l0nk.org/forum/index.php/topic,6555.msg55745.html#msg55745
Also, C2 codes replace (or "hook") an instruction in the game with a branch to your ASM code, which has a corresponding branch back from the code to the address you hooked. Typically, the instruction replaced will be placed at the end of the code.
Ok. Now onto making simple codes, and learning about more complex codes.
Thank you dcx2, you have helped me so much today! :)
Ok, so if I wanted this code to work for all versions of Gecko, I'd do this (if it wasn't a C0 codetype);
stwu r1, -80(r1)
stmw r14, 8(r1)
lis r15, 0x802B
ori r15, r15, 0xEF10
lwz r29, 0(r5)
...
End:
stw r29, 0(r15)
lmw r14, 8(r1)
addi r1, r1, 80
Ok... I put it through the compiler and got this code;
CD382E75 00000008
3CA08B38 60A52E75
80650000 2C0300C8
40810008 41810014
38630064 2C0300C8
4081FFF8 48000010
3863FF9C 2C0300C8
4080FFF8 90650000
60000000 00000000
Whats a CD codetype?
Uh...it's not a codetype.
It would be a switch (CC code type), with the first address bit set...but the CC code type doesn't use address bits.
Trust myself to go and make a code like that!