Replace all instances of strin A with string B

Started by live2play, June 14, 2010, 08:47:14 PM

Previous topic - Next topic

dcx2

You need at least 64-bits worth of values to search for.  The F6 code does not work with anything less than 64-bit chunks.

If 31323334 were the only thing that was consistent, and the bytes immediately before and after vary, I don't think the F6 code could find it.

live2play

Darn!  I appreciate your time in explaining all of this.

live2play

#17
So, what does the following line look for?

38000000 00FF0300   # if byte of interest == 03, search was successful; reset F6 code

Also, why does your code differ in the following ways from Wiiztec?

4E000010 00000000 (your code) vs. 4E000008 00000000 (Wiiztec)
14000000 F6000001 (your code) vs. 14000000 F6000003 (Wiiztec)

wiiztec

Quote from: dcx2 on June 15, 2010, 12:15:35 AM
There aren't any 8-bit ifs, so you'd need to use a 16-bit if-equal, potentially using the bitmask fields.

Also, the F6 code searches for 64-bits at a time.  So you can't just search for 31323334.  I will expand your example to be 31323334 35363738.  I will replace it with 31323335 36373839 3A3B3C3D 3E3F4041.  Note that the replacement does not have to be the same size as the search values.

Here's my attempt.  This might need some fixing (particularly the first if; not sure about that mask...), as I can't really test it...

4E000010 00000000   # get pointer to code line in po
38000000 00FF0300   # if byte of interest == 03, search was successful; reset F6 code
14000000 F6000001
14000004 90009340
E0000000 80008000   # terminator
F6000001 90009340   # searching in range 90000000 to 93400000
31323334 35363738   # For these values.  If the values are found...
16000000 00000010   # do a string write to replace them
31323335 36373839
3A3B3C3D 3E3F4041
E0000000 80008000   # terminator


that should be 4E000020

alternatively you could add 0x10 to the pointer writes
If there's any code at all that you want to be button activated, or even able to toggle on & off, and I have the game, just PM me and I'll make it happen

dcx2

#19
Quote from: live2play on June 15, 2010, 01:57:11 AM
So, what does the following line look for?

38000000 00FF0300   # if byte of interest == 03, search was successful; reset F6 code
Also, why does your code differ in the following ways from Wiiztec?

4E000010 00000000 (your code) vs. 4E000008 00000000 (Wiiztec)
14000000 F6000001 (your code) vs. 14000000 F6000003 (Wiiztec)

This is a more correct (but still potentially flawed) implementation.  It is split into two sections.  The second code is the F6 that actually does the search and the 16 that does the write.  The first code modifies the second code so that it repeatedly searches until one of the searches is not successful (i.e. all instances of Z have been replaced)

4E000020 00000000   # put pointer to real F6 code into po
38000002 00000301   # if hword of interest == 0301, search was successful...
14000000 F6000001   # Replace F6 code with "did not search yet"
14000004 90009340   # Replace S with XY
E0000000 80008000   # terminator

F6000001 90009340   # searching in range 90000000 to 93400000
31323334 35363738   # For these values.  If the values are found...
16000000 00000010   # do a string write to replace them
31323335 36373839
3A3B3C3D 3E3F4041
E0000000 80008000   # terminator

---

http://wiird.l0nk.org/codetypes.html#c27

4E000000 XXXXXXXX = po will hold the address at which the next line of code is stored
+ XXXX (XXXX is a signed 16bits value : 0xFFFF=-1).
4E000000 00000000 = po points to next code's first 32bits.
4E000004 00000000 = po points to next code's second 32bits.

4E is how you get a pointer to your code in memory.  wiiztec is right, it should have been 0x20.  This will ultimately give us a pointer to the beginning of the real F6 code (the first line of part 2) in the po.

--

http://wiird.l0nk.org/codetypes.html#c81

F60000NN XXXXYYYY
ZZZZZZZZ ZZZZZZZZ
ZZZZZZZZ ZZZZZZZZ
Creates an if (so this code requires an endif), then searches for the NN lines of Z values between XXXX0000 and YYYY0000 (or, if XXXX is 8000, between 80003000 and YYYY0000). If the Z values are found, set po to the starting address of the values (SSSSSSSS) and replace the F6 line with F60003NN SSSSSSSS. If the Z values are not found, then set code execution status to false and replace the F6 line with F60001NN XXXXYYYY. To prevent this code from causing game lag, it will only search the first time it is read by the code handler (the result is saved to the code and reused).

Note how I colored one of the numbers red.  That's like the "result" number.  A 0 means that the code has not yet run and should therefore go searching through memory from X to Y for Z.  A 1 means that it ran, but did not find Z, and so will not execute any codes up until the terminator.

A 3 means that it found Z.  A 3 ALSO means that the address of Z, S, has replaced the memory range XY.  Finally, a 3 means that the F6 code will replace the PO with S, and then execute any codes that comes after Z, (in our case, a pointer string write, code type 16) until the terminator.

N refers to the number of lines of Z values, each line corresponding to a 64-bit chunk of memory.  I am not aware of any explicit alignment requirements, but I would try to keep 32-bit alignment.

---

http://wiird.l0nk.org/codetypes.html#c14

38______ ZZZZYYYY : 16bits If equal (po) 16bits compares if ([po+address] and not(ZZZZ))==YYYY.

I was a little wrong about this before.  If the po points to the second code's first line, then we want to add 2 in order to point to the status byte.  Note how Z is used to mask NN in this case.  My corrected code line would be 38000002 00FF0300.  Z = 0x00FF.  not(Z) = 0xFF00.  This isolates the byte with the status, masking off NN.

Technically, since we know N = 0x01, we could do away with the masking stuff (i.e. Z = 0x0000), and test for 0301 (i.e. 38000002 00000301)


EDIT: fixed link to F6 code doc

live2play

#20
Thanks again for the great explanation and WiiRD documentation references.  I will give this a try.

So, if I just wanted to search for 8 bytes (e.g. 31323334 35363738) in MEM2 and replace them with 30303030 30303030), would the following code be correct using the "did I write them all?" technique as described by dcx2?  If so, how would I do the same without the "did I write them all" technique as described by Wiiztec?

4E000020 00000000
38000002 00000301
14000000 F6000001
14000004 90009340
E0000000 80008000
F6000001 90009340
31323334 35363738
16000000 00000008
30303030 30303030
E0000000 80008000

wiiztec

*wiiztec* you didn't type Dcx2 so why Wiiztec?
If there's any code at all that you want to be button activated, or even able to toggle on & off, and I have the game, just PM me and I'll make it happen

dcx2

lol, you should warn people about capitalizing in your sig, wiiztec.

That code looks good to me.  Problem is, if your string isn't in memory the first time you search, it will just stop.  If your string only appears after a certain time (e.g. not in the menus, but when you are in-game), then this will make a terrible GCT code and would require a USB Gecko.  However, add a button activator and now you can also reset the search in-game.

Regarding the actual differences between my code and wiiztec's?  The second line, 38.  Without that if statement, the F6 code will execute during every execution of the code handler...and it's not supposed to.  Other than that, for his code, S = String = 31323334 35363738, R = Replacement = 30303030 30303030.  His code should also be resetting the search range, because a successful search will have replaced XY with S.  Without that, it will probably crash when it tries to use S like XY.

live2play

Quote from: wiiztec on June 15, 2010, 01:34:40 PM
*wiiztec* you didn't type Dcx2 so why Wiiztec?

Sorry about that.  No disrespect intended.  I appreciate your help with understanding this code.