+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: ASM code to write to memory with ps2rd

  1. #1
    Join Date
    Mar 2007
    Posts
    608

    Default ASM code to write to memory with ps2rd

    This is just a tiny little thing I made in about 5 minutes and tested. It works perfectly. Just use it with ps2rd to write codes to memory while playing, since ps2rd doesn't have that ability yet. It's only 41 lines of code, which surprises me because I kept thinking something this simple would have been twice that size.

    Code:
    2??????? 0803c000
    200efff0 0???????
    200f0000 3c19000f
    200f0004 8f38fff4
    200f0008 8f2ffff8
    200f000c 8f2efffc
    200f0010 8f2dfff0
    200f0014 340cfeef
    400f0018 00040002
    118d000f 00000000
    200f001c 340cfedf
    200f0024 340cfebf
    200f002c 340cfe7f
    200f0034 340cfdef
    200f0038 118d0012
    200f003c 340cfddf
    200f0040 118d0017
    200f0044 340cfdbf
    200f0048 118d0018
    400f0050 00040002
    03e00008 00000000
    200f005c af0f0000
    200f0064 a70f0000
    200f006c a30f0000
    200f0070 af20fff4
    200f0074 af20fff8
    200f0078 34180001
    200f007c 03e00008
    200f0080 af38fffc
    200f0084 000e7040
    200f0088 34180001
    200f008c 3c0f0800
    200f0090 15f8fffe
    200f0094 27180001
    400f0098 00030003
    03e00008 00000000
    200f009c af2efffc
    200f00a0 030ec025
    200f00a8 af38fff4
    200f00ac 01ee7825
    200f00b4 af2ffff8
    That can be copied and pasted to every game if you want. Only the first and second lines are different from game to game.

    The first line is the address that jumps to this function. Just load the game's ELF file, invoke the analyzer, and use labelmates to find "scesifsendcmd". Whatever address its "jr ra" is is the address you should use to jump to this function. For example, it would be 20119c04 0803c000 for "Obscure: The Aftermath NTSC".

    The second line is the address of the joker/pad address. For "Obscure: The Aftermath NTSC" it would be 200efff0 00552b02.

    Buttons:
    L2 + Up = Write 4 bytes to address
    L2 + Right = Write 2 bytes to address
    L2 + Down = Write 1 byte to address
    L2 + Left = Reset Address & Value to 0, reset ORed value to 1
    R2 + Up = Shift ORed bit left 1 bit
    R2 + Right = OR the OR value to the address
    R2 + Down = OR the OR value to the value

    R2 + Up will intentionally pause the game for about 1 second. It's that way so you don't shift the bit left 50 times in an instant.

    You start by pressing L2 + Left. Once you know the address and value you want to write to the address, you use R2 + Up to shift the bit, and R2 + Right & R2 + Down to OR that bit to create the address and value you want write to that address. If you mess up, just Press L2 + Left and restart. Use ps2cc or whatever to see the memory in case you aren't sure of what you are doing. All you would need to look at are addresses 000efff4 (your address), 000efff8 (your value), and 000efffc (the value you OR to the address and value to create them).
    Attached Images Attached Images

  2. #2
    Join Date
    Sep 2008
    Posts
    231

    Default

    Quote Originally Posted by bungholio View Post
    R2 + Up will intentionally pause the game for about 1 second. It's that way so you don't shift the bit left 50 times in an instant.
    Just set an isHolding boolean check.

  3. #3
    Join Date
    Jul 1999
    Posts
    7,089

    Default

    ps2rd has this several versions ago, but it was unfortunately broken by an update and never fixed...

    Nice job, though
    I may be lazy, but I can...zzzZZZzzzZZZzzzZZZ...

  4. #4
    Join Date
    Sep 2006
    Location
    Germany
    Posts
    549

    Default

    I'll be adding it soon. Shouldn't be too difficult.

  5. #5
    Join Date
    Mar 2007
    Posts
    608

    Default

    Quote Originally Posted by Gtlcpimp View Post
    Just set an isHolding boolean check.
    What is a "isHolding" boolean check? I had some other too long thing that only executed something once every time I pressed a combination of buttons for changing the current dungeon level in Disgaea 1, but I doubt this "isHolding" check is as long as that. The only way I know of how to prevent the code from multiple executions is to create a pause or go for that long weird code I had for Disgaea 1.

    How do I create it, or what is it? I need an example because it's never a surprise when I miss doing something in an incredibly simpler way.



    I'm slow at doing this, but I am writing some ASM code to create watchpoints on any sw, sh, or sb commands. At this point I've got it to check addresses, see if they are a store operation, check if there are more store operations after it, check if the line before the first store operation is a jump or branch, and check if the line after the first store operation is a jump or branch assuming it only finds one store operation and there isn't a jump or branch before it already. That gives me 3 values to use, and using those I should be able to make a simple code to make the game create a custom subroutine for each store operation that will check to see what address is being written to. I'm taking the path that will probably take a lot of memory below 0x00100000, but I'm going to make the code record the location of the last store operation it created a custom subroutine for and to undo the custom subroutines it created and erase all subroutines so it can create routines for all store operations after the last one it found. I'm moving mighty slow though.
    Last edited by bungholio; 09-07-2010 at 03:57:00 PM.

  6. #6
    Join Date
    Sep 2008
    Posts
    231

    Default

    Here's an example of what I'm talking about:


    CodeDesigner v2.0 Source:
    Code:
    /*
      CodeDesigner v2.0 Source
      ReadPad() Example with isHolding check
      Created by: Gtlcpimp
    */
    
    
    address $000bfff0 // The _readPad configuration memory block
    hexcode $00100000 // Controller input address
    nop // isHolding boolean address
    
    nop // Padding to keep everything inline for ps2dis debugging
    nop // Padding to keep everything inline for ps2dis debugging
    
    address $000c0000 // Change to wherever you want
    // Or just append the _readPad function to your code
    
    
    _readPad:
    // No need to preserve registers since we are only using v0 and v1
    
    lui v1, $000c
    lw v1, $fff0(v1) // Load controller input address from config section
    
    lh v1, $0000(v1)
    addiu v0, zero, -1
    
    bne v1, v0, 7 // Check for no controller input
    nop
    lui v0, $000c
    sb zero, $fff4(v0) // Write pad button is not holding (isHolding = false)
    daddu v0, zero, zero
    daddu v1, zero, zero
    goto _readPadQuit
    
    bne v1, a0, 3
    nop
    goto _readPadHold
    
    daddu v0, zero, zero
    goto _readPadQuit
    
    _readPadHold:
    lui v0, $000c
    lb v1, $fff4(v0) // Load boolean isHolding
    bne v1, zero, 7  // See if we already are holding
    nop
    addiu v1, zero, 1
    sb v1, $fff4(v0)  // Write pad button is holding (isHolding = true)
    addiu v0, zero, 1    // Return true on button press check
    daddu v1, zero, zero // Return false on already holding
    goto _readPadQuit
    
    addiu v0, zero, 1
    addiu v1, zero, 1
    
    _readPadQuit:
    jr ra
    nop

    Hexadecimal RAW Output:
    Code:
    200BFFF0 00100000
    200BFFF4 00000000
    200BFFF8 00000000
    200BFFFC 00000000
    200C0000 3C03000C
    200C0004 8C63FFF0
    200C0008 84630000
    200C000C 2402FFFF
    200C0010 14620007
    200C0014 00000000
    200C0018 3C02000C
    200C001C A040FFF4
    200C0020 0000102D
    200C0024 0000182D
    200C0028 10000014
    200C002C 00000000
    200C0030 14640003
    200C0034 00000000
    200C0038 10000004
    200C003C 00000000
    200C0040 0000102D
    200C0044 1000000D
    200C0048 00000000
    200C004C 3C02000C
    200C0050 8043FFF4
    200C0054 14600007
    200C0058 00000000
    200C005C 24030001
    200C0060 A043FFF4
    200C0064 24020001
    200C0068 0000182D
    200C006C 10000003
    200C0070 00000000
    200C0074 24020001
    200C0078 24030001
    200C007C 03E00008
    200C0080 00000000
    Just change the controller input address in the configuration to whatever you want it to be.

    You call it with the controller button you want to know if it is being pressed or not in register a0.
    It will return the value '1' in register v0 if the button is being pressed, '0' if it is not.
    It will return the value '1' in register v1 if you are already holding the button, '0' if you are pressing it as a new button.

    It clears the isHolding when you call it and it reads NOINPUT (0xFFFF). Keep in mind it's just an example, you can implement it in your code if you wish, but it could definitely be made better. (kinda just rushed through it in a hurry)
    Last edited by Gtlcpimp; 09-07-2010 at 05:51:23 PM.

  7. #7
    Join Date
    Mar 2007
    Posts
    608

    Default

    Every bit of that looks confusing. It looks even a bit longer than the code I made for Disgaea 1.

    I've been adding to my watchpoint code all day and came to a severe stop. I have come to realize that every jump to a custom subroutine would need to be a jump and link. If I don't, I might end up overwriting the values of registers being used and am guaranteed to screw up every game. If I JAL, I may overwrite the current return address. In order to preserve the return address, I will need to write to an extra 8 bytes meaning every spot I'll be jumping and linking to a custom subroutine will need a total of 16 bytes at the least. Then the problem occurs that many entire functions are only 8 bytes in length, like:
    jr ra
    sw v1, $008c(v0)

    If I continue with what I am doing, I'll need to make the code check specifically if there's a jump return or just a jump before the store operations. If it detects that, it will need to ignore that instance of store operation(s). That's a bad thing because then I won't be able to make watchpoints for all store operations. That ruins that.

    Any other crazy idea to fix that I have in mind would just be a some kind of crazy recompiler which would change the location of all of a game's code making watchpoints incorrect and will need lots more available memory than there is.



    I have no idea of how to fix that dilemma. I'm going to need to go with some kind of interpreter thing that takes over the entire game's code without changing any of it, and it will read the game's code and execute it normally but will do an extra exception where it will specifically check if a store operation is being executed, and if it is, it will check to ee which address is being written to and compare it with the address you are watching for and then write that address to a certain place in memory if it's writing to the address you are watching for. I don't know how to do that because I don't understand how all PS2 code works by far. All I would be doing is making sure it knows how to handle branches and jumps correctly so they don't break the game, and that alone would be kind of long. I'm only going by what Pyriel once said a while ago, but doing that would slow a game way the hell down. If it weren't for that, I'd have just done that because it would have been perfect, and that code could be changed to create breakpoints and all of that other stuff like pausing a game and somehow going through the game one line of code at a time and whatever else.


    How would someone go about making watchpoints, or anything beyond just a memory scanner?
    Last edited by bungholio; 09-07-2010 at 10:55:41 PM.

  8. #8
    Join Date
    Sep 2008
    Posts
    231

    Default

    You need to preserve your registers. If you don't preserve the return address register and you perform a jump and link it changes the return address to the address 8 bytes higher than the jump and link address.

    Code:
    /*
      CodeDesigner v2.0 Source
    */
    
    addiu sp, sp, $FFF0  // Subtract the game's stack pointer for register preservation
    sq ra, $0000(sp)  // Store the return address on the game's stack
    
    jal $xxxxxxxx  // Jump and link to whatever we want
    nop  // The line executed right before the jump and link operation is executed
    
    lq ra, $0000(sp)  // Load the return address off the game's stack
    jr ra  // Jump to the return address
    addiu sp, sp, $0010  // Add the value we subtracted back to the game's stack pointer to keep the stack in line with the parent function
    Last edited by Gtlcpimp; 09-08-2010 at 07:40:42 AM.

  9. #9
    Join Date
    Mar 2007
    Posts
    608

    Default

    I fully understand that. I came to that conclusion. I keep trying to think of how to handle this "2 line long function with a jump" problem. I've got to think on this stuff a while. I always miss something simple.

  10. #10
    Join Date
    Sep 2008
    Posts
    231

    Default

    Hehe.. This is a bit off topic but I'm just a bit curious, do you or any folks you know use my CodeDesignerv2.0? The function emulator was removed from public download (it was a piece of crap since I just sped through to make it look cool lol), but the application is actually very very useful for MIPS ASM coding =D

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Similar Threads

  1. Help us write some VG hacking history!
    By Lazy Bastard in forum Announcements
    Replies: 9
    Last Post: 07-06-2011, 05:06:36 PM
  2. I Need The PS2rd With The 500 Lines Limit
    By bungholio in forum Research & Development
    Replies: 3
    Last Post: 01-09-2011, 11:05:26 AM
  3. Help with Ps2rd & Ps2cc
    By ploder in forum Research & Development
    Replies: 7
    Last Post: 07-07-2010, 06:15:02 PM
  4. ps2rd help
    By RASAS in forum School of Hacking
    Replies: 0
    Last Post: 04-07-2010, 04:48:01 AM
  5. ps2rd installation help
    By RASAS in forum Last Generation & Retro Hacking
    Replies: 0
    Last Post: 02-22-2010, 03:30:11 AM
Collapse this box.

Visitors found this page by searching for:

ps2rd

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts