aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/charset.cpp32
-rw-r--r--engines/scumm/gfx.cpp135
-rw-r--r--engines/scumm/input.cpp5
-rw-r--r--engines/scumm/scumm.cpp20
-rw-r--r--engines/scumm/scumm.h3
5 files changed, 153 insertions, 42 deletions
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 40637ec4b3..86b48c3690 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -48,6 +48,8 @@ better separation of the various modules.
void ScummEngine::loadCJKFont() {
Common::File fp;
_useCJKMode = false;
+ _textSurfaceMultiplier = 1;
+
if (_language == Common::JA_JPN && _game.version <= 5) { // FM-TOWNS v3 / v5 Kanji
int numChar = 256 * 32;
_2byteWidth = 16;
@@ -60,6 +62,7 @@ void ScummEngine::loadCJKFont() {
fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar);
fp.close();
}
+ _textSurfaceMultiplier = 2;
} else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) {
int numChar = 0;
const char *fontFile = NULL;
@@ -85,6 +88,7 @@ void ScummEngine::loadCJKFont() {
if (fontFile && fp.open(fontFile)) {
debug(2, "Loading CJK Font");
_useCJKMode = true;
+ _textSurfaceMultiplier = 1; // No multiplication here
fp.seek(2, SEEK_CUR);
_2byteWidth = fp.readByte();
_2byteHeight = fp.readByte();
@@ -276,7 +280,7 @@ int CharsetRendererCommon::getFontHeight() {
// do spacing for variable width old-style font
int CharsetRendererClassic::getCharWidth(byte chr) {
if (chr >= 0x80 && _vm->_useCJKMode)
- return _vm->_2byteWidth / 2;
+ return _vm->_2byteWidth;
int spacing = 0;
int offs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
@@ -1160,7 +1164,7 @@ CharsetRendererV2::CharsetRendererV2(ScummEngine *vm, Common::Language language)
int CharsetRendererV3::getCharWidth(byte chr) {
if (chr & 0x80 && _vm->_useCJKMode)
- return _vm->_2byteWidth / 2;
+ return _vm->_2byteWidth;
int spacing = 0;
spacing = *(_widthTable + chr);
@@ -1257,18 +1261,18 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
_hasMask = true;
_textScreenID = vs->number;
}
- if (ignoreCharsetMask || !vs->hasTwoBuffers) {
+ if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {
dst = vs->getPixels(_left, drawTop);
drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight);
} else {
- dst = (byte *)_vm->_textSurface.getBasePtr(_left, _top);
+ dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);
drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight);
}
if (_str.left > _left)
_str.left = _left;
- _left += origWidth;
+ _left += origWidth / _vm->_textSurfaceMultiplier;
if (_str.right < _left) {
_str.right = _left;
@@ -1276,8 +1280,8 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
_str.right++;
}
- if (_str.bottom < _top + height)
- _str.bottom = _top + height;
+ if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier)
+ _str.bottom = _top + height / _vm->_textSurfaceMultiplier;
}
void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
@@ -1391,8 +1395,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_top += offsY;
_left += offsX;
- if (_left + origWidth > _right + 1 || _left < 0) {
- _left += origWidth;
+ if (_left + origWidth / _vm->_textSurfaceMultiplier > _right + 1 || _left < 0) {
+ _left += origWidth / _vm->_textSurfaceMultiplier;
_top -= offsY;
return;
}
@@ -1424,7 +1428,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
printCharIntern(is2byte, charPtr, origWidth, origHeight, width, height, vs, ignoreCharsetMask);
- _left += origWidth;
+ _left += origWidth / _vm->_textSurfaceMultiplier;
if (_str.right < _left) {
_str.right = _left;
@@ -1432,8 +1436,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_str.right++;
}
- if (_str.bottom < _top + height)
- _str.bottom = _top + height;
+ if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier)
+ _str.bottom = _top + height / _vm->_textSurfaceMultiplier;
_top -= offsY;
}
@@ -1473,12 +1477,12 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
} else {
Graphics::Surface dstSurface;
Graphics::Surface backSurface;
- if (ignoreCharsetMask || !vs->hasTwoBuffers) {
+ if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {
dstSurface = *vs;
dstPtr = vs->getPixels(_left, drawTop);
} else {
dstSurface = _vm->_textSurface;
- dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch + _left;
+ dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier;
}
if (_blitAlso && vs->hasTwoBuffers) {
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index c70a0e9351..3c6f57be1a 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -561,8 +561,25 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
return;
const byte *src = vs->getPixels(x, top);
+ int m = _textSurfaceMultiplier;
+ byte *dst;
+ int vsPitch;
int pitch = vs->pitch;
+ if (_useCJKMode && _textSurfaceMultiplier == 2) {
+ dst = _fmtownsBuf;
+
+ scale2x(dst, _screenWidth * m, src, vs->pitch, width, height);
+ src = dst;
+
+ vsPitch = _screenWidth * m - width * m;
+
+ } else {
+ vsPitch = vs->pitch - width;
+ }
+
+ dst = _compositeBuf;
+
if (_game.version < 7) {
// For The Dig, FT and COMI, we just blit everything to the screen at once.
// For older games, things are more complicated. First off, we need to
@@ -572,7 +589,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
// Compute pointer to the text surface
assert(_compositeBuf);
- const byte *text = (byte *)_textSurface.getBasePtr(x, y);
+ const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m);
// The values x, width, etc. are all multiples of 8 at this point,
// so loop unrolloing might be a good idea...
@@ -594,19 +611,18 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
// but also more complicated to implement, and incurs a bigger overhead when
// writing to the text surface.
#ifdef __DS__
- DS::asmDrawStripToScreen(height, width, text, src, _compositeBuf, vs->pitch, width, _textSurface.pitch);
+ DS::asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, width, _textSurface.pitch);
#else
- byte *dst = _compositeBuf;
- for (int h = 0; h < height; ++h) {
- for (int w = 0; w < width; ++w) {
+ for (int h = 0; h < height * m; ++h) {
+ for (int w = 0; w < width * m; ++w) {
byte tmp = *text++;
if (tmp == CHARSET_MASK_TRANSPARENCY)
tmp = *src;
*dst++ = tmp;
src++;
}
- src += vs->pitch - width;
- text += _textSurface.pitch - width;
+ src += vsPitch;
+ text += _textSurface.pitch - width * m;
}
#endif
@@ -621,6 +637,12 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
// center image on the screen
x += (Common::kHercW - _screenWidth * 2) / 2; // (720 - 320*2)/2 = 40
+ } else if (_useCJKMode && m == 2) {
+ pitch *= m;
+ x *= m;
+ y *= m;
+ width *= m;
+ height *= m;
} else {
if (_renderMode == Common::kRenderCGA)
ditherCGA(_compositeBuf, width, x, y, width, height);
@@ -721,6 +743,25 @@ void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *wid
*height = dsty - *y;
}
+void ScummEngine::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) {
+ byte *dstL1 = dst;
+ byte *dstL2 = dst + dstPitch;
+
+ int dstAdd = dstPitch * 2 - w * 2;
+ int srcAdd = srcPitch - w;
+
+ while (h--) {
+ for (int x = 0; x < w; ++x, dstL1 += 2, dstL2 += 2) {
+ uint16 col = *src++;
+ col |= col << 8;
+ *(uint16*)(dstL1) = col;
+ *(uint16*)(dstL2) = col;
+ }
+ dstL1 += dstAdd; dstL2 += dstAdd;
+ src += srcAdd;
+ }
+}
+
#pragma mark -
#pragma mark --- Background buffers & charset mask ---
@@ -1117,8 +1158,8 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
error("can only copy bg to main window");
blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height);
if (_charset->_hasMask) {
- byte *mask = (byte *)_textSurface.getBasePtr(x, y - _screenTop);
- fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height);
+ byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier);
+ fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
}
} else if (_game.heversion >= 71) {
// Flags are used for different methods in HE games
@@ -3362,7 +3403,17 @@ void ScummEngine::dissolveEffect(int width, int height) {
for (i = 0; i < w * h; i++) {
x = offsets[i] % vs->pitch;
y = offsets[i] / vs->pitch;
- _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height);
+
+ if (_useCJKMode && _textSurfaceMultiplier == 2) {
+ int m = _textSurfaceMultiplier;
+ byte *dst = _fmtownsBuf + x * m + y * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, vs->getPixels(x, y), vs->pitch, width, height);
+
+ _system->copyRectToScreen(dst, _screenWidth * m, x * m, (y + vs->topline) * m, width * m, height * m);
+ } else {
+ _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height);
+ }
+
if (++blits >= blits_before_refresh) {
blits = 0;
@@ -3391,16 +3442,30 @@ void ScummEngine::scrollEffect(int dir) {
step = (step * delay) / kScrolltime;
+ byte *src;
+ int m = _textSurfaceMultiplier;
+ int vsPitch = vs->pitch;
+
switch (dir) {
case 0:
//up
y = 1 + step;
while (y < vs->h) {
moveScreen(0, -step, vs->h);
- _system->copyRectToScreen(vs->getPixels(0, y - step),
- vs->pitch,
- 0, vs->h - step,
- vs->w, step);
+
+ src = vs->getPixels(0, y - step);
+ if (_useCJKMode && m == 2) {
+ int x1 = 0, y1 = vs->h - step;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+
+ _system->copyRectToScreen(src,
+ vsPitch,
+ 0 * m, (vs->h - step) * m,
+ vs->w * m, step * m);
_system->updateScreen();
waitForTimer(delay);
@@ -3412,10 +3477,18 @@ void ScummEngine::scrollEffect(int dir) {
y = 1 + step;
while (y < vs->h) {
moveScreen(0, step, vs->h);
- _system->copyRectToScreen(vs->getPixels(0, vs->h - y),
- vs->pitch,
+ src = vs->getPixels(0, vs->h - y);
+ if (_useCJKMode && m == 2) {
+ int x1 = 0, y1 = 0;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+ _system->copyRectToScreen(src,
+ vsPitch,
0, 0,
- vs->w, step);
+ vs->w * m, step * m);
_system->updateScreen();
waitForTimer(delay);
@@ -3427,10 +3500,18 @@ void ScummEngine::scrollEffect(int dir) {
x = 1 + step;
while (x < vs->w) {
moveScreen(-step, 0, vs->h);
- _system->copyRectToScreen(vs->getPixels(x - step, 0),
- vs->pitch,
- vs->w - step, 0,
- step, vs->h);
+ src = vs->getPixels(x - step, 0);
+ if (_useCJKMode && m == 2) {
+ int x1 = vs->w - step, y1 = 0;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+ _system->copyRectToScreen(src,
+ vsPitch,
+ (vs->w - step) * m, 0,
+ step * m, vs->h * m);
_system->updateScreen();
waitForTimer(delay);
@@ -3442,8 +3523,16 @@ void ScummEngine::scrollEffect(int dir) {
x = 1 + step;
while (x < vs->w) {
moveScreen(step, 0, vs->h);
- _system->copyRectToScreen(vs->getPixels(vs->w - x, 0),
- vs->pitch,
+ src = vs->getPixels(vs->w - x, 0);
+ if (_useCJKMode && m == 2) {
+ int x1 = 0, y1 = 0;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+ _system->copyRectToScreen(src,
+ vsPitch,
0, 0,
step, vs->h);
_system->updateScreen();
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index ffcb7d03f2..6647e9fe8d 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -162,8 +162,11 @@ void ScummEngine::parseEvents() {
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
_mouse.x -= (Common::kHercW - _screenWidth * 2) / 2;
- _mouse.x /= 2;
+ _mouse.x >>= 1;
_mouse.y = _mouse.y * 4 / 7;
+ } else if (_useCJKMode && _textSurfaceMultiplier == 2) {
+ _mouse.x >>= 1;
+ _mouse.y >>= 1;
}
break;
case Common::EVENT_LBUTTONUP:
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index f29f1c7970..e54060c9e1 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -587,6 +587,7 @@ ScummEngine::~ScummEngine() {
free(_compositeBuf);
free(_herculesBuf);
+ free(_fmtownsBuf);
delete _debugger;
@@ -1078,12 +1079,19 @@ int ScummEngine::init() {
_fileHandle = new ScummFile();
}
+ // Load CJK font, if present
+ // Load it earlier so _useCJKMode variable could be set
+ loadCJKFont();
+
// Initialize backend
_system->beginGFXTransaction();
bool defaultTo1XScaler = false;
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
_system->initSize(Common::kHercW, Common::kHercH);
defaultTo1XScaler = true;
+ } else if (_useCJKMode) {
+ _system->initSize(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier);
+ defaultTo1XScaler = true;
} else {
_system->initSize(_screenWidth, _screenHeight);
defaultTo1XScaler = (_screenWidth > 320);
@@ -1135,14 +1143,11 @@ void ScummEngine::setupScumm() {
// Load localization data, if present
loadLanguageBundle();
- // Load CJK font, if present
- loadCJKFont();
-
// Create the charset renderer
setupCharsetRenderer();
// Create and clear the text surface
- _textSurface.create(_screenWidth, _screenHeight, 1);
+ _textSurface.create(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 1);
clearTextSurface();
// Create the costume renderer
@@ -1210,6 +1215,13 @@ void ScummEngine::setupScumm() {
#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
Graphics::initfonts();
#endif
+
+ _fmtownsBuf = 0;
+ if (_game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) {
+ _fmtownsBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier);
+ }
+
+ _compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier);
}
#ifndef DISABLE_SCUMM_7_8
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 438797a018..18c2275029 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1026,10 +1026,12 @@ protected:
// Screen rendering
byte *_compositeBuf;
byte *_herculesBuf;
+ byte *_fmtownsBuf;
virtual void drawDirtyScreenParts();
void updateDirtyScreen(VirtScreenNumber slot);
void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b);
void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const;
+ void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
public:
VirtScreen *findVirtScreen(int y);
@@ -1151,6 +1153,7 @@ public:
* drawStripToScreen() composits it over the game graphics.
*/
Graphics::Surface _textSurface;
+ int _textSurfaceMultiplier;
protected:
byte _charsetColor;