PSP ASM Hacking for Variable Width Font

Discussion in 'PSP - Hacking & Homebrew' started by ChepChep, Nov 28, 2014.

  1. ChepChep
    OP

    ChepChep GBAtemp Advanced Fan

    Member
    603
    611
    Feb 9, 2011
    United States
    So I have mostly completed two PSP translation patches (La Pucelle: Ragnarok and Phantom Kingdom Portable) without having to do too much ASM hacking. I had a few people help me here and there and was able to muddle my way through it.

    I want to start another game patch (super secret sneaky release) and we have had much progress. I have figured out all the encrypted files and can pack and unpack them all and still have everything working. I even found all the text for the game in the english steam version of the game (hope not too many hints which game) and wrote a script that will dump it into the PSP version. It even works on the PSP. The issue I am again plague with a game that does not support variable width font. Almost every single line of text goes way outside the textboxes throughout the entire game. It seems like every game I touch has some kinda of VWF issue.

    I was wondering if anyone has advice on how to learn how to ASM program in VWF into the game? I code quite well and have ASM programming experience. Where I get hung up is finding the locations of the things I want to change and then finding space to fix things. Right now the game supports ASCII chars but they get mapped to SHIFT-JIS fixed width font. The steam version is using a variable width font but none of code applies to the PSP. Is there anyone interested in helping me with the variable width font? I would like to learn to do it myself but I need guidance.

    Any advice or suggestions are appreciated?

    Thanks,
    -ChepChep
     


  2. Abu_Senpai

    Abu_Senpai The Red King

    Member
    1,485
    744
    Jul 13, 2014
    United Kingdom
    Tokyo
    Hey chepchep
    I can't wait to see what game it is
    Im hoping it's one of the big 10
     
  3. GHANMI

    GHANMI GBAtemp Advanced Fan

    Member
    971
    493
    Jun 10, 2012
    Why not simply change the width to 8 pixel and leave it fixed-width? It should be enough most of the time.
    If it's particularly wordy, try adding an extra line and make the message box wider.
    If that still isn't enough, just divide the text between two text boxes, like SMT1 iOS and many PS1 releases did.
     
  4. thexyz

    thexyz Member

    Newcomer
    40
    24
    Jan 8, 2014
    Serbia, Republic of
    All of this will vary greatly depending on the game but basically there are two ways:

    1) Forward -- from text to rendering
    Find your text in memory, set a read breakpoint on it (of course you will use PPSSPP, it's your best friend), trace how this data is processed. It probably will be read in several places, try to find out which one is responsible for text rendering. Try changing registers (eg change 'a' to 'z' and see if it's changed on the screen, change things that look like display offsets and see if it moves).
    2) Backwards -- from rendering to the text (ONLY do this if you're really desperate)
    You should know how PSP graphics works. Find displaylist in memory, find where your text is rendered, breakpoint this on write; use PPSSPP's graphics debugger. Try to figure out how this data got there, somewhere along the way there will be a calculation of the X and Y offsets. This is usually way harder because there are much more layers the text gets passed through after the X and Y are calculated.
     
  5. StorMyu

    StorMyu "I'm too old for this"

    Member
    899
    439
    Jan 2, 2010
    France
    Half-assed job. reducing the width is like your first step when doing a vwf, you can just go all the way then if you've find this lol
     
    GHANMI likes this.
  6. FAST6191

    FAST6191 Techromancer

    pip Reporter
    23,508
    9,322
    Nov 21, 2005
    It is for the GBA but it should give you ideas on how to set about it
    http://www.romhacking.net/documents/337/
    Generally though it is a width look up table if the font itself does not support it (or you did not want to hack it into the font). If a basic width change is not going to do it for you then you also have what I usually dub the pseudo variable width font where you take a leaf out of the old methods and encode wider characters over a couple of tiles.

    "I am again plague with a game that does not support variable width font"
    If you are going to play in Japanese game translation circles then get used to it. At least with more modern consoles it is not unheard of for them to use a fully realised font format -- on the DS I believe* the NFTR format is inherently VFW even if the devs do not use it.

    *I am told the the SDAT format will jettison the relevant part of the libraries if you do not use a given sound format in a game, I do not think NFTR does this though.

    "Almost every single line of text goes way outside the textboxes throughout the entire game."
    Do you mean that the boxes are too small for your translation or that the lines themselves do not wrap? The wrapping thing is not a font issue, though altering the font is certain an aid in such scenarios, and more of a text handling issue.
     
  7. ChepChep
    OP

    ChepChep GBAtemp Advanced Fan

    Member
    603
    611
    Feb 9, 2011
    United States
    Thanks everyone for your input. I appreciate it. Looks like I have a place to start now.
     
  8. ChepChep
    OP

    ChepChep GBAtemp Advanced Fan

    Member
    603
    611
    Feb 9, 2011
    United States
    So I found where is my iso for the fixed width is being set to 16 pixels. My issue now is trying to find space in the game to write code to adjust the width based on the character.

    How do I find space in game that I can code in that is "safe"?

    Should I just be looking for large blocks of 0x00 in the eboot.bin and hope they are safe?
     
  9. FAST6191

    FAST6191 Techromancer

    pip Reporter
    23,508
    9,322
    Nov 21, 2005
    Finding locations to put your new code is always a fun part of assembly hacking.

    Debug strings, runs of 00, error messages for wifi/network (I have seen games include several uncommon ones), areas of memory set aside, memory that never gets to be used in normal games (harder to find in more modern games) and so on and so on are all good things to look for. The worst case scenario is you have to reverse engineer and optimise/shrink existing code to gain yourself some space. Halfway between that is you break a bonus mode or something in the game and steal its data.

    You tend not to find your back up against the wall in ROM hacking (such things are more for embedded devices, small kernels and those hacking that sort of thing) but it is not like you can throw a simple malloc in there either. Mind you depending upon the game, the memory handling available and the system you are using you might actually be able to extend the binary in memory and rely on any hardcoded locations being for the binary rather than general runtime memory.
     
  10. thexyz

    thexyz Member

    Newcomer
    40
    24
    Jan 8, 2014
    Serbia, Republic of
  11. ChepChep
    OP

    ChepChep GBAtemp Advanced Fan

    Member
    603
    611
    Feb 9, 2011
    United States
    I think I found some space in the eboot.bin. I was able to insert some ASM into 0x00 block that is quite large. The adjustments to the font is working in both PPSSPP and on the PSP. I tried to follow what done for the link above but I cannot figure out exactly what is headers and what needs updating to change length of eboot.bin.
     
    Pablitox likes this.
  12. Scorp

    Scorp GBAtemp Regular

    Member
    247
    82
    Sep 23, 2010
    Kazakhstan
    Regarding that expand of eboot - very interesting, can anyone advice some decent tutorial, how to integrate new sections/expand existing ones/restrictions? As really tired in finding free spaces in eboots, there is never enough.
     
  13. Kelebek

    Kelebek GBAtemp Regular

    Member
    165
    62
    May 25, 2012
    It's pretty much the same as for .exe files. Obviously the format's different, ELF is a bit harder to do, but it's the same thing really.

    Here's a quick example using Digimon Adventure:

    Firstly here's the default (decrypted/extracted) EBOOT:

    [​IMG]

    There's a detailed explanation of the file header on http://en.wikipedia.org/wiki/Executable_and_Linkable_Format - Things to note are the pointer to the start of the program header table at 0x1c, which in this case is 0x34, and the number of program headers at 0x2c, which in this case is 0x3. So there are 3 program headers at 0x20 bytes each starting at 0x34.

    Program header struct:
    Code:
    u32 iType;
    u32 iOffset;
    u32 iVaddr;
    u32 iPaddr;
    u32 iFilesz;
    u32 iMemsz;
    u32 iFlags;
    u32 iAlign;
    
    Our 3 program sections start at 0x34, 0x54 and 0x74. You can see the first section starts at 0xc0, so luckily in this case we have more than 0x20 bytes free and can add another section without adding bytes. If you didn't have enough room, you'd just have to add another x bytes for whatever alignment the file uses (0x10 should be alright, but you can emulate the original, which in this case is 0x40) and fix a lot of other pointers: The section header table pointer in the file header. The iOffset entry for each program header entry, and iPaddr for the first program entry. Then also each individual section header entry in the section header table.

    So at 0x94, from the struct above, I can just add in a new program section:

    [​IMG]

    Increase the program header count by 1 so your new section will actually be read. I'm adding 0x1000 bytes to the end, so my file size and virtual sizes are set to 0x1000, but you can make it as big as you need. Flags set to 0x7 for read/write/execute. You can get the virtual address by adding up the iMemsz (the memory sizes) of the previous sections. I didn't align it as the game ran perfectly fine, but if you get any errors try aligning that too, 0x10 should do. Make sure you fix up the aligning at the end of the file (I was using 0x40 in this case) and set your offset there.

    Add the new x bytes to your file. I just wrote in some text so I can show it appearing in the disassembler:

    [​IMG]

    And finally, put the EBOOT back into the UMD, run the game, and we find our new 0x1000 byte section in memory, at base (in this case 0x8804000) + the specified virtual address (0x2835C9) = 0x8A875C9:

    [​IMG]

    There are other ways you can do this, you can just extend another section if you want. You'd ahve to add your bytes to the end of that section, increase the filesize for that program section, and then add the amount of bytes you increased it by to all the other program sections below the one you extended, so they point to the right place. You will likely have to mess with and add to the relocation table and crap as well eventually, to make sure offsets work correctly, like the call/jump to your new section, and any you make in your code as well. Relocations are annoying though, have fun with that. :P You can make the whole thing "cleaner" by adding your new section under the first .text section, instead of after .text/.data/.reloc as I did, but it doesn't really make any difference. Going with the extend way would be cleaner too, as both ways keep all the execute code together, but in the end it's all the same, whichever's easier is best. I do like having my own section which I can usually name .patch or something. :P

    That's the basics of adding/extending sections though. I think the biggest problem you may have is using a decrypted EBOOT. Not every game runs properly using the ELF (I think? Maybe I'm wrong here). And trying to re-crypt the EBOOT might be a bit difficult.
     
  14. Scorp

    Scorp GBAtemp Regular

    Member
    247
    82
    Sep 23, 2010
    Kazakhstan
    Thx for explanations! Well, I think even if such games exist (who do not run as decrypted Eboots), I still did not saw them :) Usually this was related with LBA issue, not Eboot encrypted. Anyway I can be wrong too, as did not have much experience in this.

    So, regarding the explanations. I just took a EBOOT, and there is a start from A0. So I need more x10 bytes as you told. So, I shift all program table +x10 bytes forward and shift the sections data table start forward for x10 too. What else I should do apart this? As after this PPSSPP started crashing on ISO load, so I suppose there is something else... I just inserted 0x10 bytes, nothing else.
     
  15. Kelebek

    Kelebek GBAtemp Regular

    Member
    165
    62
    May 25, 2012
    Which game? I think you'll have to change each section header entries as well if you're moving things. The pointer to them, as well as their size and count are defined in the file header. There's tonnes of them so it's a real uber pain to do manually, but that's always the case with manually editing executables. Probably quicker to whip up a quick script to change them for you.
     
  16. ChepChep
    OP

    ChepChep GBAtemp Advanced Fan

    Member
    603
    611
    Feb 9, 2011
    United States
    Kelebek,

    Thanks for the mini tutorial. I plan to try this out on the eboot I am working on. I need large chunk of space to put a font width table and if this work it would be great.
     
  17. Scorp

    Scorp GBAtemp Regular

    Member
    247
    82
    Sep 23, 2010
    Kazakhstan
    Already done sort of script (who told PHP is only for web?) and sent you a PM :) Maybe I can do some semi-automatic tool for my needs, if all will work correctly.
     
  18. ChepChep
    OP

    ChepChep GBAtemp Advanced Fan

    Member
    603
    611
    Feb 9, 2011
    United States
    So I have been trying to follow the "tutorial" and running into an issue with extending the eboot. When I try to extend it by 0x100 bytes with all 0's, the space is still being written to.

    The file only has one section of code in the header and no room to add another section so I took the extend the one section by 0x100 bytes route.

    The header values as displayed in memory:
    u32 iType: 0x 01 00 00 00
    u32 iOffset: 0x 54 00 00 00
    u32 iVaddr: 0x 00 40 80 08
    u32 iPaddr: 0x 98 26 1D 00
    u32 iFilesz: 0x 00 DE 1F 00
    u32 iMemsz: 0x 80 87 31 00
    u32 iFlags: 0x 07 00 00 00
    u32 iAlign: 0x 10 00 00 00

    Screenshot of eboot.bin:
    Warning: Spoilers inside!

    iFilesz = 0x001FDE00
    iMemsz = 0x00318780

    0x08804000 + 0x001FDE00 = 0x08A01E00 (ASM code ends here)

    0x08804000 + 0x00318780 = 0x08B1C780 (Not sure what this space is used for)

    If I change the iMemsz to the same as iFilesz (0x001FDE00), the game crashes when loading.

    The issue I think I am having is the filesz and memsz are different than the example above. I have tried adjusting both by 0x100 and still can see stuff being written to my new "extended" area of code and should be all 00's

    Screenshot of memory at 0x08A01E00 with PPSSPP. The next 0x100 bytes should be all 00's but things are being written to that memory from the game.
    Warning: Spoilers inside!


    Any ideas since I am stumped?

    This is about how far I got before and gave up.

    -ChepChep
     
  19. Kelebek

    Kelebek GBAtemp Regular

    Member
    165
    62
    May 25, 2012
    The iFilesz is the size as it is in the file itself. The iMemsz (and iVaddr) is the sizes (and address) of the executable in memory when it gets loaded. When you load executables they aren't 1:1 copies from file to what executes in memory. So 0x1FDE00 is the file size of the EBOOT, but 0x318780 will be the full "loaded" executable size.

    I'd recommend adding a new table, because I think it's easier, and once you've added it you can change the size of it without affecting anything. If you expand the current one you'll have to update the section header every time (and that takes ages).

    So the things you'll need to edit would be:

    Add 0x20 bytes in at 0x54, pushing the code down to 0x74.
    Add 0x20 bytes to the pointer at 0x20 in the file.
    Add 0x20 bytes to iOffset.
    Add 0x20 bytes to iPaddr of the first program header entry.

    Then go to that pointer at 0x20, that takes you to the section header table. All the offsets there need to be updated as well. There'll be 0x18 of them, each one 0x28 bytes, and the offset you need to change is 0x10 bytes into each entry. Add 0x20 to all those 0x18 entries, and then you should be set in terms of expanding.

    Then you should be able to add your new program header in just in the way I did above.

    If you want to send me the EBOOT I can do it for if you'd like. I just helped Scorp with his for Ever17.
     
  20. Scorp

    Scorp GBAtemp Regular

    Member
    247
    82
    Sep 23, 2010
    Kazakhstan
    Yes, exactly, as I stumbled into same issue :) And I think tomorrow I can show a script, which could automatically expand any (well, at least supposed to be so) EBOOT by adding a new program section just after all other section, exactly like Kelebek described. I am not really sure as there is quite strange behaviour of "Sections" part, which I cannot fully understand (so by now just do a check to skip that part).