KYRA: (LoK/KOR) - make use of new Johab string encoding

This commit is contained in:
athrxx 2022-06-13 00:16:39 +02:00
parent b5079ca5c7
commit 05b9df0821
8 changed files with 79 additions and 72 deletions

View File

@ -161,6 +161,10 @@ void releaseCJKTables() {
windows950ConversionTable = 0;
delete[] windows950ReverseConversionTable;
windows950ReverseConversionTable = 0;
delete[] johabConversionTable;
johabConversionTable = 0;
delete[] johabReverseConversionTable;
johabReverseConversionTable = 0;
}
void U32String::decodeWindows932(const char *src, uint32 len) {

View File

@ -85,10 +85,14 @@ void Util::decodeString2(const char *src, char *dst) {
}
void Util::convertString_KYRAtoGUI(char *str, int bufferSize, Common::CodePage srcCP) {
Common::strlcpy(str, Common::U32String(str, srcCP).encode(Common::kUtf8).c_str(), bufferSize);
Common::U32String in(str, srcCP);
memset(str, 0, bufferSize);
Common::strlcpy(str, in.encode(Common::kUtf8).c_str(), bufferSize - 1);
}
void Util::convertString_GUItoKYRA(char *str, int bufferSize, Common::CodePage dstCP) {
Common::strlcpy(str, Common::U32String(str, Common::kUtf8).encode(dstCP).c_str(), bufferSize);
Common::U32String in(str, Common::kUtf8);
memset(str, 0, bufferSize);
Common::strlcpy(str, in.encode(dstCP).c_str(), bufferSize);
}
Common::String Util::convertString_GUItoKYRA(Common::String &str, Common::CodePage dstCP) {
@ -104,38 +108,38 @@ void Util::convertISOToDOS(char &c) {
c = Common::U32String(Common::String::format("%c", c), Common::kISO8859_1).encode(Common::kDos850).firstChar();
}
uint16 Util::convertDOSToHAN(char c, uint8 *mergeFlags) {
uint16 Util::convertDOSToJohab(char c, uint8 *mergeFlags) {
uint16 dest = 0;
if (!((c >= (uint8)'A' && c <= (uint8)'Z') || (c >= (uint8)'a' && c <= (uint8)'z')))
return 0;
uint16 res = 0;
for (int16 lml = 0, lmu = ARRAYSIZE(_hanConvTable) - 1; lml <= lmu; ) {
for (int16 lml = 0, lmu = ARRAYSIZE(_johabConvTable) - 1; lml <= lmu; ) {
res = MAX<int>(0, (lml + lmu)) >> 1;
if (_hanConvTable[res].key > c)
if (_johabConvTable[res].key > c)
lmu = res - 1;
else
lml = res + 1;
if (_hanConvTable[res].key == c)
if (_johabConvTable[res].key == c)
break;
}
if (_hanConvTable[res].key == c) {
dest = _hanConvTable[res].hanChar | 0x8000;
if (_johabConvTable[res].key == c) {
dest = _johabConvTable[res].johabChar | 0x8000;
if (mergeFlags)
*mergeFlags = _hanConvTable[res].flags;
*mergeFlags = _johabConvTable[res].flags;
}
return dest;
}
struct HanMergeTableEntry {
struct JohabMergeTableEntry {
const char *s;
uint8 val;
};
const HanMergeTableEntry _hanMergeTable[35] = {
const JohabMergeTableEntry _johabMergeTable[35] = {
{ "R", 0x03 }, { "T", 0x16 }, { "a", 0x11 }, { "c", 0x19 }, { "d", 0x17 },
{ "e", 0x08 }, { "f", 0x09 }, { "fa", 0x0B }, { "fg", 0x10 }, { "fq", 0x0C },
{ "fr", 0x0A }, { "ft", 0x0D }, { "fv", 0x0F }, { "fx", 0x0E }, { "g", 0x1D },
@ -145,27 +149,27 @@ const HanMergeTableEntry _hanMergeTable[35] = {
{ "u", 0x00 }, { "v", 0x1C }, { "w", 0x18 }, { "x", 0x1B }, { "z", 0x1A }
};
uint16 hanMergeGetOffs(const char *srch) {
uint16 johabMergeGetOffs(const char *srch) {
uint16 res = 0;
int find = 1;
for (int16 lml = 0, lmu = ARRAYSIZE(_hanMergeTable) - 1; lml <= lmu && find; ) {
for (int16 lml = 0, lmu = ARRAYSIZE(_johabMergeTable) - 1; lml <= lmu && find; ) {
res = MAX<int>(0, (lml + lmu)) >> 1;
find = strcmp(srch, _hanMergeTable[res].s);
find = strcmp(srch, _johabMergeTable[res].s);
if (find < 0)
lmu = res - 1;
else
lml = res + 1;
}
return find ? 0 : _hanMergeTable[res].val;
return find ? 0 : _johabMergeTable[res].val;
}
uint8 _hanMergeState = 0;
uint16 _2byteBackup = 0;
char _asciiPrev = '\0';
void Util::mergeUpdateHANChars(uint16 &destHanChar0, uint16 &destHanChar1, char asciiInput, bool reset) {
void Util::mergeUpdateJohabChars(uint16 &destJohabChar0, uint16 &destJohabChar1, char asciiInput, bool reset) {
if (reset) {
_hanMergeState = 0;
_asciiPrev = '\0';
@ -178,17 +182,17 @@ void Util::mergeUpdateHANChars(uint16 &destHanChar0, uint16 &destHanChar1, char
for (int loops = 1; loops; --loops) {
uint8 flags = 0;
uint8 offs = 0;
destHanChar0 &= 0x7fff;
destHanChar1 = convertDOSToHAN(asciiInput, &flags) & 0x7fff;
destJohabChar0 &= 0x7fff;
destJohabChar1 = convertDOSToJohab(asciiInput, &flags) & 0x7fff;
char in[3];
in[0] = in[1] = in[2] = '\0';
switch (_hanMergeState) {
case 0x01:
if (flags & 6) {
_2byteBackup = destHanChar0;
destHanChar0 = (destHanChar0 & 0xFC1F) | (convertDOSToHAN(asciiInput) & 0x3E0);
destHanChar1 = 0;
_2byteBackup = destJohabChar0;
destJohabChar0 = (destJohabChar0 & 0xFC1F) | (convertDOSToJohab(asciiInput) & 0x3E0);
destJohabChar1 = 0;
_hanMergeState = flags;
} else {
++loops;
@ -199,12 +203,12 @@ void Util::mergeUpdateHANChars(uint16 &destHanChar0, uint16 &destHanChar1, char
if (flags & 0x10) {
in[0] = asciiInput;
in[1] = '\0';
offs = hanMergeGetOffs(in);
offs = johabMergeGetOffs(in);
}
if (offs) {
_2byteBackup = destHanChar0;
destHanChar0 = (destHanChar0 & 0xFFE0) | offs;
destHanChar1 = 0;
_2byteBackup = destJohabChar0;
destJohabChar0 = (destJohabChar0 & 0xFFE0) | offs;
destJohabChar1 = 0;
_hanMergeState = flags;
} else {
++loops;
@ -215,12 +219,12 @@ void Util::mergeUpdateHANChars(uint16 &destHanChar0, uint16 &destHanChar1, char
if (flags & 0x12) {
in[0] = (flags & 2) ? _asciiPrev : asciiInput;
in[1] = (flags & 2) ? asciiInput : '\0';
offs = hanMergeGetOffs(in);
offs = johabMergeGetOffs(in);
}
if (offs) {
_2byteBackup = destHanChar0;
destHanChar0 = (flags & 2) ? (destHanChar0 + offs) : ((destHanChar0 & 0xFFE0) | offs);
destHanChar1 = 0;
_2byteBackup = destJohabChar0;
destJohabChar0 = (flags & 2) ? (destJohabChar0 + offs) : ((destJohabChar0 & 0xFFE0) | offs);
destJohabChar1 = 0;
_hanMergeState = flags;
} else {
++loops;
@ -229,20 +233,19 @@ void Util::mergeUpdateHANChars(uint16 &destHanChar0, uint16 &destHanChar1, char
case 0x11:
if (flags & 6) {
uint8 h = (_2byteBackup >> 8) | 0x80;
destHanChar1 = (convertDOSToHAN(_asciiPrev) & 0xFC1F) | (convertDOSToHAN(asciiInput, &flags) & 0x3E0);
destHanChar0 = _2byteBackup;
destJohabChar1 = (convertDOSToJohab(_asciiPrev) & 0xFC1F) | (convertDOSToJohab(asciiInput, &flags) & 0x3E0);
destJohabChar0 = _2byteBackup;
_hanMergeState = flags;
} else if (flags & 0x10) {
in[0] = _asciiPrev;
in[1] = asciiInput;
in[2] = '\0';
offs = hanMergeGetOffs(in);
offs = johabMergeGetOffs(in);
}
if (offs) {
_2byteBackup = destHanChar0;
destHanChar0 = (destHanChar0 & 0xFFE0) | offs;
destHanChar1 = 0;
_2byteBackup = destJohabChar0;
destJohabChar0 = (destJohabChar0 & 0xFFE0) | offs;
destJohabChar1 = 0;
_hanMergeState = flags;
} else if (!(flags & 6)) {
++loops;
@ -251,23 +254,23 @@ void Util::mergeUpdateHANChars(uint16 &destHanChar0, uint16 &destHanChar1, char
default:
_hanMergeState = flags & 7;
_2byteBackup = destHanChar0;
destHanChar0 = 0;
_2byteBackup = destJohabChar0;
destJohabChar0 = 0;
break;
}
_asciiPrev = asciiInput;
if (loops == 2) {
destHanChar0 = 0;
destJohabChar0 = 0;
_hanMergeState = 0;
}
}
if (destHanChar0)
destHanChar0 |= 0x8000;
if (destHanChar1)
destHanChar1 |= 0x8000;
if (destJohabChar0)
destJohabChar0 |= 0x8000;
if (destJohabChar1)
destJohabChar1 |= 0x8000;
}
Common::String Util::decodeString1(const Common::String &src) {
@ -316,7 +319,7 @@ Common::String Util::findMacResourceFile(const char *baseName) {
return fileName;
}
const Util::DOS2HanEntry Util::_hanConvTable[52] = {
const Util::DOS2JOHABEntry Util::_johabConvTable[52] = {
{ 'A', 0x2041, 0x11 }, { 'B', 0x0741, 0x04 }, { 'C', 0x4041, 0x11 }, { 'D', 0x3441, 0x11 },
{ 'E', 0x1841, 0x01 }, { 'F', 0x1c41, 0x11 }, { 'G', 0x5041, 0x11 }, { 'H', 0x05a1, 0x04 },
{ 'I', 0x04a1, 0x02 }, { 'J', 0x04e1, 0x02 }, { 'K', 0x0461, 0x02 }, { 'L', 0x07a1, 0x02 },

View File

@ -41,23 +41,23 @@ public:
static Common::String convertISOToUTF8(Common::String &str);
static void convertISOToDOS(char &c);
static uint16 convertDOSToHAN(char c, uint8 *mergeFlags = 0);
static uint16 convertDOSToJohab(char c, uint8 *mergeFlags = 0);
// This method does not only need a ref to the new character, but also to the one before that, since
// both of these will be used to calculate the output and also both of these may get modfied. The
// reset parameter will reset the internal merge state (useful when the build-up process is broken,
// e. g. when typing a one-byte character, like a digit).
static void mergeUpdateHANChars(uint16 &prevHanChar, uint16 &newHanChar, char asciiInput, bool reset);
static void mergeUpdateJohabChars(uint16 &destJohabChar0, uint16 &destJohabChar1, char asciiInput, bool reset);
static Common::String findMacResourceFile(const char *baseName);
private:
struct DOS2HanEntry {
struct DOS2JOHABEntry {
char key;
uint16 hanChar;
uint16 johabChar;
uint8 flags;
};
static const DOS2HanEntry _hanConvTable[52];
static const DOS2JOHABEntry _johabConvTable[52];
};
} // End of namespace Kyra

View File

@ -1397,7 +1397,7 @@ bool Screen::loadFont(FontId fontId, const char *filename) {
}
} else if (fontId == FID_KOREAN_FNT) {
const uint16 *lookupTable = _vm->staticres()->loadRawDataBe16(k1TwoByteFontLookupTable, temp);
fnt = new HangulFontLoK(_fonts[FID_8_FNT], lookupTable, temp);
fnt = new JohabFontLoK(_fonts[FID_8_FNT], lookupTable, temp);
} else {
fnt = new DOSFont();
}
@ -1433,7 +1433,7 @@ int Screen::getFontWidth() const {
int Screen::getCharWidth(uint16 c) const {
int width = _fonts[_currentFont]->getCharWidth(c);
if (_isSegaCD || _fonts[_currentFont]->getType() == Font::kASCII || (_fonts[_currentFont]->getType() == Font::kHANGUL && c < 0x80))
if (_isSegaCD || _fonts[_currentFont]->getType() == Font::kASCII || (_fonts[_currentFont]->getType() == Font::kJohab && c < 0x80))
width += _charSpacing;
return width;
}
@ -1550,7 +1550,7 @@ uint16 Screen::fetchChar(const char *&s) const {
uint16 ch = (uint8)*s++;
if ((fontType == Font::kSJIS && (ch <= 0x7F || (ch >= 0xA1 && ch <= 0xDF))) ||
((fontType == Font::kBIG5 || fontType == Font::kHANGUL) && ch < 0x80))
((fontType == Font::kBIG5 || fontType == Font::kJohab) && ch < 0x80))
return ch;
ch |= (uint8)(*s++) << 8;

View File

@ -68,7 +68,7 @@ public:
kASCII = 0,
kSJIS,
kBIG5,
kHANGUL
kJohab
};
public:
@ -290,10 +290,10 @@ private:
const uint16 _pitch;
};
class HangulFontLoK final : public Font {
class JohabFontLoK final : public Font {
public:
HangulFontLoK(Font *&font8fat, const uint16 *lookupTable, uint32 lookupTableSize);
~HangulFontLoK() override;
JohabFontLoK(Font *&font8fat, const uint16 *lookupTable, uint32 lookupTableSize);
~JohabFontLoK() override;
enum {
kNumJongseong = 191,
@ -302,7 +302,7 @@ public:
};
bool load(Common::SeekableReadStream &data) override;
Type getType() const override { return kHANGUL; }
Type getType() const override { return kJohab; }
int getHeight() const override { return _height; }
int getWidth() const override { return _width; }
int getCharWidth(uint16 c) const override;

View File

@ -533,7 +533,7 @@ void ChineseTwoByteFontLoK::processColorMap() {
_textColor[1] = _colorMap[0] | (_colorMap[0] << 8);
}
HangulFontLoK::HangulFontLoK(Font *&font8fat, const uint16 *lookupTable, uint32 lookupTableSize) : _font8fat(font8fat), _height(15), _width(15), _fileData(0), _colorMap(0), _glyphTemp(0) {
JohabFontLoK::JohabFontLoK(Font *&font8fat, const uint16 *lookupTable, uint32 lookupTableSize) : _font8fat(font8fat), _height(15), _width(15), _fileData(0), _colorMap(0), _glyphTemp(0) {
assert(lookupTable);
assert(lookupTableSize == 224);
for (int i = 0; i < 7; ++i)
@ -542,12 +542,12 @@ HangulFontLoK::HangulFontLoK(Font *&font8fat, const uint16 *lookupTable, uint32
_glyphTemp = new uint8[30];
}
HangulFontLoK::~HangulFontLoK() {
JohabFontLoK::~JohabFontLoK() {
delete[] _fileData;
delete[] _glyphTemp;
}
bool HangulFontLoK::load(Common::SeekableReadStream &data) {
bool JohabFontLoK::load(Common::SeekableReadStream &data) {
if (_fileData)
return false;
@ -575,22 +575,22 @@ bool HangulFontLoK::load(Common::SeekableReadStream &data) {
return true;
}
int HangulFontLoK::getCharWidth(uint16 c) const {
int JohabFontLoK::getCharWidth(uint16 c) const {
assert(_font8fat);
return (c >= 0x80) ? _width + 1 : _font8fat->getCharWidth(c);
}
int HangulFontLoK::getCharHeight(uint16 c) const {
int JohabFontLoK::getCharHeight(uint16 c) const {
return _colorMap[3] ? _height + 2 : _height;
}
void HangulFontLoK::setColorMap(const uint8 *src) {
void JohabFontLoK::setColorMap(const uint8 *src) {
_colorMap = src;
assert(_font8fat);
_font8fat->setColorMap(src);
}
void HangulFontLoK::drawChar(uint16 c, byte *dst, int pitch, int) const {
void JohabFontLoK::drawChar(uint16 c, byte *dst, int pitch, int) const {
if (c < 0x80) {
assert(_font8fat);
_font8fat->drawChar(c, dst + (c == '\"' ? 0 : 5) * pitch, pitch, 0);
@ -610,7 +610,7 @@ void HangulFontLoK::drawChar(uint16 c, byte *dst, int pitch, int) const {
renderGlyph(dst, glyph, _colorMap[1], pitch);
}
const uint8 *HangulFontLoK::createGlyph(uint16 chr) const {
const uint8 *JohabFontLoK::createGlyph(uint16 chr) const {
memset(_glyphTemp, 0, 30);
uint16 t[3];
@ -653,7 +653,7 @@ const uint8 *HangulFontLoK::createGlyph(uint16 chr) const {
return _glyphTemp;
}
void HangulFontLoK::renderGlyph(byte *dst, const uint8 *glyph, uint8 col, int pitch) const {
void JohabFontLoK::renderGlyph(byte *dst, const uint8 *glyph, uint8 col, int pitch) const {
const uint8 *src = glyph;
pitch -= 15;

View File

@ -1508,7 +1508,7 @@ GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen), _n
_saveSlotStringsTemp = new char*[6];
for (int i = 0; i < 6; i++) {
_saveSlotStringsTemp[i] = new char[26]();
_saveSlotStringsTemp[i] = new char[52]();
}
_saveSlotIdTemp = new int16[7];
memset(_saveSlotIdTemp, 0xFF, sizeof(int16) * 7);
@ -3186,12 +3186,12 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
Graphics::Surface thumb;
createScreenThumbnail(thumb);
char temp[26];
Common::strlcpy(temp, _saveSlotStringsTemp[slot], 26);
char temp[52];
Common::strlcpy(temp, _saveSlotStringsTemp[slot], 52);
// Ingame auto-generated Japanese EOB SegaCD savegame descriptions have a special 1-byte encoding that
// does not survive this conversion. And the rest of the characters in these descriptions do not require it.
if (!(_vm->gameFlags().platform == Common::kPlatformSegaCD && _vm->gameFlags().lang == Common::JA_JPN && Common::String(temp).contains('\r')))
Util::convertString_KYRAtoGUI(temp, 26);
Util::convertString_KYRAtoGUI(temp, 52);
_vm->updatePlayTimer();
Common::Error err = _vm->saveGameStateIntern(_savegameOffset + slot, temp, &thumb);
thumb.free();

View File

@ -162,8 +162,8 @@ private:
bool _menuRestoreScreen;
uint8 _toplevelMenu;
int _savegameOffset;
char _savegameName[35];
char _savegameNames[5][35];
char _savegameName[35 * 4]; // allow extra space, since the string can be UTF-8, temporarily
char _savegameNames[5][35 * 4];
const char *_specialSavegameString;
bool _resetHanInput;