Announcement

Collapse
No announcement yet.

[PS2] Printing Text

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • [PS2] Printing Text

    This tutorial uses this game: SOCOM II [SCUS_972.75]

    Update: Added examples for multiple games.

    This tutorial explains how to print text to the screen using SOCOM II. This is a method tutorial as every game will be different. This tutorial assumes you are emulating the game and using PCSX2DIS.

    The code in the tutorial was created by Harry62 and Antix(aka Chronotrigga)

    Example image:
    Click image for larger version

Name:	ceOG5Cu.jpg
Views:	1
Size:	204.6 KB
ID:	163928

    Step 1: Finding the print text function
    - The easiest text to find is the ammo count. Start by looking at your ammo which is most likely "30/30". Fire your weapon and perform a string search for "29/30".
    - Once you have the pointer for that string set a read breakpoint on that address and see what loads it. There will be several functions loading this string pointer. Take note of which functions access it. Now find another string that is printed to the screen such as a start menu item. Repeat the read breakpoint and note the functions that load the string pointer. There should only be one or two for SOCOM 2 that is loading both string pointers excluding the PS2 library functions such as "strcpy" or "strcmp"(do note for other games that these functions may be useful for pinpointing the print text function).
    - If you have multiple functions accessing the string pointers then try function cutting one to see if all text disappears. If it does then you may have the correct function. This part may take some more debugging depending on the game, however for SOCOM 2 this function prints the text:
    PRINT_TEXT: 003635C0


    Step 2: Understanding how the function works
    - Now that you have the function set a breakpoint on it to see how it works.
    - You will notice two args sent to the function. a0 and a1. You should also notice that the string pointer is NOT one of the args. With the breakpoint set you will now need to look through both arguments to better understand what is happening. You will notice the string pointer we found earlier is located in the a0 stack.
    - If you continue looking through the a0 stack you will find the text size, colors, offsets, and eventually the next text pointer stack.
    - For SOCOM 2 the stack is 104 bytes in size. This stack is needed for the
    PRINT_TEXT function.
    - At this point copy the address for a0 and the address for a1. Now try sending those args to the PRINT_TEXT function with a routine that constantly calls the function. The text should render to the screen even if you press start or select.


    Step 3: Create a function for rendering text
    - We need an easy way to print text. Take note of how each a0 stack looks in the PRINT_TEXT function. Debug the stack until you know what everything does. Some data will not change anything on screen while removing other data will freeze the game. We will refer to this unknown data as filler data.
    - Create a function that fills in the filler data by default. For everything else such as the text pointer, X&Y offsets, size, color, etc, we will set those variables up as arguments.



    An example function is below for printing "Hello World".



    This is the basic code to print text to the screen.
    Code:
    address $200C8000
    print "Hello World"
    
    
    // ----------------------------------------------
    // print text to screen
    
    
    // -- This hook constantly writes the text to the screen.
    // -- NOTE: Text will disappear once the screen refreshes, therefore
    // --       you must constant write the text.
    address $2030DBA8
    j $000c9000
    
    
    address $200c9000
    addiu sp, sp, $FF80
    sw ra, $0000(sp)
    
    
    // -- print "Hello World"
    setreg a0, $000C8000 // string ptr
    setreg a1, $42f00000 // X offset (from left side of screen)
    setreg a2, $43000000 // Y offset (from top side of screen)
    setreg a3, $3f800000 // size
    setreg t0, $43000000 // Red
    setreg t1, $43000000 // Green
    setreg t2, $00000000 // Blue
    setreg t3, $43000000 // Alpha
    jal :__print_text
    nop
    
    
    lw ra, $0000(sp)
    jr ra
    addiu sp, sp, $80
    
    
    
    
    //----------------------------------------------
    // print text fnc
    /*
    args:
    a0: ptr to text to render
    a1: X offset
    a2: Y offset
    a3: text size
    t0: text color RED
    t1: text color GREEN
    t2: text color BLUE
    t3: text color ALPHA
    
    
    NOTE: There is a lot of data in this fnc that is not explained in the comments.
          This data was found in every text string I examined. It is needed for the
          SOCOM 2 text printing function.
    */
    
    
    __print_text:
    // create stack pointer
    addiu sp, sp, $FF00
    sw ra, $0000(sp)
    sw s0, $0004(sp)
    
    
    // This is where the data is stored for using this function
    setreg s0, $000CA000 // pointer setup start
    
    
    setreg v0, $00406DF0
    sw v0, $000c(s0)
    setreg v0, $3F8000CD
    sw v0, $0014(s0)
    
    
    // Set text pointer
    sw a0, $001c(s0)
    
    
    addiu v0, zero, $000F
    sw v0, $0020(s0)
    addiu v0, zero, $0006
    sw v0, $0024(s0)
    setreg v0, $414ED2E3
    sw v0, $0038(s0)
    setreg v0, $42740000
    sw v0, $003c(s0)
    
    
    // set text size
    sw a3, $0040(s0)
    // set text RGBA
    sw t0, $0048(s0)
    sw t1, $004c(s0)
    sw t2, $0050(s0)
    sw t3, $0054(s0)
    
    
    setreg v0, $80800051
    sw v0, $005c(s0)
    setreg v0, $0040D57C
    lw v0, $0000(v0)
    sw v0, $0018(s0)
    setreg v0, $004067B0
    sw v0, $0060(s0)
    addiu v0, zero, $0100
    sw v0, $0068(s0)
    addiu v0, zero, $015e
    sw v0, $0070(s0)
    setreg v0, $3F800000
    sw v0, $0078(s0)
    
    
    // set X offset
    sw a1, $0090(s0)
    // set Y offset
    sw a2, $0094(s0)
    
    
    setreg v0, $0000EC60
    sw v0, $0098(s0)
    setreg v0, $3F801B00
    sw v0, $009c(s0)
    setreg v0, $00406C10
    sw v0, $0100(s0)
    setreg v0, $00488DF8
    lw v0, $0000(v0)
    sw v0, $0104(s0)
    
    
    // Print text to screen
    daddu a0, s0, zero // a0 = start of text pointer stack
    addiu a1, s0, $0100 // set a1 to pointer in text pointer stack
    jal $003635C0 // print text fnc (native to socom 2)
    nop
    
    
    // pop stack pointer
    lw s0, $0004(sp)
    lw ra, $0000(sp)
    jr ra
    addiu sp, sp, $0100


    You can take it much further and create multiple lines such as a memory viewer:
    Click image for larger version

