[Scummvm-git-logs] scummvm master -> 23e31dd2cfd578bdd04ccab1c62f861ce4bfc22f
mgerhardy
noreply at scummvm.org
Thu May 11 20:00:36 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
23e31dd2cf TWINE: Support rendering Japanese strings in LBA1-PC
Commit: 23e31dd2cfd578bdd04ccab1c62f861ce4bfc22f
https://github.com/scummvm/scummvm/commit/23e31dd2cfd578bdd04ccab1c62f861ce4bfc22f
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-05-11T22:00:31+02:00
Commit Message:
TWINE: Support rendering Japanese strings in LBA1-PC
Changed paths:
engines/twine/resources/resources.cpp
engines/twine/resources/resources.h
engines/twine/text.cpp
engines/twine/text.h
diff --git a/engines/twine/resources/resources.cpp b/engines/twine/resources/resources.cpp
index aeac2fa4d26..53d03b81c01 100644
--- a/engines/twine/resources/resources.cpp
+++ b/engines/twine/resources/resources.cpp
@@ -20,6 +20,7 @@
*/
#include "twine/resources/resources.h"
+#include "common/file.h"
#include "common/tokenizer.h"
#include "common/util.h"
#include "twine/audio/sound.h"
@@ -40,6 +41,7 @@ Resources::~Resources() {
free(_samplesTable[i]);
}
free(_fontPtr);
+ free(_sjisFontPtr);
}
void Resources::initPalettes() {
@@ -140,6 +142,15 @@ void Resources::initResources() {
error("Failed to load font");
}
+ const int kMinSjisSize = 11072 * 24 * 3;
+ Common::File f24;
+ if (f24.open("FNT24.DAT") && f24.size() >= kMinSjisSize) {
+ // Rest is garbage
+ _sjisFontPtr = (byte *)malloc(kMinSjisSize);
+ assert(_sjisFontPtr);
+ f24.read(_sjisFontPtr, kMinSjisSize);
+ }
+
_engine->_text->setFontParameters(2, 8);
_engine->_text->setFontColor(COLOR_14);
_engine->_text->setTextCrossColor(136, 143, 2);
diff --git a/engines/twine/resources/resources.h b/engines/twine/resources/resources.h
index b5d681cafbf..93e412fed5a 100644
--- a/engines/twine/resources/resources.h
+++ b/engines/twine/resources/resources.h
@@ -174,6 +174,7 @@ public:
/** Font buffer pointer */
int32 _fontBufSize = 0;
uint8 *_fontPtr = nullptr;
+ uint8 *_sjisFontPtr = nullptr;
SpriteData _spriteShadowPtr;
SpriteBoundingBoxData _spriteBoundingBox;
diff --git a/engines/twine/text.cpp b/engines/twine/text.cpp
index 2c1316b39bd..8eb1b879a9f 100644
--- a/engines/twine/text.cpp
+++ b/engines/twine/text.cpp
@@ -48,9 +48,12 @@ namespace TwinE {
#define VOX_EXT ".vox"
static const int32 PADDING = 8;
+static const int kLBASJISCharWidth = 24;
+static const int kLBASJISCharHeight = 24;
Text::Text(TwinEEngine *engine) : _engine(engine) {
Common::fill(&_currMenuTextBuffer[0], &_currMenuTextBuffer[256], 0);
+ _isShiftJIS = _engine->getGameLang() == Common::Language::JA_JPN;
}
Text::~Text() {
@@ -172,7 +175,45 @@ void Text::initSceneTextBank() {
initDial((TextBankId)((int)_engine->_scene->_sceneTextBank + (int)TextBankId::Citadel_Island));
}
-void Text::drawCharacter(int32 x, int32 y, uint8 character) {
+void Text::drawCharacter(int32 x, int32 y, uint16 character) {
+ const uint8 usedColor = _dialTextColor;
+
+ if (_isShiftJIS && character > 0x100 && _engine->_resources->_sjisFontPtr) {
+ int index = 0;
+ if (character >= 0x8140 && character <= 0x9fff)
+ index = character - 0x8140;
+ else if (character >= 0xe040 && character <= 0xeaff)
+ index = character - 0xe040 + 8320;
+ else {
+ drawCharacter(x, y, '?');
+ return;
+ }
+
+ byte *glyphPtr = _engine->_resources->_sjisFontPtr + index * (kLBASJISCharHeight * kLBASJISCharWidth / 8);
+
+ for (uint8 fontY = 0; fontY < kLBASJISCharHeight; ++fontY) {
+ byte bits = 0;
+ int remBits = 0;
+ for (uint8 fontX = 0; fontX < kLBASJISCharWidth; ++fontX) {
+ if (remBits == 0) {
+ remBits = 8;
+ bits = *glyphPtr++;
+ }
+ int32 tempX = x + fontX;
+ int32 tempY = y + fontY;
+ if ((bits & 0x80) && tempX >= 0 && tempX < (_engine->width() - 1) && tempY >= 0 && tempY < (_engine->height() - 1)) {
+ _engine->_frontVideoBuffer.setPixel(tempX, tempY, usedColor);
+ }
+
+ remBits--;
+ bits <<= 1;
+ }
+ }
+ return;
+ }
+
+ if (character > 0x100)
+ character = '?';
Common::MemoryReadStream stream(_engine->_resources->_fontPtr, _engine->_resources->_fontBufSize);
stream.seek(character * 4);
stream.seek(stream.readSint16LE());
@@ -181,8 +222,6 @@ void Text::drawCharacter(int32 x, int32 y, uint8 character) {
x += stream.readByte();
y += stream.readByte();
- const uint8 usedColor = _dialTextColor;
-
int32 tempX = x;
int32 tempY = y;
@@ -216,7 +255,7 @@ void Text::drawCharacter(int32 x, int32 y, uint8 character) {
}
}
-void Text::drawCharacterShadow(int32 x, int32 y, uint8 character, int32 color, Common::Rect &dirtyRect) {
+void Text::drawCharacterShadow(int32 x, int32 y, uint16 character, int32 color, Common::Rect &dirtyRect) {
if (character == ' ') {
return;
}
@@ -237,6 +276,14 @@ void Text::drawCharacterShadow(int32 x, int32 y, uint8 character, int32 color, C
}
}
+uint16 Text::getNextChar(const char *&dialogue) {
+ uint16 currChar = *dialogue++ & 0xff;
+ if (_isShiftJIS && ((currChar >= 0x81 && currChar <= 0x9f)
+ || (currChar >= 0xe0 && currChar <= 0xea)) && ((*dialogue & 0xff) >= 0x40))
+ currChar = (currChar << 8) | (*dialogue++ & 0xff);
+ return currChar;
+}
+
void Text::drawText(int32 x, int32 y, const char *dialogue, bool shadow) {
// if the font is not defined
if (_engine->_resources->_fontPtr == nullptr) {
@@ -244,7 +291,7 @@ void Text::drawText(int32 x, int32 y, const char *dialogue, bool shadow) {
}
do {
- const uint8 currChar = (uint8)*dialogue++; // read the next char from the string
+ const uint16 currChar = getNextChar(dialogue); // read the next char from the string
if (currChar == '\0') {
break;
}
@@ -271,7 +318,7 @@ int32 Text::getTextSize(const char *dialogue) {
int32 dialTextSize = 0;
do {
- const uint8 currChar = (uint8) * (dialogue++);
+ const uint16 currChar = getNextChar(dialogue);
if (currChar == '\0') {
break;
}
@@ -517,14 +564,22 @@ void Text::fadeInCharacters(int32 counter, int32 fontColor) {
_engine->copyBlockPhys(dirtyRect);
}
-int32 Text::getCharWidth(uint8 chr) const {
+int32 Text::getCharWidth(uint16 chr) const {
+ if (_isShiftJIS && (chr > 0x100))
+ return kLBASJISCharWidth;
+ if (chr > 0x100)
+ chr = '?';
Common::MemoryReadStream stream(_engine->_resources->_fontPtr, _engine->_resources->_fontBufSize);
stream.seek(chr * 4);
stream.seek(stream.readSint16LE());
return stream.readByte();
}
-int32 Text::getCharHeight(uint8 chr) const {
+int32 Text::getCharHeight(uint16 chr) const {
+ if (_isShiftJIS && (chr > 0x100))
+ return kLBASJISCharHeight;
+ if (chr > 0x100)
+ chr = '?';
Common::MemoryReadStream stream(_engine->_resources->_fontPtr, _engine->_resources->_fontBufSize);
stream.seek(chr * 4);
stream.seek(stream.readSint16LE() + 1);
@@ -551,7 +606,7 @@ ProgressiveTextState Text::updateProgressiveText() { // NextDialCar
_dialTextXPos = _dialTextBox.left + PADDING;
_dialTextYPos = _dialTextBox.top + PADDING;
}
- const char currentChar = *_progressiveTextBufferPtr;
+ const uint16 currentChar = getNextChar(_progressiveTextBufferPtr);
assert(currentChar != '\0');
fillFadeInBuffer(_dialTextXPos, _dialTextYPos, currentChar);
fadeInCharacters(_fadeInCharactersPos, _dialTextStartColor);
@@ -563,9 +618,6 @@ ProgressiveTextState Text::updateProgressiveText() { // NextDialCar
_dialTextXPos += charWidth + 2;
}
- // next character
- _progressiveTextBufferPtr++;
-
// reaching 0-byte means a new line - as we are fading in per line
if (*_progressiveTextBufferPtr != '\0') {
return ProgressiveTextState::ContinueRunning;
diff --git a/engines/twine/text.h b/engines/twine/text.h
index 4c427514c06..c877167242c 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -51,7 +51,7 @@ private:
* @param y Y coordinate in screen
* @param character ascii character to display
*/
- void drawCharacter(int32 x, int32 y, uint8 character);
+ void drawCharacter(int32 x, int32 y, uint16 character);
/**
* Draw character with shadow
* @param x X coordinate in screen
@@ -59,13 +59,14 @@ private:
* @param character ascii character to display
* @param color character color
*/
- void drawCharacterShadow(int32 x, int32 y, uint8 character, int32 color, Common::Rect& dirtyRect);
+ void drawCharacterShadow(int32 x, int32 y, uint16 character, int32 color, Common::Rect& dirtyRect);
void initProgressiveTextBuffer();
struct WordSize {
int32 inChar = 0;
int32 inPixel = 0;
};
WordSize getWordSize(const char *completeText, char *wordBuf, int32 wordBufSize);
+ uint16 getNextChar(const char *&dialogue);
void processTextLine();
// draw next page arrow polygon
void renderContinueReadingTriangle();
@@ -90,7 +91,7 @@ private:
int32 _dialTextYPos = 0;
/** Current position of in the buffer of characters that are currently faded in */
- char *_progressiveTextBufferPtr = nullptr;
+ const char *_progressiveTextBufferPtr = nullptr;
int32 _dialTextBoxCurrentLine = 0;
struct BlendInCharacter {
@@ -135,6 +136,8 @@ private:
int32 _dialTextBoxLines = 0; // dialogueBoxParam1
int32 _dialTextBoxMaxX = 0; // dialogueBoxParam2
+ bool _isShiftJIS = false;
+
bool displayText(TextId index, bool showText, bool playVox, bool loop);
public:
Text(TwinEEngine *engine);
@@ -183,8 +186,8 @@ public:
* @param dialogue ascii text to display
*/
int32 getTextSize(const char *dialogue);
- int32 getCharWidth(uint8 chr) const;
- int32 getCharHeight(uint8 chr) const;
+ int32 getCharWidth(uint16 chr) const;
+ int32 getCharHeight(uint16 chr) const;
void initDialogueBox();
void initInventoryDialogueBox();
More information about the Scummvm-git-logs
mailing list