AGOS: (ELVIRA/PC98/Jp) - add Japanese font drawing

- Add dual layer graphics display to display the Japanese characters in their proper (double) resolution on top of the graphics. The original actually uses text mode.
- Adapt mouse handling to dual layer code.
- For consistency I got rid of all direct calls to _system->lockScreen() and _system->unlockScreen(), even in the sub engines that aren't affected. I find it easier to debug and to maintain this way.
This commit is contained in:
athrxx 2021-01-14 00:32:41 +01:00
parent bb8c70f865
commit 574133086d
18 changed files with 318 additions and 96 deletions

View file

@ -37,6 +37,7 @@
#include "backends/audiocd/audiocd.h"
#include "graphics/surface.h"
#include "graphics/sjis.h"
#include "audio/mididrv.h"
@ -140,7 +141,23 @@ AGOSEngine_Elvira2::AGOSEngine_Elvira2(OSystem *system, const AGOSGameDescriptio
}
AGOSEngine_Elvira1::AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescription *gd)
: AGOSEngine(system, gd) {
: AGOSEngine(system, gd), _sjisCurChar(0), _sjisFont(0) {
}
AGOSEngine_Elvira1::~AGOSEngine_Elvira1() {
delete _sjisFont;
}
Common::Error AGOSEngine_Elvira1::init() {
Common::Error ret = AGOSEngine::init();
if (ret.getCode() == Common::kNoError && getPlatform() == Common::kPlatformPC98) {
_sjisFont = Graphics::FontSJIS::createFont(Common::kPlatformPC98);
if (_sjisFont)
_sjisFont->toggleFatPrint(true);
else
error("AGOSEngine_Elvira1::init(): Failed to load SJIS font.");
}
return ret;
}
AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
@ -541,11 +558,12 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
_moveXMax = 0;
_moveYMax = 0;
_forceAscii = false;
_vc10BasePtrOld = 0;
memcpy (_hebrewCharWidths,
"\x5\x5\x4\x6\x5\x3\x4\x5\x6\x3\x5\x5\x4\x6\x5\x3\x4\x6\x5\x6\x6\x6\x5\x5\x5\x6\x5\x6\x6\x6\x6\x6", 32);
const Common::FSNode gameDataDir(ConfMan.get("path"));
// Add default file directories for Acorn version of
@ -576,7 +594,15 @@ Common::Error AGOSEngine::init() {
_screenHeight = 200;
}
initGraphics(_screenWidth, _screenHeight);
_internalWidth = _screenWidth;
_internalHeight = _screenHeight;
if (getPlatform() == Common::kPlatformPC98) {
_internalWidth <<= 1;
_internalHeight <<= 1;
}
initGraphics(_internalWidth, _internalHeight);
_midi = new MidiPlayer();
@ -601,11 +627,11 @@ Common::Error AGOSEngine::init() {
_backGroundBuf = new Graphics::Surface();
_backGroundBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
if (getGameType() == GType_FF || getGameType() == GType_PP) {
if (getGameType() == GType_FF || getGameType() == GType_PP || (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformPC98)) {
_backBuf = new Graphics::Surface();
_backBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
_scaleBuf = new Graphics::Surface();
_scaleBuf->create(_screenWidth, _screenHeight, Graphics::PixelFormat::createFormatCLUT8());
_scaleBuf->create(_internalWidth, _internalHeight, Graphics::PixelFormat::createFormatCLUT8());
}
if (getGameType() == GType_SIMON2) {

View file

@ -58,6 +58,7 @@ class SeekableReadStream;
namespace Graphics {
struct Surface;
class FontSJIS;
}
namespace AGOS {
@ -202,7 +203,7 @@ protected:
friend class Debugger;
// Engine APIs
Common::Error init();
virtual Common::Error init();
virtual Common::Error go();
Common::Error run() override {
Common::Error err;
@ -349,6 +350,7 @@ protected:
uint16 _scrollWidth, _scrollHeight;
const byte *_scrollImage;
byte _boxStarHeight;
bool _forceAscii;
SubroutineLine *_classLine;
int16 _classMask, _classMode1, _classMode2;
@ -445,6 +447,7 @@ protected:
volatile uint16 _fastFadeInFlag;
uint16 _screenWidth, _screenHeight;
uint16 _internalWidth, _internalHeight;
uint16 _noOverWrite;
bool _rejectBlock;
@ -1156,6 +1159,10 @@ protected:
void horizontalScroll(VC10_state *state);
void verticalScroll(VC10_state *state);
Graphics::Surface *getBackendSurface() const;
void updateBackendSurface(Common::Rect *area = 0) const;
virtual void clearHiResTextLayer() {}
int vcReadVarOrWord();
uint vcReadNextWord(bool forceLERead = false);
uint vcReadNextByte();
@ -1552,7 +1559,8 @@ protected:
class AGOSEngine_Elvira1 : public AGOSEngine {
public:
AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescription *gd);
//~AGOSEngine_Elvira1();
~AGOSEngine_Elvira1() override;
Common::Error init() override;
void setupGame() override;
void setupOpcodes() override;
@ -1626,8 +1634,15 @@ protected:
const OpcodeEntryElvira1 *_opcodesElvira1;
void drawIcon(WindowBlock *window, uint icon, uint x, uint y) override;
void windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) override;
void addHiResTextDirtyRect(Common::Rect rect);
void clearHiResTextLayer() override;
Common::String genSaveName(int slot) const override;
Graphics::FontSJIS *_sjisFont;
Common::Array<Common::Rect> _sjisTextFields;
uint16 _sjisCurChar;
};
class AGOSEngine_Elvira2 : public AGOSEngine_Elvira1 {

View file

@ -344,9 +344,9 @@ void MoviePlayerDXA::handleNextFrame() {
}
bool MoviePlayerDXA::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
Graphics::Surface *screen = _vm->getBackendSurface();
copyFrameToBuffer((byte *)screen->getPixels(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
_vm->updateBackendSurface();
uint32 soundTime = _mixer->getSoundElapsedTime(_bgSound);
uint32 nextFrameStartTime = ((Video::VideoDecoder::VideoTrack *)getTrack(0))->getNextFrameStartTime();
@ -495,9 +495,9 @@ void MoviePlayerSMK::nextFrame() {
}
bool MoviePlayerSMK::processFrame() {
Graphics::Surface *screen = _vm->_system->lockScreen();
Graphics::Surface *screen = _vm->getBackendSurface();
copyFrameToBuffer((byte *)screen->getPixels(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch);
_vm->_system->unlockScreen();
_vm->updateBackendSurface();
uint32 waitTime = getTimeToNextFrame();

View file

@ -28,6 +28,7 @@
#include "agos/intern.h"
#include "graphics/surface.h"
#include "graphics/sjis.h"
namespace AGOS {
@ -2921,7 +2922,7 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
dst = (byte *)screen->getPixels();
@ -3019,9 +3020,85 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
dst += dstPitch;
} while (--h);
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
void AGOSEngine_Elvira1::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
if (_language != Common::JA_JPN || _forceAscii) {
AGOSEngine::windowDrawChar(window, x, y, chr);
return;
}
if (_sjisCurChar) {
_sjisCurChar |= (chr << 8);
} else {
_sjisCurChar = chr;
if ((chr >= 0x80 && chr < 0xA0) || chr >= 0xE0)
return;
}
_videoLockOut |= 0x8000;
x = x & ~7;
y = (y + 4) & ~3;
// PC-98 uses text mode black (hardware colors, not related to the graphics mode palette
// colors) for font drawing, so I just set one of the unused black colors (color 33) here.
_sjisFont->drawChar(*_scaleBuf, _sjisCurChar, x << 1, y << 1, 33, 0);
Common::Rect dirtyRect(x, y, x + (_sjisFont->getCharWidth(_sjisCurChar) >> 1), y + (_sjisFont->getFontHeight() >> 1));
addHiResTextDirtyRect(dirtyRect);
updateBackendSurface(&dirtyRect);
_sjisCurChar = 0;
_videoLockOut &= ~0x8000;
}
void AGOSEngine_Elvira1::addHiResTextDirtyRect(Common::Rect rect) {
rect.left >>= 1;
rect.top <<= 1;
rect.right >>= 1;
rect.bottom <<= 1;
for (Common::Array<Common::Rect>::iterator i = _sjisTextFields.begin(); i != _sjisTextFields.end(); ++i) {
// Merge rects if it makes sense, but only once.
if (rect.left <= i->right && rect.right >= i->left && rect.top <= i->bottom && rect.bottom >= i->top) {
i->left = MIN<int16>(i->left, rect.left);
i->top = MIN<int16>(i->top, rect.top);
i->right = MAX<int16>(i->right, rect.right);
i->bottom = MAX<int16>(i->bottom, rect.bottom);
return;
}
}
_sjisTextFields.push_back(rect);
}
void AGOSEngine_Elvira1::clearHiResTextLayer() {
if (getPlatform() != Common::kPlatformPC98)
return;
void *p = _scaleBuf->getPixels();
assert(p);
if (_sjisTextFields.size() < 10) {
for (Common::Array<Common::Rect>::iterator i = _sjisTextFields.begin(); i != _sjisTextFields.end(); ++i) {
uint16 w = i->width();
uint16 ptch = _scaleBuf->pitch >> 2;
uint32 *dst = (uint32*)p + i->top * ptch + i->left;
for (uint32 *end = dst + i->height() * ptch; dst < end; dst += ptch)
Common::fill<uint32*, uint32>(dst, &dst[w], 0);
i->left <<= 1;
i->top >>= 1;
i->right <<= 1;
i->bottom >>= 1;
updateBackendSurface(i);
}
} else {
memset(p, 0, _scaleBuf->w * _scaleBuf->h);
updateBackendSurface();
}
_sjisTextFields.clear();
}
} // End of namespace AGOS

View file

@ -148,6 +148,11 @@ void AGOSEngine::justifyOutPut(byte chr) {
_printCharPixelCount = 0;
doOutput(&chr, 1);
clsCheck(_textWindow);
} else if (getLanguage() == Common::JA_JPN) {
// Japanese has no word wrapping
_lettersToPrintBuf[0] = chr;
_lettersToPrintBuf[1] = '\0';
doOutput(_lettersToPrintBuf, 1);
} else if (chr == 0 || chr == ' ' || chr == 10) {
bool fit;
@ -215,6 +220,7 @@ void AGOSEngine_PN::windowPutChar(WindowBlock *window, byte c, byte b) {
void AGOSEngine::windowPutChar(WindowBlock *window, byte c, byte b) {
byte width = 6;
byte textColumnWidth = 8;
if (c == 12) {
clearWindow(window);
@ -256,8 +262,9 @@ void AGOSEngine::windowPutChar(WindowBlock *window, byte c, byte b) {
return;
}
// Ignore invalid characters
if (c - 32 > 98)
if (_language == Common::JA_JPN)
textColumnWidth = width = 4;
else if (c - 32 > 98) // Ignore invalid characters
return;
if (window->textLength == window->textMaxLength) {
@ -278,16 +285,15 @@ void AGOSEngine::windowPutChar(WindowBlock *window, byte c, byte b) {
windowDrawChar(window, (window->width + window->x - window->textColumn) * 8, window->textRow * 8 + window->y, c);
window->textLength++;
} else {
windowDrawChar(window, (window->textColumn + window->x) * 8, window->textRow * 8 + window->y, c);
windowDrawChar(window, window->x * 8 + window->textColumn * textColumnWidth, window->textRow * 8 + window->y, c);
window->textLength++;
window->textColumnOffset += 6;
window->textColumnOffset += width;
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
if (c == 'i' || c == 'l')
window->textColumnOffset -= 2;
}
if (window->textColumnOffset >= 8) {
window->textColumnOffset -= 8;
if (window->textColumnOffset >= textColumnWidth) {
window->textColumnOffset -= textColumnWidth;
window->textColumn++;
}
}
@ -354,24 +360,37 @@ void AGOSEngine::windowScroll(WindowBlock *window) {
_videoLockOut |= 0x8000;
if (window->height != 1) {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *src, *dst;
uint16 w, h;
uint16 w1, h1, w2, h2;
w = window->width * 8;
h = (window->height -1) * 8;
w1 = w2 = window->width * 8;
h1 = h2 = (window->height -1) * 8;
dst = (byte *)screen->getBasePtr(window->x * 8, window->y);
src = dst + 8 * screen->pitch;
do {
memcpy(dst, src, w);
memcpy(dst, src, w1);
src += screen->pitch;
dst += screen->pitch;
} while (--h);
} while (--h1);
_system->unlockScreen();
if (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) {
w1 = w2 << 1;
h1 = h2 << 1;
dst = (byte *)_scaleBuf->getBasePtr(window->x * 16, window->y * 2);
src = dst + 16 * screen->pitch;
do {
memcpy(dst, src, w1);
src += screen->pitch;
dst += screen->pitch;
} while (--h1);
}
Common::Rect dirtyRect(window->x * 8, window->y, window->x * 8 + w2, window->y + h2);
updateBackendSurface(&dirtyRect);
}
colorBlock(window, window->x * 8, (window->height - 1) * 8 + window->y, window->width * 8, 8);

View file

@ -559,6 +559,10 @@ void AGOSEngine::handleMouseMoved() {
_needHitAreaRecalc++;
}
} else if (getGameType() == GType_ELVIRA1) {
if (getPlatform() == Common::kPlatformPC98) {
_mouse.x >>= 1;
_mouse.y >>= 1;
}
if (_mouseCursor != _variableArray[438]) {
_mouseCursor = _variableArray[438];
_needHitAreaRecalc++;
@ -784,6 +788,12 @@ static const byte mouseCursorPalette[] = {
void AGOSEngine::initMouse() {
_maxCursorWidth = 16;
_maxCursorHeight = 16;
if (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) {
_maxCursorWidth <<= 1;
_maxCursorHeight <<= 1;
}
_mouseData = (byte *)calloc(_maxCursorWidth * _maxCursorHeight, 1);
memset(_mouseData, 0xFF, _maxCursorWidth * _maxCursorHeight);
@ -864,7 +874,21 @@ void AGOSEngine::drawMousePointer() {
src += 2;
}
CursorMan.replaceCursor(_mouseData, 16, 16, 0, 0, 0xFF);
if (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) {
// Simple 2x upscaling for the cursor in dual layer hi-res mode.
uint8 ptch = 16;
uint16 *dst1 = &((uint16*)_mouseData)[16 * 16 * 2 - 1];
uint16 *dst2 = dst1 - ptch;
for (const byte *src = &_mouseData[16 * 16 - 1]; src >= _mouseData; --src) {
*dst1-- = *dst2-- = (*src << 8) | *src;
if (!(ptch = (ptch - 1) % 16)) {
dst1 -= 16;
dst2 -= 16;
}
}
}
CursorMan.replaceCursor(_mouseData, _maxCursorWidth, _maxCursorHeight, 0, 0, 0xFF);
}
}

View file

@ -536,7 +536,7 @@ void AGOSEngine::displayBoxStars() {
ha = _hitAreas;
count = ARRAYSIZE(_hitAreas);
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
do {
if (ha->id != 0 && ha->flags & kBFBoxInUse && !(ha->flags & kBFBoxDead)) {
@ -604,7 +604,7 @@ void AGOSEngine::displayBoxStars() {
}
} while (ha++, --count);
_system->unlockScreen();
updateBackendSurface();
delay(100);
@ -724,7 +724,7 @@ void AGOSEngine::fillBackFromBackGround(uint16 height, uint16 width) {
}
void AGOSEngine::fillBackFromFront() {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *src = (byte *)screen->getPixels();
byte *dst = getBackBuf();
@ -733,7 +733,7 @@ void AGOSEngine::fillBackFromFront() {
src += screen->pitch;
dst += _backBuf->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine::fillBackGroundFromBack() {
@ -747,7 +747,7 @@ void AGOSEngine::fillBackGroundFromBack() {
}
void AGOSEngine::fillBackGroundFromFront() {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *src = (byte *)screen->getPixels();
byte *dst = getBackGround();
@ -756,7 +756,7 @@ void AGOSEngine::fillBackGroundFromFront() {
src += screen->pitch;
dst += _backGroundBuf->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine::setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height) {
@ -782,7 +782,7 @@ void AGOSEngine::displayScreen() {
}
}
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
if (getGameType() == GType_PP || getGameType() == GType_FF) {
byte *src = getBackBuf();
byte *dst = (byte *)screen->getPixels();
@ -841,7 +841,7 @@ void AGOSEngine::displayScreen() {
}
}
_system->unlockScreen();
updateBackendSurface();
if (getGameType() == GType_FF && _scrollFlag) {
scrollScreen();

View file

@ -365,7 +365,7 @@ static const byte _image4[32] = {
void AGOSEngine::drawStuff(const byte *src, uint xoffs) {
const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 135;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getBasePtr(xoffs, y);
for (uint h = 0; h < 6; h++) {
@ -374,7 +374,7 @@ void AGOSEngine::drawStuff(const byte *src, uint xoffs) {
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine::playerDamageEvent(VgaTimerEntry * vte, uint dx) {

View file

@ -640,7 +640,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
if (!drawImage_clip(state))
return;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
if (getFeatures() & GF_32COLOR)
state->palette = 0xC0;
@ -738,7 +738,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
drawVertImage(state);
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine::drawBackGroundImage(VC10_state *state) {
@ -857,7 +857,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
if (!drawImage_clip(state))
return;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
uint16 xoffs = 0, yoffs = 0;
if (getGameType() == GType_WW) {
@ -951,7 +951,7 @@ void AGOSEngine::drawImage(VC10_state *state) {
drawVertImage(state);
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine::horizontalScroll(VC10_state *state) {
@ -1023,6 +1023,61 @@ void AGOSEngine::verticalScroll(VC10_state *state) {
}
}
Graphics::Surface *AGOSEngine::getBackendSurface() const {
return (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) ? _backBuf : _system->lockScreen();
}
void AGOSEngine::updateBackendSurface(Common::Rect *area) const {
if (getGameId() == GID_ELVIRA1 && getPlatform() == Common::kPlatformPC98) {
int x = 0;
int y = 0;
int w = _screenWidth;
int h = _screenHeight;
if (area) {
x = area->left;
y = area->top;
w = area->width();
h = area->height();
}
Graphics::Surface *screen = _system->lockScreen();
int src0Pitch = _backBuf->pitch;
int src1Pitch = _scaleBuf->pitch;
int dst1Pitch = screen->pitch;
const byte *src00 = (byte*)_backBuf->getBasePtr(x, y);
const byte *src10 = (byte*)_scaleBuf->getBasePtr(x << 1, y << 1);
const byte *src11 = src10 + src1Pitch;
byte *dst10 = (byte*)screen->getBasePtr(x << 1, y << 1);
byte *dst11 = dst10 + dst1Pitch;
src0Pitch -= w;
src1Pitch += (src1Pitch - (w << 1));
dst1Pitch += (dst1Pitch - (w << 1));
while (h--) {
for (int i = 0; i < w; ++i) {
uint8 v0 = *src00++;
uint8 v1 = *src10++;
*dst10++ = v1 ? v1 : v0;
v1 = *src10++;
*dst10++ = v1 ? v1 : v0;
v1 = *src11++;
*dst11++ = v1 ? v1 : v0;
v1 = *src11++;
*dst11++ = v1 ? v1 : v0;
}
src00 += src0Pitch;
src10 += src1Pitch;
src11 += src1Pitch;
dst10 += dst1Pitch;
dst11 += dst1Pitch;
}
}
_system->unlockScreen();
}
void AGOSEngine::paletteFadeOut(byte *palPtr, uint num, uint size) {
byte *p = palPtr;
@ -1372,7 +1427,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
uint width = _videoWindows[updateWindow * 4 + 2] * 16;
uint height = _videoWindows[updateWindow * 4 + 3];
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)_backGroundBuf->getBasePtr(xoffs, yoffs);
byte *src = 0;
uint srcWidth = 0;
@ -1389,7 +1444,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x20;
return;
}
@ -1404,7 +1459,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x20;
return;
}
@ -1416,7 +1471,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x20;
return;
}
@ -1428,7 +1483,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
src = (byte *)screen->getBasePtr(xoffs, yoffs);
srcWidth = screen->pitch;
} else {
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x20;
return;
}
@ -1474,7 +1529,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas
}
}
_system->unlockScreen();
updateBackendSurface();
}
_videoLockOut &= ~0x20;
@ -1485,7 +1540,7 @@ void AGOSEngine::drawEdging() {
byte *dst;
uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getBasePtr(0, 136);
uint8 len = 52;
@ -1499,7 +1554,7 @@ void AGOSEngine::drawEdging() {
dst = (byte *)screen->getBasePtr(0, 187);
memset(dst, color, _screenWidth);
_system->unlockScreen();
updateBackendSurface();
}
} // End of namespace AGOS

View file

@ -202,7 +202,7 @@ void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y)
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getPixels();
dst += 110;
@ -217,7 +217,7 @@ void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y)
src += READ_LE_UINT16(src + icon * 4 + 2);
decompressIcon(dst, src, 20, 10, 208, screen->pitch);
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -228,7 +228,7 @@ void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y)
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
@ -245,7 +245,7 @@ void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y)
decompressIcon(dst, src, 24, 12, 224, screen->pitch);
}
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -256,7 +256,7 @@ void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
@ -273,7 +273,7 @@ void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint
decompressIcon(dst, src, 24, 10, color, screen->pitch);
}
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -284,7 +284,7 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
@ -301,7 +301,7 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y
decompressIcon(dst, src, 24, 12, color, screen->pitch);
}
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -312,7 +312,7 @@ void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getPixels();
dst += (x + window->x) * 8;
@ -328,7 +328,7 @@ void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y
decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch, false);
}
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -339,7 +339,7 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getBasePtr(x * 8, y);
src = _iconFilePtr + icon * 146;
@ -365,7 +365,7 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
}
}
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -951,7 +951,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) {
src = _arrowImage;
}
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getBasePtr(x * 8, y);
for (h = 0; h < 19; h++) {
@ -964,7 +964,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) {
dst+= screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine_Simon1::removeArrows(WindowBlock *window, uint num) {
@ -1042,7 +1042,7 @@ static const byte hitBarData[12 * 7] = {
// Personal Nightmare specific
void AGOSEngine_PN::drawIconHitBar() {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getBasePtr(6 * 8, 3);
const byte *src = hitBarData;
uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15;
@ -1061,7 +1061,7 @@ void AGOSEngine_PN::drawIconHitBar() {
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine_PN::iconPage() {

View file

@ -163,7 +163,7 @@ void AGOSEngine::unlightMenuStrip() {
mouseOff();
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
src = (byte *)screen->getBasePtr(272, 8);
w = 48;
h = 82;
@ -179,7 +179,7 @@ void AGOSEngine::unlightMenuStrip() {
for (i = 120; i != 130; i++)
disableBox(i);
_system->unlockScreen();
updateBackendSurface();
mouseOn();
}
@ -191,7 +191,7 @@ void AGOSEngine::lightMenuBox(uint hitarea) {
mouseOff();
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
src = (byte *)screen->getBasePtr(ha->x, ha->y);
w = ha->width;
h = ha->height;
@ -204,7 +204,7 @@ void AGOSEngine::lightMenuBox(uint hitarea) {
src += screen->pitch;
} while (--h);
_system->unlockScreen();
updateBackendSurface();
mouseOn();
}

View file

@ -1166,6 +1166,7 @@ void AGOSEngine::printStats() {
window->flags = 1;
mouseOff();
_forceAscii = true;
// Strength
val = _variableArray[0];
@ -1215,6 +1216,7 @@ void AGOSEngine::printStats() {
val = 99;
writeChar(window, 36, 133, 4, val);
_forceAscii = false;
mouseOn();
}

View file

@ -985,7 +985,7 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) {
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
src = (byte *)screen->getBasePtr(ha->x, ha->y);
// WORKAROUND: Hitareas for saved game names aren't adjusted for scrolling locations
@ -1041,7 +1041,7 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) {
src += screen->pitch;
} while (--h);
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}

View file

@ -1182,7 +1182,7 @@ void AGOSEngine::vc31_setWindow() {
void AGOSEngine::vc32_saveScreen() {
if (getGameType() == GType_PN) {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = getBackGround();
byte *src = (byte *)screen->getPixels();
for (int i = 0; i < _screenHeight; i++) {
@ -1190,7 +1190,7 @@ void AGOSEngine::vc32_saveScreen() {
dst += _backGroundBuf->pitch;
src += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
} else {
uint16 xoffs = _videoWindows[4 * 4 + 0] * 16;
uint16 yoffs = _videoWindows[4 * 4 + 1];
@ -1251,13 +1251,14 @@ void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) {
}
if (getGameType() == GType_ELVIRA1 && num == 3) {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getPixels();
for (int i = 0; i < _screenHeight; i++) {
memset(dst, color, _screenWidth);
dst += screen->pitch;
}
_system->unlockScreen();
clearHiResTextLayer();
updateBackendSurface();
} else {
const uint16 *vlut = &_videoWindows[num * 4];
uint16 xoffs = (vlut[0] - _videoWindows[16]) * 16;

View file

@ -89,7 +89,7 @@ void AGOSEngine::vc45_setWindowPalette() {
dst += width * 2;
}
} else {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getBasePtr(vlut[0] * 16, vlut[1]);
if (getGameType() == GType_ELVIRA2 && num == 7) {
@ -107,7 +107,7 @@ void AGOSEngine::vc45_setWindowPalette() {
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
}
@ -223,7 +223,7 @@ void AGOSEngine::vc53_dissolveIn() {
uint16 count = dissolveCheck * 2;
while (count--) {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dstPtr = (byte *)screen->getBasePtr(x, y);
yoffs = _rnd.getRandomNumber(dissolveY);
@ -264,7 +264,7 @@ void AGOSEngine::vc53_dissolveIn() {
*dst &= color;
*dst |= *src & 0xF;
_system->unlockScreen();
updateBackendSurface();
dissolveCount--;
if (!dissolveCount) {
@ -296,7 +296,7 @@ void AGOSEngine::vc54_dissolveOut() {
uint16 count = dissolveCheck * 2;
while (count--) {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dstPtr = (byte *)screen->getBasePtr(x, y);
color |= dstPtr[0] & 0xF0;
@ -318,7 +318,7 @@ void AGOSEngine::vc54_dissolveOut() {
dst += xoffs;
*dst = color;
_system->unlockScreen();
updateBackendSurface();
dissolveCount--;
if (!dissolveCount) {
@ -378,7 +378,7 @@ void AGOSEngine::fullFade() {
}
void AGOSEngine::vc56_fullScreen() {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getPixels();
byte *src = _curVgaFile2 + 800;
@ -387,7 +387,7 @@ void AGOSEngine::vc56_fullScreen() {
src += 320;
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
fullFade();
}

View file

@ -154,7 +154,7 @@ void AGOSEngine::vc48_specialEffect() {
if (getPlatform() == Common::kPlatformDOS) {
if (num == 1) {
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getPixels();
for (uint h = 0; h < _screenHeight; h++) {
@ -164,7 +164,7 @@ void AGOSEngine::vc48_specialEffect() {
}
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
} else if (num == 2) {
const char *str = "There are gurgling noises from the sink.";
for (; *str; str++)
@ -204,13 +204,13 @@ void AGOSEngine_PN::clearVideoWindow(uint16 num, uint16 color) {
uint16 xoffs = vlut[0] * 16;
uint16 yoffs = vlut[1];
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getBasePtr(xoffs, yoffs);
for (uint h = 0; h < vlut[3]; h++) {
memset(dst, color, vlut[2] * 16);
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
} // End of namespace AGOS

View file

@ -142,7 +142,7 @@ void AGOSEngine::vc61() {
byte *src, *dst, *dstPtr;
uint h, tmp;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dstPtr = (byte *)screen->getPixels();
if (a == 6) {
@ -175,7 +175,7 @@ void AGOSEngine::vc61() {
}
if (a != 6) {
_system->unlockScreen();
updateBackendSurface();
return;
}
@ -189,7 +189,7 @@ void AGOSEngine::vc61() {
dst += screen->pitch;
}
_system->unlockScreen();
updateBackendSurface();
if (a == 6)
fullFade();

View file

@ -65,11 +65,13 @@ WindowBlock *AGOSEngine::openWindow(uint x, uint y, uint w, uint h, uint flags,
window->textRow = 0;
window->scrollY = 0;
// Characters are 6 pixels
// Characters are 6 pixels (except Japanese: when downscaled, 1-byte characters are 4 pixels, 2-byte characters are 8 pixels)
if (getGameType() == GType_ELVIRA2)
window->textMaxLength = (window->width * 8 - 4) / 6;
else if (getGameType() == GType_PN)
window->textMaxLength = window->width * 8 / 6 + 1;
else if (getGameType() == GType_ELVIRA1 && getPlatform() == Common::kPlatformPC98)
window->textMaxLength = window->width << 1;
else
window->textMaxLength = window->width * 8 / 6;
@ -107,6 +109,7 @@ void AGOSEngine::closeWindow(uint a) {
}
void AGOSEngine::clearWindow(WindowBlock *window) {
clearHiResTextLayer();
if (window->flags & 0x10)
restoreWindow(window);
else
@ -169,7 +172,7 @@ void AGOSEngine::colorWindow(WindowBlock *window) {
void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, uint16 h) {
_videoLockOut |= 0x8000;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
byte *dst = (byte *)screen->getBasePtr(x, y);
uint8 color = window->fillColor;
@ -181,7 +184,7 @@ void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, u
dst += screen->pitch;
} while (--h);
_system->unlockScreen();
updateBackendSurface();
_videoLockOut &= ~0x8000;
}
@ -231,7 +234,7 @@ void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) {
byte *dst, *src;
uint i;
Graphics::Surface *screen = _system->lockScreen();
Graphics::Surface *screen = getBackendSurface();
dst = (byte *)screen->getPixels();
src = getBackGround();
@ -250,7 +253,7 @@ void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) {
src += _backGroundBuf->pitch;
}
_system->unlockScreen();
updateBackendSurface();
}
void AGOSEngine::setTextColor(uint color) {