Name:	0GJExtY.jpg
Views:	1
Size:	148.8 KB
ID:	163929


    Examples in other games:

    Twisted Metal Black Online:
    Code:
    /*
    
    Use this function to print text. It must be called constantly.
    
    Printing text steps:
    1: Set text color by using this function: 00202B78 
    a0: alpha
    a1: red
    a2: green
    a3: blue
    
    2: Print text to screen using this function: 00202DF8 
    a0: text size (1 = small, 0 = large)
    a1: Screen X position (from left)
    a2: Screen Y position (fromt top)
    a3: String pointer (for text)
    
    */
    
    
    // HOOK (this calls my function constantly to render text)
    address $201399A0
    j :__TEXT_RENDER
    
    // My function start address
    address $200A0000
    __TEXT_RENDER:
    
    addiu sp, sp, $FF80
    sw ra, $0000(sp)
    
    // set text color
    addiu a0, zero, $0000 // alpha
    addiu a1, zero, $00a0 // red
    addiu a2, zero, $0010 // green
    jal $00202B78 // SET TEXT COLOR FUNCTION
    addiu a3, zero, $0000 // blue
    
    // render text
    addiu a0, zero, $1 // text size (1 = small, 0 = large)
    addiu a1, zero, $0050 // X position
    addiu a2, zero, $0050 // Y position
    setreg a3, $000B0000 // text pointer
    jal $00202DF8 // PRINT TEXT TO SCREEN FUNCTION
    nop
    
    lw ra, $0000(sp)
    jr ra
    addiu sp, sp, $80
    
    // text
    address $200B0000 
    print "Hello World"
    Call of Duty 3:
    Code:
    /*
    This function prints text to the screen. It must be called constantly to render text.
    */
    
    // HOOK
    address $201F8544 //-- constant hook //202308E8 //-- in game hook
    j $000A0000
    
    // My function start address
    address $200A0000
    
    addiu sp, sp, $FF80
    sw ra, $0000(sp)
    
    // example "Hello World"
    setreg a0, $000B0000 // text ptr
    setreg a1, $42480000 // X offset
    setreg a2, $42D40000 // Y offset
    setreg a3, $3f000000 // text size width
    setreg t0, $3f000000 // text size height
    setreg t1, $FFFFAF00 // text color ARGB
    jal :__PRINT_TEXT
    nop
    
    lw ra, $0000(sp)
    jr ra
    addiu sp, sp, $80
    
    
    __PRINT_TEXT:
    /*
    a0 - text pointer
    a1 - X offset
    a2 - Y offset
    a3 - text size width
    t0 - text size height
    t1 - text color ARGB
    */
    addiu sp, sp, $FF80
    sw ra, $0000(sp)
    sw s0, $0004(sp)
    sw s1, $0008(sp)
    
    // stack location. this can be changed to any blank area.
    setreg s1, $000A1000
    // default data
    lui s0, $3f80
    sw s0, $0000(s1)
    lui s0, $41A0
    sw s0, $0004(s1)
    addiu s0, zero, $4
    sw s0, $000C(s1)
    setreg s0, $0079E290 // text fnc stack
    sw s0, $0010(s1) 
    // default data
    lui s0, $C387
    sw s0, $0020(s1) 
    // store X and Y screen offsets
    sw a1, $002C(s1) 
    sw a2, $0030(s1) 
    // default data
    lui s0, $3F80
    sw s0, $0038(s1)
    sw s0, $003C(s1)
    sw s0, $0044(s1)
    sw s0, $0048(s1)
    // store size
    sw a3, $0050(s1) 
    sw t0, $0054(s1) 
    // store color
    sw t1, $0060(s1) // ARGB
    // default data
    addiu s0, zero, $15
    sw s0, $006C(s1)
    
    // save text pointer pointer (pointer1 >> pointer2 >> string)
    // s1+100 = pointer1 start. This is needed for the native print text function.
    addiu s0, s1, $100 // set pointer1
    sw s0, $001C(s1)
    addiu s0, s1, $10C // set pointer2
    sw s0, $0100(s1)
    setreg s0, $00400040 // text length set high
    sw s0, $0104(s1)
    
    // copy text pointer string to stack pointer
    daddu a1, a0, zero // source
    addiu a0, s1, $10C // location to copy to
    jal $0050EEF0 //strcpy
    addiu a2, zero, $100
    
    // PRINT TEXT
    daddu a0, s1, zero
    addiu a1, zero, $0
    jal $001D0A5C // native print text fnc
    nop
    
    lw ra, $0000(sp)
    lw s0, $0004(sp)
    lw s1, $0008(sp)
    jr ra
    addiu sp, sp, $80
    
    // text to print
    address $200B0000
    print "Hello World"
    nop
    Last edited by Harry62; 10-04-2016, 04:47:40 PM.

  • #2
    You used the wrong version of this code. It should be storing to the stack pointer. There is no need to allocate memory, so instead storing it on the stack we can be certain that It will be cleaned up later. This really doesn't matter in the world of coding as much but is best practice. Harry you should explain more on how to find those args and emulate it to get a function to work so we can actually get the code to work then expand on the code to have a smaller version. Overall great tutorial but add more information next time so more novice coders can understand it a bit easier.
    Last edited by Cronotrigga; 09-26-2016, 12:28:06 PM.

    Comment


    • #3
      Everytime I see stuff like this. It makes me wanna pick up my ps2 and learn to code on Socom or any game.

      Comment


      • #4
        Couldn't port from my CA version?

        Comment


        • #5
          Originally posted by Professor-X View Post
          Everytime I see stuff like this. It makes me wanna pick up my ps2 and learn to code on Socom or any game.
          I thought you already knew PS2 hacking. If not it is extremely similar to PSP hacking.


          Originally posted by Gtlcpimp View Post
          Couldn't port from my CA version?
          ??

          Comment


          • #6
            Originally posted by Harry62 View Post
            I thought you already knew PS2 hacking. If not it is extremely similar to PSP hacking.




            ??
            I do but my ps2 isn't running codemagic or custom firmware. Not sure what yall call it but yes I know it's similar far as mips assembly. I just need to find how to hack my ps2 to run sign code.

            Comment


            • #7
              The PS2 isn't protected like the PS3 and PS4. There's no firmware in the current sense of the term, and they used a more physical signature embedded into the media by essentially writing bad sectors to the discs. You either need a mod-chip, or something like Free MC Boot to run homebrew, and once you get that going, you're done.

              I haven't looked around, but it's theoretically possible to make unlicensed discs for a PS2 without the grafting solution most companies used. Datel started doing it ages ago. If they would have stuck something like uLaunchELF on one of their CDs, you could run any software you want from whatever storage you can attach to the PS2. I'm betting there's still no consumer hardware capable of making bootable CDs that don't require some sort of exploit, though.

              I'd just look for a guide for Free MC Boot. Without a mod-chip, the easiest way to install that involves cheat discs that can import save files. You can probably safely ignore any guides that simplify it or involve ISOs, as they're generally made by people with cheap mod-chips that have no launcher support, so they can already run backups, just not homebrew. There were other guides that involved hardware mods to make the PS1 swap-trick doable, and then Free MCBoot was installed from a hacked up PS1 backup. You can probably skip that too. If you have an AR MAX or a CodeBreaker, you should be able to do it without any hardware modifications.

              Comment


              • #8
                Originally posted by Gtlcpimp View Post
                Couldn't port from my CA version?
                I'd rather shoot myself in the face then try to port anything you've made :P

                Comment


                • #9
                  Originally posted by Gtlcpimp View Post
                  Couldn't port from my CA version?
                  It probably was portable but it doesn't really look the same when I checked last.

                  Comment


                  • #10
                    Originally posted by Professor-X View Post
                    I do but my ps2 isn't running codemagic or custom firmware. Not sure what yall call it but yes I know it's similar far as mips assembly. I just need to find how to hack my ps2 to run sign code.
                    Just get pcsx2dis, download the iso and some bios and you're set.
                    Last edited by Cronotrigga; 10-14-2016, 10:15:52 AM.

                    Comment

                    Working...
                    X