Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« on: November 05, 2011, 08:36:26 PM » |
|
In response to this. Spoiler for old stuff: It's going good. Here's what it looks like so far: I think any user error is pretty much taken care of. Except for if codes aren't properly formatted. >.> DON'T GIVE A F- Anyway, All that's left is the function that I call in the main function. asmPort() is called when you press the "to [region]" buttons and asmPort passes some stuff to addressSwap() which is supposed to return the ported address. But currently, this is all it does: public string addressSwap(UInt32 addy, string dumpFrom, string dumpTo) { BinaryReader binFrom = new BinaryReader(File.Open(dumpFrom, FileMode.Open)); BinaryReader binTo = new BinaryReader(File.Open(dumpTo, FileMode.Open)); //do stuff binTo.Close(); binFrom.Close(); return addy.ToString("X" + 6); } Some good ol' C#. What happens is, idk how I can tell if the asm is a branch of some sort. Well..idk how I can tell what anything is. So idk where to make it stop copying. And then the next thing is Find()... I have to work on that. It doesn't sound tough. But I haven't put any thought into that. addressSwap is supposed to do is - go to the hook address in binFrom - read backwards until it hits a branch or something - read forward until it hits a branch or something - copy the hex string in between and take note of the offset from the start of the sting to the code's hook(in some variable, of course) - First search for this string in binFrom multiple times until it isn't found again. Take note of how many hits(n) and which hit was the right hook(h(just incase)) - Now open binTo and search h times(I guess n is useless) - this is the new hook. Add the offset and grab the new address into addy or something - return addy or something So that's the TODO I guess. It currently knows what to do with 04/14, C6/D6, C2/D2, F2/F4 codetypes, assuming ba/po == 80000000. Stuff like lis r12, 0x8066, lwz r12, 0x93BC(r12) won't get fixed. Cuz idk. well.. I DON'T GIVE A F- http://dl.dropbox.com/u/24514984/asmPort.exeSource: http://dl.dropbox.com/u/24514984/asmPort.7zI used Visual C# 2008 Express Issues afaik: 1) It's a little slow but fairly accurate so far. public UInt32 findHex(byte[] hex, BinaryReader binFind, UInt32 addy) { if (addy != 0) addy++; binFind.BaseStream.Seek(addy, SeekOrigin.Begin); addy = 0xFFFFFFFF; while (binFind.BaseStream.Position + hex.Length <= binFind.BaseStream.Length) { int oneByte = binFind.ReadByte(); bool found = true; if ((byte)oneByte != hex[0]) found = false; else { for (int i = 0; i < hex.Length; i++) {
if ((byte)oneByte != hex[i]) { found = false; binFind.BaseStream.Position -= i; break; } oneByte = binFind.ReadByte(); } } if (found) { addy = Convert.ToUInt32((binFind.BaseStream.Position - (hex.Length+1))); break; } } return addy;
That's definitely the source of the slowness, cuz I checked and it's the most time consuming. I'm not sure how I can do find better though. :/ 2) It doesn't check for branches the way I wanted so it might have some issues eventually. It just checks for anything that starts with 4 to know if it's a branch: if ((u32 & 0xF0000000) == 0x40000000) break; The higher 40s are cr insructions...so there might be a slight issue there but for now this works. TODO: Improve performance Check for branches for real Other than that, it works. I successfully ported every thing I already ported to see if I get the same results and I did. I just had to wait about a minute or so. Suggestions are welcome. Help is welcome even more. Discuss!
|
|
« Last Edit: November 28, 2011, 08:22:08 PM by Stuff »
|
Logged
|
|
|
|
Bully@Wiiplaza
Hacker
Legendary Member
Karma: 93
Posts: 1853
|
|
« Reply #1 on: November 05, 2011, 09:05:25 PM » |
|
so addresses in asm won´t be recognised? Obviously Nobody can program stuff like that, hehehe. Well, I like it. I would definetely use that tool! Is there a beta release?
|
|
« Last Edit: November 05, 2011, 09:09:49 PM by Bully@Wiiplaza »
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #2 on: November 05, 2011, 09:12:20 PM » |
|
Yeah none of that in asm addresses. You just gotta know at that point. You need dumps for this so you kind of gotta be a hacker anyway, right? Oh and no jap cuz idfk. After looking at mh3-j, I just don't know what to do with that.
|
|
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #3 on: November 10, 2011, 04:29:57 PM » |
|
I was gonna use this that I found in the gecko.net source, as old as it is, for my find function: public void SearchString(byte[] searchBytes, bool caseSensitive, bool unicode, bool hex)//why pass this if it's not gonna be used? //public void SearchString(String sString, bool caseSensitive, bool unicode) { byte[] stringBytes = searchBytes; UInt32 startAddr = selAddress + 4;
UInt32 endAddress = 0;
int dumpLength = (unicode ? 2:1); bool found = false; for (int i = 0; i < ValidMemory.ValidAreas.Length; i++) { if (startAddr >= ValidMemory.ValidAreas[i].low && startAddr < ValidMemory.ValidAreas[i].high) { found = true; endAddress = ValidMemory.ValidAreas[i].high; break; } }
if (!found) { throw new Exception("Memory area could not be acquired!"); }
bool valueFound = false; int inpos = 0;
UInt32 beginAddress = startAddr;
MemoryStream ms = new MemoryStream(); long streamPos = 0; UInt32 cVal; char cChar;
UInt32 SearchBufferSize = 0xF800 * 8; // F800 is the packet size in USBGecko.cs
UInt32 dumpHigh = Math.Min(startAddr + SearchBufferSize, endAddress);
try { int index;
do { ms.Seek(0, SeekOrigin.End); int startIndex = (int)ms.Position; gecko.Dump(startAddr, dumpHigh, ms);
byte[] streamArray = ms.GetBuffer();
index = GlobalFunctions.IndexOfByteArray(streamArray, stringBytes, startIndex, caseSensitive);
if (index != -1) { valueFound = true; break; }
startAddr = dumpHigh; dumpHigh = Math.Min(startAddr + SearchBufferSize, endAddress); Application.DoEvents(); // check for cancel search } while (dumpHigh != endAddress && !valueFound && searching);
if (valueFound) { UInt32 address = (UInt32)(beginAddress + index); cAddress = address; } else { // hack to fix the jumping disassembly window cAddress = beginAddress - 4; if (dumpHigh == endAddress) MessageBox.Show("Could not find search query"); } } catch (EUSBGeckoException exc) { exceptionHandling.HandleException(exc); } }
I was only interested in what it does for hex search, but the boolean for hex doesn't even get used...Maybe it wasn't finished back then?
|
|
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #4 on: November 21, 2011, 08:47:21 PM » |
|
http://dl.dropbox.com/u/24514984/asmPort.exeIssues afaik: 1) It's a little slow but fairly accurate so far. public UInt32 findHex(byte[] hex, BinaryReader binFind, UInt32 addy) { if (addy != 0) addy++; binFind.BaseStream.Seek(addy, SeekOrigin.Begin); addy = 0xFFFFFFFF; while (binFind.BaseStream.Position + hex.Length <= binFind.BaseStream.Length) { int oneByte = binFind.ReadByte(); bool found = true; if ((byte)oneByte != hex[0]) found = false; else { for (int i = 0; i < hex.Length; i++) {
if ((byte)oneByte != hex[i]) { found = false; binFind.BaseStream.Position -= i; break; } oneByte = binFind.ReadByte(); } } if (found) { addy = Convert.ToUInt32((binFind.BaseStream.Position - (hex.Length+1))); break; } } return addy;
That's definitely the source of the slowness, cuz I checked and it's the most time consuming. I'm not sure how I can do find better though. :/ 2) It doesn't check for branches the way I wanted so it might have some issues eventually. It just checks for anything that starts with 4 to know if it's a branch: if ((u32 & 0xF0000000) == 0x40000000) break; The higher 40s are cr insructions...so there might be a slight issue there but for now this works. TODO: Improve performance Check for branches for real Other than that, it works. I successfully ported every thing I already ported to see if I get the same results and I did. I just had to wait about a minute or so. --- Copied into first post...just because
|
|
« Last Edit: November 21, 2011, 08:51:43 PM by Stuff »
|
Logged
|
|
|
|
Bully@Wiiplaza
Hacker
Legendary Member
Karma: 93
Posts: 1853
|
|
« Reply #5 on: November 22, 2011, 08:43:38 PM » |
|
yay it worked with goldeneye PAL <-> NTSC_U porting. That´s awesome work, man. Makes things way easier. Typo: *Ported with a smPort* Btw. is it the whole source you posted above this post? I´d like to mess with it. I wanna learn
|
|
« Last Edit: November 22, 2011, 08:51:49 PM by Bully@Wiiplaza »
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #6 on: November 22, 2011, 09:10:58 PM » |
|
oh oops. How'd that happen XD. Well it's fixed. Same link cuz it's in my dropbox. Not like it's a big change. >.>
Nah. The post just had the find function. I guess I could though the whole source up for dl. But googlecode asks me for license and stuff D:. idk what they talkin about. If it's not big I'll put it it a zip in my dropbox. The source is in the first post now.
|
|
« Last Edit: November 22, 2011, 09:39:58 PM by Stuff »
|
Logged
|
|
|
|
Bully@Wiiplaza
Hacker
Legendary Member
Karma: 93
Posts: 1853
|
|
« Reply #7 on: November 23, 2011, 01:31:39 PM » |
|
plz can you... - make it remember the path where one loaded RAM Dumps the last time - automatically load the latest 2 dumps that were used - change PAL & US to Source Region Dump & Destination Region Dump (so that nobody gets confused with jap excluded, etc.) - fix porting issue which messes up the result: Address 80000017 o.O (note: I didn´t use your newest typo fixed update file) I´ve the feeling that it will not do it correctly on "branch" codes. - And yeah, it´s VERY slow. 1 minute for 1 port, ugh. :/
|
|
« Last Edit: November 23, 2011, 01:39:30 PM by Bully@Wiiplaza »
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #8 on: November 23, 2011, 11:02:28 PM » |
|
plz can you...
- make it remember the path where one loaded RAM Dumps the last time - automatically load the latest 2 dumps that were used
I guess I could make it save a cfg file and then make it check for it when the form loads. I fixed a little directory issue I was having, but that doesn't make it remember anything. - change PAL & US to Source Region Dump & Destination Region Dump (so that nobody gets confused with jap excluded, etc.)
This actually makes sense. I think 2 buttons are useless. It does do the same exact functions for each. Just different arguments... Like, you can put your pal code in the us textbox and press the to pal button and it'll work as long as you open the dumps in reverse. I'll change the 2nd textbox to a label too. - fix porting issue which messes up the result: Address 80000017 o.O (note: I didn´t use your newest typo fixed update file) I´ve the feeling that it will not do it correctly on "branch" codes. XD. I guess it doesn't do branch codes properly. Try using the address directly before the code(0424BBF 4) And then add 4 to the result manually.. If that works, I could probably add a check that'll do that too...or is there a better way to port branch codes? asmPort follows the exact same steps you mentioned in the thread I linked above(the best I could atm). The typo fix was just that. No new secret feature/fixes were added. --- (related) Somebody asked me to port this. Idk who made it either so I quote the guy that didn't know first: dont know who made it .. just sharing
{MoonJump} activate with Zr 04275394 8803000A 04254B08 D01F007C 286593DC 00000004 C2275394 00000002 38000002 9803000A 8803000A 00000000 C2254B08 00000003 3E604200 927F7FF8 C01F7FF8 D01F007C 60000000 00000000 E0000000 80008000
042753F8 8803000A 04254B6C D01F007C 2865B89C 00001400 <-I changed this manually C22753F8 00000002 38000002 9803000A 8803000A 00000000 C2254B6C 00000003 3E604200 927F7FF8 C01F7FF8 D01F007C 60000000 00000000 E0000000 80008000 *Ported with asmPort* It looks like it worked. Looking at it roughly, I think each address was ntsc-u + 0x64 which sounds believable...But I was told that this doesn't work >.> (note: nothing in my code even mentions 0x64). idk if the code even worked in the first place, but it hurts me to hear such a perfectly ported code doesn't work >.>. I think I'm gonna test it myself to make sure it's not cheater derp. I wonder what went wrong. Ok it apparently came from zealnot.
--- - And yeah, it´s VERY slow. 1 minute for 1 port, ugh. :/
Yeah..this is pretty slow...needs fixing. I modified some stuff I found googling for the find function. It pretty much checks every single byte in the dump until it finds the source address. And then it does it again in the destination dump as many times as it was found in the source. If I can find a more efficient way of doing this, it'll be a major update(like 0.01->3.7 lol) cuz it's really just findHex() that's taking up that time. Everything else combined doesn't even take up 1 second.(OK maybe 2). And after that speed issue is fixed I guess I could add a check button(since I'm removing the 2nd textbox) to check if porting back returns the same code. I'll try to fix all that stuff over the weekend(not the speed thing. idk what to do with that yet).
|
|
« Last Edit: November 23, 2011, 11:40:42 PM by Stuff »
|
Logged
|
|
|
|
Bully@Wiiplaza
Hacker
Legendary Member
Karma: 93
Posts: 1853
|
|
« Reply #9 on: November 24, 2011, 08:55:59 AM » |
|
you´re right, branches are different on each region because they contain full addresses aka 0x80123456. A workaround would be, if you make it avoid branch addresses, let it port e.g. the address *before* the branch and afterwards add back the offset that got substracted... also, I´m happy that my method made it to a program code. Surely, the template testing can be done more efficiently. Maybe you find a way that it recognises more seldom ASM values like I do? I prefer store and load instructions with bigger offsets (100+) since they are quite rare. I mostly use a template with such an instruction plus a following random instruction. Branches are always a no go! That could increase chances to have less tries and faster speed. So yeah, skip values with 4XXXXXXX (aka branch) and watch out for 8XXXXXXX and 9XXXXXXX values with (100+ offset). Maybe it helps. :/
|
|
« Last Edit: November 24, 2011, 09:04:59 AM by Bully@Wiiplaza »
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #10 on: November 24, 2011, 07:39:54 PM » |
|
It copies everything inbetween the surrounding branches. It copies everything in bold: 80130960 D8010028 83A1002C 48000008 3BE00258 80130970 A81E08A6 *7C00EA14* B01E08A6 7C000734 80130980 2C000000 40800010 38000000 B01E08A6 That's as unique as any hex string gets. I wouldn't copy all that doing it manually, but if a program is doing it, there's much less chance of finding a copy. And that part doesn't take long. That gets passed to findHex() as a byte array and the reason it takes long is because it goes through every byte in the dump until it finds this hex string where it was first copied from(so that it doesn't search up to the end of the dump). It goes through the byte array pretty fast, it just has to go through the array for every byte in the dump and at every byte it starts to check if the following bytes match with the array, moving to the next byte only if there isn't a match. Writing this, I think I came up with a way to make findHex() faster. Instead of a byte array...I should pass a UInt32/Int32 array instead...why I didn't think of that before...>.> It's actually easier to pass because I don't have to convert UInt32 into 4 bytes and then get all complicated trying to append it to a byte array. And then findHex() can check 4 bytes at a time instead of 1. Cuz asm is 4 bytes. So I don't have to worry about "the next byte could be this". I'll get that done. It should reduce wait time by alot. I'd say x/4 but the checks would be faster too(when it thinks it found something). Oh and I guess that's settled. If it really is acceptable, I'll move to the previous instruction and search for that instead and then add the offset back. But what if the branch code was like a branch always instead of the default bne-, and between regions the offsets changed? That would be a bad port. --- Speed was improved. There's still a little wait time, but it's nothing like before. I said it'd be a major update, but I only changed that. When I do everything else, it'll be v1.0.
|
|
« Last Edit: November 24, 2011, 10:04:14 PM by Stuff »
|
Logged
|
|
|
|
dcx2
Computer Engineer
Moderator
Legendary Member
Karma: 165
Posts: 3468
|
|
« Reply #11 on: November 25, 2011, 02:38:59 AM » |
|
2) It doesn't check for branches the way I wanted so it might have some issues eventually. It just checks for anything that starts with 4 to know if it's a branch:
if ((u32 & 0xF0000000) == 0x40000000) break;
That's the wrong way to detect branches. Op codes are the first *six* bits of a word, not the first four. According to the datasheets for the various branches http://pds.twi.tudelft.nl/vakken/in101/labcourse/instruction-set/bclr.htmlhttp://pds.twi.tudelft.nl/vakken/in101/labcourse/instruction-set/bcctr.htmlhttp://pds.twi.tudelft.nl/vakken/in101/labcourse/instruction-set/bc.htmlhttp://pds.twi.tudelft.nl/vakken/in101/labcourse/instruction-set/b.htmlNow, it's a bit difficult to actually translate using that datasheet. The op codes are given in decimal. So the unconditional branch (the last one, b) is decimal 18 = 0x12 = 0b010010 Now that's right-justified. However the op code is the *first* six bits, so we need to left justify. I'll use ?'s for the "don't cares" (we don't care what value a don't care is, hence why they're called "don't care''s) 0b??01 0010 (right justified) = 0b0100 10?? (left justified) = 0x48 & 0xFC For the other op codes, they would be 0x49 & 0xFC, or 0x40 & 0xFC. Technically, for the first branch (bclr), you should also make sure that the reserved bits 16-20 are all 0. This would be done by masking with 0xF800 and making sure that the bits in corresponding to the 0xF8 are clear. The reason is because the 0x49 op code might represent more than one type of instruction, and the reserved bits are used to figure out which one (kinda like a "sub op code") So this would detect all branches if ((u32 & 0xFC00F800) == 0x49000000 || (u32 & 0xFC000000) == 0x48000000 || (u32 & 0xFC000000) == 0x40000000) break; Also, if you re-read brkirch's F6 tutorial, he will tell you that you should avoid branches *with large offsets*. This is because large offsets usually mean "branch to a different function", and when a game is compiled for a new region, the compiler may re-order functions, so they won't be in the same place. However, in your example in your most recent post, your flanking branches were only moving 8-16 bytes, which is a very small offset. Chances are the destination region will have the same branches. He also tells you to avoid loads and stores with large offsets as well, for much the same reason. Loads and stores with large offsets are usually region-specific pointers (which change between regions), or they use r2/r13 (which are where "globals" and that type of stuff are stored, and so the compiler is free to re-order them however it wants)
|
|
|
Logged
|
|
|
|
megazig
Hacker
Full Member
Karma: 4
Posts: 127
|
|
« Reply #12 on: November 25, 2011, 02:55:33 AM » |
|
So ugly. Use bit structs.
struct { unsigned foo: 6; unsigned bar: 26; }
|
|
|
Logged
|
|
|
|
dcx2
Computer Engineer
Moderator
Legendary Member
Karma: 165
Posts: 3468
|
|
« Reply #13 on: November 25, 2011, 03:18:16 AM » |
|
I don't think that works for C#, it's not very friendly to bit-level stuff. If it was C/C++ then yeah, you'd also want to do a union with a struct that had the reserved field so you could easily check for 0. Unions of structs...yum. stackoverflow ftw. http://stackoverflow.com/questions/14464/bit-fields-in-c-sharpalso maybe Stuff could port the C# to C++ while still in the .NET framework.
|
|
|
Logged
|
|
|
|
Stuff
Hacker
Sr. Member
Karma: 31
Posts: 415
0x80000000 = -0
|
|
« Reply #14 on: November 25, 2011, 07:13:52 AM » |
|
uh wut? structs? Unions? Port to C++?
If it means better performance, I have no problem switching to c++, but right now your speaking a foreign language. Also I don't see design view in visual c++.. I stuck with C# because I was trying to strip some data out of a dump and I decided to do this in C++...I spent a whole day trying to get past Main() arguments...And then I had no problem with that in C#. >.>
For the next update I'll just copy&paste that if(branch) and get that other stuff done. Then I'll try porting to C++. Hopefully before I make it a mess. >.<
I want to avoid branches period. I guess because one time I probably copied a branch with a large offset and that returned a bad address or no address. idr, but after that I was like "branches? no". It's interesting to hear loads and stores with large offsets are also not good. I guess that's something else to look into.
Thanks guys, for the help and such.
|
|
|
Logged
|
|
|
|
|