String length limitation when translating! Need Help!

Started by sh4d0w, April 05, 2016, 10:47:29 AM

Previous topic - Next topic


Hi there guys, I'm new here and I'm trying to translate a PSP Game (Sword Art Online: Infinity Moment) but I do have to deal with string limitation. Also a character is 2 bytes ( It uses UTF16). Now, I've been reading the "Get Start" section but when it came to the part of the pointers it just said "We won't cover that up"  :-\ :-\
So i thought I could come and ask you directly. I've uploaded two files:
1. sys    it's on OFS3 header and it contains name of the skills,monsters and so on. As you can see there are some words already translated but badly(since I had to write them no longer than japanese characters would be) Also the Font is already at the top of it so I was wondering if I needed to do a pointer table first to readress the new string on the free spaces or not.
2. mail   This one contains all the messagges the MC will see and has ONLY them! So it's just a text to be translated but no Header,no Font...nothing at all
Forgive me but I'm new into this so i would highly appreciate any help,hint,tool,guide,suggestion! Thank you!!!


EDIT: The getting started docs refer to this document:
I think it should even be promoted to the Getting Started page itself. ;D

Try reading this guide:
(The start of section 3 is needed, don't just jump to pointers.)


WOw thnx pal! I'll read it ASAP!!!!
Just one more question...I heard that an OFS3 can be unpacked and then repacked but I don't know with what software! I tried QuickBms but it doesn't open that type of file...any suggestion? THnx


May 02, 2016, 01:02:08 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

By far the simplest and quickest pointers to work with.  These pointers appear somewhat frequently. Calculating them is simple (Final Fantasy 1 uses Standard Header pointers, and the procedure for calculating them is stepped through above).

In brief, you:
1) Determine the position of the text. (SAMPLE: 12345)
2) Subtract 10 for the header. (SAMPLE: 12335)
3) Drop the Ten-thousands digit, if there is one. (SAMPLE: 2335)
4) Break the number into two pairs.  (SAMPLE: 23 35)
5) Swap the number pairs. (SAMPLE: 35 23)
Voila, you have your value.

SetOff X000
By far the most common type of pointers on the NES, SetOff X000 pointers are pointers whose position within the ROM is modified for whatever reason.  This amount of modification is indicated by the X000 value.  Why they're modified isn't important, only how.  To calculate them, you follow the same procedure as STANDARD HEADER pointers with one additional step.  (IMPORTANT NOTE: You can only calculate X by locating the pointer table, which is described below)  If you know X000, they are calculated by:
1) Determine the position of the text.  (SAMPLE: 12345)
2) Subtract 10 for the header. (SAMPLE: 12335)
3) Add X000 to your value. (SAMPLE: if you found X000 to be 3000,
then 12335 + 3000 = 15335)
4) Drop the Ten-thousands digit, if there is one.  (SAMPLE: 5335)
5) Break the number into two pairs. (SAMPLE: 53 35)
6) Swap the number pairs. (SAMPLE: 53 35)
Voila, you have your pointer value.
If you do not know X000, you need to follow the steps outlined below in LOCATING THE
POINTER TABLES.  When you get there, read through that section below, and then come back
up here and re-read this one to gain the best understanding of SetOff X000 pointers.

Some notes about SetOff X000:
1) Standard Header pointers are just SetOff 0000 pointers, but usually it's just easier to think of them as their own type.
2) For whatever reason, X seems to be 8 more frequently than most other values.
3) Although it is theoretically possible to have SetOff 1500 pointers, or some other value which is not a multiple of 1000, I have never encountered them.

Technically, this is not even a pointer system, but I include it here because being able to recognize this when it's used can save you hours of headache and searching.  Sequential text systems don't use pointers, making their widths adjustable without any problem.  Customizing a YES/NO prompt would actually be as simple as changing:
Sure.#No way!#texttextt...
This way of doing things isn't used very often, but some games do use it.
One important note: With this system, the game knows it's done when it reads enough strings. Therefore, you cannot simply remove a string you don't like without messing things up. If one string is slightly longer, the string to the right of it will have to be slightly shorter.
Rarely used for text, this system is frequently used for item and spell listings.  The game knows that the text string is a certain amount of characters long, and reads them accordingly. You don't really need to do anything with these, and you can't re-map them.

If you see these, run. I've only encountered them once, in Wily & Light no RockBoard, a Mega Man monopoly spinoff, and I'm still trying to figure out how on Earth they know everything they're supposed to.  Anyway, I'm including them here for completeness, but you're free to skip ahead.

Sequential pointers are stored in their simplest form, two digits (as opposed to the 4 used in SetOff X000 and Standard Header pointers).  They're calculated as follows:
1) Determine the position of the text.  (SAMPLE: 12345)
2) Subtract 10 for the header. (SAMPLE: 12335)
3) Drop all digits except for your ones and tens places.  (SAMPLE: 35)
Voila, you have your pointer value.
Seems easy, doesn't it?  Well, it's not, because as you try to remap these pointers, all kinds of weird things can happen without the hundreds and thousands place.  Space constraints are worse here than anywhere else.  Trust me, you really don't want to deal with these unless you absolutely have to.

Well, there you have your standard pointer systems.  Are there others?  Probably.  I've only encountered one other system on the NES, and I'm STILL trying to figure that one out...

So now do we finally get to learn about how to find the pointer table?
Yes, you deserve a reward for having read this far! Let's pull all of this together.

