Imrproved support for Elvira 1/2 and Waxworks.

svn-id: r26792
This commit is contained in:
Travis Howell 2007-05-09 15:36:05 +00:00
parent 85082dc8a0
commit 20bf83a2ce
18 changed files with 1028 additions and 444 deletions

View File

@ -199,6 +199,9 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_copyPartialMode = 0;
_fastMode = 0;
_useBackGround = 0;
_oldDrawMethod = 0;
_backFlag = 0;
_debugMode = 0;
_startMainScript = false;
@ -291,6 +294,7 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_leftButtonDown = 0;
_rightButtonDown = 0;
_clickOnly = 0;
_noRightClick = false;
_leftButton = 0;
@ -477,6 +481,17 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_backBuf = 0;
_scaleBuf = 0;
_window3Flag = 0;
_window4Flag = 0;
_window6Flag = 0;
_window4BackScn = 0;
_window6BackScn = 0;
_moveXMin = 0;
_moveYMin = 0;
_moveXMax = 0;
_moveYMax = 0;
_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);
@ -511,6 +526,12 @@ int AGOSEngine::init() {
return -1;
}
// TODO: Enable for Simon the Sorcerer 1/2 when complete
if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2 ||
getGameType() == GType_ELVIRA1) {
_oldDrawMethod = true;
}
if (getGameId() == GID_DIMP) {
_screenWidth = 496;
_screenHeight = 400;
@ -562,9 +583,25 @@ int AGOSEngine::init() {
// allocate buffers
_backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
_frontBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
_backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
if (getGameType() == GType_FF || getGameType() == GType_PP)
if (getGameType() == GType_FF || getGameType() == GType_PP) {
_scaleBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
}
if (!_oldDrawMethod) {
_backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1);
} else {
if (getGameType() == GType_SIMON2) {
_window4BackScn = (byte *)calloc(_screenWidth * _screenHeight, 1);
} else if (getGameType() == GType_SIMON1) {
_window4BackScn = (byte *)calloc(_screenWidth * 134, 1);
} else if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2) {
_window4BackScn = (byte *)calloc(224 * 127, 1);
} else if (getGameType() == GType_ELVIRA1) {
_window4BackScn = (byte *)calloc(224 * 127, 1);
_window6BackScn = (byte *)calloc(48 * 80, 1);
}
}
setupGame();
@ -851,6 +888,9 @@ AGOSEngine::~AGOSEngine() {
free(_backBuf);
free(_scaleBuf);
free(_window4BackScn);
free(_window6BackScn);
free(_variableArray);
free(_variableArray2);

View File

@ -83,9 +83,9 @@ struct VgaPointersEntry {
struct VgaSprite {
uint16 id;
uint16 image;
int16 image;
uint16 palette;
uint16 x, y; /* actually signed numbers */
int16 x, y;
uint16 flags;
uint16 priority;
uint16 windowNum, zoneNum;
@ -108,6 +108,17 @@ struct VgaTimerEntry {
VgaTimerEntry() { memset(this, 0, sizeof(*this)); }
};
struct AnimTable {
const byte *srcPtr;
int16 x;
int16 y;
uint16 width;
uint16 height;
uint16 window;
uint16 id;
AnimTable() { memset(this, 0, sizeof(*this)); }
};
enum SIMONGameType {
GType_ELVIRA1 = 0,
GType_ELVIRA2 = 1,
@ -262,6 +273,9 @@ protected:
bool _fastMode;
bool _useBackGround;
bool _oldDrawMethod;
bool _backFlag;
uint16 _debugMode;
uint16 _language;
bool _copyProtection;
@ -361,6 +375,7 @@ protected:
byte _leftButtonDown;
byte _leftButton, _leftButtonCount, _leftButtonOld;
byte _rightButtonDown;
bool _clickOnly;
bool _noRightClick;
Item *_dummyItem1;
@ -450,10 +465,11 @@ protected:
HitArea _hitAreas[250];
AnimTable _screenAnim1[60];
VgaPointersEntry _vgaBufferPointers[450];
VgaSprite _vgaSprites[200];
VgaSleepStruct _waitSyncTable[60];
VgaSleepStruct _waitEndTable[60];
VgaSleepStruct _waitSyncTable[60];
const uint16 *_pathFindArray[100];
@ -472,6 +488,15 @@ protected:
byte _videoBuf1[32000];
uint16 _videoWindows[128];
uint16 _window3Flag;
uint16 _window4Flag;
uint16 _window6Flag;
byte *_window4BackScn;
byte *_window6BackScn;
uint16 _moveXMin, _moveYMin;
uint16 _moveXMax, _moveYMax;
VgaTimerEntry _vgaTimerList[205];
WindowBlock *_windowList;
@ -1025,6 +1050,10 @@ protected:
void drawImage_init(int16 image, uint16 palette, uint16 x, uint16 y, uint16 flags);
virtual void drawImage(VC10_state *state);
void drawBackGroundImage(VC10_state *state);
void drawVertImage(VC10_state *state);
void setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height);
void horizontalScroll(VC10_state *state);
void verticalScroll(VC10_state *state);
@ -1041,7 +1070,9 @@ protected:
void checkScrollY(int16 y, int16 ypos);
void centreScroll();
void clearWindow(uint windowNum, uint color);
void clearVideoWindow(uint windowNum, uint color);
void clearVideoBackGround(uint windowNum, uint color);
void setPaletteSlot(uint srcOffs, uint dstOffs);
void checkWaitEndTable();
@ -1100,6 +1131,11 @@ protected:
void animateSpritesDebug();
void animateSpritesByY();
void dirtyClips();
void dirtyBackGround();
void restoreBackGround();
void saveBackGround(VgaSprite *vsp);
void clearSurfaces(uint num_lines);
void updateScreen();
@ -1416,6 +1452,8 @@ protected:
const OpcodeEntrySimon1 *_opcodesSimon1;
virtual void drawImage(VC10_state *state);
void drawMaskedImage(VC10_state *state);
void draw32ColorImage(VC10_state *state);
virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y);

View File

@ -703,12 +703,16 @@ void AGOSEngine_Feeble::windowNewLine(WindowBlock *window) {
}
void AGOSEngine::windowNewLine(WindowBlock *window) {
if (window->textRow != window->height)
window->textRow++;
window->textColumn = 0;
window->textColumnOffset = 0;
window->textLength = 0;
if (window->textRow == window->height) {
// TODO
debug(0, "Window Scroll");
} else {
window->textRow++;
}
}
#ifdef PALMOS_68K

View File

@ -69,8 +69,15 @@ void AGOSEngine::animateSprites() {
return;
}
vsp = _vgaSprites;
if (_oldDrawMethod) {
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
dirtyClips();
}
restoreBackGround();
}
vsp = _vgaSprites;
while (vsp->id != 0) {
vsp->windowNum &= 0x7FFF;
@ -82,17 +89,119 @@ void AGOSEngine::animateSprites() {
_vgaCurSpriteId = vsp->id;
_vgaCurSpritePriority = vsp->priority;
drawImage_init(vsp->image, vsp->palette, vsp->x, vsp->y, vsp->flags);
if (_oldDrawMethod) {
saveBackGround(vsp);
}
drawImage_init(vsp->image, vsp->palette, vsp->x, vsp->y, vsp->flags);
vsp++;
}
if (_drawImagesDebug)
memset(_backBuf, 0, _screenWidth * _screenHeight);
if (_window6Flag == 1)
_window6Flag++;
if (_window4Flag == 1)
_window4Flag++;
_updateScreen = true;
}
void AGOSEngine::dirtyClips() {
// TODO
}
void AGOSEngine::restoreBackGround() {
AnimTable *animTable;
uint images = 0;
animTable = _screenAnim1;
while (animTable->srcPtr) {
animTable++;
images++;
}
while (images--) {
animTable--;
if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
!(animTable->window & 0x8000)) {
//continue;
}
animTable->window &= 0x7FFF;
_windowNum = animTable->window;
VC10_state state;
state.srcPtr = animTable->srcPtr;
state.height = state.draw_height = animTable->height;
state.width = state.draw_width = animTable->width;
state.y = animTable->y;
state.x = animTable->x;
state.palette = 0;
state.paletteMod = 0;
state.flags = kDFNonTrans;
_backFlag = 1;
drawImage(&state);
//if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) {
animTable->srcPtr = 0;
//}
}
_backFlag = 0;
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
AnimTable *animTableTmp;
animTable = animTableTmp = _screenAnim1;
while (animTable->srcPtr != 0) {
if (!(animTable->window & 8000)) {
memcpy(animTableTmp, animTable, sizeof(AnimTable));
animTableTmp++;
}
animTable++;
}
animTableTmp->id = 0;
}
}
void AGOSEngine::saveBackGround(VgaSprite *vsp) {
if ((vsp->flags & 4) || !vsp->image)
return;
AnimTable *animTable = _screenAnim1;
while (animTable->srcPtr)
animTable++;
const byte *ptr = _curVgaFile2 + vsp->image * 8;
int16 x = vsp->x - _scrollX;
int16 y = vsp->y - _scrollY;
if (_window3Flag == 1) {
animTable->srcPtr = (const byte *)_window4BackScn;
} else {
uint xoffs = (_videoWindows[vsp->windowNum * 4 + 0] * 2 + x) * 8;
uint yoffs = (_videoWindows[vsp->windowNum * 4 + 1] + y);
animTable->srcPtr = getBackGround() + xoffs + yoffs * _screenWidth;
}
animTable->x = x;
animTable->y = y;
animTable->width = READ_BE_UINT16(ptr + 6) / 16;
if (vsp->flags & 40) {
animTable->width++;
}
animTable->height = ptr[5];
animTable->window = vsp->windowNum;
animTable->id = vsp->id;
}
void AGOSEngine::animateSpritesDebug() {
VgaSprite *vsp;
VgaPointersEntry *vpe;
@ -289,10 +398,16 @@ void AGOSEngine::displayBoxStars() {
}
void AGOSEngine::scrollScreen() {
byte *dst = getFrontBuf();
byte *dst;
const byte *src;
uint x, y;
if (!_oldDrawMethod) {
dst = getFrontBuf();
} else {
dst = getBackGround();
}
if (_scrollXMax == 0) {
uint screenSize = 8 * _screenWidth;
if (_scrollFlag < 0) {
@ -340,8 +455,16 @@ void AGOSEngine::scrollScreen() {
_scrollX += _scrollFlag;
vcWriteVar(251, _scrollX);
memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight);
memcpy(_backGroundBuf, _backBuf, _scrollHeight * _screenWidth);
if (!_oldDrawMethod) {
memcpy(_backBuf, _frontBuf, _screenWidth * _screenHeight);
memcpy(_backGroundBuf, _backBuf, _scrollHeight * _screenWidth);
} else {
memcpy(_window4BackScn, _backGroundBuf, _scrollHeight * _screenWidth);
}
setMoveRect(0, 0, 320, _scrollHeight);
_window4Flag = 1;
}
_scrollFlag = 0;
@ -390,6 +513,20 @@ void AGOSEngine::fillBackGroundFromBack(uint lines) {
memcpy(_backGroundBuf, _backBuf, lines * _screenWidth);
}
void AGOSEngine::setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height) {
if (x < _moveXMin)
_moveXMin = x;
if (y < _moveYMin)
_moveYMin = y;
if (width > _moveXMax)
_moveXMax = width;
if (height > _moveYMax)
_moveYMax = height;
}
void AGOSEngine::updateScreen() {
if (_fastFadeInFlag == 0 && _paletteFlag == 1) {
_paletteFlag = 0;
@ -399,11 +536,63 @@ void AGOSEngine::updateScreen() {
}
}
_system->copyRectToScreen(getBackBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight);
_system->updateScreen();
if (_oldDrawMethod) {
if (_window4Flag == 2) {
_window4Flag = 0;
if (getGameId() != GID_DIMP)
memcpy(getBackBuf(), getFrontBuf(), _screenWidth * _screenHeight);
uint16 srcWidth, width, height;
byte *dst = getFrontBuf();
const byte *src = _window4BackScn;
if (_window3Flag == 1) {
src = getBackGround();
}
dst += (_moveYMin + _videoWindows[17]) * _screenWidth;
dst += (_videoWindows[16] * 16) + _moveXMin;
src += (_videoWindows[18] * 16 * _moveYMin);
src += _moveXMin;
srcWidth = _videoWindows[18] * 16;
width = _moveXMax - _moveXMin;
height = _moveYMax - _moveYMin;
for (; height > 0; height--) {
memcpy(dst, src, width);
dst += _screenWidth;
src += srcWidth;
}
_moveXMin = 0xFFFF;
_moveYMin = 0xFFFF;
_moveXMax = 0;
_moveYMax = 0;
}
if (_window6Flag == 2) {
_window6Flag = 0;
byte *src = _window6BackScn;
byte *dst = getFrontBuf() + 16320;
for (int i = 0; i < 80; i++) {
memcpy(dst, src, 48);
dst += _screenWidth;
src += 48;
}
}
_system->copyRectToScreen(getFrontBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight);
_system->updateScreen();
} else {
_system->copyRectToScreen(getBackBuf(), _screenWidth, 0, 0, _screenWidth, _screenHeight);
_system->updateScreen();
if (getGameId() != GID_DIMP)
memcpy(getBackBuf(), getFrontBuf(), _screenWidth * _screenHeight);
}
if (getGameType() == GType_FF && _scrollFlag) {
scrollScreen();

View File

@ -123,6 +123,7 @@ void AGOSEngine::killAllTimers() {
next = cur->next;
delTimeEvent(cur);
}
_clickOnly = 0;
}
bool AGOSEngine::kickoffTimeEvents() {
@ -164,32 +165,30 @@ bool AGOSEngine::isVgaQueueEmpty() {
}
void AGOSEngine::haltAnimation() {
VgaTimerEntry *vte = _vgaTimerList;
if (_lockWord & 0x10)
return;
_lockWord |= 0x10;
while (vte->delay) {
vte->delay += 10;
if (_updateScreen != false) {
updateScreen();
_updateScreen = false;
}
}
void AGOSEngine::restartAnimation() {
if (!(_lockWord & 0x10))
return;
updateScreen();
_lockWord &= ~0x10;
// Check picture queue
}
void AGOSEngine::addVgaEvent(uint16 num, const byte *code_ptr, uint16 cur_sprite, uint16 curZoneNum) {
VgaTimerEntry *vte;
// When Simon talks to the Golum about stew in French version of
// Simon the Sorcerer 1 the code_ptr is at wrong location for
// sprite 200. This was a bug in the original game, which
// caused several glitches in this scene.
// We work around the problem by correcting the code_ptr for sprite
// 200 in this scene, if it is wrong.
if (getGameType() == GType_SIMON1 && _language == Common::FR_FRA &&
(code_ptr - _vgaBufferPointers[curZoneNum].vgaFile1 == 4) && (cur_sprite == 200) && (curZoneNum == 2))
code_ptr += 0x66;
_lockWord |= 1;
for (vte = _vgaTimerList; vte->delay; vte++) {

File diff suppressed because it is too large Load Diff

View File

@ -174,6 +174,7 @@ void AGOSEngine::waitForInput() {
_verbHitArea = 0;
_hitAreaSubjectItem = NULL;
_hitAreaObjectItem = NULL;
_clickOnly = 0;
_nameLocked = 0;
if (getGameType() == GType_WW) {

View File

@ -118,15 +118,21 @@ char *AGOSEngine::genSaveName(int slot) {
sprintf(buf, "feeble.%.3d", slot);
} else if (getGameType() == GType_SIMON2) {
sprintf(buf, "simon2.%.3d", slot);
} else {
} else if (getGameType() == GType_SIMON1) {
sprintf(buf, "simon1.%.3d", slot);
} else if (getGameType() == GType_WW) {
sprintf(buf, "waxworks.%.3d", slot);
} else if (getGameType() == GType_ELVIRA2) {
sprintf(buf, "elvira2.%.3d", slot);
} else if (getGameType() == GType_ELVIRA1) {
sprintf(buf, "elvira1.%.3d", slot);
}
return buf;
}
void AGOSEngine::quickLoadOrSave() {
// Quick load & save is only supported complete version of Simon the Sorcerer 1/2
if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2 ||
if (getGameType() == GType_PP || getGameType() == GType_FF ||
(getFeatures() & GF_DEMO)) {
return;
}

View File

@ -608,9 +608,9 @@ void AGOSEngine_Elvira1::oe1_pName() {
void AGOSEngine_Elvira1::oe1_pcName() {
// 115:
Item *i = getNextItemPtr();
Common::String name = (const char *)getStringPtrByID(i->itemName);
name.toUppercase();
showMessageFormat("%s", name.c_str());
// TODO: Change first letter to upper case.
showMessageFormat("%s\n", (const byte *)getStringPtrByID(i->itemName)); // Difference
}
void AGOSEngine_Elvira1::oe1_isCalled() {
@ -815,6 +815,8 @@ void AGOSEngine_Elvira1::oe1_enableInput() {
_lastHitArea3 = 0;
_lastHitArea = 0;
_clickOnly = 1;
}
void AGOSEngine_Elvira1::oe1_setTime() {
@ -1208,12 +1210,6 @@ void AGOSEngine::printScroll() {
state.x_skip = 0;
state.y_skip = 0;
state.surf2_addr = getFrontBuf();
state.surf2_pitch = _dxSurfacePitch;
state.surf_addr = getBackBuf();
state.surf_pitch = _dxSurfacePitch;
drawImage(&state);
}

View File

@ -310,7 +310,7 @@ void AGOSEngine_Elvira2::oe2_pObj() {
SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
if (subObject != NULL && subObject->objectFlags & kOFText)
showMessageFormat((const char *)getStringPtrByID(subObject->objectFlagValue[0]));
showMessageFormat("%s\n", (const char *)getStringPtrByID(subObject->objectFlagValue[0])); // Difference
}
void AGOSEngine_Elvira2::oe2_loadGame() {

View File

@ -522,7 +522,7 @@ int AGOSEngine::startSubroutine(Subroutine *sub) {
// WORKAROUND: Bit Flag 171 isn't set when Simon rides the lion to the
// goblin camp in non-English versions. Bit Flag 171 is required to display
// the red trail between locations on the map, during the ride.
if (getGameType() == GType_SIMON2) {
if (getGameType() == GType_SIMON2 && !_oldDrawMethod) {
if (sub->id == 13020)
setBitFlag(171, true);
if (sub->id == 13021)

View File

@ -682,7 +682,17 @@ void AGOSEngine::boxController(uint x, uint y, uint mode) {
_variableArray[500] = best_ha->verb & 0xBFFF;
}
}
}
if (_clickOnly != 0 && best_ha->id < 8) {
uint id = best_ha->id;
if (id >= 4)
id -= 4;
invertBox(findBox(id), 0, 0, 0, 0);
_clickOnly = 0;
return;
}
}
if (best_ha->flags & kBFDragBox) {
_lastClickRem = best_ha;

View File

@ -210,6 +210,17 @@ bool AGOSEngine::vc_maybe_skip_proc_1(uint16 a, int16 b) {
return item->state == b;
}
void AGOSEngine::dirtyBackGround() {
AnimTable *animTable = _screenAnim1;
while (animTable->srcPtr) {
if (animTable->id == _vgaCurSpriteId) {
animTable->window |= 0x8000;
break;
}
animTable++;
}
}
VgaSprite *AGOSEngine::findCurSprite() {
VgaSprite *vsp = _vgaSprites;
while (vsp->id) {
@ -400,19 +411,22 @@ void AGOSEngine::vc3_loadSprite() {
return;
}
windowNum = vcReadNextWord(); /* 0 */
windowNum = vcReadNextWord();
if (getGameType() == GType_SIMON1 && windowNum == 3) {
_window3Flag = 1;
}
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP) {
zoneNum = vcReadNextWord(); /* 0 */
vgaSpriteId = vcReadNextWord(); /* 2 */
zoneNum = vcReadNextWord();
vgaSpriteId = vcReadNextWord();
} else {
vgaSpriteId = vcReadNextWord(); /* 2 */
vgaSpriteId = vcReadNextWord();
zoneNum = vgaSpriteId / 100;
}
x = vcReadNextWord(); /* 4 */
y = vcReadNextWord(); /* 6 */
palette = vcReadNextWord(); /* 8 */
x = vcReadNextWord();
y = vcReadNextWord();
palette = vcReadNextWord();
old_file_1 = _curVgaFile1;
@ -607,6 +621,7 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, uint16 x, uint16 y,
state.image = vcReadVar(-state.image);
state.palette = palette * 16;
state.paletteMod = 0;
state.x = x - _scrollX;
state.y = y - _scrollY;
@ -718,12 +733,18 @@ void AGOSEngine::vc12_delay() {
void AGOSEngine::vc13_addToSpriteX() {
VgaSprite *vsp = findCurSprite();
vsp->x += (int16)vcReadNextWord();
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}
void AGOSEngine::vc14_addToSpriteY() {
VgaSprite *vsp = findCurSprite();
vsp->y += (int16)vcReadNextWord();
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}
@ -951,6 +972,8 @@ void AGOSEngine::vc24_setSpriteXY() {
vsp->flags = vcReadNextWord();
}
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}
@ -963,6 +986,8 @@ void AGOSEngine::vc25_halt_sprite() {
vsp++;
}
_vcPtr = (byte *)&_vc_get_out_of_code;
dirtyBackGround();
_vgaSpriteChanged++;
}
@ -1024,6 +1049,14 @@ void AGOSEngine::vc27_resetSprite() {
}
}
if (_lockWord & 0x20) {
AnimTable *animTable = _screenAnim1;
while (animTable->srcPtr) {
animTable->srcPtr = 0;
animTable++;
}
}
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF || getGameType() == GType_PP)
vcWriteVar(254, 0);
@ -1083,8 +1116,20 @@ void AGOSEngine::vc31_setWindow() {
}
void AGOSEngine::vc32_saveScreen() {
// TODO
debug(0, "vc32_saveScreen: stub");
uint xoffs = _videoWindows[4 * 4 + 0] * 16;
uint yoffs = _videoWindows[4 * 4 + 1];
uint width = _videoWindows[4 * 4 + 2] * 16;
uint height = _videoWindows[4 * 4 + 3];
byte *dst = getBackGround() + xoffs + yoffs * _screenWidth;
byte *src = _window4BackScn;
uint srcWidth = _videoWindows[4 * 4 + 2] * 16;
for (; height > 0; height--) {
memcpy(dst, src, width);
dst += _screenWidth;
src += srcWidth;
}
}
void AGOSEngine::vc33_setMouseOn() {
@ -1111,24 +1156,65 @@ void AGOSEngine::vc34_setMouseOff() {
_leftButtonDown = 0;
}
void AGOSEngine::clearWindow(uint num, uint color) {
void AGOSEngine::clearVideoBackGround(uint num, uint color) {
debug(0, "clearVideoBackGround: num %d color %d", num, color);
const uint16 *vlut = &_videoWindows[num * 4];
byte *dst = getBackGround() + vlut[0] * 16 + (vlut[1] * (vlut[2] * 16));
for (uint h = 0; h < vlut[3]; h++) {
memset(dst, color, vlut[2] * 16);
dst += _screenWidth;
}
}
void AGOSEngine::clearVideoWindow(uint num, uint color) {
if (getGameType() == GType_ELVIRA1) {
if (num == 2 || num == 6)
return;
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
if (num != 4 && num < 10)
return;
} else if (getGameType() == GType_SIMON1) {
if (num != 4)
return;
}
if (num == 3) {
memset(getBackBuf(), 0, _screenWidth * _screenHeight);
} else {
debug(0, "clearVideoWindow: num %d color %d", num, color);
if (getGameType() == GType_SIMON2) {
const uint16 *vlut = &_videoWindows[num * 4];
byte *dst = getBackBuf() + vlut[0] * 16 + vlut[1] * _dxSurfacePitch;
uint xoffs = vlut[0] * 16;
uint yoffs = vlut[1];
uint dstWidth = _videoWindows[18] * 16;
byte *dst = _window4BackScn + xoffs + yoffs * dstWidth;
setMoveRect(0, 0, vlut[2] * 16, vlut[3]);
for (uint h = 0; h < vlut[3]; h++) {
memset(dst, 0, vlut[2] * 16);
dst += _screenWidth;
memset(dst, color, vlut[2] * 16);
dst += dstWidth;
}
_window4Flag = 1;
} else {
if (getGameType() == GType_ELVIRA1 && num == 3) {
memset(getFrontBuf(), color, _screenWidth * _screenHeight);
} else if (num == 4) {
const uint16 *vlut = &_videoWindows[num * 4];
uint xoffs = (vlut[0] - _videoWindows[16]) * 16;
uint yoffs = (vlut[1] - _videoWindows[17]);
uint dstWidth = _videoWindows[18] * 16;
byte *dst = _window4BackScn + xoffs + yoffs * dstWidth;
setMoveRect(0, 0, vlut[2] * 16, vlut[3]);
for (uint h = 0; h < vlut[3]; h++) {
memset(dst, color, vlut[2] * 16);
dst += dstWidth;
}
_window4Flag = 1;
}
}
}
@ -1136,7 +1222,23 @@ void AGOSEngine::clearWindow(uint num, uint color) {
void AGOSEngine::vc35_clearWindow() {
uint16 num = vcReadNextWord();
uint16 color = vcReadNextWord();
clearWindow(num, color);
// Clear video window
clearVideoWindow(num, color);
// Clear video background
if (getGameType() == GType_ELVIRA1) {
if (num == 2 || num == 6)
return;
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
if (num != 4 && num < 10)
return;
} else if (getGameType() == GType_SIMON1) {
if (num != 4)
return;
}
clearVideoBackGround(num, color);
}
void AGOSEngine::vc36_setWindowImage() {
@ -1147,7 +1249,7 @@ void AGOSEngine::vc36_setWindowImage() {
if (getGameType() == GType_FF || getGameType() == GType_PP) {
_copyPartialMode = 2;
} else if (getGameType() == GType_SIMON1) {
if (windowNum == 16) {
if (windowNum == 16 && !_oldDrawMethod) {
_copyPartialMode = 2;
} else {
setWindowImage(windowNum, vga_res);

View File

@ -56,7 +56,7 @@ struct AnimationHeader_Feeble {
// Simon 1/2
struct ImageHeader_Simon {
uint16 id;
uint16 x_1;
uint16 color;
uint16 x_2;
uint16 scriptOffs;
};
@ -116,6 +116,7 @@ struct VC10_state {
int16 image;
uint16 flags;
byte palette;
byte paletteMod;
int16 x, y;
uint16 width, height;

View File

@ -68,21 +68,37 @@ void AGOSEngine::vc45_setWindowPalette() {
uint num = vcReadNextWord();
uint color = vcReadNextWord();
const uint16 *vlut = &_videoWindows[num * 4];
uint16 *dst = (uint16 *)getBackBuf() + vlut[0] * 8 + vlut[1] * _dxSurfacePitch / 2;
uint width = vlut[2] * 8;
if (num == 4) {
const uint16 *vlut = &_videoWindows[num * 4];
uint16 *dst = (uint16 *)_window4BackScn;
uint width = vlut[2] * 16 / 2;
uint height = vlut[3];
if (getGameType() == GType_ELVIRA2 && num == 7) {
dst -= 4;
width += 4;
}
for (uint h = 0; h < vlut[3]; h++) {
for (uint w = 0; w < width; w++) {
dst[w] &= 0xF0F;
dst[w] |= color * 16;
for (uint h = 0; h < height; h++) {
for (uint w = 0; w < width; w++) {
dst[w] &= 0xF0F;
dst[w] |= color * 16;
}
dst += width;
}
} else {
const uint16 *vlut = &_videoWindows[num * 4];
uint16 *dst = (uint16 *)getFrontBuf() + vlut[0] * 8 + vlut[1] * _dxSurfacePitch / 2;
uint width = vlut[2] * 16 / 2;
uint height = vlut[3];
if (getGameType() == GType_ELVIRA2 && num == 7) {
dst -= 4;
width += 4;
}
for (uint h = 0; h < height; h++) {
for (uint w = 0; w < width; w++) {
dst[w] &= 0xF0F;
dst[w] |= color * 16;
}
dst += _dxSurfacePitch / 2;
}
dst += _dxSurfacePitch / 2;
}
}
@ -211,7 +227,7 @@ void AGOSEngine::vc55_moveBox() {
void AGOSEngine::vc56_fullScreen() {
byte *src = _curVgaFile2 + 32;
byte *dst = getBackBuf();
byte *dst = getFrontBuf();
memcpy(dst, src + 768, _screenHeight * _screenWidth);
//fullFade();

View File

@ -103,18 +103,27 @@ void AGOSEngine::vc32_copyVar() {
void AGOSEngine::vc37_addToSpriteY() {
VgaSprite *vsp = findCurSprite();
vsp->y += vcReadVar(vcReadNextWord());
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}
void AGOSEngine::vc45_setSpriteX() {
VgaSprite *vsp = findCurSprite();
vsp->x = vcReadVar(vcReadNextWord());
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}
void AGOSEngine::vc46_setSpriteY() {
VgaSprite *vsp = findCurSprite();
vsp->y = vcReadVar(vcReadNextWord());
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}
@ -209,6 +218,8 @@ void AGOSEngine::vc61_setMaskImage() {
vsp->y += vcReadNextWord();
vsp->flags = kDFMasked | kDFUseFrontBuf;
vsp->windowNum |= 0x8000;
dirtyBackGround();
_vgaSpriteChanged++;
}

View File

@ -110,7 +110,7 @@ void AGOSEngine::vc61() {
if (a == 6) {
src = _curVgaFile2 + 800;
dstPtr = getBackBuf();
dstPtr = getFrontBuf();
memcpy(dstPtr, src, 64000);
tmp = 4 - 1;
} else {
@ -218,14 +218,21 @@ void AGOSEngine::vc62_fastFadeOut() {
}
}
// Allow one section of Simon the Sorcerer 1 introduction to be displayed
// in lower half of screen
if ((getGameType() == GType_SIMON1) && (_subroutine == 2923 || _subroutine == 2926)) {
clearSurfaces(200);
} else if (getGameType() == GType_FF || getGameType() == GType_PP) {
if (getGameType() == GType_FF || getGameType() == GType_PP) {
clearSurfaces(480);
} else if (getGameType() == GType_WW) {
memset(getFrontBuf(), 0, _screenWidth * _screenHeight);
} else if (!_oldDrawMethod) {
// Allow one section of Simon the Sorcerer 1 introduction to be displayed
// in lower half of screen
if ((getGameType() == GType_SIMON1) && (_subroutine == 2923 || _subroutine == 2926)) {
clearSurfaces(200);
} else {
clearSurfaces(_windowNum == 4 ? 134 : 200);
}
} else {
clearSurfaces(_windowNum == 4 ? 134 : 200);
if (_windowNum != 4)
memset(getFrontBuf(), 0, _screenWidth * _screenHeight);
}
}
if (getGameType() == GType_SIMON2) {

View File

@ -123,6 +123,18 @@ void AGOSEngine::colorWindow(WindowBlock *window) {
dst += _screenWidth;
}
} else {
if (getGameType() == GType_ELVIRA2 && window->y == 146) {
if (window->fill_color == 1) {
_displayPalette[33 * 4 + 0] = 48 * 4;
_displayPalette[33 * 4 + 1] = 40 * 4;
_displayPalette[33 * 4 + 2] = 32 * 4;
} else {
_displayPalette[33 * 4 + 0] = 56 * 4;
_displayPalette[33 * 4 + 1] = 56 * 4;
_displayPalette[33 * 4 + 2] = 40 * 4;
}
}
dst = getFrontBuf() + _dxSurfacePitch * window->y + window->x * 8;
h = window->height * 8;
w = window->width * 8;
@ -170,7 +182,7 @@ void AGOSEngine::restoreBlock(uint h, uint w, uint y, uint x) {
uint i;
dst = getFrontBuf();
src = _backGroundBuf;
src = getBackGround();
dst += y * _dxSurfacePitch;
src += y * _dxSurfacePitch;