mirror of
https://github.com/GTAmodding/re3.git
synced 2024-11-15 06:18:59 +00:00
added CText
This commit is contained in:
parent
188aab4196
commit
2bf6674afc
6 changed files with 260 additions and 1 deletions
|
@ -3,6 +3,7 @@
|
||||||
#include "Frontend.h"
|
#include "Frontend.h"
|
||||||
|
|
||||||
int &CMenuManager::m_PrefsBrightness = *(int*)0x5F2E50;
|
int &CMenuManager::m_PrefsBrightness = *(int*)0x5F2E50;
|
||||||
|
int &CMenuManager::m_PrefsLanguage = *(int*)0x941238;
|
||||||
CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8;
|
CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8;
|
||||||
|
|
||||||
WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); }
|
WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); }
|
||||||
|
|
|
@ -2,6 +2,14 @@
|
||||||
|
|
||||||
#include "Sprite2d.h"
|
#include "Sprite2d.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LANGUAGE_AMERICAN,
|
||||||
|
LANGUAGE_FRENCH,
|
||||||
|
LANGUAGE_GERMAN,
|
||||||
|
LANGUAGE_ITALIAN,
|
||||||
|
LANGUAGE_SPANISH,
|
||||||
|
};
|
||||||
|
|
||||||
struct tSkinInfo
|
struct tSkinInfo
|
||||||
{
|
{
|
||||||
int field_0;
|
int field_0;
|
||||||
|
@ -11,7 +19,6 @@ struct tSkinInfo
|
||||||
int field_304;
|
int field_304;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CMenuManager
|
class CMenuManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -77,6 +84,7 @@ public:
|
||||||
int m_nScreenChangeDelayTimer;
|
int m_nScreenChangeDelayTimer;
|
||||||
|
|
||||||
static int &m_PrefsBrightness;
|
static int &m_PrefsBrightness;
|
||||||
|
static int &m_PrefsLanguage;
|
||||||
|
|
||||||
void DrawFrontEnd(void);
|
void DrawFrontEnd(void);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
#include "Messages.h"
|
#include "Messages.h"
|
||||||
|
|
||||||
WRAPPER void CMessages::Display(void) { EAXJMP(0x529800); }
|
WRAPPER void CMessages::Display(void) { EAXJMP(0x529800); }
|
||||||
|
WRAPPER void CMessages::ClearAllMessagesDisplayedByGame(void) { EAXJMP(0x52B670); }
|
||||||
|
|
|
@ -4,4 +4,5 @@ class CMessages
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void Display(void);
|
static void Display(void);
|
||||||
|
static void ClearAllMessagesDisplayedByGame(void);
|
||||||
};
|
};
|
||||||
|
|
201
src/Text.cpp
Normal file
201
src/Text.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "patcher.h"
|
||||||
|
#include "FileMgr.h"
|
||||||
|
#include "Frontend.h"
|
||||||
|
#include "Messages.h"
|
||||||
|
#include "Text.h"
|
||||||
|
|
||||||
|
static wchar_t WideErrorString[25];
|
||||||
|
|
||||||
|
CText &TheText = *(CText*)0x941520;
|
||||||
|
|
||||||
|
CText::CText(void)
|
||||||
|
{
|
||||||
|
keyArray.entries = nil;
|
||||||
|
keyArray.numEntries = 0;
|
||||||
|
data.chars = nil;
|
||||||
|
data.numChars = 0;
|
||||||
|
unknown = 101; // What's this? version number?
|
||||||
|
memset(WideErrorString, 0, sizeof(WideErrorString));
|
||||||
|
}
|
||||||
|
|
||||||
|
CText::~CText(void)
|
||||||
|
{
|
||||||
|
data.Unload();
|
||||||
|
keyArray.Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CText::Load(void)
|
||||||
|
{
|
||||||
|
uint8 *filedata;
|
||||||
|
char filename[32], type[4];
|
||||||
|
int length;
|
||||||
|
int offset, sectlen;
|
||||||
|
|
||||||
|
Unload();
|
||||||
|
filedata = new uint8[0x40000];
|
||||||
|
|
||||||
|
CFileMgr::SetDir("TEXT");
|
||||||
|
switch(CMenuManager::m_PrefsLanguage){
|
||||||
|
case LANGUAGE_AMERICAN:
|
||||||
|
sprintf(filename, "AMERICAN.GXT");
|
||||||
|
break;
|
||||||
|
case LANGUAGE_FRENCH:
|
||||||
|
sprintf(filename, "FRENCH.GXT");
|
||||||
|
break;
|
||||||
|
case LANGUAGE_GERMAN:
|
||||||
|
sprintf(filename, "GERMAN.GXT");
|
||||||
|
break;
|
||||||
|
case LANGUAGE_ITALIAN:
|
||||||
|
sprintf(filename, "ITALIAN.GXT");
|
||||||
|
break;
|
||||||
|
case LANGUAGE_SPANISH:
|
||||||
|
sprintf(filename, "SPANISH.GXT");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
|
||||||
|
CFileMgr::SetDir("");
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
while(offset < length){
|
||||||
|
type[0] = filedata[offset++];
|
||||||
|
type[1] = filedata[offset++];
|
||||||
|
type[2] = filedata[offset++];
|
||||||
|
type[3] = filedata[offset++];
|
||||||
|
sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
|
||||||
|
(int)filedata[offset+1]<<8 | (int)filedata[offset+0];
|
||||||
|
offset += 4;
|
||||||
|
if(sectlen != 0){
|
||||||
|
if(strncmp(type, "TKEY", 4) == 0)
|
||||||
|
keyArray.Load(sectlen, filedata, &offset);
|
||||||
|
else if(strncmp(type, "TDAT", 4) == 0)
|
||||||
|
data.Load(sectlen, filedata, &offset);
|
||||||
|
else
|
||||||
|
offset += sectlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyArray.Update(data.chars);
|
||||||
|
|
||||||
|
delete[] filedata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CText::Unload(void)
|
||||||
|
{
|
||||||
|
CMessages::ClearAllMessagesDisplayedByGame();
|
||||||
|
data.Unload();
|
||||||
|
keyArray.Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t*
|
||||||
|
CText::Get(const char *key)
|
||||||
|
{
|
||||||
|
return keyArray.Search(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CKeyArray::Load(uint32 length, uint8 *data, int *offset)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
uint8 *rawbytes;
|
||||||
|
|
||||||
|
numEntries = length / sizeof(CKeyEntry);
|
||||||
|
entries = new CKeyEntry[numEntries];
|
||||||
|
rawbytes = (uint8*)entries;
|
||||||
|
|
||||||
|
for(i = 0; i < length; i++)
|
||||||
|
rawbytes[i] = data[(*offset)++];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CKeyArray::Unload(void)
|
||||||
|
{
|
||||||
|
delete[] entries;
|
||||||
|
entries = nil;
|
||||||
|
numEntries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CKeyArray::Update(wchar_t *chars)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < numEntries; i++)
|
||||||
|
entries[i].value = (wchar_t*)((uint8*)chars + (uintptr)entries[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
CKeyEntry*
|
||||||
|
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
|
||||||
|
{
|
||||||
|
int mid;
|
||||||
|
int diff;
|
||||||
|
|
||||||
|
if(low > high)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
mid = (low + high)/2;
|
||||||
|
diff = strcmp(key, entries[mid].key);
|
||||||
|
if(diff == 0)
|
||||||
|
return &entries[mid];
|
||||||
|
if(diff < 0)
|
||||||
|
return BinarySearch(key, entries, low, mid-1);
|
||||||
|
if(diff > 0)
|
||||||
|
return BinarySearch(key, entries, mid+1, high);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t*
|
||||||
|
CKeyArray::Search(const char *key)
|
||||||
|
{
|
||||||
|
CKeyEntry *found;
|
||||||
|
char errstr[25];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
found = BinarySearch(key, entries, 0, numEntries-1);
|
||||||
|
if(found)
|
||||||
|
return found->value;
|
||||||
|
sprintf(errstr, "%s missing", key);
|
||||||
|
for(i = 0; i < 25; i++)
|
||||||
|
WideErrorString[i] = errstr[i];
|
||||||
|
return WideErrorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CData::Load(uint32 length, uint8 *data, int *offset)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
uint8 *rawbytes;
|
||||||
|
|
||||||
|
numChars = length / sizeof(wchar_t);
|
||||||
|
chars = new wchar_t[numChars];
|
||||||
|
rawbytes = (uint8*)chars;
|
||||||
|
|
||||||
|
for(i = 0; i < length; i++)
|
||||||
|
rawbytes[i] = data[(*offset)++];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CData::Unload(void)
|
||||||
|
{
|
||||||
|
delete[] chars;
|
||||||
|
chars = nil;
|
||||||
|
numChars = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
|
||||||
|
InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
|
||||||
|
InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
|
||||||
|
|
||||||
|
InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
|
||||||
|
InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
|
||||||
|
InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
|
||||||
|
InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
|
||||||
|
InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
|
||||||
|
|
||||||
|
InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
|
||||||
|
InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
|
||||||
|
ENDPATCHES
|
47
src/Text.h
Normal file
47
src/Text.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct CKeyEntry
|
||||||
|
{
|
||||||
|
wchar_t *value;
|
||||||
|
char key[8];
|
||||||
|
};
|
||||||
|
// If this fails, CKeyArray::Load will have to be fixed
|
||||||
|
static_assert(sizeof(CKeyEntry) == 12, "CKeyEntry: error");
|
||||||
|
|
||||||
|
class CKeyArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CKeyEntry *entries;
|
||||||
|
int numEntries;
|
||||||
|
|
||||||
|
void Load(uint32 length, uint8 *data, int *offset);
|
||||||
|
void Unload(void);
|
||||||
|
void Update(wchar_t *chars);
|
||||||
|
CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);
|
||||||
|
wchar_t *Search(const char *key);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wchar_t *chars;
|
||||||
|
int numChars;
|
||||||
|
|
||||||
|
void Load(uint32 length, uint8 *data, int *offset);
|
||||||
|
void Unload(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CText
|
||||||
|
{
|
||||||
|
CKeyArray keyArray;
|
||||||
|
CData data;
|
||||||
|
int8 unknown;
|
||||||
|
public:
|
||||||
|
CText(void);
|
||||||
|
~CText(void);
|
||||||
|
void Load(void);
|
||||||
|
void Unload(void);
|
||||||
|
wchar_t *Get(const char *key);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CText &TheText;
|
Loading…
Reference in a new issue