- Joined
- May 26, 2007
- Messages
- 5,545
- Reaction score
- 1,315
How to Change Fonts and Code Pages in PT Client
This is a commonly asked question, and the answers are usually pretty vague, because there are many influencing factors.The primary one, is the default local for non Unicode programs in your OS, and that is set differently in Win 9x to 2K/XP to Vista... and I haven't tried it in Windows 7 yet.
But there are ways to avoid the conflict with the OS altogether. They just take a little Olly.
Basic PT Client Translation
First of all, lets take a look at the translations that have gone before, and see how they where done.
I'm going to look at the 1873 client by Quantumfusion, because it's a good clean Korean client translation and the translation is pretty good, but not quite complete. It's a common base for many private servers, and some of the points it misses can be seen to have slipped passed others too.:blush:
The other point of possible contention is that I tend to use the beta release of Olly Debug version 2... It's not as complete, but it's fast and stable. I'm fairly certain that the Olly v.1 debuggers are just as capable of performing all the tasks in this guide, but if the UI looks a little odd, that's the reason.
So... open the client in Olly, and lets have a look at the memory map.
You know that all these memory sections are from your main executable because of the name... 1873_quantumfusionNoXT.exe in my case.
So what about the section names? Windows has some standard accepted section names within PE files, which it will make some assumptions about.
- .text is where the main program body lies.
- .rdata is where Windows looks up initial run-time linkage libraries (DLLs) that the program should use.
- .data is assumed to be essentially variable declaration section, (if you code Pascal or Cobol) but for the whole program, not just a particular function or object.
- .rsrc is where we store program resources in .res format. Early on in NT life (NT2 or NT3) .res files where kept separate from the main executable, but since it contains the icon for the program, in NT4 (and it's cut down Windows 95) the PE executable was introduced allowing for various sections within the file (based on ELF as used in linux with backwards computability for flat DOS style MZ executables)... LE and LX executables used in Windows 3.1 and early OS/2 didn't work like this, normally.
That resource section contains your program icon, windows dialogue definitions, and is recommended to contain strings for localisation, so that you only have to change the resource you link, rather than compile a whole new executable for a different language... PT doesn't use that API facility however. It does load it's inital loading splash screen from the resource section using legal APIs though... and you can include a version string with localisation information and copyrights.
Strictly speaking, it should always be the last section in the executable... but in this case it isn't. Which begs the question "Why?".
The final section is called "KPTTrans" which is quite meaningful in it's self. Which is good, because the "Contains" column is blank for it. That's because this is not a standard section that Windows has any understanding of. That doesn't mean it won't load it, or that you can't use it, but you will have to be very specific in your program as to how you access it.
Go ahead and double click on it, and you will see why it has been added.
Right at the start of this section you will find the ASCII text string "This section is taken from rPT Client for Translation Purpose. Thanks Sandurr---" which is a nice indecator of the start of this section if you are looking at the executable in a hex editor, and tells us exactly why it is there, and where it came from.
If you highlight all of that, and press <Ctrl>+"R" or right click and Find references to... -> Selected block, you will see that that data is never actually used in the program, and is only there for our benefit as RCEs. (Reverse Code Engineers)
If you move the scroll bar right down to the bottom of that memory section however, you will find two items which are not strictly speaking translations.
- The string "COMIC SANS MS"
- A string containing an IP (I hexed in my server address already)
So why are these here? Well the first is the beginnings of an alternate font for translation... but it hasn't worked out all that well, or wasn't finished off. The second, I think we all know, is the IP that this client will look for the login (game) server on. The IP is normally held in a text file called "ptreg.rgx" in the client folder, but this client has been modified to ignore what it reads there for Server 1 and uses this IP instead... now we could continue this tactic and add the IPs of Server 2, 3 and 4 there as well... and once they are in the executable, they will be locked by the client connect code.
But if you highlight the "COMIC SANS MS" and search for references to that... you should find 5 points in the code (.text) section where the address of that string is pushed onto the stack.
If you go and look at any one of those references, you will see they are related to calling the GDI32.dlls CreateFontA() function.
You must be registered to see links
:
Code:
HFONT CreateFont(
__in int nHeight,
__in int nWidth,
__in int nEscapement,
__in int nOrientation,
__in int fnWeight,
__in DWORD fdwItalic,
__in DWORD fdwUnderline,
__in DWORD fdwStrikeOut,
__in DWORD fdwCharSet,
__in DWORD fdwOutputPrecision,
__in DWORD fdwClipPrecision,
__in DWORD fdwQuality,
__in DWORD fdwPitchAndFamily,
__in LPCTSTR lpszFace
);
Surely the character set should not be SHIFTJIS_CHARSET as this relates to the usual Windows Japanese code page?
For clarification, in C/C++ this call would be a single line like this:-
Code:
hFont = CreateFont(12,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,OUT_OUTLINE_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, FIXED_PITCH|FF_MODERN,TEXT("COMIC SANS MS"));
But if the font face specified is "COMIC SANS MS" why does this client produce text (usually) in "MS Sans Serif"?
Well... the answer to that is quite simple... for a start off there is no SHIFTJIS_CHARSET glyph table in the font "Comic Sans MS" which should match to the mangled description "COMIC SANS MS" if only via font aliasing. There is no guarantee of this however.
All upper was the way to work on Windows 3.1 but gave NT 3.1 and 3.5 problems when the fonts where stored on NTFS file systems which could store mixed case file names. In NT4 / Win95 the correct call should be to a font name, as it's defined in the file, not the files name... so if you installed a font with a different file name, whose title in it's header is "COMIC SANS MS" regardless of what it looks like, it will take prescience over "Comic Sans MS" with this description.
Fixing It
So really we want the line that says SHIFTJIS_CHARSET to say something more western.
This is what WINGDI.h from Wine has to say about CHARSET defines.
Code:
#define ANSI_CHARSET (BYTE)0 /* CP1252, ansi-0, iso8859-{1,15} */
#define DEFAULT_CHARSET (BYTE)1
#define SYMBOL_CHARSET (BYTE)2
#define SHIFTJIS_CHARSET (BYTE)128 /* CP932 */
#define HANGEUL_CHARSET (BYTE)129 /* CP949, ksc5601.1987-0 */
#define HANGUL_CHARSET HANGEUL_CHARSET
#define GB2312_CHARSET (BYTE)134 /* CP936, gb2312.1980-0 */
#define CHINESEBIG5_CHARSET (BYTE)136 /* CP950, big5.et-0 */
#define GREEK_CHARSET (BYTE)161 /* CP1253 */
#define TURKISH_CHARSET (BYTE)162 /* CP1254, -iso8859-9 */
#define HEBREW_CHARSET (BYTE)177 /* CP1255, -iso8859-8 */
#define ARABIC_CHARSET (BYTE)178 /* CP1256, -iso8859-6 */
#define BALTIC_CHARSET (BYTE)186 /* CP1257, -iso8859-13 */
#define VIETNAMESE_CHARSET (BYTE)163 /* CP1258 */
#define RUSSIAN_CHARSET (BYTE)204 /* CP1251, -iso8859-5 */
#define EE_CHARSET (BYTE)238 /* CP1250, -iso8859-2 */
#define EASTEUROPE_CHARSET EE_CHARSET
#define THAI_CHARSET (BYTE)222 /* CP874, iso8859-11, tis620 */
#define JOHAB_CHARSET (BYTE)130 /* korean (johab) CP1361 */
#define MAC_CHARSET (BYTE)77
#define OEM_CHARSET (BYTE)255
/* I don't know if the values of *_CHARSET macros are defined in Windows
* or if we can choose them as we want. -- srtxg
*/
#define VISCII_CHARSET (BYTE)240 /* viscii1.1-1 */
#define TCVN_CHARSET (BYTE)241 /* tcvn-0 */
#define KOI8_CHARSET (BYTE)242 /* koi8-{r,u,ru} */
#define ISO3_CHARSET (BYTE)243 /* iso8859-3 */
#define ISO4_CHARSET (BYTE)244 /* iso8859-4 */
#define ISO10_CHARSET (BYTE)245 /* iso8859-10 */
#define CELTIC_CHARSET (BYTE)246 /* iso8859-14 */
So now you have a choice... if you want the game to use the default character set of the clients machine, you can PUSH 1 instead of PUSH 80. (80 in hex = 128 in decimal) but if you want to force the matter, you can PUSH 0 to make sure everything is printed using the ANSI codepage.
The thing I love about this, is it disables all the kana glyphs, but allows me to use the GBP sign. "£"
Last edited: