diff options
-rw-r--r-- | engines/agos/agos.cpp | 2 | ||||
-rw-r--r-- | engines/agos/agos.h | 9 | ||||
-rw-r--r-- | engines/agos/draw.cpp | 4 | ||||
-rw-r--r-- | engines/agos/subroutine.cpp | 8 | ||||
-rw-r--r-- | engines/agos/vga.cpp | 301 |
5 files changed, 217 insertions, 107 deletions
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index c7d424dd9b..bbbed04756 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -80,7 +80,6 @@ AGOSEngine::AGOSEngine(OSystem *syst) _gameOffsetsPtr = 0; _debugger = 0; - setupVgaOpcodes(); _keyPressed = 0; @@ -630,6 +629,7 @@ void AGOSEngine::setupGame() { _variableArrayPtr = _variableArray; setupOpcodes(); + setupVgaOpcodes(); setZoneBuffers(); diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 27430db4e0..b35b68f105 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -164,8 +164,16 @@ class AGOSEngine : public Engine { int _numOpcodes; typedef void (AGOSEngine::*VgaOpcodeProc) (); + void setupVgaOpcodes(); const VgaOpcodeProc *_vga_opcode_table; + uint _numVideoOpcodes; + + void setupCommonVideoOpcodes(VgaOpcodeProc *op); + + void setupElvira1VideoOpcodes(VgaOpcodeProc *op); + void setupSimon2VideoOpcodes(VgaOpcodeProc *op); + void setupFeebleVideoOpcodes(VgaOpcodeProc *op); public: GameDescription *_gameDescription; @@ -198,7 +206,6 @@ protected: uint _vgaBaseDelay; uint _tableIndexBase; uint _textIndexBase; - uint _numVideoOpcodes; uint _vgaMemSize; uint _tableMemSize; uint _musicIndexBase; diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp index b5af30fc15..13ce3871c0 100644 --- a/engines/agos/draw.cpp +++ b/engines/agos/draw.cpp @@ -85,7 +85,7 @@ void AGOSEngine::animateSprites() { _vgaCurSpritePriority = vsp->priority; params[0] = readUint16Wrapper(&vsp->image); - if (getGameType() == GType_WW) { + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { params[1] = readUint16Wrapper(&vsp->x); params[2] = readUint16Wrapper(&vsp->y); params[3] = READ_BE_UINT16(&vsp->flags); @@ -138,7 +138,7 @@ void AGOSEngine::animateSpritesDebug() { printf("id:%5d image:%3d base-color:%3d x:%3d y:%3d flags:%x\n", vsp->id, vsp->image, vsp->palette, vsp->x, vsp->y, vsp->flags); params[0] = readUint16Wrapper(&vsp->image); - if (getGameType() == GType_WW) { + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { params[1] = readUint16Wrapper(&vsp->x); params[2] = readUint16Wrapper(&vsp->y); params[3] = READ_BE_UINT16(&vsp->flags); diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp index d7cb0d350c..11f1c19686 100644 --- a/engines/agos/subroutine.cpp +++ b/engines/agos/subroutine.cpp @@ -500,7 +500,13 @@ SubroutineLine *AGOSEngine::createSubroutineLine(Subroutine *sub, int where) { void AGOSEngine::runSubroutine101() { Subroutine *sub; - sub = getSubroutineByID(101); + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2) { + // HACK + sub = getSubroutineByID(1); + } else { + sub = getSubroutineByID(101); + } + if (sub != NULL) startSubroutineEx(sub); diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index 2fc07ea80e..bbde7f0c31 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -33,96 +33,176 @@ namespace AGOS { // Opcode tables +void AGOSEngine::setupCommonVideoOpcodes(VgaOpcodeProc *op) { + op[1] = &AGOSEngine::vc1_fadeOut; + op[2] = &AGOSEngine::vc2_call; + op[3] = &AGOSEngine::vc3_loadSprite; + op[4] = &AGOSEngine::vc4_fadeIn; + op[5] = &AGOSEngine::vc5_skip_if_neq; + op[6] = &AGOSEngine::vc6_skip_ifn_sib_with_a; + op[7] = &AGOSEngine::vc7_skip_if_sib_with_a; + op[8] = &AGOSEngine::vc8_skip_if_parent_is; + op[9] = &AGOSEngine::vc9_skip_if_unk3_is; + op[10] = &AGOSEngine::vc10_draw; + op[11] = &AGOSEngine::vc11_clearPathFinder; + op[12] = &AGOSEngine::vc12_delay; + op[13] = &AGOSEngine::vc13_addToSpriteX; + op[14] = &AGOSEngine::vc14_addToSpriteY; + op[15] = &AGOSEngine::vc15_sync; + op[16] = &AGOSEngine::vc16_waitSync; + op[17] = &AGOSEngine::vc17_setPathfinderItem; + op[18] = &AGOSEngine::vc18_jump; + op[19] = &AGOSEngine::vc19_chain_to_script; + op[20] = &AGOSEngine::vc20_setRepeat; + op[21] = &AGOSEngine::vc21_endRepeat; + op[22] = &AGOSEngine::vc22_setSpritePalette; + op[23] = &AGOSEngine::vc23_setSpritePriority; + op[24] = &AGOSEngine::vc24_setSpriteXY; + op[25] = &AGOSEngine::vc25_halt_sprite; + op[26] = &AGOSEngine::vc26_setSubWindow; + op[27] = &AGOSEngine::vc27_resetSprite; + op[28] = &AGOSEngine::vc28_dummy_op; + op[29] = &AGOSEngine::vc29_stopAllSounds; + op[30] = &AGOSEngine::vc30_setFrameRate; + op[31] = &AGOSEngine::vc31_setWindow; + op[32] = &AGOSEngine::vc32_copyVar; + op[33] = &AGOSEngine::vc33_setMouseOn; + op[34] = &AGOSEngine::vc34_setMouseOff; + op[35] = &AGOSEngine::vc35_clearWindow; + op[36] = &AGOSEngine::vc36_setWindowImage; + op[37] = &AGOSEngine::vc37_addToSpriteY; + op[38] = &AGOSEngine::vc38_skipIfVarZero; + op[39] = &AGOSEngine::vc39_setVar; + op[40] = &AGOSEngine::vc40; + op[41] = &AGOSEngine::vc41; + op[42] = &AGOSEngine::vc42_delayIfNotEQ; + op[43] = &AGOSEngine::vc43_skipIfBitClear; + op[44] = &AGOSEngine::vc44_skipIfBitSet; + op[45] = &AGOSEngine::vc45_setSpriteX; + op[46] = &AGOSEngine::vc46_setSpriteY; + op[47] = &AGOSEngine::vc47_addToVar; + op[48] = &AGOSEngine::vc48_setPathFinder; + op[49] = &AGOSEngine::vc49_setBit; + op[50] = &AGOSEngine::vc50_clearBit; + op[51] = &AGOSEngine::vc51_enableBox; + op[52] = &AGOSEngine::vc52_playSound; + op[53] = &AGOSEngine::vc53_panSFX; + op[54] = &AGOSEngine::vc54_no_op; + op[55] = &AGOSEngine::vc55_moveBox; + op[56] = &AGOSEngine::vc56_delay; + op[57] = &AGOSEngine::vc57_blackPalette; + op[58] = &AGOSEngine::vc58; + op[59] = &AGOSEngine::vc59; + op[60] = &AGOSEngine::vc60_killSprite; + op[61] = &AGOSEngine::vc61_setMaskImage; + op[62] = &AGOSEngine::vc62_fastFadeOut; + op[63] = &AGOSEngine::vc63_fastFadeIn; +} + +void AGOSEngine::setupElvira1VideoOpcodes(VgaOpcodeProc *op) { + op[1] = &AGOSEngine::vc1_fadeOut; + op[2] = &AGOSEngine::vc2_call; + op[3] = &AGOSEngine::vc3_loadSprite; + op[4] = &AGOSEngine::vc4_fadeIn; + op[5] = &AGOSEngine::vc5_skip_if_neq; + op[6] = &AGOSEngine::vc6_skip_ifn_sib_with_a; + op[7] = &AGOSEngine::vc7_skip_if_sib_with_a; + + op[10] = &AGOSEngine::vc10_draw; + + op[13] = &AGOSEngine::vc12_delay; + op[14] = &AGOSEngine::vc13_addToSpriteX; + op[15] = &AGOSEngine::vc14_addToSpriteY; + op[16] = &AGOSEngine::vc15_sync; + op[17] = &AGOSEngine::vc16_waitSync; + op[18] = &AGOSEngine::vc17_setPathfinderItem; + op[19] = &AGOSEngine::vc18_jump; + + op[21] = &AGOSEngine::vc20_setRepeat; + op[22] = &AGOSEngine::vc21_endRepeat; + op[23] = &AGOSEngine::vc22_setSpritePalette; + op[24] = &AGOSEngine::vc23_setSpritePriority; + op[25] = &AGOSEngine::vc24_setSpriteXY; + op[26] = &AGOSEngine::vc25_halt_sprite; + op[27] = &AGOSEngine::vc26_setSubWindow; + op[28] = &AGOSEngine::vc27_resetSprite; + + op[29] = &AGOSEngine::vc52_playSound; + op[30] = &AGOSEngine::vc29_stopAllSounds; + op[31] = &AGOSEngine::vc30_setFrameRate; + op[32] = &AGOSEngine::vc31_setWindow; + + op[34] = &AGOSEngine::vc33_setMouseOn; + op[35] = &AGOSEngine::vc34_setMouseOff; + + op[38] = &AGOSEngine::vc35_clearWindow; + + op[40] = &AGOSEngine::vc36_setWindowImage; + + op[51] = &AGOSEngine::vc38_skipIfVarZero; + op[52] = &AGOSEngine::vc39_setVar; + op[53] = &AGOSEngine::vc40; + op[54] = &AGOSEngine::vc41; +} + +void AGOSEngine::setupSimon2VideoOpcodes(VgaOpcodeProc *op) { + setupCommonVideoOpcodes(op); + + op[64] = &AGOSEngine::vc64_skipIfSpeechEnded; + op[65] = &AGOSEngine::vc65_slowFadeIn; + op[66] = &AGOSEngine::vc66_skipIfNotEqual; + op[67] = &AGOSEngine::vc67_skipIfGE; + op[68] = &AGOSEngine::vc68_skipIfLE; + op[69] = &AGOSEngine::vc69_playTrack; + op[70] = &AGOSEngine::vc70_queueMusic; + op[71] = &AGOSEngine::vc71_checkMusicQueue; + op[72] = &AGOSEngine::vc72_play_track_2; + op[73] = &AGOSEngine::vc73_setMark; + op[74] = &AGOSEngine::vc74_clearMark; +} + +void AGOSEngine::setupFeebleVideoOpcodes(VgaOpcodeProc *op) { + setupSimon2VideoOpcodes(op); + + op[75] = &AGOSEngine::vc75_setScale; + op[76] = &AGOSEngine::vc76_setScaleXOffs; + op[77] = &AGOSEngine::vc77_setScaleYOffs; + op[78] = &AGOSEngine::vc78_computeXY; + op[79] = &AGOSEngine::vc79_computePosNum; + op[80] = &AGOSEngine::vc80_setOverlayImage; + op[81] = &AGOSEngine::vc81_setRandom; + op[82] = &AGOSEngine::vc82_getPathValue; + op[83] = &AGOSEngine::vc83_playSoundLoop; + op[84] = &AGOSEngine::vc84_stopSoundLoop; +} + void AGOSEngine::setupVgaOpcodes() { - static const VgaOpcodeProc vga_opcode_table[] = { - NULL, - &AGOSEngine::vc1_fadeOut, - &AGOSEngine::vc2_call, - &AGOSEngine::vc3_loadSprite, - &AGOSEngine::vc4_fadeIn, - &AGOSEngine::vc5_skip_if_neq, - &AGOSEngine::vc6_skip_ifn_sib_with_a, - &AGOSEngine::vc7_skip_if_sib_with_a, - &AGOSEngine::vc8_skip_if_parent_is, - &AGOSEngine::vc9_skip_if_unk3_is, - &AGOSEngine::vc10_draw, - &AGOSEngine::vc11_clearPathFinder, - &AGOSEngine::vc12_delay, - &AGOSEngine::vc13_addToSpriteX, - &AGOSEngine::vc14_addToSpriteY, - &AGOSEngine::vc15_sync, - &AGOSEngine::vc16_waitSync, - &AGOSEngine::vc17_setPathfinderItem, - &AGOSEngine::vc18_jump, - &AGOSEngine::vc19_chain_to_script, - &AGOSEngine::vc20_setRepeat, - &AGOSEngine::vc21_endRepeat, - &AGOSEngine::vc22_setSpritePalette, - &AGOSEngine::vc23_setSpritePriority, - &AGOSEngine::vc24_setSpriteXY, - &AGOSEngine::vc25_halt_sprite, - &AGOSEngine::vc26_setSubWindow, - &AGOSEngine::vc27_resetSprite, - &AGOSEngine::vc28_dummy_op, - &AGOSEngine::vc29_stopAllSounds, - &AGOSEngine::vc30_setFrameRate, - &AGOSEngine::vc31_setWindow, - &AGOSEngine::vc32_copyVar, - &AGOSEngine::vc33_setMouseOn, - &AGOSEngine::vc34_setMouseOff, - &AGOSEngine::vc35_clearWindow, - &AGOSEngine::vc36_setWindowImage, - &AGOSEngine::vc37_addToSpriteY, - &AGOSEngine::vc38_skipIfVarZero, - &AGOSEngine::vc39_setVar, - &AGOSEngine::vc40, - &AGOSEngine::vc41, - &AGOSEngine::vc42_delayIfNotEQ, - &AGOSEngine::vc43_skipIfBitClear, - &AGOSEngine::vc44_skipIfBitSet, - &AGOSEngine::vc45_setSpriteX, - &AGOSEngine::vc46_setSpriteY, - &AGOSEngine::vc47_addToVar, - &AGOSEngine::vc48_setPathFinder, - &AGOSEngine::vc49_setBit, - &AGOSEngine::vc50_clearBit, - &AGOSEngine::vc51_enableBox, - &AGOSEngine::vc52_playSound, - &AGOSEngine::vc53_panSFX, - &AGOSEngine::vc54_no_op, - &AGOSEngine::vc55_moveBox, - &AGOSEngine::vc56_delay, - &AGOSEngine::vc57_blackPalette, - &AGOSEngine::vc58, - &AGOSEngine::vc59, - &AGOSEngine::vc60_killSprite, - &AGOSEngine::vc61_setMaskImage, - &AGOSEngine::vc62_fastFadeOut, - &AGOSEngine::vc63_fastFadeIn, - &AGOSEngine::vc64_skipIfSpeechEnded, - &AGOSEngine::vc65_slowFadeIn, - &AGOSEngine::vc66_skipIfNotEqual, - &AGOSEngine::vc67_skipIfGE, - &AGOSEngine::vc68_skipIfLE, - &AGOSEngine::vc69_playTrack, - &AGOSEngine::vc70_queueMusic, - &AGOSEngine::vc71_checkMusicQueue, - &AGOSEngine::vc72_play_track_2, - &AGOSEngine::vc73_setMark, - &AGOSEngine::vc74_clearMark, - &AGOSEngine::vc75_setScale, - &AGOSEngine::vc76_setScaleXOffs, - &AGOSEngine::vc77_setScaleYOffs, - &AGOSEngine::vc78_computeXY, - &AGOSEngine::vc79_computePosNum, - &AGOSEngine::vc80_setOverlayImage, - &AGOSEngine::vc81_setRandom, - &AGOSEngine::vc82_getPathValue, - &AGOSEngine::vc83_playSoundLoop, - &AGOSEngine::vc84_stopSoundLoop, - }; - + static VgaOpcodeProc vga_opcode_table[100]; + + for (int i = 0; i < ARRAYSIZE(vga_opcode_table); i++) + vga_opcode_table[i] = NULL; + _vga_opcode_table = vga_opcode_table; + + switch (getGameType()) { + case GType_ELVIRA: + setupElvira1VideoOpcodes(vga_opcode_table); + break; + case GType_ELVIRA2: + case GType_WW: + case GType_SIMON1: + setupCommonVideoOpcodes(vga_opcode_table); + break; + case GType_SIMON2: + setupSimon2VideoOpcodes(vga_opcode_table); + break; + case GType_FF: + case GType_PP: + setupFeebleVideoOpcodes(vga_opcode_table); + break; + default: + error("setupVgaOpcodes: Unknown game"); + } } // Script parser @@ -144,12 +224,13 @@ void AGOSEngine::runVgaScript() { _vcPtr += 2; } - if (opcode >= _numVideoOpcodes) - error("Invalid VGA opcode '%d' encountered", opcode); - if (opcode == 0) return; + debug(1, "runVgaScript: Video opcode %d", opcode); + if (opcode >= _numVideoOpcodes || !_vga_opcode_table[opcode]) + error("Invalid VGA opcode '%d' encountered", opcode); + (this->*_vga_opcode_table[opcode]) (); } } @@ -1645,7 +1726,7 @@ void AGOSEngine::vc22_setSpritePalette() { byte *offs, *palptr, *src; uint16 a = 0, b, num, palSize; - if (getGameType() != GType_WW) + if (getGameType() != GType_ELVIRA && getGameType() != GType_ELVIRA2 && getGameType() != GType_WW) a = vcReadNextWord(); b = vcReadNextWord(); @@ -1662,29 +1743,40 @@ void AGOSEngine::vc22_setSpritePalette() { palptr = &_displayPalette[(a * 64)]; offs = _curVgaFile1 + 6; } else { - num = 16; palSize = 32; + palptr = _displayPalette; offs = _curVgaFile1 + READ_BE_UINT16(_curVgaFile1 + 6); + + if (b >= 1000) { + b -= 1000; + num = 16; + } else { + num = 13; + } } src = offs + b * palSize; do { - if (getGameType() == GType_WW) { + if (getGameType() == GType_ELVIRA || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { uint16 color = READ_BE_UINT16(src); - palptr[2] = ((color & 0x00f) >> 0) * 32; - palptr[1] = ((color & 0x0f0) >> 4) * 32; palptr[0] = ((color & 0xf00) >> 8) * 32; + palptr[1] = ((color & 0x0f0) >> 4) * 32; + palptr[2] = ((color & 0x00f) >> 0) * 32; + palptr[3] = 0; + + palptr += 4; + src += 2; } else { palptr[0] = src[0] * 4; palptr[1] = src[1] * 4; palptr[2] = src[2] * 4; - } - palptr[3] = 0; + palptr[3] = 0; - palptr += 4; - src += (getGameType() == GType_WW) ? 2 : 3; + palptr += 4; + src += 3; + } } while (--num); _paletteFlag = 2; @@ -1865,14 +1957,14 @@ void AGOSEngine::vc36_setWindowImage() { if (getGameType() == GType_FF || getGameType() == GType_PP) { _copyPartialMode = 2; - } else if (getGameType() == GType_SIMON2) { - set_video_mode_internal(windowNum, vga_res); } else if (getGameType() == GType_SIMON1) { if (windowNum == 16) { _copyPartialMode = 2; } else { set_video_mode_internal(windowNum, vga_res); } + } else { + set_video_mode_internal(windowNum, vga_res); } } @@ -2113,6 +2205,11 @@ void AGOSEngine::vc51_enableBox() { void AGOSEngine::vc52_playSound() { bool ambient = false; + if (getGameType() == GType_ELVIRA) { + _vcPtr += 8; + return; + } + uint16 sound = vcReadNextWord(); if (sound >= 0x8000) { ambient = true; |