Freeze Time Assembly Language

Started by Nutmeg, August 02, 2010, 01:50:20 AM

Previous topic - Next topic

Nutmeg

Ok.  r31 stores the time!  not the seconds, but the overall time.  e.x. for 1 min and 1 sec to go, it is stored as 3D.  But it stores what is about to be loaded... so 3C if 1:01 is displayed on the game clock.

801E9FD4:  9BE3008E   stb   r31,142(r3)
801E9FD8:  BB61002C   lmw   r27,44(r1)
801E9FDC:  80010044   lwz   r0,68(r1)
801E9FE0:  7C0803A6   mtlr   r0
801E9FE4:  38210040   addi   r1,r1,64
801E9FE8:  4E800020   blr   
801E9FEC:  9421FF70   stwu   r1,-144(r1)
801E9FF0:  7C0802A6   mflr   r0
801E9FF4:  90010094   stw   r0,148(r1)
801E9FF8:  DBE10080   stfd   f31,128(r1)
801E9FFC:  F3E10088   psq_st   f31,136(r1),0,0
801EA000:  DBC10070   stfd   f30,112(r1)
801EA004:  F3C10078   psq_st   f30,120(r1),0,0
801EA008:  39610070   addi   r11,r1,112
801EA00C:  481A388D   bl   0x8038d898
801EA010:  808DDB98   lwz   r4,-9320(r13)
801EA014:  7C7A1B78   mr   r26,r3          //dupicate time is stored at r26
801EA018:  806DD8D4   lwz   r3,-10028(r13)
801EA01C:  8BC40EC5   lbz   r30,3781(r4)
801EA020:  4BE6E695   bl   0x800586b4
801EA024:  806DD8D4   lwz   r3,-10028(r13)
801EA028:  C3E2A690   lfs   f31,-22896(r2)
801EA02C:  C003001C   lfs   f0,28(r3)
801EA030:  EC410028   fsubs   f2,f1,f0
801EA034:  EFC00828   fsubs   f30,f0,f1
801EA038:  FC02F840   fcmpo   cr0,f2,f31
801EA03C:  40810008   ble-   0x801ea044
801EA040:  48000008   b   0x801ea048
801EA044:  FFE01090   fmr   f31,f2
801EA048:  FC20F090   fmr   f1,f30
801EA04C:  481A3729   bl   0x8038d774
801EA050:  2C1E0000   cmpwi   r30,0
801EA054:  4182000C   beq-   0x801ea060
801EA058:  FC20F890   fmr   f1,f31
801EA05C:  4800001C   b   0x801ea078
801EA060:  3C004330   lis   r0,17200
801EA064:  90610054   stw   r3,84(r1)  //r3 is stored at 806f7a90 + 84
801EA068:  C822A6A0   lfd   f1,-22880(r2)
801EA06C:  90010050   stw   r0,80(r1)
801EA070:  C8010050   lfd   f0,80(r1)
801EA074:  EC200828   fsubs   f1,f0,f1
801EA078:  481A36FD   bl   0x8038d774
801EA07C:  3C808889   lis   r4,-30583
801EA080:  7C7F1B78   mr   r31,r3
801EA084:  38048889   subi   r0,r4,30583
801EA088:  3B600000   li   r27,0
801EA08C:  7C001816   mulhwu   r0,r0,r3
801EA090:  541DD97E   rlwinm   r29,r0,27,5,31
801EA094:  1C1D003C   mulli   r0,r29,60
801EA098:  7F801850   sub   r28,r3,r0
801EA09C:  4BF275D1   bl   0x8011166c
801EA0A0:  C002A694   lfs   f0,-22892(r2)
801EA0A4:  FC1E0040   fcmpo   cr0,f30,f0
801EA0A8:  4C401382   cror   2,0,2
801EA0AC:  4182000C   beq-   0x801ea0b8
801EA0B0:  2C1E0000   cmpwi   r30,0
801EA0B4:  4182004C   beq-   0x801ea100
801EA0B8:  881A0054   lbz   r0,84(r26)
801EA0BC:  2C000000   cmpwi   r0,0
801EA0C0:  40820040   bne-   0x801ea100
801EA0C4:  38000001   li   r0,1
801EA0C8:  38A000CC   li   r5,204
801EA0CC:  981A0054   stb   r0,84(r26)
801EA0D0:  38600033   li   r3,51
801EA0D4:  380000FF   li   r0,255
801EA0D8:  38810028   addi   r4,r1,40
801EA0DC:  98A10028   stb   r5,40(r1)
801EA0E0:  98610029   stb   r3,41(r1)
801EA0E4:  9861002A   stb   r3,42(r1)
801EA0E8:  9801002B   stb   r0,43(r1)
801EA0EC:  807A000C   lwz   r3,12(r26)
801EA0F0:  48118295   bl   0x80302384
801EA0F4:  807A0010   lwz   r3,16(r26)
801EA0F8:  38810028   addi   r4,r1,40
801EA0FC:  48118289   bl   0x80302384
801EA100:  2C1D0000   cmpwi   r29,0
801EA104:  40820044   bne-   0x801ea148