FINDING POINTER TABLES and your pointer system (the easy way):
(if you need an example, refer back up to the Final Fantasy one above)
Does the ROM use a SEQUENTIAL TEXT or FIXED WIDTH systems?
1) To determine if you've got a FIXED WIDTH system, just look at your text strings.  If you've got a bunch of strings that are exactly the same length (especially if they use 00s, FFs, or some kind of <NULL> code at the end to guarantee that), odds are you've got a fixed width system at work.
2) To test and make sure, locate a string you can easily get the game to display.  Overwrite it with something longer which runs into the next string in your hex editor.  Save, then load the ROM and bring up that item.  If it cuts off after a certain length, you've got a fixed width system.
3) To test if you've got SEQUENTIAL TEXT, find some dialog in the game and locate in in your hex editor.  Now, go into the string BEFORE it and add an <END> code right in the middle of it.
Save, and load up your ROM again.  Bring up the dialog you used before.  If it's different, then you've got a SEQUENTIAL TEXT system.

If your ROM does not use the SEQUENTIAL TEXT or FIXED WIDTH systems:
1) Open the ROM in your hex editor.
2) Locate a string of dialog which you can bring up in the game easily or quickly. (Don't use menu options/other types of text, as these tend to be stored differently than main text)
3) Write down your offset.
4) Subtract 10 for the header.
5) Note down the last two digits of your value.  (If your adjusted position was 12345, the 45)
6) In your hex editor, Hex Search UP for this value. (the 45)
7) Usually, you'll find one close to where you started your search.  Regardless, write down the two digit number to the right of the one you just found (Let's say, searching for 45, your search returned the 45 in the following line:  AB 45 FE. Write down the FE)
8) Check the second digit in the number you just wrote down (In FE it'd be the E).  Compare that value with the hundreds place in your adjusted position (In 12345 it'd be the 3).  If they match, you may have found the
beginning of your pointer table.  In they don't, continue searching UP.
9) Since the values didn't match, we continue searching upwards until they do.  (Finally, we find it a line that includes 82 45 83)
10) Now that we've found a potential pointer, we need to test it.  Change the pointer so that the text will display differently (my favorite is to just set the ones place ahead by 1, so that the first letter doesn't display.  When that happens, you know it worked.)  Then you'll need to remap the pointer to another string of text, and see if it changed like you expected it to (What we did in the Final Fantasy example above.)
11) If the text changed as you expected it to, CONGRATULATIONS, YOU'VE JUST
12) To figure out which pointer system you're dealing with, you only need to look at the pointer you've found and compare it to the position of the text you're using.  Take the first digit of the right number in your pointer (45 83 -> Take the 8) and compare this to the thousands digit of your position (12345 -> The 2).  If they're the same, you're dealing with STANDARD HEADER pointers, otherwise you've got SetOff X000 pointers (where X is the number you just examined from the pointer -8- less the number you just took from the position -2-, or 6 => Therefore, you're dealing with SetOff 6000 pointers)

That's it.  This system will work for most of the games that many of you will want to hack out there.  Now that you know the pointer system, you can calculate the pointer for the first item in your text block.  Find that, and you've found the beginning of your pointer table.

If the above system didn't work for you, make sure you don't have any control codes (described below).  If you're sure that there aren't any in there, try this system:
1) Test for SEQUENTIAL TEXT and FIXED WIDTH systems, as outlined above.
2) Locate a string you can bring up easily in the game.
3) Using its position, calculate the pointer using the STANDARD HEADER system.
4) Search the hex for this value. Change every occurrence slightly (remember, change the second digit of the first number pair for minor changes).
5) Save, and load the ROM.  If the change you wanted occurred, then you know it's a STANDARD HEADER system.  Change matches one by one until you find the right one.
6) If that doesn't work, then calculate the pointer using the SetOff 8000 system.  Search for this value in the ROM, changing every occurrence slightly.
7) Save, and load the ROM.  If the changes you wanted occurred, then you know it's a SetOff 8000 system.  Change matches one by one until you find the right one.

If these don't work, then I'm afraid you'll have to resort to:

The system of last resort.  This will work 99.9% of the time if you know that you're not dealing with a FIXED WIDTH or SEQUENTIAL TEXT system, and that there are no control codes throwing you off (and in that 0.1% of the time, you don't want to deal with it anyway).
1) Locate a dialog string you can bring up easily in the game.
2) Locate that string in the hex editor.
3) Calculate the pointer for it using the SEQUENTIAL POINTER system (no, don't worry. Using this method does not automatically mean you've got sequential pointers).
4) From the beginning of the ROM, Hex Search through for that value.  One by one, change that value slightly.  Saving and testing to see each time if you've found the right one.
5) EVENTUALLY you'll come across it (hey, if you're lucky, the Hex Search will only turn up 500 or so occurrences).  FROM there you can figure out the pointer system as described under the easy way above.

...or you could go on and see if somebody else has found it and written it up.

So, is that it?  Do I now know everything I need to about pointers?
Almost. There are only two more minor things for me to address.

Empty Space in the ROM:
Fitting all of the text you need to into the ROM can be quite troublesome.  Fortunately, there is a solution...sometimes.  On some occasions there will be blank space within the ROM which you can use to fit some extra text in.  You can recognize this space because it's usually just a large block of 00s or FFs.  Look at the end of your ROM and you'll probably see a good example of it.
Now, because NES pointers are limited to four digits, so too are your pointers.  Therefore, your range will be limited to whatever bank the existing text is in.

Control codes:
These are codes that programmers put in with the text which tell the NES how to display it.  Much like the font tables themselves, these vary from game to game.  End of Line, End of Page, and Pause are two common examples.
I bring these up because if the text string you're using has one (or more) of these at its beginning, the pointer will point to THAT instead of the first actual letter of the message.


SOURCE: chrome-extension://gbkeegbaiigmenfmjfclcdgdpimamgkj/views/app.html