Is printf() always the same?

Started by Stuff, January 23, 2012, 06:04:25 AM

Previous topic - Next topic

Stuff

For those of you who participated in these threads, thanks again(or just thanks if I haven't already thank you)

trainer?
http://wiird.l0nk.org/forum/index.php/topic,9045.0.html

scroll speed
http://wiird.l0nk.org/forum/index.php/topic,9196.0.html

This is the outcome of those discussions:
[spoiler][/spoiler]

As you can see, I have a nice working code. I'll have a YT vid up today or tomorrow or something showing all the possible sharpness "benchmarks" along with what you would put in for sharpness in the weapon mod codes thanks to this. However, I replaced some text. And I noticed something interesting after the code's hook.

80214FA0:  4BE47871   bl   0x8005c810
I have a "Copy Function" of Monster info Display saved in a txt. When I saw that^, it looked familiar.
817C53E8:  4A897429   bl   0x8005c810 # bl this quite a few times.
I guess that's why.

817C53D4:  88B4FFFA   lbz   r5,-6(r20)
817C53D8:  88F20919   lbz   r7,2329(r18)

iirc, -6(r20) points to the color switcher portion of the code. I made the text green by replacing li r5, 0 with li r5, 3. Very interesting. And the argument from before was r7. Mhmmmmm. MID passes more arguments, but that'll be for later.

So bl   0x8005c810 is a call to the wonderful printf() that gets called for anything text related probably. But I wonder. Do you think printf() is the same in all games? Or at least in most games. Or some. Or a few.. Or just MH3... Can I search for the first few instructions and find it in any game so could have something to bl to? Cuz printf() would be awesome. After fully understanding this, no game would not have some display made by me  >:D. Here's a "Copy Function" of what I think is printf() in case you want to see/compare to one of your games.

[spoiler="I guess printf()"]8005C804:  7C630734   extsh   r3,r3
8005C808:  7C840734   extsh   r4,r4
8005C80C:  4BFFEEA4   b   0x8005b6b0
8005C810:  9421FD80   stwu   r1,-640(r1)
8005C814:  7C0802A6   mflr   r0
8005C818:  90010284   stw   r0,644(r1)
8005C81C:  93E1027C   stw   r31,636(r1)
8005C820:  93C10278   stw   r30,632(r1)
8005C824:  7CBE2B78   mr   r30,r5
8005C828:  7CDF3378   mr   r31,r6
8005C82C:  40860024   bne-   cr1,0x8005c850
8005C830:  D8210028   stfd   f1,40(r1)
8005C834:  D8410030   stfd   f2,48(r1)
8005C838:  D8610038   stfd   f3,56(r1)
8005C83C:  D8810040   stfd   f4,64(r1)
8005C840:  D8A10048   stfd   f5,72(r1)
8005C844:  D8C10050   stfd   f6,80(r1)
8005C848:  D8E10058   stfd   f7,88(r1)
8005C84C:  D9010060   stfd   f8,96(r1)
8005C850:  90610008   stw   r3,8(r1)
8005C854:  9081000C   stw   r4,12(r1)
8005C858:  90A10010   stw   r5,16(r1)
8005C85C:  90C10014   stw   r6,20(r1)
8005C860:  90E10018   stw   r7,24(r1)
8005C864:  9101001C   stw   r8,28(r1)
8005C868:  91210020   stw   r9,32(r1)
8005C86C:  91410024   stw   r10,36(r1)
8005C870:  3CA08066   lis   r5,-32666
8005C874:  38A585E0   subi   r5,r5,31264
8005C878:  88050023   lbz   r0,35(r5)
8005C87C:  28000003   cmplwi   r0,3
8005C880:  40820010   bne-   0x8005c890
8005C884:  80050010   lwz   r0,16(r5)
8005C888:  2C000000   cmpwi   r0,0
8005C88C:  4082004C   bne-   0x8005c8d8
8005C890:  7C630734   extsh   r3,r3
8005C894:  7C840734   extsh   r4,r4
8005C898:  4BFFFF4D   bl   0x8005c7e4
8005C89C:  7FC30734   extsh   r3,r30
8005C8A0:  4BFFFF51   bl   0x8005c7f0
8005C8A4:  38C10068   addi   r6,r1,104
8005C8A8:  3C000400   lis   r0,1024
8005C8AC:  90010068   stw   r0,104(r1)
8005C8B0:  38010288   addi   r0,r1,648
8005C8B4:  9001006C   stw   r0,108(r1)
8005C8B8:  38010008   addi   r0,r1,8
8005C8BC:  90010070   stw   r0,112(r1)
8005C8C0:  38610078   addi   r3,r1,120
8005C8C4:  38800200   li   r4,512
8005C8C8:  7FE5FB78   mr   r5,r31
8005C8CC:  48401401   bl   0x8045dccc
8005C8D0:  38610078   addi   r3,r1,120
8005C8D4:  4BFFFD45   bl   0x8005c618
8005C8D8:  83E1027C   lwz   r31,636(r1)
8005C8DC:  83C10278   lwz   r30,632(r1)
8005C8E0:  80010284   lwz   r0,644(r1)
8005C8E4:  7C0803A6   mtlr   r0
8005C8E8:  38210280   addi   r1,r1,640
8005C8EC:  4E800020   blr   
[/spoiler]

tr;dl
Is printf() the same in every game? printf() in spoiler.
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm

dcx2

printf is a part of the C Run Time Library.  This will probably be the same, or quite similar, for pretty much every single game.  Unless the run time changes, which is possible but probably rare for something as mature as printf.

Note that there also a few different types of printf, and not all games will use the same version of *that*.

Stuff

Ah. I tried to find it in LOZ and Kirby and didn't find it. :/ I guess a RBP on text is the way to go. So far, all text reads' callers were calling that printf().
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm

Bully@Wiiplaza

we definitely need some noob friendly tut to create or own custom text displays for any game.
This will be so beast xD
My Wii hacking site...
http://bullywiihacks.com/

My youtube account with a lot of hacking videos...
http://www.youtube.com/user/BullyWiiPlaza

~Bully

megazig

printf doesn't usually go to the screen for wii games.

I'd bet it's vsprintf that was found and that is being sent to another function that does the screen rendering

Stuff

#5
Well. I guess if you want to get technical about it, I was only calling it printf cuz idk what else to call it. For now, I'll call it (vs)printf


hmm.. dropbox's photos folder is not good. Gonna have to upload it somewhere then. First post has the image fixed now.
Quote from: Bully@Wiiplaza on January 24, 2012, 04:17:32 PM
we definitely need some noob friendly tut to create or own custom text displays for any game.
This will be so beast xD
[spoiler][/spoiler]

5 sec tutorial :p

In this game 8005c810 is (vs)printf. You just gotta call it from somewhere and your good. When you call it, this is what I've noticed:
r3 = x coordinate in pixels
r4 = y coordinate in pixels
r5 = color
r6 = points to string
r7 = 1st arg
r8 = 2nd arg
r9 = 3rd arg
r10 = 4th arg

And when the function returns, all these registers were modified. :/ So if you wanted to display more than one string, you'd need to put the pointer in another register like 20. r12 and r11 are also modified. Maybe they're 5th and 6th arguments. idk. I didn't bother experimenting more. These are the registers I know and 20-22 don't get modified by (vs)printf. MID uses these registers.

Then it's the same as printf in C++.
printf ("Stuff: %d %X  %04x %4d", r7, r8, r9, r10);

r3 and r4 would affect where the text is displayed. It's easy to find a good position with gecko.net.
r5 would change the text color. They're listed somewhere
r6 would have to point to "Stuff: %d...
when it gets up to %d, it'll show r7 as decimal, %X is r8 in uppercase hex, %04x is r9 as a 4 digit lower case hex padded with 0 and so on. It'll stop at null of course.

That's it. Now to find it, I'm sure doing a RBP on some text is enough. The equipment box text is being read by some funtion. It's caller was calling (vs)printf.

Oh and when you find (vs)printf, you'd have to mess with the registers to see what can be done in case it doesn't follow the same rules. You could probably look around and see it loading a pointer to some string into rX and possible a li rY, 0 to display white text. Replacing the text that it's reading with some text that includes "%X %X %X" would most likely lead you to find the argument registers. That's how I found out it was r7. It displaying 80746ca4 and r7 was the only register with that value before the bl. I changed an instruction that didn't look important to li r7, something, and saw the change immediately. r8-10 came from seeing it being used by MID. But I'm sure %Xing would show you all the argument registers.
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm

megazig

ah, the text output in mh3

that function is calling a pformat or a vsprintf as any *printf does to handle conversion of special characters.

it then uses the graphics engine to render to screen.  unfortunately, most games aren't as nice. 99.999% of the time you can find the proper pformat to use to convert your const char* string and ... args to the string buffer, but you won't get a special output function. and almost assuredly you won't get a nice function like this.  for many games it will involve setting up a buffer, wsprintf'ing into that buffer, and then calling their static string output function such as a nw4r::lyt::TextBox::SetText(wchar* buffer);

it's a shame, but it's just not usually done in games

Stuff

Aww. That sounds complicated. Oh well. I thought I had a thing going on. XD.
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm

dcx2

Wow, thanks for the insights megazig.

I did something like this for Tales of Symphonia: DotNW.  It had some format strings that were used to display things like character level, HP, MP, name, etc.  I hijacked them for displaying real-time feedback for my rollers.

I didn't even realize that Stuff was talking about writing arbitrary text to arbitrary coordinates on the screen.  That is quite a badass function.  I figured he was also hijacking an existing format string that gets written onto the screen by the game on its own but I assumed incorrectly.  I wonder if it would be possible to port the function and its dependencies to other games?


Quote from: Stuff on January 25, 2012, 12:20:15 AM
And when the function returns, all these registers were modified. :/ So if you wanted to display more than one string, you'd need to put the pointer in another register like 20. r12 and r11 are also modified. Maybe they're 5th and 6th arguments. idk.

Recall that the registers below r13 (excluding r1 and r2) are volatile.  The PPC EABI (the "rules of the game" for the compiler) stipulate that when you call a function, you cannot rely on the contents of volatile registers being the same after the function call returns.  The caller is allowed to do anything and everything it wants to those registers.

The PPC EABI stipulates that r11 and r12 cannot be arguments.

QuoteThese are the registers I know and 20-22 don't get modified by (vs)printf. MID uses these registers.

Just because they do not get modified does not mean that they are free to use.  Everything above r13 are non-volatile registers.  After a function call returns, the contents of non-volatile registers *must be the same* (hence all the pushing and popping).  Ironically, they often can be changed without problems, but the results can be unpredictable.  If you plan on using them, back them up just for safety.  Even if they don't look like they were used nearby, they could be used by some function much lower in the call stack that you might not even know about.

megazig

that's easy to verify by finding the _restgpr_20, 21, 22 functions and check for xrefs. you'll likely see them being used at some point. just need to make sure it's being used not on your current stack

easiest to just follow the EABI and save your volatile regs though

Stuff

Quote from: dcx2 on January 25, 2012, 02:29:36 AMI figured he was also hijacking an existing format string that gets written onto the screen by the game on its own but I assumed incorrectly.  I wonder if it would be possible to port the function and its dependencies to other games?
Well that is where I started. The string said "Select equipment to reorder" and I replaced it with my own text and added %x to see what would happen. Then the display happened. I'm glad I was able to understand it. My MID is fixed :p.

Well, 0x8045dccc has a bl that has a b to a function with conditional branches and some more bl's. It'll probably be 30-40 lines if it works. I would like to just put it after a 68 code. Then you just gotta lis, lwz bX, and mtlr(I still like blrl better XD).

The only thing is it doesn't display float properly. The image in my last post shows coordinates entirely based off of Bully's Teleport(near the map). So I assume it's correct because his code did work. But If I display it as float, I get
x: 1.2400000~ish and it's shaky o.O
y: 0.000000
z: 0.000000

So I changed it to hex because it's just wrong as float. Or maybe I'm doing it wrong. %f
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm

dcx2

You were probably getting the right output, you just needed to specify width/precision.

http://en.wikipedia.org/wiki/Printf_format_string

try %5.2f instead of %f

Personally I prefer %g

Stuff

#12
Alright I'll try that in a little bit. I tried %g and got the same stuff though.

Edit:
Nope. Maybe it's displaying a value from a float register.. And now I noticed the fregs are constantly changing >.>. Any instruction makes them change.

It is. When I change %x to %g, the x and y values were pushed to y and z. But what about those changing fregs?
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm

dcx2

The fregs have this weird issue where they lie sometimes.  I never fully figured it out, but I think the fregs only tell the truth for one breakpoint after an instruction that uses the floating point unit.  There's a bit in SRR1 that lets you know whether the fregs are fake; not sure which bit, but if you set a breakpoint and then step through a bunch of code with integer/fpu instructions, it should pop out at you.

So when you set the BP, there has almost certainly been *some* FPU instruction executed.  However, when you press step and it's not an FPU instruction, then the fregs will lie (FYI: steps are also breakpoints).  They will continue to lie as long as you step over non-fpu code.  Once you execute an fpu instruction, they'll tell the truth for one frame.  If you have a series of consecutive fpu instructions, they will all tell the truth until after the next non-fpu instruction is stepped over.

Stuff

Ah well in my case(if it's situational) the lying bit was the 19th(?). 0000B032 for truth, 00009032 for lies.

I also tried to modify all the fregs to see if anything would change. I replaced the color instruction with lfs fX,60(r21) and went through each freg and nothing happened. I also did a XBP before and after the print function and searched memory for the first float displayed but got no results. So idk where it's pulling those floats from. It's not the regs because r7 gets used as the 2nd argument after cchhanging %x to %f or %g. I don't see it in the fregs or in memory. I'm just gonna leave coordinates as hex.
.make Stuff happen.
Dropbox. If you don't have one, get it NOW! +250MB free if you follow my link :p.

Mod code Generator ~50% complete but very usable:
http://dl.dropbox.com/u/24514984/modcodes/modcodes.htm