The line above where r3 is stored at an address isn’t really stored at an address.  The time just blips in that address for a split second after the breakpoint.  After that, there is a pointer that leads to a bunch of other pointers…

How should I stop r31 from decreasing?
I'm inbetween your legs... that's not awkward.

dcx2

Seeing the value in r31 does not mean that's where it really is.  r31 is probably another copy.

@014, what is in r3?  You say "duplicate time", but r3 is being cached in r26, and r26 is being used as a pointer @0CC.

It may help you to know that bl is how the CPU calls functions, and that values are returned in r3 and r4.  So the value in r3 @04C is going to be different from the value in r3 @050.  The value in r3 that we get after calling the bl @04C will be the time you want.  This value is put into r31 @080.  It's also put on the stack @064, as part of building a float that ends up in f0 @070.

---

I like the fsubs @030/034.  The fcmpo @038 and the stuff after it through 048 are making sure that the smaller of f31 and f2 is loaded into f31.  But then f30 is put into f1...probably as part of getting ready to call that bl we like @04C.  It feels like that bl is taking the float in f1 and turning it into an integer in r3.  f30 came from the fsubs @034.  It looks like f0 has the time, stored as a float, @030/034.  f0 is loaded @02C, by a pointer in r3.

That pointer in r3 comes from a special area.  r13 is the small read/write data area.  Constants and globals and stuff like that are stored here.  So I bet the pointer to the timer object is stored as a global variable, and the pointer is loaded into r3 @024.

---

In summary, this is my guess.  r3 is loaded with the timer pointer @024.  Then the timer, as a float, is loaded @02C.  The time then ticks down once @034.  The new time is then converted to an integer by the call to 04C.  This integer is then used @064 and @080.  I think it's the value in r31 that you see.

---

Suggestion: You can test this, but it's more difficult with a float; you can't modify a float register, you need to modify the memory it reads instead.  Set a breakpoint @02C, right before f0 is loaded with the timer-as-float.  Then click Show Mem to go to Memory Viewer.  Go to the Poke box, right click, to hex->float, then increase the value you get...like, double it or something obnoxiously large, then float->hex, and click Poke.  Cross your fingers and hit Run Game.

---

In case you like the tid bits about what the code is doing...FEC through 00C is function prologue.  Make room on the stack (...144 bytes?  That's a LOT of room!), back up the LR on the stack, back up a few floats on the stack, and the bl @00C is probably backing up registers r31 through...r26?...on the stack.

You expressed interest in the stw @064.  Note that the pointer being used for that stw is coming from r1.  r1 is the stack pointer; anything that lives on the stack is short-lived and temporary.  Each function has a "stack frame"; this stack frame is created in the function prologue, and destroyed in the function epilogue at the end (when it executes a mflr/blr).  Once you go through that blr, everything on the stack is lost forever.  The next time this function is called, the stack could be different, which means that value could go to a different address each time this function is called.