mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-10 21:03:31 +00:00
SWORD2: Fix support for Korean translation
This commit is contained in:
parent
19466d352e
commit
2ea2e6d317
@ -81,6 +81,21 @@ static const ADGameDescription gameDescriptions[] = {
|
||||
GUIO0()
|
||||
},
|
||||
|
||||
{ // Korean fan translation
|
||||
"sword2",
|
||||
"",
|
||||
AD_ENTRY6s("general.clu", "31db8564f9187538f24d9fda0677f666", 7059728,
|
||||
"text.clu", "9b344d976ca8d19a1cf5aa4413397f6b", 304968,
|
||||
"speech1.clu", "a403904a0e825356107d228f8f74092e", 176260048,
|
||||
"docks.clu", "b39246fbb5b955a29f9a207c69bfc318", 20262263,
|
||||
"bs2k.fnt", NULL, 1222000,
|
||||
"korean.clu", NULL, -1),
|
||||
Common::KO_KOR,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO0()
|
||||
},
|
||||
|
||||
{ // GOG.com release version 2.0.0.6
|
||||
"sword2",
|
||||
"GOG",
|
||||
|
@ -69,6 +69,9 @@ namespace Sword2 {
|
||||
#define DUD 64 // the first "chequered flag" (dud) symbol in
|
||||
// our character set is in the '@' position
|
||||
|
||||
#define KOREAN_CHAR_WIDTH 20
|
||||
#define KOREAN_CHAR_HEIGHT 26
|
||||
|
||||
namespace {
|
||||
Common::String readLine(Common::ReadStream &stream) {
|
||||
Common::String ret = stream.readString('\n');
|
||||
@ -204,6 +207,9 @@ uint16 FontRenderer::analyzeSentence(const byte *sentence, uint16 maxWidth, uint
|
||||
if (isChinese && (ch & 0x80)) {
|
||||
w = kChineseWidth + _charSpacing;
|
||||
l = 2;
|
||||
} else if (isKoreanChar(ch, sentence[pos+1], fontRes)) {
|
||||
w += wcharWidth(ch, sentence[pos+1], fontRes) + _charSpacing;
|
||||
l = 2;
|
||||
} else {
|
||||
w = charWidth(ch, fontRes) + _charSpacing;
|
||||
l = 1;
|
||||
@ -434,12 +440,21 @@ byte *FontRenderer::buildTextSprite(const byte *sentence, uint32 fontRes, uint8
|
||||
|
||||
continue;
|
||||
}
|
||||
byte *charPtr = findChar(ch, charSet);
|
||||
byte *charPtr = NULL;
|
||||
if (isKoreanChar(ch, *currTxtLine, fontRes)) {
|
||||
charPtr = findWChar(ch, *currTxtLine++, charSet);
|
||||
j++;
|
||||
frame_head.width = KOREAN_CHAR_WIDTH;
|
||||
|
||||
frame_head.read(charPtr);
|
||||
copyWChar(charPtr, spritePtr, spriteWidth, pen);
|
||||
} else {
|
||||
charPtr = findChar(ch, charSet);
|
||||
|
||||
assert(frame_head.height == char_height);
|
||||
copyChar(charPtr, spritePtr, spriteWidth, pen);
|
||||
frame_head.read(charPtr);
|
||||
|
||||
assert(frame_head.height == char_height);
|
||||
copyChar(charPtr, spritePtr, spriteWidth, pen);
|
||||
}
|
||||
|
||||
// We must remember to free memory for generated character in psx,
|
||||
// as it is extracted differently than pc version (copyed from a
|
||||
@ -490,6 +505,20 @@ uint16 FontRenderer::charWidth(byte ch, uint32 fontRes) {
|
||||
return frame_head.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hi the KSX1001 code upper byte of the character
|
||||
* @param lo the KSX1001 code lower byte of the character
|
||||
* @param fontRes the font resource id
|
||||
* @return the width of the character
|
||||
*/
|
||||
|
||||
uint16 FontRenderer::wcharWidth(byte hi, byte lo, uint32 fontRes) {
|
||||
if (isKoreanChar(hi, lo, fontRes)) {
|
||||
return KOREAN_CHAR_WIDTH;
|
||||
}
|
||||
return charWidth(hi, fontRes) + charWidth(lo, fontRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fontRes the font resource id
|
||||
* @return the height of a character sprite
|
||||
@ -599,6 +628,17 @@ byte *FontRenderer::findChar(byte ch, byte *charSet) {
|
||||
}
|
||||
}
|
||||
|
||||
byte *FontRenderer::findWChar(byte hi, byte lo, byte *charSet) {
|
||||
uint16 frameWidth = KOREAN_CHAR_WIDTH;
|
||||
uint16 frameHeight = KOREAN_CHAR_HEIGHT;
|
||||
FrameHeader frame_head;
|
||||
byte *charPtr = findChar(0xFF, charSet);
|
||||
|
||||
frame_head.read(charPtr);
|
||||
|
||||
return charPtr + frame_head.size() + frame_head.width * frame_head.height + ((hi - 0xB0) * 94 + (lo - 0xA1)) * frameWidth * frameHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a character sprite to the sprite buffer.
|
||||
* @param charPtr pointer to the character sprite
|
||||
@ -617,6 +657,11 @@ void FontRenderer::copyChar(const byte *charPtr, byte *spritePtr, uint16 spriteW
|
||||
copyCharRaw(charPtr + FrameHeader::size(), frame.width, frame.height, spritePtr, spriteWidth, pen);
|
||||
}
|
||||
|
||||
void FontRenderer::copyWChar(const byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
|
||||
|
||||
copyCharRaw(charPtr, KOREAN_CHAR_WIDTH, KOREAN_CHAR_HEIGHT, spritePtr, spriteWidth, pen);
|
||||
}
|
||||
|
||||
void FontRenderer::copyCharRaw(const byte *source, uint16 charWidth, uint16 charHeight, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
|
||||
byte *rowPtr = spritePtr;
|
||||
|
||||
@ -658,6 +703,14 @@ void FontRenderer::copyCharRaw(const byte *source, uint16 charWidth, uint16 char
|
||||
}
|
||||
}
|
||||
|
||||
bool FontRenderer::isKoreanChar(byte hi, byte lo, uint32 fontRes) {
|
||||
if (!_vm->_isKorTrs || fontRes != ENGLISH_SPEECH_FONT_ID)
|
||||
return false;
|
||||
if (hi >= 0xB0 && hi <= 0xC8 && lo >= 0xA1 && lo <= 0xFE)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Distance to keep speech text from edges of screen
|
||||
#define TEXT_MARGIN 12
|
||||
|
||||
|
@ -103,10 +103,14 @@ private:
|
||||
uint16 analyzeSentence(const byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line, bool isChinese);
|
||||
byte *buildTextSprite(const byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines, bool isChinese);
|
||||
uint16 charWidth(byte ch, uint32 fontRes);
|
||||
uint16 wcharWidth(byte hi, byte lo, uint32 fontRes);
|
||||
uint16 charHeight(uint32 fontRes);
|
||||
byte *findChar(byte ch, byte *charSet);
|
||||
byte *findWChar(byte hi, byte lo, byte *charSet);
|
||||
void copyChar(const byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
|
||||
void copyWChar(const byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
|
||||
void copyCharRaw(const byte *source, uint16 charWidth, uint16 charHeight, byte *spritePtr, uint16 spriteWidth, uint8 pen);
|
||||
bool isKoreanChar(const byte hi, const byte lo, const uint32 fontRes);
|
||||
|
||||
public:
|
||||
FontRenderer(Sword2Engine *vm) : _vm(vm) {
|
||||
|
@ -230,6 +230,9 @@ bool ResourceManager::init() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use korean.clu instead of TEXT.CLU
|
||||
if (_vm->_isKorTrs && !scumm_stricmp(_resFiles[i].fileName, "TEXT.CLU"))
|
||||
strcpy_s(_resFiles[i].fileName, 20, "korean.clu");
|
||||
_resFiles[i].cd = cdInf[j].cd;
|
||||
}
|
||||
}
|
||||
@ -308,12 +311,38 @@ byte *ResourceManager::openResource(uint32 res, bool dump) {
|
||||
|
||||
debug(6, "res len %d", len);
|
||||
|
||||
// Ok, we know the length so try and allocate the memory.
|
||||
_resList[res].ptr = _vm->_memory->memAlloc(len, res);
|
||||
_resList[res].size = len;
|
||||
_resList[res].refCount = 0;
|
||||
if (res == ENGLISH_SPEECH_FONT_ID && _vm->_isKorTrs) {
|
||||
// Load Korean Font
|
||||
uint32 korFontSize = 0;
|
||||
Common::File *korFontFile = NULL;
|
||||
|
||||
file->read(_resList[res].ptr, len);
|
||||
korFontFile = new Common::File();
|
||||
korFontFile->open("bs2k.fnt");
|
||||
if (korFontFile->isOpen()) {
|
||||
korFontSize = korFontFile->size();
|
||||
}
|
||||
|
||||
// Ok, we know the length so try and allocate the memory.
|
||||
_resList[res].ptr = _vm->_memory->memAlloc(len + korFontSize, res);
|
||||
_resList[res].size = len + korFontSize;
|
||||
_resList[res].refCount = 0;
|
||||
|
||||
file->read(_resList[res].ptr, len);
|
||||
|
||||
if (korFontSize > 0) {
|
||||
korFontFile->read(_resList[res].ptr + len, korFontSize);
|
||||
korFontFile->close();
|
||||
}
|
||||
|
||||
len += korFontSize;
|
||||
} else {
|
||||
// Ok, we know the length so try and allocate the memory.
|
||||
_resList[res].ptr = _vm->_memory->memAlloc(len, res);
|
||||
_resList[res].size = len;
|
||||
_resList[res].refCount = 0;
|
||||
|
||||
file->read(_resList[res].ptr, len);
|
||||
}
|
||||
|
||||
debug(3, "Loaded resource '%s' (%d) from '%s' on CD %d (%d)", fetchName(_resList[res].ptr), res, _resFiles[cluFileNum].fileName, getCD(), _resFiles[cluFileNum].cd);
|
||||
|
||||
|
@ -84,6 +84,8 @@ Sword2Engine::Sword2Engine(OSystem *syst, const ADGameDescription *gameDesc) : E
|
||||
_gameSpeed = 1;
|
||||
|
||||
_gmmLoadSlot = -1; // Used to manage GMM Loading
|
||||
|
||||
_isKorTrs = gameDesc->language == Common::KO_KOR;
|
||||
}
|
||||
|
||||
Sword2Engine::~Sword2Engine() {
|
||||
|
@ -198,6 +198,8 @@ public:
|
||||
|
||||
int32 _gameCycle;
|
||||
|
||||
bool _isKorTrs;
|
||||
|
||||
#if RIGHT_CLICK_CLEARS_LUGGAGE
|
||||
bool heldIsInInventory();
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user