summaryrefslogblamecommitdiffstats
path: root/src/core/Text.cpp
blob: d7d63467ca4a5b1f8ff40b7ac7ec96a7e05488de (plain) (tree)
1
2
3
4
5
6
7
8






                     
                                 








                                   
                       









































































                                                                                     
      




                                    


















                                              






















                                                        
                               


                                       
                                                                                       





















                                                                                   
      





















                                                            

                                          













                                                
    






                                            
 
                                         

 













                                                                   
#include "common.h"
#include "patcher.h"
#include "FileMgr.h"
#include "Frontend.h"
#include "Messages.h"
#include "Text.h"

static wchar WideErrorString[25];

CText &TheText = *(CText*)0x941520;

CText::CText(void)
{
	keyArray.entries = nil;
	keyArray.numEntries = 0;
	data.chars = nil;
	data.numChars = 0;
	encoding = 101;
	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*
CText::Get(const char *key)
{
	return keyArray.Search(key);
}

wchar
CText::GetUpperCase(wchar c)
{
	// TODO: do this depending on encoding
	if(islower(c))
		return toupper(c);
	return c;
}

void
CText::UpperCase(wchar *s)
{
	while(*s){
		*s = GetUpperCase(*s);
		s++;
	}
}


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 *chars)
{
	int i;
	for(i = 0; i < numEntries; i++)
		entries[i].value = (wchar*)((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*
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);
	chars = new wchar[numChars];
	rawbytes = (uint8*)chars;

	for(i = 0; i < length; i++)
		rawbytes[i] = data[(*offset)++];
}

void
CData::Unload(void)
{
	delete[] chars;
	chars = nil;
	numChars = 0;
}

void
AsciiToUnicode(const char *src, uint16 *dst)
{
	while((*dst++ = *src++) != '\0');
}

void
TextCopy(wchar *dst, const wchar *src)
{
	while((*dst++ = *src++) != '\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