I was hoping to understand a little more about the text to item codes in use. I understand the principle and what is happening but using ASM to achieve it is out of my depth.
This animal crossing code is a good example, cant remember who made it:
286DFC80 9FEF6010
C0000000 0000000C
3F608062 637B5477
38A00000 3920000C
8D5B0002 2C0A003A
41800008 394A0009
714A000F 7D4A4830
7CA55214 3929FFFC
2C090000 4080FFDC
3F6090E2 637BEB22
3FC0805D 8BDE2477
38600000 606386C0
7FDE19D6 7F7BF214
B0BB0000 4E800020
E0000000 80008000
A button is pressed and the code fires but can I adapt this to another game by changing memory locations for example?
the code translates to:
lis r27,-32670
ori r27,r27,21623
li r5,0
li r9,12
lbzu r10,2(r27)
cmpwi r10,58
blt- 0x08
addi r10,r10,9
andi. r10,r10,15
slw r10,r10,r9
add r5,r5,r10
subi r9,r9,4
cmpwi r9,0
bge+ 0xFFFFFFDC
lis r27,-28446
ori r27,r27,60194
lis r30,-32675
lbz r30,9335(r30)
li r3,0
ori r3,r3,34496
mullw r30,r30,r3
add r27,r27,r30
sth r5,0(r27)
ta
I believe this YouTube video (http://www.youtube.com/watch?v=BoWrZyskYD8) demonstrates the code.
Animal Crossing supports an on-screen keyboard. The value of the characters in this on-screen keyboard are stored somewhere in memory. If you find it and parse the character values correctly, you can use this value as an input to modify other parts of memory.
Tomorrow morning I'll try to add some comments to the asm code, explaining what it's doing.
Thanks dcx
I basically need to turn hex string values into their actual text equivalent in a 4 character template
So if I type this into the text box:
017A
it is held in memory as this:
0030 0031 0037 0041
So I need to read those values in and convert them back to 017A and store it all is a Dword along with the amount of the item:
017A0009
Is there asm functions to convert?
dragonboy posted some helpful codes and info here on a similar note:
http://wiird.l0nk.org/forum/index.php/topic,1856.msg32072.html#msg32072
lis r27,-32670
ori r27,r27,21623 # r27 is a pointer to the unicode string
li r5,0 # r5 is our running total
li r9,12 # r9 is a bit-shifting value
lbzu r10,2(r27) # loads [r27 + 2] into r10, then adds 2 to r27 (accounts for Unicode)
cmpwi r10,58 # is this a digit or a character?
blt- 0x08 # if character...
addi r10,r10,9 # add 9
andi. r10,r10,15 # mask off everything but the last 4 bits
slw r10,r10,r9 # shift remaining bits to the appropriate position
add r5,r5,r10 # add shifted value to our running total
subi r9,r9,4 # adjust the shift value to load into the next nibble
cmpwi r9,0 # do we have more bits to shift?
bge+ 0xFFFFFFDC # branch back to lbzu
lis r27,-28446
ori r27,r27,60194 # load r27 with a base pointer
lis r30,-32675
lbz r30,9335(r30) # load r30 with a multiplier byte variable
li r3,0
ori r3,r3,34496 # load r3 with multiplier constant
mullw r30,r30,r3 # put product in r30
add r27,r27,r30 # add product as an offset to the base pointer
sth r5,0(r27) # store the text->hex value at the calculated pointer
Working our way through, using your example...
lbzu loads r10 with 0x30, and increments r27 by 2 (that's the 'u' part). It is then compared against 58 = 0x3A. Since 0x30 is less than 0x3A, it skips the addi. The andi then masks off the 3, leaving you with 0x00. slw shifts the nibble from r10 over by r9 bits so that it's in the right nibble, and then r10 is added to r5 (the running total). r9 is adjusted so that it shifts to the next nibble on the next iteration of the loop. If r9 is less than 0, we've shifted all the bits we're interested in, so we're done. Otherwise, we have to start over.
lbzu loads r10 with 0x31, incs r27 by 2. 0x31 < 0x3A, skip addi. andi masks the 3 off, leaving 0x01. slw lines the nibble up, add puts it in the running total in r5, r9 is subbed so that it points to the next nibble, and we keep going.
skip 0037...
lbzu loads r10 with 0x41, incs r27 by 2. 0x41 > 0x3A, so addi changes it to 0x4A. Mask off the 4, leaving 0x0A. By this time, r9 = 0, so the slw won't actually do anything. Add to the running total, sub r9 so that it's negative, and the loop terminates.
The last bit is just a really complicated way to get a hold of the address where we want to put this value, because it depends on a pointer and a variable offset which needs calculated. Your game might not require this kind of belly-rubbing-and-head-patting type stuff.
If you have Animal Crossing, you might want to load it and try to set a Breakpoint so you can step through the ASM and see what it's doing. But everything before the bge is probably going to be about the same.
Cant u just use 2 32bit activators ? and tie it to the Keyboard Pad section ?
I'm not sure I follow you, Skiller. Two activators? Are they reading the Unicode characters?
When you press on the keyboard, it generates Unicode values in memory somewhere. There's a non-trivial amount of massaging necessary to do Unicode -> integer casts.
Unicode is 16 bits per character, so you need to ignore every other byte. Hence the lbzu offset of 2. lbzu not only loads the destination register with the [source register + offset], but it *also* adds the offset to the source register. It does two things at once. This accounts for progressing through the Unicode string one character at a time.
Each character needs to be reduced to a 4-bit nibble that represents the character as an int. For example, '3' must be turned into 0x03. However, '3' = 0x33 (technically, a Unicode '3' is 0x0033). '4' = 0x34. Check out the ASCII chart (http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters) (Unicode is something like an extension of ASCII). That's why we andi with 15 = 0xF; this removes everything but the last four bits.
The letter Hex values need handled separate. 0x41 = 'A', which is why he adds 9 to anything greater than '9' = 0x39. 0x41 + 9 = 0x4A, mask with 0xF = 0xA.
Now we can turn Unicode characters into integer values. But we have to add up the digits that we create. In Panda's case, we want 0x100 + 0x70 + 0xA. This is the purpose of the slw with r9 and the subi with r9.
Awesome, thanks dcx
Ours should be easier because the place i want to store it is always the same and the place we get the digits from is always the same
This image shows the place where the text is stored, we just want the 4 characters 'h e l l' from hello
(http://img534.imageshack.us/img534/4972/textkp.gif)
so
char1 = 92AA1CE9
char2 = 92AA1CEB
char3 = 92AA1CED
char4 = 92AA1CEF
They then need to be written to 900E0610 as 'XXXX' and then the amount to 900E0612 as '00XX'
How familiar are you with asm? Can you load r27 with 0x92AA1CE9? Are you familiar with bit masking and bit shifting?
This is a good reference when trying to figure out what different instructions do.
http://pds.twi.tudelft.nl/vakken/in1200/labcourse/instruction-set/
Example of what i mean .. if hes just trying to do a few things not every digit ..
92AA1CE8 ????????
92AA1CEC ????????
900E0610 ????00VV
Set them Red Addresses as your 32bit = to Activator . set the values to what u want to type in . doin so should set the 900E0610 ????00VV
but i know u want to be able to type everything in not just 1 :P
I think you're suggesting an ifeq code that tests for "00000031" = Unicode '01', and another ifeq code "00370041" = Unicode '7A', and if both ifeq codes are true, then write 0x017A to 900E0610.
That's good if you're only watching for a few different inputs, but I think he wants to be able to type in an arbitrary hex value using the keyboard.
Quote from: dcx2 on May 19, 2010, 05:24:14 PM
I think you're suggesting an ifeq code that tests for "00000031" = Unicode '01', and another ifeq code "00370041" = Unicode '7A', and if both ifeq codes are true, then write 0x017A to 900E0610.
That's good if you're only watching for a few different inputs, but I think he wants to be able to type in an arbitrary hex value using the keyboard.
ya thats why i put the Second part .. it would make for some intresting Effects being able to do that :P
Yeah, i want to type in one of the Item Digits starting at 0001 all the way up to 02EA
I tried this but it freezes the game:
2865944C 00000008
C0000000 00000009
3F6092AA 637B1CE8
38A00000 3920000C
8D5B0002 2C0A003A
41800008 394A0009
714A000F 7D4A4830
7CA55214 3929FFFC
2C090000 4080FFDC
3F608000 637B180C
B0BB0000 00000000
E0000000 80008000
lis r27,-27990
ori r27,r27,7400
li r5,0
li r9,12
lbzu r10,2(r27)
cmpwi r10,58
blt- 0x08
addi r10,r10,9
andi. r10,r10,15
slw r10,r10,r9
add r5,r5,r10
subi r9,r9,4
cmpwi r9,0
bge+ 0xFFFFFFDC
lis r27,-32768
ori r27,r27,6156
sth r5,0(r27)
Are we sure it's unicode? geckoDotNet cant read it as that, only ascii
That's a good start. But your last lis r27/ori r27 is not writing to 900E0610. You're actually writing to 8000180C. Look at the immediate part of the op-code (bolded) to see the hex address instead of the decimal address.
3F608000 637B180C = lis r27,-32768; ori r27,r27,6156
Another problem is that you forgot to end your C0 code with a blr = 4E800020. Check the code-type doc.
And there's still the small issue of how you wanted to write the item count at the same time. You'll need to li your item count value into some register, and then sth that into 900E0612. Something like this, before the blr but after your sth.
li r5,10
sth r5,2(r27)
Try this code (I think the li/sth will work in this, but I'm not sure, might want to run this through the ASM converter to double-check)
2865944C 00000008
C0000000 00000009
3F6092AA 637B1CE8
38A00000 3920000C
8D5B0002 2C0A003A
41800008 394A0009
714A000F 7D4A4830
7CA55214 3929FFFC
2C090000 4080FFDC
3F60900E 637B0610
B0BB0000 38A0000A
B0BB0002 4E800020
E0000000 80008000
nice one
It should now be C0000000 0000000A though as it's got an extra line of code
I also change the 2nd line to 3F6092AA 637B1CE7 because leaving it at E8 gave me all 0's and using E9 missed the first digit off
Text to Item (C & -)
2865944C 00000048
C0000000 0000000A
3F6092AA 637B1CE7
38A00000 3920000C
8D5B0002 2C0A003A
41800008 394A0009
714A000F 7D4A4830
7CA55214 3929FFFC
2C090000 4080FFDC
3F60900E 637B0610
B0BB0000 38A0000A
B0BB0002 4E800020
E0000000 80008000
So this puts what you type in your first slot
no error checking though
thanks dcx!
Quote from: Panda On Smack on May 20, 2010, 04:09:12 PM
It should now be C0000000 0000000A though as it's got an extra line of code
lol oops
QuoteI also change the 2nd line to 3F6092AA 637B1CE9 because leaving it at E8 gave me all 0's
Yes, I forgot to check that...you have to read every other byte, and you weren't aligned with the actual data bytes.
QuoteI entered 0123 in my input box and pressed C
at 900E0610 is this: 1230000A
at 92AA1CE8 is this: 00300031
at 92AA1CEC is this: 00320033
so the code works but it misses the first 0?
When writing ASM codes, it's important to be able to step through the code and watch what's happening. I've never tried to debug a C0 code live (in fact, I've never written one, but I kinda want to...). I wonder if you could find your code in memory and set an execute breakpoint on it.
Try searching for a really unique value in your code, like 7CA55214, and limit your search to areas in MEM1 below 80010000 (I think that's it), because that's where our codes go. Set your Execute breakpoint and you should be able to step through the code live, seeing what values are being loaded into registers etc.
Anyway, I figured out the problem. lbzu r10,
2(r27). If r27 = 637B1CE9 then the lbzu will begin by reading 637B1CE
B, which is where the 1 is. Instead, you must set r27 = 637B1CE
7, so the offset of 2 will line up with the beginning of the string.
Quote from: Panda On Smack on May 20, 2010, 09:15:37 AM
Are we sure it's unicode? geckoDotNet cant read it as that, only ascii
ASCII is an 8-bit standard for representing characters. It only has 256 different things it can represent (some of them control codes, like line break and carriage return, beep, etc). Can you imagine writing Chinese with only 256 characters?
Unicode is a 16-bit standard that was designed to support Chinese, Japanese, etc with 64k possible characters. To make things easy, English Unicode is built on top of ASCII, with 0 for the first 8 bits and ASCII for the second 8 bits.
If Gecko.NET can't see the right stuff in Unicode view, then I should look into this...
ta mate, you got in before I had chance to change my reply. all working now!
lol, I missed your edit. I see you discovered all of this.
Your error checking would be making sure you don't hit C when there's something invalid in there. :)
Even if you type in garbage, it will still make numbers. You should probably make sure the final number in r5 is less than your max item value, just in case someone puts garbage in and presses C anyway, because it could cause freezing.
You might also want to consider adding an extra digit or two that allows you to specify the slot you want to put the item into. Assuming the slots are laid out adjacent in memory, you just need a mulli by the slot number (probably starts with 0, not 1), where the immediate is the number of bytes in a slot (probably 2?), and add it to the slot 0 address (900E0610?)
yeah, nice one
Hopefully I can work out how to tweak it and improve
Crap youtube vid of it:
http://www.youtube.com/watch?v=atBurJa7mYc
current ASM
lis r27,-27990
ori r27,r27,7399
li r5,0
li r9,12
lbzu r10,2(r27)
cmpwi r10,58
blt- 0x08
addi r10,r10,9
andi. r10,r10,15
slw r10,r10,r9
add r5,r5,r10
subi r9,r9,4
cmpwi r9,0
bge+ 0xFFFFFFDC
lis r27,-28658
ori r27,r27,1552
sth r5,0(r27)
li r5,15
sth r5,2(r27)
highest value someone can enter is 02EA which is 746. so do I compare r5 to 746 and if its higher then branch?
lis r27,-28658
ori r27,r27,1552
cmpwi r5,746
bgt- 0x0C
sth r5,0(r27)
li r5,15
sth r5,2(r27)
P.S. since this is an online code i presume it's not allowed in the code list? Although, this is a public part of the forum where anyone can see it.
This is a code that incidentally works online. It wasn't designed with an online advantage in mind.
Also, you should try this template instead. If r5 < 747, it does nothing. If r5 >= 747, it will load r5 with a valid value.
cmpwi r5,747
blt- 0x08
li r5, 2
sth r5,0(r27)
li r5,15
sth r5,2(r27)
Thanks again, will test it out. While I don't want to break the forum rules this code can only be used online because you cant use the chat function offline.
doh
Hm, this is tricky then, because the whole "can't chat offline" thing is the only reason it would be an "online" code. It still feels like the online aspect is accidental more than intentional.
I imagine there are already codes that allow you to create an item out of nowhere, they're just more unwieldy than the text->item code. Considering how the consensus was "some/embargo", and this code can't be used to deny someone else service, and an embargo is useless because item creation codes already exist...I don't see any real harm in it. I've largely given up on policing those threads except for the unban codes.
Quote from: dcx2 on May 21, 2010, 02:54:26 PM
Hm, this is tricky then, because the whole "can't chat offline" thing is the only reason it would be an "online" code. It still feels like the online aspect is accidental more than intentional.
I imagine there are already codes that allow you to create an item out of nowhere, they're just more unwieldy than the text->item code. Considering how the consensus was "some/embargo", and this code can't be used to deny someone else service, and an embargo is useless because item creation codes already exist...I don't see any real harm in it. I've largely given up on policing those threads except for the unban codes.
we can try to bring the Chat box into the offline play .. if we did that i could change up the full roller code for what u just made :) and we could do one for the Equipment .> hell any Mod codes we would make could use this format .
this would be cool to add to say a code type for Gecko .. so that we could just use say a few lines
Example
CTB00000 KKKKKKKK
AAAAAAAA VVVVLLLL
CT = Code type
B = Bit type
A = Address
K = Keyboard Address
V = Max Value
L = Lowest Value
0 = Unused .. but could be used for something
anything on the address that used the CT codetype would then be printed to using the Keyboard values ...
thats if the rest of the code could become universal .
Bringing the chat box offline would be an epic hack. ;D
I don't think this is standard enough for a code type, though. There will probably be a general template that people will have to port by hand.
Regarding the item roller, I imagine your do a one-press-equals-one-item. Have you considered adding a scroller? That's what I did with my Tales item modifier; left and right will change items one at a time, while + and - scroll through the items. It scrolls at 30 items/sec, so if you had more than 300 items or so you might want to consider scrolling by 2 or 3 items/frame instead of 1.
Making the chat box work in offline play would be a tricky thing I guess.
Unless the game just reads a boolean for that, you would have to Reverse Engineer the whole subroutine taking care of that.
Quote from: dcx2 on May 21, 2010, 07:34:34 PM
Bringing the chat box offline would be an epic hack. ;D
I don't think this is standard enough for a code type, though. There will probably be a general template that people will have to port by hand.
Regarding the item roller, I imagine your do a one-press-equals-one-item. Have you considered adding a scroller? That's what I did with my Tales item modifier; left and right will change items one at a time, while + and - scroll through the items. It scrolls at 30 items/sec, so if you had more than 300 items or so you might want to consider scrolling by 2 or 3 items/frame instead of 1.
i alow them to change the speed of the change ..
i have it change every Second normaly but u can set it to Change every Millsecond if u wanted .. :P