diff options
author | Dreammaster | 2013-02-15 08:25:09 -0500 |
---|---|---|
committer | Dreammaster | 2013-02-15 08:25:09 -0500 |
commit | bb3285d933419b6bdefadc55a6e320855ff0dd27 (patch) | |
tree | 2df613c52f854c33cff660ed1b064e2996ed80bb /engines | |
parent | d1a19a1d4c3e20b57250e73141d81e8d9b44a2a1 (diff) | |
parent | adc338cd719179a94ff470b28e9584262d7b47e8 (diff) | |
download | scummvm-rg350-bb3285d933419b6bdefadc55a6e320855ff0dd27.tar.gz scummvm-rg350-bb3285d933419b6bdefadc55a6e320855ff0dd27.tar.bz2 scummvm-rg350-bb3285d933419b6bdefadc55a6e320855ff0dd27.zip |
Merge branch 'master' into hopkins
Diffstat (limited to 'engines')
514 files changed, 14464 insertions, 13331 deletions
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index dd06736290..b9a64bc572 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -35,7 +35,6 @@ Console::Console(AgiEngine *vm) : GUI::Debugger() { DCmd_Register("debug", WRAP_METHOD(Console, Cmd_Debug)); DCmd_Register("cont", WRAP_METHOD(Console, Cmd_Cont)); DCmd_Register("agiver", WRAP_METHOD(Console, Cmd_Agiver)); - DCmd_Register("crc", WRAP_METHOD(Console, Cmd_Crc)); DCmd_Register("flags", WRAP_METHOD(Console, Cmd_Flags)); DCmd_Register("logic0", WRAP_METHOD(Console, Cmd_Logic0)); DCmd_Register("objs", WRAP_METHOD(Console, Cmd_Objs)); @@ -119,12 +118,6 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { return true; } -bool Console::Cmd_Crc(int argc, const char **argv) { - DebugPrintf("command removed from scummvm\n"); - - return true; -} - bool Console::Cmd_Agiver(int argc, const char **argv) { int ver, maj, min; @@ -278,22 +271,17 @@ bool Console::Cmd_BT(int argc, const char **argv) { MickeyConsole::MickeyConsole(MickeyEngine *mickey) : GUI::Debugger() { _mickey = mickey; - DCmd_Register("curRoom", WRAP_METHOD(MickeyConsole, Cmd_CurRoom)); - DCmd_Register("gotoRoom", WRAP_METHOD(MickeyConsole, Cmd_GotoRoom)); + DCmd_Register("room", WRAP_METHOD(MickeyConsole, Cmd_Room)); DCmd_Register("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic)); DCmd_Register("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj)); } -bool MickeyConsole::Cmd_CurRoom(int argc, const char **argv) { +bool MickeyConsole::Cmd_Room(int argc, const char **argv) { + if (argc == 2) + _mickey->debugGotoRoom(atoi(argv[1])); + _mickey->debugCurRoom(); - return true; -} -bool MickeyConsole::Cmd_GotoRoom(int argc, const char **argv) { - if (argc != 2) - DebugPrintf("Usage: %s <Room number>\n", argv[0]); - else - _mickey->debugGotoRoom(atoi(argv[1])); return true; } diff --git a/engines/agi/console.h b/engines/agi/console.h index 5f69460907..f8025e0562 100644 --- a/engines/agi/console.h +++ b/engines/agi/console.h @@ -49,7 +49,6 @@ private: bool Cmd_SetFlag(int argc, const char **argv); bool Cmd_SetObj(int argc, const char **argv); bool Cmd_RunOpcode(int argc, const char **argv); - bool Cmd_Crc(int argc, const char **argv); bool Cmd_Agiver(int argc, const char **argv); bool Cmd_Flags(int argc, const char **argv); bool Cmd_Vars(int argc, const char **argv); @@ -75,8 +74,7 @@ public: private: MickeyEngine *_mickey; - bool Cmd_CurRoom(int argc, const char **argv); - bool Cmd_GotoRoom(int argc, const char **argv); + bool Cmd_Room(int argc, const char **argv); bool Cmd_DrawPic(int argc, const char **argv); bool Cmd_DrawObj(int argc, const char **argv); }; diff --git a/engines/agi/logic.h b/engines/agi/logic.h index fecc2e3b8a..14137f01d2 100644 --- a/engines/agi/logic.h +++ b/engines/agi/logic.h @@ -37,6 +37,6 @@ struct AgiLogic { const char **texts; /**< message list */ }; -} // End of namespace Agi +} // End of namespace Agi #endif /* AGI_LOGIC_H */ diff --git a/engines/agi/lzw.h b/engines/agi/lzw.h index e3fbafe584..c732491e8e 100644 --- a/engines/agi/lzw.h +++ b/engines/agi/lzw.h @@ -27,6 +27,6 @@ namespace Agi { void lzwExpand(uint8 *, uint8 *, int32); -} // End of namespace Agi +} // End of namespace Agi #endif /* AGI_LZW_H */ diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index 5334407eb8..9d899b1855 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -1399,7 +1399,7 @@ void cmdDistance(AgiGame *state, uint8 *p) { // a zombie or the zombie getting turned away by the scarab) we make it appear the // zombie is far away from Rosella if the zombie is not already up and chasing her. enum zombieStates {ZOMBIE_SET_TO_RISE_UP, ZOMBIE_RISING_UP, ZOMBIE_CHASING_EGO}; - uint8 zombieStateVarNumList[] = {155, 156, (_v[vCurRoom] == 16) ? 162 : 158}; + uint8 zombieStateVarNumList[] = {155, 156, (uint8)((_v[vCurRoom] == 16) ? 162 : 158)}; uint8 zombieNum = p2 - 221; // Zombie's number (In range 0-2) uint8 zombieStateVarNum = zombieStateVarNumList[zombieNum]; // Number of the variable containing zombie's state uint8 zombieState = _v[zombieStateVarNum]; // Zombie's state diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp index 7a427bd94f..807ab2dc2c 100644 --- a/engines/agi/opcodes.cpp +++ b/engines/agi/opcodes.cpp @@ -376,6 +376,18 @@ void AgiEngine::setupOpcodes() { logicNamesTest = insV1Test; logicNamesCmd = insV1; } + + // Alter opcode parameters for specific games + // TODO: This could be either turned into a game feature, or a version + // specific check, instead of a game version check + + // The Apple IIGS versions of MH1 and Goldrush both have a parameter for + // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946. + if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) && + getPlatform() == Common::kPlatformApple2GS) { + logicNamesCmd[176].args = "n"; // hide.mouse + logicNamesCmd[178].args = "n"; // show.mouse + } } } diff --git a/engines/agi/preagi_winnie.h b/engines/agi/preagi_winnie.h index 96ae65997e..f34c80cec1 100644 --- a/engines/agi/preagi_winnie.h +++ b/engines/agi/preagi_winnie.h @@ -355,6 +355,6 @@ private: void printStrWinnie(char *szMsg); }; -} // End of namespace Agi +} // End of namespace Agi #endif diff --git a/engines/cge/events.cpp b/engines/cge/events.cpp index 1530c870ef..89802058f4 100644 --- a/engines/cge/events.cpp +++ b/engines/cge/events.cpp @@ -184,7 +184,7 @@ void Mouse::on() { step(0); if (_busy) _busy->step(0); - } + } } void Mouse::off() { diff --git a/engines/composer/detection.cpp b/engines/composer/detection.cpp index 835f3c5683..8411441c60 100644 --- a/engines/composer/detection.cpp +++ b/engines/composer/detection.cpp @@ -374,7 +374,7 @@ static const ComposerGameDescription gameDescriptions[] = { using namespace Composer; // we match from data too, to stop detection from a non-top-level directory -const static char *directoryGlobs[] = { +static const char *directoryGlobs[] = { "data", "liam", "programs", diff --git a/engines/composer/resource.cpp b/engines/composer/resource.cpp index 83e49971fb..fa29cc886b 100644 --- a/engines/composer/resource.cpp +++ b/engines/composer/resource.cpp @@ -400,4 +400,4 @@ void OldPipe::nextFrame() { _currFrame++; } -} // End of namespace Composer +} // End of namespace Composer diff --git a/engines/configure.engines b/engines/configure.engines index e17e2f67e0..3ac287e23f 100644 --- a/engines/configure.engines +++ b/engines/configure.engines @@ -20,7 +20,7 @@ add_engine hopkins "Hopkins FBI" no add_engine hugo "Hugo Trilogy" yes add_engine kyra "Kyra" yes "lol eob" "Legend of Kyrandia 1-3" add_engine lol "Lands of Lore" yes -add_engine eob "Eye of the Beholder" no +add_engine eob "Eye of the Beholder" yes add_engine lastexpress "The Last Express" no "" "" "16bit" add_engine lure "Lure of the Temptress" yes add_engine made "MADE" yes @@ -43,7 +43,7 @@ add_engine sword25 "Broken Sword 2.5" no "" "" "png zlib 16bit" add_engine teenagent "Teen Agent" yes add_engine testbed "TestBed: the Testing framework" no add_engine tinsel "Tinsel" yes -add_engine toltecs "3 Skulls of the Toltecs" no +add_engine toltecs "3 Skulls of the Toltecs" yes add_engine toon "Toonstruck" yes add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes add_engine tony "Tony Tough and the Night of Roasted Moths" yes "" "" "16bit" diff --git a/engines/cruise/linker.h b/engines/cruise/linker.h index ce212f6cea..25f4a5cc2a 100644 --- a/engines/cruise/linker.h +++ b/engines/cruise/linker.h @@ -27,5 +27,5 @@ namespace Cruise { void updateAllScriptsImports(); -} // End of namespace Cruise +} // End of namespace Cruise #endif diff --git a/engines/cruise/staticres.cpp b/engines/cruise/staticres.cpp index a3fc4f884b..08ff4d7548 100644 --- a/engines/cruise/staticres.cpp +++ b/engines/cruise/staticres.cpp @@ -177,9 +177,9 @@ const int16 spanish_fontCharacterTable[256] = { 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, -1, -1, - 0x72, 0x80 + 0x72, 0x80, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x7f, 0x79, 0x7b, 0x81, 0x82, 0x83, -1, -1, 0x7d, diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 43799f7944..7009752365 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -42,7 +42,6 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig } } -// This is the game's introduction sequence void DrasculaEngine::animation_1_1() { debug(4, "animation_1_1()"); @@ -92,12 +91,8 @@ void DrasculaEngine::animation_1_1() { playFLI("scrollb.bin", 9); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; clearRoom(); playSound(5); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; if (animate("scr2.bin", 17)) break; stopSound(); @@ -194,8 +189,6 @@ void DrasculaEngine::animation_1_1() { if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) break; talk_drascula(3); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; if (animate("lib.bin", 16)) break; if (animate("lib2.bin", 16)) @@ -211,8 +204,6 @@ void DrasculaEngine::animation_1_1() { loadPic("plan1.alg", screenSurface, HALF_PAL); updateScreen(); talk_solo(_textd[5], "d5.als"); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; if (animate("lib2.bin", 16)) break; clearRoom(); @@ -220,8 +211,6 @@ void DrasculaEngine::animation_1_1() { updateScreen(); pause(20); talk_solo(_textd[6], "d6.als"); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; if (animate("lib2.bin", 16)) break; clearRoom(); @@ -255,8 +244,6 @@ void DrasculaEngine::animation_1_1() { break; playMusic(11); talk_drascula(10); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; if (animate("rayo1.bin", 16)) break; playSound(5); @@ -372,7 +359,6 @@ void DrasculaEngine::animation_1_1() { loadPic(99, backSurface); } -// John falls in love with BJ, who is then abducted by Drascula void DrasculaEngine::animation_2_1() { debug(4, "animation_2_1()"); @@ -384,9 +370,6 @@ void DrasculaEngine::animation_2_1() { term_int = 0; while (!shouldQuit()) { - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; - if (animate("ag.bin", 14)) break; @@ -456,13 +439,8 @@ void DrasculaEngine::animation_2_1() { curY = 95; trackProtagonist = 1; hare_se_ve = 1; - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; loadPic("97g.alg", extraSurface); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; - if (animate("lev.bin", 15)) break; @@ -520,8 +498,6 @@ void DrasculaEngine::animation_2_1() { break; talk_bj(12); gotoObject(157, 98 + curHeight); - if ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()) - break; if (animate("bes.bin", 16)) break; playMusic(11); @@ -563,7 +539,6 @@ void DrasculaEngine::animation_2_1() { } } -// John Hacker talks with the bartender to book a room void DrasculaEngine::animation_3_1() { debug(4, "animation_3_1()"); @@ -574,7 +549,6 @@ void DrasculaEngine::animation_3_1() { loadPic(97, extraSurface); } -// John Hacker talks with the pianist void DrasculaEngine::animation_4_1() { debug(4, "animation_4_1()"); @@ -676,26 +650,39 @@ void DrasculaEngine::animation_4_2() { pause(5); talk_hacker(57); pause(6); - talk_blind(2); - pause(4); - talk_hacker(58); - talk_blind(3); - delay(14); - talk_hacker(59); - talk_blind(4); - talk_hacker(60); - talk_blind(5); - talk_hacker(61); - talk_blind(6); - talk_hacker(62); - talk_blind(7); - talk_hacker(63); - talk_blind(8); - copyBackground(); - updateScreen(); - _system->delayMillis(1000); - talk_hacker(64); - talk_blind(9); + + if (flags[4] == 0) { // first time + talk_blind(2); + pause(4); + talk_hacker(58); + talk_blind(3); + delay(14); + talk_hacker(59); + talk_blind(4); + talk_hacker(60); + talk_blind(5); + talk_hacker(61); + talk_blind(6); + talk_hacker(62); + talk_blind(7); + talk_hacker(63); + talk_blind(8); + copyBackground(); + updateScreen(); + _system->delayMillis(1000); + talk_hacker(64); + talk_blind(9); + + flags[4] = 1; // talked to the blind man + } else { // second time + _system->delayMillis(1000); + talk_blind(10); + talk_hacker(65); + + flags[33] = 1; + } + + flags[9] = 0; copyBackground(); updateScreen(); @@ -711,9 +698,6 @@ void DrasculaEngine::animation_4_2() { loadPic(97, extraSurface); loadPic(99, backSurface); selectVerb(kVerbNone); - - flags[9] = 0; - flags[4] = 1; } void DrasculaEngine::animation_14_2() { @@ -798,17 +782,22 @@ void DrasculaEngine::animation_16_2() { return; } - delay(3000); + uint32 now = _system->getMillis(); + while (_system->getMillis() - now < 3000 * 2) { + delay(50); + if (getScan() != 0) { + asco(); + return; + } + } if (i < 4) { fadeToBlack(1); - + clearRoom(); if (getScan() != 0) { asco(); return; } - - clearRoom(); } } @@ -818,6 +807,7 @@ void DrasculaEngine::animation_16_2() { for (int l = 1; l < 200; l++) { copyBackground(0, 0, 0, l, 320, 200 - l, drawSurface3, screenSurface); copyBackground(0, 200 - l, 0, 0, 320, l, bgSurface, screenSurface); + delay(10); updateScreen(); if (getScan() != 0) { asco(); @@ -867,6 +857,20 @@ void DrasculaEngine::animation_20_2() { void DrasculaEngine::animation_23_2() { debug(4, "animation_23_2()"); + int p_x, p_y; + int maxN; + int animX, animY; + + // Animation offsets - without earplugs + int johnFrameX[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260, + 1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223}; + int johnFrameY[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 1, 1, 1, 1}; + + // Animation offsets - with earplugs + int john2FrameX[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137}; + int john2FrameY[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73}; + loadPic("an24.alg", frontSurface); flags[21] = 1; @@ -893,10 +897,41 @@ void DrasculaEngine::animation_23_2() { trackVonBraun = 1; talk_vonBraun(18, kVonBraunNormal); - if (flags[29] == 0) - animation_23_joined(); - else - animation_23_joined2(); + if (flags[29] == 0) { + // John isn't wearing earplugs + p_x = curX + 2; + p_y = curY - 3; + maxN = 34; + animX = 36; + animY = 74; + + loadPic("an23.alg", backSurface); + } else { + // John is wearing earplugs + p_x = curX + 4; + p_y = curY; + maxN = 14; + animX = 33; + animY = 71; + + pause(50); + + loadPic("an23_2.alg", backSurface); + } + + for (int n = 0; n < maxN; n++) { + copyRect(p_x, p_y, p_x, p_y, animX, animY, bgSurface, screenSurface); + if (flags[29] == 0) + copyRect(johnFrameX[n], johnFrameY[n], p_x, p_y, animX, animY, backSurface, screenSurface); + else + copyRect(john2FrameX[n], john2FrameY[n], p_x, p_y, animX, animY, backSurface, screenSurface); + updateRefresh(); + updateScreen(p_x, p_y, p_x, p_y, animX, animY, screenSurface); + updateEvents(); + pause(5); + } + + loadPic(99, backSurface); trackVonBraun = 2; animation_25_2(); @@ -921,52 +956,6 @@ void DrasculaEngine::animation_23_2() { breakOut = 1; } -void DrasculaEngine::animation_23_joined() { - debug(4, "animation_23_joined()"); - - int p_x = curX + 2, p_y = curY - 3; - int x[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260, - 1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223}; - int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 1, 1, 1, 1}; - - loadPic("an23.alg", backSurface); - - for (int n = 0; n < 34; n++) { - copyRect(p_x, p_y, p_x, p_y, 36, 74, bgSurface, screenSurface); - copyRect(x[n], y[n], p_x, p_y, 36, 74, backSurface, screenSurface); - updateRefresh(); - updateScreen(p_x, p_y, p_x, p_y, 36, 74, screenSurface); - updateEvents(); - pause(5); - } - - loadPic(99, backSurface); -} - -void DrasculaEngine::animation_23_joined2() { - debug(4, "animation_23_joined2()"); - - int p_x = curX + 4, p_y = curY; - int x[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137}; - int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73}; - - pause(50); - - loadPic("an23_2.alg", backSurface); - - for (int n = 0; n < 14; n++) { - copyRect(p_x, p_y, p_x, p_y, 33, 71, bgSurface, screenSurface); - copyRect(x[n], y[n], p_x, p_y, 33, 71, backSurface, screenSurface); - updateRefresh(); - updateScreen(p_x,p_y, p_x,p_y, 33,71, screenSurface); - updateEvents(); - pause(5); - } - - loadPic(99, backSurface); -} - void DrasculaEngine::animation_25_2() { debug(4, "animation_25_2()"); @@ -1091,31 +1080,11 @@ void DrasculaEngine::animation_35_2() { fadeToBlack(2); } -// Use cross on Yoda void DrasculaEngine::animation_2_3() { debug(4, "animation_2_3()"); flags[0] = 1; playMusic(13); - animation_3_3(); - playMusic(13); - animation_4_3(); - flags[1] = 1; - updateRoom(); - updateScreen(120, 0, 120, 0, 200, 200, screenSurface); - animation_5_3(); - flags[0] = 0; - flags[1] = 1; - - loadPic(96, frontSurface); - loadPic(97, extraSurface); - loadPic(99, backSurface); - - gotoObject(332, 127); -} - -void DrasculaEngine::animation_3_3() { - debug(4, "animation_3_3()"); int px = curX - 20, py = curY - 1; @@ -1129,12 +1098,11 @@ void DrasculaEngine::animation_3_3() { updateAnim(75, px, py, 71, 72, 4, extraSurface, 3, true); updateAnim(2, px, py, 71, 72, 4, backSurface, 3, true); updateAnim(75, px, py, 71, 72, 4, backSurface, 3, true); -} -void DrasculaEngine::animation_4_3() { - debug(4, "animation_4_3()"); + playMusic(13); - int px = 120, py = 63; + px = 120; + py = 63; loadPic("any_1.alg", frontSurface); loadPic("any_2.alg", extraSurface); @@ -1146,12 +1114,13 @@ void DrasculaEngine::animation_4_3() { updateAnim(91, px, py, 77, 89, 4, extraSurface, 3, true); updateAnim(1, px, py, 77, 89, 4, backSurface, 3, true); updateAnim(91, px, py, 77, 89, 4, backSurface, 3, true); -} -void DrasculaEngine::animation_5_3() { - debug(4, "animation_5_3()"); + flags[1] = 1; + updateRoom(); + updateScreen(120, 0, 120, 0, 200, 200, screenSurface); - int px = curX - 20, py = curY - 1; + px = curX - 20; + py = curY - 1; loadPic("an3y_1.alg", frontSurface); loadPic("an3y_2.alg", extraSurface); @@ -1163,6 +1132,15 @@ void DrasculaEngine::animation_5_3() { updateAnim(75, px, py, 71, 72, 4, extraSurface, 3, true); updateAnim(2, px, py, 71, 72, 4, backSurface, 3, true); updateAnim(75, px, py, 71, 72, 4, backSurface, 3, true); + + flags[0] = 0; + flags[1] = 1; + + loadPic(96, frontSurface); + loadPic(97, extraSurface); + loadPic(99, backSurface); + + gotoObject(332, 127); } void DrasculaEngine::animation_6_3() { @@ -1197,8 +1175,8 @@ void DrasculaEngine::animation_6_3() { updateScreen(); } -void DrasculaEngine::animation_ray() { - debug(4, "animation_ray()"); +void DrasculaEngine::animation_castle() { + debug(4, "animation_castle()"); loadPic("anr_1.alg", frontSurface, HALF_PAL); loadPic("anr_2.alg", extraSurface); @@ -1365,18 +1343,6 @@ void DrasculaEngine::animation_5_5(){ loadPic(49, bgSurface, HALF_PAL); } -void DrasculaEngine::animation_11_5() { - debug(4, "animation_11_5()"); - - flags[9] = 1; - if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1) - animation_12_5(); - else { - flags[9] = 0; - talk(33); - } -} - void DrasculaEngine::animation_12_5() { debug(4, "animation_12_5()"); @@ -1426,7 +1392,7 @@ void DrasculaEngine::animation_12_5() { loadPic("3an11_1.alg", backSurface); for (frame = 0; frame < 8; frame++) { - if (frame == 2 || frame == 4 || frame == 8 || frame==10) + if (frame == 2 || frame == 4 || frame == 8 || frame == 10) setPalette((byte *)&bgPalette1); else if (frame == 1 || frame == 5 || frame == 7 || frame == 9) setPalette((byte *)&bgPalette2); @@ -1465,7 +1431,8 @@ void DrasculaEngine::animation_12_5() { flags[1] = 1; - animation_13_5(); + animation_12_5_frankenstein(); + playSound(1); hiccup(12); finishSound(); @@ -1487,13 +1454,11 @@ void DrasculaEngine::animation_12_5() { enterRoom(57); } -void DrasculaEngine::animation_13_5() { - debug(4, "animation_13_5()"); - +void DrasculaEngine::animation_12_5_frankenstein() { int frank_x = 199; - int frame = 0; int frus_x[] = {1, 46, 91, 136, 181, 226, 271}; int frus_y[] = {1, 1, 1, 1, 1, 1, 1, 89}; + int frame = 0; loadPic("auxfr.alg", backSurface); @@ -1898,27 +1863,6 @@ void DrasculaEngine::animation_24_2() { loadPic("an24.alg", frontSurface); - animation_32_2(); - - flags[21] = 1; - - talk_vonBraun(22, kVonBraunNormal); - - if (flags[22] == 0) - converse(4); - else - converse(5); - - exitRoom(0); - flags[21] = 0; - flags[24] = 0; - trackVonBraun = 1; - vonBraunX = 120; -} - -void DrasculaEngine::animation_32_2() { - debug(4, "animation_32_2()"); - loadPic("an32_1.alg", drawSurface3); loadPic("an32_2.alg", backSurface); @@ -1939,6 +1883,21 @@ void DrasculaEngine::animation_32_2() { } loadPic("aux18.alg", drawSurface3); + + flags[21] = 1; + + talk_vonBraun(22, kVonBraunNormal); + + if (flags[22] == 0) + converse(4); + else + converse(5); + + exitRoom(0); + flags[21] = 0; + flags[24] = 0; + trackVonBraun = 1; + vonBraunX = 120; } void DrasculaEngine::animation_34_2() { @@ -2126,55 +2085,6 @@ void DrasculaEngine::animation_6_2() { flags[9] = 0; } -void DrasculaEngine::animation_33_2() { - debug(4, "animation_33_2()"); - - stopMusic(); - flags[9] = 1; - - pause(12); - talk(60); - pause(8); - - clearRoom(); - loadPic("ciego1.alg", bgSurface, HALF_PAL); // ciego = blind - loadPic("ciego2.alg", drawSurface3); - loadPic("ciego3.alg", extraSurface); - loadPic("ciego4.alg", backSurface); - loadPic("ciego5.alg", frontSurface); - - copyBackground(); - updateScreen(); - - pause(10); - - talk_blind(1); - pause(5); - talk_hacker(57); - pause(6); - _system->delayMillis(1000); - talk_blind(10); - talk_hacker(65); - - copyBackground(); - updateScreen(); - - pause(14); - - clearRoom(); - - playMusic(roomMusic); - loadPic(9, bgSurface, HALF_PAL); - loadPic("aux9.alg", drawSurface3); - loadPic(96, frontSurface); - loadPic(97, extraSurface); - loadPic(99, backSurface); - selectVerb(kVerbNone); - - flags[33] = 1; - flags[9] = 0; -} - void DrasculaEngine::animation_1_4() { debug(4, "animation_1_4()"); diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp index d2fd32f2e5..426b2ade67 100644 --- a/engines/drascula/console.cpp +++ b/engines/drascula/console.cpp @@ -46,7 +46,6 @@ bool Console::Cmd_Room(int argc, const char **argv) { _vm->selectVerb(kVerbNone); _vm->clearRoom(); _vm->loadPic(roomNum, _vm->bgSurface, HALF_PAL); - _vm->selectionMade = 0; return false; } diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index 7abbb3214b..d045d683fc 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -167,7 +167,6 @@ void DrasculaEngine::converse(int index) { // no need to delete the stream, since TextResourceParser takes ownership // delete stream; - if (currentChapter == 2 && !strcmp(fileName, "op_5.cal") && flags[38] == 1 && flags[33] == 1) { strcpy(phrase3, _text[405]); strcpy(sound3, "405.als"); diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 760d8b7d98..e1f69e2158 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -21,10 +21,13 @@ */ #include "base/plugins.h" +#include "common/file.h" +#include "common/translation.h" #include "engines/advancedDetector.h" #include "engines/savestate.h" -#include "common/file.h" + +#include "graphics/thumbnail.h" #include "drascula/drascula.h" @@ -263,81 +266,123 @@ static const DrasculaGameDescription gameDescriptions[] = { { AD_TABLE_END_MARKER } }; -} // End of namespace Drascula +static const ExtraGuiOption drasculaExtraGuiOption = { + _s("Use original save/load screens"), + _s("Use the original save/load screens, instead of the ScummVM ones"), + "originalsaveload", + false +}; + +SaveStateDescriptor loadMetaData(Common::ReadStream *s, int slot, bool setPlayTime); class DrasculaMetaEngine : public AdvancedMetaEngine { public: DrasculaMetaEngine() : AdvancedMetaEngine(Drascula::gameDescriptions, sizeof(Drascula::DrasculaGameDescription), drasculaGames) { _singleid = "drascula"; - _guioptions = GUIO2(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD); + _guioptions = GUIO1(GUIO_NOMIDI); + } + + virtual const char *getName() const { + return "Drascula"; } - virtual bool hasFeature(MetaEngineFeature f) const { - return (f == kSupportsListSaves); + virtual const char *getOriginalCopyright() const { + return "Drascula Engine (C) 2000 Alcachofa Soft, (C) 1996 Digital Dreams Multimedia, (C) 1994 Emilio de Paz"; } - virtual SaveStateList listSaves(const char *target) const { - Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - Common::String pattern = Common::String::format("%s??", target); + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const; + virtual bool hasFeature(MetaEngineFeature f) const; + virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const; + virtual void removeSaveState(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; - // Get list of savefiles for target game - Common::StringArray filenames = saveFileMan->listSavefiles(pattern); - Common::Array<int> slots; - for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { +bool DrasculaMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail) || + (f == kSavesSupportCreationDate) || + (f == kSavesSupportPlayTime); +} - // Obtain the last 2 digits of the filename, since they correspond to the save slot - int slotNum = atoi(file->c_str() + file->size() - 2); +const ExtraGuiOptions DrasculaMetaEngine::getExtraGuiOptions(const Common::String &target) const { + ExtraGuiOptions options; + options.push_back(drasculaExtraGuiOption); + return options; +} - // Ensure save slot is within valid range - if (slotNum >= 1 && slotNum <= 10) { - slots.push_back(slotNum); +SaveStateList DrasculaMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String pattern = target; + pattern += ".???"; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + int slotNum = 0; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 3 digits of the filename, since they correspond to the save slot + slotNum = atoi(file->c_str() + file->size() - 3); + + if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) { + Common::InSaveFile *in = saveFileMan->openForLoading(*file); + if (in) { + SaveStateDescriptor desc = loadMetaData(in, slotNum, false); + if (desc.getSaveSlot() != slotNum) { + // invalid + delete in; + continue; + } + saveList.push_back(desc); + delete in; } } + } - // Sort save slot ids - Common::sort<int>(slots.begin(), slots.end()); - - // Load save index - Common::String fileEpa = Common::String::format("%s.epa", target); - Common::InSaveFile *epa = saveFileMan->openForLoading(fileEpa); - - // Get savegame names from index - Common::String saveDesc; - SaveStateList saveList; - int line = 1; - for (size_t i = 0; i < slots.size(); i++) { - // ignore lines corresponding to unused saveslots - for (; line < slots[i]; line++) - epa->readLine(); + return saveList; +} - // copy the name in the line corresponding to the save slot and truncate to 22 characters - saveDesc = Common::String(epa->readLine().c_str(), 22); +SaveStateDescriptor DrasculaMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + char fileName[MAXPATHLEN]; + sprintf(fileName, "%s.%03d", target, slot); - // handle cases where the save directory and save index are detectably out of sync - if (saveDesc == "*") - saveDesc = "No name specified."; + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fileName); - // increment line number to keep it in sync with slot number - line++; + SaveStateDescriptor desc; + // Do not allow save slot 0 (used for auto-saving) to be deleted or + // overwritten. + desc.setDeletableFlag(slot != 0); + desc.setWriteProtectedFlag(slot == 0); - // Insert savegame name into list - saveList.push_back(SaveStateDescriptor(slots[i], saveDesc)); + if (in) { + desc = Drascula::loadMetaData(in, slot, false); + if (desc.getSaveSlot() != slot) { + delete in; + return SaveStateDescriptor(); } - delete epa; - return saveList; - } + Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in); + desc.setThumbnail(thumbnail); - virtual const char *getName() const { - return "Drascula"; + delete in; } - virtual const char *getOriginalCopyright() const { - return "Drascula Engine (C) 2000 Alcachofa Soft, (C) 1996 Digital Dreams Multimedia, (C) 1994 Emilio de Paz"; - } + return desc; +} - virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; -}; +int DrasculaMetaEngine::getMaximumSaveSlot() const { return 999; } + +void DrasculaMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String fileName = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(fileName); +} bool DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { const Drascula::DrasculaGameDescription *gd = (const Drascula::DrasculaGameDescription *)desc; @@ -347,8 +392,10 @@ bool DrasculaMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD return gd != 0; } +} // End of namespace Drascula + #if PLUGIN_ENABLED_DYNAMIC(DRASCULA) - REGISTER_PLUGIN_DYNAMIC(DRASCULA, PLUGIN_TYPE_ENGINE, DrasculaMetaEngine); + REGISTER_PLUGIN_DYNAMIC(DRASCULA, PLUGIN_TYPE_ENGINE, Drascula::DrasculaMetaEngine); #else - REGISTER_PLUGIN_STATIC(DRASCULA, PLUGIN_TYPE_ENGINE, DrasculaMetaEngine); + REGISTER_PLUGIN_STATIC(DRASCULA, PLUGIN_TYPE_ENGINE, Drascula::DrasculaMetaEngine); #endif diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 1b3c4038f0..804881cf9a 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -87,6 +87,7 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam _textmisc = 0; _textd1 = 0; _talkSequences = 0; + _currentSaveSlot = 0; _color = 0; blinking = 0; @@ -187,6 +188,8 @@ Common::Error DrasculaEngine::run() { if (!loadDrasculaDat()) return Common::kUnknownError; + checkForOldSaveGames(); + setupRoomsTable(); loadArchives(); @@ -195,6 +198,13 @@ Common::Error DrasculaEngine::run() { currentChapter = 1; // values from 1 to 6 will start each part of game loadedDifferentChapter = 0; + setTotalPlayTime(0); + + // Check if a save is loaded from the launcher + int directSaveSlotLoading = ConfMan.getInt("save_slot"); + if (directSaveSlotLoading >= 0) { + loadGame(directSaveSlotLoading); + } checkCD(); @@ -233,7 +243,6 @@ Common::Error DrasculaEngine::run() { framesWithoutAction = 0; term_int = 0; musicStopped = 0; - selectionMade = 0; globalSpeed = 0; curExcuseLook = 0; curExcuseAction = 0; @@ -246,7 +255,6 @@ Common::Error DrasculaEngine::run() { allocMemory(); _subtitlesDisabled = !ConfMan.getBool("subtitles"); - selectionMade = 0; if (currentChapter != 3) loadPic(96, frontSurface, COMPLETE_PAL); @@ -261,7 +269,7 @@ Common::Error DrasculaEngine::run() { loadPic(96, frontSurface); } else if (currentChapter == 4) { if (loadedDifferentChapter == 0) - animation_ray(); + animation_castle(); loadPic(96, frontSurface); clearRoom(); } else if (currentChapter == 5) { @@ -295,6 +303,7 @@ Common::Error DrasculaEngine::run() { strcpy(iconName[i + 1], _textverbs[i]); assignPalette(defaultPalette); + if (!runCurrentChapter()) { endChapter(); break; @@ -359,7 +368,7 @@ bool DrasculaEngine::runCurrentChapter() { trackProtagonist = 1; objExit = 104; if (loadedDifferentChapter != 0) { - if (!loadGame(saveName)) { + if (!loadGame(_currentSaveSlot)) { return true; } } else { @@ -368,6 +377,8 @@ bool DrasculaEngine::runCurrentChapter() { curY = 56; gotoObject(65, 145); } + + // REMINDER: This is a good place to debug animations } else if (currentChapter == 2) { addObject(kItemPhone); trackProtagonist = 3; @@ -375,7 +386,7 @@ bool DrasculaEngine::runCurrentChapter() { if (loadedDifferentChapter == 0) enterRoom(14); else { - if (!loadGame(saveName)) { + if (!loadGame(_currentSaveSlot)) { return true; } } @@ -393,7 +404,7 @@ bool DrasculaEngine::runCurrentChapter() { if (loadedDifferentChapter == 0) enterRoom(20); else { - if (!loadGame(saveName)) { + if (!loadGame(_currentSaveSlot)) { return true; } } @@ -410,7 +421,7 @@ bool DrasculaEngine::runCurrentChapter() { curX = 235; curY = 164; } else { - if (!loadGame(saveName)) { + if (!loadGame(_currentSaveSlot)) { return true; } } @@ -429,7 +440,7 @@ bool DrasculaEngine::runCurrentChapter() { if (loadedDifferentChapter == 0) { enterRoom(45); } else { - if (!loadGame(saveName)) { + if (!loadGame(_currentSaveSlot)) { return true; } } @@ -443,7 +454,7 @@ bool DrasculaEngine::runCurrentChapter() { enterRoom(58); animation_1_6(); } else { - if (!loadGame(saveName)) { + if (!loadGame(_currentSaveSlot)) { return true; } loadPic("auxdr.alg", drawSurface2); @@ -596,13 +607,23 @@ bool DrasculaEngine::runCurrentChapter() { selectVerb(kVerbTalk); } else if (key == Common::KEYCODE_F6 && !_menuScreen) { selectVerb(kVerbMove); - } else if (key == Common::KEYCODE_F9) { - volumeControls(); - } else if (key == Common::KEYCODE_F10) { - if (!saveLoadScreen()) + } else if (key == Common::KEYCODE_F7) { + // ScummVM load screen + if (!scummVMSaveLoadDialog(false)) return true; } else if (key == Common::KEYCODE_F8) { selectVerb(kVerbNone); + } else if (key == Common::KEYCODE_F9) { + volumeControls(); + } else if (key == Common::KEYCODE_F10) { + if (!ConfMan.getBool("originalsaveload")) { + // ScummVM save screen + scummVMSaveLoadDialog(true); + } else { + // Original save/load screen + if (!saveLoadScreen()) + return true; + } } else if (key == Common::KEYCODE_v) { _subtitlesDisabled = true; ConfMan.setBool("subtitles", !_subtitlesDisabled); @@ -628,17 +649,14 @@ bool DrasculaEngine::runCurrentChapter() { } if (leftMouseButton != 0 || rightMouseButton != 0 || key != 0) - if (currentChapter != 3) - framesWithoutAction = 0; + framesWithoutAction = 0; if (framesWithoutAction == 15000) { screenSaver(); - if (currentChapter != 3) - framesWithoutAction = 0; + framesWithoutAction = 0; } - if (currentChapter != 3) - framesWithoutAction++; + framesWithoutAction++; } return false; @@ -652,8 +670,8 @@ bool DrasculaEngine::verify1() { removeObject(); else { for (l = 0; l < numRoomObjs; l++) { - if (mouseX >= x1[l] && mouseY >= y1[l] - && mouseX <= x2[l] && mouseY <= y2[l] && doBreak == 0) { + if (mouseX >= _objectX1[l] && mouseY >= _objectY1[l] + && mouseX <= _objectX2[l] && mouseY <= _objectY2[l] && doBreak == 0) { if (exitRoom(l)) return true; if (doBreak == 1) @@ -666,8 +684,8 @@ bool DrasculaEngine::verify1() { doBreak = 1; for (l = 0; l < numRoomObjs; l++) { - if (mouseX > x1[l] && mouseY > y1[l] - && mouseX < x2[l] && mouseY < y2[l] && doBreak == 0) { + if (mouseX > _objectX1[l] && mouseY > _objectY1[l] + && mouseX < _objectX2[l] && mouseY < _objectY2[l] && doBreak == 0) { roomX = roomObjX[l]; roomY = roomObjY[l]; trackFinal = trackObj[l]; @@ -700,8 +718,8 @@ bool DrasculaEngine::verify2() { return true; } else { for (l = 0; l < numRoomObjs; l++) { - if (mouseX > x1[l] && mouseY > y1[l] - && mouseX < x2[l] && mouseY < y2[l] && visible[l] == 1) { + if (mouseX > _objectX1[l] && mouseY > _objectY1[l] + && mouseX < _objectX2[l] && mouseY < _objectY2[l] && visible[l] == 1) { trackFinal = trackObj[l]; walkToObject = 1; gotoObject(roomObjX[l], roomObjY[l]); diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index 2d1954e3ca..e547503bee 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -36,6 +36,8 @@ #include "common/system.h" #include "common/util.h" +#include "engines/savestate.h" + #include "audio/mixer.h" #include "engines/engine.h" @@ -415,7 +417,7 @@ public: int inventoryObjects[43]; char _targetSurface[40][20]; int _destX[40], _destY[40], trackCharacter_alkeva[40], roomExits[40]; - int x1[40], y1[40], x2[40], y2[40]; + int _objectX1[40], _objectY1[40], _objectX2[40], _objectY2[40]; int takeObject, pickedObject; bool _subtitlesDisabled; bool _menuBar, _menuScreen, _hasName; @@ -453,11 +455,9 @@ public: int term_int; int currentChapter; int loadedDifferentChapter; - char saveName[13]; + int _currentSaveSlot; int _color; int musicStopped; - char select[23]; - int selectionMade; int mouseX; int mouseY; int leftMouseButton; @@ -494,9 +494,16 @@ public: void selectVerb(int); void updateVolume(Audio::Mixer::SoundType soundType, int prevVolume); void volumeControls(); + bool saveLoadScreen(); + bool scummVMSaveLoadDialog(bool isSave); + Common::String enterName(Common::String &selectedName); void loadSaveNames(); - void saveSaveNames(); + void saveGame(int slot, Common::String &desc); + bool loadGame(int slot); + void checkForOldSaveGames(); + void convertSaveGame(int slot, Common::String &desc); + void print_abc(const char *, int, int); void delay(int ms); bool confirmExit(); @@ -550,7 +557,6 @@ public: void updateMusic(); int musicStatus(); void updateRoom(); - bool loadGame(const char *); void updateDoor(int); void setPaletteBase(int darkness); void updateVisible(); @@ -568,7 +574,6 @@ public: void showCursor(); void hideCursor(); bool isCursorVisible(); - void enterName(); bool soundIsActive(); void waitFrameSSN(); void mixVideo(byte *OldScreen, byte *NewScreen, uint16 oldPitch); @@ -589,7 +594,6 @@ public: void quadrant_2(); void quadrant_3(); void quadrant_4(); - void saveGame(const char *gameName); void increaseFrameNum(); int whichObject(); bool checkMenuFlags(); @@ -650,63 +654,56 @@ public: bool room_62(int); bool room_102(int); - void animation_1_1(); - void animation_2_1(); - void animation_3_1(); - void animation_4_1(); - // - void animation_2_2(); - void animation_4_2(); - void animation_5_2(); - void animation_6_2(); - void animation_7_2(); - void animation_11_2(); - void animation_12_2(); - void animation_13_2(); - void animation_14_2(); void asco(); - void animation_16_2(); - void animation_20_2(); - void animation_23_2(); - void animation_23_joined(); - void animation_23_joined2(); - void animation_24_2(); - void animation_25_2(); - void animation_26_2(); - void animation_27_2(); - void animation_29_2(); - void animation_31_2(); - void animation_32_2(); - void animation_33_2(); - void animation_34_2(); - void animation_35_2(); - void animation_36_2(); + + void animation_1_1(); // Game introduction + void animation_2_1(); // John falls in love with BJ, who is then abducted by Drascula + void animation_3_1(); // John talks with the bartender to book a room + void animation_4_1(); // John talks with the pianist + // + void animation_2_2(); // John enters the chapel via the window + void animation_4_2(); // John talks with the blind man (closeup) + void animation_5_2(); // John breaks the chapel window with the pike + void animation_6_2(); // The blind man (closeup) thanks John for giving him money and hands him the sickle + void animation_7_2(); // John uses the sickle + void animation_11_2(); // The drunk man says "they're all dead, thanks *hic*" + void animation_12_2(); // Conversation screen - John talks to the pianist after BJ is abducted by Drascula + void animation_13_2(); // ??? + void animation_14_2(); // The glass box falls from the ceiling + void animation_16_2(); // The drunk tells us about Von Braun + void animation_20_2(); // Von Braun tells John that he needs to have special skills to fight vampires + void animation_23_2(); // Von Braun tests John's reactions to scratching noises + void animation_24_2(); // Conversation screen - John talks with Von Braun + void animation_25_2(); // The glass box is lifted back to the ceiling + void animation_26_2(); // John gives the book to the pianist and gets his earplugs in return + void animation_27_2(); // Von Braun admits that John is ready to fight vampires and gives him his money back + void animation_29_2(); // Von Braun tells John what ingredients he needs for the brew + void animation_31_2(); // Von Braun obtains the items needed for the brew from John and creates it + void animation_34_2(); // John kicks an object + void animation_35_2(); // John jumps into the well + void animation_36_2(); // John asks the bartender about the pianist // - void animation_2_3(); - void animation_3_3(); - void animation_4_3(); - void animation_5_3(); - void animation_6_3(); - void animation_ray(); + void animation_2_3(); // John uses the cross with the Frankenstein-zombie ("yoda") and destroys him + void animation_6_3(); // Frankenstein is blocking John's path // - void animation_1_4(); - void animation_5_4(); - void animation_6_4(); - void animation_7_4(); - void animation_8_4(); + void animation_castle(); // Chapter 4 start - Drascula's castle exterior, lightning strikes + void animation_1_4(); // Conversation screen - John talks with Igor + void animation_5_4(); // John enters Igor's room dressed as Drascula + void animation_6_4(); // Igor says that he's going for supper + void animation_7_4(); // John removes Drascula's disguise + void animation_8_4(); // Secret passage behind bookcase is revealed // - void animation_1_5(); - void animation_5_5(); - void animation_11_5(); - void animation_12_5(); - void animation_13_5(); - void animation_14_5(); + void animation_1_5(); // John finds BJ + void animation_5_5(); // ??? + void animation_12_5(); // Frankenstein comes to life + void animation_12_5_frankenstein(); + void animation_14_5(); // John finds out that an object is empty // - void animation_1_6(); - void animation_5_6(); - void animation_6_6(); - void animation_9_6(); - void animation_19_6(); + void animation_1_6(); // ??? + void animation_5_6(); // John is tied to the table. Drascula and Igor lower the pendulum + void animation_6_6(); // John uses the pendulum to break free + void animation_9_6(); // Game ending - John uses the cross on Drascula and reads BJ's letter + void animation_19_6(); // Someone pops up from behind a door when trying to open it void update_1_pre(); void update_2(); @@ -778,7 +775,7 @@ private: RoomUpdate *_roomPreUpdates, *_roomUpdates; RoomTalkAction *_roomActions; TalkSequenceCommand *_talkSequences; - char _saveNames[10][23]; + Common::String _saveNames[10]; char **loadTexts(Common::File &in); void freeTexts(char **ptr); diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 590561f0bd..3bdf724670 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -668,7 +668,7 @@ bool DrasculaEngine::animate(const char *animationFile, int FPS) { } delete stream; - return ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)); + return ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE) || shouldQuit()); } } // End of namespace Drascula diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index 4b8db63bb7..70212db9e8 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -153,52 +153,6 @@ void DrasculaEngine::clearMenu() { } } -void DrasculaEngine::enterName() { - Common::KeyCode key; - flushKeyBuffer(); - int v = 0, h = 0; - char select2[23]; - strcpy(select2, " "); - while (!shouldQuit()) { - select2[v] = '-'; - copyBackground(115, 14, 115, 14, 176, 9, bgSurface, screenSurface); - print_abc(select2, 117, 15); - updateScreen(); - - key = getScan(); - - if (key != 0) { - if (key >= 0 && key <= 0xFF && isAlpha(key)) - select2[v] = tolower(key); - else if ((key >= Common::KEYCODE_0 && key <= Common::KEYCODE_9) || key == Common::KEYCODE_SPACE) - select2[v] = key; - else if (key == Common::KEYCODE_ESCAPE) - break; - else if (key == Common::KEYCODE_RETURN) { - select2[v] = '\0'; - h = 1; - break; - } else if (key == Common::KEYCODE_BACKSPACE) - select2[v] = '\0'; - else - v--; - - if (key == Common::KEYCODE_BACKSPACE) - v--; - else - v++; - } - if (v == 22) - v = 21; - else if (v == -1) - v = 0; - } - if (h == 1) { - strcpy(select, select2); - selectionMade = 1; - } -} - bool DrasculaEngine::checkMenuFlags() { int n = whichObject(); if (n != 0) { @@ -213,8 +167,8 @@ void DrasculaEngine::showMap() { _hasName = false; for (int l = 0; l < numRoomObjs; l++) { - if (mouseX > x1[l] && mouseY > y1[l] - && mouseX < x2[l] && mouseY < y2[l] + if (mouseX > _objectX1[l] && mouseY > _objectY1[l] + && mouseX < _objectX2[l] && mouseY < _objectY2[l] && visible[l] == 1) { strcpy(textName, objName[l]); _hasName = true; diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp index 07b8464de4..f9f68c3317 100644 --- a/engines/drascula/objects.cpp +++ b/engines/drascula/objects.cpp @@ -100,8 +100,8 @@ void DrasculaEngine::checkObjects() { int l, veo = 0; for (l = 0; l < numRoomObjs; l++) { - if (mouseX > x1[l] && mouseY > y1[l] - && mouseX < x2[l] && mouseY < y2[l] + if (mouseX > _objectX1[l] && mouseY > _objectY1[l] + && mouseX < _objectX2[l] && mouseY < _objectY2[l] && visible[l] == 1 && isDoor[l] == 0) { strcpy(textName, objName[l]); _hasName = true; diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index 9f725b6d76..9f707eaa07 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -374,16 +374,16 @@ bool DrasculaEngine::room_8(int fl) { } bool DrasculaEngine::room_9(int fl) { - if (pickedObject == kVerbTalk && fl == 51 && flags[4] == 0) + // Talking with the blind man + if (pickedObject == kVerbTalk && fl == 51) { animation_4_2(); - else if (pickedObject == kVerbTalk && fl == 51 && flags[4] == 1) - animation_33_2(); - else if (pickedObject == 7 && fl == 51) { + } else if (pickedObject == 7 && fl == 51) { animation_6_2(); removeObject(kItemMoney); - pickObject(14);} - else + pickObject(14); + } else { hasAnswer = 0; + } return true; } @@ -837,9 +837,9 @@ bool DrasculaEngine::room_35(int fl) { } bool DrasculaEngine::room_49(int fl) { - if (pickedObject == kVerbTalk && fl ==51) + if (pickedObject == kVerbTalk && fl == 51) converse(9); - else if ((pickedObject == 8 && fl == 51) || (pickedObject == 8 && fl == 203)) + else if (pickedObject == 8 && (fl == 51 || fl == 203)) animation_5_5(); else hasAnswer = 0; @@ -852,7 +852,13 @@ bool DrasculaEngine::room_53(int fl) { pickObject(16); visible[3] = 0; } else if (pickedObject == kVerbMove && fl == 123) { - animation_11_5(); + flags[9] = 1; + if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1) { + animation_12_5(); + } else { + flags[9] = 0; + talk(33); + } } else if (pickedObject == 12 && fl == 52) { flags[3] = 1; talk(401); @@ -1649,7 +1655,7 @@ bool DrasculaEngine::room(int rN, int fl) { } } - // We did not find any parser, let default one work + // We did not find any parser, let the default one work hasAnswer = 0; } @@ -1706,10 +1712,10 @@ void DrasculaEngine::enterRoom(int roomIndex) { for (l = 0; l < numRoomObjs; l++) { p.parseInt(objectNum[l]); p.parseString(objName[l]); - p.parseInt(x1[l]); - p.parseInt(y1[l]); - p.parseInt(x2[l]); - p.parseInt(y2[l]); + p.parseInt(_objectX1[l]); + p.parseInt(_objectY1[l]); + p.parseInt(_objectX2[l]); + p.parseInt(_objectY2[l]); p.parseInt(roomObjX[l]); p.parseInt(roomObjY[l]); p.parseInt(trackObj[l]); diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp index 35e3821dc4..ba4148fb76 100644 --- a/engines/drascula/saveload.cpp +++ b/engines/drascula/saveload.cpp @@ -21,218 +21,270 @@ */ #include "common/textconsole.h" +#include "common/translation.h" + +#include "engines/savestate.h" +#include "graphics/thumbnail.h" +#include "gui/message.h" +#include "gui/saveload.h" #include "drascula/drascula.h" namespace Drascula { -/** - * Loads the save names from the EPA index file. - * - * TODO: We should move the save names in their respective save files and get - * rid of this completely. A good example is the sword1 engine, which also used - * to have an index file for its saves, that has been removed. - * sword1 contains code that converts the old index-based saves into the new - * format without the index file, so we could apply this idea to drascula as - * well. - */ -void DrasculaEngine::loadSaveNames() { - Common::InSaveFile *sav; - Common::String fileEpa = Common::String::format("%s.epa", _targetName.c_str()); - - // Create and initialize the index file, if it doesn't exist - if (!(sav = _saveFileMan->openForLoading(fileEpa))) { - Common::OutSaveFile *epa; - if (!(epa = _saveFileMan->openForSaving(fileEpa))) - error("Can't open %s file", fileEpa.c_str()); - for (int n = 0; n < NUM_SAVES; n++) - epa->writeString("*\n"); - epa->finalize(); - delete epa; - if (!(sav = _saveFileMan->openForLoading(fileEpa))) { - error("Can't open %s file", fileEpa.c_str()); - } +#define MAGIC_HEADER 0xD6A55A57 // (D)rascula (GA)me (S)cummVM (SA)ve (ST)ate +#define SAVEGAME_VERSION 1 + +void DrasculaEngine::checkForOldSaveGames() { + Common::String indexFileName = Common::String::format("%s.epa", _targetName.c_str()); + Common::InSaveFile *indexFile = _saveFileMan->openForLoading(indexFileName); + + // Check for the existence of an old index file + if (!indexFile) { + delete indexFile; + return; } - // Load the index file - for (int n = 0; n < NUM_SAVES; n++) { - strncpy(_saveNames[n], sav->readLine().c_str(), 23); - _saveNames[n][22] = '\0'; // make sure the savegame name is 0-terminated + GUI::MessageDialog dialog0( + _("ScummVM found that you have old savefiles for Drascula that should be converted.\n" + "The old save game format is no longer supported, so you will not be able to load your games if you don't convert them.\n\n" + "Press OK to convert them now, otherwise you will be asked again the next time you start the game.\n"), _("OK"), _("Cancel")); + + int choice = dialog0.runModal(); + if (choice == GUI::kMessageCancel) + return; + + // Convert every save slot we find in the index file to the new format + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::String pattern = Common::String::format("%s??", _targetName.c_str()); + + // Get list of savefiles for target game + Common::StringArray filenames = saveFileMan->listSavefiles(pattern); + Common::Array<int> slots; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 2 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 2); + + // Ensure save slot is within valid range + if (slotNum >= 1 && slotNum <= 10) { + slots.push_back(slotNum); + } } - delete sav; -} -/** - * Saves the save names into the EPA index file. - * - * TODO: We should move the save names in their respective save files and get - * rid of this completely. A good example is the sword1 engine, which also used - * to have an index file for its saves, that has been removed. - * sword1 contains code that converts the old index-based saves into the new - * format without the index file, so we could apply this idea to drascula as - * well. - */ -void DrasculaEngine::saveSaveNames() { - Common::OutSaveFile *tsav; - Common::String fileEpa = Common::String::format("%s.epa", _targetName.c_str()); + // Sort save slot ids + Common::sort<int>(slots.begin(), slots.end()); - if (!(tsav = _saveFileMan->openForSaving(fileEpa))) { - error("Can't open %s file", fileEpa.c_str()); - } - for (int n = 0; n < NUM_SAVES; n++) { - tsav->writeString(_saveNames[n]); - tsav->writeString("\n"); + // Get savegame names from index + Common::String saveDesc; + + int line = 1; + for (uint i = 0; i < slots.size(); i++) { + // Ignore lines corresponding to unused saveslots + for (; line < slots[i]; line++) + indexFile->readLine(); + + // Copy the name in the line corresponding to the save slot + saveDesc = indexFile->readLine(); + + // Handle cases where the save directory and save index are detectably out of sync + if (saveDesc == "*") + saveDesc = "No name specified."; + + // Increment line number to keep it in sync with slot number + line++; + + // Convert savegame + convertSaveGame(slots[i], saveDesc); } - tsav->finalize(); - delete tsav; -} -bool DrasculaEngine::saveLoadScreen() { - Common::String file; - int n, n2, num_sav = 0, y = 27; + delete indexFile; - clearRoom(); + // Remove index file + _saveFileMan->removeSavefile(indexFileName); +} - loadSaveNames(); +SaveStateDescriptor loadMetaData(Common::ReadStream *s, int slot, bool setPlayTime) { + uint32 sig = s->readUint32BE(); + byte version = s->readByte(); - loadPic("savescr.alg", bgSurface, HALF_PAL); + SaveStateDescriptor desc(-1, ""); // init to an invalid save slot - color_abc(kColorLightGreen); + if (sig != MAGIC_HEADER || version > SAVEGAME_VERSION) + return desc; - select[0] = 0; + // Save is valid, set its slot number + desc.setSaveSlot(slot); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - setCursor(kCursorCrosshair); + Common::String name; + byte size = s->readByte(); + for (int i = 0; i < size; ++i) + name += s->readByte(); + desc.setDescription(name); - while (!shouldQuit()) { - y = 27; - copyBackground(); - for (n = 0; n < NUM_SAVES; n++) { - print_abc(_saveNames[n], 116, y); - y = y + 9; - } - print_abc(select, 117, 15); - updateScreen(); - y = 27; + uint32 saveDate = s->readUint32LE(); + int day = (saveDate >> 24) & 0xFF; + int month = (saveDate >> 16) & 0xFF; + int year = saveDate & 0xFFFF; + desc.setSaveDate(year, month, day); - updateEvents(); + uint16 saveTime = s->readUint16LE(); + int hour = (saveTime >> 8) & 0xFF; + int minutes = saveTime & 0xFF; + desc.setSaveTime(hour, minutes); - if (leftMouseButton == 1) { - delay(50); - for (n = 0; n < NUM_SAVES; n++) { - if (mouseX > 115 && mouseY > y + (9 * n) && mouseX < 115 + 175 && mouseY < y + 10 + (9 * n)) { - strcpy(select, _saveNames[n]); - - if (strcmp(select, "*") != 0) - selectionMade = 1; - else { - enterName(); - strcpy(_saveNames[n], select); - if (selectionMade == 1) { - file = Common::String::format("%s%02d", _targetName.c_str(), n + 1); - saveGame(file.c_str()); - saveSaveNames(); - } - } + uint32 playTime = s->readUint32LE(); + desc.setPlayTime(playTime * 1000); + if (setPlayTime) + g_engine->setTotalPlayTime(playTime * 1000); - print_abc(select, 117, 15); - y = 27; - for (n2 = 0; n2 < NUM_SAVES; n2++) { - print_abc(_saveNames[n2], 116, y); - y = y + 9; - } - if (selectionMade == 1) { - file = Common::String::format("%s%02d", _targetName.c_str(), n + 1); - } - num_sav = n; - } - } + return desc; +} - if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && selectionMade == 1) { - enterName(); - strcpy(_saveNames[num_sav], select); - print_abc(select, 117, 15); - y = 27; - for (n2 = 0; n2 < NUM_SAVES; n2++) { - print_abc(_saveNames[n2], 116, y); - y = y + 9; - } +void saveMetaData(Common::WriteStream *s, Common::String &desc) { + TimeDate curTime; + g_system->getTimeAndDate(curTime); + + uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); + uint16 saveTime = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); + uint32 playTime = g_engine->getTotalPlayTime() / 1000; + + s->writeUint32BE(MAGIC_HEADER); + s->writeByte(SAVEGAME_VERSION); + s->writeByte(desc.size()); + s->writeString(desc); + s->writeUint32LE(saveDate); + s->writeUint16LE(saveTime); + s->writeUint32LE(playTime); +} - if (selectionMade == 1) { - file = Common::String::format("%s%02d", _targetName.c_str(), n + 1); - saveGame(file.c_str()); - saveSaveNames(); - } - } +void DrasculaEngine::convertSaveGame(int slot, Common::String &desc) { + Common::String oldFileName = Common::String::format("%s%02d", _targetName.c_str(), slot); + Common::String newFileName = Common::String::format("%s.%03d", _targetName.c_str(), slot); + Common::InSaveFile *oldFile = _saveFileMan->openForLoading(oldFileName); + if (!oldFile) + error("Can't open %s", oldFileName.c_str()); + Common::OutSaveFile *newFile = _saveFileMan->openForSaving(newFileName); + if (!newFile) + error("Can't open %s", newFileName.c_str()); + + // Read data from old file + int32 dataSize = oldFile->size(); + byte *buffer = new byte[dataSize]; + oldFile->read(buffer, dataSize); + + // First, write the appropriate meta data in the new file + saveMetaData(newFile, desc); + Graphics::saveThumbnail(*newFile); // basically, at this point this will capture a black screen + + // And then attach the actual save data + newFile->write(buffer, dataSize); + newFile->finalize(); + if (newFile->err()) + warning("Can't write file '%s'. (Disk full?)", newFileName.c_str()); + + delete[] buffer; + delete newFile; + delete oldFile; + + // Remove old save file + _saveFileMan->removeSavefile(oldFileName); +} - if (mouseX > 125 && mouseY > 123 && mouseX < 199 && mouseY < 149 && selectionMade == 1) { - if (!loadGame(file.c_str())) { - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - return false; - } - break; - } else if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149 && selectionMade == 1) { - saveGame(file.c_str()); - saveSaveNames(); - } else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180) - break; - else if (selectionMade == 0) { - print_abc("Please select a slot", 117, 15); - } - updateScreen(); - delay(200); +/** + * Loads the first 10 save names, to be used in Drascula's save/load screen + */ +void DrasculaEngine::loadSaveNames() { + Common::String saveFileName; + Common::InSaveFile *in; + + for (int n = 0; n < NUM_SAVES; n++) { + saveFileName = Common::String::format("%s.%03d", _targetName.c_str(), n + 1); + if ((in = _saveFileMan->openForLoading(saveFileName))) { + SaveStateDescriptor desc = loadMetaData(in, n + 1, false); + _saveNames[n] = desc.getDescription(); + delete in; } - y = 26; + } +} + +void DrasculaEngine::saveGame(int slot, Common::String &desc) { + Common::OutSaveFile *out; + int l; - delay(5); + Common::String saveFileName = Common::String::format("%s.%03d", _targetName.c_str(), slot); + if (!(out = _saveFileMan->openForSaving(saveFileName))) { + error("Unable to open the file"); } - selectVerb(kVerbNone); + saveMetaData(out, desc); + Graphics::saveThumbnail(*out); - clearRoom(); - loadPic(roomNumber, bgSurface, HALF_PAL); - selectionMade = 0; + // Actual save data follows + out->writeSint32LE(currentChapter); + out->write(currentData, 20); + out->writeSint32LE(curX); + out->writeSint32LE(curY); + out->writeSint32LE(trackProtagonist); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) { + out->writeSint32LE(inventoryObjects[l]); + } - return true; + for (l = 0; l < NUM_FLAGS; l++) { + out->writeSint32LE(flags[l]); + } + + out->writeSint32LE(takeObject); + out->writeSint32LE(pickedObject); + + out->finalize(); + if (out->err()) + warning("Can't write file '%s'. (Disk full?)", saveFileName.c_str()); + + delete out; } -bool DrasculaEngine::loadGame(const char *gameName) { +bool DrasculaEngine::loadGame(int slot) { int l, savedChapter, roomNum = 0; - Common::InSaveFile *sav; + Common::InSaveFile *in; previousMusic = roomMusic; _menuScreen = false; if (currentChapter != 1) clearRoom(); - if (!(sav = _saveFileMan->openForLoading(gameName))) { - error("missing savegame file"); + Common::String saveFileName = Common::String::format("%s.%03d", _targetName.c_str(), slot); + if (!(in = _saveFileMan->openForLoading(saveFileName))) { + error("missing savegame file %s", saveFileName.c_str()); } - savedChapter = sav->readSint32LE(); + loadMetaData(in, slot, true); + Graphics::skipThumbnail(*in); + + savedChapter = in->readSint32LE(); if (savedChapter != currentChapter) { - strcpy(saveName, gameName); + _currentSaveSlot = slot; currentChapter = savedChapter - 1; loadedDifferentChapter = 1; + delete in; return false; } - sav->read(currentData, 20); - curX = sav->readSint32LE(); - curY = sav->readSint32LE(); - trackProtagonist = sav->readSint32LE(); + + in->read(currentData, 20); + curX = in->readSint32LE(); + curY = in->readSint32LE(); + trackProtagonist = in->readSint32LE(); for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) { - inventoryObjects[l] = sav->readSint32LE(); + inventoryObjects[l] = in->readSint32LE(); } for (l = 0; l < NUM_FLAGS; l++) { - flags[l] = sav->readSint32LE(); + flags[l] = in->readSint32LE(); } - takeObject = sav->readSint32LE(); - pickedObject = sav->readSint32LE(); + takeObject = in->readSint32LE(); + pickedObject = in->readSint32LE(); loadedDifferentChapter = 0; if (!sscanf(currentData, "%d.ald", &roomNum)) { error("Bad save format"); @@ -243,35 +295,158 @@ bool DrasculaEngine::loadGame(const char *gameName) { return true; } -void DrasculaEngine::saveGame(const char *gameName) { - Common::OutSaveFile *out; - int l; +Common::String DrasculaEngine::enterName(Common::String &selectedName) { + Common::KeyCode key; + Common::String inputLine = selectedName; - if (!(out = _saveFileMan->openForSaving(gameName))) { - error("Unable to open the file"); + flushKeyBuffer(); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + + while (!shouldQuit()) { + copyBackground(115, 14, 115, 14, 176, 9, bgSurface, screenSurface); + print_abc((inputLine + "-").c_str(), 117, 15); + updateScreen(); + + key = getScan(); + + if (key != 0) { + if (key >= 0 && key <= 0xFF && isAlpha(key)) { + inputLine += tolower(key); + } else if ((key >= Common::KEYCODE_0 && key <= Common::KEYCODE_9) || key == Common::KEYCODE_SPACE) { + inputLine += key; + } else if (key == Common::KEYCODE_ESCAPE) { + inputLine.clear(); + break; + } else if (key == Common::KEYCODE_RETURN) { + break; + } else if (key == Common::KEYCODE_BACKSPACE) { + inputLine.deleteLastChar(); + } + } } - out->writeSint32LE(currentChapter); - out->write(currentData, 20); - out->writeSint32LE(curX); - out->writeSint32LE(curY); - out->writeSint32LE(trackProtagonist); - for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) { - out->writeSint32LE(inventoryObjects[l]); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); + return inputLine; +} + +bool DrasculaEngine::scummVMSaveLoadDialog(bool isSave) { + GUI::SaveLoadChooser *dialog; + Common::String desc; + int slot; + + if (isSave) { + dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + + slot = dialog->runModalWithCurrentTarget(); + desc = dialog->getResultString(); + + if (desc.empty()) { + // create our own description for the saved game, the user didnt enter it + desc = dialog->createDefaultSaveDescription(slot); + } + + if (desc.size() > 28) + desc = Common::String(desc.c_str(), 28); + } else { + dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + slot = dialog->runModalWithCurrentTarget(); } - for (l = 0; l < NUM_FLAGS; l++) { - out->writeSint32LE(flags[l]); + delete dialog; + + if (slot < 0) + return true; + + if (isSave) { + saveGame(slot, desc); + return true; + } else { + return loadGame(slot); } +} - out->writeSint32LE(takeObject); - out->writeSint32LE(pickedObject); +bool DrasculaEngine::saveLoadScreen() { + int n, selectedSlot = 0; + Common::String selectedName; - out->finalize(); - if (out->err()) - warning("Can't write file '%s'. (Disk full?)", gameName); + clearRoom(); + loadPic("savescr.alg", bgSurface, HALF_PAL); + color_abc(kColorLightGreen); + setCursor(kCursorCrosshair); + loadSaveNames(); - delete out; + while (!shouldQuit()) { + copyBackground(); + for (n = 0; n < NUM_SAVES; n++) { + print_abc(_saveNames[n].c_str(), 116, 27 + 9 * n); + } + print_abc(selectedName.c_str(), 117, 15); + + updateScreen(); + updateEvents(); + + if (leftMouseButton == 1) { + // Check if the user has clicked on a save slot + for (n = 0; n < NUM_SAVES; n++) { + if (mouseX > 115 && mouseY > 27 + (9 * n) && mouseX < 115 + 175 && mouseY < 27 + 10 + (9 * n)) { + selectedSlot = n; + selectedName = _saveNames[selectedSlot]; + if (selectedName.empty()) { + selectedName = enterName(selectedName); + if (!selectedName.empty()) + _saveNames[selectedSlot] = selectedName; // update save name + } + break; + } + } + + // Check if the user has clicked in the text area above the save slots + if (mouseX > 117 && mouseY > 15 && mouseX < 295 && mouseY < 24 && !selectedName.empty()) { + selectedName = enterName(selectedName); + if (!selectedName.empty()) + _saveNames[selectedSlot] = selectedName; // update save name + } + + // Check if the user has clicked a button + if (mouseX > 208 && mouseY > 123 && mouseX < 282 && mouseY < 149) { + // "Save" button + if (selectedName.empty()) { + print_abc("Please select a slot", 117, 15); + updateScreen(); + delay(200); + } else { + selectVerb(kVerbNone); + clearRoom(); + loadPic(roomNumber, bgSurface, HALF_PAL); + updateRoom(); + updateScreen(); + + saveGame(selectedSlot + 1, _saveNames[selectedSlot]); + return true; + } + } else if (mouseX > 125 && mouseY > 123 && mouseX < 199 && mouseY < 149) { + // "Load" button + if (selectedName.empty()) { + print_abc("Please select a slot", 117, 15); + updateScreen(); + delay(200); + } else { + return loadGame(selectedSlot + 1); + } + } else if (mouseX > 168 && mouseY > 154 && mouseX < 242 && mouseY < 180) { + // "Play" button + break; + } + } // if (leftMouseButton == 1) + + leftMouseButton = 0; + delay(10); + } + + selectVerb(kVerbNone); + clearRoom(); + loadPic(roomNumber, bgSurface, HALF_PAL); + return true; } } // End of namespace Drascula diff --git a/engines/dreamweb/backdrop.cpp b/engines/dreamweb/backdrop.cpp index 1db2663624..5ccc68704a 100644 --- a/engines/dreamweb/backdrop.cpp +++ b/engines/dreamweb/backdrop.cpp @@ -25,35 +25,35 @@ namespace DreamWeb { void DreamWebEngine::doBlocks() { - uint16 dstOffset = _mapAdY * 320 + _mapAdX; + uint16 dstOffset = _mapAdY * kScreenwidth + _mapAdX; uint16 mapOffset = _mapY * kMapWidth + _mapX; const uint8 *mapData = _mapData + mapOffset; uint8 *dstBuffer = workspace() + dstOffset; - for (size_t i = 0; i < 10; ++i) { - for (size_t j = 0; j < 11; ++j) { + for (uint i = 0; i < 10; ++i) { + for (uint j = 0; j < 11; ++j) { uint16 blockType = mapData[j]; if (blockType != 0) { - uint8 *dst = dstBuffer + i * 320 * 16 + j * 16; + uint8 *dst = dstBuffer + i * kScreenwidth * 16 + j * 16; const uint8 *block = _backdropBlocks + blockType * 256; - for (size_t k = 0; k < 4; ++k) { + for (uint k = 0; k < 4; ++k) { memcpy(dst, block, 16); block += 16; - dst += 320; + dst += kScreenwidth; } - for (size_t k = 0; k < 12; ++k) { + for (uint k = 0; k < 12; ++k) { memcpy(dst, block, 16); memset(dst + 16, 0xdf, 4); block += 16; - dst += 320; + dst += kScreenwidth; } dst += 4; memset(dst, 0xdf, 16); - dst += 320; + dst += kScreenwidth; memset(dst, 0xdf, 16); - dst += 320; + dst += kScreenwidth; memset(dst, 0xdf, 16); - dst += 320; + dst += kScreenwidth; memset(dst, 0xdf, 16); } } @@ -129,7 +129,7 @@ void DreamWebEngine::showAllObs() { _setList.clear(); const GraphicsFile &frameBase = _setFrames; - for (size_t i = 0; i < 128; ++i) { + for (uint i = 0; i < 128; ++i) { SetObject *setEntry = &_setDat[i]; uint16 x, y; if (getMapAd(setEntry->mapad, &x, &y) == 0) @@ -154,7 +154,7 @@ void DreamWebEngine::showAllObs() { } static bool addAlong(const MapFlag *mapFlags) { - for (size_t i = 0; i < 11; ++i) { + for (uint i = 0; i < 11; ++i) { if (mapFlags[i]._flag != 0) return true; } @@ -162,7 +162,7 @@ static bool addAlong(const MapFlag *mapFlags) { } static bool addLength(const MapFlag *mapFlags) { - for (size_t i = 0; i < 10; ++i) { + for (uint i = 0; i < 10; ++i) { if (mapFlags[11 * i]._flag != 0) return true; } @@ -205,13 +205,13 @@ void DreamWebEngine::calcMapAd() { } void DreamWebEngine::showAllFree() { - const unsigned int count = 80; + const uint count = 80; _freeList.clear(); const DynObject *freeObjects = _freeDat; const GraphicsFile &frameBase = _freeFrames; - for (size_t i = 0; i < count; ++i) { + for (uint i = 0; i < count; ++i) { uint16 x, y; uint8 mapAd = getMapAd(freeObjects[i].mapad, &x, &y); if (mapAd != 0) { @@ -236,8 +236,8 @@ void DreamWebEngine::drawFlags() { uint16 mapOffset = _mapY * kMapWidth + _mapX; const uint8 *mapData = _mapData + mapOffset; - for (size_t i = 0; i < 10; ++i) { - for (size_t j = 0; j < 11; ++j) { + for (uint i = 0; i < 10; ++i) { + for (uint j = 0; j < 11; ++j) { uint8 tile = mapData[i * kMapWidth + j]; mapFlag->_flag = _backdropFlags[tile]._flag; mapFlag->_flagEx = _backdropFlags[tile]._flagEx; @@ -248,13 +248,13 @@ void DreamWebEngine::drawFlags() { } void DreamWebEngine::showAllEx() { - const unsigned int count = 100; + const uint count = 100; _exList.clear(); DynObject *objects = _exData; const GraphicsFile &frameBase = _exFrames; - for (size_t i = 0; i < count; ++i) { + for (uint i = 0; i < count; ++i) { DynObject *object = objects + i; if (object->mapad[0] == 0xff) continue; diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index 5f5d627553..c3ede46df2 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -208,7 +208,7 @@ DreamWebEngine::DreamWebEngine(OSystem *syst, const DreamWebGameDescription *gam _addToRed = 0; _addToBlue = 0; _lastSoundReel = 0; - _lastHardKey = 0; + _lastHardKey = Common::KEYCODE_INVALID; _bufferIn = 0; _bufferOut = 0; _blinkFrame = 23; @@ -263,7 +263,7 @@ void DreamWebEngine::waitForVSync() { void DreamWebEngine::quit() { _quitRequested = true; - _lastHardKey = 1; + _lastHardKey = Common::KEYCODE_ESCAPE; } void DreamWebEngine::processEvents() { @@ -274,7 +274,7 @@ void DreamWebEngine::processEvents() { _sound->soundHandler(); Common::Event event; - int softKey, hardKey; + int softKey; while (_eventMan->pollEvent(event)) { switch(event.type) { case Common::EVENT_RTL: @@ -309,28 +309,21 @@ void DreamWebEngine::processEvents() { return; //do not pass ctrl + key to the engine } - // Some parts of the ASM code uses the hardware key - // code directly. We don't have that code, so we fake - // it for the keys where it's needed and assume it's - // 0 (which is actually an invalid value, as far as I - // know) otherwise. - - hardKey = 0; + // Some parts of the code uses the hardware key + // code directly. switch (event.kbd.keycode) { case Common::KEYCODE_ESCAPE: - hardKey = 1; + _lastHardKey = Common::KEYCODE_ESCAPE; break; case Common::KEYCODE_SPACE: - hardKey = 57; + _lastHardKey = Common::KEYCODE_SPACE; break; default: - hardKey = 0; + _lastHardKey = Common::KEYCODE_INVALID; break; } - _lastHardKey = hardKey; - // The rest of the keys are converted to ASCII. This // is fairly restrictive, and eventually we may want // to let through more keys. I think this is mostly to @@ -338,11 +331,13 @@ void DreamWebEngine::processEvents() { softKey = 0; - if (event.kbd.keycode >= Common::KEYCODE_a && event.kbd.keycode <= Common::KEYCODE_z) { - softKey = event.kbd.ascii & ~0x20; - } else if (event.kbd.keycode == Common::KEYCODE_MINUS || - event.kbd.keycode == Common::KEYCODE_SPACE || - (event.kbd.keycode >= Common::KEYCODE_0 && event.kbd.keycode <= Common::KEYCODE_9)) { + debug(1, "DreamWebEngine::processEvents() KeyDown keycode:%d ascii:0x%02x", event.kbd.keycode, event.kbd.ascii); + if ((event.kbd.ascii >= 'a' && event.kbd.ascii <= 'z') || + (event.kbd.ascii >= 'A' && event.kbd.ascii <= 'Z')) { + softKey = event.kbd.ascii & ~0x20; // (& ~0x20) forces ascii codes for a-z to map to A-Z + } else if (event.kbd.ascii == '-' || + event.kbd.ascii == ' ' || + (event.kbd.ascii >= '0' && event.kbd.ascii <= '9')) { softKey = event.kbd.ascii; } else if (event.kbd.keycode >= Common::KEYCODE_KP0 && event.kbd.keycode <= Common::KEYCODE_KP9) { softKey = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; @@ -374,6 +369,7 @@ Common::Error DreamWebEngine::run() { ConfMan.registerDefault("bright_palette", true); _hasSpeech = Common::File::exists(_speechDirName + "/r01c0000.raw") && !ConfMan.getBool("speech_mute"); _brightPalette = ConfMan.getBool("bright_palette"); + _copyProtection = ConfMan.getBool("copy_protection"); _timer->installTimerProc(vSyncInterrupt, 1000000 / 70, this, "dreamwebVSync"); dreamweb(); @@ -403,14 +399,14 @@ Common::String DreamWebEngine::getSavegameFilename(int slot) const { void DreamWebEngine::keyPressed(uint16 ascii) { debug(2, "key pressed = %04x", ascii); - uint16 in = (_bufferIn + 1) & 0x0f; + uint16 in = (_bufferIn + 1) % ARRAYSIZE(_keyBuffer); uint16 out = _bufferOut; if (in == out) { warning("keyboard buffer is full"); return; } _bufferIn = in; - DreamWeb::g_keyBuffer[in] = ascii; + _keyBuffer[in] = ascii; } void DreamWebEngine::getPalette(uint8 *data, uint start, uint count) { @@ -421,7 +417,7 @@ void DreamWebEngine::getPalette(uint8 *data, uint start, uint count) { void DreamWebEngine::setPalette(const uint8 *data, uint start, uint count) { assert(start + count <= 256); - uint8 fixed[768]; + uint8 fixed[3*256]; for (uint i = 0; i < count * 3; ++i) { fixed[i] = data[i] << 2; } @@ -429,10 +425,10 @@ void DreamWebEngine::setPalette(const uint8 *data, uint start, uint count) { } void DreamWebEngine::blit(const uint8 *src, int pitch, int x, int y, int w, int h) { - if (y + h > 200) - h = 200 - y; - if (x + w > 320) - w = 320 - x; + if (y + h > (int)kScreenheight) + h = kScreenheight - y; + if (x + w > (int)kScreenwidth) + w = kScreenwidth - x; if (h <= 0 || w <= 0) return; _system->copyRectToScreen(src, pitch, x, y, w, h); diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h index a4597b1867..eb35a73f66 100644 --- a/engines/dreamweb/dreamweb.h +++ b/engines/dreamweb/dreamweb.h @@ -25,6 +25,7 @@ #include "common/error.h" #include "common/file.h" +#include "common/keyboard.h" #include "common/random.h" #include "common/rect.h" #include "common/savefile.h" @@ -63,6 +64,7 @@ const unsigned int kMapHeight = 60; const unsigned int kLengthOfMap = kMapWidth * kMapHeight; const unsigned int kNumExObjects = 114; const unsigned int kScreenwidth = 320; +const unsigned int kScreenheight = 200; const unsigned int kDiaryx = (68+24); const unsigned int kDiaryy = (48+12); const unsigned int kInventx = 80; @@ -88,10 +90,6 @@ const unsigned int kNumRoomTexts = 38; const unsigned int kNumFreeTexts = 82; const unsigned int kNumPersonTexts = 1026; -// Keyboard buffer. data.word(kBufferin) and data.word(kBufferout) are indexes -// into this, making it a ring buffer -extern uint8 g_keyBuffer[16]; - // Engine Debug Flags enum { kDebugAnimation = (1 << 0), @@ -156,6 +154,12 @@ public: const Common::String& getSpeechDirName() { return _speechDirName; } private: + // Keyboard buffer. _bufferIn and _bufferOut are indexes + // into this, making it a ring buffer + uint8 _keyBuffer[16]; + uint16 _bufferIn; + uint16 _bufferOut; + void keyPressed(uint16 ascii); void setSpeed(uint speed); @@ -316,6 +320,7 @@ public: uint16 _charShift; uint8 _kerning; bool _brightPalette; + bool _copyProtection; uint8 _roomLoaded; uint8 _didZoom; uint16 _lineSpacing; @@ -419,9 +424,7 @@ public: uint8 _addToRed; uint8 _addToBlue; uint16 _lastSoundReel; - uint8 _lastHardKey; - uint16 _bufferIn; - uint16 _bufferOut; + Common::KeyCode _lastHardKey; uint8 _blinkFrame; uint8 _blinkCount; uint8 _reAssesChanges; @@ -750,7 +753,6 @@ public: void showRyanPage(); void switchRyanOn(); void switchRyanOff(); - void middlePanel(); void showDiary(); void readMouse(); uint16 readMouseState(); @@ -882,7 +884,6 @@ public: void obsThatDoThings(); void describeOb(); void putBackObStuff(); - void reExFromOpen(); void showDiaryPage(); void showDiaryKeys(); void dumpDiaryKeys(); diff --git a/engines/dreamweb/keypad.cpp b/engines/dreamweb/keypad.cpp index 3580f8ad52..7bbca2b979 100644 --- a/engines/dreamweb/keypad.cpp +++ b/engines/dreamweb/keypad.cpp @@ -103,7 +103,6 @@ void DreamWebEngine::enterCode(uint8 digit0, uint8 digit1, uint8 digit2, uint8 d // Note: isItRight comes from use.asm, but is only used by enterCode(), // so we place it here. bool DreamWebEngine::isItRight(uint8 digit0, uint8 digit1, uint8 digit2, uint8 digit3) { - return digit0 == _pressList[0] && digit1 == _pressList[1] && digit2 == _pressList[2] && digit3 == _pressList[3]; } @@ -434,7 +433,7 @@ void DreamWebEngine::folderExit() { void DreamWebEngine::showLeftPage() { showFrame(_folderGraphics2, 0, 12, 3, 0); uint16 y = 12+5; - for (size_t i = 0; i < 9; ++i) { + for (uint i = 0; i < 9; ++i) { showFrame(_folderGraphics2, 0, y, 4, 0); y += 16; } @@ -445,7 +444,7 @@ void DreamWebEngine::showLeftPage() { uint8 pageIndex = _folderPage - 2; const uint8 *string = getTextInFile1(pageIndex * 2); y = 48; - for (size_t i = 0; i < 2; ++i) { + for (uint i = 0; i < 2; ++i) { uint8 lastChar; do { lastChar = printDirect(&string, 2, &y, 140, false); @@ -455,19 +454,19 @@ void DreamWebEngine::showLeftPage() { _kerning = 0; _charShift = 0; _lineSpacing = 10; - uint8 *bufferToSwap = workspace() + (48*320)+2; - for (size_t i = 0; i < 120; ++i) { - for (size_t j = 0; j < 65; ++j) { + uint8 *bufferToSwap = workspace() + (48*kScreenwidth)+2; + for (uint i = 0; i < 120; ++i) { + for (uint j = 0; j < 65; ++j) { SWAP(bufferToSwap[j], bufferToSwap[130 - j]); } - bufferToSwap += 320; + bufferToSwap += kScreenwidth; } } void DreamWebEngine::showRightPage() { showFrame(_folderGraphics2, 143, 12, 0, 0); uint16 y = 12+37; - for (size_t i = 0; i < 7; ++i) { + for (uint i = 0; i < 7; ++i) { showFrame(_folderGraphics2, 143, y, 1, 0); y += 16; } @@ -478,7 +477,7 @@ void DreamWebEngine::showRightPage() { uint8 pageIndex = _folderPage - 1; const uint8 *string = getTextInFile1(pageIndex * 2); y = 48; - for (size_t i = 0; i < 2; ++i) { + for (uint i = 0; i < 2; ++i) { uint8 lastChar; do { lastChar = printDirect(&string, 152, &y, 140, false); diff --git a/engines/dreamweb/monitor.cpp b/engines/dreamweb/monitor.cpp index 1886a80b6a..b6922cba51 100644 --- a/engines/dreamweb/monitor.cpp +++ b/engines/dreamweb/monitor.cpp @@ -149,6 +149,13 @@ bool DreamWebEngine::execCommand() { return true; case 1: monMessage(6); + // An extra addition in ScummVM: available commands. + // Since the reference to the game manual is a form of copy protection, + // this extra text is wrapped around the common copy protection check, + // to keep it faithful to the original, if requested. + if (!_copyProtection) { + monPrint("VALID COMMANDS ARE EXIT, HELP, LIST, READ, LOGON, KEYS"); + } break; case 2: dirCom(); @@ -366,7 +373,7 @@ void DreamWebEngine::lockLightOff() { } void DreamWebEngine::turnOnPower() { - for (size_t i = 0; i < 3; ++i) { + for (uint i = 0; i < 3; ++i) { powerLightOn(); hangOn(30); powerLightOff(); diff --git a/engines/dreamweb/object.cpp b/engines/dreamweb/object.cpp index 1e84aba6bd..bee3a6d511 100644 --- a/engines/dreamweb/object.cpp +++ b/engines/dreamweb/object.cpp @@ -31,7 +31,7 @@ void DreamWebEngine::showRyanPage() { void DreamWebEngine::findAllRyan() { memset(_ryanInvList, 0xff, sizeof(_ryanInvList)); - for (size_t i = 0; i < kNumexobjects; ++i) { + for (uint i = 0; i < kNumexobjects; ++i) { const DynObject *extra = getExAd(i); if (extra->mapad[0] != kExObjectType) continue; @@ -47,8 +47,8 @@ void DreamWebEngine::findAllRyan() { void DreamWebEngine::fillRyan() { ObjectRef *inv = &_ryanInvList[_vars._ryanPage * 10]; findAllRyan(); - for (size_t i = 0; i < 2; ++i) { - for (size_t j = 0; j < 5; ++j) { + for (uint i = 0; i < 2; ++i) { + for (uint j = 0; j < 5; ++j) { obToInv(inv->_index, inv->_type, kInventx + j * kItempicsize, kInventy + i * kItempicsize); ++inv; } @@ -435,10 +435,23 @@ void DreamWebEngine::deleteExFrame(uint8 frameNum) { _vars._exFramePos -= frameSize; // Adjust all frame pointers pointing into the shifted data - for (unsigned int i = 0; i < 3*kNumexobjects; ++i) { - frame = &_exFrames._frames[i]; - if (frame->ptr() >= startOff) - frame->setPtr(frame->ptr() - frameSize); + for (unsigned int i = 0; i < kNumexobjects; ++i) { + if (_exData[i].mapad[0] != 0xff) { + frame = &_exFrames._frames[3*i+0]; + if (frame->ptr() >= startOff) { + frame->setPtr(frame->ptr() - frameSize); + assert(frame->ptr() + frame->width*frame->height <= _vars._exFramePos); + } else { + assert(frame->ptr() + frame->width*frame->height <= startOff); + } + frame = &_exFrames._frames[3*i+1]; + if (frame->ptr() >= startOff) { + frame->setPtr(frame->ptr() - frameSize); + assert(frame->ptr() + frame->width*frame->height <= _vars._exFramePos); + } else { + assert(frame->ptr() + frame->width*frame->height <= startOff); + } + } } } @@ -875,7 +888,7 @@ void DreamWebEngine::useOpened() { void DreamWebEngine::outOfOpen() { if (_openedOb == 255) - return; // cannot use opened object + return; // cannot use opened object ObjectRef objectId = findOpenPos(); @@ -892,13 +905,10 @@ void DreamWebEngine::outOfOpen() { } if (_mouseButton == _oldButton) - return; // notletgo4 + return; // notletgo4 - if (_mouseButton != 1) { - if (_mouseButton == 2) - reExFromOpen(); + if (_mouseButton != 1) return; - } delPointer(); _pickUp = 1; @@ -1102,4 +1112,136 @@ void DreamWebEngine::pickupConts(uint8 from, uint8 containerEx) { } } +void DreamWebEngine::incRyanPage() { + commandOnlyCond(31, 222); + + if (_mouseButton == _oldButton || !(_mouseButton & 1)) + return; + + _vars._ryanPage = (_mouseX - (kInventx + 167)) / 18; + + delPointer(); + fillRyan(); + readMouse(); + showPointer(); + workToScreen(); + delPointer(); +} + +void DreamWebEngine::emergencyPurge() { + debug(2, "Ex memory: frames %d/%d, text %d/%d", _vars._exFramePos, kExframeslen, _vars._exTextPos, kExtextlen); + + while (_vars._exFramePos + 4000 >= kExframeslen || + _vars._exTextPos + 400 >= kExtextlen) + { + purgeAnItem(); + debug(2, "Ex memory after purging: frames %d/%d, text %d/%d", _vars._exFramePos, kExframeslen, _vars._exTextPos, kExtextlen); + } +} + +void DreamWebEngine::purgeAnItem() { + const DynObject *extraObjects = _exData; + + + for (uint i = 0; i < kNumexobjects; ++i) { + if (extraObjects[i].mapad[0] == 0 && + (extraObjects[i].objId[0] == 255 || extraObjects[i].objId[0] == 2) && + extraObjects[i].initialLocation != _realLocation) { + debug(1, "Purging ex object %d", i); + deleteExObject(i); + return; + } + } + + for (uint i = 0; i < kNumexobjects; ++i) { + if (extraObjects[i].mapad[0] == 0 && extraObjects[i].objId[0] == 255) { + debug(1, "Purging ex object %d", i); + deleteExObject(i); + return; + } + } + + error("Out of Ex object memory"); +} + +void DreamWebEngine::dropError() { + _commandType = 255; + delPointer(); + printMessage(76, 21, 56, 240, 240 & 1); + workToScreenM(); + hangOnP(50); + showPanel(); + showMan(); + examIcon(); + _commandType = 255; + workToScreenM(); +} + +void DreamWebEngine::cantDrop() { + _commandType = 255; + delPointer(); + printMessage(76, 21, 24, 240, 240 & 1); + workToScreenM(); + hangOnP(50); + showPanel(); + showMan(); + examIcon(); + _commandType = 255; + workToScreenM(); +} + +void DreamWebEngine::examineInventory() { + commandOnlyCond(32, 249); + + if (!(_mouseButton & 1)) + return; + + createPanel(); + showPanel(); + showMan(); + showExit(); + examIcon(); + _pickUp = 0; + _invOpen = 2; + openInv(); + workToScreenM(); +} + +void DreamWebEngine::openInv() { + _invOpen = 1; + printMessage(80, 58 - 10, 61, 240, (240 & 1)); + fillRyan(); + _commandType = 255; +} + +void DreamWebEngine::pickupOb(uint8 command, uint8 pos) { + _lastInvPos = pos; + _objectType = kFreeObjectType; + _itemFrame = command; + _command = command; + //uint8 dummy; + //getAnyAd(&dummy, &dummy); // was in the original source, seems useless here + transferToEx(command); +} + +void DreamWebEngine::initialInv() { + if (_realLocation != 24) + return; + + pickupOb(11, 5); + pickupOb(12, 6); + pickupOb(13, 7); + pickupOb(14, 8); + pickupOb(18, 0); + pickupOb(19, 1); + pickupOb(20, 9); + pickupOb(16, 2); + _vars._watchMode = 1; + _vars._reelToHold = 0; + _vars._endOfHoldReel = 6; + _vars._watchSpeed = 1; + _vars._speedCount = 1; + switchRyanOff(); +} + } // End of namespace DreamWeb diff --git a/engines/dreamweb/pathfind.cpp b/engines/dreamweb/pathfind.cpp index c39070532c..64cffde4de 100644 --- a/engines/dreamweb/pathfind.cpp +++ b/engines/dreamweb/pathfind.cpp @@ -110,7 +110,7 @@ void DreamWebEngine::checkDest(const RoomPaths *roomsPaths) { const PathSegment *segments = roomsPaths->segments; const uint8 tmp = _mansPath << 4; uint8 destination = _destination; - for (size_t i = 0; i < 24; ++i) { + for (uint i = 0; i < 24; ++i) { if ((segments[i].b0 & 0xf0) == tmp && (segments[i].b0 & 0x0f) == _destination) { _destination = segments[i].b1 & 0x0f; diff --git a/engines/dreamweb/people.cpp b/engines/dreamweb/people.cpp index dbb81406cd..53f04d482b 100644 --- a/engines/dreamweb/people.cpp +++ b/engines/dreamweb/people.cpp @@ -194,7 +194,7 @@ void DreamWebEngine::madman(ReelRoutine &routine) { if (newReelPointer == 66) { ++_vars._combatCount; - if (_lastHardKey == 1) // ESC pressed, skip the mad man's speech + if (_lastHardKey == Common::KEYCODE_ESCAPE) // ESC pressed, skip the mad man's speech _vars._combatCount = _speechCount = (hasSpeech() ? 65 : 63); madmanText(); diff --git a/engines/dreamweb/print.cpp b/engines/dreamweb/print.cpp index 64b9849980..bc75b97e71 100644 --- a/engines/dreamweb/print.cpp +++ b/engines/dreamweb/print.cpp @@ -49,7 +49,9 @@ uint8 DreamWebEngine::getNextWord(const GraphicsFile &charSet, const uint8 *stri return 0; } firstChar = modifyChar(firstChar); - if (firstChar != 255) { + // WORKAROUND: Also filter out invalid characters here (refer to the + // workaround in printChar() below for more info). + if (firstChar >= 32 && firstChar != 255) { uint8 secondChar = *string; uint8 width = charSet._frames[firstChar - 32 + _charShift].width; width = kernChars(firstChar, secondChar, width); @@ -59,9 +61,13 @@ uint8 DreamWebEngine::getNextWord(const GraphicsFile &charSet, const uint8 *stri } void DreamWebEngine::printChar(const GraphicsFile &charSet, uint16* x, uint16 y, uint8 c, uint8 nextChar, uint8 *width, uint8 *height) { - if (c == 255) + // WORKAROUND: Some texts contain leftover tab characters, which will cause + // OOB memory access when showing a character, as all the printable ones are + // from 32 onwards. We compensate for that here by ignoring all the invalid + // characters (0 - 31). + if (c < 32 || c == 255) return; - + uint8 dummyWidth, dummyHeight; if (width == NULL) width = &dummyWidth; @@ -315,7 +321,7 @@ void DreamWebEngine::rollEndCreditsGameLost() { waitForVSync(); multiDump(25, 20, 160, 160); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) return; } @@ -325,7 +331,7 @@ void DreamWebEngine::rollEndCreditsGameLost() { c = *string++; } while (c != ':' && c != 0); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) return; } diff --git a/engines/dreamweb/rain.cpp b/engines/dreamweb/rain.cpp index 8e42e0c161..b636b7def7 100644 --- a/engines/dreamweb/rain.cpp +++ b/engines/dreamweb/rain.cpp @@ -42,12 +42,12 @@ void DreamWebEngine::showRain() { uint16 offset = (rain.w3 - rain.b5) & 511; rain.w3 = offset; const uint8 *src = frameData + offset; - uint8 *dst = workspace() + y * 320 + x; + uint8 *dst = workspace() + y * kScreenwidth + x; for (uint16 j = 0; j < size; ++j) { uint8 v = src[j]; if (v != 0) *dst = v; - dst += 320-1; // advance diagonally + dst += kScreenwidth-1; // advance diagonally } } diff --git a/engines/dreamweb/saveload.cpp b/engines/dreamweb/saveload.cpp index ea9cdc0249..8a0791d19b 100644 --- a/engines/dreamweb/saveload.cpp +++ b/engines/dreamweb/saveload.cpp @@ -156,8 +156,16 @@ void DreamWebEngine::doLoad(int savegameId) { } else { if (savegameId == -1) { - // Open dialog to get savegameId + // Wait till both mouse buttons are up. We should wait till the user + // releases the mouse button, otherwise the follow-up mouseup event + // will trigger a load of the save slot under the mouse cursor. Fixes + // bug #3582582. + while (_oldMouseState > 0) { + readMouse(); + g_system->delayMillis(10); + } + // Open dialog to get savegameId GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); savegameId = dialog->runModalWithCurrentTarget(); delete dialog; @@ -241,6 +249,15 @@ void DreamWebEngine::saveGame() { } return; } else { + // Wait till both mouse buttons are up. We should wait till the user + // releases the mouse button, otherwise the follow-up mouseup event + // will trigger a save into the save slot under the mouse cursor. Fixes + // bug #3582582. + while (_oldMouseState > 0) { + readMouse(); + g_system->delayMillis(10); + } + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); int savegameId = dialog->runModalWithCurrentTarget(); Common::String game_description = dialog->getResultString(); @@ -557,6 +574,14 @@ void DreamWebEngine::savePosition(unsigned int slot, const char *descbuf) { delete outSaveFile; } + +// Utility struct for a savegame sanity check in loadPosition +struct FrameExtent { + uint16 start; + uint16 length; + bool operator<(const struct FrameExtent& other) const { return start<other.start; } +}; + void DreamWebEngine::loadPosition(unsigned int slot) { _timeCount = 0; clearChanges(); @@ -636,6 +661,42 @@ void DreamWebEngine::loadPosition(unsigned int slot) { } delete inSaveFile; + + + // Do a sanity check on exFrames data to detect exFrames corruption + // caused by a (now fixed) bug in emergencyPurge. See bug #3591088. + // Gather the location of frame data of all used ex object frames. + Common::List<FrameExtent> flist; + for (unsigned int i = 0; i < kNumexobjects; ++i) { + if (_exData[i].mapad[0] != 0xff) { + FrameExtent fe; + Frame *frame = &_exFrames._frames[3*i+0]; + fe.start = frame->ptr(); + fe.length = frame->width * frame->height; + flist.push_back(fe); + + frame = &_exFrames._frames[3*i+1]; + fe.start = frame->ptr(); + fe.length = frame->width * frame->height; + flist.push_back(fe); + } + } + // ...and check if the frames overlap. + Common::sort(flist.begin(), flist.end(), Common::Less<FrameExtent>()); + Common::List<FrameExtent>::const_iterator iter; + uint16 curEnd = 0; + for (iter = flist.begin(); iter != flist.end(); ++iter) { + if (iter->start < curEnd) + error("exFrames data corruption in savegame"); + curEnd = iter->start + iter->length; + } + if (curEnd > _vars._exFramePos) { + if (curEnd > kExframeslen) + error("exFrames data corruption in savegame"); + warning("Fixing up exFramePos"); + _vars._exFramePos = curEnd; + } + // (end of sanity check) } // Count number of save files, and load their descriptions into _saveNames diff --git a/engines/dreamweb/sprite.cpp b/engines/dreamweb/sprite.cpp index 01570c907a..1fa2e7d6a4 100644 --- a/engines/dreamweb/sprite.cpp +++ b/engines/dreamweb/sprite.cpp @@ -26,7 +26,7 @@ namespace DreamWeb { void DreamWebEngine::printSprites() { - for (size_t priority = 0; priority < 7; ++priority) { + for (uint priority = 0; priority < 7; ++priority) { Common::List<Sprite>::const_iterator i; for (i = _spriteTable.begin(); i != _spriteTable.end(); ++i) { const Sprite &sprite = *i; diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp index f235f7c2fd..d93c2a951c 100644 --- a/engines/dreamweb/stubs.cpp +++ b/engines/dreamweb/stubs.cpp @@ -26,10 +26,6 @@ namespace DreamWeb { -// Keyboard buffer. _bufferIn and _bufferOut are indexes -// into this, making it a ring buffer -uint8 g_keyBuffer[16]; - const Room g_roomData[] = { // location 0 { "DREAMWEB.R00", // Ryan's apartment @@ -723,7 +719,6 @@ void DreamWebEngine::dreamweb() { showGun(); fadeScreenDown(); hangOn(100); - } } @@ -965,7 +960,6 @@ void DreamWebEngine::useTimedText() { } void DreamWebEngine::setupTimedTemp(uint8 textIndex, uint8 voiceIndex, uint8 x, uint8 y, uint16 countToTimed, uint16 timeCount) { - if (hasSpeech() && voiceIndex != 0) { _speechLoaded = _sound->loadSpeech('T', voiceIndex, 'T', textIndex); if (_speechLoaded) @@ -1056,7 +1050,7 @@ void DreamWebEngine::lockMon() { // key because calling readkey() drains characters from the input // buffer, we we want the user to be able to type ahead while the text // is being printed. - if (_lastHardKey == 57) { + if (_lastHardKey == Common::KEYCODE_SPACE) { // Clear the keyboard buffer. Otherwise the space that caused // the pause will be read immediately unpause the game. do { @@ -1072,7 +1066,7 @@ void DreamWebEngine::lockMon() { } // Forget the last "hard" key, otherwise the space that caused // the unpausing will immediately re-pause the game. - _lastHardKey = 0; + _lastHardKey = Common::KEYCODE_INVALID; lockLightOff(); } } @@ -1148,7 +1142,7 @@ void DreamWebEngine::plotReel(uint16 &reelPointer) { reel += 8; } - for (size_t i = 0; i < 8; ++i) { + for (uint i = 0; i < 8; ++i) { if (reel->frame() != 0xffff) showReelFrame(reel); ++reel; @@ -1247,7 +1241,7 @@ const uint8 *DreamWebEngine::findObName(uint8 type, uint8 index) { void DreamWebEngine::copyName(uint8 type, uint8 index, uint8 *dst) { const uint8 *src = findObName(type, index); - size_t i; + uint i; for (i = 0; i < 28; ++i) { char c = src[i]; if (c == ':') @@ -1377,7 +1371,7 @@ void DreamWebEngine::doChange(uint8 index, uint8 value, uint8 type) { } void DreamWebEngine::deleteTaken() { - for (size_t i = 0; i < kNumexobjects; ++i) { + for (uint i = 0; i < kNumexobjects; ++i) { uint8 location = _exData[i].initialLocation; if (location == _realLocation) { uint8 index = _exData[i].index; @@ -1388,7 +1382,7 @@ void DreamWebEngine::deleteTaken() { uint8 DreamWebEngine::getExPos() { DynObject *objects = _exData; - for (size_t i = 0; i < kNumexobjects; ++i) { + for (uint i = 0; i < kNumexobjects; ++i) { if (objects[i].mapad[0] == 0xff) return i; } @@ -1543,7 +1537,7 @@ void DreamWebEngine::printMessage2(uint16 x, uint16 y, uint8 index, uint8 maxWid bool DreamWebEngine::objectMatches(void *object, const char *id) { const char *objId = (const char *)object + 12; // whether it is a DynObject or a SetObject - for (size_t i = 0; i < 4; ++i) { + for (uint i = 0; i < 4; ++i) { if (id[i] != objId[i] + 'A') return false; } @@ -2138,7 +2132,6 @@ void DreamWebEngine::workToScreenM() { } void DreamWebEngine::atmospheres() { - const Atmosphere *a = &g_atmosphereList[0]; for (; a->_location != 255; ++a) { @@ -2208,8 +2201,8 @@ void DreamWebEngine::readKey() { return; } - bufOut = (bufOut + 1) & 15; // The buffer has size 16 - _currentKey = g_keyBuffer[bufOut]; + bufOut = (bufOut + 1) % ARRAYSIZE(_keyBuffer); + _currentKey = _keyBuffer[bufOut]; _bufferOut = bufOut; } @@ -2220,36 +2213,6 @@ void DreamWebEngine::newGame() { _getBack = 3; } -void DreamWebEngine::pickupOb(uint8 command, uint8 pos) { - _lastInvPos = pos; - _objectType = kFreeObjectType; - _itemFrame = command; - _command = command; - //uint8 dummy; - //getAnyAd(&dummy, &dummy); // was in the original source, seems useless here - transferToEx(command); -} - -void DreamWebEngine::initialInv() { - if (_realLocation != 24) - return; - - pickupOb(11, 5); - pickupOb(12, 6); - pickupOb(13, 7); - pickupOb(14, 8); - pickupOb(18, 0); - pickupOb(19, 1); - pickupOb(20, 9); - pickupOb(16, 2); - _vars._watchMode = 1; - _vars._reelToHold = 0; - _vars._endOfHoldReel = 6; - _vars._watchSpeed = 1; - _vars._speedCount = 1; - switchRyanOff(); -} - void DreamWebEngine::walkIntoRoom() { if (_vars._location == 14 && _mapX == 22) { _destination = 1; @@ -2314,13 +2277,6 @@ void DreamWebEngine::makeMainScreen() { _manIsOffScreen = 0; } -void DreamWebEngine::openInv() { - _invOpen = 1; - printMessage(80, 58 - 10, 61, 240, (240 & 1)); - fillRyan(); - _commandType = 255; -} - void DreamWebEngine::obsThatDoThings() { if (!compare(_command, _objectType, "MEMB")) return; // notlouiscard @@ -2420,10 +2376,6 @@ void DreamWebEngine::errorMessage3() { delPointer(); } -void DreamWebEngine::reExFromOpen() { - -} - void DreamWebEngine::putBackObStuff() { createPanel(); showPanel(); @@ -2444,26 +2396,6 @@ bool DreamWebEngine::isSetObOnMap(uint8 index) { return (getSetAd(index)->mapad[0] == 0); } -void DreamWebEngine::examineInventory() { - commandOnlyCond(32, 249); - - if (!(_mouseButton & 1)) - return; - - createPanel(); - showPanel(); - showMan(); - showExit(); - examIcon(); - _pickUp = 0; - _invOpen = 2; - openInv(); - workToScreenM(); -} - -void DreamWebEngine::middlePanel() { -} - void DreamWebEngine::underTextLine() { if (_foreignRelease) multiGet(_textUnder, _textAddressX, _textAddressY - 3, kUnderTextSizeX_f, kUnderTextSizeY_f); @@ -2575,7 +2507,6 @@ void DreamWebEngine::madmanRun() { _vars._lastWeapon = 8; } - void DreamWebEngine::decide() { setMode(); loadPalFromIFF(); @@ -2659,39 +2590,12 @@ void DreamWebEngine::showGun() { getRidOfTempText(); } -void DreamWebEngine::dropError() { - _commandType = 255; - delPointer(); - printMessage(76, 21, 56, 240, 240 & 1); - workToScreenM(); - hangOnP(50); - showPanel(); - showMan(); - examIcon(); - _commandType = 255; - workToScreenM(); -} - -void DreamWebEngine::cantDrop() { - _commandType = 255; - delPointer(); - printMessage(76, 21, 24, 240, 240 & 1); - workToScreenM(); - hangOnP(50); - showPanel(); - showMan(); - examIcon(); - _commandType = 255; - workToScreenM(); -} - void DreamWebEngine::getBack1() { if (_pickUp != 0) { blank(); return; } - commandOnlyCond(26, 202); if (_mouseButton == _oldButton) @@ -3003,52 +2907,4 @@ void DreamWebEngine::edensFlatReminders() { _vars._progressPoints++; // got card } -void DreamWebEngine::incRyanPage() { - commandOnlyCond(31, 222); - - if (_mouseButton == _oldButton || !(_mouseButton & 1)) - return; - - _vars._ryanPage = (_mouseX - (kInventx + 167)) / 18; - - delPointer(); - fillRyan(); - readMouse(); - showPointer(); - workToScreen(); - delPointer(); - -} - -void DreamWebEngine::emergencyPurge() { - while (true) { - if (_vars._exFramePos + 4000 < kExframeslen) { - // Not near frame end - if (_vars._exTextPos + 400 < kExtextlen) - return; // notneartextend - } - - purgeAnItem(); - } -} - -void DreamWebEngine::purgeAnItem() { - const DynObject *extraObjects = _exData; - - for (size_t i = 0; i < kNumexobjects; ++i) { - if (extraObjects[i].mapad[0] && extraObjects[i].objId[0] == 255 && - extraObjects[i].initialLocation != _realLocation) { - deleteExObject(i); - return; - } - } - - for (size_t i = 0; i < kNumexobjects; ++i) { - if (extraObjects[i].mapad[0] && extraObjects[i].objId[0] == 255) { - deleteExObject(i); - return; - } - } -} - } // End of namespace DreamWeb diff --git a/engines/dreamweb/titles.cpp b/engines/dreamweb/titles.cpp index f005279ba0..4e4faa75a0 100644 --- a/engines/dreamweb/titles.cpp +++ b/engines/dreamweb/titles.cpp @@ -105,34 +105,34 @@ void DreamWebEngine::bibleQuote() { fadeScreenUps(); hangOne(80); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "biblequotearly" } hangOne(560); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "biblequotearly" } fadeScreenDowns(); hangOne(200); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "biblequotearly" } _sound->cancelCh0(); - _lastHardKey = 0; + _lastHardKey = Common::KEYCODE_INVALID; } void DreamWebEngine::hangOne(uint16 delay) { do { waitForVSync(); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) return; // "hangonearly" } while (--delay); } @@ -150,8 +150,8 @@ void DreamWebEngine::intro() { fadeScreenUps(); runIntroSeq(); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "introearly" } @@ -160,8 +160,8 @@ void DreamWebEngine::intro() { loadIntroRoom(); runIntroSeq(); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "introearly" } @@ -170,8 +170,8 @@ void DreamWebEngine::intro() { loadIntroRoom(); runIntroSeq(); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "introearly" } @@ -181,15 +181,15 @@ void DreamWebEngine::intro() { loadIntroRoom(); runIntroSeq(); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "introearly" } getRidOfTempText(); clearBeforeLoad(); - _lastHardKey = 0; + _lastHardKey = Common::KEYCODE_INVALID; } void DreamWebEngine::runIntroSeq() { @@ -198,13 +198,13 @@ void DreamWebEngine::runIntroSeq() { do { waitForVSync(); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) break; spriteUpdate(); waitForVSync(); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) break; delEverything(); @@ -214,20 +214,20 @@ void DreamWebEngine::runIntroSeq() { useTimedText(); waitForVSync(); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) break; dumpMap(); dumpTimedText(); waitForVSync(); - if (_lastHardKey == 1) + if (_lastHardKey == Common::KEYCODE_ESCAPE) break; } while (_getBack != 1); - if (_lastHardKey == 1) { + if (_lastHardKey == Common::KEYCODE_ESCAPE) { getRidOfTempText(); clearBeforeLoad(); } @@ -266,7 +266,7 @@ void DreamWebEngine::loadIntroRoom() { _mapOffsetY = 16; clearSprites(); _vars._throughDoor = 0; - _currentKey = '0'; + _currentKey = 0; _mainMode = 0; clearWork(); _vars._newObs = 1; @@ -293,24 +293,24 @@ void DreamWebEngine::realCredits() { hangOne(2); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } allPalette(); hangOne(80); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } fadeScreenDowns(); hangOne(256); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } @@ -318,24 +318,24 @@ void DreamWebEngine::realCredits() { _sound->playChannel0(12, 0); hangOne(2); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } allPalette(); hangOne(80); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } fadeScreenDowns(); hangOne(256); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } @@ -343,24 +343,24 @@ void DreamWebEngine::realCredits() { _sound->playChannel0(12, 0); hangOne(2); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } allPalette(); hangOne(80); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } fadeScreenDowns(); hangOne(256); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } @@ -368,24 +368,24 @@ void DreamWebEngine::realCredits() { _sound->playChannel0(12, 0); hangOne(2); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } allPalette(); hangOne(80); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } fadeScreenDowns(); hangOne(256); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } @@ -393,24 +393,24 @@ void DreamWebEngine::realCredits() { _sound->playChannel0(12, 0); hangOne(2); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } allPalette(); hangOne(80); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } fadeScreenDowns(); hangOne(256); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } @@ -418,23 +418,23 @@ void DreamWebEngine::realCredits() { fadeScreenUps(); hangOne(60); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } _sound->playChannel0(13, 0); hangOne(350); - if (_lastHardKey == 1) { - _lastHardKey = 0; + if (_lastHardKey == Common::KEYCODE_ESCAPE) { + _lastHardKey = Common::KEYCODE_INVALID; return; // "realcreditsearly" } fadeScreenDowns(); hangOne(256); - _lastHardKey = 0; + _lastHardKey = Common::KEYCODE_INVALID; } } // End of namespace DreamWeb diff --git a/engines/dreamweb/use.cpp b/engines/dreamweb/use.cpp index 995eef04cd..476f847c40 100644 --- a/engines/dreamweb/use.cpp +++ b/engines/dreamweb/use.cpp @@ -131,7 +131,7 @@ void DreamWebEngine::useRoutine() { uint8 dummy; void *obj = getAnyAd(&dummy, &dummy); - for (size_t i = 0; i < sizeof(kUseList)/sizeof(UseListEntry); ++i) { + for (uint i = 0; i < ARRAYSIZE(kUseList); ++i) { const UseListEntry &entry = kUseList[i]; if (objectMatches(obj, entry.id)) { (this->*entry.callback)(); diff --git a/engines/dreamweb/vgafades.cpp b/engines/dreamweb/vgafades.cpp index c8f05641b5..d1e2480f70 100644 --- a/engines/dreamweb/vgafades.cpp +++ b/engines/dreamweb/vgafades.cpp @@ -56,8 +56,8 @@ void DreamWebEngine::fadeDOS() { //processEvents will be called from waitForVSync uint8 *dst = _startPal; getPalette(dst, 0, 64); - for (int fade = 0; fade < 64; ++fade) { - for (int c = 0; c < 768; ++c) { //original sources decrement 768 values -> 256 colors + for (uint fade = 0; fade < 64; ++fade) { + for (uint c = 0; c < 768; ++c) { //original sources decrement 768 values -> 256 colors if (dst[c]) { --dst[c]; } @@ -88,7 +88,7 @@ void DreamWebEngine::fadeCalculation() { uint8 *startPal = _startPal; const uint8 *endPal = _endPal; - for (size_t i = 0; i < 256 * 3; ++i) { + for (uint i = 0; i < 256 * 3; ++i) { uint8 s = startPal[i]; uint8 e = endPal[i]; if (s == e) @@ -212,7 +212,7 @@ void DreamWebEngine::fadeScreenDownHalf() { const uint8 *startPal = _startPal; uint8 *endPal = _endPal; - for (int i = 0; i < 256 * 3; ++i) { + for (uint i = 0; i < 256 * 3; ++i) { *endPal >>= 1; endPal++; } @@ -239,7 +239,7 @@ void DreamWebEngine::greyscaleSum() { byte *src = _mainPal; byte *dst = _endPal; - for (int i = 0; i < 256; ++i) { + for (uint i = 0; i < 256; ++i) { const unsigned int r = 20 * *src++; const unsigned int g = 59 * *src++; const unsigned int b = 11 * *src++; diff --git a/engines/dreamweb/vgagrafx.cpp b/engines/dreamweb/vgagrafx.cpp index d2390fb1fd..d8984d312b 100644 --- a/engines/dreamweb/vgagrafx.cpp +++ b/engines/dreamweb/vgagrafx.cpp @@ -31,14 +31,16 @@ const uint16 kZoomx = 8; const uint16 kZoomy = 132; void DreamWebEngine::multiGet(uint8 *dst, uint16 x, uint16 y, uint8 w, uint8 h) { - assert(x < 320); - assert(y < 200); + assert(x < kScreenwidth); + assert(y < kScreenheight); + const uint8 *src = workspace() + x + y * kScreenwidth; - if (y + h > 200) - h = 200 - y; - if (x + w > 320) - w = 320 - x; - //debug(1, "multiGet %u,%u %ux%u -> segment: %04x->%04x", x, y, w, h, (uint16)ds, (uint16)es); + + if (y + h > kScreenheight) + h = kScreenheight - y; + if (x + w > kScreenwidth) + w = kScreenwidth - x; + for (unsigned l = 0; l < h; ++l) { const uint8 *src_p = src + kScreenwidth * l; uint8 *dst_p = dst + w * l; @@ -47,14 +49,16 @@ void DreamWebEngine::multiGet(uint8 *dst, uint16 x, uint16 y, uint8 w, uint8 h) } void DreamWebEngine::multiPut(const uint8 *src, uint16 x, uint16 y, uint8 w, uint8 h) { - assert(x < 320); - assert(y < 200); + assert(x < kScreenwidth); + assert(y < kScreenheight); + uint8 *dst = workspace() + x + y * kScreenwidth; - if (y + h > 200) - h = 200 - y; - if (x + w > 320) - w = 320 - x; - //debug(1, "multiPut %ux%u -> segment: %04x->%04x", w, h, (uint16)ds, (uint16)es); + + if (y + h > kScreenheight) + h = kScreenheight - y; + if (x + w > kScreenwidth) + w = kScreenwidth - x; + for (unsigned l = 0; l < h; ++l) { const uint8 *src_p = src + w * l; uint8 *dst_p = dst + kScreenwidth * l; @@ -64,12 +68,11 @@ void DreamWebEngine::multiPut(const uint8 *src, uint16 x, uint16 y, uint8 w, uin void DreamWebEngine::multiDump(uint16 x, uint16 y, uint8 width, uint8 height) { unsigned offset = x + y * kScreenwidth; - //debug(1, "multiDump %ux%u(segment: %04x) -> %d,%d(address: %d)", w, h, (uint16)ds, x, y, offset); blit(workspace() + offset, kScreenwidth, x, y, width, height); } void DreamWebEngine::workToScreen() { - blit(workspace(), 320, 0, 0, 320, 200); + blit(workspace(), kScreenwidth, 0, 0, kScreenwidth, kScreenheight); } void DreamWebEngine::frameOutNm(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, uint16 x, uint16 y) { @@ -147,7 +150,7 @@ void DreamWebEngine::doShake() { void DreamWebEngine::setMode() { waitForVSync(); - initGraphics(320, 200, false); + initGraphics(kScreenwidth, kScreenheight, false); } void DreamWebEngine::showPCX(const Common::String &suffix) { @@ -185,7 +188,7 @@ void DreamWebEngine::showPCX(const Common::String &suffix) { void DreamWebEngine::frameOutV(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, int16 x, int16 y) { // NB : These resilience checks were not in the original engine, but did they result in undefined behaviour // or was something broken during porting to C++? - assert(pitch == 320); + assert(pitch == kScreenwidth); if (x < 0) { assert(width >= -x); @@ -199,15 +202,16 @@ void DreamWebEngine::frameOutV(uint8 *dst, const uint8 *src, uint16 pitch, uint1 src += (-y) * width; y = 0; } - if (x >= 320) + + if ((uint16)x >= kScreenwidth) return; - if (y >= 200) + if ((uint16)y >= kScreenheight) return; - if (x + width > 320) { - width = 320 - x; + if ((uint16)x + width > kScreenwidth) { + width = kScreenwidth - x; } - if (y + height > 200) { - height = 200 - y; + if ((uint16)y + height > kScreenheight) { + height = kScreenheight - y; } uint16 stride = pitch - width; @@ -246,20 +250,20 @@ void DreamWebEngine::showFrameInternal(const uint8 *pSrc, uint16 x, uint16 y, ui //addToPrintList(x - _mapAdX, y - _mapAdY); // NB: Commented in the original asm } if (effectsFlag & 4) { // flippedX - frameOutFx(workspace(), pSrc, 320, width, height, x, y); + frameOutFx(workspace(), pSrc, kScreenwidth, width, height, x, y); return; } if (effectsFlag & 2) { // noMask - frameOutNm(workspace(), pSrc, 320, width, height, x, y); + frameOutNm(workspace(), pSrc, kScreenwidth, width, height, x, y); return; } if (effectsFlag & 32) { - frameOutBh(workspace(), pSrc, 320, width, height, x, y); + frameOutBh(workspace(), pSrc, kScreenwidth, width, height, x, y); return; } } // "noEffects" - frameOutV(workspace(), pSrc, 320, width, height, x, y); + frameOutV(workspace(), pSrc, kScreenwidth, width, height, x, y); } void DreamWebEngine::showFrame(const GraphicsFile &frameData, uint16 x, uint16 y, uint16 frameNumber, uint8 effectsFlag, uint8 *width, uint8 *height) { @@ -285,7 +289,7 @@ void DreamWebEngine::showFrame(const GraphicsFile &frameData, uint16 x, uint16 y } void DreamWebEngine::clearWork() { - memset(workspace(), 0, 320*200); + memset(workspace(), 0, kScreenwidth*kScreenheight); } void DreamWebEngine::dumpZoom() { @@ -326,20 +330,20 @@ void DreamWebEngine::zoom() { putUnderZoom(); return; } - uint16 srcOffset = (_oldPointerY - 9) * 320 + (_oldPointerX - 11); - uint16 dstOffset = (kZoomy + 4) * 320 + (kZoomx + 5); + uint16 srcOffset = (_oldPointerY - 9) * kScreenwidth + (_oldPointerX - 11); + uint16 dstOffset = (kZoomy + 4) * kScreenwidth + (kZoomx + 5); const uint8 *src = workspace() + srcOffset; uint8 *dst = workspace() + dstOffset; - for (size_t i = 0; i < 20; ++i) { - for (size_t j = 0; j < 23; ++j) { + for (uint i = 0; i < 20; ++i) { + for (uint j = 0; j < 23; ++j) { uint8 v = src[j]; dst[2*j+0] = v; dst[2*j+1] = v; - dst[2*j+320] = v; - dst[2*j+321] = v; + dst[2*j+kScreenwidth] = v; + dst[2*j+kScreenwidth+1] = v; } - src += 320; - dst += 320*2; + src += kScreenwidth; + dst += kScreenwidth*2; } crosshair(); _didZoom = 1; @@ -375,7 +379,7 @@ void DreamWebEngine::loadPalFromIFF() { const uint8 *src = buf + 0x30; uint8 *dst = _mainPal; - for (size_t i = 0; i < 256*3; ++i) { + for (uint i = 0; i < 256*3; ++i) { uint8 c = src[i] / 4; if (_brightPalette) { if (c) { diff --git a/engines/engine.cpp b/engines/engine.cpp index 2ef4ecab60..c84404cc68 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -179,7 +179,12 @@ void initCommonGFX(bool defaultTo1XScaler) { } else { // Override global scaler with any game-specific define if (ConfMan.hasKey("gfx_mode")) { - g_system->setGraphicsMode(ConfMan.get("gfx_mode").c_str()); + Common::String gfxMode = ConfMan.get("gfx_mode"); + g_system->setGraphicsMode(gfxMode.c_str()); + + // HACK: For OpenGL modes, we will still honor the graphics scale override + if (defaultTo1XScaler && (gfxMode.equalsIgnoreCase("gl1") || gfxMode.equalsIgnoreCase("gl2") || gfxMode.equalsIgnoreCase("gl4"))) + g_system->resetGraphicsScale(); } } diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 63bf3eb1c6..2aa837e777 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -693,7 +693,7 @@ protected: void o7_zeroVar(); void o7_getINIValue(); void o7_setINIValue(); - void o7_loadLBMPalette(); + void o7_loadIFFPalette(); void o7_opendBase(); void o7_closedBase(); void o7_getDBString(); diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp index 6cf69ed9df..1238c23e3b 100644 --- a/engines/gob/inter_v7.cpp +++ b/engines/gob/inter_v7.cpp @@ -27,6 +27,7 @@ #include "graphics/cursorman.h" #include "graphics/wincursor.h" +#include "graphics/decoders/iff.h" #include "gob/gob.h" #include "gob/global.h" @@ -72,7 +73,7 @@ void Inter_v7::setupOpcodesDraw() { OPCODEDRAW(0x95, o7_zeroVar); OPCODEDRAW(0xA1, o7_getINIValue); OPCODEDRAW(0xA2, o7_setINIValue); - OPCODEDRAW(0xA4, o7_loadLBMPalette); + OPCODEDRAW(0xA4, o7_loadIFFPalette); OPCODEDRAW(0xC4, o7_opendBase); OPCODEDRAW(0xC5, o7_closedBase); OPCODEDRAW(0xC6, o7_getDBString); @@ -523,7 +524,7 @@ void Inter_v7::o7_setINIValue() { _inis.setValue(file, section, key, value); } -void Inter_v7::o7_loadLBMPalette() { +void Inter_v7::o7_loadIFFPalette() { Common::String file = _vm->_game->_script->evalString(); if (!file.contains('.')) file += ".LBM"; @@ -534,37 +535,46 @@ void Inter_v7::o7_loadLBMPalette() { if (startIndex > stopIndex) SWAP(startIndex, stopIndex); - Common::SeekableReadStream *lbmFile = _vm->_dataIO->getFile(file); - if (!lbmFile) { - warning("o7_loadLBMPalette(): No such file \"%s\"", file.c_str()); + Common::SeekableReadStream *iffFile = _vm->_dataIO->getFile(file); + if (!iffFile) { + warning("o7_loadIFFPalette(): No such file \"%s\"", file.c_str()); return; } - ImageType type = Surface::identifyImage(*lbmFile); - if (type != kImageTypeLBM) { - warning("o7_loadLBMPalette(): \"%s\" is no LBM", file.c_str()); + ImageType type = Surface::identifyImage(*iffFile); + if (type != kImageTypeIFF) { + warning("o7_loadIFFPalette(): \"%s\" is no IFF", file.c_str()); return; } - byte palette[768]; - - LBMLoader lbm(*lbmFile); - if (!lbm.loadPalette(palette)) { - warning("o7_loadLBMPalette(): Failed reading palette from LBM \"%s\"", file.c_str()); + Graphics::IFFDecoder decoder; + decoder.loadStream(*iffFile); + if (!decoder.getPalette() || decoder.getPaletteColorCount() != 256) { + warning("o7_loadIFFPalette(): Failed reading palette from IFF \"%s\"", file.c_str()); return; } - memset(palette , 0x00, 3); - memset(palette + 765, 0xFF, 3); - for (int i = 0; i < 768; i++) - palette[i] >>= 2; - - int16 count = stopIndex - startIndex + 1; + const byte *palette = decoder.getPalette(); startIndex *= 3; - count *= 3; + stopIndex *= 3; + + byte *dst = (byte *)_vm->_draw->_vgaPalette + startIndex; + const byte *src = palette + startIndex; + for (int i = startIndex; i <= stopIndex + 2; ++i) { + *dst++ = *src++ >> 2; + } + + if (startIndex == 0) { + dst = (byte *)_vm->_draw->_vgaPalette; + dst[0] = dst[1] = dst[2] = 0x00 >> 2; + } + + if (stopIndex == 765) { + dst = (byte *)_vm->_draw->_vgaPalette + 765; + dst[0] = dst[1] = dst[2] = 0xFF >> 2; + } - memcpy((char *)_vm->_draw->_vgaPalette + startIndex, palette + startIndex, count); _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); } diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp index afbb7c3bae..6b65eb6ab9 100644 --- a/engines/gob/surface.cpp +++ b/engines/gob/surface.cpp @@ -26,112 +26,15 @@ #include "common/stream.h" #include "common/util.h" #include "common/frac.h" +#include "common/textconsole.h" #include "graphics/primitives.h" #include "graphics/pixelformat.h" #include "graphics/surface.h" +#include "graphics/decoders/iff.h" namespace Gob { -LBMLoader::LBMLoader(Common::SeekableReadStream &stream) : _parser(&stream), - _hasHeader(false), _palette(0), _image(0) { - -} - -bool LBMLoader::loadHeader(Graphics::BMHD &header) { - if (!readHeader()) - return false; - - header = _decoder._header; - return true; -} - -bool LBMLoader::loadPalette(byte *palette) { - assert(!_palette); - assert(palette); - - _palette = palette; - - Common::Functor1Mem<Common::IFFChunk&, bool, LBMLoader> c(this, &LBMLoader::callbackPalette); - _parser.parse(c); - - if (!_palette) - return false; - - _palette = 0; - return true; -} - -bool LBMLoader::loadImage(byte *image) { - assert(!_image); - assert(image); - - if (!readHeader()) - return false; - - _image = image; - - Common::Functor1Mem<Common::IFFChunk&, bool, LBMLoader> c(this, &LBMLoader::callbackImage); - _parser.parse(c); - - if (!_image) - return false; - - _image = 0; - return true; -} - -bool LBMLoader::callbackHeader(Common::IFFChunk &chunk) { - if (chunk._type == ID_BMHD) { - if (chunk._size == sizeof(Graphics::BMHD)) { - _decoder.loadHeader(chunk._stream); - _hasHeader = true; - } - - return true; // Stop the IFF parser - } - - return false; -} - -bool LBMLoader::callbackPalette(Common::IFFChunk &chunk) { - assert(_palette); - - if (chunk._type == ID_CMAP) { - if (chunk._size == 768) { - if (chunk._stream->read(_palette, chunk._size) != chunk._size) - _palette = 0; - } else - _palette = 0; - - return true; // Stop the IFF parser - } - - return false; -} - -bool LBMLoader::callbackImage(Common::IFFChunk &chunk) { - assert(_image); - - if (chunk._type == ID_BODY) { - _decoder.loadBitmap(Graphics::ILBMDecoder::ILBM_UNPACK_PLANES, _image, chunk._stream); - return true; - } - - return false; -} - -bool LBMLoader::readHeader() { - if (_hasHeader) - return true; - - Common::Functor1Mem<Common::IFFChunk&, bool, LBMLoader> c(this, &LBMLoader::callbackHeader); - _parser.parse(c); - - return _hasHeader; -} - - static void plotPixel(int x, int y, int color, void *data) { Surface *dest = (Surface *)data; @@ -841,8 +744,8 @@ bool Surface::loadImage(Common::SeekableReadStream &stream, ImageType type) { switch (type) { case kImageTypeTGA: return loadTGA(stream); - case kImageTypeLBM: - return loadLBM(stream); + case kImageTypeIFF: + return loadIFF(stream); case kImageTypeBRC: return loadBRC(stream); case kImageTypeBMP: @@ -871,7 +774,7 @@ ImageType Surface::identifyImage(Common::SeekableReadStream &stream) { stream.seek(startPos); if (!strncmp(buffer , "FORM", 4)) - return kImageTypeLBM; + return kImageTypeIFF; if (!strncmp(buffer + 6, "JFIF", 4)) return kImageTypeJPEG; if (!strncmp(buffer , "BRC" , 3)) @@ -904,20 +807,17 @@ bool Surface::loadTGA(Common::SeekableReadStream &stream) { return false; } -bool Surface::loadLBM(Common::SeekableReadStream &stream) { +bool Surface::loadIFF(Common::SeekableReadStream &stream) { + Graphics::IFFDecoder decoder; + decoder.loadStream(stream); - LBMLoader loader(stream); - - Graphics::BMHD header; - loader.loadHeader(header); - - if (header.depth != 8) - // Only 8bpp LBMs supported for now + if (!decoder.getSurface()) return false; - resize(header.width, header.height); + resize(decoder.getSurface()->w, decoder.getSurface()->h); + memcpy(_vidMem, decoder.getSurface()->pixels, decoder.getSurface()->w * decoder.getSurface()->h); - return loader.loadImage(_vidMem); + return true; } bool Surface::loadBRC(Common::SeekableReadStream &stream) { diff --git a/engines/gob/surface.h b/engines/gob/surface.h index 8f895a7910..8a1b502a95 100644 --- a/engines/gob/surface.h +++ b/engines/gob/surface.h @@ -26,9 +26,6 @@ #include "common/scummsys.h" #include "common/ptr.h" #include "common/rational.h" -#include "common/iff_container.h" - -#include "graphics/iff.h" namespace Common { class SeekableReadStream; @@ -39,37 +36,12 @@ namespace Gob { enum ImageType { kImageTypeNone = -1, kImageTypeTGA = 0, - kImageTypeLBM, + kImageTypeIFF, kImageTypeBRC, kImageTypeBMP, kImageTypeJPEG }; -class LBMLoader { -public: - LBMLoader(Common::SeekableReadStream &stream); - - bool loadHeader (Graphics::BMHD &header); - bool loadPalette(byte *palette); - bool loadImage (byte *image); - -private: - Common::IFFParser _parser; - - bool _hasHeader; - - Graphics::ILBMDecoder _decoder; - - byte *_palette; - byte *_image; - - bool callbackHeader (Common::IFFChunk &chunk); - bool callbackPalette(Common::IFFChunk &chunk); - bool callbackImage (Common::IFFChunk &chunk); - - bool readHeader(); -}; - /** An iterator over a surface's image data, automatically handles different color depths. */ class Pixel { public: @@ -182,7 +154,7 @@ private: uint16 dWidth, uint16 dHeight, uint16 sWidth, uint16 sHeight); bool loadTGA (Common::SeekableReadStream &stream); - bool loadLBM (Common::SeekableReadStream &stream); + bool loadIFF (Common::SeekableReadStream &stream); bool loadBRC (Common::SeekableReadStream &stream); bool loadBMP (Common::SeekableReadStream &stream); bool loadJPEG(Common::SeekableReadStream &stream); diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index 895686b5e0..65452f5cf3 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -25,9 +25,12 @@ #include "groovie/saveload.h" #include "common/system.h" +#include "common/translation.h" namespace Groovie { +#define GAMEOPTION_T7G_FAST_MOVIE_SPEED GUIO_GAMEOPTIONS1 + static const PlainGameDescriptor groovieGames[] = { // Games {"t7g", "The 7th Guest"}, @@ -52,7 +55,7 @@ static const GroovieGameDescription gameDescriptions[] = { "t7g", "", AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659), Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED) }, kGroovieT7G, 0 }, @@ -63,7 +66,7 @@ static const GroovieGameDescription gameDescriptions[] = { "t7g", "", AD_ENTRY1s("T7GMac", "acdc4a58dd3f007f65e99b99d78e0bce", 1814029), Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, - GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED) }, kGroovieT7G, 0 }, @@ -79,7 +82,7 @@ static const GroovieGameDescription gameDescriptions[] = { "t7g", "", AD_ENTRY1s("T7GMac", "6bdee8d0f9eef6d58d02fcd7deec3fb2", 1830783), Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, - GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED) }, kGroovieT7G, 0 }, @@ -90,7 +93,7 @@ static const GroovieGameDescription gameDescriptions[] = { "t7g", "", AD_ENTRY1s("T7GMac", "0d595d4b44ae1814082938d051e5174e", 1830783), Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, - GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED) }, kGroovieT7G, 0 }, @@ -106,7 +109,7 @@ static const GroovieGameDescription gameDescriptions[] = { { NULL, 0, NULL, 0} }, Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, - GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED) }, kGroovieT7G, 0 }, @@ -120,7 +123,7 @@ static const GroovieGameDescription gameDescriptions[] = { { NULL, 0, NULL, 0} }, Common::EN_ANY, Common::kPlatformIOS, ADGF_NO_FLAGS, - GUIO2(GUIO_NOMIDI, GUIO_NOASPECT) + GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED) }, kGroovieT7G, 0 }, @@ -137,6 +140,36 @@ static const GroovieGameDescription gameDescriptions[] = { kGroovieV2, 1 }, + // The 11th Hour Macintosh English + { + { + "11h", "", + { + { "disk.1", 0, "5c0428cd3659fc7bbcd0aa16485ed5da", 227 }, + { "The 11th Hour Installer", 0, "bcdb4040b27f15b18f39fb9e496d384a", 1002987 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE, + GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + }, + kGroovieV2, 1 + }, + + // The 11th Hour Macintosh English (Installed) + { + { + "11h", "Installed", + { + { "disk.1", 0, "5c0428cd3659fc7bbcd0aa16485ed5da", 227 }, + { "el01.mov", 0, "70f42dfc25b1488a08011dc45bb5145d", 6039 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE, + GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + }, + kGroovieV2, 1 + }, + // The 11th Hour DOS Demo English { { @@ -159,6 +192,36 @@ static const GroovieGameDescription gameDescriptions[] = { kGroovieV2, 2 }, + // The Making of The 11th Hour Macintosh English + { + { + "11h", "Making Of", + { + { "disk.1", 0, "5c0428cd3659fc7bbcd0aa16485ed5da", 227 }, + { "The 11th Hour Installer", 0, "bcdb4040b27f15b18f39fb9e496d384a", 1002987 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE, + GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + }, + kGroovieV2, 2 + }, + + // The Making of The 11th Hour Macintosh English (Installed) + { + { + "11h", "Making Of (Installed)", + { + { "disk.1", 0, "5c0428cd3659fc7bbcd0aa16485ed5da", 227 }, + { "el01.mov", 0, "70f42dfc25b1488a08011dc45bb5145d", 6039 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE, + GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + }, + kGroovieV2, 2 + }, + // Clandestiny Trailer DOS English { { @@ -170,6 +233,36 @@ static const GroovieGameDescription gameDescriptions[] = { kGroovieV2, 3 }, + // Clandestiny Trailer Macintosh English + { + { + "clandestiny", "Trailer", + { + { "disk.1", 0, "5c0428cd3659fc7bbcd0aa16485ed5da", 227 }, + { "The 11th Hour Installer", 0, "bcdb4040b27f15b18f39fb9e496d384a", 1002987 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE, + GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + }, + kGroovieV2, 3 + }, + + // Clandestiny Trailer Macintosh English (Installed) + { + { + "clandestiny", "Trailer (Installed)", + { + { "disk.1", 0, "5c0428cd3659fc7bbcd0aa16485ed5da", 227 }, + { "el01.mov", 0, "70f42dfc25b1488a08011dc45bb5145d", 6039 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE, + GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT) + }, + kGroovieV2, 3 + }, + // Clandestiny DOS English { { @@ -207,9 +300,28 @@ static const GroovieGameDescription gameDescriptions[] = { {AD_TABLE_END_MARKER, kGroovieT7G, 0} }; +static const char *directoryGlobs[] = { + "MIDI", + 0 +}; + +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_T7G_FAST_MOVIE_SPEED, + { + _s("Fast movie speed"), + _s("Play movies at an increased speed"), + "fast_movie_speed", + false + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + class GroovieMetaEngine : public AdvancedMetaEngine { public: - GroovieMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(GroovieGameDescription), groovieGames) { + GroovieMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(GroovieGameDescription), groovieGames, optionsList) { _singleid = "groovie"; // Use kADFlagUseExtraAsHint in order to distinguish the 11th hour from @@ -222,6 +334,10 @@ public: // replaced with an according explanation. _flags = kADFlagUseExtraAsHint; _guioptions = GUIO3(GUIO_NOSUBTITLES, GUIO_NOSFX, GUIO_NOASPECT); + + // Need MIDI directory to detect 11H Mac Installed + _maxScanDepth = 2; + _directoryGlobs = directoryGlobs; } const char *getName() const { diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 726e7cbede..5ade442742 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -30,6 +30,7 @@ #include "groovie/music.h" #include "groovie/resource.h" #include "groovie/roq.h" +#include "groovie/stuffit.h" #include "groovie/vdx.h" #include "common/config-manager.h" @@ -56,15 +57,11 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) : SearchMan.addSubDirectoryMatching(gameDataDir, "groovie"); SearchMan.addSubDirectoryMatching(gameDataDir, "media"); SearchMan.addSubDirectoryMatching(gameDataDir, "system"); + SearchMan.addSubDirectoryMatching(gameDataDir, "MIDI"); _modeSpeed = kGroovieSpeedNormal; - if (ConfMan.hasKey("t7g_speed")) { - Common::String speed = ConfMan.get("t7g_speed"); - if (speed.equals("im_an_ios")) - _modeSpeed = kGroovieSpeediOS; - else if (speed.equals("tweaked")) - _modeSpeed = kGroovieSpeedTweaked; - } + if (ConfMan.hasKey("fast_movie_speed") && ConfMan.getBool("fast_movie_speed")) + _modeSpeed = kGroovieSpeedFast; // Initialize the custom debug levels DebugMan.addDebugChannel(kGroovieDebugAll, "All", "Debug everything"); @@ -93,6 +90,15 @@ GroovieEngine::~GroovieEngine() { } Common::Error GroovieEngine::run() { + if (_gameDescription->version == kGroovieV2 && getPlatform() == Common::kPlatformMacintosh) { + // Load the Mac installer with the lowest priority (in case the user has installed + // the game and has the MIDI folder present; faster to just load them) + Common::Archive *archive = createStuffItArchive("The 11th Hour Installer"); + + if (archive) + SearchMan.add("The 11th Hour Installer", archive); + } + _script = new Script(this, _gameDescription->version); // Initialize the graphics @@ -160,10 +166,10 @@ Common::Error GroovieEngine::run() { // Create the music player switch (getPlatform()) { case Common::kPlatformMacintosh: - // TODO: The 11th Hour Mac uses QuickTime MIDI files - // Right now, since the XMIDI are present and it is still detected as - // the DOS version, we don't have to do anything here. - _musicPlayer = new MusicPlayerMac(this); + if (_gameDescription->version == kGroovieT7G) + _musicPlayer = new MusicPlayerMac_t7g(this); + else + _musicPlayer = new MusicPlayerMac_v2(this); break; case Common::kPlatformIOS: _musicPlayer = new MusicPlayerIOS(this); diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index df2f062757..79abc13b1c 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -72,10 +72,16 @@ enum DebugLevels { // the current limitation is 32 debug levels (1 << 31 is the last one) }; +/** + * This enum reflects the available movie speed settings: + * - Normal: play videos at a normal speed + * - Fast: play videos with audio at a fast speed. Videos without audio, + * like teeth animations, are played at their regular speed to avoid + * audio sync issues + */ enum GameSpeed { kGroovieSpeedNormal, - kGroovieSpeediOS, - kGroovieSpeedTweaked + kGroovieSpeedFast }; struct GroovieGameDescription; diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk index 1e89ff66f5..b47eed912b 100644 --- a/engines/groovie/module.mk +++ b/engines/groovie/module.mk @@ -15,6 +15,7 @@ MODULE_OBJS := \ roq.o \ saveload.o \ script.o \ + stuffit.o \ vdx.o # This module can be built as a plugin diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index af929d439b..95637fc407 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -678,9 +678,9 @@ void MusicPlayerXMI::setTimbreMT(byte channel, const Timbre &timbre) { } -// MusicPlayerMac +// MusicPlayerMac_t7g -MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) { +MusicPlayerMac_t7g::MusicPlayerMac_t7g(GroovieEngine *vm) : MusicPlayerMidi(vm) { // Create the parser _midiParser = MidiParser::createParser_SMF(); @@ -701,7 +701,7 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) { assert(_vm->_macResFork); } -bool MusicPlayerMac::load(uint32 fileref, bool loop) { +bool MusicPlayerMac_t7g::load(uint32 fileref, bool loop) { debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); // First try for compressed MIDI @@ -722,7 +722,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { return loadParser(file, loop); } -Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadStream *stream) { +Common::SeekableReadStream *MusicPlayerMac_t7g::decompressMidi(Common::SeekableReadStream *stream) { // Initialize an output buffer of the given size uint32 size = stream->readUint32BE(); byte *output = (byte *)malloc(size); @@ -768,6 +768,52 @@ Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadS return new Common::MemoryReadStream(output, size, DisposeAfterUse::YES); } +// MusicPlayerMac_v2 + +MusicPlayerMac_v2::MusicPlayerMac_v2(GroovieEngine *vm) : MusicPlayerMidi(vm) { + // Create the parser + _midiParser = MidiParser::createParser_QT(); + + // Create the driver + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = MidiDriver::createMidi(dev); + assert(_driver); + + _driver->open(); // TODO: Handle return value != 0 (indicating an error) + + // Set the parser's driver + _midiParser->setMidiDriver(this); + + // Set the timer rate + _midiParser->setTimerRate(_driver->getBaseTempo()); +} + +bool MusicPlayerMac_v2::load(uint32 fileref, bool loop) { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); + + // Find correct filename + ResInfo info; + _vm->_resMan->getResInfo(fileref, info); + uint len = info.filename.size(); + if (len < 4) + return false; // This shouldn't actually occur + + // Remove the extension and add ".mov" + info.filename.deleteLastChar(); + info.filename.deleteLastChar(); + info.filename.deleteLastChar(); + info.filename += "mov"; + + Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(info.filename); + + if (!file) { + warning("Could not find file '%s'", info.filename.c_str()); + return false; + } + + return loadParser(file, loop); +} + MusicPlayerIOS::MusicPlayerIOS(GroovieEngine *vm) : MusicPlayer(vm) { vm->getTimerManager()->installTimerProc(&onTimer, 50 * 1000, this, "groovieMusic"); } diff --git a/engines/groovie/music.h b/engines/groovie/music.h index cc852aa8dc..92e9c8b487 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -150,9 +150,9 @@ private: void setTimbreMT(byte channel, const Timbre &timbre); }; -class MusicPlayerMac : public MusicPlayerMidi { +class MusicPlayerMac_t7g : public MusicPlayerMidi { public: - MusicPlayerMac(GroovieEngine *vm); + MusicPlayerMac_t7g(GroovieEngine *vm); protected: bool load(uint32 fileref, bool loop); @@ -161,6 +161,14 @@ private: Common::SeekableReadStream *decompressMidi(Common::SeekableReadStream *stream); }; +class MusicPlayerMac_v2 : public MusicPlayerMidi { +public: + MusicPlayerMac_v2(GroovieEngine *vm); + +protected: + bool load(uint32 fileref, bool loop); +}; + class MusicPlayerIOS : public MusicPlayer { public: MusicPlayerIOS(GroovieEngine *vm); diff --git a/engines/groovie/stuffit.cpp b/engines/groovie/stuffit.cpp new file mode 100644 index 0000000000..37f12585e7 --- /dev/null +++ b/engines/groovie/stuffit.cpp @@ -0,0 +1,537 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +// Based on the StuffIt code in ResidualVM +// StuffIt parsing based on http://code.google.com/p/theunarchiver/wiki/StuffItFormat +// Compression 14 based on libxad (http://sourceforge.net/projects/libxad/) + +#include "groovie/stuffit.h" + +#include "common/archive.h" +#include "common/bitstream.h" +#include "common/debug.h" +#include "common/hash-str.h" +#include "common/hashmap.h" +#include "common/memstream.h" +#include "common/substream.h" + +namespace Groovie { + +struct SIT14Data; + +class StuffItArchive : public Common::Archive { +public: + StuffItArchive(); + ~StuffItArchive(); + + bool open(const Common::String &filename); + void close(); + bool isOpen() const { return _stream != 0; } + + // Common::Archive API implementation + bool hasFile(const Common::String &name) const; + int listMembers(Common::ArchiveMemberList &list) const; + const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; + +private: + struct FileEntry { + byte compression; + uint32 uncompressedSize; + uint32 compressedSize; + uint32 offset; + }; + + Common::SeekableReadStream *_stream; + + typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap; + FileMap _map; + + // Decompression Functions + Common::SeekableReadStream *decompress14(Common::SeekableReadStream *src, uint32 uncompressedSize) const; + + // Decompression Helpers + void update14(uint16 first, uint16 last, byte *code, uint16 *freq) const; + void readTree14(Common::BitStream *bits, SIT14Data *dat, uint16 codesize, uint16 *result) const; +}; + +StuffItArchive::StuffItArchive() : Common::Archive() { + _stream = 0; +} + +StuffItArchive::~StuffItArchive() { + close(); +} + +// Some known values of StuffIt FourCC's +// 11H Mac in particular uses ST46 +static const uint32 s_magicNumbers[] = { + MKTAG('S', 'I', 'T', '!'), MKTAG('S', 'T', '6', '5'), MKTAG('S', 'T', '5', '0'), + MKTAG('S', 'T', '6', '0'), MKTAG('S', 'T', 'i', 'n'), MKTAG('S', 'T', 'i', '2'), + MKTAG('S', 'T', 'i', '3'), MKTAG('S', 'T', 'i', '4'), MKTAG('S', 'T', '4', '6') +}; + +bool StuffItArchive::open(const Common::String &filename) { + close(); + + _stream = SearchMan.createReadStreamForMember(filename); + + if (!_stream) + return false; + + uint32 tag = _stream->readUint32BE(); + + // Check all the possible FourCC's + bool found = false; + for (int i = 0; i < ARRAYSIZE(s_magicNumbers); i++) { + if (tag == s_magicNumbers[i]) { + found = true; + break; + } + } + + // Didn't find one, let's bail out + if (!found) { + close(); + return false; + } + + /* uint16 fileCount = */ _stream->readUint16BE(); + /* uint32 archiveSize = */ _stream->readUint32BE(); + + // Some sort of second magic number + if (_stream->readUint32BE() != MKTAG('r', 'L', 'a', 'u')) { + close(); + return false; + } + + /* byte version = */ _stream->readByte(); // meaning not clear + + _stream->skip(7); // unknown + + while (_stream->pos() < _stream->size() && !_stream->eos()) { + byte resForkCompression = _stream->readByte(); + byte dataForkCompression = _stream->readByte(); + + byte fileNameLength = _stream->readByte(); + Common::String name; + + for (byte i = 0; i < fileNameLength; i++) + name += (char)_stream->readByte(); + + // Skip remaining bytes + _stream->skip(63 - fileNameLength); + + /* uint32 fileType = */ _stream->readUint32BE(); + /* uint32 fileCreator = */ _stream->readUint32BE(); + /* uint16 finderFlags = */ _stream->readUint16BE(); + /* uint32 creationDate = */ _stream->readUint32BE(); + /* uint32 modificationDate = */ _stream->readUint32BE(); + uint32 resForkUncompressedSize = _stream->readUint32BE(); + uint32 dataForkUncompressedSize = _stream->readUint32BE(); + uint32 resForkCompressedSize = _stream->readUint32BE(); + uint32 dataForkCompressedSize = _stream->readUint32BE(); + /* uint16 resForkCRC = */ _stream->readUint16BE(); + /* uint16 dataForkCRC = */ _stream->readUint16BE(); + _stream->skip(6); // unknown + /* uint16 headerCRC = */ _stream->readUint16BE(); + + // Ignore directories for now + if (dataForkCompression == 32 || dataForkCompression == 33) + continue; + + if (dataForkUncompressedSize != 0) { + // We have a data fork + + FileEntry entry; + entry.compression = dataForkCompression; + entry.uncompressedSize = dataForkUncompressedSize; + entry.compressedSize = dataForkCompressedSize; + entry.offset = _stream->pos() + resForkCompressedSize; + _map[name] = entry; + + debug(0, "StuffIt file '%s', Compression = %d", name.c_str(), entry.compression); + } + + if (resForkUncompressedSize != 0) { + // We have a resource fork + + // Add a .rsrc extension so we know it's the resource fork + name += ".rsrc"; + + FileEntry entry; + entry.compression = resForkCompression; + entry.uncompressedSize = resForkUncompressedSize; + entry.compressedSize = resForkCompressedSize; + entry.offset = _stream->pos(); + _map[name] = entry; + + debug(0, "StuffIt file '%s', Compression = %d", name.c_str(), entry.compression); + } + + // Go to the next entry + _stream->skip(dataForkCompressedSize + resForkCompressedSize); + } + + return true; +} + +void StuffItArchive::close() { + delete _stream; _stream = 0; + _map.clear(); +} + +bool StuffItArchive::hasFile(const Common::String &name) const { + return _map.contains(name); +} + +int StuffItArchive::listMembers(Common::ArchiveMemberList &list) const { + for (FileMap::const_iterator it = _map.begin(); it != _map.end(); it++) + list.push_back(getMember(it->_key)); + + return _map.size(); +} + +const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::String &name) const { + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *StuffItArchive::createReadStreamForMember(const Common::String &name) const { + if (!_stream || !_map.contains(name)) + return 0; + + const FileEntry &entry = _map[name]; + + if (entry.compression & 0xF0) + error("Unhandled StuffIt encryption"); + + Common::SeekableSubReadStream subStream(_stream, entry.offset, entry.offset + entry.compressedSize); + + // We currently only support type 14 compression + switch (entry.compression) { + case 0: // Uncompressed + return subStream.readStream(subStream.size()); + case 14: // Installer + return decompress14(&subStream, entry.uncompressedSize); + default: + error("Unhandled StuffIt compression %d", entry.compression); + } + + return 0; +} + +void StuffItArchive::update14(uint16 first, uint16 last, byte *code, uint16 *freq) const { + uint16 i, j; + + while (last - first > 1) { + i = first; + j = last; + + do { + while (++i < last && code[first] > code[i]) + ; + + while (--j > first && code[first] < code[j]) + ; + + if (j > i) { + SWAP(code[i], code[j]); + SWAP(freq[i], freq[j]); + } + } while (j > i); + + if (first != j) { + SWAP(code[first], code[j]); + SWAP(freq[first], freq[j]); + + i = j + 1; + + if (last - i <= j - first) { + update14(i, last, code, freq); + last = j; + } else { + update14(first, j, code, freq); + first = i; + } + } else { + ++first; + } + } +} + +struct SIT14Data { + byte code[308]; + byte codecopy[308]; + uint16 freq[308]; + uint32 buff[308]; + + byte var1[52]; + uint16 var2[52]; + uint16 var3[75 * 2]; + + byte var4[76]; + uint32 var5[75]; + byte var6[1024]; + uint16 var7[308 * 2]; + byte var8[0x4000]; + + byte window[0x40000]; +}; + +// Realign to a byte boundary +#define ALIGN_BITS(b) \ + if (b->pos() & 7) \ + b->skip(8 - (b->pos() & 7)) + +void StuffItArchive::readTree14(Common::BitStream *bits, SIT14Data *dat, uint16 codesize, uint16 *result) const { + uint32 i, l, n; + uint32 k = bits->getBit(); + uint32 j = bits->getBits(2) + 2; + uint32 o = bits->getBits(3) + 1; + uint32 size = 1 << j; + uint32 m = size - 1; + k = k ? (m - 1) : 0xFFFFFFFF; + + if (bits->getBits(2) & 1) { // skip 1 bit! + // requirements for this call: dat->buff[32], dat->code[32], dat->freq[32*2] + readTree14(bits, dat, size, dat->freq); + + for (i = 0; i < codesize; ) { + l = 0; + + do { + l = dat->freq[l + bits->getBit()]; + n = size << 1; + } while (n > l); + + l -= n; + + if (k != l) { + if (l == m) { + l = 0; + + do { + l = dat->freq[l + bits->getBit()]; + n = size << 1; + } while (n > l); + + l += 3 - n; + + while (l--) { + dat->code[i] = dat->code[i - 1]; + ++i; + } + } else { + dat->code[i++] = l + o; + } + } else { + dat->code[i++] = 0; + } + } + } else { + for (i = 0; i < codesize; ) { + l = bits->getBits(j); + + if (k != l) { + if (l == m) { + l = bits->getBits(j) + 3; + + while (l--) { + dat->code[i] = dat->code[i - 1]; + ++i; + } + } else { + dat->code[i++] = l+o; + } + } else { + dat->code[i++] = 0; + } + } + } + + for (i = 0; i < codesize; ++i) { + dat->codecopy[i] = dat->code[i]; + dat->freq[i] = i; + } + + update14(0, codesize, dat->codecopy, dat->freq); + + for (i = 0; i < codesize && !dat->codecopy[i]; ++i) + ; // find first nonempty + + for (j = 0; i < codesize; ++i, ++j) { + if (i) + j <<= (dat->codecopy[i] - dat->codecopy[i - 1]); + + k = dat->codecopy[i]; m = 0; + + for (l = j; k--; l >>= 1) + m = (m << 1) | (l & 1); + + dat->buff[dat->freq[i]] = m; + } + + for (i = 0; i < (uint32)codesize * 2; ++i) + result[i] = 0; + + j = 2; + + for (i = 0; i < codesize; ++i) { + l = 0; + m = dat->buff[i]; + + for (k = 0; k < dat->code[i]; ++k) { + l += (m & 1); + + if (dat->code[i] - 1 <= (int32)k) { + result[l] = codesize * 2 + i; + } else { + if (!result[l]) { + result[l] = j; + j += 2; + } + + l = result[l]; + } + + m >>= 1; + } + } + + ALIGN_BITS(bits); +} + +#define OUTPUT_VAL(x) \ + out.writeByte(x); \ + dat->window[j++] = x; \ + j &= 0x3FFFF + +Common::SeekableReadStream *StuffItArchive::decompress14(Common::SeekableReadStream *src, uint32 uncompressedSize) const { + byte *dst = (byte *)malloc(uncompressedSize); + Common::MemoryWriteStream out(dst, uncompressedSize); + + Common::BitStream *bits = new Common::BitStream8LSB(src); + + uint32 i, j, k, l, m, n; + + SIT14Data *dat = new SIT14Data(); + + // initialization + for (i = k = 0; i < 52; ++i) { + dat->var2[i] = k; + k += (1 << (dat->var1[i] = ((i >= 4) ? ((i - 4) >> 2) : 0))); + } + + for (i = 0; i < 4; ++i) + dat->var8[i] = i; + + for (m = 1, l = 4; i < 0x4000; m <<= 1) // i is 4 + for (n = l+4; l < n; ++l) + for (j = 0; j < m; ++j) + dat->var8[i++] = l; + + for (i = 0, k = 1; i < 75; ++i) { + dat->var5[i] = k; + k += (1 << (dat->var4[i] = (i >= 3 ? ((i - 3) >> 2) : 0))); + } + + for (i = 0; i < 4; ++i) + dat->var6[i] = i - 1; + + for (m = 1, l = 3; i < 0x400; m <<= 1) // i is 4 + for (n = l + 4; l < n; ++l) + for (j = 0; j < m; ++j) + dat->var6[i++] = l; + + m = bits->getBits(16); // number of blocks + j = 0; // window position + + while (m-- && !bits->eos()) { + bits->getBits(16); // skip crunched block size + bits->getBits(16); + n = bits->getBits(16); // number of uncrunched bytes + n |= bits->getBits(16) << 16; + readTree14(bits, dat, 308, dat->var7); + readTree14(bits, dat, 75, dat->var3); + + while (n && !bits->eos()) { + for (i = 0; i < 616;) + i = dat->var7[i + bits->getBit()]; + + i -= 616; + + if (i < 0x100) { + OUTPUT_VAL(i); + --n; + } else { + i -= 0x100; + k = dat->var2[i]+4; + i = dat->var1[i]; + + if (i) + k += bits->getBits(i); + + for (i = 0; i < 150;) + i = dat->var3[i + bits->getBit()]; + + i -= 150; + l = dat->var5[i]; + i = dat->var4[i]; + + if (i) + l += bits->getBits(i); + + n -= k; + l = j + 0x40000 - l; + + while (k--) { + l &= 0x3FFFF; + OUTPUT_VAL(dat->window[l]); + l++; + } + } + } + + ALIGN_BITS(bits); + } + + delete dat; + delete bits; + + return new Common::MemoryReadStream(dst, uncompressedSize, DisposeAfterUse::YES); +} + +#undef OUTPUT_VAL +#undef ALIGN_BITS + +Common::Archive *createStuffItArchive(const Common::String &fileName) { + StuffItArchive *archive = new StuffItArchive(); + + if (!archive->open(fileName)) { + delete archive; + return 0; + } + + return archive; +} + +} // End of namespace Groovie diff --git a/engines/groovie/stuffit.h b/engines/groovie/stuffit.h new file mode 100644 index 0000000000..44f593dbea --- /dev/null +++ b/engines/groovie/stuffit.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GROOVIE_STUFFIT_H +#define GROOVIE_STUFFIT_H + +namespace Common { +class Archive; +class String; +} + +namespace Groovie { + +/** + * This factory method creates an Archive instance corresponding to the content + * of the StuffIt compressed file. + * + * May return 0 in case of a failure. + */ +Common::Archive *createStuffItArchive(const Common::String &fileName); + +} // End of namespace Groovie + +#endif diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp index b3fcf462b2..8786e75488 100644 --- a/engines/groovie/vdx.cpp +++ b/engines/groovie/vdx.cpp @@ -88,7 +88,7 @@ uint16 VDXPlayer::loadInternal() { // Enable highspeed if we're not obeying fps, and not marked as special // This will be disabled in chunk audio if we're actually an audio vdx - if ( _vm->_modeSpeed == kGroovieSpeediOS || (_vm->_modeSpeed == kGroovieSpeedTweaked && ((_flags & (1 << 15)) == 0))) + if (_vm->_modeSpeed == kGroovieSpeedFast && ((_flags & (1 << 15)) == 0)) setOverrideSpeed(true); if (_flagOnePrev && !_flagOne && !_flagEight) { diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 5fdb2026a7..2585c64fd8 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -235,7 +235,7 @@ void Parser::charHandler() { if (_cmdLineIndex >= kMaxLineSize) { //MessageBeep(MB_ICONASTERISK); warning("STUB: MessageBeep() - Command line too long"); - } else if (isprint(static_cast<unsigned char>(c))) { + } else if (Common::isPrint(c)) { _cmdLine[_cmdLineIndex++] = c; _cmdLine[_cmdLineIndex] = '\0'; } diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp index 54e1abcc2c..80a95da047 100644 --- a/engines/kyra/chargen.cpp +++ b/engines/kyra/chargen.cpp @@ -193,7 +193,7 @@ bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) { } if (inputFlag & 0x8000) { - inputFlag = (inputFlag & 0x0f) - 1; + inputFlag = (inputFlag & 0x0F) - 1; if (inputFlag == 4) { loop = false; } else { @@ -402,7 +402,7 @@ int CharacterGenerator::viewDeleteCharacter() { } if (inputFlag & 0x8000) { - inputFlag = (inputFlag & 0x0f) - 1; + inputFlag = (inputFlag & 0x0F) - 1; if (inputFlag == 4) { res = 1; loop = false; @@ -524,7 +524,7 @@ int CharacterGenerator::classMenu(int raceSex) { while (res == -1 && !_vm->shouldQuit()) { updateMagicShapes(); - int in = getInput(0) & 0xff; + int in = getInput(0) & 0xFF; Common::Point mp = _vm->getMousePos(); if (in == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_b]) { @@ -572,7 +572,7 @@ int CharacterGenerator::alignmentMenu(int cClass) { while (res == -1 && !_vm->shouldQuit()) { updateMagicShapes(); - int in = getInput(0) & 0xff; + int in = getInput(0) & 0xFF; Common::Point mp = _vm->getMousePos(); if (in == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_b]) { @@ -658,14 +658,14 @@ void CharacterGenerator::generateStats(int index) { sv[i] = _chargenMaxStats[i]; } - c->strengthCur = c->strengthMax = sv[0] & 0xff; + c->strengthCur = c->strengthMax = sv[0] & 0xFF; c->strengthExtCur = c->strengthExtMax = sv[0] >> 8; - c->intelligenceCur = c->intelligenceMax = sv[1] & 0xff; - c->wisdomCur = c->wisdomMax = sv[2] & 0xff; - c->dexterityCur = c->dexterityMax = sv[3] & 0xff; - c->constitutionCur = c->constitutionMax = sv[4] & 0xff; - c->charismaCur = c->charismaMax = sv[5] & 0xff; - c->armorClass = 10 + _vm->getDexterityArmorClassModifier(sv[3] & 0xff); + c->intelligenceCur = c->intelligenceMax = sv[1] & 0xFF; + c->wisdomCur = c->wisdomMax = sv[2] & 0xFF; + c->dexterityCur = c->dexterityMax = sv[3] & 0xFF; + c->constitutionCur = c->constitutionMax = sv[4] & 0xFF; + c->charismaCur = c->charismaMax = sv[5] & 0xFF; + c->armorClass = 10 + _vm->getDexterityArmorClassModifier(sv[3] & 0xFF); c->hitPointsCur = 0; for (int l = 0; l < 3; l++) { @@ -817,7 +817,7 @@ void CharacterGenerator::faceSelectMenu() { } else if (in == _vm->_keyMap[Common::KEYCODE_RETURN] || in == _vm->_keyMap[Common::KEYCODE_KP5]) { in = 3; } else if (in & 0x8000) { - in &= 0xff; + in &= 0xFF; } else { in = 0; } @@ -1017,7 +1017,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) { ci = -2; } else if (inputFlag & 0x8000) { - inputFlag = (inputFlag & 0x0f) - 1; + inputFlag = (inputFlag & 0x0F) - 1; if (index != inputFlag) { ci = inputFlag; loop = false; @@ -1037,7 +1037,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) { v2--; } - v1 = CLIP<uint8>(v1, _chargenMinStats[index], _chargenMaxStats[index] & 0xff); + v1 = CLIP<uint8>(v1, _chargenMinStats[index], _chargenMaxStats[index] & 0xFF); v2 = (v1 == 18 && _chargenMaxStats[index] >= 19) ? CLIP<uint8>(v2, 0, 100) : 0; if (s2) *s2 = v2; @@ -1206,7 +1206,7 @@ void CharacterGenerator::finish() { static const int8 itemList1[] = { 1, 2, 0, 17, -1, 0, 0 }; static const int8 itemList2[] = { 2, 56, 1, 17, 31, 0, 1, 23, 1, 17, 31, 0, 1 }; static const int8 itemList3[] = { 2, 1, 1, 17, 31, 1, 1, 1, 0, 17, 31, 2, 1 }; - static const int8 *itemList[] = { itemList0, itemList1, itemList2, itemList3 }; + static const int8 *const itemList[] = { itemList0, itemList1, itemList2, itemList3 }; for (int i = 0; i < 4; i++) { EoBCharacter *c = &_characters[i]; @@ -1496,7 +1496,7 @@ TransferPartyWiz::~TransferPartyWiz() { } bool TransferPartyWiz::start() { - _screen->copyPage(0, _vm->_useHiResDithering ? 1 : 12); + _screen->copyPage(0, 12); if (!selectAndLoadTransferFile()) return false; @@ -1536,7 +1536,7 @@ bool TransferPartyWiz::start() { bool TransferPartyWiz::selectAndLoadTransferFile() { do { - _screen->copyPage(_vm->_useHiResDithering ? 1 : 12, 0); + _screen->copyPage(12, 0); if (transferFileDialogue(_vm->_savegameFilename)) break; } while (_vm->_gui->confirmDialogue2(15, 68, 1)); @@ -1566,7 +1566,7 @@ bool TransferPartyWiz::selectAndLoadTransferFile() { return false; Common::String target = _vm->_gui->transferTargetMenu(eobTargets); - _screen->copyPage(_vm->_useHiResDithering ? 1 : 12, 0); + _screen->copyPage(12, 0); if (target.empty()) return true; @@ -1579,10 +1579,10 @@ bool TransferPartyWiz::selectAndLoadTransferFile() { return true; } - _screen->copyPage(_vm->_useHiResDithering ? 1 : 12, 0); + _screen->copyPage(12, 0); bool result = _vm->_gui->transferFileMenu(target, dest); - _screen->copyPage(_vm->_useHiResDithering ? 1 : 12, 0); + _screen->copyPage(12, 0); return result; } @@ -1614,7 +1614,7 @@ int TransferPartyWiz::selectCharactersMenu() { bool update = false; for (bool loop = true; loop && (!_vm->shouldQuit());) { - int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF; _vm->removeInputTop(); if (inputFlag) { @@ -1827,7 +1827,7 @@ Item TransferPartyWiz::convertItem(Item eob1Item) { itm2->flags = itm1->flags | 0x40; itm2->icon = itm1->icon; itm2->type = itm1->type; - itm2->level = 0xff; + itm2->level = 0xFF; switch (itm2->type) { case 35: @@ -1850,7 +1850,7 @@ Item TransferPartyWiz::convertItem(Item eob1Item) { return 0; } itm2->value = itm1->value; - itm2->flags = ((itm1->flags & 0x3f) + 3) | 0x40; + itm2->flags = ((itm1->flags & 0x3F) + 3) | 0x40; break; case 18: itm2->icon = 19; @@ -1860,7 +1860,7 @@ Item TransferPartyWiz::convertItem(Item eob1Item) { break; } - switch ((_vm->_itemTypes[itm2->type].extraProperties & 0x7f) - 1) { + switch ((_vm->_itemTypes[itm2->type].extraProperties & 0x7F) - 1) { case 0: case 1: case 2: diff --git a/engines/kyra/darkmoon.cpp b/engines/kyra/darkmoon.cpp index 16bd3dad58..130fb10df3 100644 --- a/engines/kyra/darkmoon.cpp +++ b/engines/kyra/darkmoon.cpp @@ -136,7 +136,7 @@ void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) { if (itm->type == 48 || itm->type == 62) { if (itm->value == 5) return; - int charges = itm->flags & 0x3f; + int charges = itm->flags & 0x3F; if (--charges) --itm->flags; else @@ -158,10 +158,7 @@ void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterInde int colx = 302 + 3 * i; for (int ii = 0; ii < 16; ii++) { - // Don't use getPagePixel() here, since in EGA mode it will try to - // undither the pixel (although the shape bitmap is undithered already) - uint8 col = _screen->getCPagePtr(_screen->_curPage | 1)[(184 + ii) * Screen::SCREEN_W + colx]; - + uint8 col = _screen->getPagePixel(_screen->_curPage, colx, 184 + ii); int iii = 0; for (; iii < 16; iii++) { if (tmpPal[iii] == col) { @@ -178,9 +175,7 @@ void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterInde memcpy(tmpPal, _monsterShapes[dci] + 4, 16); for (int iii = 0; iii < 16; iii++) { - // Don't use getPagePixel() here, since in EGA mode it will try to - // undither the pixel (although the shape bitmap is undithered already) - uint8 col = _screen->getCPagePtr(_screen->_curPage | 1)[(184 + iii) * Screen::SCREEN_W + colx + ii]; + uint8 col = _screen->getPagePixel(_screen->_curPage, colx + ii, 184 + iii); if (newPal[iii]) tmpPal[newPal[iii]] = col; } @@ -455,7 +450,7 @@ void DarkMoonEngine::characterLevelGain(int charIndex) { int s = _numLevelsPerClass[c->cClass]; for (int i = 0; i < s; i++) { uint32 er = getRequiredExperience(c->cClass, i, c->level[i] + 1); - if (er == 0xffffffff) + if (er == 0xFFFFFFFF) continue; increaseCharacterExperience(charIndex, er - c->experience[i] + 1); diff --git a/engines/kyra/darkmoon.h b/engines/kyra/darkmoon.h index f6e7b3ed2c..f0057ddd66 100644 --- a/engines/kyra/darkmoon.h +++ b/engines/kyra/darkmoon.h @@ -72,21 +72,21 @@ private: void seq_playFinale(); void seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *data, int sd, int backupPage, int tempPage, int speed); - const char * const *_introStrings; - const char * const *_cpsFilesIntro; + const char *const *_introStrings; + const char *const *_cpsFilesIntro; const DarkMoonAnimCommand **_animIntro; const DarkMoonShapeDef **_shapesIntro; - const char * const *_finaleStrings; + const char *const *_finaleStrings; const uint8 *_creditsData; - const char * const *_cpsFilesFinale; + const char *const *_cpsFilesFinale; const DarkMoonAnimCommand **_animFinale; const DarkMoonShapeDef **_shapesFinale; - static const char *_palFilesIntroVGA[]; - static const char *_palFilesIntroEGA[]; - static const char *_palFilesFinaleVGA[]; - static const char *_palFilesFinaleEGA[]; + static const char *const _palFilesIntroVGA[]; + static const char *const _palFilesIntroEGA[]; + static const char *const _palFilesFinaleVGA[]; + static const char *const _palFilesFinaleEGA[]; // Ingame sequence void seq_nightmare(); @@ -140,7 +140,7 @@ private: static const uint8 _egaDefaultPalette[]; }; -} // End of namespace Kyra +} // End of namespace Kyra #endif diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index e422f3ea19..95c4accd29 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -298,7 +298,7 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s if (in) { Kyra::KyraEngine_v1::SaveHeader header; - Kyra::KyraEngine_v1::kReadSaveHeaderError error; + Kyra::KyraEngine_v1::ReadSaveHeaderError error; error = Kyra::KyraEngine_v1::readSaveHeader(in, true, header); delete in; diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h index e2162f20e2..d948f7d12d 100644 --- a/engines/kyra/detection_tables.h +++ b/engines/kyra/detection_tables.h @@ -53,7 +53,8 @@ namespace { #define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_LOL) #define LOL_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_LOL) #define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_LOL) -#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, false, true, true, false, false, Kyra::GI_LOL) +#define LOL_PC9801_FLAGS FLAGS(false, false, false, false, true, true, false, false, Kyra::GI_LOL) +#define LOL_FMTOWNS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_LOL) #define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, Kyra::GI_LOL) #define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2) @@ -1462,7 +1463,24 @@ const KYRAGameDescription adGameDescs[] = { ADGF_NO_FLAGS, GUIO5(GUIO_NOSPEECH, GUIO_MIDIPC98, GUIO_RENDERPC9801, GAMEOPTION_LOL_SCROLLING, GAMEOPTION_LOL_CURSORS) }, - LOL_PC98_SJIS_FLAGS + LOL_PC9801_FLAGS + }, + + { + { + "lol", + 0, + { + { "GENERAL.PAK", 0, "2e4d4ce54bac9162e11fcba6907b576e", -1 }, + { "TMUS.PAK", 0, "5543dae575164e51856f5a49cfd6b368", -1 }, + { 0, 0, 0, 0 } + }, + Common::JA_JPN, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + GUIO5(GUIO_NOSPEECH, GUIO_MIDITOWNS, GUIO_RENDERFMTOWNS, GAMEOPTION_LOL_SCROLLING, GAMEOPTION_LOL_CURSORS) + }, + LOL_FMTOWNS_FLAGS }, { @@ -1495,7 +1513,7 @@ const KYRAGameDescription adGameDescs[] = { ADGF_DEMO, GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_MIDIPCSPK, GUIO_RENDERVGA) }, - LOL_KYRA2_DEMO_FLAGS + LOL_DEMO_FLAGS }, #endif // ENABLE_LOL #ifdef ENABLE_EOB diff --git a/engines/kyra/eob.cpp b/engines/kyra/eob.cpp index a7bde9f1ee..4e1707b1ac 100644 --- a/engines/kyra/eob.cpp +++ b/engines/kyra/eob.cpp @@ -316,7 +316,7 @@ void EoBEngine::runNpcDialogue(int npcIndex) { void EoBEngine::updateUsedCharacterHandItem(int charIndex, int slot) { EoBItem *itm = &_items[_characters[charIndex].inventory[slot]]; if (itm->type == 48) { - int charges = itm->flags & 0x3f; + int charges = itm->flags & 0x3F; if (--charges) --itm->flags; else @@ -359,7 +359,7 @@ void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s _screen->loadShapeSetBitmap("DOOR", 5, 3); _screen->_curPage = 2; - if (doorType1 != 0xff) { + if (doorType1 != 0xFF) { for (int i = 0; i < 3; i++) { const uint8 *enc = &_doorShapeEncodeDefs[(doorType1 * 3 + i) << 2]; _doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0); @@ -370,7 +370,7 @@ void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s } } - if (doorType2 != 0xff) { + if (doorType2 != 0xFF) { for (int i = 0; i < 3; i++) { const uint8 *enc = &_doorShapeEncodeDefs[(doorType2 * 3 + i) << 2]; _doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0); @@ -460,7 +460,7 @@ void EoBEngine::turnUndeadAuto() { int oc = _openBookChar; for (int i = 0; i < 6; i++) { - if (!testCharacter(i, 0x0d)) + if (!testCharacter(i, 0x0D)) continue; EoBCharacter *c = &_characters[i]; @@ -505,7 +505,7 @@ bool EoBEngine::checkPartyStatusExtra() { _txt->printMessage(_menuStringsDefeat[0]); while (!shouldQuit()) { removeInputTop(); - if (checkInput(0, false, 0) & 0xff) + if (checkInput(0, false, 0) & 0xFF) break; } _screen->copyPage(10, 0); diff --git a/engines/kyra/eob.h b/engines/kyra/eob.h index 37ce483702..bf5440b942 100644 --- a/engines/kyra/eob.h +++ b/engines/kyra/eob.h @@ -99,7 +99,7 @@ private: void turnUndeadAuto(); void turnUndeadAutoHit(); - const char * const *_turnUndeadString; + const char *const *_turnUndeadString; // Misc bool checkPartyStatusExtra(); @@ -113,8 +113,7 @@ private: static const uint8 _egaDefaultPalette[]; }; - -} // End of namespace Kyra +} // End of namespace Kyra #endif diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index fadb1066e0..d477209e5b 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -57,7 +57,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) _configMouse = true; _loading = false; - _useHiResDithering = false; + _enableHiResDithering = false; _envAudioTimer = 0; _flashShapeTimer = 0; @@ -364,14 +364,14 @@ void EoBCoreEngine::initKeymap() { } Common::Error EoBCoreEngine::init() { - // In EOB the timer proc is directly invoked via interrupt 0x1c, 18.2 times per second. + // In EOB the timer proc is directly invoked via interrupt 0x1C, 18.2 times per second. // This makes a tick length of 54.94. _tickLength = 55; if (ConfMan.hasKey("render_mode")) _configRenderMode = Common::parseRenderMode(ConfMan.get("render_mode")); - _useHiResDithering = (_configRenderMode == Common::kRenderEGA && _flags.useHiRes); + _enableHiResDithering = (_configRenderMode == Common::kRenderEGA && _flags.useHiRes); _screen = new Screen_EoB(this, _system); assert(_screen); @@ -417,12 +417,6 @@ Common::Error EoBCoreEngine::init() { _screen->loadFont(Screen::FID_6_FNT, "FONT6.FNT"); _screen->loadFont(Screen::FID_8_FNT, "FONT8.FNT"); - if (_useHiResDithering) { - _vcnBlockWidth <<= 1; - _vcnBlockHeight <<= 1; - SWAP(_vcnFlip0, _vcnFlip1); - } - Common::Error err = KyraRpgEngine::init(); if (err.getCode() != Common::kNoError) return err; @@ -494,8 +488,8 @@ Common::Error EoBCoreEngine::init() { _monsterFlashOverlay = new uint8[16]; _monsterStoneOverlay = new uint8[16]; - memset(_monsterFlashOverlay, (_configRenderMode == Common::kRenderCGA) ? 0xff : 0x0f, 16 * sizeof(uint8)); - memset(_monsterStoneOverlay, 0x0d, 16 * sizeof(uint8)); + memset(_monsterFlashOverlay, (_configRenderMode == Common::kRenderCGA) ? 0xFF : 0x0F, 16 * sizeof(uint8)); + memset(_monsterStoneOverlay, 0x0D, 16 * sizeof(uint8)); _monsterFlashOverlay[0] = _monsterStoneOverlay[0] = 0; // Prevent autosave on game startup @@ -991,7 +985,7 @@ void EoBCoreEngine::recalcArmorClass(int index) { int tp = _items[itm].type; - if (!(_itemTypes[tp].allowedClasses & _classModifierFlags[c->cClass]) || (_itemTypes[tp].extraProperties & 0x7f) || (i >= 1 && i <= 2 && tp != 27 && !(_flags.gameID == GI_EOB2 && tp == 57))) + if (!(_itemTypes[tp].allowedClasses & _classModifierFlags[c->cClass]) || (_itemTypes[tp].extraProperties & 0x7F) || (i >= 1 && i <= 2 && tp != 27 && !(_flags.gameID == GI_EOB2 && tp == 57))) continue; c->armorClass += _itemTypes[tp].armorClass; @@ -1003,12 +997,12 @@ void EoBCoreEngine::recalcArmorClass(int index) { int8 m2 = 0; if (c->inventory[25]) { - if (!(_itemTypes[_items[c->inventory[25]].type].extraProperties & 0x7f)) + if (!(_itemTypes[_items[c->inventory[25]].type].extraProperties & 0x7F)) m1 = _items[c->inventory[25]].value; } if (c->inventory[26]) { - if (!(_itemTypes[_items[c->inventory[26]].type].extraProperties & 0x7f)) + if (!(_itemTypes[_items[c->inventory[26]].type].extraProperties & 0x7F)) m2 = _items[c->inventory[26]].value; } @@ -1060,7 +1054,7 @@ int EoBCoreEngine::validateWeaponSlotItem(int index, int slot) { if (!itm2) return 1; - int f = (_itemTypes[tp2].extraProperties & 0x7f); + int f = (_itemTypes[tp2].extraProperties & 0x7F); if (f <= 0 || f > 3) return r; @@ -1275,12 +1269,12 @@ void EoBCoreEngine::removeCharacterFromParty(int charIndex) { if (i == 16 || !c->inventory[i]) continue; - setItemPosition((Item *)&_levelBlockProperties[_currentBlock & 0x3ff].drawObjects, _currentBlock, c->inventory[i], _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]); + setItemPosition((Item *)&_levelBlockProperties[_currentBlock & 0x3FF].drawObjects, _currentBlock, c->inventory[i], _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]); c->inventory[i] = 0; } while (c->inventory[16]) - setItemPosition((Item *)&_levelBlockProperties[_currentBlock & 0x3ff].drawObjects, _currentBlock, getQueuedItem(&c->inventory[16], 0, -1), _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]); + setItemPosition((Item *)&_levelBlockProperties[_currentBlock & 0x3FF].drawObjects, _currentBlock, getQueuedItem(&c->inventory[16], 0, -1), _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]); c->inventory[16] = 0; @@ -1326,7 +1320,7 @@ void EoBCoreEngine::increaseCharacterExperience(int charIndex, int32 points) { _characters[charIndex].experience[i] += points; uint32 er = getRequiredExperience(cl, i, _characters[charIndex].level[i] + 1); - if (er == 0xffffffff) + if (er == 0xFFFFFFFF) continue; if (_characters[charIndex].experience[i] >= er) @@ -1337,7 +1331,7 @@ void EoBCoreEngine::increaseCharacterExperience(int charIndex, int32 points) { uint32 EoBCoreEngine::getRequiredExperience(int cClass, int levelIndex, int level) { cClass = getCharacterClassType(cClass, levelIndex); if (cClass == -1) - return 0xffffffff; + return 0xFFFFFFFF; const uint32 *tbl = _expRequirementTables[cClass]; return tbl[level - 1]; @@ -1625,7 +1619,7 @@ void EoBCoreEngine::displayParchment(int id) { removeInputTop(); while (!shouldQuit()) { delay(_tickLength); - if (checkInput(0, false, 0) & 0xff) + if (checkInput(0, false, 0) & 0xFF) break; removeInputTop(); } @@ -1658,7 +1652,7 @@ int EoBCoreEngine::countResurrectionCandidates() { if (!inv) continue; - if ((_flags.gameID == GI_EOB1 && ((_itemTypes[_items[inv].type].extraProperties & 0x7f) != 8)) || (_flags.gameID == GI_EOB2 && _items[inv].type != 33)) + if ((_flags.gameID == GI_EOB1 && ((_itemTypes[_items[inv].type].extraProperties & 0x7F) != 8)) || (_flags.gameID == GI_EOB2 && _items[inv].type != 33)) continue; _rrNames[_rrCount] = _npcPreset[_items[inv].value - 1].name; @@ -1667,7 +1661,7 @@ int EoBCoreEngine::countResurrectionCandidates() { } if (_itemInHand > 0) { - if ((_flags.gameID == GI_EOB1 && ((_itemTypes[_items[_itemInHand].type].extraProperties & 0x7f) == 8)) || (_flags.gameID == GI_EOB2 && _items[_itemInHand].type == 33)) { + if ((_flags.gameID == GI_EOB1 && ((_itemTypes[_items[_itemInHand].type].extraProperties & 0x7F) == 8)) || (_flags.gameID == GI_EOB2 && _items[_itemInHand].type == 33)) { _rrNames[_rrCount] = _npcPreset[_items[_itemInHand].value - 1].name; _rrId[_rrCount++] = -_items[_itemInHand].value; } @@ -1748,7 +1742,7 @@ void EoBCoreEngine::seq_portal() { bool EoBCoreEngine::checkPassword() { char answ[20]; Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); - _screen->copyPage(0, _useHiResDithering ? 4 : 10); + _screen->copyPage(0, 10); _screen->setScreenDim(13); gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1); @@ -1775,7 +1769,7 @@ bool EoBCoreEngine::checkPassword() { _screen->modifyScreenDim(13, _screen->_curDim->sx - 1, _screen->_curDim->sy - 2, _screen->_curDim->w + 2, _screen->_curDim->h + 16); _screen->setFont(of); - _screen->copyPage(_useHiResDithering ? 4 : 10, 0); + _screen->copyPage(10, 0); return true; } @@ -1786,7 +1780,7 @@ void EoBCoreEngine::useSlotWeapon(int charIndex, int slotIndex, Item item) { if (c->effectFlags & 0x40) removeCharacterEffect(10, charIndex, 1); // remove invisibility effect - int ep = _itemTypes[tp].extraProperties & 0x7f; + int ep = _itemTypes[tp].extraProperties & 0x7F; int8 inflict = 0; if (ep == 1) { @@ -1829,14 +1823,14 @@ int EoBCoreEngine::closeDistanceAttack(int charIndex, Item item) { if (r == -1) { uint8 w = _specialWallTypes[_levelBlockProperties[d].walls[_sceneDrawVarDown]]; - if (w == 0xff) { + if (w == 0xFF) { if (_flags.gameID == GI_EOB1) { _levelBlockProperties[d].walls[_sceneDrawVarDown]++; _levelBlockProperties[d].walls[_sceneDrawVarDown ^ 2]++; } else { for (int i = 0; i < 4; i++) { - if (_specialWallTypes[_levelBlockProperties[d].walls[i]] == 0xff) + if (_specialWallTypes[_levelBlockProperties[d].walls[i]] == 0xFF) _levelBlockProperties[d].walls[i]++; } } @@ -1927,7 +1921,7 @@ int EoBCoreEngine::projectileWeaponAttack(int charIndex, Item item) { void EoBCoreEngine::inflictMonsterDamage(EoBMonsterInPlay *m, int damage, bool giveExperience) { m->hitPointsCur -= damage; - m->flags = (m->flags & 0xf7) | 1; + m->flags = (m->flags & 0xF7) | 1; if (_monsterProps[m->type].capsFlags & 0x2000) { explodeMonster(m); @@ -2033,7 +2027,7 @@ bool EoBCoreEngine::characterAttackHitTest(int charIndex, int monsterIndex, int if (charIndex < 0) return true; - int p = item ? (_flags.gameID == GI_EOB1 ? _items[item].type : (_itemTypes[_items[item].type].extraProperties & 0x7f)) : 0; + int p = item ? (_flags.gameID == GI_EOB1 ? _items[item].type : (_itemTypes[_items[item].type].extraProperties & 0x7F)) : 0; if (_monsters[monsterIndex].flags & 0x20) return true;// EOB 2 only ? @@ -2212,7 +2206,7 @@ void EoBCoreEngine::statusAttack(int charIndex, int attackStatusFlags, const cha c->flags |= attackStatusFlags; } - if ((attackStatusFlags & 0x0c) && (_openBookChar == charIndex) && _updateFlags) { + if ((attackStatusFlags & 0x0C) && (_openBookChar == charIndex) && _updateFlags) { Button b; clickedSpellbookAbort(&b); } @@ -2318,7 +2312,7 @@ int EoBCoreEngine::getSaveThrowModifier(int hpModifier, int level, int type) { } bool EoBCoreEngine::calcDamageCheckItemType(int itemType) { - itemType = _itemTypes[itemType].extraProperties & 0x7f; + itemType = _itemTypes[itemType].extraProperties & 0x7F; return (itemType == 2 || itemType == 3) ? true : false; } diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index f60e755dd7..70200d3049 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -722,21 +722,21 @@ protected: void gui_processWeaponSlotClickRight(int charIndex, int slotIndex); void gui_processInventorySlotClick(int slot); - static const int16 _buttonList1[]; + static const uint8 _buttonList1[]; int _buttonList1Size; - static const int16 _buttonList2[]; + static const uint8 _buttonList2[]; int _buttonList2Size; - static const int16 _buttonList3[]; + static const uint8 _buttonList3[]; int _buttonList3Size; - static const int16 _buttonList4[]; + static const uint8 _buttonList4[]; int _buttonList4Size; - static const int16 _buttonList5[]; + static const uint8 _buttonList5[]; int _buttonList5Size; - static const int16 _buttonList6[]; + static const uint8 _buttonList6[]; int _buttonList6Size; - static const int16 _buttonList7[]; + static const uint8 _buttonList7[]; int _buttonList7Size; - static const int16 _buttonList8[]; + static const uint8 _buttonList8[]; int _buttonList8Size; const EoBGuiButtonDef *_buttonDefs; @@ -845,7 +845,7 @@ protected: const uint8 *_cgaMappingLevel[5]; const uint8 *_cgaLevelMappingIndex; - bool _useHiResDithering; + bool _enableHiResDithering; // Default parameters will import all present original save files and push them to the top of the save dialog. bool importOriginalSaveFile(int destSlot, const char *sourceFile = 0); @@ -858,11 +858,11 @@ protected: void restoreWallOfForceTempData(LevelTempData *tmp); void releaseWallOfForceTempData(LevelTempData *tmp); - const char * const *_saveLoadStrings; + const char *const *_saveLoadStrings; const uint8 *_mnDef; - const char * const *_mnWord; - const char * const *_mnPrompt; + const char *const *_mnWord; + const char *const *_mnPrompt; int _mnNumWord; int _rrCount; diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp index e3c0743e5c..ed3aaefbd9 100644 --- a/engines/kyra/gui_eob.cpp +++ b/engines/kyra/gui_eob.cpp @@ -86,7 +86,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) { int txtCol1 = 12; int txtCol2 = 15; - if ((_flags.gameID == GI_EOB1 && c->flags & 6) || (_flags.gameID == GI_EOB2 && c->flags & 0x0e)) { + if ((_flags.gameID == GI_EOB1 && c->flags & 6) || (_flags.gameID == GI_EOB2 && c->flags & 0x0E)) { txtCol1 = 8; txtCol2 = 6; } @@ -285,7 +285,7 @@ void EoBCoreEngine::gui_drawWeaponSlot(int charIndex, int slot) { else _screen->drawShape(_screen->_curPage, _itemIconShapes[85 + slot], x + 8, y, 0); - if ((_characters[charIndex].disabledSlots & (1 << slot)) || !validateWeaponSlotItem(charIndex, slot) || (_characters[charIndex].hitPointsCur <= 0) || (_characters[charIndex].flags & 0x0c)) + if ((_characters[charIndex].disabledSlots & (1 << slot)) || !validateWeaponSlotItem(charIndex, slot) || (_characters[charIndex].hitPointsCur <= 0) || (_characters[charIndex].flags & 0x0C)) _screen->drawShape(_screen->_curPage, _weaponSlotGrid, x, y, 0); } @@ -321,7 +321,7 @@ void EoBCoreEngine::gui_drawWeaponSlotStatus(int x, int y, int status) { break; } - int textColor= (_configRenderMode == Common::kRenderCGA) ? 2 : 15; + int textColor = (_configRenderMode == Common::kRenderCGA) ? 2 : 15; if (!tmpStr2.empty()) { _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 2, textColor, 0); @@ -485,7 +485,7 @@ void EoBCoreEngine::gui_drawInventoryItem(int slot, int special, int pageNum) { uint8 col1 = guiSettings()->colors.frame1; uint8 col2 = guiSettings()->colors.frame2; - if (_configRenderMode == Common::kRenderCGA ) { + if (_configRenderMode == Common::kRenderCGA) { col1 = 1; col2 = 3; } @@ -777,11 +777,11 @@ int EoBCoreEngine::clickedCamp(Button *button) { } _screen->copyPage(0, 7); - _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, _useHiResDithering ? 1 : 12, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); _gui->runCampMenu(); - _screen->copyRegion(0, 0, 0, 120, 176, 24, _useHiResDithering ? 1 : 12, 2, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 0, 0, 120, 176, 24, 12, 2, Screen::CR_NO_P_CHECK); _screen->setScreenDim(cd); drawScene(0); @@ -808,13 +808,13 @@ int EoBCoreEngine::clickedSceneDropPickupItem(Button *button) { if (button->arg > 1) { block = calcNewBlockPosition(_currentBlock, _currentDirection); int f = _wllWallFlags[_levelBlockProperties[block].walls[_sceneDrawVarDown]]; - if (!(f & 0x0b)) + if (!(f & 0x0B)) return 1; } int d = _dropItemDirIndex[(_currentDirection << 2) + button->arg]; if (_itemInHand) { - setItemPosition((Item *)&_levelBlockProperties[block & 0x3ff].drawObjects, block, _itemInHand, d); + setItemPosition((Item *)&_levelBlockProperties[block & 0x3FF].drawObjects, block, _itemInHand, d); setHandItem(0); runLevelScript(block, 4); } else { @@ -856,7 +856,7 @@ int EoBCoreEngine::clickedWeaponSlot(Button *button) { static const uint8 sY[] = { 27, 27, 79, 79, 131, 131 }; int slot = sY[button->arg] > _mouseY ? 0 : 1; - if ((_gui->_flagsMouseLeft & 0x7f) == 1) + if ((_gui->_flagsMouseLeft & 0x7F) == 1) gui_processWeaponSlotClickLeft(button->arg, slot); else gui_processWeaponSlotClickRight(button->arg, slot); @@ -1031,9 +1031,9 @@ int EoBCoreEngine::clickedSpellbookList(Button *button) { } int EoBCoreEngine::clickedCastSpellOnCharacter(Button *button) { - _activeSpellCharId = button->arg & 0xff; + _activeSpellCharId = button->arg & 0xFF; - if (_activeSpellCharId == 0xff) { + if (_activeSpellCharId == 0xFF) { printWarning(_magicStrings3[_flags.gameID == GI_EOB1 ? 2 : 1]); if (_castScrollSlot) { gui_updateSlotAfterScrollUse(); @@ -1170,7 +1170,7 @@ int EoBCoreEngine::clickedSceneSpecial(Button *button) { int EoBCoreEngine::clickedSpellbookAbort(Button *button) { _updateFlags = 0; - _screen->copyRegion(0, 0, 64, 121, 112, 56, _useHiResDithering ? 4 : 10, 0, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 0, 64, 121, 112, 56, 10, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); gui_drawCompass(true); gui_toggleButtons(); @@ -1215,7 +1215,7 @@ void EoBCoreEngine::gui_processWeaponSlotClickLeft(int charIndex, int slotIndex) int ih = _itemInHand; int t = _items[ih].type; - uint16 v = (ih) ? _itemTypes[t].invFlags : 0xffff; + uint16 v = (ih) ? _itemTypes[t].invFlags : 0xFFFF; if (v & _slotValidationFlags[slotIndex]) { setHandItem(itm); @@ -1227,7 +1227,7 @@ void EoBCoreEngine::gui_processWeaponSlotClickLeft(int charIndex, int slotIndex) } void EoBCoreEngine::gui_processWeaponSlotClickRight(int charIndex, int slotIndex) { - if (!testCharacter(charIndex, 0x0d)) + if (!testCharacter(charIndex, 0x0D)) return; Item itm = _characters[charIndex].inventory[slotIndex]; @@ -1244,7 +1244,7 @@ void EoBCoreEngine::gui_processWeaponSlotClickRight(int charIndex, int slotIndex int8 tp = _items[itm].type; int8 vl = _items[itm].value; - uint8 ep = _itemTypes[tp].extraProperties & 0x7f; + uint8 ep = _itemTypes[tp].extraProperties & 0x7F; switch (ep) { case 0: @@ -1376,7 +1376,7 @@ GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) { _backupButtonList = 0; _progress = 0; _prcButtonUnk3 = 1; - _cflag = 0xffff; + _cflag = 0xFFFF; _menuLineSpacing = 0; _menuLastInFlags = 0; @@ -1385,8 +1385,8 @@ GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) { _numPages = (_vm->game() == GI_EOB2) ? 8 : 5; _numVisPages = (_vm->game() == GI_EOB2) ? 6 : 5; - _clericSpellAvltyFlags = (_vm->game() == GI_EOB2) ? 0xf7ffffff : 0x7bffff; - _paladinSpellAvltyFlags = (_vm->game() == GI_EOB2) ? 0xa9bbd1d : 0x800ff2; + _clericSpellAvltyFlags = (_vm->game() == GI_EOB2) ? 0xF7FFFFFF : 0x7BFFFF; + _paladinSpellAvltyFlags = (_vm->game() == GI_EOB2) ? 0xA9BBD1D : 0x800FF2; _numAssignedSpellsOfType = new int8[72]; memset(_numAssignedSpellsOfType, 0, 72); @@ -1524,7 +1524,7 @@ void GUI_EoB::processButton(Button *button) { int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 mouseWheel) { _progress = 0; - uint16 in = inputFlags & 0xff; + uint16 in = inputFlags & 0xFF; uint16 buttonReleaseFlag = 0; bool clickEvt = false; //_vm->_processingButtons = true; @@ -1543,13 +1543,13 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 //////////////////////////// if (!buttonList && !(inputFlags & 0x800)) - return inputFlags & 0xff; + return inputFlags & 0xFF; //////////////////////////// inputFlags = 0; clickEvt = true; } else if (inputFlags & 0x8000) { - inputFlags &= 0xff; + inputFlags &= 0xFF; } uint16 result = 0; @@ -1568,8 +1568,8 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 // UNUSED //if (buttonList->flags2 & 0x20) { - //if (_processButtonListExtraCallback) - // this->*_processButtonListExtraCallback(buttonList); + // if (_processButtonListExtraCallback) + // this->*_processButtonListExtraCallback(buttonList); //} if (buttonList->nextButton) @@ -1582,7 +1582,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 _specialProcessButton = 0; _prcButtonUnk3 = 1; - _cflag = 0xffff; + _cflag = 0xFFFF; } int sd = 0; @@ -1616,12 +1616,12 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 if (flgs2 & 1) flgs2 |= 8; else - flgs2 &= 0xfff7; + flgs2 &= 0xFFF7; if (flgs2 & 4) flgs2 |= 0x10; else - flgs2 &= 0xffef; + flgs2 &= 0xFFEF; uint16 vL = 0; uint16 vR = 0; @@ -1640,8 +1640,8 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 v6 = 1; } } else if (_flagsModifier || clickEvt) { - vL = flgs & 0xf00; - vR = flgs & 0xf000; + vL = flgs & 0xF00; + vR = flgs & 0xF000; if (_prcButtonUnk3) { if (sd != buttonList->dimTableIndex) { @@ -1675,7 +1675,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 flgs2 |= 4; vc = 1; } else { - flgs2 &= 0xfffb; + flgs2 &= 0xFFFB; } if (flgs & 0x100) { @@ -1702,7 +1702,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 flgs2 |= 4; vc = 1; } else { - flgs2 &= 0xfffb; + flgs2 &= 0xFFFB; } if (!(flgs & 0x200)) @@ -1730,12 +1730,12 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 } if ((flgs & 2) && (flgs2 & 1)) - flgs2 &= 0xfffe; + flgs2 &= 0xFFFE; break; case 3: if ((flgs & 4) || (!buttonList->data2Val1)) - flgs2 &= 0xfffb; + flgs2 &= 0xFFFB; else flgs2 |= 4; @@ -1745,7 +1745,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 } if ((flgs & 2) && (flgs2 & 1)) - flgs2 &= 0xfffe; + flgs2 &= 0xFFFE; break; default: @@ -1761,7 +1761,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 if ((flgs & 4) && buttonList->data2Val1) flgs2 |= 4; else - flgs2 &= 0xfffb; + flgs2 &= 0xFFFB; if (flgs & 0x1000) { v6 = 1; @@ -1786,7 +1786,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 if ((flgs & 4) && buttonList->data2Val1) flgs2 |= 4; else - flgs2 &= 0xfffb; + flgs2 &= 0xFFFB; if (!(flgs & 0x2000)) break; @@ -1812,12 +1812,12 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 } if ((flgs & 2) && (flgs2 & 1)) - flgs2 &= 0xfffe; + flgs2 &= 0xFFFE; break; case 3: if ((flgs & 4) || (!buttonList->data2Val1)) - flgs2 &= 0xfffb; + flgs2 &= 0xFFFB; else flgs2 |= 4; @@ -1827,7 +1827,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 } if ((flgs & 2) && (flgs2 & 1)) - flgs2 &= 0xfffe; + flgs2 &= 0xFFFE; break; default: @@ -1835,7 +1835,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 } } } else { // if (_vm->_mouseX >= x2 && _vm->_mouseX <= (x2 + buttonList->width)....) - flgs2 &= 0xfff9; + flgs2 &= 0xFFF9; if ((flgs & 0x40) && (!(flgs & 0x80)) && _specialProcessButton && !v8) { static const uint16 flagsTable[] = { 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 }; @@ -1859,7 +1859,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 } if ((flgs & 2) && (flgs2 & 1)) - flgs2 &= 0xfffe; + flgs2 &= 0xFFFE; } // end if (_vm->_mouseX >= x2 && _vm->_mouseX <= (x2 + buttonList->width)....) } // end if (_prcButtonUnk3) } // end if (_flagsModifier || clickEvt) @@ -1896,7 +1896,7 @@ int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 }; if ((_flagsMouseLeft == 1 || _flagsMouseRight == 1) && !v18) - _cflag = 0xffff; + _cflag = 0xFFFF; if (!result) result = inputFlags; @@ -1938,7 +1938,7 @@ int GUI_EoB::simpleMenu_process(int sd, const char *const *strings, void *b, int int x = (_screen->_curDim->sx + dm->sx) << 3; int y = _screen->_curDim->sy + dm->sy; - int inFlag = _vm->checkInput(0, false, 0) & 0x8ff; + int inFlag = _vm->checkInput(0, false, 0) & 0x8FF; _vm->removeInputTop(); Common::Point mousePos = _vm->getMousePos(); @@ -2051,7 +2051,7 @@ void GUI_EoB::runCampMenu() { newMenu = -1; } - int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80ff; + int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80FF; _vm->removeInputTop(); if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) @@ -2060,7 +2060,7 @@ void GUI_EoB::runCampMenu() { inputFlag = 0x8000 + prevHighlightButton->index; } - Button *clickedButton = _vm->gui_getButton(buttonList, inputFlag & 0x7fff); + Button *clickedButton = _vm->gui_getButton(buttonList, inputFlag & 0x7FFF); if (clickedButton) { drawMenuButton(prevHighlightButton, false, false, true); @@ -2140,8 +2140,8 @@ void GUI_EoB::runCampMenu() { displayTextBox(44); // fall through - case 0x800c: - case 0x800f: + case 0x800C: + case 0x800F: if (lastMenu == 1 || lastMenu == 2) newMenu = 0; else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) @@ -2163,7 +2163,7 @@ void GUI_EoB::runCampMenu() { newMenu = 1; break; - case 0x800a: + case 0x800A: for (; i < 6; i++) { if (_vm->testCharacter(i, 1)) cnt++; @@ -2172,7 +2172,7 @@ void GUI_EoB::runCampMenu() { if (cnt > 4) { _vm->dropCharacter(selectCharacterDialogue(53)); _vm->gui_drawPlayField(false); - _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, _vm->_useHiResDithering ? 1 : 12, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); _screen->setFont(Screen::FID_6_FNT); _vm->gui_drawAllCharPortraitsWithStats(); _screen->setFont(Screen::FID_8_FNT); @@ -2183,19 +2183,19 @@ void GUI_EoB::runCampMenu() { newMenu = 0; break; - case 0x800b: + case 0x800B: if (confirmDialogue(46)) _vm->quitGame(); newMenu = 0; break; - case 0x800d: + case 0x800D: _vm->_configSounds ^= true; _vm->_configMusic = _vm->_configSounds ? 1 : 0; newMenu = 2; break; - case 0x800e: + case 0x800E: _vm->_configHpBarGraphs ^= true; newMenu = 2; redrawPortraits = true; @@ -2290,7 +2290,7 @@ bool GUI_EoB::confirmDialogue2(int dim, int id, int deflt) { else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14)) newHighlight = 1; - int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF; _vm->removeInputTop(); if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) { @@ -2351,7 +2351,7 @@ void GUI_EoB::messageDialogue(int dim, int id, int buttonTextCol) { _screen->updateScreen(); for (bool runLoop = true; runLoop && !_vm->shouldQuit();) { - int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF; _vm->removeInputTop(); if (inputFlag == 199 || inputFlag == 201) { @@ -2392,7 +2392,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) { _screen->updateScreen(); for (bool runLoop = true; runLoop && !_vm->shouldQuit();) { - int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF; _vm->removeInputTop(); if (inputFlag == 199 || inputFlag == 201) { @@ -2607,7 +2607,7 @@ Common::String GUI_EoB::transferTargetMenu(Common::Array<Common::String> &target break; } while (_saveSlotIdTemp[slot] == -1); - _screen->copyRegion(72, 14, 72, 14, 176, 144, _vm->_useHiResDithering ? 7 : 12, 0, Screen::CR_NO_P_CHECK); + _screen->copyRegion(72, 14, 72, 14, 176, 144, 12, 0, Screen::CR_NO_P_CHECK); _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h); return (slot < 6) ? _savegameList[_savegameOffset + slot] : Common::String(); @@ -2650,7 +2650,7 @@ void GUI_EoB::createScreenThumbnail(Graphics::Surface &dst) { _screen->getRealPalette(0, screenPal); uint16 width = Screen::SCREEN_W; uint16 height = Screen::SCREEN_H; - if (_vm->_useHiResDithering) { + if (_vm->gameFlags().useHiRes) { width <<= 1; height <<= 1; } @@ -2705,11 +2705,20 @@ bool GUI_EoB::runSaveMenu(int x, int y) { for (int in = -1; in == -1 && !_vm->shouldQuit();) { _screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill); in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, 2, 0, 8); + if (in == -1) { + useSlot = false; + break; + } + if (!strlen(_saveSlotStringsTemp[slot])) { messageDialogue(11, 54, 6); in = -1; } - }; + } + + if (!useSlot) { + continue; + } _screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill); _screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, 15, 0); @@ -2755,7 +2764,7 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) { int slot = -1; for (bool runLoop = true; runLoop && !_vm->shouldQuit();) { - int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff; + int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF; _vm->removeInputTop(); if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) { @@ -2999,11 +3008,11 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) { lastHighLightText = newHighLightText; } - int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80ff; + int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80FF; _vm->removeInputTop(); if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) { - inputFlag = 0x801a + ((lastHighLightButton + 1) % _numVisPages); + inputFlag = 0x801A + ((lastHighLightButton + 1) % _numVisPages); } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT]) { inputFlag = lastHighLightButton ? 0x8019 + lastHighLightButton : 0x8019 + _numVisPages; } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) { @@ -3018,7 +3027,7 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) { } if (inputFlag & 0x8000) { - b = _vm->gui_getButton(buttonList, inputFlag & 0x7fff); + b = _vm->gui_getButton(buttonList, inputFlag & 0x7FFF); drawMenuButton(b, true, true, true); _screen->updateScreen(); _vm->_system->delayMillis(80); @@ -3065,9 +3074,9 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) { runLoop = false; } else if (inputFlag & 0x8000) { - newHighLightButton = inputFlag - 0x801a; + newHighLightButton = inputFlag - 0x801A; if (newHighLightButton == lastHighLightButton) - drawMenuButton(_vm->gui_getButton(buttonList, inputFlag & 0x7fff), false, true, true); + drawMenuButton(_vm->gui_getButton(buttonList, inputFlag & 0x7FFF), false, true, true); } } @@ -3544,7 +3553,7 @@ bool GUI_EoB::confirmDialogue(int id) { lastHighlight = newHighlight; } - int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80ff; + int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80FF; _vm->removeInputTop(); if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) { diff --git a/engines/kyra/gui_eob.h b/engines/kyra/gui_eob.h index f6be18ffbb..1b7bdf3482 100644 --- a/engines/kyra/gui_eob.h +++ b/engines/kyra/gui_eob.h @@ -156,7 +156,7 @@ private: static const uint8 _highlightColorTableEGA[]; }; -} // End of namespace Kyra +} // End of namespace Kyra #endif // ENABLE_EOB diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 36fbb0b40a..3a2c07beff 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -521,7 +521,7 @@ void KyraEngine_HoF::bookPrintText(int dstPage, const uint8 *str, int x, int y, Screen::FontId oldFont = _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_BOOKFONT_FNT); _screen->_charWidth = -2; - _screen->printText((const char *)str, x, y, color, (_flags.lang == Common::JA_JPN) ? 0xf6 : 0); + _screen->printText((const char *)str, x, y, color, (_flags.lang == Common::JA_JPN) ? 0xF6 : 0); _screen->_charWidth = 0; _screen->setFont(oldFont); diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index a79da0681e..f7a5386574 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -120,7 +120,7 @@ void LoLEngine::gui_drawScroll() { if (h) { _screen->copyRegion(201, 1, 17, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK); _screen->copyRegion(208, 1, 89, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK); - _screen->fillRect(21, 15, 89, h + 15, _flags.use16ColorMode ? 0xbb : 206); + _screen->fillRect(21, 15, 89, h + 15, _flags.use16ColorMode ? 0xBB : 206); } _screen->copyRegion(112, 16, 12, h + 15, 87, 14, 2, 2, Screen::CR_NO_P_CHECK); @@ -172,7 +172,7 @@ void LoLEngine::gui_displayCharInventory(int charNum) { gui_drawAllCharPortraitsWithStats(); if (_flags.use16ColorMode) - _screen->fprintString("%s", 156, 8, 0xe1, 0, 1, l->name); + _screen->fprintString("%s", 156, 8, 0xE1, 0, 1, l->name); else _screen->fprintString("%s", 157, 9, 254, 0, 5, l->name); @@ -182,7 +182,7 @@ void LoLEngine::gui_displayCharInventory(int charNum) { gui_drawCharInventoryItem(i); Screen::FontId of = _screen->setFont(Screen::FID_9_FNT); - _screen->fprintString("%s", 182, 103, _flags.use16ColorMode ? 0xbb : 172, 0, 5, getLangString(0x4033)); + _screen->fprintString("%s", 182, 103, _flags.use16ColorMode ? 0xBB : 172, 0, 5, getLangString(0x4033)); _screen->setFont(of); static const uint16 statusFlags[] = { 0x0080, 0x0000, 0x1000, 0x0002, 0x100, 0x0001, 0x0000, 0x0000 }; @@ -206,7 +206,7 @@ void LoLEngine::gui_displayCharInventory(int charNum) { int32 b = l->experiencePts[i] - _expRequirements[l->skillLevels[i] - 1]; int32 e = _expRequirements[l->skillLevels[i]] - _expRequirements[l->skillLevels[i] - 1]; - while (e & 0xffff8000) { + while (e & 0xFFFF8000) { e >>= 1; c = b; b >>= 1; @@ -245,7 +245,7 @@ void LoLEngine::gui_printCharacterStats(int index, int redraw, int value) { // protection if (_flags.use16ColorMode) { y = (index + 2) << 3; - col = 0xa1; + col = 0xA1; if (redraw) _screen->fprintString("%s", offs + 108, y, col, 0, 0, getLangString(0x4014 + index)); } else { @@ -260,7 +260,7 @@ void LoLEngine::gui_printCharacterStats(int index, int redraw, int value) { y = s * 10 + 62; if (_flags.use16ColorMode) { y = (s + 8) << 3; - col = _characters[_selectedCharacter].flags & (0x200 << s) ? 0xe1 : 0x81; + col = _characters[_selectedCharacter].flags & (0x200 << s) ? 0xE1 : 0x81; if (redraw) _screen->fprintString("%s", offs + 108, y, col, 0, 0, getLangString(0x4014 + index)); } else { @@ -274,7 +274,7 @@ void LoLEngine::gui_printCharacterStats(int index, int redraw, int value) { if (offs) _screen->copyRegion(294, y, 182 + offs, y, 18, 8, 6, _screen->_curPage, Screen::CR_NO_P_CHECK); - Screen::FontId of = _flags.use16ColorMode ? _screen->setFont(Screen::FID_SJIS_FNT) : _screen->_currentFont; + Screen::FontId of = (_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? _screen->setFont(Screen::FID_SJIS_FNT) : _screen->_currentFont; _screen->fprintString("%d", 200 + offs, y, col, 0, _flags.use16ColorMode ? 2 : 6, value); _screen->setFont(of); } @@ -322,12 +322,12 @@ void LoLEngine::gui_changeCharacterStats(int charNum) { void LoLEngine::gui_drawCharInventoryItem(int itemIndex) { static const uint8 slotShapes[] = { 0x30, 0x34, 0x30, 0x34, 0x2E, 0x2F, 0x32, 0x33, 0x31, 0x35, 0x35 }; - + //2Eh, 32h, 2Eh, 32h, 2Ch, 2Dh, 30h, 31h, 2Fh, 33h, 33h const uint8 *coords = &_charInvDefs[_charInvIndex[_characters[_selectedCharacter].raceClassSex] * 22 + itemIndex * 2]; uint8 x = *coords++; uint8 y = *coords; - if (y == 0xff) + if (y == 0xFF) return; if (!_screen->_curPage) @@ -366,7 +366,7 @@ void LoLEngine::gui_drawCharPortraitWithStats(int charNum) { gui_drawCharFaceShape(charNum, 0, 1, _screen->_curPage); if (_flags.use16ColorMode) { - gui_drawLiveMagicBar(33, 32, _characters[charNum].magicPointsCur, 0, _characters[charNum].magicPointsMax, 5, 32, 0xaa, 0x44, 0); + gui_drawLiveMagicBar(33, 32, _characters[charNum].magicPointsCur, 0, _characters[charNum].magicPointsMax, 5, 32, 0xAA, 0x44, 0); gui_drawLiveMagicBar(39, 32, _characters[charNum].hitPointsCur, 0, _characters[charNum].hitPointsMax, 5, 32, 0x66, 0x44, 1); _screen->printText(getLangString(0x4253), 33, 1, 0x99, 0); _screen->printText(getLangString(0x4254), 39, 1, 0x55, 0); @@ -493,7 +493,7 @@ void LoLEngine::gui_drawLiveMagicBar(int x, int y, int curPoints, int unk, int m if (flag) { t = maxPoints >> 1; if (t > curPoints) - col1 = _flags.use16ColorMode ? 0xbb : 144; + col1 = _flags.use16ColorMode ? 0xBB : 144; t = maxPoints >> 2; if (t > curPoints) col1 = _flags.use16ColorMode ? 0x88 : 132; @@ -525,9 +525,9 @@ void LoLEngine::calcCharPortraitXpos() { } void LoLEngine::gui_drawMoneyBox(int pageNum) { - static const uint16 moneyX256[] = { 0x128, 0x134, 0x12b, 0x131, 0x12e}; + static const uint16 moneyX256[] = { 0x128, 0x134, 0x12B, 0x131, 0x12E}; static const uint16 moneyY256[] = { 0x73, 0x73, 0x74, 0x74, 0x75}; - static const uint16 moneyX16[] = { 0x127, 0x133, 0x12a, 0x130, 0x12d}; + static const uint16 moneyX16[] = { 0x127, 0x133, 0x12A, 0x130, 0x12D}; static const uint16 moneyY16[] = { 0x74, 0x74, 0x75, 0x75, 0x76}; int backupPage = _screen->_curPage; @@ -551,11 +551,11 @@ void LoLEngine::gui_drawMoneyBox(int pageNum) { continue; uint8 h = _moneyColumnHeight[i] - 1; - _screen->drawClippedLine(moneyX[i], moneyY[i], moneyX[i], moneyY[i] - h, _flags.use16ColorMode ? 1 : 0xd2); - _screen->drawClippedLine(moneyX[i] + 1, moneyY[i], moneyX[i] + 1, moneyY[i] - h, _flags.use16ColorMode ? 2 : 0xd1); - _screen->drawClippedLine(moneyX[i] + 2, moneyY[i], moneyX[i] + 2, moneyY[i] - h, _flags.use16ColorMode ? 3 : 0xd0); - _screen->drawClippedLine(moneyX[i] + 3, moneyY[i], moneyX[i] + 3, moneyY[i] - h, _flags.use16ColorMode ? 2 : 0xd1); - _screen->drawClippedLine(moneyX[i] + 4, moneyY[i], moneyX[i] + 4, moneyY[i] - h, _flags.use16ColorMode ? 1 : 0xd2); + _screen->drawClippedLine(moneyX[i], moneyY[i], moneyX[i], moneyY[i] - h, _flags.use16ColorMode ? 1 : 0xD2); + _screen->drawClippedLine(moneyX[i] + 1, moneyY[i], moneyX[i] + 1, moneyY[i] - h, _flags.use16ColorMode ? 2 : 0xD1); + _screen->drawClippedLine(moneyX[i] + 2, moneyY[i], moneyX[i] + 2, moneyY[i] - h, _flags.use16ColorMode ? 3 : 0xD0); + _screen->drawClippedLine(moneyX[i] + 3, moneyY[i], moneyX[i] + 3, moneyY[i] - h, _flags.use16ColorMode ? 2 : 0xD1); + _screen->drawClippedLine(moneyX[i] + 4, moneyY[i], moneyX[i] + 4, moneyY[i] - h, _flags.use16ColorMode ? 1 : 0xD2); } Screen::FontId backupFont = _screen->setFont(Screen::FID_6_FNT); @@ -584,7 +584,7 @@ void LoLEngine::gui_drawCompass() { _compassDirection = _currentDirection << 6; } - int t = ((_compassDirection + 4) >> 3) & 0x1f; + int t = ((_compassDirection + 4) >> 3) & 0x1F; if (t == _compassDirectionIndex) return; @@ -744,13 +744,13 @@ void LoLEngine::gui_toggleFightButtons(bool disable) { if (disable) _characters[i].flags |= 0x2000; else - _characters[i].flags &= 0xdfff; + _characters[i].flags &= 0xDFFF; if (disable && !textEnabled()) { int u = _selectedCharacter; _selectedCharacter = 99; int f = _updateFlags; - _updateFlags &= 0xfffd; + _updateFlags &= 0xFFFD; gui_drawCharPortraitWithStats(i); @@ -774,7 +774,7 @@ void LoLEngine::gui_updateInput() { if (inputFlag && _activeMagicMenu != -1 && !(inputFlag & 0x8800)) { gui_enableDefaultPlayfieldButtons(); - _characters[_activeMagicMenu].flags &= 0xffef; + _characters[_activeMagicMenu].flags &= 0xFFEF; gui_drawCharPortraitWithStats(_activeMagicMenu); gui_triggerEvent(inputFlag); _preserveEvents = false; @@ -875,7 +875,7 @@ void LoLEngine::gui_initCharInventorySpecialButtons(int charNum) { const uint8 *s = &_charInvDefs[_charInvIndex[_characters[charNum].raceClassSex] * 22]; for (int i = 0; i < 11; i++) { - if (*s != 0xff) + if (*s != 0xFF) gui_initButton(33 + i, s[0], s[1], i); s += 2; } @@ -916,7 +916,7 @@ void LoLEngine::gui_initButton(int index, int x, int y, int val) { *b = Button(); b->nextButton = 0; - b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xfe; + b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xFE; b->data0Val3 = b->data1Val3 = b->data2Val3 = 0x01; b->index = cnt; @@ -925,7 +925,7 @@ void LoLEngine::gui_initButton(int index, int x, int y, int val) { b->dimTableIndex = _buttonData[index].screenDim; b->flags = _buttonData[index].buttonflags; - b->arg = (val != -1) ? (uint8)(val & 0xff) : _buttonData[index].index; + b->arg = (val != -1) ? (uint8)(val & 0xFF) : _buttonData[index].index; if (index == 15) { // magic sub menu @@ -1100,17 +1100,17 @@ int LoLEngine::clickedMagicSubmenu(Button *button) { gui_enableDefaultPlayfieldButtons(); if (checkMagic(c, _availableSpells[_selectedSpell], spellLevel)) { - _characters[c].flags &= 0xffef; + _characters[c].flags &= 0xFFEF; gui_drawCharPortraitWithStats(c); } else { _characters[c].flags |= 4; - _characters[c].flags &= 0xffef; + _characters[c].flags &= 0xFFEF; if (castSpell(c, _availableSpells[_selectedSpell], spellLevel)) { setCharacterUpdateEvent(c, 1, 8, 1); increaseExperience(c, 2, spellLevel * spellLevel); } else { - _characters[c].flags &= 0xfffb; + _characters[c].flags &= 0xFFFB; gui_drawCharPortraitWithStats(c); } } @@ -1120,7 +1120,7 @@ int LoLEngine::clickedMagicSubmenu(Button *button) { } int LoLEngine::clickedScreen(Button *button) { - _characters[_activeMagicMenu].flags &= 0xffef; + _characters[_activeMagicMenu].flags &= 0xFFEF; gui_drawCharPortraitWithStats(_activeMagicMenu); _activeMagicMenu = -1; @@ -1178,12 +1178,12 @@ int LoLEngine::clickedPortraitEtcRight(Button *button) { runItemScript(c, _itemInHand, 0x400, 0, 0); runLevelScriptCustom(_currentBlock, 0x400, c, _itemInHand, 0, 0); } else { - _txt->printMessage(2, getLangString(0x402c), _characters[c].name); + _txt->printMessage(2, getLangString(0x402C), _characters[c].name); } return 1; } - _txt->printMessage(2, "%s", getLangString((flg & 8) ? 0x4029 : ((flg & 0x10) ? 0x402a : 0x402b))); + _txt->printMessage(2, "%s", getLangString((flg & 8) ? 0x4029 : ((flg & 0x10) ? 0x402A : 0x402B))); return 1; } @@ -1235,13 +1235,13 @@ int LoLEngine::clickedCharInventorySlot(Button *button) { } int LoLEngine::clickedExitCharInventory(Button *button) { - _updateFlags &= 0xfff3; + _updateFlags &= 0xFFF3; gui_enableDefaultPlayfieldButtons(); _weaponsDisabled = false; for (int i = 0; i < 4; i++) { if (_charInventoryUnk & (1 << i)) - _characters[i].flags &= 0xf1ff; + _characters[i].flags &= 0xF1FF; } _screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer1); @@ -1315,7 +1315,7 @@ int LoLEngine::clickedScenePickupItem(Button *button) { uint16 block = (p <= 128) ? calcNewBlockPosition(_currentBlock, _currentDirection) : _currentBlock; - int found = checkSceneForItems(&_levelBlockProperties[block].drawObjects, p & 0x7f); + int found = checkSceneForItems(&_levelBlockProperties[block].drawObjects, p & 0x7F); if (found != -1) { removeLevelItem(found, block); @@ -1465,7 +1465,7 @@ int LoLEngine::clickedSpellTargetCharacter(Button *button) { int t = button->arg; _txt->printMessage(0, "%s.\r", _characters[t].name); - if ((_spellProperties[_activeSpell.spell].flags & 0xff) == 1) { + if ((_spellProperties[_activeSpell.spell].flags & 0xFF) == 1) { _activeSpell.target = t; castHealOnSingleCharacter(&_activeSpell); } @@ -1504,7 +1504,7 @@ int LoLEngine::clickedSceneThrowItem(Button *button) { uint16 y = 0; calcCoordinates(x, y, _currentBlock, 0x80, 0x80); - if (launchObject(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) { + if (launchObject(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3F)) { snd_playSoundEffect(18, -1); setHandItem(0); } @@ -1520,7 +1520,7 @@ int LoLEngine::clickedOptions(Button *button) { _updateFlags |= 4; Button b; - b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xFE; b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; if (_weaponsDisabled) @@ -1540,7 +1540,7 @@ int LoLEngine::clickedOptions(Button *button) { _gui->runMenu(_gui->_mainMenu); - _updateFlags &= 0xfffb; + _updateFlags &= 0xFFFB; setMouseCursorToItemInHand(); resetLampStatus(); gui_enableDefaultPlayfieldButtons(); @@ -1564,7 +1564,7 @@ int LoLEngine::clickedRestParty(Button *button) { gui_toggleButtonDisplayMode(_flags.isTalkie ? 77 : 75, 1); Button b; - b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xFE; b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; if (_weaponsDisabled) @@ -1710,7 +1710,7 @@ int LoLEngine::clickedRestParty(Button *button) { bool setframe = true; if (_characters[i].flags & 0x1000) { - _characters[i].flags &= 0xefff; + _characters[i].flags &= 0xEFFF; if (_partyAwake) { if (_characters[i].damageSuffered) { @@ -1733,7 +1733,7 @@ int LoLEngine::clickedRestParty(Button *button) { setTemporaryFaceFrame(i, frm, upd, 1); } - _updateFlags &= 0xfffe; + _updateFlags &= 0xFFFE; _partyAwake = true; updateDrawPage2(); gui_drawScene(0); @@ -1742,7 +1742,7 @@ int LoLEngine::clickedRestParty(Button *button) { } else { for (int i = 0; i < 4; i++) - _characters[i].flags &= 0xefff; + _characters[i].flags &= 0xEFFF; if (needPoisoningFlags) { setTemporaryFaceFrameForAllCharacters(0, 0, 0); @@ -1750,7 +1750,7 @@ int LoLEngine::clickedRestParty(Button *button) { if (needPoisoningFlags & (1 << i)) setTemporaryFaceFrame(i, 3, 8, 0); } - _txt->printMessage(0x8000, "%s", getLangString(0x405a)); + _txt->printMessage(0x8000, "%s", getLangString(0x405A)); gui_drawAllCharPortraitsWithStats(); } else { @@ -1773,10 +1773,10 @@ int LoLEngine::clickedCompass(Button *button) { return 0; if (_compassBroken) { - if (characterSays(0x425b, -1, true)) - _txt->printMessage(4, "%s", getLangString(0x425b)); + if (characterSays(0x425B, -1, true)) + _txt->printMessage(4, "%s", getLangString(0x425B)); } else { - _txt->printMessage(0, "%s", getLangString(0x402f + _currentDirection)); + _txt->printMessage(0, "%s", getLangString(0x402F + _currentDirection)); } return 1; @@ -1813,8 +1813,8 @@ int LoLEngine::clickedLamp(Button *button) { _lampOilStatus += 100; } else { - uint16 s = (_lampOilStatus >= 100) ? 0x4060 : ((!_lampOilStatus) ? 0x405c : (_lampOilStatus / 33) + 0x405d); - _txt->printMessage(0, getLangString(0x405b), getLangString(s)); + uint16 s = (_lampOilStatus >= 100) ? 0x4060 : ((!_lampOilStatus) ? 0x405C : (_lampOilStatus / 33) + 0x405D); + _txt->printMessage(0, getLangString(0x405B), getLangString(s)); } if (_brightness) @@ -1836,7 +1836,7 @@ int LoLEngine::clickedStatusIcon(Button *button) { if (str == 0 || str > 3) return 1; - _txt->printMessage(0x8002, "%s", getLangString(str == 1 ? 0x424c : (str == 2 ? 0x424e : 0x424d))); + _txt->printMessage(0x8002, "%s", getLangString(str == 1 ? 0x424C : (str == 2 ? 0x424E : 0x424D))); return 1; } @@ -2239,7 +2239,7 @@ int GUI_LoL::runMenu(Menu &menu) { if (_currentMenu == &_gameOptions) { char *s = (char *)_vm->_tempBuffer5120; - Common::strlcpy(s, _vm->getLangString(0x406f + _vm->_monsterDifficulty), 30); + Common::strlcpy(s, _vm->getLangString(0x406F + _vm->_monsterDifficulty), 30); _currentMenu->item[_vm->gameFlags().isTalkie ? 0 : 2].itemString = s; s += (strlen(s) + 1); @@ -2252,7 +2252,7 @@ int GUI_LoL::runMenu(Menu &menu) { s += (strlen(s) + 1); if (_vm->gameFlags().isTalkie) { - Common::strlcpy(s, _vm->getLangString(0x42d6 + _vm->_lang), 30); + Common::strlcpy(s, _vm->getLangString(0x42D6 + _vm->_lang), 30); _currentMenu->item[3].itemString = s; s += (strlen(s) + 1); @@ -2315,7 +2315,7 @@ int GUI_LoL::runMenu(Menu &menu) { for (int ii = 0; ii < 3; ++ii) { Button *b = getButtonListData() + 1 + (i - 1) * 3 + ii; b->nextButton = 0; - b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xfe; + b->data0Val2 = b->data1Val2 = b->data2Val2 = 0xFE; b->data0Val3 = b->data1Val3 = b->data2Val3 = 0x01; b->index = ii; @@ -2367,9 +2367,9 @@ int GUI_LoL::runMenu(Menu &menu) { int mw = (d->w << 3) + 1; int mh = d->h + 1; if (_vm->gameFlags().use16ColorMode) { - _screen->drawShadedBox(mx, my, mx + mw + 1, my + mh + 1, 0xdd, 0xff); - _screen->drawLine(true, mx + mw + 1, my, mh + 1, 0xcc); - _screen->drawLine(false, mx, my + mh + 1, mw + 2, 0xcc); + _screen->drawShadedBox(mx, my, mx + mw + 1, my + mh + 1, 0xDD, 0xFF); + _screen->drawLine(true, mx + mw + 1, my, mh + 1, 0xCC); + _screen->drawLine(false, mx, my + mh + 1, mw + 2, 0xCC); } else { _screen->drawShadedBox(mx, my, mx + mw, my + mh, 227, 223); } @@ -2622,7 +2622,7 @@ int GUI_LoL::clickedMainMenu(Button *button) { _newMenu = &_audioOptions; break; case 0x4006: - _choiceMenu.menuNameId = 0x400a; + _choiceMenu.menuNameId = 0x400A; _newMenu = &_choiceMenu; break; case 0x4005: @@ -2677,7 +2677,7 @@ int GUI_LoL::clickedDeleteMenu(Button *button) { return 1; } - _choiceMenu.menuNameId = 0x400b; + _choiceMenu.menuNameId = 0x400B; _newMenu = &_choiceMenu; int16 s = (int16)button->arg; _menuResult = _deleteMenu.item[-s - 2].saveSlot + 1; @@ -2689,7 +2689,7 @@ int GUI_LoL::clickedOptionsMenu(Button *button) { updateMenuButton(button); switch (button->arg) { - case 0xfff9: + case 0xFFF9: _vm->_configMusic ^= 1; _vm->sound()->enableMusic(_vm->_configMusic); @@ -2698,23 +2698,23 @@ int GUI_LoL::clickedOptionsMenu(Button *button) { else _vm->_sound->beginFadeOut(); break; - case 0xfff8: + case 0xFFF8: _vm->_configSounds ^= true; _vm->sound()->enableSFX(_vm->_configSounds); break; - case 0xfff7: + case 0xFFF7: _vm->_monsterDifficulty = (_vm->_monsterDifficulty + 1) % 3; break; - case 0xfff6: + case 0xFFF6: _vm->_smoothScrollingEnabled ^= true; break; - case 0xfff5: + case 0xFFF5: _vm->_floatingCursorsEnabled ^= true; break; - case 0xfff4: + case 0xFFF4: _vm->_lang = (_vm->_lang + 1) % 3; break; - case 0xfff3: + case 0xFFF3: _vm->_configVoice ^= 3; break; case 0x4072: { @@ -2793,7 +2793,7 @@ int GUI_LoL::clickedAudioMenu(Button *button) { } while (1); } else if (button->arg == 5) { _vm->_lastSpeechId = -1; - _vm->snd_playCharacterSpeech(0x42e0, 0, 0); + _vm->snd_playCharacterSpeech(0x42E0, 0, 0); } } diff --git a/engines/kyra/gui_lol.h b/engines/kyra/gui_lol.h index dbf54e41f0..79d4b6b4c9 100644 --- a/engines/kyra/gui_lol.h +++ b/engines/kyra/gui_lol.h @@ -36,9 +36,9 @@ namespace Kyra { menu.width = (dim->w << 3); \ menu.height = (dim->h); \ if (_vm->gameFlags().use16ColorMode) { \ - menu.bkgdColor = 0xcc; \ - menu.color1 = 0xff; \ - menu.color2 = 0xdd; \ + menu.bkgdColor = 0xCC; \ + menu.color1 = 0xFF; \ + menu.color2 = 0xDD; \ } else { \ menu.bkgdColor = 225; \ menu.color1 = 223; \ @@ -49,7 +49,7 @@ namespace Kyra { menu.numberOfItems = d; \ menu.titleX = (dim->sx << 3) + (dim->w << 2); \ menu.titleY = 6; \ - menu.textColor = _vm->gameFlags().use16ColorMode ? 0xe1 : 254; \ + menu.textColor = _vm->gameFlags().use16ColorMode ? 0xE1 : 254; \ menu.scrollUpButtonX = e; \ menu.scrollUpButtonY = f; \ menu.scrollDownButtonX = g; \ @@ -65,13 +65,13 @@ namespace Kyra { item.y = c; \ item.width = d; \ item.height = e; \ - item.textColor = _vm->gameFlags().use16ColorMode ? 0xc1 : 204; \ - item.highlightColor = _vm->gameFlags().use16ColorMode ? 0xe1 : 254; \ + item.textColor = _vm->gameFlags().use16ColorMode ? 0xC1 : 204; \ + item.highlightColor = _vm->gameFlags().use16ColorMode ? 0xE1 : 254; \ item.titleX = -1; \ if (_vm->gameFlags().use16ColorMode) { \ - item.bkgdColor = 0xcc; \ - item.color1 = 0xff; \ - item.color2 = 0xdd; \ + item.bkgdColor = 0xCC; \ + item.color1 = 0xFF; \ + item.color2 = 0xDD; \ } else { \ item.bkgdColor = 225; \ item.color1 = 223; \ diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 37526f9a5f..bcbfe27b69 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -25,7 +25,7 @@ #include "kyra/text_mr.h" #include "kyra/resource.h" #include "kyra/timer.h" -#include "kyra/sound.h" +#include "kyra/sound_digital.h" #include "common/system.h" diff --git a/engines/kyra/gui_rpg.cpp b/engines/kyra/gui_rpg.cpp index be40050bb1..ab25f95df8 100644 --- a/engines/kyra/gui_rpg.cpp +++ b/engines/kyra/gui_rpg.cpp @@ -76,8 +76,8 @@ void KyraRpgEngine::gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 screen()->fillRect(x + t, y, x + w - 1, y + h, col2); } -void KyraRpgEngine::gui_initButtonsFromList(const int16 *list) { - while (*list != -1) +void KyraRpgEngine::gui_initButtonsFromList(const uint8 *list) { + while (*list != 0xFF) gui_initButton(*list++); } @@ -107,7 +107,7 @@ bool KyraRpgEngine::clickedShape(int shapeIndex) { uint16 s = _levelDecorationProperties[shapeIndex].shapeIndex[1]; - if (s == 0xffff) + if (s == 0xFFFF) continue; int w = _flags.gameID == GI_LOL ? _levelDecorationShapes[s][3] : (_levelDecorationShapes[s][2] << 3); diff --git a/engines/kyra/items_eob.cpp b/engines/kyra/items_eob.cpp index 0994e12e4f..6c7ccf14dc 100644 --- a/engines/kyra/items_eob.cpp +++ b/engines/kyra/items_eob.cpp @@ -118,7 +118,7 @@ void EoBCoreEngine::setItemPosition(Item *itemQueue, int block, Item item, int p EoBItem *itm = &_items[item]; itm->pos = pos; itm->block = block; - itm->level = block < 0 ? 0xff : _currentLevel; + itm->level = block < 0 ? 0xFF : _currentLevel; if (!*itemQueue) { *itemQueue = itm->next = itm->prev = item; @@ -141,7 +141,7 @@ void EoBCoreEngine::createInventoryItem(EoBCharacter *c, Item itemIndex, int16 i if (itemValue != -1) _items[itemIndex].value = itemValue; - if (itemValue && ((_itemTypes[_items[itemIndex].type].extraProperties & 0x7f) < 4)) + if (itemValue && ((_itemTypes[_items[itemIndex].type].extraProperties & 0x7F) < 4)) _items[itemIndex].flags |= 0x80; if (c->inventory[preferedInventorySlot]) { @@ -208,7 +208,7 @@ int EoBCoreEngine::validateInventorySlotForItem(Item item, int charIndex, int sl } int itm = _characters[charIndex].inventory[slot]; - int ex = _itemTypes[_items[itm].type].extraProperties & 0x7f; + int ex = _itemTypes[_items[itm].type].extraProperties & 0x7F; if (_items[itm].flags & 0x20 && (_flags.gameID == GI_EOB1 || slot < 2)) { if (_flags.gameID == GI_EOB2 && ex > 0 && ex < 4) @@ -216,7 +216,7 @@ int EoBCoreEngine::validateInventorySlotForItem(Item item, int charIndex, int sl return 0; } - uint16 v = item ? _itemTypes[_items[item].type].invFlags : 0xffff; + uint16 v = item ? _itemTypes[_items[item].type].invFlags : 0xFFFF; if (v & _slotValidationFlags[slot]) return 1; @@ -359,7 +359,7 @@ void EoBCoreEngine::printFullItemName(Item item) { EoBItem *itm = &_items[item]; const char *nameUnid = _itemNames[itm->nameUnid]; const char *nameId = _itemNames[itm->nameId]; - uint8 f = _itemTypes[itm->type].extraProperties & 0x7f; + uint8 f = _itemTypes[itm->type].extraProperties & 0x7F; int8 v = itm->value; const char *tstr2 = 0; diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp index ef2c50c0c5..e1d3c659de 100644 --- a/engines/kyra/items_hof.cpp +++ b/engines/kyra/items_hof.cpp @@ -84,7 +84,7 @@ bool KyraEngine_HoF::dropItem(int unk1, Item item, int x, int y, int unk2) { bool success = processItemDrop(_mainCharacter.sceneId, item, x, y, unk1, unk2); if (!success) { - snd_playSoundEffect(0x0d); + snd_playSoundEffect(0x0D); if (countAllItems() >= 30) showMessageFromCCode(5, 0x84, 0); } @@ -205,7 +205,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in if (startX == dstX && startY == dstY) { if (_layerFlagTable[_screen->getLayer(dstX, dstY)] && item != 13) { updateCharFacing(); - snd_playSoundEffect(0x2d); + snd_playSoundEffect(0x2D); removeHandItem(); objectChat(getTableString(0xFF, _cCodeBuffer, 1), 0, 0x83, 0xFF); } else { @@ -213,7 +213,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in _itemList[itemSlot].y = dstY; _itemList[itemSlot].id = item; _itemList[itemSlot].sceneId = _mainCharacter.sceneId; - snd_playSoundEffect(0x0c); + snd_playSoundEffect(0x0C); addItemToAnimList(itemSlot); } } else { @@ -283,7 +283,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in if (_layerFlagTable[_screen->getLayer(dstX, dstY)] && item != 13) { updateCharFacing(); - snd_playSoundEffect(0x2d); + snd_playSoundEffect(0x2D); removeHandItem(); _screen->showMouse(); objectChat(getTableString(0xFF, _cCodeBuffer, 1), 0, 0x83, 0xFF); @@ -292,7 +292,7 @@ void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, in _itemList[itemSlot].y = dstY; _itemList[itemSlot].id = item; _itemList[itemSlot].sceneId = _mainCharacter.sceneId; - snd_playSoundEffect(0x0c); + snd_playSoundEffect(0x0C); addItemToAnimList(itemSlot); _screen->showMouse(); } @@ -307,7 +307,7 @@ void KyraEngine_HoF::exchangeMouseItem(int itemPos) { _itemInHand = itemId; addItemToAnimList(itemPos); - snd_playSoundEffect(0x0b); + snd_playSoundEffect(0x0B); setMouseCursor(_itemInHand); int str2 = 7; @@ -331,7 +331,7 @@ bool KyraEngine_HoF::pickUpItem(int x, int y) { deleteItemAnimEntry(itemPos); int itemId = _itemList[itemPos].id; _itemList[itemPos].id = kItemNone; - snd_playSoundEffect(0x0b); + snd_playSoundEffect(0x0B); setMouseCursor(itemId); int str2 = 7; diff --git a/engines/kyra/items_lok.cpp b/engines/kyra/items_lok.cpp index b92cd616c1..8ee07e8271 100644 --- a/engines/kyra/items_lok.cpp +++ b/engines/kyra/items_lok.cpp @@ -29,9 +29,9 @@ namespace Kyra { int KyraEngine_LoK::findDuplicateItemShape(int shape) { static const uint8 dupTable[] = { - 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47, - 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a, - 0x5d, 0x5a, 0x5e, 0x5a, 0xFF, 0xFF + 0x48, 0x46, 0x49, 0x47, 0x4A, 0x46, 0x4B, 0x47, + 0x4C, 0x46, 0x4D, 0x47, 0x5B, 0x5A, 0x5C, 0x5A, + 0x5D, 0x5A, 0x5E, 0x5A, 0xFF, 0xFF }; int i = 0; diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index 409b53f6f0..f7fd04bab8 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -29,7 +29,7 @@ namespace Kyra { LoLObject *LoLEngine::findObject(uint16 index) { if (index & 0x8000) - return &_monsters[index & 0x7fff]; + return &_monsters[index & 0x7FFF]; else return &_itemsInPlay[index]; } @@ -221,7 +221,7 @@ Item LoLEngine::makeItem(int itemType, int curFrame, int flags) { memset(&_itemsInPlay[slot], 0, sizeof(LoLItem)); _itemsInPlay[slot].itemPropertyIndex = itemType; - _itemsInPlay[slot].shpCurFrame_flg = (curFrame & 0x1fff) | flags; + _itemsInPlay[slot].shpCurFrame_flg = (curFrame & 0x1FFF) | flags; _itemsInPlay[slot].level = -1; return slot; @@ -292,7 +292,7 @@ void LoLEngine::runItemScript(int charNum, Item item, int flags, int next, int r memset(&scriptState, 0, sizeof(EMCState)); uint8 func = item ? _itemProperties[_itemsInPlay[item].itemPropertyIndex].itemScriptFunc : 3; - if (func == 0xff) + if (func == 0xFF) return; _emc->init(&scriptState, &_itemScript); @@ -351,8 +351,8 @@ bool LoLEngine::itemEquipped(int charNum, uint16 itemType) { void LoLEngine::setItemPosition(Item item, uint16 x, uint16 y, int flyingHeight, int moveable) { if (!flyingHeight) { - x = (x & 0xffc0) | 0x40; - y = (y & 0xffc0) | 0x40; + x = (x & 0xFFC0) | 0x40; + y = (y & 0xFFC0) | 0x40; } uint16 block = calcBlockIndex(x, y); @@ -364,7 +364,7 @@ void LoLEngine::setItemPosition(Item item, uint16 x, uint16 y, int flyingHeight, if (moveable) _itemsInPlay[item].shpCurFrame_flg |= 0x4000; else - _itemsInPlay[item].shpCurFrame_flg &= 0xbfff; + _itemsInPlay[item].shpCurFrame_flg &= 0xBFFF; assignItemToBlock(&_levelBlockProperties[block].assignedObjects, item); @@ -429,9 +429,9 @@ bool LoLEngine::launchObject(int objectType, Item item, int startX, int startY, if (attackerId != -1) { if (attackerId & 0x8000) { - t->flags &= 0xfd; + t->flags &= 0xFD; } else { - t->flags &= 0xfb; + t->flags &= 0xFB; increaseExperience(attackerId, 1, 2); } } @@ -455,8 +455,8 @@ void LoLEngine::endObjectFlight(FlyingObject *t, int x, int y, int collisionType if (t->objectType == 0 || t->objectType == 1) { objectFlightProcessHits(t, cx, cy, collisionType); - t->x = (cx & 0xffc0) | 0x40; - t->y = (cy & 0xffc0) | 0x40; + t->x = (cx & 0xFFC0) | 0x40; + t->y = (cy & 0xFFC0) | 0x40; t->flyingHeight = 0; updateObjectFlightPosition(t); } diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 7fbecb7f53..b180285ffc 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -52,13 +52,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _screen = 0; _text = 0; - _seqProcessedString = 0; - _activeWSA = 0; - _activeText = 0; - _seqWsa = 0; - _sequences = 0; - _sequenceSoundList = 0; - _gamePlayBuffer = 0; _cCodeBuffer = _optionsBuffer = _chapterBuffer = 0; @@ -89,7 +82,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn memset(&_invWsa, 0, sizeof(_invWsa)); _itemAnimDefinition = 0; - _demoAnimData = 0; _nextAnimItem = 0; for (int i = 0; i < 15; i++) @@ -136,7 +128,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn memset(_cauldronStateTables, 0, sizeof(_cauldronStateTables)); _menuDirectlyToLoad = false; - _menu = 0; _chatIsNote = false; memset(&_npcScriptData, 0, sizeof(_npcScriptData)); @@ -148,7 +139,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn KyraEngine_HoF::~KyraEngine_HoF() { cleanup(); - seq_uninit(); delete _screen; delete _text; @@ -157,15 +147,6 @@ KyraEngine_HoF::~KyraEngine_HoF() { _text = 0; delete _invWsa.wsa; - if (_sequenceSoundList) { - for (int i = 0; i < _sequenceSoundListSize; i++) { - if (_sequenceSoundList[i]) - delete[] _sequenceSoundList[i]; - } - delete[] _sequenceSoundList; - _sequenceSoundList = NULL; - } - delete[] _dlgBuffer; for (int i = 0; i < 19; i++) delete[] _conversationState[i]; @@ -179,41 +160,13 @@ KyraEngine_HoF::~KyraEngine_HoF() { void KyraEngine_HoF::pauseEngineIntern(bool pause) { KyraEngine_v2::pauseEngineIntern(pause); + seq_pausePlayer(pause); + if (!pause) { uint32 pausedTime = _system->getMillis() - _pauseStart; _pauseStart = 0; - // sequence player - // - // Timers in KyraEngine_HoF::seq_cmpFadeFrame() and KyraEngine_HoF::seq_animatedSubFrame() - // have been left out for now. I think we don't need them here. - - _seqStartTime += pausedTime; - _seqSubFrameStartTime += pausedTime; - _seqEndTime += pausedTime; - _seqSubFrameEndTimeInternal += pausedTime; - _seqWsaChatTimeout += pausedTime; - _seqWsaChatFrameTimeout += pausedTime; - - if (_activeText) { - for (int x = 0; x < 10; x++) { - if (_activeText[x].duration != -1) - _activeText[x].startTime += pausedTime; - } - } - - if (_activeWSA) { - for (int x = 0; x < 8; x++) { - if (_activeWSA[x].flags != -1) - _activeWSA[x].nextFrame += pausedTime; - } - } - _nextIdleAnim += pausedTime; - - for (int x = 0; x < _itemAnimDefinitionSize; x++) - _activeItemAnim[x].nextFrameTime += pausedTime; - _tim->refreshTimersAfterPause(pausedTime); } } @@ -244,8 +197,6 @@ Common::Error KyraEngine_HoF::init() { _screen->loadFont(_screen->FID_8_FNT, "8FAT.FNT"); _screen->loadFont(_screen->FID_BOOKFONT_FNT, "BOOKFONT.FNT"); } - _screen->loadFont(_screen->FID_GOLDFONT_FNT, "GOLDFONT.FNT"); - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : _screen->FID_8_FNT); _screen->setAnimBlockPtr(3504); @@ -254,13 +205,6 @@ Common::Error KyraEngine_HoF::init() { if (!_sound->init()) error("Couldn't init sound"); - _abortIntroFlag = false; - - if (_sequenceStrings) { - for (int i = 0; i < MIN(33, _sequenceStringsSize); i++) - _sequenceStringsDuration[i] = (int) strlen(_sequenceStrings[i]) * 8; - } - // No mouse display in demo if (_flags.isDemo && !_flags.isTalkie) return Common::kNoError; @@ -279,28 +223,24 @@ Common::Error KyraEngine_HoF::init() { } Common::Error KyraEngine_HoF::go() { + int menuChoice = 0; + if (_gameToLoad == -1) { if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) seq_showStarcraftLogo(); if (_flags.isDemo && !_flags.isTalkie) { -#ifdef ENABLE_LOL - if (_flags.gameID == GI_LOL) - seq_playSequences(kSequenceLoLDemoScene1, kSequenceLoLDemoScene6); - else -#endif // ENABLE_LOL - seq_playSequences(kSequenceDemoVirgin, kSequenceDemoFisher); - _menuChoice = 4; + menuChoice = seq_playDemo(); } else { - seq_playSequences(kSequenceVirgin, kSequenceZanfaun); + menuChoice = seq_playIntro(); } } else { - _menuChoice = 1; + menuChoice = 1; } _res->unloadAllPakFiles(); - if (_menuChoice != 4) { + if (menuChoice != 4) { // load just the pak files needed for ingame _staticres->loadStaticResourceFile(); @@ -317,24 +257,24 @@ Common::Error KyraEngine_HoF::go() { } } - _menuDirectlyToLoad = (_menuChoice == 3) ? true : false; + _menuDirectlyToLoad = (menuChoice == 3) ? true : false; _menuDirectlyToLoad &= saveFileLoadable(0); - if (_menuChoice & 1) { + if (menuChoice & 1) { startup(); if (!shouldQuit()) runLoop(); cleanup(); if (_showOutro) - seq_playSequences(kSequenceFunters, kSequenceFrash); + seq_playOutro(); } return Common::kNoError; } void KyraEngine_HoF::startup() { - _sound->setSoundList(&_soundData[kMusicIngame]); + _sound->selectAudioResourceSet(kMusicIngame); // The track map is exactly the same // for FM-TOWNS and DOS _trackMap = _dosTrackMap; @@ -1508,7 +1448,7 @@ void KyraEngine_HoF::snd_playSoundEffect(int track, int volume) { int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); if (vocIndex != -1) { - _sound->voicePlay(_ingameSoundList[vocIndex], 0, 255, true); + _sound->voicePlay(_ingameSoundList[vocIndex], 0, 255, 255, true); } else if (_flags.platform == Common::kPlatformPC) { if (_sound->getSfxType() == Sound::kMidiMT32) track = track < _mt32SfxMapSize ? _mt32SfxMap[track] - 1 : -1; diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index 182854cdf1..1b84e5b56f 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -35,158 +35,13 @@ namespace Kyra { -enum Sequences { - kSequenceVirgin = 0, - kSequenceWestwood, - kSequenceTitle, - kSequenceOverview, - kSequenceLibrary, - kSequenceHand, - kSequencePoint, - kSequenceZanfaun, - - kSequenceFunters, - kSequenceFerb, - kSequenceFish, - kSequenceFheep, - kSequenceFarmer, - kSequenceFuards, - kSequenceFirates, - kSequenceFrash, - - kSequenceArraySize -}; - -enum NestedSequences { - kSequenceFiggle = 0, - kSequenceOver1, - kSequenceOver2, - kSequenceForest, - kSequenceDragon, - kSequenceDarm, - kSequenceLibrary2, - kSequenceLibrary3, - kSequenceMarco, - kSequenceHand1a, - kSequenceHand1b, - kSequenceHand1c, - kSequenceHand2, - kSequenceHand3, - kSequenceHand4 -}; - -enum SequencesDemo { - kSequenceDemoVirgin = 0, - kSequenceDemoWestwood, - kSequenceDemoTitle, - kSequenceDemoHill, - kSequenceDemoOuthome, - kSequenceDemoWharf, - kSequenceDemoDinob, - kSequenceDemoFisher -}; - -enum NestedSequencesDemo { - kSequenceDemoWharf2 = 0, - kSequenceDemoDinob2, - kSequenceDemoWater, - kSequenceDemoBail, - kSequenceDemoDig -}; - -#ifdef ENABLE_LOL -enum SequencesLoLDemo { - kSequenceLoLDemoScene1 = 0, - kSequenceLoLDemoText1, - kSequenceLoLDemoScene2, - kSequenceLoLDemoText2, - kSequenceLoLDemoScene3, - kSequenceLoLDemoText3, - kSequenceLoLDemoScene4, - kSequenceLoLDemoText4, - kSequenceLoLDemoScene5, - kSequenceLoLDemoText5, - kSequenceLoLDemoScene6 -}; -#endif // ENABLE_LOL - -class WSAMovie_v2; -class KyraEngine_HoF; +//class WSAMovie_v2; +//class KyraEngine_HoF; class TextDisplayer_HoF; +class SeqPlayer_HOF; struct TIM; -typedef int (KyraEngine_HoF::*SeqProc)(WSAMovie_v2 *, int, int, int); - -struct ActiveWSA { - SeqProc callback; - WSAMovie_v2 *movie; - const FrameControl *control; - int16 flags; - uint16 startFrame; - uint16 endFrame; - uint16 frameDelay; - uint32 nextFrame; - uint16 currentFrame; - uint16 lastFrame; - uint16 x; - uint16 y; - uint16 startupCommand; - uint16 finalCommand; -}; - -struct ActiveText { - uint16 strIndex; - uint16 x; - uint16 y; - uint16 width; - int32 duration; - uint32 startTime; - int16 textcolor; -}; - -struct Sequence { - const char *wsaFile; - const char *cpsFile; - uint16 flags; - uint8 startupCommand; - uint8 finalCommand; - int16 stringIndex1; - int16 stringIndex2; - uint16 startFrame; - uint16 numFrames; - uint16 frameDelay; - uint16 xPos; - uint16 yPos; - uint16 duration; -}; - -struct NestedSequence { - const char *wsaFile; - const FrameControl *wsaControl; - uint16 flags; - uint16 startframe; - uint16 endFrame; - uint16 frameDelay; - uint16 x; - uint16 y; - uint16 startupCommand; - uint16 finalCommand; -}; - -struct HofSeqData { - const Sequence *seq; - int numSeq; - const NestedSequence *seqn; - int numSeqn; -}; - -struct ItemAnimData_v1 { - int16 itemIndex; - uint16 y; - const uint16 *frames; -}; - class KyraEngine_HoF : public KyraEngine_v2 { friend class Debugger_HoF; friend class TextDisplayer_HoF; @@ -202,98 +57,18 @@ public: GUI *gui() const { return _gui; } virtual TextDisplayer *text() { return _text; } int language() const { return _lang; } + protected: static const EngineDesc _hofEngineDesc; // intro/outro - void seq_playSequences(int startSeq, int endSeq = -1); - - int seq_introWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_introOver1(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introOver2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introForest(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_finaleFiggle(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_demoVirgin(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoHill(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoOuthome(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoWharf(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoDinob(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoFisher(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_demoWharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoDinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoWater(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoBail(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm); - -#ifdef ENABLE_LOL - int seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene3(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene4(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene5(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoText5(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm); -#endif // ENABLE_LOL - - void seq_sequenceCommand(int command); - void seq_loadNestedSequence(int wsaNum, int seqNum); - void seq_nestedSequenceFrame(int command, int wsaNum); - void seq_animatedSubFrame(int srcPage, int dstPage, int delaytime, - int steps, int x, int y, int w, int h, int openClose, int directionFlags); - bool seq_processNextSubFrame(int wsaNum); - void seq_resetActiveWSA(int wsaNum); - void seq_unloadWSA(int wsaNum); - void seq_processWSAs(); - void seq_cmpFadeFrame(const char *cmpFile); - void seq_playTalkText(uint8 chatNum); - void seq_resetAllTextEntries(); - uint32 seq_activeTextsTimeLeft(); - void seq_waitForTextsTimeout(); - int seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width); - void seq_processText(); - char *seq_preprocessString(const char *str, int width); - void seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor); - void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, - WSAMovie_v2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); - void seq_finaleActorScreen(); - void seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData = 0, const char *const *specialData = 0); - void seq_scrollPage(int bottom, int top); void seq_showStarcraftLogo(); - MainMenu *_menu; + int seq_playIntro(); + int seq_playOutro(); + int seq_playDemo(); - void seq_init(); - void seq_uninit(); + void seq_pausePlayer(bool toggle); Common::Error init(); Common::Error go(); @@ -311,7 +86,6 @@ protected: static const int8 _pcSpkSfxMap[]; static const int _pcSpkSfxMapSize; - AudioDataStruct _soundData[3]; protected: // game initialization void startup(); @@ -841,19 +615,19 @@ protected: bool _chatAltFlag; // sequence player - ActiveWSA *_activeWSA; +/* ActiveWSA *_activeWSA; ActiveText *_activeText; - - const char * const *_sequencePakList; - int _sequencePakListSize; - const char * const *_ingamePakList; + */ + /*const char *const *_sequencePakList; + int _sequencePakListSize;*/ + const char *const *_ingamePakList; int _ingamePakListSize; - const char * const *_musicFileListIntro; + const char *const *_musicFileListIntro; int _musicFileListIntroSize; - const char * const *_musicFileListFinale; + const char *const *_musicFileListFinale; int _musicFileListFinaleSize; - const char * const *_musicFileListIngame; + const char *const *_musicFileListIngame; int _musicFileListIngameSize; const uint8 *_cdaTrackTableIntro; int _cdaTrackTableIntroSize; @@ -861,34 +635,33 @@ protected: int _cdaTrackTableIngameSize; const uint8 *_cdaTrackTableFinale; int _cdaTrackTableFinaleSize; - const char * const *_sequenceSoundList; - int _sequenceSoundListSize; - const char * const *_ingameSoundList; + const char *const *_ingameSoundList; int _ingameSoundListSize; const uint16 *_ingameSoundIndex; int _ingameSoundIndexSize; - const char * const *_sequenceStrings; - int _sequenceStringsSize; const uint16 *_ingameTalkObjIndex; int _ingameTalkObjIndexSize; - const char * const *_ingameTimJpStr; + const char *const *_ingameTimJpStr; int _ingameTimJpStrSize; - const HofSeqData *_sequences; + const ItemAnimDefinition *_itemAnimDefinition; int _itemAnimDefinitionSize; + + /*const HofSeqData *_sequences; + const ItemAnimData_v1 *_demoAnimData; int _demoAnimSize; - int _sequenceStringsDuration[33]; + int _sequenceStringsDuration[33];*/ - static const uint8 _seqTextColorPresets[]; +/* static const uint8 _seqTextColorPresets[]; char *_seqProcessedString; WSAMovie_v2 *_seqWsa; bool _abortIntroFlag; - int _menuChoice; + int _menuChoice;*/ - uint32 _seqFrameDelay; + /*uint32 _seqFrameDelay; uint32 _seqStartTime; uint32 _seqSubFrameStartTime; uint32 _seqEndTime; @@ -902,10 +675,7 @@ protected: bool _seqSpecialFlag; bool _seqSubframePlaying; uint8 _seqTextColor[2]; - uint8 _seqTextColorMap[16]; - - const SeqProc *_callbackS; - const SeqProc *_callbackN; + uint8 _seqTextColorMap[16];*/ static const uint8 _rainbowRoomData[]; diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 27bc2ad22a..7d4e35092f 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -98,8 +98,6 @@ KyraEngine_LoK::KyraEngine_LoK(OSystem *system, const GameFlags &flags) _malcolmFrame = 0; _malcolmTimer1 = _malcolmTimer2 = 0; - - _soundFiles = 0; } KyraEngine_LoK::~KyraEngine_LoK() { @@ -123,8 +121,6 @@ KyraEngine_LoK::~KyraEngine_LoK() { delete _animator; delete _seq; - delete[] _soundFiles; - delete[] _characterList; delete[] _roomTable; @@ -194,7 +190,7 @@ Common::Error KyraEngine_LoK::init() { initStaticResource(); - _sound->setSoundList(&_soundData[kMusicIntro]); + _sound->selectAudioResourceSet(kMusicIntro); if (_flags.platform == Common::kPlatformAmiga) { _trackMap = _amigaTrackMap; @@ -349,7 +345,7 @@ void KyraEngine_LoK::startup() { static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 }; _screen->setTextColorMap(colorMap); - _sound->setSoundList(&_soundData[kMusicIngame]); + _sound->selectAudioResourceSet(kMusicIngame); if (_flags.platform == Common::kPlatformPC98) _sound->loadSoundFile("SE.DAT"); else diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index e5fb3cddca..def5cbcf6f 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -126,13 +126,13 @@ public: typedef bool (KyraEngine_LoK::*IntroProc)(); // static data access - const char * const *seqWSATable() { return _seq_WSATable; } - const char * const *seqCPSTable() { return _seq_CPSTable; } - const char * const *seqCOLTable() { return _seq_COLTable; } - const char * const *seqTextsTable() { return _seq_textsTable; } + const char *const *seqWSATable() { return _seq_WSATable; } + const char *const *seqCPSTable() { return _seq_CPSTable; } + const char *const *seqCOLTable() { return _seq_COLTable; } + const char *const *seqTextsTable() { return _seq_textsTable; } - const uint8 * const *palTable1() { return &_specialPalettes[0]; } - const uint8 * const *palTable2() { return &_specialPalettes[29]; } + const uint8 *const *palTable1() { return &_specialPalettes[0]; } + const uint8 *const *palTable2() { return &_specialPalettes[29]; } protected: virtual Common::Error go(); @@ -538,12 +538,12 @@ protected: const uint8 *_seq_Demo4; const uint8 *_seq_Reunion; - const char * const *_seq_WSATable; - const char * const *_seq_CPSTable; - const char * const *_seq_COLTable; - const char * const *_seq_textsTable; + const char *const *_seq_WSATable; + const char *const *_seq_CPSTable; + const char *const *_seq_COLTable; + const char *const *_seq_textsTable; - const char * const *_storyStrings; + const char *const *_storyStrings; int _seq_WSATable_Size; int _seq_CPSTable_Size; @@ -552,25 +552,25 @@ protected: int _storyStringsSize; - const char * const *_itemList; - const char * const *_takenList; - const char * const *_placedList; - const char * const *_droppedList; - const char * const *_noDropList; - const char * const *_putDownFirst; - const char * const *_waitForAmulet; - const char * const *_blackJewel; - const char * const *_poisonGone; - const char * const *_healingTip; - const char * const *_thePoison; - const char * const *_fluteString; - const char * const *_wispJewelStrings; - const char * const *_magicJewelString; - const char * const *_flaskFull; - const char * const *_fullFlask; - const char * const *_veryClever; - const char * const *_homeString; - const char * const *_newGameString; + const char *const *_itemList; + const char *const *_takenList; + const char *const *_placedList; + const char *const *_droppedList; + const char *const *_noDropList; + const char *const *_putDownFirst; + const char *const *_waitForAmulet; + const char *const *_blackJewel; + const char *const *_poisonGone; + const char *const *_healingTip; + const char *const *_thePoison; + const char *const *_fluteString; + const char *const *_wispJewelStrings; + const char *const *_magicJewelString; + const char *const *_flaskFull; + const char *const *_fullFlask; + const char *const *_veryClever; + const char *const *_homeString; + const char *const *_newGameString; int _itemList_Size; int _takenList_Size; @@ -592,13 +592,13 @@ protected: int _homeString_Size; int _newGameString_Size; - const char * const *_characterImageTable; + const char *const *_characterImageTable; int _characterImageTableSize; - const char * const *_guiStrings; + const char *const *_guiStrings; int _guiStringsSize; - const char * const *_configStrings; + const char *const *_configStrings; int _configStringsSize; Shape *_defaultShapeTable; @@ -636,20 +636,12 @@ protected: Room *_roomTable; int _roomTableSize; - const char * const *_roomFilenameTable; + const char *const *_roomFilenameTable; int _roomFilenameTableSize; const uint8 *_amuleteAnim; - const uint8 * const *_specialPalettes; - - const char * const *_soundFiles; - int _soundFilesSize; - const char * const *_soundFilesIntro; - int _soundFilesIntroSize; - const int32 *_cdaTrackTable; - int _cdaTrackTableSize; - AudioDataStruct _soundData[3]; + const uint8 *const *_specialPalettes; // positions of the inventory static const uint16 _itemPosX[]; diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 448e4ef70d..48ba96ec8b 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -28,7 +28,7 @@ #include "kyra/debugger.h" #include "kyra/gui_mr.h" #include "kyra/resource.h" -#include "kyra/sound.h" +#include "kyra/sound_digital.h" #include "common/system.h" #include "common/config-manager.h" @@ -213,8 +213,6 @@ Common::Error KyraEngine_MR::init() { _soundDigital = new SoundDigital(this, _mixer); assert(_soundDigital); - if (!_soundDigital->init()) - error("_soundDigital->init() failed"); KyraEngine_v1::_text = _text = new TextDisplayer_MR(this, _screen); assert(_text); _gui = new GUI_MR(this); @@ -724,7 +722,7 @@ void KyraEngine_MR::loadCharacterShapes(int newShapes) { static const uint8 numberOffset[] = { 3, 3, 4, 4, 3, 3 }; static const uint8 startShape[] = { 0x32, 0x58, 0x78, 0x98, 0xB8, 0xD8 }; static const uint8 endShape[] = { 0x57, 0x77, 0x97, 0xB7, 0xD7, 0xF7 }; - static const char * const filenames[] = { + static const char *const filenames[] = { "MSW##.SHP", "MTA##.SHP", "MTFL##.SHP", diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 004236ca04..d194fedd4d 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -182,11 +182,11 @@ private: private: // main menu - const char * const *_mainMenuStrings; + const char *const *_mainMenuStrings; int _mainMenuStringsSize; - static const char * const _mainMenuSpanishFan[]; - static const char * const _mainMenuItalianFan[]; + static const char *const _mainMenuSpanishFan[]; + static const char *const _mainMenuItalianFan[]; // animator uint8 *_gamePlayBuffer; diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp index f1d9550e8f..f8eb7d00cd 100644 --- a/engines/kyra/kyra_rpg.cpp +++ b/engines/kyra/kyra_rpg.cpp @@ -46,12 +46,7 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi _vcnTransitionMask = 0; _vcnShift = 0; _vcnColTable = 0; - _vcnBlockWidth = 4; - _vcnBlockHeight = 8; - _vcnFlip0 = 0; - _vcnFlip1 = 1; _vmpPtr = 0; - _vmpSize = 0; _blockBrightness = _wllVcnOffset = 0; _blockDrawingBuffer = 0; _sceneWindowBuffer = 0; @@ -173,9 +168,8 @@ Common::Error KyraRpgEngine::init() { _blockDrawingBuffer = new uint16[1320]; memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16)); - uint32 swbSize = 22 * _vcnBlockWidth * 2 * 15 * _vcnBlockHeight; - _sceneWindowBuffer = new uint8[swbSize]; - memset(_sceneWindowBuffer, 0, swbSize); + _sceneWindowBuffer = new uint8[21120]; + memset(_sceneWindowBuffer, 0, 21120); _lvlShapeTop = new int16[18]; memset(_lvlShapeTop, 0, 18 * sizeof(int16)); @@ -186,7 +180,7 @@ Common::Error KyraRpgEngine::init() { _vcnColTable = new uint8[128]; for (int i = 0; i < 128; i++) - _vcnColTable[i] = i & 0x0f; + _vcnColTable[i] = i & 0x0F; _doorShapes = new uint8*[6]; memset(_doorShapes, 0, 6 * sizeof(uint8 *)); @@ -210,18 +204,19 @@ bool KyraRpgEngine::posWithinRect(int posX, int posY, int x1, int y1, int x2, in void KyraRpgEngine::drawDialogueButtons() { int cp = screen()->setCurPage(0); - Screen::FontId of = screen()->setFont(gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); + Screen::FontId of = screen()->setFont(_flags.lang == Common::JA_JPN && _flags.use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); for (int i = 0; i < _dialogueNumButtons; i++) { int x = _dialogueButtonPosX[i]; - if (gameFlags().use16ColorMode) { - gui_drawBox(x, ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1, 74, 10, 0xee, 0xcc, -1); + if (_flags.lang == Common::JA_JPN && _flags.use16ColorMode) { + gui_drawBox(x, ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1, 74, 10, 0xEE, 0xCC, -1); screen()->printText(_dialogueButtonString[i], (x + 37 - (screen()->getTextWidth(_dialogueButtonString[i])) / 2) & ~3, - ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xc1 : 0xe1, 0); + ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xC1 : 0xE1, 0); } else { + int sjisYOffset = (_flags.lang == Common::JA_JPN && _dialogueButtonString[i][0] < 0) ? 2 : 0; gui_drawBox(x, (_dialogueButtonYoffs + _dialogueButtonPosY[i]), _dialogueButtonWidth, guiSettings()->buttons.height, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill); screen()->printText(_dialogueButtonString[i], x + (_dialogueButtonWidth >> 1) - (screen()->getTextWidth(_dialogueButtonString[i])) / 2, - (_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0); + (_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2 - sjisYOffset, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0); } } screen()->setFont(of); @@ -234,7 +229,7 @@ uint16 KyraRpgEngine::processDialogue() { for (int i = 0; i < _dialogueNumButtons; i++) { int x = _dialogueButtonPosX[i]; - int y = (gameFlags().use16ColorMode ? ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1 : (_dialogueButtonYoffs + _dialogueButtonPosY[i])); + int y = ((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) & ~7) - 1 : (_dialogueButtonYoffs + _dialogueButtonPosY[i])); Common::Point p = getMousePos(); if (posWithinRect(p.x, p.y, x, y, x + _dialogueButtonWidth, y + guiSettings()->buttons.height)) { _dialogueHighlightedButton = i; diff --git a/engines/kyra/kyra_rpg.h b/engines/kyra/kyra_rpg.h index 50a4c9bdc1..cd36d2a5cd 100644 --- a/engines/kyra/kyra_rpg.h +++ b/engines/kyra/kyra_rpg.h @@ -222,7 +222,6 @@ protected: uint16 _decorationCount; int16 _mappedDecorationsCount; uint16 *_vmpPtr; - uint16 _vmpSize; uint8 *_vcnBlocks; uint8 *_vcfBlocks; uint8 *_vcnTransitionMask; @@ -232,10 +231,6 @@ protected: uint8 *_sceneWindowBuffer; uint8 _blockBrightness; uint8 _wllVcnOffset; - uint8 _vcnBlockWidth; - uint8 _vcnBlockHeight; - uint8 _vcnFlip0; - uint8 _vcnFlip1; uint8 **_doorShapes; @@ -288,7 +283,7 @@ protected: void removeInputTop(); void gui_drawBox(int x, int y, int w, int h, int frameColor1, int frameColor2, int fillColor); virtual void gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2); - void gui_initButtonsFromList(const int16 *list); + void gui_initButtonsFromList(const uint8 *list); virtual void gui_initButton(int index, int x = -1, int y = -1, int val = -1) = 0; void gui_resetButtonList(); void gui_notifyButtonListChanged(); @@ -385,7 +380,7 @@ protected: bool lineIsPassable(int, int) { return false; } }; -} // End of namespace Kyra +} // End of namespace Kyra #endif // ENABLE_EOB || ENABLE_LOL diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 2672618c67..9194b64155 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -172,19 +172,6 @@ Common::Error KyraEngine_v1::init() { assert(_res); _res->reset(); - if (_flags.isDemo) { - // HACK: check whether this is the HOF demo or the LOL demo. - // The LOL demo needs to be detected and run as KyraEngine_HoF, - // but the static resource loader and the sequence player will - // need correct IDs. - if (_res->exists("scene1.cps")) -#ifdef ENABLE_LOL - _flags.gameID = GI_LOL; -#else - error("Lands of Lore demo is not supported in this build"); -#endif // !ENABLE_LOL - } - _staticres = new StaticResource(this); assert(_staticres); if (!_staticres->init()) @@ -366,84 +353,88 @@ void KyraEngine_v1::setupKeyMap() { Common::KeyCode kcScummVM; int16 kcDOS; int16 kcPC98; + int16 kcFMTowns; }; +#define UNKNOWN_KEYCODE -1 #define KC(x) Common::KEYCODE_##x static const KeyCodeMapEntry keys[] = { - { KC(SPACE), 61, 53 }, - { KC(RETURN), 43, 29 }, - { KC(UP), 96, 68 }, - { KC(KP8), 96, 68 }, - { KC(RIGHT), 102, 73 }, - { KC(KP6), 102, 73 }, - { KC(DOWN), 98, 76 }, - { KC(KP2), 98, 76 }, - { KC(KP5), 97, 72 }, - { KC(LEFT), 92, 71 }, - { KC(KP4), 92, 71 }, - { KC(HOME), 91, 67 }, - { KC(KP7), 91, 67 }, - { KC(PAGEUP), 101, 69 }, - { KC(KP9), 101, 69 }, - { KC(END), 93, 0/*unknown*/ }, - { KC(KP1), 93, 0/*unknown*/ }, - { KC(PAGEDOWN), 103, 0/*unknown*/ }, - { KC(KP3), 103, 0/*unknown*/ }, - { KC(F1), 112, 99 }, - { KC(F2), 113, 100 }, - { KC(F3), 114, 101 }, - { KC(F4), 115, 102 }, - { KC(F5), 116, 103 }, - { KC(F6), 117, 104 }, - { KC(a), 31, 31 }, - { KC(b), 50, 50 }, - { KC(c), 48, 48 }, - { KC(d), 33, 33 }, - { KC(e), 19, 19 }, - { KC(f), 34, 34 }, - { KC(i), 24, 24 }, - { KC(k), 38, 38 }, - { KC(m), 52, 52 }, - { KC(n), 51, 51 }, - { KC(o), 25, 25 }, - { KC(p), 26, 26 }, - { KC(r), 20, 20 }, - { KC(s), 32, 32 }, - { KC(w), 18, 18 }, - { KC(y), 22, 22 }, - { KC(z), 46, 46 }, - { KC(1), 2, 0/*unknown*/ }, - { KC(2), 3, 0/*unknown*/ }, - { KC(3), 4, 0/*unknown*/ }, - { KC(4), 5, 0/*unknown*/ }, - { KC(5), 6, 0/*unknown*/ }, - { KC(6), 7, 0/*unknown*/ }, - { KC(7), 8, 0/*unknown*/ }, - { KC(SLASH), 55, 55 }, - { KC(ESCAPE), 110, 1 }, - { KC(MINUS), 12, 0/*unknown*/ }, - { KC(KP_MINUS), 105, 0/*unknown*/ }, - { KC(PLUS), 13, 0/*unknown*/ }, - { KC(KP_PLUS), 106, 0/*unknown*/ }, + { KC(SPACE), 61, 53, 32 }, + { KC(RETURN), 43, 29, 13 }, + { KC(UP), 96, 68, 30 }, + { KC(KP8), 96, 68, 30 }, + { KC(RIGHT), 102, 73, 28 }, + { KC(KP6), 102, 73, 28 }, + { KC(DOWN), 98, 76, 31 }, + { KC(KP2), 98, 76, 31 }, + { KC(KP5), 97, 72, UNKNOWN_KEYCODE }, + { KC(LEFT), 92, 71, 29 }, + { KC(KP4), 92, 71, 29 }, + { KC(HOME), 91, 67, 127 }, + { KC(KP7), 91, 67, 127 }, + { KC(PAGEUP), 101, 69, 18 }, + { KC(KP9), 101, 69, 18 }, + { KC(END), 93, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(KP1), 93, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(PAGEDOWN), 103, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(KP3), 103, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(F1), 112, 99, UNKNOWN_KEYCODE }, + { KC(F2), 113, 100, UNKNOWN_KEYCODE }, + { KC(F3), 114, 101, UNKNOWN_KEYCODE }, + { KC(F4), 115, 102, UNKNOWN_KEYCODE }, + { KC(F5), 116, 103, UNKNOWN_KEYCODE }, + { KC(F6), 117, 104, UNKNOWN_KEYCODE }, + { KC(a), 31, 31, UNKNOWN_KEYCODE }, + { KC(b), 50, 50, UNKNOWN_KEYCODE }, + { KC(c), 48, 48, 67 }, + { KC(d), 33, 33, UNKNOWN_KEYCODE }, + { KC(e), 19, 19, UNKNOWN_KEYCODE }, + { KC(f), 34, 34, UNKNOWN_KEYCODE }, + { KC(i), 24, 24, UNKNOWN_KEYCODE }, + { KC(k), 38, 38, UNKNOWN_KEYCODE }, + { KC(m), 52, 52, UNKNOWN_KEYCODE }, + { KC(n), 51, 51, UNKNOWN_KEYCODE }, + { KC(o), 25, 25, 79 }, + { KC(p), 26, 26, 80 }, + { KC(r), 20, 20, 82 }, + { KC(s), 32, 32, UNKNOWN_KEYCODE }, + { KC(w), 18, 18, UNKNOWN_KEYCODE }, + { KC(y), 22, 22, UNKNOWN_KEYCODE }, + { KC(z), 46, 46, UNKNOWN_KEYCODE }, + { KC(0), UNKNOWN_KEYCODE, UNKNOWN_KEYCODE, 48 }, + { KC(1), 2, UNKNOWN_KEYCODE, 49 }, + { KC(2), 3, UNKNOWN_KEYCODE, 50 }, + { KC(3), 4, UNKNOWN_KEYCODE, 51 }, + { KC(4), 5, UNKNOWN_KEYCODE, 52 }, + { KC(5), 6, UNKNOWN_KEYCODE, 53 }, + { KC(6), 7, UNKNOWN_KEYCODE, 54 }, + { KC(7), 8, UNKNOWN_KEYCODE, 55 }, + { KC(SLASH), 55, 55, 47 }, + { KC(ESCAPE), 110, 1, 27 }, + { KC(MINUS), 12, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(KP_MINUS), 105, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(PLUS), 13, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(KP_PLUS), 106, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, // Multiple mappings for the keys to the right of the 'M' key, // since these are different for QWERTZ, QWERTY and AZERTY keyboards. // QWERTZ - { KC(COMMA), 53, 0/*unknown*/ }, - { KC(PERIOD), 54, 0/*unknown*/ }, + { KC(COMMA), 53, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(PERIOD), 54, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, // AZERTY - { KC(SEMICOLON), 53, 0/*unknown*/ }, - { KC(COLON), 54, 0/*unknown*/ }, + { KC(SEMICOLON), 53, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(COLON), 54, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, // QWERTY - { KC(LESS), 53, 0/*unknown*/ }, - { KC(GREATER), 54, 0/*unknown*/ } + { KC(LESS), 53, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE }, + { KC(GREATER), 54, UNKNOWN_KEYCODE, UNKNOWN_KEYCODE } }; #undef KC +#undef UNKNOWN_KEYCODE _keyMap.clear(); for (int i = 0; i < ARRAYSIZE(keys); i++) - _keyMap[keys[i].kcScummVM] = (_flags.platform == Common::kPlatformPC98) ? keys[i].kcPC98 : keys[i].kcDOS; + _keyMap[keys[i].kcScummVM] = (_flags.platform == Common::kPlatformPC98) ? keys[i].kcPC98 : ((_flags.platform == Common::kPlatformFMTowns) ? keys[i].kcFMTowns : keys[i].kcDOS); } void KyraEngine_v1::updateInput() { diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 0033969047..cd048563ca 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -140,14 +140,6 @@ enum { GI_EOB2 = 6 }; -struct AudioDataStruct { - const char *const *fileList; - int fileListLen; - const void *cdaTracks; - int cdaNumTracks; - int extraOffset; -}; - // TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable // in the future we maybe merge some flags and/or create new ones enum DebugLevels { @@ -164,7 +156,7 @@ enum DebugLevels { kDebugLevelTimer = 1 << 10 ///< debug level for "TimerManager" functions }; -enum MusicDataID { +enum AudioResourceSet { kMusicIntro = 0, kMusicIngame, kMusicFinale @@ -188,6 +180,7 @@ friend class GUI; friend class GUI_v1; friend class GUI_EoB; friend class SoundMidiPC; // For _eventMan +friend class SeqPlayer_HOF; // For skipFlag() friend class TransferPartyWiz; // For save state API public: KyraEngine_v1(OSystem *system, const GameFlags &flags); @@ -415,14 +408,14 @@ protected: Graphics::Surface *thumbnail; }; - enum kReadSaveHeaderError { + enum ReadSaveHeaderError { kRSHENoError = 0, kRSHEInvalidType = 1, kRSHEInvalidVersion = 2, kRSHEIoError = 3 }; - static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header); + static ReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header); void loadGameStateCheck(int slot); virtual Common::Error loadGameState(int slot) = 0; diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index d3028c5e2d..f7696d45b5 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -114,7 +114,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraRpgEngine(sy _selectedSpell = 0; _updateCharNum = _portraitSpeechAnimMode = _textColorFlag = 0; _palUpdateTimer = _updatePortraitNext = 0; - _lampStatusTimer = 0xffffffff; + _lampStatusTimer = 0xFFFFFFFF; _weaponsDisabled = false; _charInventoryUnk = 0; @@ -381,10 +381,10 @@ Common::Error LoLEngine::init() { _screen->setAnimBlockPtr(10000); _screen->setScreenDim(0); - _pageBuffer1 = new uint8[0xfa00]; - memset(_pageBuffer1, 0, 0xfa00); - _pageBuffer2 = new uint8[0xfa00]; - memset(_pageBuffer2, 0, 0xfa00); + _pageBuffer1 = new uint8[0xFA00]; + memset(_pageBuffer1, 0, 0xFA00); + _pageBuffer2 = new uint8[0xFA00]; + memset(_pageBuffer2, 0, 0xFA00); _itemsInPlay = new LoLItem[400]; memset(_itemsInPlay, 0, sizeof(LoLItem) * 400); @@ -499,6 +499,11 @@ void LoLEngine::initKeymap() { #endif } +void LoLEngine::pauseEngineIntern(bool pause) { + KyraEngine_v1::pauseEngineIntern(pause); + pauseDemoPlayer(pause); +} + Common::Error LoLEngine::go() { int action = -1; @@ -519,7 +524,7 @@ Common::Error LoLEngine::go() { // the prologue code we need to setup them manually here. if (_gameToLoad != -1 && action != 3) { preInit(); - _screen->setFont(_flags.use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); + _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); } // We have three sound.dat files, one for the intro, one for the @@ -529,7 +534,7 @@ Common::Error LoLEngine::go() { if (_flags.platform == Common::kPlatformPC98) _sound->loadSoundFile("sound.dat"); - _sound->setSoundList(&_soundData[kMusicIngame]); + _sound->selectAudioResourceSet(kMusicIngame); if (_flags.platform != Common::kPlatformPC) _sound->loadSoundFile(0); @@ -669,7 +674,7 @@ void LoLEngine::checkFloatingPointerRegions() { uint8 *LoLEngine::getItemIconShapePtr(int index) { int ix = _itemProperties[_itemsInPlay[index].itemPropertyIndex].shpIndex; if (_itemProperties[_itemsInPlay[index].itemPropertyIndex].flags & 0x200) - ix += (_itemsInPlay[index].shpCurFrame_flg & 0x1fff) - 1; + ix += (_itemsInPlay[index].shpCurFrame_flg & 0x1FFF) - 1; return _itemIconShapes[ix]; } @@ -678,14 +683,14 @@ int LoLEngine::mainMenu() { bool hasSave = saveFileLoadable(0); MainMenu::StaticData data[] = { - // 256 color mode + // 256 color ASCII mode { { 0, 0, 0, 0, 0 }, { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x3D, 0x9F }, { 0x2C, 0x19, 0x48, 0x2C }, Screen::FID_9_FNT, 1 }, - // 16 color mode + // 16 color SJIS mode { { 0, 0, 0, 0, 0 }, { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xC1, 0xE1 }, @@ -928,7 +933,7 @@ void LoLEngine::writeSettings() { case 0: default: - if (_flags.platform == Common::kPlatformPC98) + if (_flags.platform == Common::kPlatformPC98 || _flags.platform == Common::kPlatformFMTowns) _flags.lang = Common::JA_JPN; else _flags.lang = Common::EN_ANY; @@ -1024,7 +1029,7 @@ void LoLEngine::decodeSjis(const char *src, char *dst) { uint8 cmd = 0; while ((cmd = *src++) != 0) { if (cmd == 27) { - cmd = *src++ & 0x7f; + cmd = *src++ & 0x7F; memcpy(dst, src, cmd * 2); dst += cmd * 2; src += cmd * 2; @@ -1336,7 +1341,7 @@ int LoLEngine::calculateProtection(int index) { int c = 0; if (index & 0x8000) { // Monster - index &= 0x7fff; + index &= 0x7FFF; c = (_monsters[index].properties->itemProtection * _monsters[index].properties->fightingStats[2]) >> 8; } else { // Character @@ -1485,7 +1490,7 @@ void LoLEngine::increaseCharacterHitpoints(int charNum, int points, bool ignoreD points = 1; _characters[charNum].hitPointsCur = CLIP<int16>(_characters[charNum].hitPointsCur + points, 1, _characters[charNum].hitPointsMax); - _characters[charNum].flags &= 0xfff7; + _characters[charNum].flags &= 0xFFF7; } void LoLEngine::setupScreenDims() { @@ -1556,10 +1561,10 @@ void LoLEngine::gui_specialSceneSuspendControls(int controlMode) { void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { if (restoreLamp) { - _updateFlags &= 0xfffa; + _updateFlags &= 0xFFFA; resetLampStatus(); } - _updateFlags &= 0xfffe; + _updateFlags &= 0xFFFE; _specialSceneFlag = 0; checkFloatingPointerRegions(); } @@ -1567,7 +1572,7 @@ void LoLEngine::gui_specialSceneRestoreControls(int restoreLamp) { void LoLEngine::restoreAfterSceneWindowDialogue(int redraw) { gui_enableControls(); _txt->setupField(false); - _updateFlags &= 0xffdf; + _updateFlags &= 0xFFDF; setDefaultButtonState(); @@ -1596,8 +1601,8 @@ void LoLEngine::initDialogueSequence(int controlMode, int pageNum) { if (_flags.use16ColorMode) { _screen->fillRect(0, 128, 319, 199, 0x44); - gui_drawBox(0, 129, 320, 71, 0xee, 0xcc, -1); - gui_drawBox(1, 130, 318, 69, 0xee, 0xcc, 0x11); + gui_drawBox(0, 129, 320, 71, 0xEE, 0xCC, -1); + gui_drawBox(1, 130, 318, 69, 0xEE, 0xCC, 0x11); } else { _screen->fillRect(0, 128, 319, 199, 1); gui_drawBox(0, 129, 320, 71, 136, 251, -1); @@ -1646,7 +1651,7 @@ void LoLEngine::restoreAfterDialogueSequence(int controlMode) { if (_currentControlMode) { _screen->modifyScreenDim(4, 11, 124, 28, 45); _screen->modifyScreenDim(5, 85, 123, 233, 54); - _updateFlags &= 0xfffd; + _updateFlags &= 0xFFFD; } else { const ScreenDim *d = _screen->getScreenDim(5); _screen->fillRect(d->sx, d->sy, d->sx + d->w - (_flags.use16ColorMode ? 3 : 2), d->sy + d->h - 2, d->unkA); @@ -1709,14 +1714,14 @@ void LoLEngine::generateBrightnessPalette(const Palette &src, Palette &dst, int brightness = (8 - brightness) << 5; if (modifier >= 0 && modifier < 8 && (_flagsTable[31] & 0x08)) { - brightness = 256 - ((((modifier & 0xfffe) << 5) * (256 - brightness)) >> 8); + brightness = 256 - ((((modifier & 0xFFFE) << 5) * (256 - brightness)) >> 8); if (brightness < 0) brightness = 0; } for (int i = 0; i < 384; i++) { uint16 c = (dst[i] * brightness) >> 8; - dst[i] = c & 0xff; + dst[i] = c & 0xFF; } } } @@ -1726,9 +1731,9 @@ void LoLEngine::generateFlashPalette(const Palette &src, Palette &dst, int color for (int i = 2; i < 128; i++) { for (int ii = 0; ii < 3; ii++) { - uint8 t = src[i * 3 + ii] & 0x3f; + uint8 t = src[i * 3 + ii] & 0x3F; if (colorFlags & (1 << ii)) - t += ((0x3f - t) >> 1); + t += ((0x3F - t) >> 1); else t -= (t >> 1); dst[i * 3 + ii] = t; @@ -1750,7 +1755,7 @@ void LoLEngine::createTransparencyTables() { 0x88, 0x00, 0x99, 0x00, 0xAA, 0x00, 0xBB, 0x00, 0xCC, 0x00, 0xDD, 0x00, 0xEE, 0x00, 0xFF, 0x00 }; - memset(tpal, 0xff, 768); + memset(tpal, 0xFF, 768); _res->loadFileToBuf("LOL.NOL", tpal, 48); for (int i = 15; i > -1; i--) { @@ -1758,7 +1763,7 @@ void LoLEngine::createTransparencyTables() { tpal[s] = tpal[i * 3]; tpal[s + 1] = tpal[i * 3 + 1]; tpal[s + 2] = tpal[i * 3 + 2]; - tpal[i * 3 + 2] = tpal[i * 3 + 1] = tpal[i * 3] = 0xff; + tpal[i * 3 + 2] = tpal[i * 3 + 1] = tpal[i * 3] = 0xFF; } _screen->createTransparencyTablesIntern(colTbl, 16, tpal, tpal, _transparencyTable1, _transparencyTable2, 80); @@ -1948,15 +1953,15 @@ void LoLEngine::giveItemToMonster(LoLMonster *monster, Item item) { } const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) { - return (id & 0x8000) ? (const uint16 *)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers; + return (id & 0x8000) ? (const uint16 *)_monsters[id & 0x7FFF].properties->fightingStats : _characters[id].defaultModifiers; } uint16 *LoLEngine::getCharacterOrMonsterItemsMight(int id) { - return (id & 0x8000) ? _monsters[id & 0x7fff].properties->itemsMight : _characters[id].itemsMight; + return (id & 0x8000) ? _monsters[id & 0x7FFF].properties->itemsMight : _characters[id].itemsMight; } uint16 *LoLEngine::getCharacterOrMonsterProtectionAgainstItems(int id) { - return (id & 0x8000) ? _monsters[id & 0x7fff].properties->protectionAgainstItems : _characters[id].protectionAgainstItems; + return (id & 0x8000) ? _monsters[id & 0x7FFF].properties->protectionAgainstItems : _characters[id].protectionAgainstItems; } void LoLEngine::delay(uint32 millis, bool doUpdate, bool) { @@ -2093,7 +2098,7 @@ int LoLEngine::processMagicSpark(int charNum, int spellLevel) { uint16 target = getNearestMonsterFromCharacterForBlock(targetBlock, charNum); static const uint8 dmg[] = { 7, 15, 25, 60 }; - if (target != 0xffff) { + if (target != 0xFFFF) { inflictMagicalDamage(target, charNum, dmg[spellLevel], 5, 0); updateDrawPage2(); gui_drawScene(0); @@ -2111,8 +2116,8 @@ int LoLEngine::processMagicSpark(int charNum, int spellLevel) { const uint16 height = mov->height(); for (int i = 0; i < 6; i++) { - wX[i] = (_rnd.getRandomNumber(0x7fff) % 64) + ((176 - width) >> 1) + 80; - wY[i] = (_rnd.getRandomNumber(0x7fff) % 32) + ((120 - height) >> 1) - 16; + wX[i] = (_rnd.getRandomNumber(0x7FFF) % 64) + ((176 - width) >> 1) + 80; + wY[i] = (_rnd.getRandomNumber(0x7FFF) % 32) + ((120 - height) >> 1) - 16; wFrames[i] = i << 1; } @@ -2162,7 +2167,7 @@ int LoLEngine::processMagicHeal(int charNum, int spellLevel) { tpal.copy(_screen->getPalette(1)); if (_flags.use16ColorMode) { - tpal.fill(16, 240, 0xff); + tpal.fill(16, 240, 0xFF); uint8 *dst = tpal.getData(); for (int i = 1; i < 16; i++) { int s = ((i << 4) | i) * 3; @@ -2245,7 +2250,7 @@ int LoLEngine::processMagicHeal(int charNum, int spellLevel) { _screen->copyRegion(charNum * 77, 32, pX[charNum], pY, 77, 44, 2, 2, Screen::CR_NO_P_CHECK); - pts[charNum] &= 0xff; + pts[charNum] &= 0xFF; pts[charNum] += ((diff[charNum] << 8) / 16); increaseCharacterHitpoints(charNum, pts[charNum] / 256, true); gui_drawCharPortraitWithStats(charNum); @@ -2328,8 +2333,8 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { tpal[i * 3 + 1] = v; tpal[i * 3 + 2] = v << 1; - if (tpal[i * 3 + 2] > 0x3f) - tpal[i * 3 + 2] = 0x3f; + if (tpal[i * 3 + 2] > 0x3F) + tpal[i * 3 + 2] = 0x3F; } } @@ -2361,7 +2366,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s.getData(), tpal.getData(), 40, false); - _screen->fadePaletteStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength); + _screen->timedPaletteFadeStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength); if (mov->opened()) { int r = true; if (spellLevel > 2) { @@ -2390,7 +2395,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { int might = rollDice(iceDamageMin[spellLevel], iceDamageMax[spellLevel]) + iceDamageAdd[spellLevel]; int dmg = calcInflictableDamagePerItem(charNum, 0, might, 3, 2); - LoLMonster *m = &_monsters[o & 0x7fff]; + LoLMonster *m = &_monsters[o & 0x7FFF]; if (m->hitPoints <= dmg) { increaseExperience(charNum, 2, m->hitPoints); o = m->nextAssignedObject; @@ -2430,7 +2435,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal.getData(), swampCol.getData(), 40, 0); - _screen->fadePaletteStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength); + _screen->timedPaletteFadeStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength); if (breakWall) breakIceWall(tpal.getData(), swampCol.getData()); @@ -2469,7 +2474,7 @@ int LoLEngine::processMagicFireball(int charNum, int spellLevel) { while (o & 0x8000) { static const uint8 fireballDamage[] = { 20, 40, 80, 100 }; int dmg = calcInflictableDamagePerItem(charNum, o, fireballDamage[spellLevel], 4, 1); - LoLMonster *m = &_monsters[o & 0x7fff]; + LoLMonster *m = &_monsters[o & 0x7FFF]; o = m->nextAssignedObject; _envSfxUseQueue = true; inflictDamage(m->id | 0x8000, dmg, charNum, 2, 4); @@ -2519,8 +2524,8 @@ int LoLEngine::processMagicFireball(int charNum, int spellLevel) { static const int8 finShpIndex2[] = { -1, 1, 2, 3, 4, -1 }; uint8 *shp = fb->finalize ? _fireballShapes[finShpIndex1[fb->finProgress]] : _fireballShapes[0]; - int fX = (((fb->progress * _fireBallCoords[fb->tblIndex & 0xff]) >> 16) + fb->destX) - ((fb->progress / 8 + shp[3] + fireBallWH) >> 1); - int fY = (((fb->progress * _fireBallCoords[(fb->tblIndex + 64) & 0xff]) >> 16) + fb->destY) - ((fb->progress / 8 + shp[2] + fireBallWH) >> 1); + int fX = (((fb->progress * _fireBallCoords[fb->tblIndex & 0xFF]) >> 16) + fb->destX) - ((fb->progress / 8 + shp[3] + fireBallWH) >> 1); + int fY = (((fb->progress * _fireBallCoords[(fb->tblIndex + 64) & 0xFF]) >> 16) + fb->destY) - ((fb->progress / 8 + shp[2] + fireBallWH) >> 1); int sW = ((fb->progress / 8 + shp[3] + fireBallWH) << 8) / shp[3]; int sH = ((fb->progress / 8 + shp[2] + fireBallWH) << 8) / shp[2]; @@ -2532,8 +2537,8 @@ int LoLEngine::processMagicFireball(int charNum, int spellLevel) { if (finShpIndex2[fb->finProgress] != -1) { shp = _fireballShapes[finShpIndex2[fb->finProgress]]; - fX = (((fb->progress * _fireBallCoords[fb->tblIndex & 0xff]) >> 16) + fb->destX) - ((fb->progress / 8 + shp[3] + fireBallWH) >> 1); - fY = (((fb->progress * _fireBallCoords[(fb->tblIndex + 64) & 0xff]) >> 16) + fb->destY) - ((fb->progress / 8 + shp[2] + fireBallWH) >> 1); + fX = (((fb->progress * _fireBallCoords[fb->tblIndex & 0xFF]) >> 16) + fb->destX) - ((fb->progress / 8 + shp[3] + fireBallWH) >> 1); + fY = (((fb->progress * _fireBallCoords[(fb->tblIndex + 64) & 0xFF]) >> 16) + fb->destY) - ((fb->progress / 8 + shp[2] + fireBallWH) >> 1); sW = ((fb->progress / 8 + shp[3] + fireBallWH) << 8) / shp[3]; sH = ((fb->progress / 8 + shp[2] + fireBallWH) << 8) / shp[2]; _screen->drawShape(_screen->_curPage, shp, fX, fY, 0, 4, sW, sH); @@ -2634,7 +2639,7 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) { uint16 o = _levelBlockProperties[b1].assignedObjects; while (o & 0x8000) { uint16 o2 = o; - LoLMonster *m = &_monsters[o & 0x7fff]; + LoLMonster *m = &_monsters[o & 0x7FFF]; o = findObject(o)->nextAssignedObject; int nX = 0; int nY = 0; @@ -2662,7 +2667,7 @@ int LoLEngine::processMagicHandOfFate(int spellLevel) { // This might be a bug in the original code, but using // the hand of fate spell won't give any experience points int dmg = calcInflictableDamagePerItem(-1, t, damage[spellLevel - 2], 0x80, 1); - inflictDamage(t, dmg, 0xffff, 3, 0x80); + inflictDamage(t, dmg, 0xFFFF, 3, 0x80); } } @@ -2778,7 +2783,7 @@ int LoLEngine::processMagicFog() { uint16 o = _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].assignedObjects; while (o & 0x8000) { inflictMagicalDamage(o, -1, 15, 6, 0); - o = _monsters[o & 0x7fff].nextAssignedObject; + o = _monsters[o & 0x7FFF].nextAssignedObject; } gui_drawScene(0); @@ -2803,7 +2808,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) { int t = 0; uint16 o = _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].assignedObjects; while (o & 0x8000) { - o &= 0x7fff; + o &= 0x7FFF; if (_monsters[o].mode != 13) { destIds[t++] = o; @@ -2811,7 +2816,7 @@ int LoLEngine::processMagicSwarm(int charNum, int damage) { _envSfxUseQueue = true; inflictMagicalDamage(o | 0x8000, charNum, damage, 0, 0); _envSfxUseQueue = false; - _monsters[o].flags &= 0xffef; + _monsters[o].flags &= 0xFFEF; } } o = _monsters[o].nextAssignedObject; @@ -2886,7 +2891,7 @@ int LoLEngine::processMagicVaelansCube() { uint32 endTime = _system->getMillis() + 70 * _tickLength; while (_system->getMillis() < endTime) { - _screen->fadePaletteStep(tmpPal1, tmpPal2, _system->getMillis() - ctime, 70 * _tickLength); + _screen->timedPaletteFadeStep(tmpPal1, tmpPal2, _system->getMillis() - ctime, 70 * _tickLength); updateInput(); } @@ -2903,9 +2908,9 @@ int LoLEngine::processMagicVaelansCube() { uint16 o = _levelBlockProperties[bl].assignedObjects; while (o & 0x8000) { - LoLMonster *m = &_monsters[o & 0x7fff]; + LoLMonster *m = &_monsters[o & 0x7FFF]; if (m->properties->flags & 0x1000) { - inflictDamage(o, 100, 0xffff, 0, 0x80); + inflictDamage(o, 100, 0xFFFF, 0, 0x80); res = 1; } o = m->nextAssignedObject; @@ -2915,7 +2920,7 @@ int LoLEngine::processMagicVaelansCube() { endTime = _system->getMillis() + 70 * _tickLength; while (_system->getMillis() < endTime) { - _screen->fadePaletteStep(tmpPal2, tmpPal1, _system->getMillis() - ctime, 70 * _tickLength); + _screen->timedPaletteFadeStep(tmpPal2, tmpPal1, _system->getMillis() - ctime, 70 * _tickLength); updateInput(); } @@ -3031,7 +3036,7 @@ void LoLEngine::drinkBezelCup(int numUses, int charNum) { uint16 step = 0; do { - step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 1]); + step = (step & 0xFF) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 1]); increaseCharacterHitpoints(charNum, step / 256, true); gui_drawCharPortraitWithStats(charNum); @@ -3068,7 +3073,7 @@ void LoLEngine::addSpellToScroll(int spell, int charNum) { } if (_availableSpells[i] == spell) { - _txt->printMessage(2, "%s", getLangString(0x42d0)); + _txt->printMessage(2, "%s", getLangString(0x42D0)); return; } } @@ -3096,7 +3101,7 @@ void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) _screen->copyRegion(201, 1, 17, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK); _screen->copyRegion(208, 1, 89, 15, 6, h, 2, 2, Screen::CR_NO_P_CHECK); int cp = _screen->setCurPage(2); - _screen->fillRect(21, 15, 89, h + 15, _flags.use16ColorMode ? 0xbb : 206); + _screen->fillRect(21, 15, 89, h + 15, _flags.use16ColorMode ? 0xBB : 206); _screen->copyRegion(112, 16, 12, h + 15, 87, 14, 2, 2, Screen::CR_NO_P_CHECK); int y = 15; @@ -3244,7 +3249,7 @@ void LoLEngine::playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFra continue; } - if (!_screen->fadePaletteStep(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov) + if (!_screen->timedPaletteFadeStep(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov) return; if (del) { @@ -3284,7 +3289,7 @@ int LoLEngine::checkMagic(int charNum, int spellNum, int spellLevel) { } int LoLEngine::getSpellTargetBlock(int currentBlock, int direction, int maxDistance, uint16 &targetBlock) { - targetBlock = 0xffff; + targetBlock = 0xFFFF; uint16 c = calcNewBlockPosition(currentBlock, direction); int i = 0; @@ -3316,9 +3321,9 @@ void LoLEngine::inflictMagicalDamageForBlock(int block, int attacker, int damage uint16 o = _levelBlockProperties[block].assignedObjects; while (o & 0x8000) { inflictDamage(o, calcInflictableDamagePerItem(attacker, o, damage, index, 2), attacker, 2, index); - if ((_monsters[o & 0x7fff].flags & 0x20) && (_currentLevel != 22)) + if ((_monsters[o & 0x7FFF].flags & 0x20) && (_currentLevel != 22)) break; - o = _monsters[o & 0x7fff].nextAssignedObject; + o = _monsters[o & 0x7FFF].nextAssignedObject; } } @@ -3331,7 +3336,7 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { return 1; if (target & 0x8000) { - if (_monsters[target & 0x7fff].mode >= 13) + if (_monsters[target & 0x7FFF].mode >= 13) return 0; } @@ -3340,8 +3345,8 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { int sk = 0; if (attacker & 0x8000) { - hitChanceModifier = _monsters[target & 0x7fff].properties->fightingStats[0]; - sk = 100 - _monsters[target & 0x7fff].properties->skillLevel; + hitChanceModifier = _monsters[target & 0x7FFF].properties->fightingStats[0]; + sk = 100 - _monsters[target & 0x7FFF].properties->skillLevel; } else { hitChanceModifier = _characters[attacker].defaultModifiers[0]; int8 m = _characters[attacker].skillModifiers[skill]; @@ -3351,8 +3356,10 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { } if (target & 0x8000) { - evadeChanceModifier = (_monsterModifiers[9 + _monsterDifficulty] * _monsters[target & 0x7fff].properties->fightingStats[3]) >> 8; - _monsters[target & 0x7fff].flags |= 0x10; + evadeChanceModifier = _monsters[target & 0x7FFF].properties->fightingStats[3]; + if (_monsterModifiers4) + evadeChanceModifier = (evadeChanceModifier * _monsterModifiers4[_monsterDifficulty]) >> 8; + _monsters[target & 0x7FFF].flags |= 0x10; } else { evadeChanceModifier = _characters[target].defaultModifiers[3]; } @@ -3387,7 +3394,7 @@ int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int ski LoLCharacter *c = 0; if (target & 0x8000) { - m = &_monsters[target & 0x7fff]; + m = &_monsters[target & 0x7FFF]; if (m->mode >= 13) return 0; @@ -3477,7 +3484,7 @@ void LoLEngine::removeCharacterEffects(LoLCharacter *c, int first, int last) { for (int i = first; i <= last; i++) { switch (i - 1) { case 0: - c->flags &= 0xfffb; + c->flags &= 0xFFFB; c->weaponHit = 0; break; @@ -3486,19 +3493,19 @@ void LoLEngine::removeCharacterEffects(LoLCharacter *c, int first, int last) { break; case 2: - c->flags &= 0xffbf; + c->flags &= 0xFFBF; break; case 3: - c->flags &= 0xff7f; + c->flags &= 0xFF7F; break; case 4: - c->flags &= 0xfeff; + c->flags &= 0xFEFF; break; case 6: - c->flags &= 0xefff; + c->flags &= 0xEFFF; break; default: @@ -3552,7 +3559,7 @@ int LoLEngine::calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 void LoLEngine::checkForPartyDeath() { Button b; - b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xFE; b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; for (int i = 0; i < 4; i++) { @@ -3591,7 +3598,7 @@ void LoLEngine::checkForPartyDeath() { _gui->runMenu(_gui->_deathMenu); setMouseCursorToItemInHand(); - _updateFlags &= 0xfffb; + _updateFlags &= 0xFFFB; resetLampStatus(); gui_enableDefaultPlayfieldButtons(); @@ -3608,7 +3615,7 @@ void LoLEngine::applyMonsterAttackSkill(LoLMonster *monster, int16 target, int16 switch (monster->properties->attackSkillType - 1) { case 0: - t = removeCharacterItem(target, 0x7ff); + t = removeCharacterItem(target, 0x7FF); if (t) { giveItemToMonster(monster, t); if (characterSays(0x4019, _characters[target].id, true)) @@ -3625,16 +3632,16 @@ void LoLEngine::applyMonsterAttackSkill(LoLMonster *monster, int16 target, int16 t = removeCharacterItem(target, 0x20); if (t) { deleteItem(t); - if (characterSays(0x401b, _characters[target].id, true)) - _txt->printMessage(6, "%s", getLangString(0x401b)); + if (characterSays(0x401B, _characters[target].id, true)) + _txt->printMessage(6, "%s", getLangString(0x401B)); } break; case 3: - t = removeCharacterItem(target, 0x0f); + t = removeCharacterItem(target, 0x0F); if (t) { - if (characterSays(0x401e, _characters[target].id, true)) - _txt->printMessage(6, getLangString(0x401e), _characters[target].name); + if (characterSays(0x401E, _characters[target].id, true)) + _txt->printMessage(6, getLangString(0x401E), _characters[target].name); setItemPosition(t, monster->x, monster->y, 0, 1); } break; @@ -3679,27 +3686,27 @@ void LoLEngine::applyMonsterDefenseSkill(LoLMonster *monster, int16 attacker, in switch (monster->properties->defenseSkillType - 1) { case 0: case 1: - if ((flags & 0x3f) == 2 || skill) + if ((flags & 0x3F) == 2 || skill) return; for (int i = 0; i < 3; i++) { itm = _characters[attacker].items[i]; if (!itm) continue; - if ((_itemProperties[_itemsInPlay[itm].itemPropertyIndex].protection & 0x3f) != flags) + if ((_itemProperties[_itemsInPlay[itm].itemPropertyIndex].protection & 0x3F) != flags) continue; - removeCharacterItem(attacker, 0x7fff); + removeCharacterItem(attacker, 0x7FFF); if (monster->properties->defenseSkillType == 1) { giveItemToMonster(monster, itm); - if (characterSays(0x401c, _characters[attacker].id, true)) - _txt->printMessage(6, "%s", getLangString(0x401c)); + if (characterSays(0x401C, _characters[attacker].id, true)) + _txt->printMessage(6, "%s", getLangString(0x401C)); } else { deleteItem(itm); - if (characterSays(0x401d, _characters[attacker].id, true)) - _txt->printMessage(6, "%s", getLangString(0x401d)); + if (characterSays(0x401D, _characters[attacker].id, true)) + _txt->printMessage(6, "%s", getLangString(0x401D)); } } break; @@ -3890,7 +3897,7 @@ void LoLEngine::launchMagicViper() { void LoLEngine::breakIceWall(uint8 *pal1, uint8 *pal2) { _screen->hideMouse(); uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection); - _levelBlockProperties[bl].flags &= 0xef; + _levelBlockProperties[bl].flags &= 0xEF; _screen->copyPage(0, 2); gui_drawScene(2); _screen->copyPage(2, 10); @@ -3918,10 +3925,10 @@ uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(uint16 block, int charN uint16 cX = 0; uint16 cY = 0; - uint16 id = 0xffff; - int minDist = 0x7fff; + uint16 id = 0xFFFF; + int minDist = 0x7FFF; - if (block == 0xffff) + if (block == 0xFFFF) return id; calcCoordinatesForSingleCharacter(charNum, cX, cY); @@ -3929,7 +3936,7 @@ uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(uint16 block, int charN int o = _levelBlockProperties[block].assignedObjects; while (o & 0x8000) { - LoLMonster *m = &_monsters[o & 0x7fff]; + LoLMonster *m = &_monsters[o & 0x7FFF]; if (m->mode >= 13) { o = m->nextAssignedObject; continue; @@ -3948,8 +3955,8 @@ uint16 LoLEngine::getNearestMonsterFromCharacterForBlock(uint16 block, int charN } uint16 LoLEngine::getNearestMonsterFromPos(int x, int y) { - uint16 id = 0xffff; - int minDist = 0x7fff; + uint16 id = 0xFFFF; + int minDist = 0x7FFF; for (int i = 0; i < 30; i++) { if (_monsters[i].mode > 13) @@ -3966,8 +3973,8 @@ uint16 LoLEngine::getNearestMonsterFromPos(int x, int y) { } uint16 LoLEngine::getNearestPartyMemberFromPos(int x, int y) { - uint16 id = 0xffff; - int minDist = 0x7fff; + uint16 id = 0xFFFF; + int minDist = 0x7FFF; for (int i = 0; i < 4; i++) { if (!(_characters[i].flags & 1) || _characters[i].hitPointsCur <= 0) @@ -4049,7 +4056,7 @@ void LoLEngine::displayAutomap() { delayTimer = _system->getMillis() + 8 * _tickLength; } - int f = checkInput(0) & 0xff; + int f = checkInput(0) & 0xFF; removeInputTop(); if (f) { @@ -4057,7 +4064,7 @@ void LoLEngine::displayAutomap() { gui_notifyButtonListChanged(); } - if (f == 0x30) { + if (f == _keyMap[Common::KEYCODE_c]) { for (int i = 0; i < 1024; i++) _levelBlockProperties[i].flags |= 7; _mapUpdateNeeded = true; @@ -4089,7 +4096,7 @@ void LoLEngine::updateAutoMap(uint16 block) { return; _levelBlockProperties[block].flags |= 7; - uint16 x = block & 0x1f; + uint16 x = block & 0x1F; uint16 y = block >> 5; updateAutoMapIntern(block, x, y, -1, -1); @@ -4107,7 +4114,7 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff x += xOffs; y += yOffs; - if ((x & 0xffe0) || (y & 0xffe0)) + if ((x & 0xFFE0) || (y & 0xFFE0)) return false; xOffs++; @@ -4117,7 +4124,7 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff uint16 b = block + blockPosTable[6 + xOffs]; if (fx != -1) { - if (_wllAutomapData[_levelBlockProperties[b].walls[fx]] & 0xc0) + if (_wllAutomapData[_levelBlockProperties[b].walls[fx]] & 0xC0) return false; } @@ -4125,13 +4132,13 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff b = block + blockPosTable[9 + yOffs]; if (fy != -1) { - if (_wllAutomapData[_levelBlockProperties[b].walls[fy]] & 0xc0) + if (_wllAutomapData[_levelBlockProperties[b].walls[fy]] & 0xC0) return false; } b = block + blockPosTable[6 + xOffs] + blockPosTable[9 + yOffs]; - if ((fx != -1) && (fy != -1) && (_wllAutomapData[_levelBlockProperties[b].walls[fx]] & 0xc0) && (_wllAutomapData[_levelBlockProperties[b].walls[fy]] & 0xc0)) + if ((fx != -1) && (fy != -1) && (_wllAutomapData[_levelBlockProperties[b].walls[fx]] & 0xC0) && (_wllAutomapData[_levelBlockProperties[b].walls[fy]] & 0xC0)) return false; _levelBlockProperties[b].flags |= 7; @@ -4142,8 +4149,8 @@ bool LoLEngine::updateAutoMapIntern(uint16 block, uint16 x, uint16 y, int16 xOff void LoLEngine::loadMapLegendData(int level) { uint16 *legendData = (uint16 *)_tempBuffer5120; for (int i = 0; i < 32; i++) { - legendData[i * 6] = 0xffff; - legendData[i * 6 + 5] = 0xffff; + legendData[i * 6] = 0xFFFF; + legendData[i * 6 + 5] = 0xFFFF; } Common::String file = Common::String::format("level%d.xxx", level); @@ -4184,7 +4191,7 @@ void LoLEngine::drawMapPage(int pageNum) { _screen->copyRegion(236, 16, 236 + xOffset, 16, -xOffset, 1, pageNum, pageNum, Screen::CR_NO_P_CHECK); int cp = _screen->setCurPage(pageNum); - Screen::FontId of = _screen->setFont(_flags.use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); + Screen::FontId of = _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); _screen->printText(getLangString(_autoMapStrings[_currentMapLevel]), 236 + xOffset, 8, 1, 0); uint16 blX = mapGetStartPosX(); uint16 bl = (mapGetStartPosY() << 5) + blX; @@ -4194,7 +4201,7 @@ void LoLEngine::drawMapPage(int pageNum) { for (; bl < 1024; bl++) { uint8 *w = _levelBlockProperties[bl].walls; - if ((_levelBlockProperties[bl].flags & 7) == 7 && (!(_wllAutomapData[w[0]] & 0xc0)) && (!(_wllAutomapData[w[2]] & 0xc0)) && (!(_wllAutomapData[w[1]] & 0xc0)) && (!(_wllAutomapData[w[3]] & 0xc0))) { + if ((_levelBlockProperties[bl].flags & 7) == 7 && (!(_wllAutomapData[w[0]] & 0xC0)) && (!(_wllAutomapData[w[2]] & 0xC0)) && (!(_wllAutomapData[w[1]] & 0xC0)) && (!(_wllAutomapData[w[3]] & 0xC0))) { uint16 b0 = calcNewBlockPosition(bl, 0); uint16 b2 = calcNewBlockPosition(bl, 2); uint16 b1 = calcNewBlockPosition(bl, 1); @@ -4211,25 +4218,25 @@ void LoLEngine::drawMapPage(int pageNum) { // draw north wall drawMapBlockWall(b3, w31, sx, sy, 3); drawMapShape(w31, sx, sy, 3); - if (_wllAutomapData[w31] & 0xc0) + if (_wllAutomapData[w31] & 0xC0) _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 1, 6, 0, _mapOverlay); // draw west wall drawMapBlockWall(b1, w13, sx, sy, 1); drawMapShape(w13, sx, sy, 1); - if (_wllAutomapData[w13] & 0xc0) + if (_wllAutomapData[w13] & 0xC0) _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx + 6, sy, _screen->_curPage, sx + 6, sy, 1, 6, 0, _mapOverlay); // draw east wall drawMapBlockWall(b0, w02, sx, sy, 0); drawMapShape(w02, sx, sy, 0); - if (_wllAutomapData[w02] & 0xc0) + if (_wllAutomapData[w02] & 0xC0) _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 1, 0, _mapOverlay); //draw south wall drawMapBlockWall(b2, w20, sx, sy, 2); drawMapShape(w20, sx, sy, 2); - if (_wllAutomapData[w20] & 0xc0) + if (_wllAutomapData[w20] & 0xC0) _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy + 5, _screen->_curPage, sx, sy + 5, 7, 1, 0, _mapOverlay); } @@ -4244,7 +4251,7 @@ void LoLEngine::drawMapPage(int pageNum) { _screen->setFont(of); _screen->setCurPage(cp); - of = _screen->setFont(_flags.use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); + of = _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); int tY = 0; sx = mapGetStartPosX(); @@ -4255,19 +4262,19 @@ void LoLEngine::drawMapPage(int pageNum) { for (int ii = 0; ii < 32; ii++) { uint16 *l = &legendData[ii * 6]; - if (l[0] == 0xffff) + if (l[0] == 0xFFFF) break; uint16 cbl = l[0] + (l[1] << 5); if ((_levelBlockProperties[cbl].flags & 7) != 7) continue; - if (l[2] == 0xffff) + if (l[2] == 0xFFFF) continue; printMapText(l[2], 244 + xOffset, (tY << 3) + 22 + yOffset); - if (l[5] == 0xffff) { + if (l[5] == 0xFFFF) { tY++; continue; } @@ -4338,7 +4345,7 @@ bool LoLEngine::automapProcessButtons(int inputFlag) { void LoLEngine::automapForwardButton() { int i = _currentMapLevel + 1; while (!(_hasTempDataFlags & (1 << (i - 1)))) - i = (i + 1) & 0x1f; + i = (i + 1) & 0x1F; if (i == _currentMapLevel) return; @@ -4355,7 +4362,7 @@ void LoLEngine::automapForwardButton() { void LoLEngine::automapBackButton() { int i = _currentMapLevel - 1; while (!(_hasTempDataFlags & (1 << (i - 1)))) - i = (i - 1) & 0x1f; + i = (i - 1) & 0x1F; if (i == _currentMapLevel) return; @@ -4396,7 +4403,7 @@ void LoLEngine::redrawMapCursor() { } void LoLEngine::drawMapBlockWall(uint16 block, uint8 wall, int x, int y, int direction) { - if (((1 << direction) & _levelBlockProperties[block].flags) || ((_wllAutomapData[wall] & 0x1f) != 13)) + if (((1 << direction) & _levelBlockProperties[block].flags) || ((_wllAutomapData[wall] & 0x1F) != 13)) return; int cp = _screen->_curPage; @@ -4406,8 +4413,8 @@ void LoLEngine::drawMapBlockWall(uint16 block, uint8 wall, int x, int y, int dir } void LoLEngine::drawMapShape(uint8 wall, int x, int y, int direction) { - int l = _wllAutomapData[wall] & 0x1f; - if (l == 0x1f) + int l = _wllAutomapData[wall] & 0x1F; + if (l == 0x1F) return; _screen->drawShape(_screen->_curPage, _automapShapes[(l << 2) + direction], x + _mapCoords[10][direction] - 2, y + _mapCoords[11][direction] - 2, 0, 0); @@ -4473,7 +4480,7 @@ int LoLEngine::mapGetStartPosY() { } void LoLEngine::mapIncludeLegendData(int type) { - type &= 0x7f; + type &= 0x7F; for (int i = 0; i < 11; i++) { if (_defaultLegendData[i].shapeIndex != type) continue; @@ -4494,7 +4501,7 @@ void LoLEngine::printMapText(uint16 stringId, int x, int y) { void LoLEngine::printMapExitButtonText() { int cp = _screen->setCurPage(2); Screen::FontId of = _screen->setFont(Screen::FID_9_FNT); - _screen->fprintString("%s", 295, 182, _flags.use16ColorMode ? 0xbb : 172, 0, 5, getLangString(0x4033)); + _screen->fprintString("%s", 295, 182, _flags.use16ColorMode ? 0xBB : 172, 0, 5, getLangString(0x4033)); _screen->setFont(of); _screen->setCurPage(cp); } diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index dcd13804b3..4002346d31 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -270,6 +270,8 @@ public: virtual void initKeymap(); + void pauseEngineIntern(bool pause); + Screen *screen(); GUI *gui() const; @@ -334,9 +336,9 @@ private: static const char *const _charPreviewNamesDefault[]; static const char *const _charPreviewNamesRussianFloppy[]; - // PC98 specific data + // PC98/FM-TOWNS specific data static const uint16 _charPosXPC98[]; - static const uint8 _charNamesPC98[][11]; + static const char *const _charNamesJapanese[]; WSAMovie_v2 *_chargenWSA; static const uint8 _chargenFrameTableTalkie[]; @@ -389,7 +391,7 @@ private: uint8 _outroShapeTable[256]; // TODO: Consider moving these tables to kyra.dat - static const char * const _outroShapeFileTable[]; + static const char *const _outroShapeFileTable[]; static const uint8 _outroFrameTable[]; static const int16 _outroRightMonsterPos[]; @@ -400,6 +402,10 @@ private: static const int _outroMonsterScaleTableX[]; static const int _outroMonsterScaleTableY[]; + // Non-interactive demo + int playDemo(); + void pauseDemoPlayer(bool toggle); + // timers void setupTimers(); @@ -464,8 +470,6 @@ private: const uint8 *_ingamePCSpeakerSoundIndex; int _ingamePCSpeakerSoundIndexSize; - AudioDataStruct _soundData[3]; - // gui void gui_drawPlayField(); void gui_drawScene(int pageNum); @@ -554,14 +558,14 @@ private: int clickedStatusIcon(Button *button); const LoLButtonDef *_buttonData; - const int16 *_buttonList1; - const int16 *_buttonList2; - const int16 *_buttonList3; - const int16 *_buttonList4; - const int16 *_buttonList5; - const int16 *_buttonList6; - const int16 *_buttonList7; - const int16 *_buttonList8; + const uint8 *_buttonList1; + const uint8 *_buttonList2; + const uint8 *_buttonList3; + const uint8 *_buttonList4; + const uint8 *_buttonList5; + const uint8 *_buttonList6; + const uint8 *_buttonList7; + const uint8 *_buttonList8; // text int characterSays(int track, int charId, bool redraw); @@ -810,7 +814,7 @@ private: void decodeSjis(const char *src, char *dst); int decodeCyrillic(const char *src, char *dst); - static const char * const _languageExt[]; + static const char *const _languageExt[]; // graphics void setupScreenDims(); @@ -1009,8 +1013,8 @@ private: uint8 *_tempBuffer5120; - const char * const *_levelDatList; - const char * const *_levelShpList; + const char *const *_levelDatList; + const char *const *_levelShpList; const int8 *_dscWalls; @@ -1133,7 +1137,11 @@ private: uint16 _monsterCurBlock; int _objectLastDirection; - const uint16 *_monsterModifiers; + const uint16 *_monsterModifiers1; + const uint16 *_monsterModifiers2; + const uint16 *_monsterModifiers3; + const uint16 *_monsterModifiers4; + const int8 *_monsterShiftOffs; const uint8 *_monsterDirFlags; const uint8 *_monsterScaleX; diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index 985286854b..2180c5359d 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -60,7 +60,7 @@ void EoBCoreEngine::useMagicBookOrSymbol(int charIndex, int type) { } if (!_updateFlags) - _screen->copyRegion(64, 121, 0, 0, 112, 56, 0, _useHiResDithering ? 4 : 10, Screen::CR_NO_P_CHECK); + _screen->copyRegion(64, 121, 0, 0, 112, 56, 0, 10, Screen::CR_NO_P_CHECK); _updateFlags = 1; gui_setPlayFieldButtons(); gui_drawSpellbook(); @@ -179,7 +179,7 @@ void EoBCoreEngine::castSpell(int spell, int weaponSlot) { if ((s->flags & 0x100) && (c->effectFlags & 0x40)) // remove invisibility effect - removeCharacterEffect(10, _openBookChar, 1); + removeCharacterEffect(_flags.gameID == GI_EOB1 ? 8 : 10, _openBookChar, 1); int ci = _openBookChar; if (ci > 3) @@ -308,7 +308,7 @@ void EoBCoreEngine::startSpell(int spell) { EoBCharacter *c = &_characters[_activeSpellCharId]; snd_playSoundEffect(s->sound); - if (s->flags & 0xa0) + if (s->flags & 0xA0) sparkEffectDefensive(_activeSpellCharId); else if (s->flags & 0x40) sparkEffectDefensive(-1); @@ -623,7 +623,7 @@ bool EoBCoreEngine::turnUndeadHit(EoBMonsterInPlay *m, int hitChance, int caster assert(_monsterProps[m->type].tuResist > 0); uint8 e = _turnUndeadEffect[_monsterProps[m->type].tuResist * 14 + MIN(casterLevel, 14)]; - if (e == 0xff) { + if (e == 0xFF) { calcAndInflictMonsterDamage(m, 0, 0, 500, 0x200, 5, 3); } else if (hitChance < e) { return false; @@ -711,7 +711,7 @@ Item EoBCoreEngine::createMagicWeaponItem(int flags, int icon, int value, int ty void EoBCoreEngine::removeMagicWeaponItem(Item item) { _itemTypes[_items[item].type].armorClass = -30; _items[item].block = -2; - _items[item].level = 0xff; + _items[item].level = 0xFF; } void EoBCoreEngine::updateWallOfForceTimers() { @@ -841,7 +841,7 @@ bool EoBCoreEngine::spellCallback_end_magicMissile(void *obj) { } void EoBCoreEngine::spellCallback_start_shockingGrasp() { - int t = createMagicWeaponType(0, 0, 0, 0x0f, 1, 8, getMageLevel(_openBookChar), 1); + int t = createMagicWeaponType(0, 0, 0, 0x0F, 1, 8, getMageLevel(_openBookChar), 1); Item i = (t != -1) ? createMagicWeaponItem(0x10, 82, 0, t) : -1; if (t == -1 || i == -1) { if (_flags.gameID == GI_EOB2) @@ -948,7 +948,7 @@ bool EoBCoreEngine::spellCallback_end_lightningBolt(void *obj) { } void EoBCoreEngine::spellCallback_start_vampiricTouch() { - int t = createMagicWeaponType(0, 0, 0, 0x0f, getMageLevel(_openBookChar) >> 1, 6, 0, 1); + int t = createMagicWeaponType(0, 0, 0, 0x0F, getMageLevel(_openBookChar) >> 1, 6, 0, 1); Item i = (t != -1) ? createMagicWeaponItem(0x18, 83, 0, t) : -1; if (t == -1 || i == -1) { if (_flags.gameID == GI_EOB2) @@ -989,7 +989,7 @@ bool EoBCoreEngine::spellCallback_end_iceStorm(void *obj) { if (res) { for (int i = 0; i < 4; i++) { uint16 bl = fo->curBlock; - fo->curBlock = (fo->curBlock + blockAdv[i]) & 0x3ff; + fo->curBlock = (fo->curBlock + blockAdv[i]) & 0x3FF; magicObjectDamageHit(fo, 1, 6, 0, getMageLevel(fo->attackerId)); fo->curBlock = bl; } @@ -1027,7 +1027,7 @@ void EoBCoreEngine::spellCallback_start_coneOfCold() { _preventMonsterFlash = true; for (int i = 0; i < 7; i++) { - for (const int16 *m = findBlockMonsters((_currentBlock + tbl[i]) & 0x3ff, 4, _currentDirection, 1, 1); *m != -1; m++) + for (const int16 *m = findBlockMonsters((_currentBlock + tbl[i]) & 0x3FF, 4, _currentDirection, 1, 1); *m != -1; m++) calcAndInflictMonsterDamage(&_monsters[*m], cl, 4, cl, 0x41, 5, 0); } @@ -1054,7 +1054,7 @@ void EoBCoreEngine::spellCallback_start_wallOfForce() { return; } - uint32 dur = 0xffffffff; + uint32 dur = 0xFFFFFFFF; int s = 0; int i = 0; @@ -1158,7 +1158,7 @@ bool EoBCoreEngine::spellCallback_end_aid(void *obj) { } void EoBCoreEngine::spellCallback_start_flameBlade() { - int t = createMagicWeaponType(0, 0, 0, 0x0f, 1, 4, 4, 1); + int t = createMagicWeaponType(0, 0, 0, 0x0F, 1, 4, 4, 1); Item i = (t != -1) ? createMagicWeaponItem(0, 84, 0, t) : -1; if (t == -1 || i == -1) { if (_flags.gameID == GI_EOB2) diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index f2bc4e8146..5c179a7864 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -62,7 +62,7 @@ public: bool isInCacheList(Common::String name); bool loadFileList(const Common::String &filedata); - bool loadFileList(const char * const *filelist, uint32 numFiles); + bool loadFileList(const char *const *filelist, uint32 numFiles); // This unloads *all* pakfiles, even kyra.dat and protected ones. // It does not remove files from cache though! @@ -87,7 +87,7 @@ protected: Common::Archive *loadArchive(const Common::String &name, Common::ArchiveMemberPtr member); Common::Archive *loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset); - bool loadProtectedFiles(const char * const * list); + bool loadProtectedFiles(const char *const * list); void initializeLoaders(); @@ -679,7 +679,10 @@ enum KyraResources { kLoLCharDefsKieran, kLoLCharDefsAkshel, kLoLExpRequirements, - kLoLMonsterModifiers, + kLoLMonsterModifiers1, + kLoLMonsterModifiers2, + kLoLMonsterModifiers3, + kLoLMonsterModifiers4, kLoLMonsterShiftOffsets, kLoLMonsterDirFlags, kLoLMonsterScaleY, @@ -742,6 +745,8 @@ enum KyraResources { struct Shape; struct Room; struct AmigaSfxTable; +struct HoFSeqData; +struct HoFSeqItemAnimData; class StaticResource { public: @@ -755,13 +760,13 @@ public: bool init(); void deinit(); - const char * const *loadStrings(int id, int &strings); + const char *const *loadStrings(int id, int &strings); const uint8 *loadRawData(int id, int &size); const Shape *loadShapeTable(int id, int &entries); const AmigaSfxTable *loadAmigaSfxTable(int id, int &entries); const Room *loadRoomTable(int id, int &entries); - const HofSeqData *loadHofSequenceData(int id, int &entries); - const ItemAnimData_v1 *loadShapeAnimData_v1(int id, int &entries); + const HoFSeqData *loadHoFSequenceData(int id, int &entries); + const HoFSeqItemAnimData *loadHoFSeqItemAnimData(int id, int &entries); const ItemAnimDefinition *loadItemAnimDefinition(int id, int &entries); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) const uint16 *loadRawDataBe16(int id, int &entries); @@ -803,8 +808,8 @@ private: bool loadShapeTable(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadAmigaSfxTable(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadRoomTable(Common::SeekableReadStream &stream, void *&ptr, int &size); - bool loadHofSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size); - bool loadShapeAnimData_v1(Common::SeekableReadStream &stream, void *&ptr, int &size); + bool loadHoFSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size); + bool loadHoFSeqItemAnimData(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadItemAnimDefinition(Common::SeekableReadStream &stream, void *&ptr, int &size); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) bool loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size); @@ -829,8 +834,8 @@ private: void freeShapeTable(void *&ptr, int &size); void freeAmigaSfxTable(void *&ptr, int &size); void freeRoomTable(void *&ptr, int &size); - void freeHofSequenceData(void *&ptr, int &size); - void freeHofShapeAnimDataV1(void *&ptr, int &size); + void freeHoFSequenceData(void *&ptr, int &size); + void freeHoFSeqItemAnimData(void *&ptr, int &size); void freeItemAnimDefinition(void *&ptr, int &size); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) void freeRawDataBe16(void *&ptr, int &size); @@ -857,7 +862,7 @@ private: kAmigaSfxTable = 4, k2SeqData = 5, - k2ShpAnimDataV1 = 6, + k2SeqItemAnimData = 6, k2ItemAnimDefinition = 7, kLoLCharData = 8, diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index 6f7591ccf1..4c413487ff 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -496,7 +496,7 @@ public: void advSrcBitsBy1(); void advSrcBitsByIndex(uint8 newIndex); - uint8 getKeyLower() const { return _key & 0xff; } + uint8 getKeyLower() const { return _key & 0xFF; } void setIndex(uint8 index) { _index = index; } uint16 getKeyMasked(uint8 newIndex); uint16 keyMaskedAlign(uint16 val); @@ -515,7 +515,7 @@ void FileExpanderSource::advSrcBitsBy1() { _key >>= 1; if (!--_bitsLeft) { if (_dataPtr < _endofBuffer) - _key = ((*_dataPtr++) << 8) | (_key & 0xff); + _key = ((*_dataPtr++) << 8) | (_key & 0xFF); _bitsLeft = 8; } } @@ -528,7 +528,7 @@ void FileExpanderSource::advSrcBitsByIndex(uint8 newIndex) { _index = -_bitsLeft; _bitsLeft = 8 - _index; if (_dataPtr < _endofBuffer) - _key = (*_dataPtr++ << 8) | (_key & 0xff); + _key = (*_dataPtr++ << 8) | (_key & 0xFF); } _key >>= _index; } @@ -540,13 +540,13 @@ uint16 FileExpanderSource::getKeyMasked(uint8 newIndex) { if (_index > 8) { newIndex = _index - 8; - res = (_key & 0xff) & mskTable[8]; + res = (_key & 0xFF) & mskTable[8]; advSrcBitsByIndex(8); _index = newIndex; - res |= (((_key & 0xff) & mskTable[_index]) << 8); + res |= (((_key & 0xFF) & mskTable[_index]) << 8); advSrcBitsByIndex(_index); } else { - res = (_key & 0xff) & mskTable[_index]; + res = (_key & 0xFF) & mskTable[_index]; advSrcBitsByIndex(_index); } @@ -568,10 +568,10 @@ void FileExpanderSource::copyBytes(uint8 *& dst) { uint16 FileExpanderSource::keyMaskedAlign(uint16 val) { val -= 0x101; - _index = (val & 0xff) >> 2; + _index = (val & 0xFF) >> 2; int16 b = ((_bitsLeft << 8) | _index) - 1; _bitsLeft = b >> 8; - _index = b & 0xff; + _index = b & 0xFF; uint16 res = (((val & 3) + 4) << _index) + 0x101; return res + getKeyMasked(_index); } @@ -727,20 +727,20 @@ bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 cmd = ((int16 *)_tables[2])[_src->getKeyLower()]; _src->advSrcBitsByIndex(cmd < 0 ? calcCmdAndIndex(_tables[3], cmd) : _tables[0][cmd]); - if (cmd == 0x11d) { + if (cmd == 0x11D) { cmd = 0x200; } else if (cmd > 0x108) { cmd = _src->keyMaskedAlign(cmd); } if (!(cmd >> 8)) { - *d++ = cmd & 0xff; + *d++ = cmd & 0xFF; } else if (cmd != 0x100) { - cmd -= 0xfe; + cmd -= 0xFE; int16 offset = ((int16 *)_tables[4])[_src->getKeyLower()]; _src->advSrcBitsByIndex(offset < 0 ? calcCmdAndIndex(_tables[5], offset) : _tables[1][offset]); - if ((offset & 0xff) >= 4) { - uint8 newIndex = ((offset & 0xff) >> 1) - 1; + if ((offset & 0xFF) >= 4) { + uint8 newIndex = ((offset & 0xFF) >> 1) - 1; offset = (((offset & 1) + 2) << newIndex); offset += _src->getKeyMasked(newIndex); } @@ -775,7 +775,7 @@ bool FileExpander::process(uint8 *dst, const uint8 *src, uint32 outsize, uint32 void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex2, int cnt) { uint8 *tbl1 = _tables[srcIndex]; uint8 *tbl2 = _tables[dstIndex]; - uint8 *tbl3 = dstIndex2 == 0xff ? 0 : _tables[dstIndex2]; + uint8 *tbl3 = dstIndex2 == 0xFF ? 0 : _tables[dstIndex2]; if (!cnt) return; @@ -859,7 +859,7 @@ void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex do { s2[o] = cnt; o += inc; - } while (!(o & 0xf00)); + } while (!(o & 0xF00)); } else if (t > 8) { if (!bt) @@ -868,7 +868,7 @@ void FileExpander::generateTables(uint8 srcIndex, uint8 dstIndex, uint8 dstIndex t -= 8; uint8 shiftCnt = 1; uint8 v = (*d) >> 8; - s2 = &((uint16 *)tbl2)[*d & 0xff]; + s2 = &((uint16 *)tbl2)[*d & 0xFF]; do { if (!*s2) { @@ -897,7 +897,7 @@ uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 ¶) { do { newIndex++; - para = t[((~para) & 0xfffe) | (v & 1)]; + para = t[((~para) & 0xFFFE) | (v & 1)]; v >>= 1; } while (para < 0); @@ -1020,7 +1020,7 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi pos = 0; - const uint32 kExecSize = 0x0bba; + const uint32 kExecSize = 0x0BBA; const uint32 kHeaderSize = 30; const uint32 kHeaderSize2 = 46; diff --git a/engines/kyra/resource_intern.h b/engines/kyra/resource_intern.h index 9d9574d823..e63eab7d6a 100644 --- a/engines/kyra/resource_intern.h +++ b/engines/kyra/resource_intern.h @@ -75,7 +75,7 @@ private: const uint32 *findFile(const Common::String &name) const; const uint16 _entryCount; - const uint32 * const _fileEntries; + const uint32 *const _fileEntries; }; class CachedArchive : public Common::Archive { diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index 41ba1e5e50..bacfb62c16 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -37,7 +37,7 @@ namespace Kyra { -KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) { +KyraEngine_v1::ReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) { uint32 type = in->readUint32BE(); header.originalSave = false; header.oldHeader = false; @@ -140,7 +140,7 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena if (!(in = _saveFileMan->openForLoading(filename))) return 0; - kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header); + ReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header); if (errorCode != kRSHENoError) { if (errorCode == kRSHEInvalidType) warning("No ScummVM Kyra engine savefile header"); diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp index f7d7d95b57..e4f53a852d 100644 --- a/engines/kyra/saveload_eob.cpp +++ b/engines/kyra/saveload_eob.cpp @@ -298,7 +298,7 @@ Common::Error EoBCoreEngine::loadGameState(int slot) { useMagicBookOrSymbol(_openBookChar, _openBookType); } - _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, _useHiResDithering ? 1 : 12, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); gui_toggleButtons(); setHandItem(_itemInHand); @@ -453,7 +453,7 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName, out->write(l->wallsXorData, 4096); for (int ii = 0; ii < 1024; ii++) - out->writeByte(l->flags[ii] & 0xff); + out->writeByte(l->flags[ii] & 0xFF); EoBMonsterInPlay *lm = (EoBMonsterInPlay *)_lvlTempData[i]->monsters; EoBFlyingObject *lf = (EoBFlyingObject *)_lvlTempData[i]->flyingObjects; @@ -680,7 +680,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) { in.skip(4); delete[] c->faceShape; c->faceShape = 0; - in.read(c->mageSpells, (_flags.gameID == GI_EOB1) ? 30 :80); + in.read(c->mageSpells, (_flags.gameID == GI_EOB1) ? 30 : 80); in.read(c->clericSpells, (_flags.gameID == GI_EOB1) ? 30 : 80); c->mageSpellsAvailableFlags = in.readUint32(); for (int ii = 0; ii < 27; ii++) diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index b76d1da52a..f8cca1ab7b 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -150,7 +150,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { // it wasn't made sure that _curSfxFile was initialized // so if it's out of bounds we just set it to 0. if (_flags.platform == Common::kPlatformFMTowns) { - if (_curSfxFile >= _soundData->fileListLen || _curSfxFile < 0) + if (!_sound->hasSoundFile(_curSfxFile)) _curSfxFile = 0; _sound->loadSoundFile(_curSfxFile); } diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp index b6840663e9..6c83ebd51b 100644 --- a/engines/kyra/saveload_lol.cpp +++ b/engines/kyra/saveload_lol.cpp @@ -41,7 +41,7 @@ Common::Error LoLEngine::loadGameState(int slot) { SaveHeader header; Common::InSaveFile *saveFile = openSaveForReading(fileName, header); if (!saveFile) { - _txt->printMessage(2, "%s", getLangString(0x425d)); + _txt->printMessage(2, "%s", getLangString(0x425D)); return Common::kNoError; } @@ -437,7 +437,7 @@ Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, con out->write(l->wallsXorData, 4096); for (int ii = 0; ii < 1024; ii++) - out->writeByte(l->flags[ii] & 0xff); + out->writeByte(l->flags[ii] & 0xFF); LoLMonster *lm = (LoLMonster *)_lvlTempData[i]->monsters; FlyingObject *lf = (FlyingObject *)_lvlTempData[i]->flyingObjects; @@ -547,7 +547,7 @@ void LoLEngine::restoreTempDataAdjustMonsterStrength(int index) { if (_lvlTempData[index]->monsterDifficulty == _monsterDifficulty) return; - uint16 d = (_monsterModifiers[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers[_monsterDifficulty]; + uint16 d = (_monsterModifiers1[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers1[_monsterDifficulty]; for (int i = 0; i < 30; i++) { if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0) diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp index 3db055db90..84cf4a3809 100644 --- a/engines/kyra/scene_eob.cpp +++ b/engines/kyra/scene_eob.cpp @@ -100,7 +100,7 @@ void EoBCoreEngine::loadLevel(int level, int sub) { void EoBCoreEngine::readLevelFileData(int level) { Common::String file; Common::SeekableReadStream *s = 0; - static const char *suffix[] = { "INF", "DRO", "ELO", 0 }; + static const char *const suffix[] = { "INF", "DRO", "ELO", 0 }; for (const char *const *sf = suffix; *sf && !s; sf++) { file = Common::String::format("LEVEL%d.%s", level, *sf); @@ -144,10 +144,10 @@ Common::String EoBCoreEngine::initLevelData(int sub) { const char *vmpPattern = (_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.EMP" : "%s.VMP"; Common::SeekableReadStream *s = _res->createReadStream(Common::String::format(vmpPattern, (const char *)pos)); - _vmpSize = s->readUint16LE(); + uint16 size = s->readUint16LE(); delete[] _vmpPtr; - _vmpPtr = new uint16[_vmpSize]; - for (int i = 0; i < _vmpSize; i++) + _vmpPtr = new uint16[size]; + for (int i = 0; i < size; i++) _vmpPtr[i] = s->readUint16LE(); delete s; @@ -157,7 +157,7 @@ Common::String EoBCoreEngine::initLevelData(int sub) { _curGfxFile = (const char *)pos; pos += slen; - if (*pos++ != 0xff && _flags.gameID == GI_EOB2) { + if (*pos++ != 0xFF && _flags.gameID == GI_EOB2) { tmpStr = Common::String::format(paletteFilePattern, (const char *)pos); pos += 13; } @@ -174,7 +174,7 @@ Common::String EoBCoreEngine::initLevelData(int sub) { if (_configRenderMode != Common::kRenderCGA) { Palette backupPal(256); backupPal.copy(_screen->getPalette(0), 224, 32, 224); - _screen->getPalette(0).fill(224, 32, 0x3f); + _screen->getPalette(0).fill(224, 32, 0x3F); uint8 *src = _screen->getPalette(0).getData(); _screen->createFadeTable(src, _screen->getFadeTable(0), 4, 75); // green @@ -271,7 +271,7 @@ void EoBCoreEngine::addLevelItems() { for (int i = 0; i < 600; i++) { if (_items[i].level != _currentLevel || _items[i].block <= 0) continue; - setItemPosition((Item *)&_levelBlockProperties[_items[i].block & 0x3ff].drawObjects, _items[i].block, i, _items[i].pos); + setItemPosition((Item *)&_levelBlockProperties[_items[i].block & 0x3FF].drawObjects, _items[i].block, i, _items[i].pos); } } @@ -283,7 +283,7 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) { _screen->loadBitmap(Common::String::format(filePattern, _lastBlockDataFile).c_str(), 3, 3, 0); const uint8 *pos = _screen->getCPagePtr(3); - uint32 vcnSize = READ_LE_UINT16(pos) * _vcnBlockWidth * _vcnBlockHeight; + uint32 vcnSize = READ_LE_UINT16(pos) << 5; pos += 2; const uint8 *colMap = pos; @@ -292,78 +292,28 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) { delete[] _vcnBlocks; _vcnBlocks = new uint8[vcnSize]; - if (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA) { - const uint8 *egaTable = _screen->getEGADitheringTable(); - assert(_vmpPtr); - assert(egaTable); - - delete[] _vcnTransitionMask; - _vcnTransitionMask = new uint8[vcnSize]; - - for (int i = 0; i < _vmpSize; i++) { - uint16 vcnOffs = _vmpPtr[i] & 0x3FFF; - const uint8 *src = &pos[vcnOffs << 5]; - uint8 *dst1 = &_vcnBlocks[vcnOffs << 7]; - uint8 *dst3 = &_vcnTransitionMask[vcnOffs << 7]; - int palOffset = (i < 330) ? 0 : _wllVcnOffset; - - for (int y = 0; y < 8; y++) { - uint8 *dst2 = dst1 + 8; - uint8 *dst4 = dst3 + 8; - - for (int x = 0; x < 4; x++) { - uint8 in = *src++; - - dst1[0] = dst2[0] = egaTable[colMap[(in >> 4) + palOffset]]; - dst1[1] = dst2[1] = egaTable[colMap[(in & 0x0f) + palOffset]]; - dst3[0] = dst4[0] = (in & 0xf0) ? 0 : 0xff; - dst3[1] = dst4[1] = (in & 0x0f) ? 0 : 0xff; - - dst1 += 2; - dst2 += 2; - dst3 += 2; - dst4 += 2; - } - - dst1 += 8; - dst3 += 8; - } - } - } else if (_configRenderMode == Common::kRenderCGA) { + if (_configRenderMode == Common::kRenderCGA) { uint8 *tmp = _screen->encodeShape(0, 0, 1, 8, false, cgaMapping); delete[] tmp; delete[] _vcnTransitionMask; _vcnTransitionMask = new uint8[vcnSize]; - uint8 tblSwitch = 0; + uint8 tblSwitch = 1; uint8 *dst = _vcnBlocks; uint8 *dst2 = _vcnTransitionMask; while (dst < _vcnBlocks + vcnSize) { const uint16 *table = _screen->getCGADitheringTable((tblSwitch++) & 1); for (int ii = 0; ii < 2; ii++) { - *dst++ = ((table[pos[0]] & 0x000f) << 4) | ((table[pos[0]] & 0x0f00) >> 8); - *dst++= ((table[pos[1]] & 0x000f) << 4) | ((table[pos[1]] & 0x0f00) >> 8); - - uint8 msk = 0; - if (pos[0] & 0xf0) - msk |= 0x30; - if (pos[0] & 0x0f) - msk |= 0x03; - *dst2++ = msk ^ 0x33; - - msk = 0; - if (pos[1] & 0xf0) - msk |= 0x30; - if (pos[1] & 0x0f) - msk |= 0x03; - *dst2++ = msk ^ 0x33; - + *dst++ = (table[pos[0]] & 0x000F) | ((table[pos[0]] & 0x0F00) >> 4); + *dst++ = (table[pos[1]] & 0x000F) | ((table[pos[1]] & 0x0F00) >> 4); + *dst2++ = ((pos[0] & 0xF0 ? 0x30 : 0) | (pos[0] & 0x0F ? 0x03 : 0)) ^ 0x33; + *dst2++ = ((pos[1] & 0xF0 ? 0x30 : 0) | (pos[1] & 0x0F ? 0x03 : 0)) ^ 0x33; pos += 2; } } } else { - if (_configRenderMode != Common::kRenderEGA) + if (!(_flags.gameID == GI_EOB1 && _configRenderMode == Common::kRenderEGA)) memcpy(_vcnColTable, colMap, 32); memcpy(_vcnBlocks, pos, vcnSize); } @@ -429,8 +379,8 @@ void EoBCoreEngine::loadDecorations(const char *cpsFile, const char *decFile) { LevelDecorationProperty *l = &_levelDecorationData[i]; for (int ii = 0; ii < 10; ii++) { l->shapeIndex[ii] = s->readByte(); - if (l->shapeIndex[ii] == 0xff) - l->shapeIndex[ii] = 0xffff; + if (l->shapeIndex[ii] == 0xFF) + l->shapeIndex[ii] = 0xFFFF; } l->next = s->readByte(); l->flags = s->readByte(); @@ -477,7 +427,7 @@ void EoBCoreEngine::assignWallsAndDecorations(int wallIndex, int vmpIndex, int d for (int i = 0; i < 10; i++) { uint16 t = _levelDecorationProperties[_mappedDecorationsCount].shapeIndex[i]; - if (t == 0xffff) + if (t == 0xFFFF) continue; if (_levelDecorationShapes[t]) @@ -529,7 +479,7 @@ void EoBCoreEngine::toggleWallState(int wall, int toggle) { if (toggle) _wllWallFlags[wall + i] |= 2; else - _wllWallFlags[wall + i] &= 0xfd; + _wllWallFlags[wall + i] &= 0xFD; } } @@ -643,7 +593,7 @@ void EoBCoreEngine::drawDecorations(int index) { if ((i == 0) && (flg & 1 || ((flg & 2) && _wllProcessFlag))) ix = -ix; - if (_levelDecorationProperties[l].shapeIndex[shpIx] == 0xffff) { + if (_levelDecorationProperties[l].shapeIndex[shpIx] == 0xFFFF) { l = _levelDecorationProperties[l].next; continue; } @@ -758,7 +708,7 @@ int EoBCoreEngine::clickedNiche(uint16 block, uint16 direction) { if (_dscItemShapeMap[_items[_itemInHand].icon] <= 14) { _txt->printMessage(_pryDoorStrings[5]); } else { - setItemPosition((Item *)&_levelBlockProperties[block & 0x3ff].drawObjects, block, _itemInHand, 8); + setItemPosition((Item *)&_levelBlockProperties[block & 0x3FF].drawObjects, block, _itemInHand, 8); runLevelScript(block, 4); setHandItem(0); _sceneUpdateRequired = true; @@ -781,7 +731,7 @@ int EoBCoreEngine::clickedDoorPry(uint16 block, uint16 direction) { int d = -1; for (int i = 0; i < 6; i++) { - if (!testCharacter(i, 0x0d)) + if (!testCharacter(i, 0x0D)) continue; if (d >= 0) { int s1 = _characters[i].strengthCur + _characters[i].strengthExtCur; @@ -826,7 +776,7 @@ int EoBCoreEngine::clickedDoorNoPry(uint16 block, uint16 direction) { int EoBCoreEngine::specialWallAction(int block, int direction) { direction ^= 2; uint8 type = _specialWallTypes[_levelBlockProperties[block].walls[direction]]; - if (!type || !(_clickedSpecialFlag & (((_levelBlockProperties[block].flags & 0xf8) >> 3) | 0xe0))) + if (!type || !(_clickedSpecialFlag & (((_levelBlockProperties[block].flags & 0xF8) >> 3) | 0xE0))) return 0; int res = 0; diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 628654f127..f1045d2ddf 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -193,7 +193,7 @@ int LoLEngine::assignLevelDecorationShapes(int index) { for (int i = 0; i < 10; i++) { uint16 t = _levelDecorationProperties[o].shapeIndex[i]; - if (t == 0xffff) + if (t == 0xFFFF) continue; uint16 pv = p1[t]; @@ -254,7 +254,7 @@ void LoLEngine::loadBlockProperties(const char *cmzFile) { _levelBlockProperties[i].direction = 5; if (_wllAutomapData[_levelBlockProperties[i].walls[0]] == 17) { - _levelBlockProperties[i].flags &= 0xef; + _levelBlockProperties[i].flags &= 0xEF; _levelBlockProperties[i].flags |= 0x20; } } @@ -315,9 +315,9 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight if (_lastSpecialColor == 1) _lastSpecialColor = 0x44; else if (_lastSpecialColor == 0x66) - _lastSpecialColor = scumm_stricmp(file, "YVEL2") ? 0xcc : 0x44; - else if (_lastSpecialColor == 0x6b) - _lastSpecialColor = 0xcc; + _lastSpecialColor = scumm_stricmp(file, "YVEL2") ? 0xCC : 0x44; + else if (_lastSpecialColor == 0x6B) + _lastSpecialColor = 0xCC; else _lastSpecialColor = 0x44; } @@ -431,17 +431,17 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight } for (int ii = l; ii < 256; ii++) - levelOverlay[ii] = ii & 0xff; + levelOverlay[ii] = ii & 0xFF; } uint8 *levelOverlay = _screen->getLevelOverlay(7); for (int i = 0; i < 256; i++) - levelOverlay[i] = i & 0xff; + levelOverlay[i] = i & 0xFF; if (_flags.use16ColorMode) { - _screen->getLevelOverlay(6)[0xee] = 0xee; + _screen->getLevelOverlay(6)[0xEE] = 0xEE; if (_lastSpecialColor == 0x44) - _screen->getLevelOverlay(5)[0xee] = 0xee; + _screen->getLevelOverlay(5)[0xEE] = 0xEE; for (int i = 0; i < 7; i++) memcpy(_screen->getLevelOverlay(i), _screen->getLevelOverlay(i + 1), 256); @@ -505,14 +505,14 @@ void LoLEngine::resetBlockProperties() { for (int i = 0; i < 1024; i++) { LevelBlockProperty *l = &_levelBlockProperties[i]; if (l->flags & 0x10) { - l->flags &= 0xef; + l->flags &= 0xEF; if (testWallInvisibility(i, 0) && testWallInvisibility(i, 1)) l->flags |= 0x40; } else { if (l->flags & 0x40) - l->flags &= 0xbf; + l->flags &= 0xBF; else if (l->flags & 0x80) - l->flags &= 0x7f; + l->flags &= 0x7F; } } } @@ -574,7 +574,7 @@ void LoLEngine::updateLampStatus() { setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect); _lampStatusTimer = _system->getMillis() + (10 + rollDice(1, 30)) * _tickLength; } else { - if ((_lampEffect & 0xfe) == (newLampEffect & 0xfe)) { + if ((_lampEffect & 0xFE) == (newLampEffect & 0xFE)) { if (_system->getMillis() <= _lampStatusTimer) { newLampEffect = _lampEffect; } else { @@ -702,7 +702,7 @@ void LoLEngine::moveParty(uint16 direction, int unk1, int unk2, int buttonShape) runLevelScript(opos, 8); runLevelScript(npos, 2); - if (_levelBlockProperties[npos].walls[0] == 0x1a) + if (_levelBlockProperties[npos].walls[0] == 0x1A) memset(_levelBlockProperties[npos].walls, 0, 4); } } @@ -711,12 +711,12 @@ void LoLEngine::moveParty(uint16 direction, int unk1, int unk2, int buttonShape) } uint16 LoLEngine::calcBlockIndex(uint16 x, uint16 y) { - return (((y & 0xff00) >> 3) | (x >> 8)) & 0x3ff; + return (((y & 0xFF00) >> 3) | (x >> 8)) & 0x3FF; } void LoLEngine::calcCoordinates(uint16 &x, uint16 &y, int block, uint16 xOffs, uint16 yOffs) { - x = (block & 0x1f) << 8 | xOffs; - y = ((block & 0xffe0) << 3) | yOffs; + x = (block & 0x1F) << 8 | xOffs; + y = ((block & 0xFFE0) << 3) | yOffs; } void LoLEngine::calcCoordinatesForSingleCharacter(int charNum, uint16 &x, uint16 &y) { @@ -732,8 +732,8 @@ void LoLEngine::calcCoordinatesForSingleCharacter(int charNum, uint16 &x, uint16 calcCoordinatesAddDirectionOffset(x, y, _currentDirection); - x |= (_partyPosX & 0xff00); - y |= (_partyPosY & 0xff00); + x |= (_partyPosX & 0xFF00); + y |= (_partyPosY & 0xFF00); } void LoLEngine::calcCoordinatesAddDirectionOffset(uint16 &x, uint16 &y, int direction) { @@ -777,7 +777,7 @@ void LoLEngine::notifyBlockNotPassable(int scrollFlag) { movePartySmoothScrollBlocked(2); snd_stopSpeech(true); - _txt->printMessage(0x8002, "%s", getLangString(0x403f)); + _txt->printMessage(0x8002, "%s", getLangString(0x403F)); snd_playSoundEffect(19, -1); } @@ -804,7 +804,7 @@ int LoLEngine::clickedNiche(uint16 block, uint16 direction) { return 0; uint16 x = 0x80; - uint16 y = 0xff; + uint16 y = 0xFF; calcCoordinatesAddDirectionOffset(x, y, _currentDirection); calcCoordinates(x, y, block, x, y); setItemPosition(_itemInHand, x, y, 8, 1); @@ -1180,14 +1180,14 @@ void LoLEngine::processGasExplosion(int soundId) { memcpy(p2, p1, 768); for (int i = 1; i < 128; i++) - p2[i * 3] = 0x3f; + p2[i * 3] = 0x3F; uint32 ctime = _system->getMillis(); - while (_screen->fadePaletteStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10)) + while (_screen->timedPaletteFadeStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10)) updateInput(); ctime = _system->getMillis(); - while (_screen->fadePaletteStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50)) + while (_screen->timedPaletteFadeStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50)) updateInput(); } @@ -1244,10 +1244,10 @@ void LoLEngine::setWallType(int block, int wall, int val) { for (int i = 0; i < 4; i++) _levelBlockProperties[block].walls[i] = val; if (_wllAutomapData[val] == 17) { - _levelBlockProperties[block].flags &= 0xef; + _levelBlockProperties[block].flags &= 0xEF; _levelBlockProperties[block].flags |= 0x20; } else { - _levelBlockProperties[block].flags &= 0xdf; + _levelBlockProperties[block].flags &= 0xDF; } } else { _levelBlockProperties[block].walls[wall] = val; @@ -1491,7 +1491,7 @@ void LoLEngine::drawDecorations(int index) { ov = 0; } ovl = _screen->getLevelOverlay(ov); - } else if (_levelDecorationProperties[l].shapeIndex[shpIx] != 0xffff) { + } else if (_levelDecorationProperties[l].shapeIndex[shpIx] != 0xFFFF) { scaleW = scaleH = 0x100; int ov = 7; if (_flags.use16ColorMode) { @@ -1504,7 +1504,7 @@ void LoLEngine::drawDecorations(int index) { ovl = _screen->getLevelOverlay(ov); } - if (_levelDecorationProperties[l].shapeIndex[shpIx] != 0xffff) { + if (_levelDecorationProperties[l].shapeIndex[shpIx] != 0xFFFF) { shapeData = _levelDecorationShapes[_levelDecorationProperties[l].shapeIndex[shpIx]]; if (shapeData) { if (ix < 0) { @@ -1538,10 +1538,10 @@ void LoLEngine::drawDecorations(int index) { } void LoLEngine::drawBlockEffects(int index, int type) { - static const uint16 yOffs[] = { 0xff, 0xff, 0x80, 0x80 }; + static const uint16 yOffs[] = { 0xFF, 0xFF, 0x80, 0x80 }; uint8 flg = _visibleBlocks[index]->flags; // flags: 0x10 = ice wall, 0x20 = teleporter, 0x40 = blue slime spot, 0x80 = blood spot - if (!(flg & 0xf0)) + if (!(flg & 0xF0)) return; type = (type == 0) ? 2 : 0; @@ -1562,8 +1562,8 @@ void LoLEngine::drawBlockEffects(int index, int type) { calcCoordinatesAddDirectionOffset(x, y, _currentDirection); - x |= ((_visibleBlockIndex[index] & 0x1f) << 8); - y |= ((_visibleBlockIndex[index] & 0xffe0) << 3); + x |= ((_visibleBlockIndex[index] & 0x1F) << 8); + y |= ((_visibleBlockIndex[index] & 0xFFE0) << 3); drawItemOrMonster(_effectShapes[type], ovl, x, y, 0, (type == 1) ? -20 : 0, drawFlag, -1, false); } diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index d6df523f82..c9486d9c45 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -22,7 +22,7 @@ #include "kyra/kyra_mr.h" #include "kyra/screen_mr.h" -#include "kyra/sound.h" +#include "kyra/sound_digital.h" #include "kyra/resource.h" #include "common/system.h" diff --git a/engines/kyra/scene_rpg.cpp b/engines/kyra/scene_rpg.cpp index 3a694e05fe..6d724efed0 100644 --- a/engines/kyra/scene_rpg.cpp +++ b/engines/kyra/scene_rpg.cpp @@ -151,7 +151,7 @@ void KyraRpgEngine::generateBlockDrawingBuffer() { memset(_blockDrawingBuffer, 0, 660 * sizeof(uint16)); - _wllProcessFlag = ((_currentBlock >> 5) + (_currentBlock & 0x1f) + _currentDirection) & 1; + _wllProcessFlag = ((_currentBlock >> 5) + (_currentBlock & 0x1F) + _currentDirection) & 1; if (_wllProcessFlag) // floor and ceiling generateVmpTileDataFlipped(0, 15, 1, -330, 22, 15); @@ -318,7 +318,7 @@ bool KyraRpgEngine::hasWall(int index) { void KyraRpgEngine::assignVisibleBlocks(int block, int direction) { for (int i = 0; i < 18; i++) { - uint16 t = (block + _dscBlockIndex[direction * 18 + i]) & 0x3ff; + uint16 t = (block + _dscBlockIndex[direction * 18 + i]) & 0x3FF; _visibleBlockIndex[i] = t; _visibleBlocks[i] = &_levelBlockProperties[t]; @@ -348,9 +348,6 @@ bool KyraRpgEngine::checkSceneUpdateNeed(int block) { void KyraRpgEngine::drawVcnBlocks() { uint8 *d = _sceneWindowBuffer; uint16 *bdb = _blockDrawingBuffer; - uint16 pitch = 22 * _vcnBlockWidth * 2; - uint8 pxl[2]; - pxl[0] = pxl[1] = 0; for (int y = 0; y < 15; y++) { for (int x = 0; x < 22; x++) { @@ -369,96 +366,95 @@ void KyraRpgEngine::drawVcnBlocks() { if (vcnOffset & 0x4000) { horizontalFlip = true; - vcnOffset &= 0x3fff; + vcnOffset &= 0x3FFF; } uint8 *src = 0; if (vcnOffset) { - src = &_vcnBlocks[vcnOffset * _vcnBlockWidth * _vcnBlockHeight]; + src = &_vcnBlocks[vcnOffset << 5]; wllVcnOffset = _wllVcnOffset; } else { // floor/ceiling blocks vcnOffset = bdb[329]; if (vcnOffset & 0x4000) { horizontalFlip = true; - vcnOffset &= 0x3fff; + vcnOffset &= 0x3FFF; } - src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset * _vcnBlockWidth * _vcnBlockHeight); + src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset << 5); } uint8 shift = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness; if (horizontalFlip) { - for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { - src += (_vcnBlockWidth - 1); - for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) { + for (int blockY = 0; blockY < 8; blockY++) { + src += 3; + for (int blockX = 0; blockX < 4; blockX++) { uint8 bl = *src--; - d[_vcnFlip0] = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift]; - d[_vcnFlip1] = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; - d += 2; + *d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift]; + *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; } - src += (_vcnBlockWidth + 1); - d += (pitch - 2 * _vcnBlockWidth); + src += 5; + d += 168; } } else { - for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { - for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) { + for (int blockY = 0; blockY < 8; blockY++) { + for (int blockX = 0; blockX < 4; blockX++) { uint8 bl = *src++; *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; - *d++ = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift]; + *d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift]; } - d += (pitch - 2 * _vcnBlockWidth); + d += 168; } } - d -= (pitch * _vcnBlockHeight - 2 * _vcnBlockWidth); + d -= 1400; if (vcnExtraOffsetWll) { - d -= (2 * _vcnBlockWidth); + d -= 8; horizontalFlip = false; if (vcnExtraOffsetWll & 0x4000) { - vcnExtraOffsetWll &= 0x3fff; + vcnExtraOffsetWll &= 0x3FFF; horizontalFlip = true; } shift = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness; - src = &_vcnBlocks[vcnExtraOffsetWll * _vcnBlockWidth * _vcnBlockHeight]; - uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll * _vcnBlockWidth * _vcnBlockHeight] : 0; + src = &_vcnBlocks[vcnExtraOffsetWll << 5]; + uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll << 5] : 0; if (horizontalFlip) { - for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { - src += (_vcnBlockWidth - 1); - maskTable += (_vcnBlockWidth - 1); - for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) { + for (int blockY = 0; blockY < 8; blockY++) { + src += 3; + maskTable += 3; + for (int blockX = 0; blockX < 4; blockX++) { uint8 bl = *src--; uint8 mask = _vcnTransitionMask ? *maskTable-- : 0; - pxl[_vcnFlip0] = _vcnColTable[((bl & 0x0f) + wllVcnRmdOffset) | shift]; - pxl[_vcnFlip1] = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; + uint8 h = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift]; + uint8 l = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; if (_vcnTransitionMask) - *d = (*d & (mask & 0x0f)) | pxl[0]; - else if (pxl[0]) - *d = pxl[0]; + *d = (*d & (mask & 0x0F)) | h; + else if (h) + *d = h; d++; if (_vcnTransitionMask) - *d = (*d & (mask >> 4)) | pxl[1]; - else if (pxl[1]) - *d = pxl[1]; + *d = (*d & (mask >> 4)) | l; + else if (l) + *d = l; d++; } - src += (_vcnBlockWidth + 1); - maskTable += (_vcnBlockWidth + 1); - d += (pitch - 2 * _vcnBlockWidth); + src += 5; + maskTable += 5; + d += 168; } } else { - for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { - for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) { + for (int blockY = 0; blockY < 8; blockY++) { + for (int blockX = 0; blockX < 4; blockX++) { uint8 bl = *src++; uint8 mask = _vcnTransitionMask ? *maskTable++ : 0; uint8 h = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; - uint8 l = _vcnColTable[((bl & 0x0f) + wllVcnRmdOffset) | shift]; + uint8 l = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift]; if (_vcnTransitionMask) *d = (*d & (mask >> 4)) | h; @@ -467,18 +463,18 @@ void KyraRpgEngine::drawVcnBlocks() { d++; if (_vcnTransitionMask) - *d = (*d & (mask & 0x0f)) | l; + *d = (*d & (mask & 0x0F)) | l; else if (l) *d = l; d++; } - d += (pitch - 2 * _vcnBlockWidth); + d += 168; } } - d -= (pitch * _vcnBlockHeight - 2 * _vcnBlockWidth); + d -= 1400; } } - d += (pitch * (_vcnBlockHeight - 1)); + d += 1232; } screen()->copyBlockToPage(_sceneDrawPage1, _sceneXoffset, 0, 176, 120, _sceneWindowBuffer); @@ -486,7 +482,7 @@ void KyraRpgEngine::drawVcnBlocks() { uint16 KyraRpgEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) { static const int16 blockPosTable[] = { -32, 1, 32, -1 }; - return (curBlock + blockPosTable[direction]) & 0x3ff; + return (curBlock + blockPosTable[direction]) & 0x3FF; } int KyraRpgEngine::clickedWallShape(uint16 block, uint16 direction) { diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 04d805737f..419b630714 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -51,13 +51,12 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co memset(_fonts, 0, sizeof(_fonts)); memset(_pagePtrs, 0, sizeof(_pagePtrs)); - // Set scale factor to 1 (no scaling) for all pages - memset(_pageScaleFactor, 1, sizeof(_pageScaleFactor)); // In VGA mode the odd and even page pointers point to the same buffers. for (int i = 0; i < SCREEN_PAGE_NUM; i++) _pageMapping[i] = i & ~1; _renderMode = Common::kRenderDefault; + _sjisMixedFontMode = false; _currentFont = FID_8_FNT; _paletteChanged = true; @@ -114,7 +113,7 @@ bool Screen::init() { } // CGA and EGA modes use additional pages to do the CGA/EGA specific graphics conversions. - if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) { + if (_vm->game() == GI_EOB1 && (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA)) { for (int i = 0; i < 8; i++) _pageMapping[i] = i; } @@ -126,6 +125,7 @@ bool Screen::init() { if (_useOverlays) { _useSJIS = (_vm->gameFlags().lang == Common::JA_JPN); _sjisInvisibleColor = (_vm->game() == GI_KYRA1) ? 0x80 : 0xF6; + _sjisMixedFontMode = !_use16ColorMode; for (int i = 0; i < SCREEN_OVLS_NUM; ++i) { if (!_sjisOverlayPtrs[i]) { @@ -141,7 +141,7 @@ bool Screen::init() { if (!font) error("Could not load any SJIS font, neither the original nor ScummVM's 'SJIS.FNT'"); - _fonts[FID_SJIS_FNT] = new SJISFont(font, _sjisInvisibleColor, _use16ColorMode, !_use16ColorMode); + _fonts[FID_SJIS_FNT] = new SJISFont(font, _sjisInvisibleColor, _use16ColorMode, !_use16ColorMode && _vm->game() != GI_LOL, _vm->game() == GI_LOL ? 1 : 0); } } @@ -154,9 +154,7 @@ bool Screen::init() { } int numPages = realPages.size(); - uint32 bufferSize = 0; - for (int i = 0; i < numPages; i++) - bufferSize += (SCREEN_PAGE_SIZE * _pageScaleFactor[realPages[i]] * _pageScaleFactor[realPages[i]]); + uint32 bufferSize = numPages * SCREEN_PAGE_SIZE; uint8 *pagePtr = new uint8[bufferSize]; memset(pagePtr, 0, bufferSize); @@ -167,7 +165,7 @@ bool Screen::init() { _pagePtrs[i] = _pagePtrs[_pageMapping[i]]; } else { _pagePtrs[i] = pagePtr; - pagePtr += (SCREEN_PAGE_SIZE * _pageScaleFactor[i] * _pageScaleFactor[i]); + pagePtr += SCREEN_PAGE_SIZE; } } @@ -292,7 +290,7 @@ void Screen::updateScreen() { needRealUpdate = true; if (!_useOverlays) - _system->copyRectToScreen(getPagePtr(2), SCREEN_W, 320, 0, SCREEN_W * _pageScaleFactor[2], SCREEN_H * _pageScaleFactor[2]); + _system->copyRectToScreen(getPagePtr(2), SCREEN_W, 320, 0, SCREEN_W, SCREEN_H); else _system->copyRectToScreen(getPagePtr(2), SCREEN_W, 640, 0, SCREEN_W, SCREEN_H); } @@ -303,12 +301,12 @@ void Screen::updateScreen() { void Screen::updateDirtyRects() { if (_forceFullUpdate) { - _system->copyRectToScreen(getCPagePtr(0), SCREEN_W * _pageScaleFactor[0], 0, 0, SCREEN_W * _pageScaleFactor[0], SCREEN_H * _pageScaleFactor[0]); + _system->copyRectToScreen(getCPagePtr(0), SCREEN_W, 0, 0, SCREEN_W, SCREEN_H); } else { const byte *page0 = getCPagePtr(0); Common::List<Common::Rect>::iterator it; for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { - _system->copyRectToScreen(page0 + it->top * SCREEN_W * _pageScaleFactor[0] + it->left, SCREEN_W * _pageScaleFactor[0], it->left, it->top, it->width(), it->height()); + _system->copyRectToScreen(page0 + it->top * SCREEN_W + it->left, SCREEN_W, it->left, it->top, it->width(), it->height()); } } _forceFullUpdate = false; @@ -493,7 +491,7 @@ void Screen::clearPage(int pageNum) { assert(pageNum < SCREEN_PAGE_NUM); if (pageNum == 0 || pageNum == 1) _forceFullUpdate = true; - memset(getPagePtr(pageNum), 0, SCREEN_PAGE_SIZE * _pageScaleFactor[_curPage] * _pageScaleFactor[_curPage]); + memset(getPagePtr(pageNum), 0, SCREEN_PAGE_SIZE); clearOverlayPage(pageNum); } @@ -507,7 +505,7 @@ int Screen::setCurPage(int pageNum) { void Screen::clearCurPage() { if (_curPage == 0 || _curPage == 1) _forceFullUpdate = true; - memset(getPagePtr(_curPage), 0, SCREEN_PAGE_SIZE * _pageScaleFactor[_curPage] * _pageScaleFactor[_curPage]); + memset(getPagePtr(_curPage), 0, SCREEN_PAGE_SIZE); clearOverlayPage(_curPage); } @@ -672,7 +670,7 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) { color |= (color << 4); } else if (_renderMode == Common::kRenderCGA) { color &= 0x03; - } else if (_renderMode == Common::kRenderEGA) { + } else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) { color &= 0x0F; } @@ -881,26 +879,16 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { } void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage, int flags) { - // Since we don't (need to) do any actual scaling, we check for compatible pages here - assert(_pageScaleFactor[srcPage] == _pageScaleFactor[dstPage]); - - x1 *= _pageScaleFactor[srcPage]; - y1 *= _pageScaleFactor[srcPage]; - x2 *= _pageScaleFactor[dstPage]; - y2 *= _pageScaleFactor[dstPage]; - w *= _pageScaleFactor[srcPage]; - h *= _pageScaleFactor[srcPage]; - if (x2 < 0) { if (x2 <= -w) return; w += x2; x1 -= x2; x2 = 0; - } else if (x2 + w >= SCREEN_W * _pageScaleFactor[dstPage]) { - if (x2 > SCREEN_W * _pageScaleFactor[dstPage]) + } else if (x2 + w >= SCREEN_W) { + if (x2 > SCREEN_W) return; - w = SCREEN_W * _pageScaleFactor[srcPage] - x2; + w = SCREEN_W - x2; } if (y2 < 0) { @@ -909,14 +897,14 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag h += y2; y1 -= y2; y2 = 0; - } else if (y2 + h >= SCREEN_H * _pageScaleFactor[dstPage]) { - if (y2 > SCREEN_H * _pageScaleFactor[dstPage]) + } else if (y2 + h >= SCREEN_H) { + if (y2 > SCREEN_H) return; - h = SCREEN_H * _pageScaleFactor[srcPage] - y2; + h = SCREEN_H - y2; } - const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W * _pageScaleFactor[srcPage] + x1; - uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W * _pageScaleFactor[dstPage] + x2; + const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W + x1; + uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W + x2; if (src == dst) return; @@ -929,8 +917,8 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag if (flags & CR_NO_P_CHECK) { while (h--) { memmove(dst, src, w); - src += SCREEN_W * _pageScaleFactor[srcPage]; - dst += SCREEN_W * _pageScaleFactor[dstPage]; + src += SCREEN_W; + dst += SCREEN_W; } } else { while (h--) { @@ -938,24 +926,19 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag if (src[i]) dst[i] = src[i]; } - src += SCREEN_W * _pageScaleFactor[srcPage]; - dst += SCREEN_W * _pageScaleFactor[dstPage]; + src += SCREEN_W; + dst += SCREEN_W; } } } void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *dest) { - x *= _pageScaleFactor[pageNum]; - y *= _pageScaleFactor[pageNum]; - w *= _pageScaleFactor[pageNum]; - h *= _pageScaleFactor[pageNum]; - if (y < 0) { dest += (-y) * w; h += y; y = 0; } else if (y + h > SCREEN_H) { - h = SCREEN_H * _pageScaleFactor[pageNum] - y; + h = SCREEN_H - y; } if (x < 0) { @@ -963,7 +946,7 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 * w += x; x = 0; } else if (x + w > SCREEN_W) { - w = SCREEN_W * _pageScaleFactor[pageNum] - x; + w = SCREEN_W - x; } if (w < 0 || h < 0) @@ -972,17 +955,14 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 * uint8 *pagePtr = getPagePtr(pageNum); for (int i = y; i < y + h; ++i) - memcpy(dest + (i - y) * w, pagePtr + i * SCREEN_W * _pageScaleFactor[pageNum] + x, w); + memcpy(dest + (i - y) * w, pagePtr + i * SCREEN_W + x, w); } void Screen::copyPage(uint8 srcPage, uint8 dstPage) { - // Since we don't (need to) do any actual scaling, we check for compatible pages here - assert(_pageScaleFactor[srcPage] == _pageScaleFactor[dstPage]); - uint8 *src = getPagePtr(srcPage); uint8 *dst = getPagePtr(dstPage); if (src != dst) - memcpy(dst, src, SCREEN_W * _pageScaleFactor[srcPage] * SCREEN_H * _pageScaleFactor[srcPage]); + memcpy(dst, src, SCREEN_W * SCREEN_H); copyOverlayRegion(0, 0, 0, 0, SCREEN_W, SCREEN_H, srcPage, dstPage); if (dstPage == 0 || dstPage == 1) @@ -1009,12 +989,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint if (w < 0 || h < 0) return; - x *= _pageScaleFactor[pageNum]; - y *= _pageScaleFactor[pageNum]; - w *= _pageScaleFactor[pageNum]; - h *= _pageScaleFactor[pageNum]; - - uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W * _pageScaleFactor[pageNum] + x; + uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W + x; if (pageNum == 0 || pageNum == 1) addDirtyRect(x, y, w, h); @@ -1023,7 +998,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint while (h--) { memcpy(dst, src, w); - dst += SCREEN_W * _pageScaleFactor[pageNum]; + dst += SCREEN_W; src += w; } } @@ -1101,7 +1076,7 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, color |= (color << 4); } else if (_renderMode == Common::kRenderCGA) { color &= 0x03; - } else if (_renderMode == Common::kRenderEGA) { + } else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) { color &= 0x0F; } @@ -1178,7 +1153,7 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) { color |= (color << 4); } else if (_renderMode == Common::kRenderCGA) { color &= 0x03; - } else if (_renderMode == Common::kRenderEGA) { + } else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) { color &= 0x0F; } @@ -1187,7 +1162,7 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) { int currLine = 0; while (currLine < length) { *ptr = color; - ptr += SCREEN_W * _pageScaleFactor[_curPage]; + ptr += SCREEN_W; currLine++; } } else { @@ -1233,7 +1208,8 @@ bool Screen::loadFont(FontId fontId, const char *filename) { fnt = new AMIGAFont(); #ifdef ENABLE_EOB else if (_vm->game() == GI_EOB1 || _vm->game() == GI_EOB2) - fnt = new OldDOSFont(_renderMode, _vm->gameFlags().useHiRes); + // We use normal VGA rendering in EOB II, since we do the complete EGA dithering in updateScreen(). + fnt = new OldDOSFont(_useHiResEGADithering ? Common::kRenderVGA : _renderMode); #endif // ENABLE_EOB else fnt = new DOSFont(); @@ -1272,11 +1248,16 @@ int Screen::getCharWidth(uint16 c) const { return width + ((_currentFont != FID_SJIS_FNT) ? _charWidth : 0); } -int Screen::getTextWidth(const char *str) const { +int Screen::getTextWidth(const char *str) { int curLineLen = 0; int maxLineLen = 0; + FontId curFont = _currentFont; + while (1) { + if (_sjisMixedFontMode) + setFont(*str < 0 ? FID_SJIS_FNT : curFont); + uint c = fetchChar(str); if (c == 0) { @@ -1300,7 +1281,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 cmap[1] = color1; setTextColor(cmap, 0, 1); - const uint8 charHeightFnt = getFontHeight(); + FontId curFont = _currentFont; if (x < 0) x = 0; @@ -1314,6 +1295,11 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 return; while (1) { + if (_sjisMixedFontMode) + setFont(*str < 0 ? FID_SJIS_FNT : curFont); + + uint8 charHeightFnt = getFontHeight(); + uint c = fetchChar(str); if (c == 0) { @@ -1362,9 +1348,6 @@ void Screen::drawChar(uint16 c, int x, int y) { if (x + charWidth > SCREEN_W || y + charHeight > SCREEN_H) return; - x *= _pageScaleFactor[_curPage]; - y *= _pageScaleFactor[_curPage]; - if (useOverlay) { uint8 *destPage = getOverlayPtr(_curPage); if (!destPage) { @@ -1376,11 +1359,11 @@ void Screen::drawChar(uint16 c, int x, int y) { fnt->drawChar(c, destPage, 640); } else { - fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W * _pageScaleFactor[_curPage] + x, SCREEN_W * _pageScaleFactor[_curPage]); + fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W); } if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, charWidth * _pageScaleFactor[_curPage], charHeight * _pageScaleFactor[_curPage]); + addDirtyRect(x, y, charWidth, charHeight); } void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { @@ -1519,7 +1502,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int int scaleCounterV = 0; - const int drawFunc = flags & 0x0f; + const int drawFunc = flags & 0x0F; _dsProcessMargin = dsMarginFunc[drawFunc]; _dsScaleSkip = dsSkipFunc[drawFunc]; _dsProcessLine = dsLineFunc[drawFunc]; @@ -1776,7 +1759,7 @@ int Screen::drawShapeMarginScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt) _dsTmpWidth += cnt; int i = (_dsOffscreenLeft - cnt) * _dsScaleW; - int res = i & 0xff; + int res = i & 0xFF; i >>= 8; i -= _dsOffscreenScaleVal2; dst += i; @@ -1802,7 +1785,7 @@ int Screen::drawShapeMarginScaleDownwind(uint8 *&dst, const uint8 *&src, int &cn _dsTmpWidth += cnt; int i = (_dsOffscreenLeft - cnt) * _dsScaleW; - int res = i & 0xff; + int res = i & 0xFF; i >>= 8; i -= _dsOffscreenScaleVal2; dst -= i; @@ -1891,7 +1874,7 @@ void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int int r = c * _dsScaleW + scaleState; dst += (r >> 8); cnt -= (r >> 8); - scaleState = r & 0xff; + scaleState = r & 0xFF; } } else if (scaleState) { (this->*_dsPlot)(dst++, c); @@ -1919,7 +1902,7 @@ void Screen::drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, i int r = c * _dsScaleW + scaleState; dst -= (r >> 8); cnt -= (r >> 8); - scaleState = r & 0xff; + scaleState = r & 0xFF; } } else { (this->*_dsPlot)(dst--, c); @@ -1967,9 +1950,9 @@ void Screen::drawShapePlotType5(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType6(uint8 *dst, uint8 cmd) { int t = _drawShapeVar4 + _drawShapeVar5; - if (t & 0xff00) { + if (t & 0xFF00) { cmd = dst[_drawShapeVar3]; - t &= 0xff; + t &= 0xFF; } else { cmd = _dsTable2[cmd]; } @@ -1980,7 +1963,7 @@ void Screen::drawShapePlotType6(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType8(uint8 *dst, uint8 cmd) { uint32 relOffs = dst - _dsDstPage; - int t = (_shapePages[0][relOffs] & 0x7f) & 0x87; + int t = (_shapePages[0][relOffs] & 0x7F) & 0x87; if (_dsDrawLayer < t) cmd = _shapePages[1][relOffs]; @@ -1989,7 +1972,7 @@ void Screen::drawShapePlotType8(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType9(uint8 *dst, uint8 cmd) { uint32 relOffs = dst - _dsDstPage; - int t = (_shapePages[0][relOffs] & 0x7f) & 0x87; + int t = (_shapePages[0][relOffs] & 0x7F) & 0x87; if (_dsDrawLayer < t) { cmd = _shapePages[1][relOffs]; } else { @@ -2003,7 +1986,7 @@ void Screen::drawShapePlotType9(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType11_15(uint8 *dst, uint8 cmd) { uint32 relOffs = dst - _dsDstPage; - int t = (_shapePages[0][relOffs] & 0x7f) & 0x87; + int t = (_shapePages[0][relOffs] & 0x7F) & 0x87; if (_dsDrawLayer < t) { cmd = _shapePages[1][relOffs]; @@ -2019,7 +2002,7 @@ void Screen::drawShapePlotType11_15(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType12(uint8 *dst, uint8 cmd) { uint32 relOffs = dst - _dsDstPage; - int t = (_shapePages[0][relOffs] & 0x7f) & 0x87; + int t = (_shapePages[0][relOffs] & 0x7F) & 0x87; if (_dsDrawLayer < t) { cmd = _shapePages[1][relOffs]; } else { @@ -2031,7 +2014,7 @@ void Screen::drawShapePlotType12(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType13(uint8 *dst, uint8 cmd) { uint32 relOffs = dst - _dsDstPage; - int t = (_shapePages[0][relOffs] & 0x7f) & 0x87; + int t = (_shapePages[0][relOffs] & 0x7F) & 0x87; if (_dsDrawLayer < t) { cmd = _shapePages[1][relOffs]; } else { @@ -2046,14 +2029,14 @@ void Screen::drawShapePlotType13(uint8 *dst, uint8 cmd) { void Screen::drawShapePlotType14(uint8 *dst, uint8 cmd) { uint32 relOffs = dst - _dsDstPage; - int t = (_shapePages[0][relOffs] & 0x7f) & 0x87; + int t = (_shapePages[0][relOffs] & 0x7F) & 0x87; if (_dsDrawLayer < t) { cmd = _shapePages[1][relOffs]; } else { t = _drawShapeVar4 + _drawShapeVar5; - if (t & 0xff00) { + if (t & 0xFF00) { cmd = dst[_drawShapeVar3]; - t &= 0xff; + t &= 0xFF; } else { cmd = _dsTable2[cmd]; } @@ -2147,7 +2130,7 @@ void Screen::decodeFrame1(const uint8 *src, uint8 *dst, uint32 size) { uint8 nib = 0; uint16 code = decodeEGAGetCode(src, nib); - uint8 last = code & 0xff; + uint8 last = code & 0xFF; uint8 *dstPrev = dst; uint16 count = 1; @@ -2160,7 +2143,7 @@ void Screen::decodeFrame1(const uint8 *src, uint8 *dst, uint32 size) { uint8 cmd = code >> 8; if (cmd--) { - code = (cmd << 8) | (code & 0xff); + code = (cmd << 8) | (code & 0xFF); uint8 *tmpDst = dst; if (code < numPatterns) { @@ -2188,7 +2171,7 @@ void Screen::decodeFrame1(const uint8 *src, uint8 *dst, uint32 size) { count = countPrev; } else { - *dst++ = last = (code & 0xff); + *dst++ = last = (code & 0xFF); if (numPatterns < 3840) { patterns[numPatterns].pos = dstPrev; @@ -2209,7 +2192,7 @@ uint16 Screen::decodeEGAGetCode(const uint8 *&pos, uint8 &nib) { res >>= 4; } else { pos++; - res &= 0xfff; + res &= 0xFFF; } return res; } @@ -2891,8 +2874,6 @@ void Screen::setShapePages(int page1, int page2, int minY, int maxY) { void Screen::setMouseCursor(int x, int y, const byte *shape) { if (!shape) return; - // if mouseDisabled - // return _mouseShape if (_vm->gameFlags().useAltShapeHeader) shape += 2; @@ -3215,7 +3196,7 @@ void Screen::addDirtyRect(int x, int y, int w, int h) { Common::Rect r(x, y, x + w, y + h); // Clip rectangle - r.clip(SCREEN_W * _pageScaleFactor[0], SCREEN_H * _pageScaleFactor[0]); + r.clip(SCREEN_W, SCREEN_H); // If it is empty after clipping, we are done if (r.isEmpty()) @@ -3322,8 +3303,6 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s if (srcPage > 13 || dstPage > 13) error("Screen::crossFadeRegion(): attempting to use temp page as source or dest page."); - assert(_pageScaleFactor[srcPage] == _pageScaleFactor[dstPage]); - hideMouse(); uint16 *wB = (uint16 *)_pagePtrs[14]; @@ -3341,6 +3320,9 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s for (int i = 0; i < h; i++) SWAP(hB[_vm->_rnd.getRandomNumberRng(0, h - 1)], hB[i]); + uint8 *s = _pagePtrs[srcPage]; + uint8 *d = _pagePtrs[dstPage]; + for (int i = 0; i < h; i++) { int iH = i; uint32 end = _system->getMillis() + 3; @@ -3353,7 +3335,8 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s if (++iH >= h) iH = 0; - setPagePixel(dstPage, dX, dY, getPagePixel(srcPage, sX, sY)); + d[dY * 320 + dX] = s[sY * 320 + sX]; + addDirtyRect(dX, dY, 1, 1); } // This tries to speed things up, to get similiar speeds as in DOSBox etc. @@ -3595,11 +3578,11 @@ void AMIGAFont::unload() { memset(_chars, 0, sizeof(_chars)); } -SJISFont::SJISFont(Graphics::FontSJIS *font, const uint8 invisColor, bool is16Color, bool outlineSize) - : _colorMap(0), _font(font), _invisColor(invisColor), _is16Color(is16Color) { +SJISFont::SJISFont(Graphics::FontSJIS *font, const uint8 invisColor, bool is16Color, bool drawOutline, int extraSpacing) + : _colorMap(0), _font(font), _invisColor(invisColor), _is16Color(is16Color), _drawOutline(drawOutline), _sjisWidthOffset(extraSpacing) { assert(_font); - _font->setDrawingMode(outlineSize ? Graphics::FontSJIS::kOutlineMode : Graphics::FontSJIS::kDefaultMode); + _font->setDrawingMode(_drawOutline ? Graphics::FontSJIS::kOutlineMode : Graphics::FontSJIS::kDefaultMode); _sjisWidth = _font->getMaxFontWidth() >> 1; _fontHeight = _font->getFontHeight() >> 1; @@ -3616,14 +3599,14 @@ int SJISFont::getHeight() const { } int SJISFont::getWidth() const { - return _sjisWidth; + return _sjisWidth + _sjisWidthOffset; } int SJISFont::getCharWidth(uint16 c) const { if (c <= 0x7F || (c >= 0xA1 && c <= 0xDF)) return _asciiWidth; else - return _sjisWidth; + return _sjisWidth + _sjisWidthOffset; } void SJISFont::setColorMap(const uint8 *src) { @@ -3633,7 +3616,7 @@ void SJISFont::setColorMap(const uint8 *src) { if (_colorMap[0] == _invisColor) _font->setDrawingMode(Graphics::FontSJIS::kDefaultMode); else - _font->setDrawingMode(Graphics::FontSJIS::kOutlineMode); + _font->setDrawingMode(_drawOutline ? Graphics::FontSJIS::kOutlineMode : Graphics::FontSJIS::kDefaultMode); } } @@ -3672,7 +3655,7 @@ void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int col uint8 *pos = _palData + startIndex * 3; for (int i = 0 ; i < colors * 3; i++) - *pos++ = stream.readByte() & 0x3f; + *pos++ = stream.readByte() & 0x3F; } void Palette::loadEGAPalette(Common::ReadStream &stream, int startIndex, int colors) { diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 60bfeb3241..156b5b9a7c 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -146,7 +146,7 @@ private: */ class OldDOSFont : public Font { public: - OldDOSFont(Common::RenderMode mode, bool useHiResEGADithering); + OldDOSFont(Common::RenderMode mode); ~OldDOSFont(); bool load(Common::SeekableReadStream &file); @@ -168,8 +168,6 @@ private: int _numGlyphs; Common::RenderMode _renderMode; - bool _useHiResEGADithering; - bool _useLoResEGA; static uint16 *_cgaDitheringTable; static int _numRef; @@ -213,7 +211,7 @@ private: */ class SJISFont : public Font { public: - SJISFont(Graphics::FontSJIS *font, const uint8 invisColor, bool is16Color, bool outlineSize); + SJISFont(Graphics::FontSJIS *font, const uint8 invisColor, bool is16Color, bool drawOutline, int extraSpacing); ~SJISFont() { unload(); } bool usesOverlay() const { return true; } @@ -232,6 +230,12 @@ private: Graphics::FontSJIS *_font; const uint8 _invisColor; const bool _is16Color; + const bool _drawOutline; + // We use this for cases where the font width returned by getWidth() or getCharWidth() does not match the original. + // The original Japanese game versions use hard coded sjis font widths of 8 or 9. However, this does not necessarily + // depend on whether an outline is used or not (neither LOL/PC-9801 nor LOL/FM-TOWNS use an outline, but the first + // version uses a font width of 8 where the latter uses a font width of 9). + const int _sjisWidthOffset; int _sjisWidth, _asciiWidth; int _fontHeight; @@ -426,12 +430,12 @@ public: void copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint8 *src); void shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPage, int ticks, bool transparent); - virtual void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false); + void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false); void clearPage(int pageNum); - virtual uint8 getPagePixel(int pageNum, int x, int y); - virtual void setPagePixel(int pageNum, int x, int y, uint8 color); + uint8 getPagePixel(int pageNum, int x, int y); + void setPagePixel(int pageNum, int x, int y, uint8 color); const uint8 *getCPagePtr(int pageNum) const; uint8 *getPageRect(int pageNum, int x, int y, int w, int h); @@ -457,7 +461,7 @@ public: void copyPalette(const int dst, const int src); // gui specific (processing on _curPage) - virtual void drawLine(bool vertical, int x, int y, int length, int color); + void drawLine(bool vertical, int x, int y, int length, int color); void drawClippedLine(int x1, int y1, int x2, int y2, int color); virtual void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2); void drawBox(int x1, int y1, int x2, int y2, int color); @@ -470,9 +474,9 @@ public: int getFontWidth() const; int getCharWidth(uint16 c) const; - int getTextWidth(const char *str) const; + int getTextWidth(const char *str); - virtual void printText(const char *str, int x, int y, uint8 color1, uint8 color2); + void printText(const char *str, int x, int y, uint8 color1, uint8 color2); virtual void setTextColorMap(const uint8 *cmap) = 0; void setTextColor(const uint8 *cmap, int a, int b); @@ -549,7 +553,7 @@ public: protected: uint8 *getPagePtr(int pageNum); - void updateDirtyRects(); + virtual void updateDirtyRects(); void updateDirtyRectsAmiga(); void updateDirtyRectsOvl(); @@ -573,18 +577,17 @@ protected: uint8 *_pagePtrs[16]; uint8 *_sjisOverlayPtrs[SCREEN_OVLS_NUM]; - uint8 _pageScaleFactor[SCREEN_PAGE_NUM]; uint8 _pageMapping[SCREEN_PAGE_NUM]; bool _useOverlays; bool _useSJIS; bool _use16ColorMode; bool _useHiResEGADithering; - bool _useLoResEGA; bool _isAmiga; Common::RenderMode _renderMode; uint8 _sjisInvisibleColor; + bool _sjisMixedFontMode; Palette *_screenPalette; Common::Array<Palette *> _palettes; @@ -600,7 +603,7 @@ protected: int _animBlockSize; // dimension handling - const ScreenDim * const _dimTable; + const ScreenDim *const _dimTable; ScreenDim **_customDimTable; const int _dimTableCount; int _curDimIndex; diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp index ae75c111b4..b1b26357f8 100644 --- a/engines/kyra/screen_eob.cpp +++ b/engines/kyra/screen_eob.cpp @@ -52,10 +52,10 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, _cgaScaleTable = 0; _gfxMaxY = 0; _egaDitheringTable = 0; - _egaPixelValueTable = 0; + _egaDitheringTempPage = 0; _cgaMappingDefault = 0; _cgaDitheringTables[0] = _cgaDitheringTables[1] = 0; - _useLoResEGA = _useHiResEGADithering = false; + _useHiResEGADithering = false; } Screen_EoB::~Screen_EoB() { @@ -63,18 +63,12 @@ Screen_EoB::~Screen_EoB() { delete[] _dsTempPage; delete[] _cgaScaleTable; delete[] _egaDitheringTable; - delete[] _egaPixelValueTable; + delete[] _egaDitheringTempPage; delete[] _cgaDitheringTables[0]; delete[] _cgaDitheringTables[1]; } bool Screen_EoB::init() { - // Define hi-res pages for EGA mode in EOB II - if (_vm->gameFlags().useHiRes) { - for (int i = 0; i < 8; i++) - _pageScaleFactor[i] = 2; - } - if (Screen::init()) { int temp; _gfxMaxY = _vm->staticres()->loadRawData(kEoBBaseExpObjectY, temp); @@ -98,13 +92,9 @@ bool Screen_EoB::init() { if (_vm->gameFlags().useHiRes && _renderMode == Common::kRenderEGA) { _useHiResEGADithering = true; _egaDitheringTable = new uint8[256]; - _egaPixelValueTable = new uint8[256]; - for (int i = 0; i < 256; i++) { - _egaDitheringTable[i] = i & 0x0f; - _egaPixelValueTable[i] = i & 0x0f; - } - } else if (_renderMode == Common::kRenderEGA) { - _useLoResEGA = true; + _egaDitheringTempPage = new uint8[SCREEN_W * 2 * SCREEN_H * 2]; + for (int i = 0; i < 256; i++) + _egaDitheringTable[i] = i & 0x0F; } else if (_renderMode == Common::kRenderCGA) { _cgaMappingDefault = _vm->staticres()->loadRawData(kEoB1CgaMappingDefault, temp); _cgaDitheringTables[0] = new uint16[256]; @@ -115,7 +105,7 @@ bool Screen_EoB::init() { _cgaScaleTable = new uint8[256]; memset(_cgaScaleTable, 0, 256 * sizeof(uint8)); for (int i = 0; i < 256; i++) - _cgaScaleTable[i] = ((i & 0xf0) >> 2) | (i & 0x03); + _cgaScaleTable[i] = ((i & 0xF0) >> 2) | (i & 0x03); } return true; @@ -144,14 +134,20 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov int mouseH = (shape[3]); int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : _cursorColorKey; - uint8 *cursor = new uint8[mouseW * _pageScaleFactor[6] * mouseH * _pageScaleFactor[6]]; + int scaleFactor = _useHiResEGADithering ? 2 : 1; + + uint8 *cursor = new uint8[mouseW * scaleFactor * mouseH * scaleFactor]; // We use memset and copyBlockToPage instead of fillRect to make sure that the // color key 0xFF doesn't get converted into EGA color - memset(cursor, colorKey, mouseW * _pageScaleFactor[6] * mouseH * _pageScaleFactor[6]); - copyBlockToPage(6, 0, 0, mouseW, mouseH, cursor); + memset(cursor, colorKey, mouseW * scaleFactor * mouseH * scaleFactor); + copyBlockToPage(6, 0, 0, mouseW * scaleFactor, mouseH * scaleFactor, cursor); drawShape(6, shape, 0, 0, 0, 2, ovl); CursorMan.showMouse(false); - copyRegionToBuffer(6, 0, 0, mouseW, mouseH, cursor); + + if (_useHiResEGADithering) + ditherRect(getCPagePtr(6), cursor, mouseW * scaleFactor, mouseW, mouseH, colorKey); + else + copyRegionToBuffer(6, 0, 0, mouseW, mouseH, cursor); // Mouse cursor post processing for CGA mode. Unlike the original (which uses drawShape for the mouse cursor) // the cursor manager cannot know whether a pixel value of 0 is supposed to be black or transparent. Thus, we @@ -176,7 +172,7 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov } } - CursorMan.replaceCursor(cursor, mouseW * _pageScaleFactor[6], mouseH * _pageScaleFactor[6], x, y, colorKey); + CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x, y, colorKey); if (isMouseVisible()) CursorMan.showMouse(true); delete[] cursor; @@ -192,19 +188,6 @@ void Screen_EoB::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, s->read(_pagePtrs[pageNum], size); } -void Screen_EoB::printText(const char *str, int x, int y, uint8 color1, uint8 color2) { - if (_useHiResEGADithering) { - // This is sort of an abuse of the text color map. But since EOB doesn't use it anyway - // and the font drawing code needs access to both the original color values and the - // EGA dithering colors we pass them on like this. - uint8 cmap[2]; - cmap[0] = _egaDitheringTable[color2]; - cmap[1] = _egaDitheringTable[color1]; - setTextColor(cmap, 2, 3); - } - Screen::printText(str, x, y, color1, color2); -} - void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int col2) { printText(string, x - 1, y, 12, col2); printText(string, x, y + 1, 12, 0); @@ -272,32 +255,19 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping) if (cgaMapping) generateCGADitheringTables(cgaMapping); - uint16 *d = (uint16*)dst; + uint16 *d = (uint16 *)dst; uint8 tblSwitch = 0; for (int height = SCREEN_H; height; height--) { const uint16 *table = _cgaDitheringTables[(tblSwitch++) & 1]; for (int width = SCREEN_W / 2; width; width--) { - WRITE_LE_UINT16(d++, table[((src[1] & 0x0f) << 4) | (src[0] & 0x0f)]); + WRITE_LE_UINT16(d++, table[((src[1] & 0x0F) << 4) | (src[0] & 0x0F)]); src += 2; } } - - } else if (_useHiResEGADithering) { - for (int height = SCREEN_H; height; height--) { - uint8 *dst2 = dst + SCREEN_W * 2; - for (int width = SCREEN_W; width; width--) { - uint8 in = _egaDitheringTable[*src++]; - *dst++ = *dst2++ = in >> 4; - *dst++ = *dst2++ = in & 0x0f; - } - dst += (SCREEN_W * 2); - } - - } else if (_renderMode == Common::kRenderEGA) { + } else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) { uint32 len = SCREEN_W * SCREEN_H; while (len--) - *dst++ = *src++ & 0x0f; - + *dst++ = *src++ & 0x0F; } else { copyPage(srcPage, dstPage); } @@ -306,111 +276,6 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping) _forceFullUpdate = true; } -void Screen_EoB::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, bool xored) { - if (!_useHiResEGADithering) { - Screen::fillRect(x1, y1, x2, y2, color, pageNum, xored); - return; - } - - assert(x2 < SCREEN_W && y2 < SCREEN_H); - if (pageNum == -1) - pageNum = _curPage; - - uint16 pitch = (SCREEN_W - (x2 - x1 + 1)) * _pageScaleFactor[pageNum]; - uint8 col1 = (_egaDitheringTable[color] >> 4); - uint8 col2 = (_egaDitheringTable[color] & 0x0f); - - x1 *= _pageScaleFactor[pageNum]; - y1 *= _pageScaleFactor[pageNum]; - x2 *= _pageScaleFactor[pageNum]; - y2 *= _pageScaleFactor[pageNum]; - uint16 w = x2 - x1 + _pageScaleFactor[pageNum]; - uint16 h = y2 - y1 + _pageScaleFactor[pageNum]; - - uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W * _pageScaleFactor[pageNum] + x1; - if (pageNum == 0 || pageNum == 1) - addDirtyRect(x1, y1, w, h); - - while (h--) { - for (uint16 w1 = w; w1; w1 -= 2) { - *dst++ = col1; - *dst++ = col2; - } - dst += pitch; - } -} - -void Screen_EoB::drawLine(bool vertical, int x, int y, int length, int color) { - if (!_useHiResEGADithering) { - Screen::drawLine(vertical, x, y, length, color); - return; - } - - uint16 pitch = (SCREEN_W - 1) * _pageScaleFactor[_curPage]; - uint8 col1 = (_egaDitheringTable[color] >> 4); - uint8 col2 = (_egaDitheringTable[color] & 0x0f); - - x *= _pageScaleFactor[_curPage]; - y *= _pageScaleFactor[_curPage]; - length *= _pageScaleFactor[_curPage]; - uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W * _pageScaleFactor[_curPage] + x; - uint8 *ptr2 = ptr + SCREEN_W * _pageScaleFactor[_curPage]; - - if (vertical) { - assert((y + length) <= SCREEN_H * _pageScaleFactor[_curPage]); - int currLine = 0; - while (currLine < length) { - *ptr++ = col1; - *ptr++ = col2; - ptr += pitch; - currLine++; - } - } else { - assert((x + length) <= SCREEN_W * _pageScaleFactor[_curPage]); - int currLine = 0; - while (currLine < length) { - *ptr++ = *ptr2++ = col1; - *ptr++ = *ptr2++ = col2; - currLine += 2; - } - } - - if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, (vertical) ? _pageScaleFactor[_curPage] : length, (vertical) ? length : _pageScaleFactor[_curPage]); -} - -uint8 Screen_EoB::getPagePixel(int pageNum, int x, int y) { - if (!_useHiResEGADithering) - return Screen::getPagePixel(pageNum, x, y); - - x *= _pageScaleFactor[_curPage]; - y *= _pageScaleFactor[_curPage]; - uint8 *pos = &_pagePtrs[pageNum][y * SCREEN_W * _pageScaleFactor[_curPage] + x]; - - return _egaPixelValueTable[(pos[0] << 4) | (pos[1] & 0x0f)]; -} - -void Screen_EoB::setPagePixel(int pageNum, int x, int y, uint8 color) { - if (!_useHiResEGADithering) { - Screen::setPagePixel(pageNum, x, y, color); - return; - } - - assert(pageNum < SCREEN_PAGE_NUM); - assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H); - - x *= _pageScaleFactor[_curPage]; - y *= _pageScaleFactor[_curPage]; - - if (pageNum == 0 || pageNum == 1) - addDirtyRect(x, y, _pageScaleFactor[pageNum], _pageScaleFactor[pageNum]); - - uint8 *pos = &_pagePtrs[pageNum][y * SCREEN_W * _pageScaleFactor[_curPage] + x]; - uint8 *pos2 = pos + SCREEN_W * _pageScaleFactor[_curPage]; - pos[0] = pos2[0] = _egaDitheringTable[color] >> 4; - pos[1] = pos2[1] = _egaDitheringTable[color] & 0x0f; -} - void Screen_EoB::setScreenPalette(const Palette &pal) { if (_useHiResEGADithering && pal.getNumColors() != 16) { generateEGADitheringTable(pal); @@ -444,7 +309,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco uint8 *srcLineStart = getPagePtr(_curPage | 1) + y * 320 + (x << 3); uint8 *src = srcLineStart; - if (_useLoResEGA) + if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) encode8bit = false; if (_renderMode == Common::kRenderCGA) { @@ -456,9 +321,9 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco uint8 *dst = shp; *dst++ = 4; - *dst++ = (h & 0xff); - *dst++ = (w & 0xff); - *dst++ = (h & 0xff); + *dst++ = (h & 0xFF); + *dst++ = (w & 0xFF); + *dst++ = (h & 0xFF); uint8 *dst2 = dst + (h * (w << 1)); @@ -469,8 +334,8 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco const uint16 *table = _cgaDitheringTables[(tblSwitch++) & 1]; while (w1--) { - uint16 p0 = table[((src[1] & 0x0f) << 4) | (src[0] & 0x0f)]; - uint16 p1 = table[((src[3] & 0x0f) << 4) | (src[2] & 0x0f)]; + uint16 p0 = table[((src[1] & 0x0F) << 4) | (src[0] & 0x0F)]; + uint16 p1 = table[((src[3] & 0x0F) << 4) | (src[2] & 0x0F)]; *dst++ = ((p0 & 0x0003) << 6) | ((p0 & 0x0300) >> 4) | ((p1 & 0x0003) << 2) | ((p1 & 0x0300) >> 8); @@ -515,9 +380,9 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco uint8 *dst = shp; *dst++ = 8; - *dst++ = (h & 0xff); - *dst++ = (w & 0xff); - *dst++ = (h & 0xff); + *dst++ = (h & 0xFF); + *dst++ = (w & 0xFF); + *dst++ = (h & 0xFF); srcLineStart = getPagePtr(_curPage | 1) + y * 320 + (x << 3); src = srcLineStart; @@ -540,7 +405,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco *dst++ = 0; numZero -= 255; } - val = numZero & 0xff; + val = numZero & 0xFF; } *dst++ = val; } while (src != lineEnd); @@ -555,7 +420,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco if (_renderMode != Common::kRenderEGA || _useHiResEGADithering) { colorMap = new uint8[0x100]; - memset(colorMap, 0xff, 0x100); + memset(colorMap, 0xFF, 0x100); } shapesize = h * (w << 2) + 20; @@ -564,15 +429,15 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco uint8 *dst = shp; *dst++ = 2; - *dst++ = (h & 0xff); - *dst++ = (w & 0xff); - *dst++ = (h & 0xff); + *dst++ = (h & 0xFF); + *dst++ = (w & 0xFF); + *dst++ = (h & 0xFF); - if (_useLoResEGA) { + if (_renderMode != Common::kRenderEGA || _useHiResEGADithering) { + memset(dst, 0xFF, 0x10); + } else { for (int i = 0; i < 16; i++) dst[i] = i; - } else { - memset(dst, 0xff, 0x10); } uint8 *pal = dst; @@ -584,10 +449,10 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco uint16 w1 = w << 3; while (w1--) { uint8 s = *src++; - uint8 c = s & 0x0f; + uint8 c = s & 0x0F; if (colorMap) { c = colorMap[s]; - if (c == 0xff) { + if (c == 0xFF) { if (col < 0x10) { *pal++ = s; c = colorMap[s] = col++; @@ -632,7 +497,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, y += _dsY1; } - dst += (_dsX1 << 3) * _pageScaleFactor[pageNum]; + dst += (_dsX1 << 3); int16 dX = x - (_dsX1 << 3); int16 dY = y; int16 dW = _dsX2 - _dsX1; @@ -704,11 +569,11 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, marginRight = w2 - marginLeft - width; } - dst += (dY * SCREEN_W * _pageScaleFactor[pageNum] * _pageScaleFactor[pageNum] + dX * _pageScaleFactor[pageNum]); + dst += (dY * SCREEN_W + dX); uint8 *dstL = dst; if (pageNum == 0 || pageNum == 1) - addDirtyRect(rX * _pageScaleFactor[pageNum], rY * _pageScaleFactor[pageNum], rW * _pageScaleFactor[pageNum], rH * _pageScaleFactor[pageNum]); + addDirtyRect(rX, rY, rW, rH); while (dH--) { int16 xpos = (int16) marginLeft; @@ -743,7 +608,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, } while (xpos > 0); } - dst -= (xpos * _pageScaleFactor[pageNum]); + dst -= xpos; xpos += width; while (xpos > 0) { @@ -752,12 +617,12 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, src += pixelStep; if (m) { - drawShapeSetPixel(dst, c, SCREEN_W * _pageScaleFactor[pageNum]); - dst += _pageScaleFactor[pageNum]; + drawShapeSetPixel(dst, c); + dst++; xpos--; } else { uint8 len = (flags & 1) ? src[1] : src[0]; - dst += (len * _pageScaleFactor[pageNum]); + dst += len; xpos -= len; src += pixelStep; } @@ -783,7 +648,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, } while (xpos > 0); } - dstL += SCREEN_W * _pageScaleFactor[pageNum] * _pageScaleFactor[pageNum]; + dstL += SCREEN_W; dst = dstL; if (flags & 1) src = src2 + 1; @@ -797,7 +662,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, pal = ovl ? ovl : src; src += 16; } else { - static const uint8 cgaDefOvl[] = { 0x00, 0x55, 0xaa, 0xff }; + static const uint8 cgaDefOvl[] = { 0x00, 0x55, 0xAA, 0xFF }; pal = ovl ? ovl : cgaDefOvl; for (int i = 0; i < 4; i++) cgaPal[i] = pal[i] & 3; @@ -851,12 +716,12 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, if (d < width) width = d; - dst += (dY * _pageScaleFactor[pageNum] * SCREEN_W * _pageScaleFactor[pageNum] + dX * _pageScaleFactor[pageNum]); + dst += (dY * SCREEN_W + dX); if (pageNum == 0 || pageNum == 1) - addDirtyRect(rX * _pageScaleFactor[pageNum], rY * _pageScaleFactor[pageNum], rW * _pageScaleFactor[pageNum], rH * _pageScaleFactor[pageNum]); + addDirtyRect(rX, rY, rW, rH); - int pitch = SCREEN_W * _pageScaleFactor[pageNum] * _pageScaleFactor[pageNum] - width * _pageScaleFactor[pageNum]; + int pitch = SCREEN_W - width; int16 lineSrcStep = (w2 - width) / pixelsPerByte; uint8 lineSrcStepRemainder = (w2 - width) % pixelsPerByte; @@ -899,8 +764,8 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, } uint8 col = (pixelsPerByte == 2) ? pal[(in >> shift) & pixelPackingMask] : (*dst & ((trans >> shift) & (pixelPackingMask))) | pal[(in >> shift) & pixelPackingMask]; if (col || pixelsPerByte == 4) - drawShapeSetPixel(dst, col, SCREEN_W * _pageScaleFactor[pageNum]); - dst += _pageScaleFactor[pageNum]; + drawShapeSetPixel(dst, col); + dst++; shift = ((shift - (pixelStep * pixelPacking)) & 7); } src += lineSrcStep; @@ -922,7 +787,7 @@ const uint8 *Screen_EoB::scaleShapeStep(const uint8 *shp) { uint8 *dst = (shp != _dsTempPage) ? _dsTempPage : _dsTempPage + 6000; uint8 *d = dst; uint8 pixelsPerByte = *d++ = *shp++; - assert (pixelsPerByte > 1); + assert(pixelsPerByte > 1); uint16 h = shp[0] + 1; d[0] = d[2] = (h << 1) / 3; @@ -952,7 +817,7 @@ const uint8 *Screen_EoB::scaleShapeStep(const uint8 *shp) { else i = -i; - _dsScaleTrans = (i << 4) | (i & 0x0f); + _dsScaleTrans = (i << 4) | (i & 0x0F); for (int ii = 0; ii < 16; ii++) *d++ = *shp++; } @@ -976,7 +841,7 @@ const uint8 *Screen_EoB::scaleShapeStep(const uint8 *shp) { shp += w2; } - return (const uint8*)dst; + return (const uint8 *)dst; } const uint8 *Screen_EoB::generateShapeOverlay(const uint8 *shp, int paletteOverlayIndex) { @@ -1328,14 +1193,14 @@ void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, ui for (uint8 i = 1; i; i++) { uint16 tmp = (uint16)((*src - r) * weight) << 1; - tr = *src++ - ((tmp >> 8) & 0xff); + tr = *src++ - ((tmp >> 8) & 0xFF); tmp = (uint16)((*src - g) * weight) << 1; - tg = *src++ - ((tmp >> 8) & 0xff); + tg = *src++ - ((tmp >> 8) & 0xFF); tmp = (uint16)((*src - b) * weight) << 1; - tb = *src++ - ((tmp >> 8) & 0xff); + tb = *src++ - ((tmp >> 8) & 0xFF); uint8 *d = palData + 3; - uint16 v = 0xffff; + uint16 v = 0xFFFF; uint8 col = rootColor; for (uint8 ii = 1; ii; ii++) { @@ -1367,15 +1232,55 @@ const uint8 *Screen_EoB::getEGADitheringTable() { return _egaDitheringTable; } -void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col, uint16 pitch) { +void Screen_EoB::updateDirtyRects() { + if (!_useHiResEGADithering) { + Screen::updateDirtyRects(); + return; + } + + if (_forceFullUpdate) { + ditherRect(getCPagePtr(0), _egaDitheringTempPage, SCREEN_W * 2, SCREEN_W, SCREEN_H); + _system->copyRectToScreen(_egaDitheringTempPage, SCREEN_W * 2, 0, 0, SCREEN_W * 2, SCREEN_H * 2); + } else { + const byte *page0 = getCPagePtr(0); + Common::List<Common::Rect>::iterator it; + for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { + ditherRect(page0 + it->top * SCREEN_W + it->left, _egaDitheringTempPage, SCREEN_W * 2, it->width(), it->height()); + _system->copyRectToScreen(_egaDitheringTempPage, SCREEN_W * 2, it->left * 2, it->top * 2, it->width() * 2, it->height() * 2); + } + } + _forceFullUpdate = false; + _dirtyRects.clear(); +} + +void Screen_EoB::ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW, int srcH, int colorKey) { + while (srcH--) { + uint8 *dst2 = dst + dstPitch; + for (int i = 0; i < srcW; i++) { + int in = *src++; + if (in != colorKey) { + in = _egaDitheringTable[in]; + *dst++ = *dst2++ = in >> 4; + *dst++ = *dst2++ = in & 0x0F; + } else { + dst[0] = dst[1] = dst2[0] = dst2[1] = colorKey; + dst += 2; + dst2 += 2; + } + } + src += (SCREEN_W - srcW); + dst += ((dstPitch - srcW) * 2); + } +} + +void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) { if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) { if (_shapeFadeMode[0]) { if (_shapeFadeMode[1]) { - col = _useHiResEGADithering ? _egaPixelValueTable[(dst[0] << 4) | (dst[1] & 0x0f)] : *dst; + col = *dst; } else { _shapeFadeInternal &= 7; - col = _useHiResEGADithering ? _egaPixelValueTable[(dst[_shapeFadeInternal] << 4) | (dst[_shapeFadeInternal + 1] & 0x0f)] : dst[_shapeFadeInternal]; - _shapeFadeInternal++; + col = *(dst + _shapeFadeInternal++); } } @@ -1386,21 +1291,15 @@ void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col, uint16 pitch) { } } - if (_useHiResEGADithering) { - col = _egaDitheringTable[col]; - dst[0] = dst[pitch] = col >> 4; - dst[1] = dst[pitch + 1] = col & 0x0f; - } else { - *dst = col; - } + *dst = col; } void Screen_EoB::scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, uint32 transOffsetDst, uint32 transOffsetSrc) { for (int i = 0; i < _dsDiv; i++) { shpDst[0] = (_cgaScaleTable[shpSrc[0]] << 2) | (shpSrc[1] >> 6); - shpDst[1] = ((shpSrc[1] & 0x0f) << 4) | ((shpSrc[2] >> 2) & 0x0f); + shpDst[1] = ((shpSrc[1] & 0x0F) << 4) | ((shpSrc[2] >> 2) & 0x0F); shpDst[transOffsetDst] = (_cgaScaleTable[shpSrc[transOffsetSrc]] << 2) | (shpSrc[transOffsetSrc + 1] >> 6); - shpDst[transOffsetDst + 1] = ((shpSrc[transOffsetSrc + 1] & 0x0f) << 4) | ((shpSrc[transOffsetSrc + 2] >> 2) & 0x0f); + shpDst[transOffsetDst + 1] = ((shpSrc[transOffsetSrc + 1] & 0x0F) << 4) | ((shpSrc[transOffsetSrc + 2] >> 2) & 0x0F); shpSrc += 3; shpDst += 2; } @@ -1409,15 +1308,15 @@ void Screen_EoB::scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, shpDst[0] = _cgaScaleTable[shpSrc[0]] << 2; shpDst[1] = 0; shpDst[transOffsetDst] = (_cgaScaleTable[shpSrc[transOffsetSrc]] << 2) | 3; - shpDst[transOffsetDst + 1] = 0xff; + shpDst[transOffsetDst + 1] = 0xFF; shpSrc++; shpDst += 2; } else if (_dsRem == 2) { shpDst[0] = (_cgaScaleTable[shpSrc[0]] << 2) | (shpSrc[1] >> 6); - shpDst[1] = (shpSrc[1] & 0x3f) << 2; + shpDst[1] = (shpSrc[1] & 0x3F) << 2; shpDst[transOffsetDst] = (_cgaScaleTable[shpSrc[transOffsetSrc]] << 2) | (shpSrc[transOffsetSrc + 1] >> 6); - shpDst[transOffsetDst + 1] = ((shpSrc[transOffsetSrc + 1] & 0x3f) << 2) | 3; + shpDst[transOffsetDst + 1] = ((shpSrc[transOffsetSrc + 1] & 0x3F) << 2) | 3; shpSrc += 2; shpDst += 2; } @@ -1426,7 +1325,7 @@ void Screen_EoB::scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, void Screen_EoB::scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src) { for (int i = 0; i < _dsDiv; i++) { *dst++ = *src++; - *dst++ = (READ_BE_UINT16(src) >> 4) & 0xff; + *dst++ = (READ_BE_UINT16(src) >> 4) & 0xFF; src += 2; } @@ -1434,7 +1333,7 @@ void Screen_EoB::scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src) { *dst++ = *src++; *dst++ = _dsScaleTrans; } else if (_dsRem == 2) { - *dst++ = (src[0] & 0xf0) | (src[1] >> 4); + *dst++ = (src[0] & 0xF0) | (src[1] >> 4); src += 2; *dst++ = _dsScaleTrans; *dst++ = _dsScaleTrans; @@ -1463,7 +1362,7 @@ void Screen_EoB::generateEGADitheringTable(const Palette &pal) { for (int ii = 256; ii; ii--) { const uint8 *palEntry = _egaMatchTable + (ii - 1) * 3; - if (*palEntry == 0xff) + if (*palEntry == 0xFF) continue; int e_r = palEntry[0] - r; @@ -1479,16 +1378,12 @@ void Screen_EoB::generateEGADitheringTable(const Palette &pal) { } *dst++ = col; } - - memset(_egaPixelValueTable, 0, 256); - for (int i = 0; i < 256; i++) - _egaPixelValueTable[_egaDitheringTable[i]] = i; } void Screen_EoB::generateCGADitheringTables(const uint8 *mappingData) { for (int i = 0; i < 256; i++) { - _cgaDitheringTables[0][i] = (mappingData[(i >> 4) + 16] << 8) | mappingData[i & 0x0f]; - _cgaDitheringTables[1][i] = (mappingData[i >> 4] << 8) | mappingData[(i & 0x0f) + 16]; + _cgaDitheringTables[0][i] = (mappingData[(i >> 4) + 16] << 8) | mappingData[i & 0x0F]; + _cgaDitheringTables[1][i] = (mappingData[i >> 4] << 8) | mappingData[(i & 0x0F) + 16]; } } @@ -1546,11 +1441,10 @@ const uint8 Screen_EoB::_egaMatchTable[] = { uint16 *OldDOSFont::_cgaDitheringTable = 0; int OldDOSFont::_numRef = 0; -OldDOSFont::OldDOSFont(Common::RenderMode mode, bool useHiResEGADithering) : _renderMode(mode), _useHiResEGADithering(useHiResEGADithering) { +OldDOSFont::OldDOSFont(Common::RenderMode mode) : _renderMode(mode) { _data = 0; _width = _height = _numGlyphs = 0; _bitmapOffsets = 0; - _useLoResEGA = (_renderMode == Common::kRenderEGA && !_useHiResEGADithering); _numRef++; if (!_cgaDitheringTable && _numRef == 1) { @@ -1615,42 +1509,42 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { if (_width == 6) { switch (c) { case 0x81: - case 0x9a: - c = 0x5d; + case 0x9A: + c = 0x5D; break; case 0x84: - case 0x8e: - c = 0x5b; + case 0x8E: + c = 0x5B; break; case 0x94: case 0x99: c = 0x40; - case 0xe1: + case 0xE1: // TODO: recheck this: no conversion for 'ß' ? break; } } else if (_width == 8) { switch (c) { case 0x81: - case 0x9a: - case 0x5d: - c = 0x1d; + case 0x9A: + case 0x5D: + c = 0x1D; break; case 0x84: - case 0x5b: - c = 0x1e; + case 0x5B: + c = 0x1E; break; case 0x94: case 0x40: - c = 0x1f; + c = 0x1F; break; - case 0x8e: - c = 0x1b; + case 0x8E: + c = 0x1B; break; case 0x99: - c = 0x1c; + c = 0x1C; break; - case 0xe1: + case 0xE1: c = 0x19; break; } @@ -1662,24 +1556,16 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { int w = (_width - 1) >> 3; pitch -= _width; - if (_useHiResEGADithering) - pitch *= 2; - uint8 color1 = _colorMap[1]; uint8 color2 = _colorMap[0]; - uint8 colEGA11 = _colorMap[3] >> 4; - uint8 colEGA12 = _colorMap[3] & 0x0f; - uint8 colEGA21 = _colorMap[2] >> 4; - uint8 colEGA22 = _colorMap[2] & 0x0f; - static const uint16 cgaColorMask[] = { 0, 0x5555, 0xAAAA, 0xFFFF }; uint16 cgaMask1 = cgaColorMask[color1 & 3]; uint16 cgaMask2 = cgaColorMask[color2 & 3]; - if (_renderMode == Common::kRenderCGA || _useLoResEGA) { - color1 &= 0x0f; - color2 &= 0x0f; + if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) { + color1 &= 0x0F; + color2 &= 0x0F; } int cH = _height; @@ -1710,7 +1596,7 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { uint8 sh = 6; for (int i = 0; i < _width; i++) { cDst |= ((dst[i] & 3) << sh); - sh = (sh - 2) & 0x0f; + sh = (sh - 2) & 0x0F; } uint16 out = (~(cmp1 | cmp2) & cDst) | (cmp1 & cgaMask1) | (cmp2 & cgaMask2); @@ -1718,7 +1604,7 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { sh = 6; for (int i = 0; i < _width; i++) { *dst++ = (out >> sh) & 3; - sh = (sh - 2) & 0x0f; + sh = (sh - 2) & 0x0F; } last = s; @@ -1734,27 +1620,13 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { break; } - if (_useHiResEGADithering) { - if (s & i) { - if (color1) { - dst[0] = dst2[0] = colEGA11; - dst[1] = dst2[1] = colEGA12; - } - } else if (color2) { - dst[0] = dst2[0] = colEGA21; - dst[1] = dst2[1] = colEGA22; - } - dst += 2; - dst2 += 2; - } else { - if (s & i) { - if (color1) - *dst = color1; - } else if (color2) { - *dst = color2; - } - dst++; + if (s & i) { + if (color1) + *dst = color1; + } else if (color2) { + *dst = color2; } + dst++; } if (cW) diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h index fc40cfe903..934483d146 100644 --- a/engines/kyra/screen_eob.h +++ b/engines/kyra/screen_eob.h @@ -45,7 +45,6 @@ public: void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size); - void printText(const char *str, int x, int y, uint8 color1, uint8 color2); void printShadedText(const char *string, int x, int y, int col1, int col2); void loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage); @@ -53,11 +52,6 @@ public: void convertPage(int srcPage, int dstPage, const uint8 *cgaMapping); - void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false); - void drawLine(bool vertical, int x, int y, int length, int color); - uint8 getPagePixel(int pageNum, int x, int y); - void setPagePixel(int pageNum, int x, int y, uint8 color); - void setScreenPalette(const Palette &pal); void getRealPalette(int num, uint8 *dst); @@ -68,7 +62,7 @@ public: const uint8 *generateShapeOverlay(const uint8 *shp, int paletteOverlayIndex); void setShapeFrame(int x1, int y1, int x2, int y2); - void setShapeFadeMode (uint8 i, bool b); + void setShapeFadeMode(uint8 i, bool b); void setGfxParameters(int x, int y, int col); void drawExplosion(int scale, int radius, int numElements, int stepSize, int aspectRatio, const uint8 *colorTable, int colorTableSize); @@ -88,7 +82,10 @@ public: const uint8 *getEGADitheringTable(); private: - void drawShapeSetPixel(uint8 *dst, uint8 col, uint16 pitch); + void updateDirtyRects(); + void ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW, int srcH, int colorKey = -1); + + void drawShapeSetPixel(uint8 *dst, uint8 col); void scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, uint32 transOffsetDst, uint32 transOffsetSrc); void scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src); bool posWithinRect(int posX, int posY, int x1, int y1, int x2, int y2); @@ -115,14 +112,14 @@ private: const uint8 *_cgaMappingDefault; uint8 *_egaDitheringTable; - uint8 *_egaPixelValueTable; + uint8 *_egaDitheringTempPage; static const uint8 _egaMatchTable[]; static const ScreenDim _screenDimTable[]; static const int _screenDimTableCount; }; -} // End of namespace Kyra +} // End of namespace Kyra #endif // ENABLE_EOB diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp index ac6ee5eb77..b7de7988b8 100644 --- a/engines/kyra/screen_hof.cpp +++ b/engines/kyra/screen_hof.cpp @@ -34,16 +34,16 @@ void Screen_HoF::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, for (int i = 0; i != lastColor; i++) { if (flag) { - int v = ((((srcPal[3 * i] & 0x3f) + (srcPal[3 * i + 1] & 0x3f) - + (srcPal[3 * i + 2] & 0x3f)) / 3) * factor) / 0x40; - tmpPal[3 * i] = tmpPal[3 * i + 1] = tmpPal[3 * i + 2] = v & 0xff; + int v = ((((srcPal[3 * i] & 0x3F) + (srcPal[3 * i + 1] & 0x3F) + + (srcPal[3 * i + 2] & 0x3F)) / 3) * factor) / 0x40; + tmpPal[3 * i] = tmpPal[3 * i + 1] = tmpPal[3 * i + 2] = v & 0xFF; } else { - int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR; - tmpPal[3 * i] = (v > 0x3f) ? 0x3f : v & 0xff; - v = (((srcPal[3 * i + 1] & 0x3f) * factor) / 0x40) + addG; - tmpPal[3 * i + 1] = (v > 0x3f) ? 0x3f : v & 0xff; - v = (((srcPal[3 * i + 2] & 0x3f) * factor) / 0x40) + addB; - tmpPal[3 * i + 2] = (v > 0x3f) ? 0x3f : v & 0xff; + int v = (((srcPal[3 * i] & 0x3F) * factor) / 0x40) + addR; + tmpPal[3 * i] = (v > 0x3F) ? 0x3F : v & 0xFF; + v = (((srcPal[3 * i + 1] & 0x3F) * factor) / 0x40) + addG; + tmpPal[3 * i + 1] = (v > 0x3F) ? 0x3F : v & 0xFF; + v = (((srcPal[3 * i + 2] & 0x3F) * factor) / 0x40) + addB; + tmpPal[3 * i + 2] = (v > 0x3F) ? 0x3F : v & 0xFF; } } @@ -93,46 +93,4 @@ void Screen_HoF::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int } } -void Screen_HoF::copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes) { - const uint8 *src = getPagePtr(srcPage) + srcPos; - uint8 *dst = getPagePtr(dstPage) + dstPos; - memcpy(dst, src, numBytes); -} - -void Screen_HoF::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX, int dstY, int dstW, int dstH, const ScreenDim *dim, bool flag) { - int x0 = dim->sx << 3; - int y0 = dim->sy; - int w0 = dim->w << 3; - int h0 = dim->h; - - int x1 = dstX; - int y1 = dstY; - int w1 = dstW; - int h1 = dstH; - - int x2, y2, w2; - - calcBounds(w0, h0, x1, y1, w1, h1, x2, y2, w2); - - const uint8 *src = getPagePtr(srcPage) + (320 * srcH) + srcW; - uint8 *dst = getPagePtr(dstPage) + 320 * (y0 + y1); - - for (int y = 0; y < h1; y++) { - const uint8 *s = src + x2; - uint8 *d = dst + x0 + x1; - - if (flag) - d += (h1 >> 1); - - for (int x = 0; x < w1; x++) { - if (*s) - *d = *s; - s++; - d++; - } - dst += 320; - src += 320; - } -} - } // End of namespace Kyra diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h index 51c6a001fa..95f461677d 100644 --- a/engines/kyra/screen_hof.h +++ b/engines/kyra/screen_hof.h @@ -37,8 +37,7 @@ public: // sequence player void generateGrayOverlay(const Palette &pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage); - void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); - void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false); + private: KyraEngine_HoF *_vm; diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 3726b1f4b9..16a77c8fcb 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -133,12 +133,12 @@ void Screen_LoL::generateGrayOverlay(const Palette &srcPal, uint8 *grayOverlay, Palette tmpPal(lastColor); for (int i = 0; i != lastColor; i++) { - int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR; - tmpPal[3 * i] = (v > 0x3f) ? 0x3f : v & 0xff; - v = (((srcPal[3 * i + 1] & 0x3f) * factor) / 0x40) + addG; - tmpPal[3 * i + 1] = (v > 0x3f) ? 0x3f : v & 0xff; - v = (((srcPal[3 * i + 2] & 0x3f) * factor) / 0x40) + addB; - tmpPal[3 * i + 2] = (v > 0x3f) ? 0x3f : v & 0xff; + int v = (((srcPal[3 * i] & 0x3F) * factor) / 0x40) + addR; + tmpPal[3 * i] = (v > 0x3F) ? 0x3F : v & 0xFF; + v = (((srcPal[3 * i + 1] & 0x3F) * factor) / 0x40) + addG; + tmpPal[3 * i + 1] = (v > 0x3F) ? 0x3F : v & 0xFF; + v = (((srcPal[3 * i + 2] & 0x3F) * factor) / 0x40) + addB; + tmpPal[3 * i + 2] = (v > 0x3F) ? 0x3F : v & 0xFF; } for (int i = 0; i < lastColor; i++) @@ -149,7 +149,7 @@ void Screen_LoL::createTransparencyTablesIntern(const uint8 *ovl, int a, const u Palette screenPal(256); screenPal.copy(fxPal2, 0, 256); - memset(outTable1, 0xff, 256); + memset(outTable1, 0xFF, 256); for (int i = 0; i < a; i++) outTable1[ovl[i]] = i; @@ -233,8 +233,6 @@ void Screen_LoL::drawGridBox(int x, int y, int w, int h, int col) { *(p + tmp) = col; p += 2; } - } else { - w = 1; } if (s == 1) { @@ -270,7 +268,7 @@ void Screen_LoL::fadeClearSceneWindow(int delay) { void Screen_LoL::backupSceneWindow(int srcPageNum, int dstPageNum) { uint8 *src = getPagePtr(srcPageNum) + 112; - uint8 *dst = getPagePtr(dstPageNum) + 0xa500; + uint8 *dst = getPagePtr(dstPageNum) + 0xA500; for (int h = 0; h < 120; h++) { for (int w = 0; w < 176; w++) @@ -280,7 +278,7 @@ void Screen_LoL::backupSceneWindow(int srcPageNum, int dstPageNum) { } void Screen_LoL::restoreSceneWindow(int srcPageNum, int dstPageNum) { - uint8 *src = getPagePtr(srcPageNum) + 0xa500; + uint8 *src = getPagePtr(srcPageNum) + 0xA500; uint8 *dst = getPagePtr(dstPageNum) + 112; for (int h = 0; h < 120; h++) { @@ -294,7 +292,7 @@ void Screen_LoL::restoreSceneWindow(int srcPageNum, int dstPageNum) { } void Screen_LoL::clearGuiShapeMemory(int pageNum) { - uint8 *dst = getPagePtr(pageNum) + 0x79b0; + uint8 *dst = getPagePtr(pageNum) + 0x79B0; for (int i = 0; i < 23; i++) { memset(dst, 0, 176); dst += 320; @@ -302,7 +300,7 @@ void Screen_LoL::clearGuiShapeMemory(int pageNum) { } void Screen_LoL::copyGuiShapeFromSceneBackupBuffer(int srcPageNum, int dstPageNum) { - uint8 *src = getPagePtr(srcPageNum) + 0x79c3; + uint8 *src = getPagePtr(srcPageNum) + 0x79C3; uint8 *dst = getPagePtr(dstPageNum); for (int i = 0; i < 23; i++) { @@ -325,7 +323,7 @@ void Screen_LoL::copyGuiShapeFromSceneBackupBuffer(int srcPageNum, int dstPageN void Screen_LoL::copyGuiShapeToSurface(int srcPageNum, int dstPageNum) { uint8 *src = getPagePtr(srcPageNum); - uint8 *dst = getPagePtr(dstPageNum) + 0xe7c3; + uint8 *dst = getPagePtr(dstPageNum) + 0xE7C3; for (int i = 0; i < 23; i++) { uint8 v = *src++; @@ -344,8 +342,8 @@ void Screen_LoL::copyGuiShapeToSurface(int srcPageNum, int dstPageNum) { } void Screen_LoL::smoothScrollZoomStepTop(int srcPageNum, int dstPageNum, int x, int y) { - uint8 *src = getPagePtr(srcPageNum) + 0xa500 + y * 176 + x; - uint8 *dst = getPagePtr(dstPageNum) + 0xa500; + uint8 *src = getPagePtr(srcPageNum) + 0xA500 + y * 176 + x; + uint8 *dst = getPagePtr(dstPageNum) + 0xA500; x <<= 1; uint16 width = 176 - x; @@ -365,7 +363,7 @@ void Screen_LoL::smoothScrollZoomStepTop(int srcPageNum, int dstPageNum, int x, do { scaleXc += scaleX; int numbytes = cntW + (scaleXc >> 16); - scaleXc &= 0xffff; + scaleXc &= 0xFFFF; memset(dst, *src++, numbytes); dst += numbytes; } while (--widthCnt); @@ -387,8 +385,8 @@ void Screen_LoL::smoothScrollZoomStepTop(int srcPageNum, int dstPageNum, int x, } void Screen_LoL::smoothScrollZoomStepBottom(int srcPageNum, int dstPageNum, int x, int y) { - uint8 *src = getPagePtr(srcPageNum) + 0xc4a0 + x; - uint8 *dst = getPagePtr(dstPageNum) + 0xc4a0; + uint8 *src = getPagePtr(srcPageNum) + 0xC4A0 + x; + uint8 *dst = getPagePtr(dstPageNum) + 0xC4A0; x <<= 1; uint16 width = 176 - x; @@ -408,7 +406,7 @@ void Screen_LoL::smoothScrollZoomStepBottom(int srcPageNum, int dstPageNum, int do { scaleXc += scaleX; int numbytes = cntW + (scaleXc >> 16); - scaleXc &= 0xffff; + scaleXc &= 0xFFFF; memset(dst, *src++, numbytes); dst += numbytes; } while (--widthCnt); @@ -455,7 +453,7 @@ void Screen_LoL::smoothScrollHorizontalStep(int pageNum, int srcX, int dstX, int void Screen_LoL::smoothScrollTurnStep1(int srcPage1Num, int srcPage2Num, int dstPageNum) { uint8 *s = getPagePtr(srcPage1Num) + 273; - uint8 *d = getPagePtr(dstPageNum) + 0xa500; + uint8 *d = getPagePtr(dstPageNum) + 0xA500; for (int i = 0; i < 120; i++) { uint8 a = *s++; @@ -474,7 +472,7 @@ void Screen_LoL::smoothScrollTurnStep1(int srcPage1Num, int srcPage2Num, int dst } s = getPagePtr(srcPage2Num) + 112; - d = getPagePtr(dstPageNum) + 0xa52c; + d = getPagePtr(dstPageNum) + 0xA52C; for (int i = 0; i < 120; i++) { for (int ii = 0; ii < 33; ii++) { @@ -492,7 +490,7 @@ void Screen_LoL::smoothScrollTurnStep1(int srcPage1Num, int srcPage2Num, int dst void Screen_LoL::smoothScrollTurnStep2(int srcPage1Num, int srcPage2Num, int dstPageNum) { uint8 *s = getPagePtr(srcPage1Num) + 244; - uint8 *d = getPagePtr(dstPageNum) + 0xa500; + uint8 *d = getPagePtr(dstPageNum) + 0xA500; for (int k = 0; k < 2; k++) { for (int i = 0; i < 120; i++) { @@ -507,13 +505,13 @@ void Screen_LoL::smoothScrollTurnStep2(int srcPage1Num, int srcPage2Num, int dst } s = getPagePtr(srcPage2Num) + 112; - d = getPagePtr(dstPageNum) + 0xa558; + d = getPagePtr(dstPageNum) + 0xA558; } } void Screen_LoL::smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dstPageNum) { uint8 *s = getPagePtr(srcPage1Num) + 189; - uint8 *d = getPagePtr(dstPageNum) + 0xa500; + uint8 *d = getPagePtr(dstPageNum) + 0xA500; for (int i = 0; i < 120; i++) { for (int ii = 0; ii < 33; ii++) { @@ -529,7 +527,7 @@ void Screen_LoL::smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dst } s = getPagePtr(srcPage2Num) + 112; - d = getPagePtr(dstPageNum) + 0xa584; + d = getPagePtr(dstPageNum) + 0xA584; for (int i = 0; i < 120; i++) { for (int ii = 0; ii < 14; ii++) { @@ -783,8 +781,8 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT for (int i = 0; i < 3; i++) { if (elapsedTicks < totalTicks) { - srcV = *src & 0x3f; - dstV = *dst & 0x3f; + srcV = *src & 0x3F; + dstV = *dst & 0x3F; outV = srcV - dstV; if (outV) @@ -796,7 +794,7 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT res = false; } - tmpPalEntry[i] = outV & 0xff; + tmpPalEntry[i] = outV & 0xFF; src++; dst++; p++; @@ -810,34 +808,6 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT return res; } -bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) { - Palette &p1 = getPalette(1); - - bool res = false; - for (int i = 0; i < p1.getNumColors() * 3; i++) { - uint8 out = 0; - - if (elapsedTime < targetTime) { - int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f)); - if (d) - res = true; - - int32 val = ((((d << 8) / (int32)targetTime) * (int32)elapsedTime) >> 8); - out = ((pal1[i] & 0x3f) + (int8)val); - } else { - out = p1[i] = (pal2[i] & 0x3f); - res = false; - } - - (*_internFadePalette)[i] = out; - } - - setScreenPalette(*_internFadePalette); - updateScreen(); - - return res; -} - Palette **Screen_LoL::generateFadeTable(Palette **dst, Palette *src1, Palette *src2, int numTabs) { int len = _use16ColorMode ? 48 : 768; if (!src1) diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 09496705bb..8ceb8431bc 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -65,7 +65,6 @@ public: void loadSpecialColors(Palette &dst); void copyColor(int dstColorIndex, int srcColorIndex); bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTicks, uint32 totalTicks); - bool fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime); Palette **generateFadeTable(Palette **dst, Palette *src1, Palette *src2, int numTabs); void generateGrayOverlay(const Palette &Pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index 7d4b064e2a..cc7d526ffe 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -117,11 +117,11 @@ void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint } int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const Palette &pal, uint8 firstColor, uint16 numColors, bool skipSpecialColors) { - int m = 0x7fff; + int m = 0x7FFF; int r = 0x101; for (int i = 0; i < numColors; i++) { - if (skipSpecialColors && i >= 0xc0 && i <= 0xc3) + if (skipSpecialColors && i >= 0xC0 && i <= 0xC3) continue; int v = paletteEntry[0] - pal[(i + firstColor) * 3 + 0]; @@ -162,6 +162,34 @@ void Screen_v2::getFadeParams(const Palette &pal, int delay, int &delayInc, int } } +bool Screen_v2::timedPaletteFadeStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 totalTime) { + Palette &p1 = getPalette(1); + + bool res = false; + for (int i = 0; i < p1.getNumColors() * 3; i++) { + uint8 out = 0; + + if (elapsedTime < totalTime) { + int32 d = ((pal2[i] & 0x3F) - (pal1[i] & 0x3F)); + if (d) + res = true; + + int32 val = ((((d << 8) / (int32)totalTime) * (int32)elapsedTime) >> 8); + out = ((pal1[i] & 0x3F) + (int8)val); + } else { + out = p1[i] = (pal2[i] & 0x3F); + res = false; + } + + (*_internFadePalette)[i] = out; + } + + setScreenPalette(*_internFadePalette); + updateScreen(); + + return res; +} + const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) { uint16 shapes = READ_LE_UINT16(shpFile); @@ -283,13 +311,13 @@ void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, if (w1 == 1) { memset(dt, *s, w2); } else { - t = ((((((w2 - w1 + 1) & 0xffff) << 8) / w1) + 0x100) & 0xffff) << 8; + t = ((((((w2 - w1 + 1) & 0xFFFF) << 8) / w1) + 0x100) & 0xFFFF) << 8; int bp = 0; for (int i = 0; i < w1; i++) { int cnt = (t >> 16); - bp += (t & 0xffff); - if (bp > 0xffff) { - bp -= 0xffff; + bp += (t & 0xFFFF); + if (bp > 0xFFFF) { + bp -= 0xFFFF; cnt++; } memset(dt, *s++, cnt); @@ -300,13 +328,13 @@ void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, if (w2 == 1) { *dt = *s; } else { - t = (((((w1 - w2) & 0xffff) << 8) / w2) & 0xffff) << 8; + t = (((((w1 - w2) & 0xFFFF) << 8) / w2) & 0xFFFF) << 8; int bp = 0; for (int i = 0; i < w2; i++) { *dt++ = *s++; - bp += (t & 0xffff); - if (bp > 0xffff) { - bp -= 0xffff; + bp += (t & 0xFFFF); + if (bp > 0xFFFF) { + bp -= 0xFFFF; s++; } s += (t >> 16); @@ -322,6 +350,48 @@ void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, addDirtyRect(x2, y2, w2, h2); } +void Screen_v2::copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes) { + const uint8 *src = getPagePtr(srcPage) + srcPos; + uint8 *dst = getPagePtr(dstPage) + dstPos; + memcpy(dst, src, numBytes); +} + +void Screen_v2::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX, int dstY, int dstW, int dstH, const ScreenDim *dim, bool flag) { + int x0 = dim->sx << 3; + int y0 = dim->sy; + int w0 = dim->w << 3; + int h0 = dim->h; + + int x1 = dstX; + int y1 = dstY; + int w1 = dstW; + int h1 = dstH; + + int x2, y2, w2; + + calcBounds(w0, h0, x1, y1, w1, h1, x2, y2, w2); + + const uint8 *src = getPagePtr(srcPage) + (320 * srcH) + srcW; + uint8 *dst = getPagePtr(dstPage) + 320 * (y0 + y1); + + for (int y = 0; y < h1; y++) { + const uint8 *s = src + x2; + uint8 *d = dst + x0 + x1; + + if (flag) + d += (h1 >> 1); + + for (int x = 0; x < w1; x++) { + if (*s) + *d = *s; + s++; + d++; + } + dst += 320; + src += 320; + } +} + bool Screen_v2::calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2) { x2 = 0; y2 = 0; diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h index f84c923128..6f4d67136a 100644 --- a/engines/kyra/screen_v2.h +++ b/engines/kyra/screen_v2.h @@ -43,6 +43,8 @@ public: virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); + bool timedPaletteFadeStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 totalTime); + // shape handling uint8 *getPtrToShape(uint8 *shpFile, int shape); const uint8 *getPtrToShape(const uint8 *shpFile, int shape); @@ -66,6 +68,10 @@ public: // special WSA handling void wsaFrameAnimationStep(int x1, int y1, int x2, int y2, int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim); + + // used in non-interactive HoF/LoL demos + void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); + void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false); protected: uint8 *_wsaFrameAnimBuffer; }; diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp index c07c41f706..e5ccbf2c2e 100644 --- a/engines/kyra/script_eob.cpp +++ b/engines/kyra/script_eob.cpp @@ -175,7 +175,7 @@ void EoBInfProcessor::run(int func, int flags) { uint16 f = _vm->_levelBlockProperties[func].flags; - uint16 subFlags = ((f & 0xfff8) >> 3) | 0xe0; + uint16 subFlags = ((f & 0xFFF8) >> 3) | 0xE0; if (!(flags & subFlags)) return; @@ -233,7 +233,7 @@ void EoBInfProcessor::reset() { } const char *EoBInfProcessor::getString(uint16 index) { - if (index == 0xffff) + if (index == 0xFFFF) return 0; int8 *res = _scriptData + READ_LE_UINT16(_scriptData); @@ -348,7 +348,7 @@ int EoBInfProcessor::oeob_movePartyOrObject(int8 *data) { int8 *pos = data; int8 a = *pos++; - uint16 b = 0xffff; + uint16 b = 0xFFFF; uint16 c = 0; uint16 d = 0; @@ -972,7 +972,7 @@ int EoBInfProcessor::oeob_eval_v2(int8 *data) { case 9: switch (*pos++) { case -36: - _stack[_stackIndex++] = _vm->_itemTypes[_vm->_items[_vm->_lastUsedItem].type].extraProperties & 0x7f; + _stack[_stackIndex++] = _vm->_itemTypes[_vm->_items[_vm->_lastUsedItem].type].extraProperties & 0x7F; break; case -31: _stack[_stackIndex++] = _vm->_items[_vm->_lastUsedItem].type; @@ -1097,7 +1097,7 @@ int EoBInfProcessor::oeob_eval_v2(int8 *data) { case 26: a = 0; for (i = 0; i < 6; i++) { - if (_vm->testCharacter(i, 0x0f)) + if (_vm->testCharacter(i, 0x0F)) a++; } _stack[_stackIndex++] = a; @@ -1260,7 +1260,7 @@ int EoBInfProcessor::oeob_loadNewLevelOrMonsters(int8 *data) { pos += 2; uint8 dir = (uint8)*pos++; - if (dir != 0xff) + if (dir != 0xFF) _vm->_currentDirection = dir; for (int i = 0; i < 30; i++) @@ -1328,11 +1328,11 @@ int EoBInfProcessor::oeob_createItem_v1(int8 *data) { uint8 itmPos = *pos++; if (itm) { - if (block == 0xffff && !_vm->_itemInHand) { + if (block == 0xFFFF && !_vm->_itemInHand) { _vm->setHandItem(itm); debugC(5, kDebugLevelScript, " - create hand item '%d'", itm); - } else if (block != 0xffff) { - _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block & 0x3ff].drawObjects, block, itm, itmPos); + } else if (block != 0xFFFF) { + _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block & 0x3FF].drawObjects, block, itm, itmPos); debugC(5, kDebugLevelScript, " - create item '%d' on block '0x%.04X', position '%d'", itm, block, itmPos); } } @@ -1363,19 +1363,19 @@ int EoBInfProcessor::oeob_createItem_v2(int8 *data) { if (!itm) return pos - data; - if (block == 0xffff) { + if (block == 0xFFFF) { if (!_vm->_itemInHand) { _vm->setHandItem(itm); debugC(5, kDebugLevelScript, " - create hand item '%d' (value '%d', flags '0x%X', icon number '%d')", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon); } else { - _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[_vm->_currentBlock & 0x3ff].drawObjects, _vm->_currentBlock, itm, _itemPos[_vm->rollDice(1, 2, -1)]); + _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[_vm->_currentBlock & 0x3FF].drawObjects, _vm->_currentBlock, itm, _itemPos[_vm->rollDice(1, 2, -1)]); debugC(5, kDebugLevelScript, " - create item '%d' (value '%d', flags '0x%X', icon number '%d') on current block", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon); } - } else if (block == 0xfffe) { - _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[_vm->_currentBlock & 0x3ff].drawObjects, _vm->_currentBlock, itm, _itemPos[(_vm->_currentDirection << 2) + _vm->rollDice(1, 2, -1)]); + } else if (block == 0xFFFE) { + _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[_vm->_currentBlock & 0x3FF].drawObjects, _vm->_currentBlock, itm, _itemPos[(_vm->_currentDirection << 2) + _vm->rollDice(1, 2, -1)]); debugC(5, kDebugLevelScript, " - create item '%d' (value '%d', flags '0x%X', icon number '%d') on current block", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon); } else { - _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block & 0x3ff].drawObjects, block, itm, itmPos); + _vm->setItemPosition((Item *)&_vm->_levelBlockProperties[block & 0x3FF].drawObjects, block, itm, itmPos); debugC(5, kDebugLevelScript, " - create item '%d' (value '%d', flags '0x%X', icon number '%d') on block '0x%.04X', position '%d'", itm, _vm->_items[itm].value, _vm->_items[itm].flags, _vm->_items[itm].icon, block, itmPos); } @@ -1530,7 +1530,7 @@ int EoBInfProcessor::oeob_dialogue(int8 *data) { break; case -40: - _dlgResult = _vm->runDialogue(READ_LE_UINT16(pos), READ_LE_UINT16(pos + 6) == 0xffff ? 2 : 3, getString(READ_LE_UINT16(pos + 2)), getString(READ_LE_UINT16(pos + 4)), getString(READ_LE_UINT16(pos + 6))); + _dlgResult = _vm->runDialogue(READ_LE_UINT16(pos), READ_LE_UINT16(pos + 6) == 0xFFFF ? 2 : 3, getString(READ_LE_UINT16(pos + 2)), getString(READ_LE_UINT16(pos + 4)), getString(READ_LE_UINT16(pos + 6))); pos += 8; break; diff --git a/engines/kyra/script_eob.h b/engines/kyra/script_eob.h index fc8b4cfc31..ff3a5e0fac 100644 --- a/engines/kyra/script_eob.h +++ b/engines/kyra/script_eob.h @@ -91,7 +91,7 @@ private: EoBCoreEngine *_vm; Screen_EoB *_screen; - typedef Common::Functor1Mem<int8*, int, EoBInfProcessor> InfProc; + typedef Common::Functor1Mem<int8 *, int, EoBInfProcessor> InfProc; struct InfOpcode : private Common::NonCopyable { InfOpcode(InfProc *p, const char *d) : proc(p), desc(d) {} ~InfOpcode() { delete proc; } diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index fca83ae632..5bf8f6e78d 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -253,7 +253,7 @@ int KyraEngine_HoF::o2_displayWsaSequentialFrames(EMCState *script) { uint16 currentFrame = stackPos(3); uint16 lastFrame = stackPos(4); uint16 index = stackPos(5); - uint16 copyParam = stackPos(6) | 0xc000; + uint16 copyParam = stackPos(6) | 0xC000; _screen->hideMouse(); @@ -278,7 +278,7 @@ int KyraEngine_HoF::o2_displayWsaSequence(EMCState *script) { const int frameDelay = stackPos(2) * _tickLength; const int index = stackPos(3); const bool doUpdate = (stackPos(4) != 0); - const uint16 copyParam = stackPos(5) | 0xc000; + const uint16 copyParam = stackPos(5) | 0xC000; _screen->hideMouse(); @@ -319,8 +319,8 @@ int KyraEngine_HoF::o2_drawShape(EMCState *script) { uint8 *shp = getShapePtr(stackPos(0) + 64); int x = stackPos(1); int y = stackPos(2); - uint8 dsFlag = stackPos(3) & 0xff; - uint8 modeFlag = stackPos(4) & 0xff; + uint8 dsFlag = stackPos(3) & 0xFF; + uint8 modeFlag = stackPos(4) & 0xFF; if (modeFlag) { _screen->drawShape(2, shp, x, y, 2, dsFlag ? 1 : 0); @@ -918,7 +918,7 @@ int KyraEngine_HoF::o2_useItemOnMainChar(EMCState *script) { tmpScript.regs[0] = _mainCharacter.sceneId; int oldVocH = _vocHigh; - _vocHigh = 0x5a; + _vocHigh = 0x5A; while (_emc->isValid(&tmpScript)) _emc->run(&tmpScript); @@ -955,7 +955,7 @@ int KyraEngine_HoF::o2_pressColorKey(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_pressColorKey(%p) (%d)", (const void *)script, stackPos(0)); for (int i = 6; i; i--) _inputColorCode[i] = _inputColorCode[i - 1]; - _inputColorCode[0] = stackPos(0) & 0xff; + _inputColorCode[0] = stackPos(0) & 0xFF; for (int i = 0; i < 7; i++) { if (_presetColorCode[i] != _inputColorCode[6 - i]) return _dbgPass; @@ -1023,8 +1023,8 @@ int KyraEngine_HoF::o2_getColorCodeValue(EMCState *script) { int KyraEngine_HoF::o2_setColorCodeValue(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_setColorCodeValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _presetColorCode[stackPos(0)] = stackPos(1) & 0xff; - return stackPos(1) & 0xff; + _presetColorCode[stackPos(0)] = stackPos(1) & 0xFF; + return stackPos(1) & 0xFF; } int KyraEngine_HoF::o2_countItemInstances(EMCState *script) { @@ -1495,7 +1495,7 @@ void KyraEngine_HoF::setupOpcodeTable() { OpcodeUnImpl(); OpcodeUnImpl(); Opcode(o2_setCharacterAnimFrame); - // 0x0c + // 0x0C Opcode(o2_setCharacterFacingOverwrite); Opcode(o2_trySceneChange); Opcode(o2_moveCharacter); @@ -1515,7 +1515,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_wsaOpen); Opcode(o2_displayWsaSequentialFrames); Opcode(o2_displayWsaSequence); - // 0x1c + // 0x1C Opcode(o2_addItemToInventory); Opcode(o2_drawShape); Opcode(o2_addItemToCurScene); @@ -1536,7 +1536,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o1_setGameFlag); Opcode(o1_setHandItem); Opcode(o1_removeHandItem); - // 0x2c + // 0x2C Opcode(o1_getMouseState); Opcode(o1_hideMouse); Opcode(o2_addSpecialExit); @@ -1556,7 +1556,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_setTimerDelay); Opcode(o2_setScaleTableItem); Opcode(o2_setDrawLayerTableItem); - // 0x3c + // 0x3C Opcode(o2_setCharPalEntry); Opcode(o2_loadZShapes); Opcode(o2_drawSceneShape); @@ -1576,7 +1576,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_restoreInventoryGfx); Opcode(o2_setSceneAnimPos2); Opcode(o2_update); - // 0x4c + // 0x4C OpcodeUnImpl(); Opcode(o2_fadeScenePal); Opcode(o2_dummy); @@ -1596,7 +1596,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o1_playSoundEffect); Opcode(o2_setSceneAnimPos); Opcode(o1_blockInWalkableRegion); - // 0x5c + // 0x5C Opcode(o1_blockOutWalkableRegion); OpcodeUnImpl(); Opcode(o2_setCauldronState); @@ -1616,7 +1616,7 @@ void KyraEngine_HoF::setupOpcodeTable() { OpcodeUnImpl(); Opcode(o2_playFireflyScore); Opcode(o2_waitForConfirmationClick); - // 0x6c + // 0x6C Opcode(o2_encodeShape); Opcode(o2_defineRoomEntrance); Opcode(o2_runAnimationScript); @@ -1636,7 +1636,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_defineScene); Opcode(o2_addCauldronStateTableEntry); Opcode(o2_setCountDown); - // 0x7c + // 0x7C Opcode(o2_getCountDown); Opcode(o2_dummy); Opcode(o2_dummy); @@ -1656,7 +1656,7 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_removeItemFromScene); Opcode(o2_initObject); Opcode(o2_npcChat); - // 0x8c + // 0x8C Opcode(o2_deinitObject); Opcode(o2_playTimSequence); Opcode(o2_makeBookOrCauldronAppear); @@ -1676,27 +1676,27 @@ void KyraEngine_HoF::setupOpcodeTable() { Opcode(o2_customChatFinish); Opcode(o2_setupSceneAnimation); Opcode(o2_stopSceneAnimation); - // 0x9c + // 0x9C Opcode(o2_disableTimer); Opcode(o2_enableTimer); Opcode(o2_setTimerCountdown); Opcode(o2_processPaletteIndex); - // 0xa0 + // 0xA0 Opcode(o2_updateTwoSceneAnims); Opcode(o2_getRainbowRoomData); Opcode(o2_drawSceneShapeEx); Opcode(o2_midiSoundFadeout); - // 0xa4 + // 0xA4 Opcode(o2_getSfxDriver); Opcode(o2_getVocSupport); Opcode(o2_getMusicDriver); Opcode(o2_setVocHigh); - // 0xa8 + // 0xA8 Opcode(o2_getVocHigh); Opcode(o2_zanthiaChat); Opcode(o2_isVoiceEnabled); Opcode(o2_isVoicePlaying); - // 0xac + // 0xAC Opcode(o2_stopVoicePlaying); Opcode(o2_getGameLanguage); Opcode(o2_demoFinale); diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index db9e01cabb..22d5e9fd7c 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -1774,7 +1774,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_blockInWalkableRegion); Opcode(o1_blockOutWalkableRegion); Opcode(o1_walkPlayerToPoint); - // 0x0c + // 0x0C Opcode(o1_dropItemInScene); Opcode(o1_drawAnimShapeIntoScene); Opcode(o1_setHandItem); @@ -1794,7 +1794,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_phaseInSameScene); Opcode(o1_setScenePhasingFlag); Opcode(o1_resetScenePhasingFlag); - // 0x1c + // 0x1C Opcode(o1_queryScenePhasingFlag); Opcode(o1_sceneToDirection); Opcode(o1_setBirthstoneGem); @@ -1814,7 +1814,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_openWSAFile); Opcode(o1_closeWSAFile); Opcode(o1_runWSAFromBeginningToEnd); - // 0x2c + // 0x2C Opcode(o1_displayWSAFrame); Opcode(o1_enterNewScene); Opcode(o1_setSpecialEnterXAndY); @@ -1834,7 +1834,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_getCharacterY); Opcode(o1_setCharacterFacing); Opcode(o1_copyWSARegion); - // 0x3c + // 0x3C Opcode(o1_printText); Opcode(o1_getRand); Opcode(o1_loadSoundFile); @@ -1854,7 +1854,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_placeCharacterInOtherScene); Opcode(o1_getKey); Opcode(o1_specificItemInInventory); - // 0x4c + // 0x4C Opcode(o1_popMobileNPCIntoScene); Opcode(o1_mobileCharacterInScene); Opcode(o1_hideMobileCharacter); @@ -1874,7 +1874,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_setCharacterMovementDelay); Opcode(o1_getCharacterFacing); Opcode(o1_bkgdScrollSceneAndMasksRight); - // 0x5c + // 0x5C Opcode(o1_dispelMagicAnimation); Opcode(o1_findBrightestFireberry); Opcode(o1_setFireberryGlowPalette); @@ -1894,7 +1894,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_addItemToInventory); Opcode(o1_intPrint); Opcode(o1_shakeScreen); - // 0x6c + // 0x6C Opcode(o1_createAmuletJewel); Opcode(o1_setSceneAnimCurrXY); Opcode(o1_poisonBrandonAndRemaps); @@ -1914,7 +1914,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_setMousePos); Opcode(o1_getMouseState); Opcode(o1_setEntranceMouseCursorTrack); - // 0x7c + // 0x7C Opcode(o1_itemAppearsOnGround); Opcode(o1_setNoDrawShapesFlag); Opcode(o1_fadeEntirePalette); @@ -1934,7 +1934,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_getScaleDepthTableValue); Opcode(o1_setScaleDepthTableValue); Opcode(o1_message); - // 0x8c + // 0x8C Opcode(o1_checkClickOnNPC); Opcode(o1_getFoyerItem); Opcode(o1_setFoyerItem); @@ -1954,7 +1954,7 @@ void KyraEngine_LoK::setupOpcodeTable() { Opcode(o1_fillRect); Opcode(o1_vocUnload); Opcode(o1_vocLoad); - // 0x9c + // 0x9C Opcode(o1_dummy); } #undef Opcode diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 9c0fe21ad4..0bbe66f530 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -126,7 +126,7 @@ int LoLEngine::olol_moveParty(EMCState *script) { mode = (mode - 6 - _currentDirection) & 3; Button b; - b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xfe; + b.data0Val2 = b.data1Val2 = b.data2Val2 = 0xFE; b.data0Val3 = b.data1Val3 = b.data2Val3 = 0x01; switch (mode) { @@ -268,7 +268,7 @@ int LoLEngine::olol_makeItem(EMCState *script) { int LoLEngine::olol_placeMoveLevelItem(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_placeMoveLevelItem(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - placeMoveLevelItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3) & 0xff, stackPos(4) & 0xff, stackPos(5)); + placeMoveLevelItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, stackPos(4) & 0xFF, stackPos(5)); return 1; } @@ -321,7 +321,7 @@ int LoLEngine::olol_getItemPara(EMCState *script) { case 14: return p->unkB; case 15: - return i->shpCurFrame_flg & 0x1fff; + return i->shpCurFrame_flg & 0x1FFF; case 16: return p->flags; case 17: @@ -397,7 +397,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) { break; case 1: - c->raceClassSex = e & 0x0f; + c->raceClassSex = e & 0x0F; break; case 5: @@ -478,19 +478,19 @@ int LoLEngine::olol_loadDoorShapes(EMCState *script) { _wllWallFlags[i + 3] |= 7; int t = i % 5; if (t == 4) - _wllWallFlags[i + 3] &= 0xf8; + _wllWallFlags[i + 3] &= 0xF8; if (t == 3) - _wllWallFlags[i + 3] &= 0xfd; + _wllWallFlags[i + 3] &= 0xFD; } if (stackPos(3)) { for (int i = 3; i < 13; i++) - _wllWallFlags[i] &= 0xfd; + _wllWallFlags[i] &= 0xFD; } if (stackPos(4)) { for (int i = 13; i < 23; i++) - _wllWallFlags[i] &= 0xfd; + _wllWallFlags[i] &= 0xFD; } return 1; @@ -683,7 +683,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) { break; case 2: - _currentLevel = b & 0xff; + _currentLevel = b & 0xFF; break; case 3: @@ -691,7 +691,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) { break; case 4: - _brightness = b & 0xff; + _brightness = b & 0xFF; break; case 5: @@ -717,20 +717,20 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) { break; case 9: - _lampOilStatus = b & 0xff; + _lampOilStatus = b & 0xFF; break; case 10: - _sceneDefaultUpdate = b & 0xff; + _sceneDefaultUpdate = b & 0xFF; gui_toggleButtonDisplayMode(0, 0); break; case 11: - _compassBroken = a & 0xff; + _compassBroken = a & 0xFF; break; case 12: - _drainMagic = a & 0xff; + _drainMagic = a & 0xFF; break; default: @@ -763,9 +763,9 @@ int LoLEngine::olol_checkEquippedItemScriptFlags(EMCState *script) { int LoLEngine::olol_setDoorState(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setDoorState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); if (stackPos(1)) - _levelBlockProperties[stackPos(0)].flags = (_levelBlockProperties[stackPos(0)].flags & 0xef) | 0x20; + _levelBlockProperties[stackPos(0)].flags = (_levelBlockProperties[stackPos(0)].flags & 0xEF) | 0x20; else - _levelBlockProperties[stackPos(0)].flags &= 0xdf; + _levelBlockProperties[stackPos(0)].flags &= 0xDF; return 1; } @@ -784,7 +784,7 @@ int LoLEngine::olol_assignLevelDecorationShape(EMCState *script) { int LoLEngine::olol_resetBlockShapeAssignment(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_resetBlockShapeAssignment(%p) (%d)", (const void *)script, stackPos(0)); - uint8 v = stackPos(0) & 0xff; + uint8 v = stackPos(0) & 0xFF; memset(_wllShapeMap + 3, v, 5); memset(_wllShapeMap + 13, v, 5); return 1; @@ -823,7 +823,7 @@ int LoLEngine::olol_initMonster(EMCState *script) { l->type = stackPos(4); l->properties = &_monsterProperties[l->type]; l->direction = l->facing << 1; - l->hitPoints = (l->properties->hitPoints * _monsterModifiers[_monsterDifficulty]) >> 8; + l->hitPoints = (l->properties->hitPoints * _monsterModifiers1[_monsterDifficulty]) >> 8; if (_currentLevel != 12 || l->type != 2) l->hitPoints = (l->hitPoints * (rollDice(1, 128) + 192)) >> 8; @@ -842,7 +842,7 @@ int LoLEngine::olol_initMonster(EMCState *script) { l->destDirection = l->direction; for (int ii = 0; ii < 4; ii++) - l->equipmentShapes[ii] = stackPos(7 + ii) & 0xff; + l->equipmentShapes[ii] = stackPos(7 + ii) & 0xFF; checkSceneUpdateNeed(l->block); return i; @@ -927,7 +927,7 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) { stackPos(35), stackPos(36), stackPos(37), stackPos(38), stackPos(39), stackPos(40), stackPos(41)); LoLMonsterProperty *l = &_monsterProperties[stackPos(0)]; - l->shapeIndex = stackPos(1) & 0xff; + l->shapeIndex = stackPos(1) & 0xFF; int shpWidthMax = 0; @@ -1079,7 +1079,7 @@ int LoLEngine::olol_addRemoveCharacter(EMCState *script) { if (!(_characters[i].flags & 1) || _characters[i].id != id) continue; - _characters[i].flags &= 0xfffe; + _characters[i].flags &= 0xFFFE; calcCharPortraitXpos(); if (_selectedCharacter == i) @@ -1192,7 +1192,7 @@ int LoLEngine::olol_changeMonsterStat(EMCState *script) { if (stackPos(0) == -1) return 1; - LoLMonster *m = &_monsters[stackPos(0) & 0x7fff]; + LoLMonster *m = &_monsters[stackPos(0) & 0x7FFF]; int16 d = stackPos(2); uint16 x = 0; @@ -1208,7 +1208,7 @@ int LoLEngine::olol_changeMonsterStat(EMCState *script) { break; case 2: - calcCoordinates(x, y, d, m->x & 0xff, m->y & 0xff); + calcCoordinates(x, y, d, m->x & 0xFF, m->y & 0xFF); if (!walkMonsterCheckDest(x, y, m, 7)) placeMonster(m, x, y); break; @@ -1233,7 +1233,7 @@ int LoLEngine::olol_getMonsterStat(EMCState *script) { if (stackPos(0) == -1) return 0; - LoLMonster *m = &_monsters[stackPos(0) & 0x7fff]; + LoLMonster *m = &_monsters[stackPos(0) & 0x7FFF]; int d = stackPos(1); switch (d) { @@ -1318,8 +1318,8 @@ int LoLEngine::olol_drawExitButton(EMCState *script) { int w = _screen->getTextWidth(str); if (_flags.use16ColorMode) { - gui_drawBox(x - offs - w, y - 9, w + offs, 9, 0xee, 0xcc, 0x11); - _screen->printText(str, x - (offs >> 1) - w, y - 7, 0xbb, 0); + gui_drawBox(x - offs - w, y - 9, w + offs, 9, 0xEE, 0xCC, 0x11); + _screen->printText(str, x - (offs >> 1) - w, y - 7, 0xBB, 0); } else { gui_drawBox(x - offs - w, y - 9, w + offs, 9, 136, 251, 252); _screen->printText(str, x - (offs >> 1) - w, y - 7, 144, 0); @@ -1497,7 +1497,7 @@ int LoLEngine::olol_distanceAttack(EMCState *script) { uint16 y = 0; calcCoordinates(x, y, stackPos(2), fX, fY); - if (launchObject(stackPos(0), stackPos(1), x, y, stackPos(5), stackPos(6) << 1, stackPos(7), stackPos(8), 0x3f)) + if (launchObject(stackPos(0), stackPos(1), x, y, stackPos(5), stackPos(6) << 1, stackPos(7), stackPos(8), 0x3F)) return 1; deleteItem(stackPos(1)); @@ -1532,7 +1532,7 @@ int LoLEngine::olol_moveBlockObjects(EMCState *script) { // WORKAROUND for script bug // Items would vanish when thrown towards the stairs // in white tower level 3. - if (_currentLevel == 21 && level == 21 && destBlock == 0x3e0) { + if (_currentLevel == 21 && level == 21 && destBlock == 0x3E0) { level = 20; destBlock = 0x0247; } @@ -1544,7 +1544,7 @@ int LoLEngine::olol_moveBlockObjects(EMCState *script) { if (!includeMonsters) continue; - l &= 0x7fff; + l &= 0x7FFF; LoLMonster *m = &_monsters[l]; @@ -1558,7 +1558,7 @@ int LoLEngine::olol_moveBlockObjects(EMCState *script) { if (!(_itemsInPlay[l].shpCurFrame_flg & 0x4000) || !includeItems) continue; - placeMoveLevelItem(l, level, destBlock, _itemsInPlay[l].x & 0xff, _itemsInPlay[l].y & 0xff, _itemsInPlay[l].flyingHeight); + placeMoveLevelItem(l, level, destBlock, _itemsInPlay[l].x & 0xFF, _itemsInPlay[l].y & 0xFF, _itemsInPlay[l].flyingHeight); res = 1; if (!runScript || level != _currentLevel) @@ -1617,7 +1617,7 @@ int LoLEngine::olol_dummy1(EMCState *script) { int LoLEngine::olol_suspendMonster(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_suspendMonster(%p) (%d)", (const void *)script, stackPos(0)); - LoLMonster *m = &_monsters[stackPos(0) & 0x7fff]; + LoLMonster *m = &_monsters[stackPos(0) & 0x7FFF]; setMonsterMode(m, 14); checkSceneUpdateNeed(m->block); placeMonster(m, 0, 0); @@ -1732,11 +1732,11 @@ int LoLEngine::olol_getItemOnPos(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getItemOnPos(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int pX = stackPos(1); if (pX != -1) - pX &= 0xff; + pX &= 0xFF; int pY = stackPos(2); if (pY != -1) - pY &= 0xff; + pY &= 0xFF; int o = (stackPos(3) || _emcLastItem == -1) ? stackPos(0) : _emcLastItem; @@ -1744,19 +1744,19 @@ int LoLEngine::olol_getItemOnPos(EMCState *script) { while (_emcLastItem) { if (_emcLastItem & 0x8000) { - o = _emcLastItem & 0x7fff; + o = _emcLastItem & 0x7FFF; _emcLastItem = _levelBlockProperties[o].assignedObjects; continue; } - if (pX != -1 && (_itemsInPlay[_emcLastItem].x & 0xff) != pX) { - o = _emcLastItem & 0x7fff; + if (pX != -1 && (_itemsInPlay[_emcLastItem].x & 0xFF) != pX) { + o = _emcLastItem & 0x7FFF; _emcLastItem = _levelBlockProperties[o].assignedObjects; continue; } - if (pY != -1 && (_itemsInPlay[_emcLastItem].y & 0xff) != pY) { - o = _emcLastItem & 0x7fff; + if (pY != -1 && (_itemsInPlay[_emcLastItem].y & 0xFF) != pY) { + o = _emcLastItem & 0x7FFF; _emcLastItem = _levelBlockProperties[o].assignedObjects; continue; } @@ -1835,7 +1835,7 @@ int LoLEngine::olol_assignCustomSfx(EMCState *script) { return 0; uint16 t = READ_LE_UINT16(&_ingameSoundIndex[i << 1]); - if (t == 0xffff) + if (t == 0xFFFF) return 0; strcpy(_ingameSoundList[t], c); @@ -1848,7 +1848,7 @@ int LoLEngine::olol_findAssignedMonster(EMCState *script) { uint16 o = stackPos(1) == -1 ? _levelBlockProperties[stackPos(0)].assignedObjects : findObject(stackPos(1))->nextAssignedObject; while (o) { if (o & 0x8000) - return o & 0x7fff; + return o & 0x7FFF; o = findObject(o)->nextAssignedObject; } return -1; @@ -1861,8 +1861,8 @@ int LoLEngine::olol_checkBlockForMonster(EMCState *script) { uint16 o = _levelBlockProperties[block].assignedObjects; while (o & 0x8000) { - if (id == 0xffff || id == o) - return o & 0x7fff; + if (id == 0xFFFF || id == o) + return o & 0x7FFF; o = findObject(o)->nextAssignedObject; } return -1; @@ -2040,7 +2040,7 @@ int LoLEngine::olol_changeItemTypeOrFlag(EMCState *script) { if (stackPos(1) == 4) i->itemPropertyIndex = val; else if (stackPos(1) == 15) - i->shpCurFrame_flg = (i->shpCurFrame_flg & 0xe000) | (val & 0x1fff); + i->shpCurFrame_flg = (i->shpCurFrame_flg & 0xE000) | (val & 0x1FFF); else val = -1; @@ -2129,7 +2129,7 @@ int LoLEngine::olol_paletteFlash(EMCState *script) { uint8 *d = p2.getData(); for (int i = 0; i < 16; i++) - d[i * 3] = 0x3f; + d[i * 3] = 0x3F; _screen->setScreenPalette(p2); _screen->updateScreen(); diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index 22d0bc4e95..f656b162fd 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -1144,7 +1144,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_dummy); Opcode(o3_dummy); Opcode(o3_getCharacterFrameFromFacing); - // 0x0c + // 0x0C Opcode(o2_setCharacterFacingOverwrite); Opcode(o2_trySceneChange); Opcode(o2_moveCharacter); @@ -1164,7 +1164,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_showAlbum); Opcode(o3_setInventorySlot); Opcode(o3_getInventorySlot); - // 0x1c + // 0x1C Opcode(o3_addItemToInventory); OpcodeUnImpl(); Opcode(o3_addItemToCurScene); @@ -1184,7 +1184,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o1_setGameFlag); Opcode(o1_setHandItem); Opcode(o1_removeHandItem); - // 0x2c + // 0x2C Opcode(o1_getMouseState); Opcode(o1_hideMouse); Opcode(o2_addSpecialExit); @@ -1204,7 +1204,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_makeSecondChanceSave); Opcode(o3_setSceneFilename); OpcodeUnImpl(); - // 0x3c + // 0x3C Opcode(o3_removeItemsFromScene); Opcode(o3_disguiseMalcolm); Opcode(o3_drawSceneShape); @@ -1224,7 +1224,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_dummy); Opcode(o3_setSceneAnimPosAndFrame); Opcode(o2_update); - // 0x4c + // 0x4C Opcode(o3_removeItemInstances); Opcode(o3_dummy); Opcode(o3_disableInventory); @@ -1244,7 +1244,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_playSoundEffect); Opcode(o3_getScore); Opcode(o3_daggerWarning); - // 0x5c + // 0x5C Opcode(o3_blockOutWalkableRegion); Opcode(o3_dummy); Opcode(o3_showSceneStringsMessage); @@ -1264,7 +1264,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_dummy); Opcode(o3_dummy); Opcode(o2_waitForConfirmationClick); - // 0x6c + // 0x6C Opcode(o3_dummy); Opcode(o2_defineRoomEntrance); Opcode(o2_runAnimationScript); @@ -1284,7 +1284,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o2_defineScene); Opcode(o3_setConversationState); OpcodeUnImpl(); - // 0x7c + // 0x7C OpcodeUnImpl(); Opcode(o3_getConversationState); Opcode(o3_dummy); @@ -1304,7 +1304,7 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_dummy); Opcode(o3_dialogStartScript); Opcode(o3_dummy); - // 0x8c + // 0x8C Opcode(o3_dialogEndScript); Opcode(o3_dummy); Opcode(o3_dummy); @@ -1324,27 +1324,27 @@ void KyraEngine_MR::setupOpcodeTable() { Opcode(o3_customChatFinish); Opcode(o3_setupSceneAnimObject); Opcode(o3_removeSceneAnimObject); - // 0x9c + // 0x9C Opcode(o2_disableTimer); Opcode(o2_enableTimer); Opcode(o2_setTimerCountdown); OpcodeUnImpl(); - // 0xa0 + // 0xA0 Opcode(o3_dummy); Opcode(o3_dummy); Opcode(o3_dummy); Opcode(o3_dummy); - // 0xa4 + // 0xA4 OpcodeUnImpl(); OpcodeUnImpl(); OpcodeUnImpl(); Opcode(o2_setVocHigh); - // 0xa8 + // 0xA8 Opcode(o2_getVocHigh); OpcodeUnImpl(); OpcodeUnImpl(); OpcodeUnImpl(); - // 0xac + // 0xAC OpcodeUnImpl(); Opcode(o3_dummy); OpcodeUnImpl(); diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 177d7993a0..ba0f62a2b4 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -297,20 +297,20 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { memcpy(filename, text+1, end-1-text); } - const bool isPC98 = (_vm->gameFlags().platform == Common::kPlatformPC98); + const bool sjisMode = (_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode); if (filename[0] && (_vm->speechEnabled() || !_vm->gameFlags().isTalkie)) - _vm->sound()->voicePlay(filename); + _vm->sound()->voicePlay(filename, 0, 255, 255, !_vm->gameFlags().isTalkie); if (text[0] == '$') text = strchr(text + 1, '$') + 1; - if (!isPC98) + if (!_vm->gameFlags().use16ColorMode) setupTextPalette((flags < 0) ? 1 : flags, 0); if (flags < 0) { static const uint8 colorMap[] = { 0x00, 0xF0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - _screen->setFont(isPC98 ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); + _screen->setFont(sjisMode ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); _screen->setTextColorMap(colorMap); _screen->_charWidth = -2; } @@ -335,7 +335,7 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { int width = _screen->getTextWidth(str); if (flags >= 0) { - if (isPC98) { + if (_vm->gameFlags().use16ColorMode) { static const uint8 colorMap[] = { 0xE1, 0xE1, 0xC1, 0xA1, 0x81, 0x61 }; _screen->printText(str, (320 - width) >> 1, 160 + heightAdd, colorMap[flags], 0x00); } else { @@ -359,7 +359,7 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags) { if (flags < 0) { static const uint8 colorMap[] = { 0x00, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00 }; - _screen->setFont(isPC98 ? Screen::FID_SJIS_FNT : Screen::FID_INTRO_FNT); + _screen->setFont(sjisMode ? Screen::FID_SJIS_FNT : Screen::FID_INTRO_FNT); _screen->setTextColorMap(colorMap); _screen->_charWidth = 0; } @@ -377,7 +377,7 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags, uint8 color) { if (flags == 255) return; - _screen->setFont(_vm->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_INTRO_FNT); + _screen->setFont((_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_INTRO_FNT); static const uint8 colorMap[] = { 0x00, 0xA0, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; _screen->setTextColorMap(colorMap); @@ -393,14 +393,14 @@ void TIMInterpreter::displayText(uint16 textId, int16 flags, uint8 color) { int y = 0; if (_vm->gameFlags().use16ColorMode) { - if (color == 0xda) - color = 0xa1; - else if (color == 0xf2) - color = 0xe1; + if (color == 0xDA) + color = 0xA1; + else if (color == 0xF2) + color = 0xE1; else if (flags < 0) - color = 0xe1; + color = 0xE1; else - color = 0xc1; + color = 0xC1; } while (str[0]) { @@ -736,7 +736,7 @@ int TIMInterpreter::cmd_playVocFile(const uint16 *param) { const int volume = (param[1] * 255) / 100; if (index < ARRAYSIZE(_vocFiles) && !_vocFiles[index].empty()) - _vm->sound()->voicePlay(_vocFiles[index].c_str(), 0, volume, true); + _vm->sound()->voicePlay(_vocFiles[index].c_str(), 0, volume, 255, true); else if (index == 7 && !_vm->gameFlags().isTalkie) _vm->sound()->playTrack(index); else @@ -1083,7 +1083,7 @@ int TIMInterpreter_LoL::cmd_dialogueBox(const uint16 *param) { int cnt = 0; for (int i = 1; i < 4; i++) { - if (param[i] != 0xffff) { + if (param[i] != 0xFFFF) { tmpStr[i-1] = getTableString(param[i]); cnt++; } else { diff --git a/engines/kyra/sequences_darkmoon.cpp b/engines/kyra/sequences_darkmoon.cpp index d4f5c847fd..d2e6e85218 100644 --- a/engines/kyra/sequences_darkmoon.cpp +++ b/engines/kyra/sequences_darkmoon.cpp @@ -867,7 +867,7 @@ void DarkMoonEngine::seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *da int16 nextY = i ? items[i].y + items[i].size + (items[i].size >> 2) : dm->h; const char *posOld = pos; - pos = strchr(pos, 0x0d); + pos = strchr(pos, 0x0D); if (!pos) pos = strchr(posOld, 0x00); @@ -893,7 +893,7 @@ void DarkMoonEngine::seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *da items[i + 1].dataType = 0; int l = pos - posOld; - if (items[i + 1].crlf != 0x0d) + if (items[i + 1].crlf != 0x0D) l++; delete[] items[i + 1].str; @@ -1071,7 +1071,7 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) { uint32 end = 0; - for (const DarkMoonAnimCommand *s = _config->animData[index]; s->command != 0xff && !_vm->skipFlag() && !_vm->shouldQuit(); s++) { + for (const DarkMoonAnimCommand *s = _config->animData[index]; s->command != 0xFF && !_vm->skipFlag() && !_vm->shouldQuit(); s++) { int palIndex = _config->mode == kFinale ? (s->pal + 1) : s->pal; int x = s->x1; int y = s->y1; @@ -1187,7 +1187,7 @@ void DarkmoonSequenceHelper::animCommand(int index, int del) { case 6: // play sound effect - if (s->obj != 0xff) + if (s->obj != 0xFF) _vm->snd_playSoundEffect(s->obj); break; diff --git a/engines/kyra/sequences_eob.cpp b/engines/kyra/sequences_eob.cpp index 4a9f7d8a65..0fec386485 100644 --- a/engines/kyra/sequences_eob.cpp +++ b/engines/kyra/sequences_eob.cpp @@ -706,7 +706,7 @@ void EoBIntroPlayer::waterdeepExit() { _vm->delay(60 * _vm->_tickLength); for (int i = 0; i < 56 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) { - uint32 end = _vm->_system->getMillis() +_vm->_tickLength; + uint32 end = _vm->_system->getMillis() + _vm->_tickLength; _screen->copyRegion(0, 136 + i, 80, 16, 160, 56 - i, 2, 0, Screen::CR_NO_P_CHECK); _screen->copyRegion(160, 0, 80, 72 - i, 160, 96 + i, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); @@ -1061,7 +1061,7 @@ void EoBEngine::seq_playFinale() { gui_drawBox(0, 0, 176, 175, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill); _txt->printDialogueText(51, _moreStrings[0]); - if (!checkScriptFlags(0x1ffe)) { + if (!checkScriptFlags(0x1FFE)) { _screen->fadeToBlack(); return; } diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index f2abfb81dc..231337e6d4 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -21,94 +21,659 @@ */ #include "kyra/kyra_hof.h" -#include "kyra/timer.h" +#include "kyra/screen_hof.h" +#include "kyra/screen_lol.h" #include "kyra/resource.h" #include "kyra/sound.h" +#include "kyra/sequences_hof.h" +#include "kyra/timer.h" #include "common/system.h" namespace Kyra { -void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { - seq_init(); +enum SequenceID { + kSequenceNoLooping = -1, + kSequenceVirgin = 0, + kSequenceWestwood, + kSequenceTitle, + kSequenceOverview, + kSequenceLibrary, + kSequenceHand, + kSequencePoint, + kSequenceZanfaun, + + kSequenceFunters, + kSequenceFerb, + kSequenceFish, + kSequenceFheep, + kSequenceFarmer, + kSequenceFuards, + kSequenceFirates, + kSequenceFrash, + + kSequenceHoFDemoVirgin, + kSequenceHoFDemoWestwood, + kSequenceHoFDemoTitle, + kSequenceHoFDemoHill, + kSequenceHoFDemoOuthome, + kSequenceHoFDemoWharf, + kSequenceHoFDemoDinob, + kSequenceHoFDemoFisher, + +// The following enums remain active even if LoL is disabled + kSequenceLoLDemoScene1, + kSequenceLoLDemoText1, + kSequenceLoLDemoScene2, + kSequenceLoLDemoText2, + kSequenceLoLDemoScene3, + kSequenceLoLDemoText3, + kSequenceLoLDemoScene4, + kSequenceLoLDemoText4, + kSequenceLoLDemoScene5, + kSequenceLoLDemoText5, + kSequenceLoLDemoScene6, + + kSequenceArraySize +}; + +enum NestedSequenceID { + kNestedSequenceFiggle = 0, + + kNestedSequenceOver1, + kNestedSequenceOver2, + kNestedSequenceForest, + kNestedSequenceDragon, + kNestedSequenceDarm, + kNestedSequenceLibrary2, + kNestedSequenceLibrary3, + kNestedSequenceMarco, + kNestedSequenceHand1a, + kNestedSequenceHand1b, + kNestedSequenceHand1c, + kNestedSequenceHand2, + kNestedSequenceHand3, + kNestedSequenceHand4, + + kNestedSequenceHoFDemoWharf2, + kNestedSequenceHoFDemoDinob2, + kNestedSequenceHoFDemoWater, + kNestedSequenceHoFDemoBail, + kNestedSequenceHoFDemoDig, + + kNestedSequenceArraySize +}; + +typedef int (SeqPlayer_HOF::*SeqProc)(WSAMovie_v2 *, int, int, int); + +struct SeqPlayerConfig { + SeqPlayerConfig(const HoFSeqData *data, const SeqProc *callbacks, const SeqProc *nestedCallbacks) : seq(data->seq), seqProc(callbacks), numSeq(data->numSeq), nestedSeq(data->nestedSeq), nestedSeqProc(nestedCallbacks), numNestedSeq(data->numNestedSeq) {} + const HoFSequence *seq; + const SeqProc *seqProc; + int numSeq; + const HoFNestedSequence *nestedSeq; + const SeqProc *nestedSeqProc; + int numNestedSeq; +}; + +class SeqPlayer_HOF { +public: + SeqPlayer_HOF(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *system, bool startupSaveLoadable = false); + ~SeqPlayer_HOF(); + + int play(SequenceID firstScene, SequenceID loopStartScene); + void pause(bool toggle); + + static SeqPlayer_HOF *instance() { return _instance; } + +private: + // Init + void setupCallbacks(); + + // Playback loop + void runLoop(); + void playScenes(); + + bool checkAbortPlayback(); + bool checkPlaybackStatus(); + + bool _abortRequested; + uint32 _pauseStart; + + // Sequence transitions + void doTransition(int type); + void nestedFrameAnimTransition(int srcPage, int dstPage, int delaytime, int steps, int x, int y, int w, int h, int openClose, int directionFlags); + void nestedFrameFadeTransition(const char *cmpFile); + + // Animations + void playAnimation(WSAMovie_v2 *wsaObj, int startFrame, int numFrames, int frameRate, int x, int y, const SeqProc callback, Palette *fadePal1, Palette *fadePal2, int fadeRate, bool restoreScreen); + void playDialogueAnimation(uint16 strID, uint16 soundID, int textColor, int textPosX, int textPosY, int textWidth, WSAMovie_v2 *wsaObj, int animStartFrame, int animLastFrame, int animPosX, int animPosY); + + void startNestedAnimation(int animSlot, int sequenceID); + void closeNestedAnimation(int animSlot); + void unloadNestedAnimation(int animSlot); + void doNestedFrameTransition(int transitionType, int animSlot); + void updateAllNestedAnimations(); + bool updateNestedAnimation(int animSlot); + + struct AnimSlot { + SeqProc callback; + WSAMovie_v2 *movie; + const FrameControl *control; + int16 flags; + uint16 startFrame; + uint16 endFrame; + uint16 frameDelay; + uint32 nextFrame; + uint16 currentFrame; + uint16 lastFrame; + uint16 x; + uint16 y; + uint16 fadeInTransitionType; + uint16 fadeOutTransitionType; + }; + + AnimSlot _animSlots[8]; + + bool _updateAnimations; + uint32 _animDuration; + int _animCurrentFrame; + int _callbackCurrentFrame; + + // The only reason to declare these here (instead of just locally) is being able to increase them after pausing the Engine + uint32 _specialAnimTimeOutTotal; + uint32 _specialAnimFrameTimeOut; + + // Subtitles/Dialogue/Sound + void playSoundEffect(uint16 id, int16 vol); + void playSoundAndDisplaySubTitle(uint16 id); + void printFadingText(uint16 strID, int x, int y, const uint8 *colorMap, uint8 textcolor); + + int displaySubTitle(uint16 strID, uint16 posX, uint16 posY, int duration, uint16 width); + void updateSubTitles(); + char *preprocessString(const char *str, int width); + void waitForSubTitlesTimeout(); + uint32 ticksTillSubTitlesTimeout(); + void resetAllTextSlots(); + + void fadeOutMusic(); + + struct TextSlot { + uint16 strIndex; + uint16 x; + uint16 y; + uint16 width; + int32 duration; + uint32 startTime; + int16 textcolor; + }; - bool allowSkip = (_flags.isDemo && !_flags.isTalkie) || startSeq != kSequenceTitle; + TextSlot _textSlots[10]; - if (endSeq == -1) - endSeq = startSeq; + char *_tempString; - assert(startSeq >= 0 && endSeq < kSequenceArraySize && startSeq <= endSeq); + uint8 _textColor[2]; + uint8 _textColorMap[16]; + int _textDuration[33]; - _sound->setSoundList(&_soundData[(startSeq > kSequenceZanfaun) ? kMusicFinale : kMusicIntro]); - _sound->loadSoundFile(0); + const char *const *_sequenceStrings; + const char *const *_sequenceSoundList; + int _sequenceSoundListSize; - _screen->_charWidth = (_flags.gameID == GI_LOL) ? 0 : -2; + static const uint8 _textColorPresets[]; - memset(_activeWSA, 0, sizeof(ActiveWSA) * 8); - for (int i = 0; i < 8; ++i) - _activeWSA[i].flags = -1; + // HOF credits + void playHoFTalkieCredits(); + void displayHoFTalkieScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData = 0, const char *const *specialData = 0); + + bool _talkieFinaleExtraFlag; + + // HOF+LOL demo specific + void updateDemoAdText(int bottom, int top); + + ActiveItemAnim _hofDemoActiveItemAnim[5]; + const HoFSeqItemAnimData *_hofDemoAnimData; + + uint32 _fisherAnimCurTime; + int _scrollProgressCounter; + + uint8 *_hofDemoShapeData; + uint8 *_hofDemoItemShapes[20]; + + // Misc + void delayTicks(uint32 ticks); + void delayUntil(uint32 dest); + void setCountDown(uint32 ticks); + bool countDownRunning(); + + uint32 _countDownRemainder; + uint32 _countDownLastUpdate; + + enum SeqPlayerTargetInfo { + kHoF = 0, + kHoFDemo, + kLoLDemo + }; + + SeqPlayerTargetInfo _target; + int _firstScene, _loopStartScene, _curScene, _preventSkipBeforeScene, _lastScene; + bool _startupSaveLoadable, _isFinale, _preventLooping; + + SeqPlayerConfig *_config; + + MainMenu *_menu; + int _result; + + bool _abortPlayback; + + KyraEngine_v1 *_vm; + Screen_v2 *_screen; + // We might consider getting rid of Screen_HoF, since there are only 2 methods left in that class anyway + Screen_HoF *_screenHoF; + OSystem *_system; + + static SeqPlayer_HOF *_instance; + +private: + // Sequence specific callback functions + int cbHOF_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_title(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_overview(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_library(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_point(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_zanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOF_over1(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_over2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_forest(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_dragon(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_darm(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_library2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_marco(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand3(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOF_funters(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_ferb(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_fish(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_fheep(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_farmer(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_fuards(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_firates(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_frash(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOF_figgle(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOFDEMO_virgin(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_title(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_hill(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_outhome(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_wharf(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_dinob(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_fisher(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOFDEMO_wharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_dinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_water(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_bail(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_dig(WSAMovie_v2 *wsaObj, int x, int y, int frm); + +#ifdef ENABLE_LOL + int cbLOLDEMO_scene1(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene3(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene4(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene5(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_text5(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene6(WSAMovie_v2 *wsaObj, int x, int y, int frm); +#endif // ENABLE_LOL +}; + +SeqPlayer_HOF *SeqPlayer_HOF::_instance = 0; + +SeqPlayer_HOF::SeqPlayer_HOF(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *system, bool startupSaveLoadable) : _vm(vm), _screen(screen), _system(system), _startupSaveLoadable(startupSaveLoadable) { + // We use a static pointer for pauseEngine functionality. Since we don't + // ever need more than one SeqPlayer_HOF object at the same time we keep + // this simple and just add an assert to detect typos, regressions, etc. + assert(_instance == 0); + + memset(_animSlots, 0, sizeof(_animSlots)); + memset(_textSlots, 0, sizeof(_textSlots)); + memset(_hofDemoActiveItemAnim, 0, sizeof(_hofDemoActiveItemAnim)); + + _screenHoF = _vm->game() == GI_KYRA2 ? (Screen_HoF*)screen : 0; + _config = 0; + _result = 0; + _sequenceSoundList = 0; + _hofDemoAnimData = 0; + _hofDemoShapeData = 0; + _isFinale = false; + _preventLooping = false; + _menu = 0; + _abortRequested = false; + _pauseStart = 0; + + _updateAnimations = false; + _animDuration = 0; + _animCurrentFrame = 0; + _callbackCurrentFrame = 0; + + _abortPlayback = false; + _curScene = 0; + _preventSkipBeforeScene = -1; + _lastScene = 0; + + _scrollProgressCounter = 0; + _fisherAnimCurTime = 0; + + _tempString = new char[200]; + + _countDownRemainder = 0; + _countDownLastUpdate = 0; + + int tempSize = 0; + _vm->resource()->unloadAllPakFiles(); + _vm->resource()->loadPakFile(StaticResource::staticDataFilename()); + const char *const *files = _vm->staticres()->loadStrings(k2SeqplayPakFiles, tempSize); + _vm->resource()->loadFileList(files, tempSize); + + _sequenceStrings = _vm->staticres()->loadStrings(k2SeqplayStrings, tempSize); + uint8 multiplier = (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) ? 12 : 8; + for (int i = 0; i < MIN(33, tempSize); i++) + _textDuration[i] = (int) strlen(_sequenceStrings[i]) * multiplier; + + if (_sequenceSoundList) { + for (int i = 0; i < _sequenceSoundListSize; i++) { + if (_sequenceSoundList[i]) + delete[] _sequenceSoundList[i]; + } + delete[] _sequenceSoundList; + _sequenceSoundList = 0; + } - memset(_activeText, 0, sizeof(ActiveText) * 10); - seq_resetAllTextEntries(); + const char *const *seqSoundList = _vm->staticres()->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); + // replace sequence talkie files with localized versions + const char *const *tlkfiles = _vm->staticres()->loadStrings(k2SeqplayTlkFiles, tempSize); + char **tmpSndLst = new char *[_sequenceSoundListSize]; + + for (int i = 0; i < _sequenceSoundListSize; i++) { + const int len = strlen(seqSoundList[i]); + + tmpSndLst[i] = new char[len + 1]; + tmpSndLst[i][0] = 0; + + if (tlkfiles && len > 1) { + for (int ii = 0; ii < tempSize; ii++) { + if (strlen(tlkfiles[ii]) > 1 && !scumm_stricmp(&seqSoundList[i][1], &tlkfiles[ii][1])) + strcpy(tmpSndLst[i], tlkfiles[ii]); + } + } + + if (tmpSndLst[i][0] == 0) + strcpy(tmpSndLst[i], seqSoundList[i]); + } + + tlkfiles = seqSoundList = 0; + _vm->staticres()->unloadId(k2SeqplayTlkFiles); + _vm->staticres()->unloadId(k2SeqplaySfxFiles); + _sequenceSoundList = tmpSndLst; + + if (_vm->gameFlags().platform == Common::kPlatformPC98) + _vm->sound()->loadSoundFile("SOUND.DAT"); + + _screen->loadFont(_screen->FID_GOLDFONT_FNT, "GOLDFONT.FNT"); + _screen->setFont(_vm->gameFlags().lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); + + if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) { + if (_vm->game() == GI_KYRA2) { + _hofDemoAnimData = _vm->staticres()->loadHoFSeqItemAnimData(k2SeqplayShapeAnimData, tempSize); + uint8 *shp = _vm->resource()->fileData("ICONS.SHP", 0); + uint32 outsize = READ_LE_UINT16(shp + 4); + _hofDemoShapeData = new uint8[outsize]; + Screen::decodeFrame4(shp + 10, _hofDemoShapeData, outsize); + for (int i = 0; i < 20; i++) + _hofDemoItemShapes[i] = _screen->getPtrToShape(_hofDemoShapeData, i); + delete[] shp; + } + } else { + const MainMenu::StaticData data = { + { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98], 0 }, + { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xD7, 0xD6 }, + { 0xD8, 0xDA, 0xD9, 0xD8 }, + (_vm->gameFlags().lang == Common::JA_JPN) ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT, 240 + }; + + _menu = new MainMenu(_vm); + _menu->init(data, MainMenu::Animation()); + } + + _instance = this; +} + +SeqPlayer_HOF::~SeqPlayer_HOF() { + _instance = 0; + + if (_sequenceSoundList) { + for (int i = 0; i < _sequenceSoundListSize; i++) { + if (_sequenceSoundList[i]) + delete[] _sequenceSoundList[i]; + } + delete[] _sequenceSoundList; + _sequenceSoundList = NULL; + } + + delete[] _tempString; + delete[] _hofDemoShapeData; + delete _menu; + + if (_vm->game() != GI_LOL) + _screen->setFont(_vm->gameFlags().lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); +} + +int SeqPlayer_HOF::play(SequenceID firstScene, SequenceID loopStartScene) { + bool incompatibleData = false; + AudioResourceSet soundSet = kMusicIntro; + _firstScene = firstScene; + _loopStartScene = loopStartScene; + _preventLooping = false; + _result = 0; + + if (firstScene >= kSequenceArraySize || firstScene < kSequenceVirgin || loopStartScene >= kSequenceArraySize || loopStartScene < kSequenceNoLooping) { + return 0; + } else if (firstScene >= kSequenceLoLDemoScene1) { +#ifndef ENABLE_LOL + error("SeqPlayer_HOF::play(): The Lands of Lore sub engine (including this non-interactive demo) has been disabled in this build"); +#endif + incompatibleData = (_vm->game() != GI_LOL); + _firstScene -= kSequenceLoLDemoScene1; + if (loopStartScene != kSequenceNoLooping) + _loopStartScene -= kSequenceLoLDemoScene1; + _lastScene = kSequenceLoLDemoScene6 - kSequenceLoLDemoScene1; + _target = kLoLDemo; + _screen->_charWidth = 0; + } else if (firstScene >= kSequenceHoFDemoVirgin) { + incompatibleData = (_vm->game() != GI_KYRA2 || !_vm->gameFlags().isDemo || _vm->gameFlags().isTalkie); + _firstScene -= kSequenceHoFDemoVirgin; + if (loopStartScene != kSequenceNoLooping) + _loopStartScene -= kSequenceHoFDemoVirgin; + _lastScene = kSequenceHoFDemoFisher - kSequenceHoFDemoVirgin; + _target = kHoFDemo; + _screen->_charWidth = -2; + } else { + _isFinale = _preventLooping = firstScene > kSequenceZanfaun; + incompatibleData = (_vm->game() != GI_KYRA2 || (_vm->gameFlags().isDemo && (!_vm->gameFlags().isTalkie || _isFinale))); + _target = kHoF; + _screen->_charWidth = -2; + if (_isFinale) { + soundSet = kMusicFinale; + _lastScene = kSequenceFrash; + } else { + _lastScene = kSequenceZanfaun; + } + } + + if (incompatibleData) + error("SeqPlayer_HOF::play(): Specified sequences do not match the available sequence data for this target"); + + _vm->sound()->selectAudioResourceSet(soundSet); + _vm->sound()->loadSoundFile(0); + + setupCallbacks(); + runLoop(); + + return _result; +} + +void SeqPlayer_HOF::pause(bool toggle) { + if (toggle) { + _pauseStart = _system->getMillis(); + } else { + uint32 pausedTime = _system->getMillis() - _pauseStart; + _pauseStart = 0; + + _countDownLastUpdate += pausedTime; + _fisherAnimCurTime += pausedTime; + _specialAnimTimeOutTotal += pausedTime; + _specialAnimFrameTimeOut += pausedTime; + + for (int i = 0; i < 10; i++) { + if (_textSlots[i].duration != -1) + _textSlots[i].startTime += pausedTime; + } + + for (int i = 0; i < 8; i++) { + if (_animSlots[i].flags != -1) + _animSlots[i].nextFrame += pausedTime; + } + } +} + +void SeqPlayer_HOF::setupCallbacks() { +#define SCB(x) &SeqPlayer_HOF::cbHOF_##x + static const SeqProc seqCallbacksHoF[] = { 0, SCB(westwood), SCB(title), SCB(overview), SCB(library), SCB(hand), SCB(point), SCB(zanfaun), SCB(funters), SCB(ferb), SCB(fish), SCB(fheep), SCB(farmer), SCB(fuards), SCB(firates), SCB(frash) }; + static const SeqProc nestedSeqCallbacksHoF[] = { SCB(figgle), SCB(over1), SCB(over2), SCB(forest), SCB(dragon), SCB(darm), SCB(library2), SCB(library2), SCB(marco), SCB(hand1a), SCB(hand1b), SCB(hand1c), SCB(hand2), SCB(hand3), 0 }; +#undef SCB +#define SCB(x) &SeqPlayer_HOF::cbHOFDEMO_##x + static const SeqProc seqCallbacksHoFDemo[] = { SCB(virgin), SCB(westwood), SCB(title), SCB(hill), SCB(outhome), SCB(wharf), SCB(dinob), SCB(fisher) }; + static const SeqProc nestedSeqCallbacksHoFDemo[] = { SCB(wharf2), SCB(dinob2), SCB(water), SCB(bail), SCB(dig), 0 }; +#undef SCB +#ifdef ENABLE_LOL +#define SCB(x) &SeqPlayer_HOF::cbLOLDEMO_##x + static const SeqProc seqCallbacksLoLDemo[] = { SCB(scene1), 0, SCB(scene2), 0, SCB(scene3), 0, SCB(scene4), 0, SCB(scene5), SCB(text5), SCB(scene6), 0 }; +#undef SCB +#else + static const SeqProc seqCallbacksLoLDemo[] = { 0 }; +#endif + static const SeqProc nestedSeqCallbacksLoLDemo[] = { 0 }; + + static const SeqProc *const seqCallbacks[] = { seqCallbacksHoF, seqCallbacksHoFDemo, seqCallbacksLoLDemo}; + static const SeqProc *const nestedSeqCallbacks[] = { nestedSeqCallbacksHoF, nestedSeqCallbacksHoFDemo, nestedSeqCallbacksLoLDemo}; + + int tmpSize = 0; + delete _config; + _config = new SeqPlayerConfig(_vm->staticres()->loadHoFSequenceData(k2SeqplaySeqData, tmpSize), seqCallbacks[_target], nestedSeqCallbacks[_target]); +} + +void SeqPlayer_HOF::runLoop() { + memset(_animSlots, 0, sizeof(_animSlots)); + memset(_textSlots, 0, sizeof(_textSlots)); + memset(_hofDemoActiveItemAnim, 0, sizeof(_hofDemoActiveItemAnim)); + for (int i = 0; i < 8; ++i) + _animSlots[i].flags = -1; + + _screen->clearPage(10); + _screen->clearPage(12); _screen->hideMouse(); int oldPage = _screen->setCurPage(2); for (int i = 0; i < 4; ++i) _screen->getPalette(i).clear(); - _screen->clearPage(10); - _screen->clearPage(12); + _updateAnimations = false; + _animCurrentFrame = 0; + _textColor[0] = _textColor[1] = 0; + _curScene = _firstScene; - _seqSubframePlaying = false; + do { + playScenes(); + doTransition(0); + resetAllTextSlots(); + fadeOutMusic(); + _firstScene = ((!_startupSaveLoadable || _preventLooping) && _curScene >= _loopStartScene) ? kSequenceNoLooping : _loopStartScene; + } while (!_vm->shouldQuit() && _firstScene != kSequenceNoLooping); - _seqWsaCurrentFrame = 0; - _seqTextColor[0] = _seqTextColor[1] = 0; - _seqEndTime = 0; - _menuChoice = 0; + checkPlaybackStatus(); - for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { - _screen->clearPage(0); - _screen->clearPage(8); - _screen->copyPalette(1, 0); - _seqFrameCounter = 0; - _seqStartTime = _system->getMillis(); + for (int i = 0; i < 8; i++) + unloadNestedAnimation(i); + + if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) + _screen->fadeToBlack(); - allowSkip = (_flags.isDemo && !_flags.isTalkie) || seqNum != kSequenceTitle; + if (!_result) + delayTicks(75); - Sequence cseq = _sequences->seq[seqNum]; - SeqProc cb = _callbackS[seqNum]; + _screen->setCurPage(oldPage); + _screen->_charWidth = 0; + _screen->showMouse(); +} - if (cseq.flags & 2) { - _screen->loadBitmap(cseq.cpsFile, 2, 2, &_screen->getPalette(0)); +void SeqPlayer_HOF::playScenes() { + _vm->sound()->stopAllSoundEffects(); + _curScene = _firstScene; + + _screen->copyPalette(1, 0); + WSAMovie_v2 anim(_vm); + _abortRequested = false; + + _scrollProgressCounter = 0; + + while (!_vm->shouldQuit()) { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; + + _callbackCurrentFrame = 0; + + if (_curScene > _lastScene) + break; + + const Kyra::HoFSequence &sq = _config->seq[_curScene]; + + if (sq.flags & 2) { + _screen->loadBitmap(sq.cpsFile, 2, 2, &_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); } else { _screen->setCurPage(2); _screen->clearPage(2); - _screen->loadPalette("goldfont.col", _screen->getPalette(0)); + _screen->loadPalette("GOLDFONT.COL", _screen->getPalette(0)); } - if (cb && !(_flags.isDemo && !_flags.isTalkie)) - (this->*cb)(0, 0, 0, -1); + if (_config->seqProc[_curScene] && !(_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie)) + (this->*_config->seqProc[_curScene])(0, 0, 0, -1); - if (cseq.flags & 1) { - _seqWsa->close(); - _seqWsa->open(cseq.wsaFile, 0, &_screen->getPalette(0)); - _screen->setScreenPalette(_screen->getPalette(0)); - _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0, 0, 0); + if (sq.flags & 1) { + anim.open(sq.wsaFile, 0, &_screen->getPalette(0)); + if (!(sq.flags & 2)) + anim.displayFrame(0, 2, sq.xPos, sq.yPos, 0x4000, 0, 0); } - if (cseq.flags & 4) { + if (sq.flags & 4) { int cp = _screen->setCurPage(2); - Screen::FontId cf = _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); - if (cseq.stringIndex1 != -1) { - int sX = (320 - _screen->getTextWidth(_sequenceStrings[cseq.stringIndex1])) / 2; - _screen->printText(_sequenceStrings[cseq.stringIndex1], sX, 100 - _screen->getFontHeight(), 1, 0); - } - if (cseq.stringIndex2 != -1) { - int sX = (320 - _screen->getTextWidth(_sequenceStrings[cseq.stringIndex2])) / 2; - _screen->printText(_sequenceStrings[cseq.stringIndex2], sX, 100, 1, 0); - } + Screen::FontId cf = _screen->setFont(_vm->gameFlags().lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); + + if (sq.stringIndex1 != -1) + _screen->printText(_sequenceStrings[sq.stringIndex1], (320 - _screen->getTextWidth(_sequenceStrings[sq.stringIndex1])) / 2, 100 - _screen->getFontHeight(), 1, 0); + + if (sq.stringIndex2 != -1) + _screen->printText(_sequenceStrings[sq.stringIndex2], (320 - _screen->getTextWidth(_sequenceStrings[sq.stringIndex2])) / 2, 100, 1, 0); + _screen->setFont(cf); _screen->setCurPage(cp); } @@ -118,235 +683,1107 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { _screen->copyPage(2, 10); _screen->copyPage(12, 2); - seq_sequenceCommand(cseq.startupCommand); + doTransition(sq.fadeInTransitionType); - if (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { + if (!(checkAbortPlayback() || _vm->shouldQuit() || _result)) { _screen->copyPage(2, 0); _screen->updateScreen(); } - if (cseq.flags & 1) { - int x = cseq.xPos; - int y = cseq.yPos; + //_screen->copyPage(2, 6); - _seqFrameDelay = cseq.frameDelay; + if (sq.flags & 1) { + playAnimation(&anim, sq.startFrame, sq.numFrames, sq.duration, sq.xPos, sq.yPos, _config->seqProc[_curScene], &_screen->getPalette(1), &_screen->getPalette(0), 30, 0); + anim.close(); + } else { + _animDuration = sq.duration; + setCountDown(_animDuration); - if (_seqWsa) { - if (x < 0) { - _seqWsa->setWidth(_seqWsa->width() + x); - x = 0; - } + while (!checkAbortPlayback() && !_vm->shouldQuit() && (countDownRunning() || _updateAnimations)) { + uint32 endFrame = (_system->getMillis() + _vm->tickLength()) & ~(_vm->tickLength() - 1); + updateAllNestedAnimations(); - if (y < 0) { - _seqWsa->setHeight(_seqWsa->height() + y); - y = 0; - } + if (_config->seqProc[_curScene]) + (this->*_config->seqProc[_curScene])(0, 0, 0, 0); - if (cseq.xPos + _seqWsa->width() > 319) - _seqWsa->setWidth(320 - cseq.xPos); + updateSubTitles(); - if (cseq.yPos + _seqWsa->height() > 199) - _seqWsa->setHeight(199 - cseq.yPos); - } - uint8 dir = (cseq.startFrame > cseq.numFrames) ? 0 : 1; - _seqWsaCurrentFrame = cseq.startFrame; + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->copyPage(12, 2); - bool loop = true; - while (loop && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; + do { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; + } while (_system->getMillis() < endFrame); + } + } - if (_seqWsa || !cb) - _screen->copyPage(12, 2); + if (_config->seqProc[_curScene] && !(_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie)) + (this->*_config->seqProc[_curScene])(0, 0, 0, -2); - if (cb) { - int f = _seqWsaCurrentFrame % _seqWsa->frames(); - (this->*cb)(_seqWsa, cseq.xPos, cseq.yPos, f); - } + uint32 textTimeOut = ticksTillSubTitlesTimeout(); + setCountDown(sq.timeout < textTimeOut ? textTimeOut : sq.timeout); - if (_seqWsa) { - int f = _seqWsaCurrentFrame % _seqWsa->frames(); - _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0, 0, 0); - } + while (!checkAbortPlayback() && !_vm->shouldQuit() && (countDownRunning() || _updateAnimations)) { + updateAllNestedAnimations(); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->copyPage(12, 2); + } - _screen->copyPage(2, 12); + doTransition(sq.fadeOutTransitionType); + _curScene++; + } - seq_processWSAs(); - seq_processText(); + resetAllTextSlots(); + _vm->sound()->haltTrack(); + _vm->sound()->voiceStop(); - if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _screen->copyPage(2, 0); - _screen->updateScreen(); - } + if ((!checkAbortPlayback() || _vm->shouldQuit()) && _vm->gameFlags().isDemo) + _curScene = -1; +} - bool loop2 = true; - while (loop2 && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - if (_seqWsa) { - seq_processText(); - if (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _screen->copyPage(2, 0); - _screen->updateScreen(); - } +bool SeqPlayer_HOF::checkAbortPlayback() { + Common::Event event; - uint32 now = _system->getMillis(); - if (now >= _seqEndTime) { - loop2 = false; - } else { - uint32 tdiff = _seqEndTime - now; - uint32 dly = tdiff < _tickLength ? tdiff : _tickLength; - delay(dly); - } - } else { - loop = loop2 = false; - } - } + if (_vm->skipFlag()) { + _abortRequested = true; + _vm->resetSkipFlag(); + } - if (loop) { - if (dir == 1) { - if (++_seqWsaCurrentFrame >= cseq.numFrames) - loop = false; - } else { - if (--_seqWsaCurrentFrame < cseq.numFrames) - loop = false; - } - } + if (_abortRequested) + return true; + + while (_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_q && event.kbd.hasFlags(Common::KBD_CTRL)) { + _abortRequested = true; + _vm->quitGame(); + return true; + } else if (event.kbd.keycode != Common::KEYCODE_ESCAPE && event.kbd.keycode != Common::KEYCODE_RETURN && event.kbd.keycode != Common::KEYCODE_SPACE) { + continue; } - _seqWsa->close(); - } else { - _seqFrameDelay = cseq.frameDelay; - _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - while (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _seqSubFrameStartTime = _system->getMillis(); - seq_processWSAs(); - if (cb) - (this->*cb)(0, 0, 0, 0); + // fall through + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _abortRequested = true; + return true; + default: + break; + } + } - seq_processText(); + return false; +} - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->copyPage(12, 2); +bool SeqPlayer_HOF::checkPlaybackStatus() { + _updateAnimations = false; - uint32 now = _system->getMillis(); - if (now >= _seqEndTime && !_seqSubframePlaying) - break; + if (_curScene <= _preventSkipBeforeScene || (_curScene == _loopStartScene && !_isFinale)) { + _abortRequested = false; + return false; + } - uint32 tdiff = _seqEndTime - _seqSubFrameStartTime; - int32 dly = _tickLength - (now - _seqSubFrameStartTime); - if (dly > 0) - delay(MIN<uint32>(dly, tdiff)); - else - updateInput(); - } + if (_loopStartScene == kSequenceNoLooping) { + doTransition(0); + fadeOutMusic(); + _abortPlayback = true; + } else { + return true; + } + + return false; +} + +void SeqPlayer_HOF::doTransition(int type) { + for (int i = 0; i < 8; i++) + closeNestedAnimation(i); + + switch (type) { + case 0: + _screen->fadeToBlack(36); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); + break; + + case 1: + playSoundAndDisplaySubTitle(_vm->_rnd.getRandomBit()); + + _screen->getPalette(0).fill(0, 256, 0x3F); + _screen->fadePalette(_screen->getPalette(0), 16); + + _screen->copyPalette(1, 0); + break; + + case 3: + _screen->copyPage(2, 0); + _screen->fadePalette(_screen->getPalette(0), 16); + _screen->copyPalette(1, 0); + break; + + case 4: + _screen->copyPage(2, 0); + _screen->fadePalette(_screen->getPalette(0), 36); + _screen->copyPalette(1, 0); + break; + + case 5: + _screen->copyPage(2, 0); + break; + + case 6: + // UNUSED + // seq_loadBLD("library.bld"); + break; + + case 7: + // UNUSED + // seq_loadBLD("marco.bld"); + break; + + case 8: + _screen->fadeToBlack(16); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); + + delayTicks(120); + break; + + case 9: { + Palette &pal = _screen->getPalette(0); + for (int i = 0; i < 255; i++) + pal.fill(i, 1, (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3); + pal.fill(255, 1, 0x3F); + + _screen->fadePalette(pal, 64); + _screen->copyPalette(1, 0); + } break; + + default: + break; + } +} + +void SeqPlayer_HOF::nestedFrameAnimTransition(int srcPage, int dstPage, int delaytime, int steps, int x, int y, int w, int h, int openClose, int directionFlags) { + if (openClose) { + for (int i = 1; i < steps; i++) { + uint32 endtime = _system->getMillis() + delaytime * _vm->tickLength(); + + int w2 = (((w * 256) / steps) * i) / 256; + int h2 = (((h * 256) / steps) * i) / 256; + + int ym = (directionFlags & 2) ? (h - h2) : 0; + int xm = (directionFlags & 1) ? (w - w2) : 0; + + _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); + + _screen->copyPage(dstPage, 6); + _screen->copyPage(dstPage, 0); + _screen->updateScreen(); + + _screen->copyPage(12, dstPage); + delayUntil(endtime); } - if (cb && !(_flags.isDemo && !_flags.isTalkie)) - (this->*cb)(0, 0, 0, -2); + _screen->wsaFrameAnimationStep(0, 0, x, y, w, h, w, h, srcPage, dstPage, 0); + _screen->copyPage(dstPage, 6); + _screen->copyPage(dstPage, 0); + _screen->updateScreen(); + } else { + _screen->copyPage(12, dstPage); + for (int i = steps; i; i--) { + uint32 endtime = _system->getMillis() + delaytime * _vm->tickLength(); + + int w2 = (((w * 256) / steps) * i) / 256; + int h2 = (((h * 256) / steps) * i) / 256; + + int ym = (directionFlags & 2) ? (h - h2) : 0; + int xm = (directionFlags & 1) ? (w - w2) : 0; - uint32 ct = seq_activeTextsTimeLeft(); - uint32 dl = cseq.duration * _tickLength; - if (dl < ct) - dl = ct; - _seqEndTime = _system->getMillis() + dl; + _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); - while (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _seqSubFrameStartTime = _system->getMillis(); - seq_processWSAs(); + _screen->copyPage(dstPage, 6); + _screen->copyPage(dstPage, 0); + _screen->updateScreen(); + _screen->copyPage(12, dstPage); + delayUntil(endtime); + } + } +} + +void SeqPlayer_HOF::nestedFrameFadeTransition(const char *cmpFile) { + _screen->copyPage(10, 2); + _screen->copyPage(4, 10); + _screen->clearPage(6); + _screen->loadBitmap(cmpFile, 6, 6, 0); + _screen->copyPage(12, 4); + + for (int i = 0; i < 3; i++) { + uint32 endtime = _system->getMillis() + 4 * _vm->tickLength(); + assert(_screenHoF); + _screenHoF->cmpFadeFrameStep(4, 320, 200, 0, 0, 2, 320, 200, 0, 0, 320, 200, 6); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); + delayUntil(endtime); + } + + _screen->copyPage(4, 0); + _screen->updateScreen(); + _screen->copyPage(4, 2); + _screen->copyPage(4, 6); + _screen->copyPage(10, 4); +} + +void SeqPlayer_HOF::playAnimation(WSAMovie_v2 *wsaObj, int startFrame, int lastFrame, int frameRate, int x, int y, const SeqProc callback, Palette *fadePal1, Palette *fadePal2, int fadeRate, bool restoreScreen) { + bool finished = false; + uint32 startTime = _system->getMillis(); + + int origW = wsaObj->width(); + int origH = wsaObj->width(); + int drwX = x; + int drwY = y; + int drwW = origW; + int drwH = origH; + + _animDuration = frameRate; + + if (wsaObj) { + if (x < 0) { + drwW += x; + drwX = 0; + } + + if (y < 0) { + drwH += y; + drwY = 0; + } + + if (x + origW > 319) + origW = 320 - x; + + if (y + origH > 199) + origW = 200 - y; + } + + int8 frameStep = (startFrame > lastFrame) ? -1 : 1; + _animCurrentFrame = startFrame; + + while (!_vm->shouldQuit() && !finished) { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; + + setCountDown(_animDuration); + + if (wsaObj || callback) + _screen->copyPage(12, 2); + + int frameIndex = _animCurrentFrame; + if (wsaObj) + frameIndex %= wsaObj->frames(); + + if (callback) + (this->*callback)(wsaObj, x, y, frameIndex); + + if (wsaObj) + wsaObj->displayFrame(frameIndex, 2, x, y, 0, 0, 0); + + _screen->copyPage(2, 12); + + updateAllNestedAnimations(); + updateSubTitles(); + + if ((wsaObj || callback) && (!(checkAbortPlayback() || _vm->shouldQuit() || _result))) { _screen->copyPage(2, 0); _screen->updateScreen(); + } + + while (!_vm->shouldQuit()) { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; + + if (fadePal1 && fadePal2) { + if (!_screen->timedPaletteFadeStep(fadePal1->getData(), fadePal2->getData(), _system->getMillis() - startTime, fadeRate * _vm->tickLength()) && !wsaObj) + break; + } + + if ((wsaObj || callback) && (!(checkAbortPlayback() || _vm->shouldQuit() || _result))) { + _screen->copyPage(2, 0); + _screen->updateScreen(); + } + + updateSubTitles(); + + if (!countDownRunning()) + break; + } + + if (wsaObj) { + _animCurrentFrame += frameStep; + if ((frameStep > 0 && _animCurrentFrame >= lastFrame) || (frameStep < 0 && _animCurrentFrame < lastFrame)) + finished = true; + } + + if (restoreScreen && (wsaObj || callback)) { _screen->copyPage(12, 2); + _screen->copyRegion(drwX, drwY, drwX, drwY, drwW, drwH, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } + } +} + +void SeqPlayer_HOF::playDialogueAnimation(uint16 strID, uint16 soundID, int textColor, int textPosX, int textPosY, int textWidth, WSAMovie_v2 *wsaObj, int animStartFrame, int animLastFrame, int animPosX, int animPosY) { + int dur = int(strlen(_sequenceStrings[strID])) * (_vm->gameFlags().isTalkie ? 7 : 15); + if (_vm->textEnabled()) { + int slot = displaySubTitle(strID, textPosX, textPosY, dur, textWidth); + _textSlots[slot].textcolor = textColor; + } + _specialAnimTimeOutTotal = _system->getMillis() + dur * _vm->tickLength(); + int curframe = animStartFrame; + + if (soundID && _vm->speechEnabled()) { + while (_vm->sound()->voiceIsPlaying() && !_abortPlayback) + delayTicks(1); + playSoundAndDisplaySubTitle(soundID); + } + + while (_system->getMillis() < _specialAnimTimeOutTotal && !_abortPlayback) { + if (animLastFrame < 0) { + int t = ABS(animLastFrame); + if (t < curframe) + curframe = t; + } + + if (ABS(animLastFrame) < curframe) + curframe = animStartFrame; - uint32 now = _system->getMillis(); - if (now >= _seqEndTime && !_seqSubframePlaying) { + _specialAnimFrameTimeOut = _system->getMillis() + _animDuration * _vm->tickLength(); + setCountDown(_animDuration); + + if (wsaObj) + wsaObj->displayFrame(curframe % wsaObj->frames(), 2, animPosX, animPosY, 0, 0, 0); + + _screen->copyPage(2, 12); + updateSubTitles(); + delayUntil(MIN(_specialAnimFrameTimeOut, _specialAnimTimeOutTotal)); + + if (_vm->speechEnabled() && !_vm->textEnabled() && !_vm->snd_voiceIsPlaying()) + break; + + if (checkAbortPlayback()) + if (checkPlaybackStatus()) break; - } - uint32 tdiff = _seqEndTime - _seqSubFrameStartTime; - int32 dly = _tickLength - (now - _seqSubFrameStartTime); - if (dly > 0) - delay(MIN<uint32>(dly, tdiff)); + _screen->copyPage(2, 0); + _screen->updateScreen(); + curframe++; + } + + if (_abortPlayback) + _vm->sound()->voiceStop(); + + if (ABS(animLastFrame) < curframe) + curframe = ABS(animLastFrame); + + if (curframe == animStartFrame) + curframe++; + + _animCurrentFrame = curframe; +} + +void SeqPlayer_HOF::startNestedAnimation(int animSlot, int sequenceID) { + if (_animSlots[animSlot].flags != -1) + return; + + if (_target == kLoLDemo) { + return; + } else if (_target == kHoFDemo) { + assert(sequenceID >= kNestedSequenceHoFDemoWharf2); + sequenceID -= kNestedSequenceHoFDemoWharf2; + } + + HoFNestedSequence s = _config->nestedSeq[sequenceID]; + + if (!_animSlots[animSlot].movie) { + _animSlots[animSlot].movie = new WSAMovie_v2(_vm); + assert(_animSlots[animSlot].movie); + } + + _animSlots[animSlot].movie->close(); + + _animSlots[animSlot].movie->open(s.wsaFile, 0, 0); + + if (!_animSlots[animSlot].movie->opened()) { + delete _animSlots[animSlot].movie; + _animSlots[animSlot].movie = 0; + return; + } + + _animSlots[animSlot].endFrame = s.endFrame; + _animSlots[animSlot].startFrame = _animSlots[animSlot].currentFrame = s.startframe; + _animSlots[animSlot].frameDelay = s.frameDelay; + _animSlots[animSlot].callback = _config->nestedSeqProc[sequenceID]; + _animSlots[animSlot].control = s.wsaControl; + + _animSlots[animSlot].flags = s.flags | 1; + _animSlots[animSlot].x = s.x; + _animSlots[animSlot].y = s.y; + _animSlots[animSlot].fadeInTransitionType = s.fadeInTransitionType; + _animSlots[animSlot].fadeOutTransitionType = s.fadeOutTransitionType; + _animSlots[animSlot].lastFrame = 0xFFFF; + + doNestedFrameTransition(s.fadeInTransitionType, animSlot); + + if (!s.fadeInTransitionType) + updateNestedAnimation(animSlot); + + _animSlots[animSlot].nextFrame = _system->getMillis() & ~(_vm->tickLength() - 1); +} + +void SeqPlayer_HOF::closeNestedAnimation(int animSlot) { + if (_animSlots[animSlot].flags == -1) + return; + + _animSlots[animSlot].flags = -1; + doNestedFrameTransition(_animSlots[animSlot].fadeOutTransitionType, animSlot); + _animSlots[animSlot].movie->close(); +} + +void SeqPlayer_HOF::unloadNestedAnimation(int animSlot) { + if (_animSlots[animSlot].movie) { + _animSlots[animSlot].movie->close(); + delete _animSlots[animSlot].movie; + _animSlots[animSlot].movie = 0; + } +} + +void SeqPlayer_HOF::doNestedFrameTransition(int transitionType, int animSlot) { + int xa = 0, ya = 0; + transitionType--; + if (!_animSlots[animSlot].movie || _abortPlayback || _vm->shouldQuit()) + return; + + switch (transitionType) { + case 0: + xa = -_animSlots[animSlot].movie->xAdd(); + ya = -_animSlots[animSlot].movie->yAdd(); + _animSlots[animSlot].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); + nestedFrameAnimTransition(8, 2, 7, 8, _animSlots[animSlot].movie->xAdd(), _animSlots[animSlot].movie->yAdd(), + _animSlots[animSlot].movie->width(), _animSlots[animSlot].movie->height(), 1, 2); + break; + + case 1: + xa = -_animSlots[animSlot].movie->xAdd(); + ya = -_animSlots[animSlot].movie->yAdd(); + _animSlots[animSlot].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); + nestedFrameAnimTransition(8, 2, 7, 8, _animSlots[animSlot].movie->xAdd(), _animSlots[animSlot].movie->yAdd(), + _animSlots[animSlot].movie->width(), _animSlots[animSlot].movie->height(), 1, 1); + break; + + case 2: + waitForSubTitlesTimeout(); + xa = -_animSlots[animSlot].movie->xAdd(); + ya = -_animSlots[animSlot].movie->yAdd(); + _animSlots[animSlot].movie->displayFrame(21, 8, xa, ya, 0, 0, 0); + nestedFrameAnimTransition(8, 2, 7, 8, _animSlots[animSlot].movie->xAdd(), _animSlots[animSlot].movie->yAdd(), + _animSlots[animSlot].movie->width(), _animSlots[animSlot].movie->height(), 0, 2); + break; + + case 3: + _screen->copyPage(2, 10); + _animSlots[animSlot].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); + _screen->copyPage(2, 12); + nestedFrameFadeTransition("scene2.cmp"); + break; + + case 4: + _screen->copyPage(2, 10); + _animSlots[animSlot].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); + _screen->copyPage(2, 12); + nestedFrameFadeTransition("scene3.cmp"); + break; + + default: + break; + } +} + +void SeqPlayer_HOF::updateAllNestedAnimations() { + for (int i = 0; i < 8; i++) { + if (_animSlots[i].flags != -1) { + if (updateNestedAnimation(i)) + closeNestedAnimation(i); + } + } +} + +bool SeqPlayer_HOF::updateNestedAnimation(int animSlot) { + uint16 currentFrame = _animSlots[animSlot].currentFrame; + uint32 curTick = _system->getMillis() & ~(_vm->tickLength() - 1); + + if (_animSlots[animSlot].callback && currentFrame != _animSlots[animSlot].lastFrame) { + _animSlots[animSlot].lastFrame = currentFrame; + currentFrame = (this->*_animSlots[animSlot].callback)(_animSlots[animSlot].movie, _animSlots[animSlot].x, _animSlots[animSlot].y, currentFrame); + } + + if (_animSlots[animSlot].movie) { + if (_animSlots[animSlot].flags & 0x20) { + _animSlots[animSlot].movie->displayFrame(_animSlots[animSlot].control[currentFrame].index, 2, _animSlots[animSlot].x, _animSlots[animSlot].y, 0x4000, 0, 0); + _animSlots[animSlot].frameDelay = _animSlots[animSlot].control[currentFrame].delay; + } else { + _animSlots[animSlot].movie->displayFrame(currentFrame % _animSlots[animSlot].movie->frames(), 2, _animSlots[animSlot].x, _animSlots[animSlot].y, 0x4000, 0, 0); + } + } + + if (_animSlots[animSlot].flags & 0x10) { + currentFrame = (curTick - _animSlots[animSlot].nextFrame) / (_animSlots[animSlot].frameDelay * _vm->tickLength()); + } else { + int diff = (curTick - _animSlots[animSlot].nextFrame) / (_animSlots[animSlot].frameDelay * _vm->tickLength()); + if (diff > 0) { + currentFrame++; + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + _animSlots[animSlot].nextFrame += ((curTick - _animSlots[animSlot].nextFrame) * 2 / 3); else - updateInput(); + _animSlots[animSlot].nextFrame = curTick; } + } - seq_sequenceCommand(cseq.finalCommand); - seq_resetAllTextEntries(); + bool res = false; + + if (currentFrame >= _animSlots[animSlot].endFrame) { + int sw = ((_animSlots[animSlot].flags & 0x1E) - 2); + switch (sw) { + case 0: + res = true; + currentFrame = _animSlots[animSlot].endFrame; + _screen->copyPage(2, 12); + break; + + case 6: + case 8: + currentFrame = _animSlots[animSlot].endFrame - 1; + break; - if (_abortIntroFlag || skipFlag()) { - _sound->haltTrack(); - _sound->voiceStop(); + case 2: + case 10: + currentFrame = _animSlots[animSlot].startFrame; + break; + + default: + currentFrame = _animSlots[animSlot].endFrame - 1; + res = true; } + } + + _animSlots[animSlot].currentFrame = currentFrame; + return res; +} - if (!_flags.isDemo || _flags.isTalkie) { - if ((seqNum != kSequenceTitle && seqNum < kSequenceZanfaun && - (_abortIntroFlag || skipFlag())) || seqNum == kSequenceZanfaun) { - _abortIntroFlag = false; - _eventList.clear(); - seqNum = kSequenceWestwood; - } else if (seqNum < kSequenceFrash && (_abortIntroFlag || skipFlag())) { - _abortIntroFlag = false; - _eventList.clear(); - seqNum = kSequenceFirates; +void SeqPlayer_HOF::playSoundEffect(uint16 id, int16 vol) { + assert(id < _sequenceSoundListSize); + _vm->sound()->voicePlay(_sequenceSoundList[id], 0, vol); +} + +void SeqPlayer_HOF::playSoundAndDisplaySubTitle(uint16 id) { + assert(id < _sequenceSoundListSize); + + if (id < 12 && !_vm->gameFlags().isDemo && _vm->textEnabled()) + displaySubTitle(id, 160, 168, _textDuration[id], 160); + + _vm->sound()->voicePlay(_sequenceSoundList[id], 0); +} + +void SeqPlayer_HOF::printFadingText(uint16 strID, int x, int y, const uint8 *colorMap, uint8 textcolor) { + uint8 cmap[16]; + + if (checkAbortPlayback()) + checkPlaybackStatus(); + + if (_abortPlayback || _abortRequested || _vm->shouldQuit() || _result) + return; + + Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); + _screen->getPalette(0).fill(254, 2, 63); + _screen->setPaletteIndex(252, 63, 32, 48); + cmap[0] = colorMap[0]; + cmap[1] = 253; + memcpy(&cmap[2], &colorMap[2], 14); + uint8 col0 = _textColor[0]; + + _textColor[0] = 253; + _screen->setTextColorMap(cmap); + resetAllTextSlots(); + displaySubTitle(strID, x, y, 128, 120); + updateSubTitles(); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->getPalette(0).copy(_screen->getPalette(0), textcolor, 1, 253); + _screen->fadePalette(_screen->getPalette(0), 24); + + _textColor[0] = textcolor; + _screen->setTextColorMap(colorMap); + resetAllTextSlots(); + displaySubTitle(strID, x, y, 128, 120); + updateSubTitles(); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->getPalette(0).fill(253, 1, 0); + _screen->fadePalette(_screen->getPalette(0), 1); + + _screen->copyPage(2, 12); + resetAllTextSlots(); + + _textColor[0] = col0; + + _screen->setFont(of); +} + +int SeqPlayer_HOF::displaySubTitle(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width) { + for (int i = 0; i < 10; i++) { + if (_textSlots[i].duration != -1) { + if (i < 9) + continue; + else + return -1; + } + + _textSlots[i].strIndex = strIndex; + _textSlots[i].x = posX; + _textSlots[i].y = posY; + _textSlots[i].duration = duration * _vm->tickLength(); + _textSlots[i].width = width; + _textSlots[i].startTime = _system->getMillis(); + _textSlots[i].textcolor = -1; + + return i; + } + return -1; +} + +void SeqPlayer_HOF::updateSubTitles() { + int curPage = _screen->setCurPage(2); + char outputStr[70]; + + for (int i = 0; i < 10; i++) { + if (_textSlots[i].startTime + _textSlots[i].duration > _system->getMillis() && _textSlots[i].duration != -1) { + + char *srcStr = preprocessString(_sequenceStrings[_textSlots[i].strIndex], _textSlots[i].width); + int yPos = _textSlots[i].y; + + while (*srcStr) { + uint32 linePos = 0; + for (; *srcStr; linePos++) { + if (*srcStr == '\r') + break; + outputStr[linePos] = *srcStr; + srcStr++; + } + outputStr[linePos] = 0; + if (*srcStr == '\r') + srcStr++; + + uint8 textColor = (_textSlots[i].textcolor >= 0) ? _textSlots[i].textcolor : _textColor[0]; + _screen->printText(outputStr, _textSlots[i].x - (_screen->getTextWidth(outputStr) / 2), yPos, textColor, 0); + yPos += 10; } - } else if (seqNum == endSeq && !(_abortIntroFlag || skipFlag())) { - seqNum = 0; + } else { + _textSlots[i].duration = -1; + } + } + + _screen->setCurPage(curPage); +} + +char *SeqPlayer_HOF::preprocessString(const char *srcStr, int width) { + char *dstStr = _tempString; + int lineStart = 0; + int linePos = 0; + + while (*srcStr) { + while (*srcStr && *srcStr != ' ') + dstStr[lineStart + linePos++] = *srcStr++; + dstStr[lineStart + linePos] = 0; + + int len = _screen->getTextWidth(&dstStr[lineStart]); + if (width >= len && *srcStr) { + dstStr[lineStart + linePos++] = *srcStr++; + } else { + dstStr[lineStart + linePos] = '\r'; + lineStart += linePos + 1; + linePos = 0; + if (*srcStr) + srcStr++; } + } + dstStr[lineStart + linePos] = 0; - if (_menuChoice) { - _abortIntroFlag = false; - _eventList.clear(); + return strlen(_tempString) ? dstStr : 0; +} + +void SeqPlayer_HOF::waitForSubTitlesTimeout() { + uint32 timeOut = _system->getMillis() + ticksTillSubTitlesTimeout() * _vm->tickLength(); - if (_menuChoice == 2) { - seqNum = kSequenceTitle; - _menuChoice = 0; + if (_vm->textEnabled()) { + delayUntil(timeOut); + } else if (_vm->speechEnabled()) { + while (_vm->snd_voiceIsPlaying()) + delayTicks(1); + } + + resetAllTextSlots(); +} + +uint32 SeqPlayer_HOF::ticksTillSubTitlesTimeout() { + uint32 longest = 0; + + for (int i = 0; i < 10; i++) { + uint32 timeOut = (_textSlots[i].duration + _textSlots[i].startTime); + uint32 curtime = _system->getMillis(); + if (_textSlots[i].duration != -1 && timeOut > curtime) { + timeOut -= curtime; + if (longest < timeOut) + longest = timeOut; + } + } + + uint32 tl = _vm->tickLength(); + return (longest + (tl - 1)) / tl; +} + +void SeqPlayer_HOF::resetAllTextSlots() { + for (int i = 0; i < 10; i++) + _textSlots[i].duration = -1; +} + +void SeqPlayer_HOF::fadeOutMusic() { + _vm->sound()->beginFadeOut(); + delayTicks(80); +} + +void SeqPlayer_HOF::playHoFTalkieCredits() { + static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 }; + + _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0)); + _screen->setFont(Screen::FID_GOLDFONT_FNT); + + int talkieCreditsSize, talkieCreditsSpecialSize; + const uint8 *talkieCredits = _vm->staticres()->loadRawData(k2SeqplayCredits, talkieCreditsSize); + const char *const *talkieCreditsSpecial = _vm->staticres()->loadStrings(k2SeqplayCreditsSpecial, talkieCreditsSpecialSize); + + _vm->sound()->selectAudioResourceSet(kMusicIngame); + _vm->sound()->loadSoundFile(3); + _vm->sound()->playTrack(3); + + _screen->setTextColorMap(colormap); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); + _screen->fadeFromBlack(); + + _screen->_charWidth = -2; + uint8 *dataPtr = new uint8[0xAFD]; + memcpy(dataPtr, talkieCredits, talkieCreditsSize); + _vm->staticres()->unloadId(k2SeqplayCredits); + + displayHoFTalkieScrollText(dataPtr, &d, 2, 6, 5, 1, Screen::FID_GOLDFONT_FNT, Screen::FID_GOLDFONT_FNT, 0, talkieCreditsSpecial); + delayTicks(8); + + delete[] dataPtr; + _vm->staticres()->unloadId(k2SeqplayCreditsSpecial); + _vm->sound()->selectAudioResourceSet(kMusicFinale); + _vm->sound()->loadSoundFile(0); +} + +void SeqPlayer_HOF::displayHoFTalkieScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, + int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData, const char *const *specialData) { + if (!data) + return; + + static const char mark[] = { 5, 13, 0 }; + + _screen->clearPage(tempPage1); + _screen->clearPage(tempPage2); + _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, 0, tempPage1); + + struct ScrollTextData { + int16 x; + int16 y; + uint8 *text; + byte unk1; + byte height; + byte adjust; + + ScrollTextData() { + x = 0; // 0 11 + y = 0; // 2 13 + text = 0; // 4 15 + unk1 = 0; // 8 19 + height = 0; // 9 20 + adjust = 0; // 10 21 + } + }; + + ScrollTextData *textData = new ScrollTextData[36]; + uint8 *ptr = data; + + bool loop = true; + int cnt = 0; + + while (loop) { + uint32 loopEnd = _system->getMillis() + speed * _vm->tickLength(); + + while (cnt < 35 && *ptr) { + uint16 cH; + + if (cnt) + cH = textData[cnt].y + textData[cnt].height + (textData[cnt].height >> 3); + else + cH = d->h; + + char *str = (char *)ptr; + + ptr = (uint8 *)strpbrk(str, mark); + if (!ptr) + ptr = (uint8 *)strchr(str, 0); + + textData[cnt + 1].unk1 = *ptr; + *ptr = 0; + if (textData[cnt + 1].unk1) + ptr++; + + if (*str == 3 || *str == 4) + textData[cnt + 1].adjust = *str++; + else + textData[cnt + 1].adjust = 0; + + _screen->setFont(fid1); + + if (*str == 1) { + _screen->setFont(fid2); + str++; + } else if (*str == 2) { + str++; + } + + textData[cnt + 1].height = _screen->getFontHeight(); + + switch (textData[cnt + 1].adjust) { + case 3: + textData[cnt + 1].x = 157 - _screen->getTextWidth(str); + break; + case 4: + textData[cnt + 1].x = 161; + break; + default: + textData[cnt + 1].x = (((d->w << 3) - _screen->getTextWidth(str)) >> 1) + 1; } + + if (textData[cnt].unk1 == 5) + cH -= (textData[cnt].height + (textData[cnt].height >> 3)); + + textData[cnt + 1].y = cH; + textData[cnt + 1].text = (uint8 *)str; + cnt++; } + + _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage1, tempPage2); + + int cnt2 = 0; + bool palCycle = 0; + + while (cnt2 < cnt) { + const char *str = (const char *)textData[cnt2 + 1].text; + const char *str2 = str; + int16 cW = textData[cnt2 + 1].x - 10; + int16 cH = textData[cnt2 + 1].y; + int x = (d->sx << 3) + cW; + int y = d->sy + cH; + int col1 = 255; + + if (cH < d->h) { + _screen->setCurPage(tempPage2); + _screen->setFont(fid1); + if (textData[cnt2 + 1].height != _screen->getFontHeight()) + _screen->setFont(fid2); + + if (specialData) { + if (!strcmp(str, specialData[0])) { + col1 = 112; + char cChar[2] = " "; + while (*str2) { + cChar[0] = *str2; + _screen->printText(cChar, x, y, col1++, 0); + x += _screen->getCharWidth((uint8)*str2++); + } + palCycle = true; + } else if (!strcmp(str, specialData[1])) { + col1 = 133; + char cChar[2] = " "; + while (*str2) { + cChar[0] = *str2; + _screen->printText(cChar, x, y, col1--, 0); + x += _screen->getCharWidth((uint8)*str2++); + } + palCycle = true; + } else { + _screen->printText(str, x, y, col1, 0); + } + } else { + _screen->printText(str, x, y, col1, 0); + } + _screen->setCurPage(0); + } + + textData[cnt2 + 1].y -= step; + cnt2++; + } + + _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage2, 0); + _screen->updateScreen(); + + if (textData[1].y < -10) { + textData[1].text += strlen((char *)textData[1].text); + textData[1].text[0] = textData[1].unk1; + cnt--; + memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); + } + + if (palCycle) { + for (int col = 133; col > 112; col--) + _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col); + _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112); + _screen->setScreenPalette(_screen->getPalette(0)); + } + + delayUntil(loopEnd); + + if ((cnt < 36) && ((d->sy + d->h) > (textData[cnt].y + textData[cnt].height)) && !_abortPlayback) { + delayTicks(500); + cnt = 0; + } + + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + loop = false; + + if (!cnt || _abortPlayback) + loop = false; } - if (_flags.isDemo && !_flags.isTalkie) { - _eventList.clear(); - _screen->fadeToBlack(); + _vm->sound()->beginFadeOut(); + _screen->fadeToBlack(); + + _abortPlayback = _abortRequested = false; + + delete[] textData; +} + +void SeqPlayer_HOF::updateDemoAdText(int bottom, int top) { + int dstY, dstH, srcH; + + static const ScreenDim d = { 0x00, 0x00, 0x28, 0x320, 0xFF, 0xFE, 0x00, 0x00 }; + + if (_scrollProgressCounter - (top - 1) < 0) { + dstY = top - _scrollProgressCounter; + dstH = _scrollProgressCounter; + srcH = 0; + } else { + dstY = 0; + srcH = _scrollProgressCounter - top; + dstH = (400 - srcH <= top) ? 400 - srcH : top; } - if (!_menuChoice) - delay(1200); + if (dstH > 0) { + if (_hofDemoAnimData) { + for (int i = 0; i < 4; i++) { + const HoFSeqItemAnimData *def = &_hofDemoAnimData[i]; + ActiveItemAnim *a = &_hofDemoActiveItemAnim[i]; - _screen->setCurPage(oldPage); - _screen->showMouse(); + _screen->fillRect(12, def->y - 8, 28, def->y + 8, 0, 4); + _screen->drawShape(4, _hofDemoItemShapes[def->itemIndex + def->frames[a->currentFrame]], 12, def->y - 8, 0, 0); + if (_callbackCurrentFrame % 2 == 0) + a->currentFrame = (a->currentFrame + 1) % 20; + } + } + _screen->copyRegionEx(4, 0, srcH, 2, 2, dstY + bottom, 320, dstH, &d); + } +} - for (int i = 0; i < 8; i++) - seq_unloadWSA(i); +void SeqPlayer_HOF::delayTicks(uint32 ticks) { + uint32 len = ticks * _vm->tickLength(); + while (len && !_vm->shouldQuit() && !checkAbortPlayback()) { + uint32 step = (len >= 10) ? 10 : len; + _system->delayMillis(step); + len -= step; + } +} - _seqWsa->close(); +void SeqPlayer_HOF::delayUntil(uint32 dest) { + for (uint32 ct = _system->getMillis(); ct < dest && !_vm->shouldQuit() && !checkAbortPlayback(); ) { + uint32 step = (dest - ct >= 10) ? 10 : (dest - ct); + _system->delayMillis(step); + ct = _system->getMillis(); + } +} - _screen->_charWidth = 0; +void SeqPlayer_HOF::setCountDown(uint32 ticks) { + _countDownRemainder = ticks * _vm->tickLength(); + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + _countDownRemainder = _countDownRemainder * 2 / 3; + _countDownLastUpdate = _system->getMillis() & ~(_vm->tickLength() - 1); +} - seq_uninit(); +bool SeqPlayer_HOF::countDownRunning() { + uint32 cur = _system->getMillis(); + uint32 step = cur - _countDownLastUpdate; + _countDownLastUpdate = cur; + _countDownRemainder = (step <= _countDownRemainder) ? _countDownRemainder - step : 0; + return _countDownRemainder; } -int KyraEngine_HoF::seq_introWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +#define CASE_ALT(dosCase, towns98Case)\ + case dosCase:\ + case towns98Case:\ + if (!((_callbackCurrentFrame == towns98Case && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == dosCase && _vm->gameFlags().platform == Common::kPlatformPC)))\ + break; + +int SeqPlayer_HOF::cbHOF_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == -2) { - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) - delay(300 * _tickLength); + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + delayTicks(300); } else if (!frm) { - _sound->playTrack(2); + _vm->sound()->playTrack(2); } return 0; } -int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_title(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 1) { - _sound->playTrack(3); - } else if (frm == 25) { + _vm->sound()->playTrack(3); + } else if (frm == 25 && _startupSaveLoadable) { int cp = _screen->setCurPage(0); _screen->showMouse(); _system->updateScreen(); - _menuChoice = _menu->handle(11) + 1; - _seqEndTime = 0; - _seqSubframePlaying = false; - if (_menuChoice == 4) - quitGame(); + _result = _menu->handle(11) + 1; + _updateAnimations = false; + + if (_result == 1) { + _curScene = _lastScene; + _preventLooping = true; + } else { + setCountDown(200); + } + + if (_result == 4) + _vm->quitGame(); _screen->hideMouse(); _screen->setCurPage(cp); @@ -355,31 +1792,29 @@ int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return 0; } -int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_overview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { uint8 *tmpPal = _screen->getPalette(3).getData() + 0x101; memset(tmpPal, 0, 256); - _seqSubFrameEndTimeInternal = 0; - uint32 now = 0; + uint32 frameEnd = 0; - switch (_seqFrameCounter) { + switch (_callbackCurrentFrame) { case 0: - _seqSubframePlaying = true; - _sound->playTrack(4); - _seqSubFrameEndTimeInternal = _system->getMillis() + 60 * _tickLength; + _updateAnimations = true; + fadeOutMusic(); + _vm->sound()->playTrack(4); + frameEnd = _system->getMillis() + 60 * _vm->tickLength(); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColorMap[1] = _textColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xFF; + _screen->setTextColorMap(_textColorMap); - _screen->setTextColorMap(_seqTextColorMap); - - now = _system->getMillis(); - if (_seqSubFrameEndTimeInternal > now) - delay(_seqSubFrameEndTimeInternal - now); + delayUntil(frameEnd); break; case 1: - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true); + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true); for (int i = 0; i < 256; i++) tmpPal[_screen->getPalette(3)[i]] = 1; @@ -393,19 +1828,19 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm break; case 40: - seq_loadNestedSequence(0, kSequenceOver1); + startNestedAnimation(0, kNestedSequenceOver1); break; case 60: - seq_loadNestedSequence(1, kSequenceOver2); + startNestedAnimation(1, kNestedSequenceOver2); break; case 120: - seq_playTalkText(0); + playSoundAndDisplaySubTitle(0); break; case 200: - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); _screen->fadePalette(_screen->getPalette(2), 64); break; @@ -417,64 +1852,57 @@ int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->setScreenPalette(_screen->getPalette(0)); _screen->updateScreen(); - seq_resetActiveWSA(0); - seq_resetActiveWSA(1); + closeNestedAnimation(0); + closeNestedAnimation(1); break; case 282: - seq_loadNestedSequence(0, kSequenceForest); - seq_playTalkText(1); + startNestedAnimation(0, kNestedSequenceForest); + playSoundAndDisplaySubTitle(1); break; - case 354: - case 434: - if (!((_seqFrameCounter == 354 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 434 && _flags.platform == Common::kPlatformPC))) - break; - - seq_resetActiveWSA(0); - seq_loadNestedSequence(0, kSequenceDragon); + CASE_ALT(434, 354) + closeNestedAnimation(0); + startNestedAnimation(0, kNestedSequenceDragon); break; - case 400: - case 540: - if (!((_seqFrameCounter == 400 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 540 && _flags.platform == Common::kPlatformPC))) - break; - - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - _seqEndTime = 0; - _seqSubframePlaying = false; + CASE_ALT(540, 400) + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + setCountDown(0); + _updateAnimations = false; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter) { +int SeqPlayer_HOF::cbHOF_library(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame) { case 0: - _seqSubframePlaying = true; - _sound->playTrack(5); + _updateAnimations = true; + _vm->sound()->playTrack(5); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColorMap[1] = _textColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xFF; - _screen->setTextColorMap(_seqTextColorMap); + _screen->setTextColorMap(_textColorMap); break; case 1: - seq_loadNestedSequence(0, kSequenceLibrary3); - seq_playTalkText(4); + startNestedAnimation(0, kNestedSequenceLibrary3); + playSoundAndDisplaySubTitle(4); break; case 100: - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); _screen->copyPage(12, 2); _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); @@ -482,585 +1910,560 @@ int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) _screen->updateScreen(); _screen->copyPage(2, 12); - seq_resetActiveWSA(0); - seq_loadNestedSequence(0, kSequenceDarm); + closeNestedAnimation(0); + startNestedAnimation(0, kNestedSequenceDarm); break; case 104: - seq_playTalkText(5); + playSoundAndDisplaySubTitle(5); break; case 240: - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - seq_loadNestedSequence(0, kSequenceLibrary2); + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + startNestedAnimation(0, kNestedSequenceLibrary2); break; case 340: - seq_resetActiveWSA(0); + closeNestedAnimation(0); _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); - seq_loadNestedSequence(0, kSequenceMarco); - seq_playTalkText(6); + startNestedAnimation(0, kNestedSequenceMarco); + playSoundAndDisplaySubTitle(6); break; - case 480: - case 660: - if (!((_seqFrameCounter == 480 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 660 && _flags.platform == Common::kPlatformPC))) - break; - + CASE_ALT(660, 480) _screen->copyPage(2, 12); - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - _seqEndTime = 0; - _seqSubframePlaying = false; + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + setCountDown(0); + _updateAnimations = false; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } - -int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter) { +int SeqPlayer_HOF::cbHOF_hand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame) { case 0: - _seqSubframePlaying = true; - _sound->playTrack(6); + _updateAnimations = true; + _vm->sound()->playTrack(6); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColorMap[1] = _textColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xFF; - _screen->setTextColorMap(_seqTextColorMap); + _screen->setTextColorMap(_textColorMap); break; case 1: - seq_loadNestedSequence(0, kSequenceHand1a); - seq_loadNestedSequence(1, kSequenceHand1b); - seq_loadNestedSequence(2, kSequenceHand1c); - seq_playTalkText(7); + startNestedAnimation(0, kNestedSequenceHand1a); + startNestedAnimation(1, kNestedSequenceHand1b); + startNestedAnimation(2, kNestedSequenceHand1c); + playSoundAndDisplaySubTitle(7); break; case 201: - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); _screen->copyPage(2, 12); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); - seq_resetActiveWSA(0); - seq_resetActiveWSA(1); - seq_resetActiveWSA(2); - seq_loadNestedSequence(0, kSequenceHand2); - seq_playTalkText(8); + closeNestedAnimation(0); + closeNestedAnimation(1); + closeNestedAnimation(2); + startNestedAnimation(0, kNestedSequenceHand2); + playSoundAndDisplaySubTitle(8); break; - case 260: - case 395: - if (!((_seqFrameCounter == 260 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 395 && _flags.platform == Common::kPlatformPC))) - break; - - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - seq_loadNestedSequence(1, kSequenceHand3); - seq_playTalkText(9); + CASE_ALT(395, 260) + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + startNestedAnimation(1, kNestedSequenceHand3); + playSoundAndDisplaySubTitle(9); break; - case 365: - case 500: - if (!((_seqFrameCounter == 365 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 500 && _flags.platform == Common::kPlatformPC))) - break; - - seq_waitForTextsTimeout(); - seq_resetActiveWSA(1); - seq_loadNestedSequence(0, kSequenceHand4); + CASE_ALT(500, 365) + waitForSubTitlesTimeout(); + closeNestedAnimation(1); + startNestedAnimation(0, kNestedSequenceHand4); break; - case 405: - case 540: - if (!((_seqFrameCounter == 405 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 540 && _flags.platform == Common::kPlatformPC))) - break; - - seq_playTalkText(10); + CASE_ALT(540, 405) + playSoundAndDisplaySubTitle(10); break; - case 484: - case 630: - if (!((_seqFrameCounter == 484 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 630 && _flags.platform == Common::kPlatformPC))) - break; - - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - _seqEndTime = 0; - _seqSubframePlaying = false; + CASE_ALT(630, 484) + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + setCountDown(0); + _updateAnimations = false; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_point(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == -2) { - seq_waitForTextsTimeout(); - _seqEndTime = 0; + waitForSubTitlesTimeout(); + setCountDown(0); } - switch (_seqFrameCounter) { + switch (_callbackCurrentFrame) { case -2: - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); break; case 0: - _sound->playTrack(7); + _vm->sound()->playTrack(7); - _seqTextColor[1] = 0xf7; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; - _screen->setTextColorMap(_seqTextColorMap); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _textColor[1] = 0xF7; + memset(_textColorMap, _textColor[1], 16); + _textColorMap[1] = _textColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xFF; + _screen->setTextColorMap(_textColorMap); + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); break; case 1: - seq_playTalkText(11); + playSoundAndDisplaySubTitle(11); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_zanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == -2) { - seq_waitForTextsTimeout(); - _seqEndTime = 0; + waitForSubTitlesTimeout(); + setCountDown(0); return 0; } - switch (_seqFrameCounter) { + switch (_callbackCurrentFrame) { case 0: - _sound->playTrack(8); + _vm->sound()->playTrack(8); - _seqTextColor[1] = 0xfd; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; - _screen->setTextColorMap(_seqTextColorMap); + _textColor[1] = 0xFD; + memset(_textColorMap, _textColor[1], 16); + _textColorMap[1] = _textColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xFF; + _screen->setTextColorMap(_textColorMap); break; case 1: - if (_flags.isTalkie) { - seq_playWsaSyncDialogue(21, 13, -1, 140, 70, 160, wsaObj, 0, 8, x, y); + if (_vm->gameFlags().isTalkie) { + playDialogueAnimation(21, 13, -1, 140, 70, 160, wsaObj, 0, 8, x, y); } else { - seq_setTextEntry(21, 140, 70, 200, 160); - _seqFrameDelay = 200; + displaySubTitle(21, 140, 70, 200, 160); + _animDuration = 200; } break; case 2: case 11: case 21: - if (!_flags.isTalkie) - _seqFrameDelay = 12; + if (!_vm->gameFlags().isTalkie) + _animDuration = 12; break; case 9: - if (_flags.isTalkie) - seq_playWsaSyncDialogue(13, 14, -1, 140, (_flags.lang == Common::FR_FRA - || _flags.lang == Common::DE_DEU) ? 50 : 70, 160, wsaObj, 9, 15, x, y); + if (_vm->gameFlags().isTalkie) + playDialogueAnimation(13, 14, -1, 140, (_vm->gameFlags().lang == Common::FR_FRA + || _vm->gameFlags().lang == Common::DE_DEU) ? 50 : 70, 160, wsaObj, 9, 15, x, y); break; case 10: - if (!_flags.isTalkie) { - seq_waitForTextsTimeout(); - seq_setTextEntry(13, 140, 50, _sequenceStringsDuration[13], 160); - _seqFrameDelay = 300; + if (!_vm->gameFlags().isTalkie) { + waitForSubTitlesTimeout(); + displaySubTitle(13, 140, 50, _textDuration[13], 160); + _animDuration = 300; } break; case 16: - if (_flags.isTalkie) - seq_playWsaSyncDialogue(18, 15, -1, 140, (_flags.lang == Common::FR_FRA) ? 50 : - (_flags.lang == Common::DE_DEU ? 40 : 70), 160, wsaObj, 10, 16, x, y); + if (_vm->gameFlags().isTalkie) + playDialogueAnimation(18, 15, -1, 140, (_vm->gameFlags().lang == Common::FR_FRA) ? 50 : + (_vm->gameFlags().lang == Common::DE_DEU ? 40 : 70), 160, wsaObj, 10, 16, x, y); break; case 17: - if (_flags.isTalkie) - _seqFrameDelay = 12; + if (_vm->gameFlags().isTalkie) + _animDuration = 12; break; case 20: - if (!_flags.isTalkie) { - seq_waitForTextsTimeout(); - seq_setTextEntry(18, 160, 50, _sequenceStringsDuration[18], 160); - _seqFrameDelay = 200; + if (!_vm->gameFlags().isTalkie) { + waitForSubTitlesTimeout(); + displaySubTitle(18, 160, 50, _textDuration[18], 160); + _animDuration = 200; } break; case 26: - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); break; case 46: - if (_flags.isTalkie) { - seq_playWsaSyncDialogue(16, 16, -1, 200, 50, 120, wsaObj, 46, 46, x, y); + if (_vm->gameFlags().isTalkie) { + playDialogueAnimation(16, 16, -1, 200, 50, 120, wsaObj, 46, 46, x, y); } else { - seq_waitForTextsTimeout(); - seq_setTextEntry(16, 200, 50, _sequenceStringsDuration[16], 120); + waitForSubTitlesTimeout(); + displaySubTitle(16, 200, 50, _textDuration[16], 120); } - _seqEndTime = _system->getMillis() + 120 * _tickLength; + setCountDown(120); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_introOver1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_over1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 2) - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); else if (frm == 3) - seq_playTalkText(12); + playSoundAndDisplaySubTitle(12); return frm; } - -int KyraEngine_HoF::seq_introOver2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_over2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 1) - seq_playTalkText(12); + playSoundAndDisplaySubTitle(12); return frm; } -int KyraEngine_HoF::seq_introForest(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_forest(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 11) - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); else if (frm == 12) - seq_playTalkText(2); + playSoundAndDisplaySubTitle(2); return frm; } -int KyraEngine_HoF::seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_dragon(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 11) - seq_waitForTextsTimeout(); + waitForSubTitlesTimeout(); else if (frm == 3) - seq_playTalkText(3); + playSoundAndDisplaySubTitle(3); return frm; } -int KyraEngine_HoF::seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) +int SeqPlayer_HOF::cbHOF_darm(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) +int SeqPlayer_HOF::cbHOF_library2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_marco(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 36) { - seq_waitForTextsTimeout(); - _seqEndTime = 0; + waitForSubTitlesTimeout(); + setCountDown(0); } return frm; } -int KyraEngine_HoF::seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) +int SeqPlayer_HOF::cbHOF_hand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introHand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_hand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 15) frm = 12; return frm; } -int KyraEngine_HoF::seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_hand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 8) frm = 4; return frm; } -int KyraEngine_HoF::seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) +int SeqPlayer_HOF::cbHOF_hand2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) +int SeqPlayer_HOF::cbHOF_hand3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; +int SeqPlayer_HOF::cbHOF_funters(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; + int subTitleFirstFrame = 0; + int subTitleLastFrame = 0; uint16 voiceIndex = 0; switch (frm) { case -2: - seq_sequenceCommand(9); + doTransition(9); break; case 0: - _sound->playTrack(3); + _vm->sound()->playTrack(3); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 0xFF; + _screen->setTextColorMap(_textColorMap); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(81, 240, 70, _seqTextColorMap, 252); - seq_printCreditsString(82, 240, 90, _seqTextColorMap, _seqTextColor[0]); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + printFadingText(81, 240, 70, _textColorMap, 252); + printFadingText(82, 240, 90, _textColorMap, _textColor[0]); _screen->copyPage(2, 12); - seq_playTalkText(_flags.isTalkie ? 28 : 24); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqTextColor[0] = 1; - - if (_flags.isTalkie) { - chatY = (_flags.lang == Common::FR_FRA) ? 70 : 78; - chatFirstFrame = 9; - chatLastFrame = 15; + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 28 : 24); + delayUntil(frameEnd); + _textColor[0] = 1; + + if (_vm->gameFlags().isTalkie) { + subTitleY = (_vm->gameFlags().lang == Common::FR_FRA) ? 70 : 78; + subTitleFirstFrame = 9; + subTitleLastFrame = 15; voiceIndex = 34; } else { - chatY = (_flags.lang == Common::FR_FRA) ? 78 : 70; - chatFirstFrame = 0; - chatLastFrame = 8; + subTitleY = (_vm->gameFlags().lang == Common::FR_FRA) ? 78 : 70; + subTitleFirstFrame = 0; + subTitleLastFrame = 8; } - chatX = (_flags.lang == Common::FR_FRA) ? 84 : 88; - chatW = 100; + subTitleX = (_vm->gameFlags().lang == Common::FR_FRA) ? 84 : 88; + subTitleW = 100; - seq_playWsaSyncDialogue(22, voiceIndex, 187, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + playDialogueAnimation(22, voiceIndex, 187, subTitleX, subTitleY, subTitleW, wsaObj, subTitleFirstFrame, subTitleLastFrame, x, y); break; case 9: case 16: - if (!((frm == 9 && !_flags.isTalkie) || (frm == 16 && _flags.isTalkie))) + if (!((frm == 9 && !_vm->gameFlags().isTalkie) || (frm == 16 && _vm->gameFlags().isTalkie))) break; - _seqFrameDelay = 12; + _animDuration = 12; - if (_flags.lang == Common::FR_FRA) { - chatX = 80; - chatW = 112; + if (_vm->gameFlags().lang == Common::FR_FRA) { + subTitleX = 80; + subTitleW = 112; } else { - chatX = (_flags.lang == Common::DE_DEU) ? 84 : 96; - chatW = 100; + subTitleX = (_vm->gameFlags().lang == Common::DE_DEU) ? 84 : 96; + subTitleW = 100; } - if (_flags.isTalkie) { - chatFirstFrame = 0; - chatLastFrame = 8; + if (_vm->gameFlags().isTalkie) { + subTitleFirstFrame = 0; + subTitleLastFrame = 8; voiceIndex = 35; } else { - chatFirstFrame = 9; - chatLastFrame = 15; + subTitleFirstFrame = 9; + subTitleLastFrame = 15; } - chatY = 70; + subTitleY = 70; - seq_playWsaSyncDialogue(23, voiceIndex, 137, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 17; + playDialogueAnimation(23, voiceIndex, 137, subTitleX, subTitleY, subTitleW, wsaObj, subTitleFirstFrame, subTitleLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 17; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; +int SeqPlayer_HOF::cbHOF_ferb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; + int subTitleFirstFrame = 0; + int subTitleLastFrame = 0; uint16 voiceIndex = 0; switch (frm) { case -2: - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(34, 240, _flags.isTalkie ? 60 : 40, _seqTextColorMap, 252); - seq_printCreditsString(35, 240, _flags.isTalkie ? 70 : 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(36, 240, _flags.isTalkie ? 90 : 70, _seqTextColorMap, 252); - seq_printCreditsString(37, 240, _flags.isTalkie ? 100 : 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(38, 240, _flags.isTalkie ? 120 : 110, _seqTextColorMap, 252); - seq_printCreditsString(39, 240, _flags.isTalkie ? 130 : 120, _seqTextColorMap, _seqTextColor[0]); - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) - seq_printCreditsString(103, 240, 130, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + printFadingText(34, 240, _vm->gameFlags().isTalkie ? 60 : 40, _textColorMap, 252); + printFadingText(35, 240, _vm->gameFlags().isTalkie ? 70 : 50, _textColorMap, _textColor[0]); + printFadingText(36, 240, _vm->gameFlags().isTalkie ? 90 : 70, _textColorMap, 252); + printFadingText(37, 240, _vm->gameFlags().isTalkie ? 100 : 90, _textColorMap, _textColor[0]); + printFadingText(38, 240, _vm->gameFlags().isTalkie ? 120 : 110, _textColorMap, 252); + printFadingText(39, 240, _vm->gameFlags().isTalkie ? 130 : 120, _textColorMap, _textColor[0]); + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + printFadingText(103, 240, 130, _textColorMap, _textColor[0]); + delayUntil(frameEnd); + setCountDown(0); break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 255; - _screen->setTextColorMap(_seqTextColorMap); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 255; + _screen->setTextColorMap(_textColorMap); break; case 5: - if (!_flags.isTalkie) - seq_playTalkText(18); - _seqFrameDelay = 16; + if (!_vm->gameFlags().isTalkie) + playSoundAndDisplaySubTitle(18); + _animDuration = 16; - if (_flags.isTalkie) { - chatFirstFrame = 5; - chatLastFrame = 8; + if (_vm->gameFlags().isTalkie) { + subTitleFirstFrame = 5; + subTitleLastFrame = 8; voiceIndex = 22; } else { - chatLastFrame = 14; + subTitleLastFrame = 14; } - chatX = 116; - chatY = 90; - chatW = 60; + subTitleX = 116; + subTitleY = 90; + subTitleW = 60; - seq_playWsaSyncDialogue(24, voiceIndex, 149, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + playDialogueAnimation(24, voiceIndex, 149, subTitleX, subTitleY, subTitleW, wsaObj, subTitleFirstFrame, subTitleLastFrame, x, y); break; case 11: - if (_flags.isTalkie) - seq_playWsaSyncDialogue(24, 22, 149, 116, 90, 60, wsaObj, 11, 14, x, y); + if (_vm->gameFlags().isTalkie) + playDialogueAnimation(24, 22, 149, 116, 90, 60, wsaObj, 11, 14, x, y); break; case 16: - seq_playTalkText(_flags.isTalkie ? 23 : 19); - _seqFrameDelay = _flags.isTalkie ? 20 : 16; + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 23 : 19); + _animDuration = _vm->gameFlags().isTalkie ? 20 : 16; - if (_flags.lang == Common::FR_FRA) { - chatY = 48; - chatW = 88; + if (_vm->gameFlags().lang == Common::FR_FRA) { + subTitleY = 48; + subTitleW = 88; } else { - chatY = 60; - chatW = 100; + subTitleY = 60; + subTitleW = 100; } - chatX = 60; + subTitleX = 60; - if (_flags.isTalkie) + if (_vm->gameFlags().isTalkie) voiceIndex = 36; - seq_playWsaSyncDialogue(25, voiceIndex, 143, chatX, chatY, chatW, wsaObj, 16, 25, x, y); - _seqFrameDelay = 16; + playDialogueAnimation(25, voiceIndex, 143, subTitleX, subTitleY, subTitleW, wsaObj, 16, 25, x, y); + _animDuration = 16; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; +int SeqPlayer_HOF::cbHOF_fish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; uint16 voiceIndex = 0; switch (frm) { case -2: - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); - seq_printCreditsString(40, 240, _flags.isTalkie ? 55 : 40, _seqTextColorMap, 252); - seq_printCreditsString(41, 240, _flags.isTalkie ? 65 : 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(42, 240, _flags.isTalkie ? 75 : 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(43, 240, _flags.isTalkie ? 95 : 80, _seqTextColorMap, 252); - seq_printCreditsString(44, 240, _flags.isTalkie ? 105 : 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(93, 240, _flags.isTalkie ? 125 : 110, _seqTextColorMap, 252); - seq_printCreditsString(94, 240, _flags.isTalkie ? 135 : 120, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; + printFadingText(40, 240, _vm->gameFlags().isTalkie ? 55 : 40, _textColorMap, 252); + printFadingText(41, 240, _vm->gameFlags().isTalkie ? 65 : 50, _textColorMap, _textColor[0]); + printFadingText(42, 240, _vm->gameFlags().isTalkie ? 75 : 60, _textColorMap, _textColor[0]); + printFadingText(43, 240, _vm->gameFlags().isTalkie ? 95 : 80, _textColorMap, 252); + printFadingText(44, 240, _vm->gameFlags().isTalkie ? 105 : 90, _textColorMap, _textColor[0]); + printFadingText(93, 240, _vm->gameFlags().isTalkie ? 125 : 110, _textColorMap, 252); + printFadingText(94, 240, _vm->gameFlags().isTalkie ? 135 : 120, _textColorMap, _textColor[0]); + delayUntil(frameEnd); + setCountDown(0); break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 0xFF; + _screen->setTextColorMap(_textColorMap); break; case 4: - chatX = 94; - chatY = 42; - chatW = 100; - if (_flags.isTalkie) + subTitleX = 94; + subTitleY = 42; + subTitleW = 100; + if (_vm->gameFlags().isTalkie) voiceIndex = 37; - seq_playWsaSyncDialogue(26, voiceIndex, 149, chatX, chatY, chatW, wsaObj, 3, 12, x, y); + playDialogueAnimation(26, voiceIndex, 149, subTitleX, subTitleY, subTitleW, wsaObj, 3, 12, x, y); break; case 14: - seq_playTalkText(_flags.isTalkie ? 19 : 15); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 19 : 15); break; case 23: - seq_playTalkText(_flags.isTalkie ? 20 : 16); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 20 : 16); break; case 29: - chatX = (_flags.lang == Common::DE_DEU) ? 82 : ((_flags.lang == Common::FR_FRA) ? 92 : 88); - chatY = 40; - chatW = 100; + subTitleX = (_vm->gameFlags().lang == Common::DE_DEU) ? 82 : ((_vm->gameFlags().lang == Common::FR_FRA) ? 92 : 88); + subTitleY = 40; + subTitleW = 100; - if (_flags.isTalkie) { - if (_flags.lang == Common::DE_DEU) - chatY = 35; + if (_vm->gameFlags().isTalkie) { + if (_vm->gameFlags().lang == Common::DE_DEU) + subTitleY = 35; voiceIndex = 38; } - seq_playWsaSyncDialogue(27, voiceIndex, 187, chatX, chatY, chatW, wsaObj, 28, 34, x, y); + playDialogueAnimation(27, voiceIndex, 187, subTitleX, subTitleY, subTitleW, wsaObj, 28, 34, x, y); break; case 45: - seq_playTalkText(_flags.isTalkie ? 21 : 17); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 21 : 17); break; case 50: - seq_playTalkText(_flags.isTalkie ? 29 : 25); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 29 : 25); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; +int SeqPlayer_HOF::cbHOF_fheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; + int subTitleFirstFrame = 0; + int subTitleLastFrame = 0; uint16 voiceIndex = 0; switch (frm) { @@ -1068,79 +2471,79 @@ int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) _screen->copyPage(12, 2); _screen->copyPage(2, 0); _screen->updateScreen(); - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(49, 240, 20, _seqTextColorMap, 252); - seq_printCreditsString(50, 240, 30, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(51, 240, 40, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(52, 240, 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(53, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(54, 240, 70, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(55, 240, 80, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(56, 240, 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(57, 240, 100, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(58, 240, 110, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(60, 240, 120, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(61, 240, 130, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(62, 240, 140, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(63, 240, 150, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(64, 240, 160, _seqTextColorMap, _seqTextColor[0]); - - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + printFadingText(49, 240, 20, _textColorMap, 252); + printFadingText(50, 240, 30, _textColorMap, _textColor[0]); + printFadingText(51, 240, 40, _textColorMap, _textColor[0]); + printFadingText(52, 240, 50, _textColorMap, _textColor[0]); + printFadingText(53, 240, 60, _textColorMap, _textColor[0]); + printFadingText(54, 240, 70, _textColorMap, _textColor[0]); + printFadingText(55, 240, 80, _textColorMap, _textColor[0]); + printFadingText(56, 240, 90, _textColorMap, _textColor[0]); + printFadingText(57, 240, 100, _textColorMap, _textColor[0]); + printFadingText(58, 240, 110, _textColorMap, _textColor[0]); + printFadingText(60, 240, 120, _textColorMap, _textColor[0]); + printFadingText(61, 240, 130, _textColorMap, _textColor[0]); + printFadingText(62, 240, 140, _textColorMap, _textColor[0]); + printFadingText(63, 240, 150, _textColorMap, _textColor[0]); + printFadingText(64, 240, 160, _textColorMap, _textColor[0]); + + delayUntil(frameEnd); + setCountDown(0); break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 0xFF; + _screen->setTextColorMap(_textColorMap); break; case 2: - seq_playTalkText(_flags.isTalkie ? 25 : 21); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 25 : 21); - if (_flags.lang == Common::FR_FRA) { - chatX = 92; - chatY = 72; + if (_vm->gameFlags().lang == Common::FR_FRA) { + subTitleX = 92; + subTitleY = 72; } else { - chatX = (_flags.lang == Common::DE_DEU) ? 90 : 98; - chatY = 84; + subTitleX = (_vm->gameFlags().lang == Common::DE_DEU) ? 90 : 98; + subTitleY = 84; } - if (_flags.isTalkie) { - chatFirstFrame = 8; - chatLastFrame = 9; + if (_vm->gameFlags().isTalkie) { + subTitleFirstFrame = 8; + subTitleLastFrame = 9; voiceIndex = 39; } else { - chatFirstFrame = 2; - chatLastFrame = -8; + subTitleFirstFrame = 2; + subTitleLastFrame = -8; } - chatW = 100; + subTitleW = 100; - seq_playWsaSyncDialogue(28, voiceIndex, -1, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 4; + playDialogueAnimation(28, voiceIndex, -1, subTitleX, subTitleY, subTitleW, wsaObj, subTitleFirstFrame, subTitleLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 4; break; case 9: - seq_playTalkText(_flags.isTalkie ? 24 : 20); - _seqFrameDelay = 100; + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 24 : 20); + _animDuration = 100; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; +int SeqPlayer_HOF::cbHOF_farmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; uint16 voiceIndex = 0; switch (frm) { @@ -1148,169 +2551,164 @@ int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) _screen->copyPage(12, 2); _screen->copyPage(2, 0); _screen->updateScreen(); - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(45, 240, 40, _seqTextColorMap, 252); - seq_printCreditsString(46, 240, 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(47, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(83, 240, 80, _seqTextColorMap, 252); - seq_printCreditsString(48, 240, 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(65, 240, 110, _seqTextColorMap, 252); - seq_printCreditsString(66, 240, 120, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(67, 240, 130, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(68, 240, 140, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(69, 240, 150, _seqTextColorMap, _seqTextColor[0]); - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) - seq_printCreditsString(104, 240, 160, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + printFadingText(45, 240, 40, _textColorMap, 252); + printFadingText(46, 240, 50, _textColorMap, _textColor[0]); + printFadingText(47, 240, 60, _textColorMap, _textColor[0]); + printFadingText(83, 240, 80, _textColorMap, 252); + printFadingText(48, 240, 90, _textColorMap, _textColor[0]); + printFadingText(65, 240, 110, _textColorMap, 252); + printFadingText(66, 240, 120, _textColorMap, _textColor[0]); + printFadingText(67, 240, 130, _textColorMap, _textColor[0]); + printFadingText(68, 240, 140, _textColorMap, _textColor[0]); + printFadingText(69, 240, 150, _textColorMap, _textColor[0]); + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + printFadingText(104, 240, 160, _textColorMap, _textColor[0]); + delayUntil(frameEnd); + setCountDown(0); break; case 0: - _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 254) & 0xff); - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xff); - _screen->setTextColorMap(_seqTextColorMap); - seq_playTalkText(_flags.isTalkie ? 30 : 26); + _textColor[1] = 1 + (_screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 254) & 0xFF); + memset(_textColorMap, _textColor[1], 16); + _textColorMap[1] = _textColor[0] = 1 + (_screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xFF); + _screen->setTextColorMap(_textColorMap); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 30 : 26); break; case 6: - if (_flags.isTalkie) - seq_playTalkText(18); + if (_vm->gameFlags().isTalkie) + playSoundAndDisplaySubTitle(18); break; case 12: - if (!_flags.isTalkie) - seq_playTalkText(14); + if (!_vm->gameFlags().isTalkie) + playSoundAndDisplaySubTitle(14); - chatX = 90; - chatY = 30; - chatW = 100; + subTitleX = 90; + subTitleY = 30; + subTitleW = 100; - if (_flags.isTalkie) { - if (_flags.lang == Common::FR_FRA || _flags.lang == Common::DE_DEU) { - chatX = 75; - chatY = 25; + if (_vm->gameFlags().isTalkie) { + if (_vm->gameFlags().lang == Common::FR_FRA || _vm->gameFlags().lang == Common::DE_DEU) { + subTitleX = 75; + subTitleY = 25; } voiceIndex = 40; } - seq_playWsaSyncDialogue(29, voiceIndex, 150, chatX, chatY, chatW, wsaObj, 12, -21, x, y); + playDialogueAnimation(29, voiceIndex, 150, subTitleX, subTitleY, subTitleW, wsaObj, 12, -21, x, y); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; - //int textCol = 0; +int SeqPlayer_HOF::cbHOF_fuards(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; + int subTitleFirstFrame = 0; + int subTitleLastFrame = 0; uint16 voiceIndex = 0; switch (frm) { case -2: - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(70, 240, 20, _seqTextColorMap, 252); - seq_printCreditsString(71, 240, 30, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(72, 240, 40, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(73, 240, 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(74, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(75, 240, 70, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(101, 240, 80, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(102, 240, 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(87, 240, 100, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(88, 240, 110, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(89, 240, 120, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(90, 240, 130, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(91, 240, 140, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(92, 240, 150, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + printFadingText(70, 240, 20, _textColorMap, 252); + printFadingText(71, 240, 30, _textColorMap, _textColor[0]); + printFadingText(72, 240, 40, _textColorMap, _textColor[0]); + printFadingText(73, 240, 50, _textColorMap, _textColor[0]); + printFadingText(74, 240, 60, _textColorMap, _textColor[0]); + printFadingText(75, 240, 70, _textColorMap, _textColor[0]); + printFadingText(101, 240, 80, _textColorMap, _textColor[0]); + printFadingText(102, 240, 90, _textColorMap, _textColor[0]); + printFadingText(87, 240, 100, _textColorMap, _textColor[0]); + printFadingText(88, 240, 110, _textColorMap, _textColor[0]); + printFadingText(89, 240, 120, _textColorMap, _textColor[0]); + printFadingText(90, 240, 130, _textColorMap, _textColor[0]); + printFadingText(91, 240, 140, _textColorMap, _textColor[0]); + printFadingText(92, 240, 150, _textColorMap, _textColor[0]); + delayUntil(frameEnd); + setCountDown(0); break; case 0: for (int i = 0; i < 0x300; i++) - _screen->getPalette(0)[i] &= 0x3f; - _seqTextColor[1] = 0xCf; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xfe; + _screen->getPalette(0)[i] &= 0x3F; + _textColor[1] = 0xCf; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 0xFE; - _screen->setTextColorMap(_seqTextColorMap); + _screen->setTextColorMap(_textColorMap); break; case 6: - _seqFrameDelay = 20; + _animDuration = 20; - if (_flags.isTalkie) { - chatX = 82; - //textCol = 143; - chatFirstFrame = 16; - chatLastFrame = 21; + if (_vm->gameFlags().isTalkie) { + subTitleX = 82; + subTitleFirstFrame = 16; + subTitleLastFrame = 21; voiceIndex = 41; } else { - chatX = 62; - //textCol = 137; - chatFirstFrame = 9; - chatLastFrame = 13; + subTitleX = 62; + subTitleFirstFrame = 9; + subTitleLastFrame = 13; } - chatY = (_flags.lang == Common::FR_FRA || _flags.lang == Common::DE_DEU) ? 88 :100; - chatW = 80; + subTitleY = (_vm->gameFlags().lang == Common::FR_FRA || _vm->gameFlags().lang == Common::DE_DEU) ? 88 :100; + subTitleW = 80; - seq_playWsaSyncDialogue(30, voiceIndex, 137, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 8; + playDialogueAnimation(30, voiceIndex, 137, subTitleX, subTitleY, subTitleW, wsaObj, subTitleFirstFrame, subTitleLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 8; break; case 9: case 16: - if (_flags.isTalkie) { + if (_vm->gameFlags().isTalkie) { if (frm == 16) break; - chatX = 64; - //textCol = 137; - chatFirstFrame = 9; - chatLastFrame = 13; + subTitleX = 64; + subTitleFirstFrame = 9; + subTitleLastFrame = 13; voiceIndex = 42; } else { if (frm == 9) break; - chatX = 80; - //textCol = 143; - chatFirstFrame = 16; - chatLastFrame = 21; + subTitleX = 80; + subTitleFirstFrame = 16; + subTitleLastFrame = 21; } - chatY = 100; - chatW = 100; + subTitleY = 100; + subTitleW = 100; - seq_playWsaSyncDialogue(31, voiceIndex, 143, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 21; + playDialogueAnimation(31, voiceIndex, 143, subTitleX, subTitleY, subTitleW, wsaObj, subTitleFirstFrame, subTitleLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 21; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; +int SeqPlayer_HOF::cbHOF_firates(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int subTitleX = 0; + int subTitleY = 0; + int subTitleW = 0; uint16 voiceIndex = 0; switch (frm) { @@ -1318,87 +2716,87 @@ int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm _screen->copyPage(12, 2); _screen->copyPage(2, 0); _screen->updateScreen(); - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(76, 240, 40, _seqTextColorMap, 252); - seq_printCreditsString(77, 240, 50, _seqTextColorMap, 252); - seq_printCreditsString(78, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(79, 240, 70, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(80, 240, 80, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(84, 240, 100, _seqTextColorMap, 252); - seq_printCreditsString(85, 240, 110, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(99, 240, 130, _seqTextColorMap, 252); - seq_printCreditsString(100, 240, 140, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + printFadingText(76, 240, 40, _textColorMap, 252); + printFadingText(77, 240, 50, _textColorMap, 252); + printFadingText(78, 240, 60, _textColorMap, _textColor[0]); + printFadingText(79, 240, 70, _textColorMap, _textColor[0]); + printFadingText(80, 240, 80, _textColorMap, _textColor[0]); + printFadingText(84, 240, 100, _textColorMap, 252); + printFadingText(85, 240, 110, _textColorMap, _textColor[0]); + printFadingText(99, 240, 130, _textColorMap, 252); + printFadingText(100, 240, 140, _textColorMap, _textColor[0]); + delayUntil(frameEnd); + setCountDown(0); break; case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 0xFF; + _screen->setTextColorMap(_textColorMap); break; case 6: - seq_playTalkText(_flags.isTalkie ? 31 : 27); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 31 : 27); break; case 14: case 15: - if (!((frm == 15 && !_flags.isTalkie) || (frm == 14 && _flags.isTalkie))) + if (!((frm == 15 && !_vm->gameFlags().isTalkie) || (frm == 14 && _vm->gameFlags().isTalkie))) break; - seq_playTalkText(_flags.isTalkie ? 31 : 27); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 31 : 27); - if (_flags.lang == Common::DE_DEU) { - chatX = 82; - chatY = 84; - chatW = 140; + if (_vm->gameFlags().lang == Common::DE_DEU) { + subTitleX = 82; + subTitleY = 84; + subTitleW = 140; } else { - chatX = 74; - chatY = (_flags.lang == Common::FR_FRA) ? 96: 108; - chatW = 80; + subTitleX = 74; + subTitleY = (_vm->gameFlags().lang == Common::FR_FRA) ? 96: 108; + subTitleW = 80; } - if (_flags.isTalkie) + if (_vm->gameFlags().isTalkie) voiceIndex = 43; - seq_playWsaSyncDialogue(32, voiceIndex, 137, chatX, chatY, chatW, wsaObj, 14, 16, x, y); + playDialogueAnimation(32, voiceIndex, 137, subTitleX, subTitleY, subTitleW, wsaObj, 14, 16, x, y); break; case 28: - seq_playTalkText(_flags.isTalkie ? 32 : 28); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 32 : 28); break; case 29: - seq_playTalkText(_flags.isTalkie ? 33 : 29); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 33 : 29); break; case 31: - if (_flags.isTalkie) + if (_vm->gameFlags().isTalkie) voiceIndex = 44; - chatX = 90; - chatY = (_flags.lang == Common::DE_DEU) ? 60 : 76; - chatW = 80; + subTitleX = 90; + subTitleY = (_vm->gameFlags().lang == Common::DE_DEU) ? 60 : 76; + subTitleW = 80; - seq_playWsaSyncDialogue(33, voiceIndex, 143, chatX, chatY, chatW, wsaObj, 31, 34, x, y); + playDialogueAnimation(33, voiceIndex, 143, subTitleX, subTitleY, subTitleW, wsaObj, 31, 34, x, y); break; case 35: - _seqFrameDelay = 300; + _animDuration = 300; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_frash(WSAMovie_v2 *wsaObj, int x, int y, int frm) { int tmp = 0; switch (frm) { @@ -1408,473 +2806,440 @@ int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm) _screen->copyPage(2, 12); _screen->copyPage(2, 0); _screen->updateScreen(); - _seqFrameCounter = 0; - seq_loadNestedSequence(0, kSequenceFiggle); + _callbackCurrentFrame = 0; + startNestedAnimation(0, kNestedSequenceFiggle); break; case -1: - if (_flags.isTalkie) - seq_finaleActorScreen(); - _seqSpecialFlag = _flags.isTalkie; + if (_vm->gameFlags().isTalkie) + playHoFTalkieCredits(); + _talkieFinaleExtraFlag = _vm->gameFlags().isTalkie; break; case 0: - if (_seqFrameCounter == 1) { - _sound->playTrack(4); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); + if (_callbackCurrentFrame == 1) { + _vm->sound()->playTrack(4); + _textColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xFF; + memset(_textColorMap, _textColor[1], 16); + _textColor[0] = _textColorMap[1] = 0xFF; + _screen->setTextColorMap(_textColorMap); } - _seqFrameDelay = 10; + _animDuration = 10; break; case 1: - if (_seqFrameCounter < 20 && _seqSpecialFlag) { - _seqWsaCurrentFrame = 0; + if (_callbackCurrentFrame < 20 && _talkieFinaleExtraFlag) { + _animCurrentFrame = 0; } else { - _seqFrameDelay = _flags.isTalkie ? 500 : (300 + _rnd.getRandomNumberRng(1, 300)); - seq_playTalkText(_flags.isTalkie ? 26 : 22); - if (_seqSpecialFlag) { - _seqFrameCounter = 3; - _seqSpecialFlag = false; + _animDuration = _vm->gameFlags().isTalkie ? 500 : (300 + _vm->_rnd.getRandomNumberRng(1, 300)); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 26 : 22); + if (_talkieFinaleExtraFlag) { + _callbackCurrentFrame = 3; + _talkieFinaleExtraFlag = false; } } break; case 2: - _seqFrameDelay = 20; + _animDuration = 20; break; case 3: - seq_playTalkText(_flags.isTalkie ? 27 : 23); - _seqFrameDelay = _flags.isTalkie ? 500 : (300 + _rnd.getRandomNumberRng(1, 300)); + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 27 : 23); + _animDuration = _vm->gameFlags().isTalkie ? 500 : (300 + _vm->_rnd.getRandomNumberRng(1, 300)); break; case 4: - _seqFrameDelay = 10; + _animDuration = 10; break; case 5: - seq_playTalkText(_flags.isTalkie ? 27 : 23); - tmp = _seqFrameCounter / 6; + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 27 : 23); + tmp = _callbackCurrentFrame / 6; if (tmp == 2) - _seqFrameDelay = _flags.isTalkie ? 7 : (1 + _rnd.getRandomNumberRng(1, 10)); + _animDuration = _vm->gameFlags().isTalkie ? 7 : (1 + _vm->_rnd.getRandomNumberRng(1, 10)); else if (tmp < 2) - _seqFrameDelay = _flags.isTalkie ? 500 : (300 + _rnd.getRandomNumberRng(1, 300)); + _animDuration = _vm->gameFlags().isTalkie ? 500 : (300 + _vm->_rnd.getRandomNumberRng(1, 300)); break; case 6: - _seqFrameDelay = 10; - tmp = _seqFrameCounter / 6; + _animDuration = 10; + tmp = _callbackCurrentFrame / 6; if (tmp == 2) - _seqWsaCurrentFrame = 4; + _animCurrentFrame = 4; else if (tmp < 2) - _seqWsaCurrentFrame = 0; + _animCurrentFrame = 0; break; case 7: - _seqFrameCounter = 0; - _seqFrameDelay = 5; - seq_playTalkText(_flags.isTalkie ? 26 : 22); + _callbackCurrentFrame = 0; + _animDuration = 5; + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 26 : 22); break; case 11: - if (_seqFrameCounter < 8) - _seqWsaCurrentFrame = 8; + if (_callbackCurrentFrame < 8) + _animCurrentFrame = 8; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -void KyraEngine_HoF::seq_finaleActorScreen() { - static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 }; - - _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0)); - _screen->setFont(Screen::FID_GOLDFONT_FNT); - - int talkieCreditsSize, talkieCreditsSpecialSize; - const uint8 *talkieCredits = _staticres->loadRawData(k2SeqplayCredits, talkieCreditsSize); - const char * const *talkieCreditsSpecial = _staticres->loadStrings(k2SeqplayCreditsSpecial, talkieCreditsSpecialSize); - - _sound->setSoundList(&_soundData[kMusicIngame]); - _sound->loadSoundFile(3); - _sound->playTrack(3); - - _screen->setTextColorMap(colormap); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); - _screen->fadeFromBlack(); - - _screen->_charWidth = -2; - uint8 *dataPtr = new uint8[0xafd]; - memcpy(dataPtr, talkieCredits, talkieCreditsSize); - _staticres->unloadId(k2SeqplayCredits); - - seq_displayScrollText(dataPtr, &d, 2, 6, 5, 1, Screen::FID_GOLDFONT_FNT, Screen::FID_GOLDFONT_FNT, 0, talkieCreditsSpecial); - delay(120); - - delete[] dataPtr; - _staticres->unloadId(k2SeqplayCreditsSpecial); - _sound->setSoundList(&_soundData[kMusicFinale]); - _sound->loadSoundFile(0); -} - -int KyraEngine_HoF::seq_finaleFiggle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (_seqFrameCounter == 10) - _seqEndTime = 0; - if (_seqFrameCounter == 10 || _seqFrameCounter == 5 || _seqFrameCounter == 7) - seq_playTalkText(_flags.isTalkie ? 45 : 30); +int SeqPlayer_HOF::cbHOF_figgle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (_callbackCurrentFrame == 10) + setCountDown(0); + if (_callbackCurrentFrame == 10 || _callbackCurrentFrame == 5 || _callbackCurrentFrame == 7) + playSoundAndDisplaySubTitle(_vm->gameFlags().isTalkie ? 45 : 30); - _seqFrameCounter++; + _callbackCurrentFrame++; return frm; } -int KyraEngine_HoF::seq_demoVirgin(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_virgin(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) - delay(50 * _tickLength); + delayTicks(50); return 0; } -int KyraEngine_HoF::seq_demoWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) - _sound->playTrack(2); + _vm->sound()->playTrack(2); return 0; } -int KyraEngine_HoF::seq_demoTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + +int SeqPlayer_HOF::cbHOFDEMO_title(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) { - _sound->playTrack(3); + _vm->sound()->playTrack(3); } else if (frm == 25) { - delay(60 * _tickLength); - _seqEndTime = 0; - seq_sequenceCommand(0); + delayTicks(60); + setCountDown(0); + doTransition(0); } return 0; } -int KyraEngine_HoF::seq_demoHill(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_hill(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (!frm) { - _sound->playTrack(4); + _vm->sound()->playTrack(4); } else if (frm == 25) { - seq_loadNestedSequence(0, kSequenceDemoWater); - _seqFrameDelay--; + startNestedAnimation(0, kNestedSequenceHoFDemoWater); + _animDuration--; } else if (frm > 25 && frm < 50) { - if (_seqFrameDelay > 3) - _seqFrameDelay--; + if (_animDuration > 3) + _animDuration--; } else if (frm == 95) { - _seqFrameDelay = 70; + _animDuration = 70; } else if (frm == 96) { - _seqFrameDelay = 7; + _animDuration = 7; } else if (frm == 129) { - seq_resetActiveWSA(0); + closeNestedAnimation(0); } return 0; } -int KyraEngine_HoF::seq_demoOuthome(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_outhome(WSAMovie_v2 *wsaObj, int x, int y, int frm) { switch (frm) { case 12: - seq_playTalkText(4); + playSoundAndDisplaySubTitle(4); break; case 32: - seq_playTalkText(7); + playSoundAndDisplaySubTitle(7); break; case 36: - seq_playTalkText(10); + playSoundAndDisplaySubTitle(10); break; case 57: - seq_playTalkText(9); + playSoundAndDisplaySubTitle(9); break; case 80: case 96: case 149: - _seqFrameDelay = 70; + _animDuration = 70; break; case 81: case 97: - _seqFrameDelay = 5; + _animDuration = 5; break; case 110: - seq_playTalkText(5); + playSoundAndDisplaySubTitle(5); break; case 137: - seq_playTalkText(6); + playSoundAndDisplaySubTitle(6); break; } return 0; } -int KyraEngine_HoF::seq_demoWharf(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (!_seqFrameCounter) - seq_loadNestedSequence(0, kSequenceDemoWharf2); +int SeqPlayer_HOF::cbHOFDEMO_wharf(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (!_callbackCurrentFrame) + startNestedAnimation(0, kNestedSequenceHoFDemoWharf2); switch (frm) { case 0: - seq_playTalkText(11); + playSoundAndDisplaySubTitle(11); break; case 5: - if ((_seqFrameCounter / 8) <= 2 || _activeWSA[0].flags != -1) - _seqWsaCurrentFrame = 0; + if ((_callbackCurrentFrame / 8) <= 2 || _animSlots[0].flags != -1) + _animCurrentFrame = 0; else - seq_resetActiveWSA(0); + closeNestedAnimation(0); break; case 6: - seq_resetActiveWSA(0); + closeNestedAnimation(0); break; case 8: case 10: - seq_playTalkText(2); + playSoundAndDisplaySubTitle(2); break; case 13: - seq_playTalkText(7); + playSoundAndDisplaySubTitle(7); break; case 16: - seq_playTalkText(12); + playSoundAndDisplaySubTitle(12); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_demoDinob(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_dinob(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 0) { - if (!(_seqFrameCounter/8)) { - seq_loadNestedSequence(0, kSequenceDemoDinob2); - _seqWsaCurrentFrame = 0; + if (!(_callbackCurrentFrame/8)) { + startNestedAnimation(0, kNestedSequenceHoFDemoDinob2); + _animCurrentFrame = 0; } } else if (frm == 3) { - if (_activeWSA[0].flags != -1) { - _seqWsaCurrentFrame = 0; + if (_animSlots[0].flags != -1) { + _animCurrentFrame = 0; } else { - seq_resetActiveWSA(0); + closeNestedAnimation(0); _screen->copyPage(2, 12); } } else if (frm == 4) { - seq_resetActiveWSA(0); + closeNestedAnimation(0); } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_demoFisher(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (((_system->getMillis() - _seqStartTime) / (5 * _tickLength)) > 0) { - _seqStartTime = _system->getMillis(); - if (!_seqFrameCounter) { - seq_loadNestedSequence(0, kSequenceDemoBail); - seq_loadNestedSequence(1, kSequenceDemoDig); +int SeqPlayer_HOF::cbHOFDEMO_fisher(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (((_system->getMillis() - _fisherAnimCurTime) / (5 * _vm->tickLength())) > 0) { + _fisherAnimCurTime = _system->getMillis(); + if (!_callbackCurrentFrame) { + startNestedAnimation(0, kNestedSequenceHoFDemoBail); + startNestedAnimation(1, kNestedSequenceHoFDemoDig); } - if (_seqScrollTextCounter >= 0x18f && !_seqFrameCounter) + if (_scrollProgressCounter >= 0x18F && !_callbackCurrentFrame) return 0; - if (!_seqFrameCounter) { + if (!_callbackCurrentFrame) { _screen->loadBitmap("adtext.cps", 4, 4, 0); _screen->loadBitmap("adtext2.cps", 6, 6, 0); _screen->copyPageMemory(6, 0, 4, 64000, 1024); _screen->copyPageMemory(6, 1023, 6, 0, 64000); - _seqScrollTextCounter = 0; + _scrollProgressCounter = 0; } - seq_scrollPage(24, 144); - _seqFrameCounter++; - if (_seqFrameCounter < 0x256 || _seqFrameCounter > 0x31c) { - if (_seqFrameCounter < 0x174 || _seqFrameCounter > 0x1d7) { - if (_seqFrameCounter < 0x84 || _seqFrameCounter > 0xe7) { - _seqScrollTextCounter++; + updateDemoAdText(24, 144); + _callbackCurrentFrame++; + if (_callbackCurrentFrame < 0x256 || _callbackCurrentFrame > 0x31C) { + if (_callbackCurrentFrame < 0x174 || _callbackCurrentFrame > 0x1D7) { + if (_callbackCurrentFrame < 0x84 || _callbackCurrentFrame > 0xE7) { + _scrollProgressCounter++; } } } - if (_seqFrameCounter > 0x31e) { - seq_resetActiveWSA(0); - seq_resetActiveWSA(1); - _seqEndTime = 0; + if (_callbackCurrentFrame > 0x31E) { + closeNestedAnimation(0); + closeNestedAnimation(1); + setCountDown(0); _screen->copyPage(2, 12); } } else { - seq_scrollPage(24, 144); + updateDemoAdText(24, 144); } return 0; } -int KyraEngine_HoF::seq_demoWharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_wharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 69) - _seqWsaCurrentFrame = 8; + _animCurrentFrame = 8; return frm; } -int KyraEngine_HoF::seq_demoDinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_dinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { switch (frm) { case 19: - seq_playTalkText(13); + playSoundAndDisplaySubTitle(13); break; case 54: - seq_playTalkText(15); + playSoundAndDisplaySubTitle(15); break; case 61: - seq_playTalkText(16); + playSoundAndDisplaySubTitle(16); break; case 69: - seq_playTalkText(14); + playSoundAndDisplaySubTitle(14); break; case 77: - seq_playTalkText(13); + playSoundAndDisplaySubTitle(13); break; case 79: - _seqWsaCurrentFrame = 4; + _animCurrentFrame = 4; break; } return frm; } -int KyraEngine_HoF::seq_demoWater(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_water(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 1) - seq_playTalkText(11); + playSoundAndDisplaySubTitle(11); return frm; } -int KyraEngine_HoF::seq_demoBail(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_bail(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } -int KyraEngine_HoF::seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOFDEMO_dig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { return frm; } #ifdef ENABLE_LOL -int KyraEngine_HoF::seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbLOLDEMO_scene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { Palette &tmpPal = _screen->getPalette(2); - if (!(_seqFrameCounter % 100)) { - if (_seqFrameCounter == 0) { - _sound->haltTrack(); - _sound->playTrack(6); + if (!(_callbackCurrentFrame % 100)) { + if (_callbackCurrentFrame == 0) { + _vm->sound()->haltTrack(); + _vm->sound()->playTrack(6); } tmpPal.copy(_screen->getPalette(0)); - for (int i = 3; i < 0x300; i++) { + for (int i = 3; i < 768; i++) { tmpPal[i] = ((int)tmpPal[i] * 120) / 64; - if (tmpPal[i] > 0x3f) - tmpPal[i] = 0x3f; + if (tmpPal[i] > 0x3F) + tmpPal[i] = 0x3F; } - seq_playTalkText(_rnd.getRandomBit()); + playSoundAndDisplaySubTitle(_vm->_rnd.getRandomBit()); _screen->setScreenPalette(tmpPal); _screen->updateScreen(); - delay(8); + _vm->delay(8); } else { _screen->setScreenPalette(_screen->getPalette(0)); _screen->updateScreen(); - if (_seqFrameCounter == 40) - seq_playTalkText(3); + if (_callbackCurrentFrame == 40) + playSoundAndDisplaySubTitle(3); } - _seqFrameCounter++; + _callbackCurrentFrame++; return frm; } -int KyraEngine_HoF::seq_lolDemoScene2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter - 17) { +int SeqPlayer_HOF::cbLOLDEMO_scene2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (frm - 17) { case 0: - _seqFrameDelay = 8; + _animDuration = 8; break; case 3: case 6: case 9: - seq_playTalkText(8); + playSoundEffect(8, 255 - ((26 - frm) << 3)); break; case 15: - seq_playTalkText(9); + playSoundAndDisplaySubTitle(9); break; case 18: - seq_playTalkText(2); + playSoundAndDisplaySubTitle(2); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return frm; } -int KyraEngine_HoF::seq_lolDemoScene3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (_seqFrameCounter == 1) - seq_playTalkText(6); - else if (frm == 26) - seq_playTalkText(7); +int SeqPlayer_HOF::cbLOLDEMO_scene3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 1) + playSoundAndDisplaySubTitle(6); + else if (frm == 24) + playSoundAndDisplaySubTitle(7); - _seqFrameCounter++; + _callbackCurrentFrame++; return frm; } -int KyraEngine_HoF::seq_lolDemoScene4(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter) { +int SeqPlayer_HOF::cbLOLDEMO_scene4(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (frm) { case 11: case 14: case 17: case 20: - seq_playTalkText(8); + playSoundEffect(8, 255 - ((22 - frm) << 3)); break; case 22: - seq_playTalkText(11); + playSoundAndDisplaySubTitle(11); break; case 24: - seq_playTalkText(8); + playSoundAndDisplaySubTitle(8); break; case 30: - seq_playTalkText(15); + playSoundAndDisplaySubTitle(15); break; case 34: - seq_playTalkText(14); + playSoundAndDisplaySubTitle(14); break; case 38: - seq_playTalkText(13); + playSoundAndDisplaySubTitle(13); break; case 42: - seq_playTalkText(12); + playSoundAndDisplaySubTitle(12); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return frm; } -int KyraEngine_HoF::seq_lolDemoScene5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter++) { +int SeqPlayer_HOF::cbLOLDEMO_scene5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame++) { case 0: case 4: case 6: @@ -1889,13 +3254,13 @@ int KyraEngine_HoF::seq_lolDemoScene5(WSAMovie_v2 *wsaObj, int x, int y, int frm case 26: case 28: case 30: - seq_playTalkText(15); + playSoundEffect(15, 255 - ((31 - frm) << 3)); break; case 32: - seq_playTalkText(16); + playSoundAndDisplaySubTitle(16); break; case 42: - seq_playTalkText(6); + playSoundAndDisplaySubTitle(6); break; default: break; @@ -1903,24 +3268,24 @@ int KyraEngine_HoF::seq_lolDemoScene5(WSAMovie_v2 *wsaObj, int x, int y, int frm return frm; } -int KyraEngine_HoF::seq_lolDemoText5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (_seqFrameCounter++ == 100) - seq_playTalkText(5); +int SeqPlayer_HOF::cbLOLDEMO_text5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (_callbackCurrentFrame++ == 100) + playSoundAndDisplaySubTitle(5); return frm; } -int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - while (_seqScrollTextCounter < 0x122) { - _seqEndTime = _system->getMillis() + 6 * _tickLength; - if (!_seqFrameCounter) { +int SeqPlayer_HOF::cbLOLDEMO_scene6(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + while (_scrollProgressCounter < 290) { + setCountDown(6); + if (!_callbackCurrentFrame) { _screen->loadBitmap("adtext.cps", 4, 4, 0); _screen->loadBitmap("adtext2.cps", 6, 6, 0); _screen->copyPageMemory(6, 0, 4, 64000, 1024); _screen->copyPageMemory(6, 1023, 6, 0, 64000); - _seqScrollTextCounter = 0; + _scrollProgressCounter = 0; } - if (_seqFrameCounter % 175) { + if (_callbackCurrentFrame % 175) { _screen->setScreenPalette(_screen->getPalette(0)); } else { Palette &tmpPal = _screen->getPalette(2); @@ -1928,27 +3293,29 @@ int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm for (int i = 3; i < 0x300; i++) { tmpPal[i] = ((int)tmpPal[i] * 120) / 64; - if (tmpPal[i] > 0x3f) - tmpPal[i] = 0x3f; + if (tmpPal[i] > 0x3F) + tmpPal[i] = 0x3F; } - seq_playTalkText(_rnd.getRandomBit()); + playSoundAndDisplaySubTitle(_vm->_rnd.getRandomBit()); _screen->setScreenPalette(tmpPal); _screen->updateScreen(); - delay(8); + _vm->delay(8); } - if (_seqFrameCounter == 40 || _seqFrameCounter == 80 || _seqFrameCounter == 150 || _seqFrameCounter == 300) - seq_playTalkText(3); + if (_callbackCurrentFrame == 40 || _callbackCurrentFrame == 80 || _callbackCurrentFrame == 150 || _callbackCurrentFrame == 300) + playSoundAndDisplaySubTitle(3); _screen->copyPage(12, 2); - seq_scrollPage(70, 130); + updateDemoAdText(70, 130); _screen->copyPage(2, 0); _screen->updateScreen(); - _seqFrameCounter++; - if (_seqFrameCounter < 128 || _seqFrameCounter > 207) - _seqScrollTextCounter++; - delayUntil(_seqEndTime); + _callbackCurrentFrame++; + if (_callbackCurrentFrame < 128 || _callbackCurrentFrame > 207) + _scrollProgressCounter++; + + while (countDownRunning()) + delayTicks(1); } _screen->copyPage(2, 12); @@ -1956,776 +3323,16 @@ int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm } #endif // ENABLE_LOL -uint32 KyraEngine_HoF::seq_activeTextsTimeLeft() { - uint32 res = 0; - - for (int i = 0; i < 10; i++) { - uint32 chatend = (_activeText[i].duration + _activeText[i].startTime); - uint32 curtime = _system->getMillis(); - if (_activeText[i].duration != -1 && chatend > curtime) { - chatend -= curtime; - if (res < chatend) - res = chatend; - } - } - - return res; -} - -void KyraEngine_HoF::seq_processWSAs() { - for (int i = 0; i < 8; i++) { - if (_activeWSA[i].flags != -1) { - if (seq_processNextSubFrame(i)) - seq_resetActiveWSA(i); - } - } -} - -void KyraEngine_HoF::seq_processText() { - int curPage = _screen->setCurPage(2); - char outputStr[70]; - - for (int i = 0; i < 10; i++) { - if (_activeText[i].startTime + _activeText[i].duration > _system->getMillis() && _activeText[i].duration != -1) { - - char *srcStr = seq_preprocessString(_sequenceStrings[_activeText[i].strIndex], _activeText[i].width); - int yPos = _activeText[i].y; - - while (*srcStr) { - uint32 linePos = 0; - for (; *srcStr; linePos++) { - if (*srcStr == 0x0d) // Carriage return - break; - outputStr[linePos] = *srcStr; - srcStr++; - } - outputStr[linePos] = 0; - if (*srcStr == 0x0d) - srcStr++; - - uint8 textColor = (_activeText[i].textcolor >= 0) ? _activeText[i].textcolor : _seqTextColor[0]; - _screen->printText(outputStr, _activeText[i].x - (_screen->getTextWidth(outputStr) / 2), yPos, textColor, 0); - yPos += 10; - } - } else { - _activeText[i].duration = -1; - } - } - - _screen->setCurPage(curPage); -} - -char *KyraEngine_HoF::seq_preprocessString(const char *srcStr, int width) { - char *dstStr = _seqProcessedString; - int lineStart = 0; - int linePos = 0; - - while (*srcStr) { - while (*srcStr && *srcStr != 0x20) // Space - dstStr[lineStart + linePos++] = *srcStr++; - dstStr[lineStart + linePos] = 0; - - int len = _screen->getTextWidth(&dstStr[lineStart]); - if (width >= len && *srcStr) { - dstStr[lineStart + linePos++] = *srcStr++; - } else { - dstStr[lineStart + linePos] = 0x0d; // Carriage return - lineStart += linePos + 1; - linePos = 0; - if (*srcStr) - srcStr++; - } - } - dstStr[lineStart + linePos] = 0; - - return strlen(_seqProcessedString) ? dstStr : 0; -} - -void KyraEngine_HoF::seq_sequenceCommand(int command) { - for (int i = 0; i < 8; i++) - seq_resetActiveWSA(i); - - switch (command) { - case 0: - _screen->fadeToBlack(36); - _screen->getPalette(0).clear(); - _screen->getPalette(1).clear(); - break; - - case 1: - seq_playTalkText(_rnd.getRandomBit()); - - _screen->getPalette(0).fill(0, 256, 0x3F); - _screen->fadePalette(_screen->getPalette(0), 16); - - _screen->copyPalette(1, 0); - break; - - case 3: - _screen->copyPage(2, 0); - _screen->fadePalette(_screen->getPalette(0), 16); - _screen->copyPalette(1, 0); - break; - - case 4: - _screen->copyPage(2, 0); - _screen->fadePalette(_screen->getPalette(0), 36); - _screen->copyPalette(1, 0); - break; - - case 5: - _screen->copyPage(2, 0); - break; - - case 6: - // UNUSED - // seq_loadBLD("library.bld"); - break; - - case 7: - // UNUSED - // seq_loadBLD("marco.bld"); - break; - - case 8: - _screen->fadeToBlack(16); - _screen->getPalette(0).clear(); - _screen->getPalette(1).clear(); - - delay(120 * _tickLength); - break; - - case 9: { - Palette &pal = _screen->getPalette(0); - for (int i = 0; i < 256; i++) { - int pv = (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3; - pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff; - } - - //int a = 0x100; - //int d = (0x800 << 5) - 0x100; - //pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f; - - _screen->fadePalette(pal, 64); - _screen->copyPalette(1, 0); - } break; - - default: - break; - } -} - -void KyraEngine_HoF::seq_cmpFadeFrame(const char *cmpFile) { - _screen->copyPage(10, 2); - _screen->copyPage(4, 10); - _screen->clearPage(6); - _screen->loadBitmap(cmpFile, 6, 6, 0); - _screen->copyPage(12, 4); - - for (int i = 0; i < 3; i++) { - uint32 endtime = _system->getMillis() + 4 * _tickLength; - _screen->cmpFadeFrameStep(4, 320, 200, 0, 0, 2, 320, 200, 0, 0, 320, 200, 6); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); - delayUntil(endtime); - } - - _screen->copyPage(4, 0); - _screen->updateScreen(); - _screen->copyPage(4, 2); - _screen->copyPage(4, 6); - _screen->copyPage(10, 4); -} - -void KyraEngine_HoF::seq_playTalkText(uint8 chatNum) { - assert(chatNum < _sequenceSoundListSize); - - if (chatNum < 12 && !_flags.isDemo && textEnabled()) - seq_setTextEntry(chatNum, 160, 168, _sequenceStringsDuration[chatNum], 160); - - _sound->voicePlay(_sequenceSoundList[chatNum], &_speechHandle); -} - -void KyraEngine_HoF::seq_waitForTextsTimeout() { - uint32 longest = seq_activeTextsTimeLeft() + _system->getMillis(); - uint32 now = _system->getMillis(); - - if (textEnabled()) { - if (longest > now) - delay(longest - now); - } else if (speechEnabled()) { - while (snd_voiceIsPlaying()) - delay(_tickLength); - } - - seq_resetAllTextEntries(); -} - -void KyraEngine_HoF::seq_resetAllTextEntries() { - for (int i = 0; i < 10; i++) - _activeText[i].duration = -1; -} - -int KyraEngine_HoF::seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width) { - for (int i = 0; i < 10; i++) { - if (_activeText[i].duration != -1) { - if (i < 9) - continue; - else - return -1; - } - - _activeText[i].strIndex = strIndex; - _activeText[i].x = posX; - _activeText[i].y = posY; - _activeText[i].duration = duration * _tickLength; - _activeText[i].width = width; - _activeText[i].startTime = _system->getMillis(); - _activeText[i].textcolor = -1; - - return i; - } - return -1; -} - -void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { - if (_activeWSA[wsaNum].flags != -1) - return; - - NestedSequence s = _sequences->seqn[seqNum]; - - if (!_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie = new WSAMovie_v2(this); - assert(_activeWSA[wsaNum].movie); - } - - _activeWSA[wsaNum].movie->close(); - - _activeWSA[wsaNum].movie->open(s.wsaFile, 0, 0); - - if (!_activeWSA[wsaNum].movie->opened()) { - delete _activeWSA[wsaNum].movie; - _activeWSA[wsaNum].movie = 0; - return; - } - - _activeWSA[wsaNum].endFrame = s.endFrame; - _activeWSA[wsaNum].startFrame = _activeWSA[wsaNum].currentFrame = s.startframe; - _activeWSA[wsaNum].frameDelay = s.frameDelay; - _activeWSA[wsaNum].callback = _callbackN[seqNum]; - _activeWSA[wsaNum].control = s.wsaControl; - - _activeWSA[wsaNum].flags = s.flags | 1; - _activeWSA[wsaNum].x = s.x; - _activeWSA[wsaNum].y = s.y; - _activeWSA[wsaNum].startupCommand = s.startupCommand; - _activeWSA[wsaNum].finalCommand = s.finalCommand; - _activeWSA[wsaNum].lastFrame = 0xffff; - - seq_nestedSequenceFrame(s.startupCommand, wsaNum); - - if (!s.startupCommand) - seq_processNextSubFrame(wsaNum); - - _activeWSA[wsaNum].nextFrame = _system->getMillis(); -} - -void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { - int xa = 0, ya = 0; - command--; - if (!_activeWSA[wsaNum].movie || skipFlag() || shouldQuit() || _abortIntroFlag) - return; - - switch (command) { - case 0: - xa = -_activeWSA[wsaNum].movie->xAdd(); - ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); - seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), - _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2); - break; - - case 1: - xa = -_activeWSA[wsaNum].movie->xAdd(); - ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); - seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), - _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1); - break; - - case 2: - seq_waitForTextsTimeout(); - xa = -_activeWSA[wsaNum].movie->xAdd(); - ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0, 0, 0); - seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), - _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2); - break; - - case 3: - _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); - _screen->copyPage(2, 12); - seq_cmpFadeFrame("scene2.cmp"); - break; - - case 4: - _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); - _screen->copyPage(2, 12); - seq_cmpFadeFrame("scene3.cmp"); - break; - - default: - break; - } -} - -void KyraEngine_HoF::seq_animatedSubFrame(int srcPage, int dstPage, int delaytime, int steps, - int x, int y, int w, int h, int openClose, int directionFlags) { - if (openClose) { - for (int i = 1; i < steps; i++) { - uint32 endtime = _system->getMillis() + delaytime * _tickLength; - - int w2 = (((w * 256) / steps) * i) / 256; - int h2 = (((h * 256) / steps) * i) / 256; - - int ym = (directionFlags & 2) ? (h - h2) : 0; - int xm = (directionFlags & 1) ? (w - w2) : 0; - - _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); - - _screen->copyPage(dstPage, 6); - _screen->copyPage(dstPage, 0); - _screen->updateScreen(); - - _screen->copyPage(12, dstPage); - delayUntil(endtime); - } - - _screen->wsaFrameAnimationStep(0, 0, x, y, w, h, w, h, srcPage, dstPage, 0); - _screen->copyPage(dstPage, 6); - _screen->copyPage(dstPage, 0); - _screen->updateScreen(); - } else { - _screen->copyPage(12, dstPage); - for (int i = steps; i; i--) { - uint32 endtime = _system->getMillis() + delaytime * _tickLength; - - int w2 = (((w * 256) / steps) * i) / 256; - int h2 = (((h * 256) / steps) * i) / 256; +#undef CASE_ALT - int ym = (directionFlags & 2) ? (h - h2) : 0; - int xm = (directionFlags & 1) ? (w - w2) : 0; - - _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); - - _screen->copyPage(dstPage, 6); - _screen->copyPage(dstPage, 0); - _screen->updateScreen(); - - _screen->copyPage(12, dstPage); - delayUntil(endtime); - } - } -} - -void KyraEngine_HoF::seq_resetActiveWSA(int wsaNum) { - if (_activeWSA[wsaNum].flags == -1) - return; - - _activeWSA[wsaNum].flags = -1; - seq_nestedSequenceFrame(_activeWSA[wsaNum].finalCommand, wsaNum); - _activeWSA[wsaNum].movie->close(); -} - -void KyraEngine_HoF::seq_unloadWSA(int wsaNum) { - if (_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie->close(); - delete _activeWSA[wsaNum].movie; - _activeWSA[wsaNum].movie = 0; - } -} - -bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { - uint32 currentFrame = _activeWSA[wsaNum].currentFrame; - uint32 currentTime = _system->getMillis(); - - if (_activeWSA[wsaNum].callback && currentFrame != _activeWSA[wsaNum].lastFrame) { - _activeWSA[wsaNum].lastFrame = currentFrame; - currentFrame = (this->*_activeWSA[wsaNum].callback)(_activeWSA[wsaNum].movie, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, currentFrame); - } - - if (_activeWSA[wsaNum].movie) { - if (_activeWSA[wsaNum].flags & 0x20) { - _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); - _activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay; - } else { - _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); - } - } - - if (_activeWSA[wsaNum].flags & 0x10) { - currentFrame = (currentTime - _activeWSA[wsaNum].nextFrame) / (_activeWSA[wsaNum].frameDelay * _tickLength); - } else { - if (((int32)(currentTime - _activeWSA[wsaNum].nextFrame) / (int32)(_activeWSA[wsaNum].frameDelay * _tickLength)) > 0) { - currentFrame++; - _activeWSA[wsaNum].nextFrame = currentTime; - } - } - - bool res = false; - - if (currentFrame >= _activeWSA[wsaNum].endFrame) { - int sw = ((_activeWSA[wsaNum].flags & 0x1e) - 2); - switch (sw) { - case 0: - res = true; - currentFrame = _activeWSA[wsaNum].endFrame; - _screen->copyPage(2, 12); - break; - - case 6: - case 8: - currentFrame = _activeWSA[wsaNum].endFrame - 1; - break; - - case 2: - case 10: - currentFrame = _activeWSA[wsaNum].startFrame; - break; - - default: - currentFrame = _activeWSA[wsaNum].endFrame - 1; - res = true; - } - } - - _activeWSA[wsaNum].currentFrame = currentFrame & 0xffff; - return res; -} - -void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) { - uint8 colormap[16]; - if (skipFlag() || shouldQuit() || _abortIntroFlag || _menuChoice) - return; - - Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); - - memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6); - _screen->getPalette(0)[0x2f6] = 0x3f; - _screen->getPalette(0)[0x2f5] = 0x20; - _screen->getPalette(0)[0x2f4] = 0x30; - colormap[0] = colorMap[0]; - colormap[1] = 0xfd; - memcpy(&colormap[2], &colorMap[2], 14); - uint8 seqTextColor0 = _seqTextColor[0]; - - _seqTextColor[0] = 0xfd; - _screen->setTextColorMap(colormap); - seq_resetAllTextEntries(); - seq_setTextEntry(strIndex, x, y, 0x80, 0x78); - seq_processText(); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->getPalette(0)[0x2f7] = _screen->getPalette(0)[textcolor * 3]; - _screen->getPalette(0)[0x2f8] = _screen->getPalette(0)[textcolor * 3 + 1]; - _screen->getPalette(0)[0x2f9] = _screen->getPalette(0)[textcolor * 3 + 2]; - _screen->fadePalette(_screen->getPalette(0), 0x18); - - _seqTextColor[0] = textcolor; - _screen->setTextColorMap(colorMap); - seq_resetAllTextEntries(); - seq_setTextEntry(strIndex, x, y, 0x80, 0x78); - seq_processText(); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->getPalette(0)[0x2f7] = _screen->getPalette(0)[0x2f8] = _screen->getPalette(0)[0x2f9] = 0; - _screen->fadePalette(_screen->getPalette(0), 1); - _screen->copyPage(2, 12); - seq_resetAllTextEntries(); - - _seqTextColor[0] = seqTextColor0; - - _screen->setFont(of); -} - -void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovie_v2 *wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos) { - int dur = int(strlen(_sequenceStrings[strIndex])) * (_flags.isTalkie ? 7 : 15); - if (textEnabled()) { - int entry = seq_setTextEntry(strIndex, x, y, dur, width); - _activeText[entry].textcolor = textColor; - } - _seqWsaChatTimeout = _system->getMillis() + dur * _tickLength; - int curframe = firstframe; - - if (vocIndex && speechEnabled()) { - while (_sound->voiceIsPlaying() && !skipFlag()) - delay(4); - seq_playTalkText(vocIndex); - } - - while (_system->getMillis() < _seqWsaChatTimeout && !(_abortIntroFlag || skipFlag())) { - if (lastframe < 0) { - int t = ABS(lastframe); - if (t < curframe) - curframe = t; - } - - if (ABS(lastframe) < curframe) - curframe = firstframe; - - _seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - if (wsa) - wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0, 0, 0); - - _screen->copyPage(2, 12); - - seq_processText(); - - uint32 tm = _system->getMillis(); - if (_seqWsaChatFrameTimeout > tm && _seqWsaChatTimeout > tm) - delay(MIN(_seqWsaChatFrameTimeout - tm, _seqWsaChatTimeout - tm)); - - if (speechEnabled() && !textEnabled() && !snd_voiceIsPlaying()) - break; - - _screen->copyPage(2, 0); - _screen->updateScreen(); - curframe++; - } - - if (_abortIntroFlag || skipFlag()) - _sound->voiceStop(); - - if (ABS(lastframe) < curframe) - curframe = ABS(lastframe); - - if (curframe == firstframe) - curframe++; - - _seqWsaCurrentFrame = curframe; -} - -void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, - int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData, const char *const *specialData) { - if (!data) - return; - - static const char mark[] = { 5, 13, 0 }; - - _screen->clearPage(tempPage1); - _screen->clearPage(tempPage2); - _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, 0, tempPage1); - - struct ScrollTextData { - int16 x; - int16 y; - uint8 *text; - byte unk1; - byte height; - byte adjust; - - ScrollTextData() { - x = 0; // 0 11 - y = 0; // 2 13 - text = 0; // 4 15 - unk1 = 0; // 8 19 - height = 0; // 9 20 - adjust = 0; // 10 21 - } - }; - - ScrollTextData *textData = new ScrollTextData[36]; - uint8 *ptr = data; - - bool loop = true; - int cnt = 0; - - while (loop) { - _seqSubFrameEndTimeInternal = _system->getMillis() + speed * _tickLength; - - while (cnt < 35 && *ptr) { - uint16 cH; - - if (cnt) - cH = textData[cnt].y + textData[cnt].height + (textData[cnt].height >> 3); - else - cH = d->h; - - char *str = (char *)ptr; - - ptr = (uint8 *)strpbrk(str, mark); - if (!ptr) - ptr = (uint8 *)strchr(str, 0); - - textData[cnt + 1].unk1 = *ptr; - *ptr = 0; - if (textData[cnt + 1].unk1) - ptr++; - - if (*str == 3 || *str == 4) - textData[cnt + 1].adjust = *str++; - else - textData[cnt + 1].adjust = 0; - - _screen->setFont(fid1); - - if (*str == 1) { - _screen->setFont(fid2); - str++; - } else if (*str == 2) { - str++; - } - - textData[cnt + 1].height = _screen->getFontHeight(); - - switch (textData[cnt + 1].adjust) { - case 3: - textData[cnt + 1].x = 157 - _screen->getTextWidth(str); - break; - case 4: - textData[cnt + 1].x = 161; - break; - default: - textData[cnt + 1].x = (((d->w << 3) - _screen->getTextWidth(str)) >> 1) + 1; - } - - if (textData[cnt].unk1 == 5) - cH -= (textData[cnt].height + (textData[cnt].height >> 3)); - - textData[cnt + 1].y = cH; - textData[cnt + 1].text = (uint8 *)str; - cnt++; - } - - _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage1, tempPage2); - - int cnt2 = 0; - bool palCycle = 0; - - while (cnt2 < cnt) { - const char *str = (const char *)textData[cnt2 + 1].text; - const char *str2 = str; - int16 cW = textData[cnt2 + 1].x - 10; - int16 cH = textData[cnt2 + 1].y; - int x = (d->sx << 3) + cW; - int y = d->sy + cH; - int col1 = 255; - - if (cH < d->h) { - _screen->setCurPage(tempPage2); - _screen->setFont(fid1); - if (textData[cnt2 + 1].height != _screen->getFontHeight()) - _screen->setFont(fid2); - - if (specialData) { - if (!strcmp(str, specialData[0])) { - col1 = 112; - char cChar[2] = " "; - while (*str2) { - cChar[0] = *str2; - _screen->printText(cChar, x, y, col1++, 0); - x += _screen->getCharWidth((uint8)*str2++); - } - palCycle = true; - } else if (!strcmp(str, specialData[1])) { - col1 = 133; - char cChar[2] = " "; - while (*str2) { - cChar[0] = *str2; - _screen->printText(cChar, x, y, col1--, 0); - x += _screen->getCharWidth((uint8)*str2++); - } - palCycle = true; - } else { - _screen->printText(str, x, y, col1, 0); - } - } else { - _screen->printText(str, x, y, col1, 0); - } - _screen->setCurPage(0); - } - - textData[cnt2 + 1].y -= step; - cnt2++; - } - - _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage2, 0); - _screen->updateScreen(); - - if (textData[1].y < -10) { - textData[1].text += strlen((char *)textData[1].text); - textData[1].text[0] = textData[1].unk1; - cnt--; - memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); - } - - if (palCycle) { - for (int col = 133; col > 112; col--) - _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col); - _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112); - _screen->setScreenPalette(_screen->getPalette(0)); - } - - delayUntil(_seqSubFrameEndTimeInternal); - - if ((cnt < 36) && ((d->sy + d->h) > (textData[cnt].y + textData[cnt].height)) && !skipFlag()) { - resetSkipFlag(); - delay(_tickLength * 500); - cnt = 0; - } - - if (!cnt || skipFlag()) - loop = false; - } - - _sound->beginFadeOut(); - _screen->fadeToBlack(); - - _abortIntroFlag= false; - resetSkipFlag(); - - delete[] textData; -} - -void KyraEngine_HoF::seq_scrollPage(int bottom, int top) { - int dstY, dstH, srcH; - - static const ScreenDim d = { 0x00, 0x00, 0x28, 0x320, 0xFF, 0xFE, 0x00, 0x00 }; - - if (_seqScrollTextCounter - (top - 1) < 0) { - dstY = top - _seqScrollTextCounter; - dstH = _seqScrollTextCounter; - srcH = 0; - } else { - dstY = 0; - srcH = _seqScrollTextCounter - top; - dstH = (400 - srcH <= top) ? 400 - srcH : top; - } - - if (dstH > 0) { - if (_demoAnimData) { - for (int i = 0; i < 4; i++) { - const ItemAnimData_v1 *def = &_demoAnimData[i]; - ActiveItemAnim *a = &_activeItemAnim[i]; - - _screen->fillRect(12, def->y - 8, 28, def->y + 8, 0, 4); - _screen->drawShape(4, getShapePtr(def->itemIndex + def->frames[a->currentFrame]), 12, def->y - 8, 0, 0); - if (_seqFrameCounter % 2 == 0) - a->currentFrame = (a->currentFrame + 1) % 20; - } - } - _screen->copyRegionEx(4, 0, srcH, 2, 2, dstY + bottom, 320, dstH, &d); - } -} +const uint8 SeqPlayer_HOF::_textColorPresets[] = { 0x01, 0x01, 0x00, 0x3F, 0x3F, 0x3F }; void KyraEngine_HoF::seq_showStarcraftLogo() { WSAMovie_v2 *ci = new WSAMovie_v2(this); assert(ci); _screen->clearPage(2); _res->loadPakFile("INTROGEN.PAK"); - int endframe = ci->open("ci.wsa", 0, &_screen->getPalette(0)); + int endframe = ci->open("CI.WSA", 0, &_screen->getPalette(0)); _res->unloadPakFile("INTROGEN.PAK"); if (!ci->opened()) { delete ci; @@ -2736,20 +3343,28 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { _screen->copyPage(2, 0); _screen->fadeFromBlack(); for (int i = 1; i < endframe; i++) { - _seqEndTime = _system->getMillis() + 50; + uint32 end = _system->getMillis() + 50; if (skipFlag()) break; ci->displayFrame(i, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); - delay(_seqEndTime - _system->getMillis()); + uint32 cur = _system->getMillis(); + if (end > cur) + delay(end - cur); + else + updateInput(); } if (!skipFlag()) { - _seqEndTime = _system->getMillis() + 50; + uint32 end = _system->getMillis() + 50; ci->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); - delay(_seqEndTime - _system->getMillis()); + uint32 cur = _system->getMillis(); + if (end > cur) + delay(end - cur); + else + updateInput(); } _screen->fadeToBlack(); _screen->showMouse(); @@ -2758,67 +3373,38 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { delete ci; } -void KyraEngine_HoF::seq_init() { - _seqProcessedString = new char[200]; - _seqWsa = new WSAMovie_v2(this); - _activeWSA = new ActiveWSA[8]; - _activeText = new ActiveText[10]; - - _res->unloadAllPakFiles(); - _res->loadPakFile(StaticResource::staticDataFilename()); - _res->loadFileList(_sequencePakList, _sequencePakListSize); - - if (_flags.platform == Common::kPlatformPC98) - _sound->loadSoundFile("SOUND.DAT"); - - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); - - if (_flags.gameID == GI_LOL) - return; - - if (_flags.isDemo && !_flags.isTalkie) { - _demoAnimData = _staticres->loadShapeAnimData_v1(k2SeqplayShapeAnimData, _itemAnimDefinitionSize); - uint8 *shp = _res->fileData("icons.shp", 0); - uint32 outsize = READ_LE_UINT16(shp + 4); - _animShapeFiledata = new uint8[outsize]; - Screen::decodeFrame4(shp + 10, _animShapeFiledata, outsize); - delete[] shp; - - for (int i = 0; i < 20; i++) - addShapeToPool(_screen->getPtrToShape(_animShapeFiledata, i), i); - } else { - const MainMenu::StaticData data = { - { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98], 0 }, - { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xd7, 0xd6 }, - { 0xd8, 0xda, 0xd9, 0xd8 }, - (_flags.lang == Common::JA_JPN) ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT, 240 - }; - - _menu = new MainMenu(this); - _menu->init(data, MainMenu::Animation()); - } +int KyraEngine_HoF::seq_playIntro() { + bool startupSaveLoadable = saveFileLoadable(0); + return SeqPlayer_HOF(this, _screen, _system, startupSaveLoadable).play(kSequenceVirgin, startupSaveLoadable? kSequenceTitle : kSequenceNoLooping); } -void KyraEngine_HoF::seq_uninit() { - delete[] _seqProcessedString; - _seqProcessedString = NULL; - - delete[] _activeWSA; - _activeWSA = NULL; +int KyraEngine_HoF::seq_playOutro() { + return SeqPlayer_HOF(this, _screen, _system).play(kSequenceFunters, kSequenceFrash); +} - delete[] _activeText; - _activeText = NULL; +int KyraEngine_HoF::seq_playDemo() { + SeqPlayer_HOF(this, _screen, _system).play(kSequenceHoFDemoVirgin, kSequenceHoFDemoVirgin); + return 4; +} - delete _seqWsa; - _seqWsa = NULL; +void KyraEngine_HoF::seq_pausePlayer(bool toggle) { + SeqPlayer_HOF *activePlayer = SeqPlayer_HOF::instance(); + if (activePlayer) + activePlayer->pause(toggle); +} - delete[] _animShapeFiledata; - _animShapeFiledata = 0; +#ifdef ENABLE_LOL +int LoLEngine::playDemo() { + SeqPlayer_HOF(this, _screen, _system).play(kSequenceLoLDemoScene1, kSequenceLoLDemoScene1); + return -1; +} - delete _menu; - _menu = 0; - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); +void LoLEngine::pauseDemoPlayer(bool toggle) { + SeqPlayer_HOF *activePlayer = SeqPlayer_HOF::instance(); + if (activePlayer) + activePlayer->pause(toggle); } +#endif // ENABLE_LOL #pragma mark - #pragma mark - Ingame sequences diff --git a/engines/kyra/sequences_hof.h b/engines/kyra/sequences_hof.h new file mode 100644 index 0000000000..2558a68a6a --- /dev/null +++ b/engines/kyra/sequences_hof.h @@ -0,0 +1,74 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef KYRA_SEQUENCES_HOF_H +#define KYRA_SEQUENCES_HOF_H + +#include "kyra/kyra_v2.h" + +namespace Kyra { + +struct HoFSequence { + const char *wsaFile; + const char *cpsFile; + uint16 flags; + uint8 fadeInTransitionType; + uint8 fadeOutTransitionType; + int16 stringIndex1; + int16 stringIndex2; + uint16 startFrame; + uint16 numFrames; + uint16 duration; + uint16 xPos; + uint16 yPos; + uint16 timeout; +}; + +struct HoFNestedSequence { + const char *wsaFile; + const FrameControl *wsaControl; + uint16 flags; + uint16 startframe; + uint16 endFrame; + uint16 frameDelay; + uint16 x; + uint16 y; + uint16 fadeInTransitionType; + uint16 fadeOutTransitionType; +}; + +struct HoFSeqData { + const HoFSequence *seq; + int numSeq; + const HoFNestedSequence *nestedSeq; + int numNestedSeq; +}; + +struct HoFSeqItemAnimData { + int16 itemIndex; + uint16 y; + const uint16 *frames; +}; + +} // End of namespace Kyra + +#endif diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index e63d0a7d8f..994bd2ba9b 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -1207,7 +1207,7 @@ struct CreditsLine { void KyraEngine_LoK::seq_playCredits() { static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static const char stringTerms[] = { 0x5, 0xd, 0x0}; + static const char stringTerms[] = { 0x5, 0xD, 0x0}; typedef Common::List<CreditsLine> CreditsLineList; CreditsLineList lines; diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index a06f2077ba..c8f97eb770 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -36,10 +36,16 @@ namespace Kyra { #pragma mark - Intro int LoLEngine::processPrologue() { - setupPrologueData(true); - - if (!saveFileLoadable(0) || _flags.isDemo) - showIntro(); + // There are two non-interactive demos (one which plays the intro and another one) which plays a number of specific scenes. + // We try to identify the latter one by looking for a specific file. + _res->loadPakFile("GENERAL.PAK"); + if (_flags.isDemo && _res->exists("scene1.cps")) { + return playDemo(); + } else { + setupPrologueData(true); + if (!saveFileLoadable(0) || _flags.isDemo) + showIntro(); + } if (_flags.isDemo) { _screen->fadePalette(_screen->getPalette(1), 30, 0); @@ -66,7 +72,7 @@ int LoLEngine::processPrologue() { // Original version: (260|193) "V CD1.02 D" const int width = _screen->getTextWidth(versionString.c_str()); _screen->fprintString("%s", 320 - width, 193, 0x67, 0x00, 0x04, versionString.c_str()); - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); + _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); _screen->fadePalette(_screen->getPalette(0), 0x1E); _screen->updateScreen(); @@ -139,7 +145,12 @@ void LoLEngine::setupPrologueData(bool load) { static const char *const fileListFloppy[] = { "INTRO.PAK", "INTROVOC.PAK", 0 }; - const char *const *fileList = _flags.isTalkie ? fileListCD : fileListFloppy; + + static const char *const fileListTowns[] = { + "INTRO.PAK", "TINTROVO.PAK", 0 + }; + + const char *const *fileList = _flags.isTalkie ? fileListCD : (_flags.platform == Common::kPlatformFMTowns ? fileListTowns : fileListFloppy); char filename[32]; for (uint i = 0; fileList[i]; ++i) { @@ -176,7 +187,7 @@ void LoLEngine::setupPrologueData(bool load) { memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers)); _screen->getPalette(1).clear(); - _sound->setSoundList(&_soundData[kMusicIntro]); + _sound->selectAudioResourceSet(kMusicIntro); // We have three sound.dat files, one for the intro, one for the // end sequence and one for ingame, each contained in a different @@ -197,7 +208,7 @@ void LoLEngine::setupPrologueData(bool load) { return; _eventList.clear(); - _sound->setSoundList(0); + _sound->selectAudioResourceSet(kMusicIntro); } } @@ -219,7 +230,7 @@ void LoLEngine::showIntro() { _screen->loadFont(Screen::FID_8_FNT, "NEW8P.FNT"); _screen->loadFont(Screen::FID_INTRO_FNT, "INTRO.FNT"); - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); + _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); _tim->resetFinishedFlag(); _tim->setLangData("LOLINTRO.DIP"); @@ -289,10 +300,10 @@ int LoLEngine::chooseCharacter() { _chargenWSA->displayFrame(0, 2, 113, 0, 0, 0, 0); - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); + _screen->setFont((_flags.lang == Common::JA_JPN && _flags.use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); _screen->_curPage = 2; - if (_flags.platform == Common::kPlatformPC98) { + if (_flags.platform == Common::kPlatformPC98 && _flags.use16ColorMode) { _screen->fillRect(17, 29, 94, 97, 17); _screen->fillRect(68, 167, 310, 199, 17); _screen->drawClippedLine(68, 166, 311, 166, 238); @@ -304,7 +315,7 @@ int LoLEngine::chooseCharacter() { _screen->_curPage = 2; for (int i = 0; i < 4; ++i) { - _screen->printText((const char *)_charNamesPC98[i], _charPosXPC98[i], 168, 0xC1, 0x00); + _screen->printText(_charNamesJapanese[i], _charPosXPC98[i], 168, 0xC1, 0x00); Screen::FontId old = _screen->setFont(Screen::FID_SJIS_FNT); for (int j = 0; j < 3; ++j) { @@ -318,7 +329,7 @@ int LoLEngine::chooseCharacter() { _screen->printText(_tim->getCTableEntry(53), 72, 184, 0x81, 0x00); _screen->printText(_tim->getCTableEntry(55), 72, 192, 0x81, 0x00); } else { - const char *const *previewNames = (_flags.lang == Common::RU_RUS && !_flags.isTalkie) ? _charPreviewNamesRussianFloppy : _charPreviewNamesDefault; + const char *const *previewNames = (_flags.lang == Common::RU_RUS && !_flags.isTalkie) ? _charPreviewNamesRussianFloppy : (_flags.lang == Common::JA_JPN ? _charNamesJapanese : _charPreviewNamesDefault); for (int i = 0; i < 4; ++i) { _screen->fprintStringIntro("%s", _charPreviews[i].x + 16, _charPreviews[i].y + 36, 0xC0, 0x00, 0x9C, 0x120, previewNames[i]); _screen->fprintStringIntro("%d", _charPreviews[i].x + 21, _charPreviews[i].y + 48, 0x98, 0x00, 0x9C, 0x220, _charPreviews[i].attrib[0]); @@ -710,7 +721,7 @@ void LoLEngine::showStarcraftLogo() { _screen->fadeFromBlack(); int inputFlag = 0; for (int i = 0; i < endframe; i++) { - inputFlag = checkInput(0) & 0xff; + inputFlag = checkInput(0) & 0xFF; if (shouldQuit() || inputFlag) break; ci->displayFrame(i, 2, 32, 80, 0, 0, 0); @@ -722,7 +733,7 @@ void LoLEngine::showStarcraftLogo() { if (!(shouldQuit() || inputFlag)) { _sound->voicePlay("star2", &_speechHandle); while (_sound->voiceIsPlaying(&_speechHandle) && !(shouldQuit() || inputFlag)) { - inputFlag = checkInput(0) & 0xff; + inputFlag = checkInput(0) & 0xFF; delay(_tickLength); } } @@ -1009,7 +1020,11 @@ void LoLEngine::setupEpilogueData(bool load) { "GENERAL.PAK", "INTRO.PAK", "FINALE1.PAK", "FINALE2.PAK", 0 }; - const char *const *fileList = _flags.isTalkie ? fileListCD : fileListFloppy; + static const char *const fileListTowns[] = { + "GENERAL.PAK", "INTRO.PAK", "FINALE1.PAK", "TFINALE2.PAK", 0 + }; + + const char *const *fileList = _flags.isTalkie ? fileListCD : (_flags.platform == Common::kPlatformFMTowns ? fileListTowns : fileListFloppy); assert(fileList); char filename[32]; @@ -1035,7 +1050,7 @@ void LoLEngine::setupEpilogueData(bool load) { _screen->clearPage(3); if (load) { - _sound->setSoundList(&_soundData[kMusicFinale]); + _sound->selectAudioResourceSet(kMusicFinale); // We have three sound.dat files, one for the intro, one for the // end sequence and one for ingame, each contained in a different @@ -1051,7 +1066,7 @@ void LoLEngine::setupEpilogueData(bool load) { return; _eventList.clear(); - _sound->setSoundList(0); + _sound->selectAudioResourceSet(kMusicIntro); } } diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 73c20ee6df..32d175bdb0 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -37,7 +37,7 @@ namespace Kyra { Sound::Sound(KyraEngine_v1 *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer), _soundChannels(), _musicEnabled(1), - _sfxEnabled(true), _soundDataList(0) { + _sfxEnabled(true) { } Sound::~Sound() { @@ -47,14 +47,6 @@ Sound::kType Sound::getSfxType() const { return getMusicType(); } -void Sound::setSoundList(const AudioDataStruct *list) { - _soundDataList = list; -} - -bool Sound::hasSoundFile(uint file) const { - return (fileListEntry(file) != 0); -} - bool Sound::isPlaying() const { return false; } @@ -73,7 +65,7 @@ bool Sound::isVoicePresent(const char *file) const { return false; } -int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { +int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) { Audio::SeekableAudioStream *audioStream = getVoiceStream(file); if (!audioStream) { @@ -81,7 +73,7 @@ int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volum } int playTime = audioStream->getLength().msecs(); - playVoiceStream(audioStream, handle, volume, isSfx); + playVoiceStream(audioStream, handle, volume, priority, isSfx); return playTime; } @@ -109,12 +101,20 @@ Audio::SeekableAudioStream *Sound::getVoiceStream(const char *file) const { } } -bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { +bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) { int h = 0; - while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h])) + while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h].handle)) ++h; if (h >= kNumChannelHandles) { + h = 0; + while (h < kNumChannelHandles && _soundChannels[h].priority > priority) + ++h; + if (h < kNumChannelHandles) + voiceStop(&_soundChannels[h].handle); + } + + if (h >= kNumChannelHandles) { // When we run out of handles we need to destroy the stream object, // this is to avoid memory leaks in some scenes where too many sfx // are started. @@ -123,9 +123,10 @@ bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *hand return false; } - _mixer->playStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h], stream, -1, volume); + _mixer->playStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].handle, stream, -1, volume); + _soundChannels[h].priority = priority; if (handle) - *handle = _soundChannels[h]; + *handle = _soundChannels[h].handle; return true; } @@ -133,8 +134,8 @@ bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *hand void Sound::voiceStop(const Audio::SoundHandle *handle) { if (!handle) { for (int h = 0; h < kNumChannelHandles; ++h) { - if (_mixer->isSoundHandleActive(_soundChannels[h])) - _mixer->stopHandle(_soundChannels[h]); + if (_mixer->isSoundHandleActive(_soundChannels[h].handle)) + _mixer->stopHandle(_soundChannels[h].handle); } } else { _mixer->stopHandle(*handle); @@ -144,7 +145,7 @@ void Sound::voiceStop(const Audio::SoundHandle *handle) { bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const { if (!handle) { for (int h = 0; h < kNumChannelHandles; ++h) { - if (_mixer->isSoundHandleActive(_soundChannels[h])) + if (_mixer->isSoundHandleActive(_soundChannels[h].handle)) return true; } } else { @@ -156,7 +157,7 @@ bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const { bool Sound::allVoiceChannelsPlaying() const { for (int i = 0; i < kNumChannelHandles; ++i) - if (!_mixer->isSoundHandleActive(_soundChannels[i])) + if (!_mixer->isSoundHandleActive(_soundChannels[i].handle)) return false; return true; } @@ -194,9 +195,14 @@ void MixedSoundDriver::updateVolumeSettings() { _sfx->updateVolumeSettings(); } -void MixedSoundDriver::setSoundList(const AudioDataStruct *list) { - _music->setSoundList(list); - _sfx->setSoundList(list); +void MixedSoundDriver::initAudioResourceInfo(int set, void *info) { + _music->initAudioResourceInfo(set, info); + _sfx->initAudioResourceInfo(set, info); +} + +void MixedSoundDriver::selectAudioResourceSet(int set) { + _music->selectAudioResourceSet(set); + _sfx->selectAudioResourceSet(set); } bool MixedSoundDriver::hasSoundFile(uint file) const { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 63cec48d00..2f5a0b6121 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -37,6 +37,35 @@ class SeekableAudioStream; namespace Kyra { +// Helper structs to format the data passed to the various initAudioResourceInfo() implementations +struct SoundResourceInfo_PC { + SoundResourceInfo_PC(const char *const *files, int numFiles) : fileList(files), fileListSize(numFiles) {} + const char *const *fileList; + uint fileListSize; +}; + +struct SoundResourceInfo_Towns { + SoundResourceInfo_Towns(const char *const *files, int numFiles, const int32 *cdaTbl, int cdaTblSize) : fileList(files), fileListSize(numFiles), cdaTable(cdaTbl), cdaTableSize(cdaTblSize) {} + const char *const *fileList; + uint fileListSize; + const int32 *cdaTable; + uint cdaTableSize; +}; + +struct SoundResourceInfo_PC98 { + SoundResourceInfo_PC98(const char *fileNamePattern) : pattern(fileNamePattern) {} + const char *pattern; +}; + +struct SoundResourceInfo_TownsPC98V2 { + SoundResourceInfo_TownsPC98V2(const char *const *files, int numFiles, const char *fileNamePattern, const uint16 *cdaTbl, int cdaTblSize) : fileList(files), fileListSize(numFiles), pattern(fileNamePattern), cdaTable(cdaTbl), cdaTableSize(cdaTblSize) {} + const char *const *fileList; + uint fileListSize; + const char *pattern; + const uint16 *cdaTable; + uint cdaTableSize; +}; + /** * Analog audio output device API for Kyrandia games. * It contains functionality to play music tracks, @@ -78,12 +107,20 @@ public: virtual void updateVolumeSettings() {} /** - * Sets the soundfiles the output device will use - * when playing a track and/or sound effect. + * Assigns static resource data with information on how to load + * audio resources to * - * @param list soundfile list + * @param set value defined in AudioResourceSet enum + * info various types of resource info data (file list, file name pattern, struct, etc. - depending on the inheriting driver type) */ - virtual void setSoundList(const AudioDataStruct *list); + virtual void initAudioResourceInfo(int set, void *info) = 0; + + /** + * Select audio resource set. + * + * @param set value defined in AudioResourceSet enum + */ + virtual void selectAudioResourceSet(int set) = 0; /** * Checks if a given sound file is present. @@ -91,7 +128,7 @@ public: * @param track track number * @return true if available, false otherwise */ - virtual bool hasSoundFile(uint file) const; + virtual bool hasSoundFile(uint file) const = 0; /** * Load a specifc sound file for use of @@ -128,7 +165,7 @@ public: * * @param track sound effect id */ - virtual void playSoundEffect(uint8 track, uint8 volume = 0xff) = 0; + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) = 0; /** * Stop playback of all sfx tracks. @@ -184,11 +221,11 @@ public: * @param handle store a copy of the sound handle * @return playtime of the voice file (-1 marks unknown playtime) */ - virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); + virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, uint8 priority = 255, bool isSfx = false); Audio::SeekableAudioStream *getVoiceStream(const char *file) const; - bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); + bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, uint8 priority = 255, bool isSfx = false); /** * Checks if a voice is being played. @@ -228,17 +265,17 @@ public: */ virtual void resetTrigger() {} protected: - const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->fileListLen) ? _soundDataList->fileList[file] : ""; } - int fileListLen() const { return _soundDataList->fileListLen; } - const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->cdaTracks : 0; } - int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->cdaNumTracks : 0; } - int extraOffset() const { return _soundDataList != 0 ? _soundDataList->extraOffset : 0; } - enum { kNumChannelHandles = 4 }; - Audio::SoundHandle _soundChannels[kNumChannelHandles]; + struct SoundChannel { + SoundChannel() : handle(), priority(0) {} + Audio::SoundHandle handle; + int priority; + }; + + SoundChannel _soundChannels[kNumChannelHandles]; int _musicEnabled; bool _sfxEnabled; @@ -247,8 +284,6 @@ protected: Audio::Mixer *_mixer; private: - const AudioDataStruct *_soundDataList; - struct SpeechCodecs { const char *fileext; Audio::SeekableAudioStream *(*streamFunc)( @@ -272,7 +307,8 @@ public: virtual void updateVolumeSettings(); - virtual void setSoundList(const AudioDataStruct *list); + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); virtual bool hasSoundFile(uint file) const; virtual void loadSoundFile(uint file); virtual void loadSoundFile(Common::String file); @@ -283,7 +319,7 @@ public: virtual void haltTrack(); virtual bool isPlaying() const; - virtual void playSoundEffect(uint8 track, uint8 volume = 0xff); + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); virtual void stopAllSoundEffects(); @@ -293,88 +329,6 @@ private: Sound *_music, *_sfx; }; -// Digital Audio -class AUDStream; -class KyraAudioStream; -class KyraEngine_MR; - -/** - * Digital audio output device. - * - * This is just used for Kyrandia 3. - */ -class SoundDigital { -public: - SoundDigital(KyraEngine_MR *vm, Audio::Mixer *mixer); - ~SoundDigital(); - - bool init() { return true; } - - /** - * Plays a sound. - * - * @param filename file to be played - * @param priority priority of the sound - * @param type type - * @param volume channel volume - * @param loop true if the sound should loop (endlessly) - * @param channel tell the sound player to use a specific channel for playback - * - * @return channel playing the sound - */ - int playSound(const char *filename, uint8 priority, Audio::Mixer::SoundType type, int volume = 255, bool loop = false, int channel = -1); - - /** - * Checks if a given channel is playing a sound. - * - * @param channel channel number to check - * @return true if playing, else false - */ - bool isPlaying(int channel); - - /** - * Stop the playback of a sound in the given - * channel. - * - * @param channel channel number - */ - void stopSound(int channel); - - /** - * Stops playback of all sounds. - */ - void stopAllSounds(); - - /** - * Makes the sound in a given channel - * fading out. - * - * @param channel channel number - * @param ticks fadeout time - */ - void beginFadeOut(int channel, int ticks); -private: - KyraEngine_MR *_vm; - Audio::Mixer *_mixer; - - struct Sound { - Audio::SoundHandle handle; - - char filename[16]; - uint8 priority; - KyraAudioStream *stream; - } _sounds[4]; - - struct AudioCodecs { - const char *fileext; - Audio::SeekableAudioStream *(*streamFunc)( - Common::SeekableReadStream *stream, - DisposeAfterUse::Flag disposeAfterUse); - }; - - static const AudioCodecs _supportedCodecs[]; -}; - } // End of namespace Kyra #endif diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp index 668e662413..1d665709e5 100644 --- a/engines/kyra/sound_adlib.cpp +++ b/engines/kyra/sound_adlib.cpp @@ -683,14 +683,14 @@ void AdLibDriver::adjustSfxData(uint8 *ptr, int volume) { _sfxVelocity = ptr[3]; // Adjust the values. - if (volume != 0xff) { + if (volume != 0xFF) { if (_version >= 3) { int newVal = ((((ptr[3]) + 63) * volume) >> 8) & 0xFF; ptr[3] = -newVal + 63; ptr[1] = ((ptr[1] * volume) >> 8) & 0xFF; } else { - int newVal = ((_sfxVelocity << 2) ^ 0xff) * volume; - ptr[3] = (newVal >> 10) ^ 0x3f; + int newVal = ((_sfxVelocity << 2) ^ 0xFF) * volume; + ptr[3] = (newVal >> 10) ^ 0x3F; ptr[1] = newVal >> 11; } } @@ -2292,6 +2292,8 @@ SoundAdLibPC::SoundAdLibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer) _numSoundTriggers = 0; _sfxPlayingSound = -1; _soundFileLoaded.clear(); + _currentResourceSet = 0; + memset(&_resInfo, 0, sizeof(_resInfo)); switch (vm->game()) { case GI_LOL: @@ -2322,6 +2324,8 @@ SoundAdLibPC::SoundAdLibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer) SoundAdLibPC::~SoundAdLibPC() { delete _driver; delete[] _soundDataPtr; + for (int i = 0; i < 3; i++) + initAudioResourceInfo(i, 0); } bool SoundAdLibPC::init() { @@ -2371,7 +2375,7 @@ void SoundAdLibPC::playTrack(uint8 track) { _driver->setSyncJumpMask(0x000F); else _driver->setSyncJumpMask(0); - play(track, 0xff); + play(track, 0xFF); } } @@ -2405,7 +2409,7 @@ void SoundAdLibPC::play(uint8 track, uint8 volume) { } void SoundAdLibPC::beginFadeOut() { - play(_version > 2 ? 1 : 15, 0xff); + play(_version > 2 ? 1 : 15, 0xFF); } int SoundAdLibPC::checkTrigger() { @@ -2416,8 +2420,29 @@ void SoundAdLibPC::resetTrigger() { _driver->resetSoundTrigger(); } +void SoundAdLibPC::initAudioResourceInfo(int set, void *info) { + if (set >= kMusicIntro && set <= kMusicFinale) { + delete _resInfo[set]; + _resInfo[set] = info ? new SoundResourceInfo_PC(*(SoundResourceInfo_PC*)info) : 0; + } +} + +void SoundAdLibPC::selectAudioResourceSet(int set) { + if (set >= kMusicIntro && set <= kMusicFinale) { + if (_resInfo[set]) + _currentResourceSet = set; + } +} + +bool SoundAdLibPC::hasSoundFile(uint file) const { + if (file < res()->fileListSize) + return (res()->fileList[file] != 0); + return false; +} + void SoundAdLibPC::loadSoundFile(uint file) { - internalLoadFile(fileListEntry(file)); + if (file < res()->fileListSize) + internalLoadFile(res()->fileList[file]); } void SoundAdLibPC::loadSoundFile(Common::String file) { diff --git a/engines/kyra/sound_adlib.h b/engines/kyra/sound_adlib.h index 8492f3b99a..f8486499ab 100644 --- a/engines/kyra/sound_adlib.h +++ b/engines/kyra/sound_adlib.h @@ -69,6 +69,9 @@ public: virtual void updateVolumeSettings(); + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); + virtual bool hasSoundFile(uint file) const; virtual void loadSoundFile(uint file); virtual void loadSoundFile(Common::String file); @@ -76,7 +79,7 @@ public: virtual void haltTrack(); virtual bool isPlaying() const; - virtual void playSoundEffect(uint8 track, uint8 volume = 0xff); + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); virtual void beginFadeOut(); @@ -87,6 +90,10 @@ private: void play(uint8 track, uint8 volume); + const SoundResourceInfo_PC *res() const {return _resInfo[_currentResourceSet]; } + SoundResourceInfo_PC *_resInfo[3]; + int _currentResourceSet; + AdLibDriver *_driver; int _version; diff --git a/engines/kyra/sound_amiga.cpp b/engines/kyra/sound_amiga.cpp index ec2748dd38..7292541594 100644 --- a/engines/kyra/sound_amiga.cpp +++ b/engines/kyra/sound_amiga.cpp @@ -53,10 +53,26 @@ bool SoundAmiga::init() { return _driver != 0 && _tableSfxIntro && _tableSfxGame; } +void SoundAmiga::initAudioResourceInfo(int set, void *info) { + // See comment below +} + +void SoundAmiga::selectAudioResourceSet(int set) { + // It seems that loadSoundFile() is doing what would normally be done in here. + // As long as this driver is only required for one single target (Kyra 1 Amiga) + // this doesn't matter much. +} + +bool SoundAmiga::hasSoundFile(uint file) const { + if (file < 3) + return true; + return false; +} + void SoundAmiga::loadSoundFile(uint file) { debugC(5, kDebugLevelSound, "SoundAmiga::loadSoundFile(%d)", file); - static const char * const tableFilenames[3][2] = { + static const char *const tableFilenames[3][2] = { { "introscr.mx", "introinst.mx" }, { "kyramusic.mx", 0 }, { "finalescr.mx", "introinst.mx" } diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index fe0f1fb9bc..518805c43e 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -20,7 +20,7 @@ * */ -#include "kyra/sound.h" +#include "kyra/sound_digital.h" #include "kyra/resource.h" #include "kyra/kyra_mr.h" @@ -271,8 +271,8 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { while (outSize > 0) { input = _inBuffer[i++] << 2; - code = (input >> 8) & 0xff; - count = (input & 0xff) >> 2; + code = (input >> 8) & 0xFF; + count = (input & 0xFF) >> 2; switch (code) { case 2: @@ -294,7 +294,7 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { for (; count >= 0; count--) { code = _inBuffer[i++]; - curSample += WSTable4Bit[code & 0x0f]; + curSample += WSTable4Bit[code & 0x0F]; curSample = clip8BitSample(curSample); _outBuffer[j++] = curSample; diff --git a/engines/kyra/sound_digital.h b/engines/kyra/sound_digital.h new file mode 100644 index 0000000000..271dde6a21 --- /dev/null +++ b/engines/kyra/sound_digital.h @@ -0,0 +1,119 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef KYRA_SOUND_DIGITAL_H +#define KYRA_SOUND_DIGITAL_H + +#include "audio/mixer.h" + +namespace Common { +class SeekableReadStream; +} // End of namespace Common + +namespace Audio { +class SeekableAudioStream; +} // End of namespace Audio + +namespace Kyra { + +// Digital Audio +class KyraAudioStream; +class KyraEngine_MR; + +/** + * Digital audio output device. + * + * This is just used for Kyrandia 3. + */ +class SoundDigital { +public: + SoundDigital(KyraEngine_MR *vm, Audio::Mixer *mixer); + ~SoundDigital(); + + /** + * Plays a sound. + * + * @param filename file to be played + * @param priority priority of the sound + * @param type type + * @param volume channel volume + * @param loop true if the sound should loop (endlessly) + * @param channel tell the sound player to use a specific channel for playback + * + * @return channel playing the sound + */ + int playSound(const char *filename, uint8 priority, Audio::Mixer::SoundType type, int volume = 255, bool loop = false, int channel = -1); + + /** + * Checks if a given channel is playing a sound. + * + * @param channel channel number to check + * @return true if playing, else false + */ + bool isPlaying(int channel); + + /** + * Stop the playback of a sound in the given + * channel. + * + * @param channel channel number + */ + void stopSound(int channel); + + /** + * Stops playback of all sounds. + */ + void stopAllSounds(); + + /** + * Makes the sound in a given channel + * fading out. + * + * @param channel channel number + * @param ticks fadeout time + */ + void beginFadeOut(int channel, int ticks); +private: + KyraEngine_MR *_vm; + Audio::Mixer *_mixer; + + struct Sound { + Audio::SoundHandle handle; + + char filename[16]; + uint8 priority; + KyraAudioStream *stream; + } _sounds[4]; + + struct AudioCodecs { + const char *fileext; + Audio::SeekableAudioStream *(*streamFunc)( + Common::SeekableReadStream *stream, + DisposeAfterUse::Flag disposeAfterUse); + }; + + static const AudioCodecs _supportedCodecs[]; +}; + +} // End of namespace Kyra + +#endif diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h index 827a487685..007ca3d3f5 100644 --- a/engines/kyra/sound_intern.h +++ b/engines/kyra/sound_intern.h @@ -23,6 +23,8 @@ #ifndef KYRA_SOUND_INTERN_H #define KYRA_SOUND_INTERN_H + + #include "kyra/sound.h" #include "kyra/sound_adlib.h" @@ -40,6 +42,7 @@ class MaxTrax; } // End of namespace Audio namespace Kyra { + class MidiOutput; /** @@ -51,28 +54,31 @@ class MidiOutput; class SoundMidiPC : public Sound { public: SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *driver, kType type); - ~SoundMidiPC(); + virtual ~SoundMidiPC(); - kType getMusicType() const { return _type; } + virtual kType getMusicType() const { return _type; } - bool init(); + virtual bool init(); - void updateVolumeSettings(); + virtual void updateVolumeSettings(); - void loadSoundFile(uint file); - void loadSoundFile(Common::String file); - void loadSfxFile(Common::String file); + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); + virtual bool hasSoundFile(uint file) const; + virtual void loadSoundFile(uint file); + virtual void loadSoundFile(Common::String file); + virtual void loadSfxFile(Common::String file); - void playTrack(uint8 track); - void haltTrack(); - bool isPlaying() const; + virtual void playTrack(uint8 track); + virtual void haltTrack(); + virtual bool isPlaying() const; - void playSoundEffect(uint8 track, uint8 volume = 0xff); - void stopAllSoundEffects(); + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); + virtual void stopAllSoundEffects(); - void beginFadeOut(); + virtual void beginFadeOut(); - void pause(bool paused); + virtual void pause(bool paused); private: static void onTimer(void *data); @@ -89,6 +95,10 @@ private: MidiParser *_music; MidiParser *_sfx[3]; + const SoundResourceInfo_PC *res() const {return _resInfo[_currentResourceSet]; } + SoundResourceInfo_PC *_resInfo[3]; + int _currentResourceSet; + // misc kType _type; Common::String getFileName(const Common::String &str); @@ -103,25 +113,28 @@ private: class SoundTowns : public Sound { public: SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer); - ~SoundTowns(); + virtual ~SoundTowns(); - kType getMusicType() const { return kTowns; } + virtual kType getMusicType() const { return kTowns; } - bool init(); - void process(); + virtual bool init(); + virtual void process(); - void loadSoundFile(uint file); - void loadSoundFile(Common::String) {} + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); + virtual bool hasSoundFile(uint file) const; + virtual void loadSoundFile(uint file); + virtual void loadSoundFile(Common::String) {} - void playTrack(uint8 track); - void haltTrack(); + virtual void playTrack(uint8 track); + virtual void haltTrack(); - void playSoundEffect(uint8 track, uint8 volume = 0xff); - void stopAllSoundEffects(); + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); + virtual void stopAllSoundEffects(); - void beginFadeOut(); + virtual void beginFadeOut(); - void updateVolumeSettings(); + virtual void updateVolumeSettings(); private: bool loadInstruments(); @@ -142,6 +155,10 @@ private: bool _cdaPlaying; + const SoundResourceInfo_Towns *res() const {return _resInfo[_currentResourceSet]; } + SoundResourceInfo_Towns *_resInfo[3]; + int _currentResourceSet; + const uint8 *_musicFadeTable; const uint8 *_sfxBTTable; const uint8 *_sfxWDTable; @@ -150,55 +167,64 @@ private: class SoundPC98 : public Sound { public: SoundPC98(KyraEngine_v1 *vm, Audio::Mixer *mixer); - ~SoundPC98(); + virtual ~SoundPC98(); virtual kType getMusicType() const { return kPC98; } - bool init(); + virtual bool init(); - void process() {} - void loadSoundFile(uint file); - void loadSoundFile(Common::String file); + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); + virtual bool hasSoundFile(uint file) const; + virtual void loadSoundFile(uint file); + virtual void loadSoundFile(Common::String file); - void playTrack(uint8 track); - void haltTrack(); - void beginFadeOut(); + virtual void playTrack(uint8 track); + virtual void haltTrack(); + virtual void beginFadeOut(); - int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { return -1; } - void playSoundEffect(uint8 track, uint8 volume = 0xff); + virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) override { return -1; } + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); - void updateVolumeSettings(); + virtual void updateVolumeSettings(); -protected: +private: int _lastTrack; uint8 *_musicTrackData; uint8 *_sfxTrackData; TownsPC98_AudioDriver *_driver; + + const char *resPattern() {return _resInfo[_currentResourceSet]->c_str(); } + Common::String *_resInfo[3]; + int _currentResourceSet; }; class SoundTownsPC98_v2 : public Sound { public: SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer); - ~SoundTownsPC98_v2(); + virtual ~SoundTownsPC98_v2(); - kType getMusicType() const { return _vm->gameFlags().platform == Common::kPlatformFMTowns ? kTowns : kPC98; } + virtual kType getMusicType() const { return _vm->gameFlags().platform == Common::kPlatformFMTowns ? kTowns : kPC98; } - bool init(); - void process(); + virtual bool init(); + virtual void process(); - void loadSoundFile(uint file) {} - void loadSoundFile(Common::String file); + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); + virtual bool hasSoundFile(uint file) const; + virtual void loadSoundFile(uint file) {} + virtual void loadSoundFile(Common::String file); - void playTrack(uint8 track); - void haltTrack(); - void beginFadeOut(); + virtual void playTrack(uint8 track); + virtual void haltTrack(); + virtual void beginFadeOut(); - int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx); - void playSoundEffect(uint8 track, uint8 volume = 0xff); + virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume = 255, uint8 priority = 255, bool isSfx = true) override; + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); - void updateVolumeSettings(); + virtual void updateVolumeSettings(); -protected: +private: Audio::AudioStream *_currentSFX; int _lastTrack; bool _useFmSfx; @@ -206,6 +232,10 @@ protected: uint8 *_musicTrackData; uint8 *_sfxTrackData; TownsPC98_AudioDriver *_driver; + + const SoundResourceInfo_TownsPC98V2 *res() const {return _resInfo[_currentResourceSet]; } + SoundResourceInfo_TownsPC98V2 *_resInfo[3]; + int _currentResourceSet; }; // PC Speaker MIDI driver @@ -288,22 +318,24 @@ struct AmigaSfxTable { class SoundAmiga : public Sound { public: SoundAmiga(KyraEngine_v1 *vm, Audio::Mixer *mixer); - ~SoundAmiga(); + virtual ~SoundAmiga(); virtual kType getMusicType() const { return kAmiga; } //FIXME - bool init(); + virtual bool init(); - void process() {} - void loadSoundFile(uint file); - void loadSoundFile(Common::String) {} + virtual void initAudioResourceInfo(int set, void *info); + virtual void selectAudioResourceSet(int set); + virtual bool hasSoundFile(uint file) const; + virtual void loadSoundFile(uint file); + virtual void loadSoundFile(Common::String) {} - void playTrack(uint8 track); - void haltTrack(); - void beginFadeOut(); + virtual void playTrack(uint8 track); + virtual void haltTrack(); + virtual void beginFadeOut(); - int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { return -1; } - void playSoundEffect(uint8 track, uint8 volume = 0xff); + virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) override { return -1; } + virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF); protected: Audio::MaxTrax *_driver; diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index cb9be43b07..48230d025c 100644 --- a/engines/kyra/sound_lol.cpp +++ b/engines/kyra/sound_lol.cpp @@ -60,7 +60,7 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { Common::String pattern2 = Common::String::format("%02d", id & 0x4000 ? 0 : _curTlkFile); if (id & 0x4000) { - pattern1 = Common::String::format("%03X", id & 0x3fff); + pattern1 = Common::String::format("%03X", id & 0x3FFF); } else if (id < 1000) { pattern1 = Common::String::format("%03d", id); } else { @@ -164,11 +164,19 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { if (track == -1 || track >= _ingameSoundListSize) return; - volume &= 0xff; - int16 volIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); + volume &= 0xFF; + int16 prIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]); + uint16 priority = (prIndex > 0) ? (prIndex * volume) >> 8 : -prIndex; - uint16 vocLevel = (volIndex > 0) ? (volIndex * volume) >> 8 : -volIndex; - vocLevel = CLIP(volume >> 4, 2, 13) * 7 + 164; + static const uint8 volTable1[] = { 223, 159, 95, 47, 15, 0 }; + static const uint8 volTable2[] = { 255, 191, 127, 63, 30, 0 }; + + for (int i = 0; i < 6; i++) { + if (volTable1[i] < volume) { + volume = volTable2[i]; + break; + } + } int16 vocIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2]); @@ -180,7 +188,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) { if (hasVocFile) { if (_sound->isVoicePresent(_ingameSoundList[vocIndex])) - _sound->voicePlay(_ingameSoundList[vocIndex], 0, vocLevel & 0xff, true); + _sound->voicePlay(_ingameSoundList[vocIndex], 0, volume, priority, true); } else if (_flags.platform == Common::kPlatformPC) { if (_sound->getSfxType() == Sound::kMidiMT32) track = (track < _ingameMT32SoundIndexSize) ? (_ingameMT32SoundIndex[track] - 1) : -1; @@ -206,8 +214,8 @@ bool LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) { uint16 cbl = _currentBlock; for (int i = 3; i > 0; i--) { - int dir = calcMonsterDirection(cbl & 0x1f, cbl >> 5, block & 0x1f, block >> 5); - cbl = (cbl + blockShiftTable[dir]) & 0x3ff; + int dir = calcMonsterDirection(cbl & 0x1F, cbl >> 5, block & 0x1F, block >> 5); + cbl = (cbl + blockShiftTable[dir]) & 0x3FF; if (cbl != block) { if (testWallFlag(cbl, 0, 1)) _environmentSfxVol >>= 1; @@ -239,7 +247,7 @@ void LoLEngine::snd_playQueuedEffects() { void LoLEngine::snd_loadSoundFile(int track) { if (_sound->musicEnabled()) { - if (_flags.platform != Common::kPlatformPC98) { + if (_flags.platform == Common::kPlatformPC) { int t = (track - 250) * 3; if (_curMusicFileIndex != _musicTrackMap[t] || _curMusicFileExt != (char)_musicTrackMap[t + 1]) { snd_stopMusic(); @@ -261,12 +269,12 @@ int LoLEngine::snd_playTrack(int track) { _lastMusicTrack = track; if (_sound->musicEnabled()) { - if (_flags.platform == Common::kPlatformPC98) { - _sound->playTrack(track - 249); - } else { + if (_flags.platform == Common::kPlatformPC) { snd_loadSoundFile(track); int t = (track - 250) * 3; _sound->playTrack(_musicTrackMap[t + 2]); + } else { + _sound->playTrack(track - 249); } } diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp index 70cc304192..a54c52612b 100644 --- a/engines/kyra/sound_midi.cpp +++ b/engines/kyra/sound_midi.cpp @@ -442,6 +442,8 @@ SoundMidiPC::SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *dri _output = 0; _musicFile = _sfxFile = 0; + _currentResourceSet = 0; + memset(&_resInfo, 0, sizeof(_resInfo)); _music = MidiParser::createParser_XMIDI(); assert(_music); @@ -495,6 +497,9 @@ SoundMidiPC::~SoundMidiPC() { delete[] _sfxFile; delete[] _musicFile; + + for (int i = 0; i < 3; i++) + initAudioResourceInfo(i, 0); } bool SoundMidiPC::init() { @@ -586,8 +591,29 @@ void SoundMidiPC::updateVolumeSettings() { _output->setSourceVolume(i, _sfxVolume, false); } +void SoundMidiPC::initAudioResourceInfo(int set, void *info) { + if (set >= kMusicIntro && set <= kMusicFinale) { + delete _resInfo[set]; + _resInfo[set] = info ? new SoundResourceInfo_PC(*(SoundResourceInfo_PC*)info) : 0; + } +} + +void SoundMidiPC::selectAudioResourceSet(int set) { + if (set >= kMusicIntro && set <= kMusicFinale) { + if (_resInfo[set]) + _currentResourceSet = set; + } +} + +bool SoundMidiPC::hasSoundFile(uint file) const { + if (file < res()->fileListSize) + return (res()->fileList[file] != 0); + return false; +} + void SoundMidiPC::loadSoundFile(uint file) { - loadSoundFile(fileListEntry(file)); + if (file < res()->fileListSize) + loadSoundFile(res()->fileList[file]); } void SoundMidiPC::loadSoundFile(Common::String file) { diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 4b25db33f2..af741a1ebe 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -35,8 +35,8 @@ namespace Kyra { SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1), _musicTrackData(0), _sfxFileData(0), _cdaPlaying(0), - _sfxFileIndex((uint)-1), _musicFadeTable(0), _sfxWDTable(0), _sfxBTTable(0), _sfxChannel(0x46) { - + _sfxFileIndex((uint)-1), _musicFadeTable(0), _sfxWDTable(0), _sfxBTTable(0), _sfxChannel(0x46), _currentResourceSet(0) { + memset(&_resInfo, 0, sizeof(_resInfo)); _driver = new TownsEuphonyDriver(_mixer); } @@ -46,6 +46,8 @@ SoundTowns::~SoundTowns() { delete _driver; delete[] _musicTrackData; delete[] _sfxFileData; + for (int i = 0; i < 3; i++) + initAudioResourceInfo(i, 0); } bool SoundTowns::init() { @@ -78,11 +80,12 @@ void SoundTowns::playTrack(uint8 track) { return; track -= 2; - const int32 *const tTable = (const int32 *)cdaData(); - int tTableIndex = 3 * track; + uint tTableIndex = 3 * track; + + assert(tTableIndex + 2 < res()->cdaTableSize); - int trackNum = (int)READ_LE_UINT32(&tTable[tTableIndex + 2]); - int32 loop = (int32)READ_LE_UINT32(&tTable[tTableIndex + 1]); + int trackNum = (int)READ_LE_UINT32(&res()->cdaTable[tTableIndex + 2]); + int32 loop = (int32)READ_LE_UINT32(&res()->cdaTable[tTableIndex + 1]); if (track == _lastTrack && _musicEnabled) return; @@ -95,7 +98,7 @@ void SoundTowns::playTrack(uint8 track) { g_system->getAudioCDManager()->updateCD(); _cdaPlaying = true; } else if (_musicEnabled) { - playEuphonyTrack(READ_LE_UINT32(&tTable[tTableIndex]), loop); + playEuphonyTrack(READ_LE_UINT32(&res()->cdaTable[tTableIndex]), loop); _cdaPlaying = false; } @@ -117,12 +120,32 @@ void SoundTowns::haltTrack() { _driver->stopParser(); } +void SoundTowns::initAudioResourceInfo(int set, void *info) { + if (set >= kMusicIntro && set <= kMusicFinale) { + delete _resInfo[set]; + _resInfo[set] = info ? new SoundResourceInfo_Towns(*(SoundResourceInfo_Towns*)info) : 0; + } +} + +void SoundTowns::selectAudioResourceSet(int set) { + if (set >= kMusicIntro && set <= kMusicFinale) { + if (_resInfo[set]) + _currentResourceSet = set; + } +} + +bool SoundTowns::hasSoundFile(uint file) const { + if (file < res()->fileListSize) + return (res()->fileList[file] != 0); + return false; +} + void SoundTowns::loadSoundFile(uint file) { - if (_sfxFileIndex == file) + if (_sfxFileIndex == file || file >= res()->fileListSize) return; _sfxFileIndex = file; delete[] _sfxFileData; - _sfxFileData = _vm->resource()->fileData(fileListEntry(file), 0); + _sfxFileData = _vm->resource()->fileData(res()->fileList[file], 0); } void SoundTowns::playSoundEffect(uint8 track, uint8) { @@ -151,8 +174,8 @@ void SoundTowns::playSoundEffect(uint8 track, uint8) { } } - uint8 *fileBody = _sfxFileData + 0x01b8; - int32 offset = (int32)READ_LE_UINT32(_sfxFileData + (track - 0x0b) * 4); + uint8 *fileBody = _sfxFileData + 0x01B8; + int32 offset = (int32)READ_LE_UINT32(_sfxFileData + (track - 0x0B) * 4); if (offset == -1) return; @@ -191,10 +214,10 @@ void SoundTowns::playSoundEffect(uint8 track, uint8) { sfx_WdTable_Number = READ_LE_UINT16(_sfxWDTable + sfx_WdTable_Offset); sfx_BtTable_Offset += (int16)READ_LE_UINT16(_sfxWDTable + sfx_WdTable_Offset + 2); - *tgt++ = _sfxBTTable[((sfx_BtTable_Offset >> 2) & 0xff)]; + *tgt++ = _sfxBTTable[((sfx_BtTable_Offset >> 2) & 0xFF)]; sfx_BtTable_Offset += (int16)READ_LE_UINT16(_sfxWDTable + sfx_WdTable_Offset + 4); - *tgt++ = _sfxBTTable[((sfx_BtTable_Offset >> 2) & 0xff)]; + *tgt++ = _sfxBTTable[((sfx_BtTable_Offset >> 2) & 0xFF)]; } } @@ -270,7 +293,7 @@ void SoundTowns::beginFadeOut() { for (int ii = 0; ii < 6; ii++) _driver->chanVolume(ii, fadeVolCur[ii]); for (int ii = 0x40; ii < 0x46; ii++) - _driver->chanVolume(ii, fadeVolCur[ii - 0x3a]); + _driver->chanVolume(ii, fadeVolCur[ii - 0x3A]); for (int ii = 0; ii < 6; ii++) { fadeVolCur[ii] -= fadeVolStep[ii]; @@ -367,13 +390,16 @@ void SoundTowns::fadeOutSoundEffects() { } SoundPC98::SoundPC98(KyraEngine_v1 *vm, Audio::Mixer *mixer) : - Sound(vm, mixer), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0) { + Sound(vm, mixer), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0), _currentResourceSet(0) { + memset(&_resInfo, 0, sizeof(_resInfo)); } SoundPC98::~SoundPC98() { delete[] _musicTrackData; delete[] _sfxTrackData; delete _driver; + for (int i = 0; i < 3; i++) + initAudioResourceInfo(i, 0); } bool SoundPC98::init() { @@ -383,8 +409,26 @@ bool SoundPC98::init() { return reslt; } -void SoundPC98::loadSoundFile(uint file) { - if (!scumm_strnicmp(fileListEntry(0), "INTRO", 5)) { +void SoundPC98::initAudioResourceInfo(int set, void *info) { + if (set >= kMusicIntro && set <= kMusicFinale) { + delete _resInfo[set]; + _resInfo[set] = info ? new Common::String(((SoundResourceInfo_PC98*)info)->pattern) : 0; + } +} + +void SoundPC98::selectAudioResourceSet(int set) { + if (set >= kMusicIntro && set <= kMusicFinale) { + if (_resInfo[set]) + _currentResourceSet = set; + } +} + +bool SoundPC98::hasSoundFile(uint file) const { + return true; +} + +void SoundPC98::loadSoundFile(uint) { + if (_currentResourceSet == kMusicIntro) { delete[] _sfxTrackData; _sfxTrackData = 0; @@ -407,14 +451,14 @@ void SoundPC98::loadSoundFile(Common::String file) { } void SoundPC98::playTrack(uint8 track) { - track += extraOffset(); + track -= 1; if (track == _lastTrack && _musicEnabled) return; beginFadeOut(); - Common::String musicFile = fileListLen() == 1 ? Common::String::format(fileListEntry(0), track) : fileListEntry(track); + Common::String musicFile = Common::String::format(resPattern(), track); delete[] _musicTrackData; _musicTrackData = _vm->resource()->fileData(musicFile.c_str(), 0); if (_musicEnabled) @@ -464,13 +508,16 @@ void SoundPC98::updateVolumeSettings() { // KYRA 2 SoundTownsPC98_v2::SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) : - Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false) { + Sound(vm, mixer), _currentSFX(0), _musicTrackData(0), _sfxTrackData(0), _lastTrack(-1), _driver(0), _useFmSfx(false), _currentResourceSet(0) { + memset(&_resInfo, 0, sizeof(_resInfo)); } SoundTownsPC98_v2::~SoundTownsPC98_v2() { delete[] _musicTrackData; delete[] _sfxTrackData; delete _driver; + for (int i = 0; i < 3; i++) + initAudioResourceInfo(i, 0); } bool SoundTownsPC98_v2::init() { @@ -478,7 +525,9 @@ bool SoundTownsPC98_v2::init() { TownsPC98_AudioDriver::kType86 : TownsPC98_AudioDriver::kTypeTowns); if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { - _vm->checkCD(); + if (_resInfo[_currentResourceSet]) + if (_resInfo[_currentResourceSet]->cdaTableSize) + _vm->checkCD(); // FIXME: While checking for 'track1.XXX(X)' looks like // a good idea, we should definitely not be doing this // here. Basically our filenaming scheme could change @@ -486,9 +535,9 @@ bool SoundTownsPC98_v2::init() { // this misses the possibility that we play the tracks // right off CD. So we should find another way to // check if we have access to CD audio. - Resource *res = _vm->resource(); + Resource *r = _vm->resource(); if (_musicEnabled && - (res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla"))) + (r->exists("track1.mp3") || r->exists("track1.ogg") || r->exists("track1.flac") || r->exists("track1.fla"))) _musicEnabled = 2; else _musicEnabled = 1; @@ -503,6 +552,26 @@ bool SoundTownsPC98_v2::init() { return reslt; } +void SoundTownsPC98_v2::initAudioResourceInfo(int set, void *info) { + if (set >= kMusicIntro && set <= kMusicFinale) { + delete _resInfo[set]; + _resInfo[set] = info ? new SoundResourceInfo_TownsPC98V2(*(SoundResourceInfo_TownsPC98V2*)info) : 0; + } +} + +void SoundTownsPC98_v2::selectAudioResourceSet(int set) { + if (set >= kMusicIntro && set <= kMusicFinale) { + if (_resInfo[set]) + _currentResourceSet = set; + } +} + +bool SoundTownsPC98_v2::hasSoundFile(uint file) const { + if (file < res()->fileListSize) + return (res()->fileList[file] != 0); + return false; +} + void SoundTownsPC98_v2::loadSoundFile(Common::String file) { delete[] _sfxTrackData; _sfxTrackData = _vm->resource()->fileData(file.c_str(), 0); @@ -513,18 +582,14 @@ void SoundTownsPC98_v2::process() { } void SoundTownsPC98_v2::playTrack(uint8 track) { - track += extraOffset(); - if (track == _lastTrack && _musicEnabled) return; - const uint16 *const cdaTracks = (const uint16 *)cdaData(); - int trackNum = -1; if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { - for (int i = 0; i < cdaTrackNum(); i++) { - if (track == (uint8) READ_LE_UINT16(&cdaTracks[i * 2])) { - trackNum = (int) READ_LE_UINT16(&cdaTracks[i * 2 + 1]) - 1; + for (uint i = 0; i < res()->cdaTableSize; i++) { + if (track == (uint8) READ_LE_UINT16(&res()->cdaTable[i * 2])) { + trackNum = (int) READ_LE_UINT16(&res()->cdaTable[i * 2 + 1]) - 1; break; } } @@ -532,9 +597,10 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { beginFadeOut(); - Common::String musicFile = fileListLen() == 1 ? Common::String::format(fileListEntry(0), track) : fileListEntry(track); + Common::String musicFile = res()->pattern ? Common::String::format(res()->pattern, track) : (res()->fileList ? res()->fileList[track] : 0); if (musicFile.empty()) return; + delete[] _musicTrackData; _musicTrackData = _vm->resource()->fileData(musicFile.c_str(), 0); @@ -569,15 +635,24 @@ void SoundTownsPC98_v2::beginFadeOut() { haltTrack(); } -int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8, bool) { +int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool) { static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; static const char patternHOF[] = "%s.PCM"; static const char patternLOL[] = "%s.VOC"; int h = 0; if (_currentSFX) { - while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h])) + while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h].handle)) h++; + + if (h >= kNumChannelHandles) { + h = 0; + while (h < kNumChannelHandles && _soundChannels[h].priority > priority) + ++h; + if (h < kNumChannelHandles) + voiceStop(&_soundChannels[h].handle); + } + if (h >= kNumChannelHandles) return 0; } @@ -621,7 +696,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, cmd = ~cmd; } else { cmd |= 0x80; - if (cmd == 0xff) + if (cmd == 0xFF) cmd--; } if (cmd < 0x80) @@ -630,9 +705,10 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, } _currentSFX = Audio::makeRawStream(sfx, outsize, sfxRate * 10, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h], _currentSFX); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h].handle, _currentSFX, -1, volume); + _soundChannels[h].priority = priority; if (handle) - *handle = _soundChannels[h]; + *handle = _soundChannels[h].handle; delete[] data; return 1; diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index 5c679f5cb4..962efe6a4e 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -58,7 +58,7 @@ void EoBCoreEngine::releaseMonsterShapes(int first, int num) { const uint8 *EoBCoreEngine::loadMonsterProperties(const uint8 *data) { uint8 cmd = *data++; - while (cmd != 0xff) { + while (cmd != 0xFF) { EoBMonsterProperty *d = &_monsterProps[cmd]; d->armorClass = (int8)*data++; d->hitChance = (int8)*data++; @@ -90,7 +90,7 @@ const uint8 *EoBCoreEngine::loadMonsterProperties(const uint8 *data) { d->sound2 = (int8)*data++; d->numRemoteAttacks = *data++; - if (*data++ != 0xff) { + if (*data++ != 0xFF) { d->remoteWeaponChangeMode = *data++; d->numRemoteWeapons = *data++; @@ -113,7 +113,7 @@ const uint8 *EoBCoreEngine::loadMonsterProperties(const uint8 *data) { } const uint8 *EoBCoreEngine::loadActiveMonsterData(const uint8 *data, int level) { - for (uint8 p = *data++; p != 0xff; p = *data++) { + for (uint8 p = *data++; p != 0xFF; p = *data++) { uint8 v = *data++; _timer->setCountdown(0x20 + (p << 1), v); _timer->setCountdown(0x21 + (p << 1), v); @@ -132,7 +132,7 @@ const uint8 *EoBCoreEngine::loadActiveMonsterData(const uint8 *data, int level) memset(_monsters, 0, 30 * sizeof(EoBMonsterInPlay)); for (int i = 0; i < 30; i++, data += 14) { - if (*data == 0xff) + if (*data == 0xFF) continue; initMonster(data[0], data[1], READ_LE_UINT16(&data[2]), data[4], (int8)data[5], data[6], data[7], data[8], data[9], READ_LE_UINT16(&data[10]), READ_LE_UINT16(&data[12])); @@ -174,7 +174,7 @@ void EoBCoreEngine::initMonster(int index, int unit, uint16 block, int pos, int } void EoBCoreEngine::placeMonster(EoBMonsterInPlay *m, uint16 block, int dir) { - if (block != 0xffff) { + if (block != 0xFFFF) { checkSceneUpdateNeed(m->block); if (_levelBlockProperties[m->block].flags & 7) { _levelBlockProperties[m->block].flags--; @@ -201,11 +201,11 @@ void EoBCoreEngine::killMonster(EoBMonsterInPlay *m, bool giveExperience) { if (m->randItem) { if (rollDice(1, 10, 0) == 1) - setItemPosition((Item *)&_levelBlockProperties[m->block & 0x3ff].drawObjects, m->block, duplicateItem(m->randItem), pos); + setItemPosition((Item *)&_levelBlockProperties[m->block & 0x3FF].drawObjects, m->block, duplicateItem(m->randItem), pos); } if (m->fixedItem) - setItemPosition((Item *)&_levelBlockProperties[m->block & 0x3ff].drawObjects, m->block, duplicateItem(m->fixedItem), pos); + setItemPosition((Item *)&_levelBlockProperties[m->block & 0x3FF].drawObjects, m->block, duplicateItem(m->fixedItem), pos); if (giveExperience) increasePartyExperience(_monsterProps[m->type].experience); @@ -357,7 +357,7 @@ void EoBCoreEngine::flashMonsterShape(EoBMonsterInPlay *m) { disableSysTimer(2); _flashShapeTimer = 0; drawScene(1); - m->flags &= 0xfd; + m->flags &= 0xFD; _flashShapeTimer = _system->getMillis() + _tickLength; enableSysTimer(2); @@ -536,7 +536,7 @@ void EoBCoreEngine::drawMonsters(int index) { int h = shp[1]; x = x - (w >> 1) + (d->idleAnimState >> 4); - y = y - h + (d->idleAnimState & 0x0f); + y = y - h + (d->idleAnimState & 0x0F); drawMonsterShape(shp, x, y, f >= 0 ? 0 : 1, d->flags, palIndex); diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index f4bae113c5..88b24e1367 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -66,7 +66,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int animTy of[2] = _screen->makeShapeCopy(p, s + 2); } } - _monsterAnimType[monsterIndex] = animType & 0xff; + _monsterAnimType[monsterIndex] = animType & 0xFF; uint8 *palShape = _screen->makeShapeCopy(p, 16); @@ -90,7 +90,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int animTy uint16 sz = MIN(_screen->getShapeSize(_monsterShapes[pos]) - 10, 256); memset(tmpPal2, 0, 256); memcpy(tmpPal2, _monsterShapes[pos] + 10, sz); - memset(tmpPal3, 0xff, 256 * sizeof(uint16)); + memset(tmpPal3, 0xFF, 256 * sizeof(uint16)); uint8 numCol = *tmpPal2; for (int ii = 0; ii < numCol; ii++) { @@ -104,7 +104,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int animTy memset(tmpPal2, 0, 256); memcpy(tmpPal2, _monsterShapes[pos] + 10, sz); for (int iii = 0; iii < numCol; iii++) { - if (tmpPal3[iii] == 0xffff) + if (tmpPal3[iii] == 0xFFFF) continue; if (p[tmpPal3[iii] * 320 + ii + 1]) tmpPal2[1 + iii] = p[tmpPal3[iii] * 320 + ii + 1]; @@ -159,7 +159,7 @@ int LoLEngine::deleteMonstersFromBlock(int block) { continue; } - LoLMonster *m = &_monsters[i & 0x7fff]; + LoLMonster *m = &_monsters[i & 0x7FFF]; cnt++; setMonsterMode(m, 14); @@ -215,8 +215,8 @@ bool LoLEngine::updateMonsterAdjustBlocks(LoLMonster *monster) { if (monster->properties->flags & 8) return true; - uint16 x1 = (monster->x & 0xff00) | 0x80; - uint16 y1 = (monster->y & 0xff00) | 0x80; + uint16 x1 = (monster->x & 0xFF00) | 0x80; + uint16 y1 = (monster->y & 0xFF00) | 0x80; int x2 = _partyPosX; int y2 = _partyPosY; @@ -242,7 +242,7 @@ bool LoLEngine::updateMonsterAdjustBlocks(LoLMonster *monster) { return false; for (int i = 0; i < 18; i++) - _visibleBlocks[i] = &_levelBlockProperties[(monster->block + _dscBlockIndex[dir + i]) & 0x3ff]; + _visibleBlocks[i] = &_levelBlockProperties[(monster->block + _dscBlockIndex[dir + i]) & 0x3FF]; int16 fx1 = 0; int16 fx2 = 0; @@ -277,8 +277,8 @@ void LoLEngine::placeMonster(LoLMonster *monster, uint16 x, uint16 y) { _levelBlockProperties[monster->block].direction = 5; checkSceneUpdateNeed(monster->block); - // WORKAROUND: Some monsters in the white tower have sound id's of 0xff. This is definitely a bug, since the - // last valid track number is 249 and there is no specific handling for 0xff. Nonetheless this wouldn't + // WORKAROUND: Some monsters in the white tower have sound id's of 0xFF. This is definitely a bug, since the + // last valid track number is 249 and there is no specific handling for 0xFF. Nonetheless this wouldn't // cause problems in the original code, because it just so happens that the invalid memory address points // to an entry in _ingameGMSoundIndex which just so happens to have a value of -1 if (monster->properties->sounds[0] == 0 || monster->properties->sounds[0] == 255 || cont == false) @@ -364,7 +364,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 object return 4; if (x & 0x80) { - if (((x & 0xff) + objectWidth) & 0xff00) { + if (((x & 0xFF) + objectWidth) & 0xFF00) { xOffs = 1; _objectLastDirection = 2; x2 = x + objectWidth; @@ -380,7 +380,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 object flag = 1; } } else { - if (((x & 0xff) - objectWidth) & 0xff00) { + if (((x & 0xFF) - objectWidth) & 0xFF00) { xOffs = -1; _objectLastDirection = 6; x2 = x - objectWidth; @@ -398,7 +398,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 object } if (y & 0x80) { - if (((y & 0xff) + objectWidth) & 0xff00) { + if (((y & 0xFF) + objectWidth) & 0xFF00) { yOffs = 1; _objectLastDirection = 4; y2 = y + objectWidth; @@ -415,7 +415,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 object flag = 0; } } else { - if (((y & 0xff) - objectWidth) & 0xff00) { + if (((y & 0xFF) - objectWidth) & 0xFF00) { yOffs = -1; _objectLastDirection = 0; y2 = y - objectWidth; @@ -449,7 +449,7 @@ int LoLEngine::checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 object int LoLEngine::testBlockPassability(int block, int x, int y, int objectWidth, int testFlag, int wallFlag) { if (block == _currentBlock) - testFlag &= 0xfffe; + testFlag &= 0xFFFE; if (testFlag & 1) { _monsterCurBlock = block; @@ -463,7 +463,7 @@ int LoLEngine::testBlockPassability(int block, int x, int y, int objectWidth, in uint16 obj = _levelBlockProperties[block].assignedObjects; while (obj & 0x8000) { - LoLMonster *monster = &_monsters[obj & 0x7fff]; + LoLMonster *monster = &_monsters[obj & 0x7FFF]; if (monster->mode < 13) { int r = checkDrawObjectSpace(x, y, monster->x, monster->y); @@ -481,19 +481,8 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) { const uint16 *c = getCharacterOrMonsterStats(id); int r = (a << 8) / c[4]; - /* - if (!(id & 0x8000)) - r = (r * _monsterModifiers[3 + _monsterDifficulty]) >> 8; - - id &= 0x7fff; - - if (_characters[id].skillLevels[1] <= 3) - return r; - else if (_characters[id].skillLevels[1] <= 7) - return (r- (r >> 2));*/ - if (id & 0x8000) { - r = (r * _monsterModifiers[3 + _monsterDifficulty]) >> 8; + r = (r * _monsterModifiers2[3 + _monsterDifficulty]) >> 8; } else { if (_characters[id].skillLevels[1] > 7) r = (r - (r >> 1)); @@ -530,7 +519,7 @@ void LoLEngine::drawBlockObjects(int blockArrayIndex) { s = l->drawObjects; while (s) { if (s & 0x8000) { - s &= 0x7fff; + s &= 0x7FFF; if (blockArrayIndex < 15) drawMonster(s); s = _monsters[s].nextDrawObject; @@ -607,7 +596,7 @@ void LoLEngine::drawBlockObjects(int blockArrayIndex) { void LoLEngine::drawMonster(uint16 id) { LoLMonster *m = &_monsters[id]; int16 flg = _monsterDirFlags[(_currentDirection << 2) + m->facing]; - int curFrm = getMonsterCurFrame(m, flg & 0xffef); + int curFrm = getMonsterCurFrame(m, flg & 0xFFEF); uint8 *shp = 0; if (curFrm == -1) { @@ -622,7 +611,7 @@ void LoLEngine::drawMonster(uint16 id) { if (m->properties->flags & 0x800) flg |= 0x20; - uint8 *monsterPalette = d ? _monsterPalettes[(m->properties->shapeIndex << 4) + (curFrm & 0x0f)] + (shp[10] * (d - 1)) : 0; + uint8 *monsterPalette = d ? _monsterPalettes[(m->properties->shapeIndex << 4) + (curFrm & 0x0F)] + (shp[10] * (d - 1)) : 0; uint8 *brightnessOverlay = drawItemOrMonster(shp, monsterPalette, m->x + _monsterShiftOffs[m->shiftStep << 1], m->y + _monsterShiftOffs[(m->shiftStep << 1) + 1], 0, 0, flg | 1, -1, flip); for (int i = 0; i < 4; i++) { @@ -644,16 +633,16 @@ void LoLEngine::drawMonster(uint16 id) { int dW = _screen->getShapeScaledWidth(shp, _dmScaleW) >> 1; int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1; - int bloodAmount = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->hitPoints / (m->damageReceived & 0x7fff)); + int bloodAmount = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->hitPoints / (m->damageReceived & 0x7FFF)); shp = _gameShapes[6]; - int bloodType = m->properties->flags & 0xc000; + int bloodType = m->properties->flags & 0xC000; if (bloodType == 0x4000) - bloodType = _flags.use16ColorMode ? 0xbb : 63; + bloodType = _flags.use16ColorMode ? 0xBB : 63; else if (bloodType == 0x8000) bloodType = _flags.use16ColorMode ? 0x55 : 15; - else if (bloodType == 0xc000) + else if (bloodType == 0xC000) bloodType = _flags.use16ColorMode ? 0x33 : 74; else bloodType = 0; @@ -708,7 +697,9 @@ int LoLEngine::getMonsterCurFrame(LoLMonster *m, uint16 dirFlags) { break; case 1: // monsters whose outward appearance reflects the damage they have taken - tmp = (m->properties->hitPoints * _monsterModifiers[_monsterDifficulty]) >> 8; + tmp = m->properties->hitPoints; + if (_flags.isTalkie) + tmp = (tmp * _monsterModifiers1[_monsterDifficulty]) >> 8; if (m->hitPoints > (tmp >> 1)) tmp = 0; else if (m->hitPoints > (tmp >> 2)) @@ -796,7 +787,7 @@ void LoLEngine::redrawSceneItem() { int t = (i << 7) + 1; while (s) { if (s & 0x8000) { - s = _monsters[s & 0x7fff].nextDrawObject; + s = _monsters[s & 0x7FFF].nextDrawObject; } else { LoLItem *item = &_itemsInPlay[s]; @@ -934,7 +925,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *monsterPalette, int x, uint8 tmpOvl[16]; if (flags & 0x80) { - flags &= 0xff7f; + flags &= 0xFF7F; ovl2 = monsterPalette; monsterPalette = 0; } else { @@ -969,7 +960,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *monsterPalette, int x, if (_flags.use16ColorMode) { if (_currentLevel != 22) - flg &= 0xdfff; + flg &= 0xDFFF; } else { if (_currentLevel == 22) { @@ -1059,7 +1050,7 @@ void LoLEngine::updateMonster(LoLMonster *monster) { if ((monster->mode != 11) && (monster->mode != 14)) { if (!(_rnd.getRandomNumber(255) & 3)) { - monster->shiftStep = (monster->shiftStep + 1) & 0x0f; + monster->shiftStep = (monster->shiftStep + 1) & 0x0F; checkSceneUpdateNeed(monster->block); } } @@ -1127,7 +1118,7 @@ void LoLEngine::updateMonster(LoLMonster *monster) { // first recovery phase after delivering an attack if (++monster->fightCurTick > 2) { setMonsterMode(monster, 5); - monster->fightCurTick = (int8)((((8 << 8) / monster->properties->fightingStats[4]) * _monsterModifiers[6 + _monsterDifficulty]) >> 8); + monster->fightCurTick = (int8)((((8 << 8) / monster->properties->fightingStats[4]) * _monsterModifiers3[_monsterDifficulty]) >> 8); } checkSceneUpdateNeed(monster->block); break; @@ -1137,7 +1128,7 @@ void LoLEngine::updateMonster(LoLMonster *monster) { chasePartyWithCloseAttacks(monster); } else { setMonsterMode(monster, 7); - monster->flags &= 0xfff7; + monster->flags &= 0xFFF7; } break; @@ -1164,13 +1155,13 @@ void LoLEngine::updateMonster(LoLMonster *monster) { if (monster->damageReceived) { if (monster->damageReceived & 0x8000) - monster->damageReceived &= 0x7fff; + monster->damageReceived &= 0x7FFF; else monster->damageReceived = 0; checkSceneUpdateNeed(monster->block); } - monster->flags &= 0xffef; + monster->flags &= 0xFFEF; } void LoLEngine::moveMonster(LoLMonster *monster) { @@ -1239,13 +1230,13 @@ bool LoLEngine::chasePartyWithDistanceAttacks(LoLMonster *monster) { int flyingObject = monster->properties->distWeapons[s]; - if (flyingObject & 0xc000) { + if (flyingObject & 0xC000) { if (getBlockDistance(monster->block, _currentBlock) > 1) { int type = flyingObject & 0x4000 ? 0 : 1; - flyingObject = makeItem(flyingObject & 0x3fff, 0, 0); + flyingObject = makeItem(flyingObject & 0x3FFF, 0, 0); if (flyingObject) { - if (!launchObject(type, flyingObject, monster->x, monster->y, 12, dir << 1, -1, monster->id | 0x8000, 0x3f)) + if (!launchObject(type, flyingObject, monster->x, monster->y, 12, dir << 1, -1, monster->id | 0x8000, 0x3F)) deleteItem(flyingObject); } } @@ -1274,7 +1265,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(LoLMonster *monster) { if (getBlockDistance(monster->block, _monsters[i].block) < 7) setMonsterMode(monster, 7); } - _txt->printMessage(2, "%s", getLangString(0x401a)); + _txt->printMessage(2, "%s", getLangString(0x401A)); } else if (flyingObject == 4) { launchMagicViper(); @@ -1294,7 +1285,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(LoLMonster *monster) { void LoLEngine::chasePartyWithCloseAttacks(LoLMonster *monster) { if (!(monster->flags & 8)) { - int dir = calcMonsterDirection(monster->x & 0xff00, monster->y & 0xff00, _partyPosX & 0xff00, _partyPosY & 0xff00); + int dir = calcMonsterDirection(monster->x & 0xFF00, monster->y & 0xFF00, _partyPosX & 0xFF00, _partyPosY & 0xFF00); int x1 = _partyPosX; int y1 = _partyPosY; @@ -1396,11 +1387,11 @@ int LoLEngine::checkForPossibleDistanceAttack(uint16 monsterBlock, int direction if (mdist > distance) return 5; - int dir = calcMonsterDirection(monsterBlock & 0x1f, monsterBlock >> 5, curBlock & 0x1f, curBlock >> 5); + int dir = calcMonsterDirection(monsterBlock & 0x1F, monsterBlock >> 5, curBlock & 0x1F, curBlock >> 5); if ((dir & 1) || (dir != (direction << 1))) return 5; - if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) && ((monsterBlock & 0xffe0) != (curBlock & 0xffe0))) + if (((monsterBlock & 0x1F) != (curBlock & 0x1F)) && ((monsterBlock & 0xFFE0) != (curBlock & 0xFFE0))) return 5; if (distance < 0) @@ -1438,8 +1429,8 @@ void LoLEngine::getNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY, static const int8 stepAdjustX[] = { 0, 32, 32, 32, 0, -32, -32, -32 }; static const int8 stepAdjustY[] = { -32, -32, 0, 32, 32, 32, 0, -32 }; - newX = (srcX + stepAdjustX[direction]) & 0x1fff; - newY = (srcY + stepAdjustY[direction]) & 0x1fff; + newX = (srcX + stepAdjustX[direction]) & 0x1FFF; + newY = (srcY + stepAdjustY[direction]) & 0x1FFF; } void LoLEngine::alignMonsterToParty(LoLMonster *monster) { @@ -1447,7 +1438,7 @@ void LoLEngine::alignMonsterToParty(LoLMonster *monster) { uint16 mx = monster->x; uint16 my = monster->y; uint16 *pos = (mdir & 1) ? &my : &mx; - bool centered = (*pos & 0x7f) == 0; + bool centered = (*pos & 0x7F) == 0; bool posFlag = true; if (monster->properties->maxWidth <= 63) { @@ -1458,7 +1449,7 @@ void LoLEngine::alignMonsterToParty(LoLMonster *monster) { r = true; } else { uint16 id = _levelBlockProperties[monster->block].assignedObjects; - id = (id & 0x8000) ? (id & 0x7fff) : 0xffff; + id = (id & 0x8000) ? (id & 0x7FFF) : 0xFFFF; if (id != monster->id) { r = true; @@ -1466,8 +1457,8 @@ void LoLEngine::alignMonsterToParty(LoLMonster *monster) { for (int i = 0; i < 3; i++) { mdir = (mdir + 1) & 3; id = _levelBlockProperties[calcNewBlockPosition(monster->block, mdir)].assignedObjects; - id = (id & 0x8000) ? (id & 0x7fff) : 0xffff; - if (id != 0xffff) { + id = (id & 0x8000) ? (id & 0x7FFF) : 0xFFFF; + if (id != 0xFFFF) { r = true; break; } diff --git a/engines/kyra/sprites_rpg.cpp b/engines/kyra/sprites_rpg.cpp index 0c4fcb09ab..9c08bc8dd6 100644 --- a/engines/kyra/sprites_rpg.cpp +++ b/engines/kyra/sprites_rpg.cpp @@ -27,9 +27,9 @@ namespace Kyra { int KyraRpgEngine::getBlockDistance(uint16 block1, uint16 block2) { - int b1x = block1 & 0x1f; + int b1x = block1 & 0x1F; int b1y = block1 >> 5; - int b2x = block2 & 0x1f; + int b2x = block2 & 0x1F; int b2y = block2 >> 5; uint8 dy = ABS(b2y - b1y); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 00dc4f9e13..bac31f0a3e 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -31,6 +31,7 @@ #include "kyra/gui_lok.h" #include "kyra/gui_hof.h" #include "kyra/gui_mr.h" +#include "kyra/sequences_hof.h" #include "kyra/sound_intern.h" #include "common/endian.h" @@ -38,7 +39,7 @@ namespace Kyra { -#define RESFILE_VERSION 83 +#define RESFILE_VERSION 84 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -245,8 +246,8 @@ bool StaticResource::init() { { kAmigaSfxTable, proc(loadAmigaSfxTable), proc(freeAmigaSfxTable) }, { kRawData, proc(loadRawData), proc(freeRawData) }, - { k2SeqData, proc(loadHofSequenceData), proc(freeHofSequenceData) }, - { k2ShpAnimDataV1, proc(loadShapeAnimData_v1), proc(freeHofShapeAnimDataV1) }, + { k2SeqData, proc(loadHoFSequenceData), proc(freeHoFSequenceData) }, + { k2SeqItemAnimData, proc(loadHoFSeqItemAnimData), proc(freeHoFSeqItemAnimData) }, { k2ItemAnimDefinition, proc(loadItemAnimDefinition), proc(freeItemAnimDefinition) }, #ifdef ENABLE_LOL @@ -289,7 +290,7 @@ void StaticResource::deinit() { } const char *const *StaticResource::loadStrings(int id, int &strings) { - return (const char * const *)getData(id, kStringList, strings); + return (const char *const *)getData(id, kStringList, strings); } const uint8 *StaticResource::loadRawData(int id, int &size) { @@ -308,12 +309,12 @@ const Room *StaticResource::loadRoomTable(int id, int &entries) { return (const Room *)getData(id, StaticResource::kRoomList, entries); } -const HofSeqData *StaticResource::loadHofSequenceData(int id, int &entries) { - return (const HofSeqData *)getData(id, k2SeqData, entries); +const HoFSeqData *StaticResource::loadHoFSequenceData(int id, int &entries) { + return (const HoFSeqData *)getData(id, k2SeqData, entries); } -const ItemAnimData_v1 *StaticResource::loadShapeAnimData_v1(int id, int &entries) { - return (const ItemAnimData_v1 *)getData(id, k2ShpAnimDataV1, entries); +const HoFSeqItemAnimData *StaticResource::loadHoFSeqItemAnimData(int id, int &entries) { + return (const HoFSeqItemAnimData *)getData(id, k2SeqItemAnimData, entries); } const ItemAnimDefinition *StaticResource::loadItemAnimDefinition(int id, int &entries) { @@ -513,12 +514,12 @@ bool StaticResource::loadRoomTable(Common::SeekableReadStream &stream, void *&pt return true; } -bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size) { +bool StaticResource::loadHoFSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size) { int numSeq = stream.readUint16BE(); uint32 offset = 2; - Sequence *tmp_s = new Sequence[numSeq]; + HoFSequence *tmp_s = new HoFSequence[numSeq]; - size = sizeof(HofSeqData) + numSeq * (sizeof(Sequence) + 28); + size = sizeof(HoFSeqData) + numSeq * (sizeof(HoFSequence) + 28); for (int i = 0; i < numSeq; i++) { stream.seek(offset, SEEK_SET); offset += 2; @@ -529,22 +530,22 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi stream.read(const_cast<char *>(tmp_s[i].wsaFile), 14); tmp_s[i].cpsFile = new char[14]; stream.read(const_cast<char *>(tmp_s[i].cpsFile), 14); - tmp_s[i].startupCommand = stream.readByte(); - tmp_s[i].finalCommand = stream.readByte(); + tmp_s[i].fadeInTransitionType = stream.readByte(); + tmp_s[i].fadeOutTransitionType = stream.readByte(); tmp_s[i].stringIndex1 = stream.readUint16BE(); tmp_s[i].stringIndex2 = stream.readUint16BE(); tmp_s[i].startFrame = stream.readUint16BE(); tmp_s[i].numFrames = stream.readUint16BE(); - tmp_s[i].frameDelay = stream.readUint16BE(); + tmp_s[i].duration = stream.readUint16BE(); tmp_s[i].xPos = stream.readUint16BE(); tmp_s[i].yPos = stream.readUint16BE(); - tmp_s[i].duration = stream.readUint16BE(); + tmp_s[i].timeout = stream.readUint16BE(); } stream.seek(offset, SEEK_SET); offset += 2; int numSeqN = stream.readUint16BE(); - NestedSequence *tmp_n = new NestedSequence[numSeqN]; - size += (numSeqN * (sizeof(NestedSequence) + 14)); + HoFNestedSequence *tmp_n = new HoFNestedSequence[numSeqN]; + size += (numSeqN * (sizeof(HoFNestedSequence) + 14)); for (int i = 0; i < numSeqN; i++) { stream.seek(offset, SEEK_SET); offset += 2; @@ -559,8 +560,8 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi tmp_n[i].x = stream.readUint16BE(); tmp_n[i].y = stream.readUint16BE(); uint16 ctrlOffs = stream.readUint16BE(); - tmp_n[i].startupCommand = stream.readUint16BE(); - tmp_n[i].finalCommand = stream.readUint16BE(); + tmp_n[i].fadeInTransitionType = stream.readUint16BE(); + tmp_n[i].fadeOutTransitionType = stream.readUint16BE(); if (ctrlOffs) { stream.seek(ctrlOffs, SEEK_SET); @@ -580,21 +581,21 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi } } - HofSeqData *loadTo = new HofSeqData; + HoFSeqData *loadTo = new HoFSeqData; assert(loadTo); loadTo->seq = tmp_s; - loadTo->seqn = tmp_n; + loadTo->nestedSeq = tmp_n; loadTo->numSeq = numSeq; - loadTo->numSeqn = numSeqN; + loadTo->numNestedSeq = numSeqN; ptr = loadTo; return true; } -bool StaticResource::loadShapeAnimData_v1(Common::SeekableReadStream &stream, void *&ptr, int &size) { +bool StaticResource::loadHoFSeqItemAnimData(Common::SeekableReadStream &stream, void *&ptr, int &size) { size = stream.readByte(); - ItemAnimData_v1 *loadTo = new ItemAnimData_v1[size]; + HoFSeqItemAnimData *loadTo = new HoFSeqItemAnimData[size]; assert(loadTo); for (int i = 0; i < size; i++) { @@ -670,8 +671,8 @@ void StaticResource::freeRoomTable(void *&ptr, int &size) { size = 0; } -void StaticResource::freeHofSequenceData(void *&ptr, int &size) { - HofSeqData *h = (HofSeqData *)ptr; +void StaticResource::freeHoFSequenceData(void *&ptr, int &size) { + HoFSeqData *h = (HoFSeqData *)ptr; for (int i = 0; i < h->numSeq; i++) { delete[] h->seq[i].wsaFile; @@ -679,19 +680,19 @@ void StaticResource::freeHofSequenceData(void *&ptr, int &size) { } delete[] h->seq; - for (int i = 0; i < h->numSeqn; i++) { - delete[] h->seqn[i].wsaFile; - delete[] h->seqn[i].wsaControl; + for (int i = 0; i < h->numNestedSeq; i++) { + delete[] h->nestedSeq[i].wsaFile; + delete[] h->nestedSeq[i].wsaControl; } - delete[] h->seqn; + delete[] h->nestedSeq; delete h; ptr = 0; size = 0; } -void StaticResource::freeHofShapeAnimDataV1(void *&ptr, int &size) { - ItemAnimData_v1 *d = (ItemAnimData_v1 *)ptr; +void StaticResource::freeHoFSeqItemAnimData(void *&ptr, int &size) { + HoFSeqItemAnimData *d = (HoFSeqItemAnimData *)ptr; for (int i = 0; i < size; i++) delete[] d[i].frames; delete[] d; @@ -777,22 +778,6 @@ void KyraEngine_LoK::initStaticResource() { _storyStrings = _staticres->loadStrings(k1PC98StoryStrings, _storyStringsSize); - int size1, size2; - const char *const *soundfiles1 = _staticres->loadStrings(k1AudioTracks, size1); - const char *const *soundfiles2 = _staticres->loadStrings(k1AudioTracks2, size2); - _soundFilesSize = size1 + size2; - if (_soundFilesSize) { - delete[] _soundFiles; - const char **soundfiles = new const char*[_soundFilesSize]; - for (int i = 0; i < _soundFilesSize; i++) - soundfiles[i] = (i < size1) ? soundfiles1[i] : soundfiles2[i - size1]; - _soundFiles = soundfiles; - } - _soundFilesIntro = _staticres->loadStrings(k1AudioTracksIntro, _soundFilesIntroSize); - _cdaTrackTable = (const int32 *)_staticres->loadRawData(k1TownsCDATable, _cdaTrackTableSize); - - // copied static res - // room list const Room *tempRoomList = _staticres->loadRoomTable(k1RoomList, _roomTableSize); @@ -819,34 +804,40 @@ void KyraEngine_LoK::initStaticResource() { _staticres->unloadId(k1DefaultShapes); } - // audio data tables - static const char *const tIntro98[] = { "INTRO%d.DAT" }; - static const char *const tIngame98[] = { "KYRAM%d.DAT" }; + // audio resource assignment + int size1, size2; + const char *const *soundfiles1 = _staticres->loadStrings(k1AudioTracks, size1); + const char *const *soundfiles2 = _staticres->loadStrings(k1AudioTracks2, size2); + int soundFilesSize = size1 + size2; + int soundFilesIntroSize = 0; + int cdaTableSize = 0; + const char **soundFiles = 0; + + if (soundFilesSize) { + soundFiles = new const char*[soundFilesSize]; + for (int i = 0; i < soundFilesSize; i++) + soundFiles[i] = (i < size1) ? soundfiles1[i] : soundfiles2[i - size1]; + } + const char *const *soundFilesIntro = _staticres->loadStrings(k1AudioTracksIntro, temp); + const int32 *cdaTable = (const int32 *)_staticres->loadRawData(k1TownsCDATable, cdaTableSize); // FIXME: It seems Kyra1 MAC CD includes AdLib and MIDI music and sfx, thus we enable // support for those for now. (Based on patch #2767489 "Support for Mac Kyrandia 1 CD" by satz). - memset(_soundData, 0, sizeof(_soundData)); if (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformMacintosh) { - _soundData[0].fileList = _soundFilesIntro; - _soundData[0].fileListLen = _soundFilesIntroSize; - _soundData[1].fileList = _soundFiles; - _soundData[1].fileListLen = _soundFilesSize; + SoundResourceInfo_PC resInfoIntro(soundFilesIntro, soundFilesIntroSize); + SoundResourceInfo_PC resInfoIngame(soundFiles, soundFilesSize); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); } else if (_flags.platform == Common::kPlatformFMTowns) { - _soundData[0].fileList = _soundFiles; - _soundData[0].fileListLen = _soundFilesSize; - _soundData[0].cdaTracks = _cdaTrackTable; - _soundData[0].cdaNumTracks = _cdaTrackTableSize; - _soundData[1].fileList = _soundFiles; - _soundData[1].fileListLen = _soundFilesSize; - _soundData[1].cdaTracks = _cdaTrackTable; - _soundData[1].cdaNumTracks = _cdaTrackTableSize; + SoundResourceInfo_Towns resInfoIntro(soundFiles, soundFilesSize, cdaTable, cdaTableSize); + SoundResourceInfo_Towns resInfoIngame(soundFiles, soundFilesSize, cdaTable, cdaTableSize); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); } else if (_flags.platform == Common::kPlatformPC98) { - _soundData[0].fileList = tIntro98; - _soundData[0].fileListLen = 1; - _soundData[0].extraOffset = -1; - _soundData[1].fileList = tIngame98; - _soundData[1].fileListLen = 1; - _soundData[1].extraOffset = -1; + SoundResourceInfo_PC98 resInfoIntro("INTRO%d.DAT"); + SoundResourceInfo_PC98 resInfoIngame("KYRAM%d.DAT"); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); } } @@ -992,11 +983,7 @@ void KyraEngine_LoK::loadMainScreen(int page) { } void KyraEngine_HoF::initStaticResource() { - int tmpSize = 0; - - _sequencePakList = _staticres->loadStrings(k2SeqplayPakFiles, _sequencePakListSize); _ingamePakList = _staticres->loadStrings(k2IngamePakFiles, _ingamePakListSize); - _sequenceStrings = _staticres->loadStrings(k2SeqplayStrings, _sequenceStringsSize); _ingameSoundList = _staticres->loadStrings(k2IngameSfxFiles, _ingameSoundListSize); _ingameSoundIndex = (const uint16 *)_staticres->loadRawData(k2IngameSfxIndex, _ingameSoundIndexSize); _musicFileListIntro = _staticres->loadStrings(k2SeqplayIntroTracks, _musicFileListIntroSize); @@ -1009,131 +996,29 @@ void KyraEngine_HoF::initStaticResource() { _ingameTimJpStr = _staticres->loadStrings(k2IngameTimJpStrings, _ingameTimJpStrSize); _itemAnimDefinition = _staticres->loadItemAnimDefinition(k2IngameShapeAnimData, _itemAnimDefinitionSize); - // replace sequence talkie files with localized versions - const char *const *seqSoundList = _staticres->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); - const char *const *tlkfiles = _staticres->loadStrings(k2SeqplayTlkFiles, tmpSize); - char **tmpSndLst = new char *[_sequenceSoundListSize]; - - for (int i = 0; i < _sequenceSoundListSize; i++) { - const int len = strlen(seqSoundList[i]); - - tmpSndLst[i] = new char[len + 1]; - tmpSndLst[i][0] = 0; - - if (tlkfiles && len > 1) { - for (int ii = 0; ii < tmpSize; ii++) { - if (strlen(tlkfiles[ii]) > 1 && !scumm_stricmp(&seqSoundList[i][1], &tlkfiles[ii][1])) - strcpy(tmpSndLst[i], tlkfiles[ii]); - } - } - - if (tmpSndLst[i][0] == 0) - strcpy(tmpSndLst[i], seqSoundList[i]); - } - - tlkfiles = seqSoundList = 0; - _staticres->unloadId(k2SeqplayTlkFiles); - _staticres->unloadId(k2SeqplaySfxFiles); - _sequenceSoundList = tmpSndLst; - // assign music data - static const char *const fmtMusicFileListIntro[] = { "intro%d.twn" }; - static const char *const fmtMusicFileListFinale[] = { "finale%d.twn" }; - static const char *const fmtMusicFileListIngame[] = { "km%02d.twn" }; - - static const char *const pc98MusicFileListIntro[] = { "intro%d.86" }; - static const char *const pc98MusicFileListFinale[] = { "finale%d.86" }; - static const char *const pc98MusicFileListIngame[] = { "km%02d.86" }; - - memset(_soundData, 0, sizeof(_soundData)); if (_flags.platform == Common::kPlatformPC) { - _soundData[0].fileList = _musicFileListIntro; - _soundData[0].fileListLen = _musicFileListIntroSize; - _soundData[1].fileList = _musicFileListIngame; - _soundData[1].fileListLen = _musicFileListIngameSize; - _soundData[2].fileList = _musicFileListFinale; - _soundData[2].fileListLen = _musicFileListIntroSize; + SoundResourceInfo_PC resInfoIntro(_musicFileListIntro, _musicFileListIntroSize); + SoundResourceInfo_PC resInfoIngame(_musicFileListIngame, _musicFileListIngameSize); + SoundResourceInfo_PC resInfoFinale(_musicFileListFinale, _musicFileListFinaleSize); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); + _sound->initAudioResourceInfo(kMusicFinale, &resInfoFinale); } else if (_flags.platform == Common::kPlatformFMTowns) { - _soundData[0].fileList = fmtMusicFileListIntro; - _soundData[0].fileListLen = 1; - _soundData[0].cdaTracks = _cdaTrackTableIntro; - _soundData[0].cdaNumTracks = _cdaTrackTableIntroSize >> 1; - _soundData[1].fileList = fmtMusicFileListIngame; - _soundData[1].fileListLen = 1; - _soundData[1].cdaTracks = _cdaTrackTableIngame; - _soundData[1].cdaNumTracks = _cdaTrackTableIngameSize >> 1; - _soundData[2].fileList = fmtMusicFileListFinale; - _soundData[2].fileListLen = 1; - _soundData[2].cdaTracks = _cdaTrackTableFinale; - _soundData[2].cdaNumTracks = _cdaTrackTableFinaleSize >> 1; + SoundResourceInfo_TownsPC98V2 resInfoIntro(0, 0, "intro%d.twn", (const uint16*)_cdaTrackTableIntro, _cdaTrackTableIntroSize >> 1); + SoundResourceInfo_TownsPC98V2 resInfoIngame(0, 0, "km%02d.twn", (const uint16*)_cdaTrackTableIngame, _cdaTrackTableIngameSize >> 1); + SoundResourceInfo_TownsPC98V2 resInfoFinale(0, 0, "finale%d.twn", (const uint16*)_cdaTrackTableFinale, _cdaTrackTableFinaleSize >> 1); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); + _sound->initAudioResourceInfo(kMusicFinale, &resInfoFinale); } else if (_flags.platform == Common::kPlatformPC98) { - _soundData[0].fileList = pc98MusicFileListIntro; - _soundData[0].fileListLen = 1; - _soundData[1].fileList = pc98MusicFileListIngame; - _soundData[1].fileListLen = 1; - _soundData[2].fileList = pc98MusicFileListFinale; - _soundData[2].fileListLen = 1; + SoundResourceInfo_TownsPC98V2 resInfoIntro(0, 0, "intro%d.86", 0, 0); + SoundResourceInfo_TownsPC98V2 resInfoIngame(0, 0, "km%02d.86", 0, 0); + SoundResourceInfo_TownsPC98V2 resInfoFinale(0, 0, "finale%d.86", 0, 0); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); + _sound->initAudioResourceInfo(kMusicFinale, &resInfoFinale); } - - // setup sequence data - _sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize); - - static const SeqProc hofSequenceCallbacks[] = { - 0, &KyraEngine_HoF::seq_introWestwood, - &KyraEngine_HoF::seq_introTitle, &KyraEngine_HoF::seq_introOverview, - &KyraEngine_HoF::seq_introLibrary, &KyraEngine_HoF::seq_introHand, - &KyraEngine_HoF::seq_introPoint, &KyraEngine_HoF::seq_introZanfaun, - &KyraEngine_HoF::seq_finaleFunters, &KyraEngine_HoF::seq_finaleFerb, - &KyraEngine_HoF::seq_finaleFish, &KyraEngine_HoF::seq_finaleFheep, - &KyraEngine_HoF::seq_finaleFarmer, &KyraEngine_HoF::seq_finaleFuards, - &KyraEngine_HoF::seq_finaleFirates, &KyraEngine_HoF::seq_finaleFrash - }; - - static const SeqProc hofNestedSequenceCallbacks[] = { - &KyraEngine_HoF::seq_finaleFiggle, &KyraEngine_HoF::seq_introOver1, - &KyraEngine_HoF::seq_introOver2, &KyraEngine_HoF::seq_introForest, - &KyraEngine_HoF::seq_introDragon, &KyraEngine_HoF::seq_introDarm, - &KyraEngine_HoF::seq_introLibrary2, &KyraEngine_HoF::seq_introLibrary2, - &KyraEngine_HoF::seq_introMarco, &KyraEngine_HoF::seq_introHand1a, - &KyraEngine_HoF::seq_introHand1b, &KyraEngine_HoF::seq_introHand1c, - &KyraEngine_HoF::seq_introHand2, &KyraEngine_HoF::seq_introHand3, 0 - }; - - static const SeqProc hofDemoSequenceCallbacks[] = { - &KyraEngine_HoF::seq_demoVirgin, &KyraEngine_HoF::seq_demoWestwood, - &KyraEngine_HoF::seq_demoTitle, &KyraEngine_HoF::seq_demoHill, - &KyraEngine_HoF::seq_demoOuthome, &KyraEngine_HoF::seq_demoWharf, - &KyraEngine_HoF::seq_demoDinob, &KyraEngine_HoF::seq_demoFisher, 0 - }; - - static const SeqProc hofDemoNestedSequenceCallbacks[] = { - &KyraEngine_HoF::seq_demoWharf2, &KyraEngine_HoF::seq_demoDinob2, - &KyraEngine_HoF::seq_demoWater, &KyraEngine_HoF::seq_demoBail, - &KyraEngine_HoF::seq_demoDig, 0 - }; - -#ifdef ENABLE_LOL - static const SeqProc kLoLDemoSequenceCallbacks[] = { - &KyraEngine_HoF::seq_lolDemoScene1, 0, &KyraEngine_HoF::seq_lolDemoScene2, 0, - &KyraEngine_HoF::seq_lolDemoScene3, 0, &KyraEngine_HoF::seq_lolDemoScene4, 0, - &KyraEngine_HoF::seq_lolDemoScene5, &KyraEngine_HoF::seq_lolDemoText5, - &KyraEngine_HoF::seq_lolDemoScene6, 0 - }; - - static const SeqProc kLoLDemoNestedSequenceCallbacks[] = { 0 }; -#endif // ENABLE_LOL - - _callbackS = -#ifdef ENABLE_LOL - _flags.gameID == GI_LOL ? kLoLDemoSequenceCallbacks : -#endif // ENABLE_LOL - ((_flags.isDemo && !_flags.isTalkie) ? hofDemoSequenceCallbacks : hofSequenceCallbacks); - - _callbackN = -#ifdef ENABLE_LOL - _flags.gameID == GI_LOL ? kLoLDemoNestedSequenceCallbacks : -#endif // ENABLE_LOL - ((_flags.isDemo && !_flags.isTalkie) ? hofDemoNestedSequenceCallbacks : hofNestedSequenceCallbacks); } void KyraEngine_MR::initStaticResource() { @@ -1224,13 +1109,13 @@ const uint8 KyraEngine_LoK::_itemPosY[] = { }; void GUI_LoK::initStaticResource() { - GUI_V1_BUTTON(_scrollUpButton, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0x18, 0x0f, 0); - GUI_V1_BUTTON(_scrollDownButton, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0x18, 0x0f, 0); + GUI_V1_BUTTON(_scrollUpButton, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0x18, 0x0F, 0); + GUI_V1_BUTTON(_scrollDownButton, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0x18, 0x0F, 0); - GUI_V1_BUTTON(_menuButtonData[0], 0x0c, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); - GUI_V1_BUTTON(_menuButtonData[1], 0x0d, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); - GUI_V1_BUTTON(_menuButtonData[2], 0x0e, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); - GUI_V1_BUTTON(_menuButtonData[3], 0x0f, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); + GUI_V1_BUTTON(_menuButtonData[0], 0x0C, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); + GUI_V1_BUTTON(_menuButtonData[1], 0x0D, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); + GUI_V1_BUTTON(_menuButtonData[2], 0x0E, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); + GUI_V1_BUTTON(_menuButtonData[3], 0x0F, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); GUI_V1_BUTTON(_menuButtonData[4], 0x10, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); GUI_V1_BUTTON(_menuButtonData[5], 0x11, 1, 1, 1, 0x487, 0, 0, 0, 0, 0, 0); @@ -1412,8 +1297,6 @@ const int GUI_v2::_sliderBarsPosition[] = { // kyra 2 static res -const uint8 KyraEngine_HoF::_seqTextColorPresets[] = { 0x01, 0x01, 0x00, 0x3f, 0x3f, 0x3f }; - const char *const KyraEngine_HoF::_languageExtension[] = { "ENG", "FRE", @@ -1631,7 +1514,7 @@ void KyraEngine_HoF::initInventoryButtonList() { _inventoryButtons[i].buttonCallback = inventoryCallback; _buttonList = &_inventoryButtons[0]; - for (size_t i = 1; i < 15; ++i) + for (int i = 1; i < 15; ++i) _buttonList = _gui->addButtonToList(_buttonList, &_inventoryButtons[i]); } diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index 7a5012f117..e0a2862dea 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -220,44 +220,44 @@ const uint8 EoBCoreEngine::_wallOfForceShapeDefs[] = { 0x0C, 0x00, 0x05, 0x10 }; -const int16 EoBCoreEngine::_buttonList1[] = { +const uint8 EoBCoreEngine::_buttonList1[] = { 58, 0, 1, 2, 3, 90, 91, 4, 5, 6, 7, 8, 9, 10, 11, 12, 78, 79, 13, 14, 15, 16, - 80, 81, 17, 18, 19, 20, 82, 83, 49, 50, 51, 52, 53, 54, 56, 57, -1 + 80, 81, 17, 18, 19, 20, 82, 83, 49, 50, 51, 52, 53, 54, 56, 57, 255 }; -const int16 EoBCoreEngine::_buttonList2[] = { +const uint8 EoBCoreEngine::_buttonList2[] = { 58, 61, 62, 63, 64, 65, 93, 94, 66, 67, 68, 69, 70, 71, 76, 77, 88, 0, 1, 2, 3, 90, 91, 4, 5, 6, 7, 8, 9, 10, 11, 12, 78, 79, 13, 14, 15, 16, 80, 81, 17, 18, - 19, 20, 82, 83, 49, 50, 51, 52, 53, 54, 56, 57, -1 + 19, 20, 82, 83, 49, 50, 51, 52, 53, 54, 56, 57, 255 }; -const int16 EoBCoreEngine::_buttonList3[] = { +const uint8 EoBCoreEngine::_buttonList3[] = { 58, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 84, 85, 46, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, - 51, 52, 53, 54, 56, 57, -1 + 51, 52, 53, 54, 56, 57, 255 }; -const int16 EoBCoreEngine::_buttonList4[] = { - 58, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, -1 +const uint8 EoBCoreEngine::_buttonList4[] = { + 58, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, 255 }; -const int16 EoBCoreEngine::_buttonList5[] = { +const uint8 EoBCoreEngine::_buttonList5[] = { 58, 61, 62, 63, 64, 65, 93, 66, 67, 68, 69, 70, 71, 88, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 84, - 85, 46, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, -1 + 85, 46, 47, 48, 60, 59, 92, 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, 255 }; -const int16 EoBCoreEngine::_buttonList6[] = { +const uint8 EoBCoreEngine::_buttonList6[] = { 58, 61, 62, 63, 64, 65, 93, 66, 67, 68, 69, 70, 71, 88, 46, 47, 48, 60, 59, 92, - 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, -1 + 4, 5, 6, 7, 8, 49, 50, 51, 52, 53, 54, 56, 57, 255 }; -const int16 EoBCoreEngine::_buttonList7[] = { - 17, 18, 19, 20, 82, 83, 55, -1 +const uint8 EoBCoreEngine::_buttonList7[] = { + 17, 18, 19, 20, 82, 83, 55, 255 }; -const int16 EoBCoreEngine::_buttonList8[] = { - 72, 73, 74, 75, 86, 87, 89, -1 +const uint8 EoBCoreEngine::_buttonList8[] = { + 72, 73, 74, 75, 86, 87, 89, 255 }; const uint8 EoBCoreEngine::_clock2Timers[] = { @@ -465,13 +465,13 @@ void EoBCoreEngine::initStaticResource() { // EOB I doesn't have load and save menus, because there is only one single // save slot. Instead of emulating this we provide a menu similiar to EOB II. - static const char *saveLoadStrings[3][4] = { + static const char *const saveLoadStrings[3][4] = { { "Cancel", "Empty Slot", "Save Game", "Load Game" }, { "Abbr.", "Leerer Slot", "Speichern", " Laden" }, { 0, 0, 0, 0 } }; - static const char *errorSlotEmptyString[3] = { + static const char *const errorSlotEmptyString[3] = { "There is no game\rsaved in that slot!", "Hier ist noch kein\rSpiel gespeichert!", 0 @@ -1096,7 +1096,7 @@ void EoBEngine::initStaticResource() { p->dmgModifierEvade = *ps++; } - static const char *errorSlotNoNameString[3] = { + static const char *const errorSlotNoNameString[3] = { " You must specify\r a name for your\r save game!", " Spielstaende mues-\r sen einen Namen\r haben!", 0 @@ -1118,10 +1118,10 @@ void EoBEngine::initSpells() { { 0x0000, 0x000000, 0x00 }, // dummy { 0x0033, 0x000001, 0x00 }, // armor { 0x0100, 0x000000, 0x21 }, // burning hands - { 0x004c, 0x000002, 0x00 }, // detect magic + { 0x004C, 0x000002, 0x00 }, // detect magic { 0x0100, 0x000000, 0x01 }, // magic missile { 0x0000, 0x000000, 0x00 }, // dummy - { 0x008b, 0x000008, 0x00 }, // shield + { 0x008B, 0x000008, 0x00 }, // shield { 0x0488, 0x000000, 0x03 }, // shocking grasp { 0x0021, 0x000040, 0x00 }, // invisibility { 0x0000, 0x000000, 0x00 }, // dummy @@ -1141,10 +1141,10 @@ void EoBEngine::initSpells() { { 0x0000, 0x000000, 0x00 }, // CLOUD KILL { 0x0100, 0x000000, 0x41 }, // cone of cold { 0x0100, 0x000000, 0x00 }, // hold monster - { 0x005c, 0x000400, 0x00 }, // bless + { 0x005C, 0x000400, 0x00 }, // bless { 0x0020, 0x000000, 0x00 }, // cure light wounds { 0x0100, 0x000000, 0x01 }, // cause light wounds - { 0x004c, 0x000002, 0x00 }, // detect magic + { 0x004C, 0x000002, 0x00 }, // detect magic { 0x0029, 0x000800, 0x00 }, // prot from evil { 0x0039, 0x000000, 0x00 }, // aid { 0x2408, 0x000000, 0x21 }, // flame blade @@ -1153,7 +1153,7 @@ void EoBEngine::initSpells() { { 0x0040, 0x000000, 0x00 }, // create food { 0x1000, 0x000000, 0x00 }, // dispel magic { 0x0099, 0x004000, 0x00 }, // magical vestment - { 0x004c, 0x008000, 0x00 }, // prayer + { 0x004C, 0x008000, 0x00 }, // prayer { 0x0040, 0x000000, 0x00 }, // remove paralysis { 0x0020, 0x000000, 0x00 }, // cure serious { 0x0100, 0x000000, 0x01 }, // cause serious @@ -1187,7 +1187,7 @@ void EoBEngine::initSpells() { const KyraRpgGUISettings EoBEngine::_guiSettingsVGA = { { 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } }, - { 135, 130, 132, 133, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180 } + { 135, 130, 132, 133, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180 } }; const KyraRpgGUISettings EoBEngine::_guiSettingsEGA = { @@ -1210,7 +1210,7 @@ void DarkMoonEngine::initStaticResource() { _animIntro[i] = _staticres->loadEoB2SeqData(kEob2IntroAnimData00 + i, temp); _shapesIntro = new const DarkMoonShapeDef*[13]; - memset(_shapesIntro, 0, sizeof(DarkMoonShapeDef*) * 13); + memset(_shapesIntro, 0, sizeof(DarkMoonShapeDef *) * 13); _shapesIntro[0] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes00, temp); _shapesIntro[1] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes01, temp); _shapesIntro[4] = _staticres->loadEoB2ShapeData(kEoB2IntroShapes04, temp); @@ -1225,7 +1225,7 @@ void DarkMoonEngine::initStaticResource() { _animFinale[i] = _staticres->loadEoB2SeqData(kEob2FinaleAnimData00 + i, temp); _shapesFinale = new const DarkMoonShapeDef*[13]; - memset(_shapesFinale, 0, sizeof(DarkMoonShapeDef*) * 13); + memset(_shapesFinale, 0, sizeof(DarkMoonShapeDef *) * 13); _shapesFinale[0] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes00, temp); _shapesFinale[3] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes03, temp); _shapesFinale[7] = _staticres->loadEoB2ShapeData(kEoB2FinaleShapes07, temp); @@ -1249,7 +1249,7 @@ void DarkMoonEngine::initStaticResource() { _wallOfForceDsNumH = _staticres->loadRawData(kEoB2WallOfForceNumH, temp); _wallOfForceShpId = _staticres->loadRawData(kEoB2WallOfForceShpId, temp); - static const char *errorSlotNoNameString[3] = { + static const char *const errorSlotNoNameString[3] = { " You must specify\r a name for your\r save game!", " Spielst[nde m]ssen\r einen Namen haben!", 0 @@ -1258,7 +1258,7 @@ void DarkMoonEngine::initStaticResource() { _errorSlotNoNameString = errorSlotNoNameString[(_flags.lang == Common::EN_ANY) ? 0 : ((_flags.lang == Common::DE_DEU) ? 1 : 2)]; // ScummVM specific - static const char *transferStringsScummVM[3][5] = { + static const char *const transferStringsScummVM[3][5] = { { "\r We cannot find any EOB save game\r file. Please make sure that the\r save game file with the party\r you wish to transfer is located\r in your ScummVM save game\r directory. If you have set up\r multiple save directories you\r have to copy the EOB save file\r into your EOB II save directory.\r Do you wish to try again?", "Game ID", @@ -1300,7 +1300,7 @@ void DarkMoonEngine::initSpells() { } } -const char *DarkMoonEngine::_palFilesIntroVGA[] = { +const char *const DarkMoonEngine::_palFilesIntroVGA[] = { "PALETTE1.PAL", "PALETTE3.PAL", "PALETTE2.PAL", @@ -1308,7 +1308,7 @@ const char *DarkMoonEngine::_palFilesIntroVGA[] = { 0 }; -const char *DarkMoonEngine::_palFilesIntroEGA[] = { +const char *const DarkMoonEngine::_palFilesIntroEGA[] = { "PALETTE0.PAL", "PALETTE3.PAL", "PALETTE2.PAL", @@ -1316,7 +1316,7 @@ const char *DarkMoonEngine::_palFilesIntroEGA[] = { 0 }; -const char *DarkMoonEngine::_palFilesFinaleVGA[] = { +const char *const DarkMoonEngine::_palFilesFinaleVGA[] = { "FINALE_0.PAL", "FINALE_0.PAL", "FINALE_1.PAL", @@ -1329,7 +1329,7 @@ const char *DarkMoonEngine::_palFilesFinaleVGA[] = { 0 }; -const char *DarkMoonEngine::_palFilesFinaleEGA[] = { +const char *const DarkMoonEngine::_palFilesFinaleEGA[] = { "FINALE_0.PAL", "FINALE_0.PAL", "FINALE_1.PAL", diff --git a/engines/kyra/staticres_lol.cpp b/engines/kyra/staticres_lol.cpp index 63bc7fa99b..a1c5ff340c 100644 --- a/engines/kyra/staticres_lol.cpp +++ b/engines/kyra/staticres_lol.cpp @@ -24,6 +24,7 @@ #include "kyra/lol.h" #include "kyra/screen_lol.h" #include "kyra/gui_lol.h" +#include "kyra/sound_intern.h" #ifdef ENABLE_LOL @@ -213,30 +214,39 @@ void StaticResource::freeButtonDefs(void *&ptr, int &size) { } void LoLEngine::initStaticResource() { - // assign music data - static const char *const pcMusicFileListIntro[] = { "LOREINTR" }; - static const char *const pcMusicFileListFinale[] = { "LOREFINL" }; - static const char *const pcMusicFileListIngame[] = { "LORE%02d%c" }; - - static const char *const pc98MusicFileListIntro[] = { 0, "lore84.86", "lore82.86", 0, 0, 0, "lore83.86", "lore81.86" }; - static const char *const pc98MusicFileListFinale[] = { 0, 0, "lore85.86", "lore86.86", "lore87.86" }; - static const char *const pc98MusicFileListIngame[] = { "lore%02d.86" }; - - memset(_soundData, 0, sizeof(_soundData)); + // assign music resource data. if (_flags.platform == Common::kPlatformPC) { - _soundData[0].fileList = pcMusicFileListIntro; - _soundData[0].fileListLen = ARRAYSIZE(pcMusicFileListIntro); - _soundData[1].fileList = pcMusicFileListIngame; - _soundData[1].fileListLen = ARRAYSIZE(pcMusicFileListIngame); - _soundData[2].fileList = pcMusicFileListFinale; - _soundData[2].fileListLen = ARRAYSIZE(pcMusicFileListFinale); + if (_flags.isDemo) { + static const char *const file[] = { "LOREDEMO" }; + SoundResourceInfo_PC resInfoDemo(file, ARRAYSIZE(file)); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoDemo); + } else { + static const char *const intro[] = { "LOREINTR" }; + static const char *const finale[] = { "LOREFINL" }; + SoundResourceInfo_PC resInfoIntro(intro, ARRAYSIZE(intro)); + SoundResourceInfo_PC resInfoFinale(finale, ARRAYSIZE(finale)); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + // In game music file handling is different, thus does not need a file list. + _sound->initAudioResourceInfo(kMusicFinale, &resInfoFinale); + } } else if (_flags.platform == Common::kPlatformPC98) { - _soundData[0].fileList = pc98MusicFileListIntro; - _soundData[0].fileListLen = ARRAYSIZE(pc98MusicFileListIntro); - _soundData[1].fileList = pc98MusicFileListIngame; - _soundData[1].fileListLen = ARRAYSIZE(pc98MusicFileListIngame); - _soundData[2].fileList = pc98MusicFileListFinale; - _soundData[2].fileListLen = ARRAYSIZE(pc98MusicFileListFinale); + static const char *const fileListIntro[] = { 0, "lore84.86", "lore82.86", 0, 0, 0, "lore83.86", "lore81.86" }; + static const char *const fileListFinale[] = { 0, 0, "lore85.86", "lore86.86", "lore87.86" }; + SoundResourceInfo_TownsPC98V2 resInfoIntro(fileListIntro, ARRAYSIZE(fileListIntro), 0, 0, 0); + SoundResourceInfo_TownsPC98V2 resInfoIngame(0, 0, "lore%02d.86", 0, 0); + SoundResourceInfo_TownsPC98V2 resInfoFinale(fileListFinale, ARRAYSIZE(fileListFinale), 0, 0, 0); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); + _sound->initAudioResourceInfo(kMusicFinale, &resInfoFinale); + } else if (_flags.platform == Common::kPlatformFMTowns) { + static const char *const fileListIntro[] = { 0, "lore84.twn", "lore82.twn", 0, 0, 0, "lore83.twn", "lore81.twn" }; + static const char *const fileListFinale[] = { 0, 0, "lore85.twn", "lore86.twn", "lore87.twn" }; + SoundResourceInfo_TownsPC98V2 resInfoIntro(fileListIntro, ARRAYSIZE(fileListIntro), 0, 0, 0); + SoundResourceInfo_TownsPC98V2 resInfoIngame(0, 0, "lore%02d.twn", 0, 0); + SoundResourceInfo_TownsPC98V2 resInfoFinale(fileListFinale, ARRAYSIZE(fileListFinale), 0, 0, 0); + _sound->initAudioResourceInfo(kMusicIntro, &resInfoIntro); + _sound->initAudioResourceInfo(kMusicIngame, &resInfoIngame); + _sound->initAudioResourceInfo(kMusicFinale, &resInfoFinale); } if (_flags.isDemo) @@ -260,7 +270,10 @@ void LoLEngine::initStaticResource() { _charDefsKieran = _staticres->loadRawDataBe16(kLoLCharDefsKieran, tempSize); _charDefsAkshel = _staticres->loadRawDataBe16(kLoLCharDefsAkshel, tempSize); _expRequirements = (const int32 *)_staticres->loadRawDataBe32(kLoLExpRequirements, tempSize); - _monsterModifiers = _staticres->loadRawDataBe16(kLoLMonsterModifiers, tempSize); + _monsterModifiers1 = _staticres->loadRawDataBe16(kLoLMonsterModifiers1, tempSize); + _monsterModifiers2 = _staticres->loadRawDataBe16(kLoLMonsterModifiers2, tempSize); + _monsterModifiers3 = _staticres->loadRawDataBe16(kLoLMonsterModifiers3, tempSize); + _monsterModifiers4 = _staticres->loadRawDataBe16(kLoLMonsterModifiers4, tempSize); _monsterShiftOffs = (const int8 *)_staticres->loadRawData(kLoLMonsterShiftOffsets, tempSize); _monsterDirFlags = _staticres->loadRawData(kLoLMonsterDirFlags, tempSize); _monsterScaleX = _staticres->loadRawData(kLoLMonsterScaleX, tempSize); @@ -303,14 +316,14 @@ void LoLEngine::initStaticResource() { } _buttonData = _staticres->loadButtonDefs(kLoLButtonDefs, tempSize); - _buttonList1 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList1, tempSize); - _buttonList2 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList2, tempSize); - _buttonList3 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList3, tempSize); - _buttonList4 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList4, tempSize); - _buttonList5 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList5, tempSize); - _buttonList6 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList6, tempSize); - _buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList7, tempSize); - _buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLoLButtonList8, tempSize); + _buttonList1 = _staticres->loadRawData(kLoLButtonList1, tempSize); + _buttonList2 = _staticres->loadRawData(kLoLButtonList2, tempSize); + _buttonList3 = _staticres->loadRawData(kLoLButtonList3, tempSize); + _buttonList4 = _staticres->loadRawData(kLoLButtonList4, tempSize); + _buttonList5 = _staticres->loadRawData(kLoLButtonList5, tempSize); + _buttonList6 = _staticres->loadRawData(kLoLButtonList6, tempSize); + _buttonList7 = _staticres->loadRawData(kLoLButtonList7, tempSize); + _buttonList8 = _staticres->loadRawData(kLoLButtonList8, tempSize); _autoMapStrings = _staticres->loadRawDataBe16(kLoLMapStringId, tempSize); @@ -457,11 +470,11 @@ void LoLEngine::initStaticResource() { } void GUI_LoL::initStaticData() { - GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); - GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + GUI_V2_BUTTON(_scrollUpButton, 20, 96, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0); + GUI_V2_BUTTON(_scrollDownButton, 21, 98, 0, 1, 1, 1, 0x4487, 0, 0, 0, 25, 16, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0); for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) - GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0); + GUI_V2_BUTTON(_menuButtons[i], i, 0, 0, 0, 0, 0, 0x4487, 0, 0, 0, 0, 0, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0); if (_vm->gameFlags().isTalkie) GUI_LOL_MENU(_mainMenu, 9, 0x4000, 0, 7, -1, -1, -1, -1); @@ -486,61 +499,61 @@ void GUI_LoL::initStaticData() { for (int i = 0; i < _mainMenu.numberOfItems; ++i) _mainMenu.item[i].callback = mainMenuFunctor; - GUI_LOL_MENU(_loadMenu, 10, 0x400e, 1, 5, 128, 20, 128, 118); - GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU(_loadMenu, 10, 0x400E, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_loadMenu.item[0], 0xFFFE, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[1], 0xFFFD, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[2], 0xFFFC, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_loadMenu.item[3], 0xFFFB, 8, 90, 256, 15, 0, 0); GUI_LOL_MENU_ITEM(_loadMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]); Button::Callback loadMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedLoadMenu); for (int i = 0; i < 5; ++i) _loadMenu.item[i].callback = loadMenuFunctor; - GUI_LOL_MENU(_saveMenu, 10, 0x400d, 1, 5, 128, 20, 128, 118); - GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU(_saveMenu, 10, 0x400D, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_saveMenu.item[0], 0xFFFE, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[1], 0xFFFD, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[2], 0xFFFC, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_saveMenu.item[3], 0xFFFB, 8, 90, 256, 15, 0, 0); GUI_LOL_MENU_ITEM(_saveMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]); Button::Callback saveMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedSaveMenu); for (int i = 0; i < 5; ++i) _saveMenu.item[i].callback = saveMenuFunctor; - GUI_LOL_MENU(_deleteMenu, 10, 0x400f, 1, 5, 128, 20, 128, 118); - GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xfffe, 8, 39, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xfffd, 8, 56, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xfffc, 8, 73, 256, 15, 0, 0); - GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xfffb, 8, 90, 256, 15, 0, 0); + GUI_LOL_MENU(_deleteMenu, 10, 0x400F, 1, 5, 128, 20, 128, 118); + GUI_LOL_MENU_ITEM(_deleteMenu.item[0], 0xFFFE, 8, 39, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[1], 0xFFFD, 8, 56, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[2], 0xFFFC, 8, 73, 256, 15, 0, 0); + GUI_LOL_MENU_ITEM(_deleteMenu.item[3], 0xFFFB, 8, 90, 256, 15, 0, 0); GUI_LOL_MENU_ITEM(_deleteMenu.item[4], 0x4011, 168, 118, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]); Button::Callback deleteMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedDeleteMenu); for (int i = 0; i < 5; ++i) _deleteMenu.item[i].callback = deleteMenuFunctor; - GUI_LOL_MENU(_gameOptions, 17, 0x400c, 0, 6, -1, -1, -1, -1); + GUI_LOL_MENU(_gameOptions, 17, 0x400C, 0, 6, -1, -1, -1, -1); if (_vm->gameFlags().isTalkie) { - GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff7, 120, 22, 80, 15, 0x406e, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff6, 120, 39, 80, 15, 0x406c, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff5, 120, 56, 80, 15, 0x406d, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff4, 120, 73, 80, 15, 0x42d5, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff3, 120, 90, 80, 15, 0x42d2, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xFFF7, 120, 22, 80, 15, 0x406E, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xFFF6, 120, 39, 80, 15, 0x406C, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xFFF5, 120, 56, 80, 15, 0x406D, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xFFF4, 120, 73, 80, 15, 0x42D5, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xFFF3, 120, 90, 80, 15, 0x42D2, 0); GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]); } else { - GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xfff9, 120, 22, 80, 15, 0x406a, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xfff8, 120, 39, 80, 15, 0x406b, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xfff7, 120, 56, 80, 15, 0x406e, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xfff6, 120, 73, 80, 15, 0x406c, 0); - GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xfff5, 120, 90, 80, 15, 0x406d, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[0], 0xFFF9, 120, 22, 80, 15, 0x406A, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[1], 0xFFF8, 120, 39, 80, 15, 0x406B, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[2], 0xFFF7, 120, 56, 80, 15, 0x406E, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[3], 0xFFF6, 120, 73, 80, 15, 0x406C, 0); + GUI_LOL_MENU_ITEM(_gameOptions.item[4], 0xFFF5, 120, 90, 80, 15, 0x406D, 0); GUI_LOL_MENU_ITEM(_gameOptions.item[5], 0x4072, 104, 110, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]); } Button::Callback optionsMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedOptionsMenu); for (int i = 0; i < _gameOptions.numberOfItems; ++i) _gameOptions.item[i].callback = optionsMenuFunctor; - GUI_LOL_MENU(_audioOptions, 18, 0x42d9, 2, 1, -1, -1, -1, -1); + GUI_LOL_MENU(_audioOptions, 18, 0x42D9, 2, 1, -1, -1, -1, -1); GUI_LOL_MENU_ITEM(_audioOptions.item[0], 0x4072, 152, 76, 96, 15, 0, _vm->_keyMap[Common::KEYCODE_ESCAPE]); - GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42db, 0); - GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42da, 0); - GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42dc, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[1], 3, 128, 22, 114, 14, 0x42DB, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[2], 4, 128, 39, 114, 14, 0x42DA, 0); + GUI_LOL_MENU_ITEM(_audioOptions.item[3], 5, 128, 56, 114, 14, 0x42DC, 0); Button::Callback audioMenuFunctor = BUTTON_FUNCTOR(GUI_LoL, this, &GUI_LoL::clickedAudioMenu); for (int i = 0; i < 4; ++i) _audioOptions.item[i].callback = audioMenuFunctor; @@ -658,11 +671,11 @@ const uint16 LoLEngine::_charPosXPC98[] = { 92, 152, 212, 268 }; -const uint8 LoLEngine::_charNamesPC98[][11] = { - { 0x83, 0x41, 0x83, 0x4E, 0x83, 0x56, 0x83, 0x46, 0x83, 0x8B, 0x00 }, - { 0x83, 0x7D, 0x83, 0x43, 0x83, 0x50, 0x83, 0x8B, 0x00, 0x00, 0x00 }, - { 0x83, 0x4C, 0x81, 0x5B, 0x83, 0x89, 0x83, 0x93, 0x00, 0x00, 0x00 }, - { 0x83, 0x52, 0x83, 0x93, 0x83, 0x89, 0x83, 0x62, 0x83, 0x68, 0x00 } +const char *const LoLEngine::_charNamesJapanese[] = { + "\x83\x41\x83\x4E\x83\x56\x83\x46\x83\x8B\0", + "\x83\x7D\x83\x43\x83\x50\x83\x8B\x00\x00\0", + "\x83\x4C\x81\x5B\x83\x89\x83\x93\x00\x00\0", + "\x83\x52\x83\x93\x83\x89\x83\x62\x83\x68\0" }; const uint8 LoLEngine::_chargenFrameTableTalkie[] = { diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index 06067d6693..7fa823da0f 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -464,9 +464,9 @@ void KyraEngine_HoF::processDialogue(int dlgOffset, int vocH, int csEntry) { nextTimSequence = READ_LE_UINT16(&_ingameTalkObjIndex[cmd]); if (nextTimSequence == 10) { - if (queryGameFlag(0x3e)) + if (queryGameFlag(0x3E)) nextTimSequence = 14; - if (queryGameFlag(0x3f)) + if (queryGameFlag(0x3F)) nextTimSequence = 15; if (queryGameFlag(0x40)) nextTimSequence = 16; diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index ee42d6db92..6e77db1f8a 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -85,7 +85,7 @@ void TextDisplayer_LoL::setupField(bool mode) { _screen->copyBlockToPage(3, 0, 0, 320, 200, _vm->_pageBuffer1); _screen->setCurPage(cp); - _vm->_updateFlags &= 0xfffd; + _vm->_updateFlags &= 0xFFFD; } } else { if (!mode) @@ -136,18 +136,16 @@ void TextDisplayer_LoL::expandField() { void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) { int oldDim = 0; - const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98); - if (dim == 3) { if (_vm->_updateFlags & 2) { oldDim = clearDim(4); - _textDimData[4].color1 = isPc98 ? 0x33 : 254; + _textDimData[4].color1 = _vm->gameFlags().use16ColorMode ? 0x33 : 254; _textDimData[4].color2 = _screen->_curDim->unkA; } else { oldDim = clearDim(3); - _textDimData[3].color1 = isPc98 ? 0x33 : 192; + _textDimData[3].color1 = _vm->gameFlags().use16ColorMode ? 0x33 : 192; _textDimData[3].color2 = _screen->_curDim->unkA; - if (!isPc98) + if (!_vm->gameFlags().use16ColorMode) _screen->copyColor(192, 254); _vm->enableTimer(11); _vm->_textColorFlag = 0; @@ -157,12 +155,12 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, oldDim = _screen->curDimIndex(); _screen->setScreenDim(dim); _lineCount = 0; - _textDimData[dim].color1 = isPc98 ? 0x33 : 254; + _textDimData[dim].color1 = _vm->gameFlags().use16ColorMode ? 0x33 : 254; _textDimData[dim].color2 = _screen->_curDim->unkA; } int cp = _screen->setCurPage(0); - Screen::FontId of = _screen->setFont(_vm->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); + Screen::FontId of = _screen->setFont((_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_9_FNT); preprocessString(str, script, paramList, paramIndex); _numCharsTotal = strlen(_dialogueBuffer); @@ -176,8 +174,8 @@ void TextDisplayer_LoL::printDialogueText(int dim, char *str, EMCState *script, } void TextDisplayer_LoL::printMessage(uint16 type, const char *str, ...) { - static const uint8 textColors256[] = { 0xfe, 0xa2, 0x84, 0x97, 0x9F }; - static const uint8 textColors16[] = { 0x33, 0xaa, 0x88, 0x55, 0x99 }; + static const uint8 textColors256[] = { 0xFE, 0xA2, 0x84, 0x97, 0x9F }; + static const uint8 textColors16[] = { 0x33, 0xAA, 0x88, 0x55, 0x99 }; static const uint8 soundEffect[] = { 0x0B, 0x00, 0x2B, 0x1B, 0x00 }; const uint8 *textColors = _vm->gameFlags().use16ColorMode ? textColors16 : textColors256; @@ -187,7 +185,7 @@ void TextDisplayer_LoL::printMessage(uint16 type, const char *str, ...) { else _vm->stopPortraitSpeechAnim(); - uint16 col = textColors[type & 0x7fff]; + uint16 col = textColors[type & 0x7FFF]; int od = _screen->curDimIndex(); @@ -222,16 +220,15 @@ void TextDisplayer_LoL::printMessage(uint16 type, const char *str, ...) { _vm->sound()->playSoundEffect(soundEffect[type]); } - _vm->_textColorFlag = type & 0x7fff; + _vm->_textColorFlag = type & 0x7FFF; _vm->_fadeText = false; } void TextDisplayer_LoL::preprocessString(char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) { char *dst = _dialogueBuffer; - const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98); for (char *s = str; *s;) { - if (isPc98) { + if (_vm->gameFlags().lang == Common::JA_JPN) { uint8 c = *s; if (c >= 0xE0 || (c > 0x80 && c < 0xA0)) { *dst++ = *s++; diff --git a/engines/kyra/text_rpg.cpp b/engines/kyra/text_rpg.cpp index 52c14c7223..a19d678e35 100644 --- a/engines/kyra/text_rpg.cpp +++ b/engines/kyra/text_rpg.cpp @@ -36,7 +36,7 @@ enum { TextDisplayer_rpg::TextDisplayer_rpg(KyraRpgEngine *engine, Screen *scr) : _vm(engine), _screen(scr), _lineCount(0), _printFlag(false), _lineWidth(0), _numCharsTotal(0), _allowPageBreak(true), - _numCharsLeft(0), _numCharsPrinted(0), _sjisLineBreakFlag(false), _waitButtonMode(1) { + _numCharsLeft(0), _numCharsPrinted(0), _sjisTextModeLineBreak(false), _waitButtonMode(1) { _dialogueBuffer = new char[kEoBTextBufferSize]; memset(_dialogueBuffer, 0, kEoBTextBufferSize); @@ -88,8 +88,8 @@ void TextDisplayer_rpg::resetDimTextPositions(int dim) { } void TextDisplayer_rpg::resetPageBreakString() { - if (vm()->_moreStrings) - strcpy(_pageBreakString, vm()->_moreStrings[0]); + if (_vm->_moreStrings) + strcpy(_pageBreakString, _vm->_moreStrings[0]); } void TextDisplayer_rpg::setPageBreakFlag() { @@ -102,8 +102,6 @@ void TextDisplayer_rpg::removePageBreakFlag() { } void TextDisplayer_rpg::displayText(char *str, ...) { - const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98); - _printFlag = false; _lineWidth = 0; @@ -125,7 +123,9 @@ void TextDisplayer_rpg::displayText(char *str, ...) { const ScreenDim *sd = _screen->_curDim; int sdx = _screen->curDimIndex(); - bool pc98PrintFlag = (isPc98 && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false; + bool sjisTextMode = (_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false; + int sjisOffs = sjisTextMode ? 8 : 9; + uint16 charsPerLine = (sd->w << 3) / (_screen->getFontWidth() + _screen->_charWidth); while (c) { @@ -146,15 +146,25 @@ void TextDisplayer_rpg::displayText(char *str, ...) { c = parseCommand(); } - if (isPc98) { + if (_vm->gameFlags().lang == Common::JA_JPN) { uint8 cu = (uint8) c; if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0)) { - _currentLine[_numCharsLeft++] = c; - _currentLine[_numCharsLeft++] = parseCommand(); - _currentLine[_numCharsLeft] = '\0'; - _lineWidth += 8; - if ((_textDimData[sdx].column + _lineWidth) > (sd->w << 3)) + if (sjisTextMode) { + _currentLine[_numCharsLeft++] = c; + _currentLine[_numCharsLeft++] = parseCommand(); + _currentLine[_numCharsLeft] = '\0'; + } + + if ((_textDimData[sdx].column + _lineWidth + sjisOffs) > (sd->w << 3)) printLine(_currentLine); + + if (!sjisTextMode) { + _currentLine[_numCharsLeft++] = c; + _currentLine[_numCharsLeft++] = parseCommand(); + _currentLine[_numCharsLeft] = '\0'; + } + + _lineWidth += sjisOffs; c = parseCommand(); continue; } @@ -182,17 +192,17 @@ void TextDisplayer_rpg::displayText(char *str, ...) { case 8: printLine(_currentLine); dv = _textDimData[sdx].column / (_screen->getFontWidth() + _screen->_charWidth); - dv = ((dv + 8) & 0xfff8) - 1; + dv = ((dv + 8) & 0xFFF8) - 1; if (dv >= charsPerLine) dv = 0; _textDimData[sdx].column = (_screen->getFontWidth() + _screen->_charWidth) * dv; break; case 12: - if (isPc98) - _sjisLineBreakFlag = true; + if (sjisTextMode) + _sjisTextModeLineBreak = true; printLine(_currentLine); - _sjisLineBreakFlag = false; + _sjisTextModeLineBreak = false; _lineCount++; _textDimData[sdx].column = 0; _textDimData[sdx].line++; @@ -208,7 +218,7 @@ void TextDisplayer_rpg::displayText(char *str, ...) { default: if (_vm->game() == GI_LOL || (unsigned char)c > 30) { - _lineWidth += (pc98PrintFlag ? 4 : _screen->getCharWidth((uint8)c)); + _lineWidth += (sjisTextMode ? 4 : (_screen->_currentFont == Screen::FID_SJIS_FNT ? 9 : _screen->getCharWidth((uint8)c))); _currentLine[_numCharsLeft++] = c; _currentLine[_numCharsLeft] = 0; @@ -266,7 +276,7 @@ void TextDisplayer_rpg::readNextPara() { // versions depend on this code we'll have to look at this again. #if 0 if ((_vm->game() != GI_LOL) && (d & 0x80)) { - d &= 0x7f; + d &= 0x7F; c = d & 7; d = (d & 0x78) >> 3; uint8 l = d; @@ -280,10 +290,9 @@ void TextDisplayer_rpg::readNextPara() { } void TextDisplayer_rpg::printLine(char *str) { - const bool isPc98 = (_vm->gameFlags().platform == Common::kPlatformPC98); const ScreenDim *sd = _screen->_curDim; int sdx = _screen->curDimIndex(); - bool pc98PrintFlag = (isPc98 && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false; + bool sjisTextMode = (_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode && (sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) ? true : false; int fh = (_screen->_currentFont == Screen::FID_SJIS_FNT) ? 9 : (_screen->getFontHeight() + _screen->_charOffset); int lines = (sd->h - _screen->_charOffset) / fh; @@ -307,25 +316,27 @@ void TextDisplayer_rpg::printLine(char *str) { } int x1 = (sd->sx << 3) + _textDimData[sdx].column; - int y = sd->sy + (pc98PrintFlag ? (_textDimData[sdx].line << 3) : (fh * _textDimData[sdx].line)); + int y = sd->sy + (sjisTextMode ? (_textDimData[sdx].line << 3) : (fh * _textDimData[sdx].line)); int w = sd->w << 3; int lw = _lineWidth; int s = _numCharsLeft; char c = 0; + uint8 twoByteCharOffs = 0; - if (pc98PrintFlag) { + + if (sjisTextMode) { bool ct = true; if ((lw + _textDimData[sdx].column) > w) { if ((lines - 1 - (_waitButtonSpace << 1)) <= _lineCount) // cut off line to leave space for "MORE" button - w -= vm()->guiSettings()->buttons.waitReserve; + w -= _vm->guiSettings()->buttons.waitReserve; } else { - if (!_sjisLineBreakFlag || (_lineCount + 1 < lines - 1)) + if (!_sjisTextModeLineBreak || (_lineCount + 1 < lines - 1)) ct = false; else // cut off line to leave space for "MORE" button - w -= vm()->guiSettings()->buttons.waitReserve; + w -= _vm->guiSettings()->buttons.waitReserve; } if (ct) { @@ -344,41 +355,88 @@ void TextDisplayer_rpg::printLine(char *str) { s = n2; } } else { - if ((lw + _textDimData[sdx].column) > w) { + if (_vm->gameFlags().lang == Common::JA_JPN) { + for (int i = 0; i < s; ++i) { + uint8 cu = (uint8) str[i]; + if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0)) + twoByteCharOffs = 8; + } + } + + if ((lw + _textDimData[sdx].column) >= w) { if ((lines - 1) <= _lineCount && _allowPageBreak) // cut off line to leave space for "MORE" button - w -= vm()->guiSettings()->buttons.waitReserve; + w -= _vm->guiSettings()->buttons.waitReserve; w -= _textDimData[sdx].column; - int n2 = 0; - int n1 = s - 1; + int lineLastCharPos = 0; + int strPos = s - 1; + + if (twoByteCharOffs) { + lw = 0; + int prevStrPos = 0; + c = str[0]; + + for (strPos = 0; strPos < s; ++strPos) { + uint8 cu = (uint8) str[strPos]; + if (cu >= 0xE0 || (cu > 0x80 && cu < 0xA0)) { + lw += 9; + strPos++; + } else { + lw += _screen->getCharWidth((uint8)c); + } + + if (!lineLastCharPos && w < lw + twoByteCharOffs) + lineLastCharPos = prevStrPos; + + if (lineLastCharPos && c == ' ') { + s = strPos; + _printFlag = false; + break; + } + prevStrPos = strPos; + c = (char) cu; + } + + if (!lineLastCharPos) { + lineLastCharPos = s - 1; + if (lineLastCharPos && str[lineLastCharPos] == ' ') { + s = strPos; + _printFlag = false; + } + } - while (n1 > 0) { - //cut off line after last space - c = str[n1]; + lw = _lineWidth; - lw -= _screen->getCharWidth((uint8)c); + } else { + while (strPos > 0) { + //cut off line after last space + c = str[strPos]; - if (!n2 && lw <= w) - n2 = n1; + lw -= _screen->getCharWidth((uint8)c); - if (n2 && c == ' ') { - s = n1; - _printFlag = false; - break; + if (!lineLastCharPos && lw <= w) + lineLastCharPos = strPos; + + if (lineLastCharPos && c == ' ') { + s = strPos; + _printFlag = false; + break; + } + strPos--; } - n1--; } - if (!n1) { + if (!strPos) { if (_textDimData[sdx].column && !_printFlag) { s = lw = 0; _printFlag = true; } else { - s = n2; + s = lineLastCharPos; } } + } } @@ -386,7 +444,7 @@ void TextDisplayer_rpg::printLine(char *str) { str[s] = 0; uint8 col = _textDimData[sdx].color1; - if (isPc98 && (sdx == 2 || sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) { + if (sjisTextMode && (sdx == 2 || sdx == 3 || sdx == 4 || sdx == 5 || sdx == 15)) { switch (_textDimData[sdx].color1) { case 0x88: col = 0x41; @@ -394,14 +452,14 @@ void TextDisplayer_rpg::printLine(char *str) { case 0x55: col = 0x81; break; - case 0xaa: + case 0xAA: col = 0x21; break; case 0x99: - col = 0xa1; + col = 0xA1; break; case 0x33: - col = 0xe1; + col = 0xE1; break; case 0x18: col = 0x61; @@ -413,6 +471,7 @@ void TextDisplayer_rpg::printLine(char *str) { _screen->printText(str, x1 & ~3, (y + 8) & ~7, col, 0); } else { _screen->printText(str, x1, y, col, _textDimData[sdx].color2); + _screen->updateScreen(); } _textDimData[sdx].column += lw; @@ -432,9 +491,9 @@ void TextDisplayer_rpg::printLine(char *str) { str[len] = 0; _numCharsLeft = strlen(str); - _lineWidth = pc98PrintFlag ? (_numCharsLeft << 2) : _screen->getTextWidth(str); + _lineWidth = sjisTextMode ? (_numCharsLeft << 2) : (_screen->_currentFont == Screen::FID_SJIS_FNT ? _numCharsLeft * 9: _screen->getTextWidth(str)); - if (!_numCharsLeft && _textDimData[sdx].column < (sd->w << 3)) + if (!_numCharsLeft && (_textDimData[sdx].column + twoByteCharOffs) <= (sd->w << 3)) return; _textDimData[sdx].column = 0; @@ -483,7 +542,7 @@ void TextDisplayer_rpg::printMessage(const char *str, int textColor, ...) { displayText(_dialogueBuffer); - if (vm()->game() != GI_EOB1) + if (_vm->game() != GI_EOB1) _textDimData[_screen->curDimIndex()].color1 = tc; if (!_screen->_curPage) @@ -494,7 +553,7 @@ int TextDisplayer_rpg::clearDim(int dim) { int res = _screen->curDimIndex(); _screen->setScreenDim(dim); _textDimData[dim].color1 = _screen->_curDim->unk8; - _textDimData[dim].color2 = vm()->game() == GI_LOL ? _screen->_curDim->unkA : vm()->guiSettings()->colors.fill; + _textDimData[dim].color2 = _vm->game() == GI_LOL ? _screen->_curDim->unkA : _vm->guiSettings()->colors.fill; clearCurDim(); return res; } @@ -502,7 +561,7 @@ int TextDisplayer_rpg::clearDim(int dim) { void TextDisplayer_rpg::clearCurDim() { int d = _screen->curDimIndex(); const ScreenDim *tmp = _screen->getScreenDim(d); - if (vm()->gameFlags().use16ColorMode) { + if (_vm->gameFlags().use16ColorMode) { _screen->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 2, (tmp->sy + tmp->h) - 2, _textDimData[d].color2); } else _screen->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, _textDimData[d].color2); @@ -512,40 +571,40 @@ void TextDisplayer_rpg::clearCurDim() { } void TextDisplayer_rpg::textPageBreak() { - if (vm()->game() != GI_LOL) - SWAP(vm()->_dialogueButtonLabelColor1, vm()->_dialogueButtonLabelColor2); + if (_vm->game() != GI_LOL) + SWAP(_vm->_dialogueButtonLabelColor1, _vm->_dialogueButtonLabelColor2); int cp = _screen->setCurPage(0); - Screen::FontId cf = _screen->setFont(vm()->gameFlags().use16ColorMode ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); + Screen::FontId cf = _screen->setFont((_vm->gameFlags().lang == Common::JA_JPN && _vm->gameFlags().use16ColorMode) ? Screen::FID_SJIS_FNT : Screen::FID_6_FNT); - if (vm()->game() == GI_LOL) - vm()->_timer->pauseSingleTimer(11, true); + if (_vm->game() == GI_LOL) + _vm->_timer->pauseSingleTimer(11, true); - vm()->_fadeText = false; + _vm->_fadeText = false; int resetPortraitAfterSpeechAnim = 0; int updatePortraitSpeechAnimDuration = 0; - if (vm()->_updateCharNum != -1) { - resetPortraitAfterSpeechAnim = vm()->_resetPortraitAfterSpeechAnim; - vm()->_resetPortraitAfterSpeechAnim = 0; - updatePortraitSpeechAnimDuration = vm()->_updatePortraitSpeechAnimDuration; - if (vm()->_updatePortraitSpeechAnimDuration > 36) - vm()->_updatePortraitSpeechAnimDuration = 36; + if (_vm->_updateCharNum != -1) { + resetPortraitAfterSpeechAnim = _vm->_resetPortraitAfterSpeechAnim; + _vm->_resetPortraitAfterSpeechAnim = 0; + updatePortraitSpeechAnimDuration = _vm->_updatePortraitSpeechAnimDuration; + if (_vm->_updatePortraitSpeechAnimDuration > 36) + _vm->_updatePortraitSpeechAnimDuration = 36; } uint32 speechPartTime = 0; - if (vm()->speechEnabled() && vm()->_activeVoiceFileTotalTime && _numCharsTotal) - speechPartTime = vm()->_system->getMillis() + ((_numCharsPrinted * vm()->_activeVoiceFileTotalTime) / _numCharsTotal); + if (_vm->speechEnabled() && _vm->_activeVoiceFileTotalTime && _numCharsTotal) + speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numCharsTotal); const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex()); int x = ((dim->sx + dim->w) << 3) - (_vm->_dialogueButtonWidth + 3); int y = 0; - int w = vm()->_dialogueButtonWidth; + int w = _vm->_dialogueButtonWidth; - if (vm()->game() == GI_LOL) { - if (vm()->_needSceneRestore && (vm()->_updateFlags & 2)) { - if (vm()->_currentControlMode || !(vm()->_updateFlags & 2)) { + if (_vm->game() == GI_LOL) { + if (_vm->_needSceneRestore && (_vm->_updateFlags & 2)) { + if (_vm->_currentControlMode || !(_vm->_updateFlags & 2)) { y = dim->sy + dim->h - 5; } else { x += 6; @@ -555,49 +614,49 @@ void TextDisplayer_rpg::textPageBreak() { y = dim->sy + dim->h - 10; } } else { - y = vm()->guiSettings()->buttons.waitY[_waitButtonMode]; - x = vm()->guiSettings()->buttons.waitX[_waitButtonMode]; - w = vm()->guiSettings()->buttons.waitWidth[_waitButtonMode]; + y = _vm->guiSettings()->buttons.waitY[_waitButtonMode]; + x = _vm->guiSettings()->buttons.waitX[_waitButtonMode]; + w = _vm->guiSettings()->buttons.waitWidth[_waitButtonMode]; } - if (vm()->gameFlags().use16ColorMode) { - vm()->gui_drawBox(x + 8, (y & ~7) - 1, 66, 10, 0xee, 0xcc, -1); - _screen->printText(_pageBreakString, (x + 37 - (strlen(_pageBreakString) << 1) + 4) & ~3, (y + 2) & ~7, 0xc1, 0); + if (_vm->gameFlags().use16ColorMode) { + _vm->gui_drawBox(x + 8, (y & ~7) - 1, 66, 10, 0xEE, 0xCC, -1); + _screen->printText(_pageBreakString, (x + 37 - (strlen(_pageBreakString) << 1) + 4) & ~3, (y + 2) & ~7, 0xC1, 0); } else { - vm()->gui_drawBox(x, y, w, vm()->guiSettings()->buttons.height, vm()->guiSettings()->colors.frame1, vm()->guiSettings()->colors.frame2, vm()->guiSettings()->colors.fill); - _screen->printText(_pageBreakString, x + (w >> 1) - (vm()->screen()->getTextWidth(_pageBreakString) >> 1), y + 2, vm()->_dialogueButtonLabelColor1, 0); + _vm->gui_drawBox(x, y, w, _vm->guiSettings()->buttons.height, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill); + _screen->printText(_pageBreakString, x + (w >> 1) - (_vm->screen()->getTextWidth(_pageBreakString) >> 1), y + 2, _vm->_dialogueButtonLabelColor1, 0); } - vm()->removeInputTop(); + _vm->removeInputTop(); bool loop = true; bool target = false; do { - int inputFlag = vm()->checkInput(0, false) & 0xFF; - vm()->removeInputTop(); + int inputFlag = _vm->checkInput(0, false) & 0xFF; + _vm->removeInputTop(); while (!inputFlag && !_vm->shouldQuit()) { - vm()->update(); + _vm->update(); - if (vm()->speechEnabled()) { - if (((vm()->_system->getMillis() > speechPartTime) || (vm()->snd_updateCharacterSpeech() != 2)) && speechPartTime) { + if (_vm->speechEnabled()) { + if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_updateCharacterSpeech() != 2)) && speechPartTime) { loop = false; - inputFlag = vm()->_keyMap[Common::KEYCODE_RETURN]; + inputFlag = _vm->_keyMap[Common::KEYCODE_RETURN]; break; } } - inputFlag = vm()->checkInput(0, false) & 0xFF; - vm()->removeInputTop(); + inputFlag = _vm->checkInput(0, false) & 0xFF; + _vm->removeInputTop(); } - vm()->gui_notifyButtonListChanged(); + _vm->gui_notifyButtonListChanged(); - if (inputFlag == vm()->_keyMap[Common::KEYCODE_SPACE] || inputFlag == vm()->_keyMap[Common::KEYCODE_RETURN]) { + if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) { loop = false; } else if (inputFlag == 199 || inputFlag == 201) { - if (vm()->posWithinRect(vm()->_mouseX, vm()->_mouseY, x, y, x + w, y + 9)) { + if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, y, x + w, y + 9)) { if (_vm->game() == GI_LOL) target = true; else @@ -609,7 +668,7 @@ void TextDisplayer_rpg::textPageBreak() { } } while (loop && !_vm->shouldQuit()); - if (vm()->gameFlags().use16ColorMode) + if (_vm->gameFlags().use16ColorMode) _screen->fillRect(x + 8, y, x + 57, y + 9, _textDimData[_screen->curDimIndex()].color2); else _screen->fillRect(x, y, x + w - 1, y + 8, _textDimData[_screen->curDimIndex()].color2); @@ -617,52 +676,52 @@ void TextDisplayer_rpg::textPageBreak() { clearCurDim(); _screen->updateScreen(); - if (vm()->game() == GI_LOL) - vm()->_timer->pauseSingleTimer(11, false); + if (_vm->game() == GI_LOL) + _vm->_timer->pauseSingleTimer(11, false); - if (vm()->_updateCharNum != -1) { - vm()->_resetPortraitAfterSpeechAnim = resetPortraitAfterSpeechAnim; + if (_vm->_updateCharNum != -1) { + _vm->_resetPortraitAfterSpeechAnim = resetPortraitAfterSpeechAnim; if (updatePortraitSpeechAnimDuration > 36) updatePortraitSpeechAnimDuration -= 36; else updatePortraitSpeechAnimDuration >>= 1; - vm()->_updatePortraitSpeechAnimDuration = updatePortraitSpeechAnimDuration; + _vm->_updatePortraitSpeechAnimDuration = updatePortraitSpeechAnimDuration; } _screen->setFont(cf); _screen->setCurPage(cp); - if (vm()->game() != GI_LOL) - SWAP(vm()->_dialogueButtonLabelColor1, vm()->_dialogueButtonLabelColor2); + if (_vm->game() != GI_LOL) + SWAP(_vm->_dialogueButtonLabelColor1, _vm->_dialogueButtonLabelColor2); - vm()->removeInputTop(); + _vm->removeInputTop(); } void TextDisplayer_rpg::displayWaitButton() { - vm()->_dialogueNumButtons = 1; - vm()->_dialogueButtonString[0] = _pageBreakString; - vm()->_dialogueButtonString[1] = 0; - vm()->_dialogueButtonString[2] = 0; - vm()->_dialogueHighlightedButton = 0; + _vm->_dialogueNumButtons = 1; + _vm->_dialogueButtonString[0] = _pageBreakString; + _vm->_dialogueButtonString[1] = 0; + _vm->_dialogueButtonString[2] = 0; + _vm->_dialogueHighlightedButton = 0; - vm()->_dialogueButtonPosX = &vm()->guiSettings()->buttons.waitX[_waitButtonMode]; - vm()->_dialogueButtonPosY = &vm()->guiSettings()->buttons.waitY[_waitButtonMode]; - vm()->_dialogueButtonWidth = vm()->guiSettings()->buttons.waitWidth[_waitButtonMode]; - vm()->_dialogueButtonYoffs = 0; + _vm->_dialogueButtonPosX = &_vm->guiSettings()->buttons.waitX[_waitButtonMode]; + _vm->_dialogueButtonPosY = &_vm->guiSettings()->buttons.waitY[_waitButtonMode]; + _vm->_dialogueButtonWidth = _vm->guiSettings()->buttons.waitWidth[_waitButtonMode]; + _vm->_dialogueButtonYoffs = 0; - SWAP(vm()->_dialogueButtonLabelColor1, vm()->_dialogueButtonLabelColor2); - vm()->drawDialogueButtons(); + SWAP(_vm->_dialogueButtonLabelColor1, _vm->_dialogueButtonLabelColor2); + _vm->drawDialogueButtons(); - if (!vm()->shouldQuit()) - vm()->removeInputTop(); + if (!_vm->shouldQuit()) + _vm->removeInputTop(); - while (!vm()->processDialogue() && !vm()->shouldQuit()) {} + while (!_vm->processDialogue() && !_vm->shouldQuit()) {} - _screen->fillRect(vm()->_dialogueButtonPosX[0], vm()->_dialogueButtonPosY[0], vm()->_dialogueButtonPosX[0] + vm()->_dialogueButtonWidth - 1, vm()->_dialogueButtonPosY[0] + vm()->guiSettings()->buttons.height - 1, vm()->guiSettings()->colors.fill); + _screen->fillRect(_vm->_dialogueButtonPosX[0], _vm->_dialogueButtonPosY[0], _vm->_dialogueButtonPosX[0] + _vm->_dialogueButtonWidth - 1, _vm->_dialogueButtonPosY[0] + _vm->guiSettings()->buttons.height - 1, _vm->guiSettings()->colors.fill); _screen->updateScreen(); - vm()->_dialogueButtonWidth = 95; - SWAP(vm()->_dialogueButtonLabelColor1, vm()->_dialogueButtonLabelColor2); + _vm->_dialogueButtonWidth = 95; + SWAP(_vm->_dialogueButtonLabelColor1, _vm->_dialogueButtonLabelColor2); clearCurDim(); } diff --git a/engines/kyra/text_rpg.h b/engines/kyra/text_rpg.h index 5ad8899484..eb8617a371 100644 --- a/engines/kyra/text_rpg.h +++ b/engines/kyra/text_rpg.h @@ -79,7 +79,7 @@ protected: uint32 _numCharsPrinted; bool _printFlag; - bool _sjisLineBreakFlag; + bool _sjisTextModeLineBreak; char _pageBreakString[20]; char _scriptParaString[11]; diff --git a/engines/kyra/timer_eob.cpp b/engines/kyra/timer_eob.cpp index 766fe453ab..effda22ac9 100644 --- a/engines/kyra/timer_eob.cpp +++ b/engines/kyra/timer_eob.cpp @@ -57,7 +57,7 @@ void EoBCoreEngine::setupTimers() { void EoBCoreEngine::setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer) { uint32 ntime = _system->getMillis() + countdown * _tickLength; - uint8 timerId = 0x30 | (charIndex & 0x0f); + uint8 timerId = 0x30 | (charIndex & 0x0F); EoBCharacter *c = &_characters[charIndex]; if (!_timer->isEnabled(timerId)) { @@ -118,7 +118,7 @@ void EoBCoreEngine::setupCharacterTimers() { if (!testCharacter(i, 1)) continue; - uint32 nextTimer = 0xffffffff; + uint32 nextTimer = 0xFFFFFFFF; for (int ii = 0; ii < 10; ii++) { if (c->timers[ii] && c->timers[ii] < nextTimer) @@ -126,7 +126,7 @@ void EoBCoreEngine::setupCharacterTimers() { } uint32 ctime = _system->getMillis(); - if (nextTimer == 0xffffffff) + if (nextTimer == 0xFFFFFFFF) _timer->disable(0x30 | i); else { enableTimer(0x30 | i); @@ -219,11 +219,11 @@ void EoBCoreEngine::timerProcessFlyingObjects(int timerNum) { } void EoBCoreEngine::timerProcessMonsters(int timerNum) { - updateMonsters(timerNum & 0x0f); + updateMonsters(timerNum & 0x0F); } void EoBCoreEngine::timerSpecialCharacterUpdate(int timerNum) { - int charIndex = timerNum & 0x0f; + int charIndex = timerNum & 0x0F; EoBCharacter *c = &_characters[charIndex]; uint32 ctime = _system->getMillis(); @@ -309,13 +309,13 @@ void EoBCoreEngine::timerSpecialCharacterUpdate(int timerNum) { _screen->setFont(of); } - uint32 nextTimer = 0xffffffff; + uint32 nextTimer = 0xFFFFFFFF; for (int i = 0; i < 10; i++) { if (c->timers[i] && c->timers[i] < nextTimer) nextTimer = c->timers[i]; } - if (nextTimer == 0xffffffff) + if (nextTimer == 0xFFFFFFFF) _timer->disable(timerNum); else _timer->setCountdown(timerNum, (nextTimer - ctime) / _tickLength); diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index a3df8dbe00..9d0cc0dd72 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -49,7 +49,7 @@ void LoLEngine::setupTimers() { } void LoLEngine::timerProcessMonsters(int timerNum) { - for (int i = timerNum & 0x0f; i < 30; i += 2) + for (int i = timerNum & 0x0F; i < 30; i += 2) updateMonster(&_monsters[i]); } @@ -77,7 +77,7 @@ void LoLEngine::timerSpecialCharacterUpdate(int timerNum) { if (_characters[i].characterUpdateDelay[ii] > eventsLeft) eventsLeft = _characters[i].characterUpdateDelay[ii]; } else { - _characters[i].flags &= 0xfffb; + _characters[i].flags &= 0xFFFB; } gui_drawCharPortraitWithStats(i); @@ -89,7 +89,7 @@ void LoLEngine::timerSpecialCharacterUpdate(int timerNum) { break; case 2: - _characters[i].flags &= 0xffbf; + _characters[i].flags &= 0xFFBF; gui_drawCharPortraitWithStats(i); break; @@ -104,7 +104,7 @@ void LoLEngine::timerSpecialCharacterUpdate(int timerNum) { break; case 4: - _characters[i].flags &= 0xfeff; + _characters[i].flags &= 0xFEFF; _txt->printMessage(0, getLangString(0x4027), _characters[i].name); gui_drawCharPortraitWithStats(i); break; @@ -114,7 +114,7 @@ void LoLEngine::timerSpecialCharacterUpdate(int timerNum) { break; case 6: - _characters[i].flags &= 0xefff; + _characters[i].flags &= 0xEFFF; gui_drawCharPortraitWithStats(i); break; @@ -146,7 +146,7 @@ void LoLEngine::timerProcessFlyingObjects(int timerNum) { } void LoLEngine::timerRunSceneAnimScript(int timerNum) { - runLevelScript(0x401 + (timerNum & 0x0f), -1); + runLevelScript(0x401 + (timerNum & 0x0F), -1); } void LoLEngine::timerRegeneratePoints(int timerNum) { diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 471e83c9ed..081d94a050 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -126,8 +126,8 @@ void VQAMovie::decodeSND1(byte *inbuf, uint32 insize, byte *outbuf, uint32 outsi while (outsize > 0) { input = *inbuf++ << 2; - code = (input >> 8) & 0xff; - count = (input & 0xff) >> 2; + code = (input >> 8) & 0xFF; + count = (input & 0xFF) >> 2; switch (code) { case 2: @@ -149,7 +149,7 @@ void VQAMovie::decodeSND1(byte *inbuf, uint32 insize, byte *outbuf, uint32 outsi for (; count >= 0; count--) { code = *inbuf++; - curSample += WSTable4Bit[code & 0x0f]; + curSample += WSTable4Bit[code & 0x0F]; curSample = CLIP<int16>(curSample, 0, 255); *outbuf++ = curSample; @@ -264,7 +264,7 @@ bool VQAMovie::open(const char *filename) { _frameInfo = new uint32[_header.numFrames]; _frame = new byte[_header.width * _header.height]; - _codeBookSize = 0xf00 * _header.blockW * _header.blockH; + _codeBookSize = 0xF00 * _header.blockW * _header.blockH; _codeBook = new byte[_codeBookSize]; _partialCodeBook = new byte[_codeBookSize]; memset(_codeBook, 0, _codeBookSize); diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index a7a650d8ed..fc957e895e 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -75,7 +75,7 @@ bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) { } _vm->_sound->stopSound(); - _vm->changeToCard((uint16)atoi(argv[1]), true); + _vm->changeToCard((uint16)atoi(argv[1]), kTransitionCopy); return false; } diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index e73d4ed6a3..cdb4e1482f 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -106,8 +106,8 @@ void MystCursorManager::hideCursor() { void MystCursorManager::setCursor(uint16 id) { // Zero means empty cursor if (id == 0) { - static const byte emptyCursor = 0; - CursorMan.replaceCursor(&emptyCursor, 1, 1, 0, 0, 0); + static const byte emptyCursor[4] = { 0, 0, 0, 0 }; + CursorMan.replaceCursor(&emptyCursor, 2, 2, 0, 0, 0); return; } diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 5664929948..ef07de0180 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -143,6 +143,7 @@ static const PlainGameDescriptor mohawkGames[] = { {"harryhh","Harry and the Haunted House"}, {"stellaluna", "Stellaluna"}, {"sheila", "Sheila Rae, the Brave"}, + {"rugratsps", "Rugrats Print Shop" }, {0, 0} }; diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 55814af1c3..fc7dfce9bb 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -2096,6 +2096,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // Rugrats Adventure Game + // English Windows Demo + // From GeorgeQGreg (Rugrats Movie Soundtrack) + { + { + "rugrats", + "Demo", + AD_ENTRY1("outline", "adbd7ff6c5e1bdb7062c89879a4e39e6"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO | ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_LIVINGBOOKSV4, + 0, + 0 + }, + { { "lbsampler", @@ -2507,6 +2525,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // Rugrats Print Shop + // English Windows Demo + // From GeorgeQGreg (Rugrats Movie Soundtrack) + { + { + "rugratsps", + "Demo", + AD_ENTRY1("outline", "808d5ee8427180ddebdd5dd4199b47cb"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO | ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_LIVINGBOOKSV4, + 0, + 0 + }, + { AD_TABLE_END_MARKER, 0, 0, 0 } }; diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp index 4461a30ad4..5f5a3b3800 100644 --- a/engines/mohawk/dialogs.cpp +++ b/engines/mohawk/dialogs.cpp @@ -137,12 +137,6 @@ void MystOptionsDialog::open() { void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) { switch (cmd) { - case kZipCmd: - _vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState(); - break; - case kTransCmd: - _vm->_gameState->_globals.transitions = _transitionsCheckbox->getState(); - break; case kDropCmd: _vm->_needsPageDrop = true; close(); @@ -155,8 +149,10 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui _vm->_needsShowDemoMenu = true; close(); break; - case GUI::kCloseCmd: - close(); + case GUI::kOKCmd: + _vm->_gameState->_globals.zipMode = _zipModeCheckbox->getState(); + _vm->_gameState->_globals.transitions = _transitionsCheckbox->getState(); + GUI::OptionsDialog::handleCommand(sender, cmd, data); break; default: GUI::OptionsDialog::handleCommand(sender, cmd, data); diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp index 636b7ae476..5af95f27e3 100644 --- a/engines/mohawk/installer_archive.cpp +++ b/engines/mohawk/installer_archive.cpp @@ -133,4 +133,4 @@ Common::SeekableReadStream *InstallerArchive::createReadStreamForMember(const Co return Common::decompressDCL(_stream, entry.compressedSize, entry.uncompressedSize); } -} // End of namespace Mohawk +} // End of namespace Mohawk diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp index 9c0e642203..8140817eb3 100644 --- a/engines/mohawk/myst.cpp +++ b/engines/mohawk/myst.cpp @@ -523,7 +523,7 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS _video->playMovieBlockingCentered(wrapMovieFilename(flyby, kMasterpieceOnly)); } - changeToCard(card, true); + changeToCard(card, kTransitionCopy); if (linkDstSound) _sound->playSoundBlocking(linkDstSound); @@ -549,7 +549,7 @@ void MohawkEngine_Myst::drawCardBackground() { _gfx->copyImageToBackBuffer(getCardBackgroundId(), Common::Rect(0, 0, 544, 332)); } -void MohawkEngine_Myst::changeToCard(uint16 card, bool updateScreen) { +void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) { debug(2, "changeToCard(%d)", card); _scriptParser->disablePersistentScripts(); @@ -629,9 +629,11 @@ void MohawkEngine_Myst::changeToCard(uint16 card, bool updateScreen) { } // Make sure the screen is updated - if (updateScreen) { - _gfx->copyBackBufferToScreen(Common::Rect(544, 333)); - _system->updateScreen(); + if (transition != kNoTransition) { + if (!_gameState->_globals.transitions) + transition = kTransitionCopy; + + _gfx->runTransition(transition, Common::Rect(544, 333), 10, 0); } // Make sure we have the right cursor showing @@ -1179,41 +1181,41 @@ bool MohawkEngine_Myst::canSaveGameStateCurrently() { } void MohawkEngine_Myst::dropPage() { - uint16 page = _gameState->_globals.heldPage; + uint16 page = _gameState->_globals.heldPage; bool whitePage = page == 13; bool bluePage = page - 1 < 6; - bool redPage = page - 7 < 6; - - // Play drop page sound - _sound->replaceSoundMyst(800); - - // Drop page - _gameState->_globals.heldPage = 0; - - // Redraw page area - if (whitePage && _gameState->_globals.currentAge == 2) { - redrawArea(41); - } else if (bluePage) { - if (page == 6) { - if (_gameState->_globals.currentAge == 2) - redrawArea(24); - } else { - redrawArea(103); - } - } else if (redPage) { - if (page == 12) { - if (_gameState->_globals.currentAge == 2) - redrawArea(25); - } else if (page == 10) { - if (_gameState->_globals.currentAge == 1) - redrawArea(35); - } else { - redrawArea(102); - } - } - - setMainCursor(kDefaultMystCursor); - checkCursorHints(); + bool redPage = page - 7 < 6; + + // Play drop page sound + _sound->replaceSoundMyst(800); + + // Drop page + _gameState->_globals.heldPage = 0; + + // Redraw page area + if (whitePage && _gameState->_globals.currentAge == 2) { + redrawArea(41); + } else if (bluePage) { + if (page == 6) { + if (_gameState->_globals.currentAge == 2) + redrawArea(24); + } else { + redrawArea(103); + } + } else if (redPage) { + if (page == 12) { + if (_gameState->_globals.currentAge == 2) + redrawArea(25); + } else if (page == 10) { + if (_gameState->_globals.currentAge == 1) + redrawArea(35); + } else { + redrawArea(102); + } + } + + setMainCursor(kDefaultMystCursor); + checkCursorHints(); } } // End of namespace Mohawk diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h index 30770f7ec9..a268c19737 100644 --- a/engines/mohawk/myst.h +++ b/engines/mohawk/myst.h @@ -75,6 +75,23 @@ enum { kStoneshipStack // Stoneship Age }; +// Transitions +enum TransitionType { + kTransitionLeftToRight = 0, + kTransitionRightToLeft = 1, + kTransitionSlideToLeft = 2, + kTransitionSlideToRight = 3, + kTransitionDissolve = 4, + kTransitionTopToBottom = 5, + kTransitionBottomToTop = 6, + kTransitionSlideToTop = 7, + kTransitionSlideToBottom= 8, + kTransitionPartToRight = 9, + kTransitionPartToLeft = 10, + kTransitionCopy = 11, + kNoTransition = 999 +}; + const uint16 kMasterpieceOnly = 0xFFFF; struct MystCondition { @@ -154,7 +171,7 @@ public: void reloadSaveList(); void changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound); - void changeToCard(uint16 card, bool updateScreen); + void changeToCard(uint16 card, TransitionType transition); uint16 getCurCard() { return _curCard; } uint16 getCurStack() { return _curStack; } void setMainCursor(uint16 cursor); diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp index a54b67bef4..12a2c7f44c 100644 --- a/engines/mohawk/myst_areas.cpp +++ b/engines/mohawk/myst_areas.cpp @@ -70,10 +70,30 @@ MystResource::~MystResource() { } void MystResource::handleMouseUp() { - if (_dest != 0) - _vm->changeToCard(_dest, true); - else + if (_dest == 0) { warning("Movement type resource with null destination at position (%d, %d), (%d, %d)", _rect.left, _rect.top, _rect.right, _rect.bottom); + return; + } + + uint16 opcode; + + switch (type) { + case kMystForwardArea: + opcode = 6; + break; + case kMystLeftArea: + opcode = 8; + break; + case kMystRightArea: + opcode = 7; + break; + default: + opcode = 48; + break; + } + + _vm->_scriptParser->setInvokingResource(this); + _vm->_scriptParser->runOpcode(opcode, 0); } bool MystResource::canBecomeActive() { @@ -202,22 +222,23 @@ VideoHandle MystResourceType6::playMovie() { // Check if the video is already running VideoHandle handle = _vm->_video->findVideoHandle(_videoFile); - if (_direction != 1) - warning("Playing QT movies backwards is not implemented"); - // If the video is not running, play it if (handle == NULL_VID_HANDLE || _vm->_video->endOfVideo(handle)) { - if (_playBlocking) { - _vm->_video->playMovieBlocking(_videoFile, _left, _top); - handle = NULL_VID_HANDLE; - } else { - handle = _vm->_video->playMovie(_videoFile, _left, _top, _loop); + handle = _vm->_video->playMovie(_videoFile, _left, _top, _loop); + if (_direction == -1) { + _vm->_video->seekToTime(handle, _vm->_video->getDuration(handle)); + _vm->_video->setVideoRate(handle, -1); } } else { // Resume the video _vm->_video->pauseMovie(handle, false); } + if (_playBlocking) { + _vm->_video->waitUntilMovieEnds(handle); + handle = NULL_VID_HANDLE; + } + return handle; } diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp index 2df0f7e6ba..6a292c66e2 100644 --- a/engines/mohawk/myst_graphics.cpp +++ b/engines/mohawk/myst_graphics.cpp @@ -209,15 +209,15 @@ void MystGraphics::copyBackBufferToScreen(Common::Rect r) { _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(r.left, r.top), _backBuffer->pitch, r.left, r.top, r.width(), r.height()); } -void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay) { +void MystGraphics::runTransition(TransitionType type, Common::Rect rect, uint16 steps, uint16 delay) { // Do not artificially delay during transitions int oldEnableDrawingTimeSimulation = _enableDrawingTimeSimulation; _enableDrawingTimeSimulation = 0; switch (type) { - case 0: { - debugC(kDebugScript, "Left to Right"); + case kTransitionLeftToRight: { + debugC(kDebugView, "Left to Right"); uint16 step = (rect.right - rect.left) / steps; Common::Rect area = rect; @@ -239,8 +239,8 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - case 1: { - debugC(kDebugScript, "Right to Left"); + case kTransitionRightToLeft: { + debugC(kDebugView, "Right to Left"); uint16 step = (rect.right - rect.left) / steps; Common::Rect area = rect; @@ -262,8 +262,25 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - case 5: { - debugC(kDebugScript, "Top to Bottom"); + case kTransitionSlideToLeft: + debugC(kDebugView, "Slide to left"); + transitionSlideToLeft(rect, steps, delay); + break; + case kTransitionSlideToRight: + debugC(kDebugView, "Slide to right"); + transitionSlideToRight(rect, steps, delay); + break; + case kTransitionDissolve: { + debugC(kDebugView, "Dissolve"); + + for (int16 step = 0; step < 8; step++) { + simulatePreviousDrawDelay(rect); + transitionDissolve(rect, step); + } + } + break; + case kTransitionTopToBottom: { + debugC(kDebugView, "Top to Bottom"); uint16 step = (rect.bottom - rect.top) / steps; Common::Rect area = rect; @@ -285,8 +302,8 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - case 6: { - debugC(kDebugScript, "Bottom to Top"); + case kTransitionBottomToTop: { + debugC(kDebugView, "Bottom to Top"); uint16 step = (rect.bottom - rect.top) / steps; Common::Rect area = rect; @@ -308,18 +325,260 @@ void MystGraphics::runTransition(uint16 type, Common::Rect rect, uint16 steps, u } } break; - default: - warning("Unknown Update Direction"); + case kTransitionSlideToTop: + debugC(kDebugView, "Slide to top"); + transitionSlideToTop(rect, steps, delay); + break; + case kTransitionSlideToBottom: + debugC(kDebugView, "Slide to bottom"); + transitionSlideToBottom(rect, steps, delay); + break; + case kTransitionPartToRight: { + debugC(kDebugView, "Partial left to right"); + + transitionPartialToRight(rect, 75, 3); + } + break; + case kTransitionPartToLeft: { + debugC(kDebugView, "Partial right to left"); - //TODO: Replace minimal implementation + transitionPartialToLeft(rect, 75, 3); + } + break; + case kTransitionCopy: copyBackBufferToScreen(rect); _vm->_system->updateScreen(); break; + default: + error("Unknown transition %d", type); } _enableDrawingTimeSimulation = oldEnableDrawingTimeSimulation; } +void MystGraphics::transitionDissolve(Common::Rect rect, uint step) { + static const bool pattern[][4][4] = { + { + { true, false, false, false }, + { false, false, false, false }, + { false, false, true, false }, + { false, false, false, false } + }, + { + { false, false, true, false }, + { false, false, false, false }, + { true, false, false, false }, + { false, false, false, false } + }, + { + { false, false, false, false }, + { false, true, false, false }, + { false, false, false, false }, + { false, false, false, true } + }, + { + { false, false, false, false }, + { false, false, false, true }, + { false, false, false, false }, + { false, true, false, false } + }, + { + { false, false, false, false }, + { false, false, true, false }, + { false, true, false, false }, + { false, false, false, false } + }, + { + { false, true, false, false }, + { false, false, false, false }, + { false, false, false, false }, + { false, false, true, false } + }, + { + { false, false, false, false }, + { true, false, false, false }, + { false, false, false, true }, + { false, false, false, false } + }, + { + { false, false, false, true }, + { false, false, false, false }, + { false, false, false, false }, + { true, false, false, false } + } + }; + + rect.clip(_viewport); + + Graphics::Surface *screen = _vm->_system->lockScreen(); + + for (uint16 y = rect.top; y < rect.bottom; y++) { + const bool *linePattern = pattern[step][y % 4]; + + if (!linePattern[0] && !linePattern[1] && !linePattern[2] && !linePattern[3]) + continue; + + for (uint16 x = rect.left; x < rect.right; x++) { + if (linePattern[x % 4]) { + if (_pixelFormat.bytesPerPixel == 2) { + uint16 *dst = (uint16 *)screen->getBasePtr(x, y); + *dst = *(const uint16 *)_backBuffer->getBasePtr(x, y); + } else { + uint32 *dst = (uint32 *)screen->getBasePtr(x, y); + *dst = *(const uint32 *)_backBuffer->getBasePtr(x, y); + } + } + } + } + + _vm->_system->unlockScreen(); + _vm->_system->updateScreen(); +} + +void MystGraphics::transitionSlideToLeft(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.right - rect.left) / steps; + Common::Rect srcRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.right = dstRect.left + step * stepWidth; + srcRect.left = srcRect.right - step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + if (dstRect.right != rect.right) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionSlideToRight(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.right - rect.left) / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.left = dstRect.right - step * stepWidth; + srcRect.right = srcRect.left + step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + if (dstRect.left != rect.left) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionSlideToTop(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.bottom - rect.top) / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.bottom, rect.right, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.left, rect.top, rect.right, rect.top); + + for (uint step = 1; step <= steps; step++) { + dstRect.bottom = dstRect.top + step * stepWidth; + srcRect.top = srcRect.bottom - step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + + if (dstRect.bottom < rect.bottom) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionSlideToBottom(Common::Rect rect, uint16 steps, uint16 delay) { + rect.clip(_viewport); + + uint32 stepWidth = (rect.bottom - rect.top) / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.top, rect.right, rect.top); + Common::Rect dstRect = Common::Rect(rect.left, rect.bottom, rect.right, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.top = dstRect.bottom - step * stepWidth; + srcRect.bottom = srcRect.top + step * stepWidth; + + _vm->_system->delayMillis(delay); + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + + if (dstRect.top > rect.top) { + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); + } +} + +void MystGraphics::transitionPartialToRight(Common::Rect rect, uint32 width, uint32 steps) { + rect.clip(_viewport); + + uint32 stepWidth = width / steps; + Common::Rect srcRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.right = dstRect.left + step * stepWidth; + srcRect.left = srcRect.right - step * stepWidth; + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); +} + +void MystGraphics::transitionPartialToLeft(Common::Rect rect, uint32 width, uint32 steps) { + rect.clip(_viewport); + + uint32 stepWidth = width / steps; + Common::Rect srcRect = Common::Rect(rect.left, rect.top, rect.left, rect.bottom); + Common::Rect dstRect = Common::Rect(rect.right, rect.top, rect.right, rect.bottom); + + for (uint step = 1; step <= steps; step++) { + dstRect.left = dstRect.right - step * stepWidth; + srcRect.right = srcRect.left + step * stepWidth; + + simulatePreviousDrawDelay(dstRect); + _vm->_system->copyRectToScreen(_backBuffer->getBasePtr(dstRect.left, dstRect.top), + _backBuffer->pitch, srcRect.left, srcRect.top, srcRect.width(), srcRect.height()); + _vm->_system->updateScreen(); + } + + copyBackBufferToScreen(rect); + _vm->_system->updateScreen(); +} + void MystGraphics::drawRect(Common::Rect rect, RectState state) { rect.clip(_viewport); diff --git a/engines/mohawk/myst_graphics.h b/engines/mohawk/myst_graphics.h index de8fe521e6..4bbc8d5b8c 100644 --- a/engines/mohawk/myst_graphics.h +++ b/engines/mohawk/myst_graphics.h @@ -48,7 +48,7 @@ public: void copyImageToScreen(uint16 image, Common::Rect dest); void copyImageToBackBuffer(uint16 image, Common::Rect dest); void copyBackBufferToScreen(Common::Rect r); - void runTransition(uint16 type, Common::Rect rect, uint16 steps, uint16 delay); + void runTransition(TransitionType type, Common::Rect rect, uint16 steps, uint16 delay); void drawRect(Common::Rect rect, RectState state); void drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color); void enableDrawingTimeSimulation(bool enable); @@ -60,7 +60,13 @@ protected: MohawkEngine *getVM() { return (MohawkEngine *)_vm; } void simulatePreviousDrawDelay(const Common::Rect &dest); void copyBackBufferToScreenWithSaturation(int16 saturation); - + void transitionDissolve(Common::Rect rect, uint step); + void transitionSlideToLeft(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToRight(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToTop(Common::Rect rect, uint16 steps, uint16 delay); + void transitionSlideToBottom(Common::Rect rect, uint16 steps, uint16 delay); + void transitionPartialToRight(Common::Rect rect, uint32 width, uint32 steps); + void transitionPartialToLeft(Common::Rect rect, uint32 width, uint32 steps); private: MohawkEngine_Myst *_vm; MystBitmap *_bmpDecoder; diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp index 107a8b03e9..c1b75df4cf 100644 --- a/engines/mohawk/myst_scripts.cpp +++ b/engines/mohawk/myst_scripts.cpp @@ -100,18 +100,18 @@ void MystScriptParser::setupCommonOpcodes() { // "Standard" Opcodes OPCODE(0, o_toggleVar); OPCODE(1, o_setVar); - OPCODE(2, o_changeCardSwitch); + OPCODE(2, o_changeCardSwitch4); OPCODE(3, o_takePage); OPCODE(4, o_redrawCard); // Opcode 5 Not Present - OPCODE(6, o_goToDest); - OPCODE(7, o_goToDest); - OPCODE(8, o_goToDest); + OPCODE(6, o_goToDestForward); + OPCODE(7, o_goToDestLeft); + OPCODE(8, o_goToDestRight); OPCODE(9, o_triggerMovie); OPCODE(10, o_toggleVarNoRedraw); // Opcode 11 Not Present - OPCODE(12, o_changeCardSwitch); - OPCODE(13, o_changeCardSwitch); + OPCODE(12, o_changeCardSwitchLtR); + OPCODE(13, o_changeCardSwitchRtL); OPCODE(14, o_drawAreaState); OPCODE(15, o_redrawAreaForVar); OPCODE(16, o_changeCardDirectional); @@ -120,7 +120,7 @@ void MystScriptParser::setupCommonOpcodes() { OPCODE(19, o_enableAreas); OPCODE(20, o_disableAreas); OPCODE(21, o_directionalUpdate); - OPCODE(22, o_goToDest); + OPCODE(22, o_goToDestUp); OPCODE(23, o_toggleAreasActivation); OPCODE(24, o_playSound); // Opcode 25 is unused; original calls replaceSoundMyst @@ -145,6 +145,7 @@ void MystScriptParser::setupCommonOpcodes() { OPCODE(44, o_restoreMainCursor); // Opcode 45 Not Present OPCODE(46, o_soundWaitStop); + OPCODE(48, o_goToDest); OPCODE(51, o_exitMap); // Opcodes 47 to 99 Not Present @@ -273,7 +274,7 @@ void MystScriptParser::animatedUpdate(uint16 argc, uint16 *argv, uint16 delay) { while (argsRead < argc) { Common::Rect rect = Common::Rect(argv[argsRead], argv[argsRead + 1], argv[argsRead + 2], argv[argsRead + 3]); - uint16 kind = argv[argsRead + 4]; + TransitionType kind = static_cast<TransitionType>(argv[argsRead + 4]); uint16 steps = argv[argsRead + 5]; debugC(kDebugScript, "\trect.left: %d", rect.left); @@ -323,16 +324,41 @@ void MystScriptParser::o_setVar(uint16 op, uint16 var, uint16 argc, uint16 *argv _vm->redrawArea(var); } -void MystScriptParser::o_changeCardSwitch(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - // Opcodes 2, 12, and 13 are the same +void MystScriptParser::o_changeCardSwitch4(uint16 op, uint16 var, uint16 argc, uint16 *argv) { uint16 value = getVar(var); debugC(kDebugScript, "Opcode %d: changeCardSwitch var %d: %d", op, var, value); if (value) - _vm->changeToCard(argv[value -1 ], true); + _vm->changeToCard(argv[value -1 ], kTransitionDissolve); else if (_invokingResource != NULL) - _vm->changeToCard(_invokingResource->getDest(), true); + _vm->changeToCard(_invokingResource->getDest(), kTransitionDissolve); + else + warning("Missing invokingResource in altDest call"); +} + +void MystScriptParser::o_changeCardSwitchLtR(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + uint16 value = getVar(var); + + debugC(kDebugScript, "Opcode %d: changeCardSwitch var %d: %d", op, var, value); + + if (value) + _vm->changeToCard(argv[value -1 ], kTransitionLeftToRight); + else if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionLeftToRight); + else + warning("Missing invokingResource in altDest call"); +} + +void MystScriptParser::o_changeCardSwitchRtL(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + uint16 value = getVar(var); + + debugC(kDebugScript, "Opcode %d: changeCardSwitch var %d: %d", op, var, value); + + if (value) + _vm->changeToCard(argv[value -1 ], kTransitionRightToLeft); + else if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionRightToLeft); else warning("Missing invokingResource in altDest call"); } @@ -373,10 +399,47 @@ void MystScriptParser::o_goToDest(uint16 op, uint16 var, uint16 argc, uint16 *ar debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); if (_invokingResource != NULL) - _vm->changeToCard(_invokingResource->getDest(), true); + _vm->changeToCard(_invokingResource->getDest(), kTransitionCopy); + else + warning("Opcode %d: Missing invokingResource", op); +} + +void MystScriptParser::o_goToDestForward(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionDissolve); + else + warning("Opcode %d: Missing invokingResource", op); +} + +void MystScriptParser::o_goToDestLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionPartToRight); + else + warning("Opcode %d: Missing invokingResource", op); +} + +void MystScriptParser::o_goToDestRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionPartToLeft); else warning("Opcode %d: Missing invokingResource", op); } + +void MystScriptParser::o_goToDestUp(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Change To Dest of Invoking Resource", op); + + if (_invokingResource != NULL) + _vm->changeToCard(_invokingResource->getDest(), kTransitionTopToBottom); + else + warning("Opcode %d: Missing invokingResource", op); +} + void MystScriptParser::o_triggerMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Trigger Type 6 Resource Movie..", op); // TODO: If movie has sound, pause background music @@ -427,7 +490,7 @@ void MystScriptParser::o_changeCardDirectional(uint16 op, uint16 var, uint16 arg debugC(kDebugScript, "\tcardId: %d", cardId); debugC(kDebugScript, "\tdirectonal update data size: %d", directionalUpdateDataSize); - _vm->changeToCard(cardId, false); + _vm->changeToCard(cardId, kNoTransition); animatedUpdate(directionalUpdateDataSize, &argv[2], 0); } @@ -440,23 +503,23 @@ void MystScriptParser::o_changeCardPush(uint16 op, uint16 var, uint16 argc, uint debugC(kDebugScript, "Opcode %d: Jump to Card Id, Storing Current Card Id", op); _savedCardId = _vm->getCurCard(); - uint16 cardId = argv[0]; - // argv[1] is not used in the original engine + uint16 cardId = argv[0]; + TransitionType transition = static_cast<TransitionType>(argv[1]); debugC(kDebugScript, "\tCurrent CardId: %d", _savedCardId); debugC(kDebugScript, "\tJump to CardId: %d", cardId); - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, transition); } void MystScriptParser::o_changeCardPop(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Return To Stored Card Id", op); debugC(kDebugScript, "\tCardId: %d", _savedCardId); - // argv[0] is not used in the original engine + TransitionType transition = static_cast<TransitionType>(argv[0]); - _vm->changeToCard(_savedCardId, true); + _vm->changeToCard(_savedCardId, transition); } void MystScriptParser::o_enableAreas(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -752,14 +815,11 @@ void MystScriptParser::o_changeCard(uint16 op, uint16 var, uint16 argc, uint16 * debugC(kDebugScript, "Opcode %d: Change Card", op); uint16 cardId = argv[0]; - - // Argument 1 if present is not used - // uint16 u0 = argv[1]; + TransitionType transition = static_cast<TransitionType>(argv[1]); debugC(kDebugScript, "\tTarget Card: %d", cardId); - //debugC(kDebugScript, "\tu0: %d", u0); // Unused data - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, transition); } void MystScriptParser::o_drawImageChangeCard(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -767,7 +827,7 @@ void MystScriptParser::o_drawImageChangeCard(uint16 op, uint16 var, uint16 argc, uint16 imageId = argv[0]; uint16 cardId = argv[1]; - // argv[2] is not used in the original engine + TransitionType transition = static_cast<TransitionType>(argv[2]); debugC(kDebugScript, "\timageId: %d", imageId); debugC(kDebugScript, "\tcardId: %d", cardId); @@ -775,7 +835,7 @@ void MystScriptParser::o_drawImageChangeCard(uint16 op, uint16 var, uint16 argc, _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333)); _vm->_system->updateScreen(); - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, transition); } void MystScriptParser::o_changeMainCursor(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -850,7 +910,7 @@ void MystScriptParser::o_changeCardPlaySoundDirectional(uint16 op, uint16 var, u if (soundId) _vm->_sound->replaceSoundMyst(soundId); - _vm->changeToCard(cardId, false); + _vm->changeToCard(cardId, kNoTransition); animatedUpdate(dataSize, &argv[4], delayBetweenSteps); } @@ -901,12 +961,12 @@ void MystScriptParser::o_quit(uint16 op, uint16 var, uint16 argc, uint16 *argv) void MystScriptParser::showMap() { if (_vm->getCurCard() != getMap()) { _savedMapCardId = _vm->getCurCard(); - _vm->changeToCard(getMap(), true); + _vm->changeToCard(getMap(), kTransitionCopy); } } void MystScriptParser::o_exitMap(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - _vm->changeToCard(_savedMapCardId, true); + _vm->changeToCard(_savedMapCardId, kTransitionCopy); } } // End of namespace Mohawk diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h index ccb76e0dc8..b75da0801a 100644 --- a/engines/mohawk/myst_scripts.h +++ b/engines/mohawk/myst_scripts.h @@ -86,10 +86,16 @@ public: // Common opcodes DECLARE_OPCODE(o_toggleVar); DECLARE_OPCODE(o_setVar); - DECLARE_OPCODE(o_changeCardSwitch); + DECLARE_OPCODE(o_changeCardSwitch4); + DECLARE_OPCODE(o_changeCardSwitchLtR); + DECLARE_OPCODE(o_changeCardSwitchRtL); DECLARE_OPCODE(o_takePage); DECLARE_OPCODE(o_redrawCard); DECLARE_OPCODE(o_goToDest); + DECLARE_OPCODE(o_goToDestForward); + DECLARE_OPCODE(o_goToDestLeft); + DECLARE_OPCODE(o_goToDestRight); + DECLARE_OPCODE(o_goToDestUp); DECLARE_OPCODE(o_triggerMovie); DECLARE_OPCODE(o_toggleVarNoRedraw); DECLARE_OPCODE(o_drawAreaState); diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp index 069281f5dc..63ba5f7c85 100644 --- a/engines/mohawk/myst_stacks/channelwood.cpp +++ b/engines/mohawk/myst_stacks/channelwood.cpp @@ -341,7 +341,7 @@ void Channelwood::o_drawImageChangeCardAndVolume(uint16 op, uint16 var, uint16 a _vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333)); _vm->_system->updateScreen(); - _vm->changeToCard(cardId, true); + _vm->changeToCard(cardId, kTransitionPartToLeft); if (argc == 3) { uint16 volume = argv[2]; @@ -476,9 +476,12 @@ void Channelwood::o_stairsDoorToggle(uint16 op, uint16 var, uint16 argc, uint16 MystResourceType6 *movie = static_cast<MystResourceType6 *>(_invokingResource); if (_state.stairsUpperDoorState) { - // TODO: Play backwards + // Close door, play the open movie backwards + movie->setDirection(-1); movie->playMovie(); } else { + // Open door + movie->setDirection(1); movie->playMovie(); } } diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp index 29a12571fd..9f393ea401 100644 --- a/engines/mohawk/myst_stacks/demo.cpp +++ b/engines/mohawk/myst_stacks/demo.cpp @@ -104,14 +104,14 @@ void Demo::returnToMenu_run() { switch (_returnToMenuStep){ case 0: _vm->_gfx->fadeToBlack(); - _vm->changeToCard(2003, false); + _vm->changeToCard(2003, kNoTransition); _vm->_gfx->fadeFromBlack(); _returnToMenuStep++; break; case 1: _vm->_gfx->fadeToBlack(); - _vm->changeToCard(2001, false); + _vm->changeToCard(2001, kNoTransition); _vm->_gfx->fadeFromBlack(); _vm->_cursor->showCursor(); diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp index 545b97d956..71733227ac 100644 --- a/engines/mohawk/myst_stacks/intro.cpp +++ b/engines/mohawk/myst_stacks/intro.cpp @@ -127,9 +127,9 @@ void Intro::introMovies_run() { break; default: if (_vm->getFeatures() & GF_DEMO) - _vm->changeToCard(2001, true); + _vm->changeToCard(2001, kTransitionRightToLeft); else - _vm->changeToCard(2, true); + _vm->changeToCard(2, kTransitionRightToLeft); } } @@ -148,7 +148,7 @@ void Intro::mystLinkBook_run() { _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); } } else if (!_linkBookMovie->isPlaying()) { - _vm->changeToCard(5, true); + _vm->changeToCard(5, kTransitionRightToLeft); } } diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp index 79de03308c..43e9bcfed5 100644 --- a/engines/mohawk/myst_stacks/mechanical.cpp +++ b/engines/mohawk/myst_stacks/mechanical.cpp @@ -39,8 +39,17 @@ Mechanical::Mechanical(MohawkEngine_Myst *vm) : MystScriptParser(vm), _state(vm->_gameState->_mechanical) { setupOpcodes(); + _elevatorGoingMiddle = false; + _mystStaircaseState = false; _fortressPosition = 0; + _fortressRotationSpeed = 0; + _fortressSimulationSpeed = 0; + _gearsWereRunning = false; + + _fortressRotationShortMovieWorkaround = false; + _fortressRotationShortMovieCount = 0; + _fortressRotationShortMovieLast = 0; } Mechanical::~Mechanical() { @@ -74,9 +83,9 @@ void Mechanical::setupOpcodes() { OPCODE(121, o_elevatorWindowMovie); OPCODE(122, o_elevatorGoMiddle); OPCODE(123, o_elevatorTopMovie); - OPCODE(124, opcode_124); + OPCODE(124, o_fortressRotationSetPosition); OPCODE(125, o_mystStaircaseMovie); - OPCODE(126, opcode_126); + OPCODE(126, o_elevatorWaitTimeout); OPCODE(127, o_crystalEnterYellow); OPCODE(128, o_crystalLeaveYellow); OPCODE(129, o_crystalEnterGreen); @@ -103,7 +112,6 @@ void Mechanical::setupOpcodes() { void Mechanical::disablePersistentScripts() { _fortressSimulationRunning = false; _elevatorRotationLeverMoving = false; - _elevatorGoingMiddle = false; _birdSinging = false; _fortressRotationRunning = false; } @@ -599,30 +607,33 @@ void Mechanical::elevatorGoMiddle_run() { _vm->_gfx->copyBackBufferToScreen(Common::Rect(10, 137, 61, 165)); _vm->_system->updateScreen(); } - } else if (_elevatorInCabin) { + } else { _elevatorTooLate = true; - - // Elevator going to middle animation - _vm->_cursor->hideCursor(); - _vm->_sound->playSoundBlocking(11120); - _vm->_gfx->copyImageToBackBuffer(6118, Common::Rect(544, 333)); - _vm->_sound->replaceSoundMyst(12120); - _vm->_gfx->runTransition(2, Common::Rect(177, 0, 370, 333), 25, 0); - _vm->_sound->playSoundBlocking(13120); - _vm->_sound->replaceSoundMyst(8120); - _vm->_gfx->copyImageToBackBuffer(6327, Common::Rect(544, 333)); - _vm->_system->delayMillis(500); - _vm->_sound->replaceSoundMyst(9120); - static uint16 moviePos[2] = { 3540, 5380 }; - o_elevatorWindowMovie(121, 0, 2, moviePos); - _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); - _vm->_sound->replaceSoundMyst(10120); - _vm->_cursor->showCursor(); - _elevatorGoingMiddle = false; - _elevatorPosition = 1; - _vm->changeToCard(6327, true); + if (_elevatorInCabin) { + + // Elevator going to middle animation + _vm->_cursor->hideCursor(); + _vm->_sound->playSoundBlocking(11120); + _vm->_gfx->copyImageToBackBuffer(6118, Common::Rect(544, 333)); + _vm->_sound->replaceSoundMyst(12120); + _vm->_gfx->runTransition(kTransitionSlideToLeft, Common::Rect(177, 0, 370, 333), 25, 0); + _vm->_sound->playSoundBlocking(13120); + _vm->_sound->replaceSoundMyst(8120); + _vm->_gfx->copyImageToBackBuffer(6327, Common::Rect(544, 333)); + _vm->_system->delayMillis(500); + _vm->_sound->replaceSoundMyst(9120); + static uint16 moviePos[2] = { 3540, 5380 }; + o_elevatorWindowMovie(121, 0, 2, moviePos); + _vm->_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); + _vm->_sound->replaceSoundMyst(10120); + _vm->_cursor->showCursor(); + + _elevatorPosition = 1; + + _vm->changeToCard(6327, kTransitionRightToLeft); + } } } } @@ -638,16 +649,18 @@ void Mechanical::o_elevatorTopMovie(uint16 op, uint16 var, uint16 argc, uint16 * _vm->_video->waitUntilMovieEnds(window); } -void Mechanical::opcode_124(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Mechanical::o_fortressRotationSetPosition(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Set fortress position", op); - if (argc == 0) { - // Used by Card 6156 (Fortress Rotation Controls) - // Called when Red Exit Button Pressed to raise Elevator + VideoHandle gears = _fortressRotationGears->playMovie(); + uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames(); + + // Myst ME short movie workaround, explained in o_fortressRotation_init + if (_fortressRotationShortMovieWorkaround) { + moviePosition += 3600 * _fortressRotationShortMovieCount; + } - // TODO: Fill in Code... - } else - unknown(op, var, argc, argv); + _fortressPosition = (moviePosition + 900) / 1800 % 4; } void Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -656,17 +669,14 @@ void Mechanical::o_mystStaircaseMovie(uint16 op, uint16 var, uint16 argc, uint16 _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("sstairs", kMechanicalStack), 199, 108); } -void Mechanical::opcode_126(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Mechanical::o_elevatorWaitTimeout(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Wait for the elevator to go middle", op); - if (argc == 0) { - // Used by Card 6120 (Fortress Elevator) - // Called when Red Exit Button Pressed to raise Elevator and - // exit is clicked... - - // TODO: Fill in Code... - } else - unknown(op, var, argc, argv); + // Wait while the elevator times out + while (_elevatorGoingMiddle) { + runPersistentScripts(); + _vm->skippableWait(10); + } } void Mechanical::o_crystalEnterYellow(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -776,8 +786,76 @@ void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uin } void Mechanical::fortressRotation_run() { - // Used for Card 6156 (Fortress Rotation Controls) - // TODO: Fill in function... + VideoHandle gears = _fortressRotationGears->playMovie(); + + double oldRate = _vm->_video->getVideoRate(gears).toDouble(); + + uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames(); + + // Myst ME short movie workaround, explained in o_fortressRotation_init + if (_fortressRotationShortMovieWorkaround) { + // Detect if we just looped + if (ABS<int32>(_fortressRotationShortMovieLast - 3680) < 50 + && ABS<int32>(moviePosition) < 50) { + _fortressRotationShortMovieCount++; + } + + _fortressRotationShortMovieLast = moviePosition; + + // Simulate longer movie + moviePosition += 3600 * _fortressRotationShortMovieCount; + } + + int32 positionInQuarter = 900 - (moviePosition + 900) % 1800; + + // Are the gears moving? + if (oldRate >= 0.1 || ABS<int32>(positionInQuarter) >= 30 || _fortressRotationBrake) { + + double newRate = oldRate; + if (_fortressRotationBrake && (double)_fortressRotationBrake * 0.2 > oldRate) { + newRate += 0.1; + } + + // Don't let the gears get stuck between two fortress positions + if (ABS<double>(oldRate) <= 0.05) { + if (oldRate <= 0.0) { + newRate += oldRate; + } else { + newRate -= oldRate; + } + } else { + if (oldRate <= 0.0) { + newRate += 0.05; + } else { + newRate -= 0.05; + } + } + + // Adjust speed accordingly to acceleration lever + newRate += (double) (positionInQuarter / 1500.0) + * (double) (9 - _fortressRotationSpeed) / 9.0; + + newRate = CLIP<double>(newRate, -2.5, 2.5); + + _vm->_video->setVideoRate(gears, Common::Rational((int)(newRate * 1000.0), 1000)); + + _gearsWereRunning = true; + } else if (_gearsWereRunning) { + // The fortress has stopped. Set its new position + _fortressPosition = (moviePosition + 900) / 1800 % 4; + + _vm->_video->setVideoRate(gears, 0); + + if (!_fortressRotationShortMovieWorkaround) { + _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600)); + } else { + _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * (_fortressPosition % 2), 600)); + } + + _vm->_sound->playSoundBlocking(_fortressRotationSounds[_fortressPosition]); + + _gearsWereRunning = false; + } } void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -785,6 +863,11 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin _fortressRotationGears = static_cast<MystResourceType6 *>(_invokingResource); + VideoHandle gears = _fortressRotationGears->playMovie(); + _vm->_video->setVideoLooping(gears, true); + _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600)); + _vm->_video->setVideoRate(gears, 0); + _fortressRotationSounds[0] = argv[0]; _fortressRotationSounds[1] = argv[1]; _fortressRotationSounds[2] = argv[2]; @@ -792,12 +875,113 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin _fortressRotationBrake = 0; + // WORKAROUND for the tower rotation bug in Myst ME. + // The original engine only allowed to visit two out of the three small islands, + // preventing the game from being fully completable. + // The fortress rotation is computed from the current position in the movie + // hcgears.mov. The version of this movie that shipped with the ME edition is + // too short to allow to visit all the islands. + // ScummVM simulates a longer movie by counting the number of times the movie + // looped and adding that time to the current movie position. + // Hence allowing the fortress position to be properly computed. + uint32 movieDuration = _vm->_video->getDuration(gears).convertToFramerate(600).totalNumberOfFrames(); + if (movieDuration == 3680) { + _fortressRotationShortMovieWorkaround = true; + _fortressRotationShortMovieCount = 0; + _fortressRotationShortMovieLast = 0; + } + _fortressRotationRunning = true; + _gearsWereRunning = false; } void Mechanical::fortressSimulation_run() { - // Used for Card 6044 (Fortress Rotation Simulator) - // TODO: Fill in function... + if (_fortressSimulationInit) { + // Init sequence + _vm->_sound->replaceBackgroundMyst(_fortressSimulationStartSound1, 65535); + _vm->skippableWait(5000); + _vm->_sound->replaceSoundMyst(_fortressSimulationStartSound2); + + // Update movie while the sound is playing + VideoHandle startup = _fortressSimulationStartup->playMovie(); + while (_vm->_sound->isPlaying(_fortressSimulationStartSound2)) { + if (_vm->_video->updateMovies()) + _vm->_system->updateScreen(); + + _vm->_system->delayMillis(10); + } + _vm->_sound->replaceBackgroundMyst(_fortressSimulationStartSound1, 65535); + _vm->_video->waitUntilMovieEnds(startup); + _vm->_sound->stopBackgroundMyst(); + _vm->_sound->replaceSoundMyst(_fortressSimulationStartSound2); + + + Common::Rect src = Common::Rect(0, 0, 176, 176); + Common::Rect dst = Common::Rect(187, 3, 363, 179); + _vm->_gfx->copyImageSectionToBackBuffer(6046, src, dst); + _vm->_gfx->copyBackBufferToScreen(dst); + _vm->_system->updateScreen(); + + _fortressSimulationStartup->pauseMovie(true); + VideoHandle holo = _fortressSimulationHolo->playMovie(); + _vm->_video->setVideoLooping(holo, true); + _vm->_video->setVideoRate(holo, 0); + + _vm->_cursor->showCursor(); + + _fortressSimulationInit = false; + } else { + VideoHandle holo = _fortressSimulationHolo->playMovie(); + + double oldRate = _vm->_video->getVideoRate(holo).toDouble(); + + uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(holo), 600).totalNumberOfFrames(); + + int32 positionInQuarter = 900 - (moviePosition + 900) % 1800; + + // Are the gears moving? + if (oldRate >= 0.1 || ABS<int32>(positionInQuarter) >= 30 || _fortressSimulationBrake) { + + double newRate = oldRate; + if (_fortressSimulationBrake && (double)_fortressSimulationBrake * 0.2 > oldRate) { + newRate += 0.1; + } + + // Don't let the gears get stuck between two fortress positions + if (ABS<double>(oldRate) <= 0.05) { + if (oldRate <= 0.0) { + newRate += oldRate; + } else { + newRate -= oldRate; + } + } else { + if (oldRate <= 0.0) { + newRate += 0.05; + } else { + newRate -= 0.05; + } + } + + // Adjust speed accordingly to acceleration lever + newRate += (double) (positionInQuarter / 1500.0) + * (double) (9 - _fortressSimulationSpeed) / 9.0; + + newRate = CLIP<double>(newRate, -2.5, 2.5); + + _vm->_video->setVideoRate(holo, Common::Rational((int)(newRate * 1000.0), 1000)); + + _gearsWereRunning = true; + } else if (_gearsWereRunning) { + // The fortress has stopped. Set its new position + uint16 simulationPosition = (moviePosition + 900) / 1800 % 4; + + _vm->_video->setVideoRate(holo, 0); + _vm->_video->seekToTime(holo, Audio::Timestamp(0, 1800 * simulationPosition, 600)); + _vm->_sound->playSoundBlocking( _fortressRotationSounds[simulationPosition]); + + _gearsWereRunning = false; + } + } } void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -816,6 +1000,10 @@ void Mechanical::o_fortressSimulation_init(uint16 op, uint16 var, uint16 argc, u _fortressSimulationBrake = 0; _fortressSimulationRunning = true; + _gearsWereRunning = false; + _fortressSimulationInit = true; + + _vm->_cursor->hideCursor(); } void Mechanical::o_fortressSimulationStartup_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/myst_stacks/mechanical.h b/engines/mohawk/myst_stacks/mechanical.h index 3bd7f2d71b..7f3d5143e4 100644 --- a/engines/mohawk/myst_stacks/mechanical.h +++ b/engines/mohawk/myst_stacks/mechanical.h @@ -80,9 +80,9 @@ private: DECLARE_OPCODE(o_elevatorWindowMovie); DECLARE_OPCODE(o_elevatorGoMiddle); DECLARE_OPCODE(o_elevatorTopMovie); - DECLARE_OPCODE(opcode_124); + DECLARE_OPCODE(o_fortressRotationSetPosition); DECLARE_OPCODE(o_mystStaircaseMovie); - DECLARE_OPCODE(opcode_126); + DECLARE_OPCODE(o_elevatorWaitTimeout); DECLARE_OPCODE(o_crystalEnterYellow); DECLARE_OPCODE(o_crystalEnterGreen); DECLARE_OPCODE(o_crystalEnterRed); @@ -104,13 +104,19 @@ private: bool _mystStaircaseState; // 76 bool _fortressRotationRunning; + bool _gearsWereRunning; uint16 _fortressRotationSpeed; // 78 uint16 _fortressRotationBrake; // 80 uint16 _fortressPosition; // 82 uint16 _fortressRotationSounds[4]; // 86 to 92 MystResourceType6 *_fortressRotationGears; // 172 + bool _fortressRotationShortMovieWorkaround; + uint32 _fortressRotationShortMovieCount; + uint32 _fortressRotationShortMovieLast; + bool _fortressSimulationRunning; + bool _fortressSimulationInit; // 94 uint16 _fortressSimulationSpeed; // 96 uint16 _fortressSimulationBrake; // 98 uint16 _fortressSimulationStartSound1; // 102 diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index c1ddc74c82..f17d765c99 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -51,6 +51,8 @@ Myst::Myst(MohawkEngine_Myst *vm) : _dockVaultState = 0; _cabinDoorOpened = 0; _cabinMatchState = 2; + _cabinGaugeMovie = NULL_VID_HANDLE; + _cabinFireMovie = NULL_VID_HANDLE; _matchBurning = false; _tree = 0; _treeAlcove = 0; @@ -189,7 +191,7 @@ void Myst::setupOpcodes() { OPCODE(215, o_gulls2_init); OPCODE(216, o_treeCard_init); OPCODE(217, o_treeEntry_init); - OPCODE(218, opcode_218); + OPCODE(218, o_boilerMovies_init); OPCODE(219, o_rocketSliders_init); OPCODE(220, o_rocketLinkVideo_init); OPCODE(221, o_greenBook_init); @@ -202,7 +204,7 @@ void Myst::setupOpcodes() { OPCODE(303, NOP); OPCODE(304, o_treeCard_exit); OPCODE(305, o_treeEntry_exit); - OPCODE(306, NOP); + OPCODE(306, o_boiler_exit); OPCODE(307, o_generatorControlRoom_exit); OPCODE(308, NOP); OPCODE(309, NOP); @@ -608,6 +610,8 @@ uint16 Myst::getVar(uint16 var) { return 1; case 302: // Green Book Opened Before Flag return _state.greenBookOpenedBefore; + case 303: // Library Bookcase status changed + return _libraryBookcaseChanged; case 304: // Tower Rotation Map Initialized return _towerRotationMapInitialized; case 305: // Cabin Boiler Lit @@ -1041,7 +1045,7 @@ void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { // No page or white page if (!_globals.heldPage || _globals.heldPage == 13) { - _vm->changeToCard(cardIdBookCover, true); + _vm->changeToCard(cardIdBookCover, kTransitionDissolve); return; } @@ -1083,7 +1087,7 @@ void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { // Wrong book if (bookVar != var) { - _vm->changeToCard(cardIdBookCover, true); + _vm->changeToCard(cardIdBookCover, kTransitionDissolve); return; } @@ -1109,9 +1113,9 @@ void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { else _globals.currentAge = 10; - _vm->changeToCard(cardIdLose, true); + _vm->changeToCard(cardIdLose, kTransitionDissolve); } else { - _vm->changeToCard(cardIdBookCover, true); + _vm->changeToCard(cardIdBookCover, kTransitionDissolve); } } @@ -1298,7 +1302,7 @@ void Myst::imagerValidation_run() { if (_imagerValidationStep == 11) { _imagerValidationStep = 0; - _vm->changeToCard(_imagerValidationCard, true); + _vm->changeToCard(_imagerValidationCard, kTransitionBottomToTop); } else { _startTime = time + 100; } @@ -1473,10 +1477,10 @@ void Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16 argc, uint16 *arg if (soundId) _vm->_sound->replaceSoundMyst(soundId); - _vm->changeToCard(4103, false); + _vm->changeToCard(4103, kNoTransition); Common::Rect screenRect = Common::Rect(544, 333); - _vm->_gfx->runTransition(0, screenRect, 2, 5); + _vm->_gfx->runTransition(kTransitionLeftToRight, screenRect, 2, 5); } _tempVar = 1; } else { @@ -1869,17 +1873,50 @@ void Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 argc, uint16 *argv) _state.cabinPilotLightLit = 1; _vm->redrawArea(98); + boilerFireUpdate(false); + // Put out match _matchGoOutTime = _vm->_system->getMillis(); if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - if (_state.cabinValvePosition > 12) + if (_state.cabinValvePosition > 12) { + // Compute the speed of the gauge to synchronize it with the next tree move + uint32 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + boilerResetGauge(rate); + _state.treeLastMoveTime = _vm->_system->getMillis(); + } + } +} - // TODO: Complete. Play movies +Common::Rational Myst::boilerComputeGaugeRate(uint16 pressure, uint32 delay) { + Common::Rational rate = Common::Rational(2088, delay); + if (pressure < 12) + return -rate; + else + return rate; +} + +void Myst::boilerResetGauge(const Common::Rational &rate) { + if (_vm->_video->endOfVideo(_cabinGaugeMovie)) { + if (_vm->getCurCard() == 4098) { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); + } else { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136); + } } + + Audio::Timestamp goTo; + if (rate > 0) + goTo = Audio::Timestamp(0, 0, 600); + else + goTo = _vm->_video->getDuration(_cabinGaugeMovie); + + _vm->_video->seekToTime(_cabinGaugeMovie, goTo); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); } void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -1893,7 +1930,12 @@ void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - // TODO: Play movies + if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + } + } else if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10); } @@ -1903,7 +1945,8 @@ void Myst::boilerPressureIncrease_run() { if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition < 25) { _state.cabinValvePosition++; if (_state.cabinValvePosition == 1) { - // TODO: Play fire movie + // Set fire to high + boilerFireUpdate(false); // Draw fire _vm->redrawArea(305); @@ -1927,7 +1970,8 @@ void Myst::boilerPressureDecrease_run() { if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition > 0) { _state.cabinValvePosition--; if (_state.cabinValvePosition == 0) { - // TODO: Play fire movie + // Set fire to low + boilerFireUpdate(false); // Draw fire _vm->redrawArea(305); @@ -1961,7 +2005,12 @@ void Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - // TODO: Play movies + if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + } + } else { if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10); @@ -2067,6 +2116,11 @@ void Myst::tree_run() { // Check if alcove is accessible treeSetAlcoveAccessible(); + if (_cabinGaugeMovie != NULL_VID_HANDLE) { + Common::Rational rate = boilerComputeGaugeRate(pressure, delay); + boilerResetGauge(rate); + } + _state.treeLastMoveTime = time; } } @@ -2968,7 +3022,12 @@ void Myst::clockReset() { _vm->_system->delayMillis(1000); _vm->_sound->replaceSoundMyst(7113); - // TODO: Play cl1wggat backwards + // Gear closing movie + VideoHandle handle = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack) , 195, 225); + _vm->_video->seekToTime(handle, _vm->_video->getDuration(handle)); + _vm->_video->setVideoRate(handle, -1); + _vm->_video->waitUntilMovieEnds(handle); + // Redraw gear _state.gearsOpen = 0; _vm->redrawArea(40); @@ -2980,16 +3039,9 @@ void Myst::clockReset() { void Myst::clockResetWeight() { _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0); - if (!(_vm->getFeatures() & GF_ME)) { - // Set video bounds, weight going up - _vm->_video->setVideoBounds(_clockWeightVideo, - Audio::Timestamp(0, 2214 * 2 - _clockWeightPosition, 600), - Audio::Timestamp(0, 2214 * 2, 600)); - } else { - //FIXME: Needs QT backwards playing, for now just display the weight up - warning("Weight going back up not implemented"); - _vm->_video->drawVideoFrame(_clockWeightVideo, Audio::Timestamp(0, 0, 600)); - } + // Play the movie backwards, weight going up + _vm->_video->seekToTime(_clockWeightVideo, Audio::Timestamp(0, _clockWeightPosition, 600)); + _vm->_video->setVideoRate(_clockWeightVideo, -1); // Reset position _clockWeightPosition = 0; @@ -3246,7 +3298,7 @@ void Myst::libraryBookcaseTransform_run(void) { if (_state.libraryBookcaseDoor) { _vm->_gfx->copyImageSectionToBackBuffer(11179, Common::Rect(0, 0, 106, 81), Common::Rect(0, 72, 106, 153)); - _vm->_gfx->runTransition(6, Common::Rect(0, 72, 106, 153), 5, 10); + _vm->_gfx->runTransition(kTransitionBottomToTop, Common::Rect(0, 72, 106, 153), 5, 10); _vm->_sound->playSoundBlocking(7348); _vm->_sound->replaceBackgroundMyst(4348, 16384); } else { @@ -3510,22 +3562,60 @@ void Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { treeSetAlcoveAccessible(); } -void Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Myst::o_boilerMovies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Boiler movies init", op); - // Used for Card 4097 (Cabin Boiler) - // TODO: Fill in logic - if (false) { - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244); - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 138); + boilerFireInit(); + boilerGaugeInit(); +} + +void Myst::boilerFireInit() { + if (_vm->getCurCard() == 4098) { + _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279, true); + _vm->_video->pauseMovie(_cabinFireMovie, true); + + _vm->redrawArea(305); + boilerFireUpdate(true); + } else { + if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition >= 1) { + _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244, true); + } + } +} + +void Myst::boilerFireUpdate(bool init) { + uint position = _vm->_video->getTime(_cabinFireMovie); + + if (_state.cabinPilotLightLit == 1) { + if (_state.cabinValvePosition == 0) { + if (position > (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { + _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 100, 600)); + _vm->_video->pauseMovie(_cabinFireMovie, false); + } + } else { + if (position < (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { + _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 201, 600), Audio::Timestamp(0, 1900, 600)); + _vm->_video->pauseMovie(_cabinFireMovie, false); + } + } } +} - // Used for Card 4098 (Cabin Boiler) - // TODO: Fill in logic - if (false) { - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279); - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 97); +void Myst::boilerGaugeInit() { + if (_vm->getCurCard() == 4098) { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); + } else { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136); } + + Audio::Timestamp frame; + + if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12) + frame = _vm->_video->getDuration(_cabinGaugeMovie); + else + frame = Audio::Timestamp(0, 0, 600); + + _vm->_video->drawVideoFrame(_cabinGaugeMovie, frame); } void Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -3648,6 +3738,13 @@ void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { _treeAlcove = 0; } +void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Exit boiler card", op); + + _cabinGaugeMovie = NULL_VID_HANDLE; + _cabinFireMovie = NULL_VID_HANDLE; +} + void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Generator room exit", op); diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h index e9bff08cb4..de88843d59 100644 --- a/engines/mohawk/myst_stacks/myst.h +++ b/engines/mohawk/myst_stacks/myst.h @@ -43,7 +43,7 @@ public: virtual void disablePersistentScripts(); virtual void runPersistentScripts(); -private: +protected: void setupOpcodes(); uint16 getVar(uint16 var); void toggleVar(uint16 var); @@ -52,7 +52,7 @@ private: virtual uint16 getMap() { return 9934; } void towerRotationMap_run(); - void libraryBookcaseTransform_run(); + virtual void libraryBookcaseTransform_run(); void generatorControlRoom_run(); void opcode_212_run(); void libraryCombinationBook_run(); @@ -174,7 +174,7 @@ private: DECLARE_OPCODE(o_gulls2_init); DECLARE_OPCODE(o_treeCard_init); DECLARE_OPCODE(o_treeEntry_init); - DECLARE_OPCODE(opcode_218); + DECLARE_OPCODE(o_boilerMovies_init); DECLARE_OPCODE(o_rocketSliders_init); DECLARE_OPCODE(o_rocketLinkVideo_init); DECLARE_OPCODE(o_greenBook_init); @@ -183,6 +183,7 @@ private: DECLARE_OPCODE(o_bookAddSpecialPage_exit); DECLARE_OPCODE(o_treeCard_exit); DECLARE_OPCODE(o_treeEntry_exit); + DECLARE_OPCODE(o_boiler_exit); DECLARE_OPCODE(o_generatorControlRoom_exit); @@ -259,6 +260,9 @@ private: uint16 _cabinMatchState; // 60 uint32 _matchGoOutTime; // 144 + VideoHandle _cabinFireMovie; // 240 + VideoHandle _cabinGaugeMovie; // 244 + bool _boilerPressureIncreasing; bool _boilerPressureDecreasing; bool _basementPressureIncreasing; @@ -317,6 +321,12 @@ private: Common::Point towerRotationMapComputeCoords(const Common::Point ¢er, uint16 angle); void towerRotationMapDrawLine(const Common::Point ¢er, const Common::Point &end); + void boilerFireInit(); + void boilerFireUpdate(bool init); + void boilerGaugeInit(); + Common::Rational boilerComputeGaugeRate(uint16 pressure, uint32 delay); + void boilerResetGauge(const Common::Rational &rate); + void treeSetAlcoveAccessible(); uint32 treeNextMoveDelay(uint16 pressure); diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp index 0b8dcf897a..75e870281e 100644 --- a/engines/mohawk/myst_stacks/preview.cpp +++ b/engines/mohawk/myst_stacks/preview.cpp @@ -60,6 +60,7 @@ void Preview::setupOpcodes() { OVERRIDE_OPCODE(199, o_speechStop); // "Init" Opcodes + OVERRIDE_OPCODE(209, o_libraryBookcaseTransformDemo_init); OPCODE(298, o_speech_init); OPCODE(299, o_library_init); } @@ -139,7 +140,7 @@ void Preview::speech_run() { break; case 1: // Open book if (_currentCue >= 1) { - _vm->changeToCard(3001, true); + _vm->changeToCard(3001, kTransitionDissolve); _speechStep++; } @@ -147,7 +148,7 @@ void Preview::speech_run() { case 2: // Go to Myst if (_currentCue >= 2) { _vm->_gfx->fadeToBlack(); - _vm->changeToCard(3002, false); + _vm->changeToCard(3002, kNoTransition); _vm->_gfx->fadeFromBlack(); _speechStep++; @@ -164,7 +165,7 @@ void Preview::speech_run() { if (_currentCue >= 4) { _library->drawConditionalDataToScreen(0); - _vm->changeToCard(3003, true); + _vm->changeToCard(3003, kTransitionDissolve); _speechNextTime = time + 2000; _speechStep++; @@ -181,7 +182,7 @@ void Preview::speech_run() { if (time < _speechNextTime) break; - _vm->changeToCard(3004, true); + _vm->changeToCard(3004, kTransitionDissolve); _speechNextTime = time + 2000; _speechStep++; break; @@ -190,7 +191,7 @@ void Preview::speech_run() { break; _vm->_gfx->fadeToBlack(); - _vm->changeToCard(3005, false); + _vm->changeToCard(3005, kNoTransition); _vm->_gfx->fadeFromBlack(); _speechNextTime = time + 1000; _speechStep++; @@ -205,7 +206,7 @@ void Preview::speech_run() { if (time < _speechNextTime) break; - _vm->changeToCard(3006 + _speechStep - 7, true); + _vm->changeToCard(3006 + _speechStep - 7, kTransitionDissolve); _speechNextTime = time + 2000; _speechStep++; break; @@ -213,7 +214,7 @@ void Preview::speech_run() { if (time < _speechNextTime) break; - _vm->changeToCard(4329, true); + _vm->changeToCard(4329, kTransitionDissolve); _speechRunning = false; _globals.currentAge = 2; @@ -241,5 +242,22 @@ void Preview::o_library_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { _library = static_cast<MystResourceType8 *>(_invokingResource); } +void Preview::o_libraryBookcaseTransformDemo_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + if (_libraryBookcaseChanged) { + MystResourceType7 *resource = static_cast<MystResourceType7 *>(_invokingResource); + _libraryBookcaseMovie = static_cast<MystResourceType6 *>(resource->getSubResource(getVar(303))); + _libraryBookcaseSoundId = argv[0]; + _libraryBookcaseMoving = true; + } +} + +void Preview::libraryBookcaseTransform_run() { + if (_libraryBookcaseChanged) + _state.libraryBookcaseDoor = !_state.libraryBookcaseDoor; + + Myst::libraryBookcaseTransform_run(); +} + + } // End of namespace MystStacks } // End of namespace Mohawk diff --git a/engines/mohawk/myst_stacks/preview.h b/engines/mohawk/myst_stacks/preview.h index 1e4ff3efb4..706220e8ed 100644 --- a/engines/mohawk/myst_stacks/preview.h +++ b/engines/mohawk/myst_stacks/preview.h @@ -51,6 +51,7 @@ private: DECLARE_OPCODE(o_stayHere); DECLARE_OPCODE(o_speechStop); + DECLARE_OPCODE(o_libraryBookcaseTransformDemo_init); DECLARE_OPCODE(o_speech_init); DECLARE_OPCODE(o_library_init); @@ -65,6 +66,8 @@ private: void speech_run(); void speechUpdateCue(); + + void libraryBookcaseTransform_run(); }; } // End of namespace MystStacks diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp index 1473742259..a941b14eaa 100644 --- a/engines/mohawk/myst_stacks/selenitic.cpp +++ b/engines/mohawk/myst_stacks/selenitic.cpp @@ -729,11 +729,11 @@ void Selenitic::o_mazeRunnerDoorButton(uint16 op, uint16 var, uint16 argc, uint1 uint16 cardIdEntry = argv[1]; if (_mazeRunnerPosition == 288) { - _vm->changeToCard(cardIdEntry, false); + _vm->changeToCard(cardIdEntry, kNoTransition); _vm->_sound->replaceSoundMyst(cardIdEntry); animatedUpdate(argv[2], &argv[3], 10); } else if (_mazeRunnerPosition == 289) { - _vm->changeToCard(cardIdExit, false); + _vm->changeToCard(cardIdExit, kNoTransition); _vm->_sound->replaceSoundMyst(cardIdExit); animatedUpdate(argv[2], &argv[3], 10); } @@ -895,9 +895,9 @@ void Selenitic::o_soundLockButton(uint16 op, uint16 var, uint16 argc, uint16 *ar uint16 cardIdClosed = argv[0]; uint16 cardIdOpen = argv[1]; - _vm->changeToCard(cardIdClosed, true); + _vm->changeToCard(cardIdClosed, kTransitionDissolve); - _vm->changeToCard(cardIdOpen, false); + _vm->changeToCard(cardIdOpen, kNoTransition); _vm->_sound->replaceSoundMyst(argv[2]); animatedUpdate(argv[4], &argv[5], argv[3]); diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp index c0bb400db1..720926904a 100644 --- a/engines/mohawk/myst_stacks/slides.cpp +++ b/engines/mohawk/myst_stacks/slides.cpp @@ -63,7 +63,7 @@ void Slides::runPersistentScripts() { // Used on Cards... if (_vm->_system->getMillis() > _nextCardTime) { _vm->_gfx->fadeToBlack(); - _vm->changeToCard(_nextCardID, false); + _vm->changeToCard(_nextCardID, kNoTransition); _vm->_gfx->fadeFromBlack(); } } diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp index ef228e62f3..1359685302 100644 --- a/engines/mohawk/myst_stacks/stoneship.cpp +++ b/engines/mohawk/myst_stacks/stoneship.cpp @@ -440,9 +440,9 @@ void Stoneship::o_drawerOpenSirius(uint16 op, uint16 var, uint16 argc, uint16 *a drawer->drawConditionalDataToScreen(0, 0); } - uint16 transition = 5; + TransitionType transition = kTransitionTopToBottom; if (argc == 2 && argv[1]) - transition = 11; + transition = kTransitionCopy; _vm->_gfx->runTransition(transition, drawer->getRect(), 25, 5); } @@ -579,7 +579,7 @@ void Stoneship::o_drawerOpenAchenar(uint16 op, uint16 var, uint16 argc, uint16 * MystResourceType8 *drawer = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]); drawer->drawConditionalDataToScreen(0, 0); - _vm->_gfx->runTransition(5, drawer->getRect(), 25, 5); + _vm->_gfx->runTransition(kTransitionTopToBottom, drawer->getRect(), 25, 5); } void Stoneship::o_hologramPlayback(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -692,9 +692,9 @@ void Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint16 argc, uint16 *a _vm->_sound->resumeBackgroundMyst(); } else { // Valve opening - // TODO: Play backwards VideoHandle valve = _vm->_video->playMovie(movie, 97, 267); - _vm->_video->setVideoBounds(valve, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 350, 600)); + _vm->_video->seekToTime(valve, Audio::Timestamp(0, 350, 600)); + _vm->_video->setVideoRate(valve, -1); _vm->_video->waitUntilMovieEnds(valve); } } @@ -777,7 +777,7 @@ void Stoneship::o_cloudOrbLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv _cloudOrbMovie->pauseMovie(true); _vm->_sound->replaceSoundMyst(_cloudOrbStopSound); - _vm->_gfx->runTransition(5, _invokingResource->getRect(), 4, 0); + _vm->_gfx->runTransition(kTransitionTopToBottom, _invokingResource->getRect(), 4, 0); } void Stoneship::o_drawerCloseOpened(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -794,7 +794,7 @@ void Stoneship::drawerClose(uint16 drawer) { _vm->drawResourceImages(); MystResource *res = _vm->_resources[drawer]; - _vm->_gfx->runTransition(6, res->getRect(), 25, 5); + _vm->_gfx->runTransition(kTransitionBottomToTop, res->getRect(), 25, 5); } void Stoneship::o_hologramDisplay_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp index f01375bacf..d7e829118a 100644 --- a/engines/mohawk/resource.cpp +++ b/engines/mohawk/resource.cpp @@ -464,4 +464,4 @@ bool DOSArchive_v2::openStream(Common::SeekableReadStream *stream) { return true; } -} // End of namespace Mohawk +} // End of namespace Mohawk diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 32613c6185..71aa371073 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -177,7 +177,7 @@ Common::Error MohawkEngine_Riven::run() { } } else { // Otherwise, start us off at aspit's card 1 (the main menu) - changeToStack(aspit); + changeToStack(aspit); changeToCard(1); } @@ -830,7 +830,7 @@ static void sunnersTopStairsTimer(MohawkEngine_Riven *vm) { } else if (sunnerTime < vm->getTotalPlayTime()) { VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(1, 3)); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(2, 15) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(2, 15) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -868,7 +868,7 @@ static void sunnersMidStairsTimer(MohawkEngine_Riven *vm) { VideoHandle handle = vm->_video->playMovieRiven(movie); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 10) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 10) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -898,7 +898,7 @@ static void sunnersLowerStairsTimer(MohawkEngine_Riven *vm) { } else if (sunnerTime < vm->getTotalPlayTime()) { VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(3, 5)); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 30) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -932,7 +932,7 @@ static void sunnersBeachTimer(MohawkEngine_Riven *vm) { vm->_video->activateMLST(mlstID, vm->getCurCard()); VideoHandle handle = vm->_video->playMovieRiven(mlstID); - timerTime = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(1, 30) * 1000; + timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 337a57e3e1..384e89a4cf 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -1467,7 +1467,7 @@ static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) { VideoHandle videoHandle = vm->_video->playMovieRiven(30); // Reset the timer - vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle) + vm->_rnd->getRandomNumber(60) * 1000); + vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle).msecs() + vm->_rnd->getRandomNumber(60) * 1000); } void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { @@ -1507,7 +1507,7 @@ void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { _vm->_video->activateMLST(cathMovie, _vm->getCurCard()); VideoHandle videoHandle = _vm->_video->playMovieRiven(30); - timeUntilNextMovie = _vm->_video->getDuration(videoHandle) + _vm->_rnd->getRandomNumber(60) * 1000; + timeUntilNextMovie = _vm->_video->getDuration(videoHandle).msecs() + _vm->_rnd->getRandomNumber(60) * 1000; } else { // Otherwise, just redraw the imager timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000; @@ -2335,7 +2335,7 @@ static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) { VideoHandle handle = vm->_video->playMovieRiven(movie); // Ensure the next video starts after this one ends - uint32 timeUntilNextVideo = vm->_video->getDuration(handle) + vm->_rnd->getRandomNumberRng(38, 58) * 1000; + uint32 timeUntilNextVideo = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(38, 58) * 1000; // Save the time in case we leave the card and return vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime(); diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index b1b99722d5..8b0130d711 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -493,9 +493,9 @@ uint32 VideoManager::getTime(VideoHandle handle) { return _videoStreams[handle]->getTime(); } -uint32 VideoManager::getDuration(VideoHandle handle) { +Audio::Timestamp VideoManager::getDuration(VideoHandle handle) { assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getDuration().msecs(); + return _videoStreams[handle]->getDuration(); } bool VideoManager::endOfVideo(VideoHandle handle) { @@ -536,6 +536,16 @@ void VideoManager::setVideoLooping(VideoHandle handle, bool loop) { _videoStreams[handle].loop = loop; } +Common::Rational VideoManager::getVideoRate(VideoHandle handle) const { + assert(handle != NULL_VID_HANDLE); + return _videoStreams[handle]->getRate(); +} + +void VideoManager::setVideoRate(VideoHandle handle, const Common::Rational &rate) { + assert(handle != NULL_VID_HANDLE); + _videoStreams[handle]->setRate(rate); +} + void VideoManager::pauseMovie(VideoHandle handle, bool pause) { assert(handle != NULL_VID_HANDLE); _videoStreams[handle]->pauseVideo(pause); diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h index 6d2783936d..2c4c827aa8 100644 --- a/engines/mohawk/video.h +++ b/engines/mohawk/video.h @@ -101,12 +101,14 @@ public: int getCurFrame(VideoHandle handle); uint32 getFrameCount(VideoHandle handle); uint32 getTime(VideoHandle handle); - uint32 getDuration(VideoHandle videoHandle); + Audio::Timestamp getDuration(VideoHandle videoHandle); bool endOfVideo(VideoHandle handle); void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end); void drawVideoFrame(VideoHandle handle, Audio::Timestamp time); void seekToTime(VideoHandle handle, Audio::Timestamp time); void setVideoLooping(VideoHandle handle, bool loop); + Common::Rational getVideoRate(VideoHandle handle) const; + void setVideoRate(VideoHandle handle, const Common::Rational &rate); void waitUntilMovieEnds(VideoHandle videoHandle); void delayUntilMovieEnds(VideoHandle videoHandle); void pauseMovie(VideoHandle videoHandle, bool pause); diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp deleted file mode 100644 index f20e05771a..0000000000 --- a/engines/parallaction/disk.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/iff_container.h" -#include "common/textconsole.h" - -#include "parallaction/disk.h" -#include "parallaction/graphics.h" - -namespace Parallaction { - -void ILBMLoader::setupBuffer(uint32 w, uint32 h) { - _intBuffer = 0; - switch (_bodyMode) { - case BODYMODE_SURFACE: - if (!_surf) { - _surf = new Graphics::Surface; - assert(_surf); - } - _surf->create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - _mode = Graphics::ILBMDecoder::ILBM_UNPACK_PLANES; - _intBuffer = (byte *)_surf->pixels; - break; - - case BODYMODE_MASKBUFFER: - if (!_maskBuffer) { - _maskBuffer = new MaskBuffer; - assert(_maskBuffer); - } - _maskBuffer->create(w, h); - _mode = Graphics::ILBMDecoder::ILBM_2_PACK_PLANES; - _intBuffer = _maskBuffer->data; - break; - - case BODYMODE_PATHBUFFER: - if (!_pathBuffer) { - _pathBuffer = new PathBuffer; - assert(_pathBuffer); - } - _pathBuffer->create(w, h); - _mode = Graphics::ILBMDecoder::ILBM_1_PACK_PLANES; - _intBuffer = _pathBuffer->data; - break; - - default: - error("Invalid bodyMode '%i' for ILBMLoader", _bodyMode); - break; - } -} - -bool ILBMLoader::callback(Common::IFFChunk &chunk) { - switch (chunk._type) { - case ID_BMHD: - _decoder.loadHeader(chunk._stream); - break; - - case ID_CMAP: - if (_palette) { - chunk._stream->read(_palette, chunk._size); - } - break; - - case ID_CRNG: - if (_crng) { - PaletteFxRange *ptr = &_crng[_numCRNG]; - chunk._stream->read((byte *)ptr, chunk._size); - ptr->_timer = FROM_BE_16(ptr->_timer); - ptr->_step = FROM_BE_16(ptr->_step); - ptr->_flags = FROM_BE_16(ptr->_flags); - ++_numCRNG; - } - break; - - case ID_BODY: - setupBuffer(_decoder._header.width, _decoder._header.height); - assert(_intBuffer); - _decoder.loadBitmap(_mode, _intBuffer, chunk._stream); - return true; // stop the parser - } - - return false; -} - -void ILBMLoader::load(Common::ReadStream *in, bool disposeStream) { - Common::IFFParser parser(in, disposeStream); - Common::Functor1Mem< Common::IFFChunk&, bool, ILBMLoader > c(this, &ILBMLoader::callback); - parser.parse(c); -} - -ILBMLoader::ILBMLoader(uint32 bodyMode, byte *palette, PaletteFxRange *crng) { - _bodyMode = bodyMode; - _surf = 0; - _maskBuffer = 0; - _pathBuffer = 0; - _palette = palette; - _crng = crng; - _numCRNG = 0; -} - -ILBMLoader::ILBMLoader(Graphics::Surface *surf, byte *palette, PaletteFxRange *crng) { - _bodyMode = ILBMLoader::BODYMODE_SURFACE; - _surf = surf; - _palette = palette; - _crng = crng; - _numCRNG = 0; -} - -ILBMLoader::ILBMLoader(MaskBuffer *buffer) { - _bodyMode = ILBMLoader::BODYMODE_MASKBUFFER; - _maskBuffer = buffer; - _palette = 0; - _crng = 0; - _numCRNG = 0; -} - -ILBMLoader::ILBMLoader(PathBuffer *buffer) { - _bodyMode = ILBMLoader::BODYMODE_PATHBUFFER; - _pathBuffer = buffer; - _palette = 0; - _crng = 0; - _numCRNG = 0; -} - - - -} diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index d1171c3179..63e33dcfbd 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -28,13 +28,10 @@ #include "common/archive.h" #include "common/str.h" -#include "graphics/iff.h" - namespace Common { class FSDirectory; class ReadStream; class SeekableReadStream; -struct IFFChunk; } namespace Graphics { @@ -86,36 +83,6 @@ public: virtual PathBuffer *loadPath(const char *name, uint32 w, uint32 h) { return 0; } }; -struct PaletteFxRange; - -struct ILBMLoader { - enum { - BODYMODE_SURFACE, - BODYMODE_MASKBUFFER, - BODYMODE_PATHBUFFER - }; - uint32 _bodyMode; - Graphics::Surface *_surf; - MaskBuffer *_maskBuffer; - PathBuffer *_pathBuffer; - byte *_palette; - PaletteFxRange *_crng; - uint32 _mode; - byte* _intBuffer; - uint32 _numCRNG; - Graphics::ILBMDecoder _decoder; - - ILBMLoader(uint32 bodyMode, byte *palette = 0, PaletteFxRange *crng = 0); - ILBMLoader(Graphics::Surface *surf, byte *palette = 0, PaletteFxRange *crng = 0); - ILBMLoader(MaskBuffer *buffer); - ILBMLoader(PathBuffer *buffer); - - bool callback(Common::IFFChunk &chunk); - void setupBuffer(uint32 w, uint32 h); - void load(Common::ReadStream *in, bool disposeStream = false); -}; - - class Disk_ns : public Disk { protected: diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 8988897456..3135c3e8c5 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -20,11 +20,10 @@ * */ -#include "graphics/iff.h" - #include "common/config-manager.h" #include "common/fs.h" #include "common/textconsole.h" +#include "graphics/decoders/iff.h" #include "parallaction/parallaction.h" #include "parallaction/parser.h" @@ -459,8 +458,9 @@ void AmigaDisk_br::adjustForPalette(Graphics::Surface &surf, int transparentColo void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { byte r,g,b; - byte *p; + const byte *p; Common::SeekableReadStream *stream; + Graphics::IFFDecoder decoder; uint i; stream = tryOpenFile("backs/" + Common::String(filename), ".ap"); @@ -488,15 +488,16 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { } stream = openFile("backs/" + Common::String(filename), ".bkg"); + decoder.loadStream(*stream); - byte pal[768]; - ILBMLoader loader(&info.bg, pal); - loader.load(stream, true); - + info.bg.copyFrom(*decoder.getSurface()); info.width = info.bg.w; info.height = info.bg.h; - p = pal; + // Overwrite the first color (transparent key) in the palette + p = decoder.getPalette(); + info.palette.setEntry(0, p[0] >> 2, p[1] >> 2, p[2] >> 0); + for (i = 16; i < 32; i++) { r = *p >> 2; p++; @@ -507,9 +508,6 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { info.palette.setEntry(i, r, g, b); } - // Overwrite the first color (transparent key) in the palette - info.palette.setEntry(0, pal[0] >> 2, pal[1] >> 2, pal[2] >> 0); - // background data is drawn used the upper portion of the palette adjustForPalette(info.bg); } @@ -546,10 +544,15 @@ MaskBuffer *AmigaDisk_br::loadMask(const char *name, uint32 w, uint32 h) { return 0; } - ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER); - loader.load(stream, true); + Graphics::IFFDecoder decoder; + decoder.setNumRelevantPlanes(2); // use only 2 first bits from each pixels + decoder.setPixelPacking(true); // pack 4 2bit pixels into 1 byte + decoder.loadStream(*stream); - MaskBuffer *buffer = loader._maskBuffer; + MaskBuffer *buffer = new MaskBuffer; + // surface width was shrunk to 1/4th of the bitmap width due to the pixel packing + buffer->create(decoder.getSurface()->w * 4, decoder.getSurface()->h); + memcpy(buffer->data, decoder.getSurface()->pixels, buffer->size); buffer->bigEndian = true; finalpass(buffer->data, buffer->size); return buffer; @@ -580,12 +583,12 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) { Common::String sName = name; Common::SeekableReadStream *stream = openFile("ras/" + sName, ".ras"); + Graphics::IFFDecoder decoder; + decoder.loadStream(*stream); - ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE); - loader.load(stream, true); - - Graphics::Surface* surf = loader._surf; + Graphics::Surface *surf = new Graphics::Surface; assert(surf); + surf->copyFrom(*decoder.getSurface()); // Static pictures are drawn used the upper half of the palette: this must be // done before shadow mask is applied. This way, only really transparent pixels @@ -717,23 +720,23 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) { debugC(5, kDebugDisk, "AmigaDisk_br::loadObjects"); Common::SeekableReadStream *stream = openFile(name); - ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE); - loader.load(stream, true); + Graphics::IFFDecoder decoder; + decoder.loadStream(*stream); uint16 max = objectsMax[part]; if (_vm->getFeatures() & GF_DEMO) max = 72; byte *data = new byte[max * 2601]; - byte *srcPtr = (byte *)loader._surf->getBasePtr(0,0); - int w = loader._surf->w; + const byte *srcPtr = (const byte *)decoder.getSurface()->getBasePtr(0,0); + int w = decoder.getSurface()->w; // Convert to the expected display format for (int i = 0; i < max; i++) { uint16 x = (i % 8) * 51; uint16 y = (i / 8) * 51; - byte *src = srcPtr + y * w + x; + const byte *src = srcPtr + y * w + x; byte *dst = data + i * 2601; for (int h = 0; h < 51; h++) { memcpy(dst, src, 51); @@ -741,7 +744,6 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) { dst += 51; } } - delete loader._surf; return new GfxObj(0, new Cnv(max, 51, 51, data, true)); } diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index bad854525d..f03f16ca37 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -22,9 +22,11 @@ #include "common/config-manager.h" #include "common/fs.h" +#include "common/iff_container.h" #include "common/memstream.h" #include "common/substream.h" #include "common/textconsole.h" +#include "graphics/decoders/iff.h" #include "parallaction/parser.h" #include "parallaction/parallaction.h" @@ -312,7 +314,7 @@ void DosDisk_ns::decodeCnv(byte *data, uint16 numFrames, uint16 width, uint16 he int32 decsize = numFrames * width * height; bool packed = (stream->size() - stream->pos()) != decsize; if (packed) { - Graphics::PackBitsReadStream decoder(*stream); + Common::PackBitsReadStream decoder(*stream); decoder.read(data, decsize); } else { stream->read(data, decsize); @@ -914,17 +916,15 @@ void AmigaDisk_ns::buildMask(byte* buf) { void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) { - PaletteFxRange ranges[6]; - byte pal[768]; - Common::SeekableReadStream *s = openFile(name); - ILBMLoader loader(&info.bg, pal, ranges); - loader.load(s, true); + Graphics::IFFDecoder decoder; + decoder.loadStream(*s); + info.bg.copyFrom(*decoder.getSurface()); info.width = info.bg.w; info.height = info.bg.h; - byte *p = pal; + const byte *p = decoder.getPalette(); for (uint i = 0; i < 32; i++) { byte r = *p >> 2; p++; @@ -935,8 +935,15 @@ void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) { info.palette.setEntry(i, r, g, b); } - for (uint j = 0; j < 6; j++) { - info.setPaletteRange(j, ranges[j]); + const Common::Array<Graphics::IFFDecoder::PaletteRange> &paletteRanges = decoder.getPaletteRanges(); + for (uint j = 0; j < 6 && j < paletteRanges.size(); j++) { + PaletteFxRange range; + range._timer = paletteRanges[j].timer; + range._step = paletteRanges[j].step; + range._flags = paletteRanges[j].flags; + range._first = paletteRanges[j].first; + range._last = paletteRanges[j].last; + info.setPaletteRange(j, range); } } @@ -952,19 +959,25 @@ void AmigaDisk_ns::loadMask_internal(BackgroundInfo& info, const char *name) { return; // no errors if missing mask files: not every location has one } - byte pal[768]; - ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER, pal); - loader.load(s, true); + Graphics::IFFDecoder decoder; + decoder.setNumRelevantPlanes(2); // use only 2 first bits from each pixel + decoder.setPixelPacking(true); // pack 4 2bit pixels into 1 byte + decoder.loadStream(*s); + const byte *p = decoder.getPalette(); byte r, g, b; for (uint i = 0; i < 4; i++) { - r = pal[i*3]; - g = pal[i*3+1]; - b = pal[i*3+2]; + r = p[i*3]; + g = p[i*3+1]; + b = p[i*3+2]; info.layers[i] = (((r << 4) & 0xF00) | (g & 0xF0) | (b >> 4)) & 0xFF; } - info._mask = loader._maskBuffer; + info._mask = new MaskBuffer; + // surface width was shrunk to 1/4th of the bitmap width due to the pixel packing + info._mask->create(decoder.getSurface()->w * 4, decoder.getSurface()->h); + memcpy(info._mask->data, decoder.getSurface()->pixels, info._mask->size); + info._mask->bigEndian = true; } void AmigaDisk_ns::loadPath_internal(BackgroundInfo& info, const char *name) { @@ -977,9 +990,15 @@ void AmigaDisk_ns::loadPath_internal(BackgroundInfo& info, const char *name) { return; // no errors if missing path files: not every location has one } - ILBMLoader loader(ILBMLoader::BODYMODE_PATHBUFFER); - loader.load(s, true); - info._path = loader._pathBuffer; + Graphics::IFFDecoder decoder; + decoder.setNumRelevantPlanes(1); // use only first bit from each pixel + decoder.setPixelPacking(true); // pack 8 1bit pixels into 1 byte + decoder.loadStream(*s); + + info._path = new PathBuffer; + // surface width was shrunk to 1/8th of the bitmap width due to the pixel packing + info._path->create(decoder.getSurface()->w * 8, decoder.getSurface()->h); + memcpy(info._path->data, decoder.getSurface()->pixels, info._path->size); info._path->bigEndian = true; } diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index 36572a51df..f8a4e0b9a3 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -8,7 +8,6 @@ MODULE_OBJS := \ debug.o \ detection.o \ dialogue.o \ - disk.o \ disk_br.o \ disk_ns.o \ exec.o \ diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp index e7f1b1b1ed..e60349ffa8 100644 --- a/engines/parallaction/parser_br.cpp +++ b/engines/parallaction/parser_br.cpp @@ -325,6 +325,7 @@ DECLARE_LOCATION_PARSER(location) { nextToken = 2; } + debugC(7, kDebugParser, "flip: %d", flip); // TODO: handle background horizontal flip (via a context parameter) if (_tokens[nextToken][0] != '\0') { diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp index 908005b665..ba631148d5 100644 --- a/engines/pegasus/detection.cpp +++ b/engines/pegasus/detection.cpp @@ -119,12 +119,12 @@ SaveStateList PegasusMetaEngine::listSaves(const char *target) const { // The original had no pattern, so the user must rename theirs // Note that we ignore the target because saves are compatible between // all versions - Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav"); + Common::StringArray fileNames = Pegasus::PegasusEngine::listSaveFiles(); SaveStateList saveList; - for (uint32 i = 0; i < filenames.size(); i++) { + for (uint32 i = 0; i < fileNames.size(); i++) { // Isolate the description from the file name - Common::String desc = filenames[i].c_str() + 8; + Common::String desc = fileNames[i].c_str() + 8; for (int j = 0; j < 4; j++) desc.deleteLastChar(); @@ -136,8 +136,8 @@ SaveStateList PegasusMetaEngine::listSaves(const char *target) const { void PegasusMetaEngine::removeSaveState(const char *target, int slot) const { // See listSaves() for info on the pattern - Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav"); - g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str()); + Common::StringArray fileNames = Pegasus::PegasusEngine::listSaveFiles(); + g_system->getSavefileManager()->removeSavefile(fileNames[slot].c_str()); } bool PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { diff --git a/engines/pegasus/elements.cpp b/engines/pegasus/elements.cpp index c84d555444..87fb69a557 100644 --- a/engines/pegasus/elements.cpp +++ b/engines/pegasus/elements.cpp @@ -259,8 +259,8 @@ void FrameSequence::openFrameSequence() { _frameTimes.clear(); for (uint32 i = 0; i < _numFrames; i++) { TimeValue time = res->readUint32BE(); - _duration += time; _frameTimes.push_back(_duration); + _duration += time; } setScale(scale); diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp index 8aa77eb341..be9d205360 100644 --- a/engines/pegasus/energymonitor.cpp +++ b/engines/pegasus/energymonitor.cpp @@ -262,9 +262,9 @@ void EnergyMonitor::calibrateEnergyBar() { _energyLight.setCurrentFrameIndex(0); _energyLight.hide(); - show(); setEnergyValue(0); setEnergyDrainRate(-(int32)kMaxJMPEnergy / 2); + show(); // Make sure warning light is hidden... _energyLight.hide(); diff --git a/engines/pegasus/movie.cpp b/engines/pegasus/movie.cpp index 75c287c7a6..59814a753d 100644 --- a/engines/pegasus/movie.cpp +++ b/engines/pegasus/movie.cpp @@ -161,9 +161,10 @@ void Movie::setTime(const TimeValue time, const TimeScale scale) { } void Movie::setRate(const Common::Rational rate) { - if (rate != 1 && rate != 0) { - warning("Cannot set movie rate"); - start(); + if (_video) { + _video->setRate(rate); + + TimeBase::setRate(_video->getRate()); return; } diff --git a/engines/pegasus/neighborhood/mars/reactor.cpp b/engines/pegasus/neighborhood/mars/reactor.cpp index 334fb98879..3a7ef9d7eb 100644 --- a/engines/pegasus/neighborhood/mars/reactor.cpp +++ b/engines/pegasus/neighborhood/mars/reactor.cpp @@ -244,9 +244,9 @@ void ReactorHistory::draw(const Common::Rect &) { static const CoordType kColorTops[5] = { 0, kColorHeights[0], - kColorHeights[0] + kColorHeights[1], - kColorHeights[0] + kColorHeights[1] + kColorHeights[2], - kColorHeights[0] + kColorHeights[1] + kColorHeights[2] + kColorHeights[3], + (CoordType)(kColorHeights[0] + kColorHeights[1]), + (CoordType)(kColorHeights[0] + kColorHeights[1] + kColorHeights[2]), + (CoordType)(kColorHeights[0] + kColorHeights[1] + kColorHeights[2] + kColorHeights[3]), }; if (_colors.isSurfaceValid() && _digits.isSurfaceValid()) { diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp index 07be62c957..38366c4ba2 100644 --- a/engines/pegasus/neighborhood/neighborhood.cpp +++ b/engines/pegasus/neighborhood/neighborhood.cpp @@ -1761,10 +1761,10 @@ void Neighborhood::pauseTimer() { } void Neighborhood::resumeTimer() { - // NOTE: Yes, this function calls pauseFuse! - // Looks like an original game bug, will need - // to investigate how this affects gameplay. - _eventTimer.pauseFuse(); + // NOTE: The original calls pauseFuse() here, which causes a bug with the robot + // in WSC on the catwalk, causing him never to come after you if you don't act + // against him. + _eventTimer.resumeFuse(); } bool Neighborhood::timerPaused() { diff --git a/engines/pegasus/neighborhood/norad/pressuredoor.cpp b/engines/pegasus/neighborhood/norad/pressuredoor.cpp index d1378567d3..a12e971d10 100644 --- a/engines/pegasus/neighborhood/norad/pressuredoor.cpp +++ b/engines/pegasus/neighborhood/norad/pressuredoor.cpp @@ -323,7 +323,8 @@ void PressureDoor::receiveNotification(Notification *notification, const Notific _robotState = kRobotDead; _levelsMovie.stop(); _levelsMovie.setSegment((kNormalSubRoomPressure + kPressureBase) * _levelsScale, - (GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale); + (GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale + 1); + _levelsMovie.setTime((GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale); _pressureCallBack.setCallBackFlag(kPressureDroppingFlag); _pressureCallBack.scheduleCallBack(kTriggerAtStart, 0, 0); _typeMovie.stop(); @@ -335,7 +336,7 @@ void PressureDoor::receiveNotification(Notification *notification, const Notific _downButton.setCurrentFrameIndex(1); _gameState = kGameOver; allowInput(false); - _levelsMovie.setRate(Common::Rational(0x5555, 0x10000) - 1); // Should match door tracker. + _levelsMovie.setRate(Common::Rational(-4, 3)); // Should match door tracker. break; case kRobotDead: allowInput(true); diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp index b598841b45..9b843da5d6 100644 --- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp +++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp @@ -622,6 +622,13 @@ void RipTimer::draw(const Common::Rect &updateRect) { } void RipTimer::timeChanged(const TimeValue newTime) { + // WORKAROUND: If the timer isn't running, don't run the following code. + // Fixes use of the code when it shouldn't be running (since this is an + // IdlerAnimation, this is called on useIdleTime() but this specific + // timer only makes sense when used as an actual timer). + if (!isRunning()) + return; + Common::Rect bounds; getBounds(bounds); diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index 420ca39331..eedfaa7db3 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -33,6 +33,7 @@ #include "common/textconsole.h" #include "common/translation.h" #include "common/random.h" +#include "backends/keymapper/keymapper.h" #include "base/plugins.h" #include "base/version.h" #include "gui/saveload.h" @@ -151,6 +152,7 @@ Common::Error PegasusEngine::run() { } // Set up input + initKeymap(); InputHandler::setInputHandler(this); allowInput(true); @@ -637,9 +639,15 @@ void PegasusEngine::writeContinueStream(Common::WriteStream *stream) { delete[] data; } +Common::StringArray PegasusEngine::listSaveFiles() { + Common::StringArray fileNames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav"); + Common::sort(fileNames.begin(), fileNames.end()); + return fileNames; +} + Common::Error PegasusEngine::loadGameState(int slot) { - Common::StringArray filenames = _saveFileMan->listSavefiles("pegasus-*.sav"); - Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filenames[slot]); + Common::StringArray fileNames = listSaveFiles(); + Common::InSaveFile *loadFile = _saveFileMan->openForLoading(fileNames[slot]); if (!loadFile) return Common::kUnknownError; @@ -649,7 +657,23 @@ Common::Error PegasusEngine::loadGameState(int slot) { return valid ? Common::kNoError : Common::kUnknownError; } +static bool isValidSaveFileChar(char c) { + // Limit it to letters, digits, and a few other characters that should be safe + return Common::isAlnum(c) || c == ' ' || c == '_' || c == '+' || c == '-' || c == '.'; +} + +static bool isValidSaveFileName(const Common::String &desc) { + for (uint32 i = 0; i < desc.size(); i++) + if (!isValidSaveFileChar(desc[i])) + return false; + + return true; +} + Common::Error PegasusEngine::saveGameState(int slot, const Common::String &desc) { + if (!isValidSaveFileName(desc)) + return Common::Error(Common::kCreatingFileFailed, _("Invalid save file name")); + Common::String output = Common::String::format("pegasus-%s.sav", desc.c_str()); Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(output, false); if (!saveFile) @@ -667,19 +691,35 @@ void PegasusEngine::receiveNotification(Notification *notification, const Notifi case kGameStartingFlag: { useMenu(new MainMenu()); - if (!isDemo()) { + if (isDemo()) { + // Start playing the music earlier here + ((MainMenu *)_gameMenu)->startMainMenuLoop(); + + // Show the intro splash screen + showTempScreen("Images/Demo/NGsplashScrn.pict"); + + if (shouldQuit()) { + useMenu(0); + return; + } + + // Fade out and then back in with the main menu + _gfx->doFadeOutSync(); + _gfx->updateDisplay(); + _gfx->doFadeInSync(); + } else { + // Display the intro runIntro(); resetIntroTimer(); - } else { - showTempScreen("Images/Demo/NGsplashScrn.pict"); - } - if (shouldQuit()) - return; + if (shouldQuit()) + return; - _gfx->invalRect(Common::Rect(0, 0, 640, 480)); - _gfx->updateDisplay(); - ((MainMenu *)_gameMenu)->startMainMenuLoop(); + // Now display the main menu + _gfx->invalRect(Common::Rect(0, 0, 640, 480)); + _gfx->updateDisplay(); + ((MainMenu *)_gameMenu)->startMainMenuLoop(); + } break; } case kPlayerDiedFlag: @@ -818,7 +858,8 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) { case kMenuCmdDeathQuitDemo: if (isDemo()) showTempScreen("Images/Demo/NGquitScrn.pict"); - _system->quit(); + _gfx->doFadeOutSync(); + quitGame(); break; case kMenuCmdOverview: stopIntroTimer(); @@ -1132,8 +1173,12 @@ void PegasusEngine::doInterfaceOverview() { controllerHighlight.hide(); } - overviewText.setTime(time * 3 + 2, 15); - overviewText.redrawMovieWorld(); + // The original just constantly redraws the frame, but that + // doesn't actually need to be done. + if ((time * 3 + 2) * 40 != overviewText.getTime()) { + overviewText.setTime(time * 3 + 2, 15); + overviewText.redrawMovieWorld(); + } refreshDisplay(); _system->delayMillis(10); @@ -1421,6 +1466,10 @@ void PegasusEngine::switchGameMode(const GameMode newMode, const GameMode oldMod } bool PegasusEngine::canSwitchGameMode(const GameMode newMode, const GameMode oldMode) { + // WORKAROUND: Don't allow game mode switches when the interface is not set up. + // Prevents segfaults when pressing 'i' when in the space chase. + if (!g_interface) + return false; if (newMode == kModeInventoryPick && oldMode == kModeBiochipPick) return false; if (newMode == kModeBiochipPick && oldMode == kModeInventoryPick) @@ -2344,4 +2393,41 @@ uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const { return 1; } +void PegasusEngine::initKeymap() { +#ifdef ENABLE_KEYMAPPER + static const char *const kKeymapName = "pegasus"; + Common::Keymapper *const mapper = _eventMan->getKeymapper(); + + // Do not try to recreate same keymap over again + if (mapper->getKeymap(kKeymapName) != 0) + return; + + Common::Keymap *const engineKeyMap = new Common::Keymap(kKeymapName); + + // Since the game has multiple built-in keys for each of these anyway, + // this just attempts to remap one of them. + const Common::KeyActionEntry keyActionEntries[] = { + { Common::KEYCODE_UP, "UP", _("Up/Zoom In/Move Forward/Open Doors") }, + { Common::KEYCODE_DOWN, "DWN", _("Down/Zoom Out") }, + { Common::KEYCODE_LEFT, "TL", _("Turn Left") }, + { Common::KEYCODE_RIGHT, "TR", _("Turn Right") }, + { Common::KEYCODE_BACKQUOTE, "TIV", _("Display/Hide Inventory Tray") }, + { Common::KEYCODE_BACKSPACE, "TBI", _("Display/Hide Biochip Tray") }, + { Common::KEYCODE_RETURN, "ENT", _("Action/Select") }, + { Common::KEYCODE_t, "TMA", _("Toggle Center Data Display") }, + { Common::KEYCODE_i, "TIN", _("Display/Hide Info Screen") }, + { Common::KEYCODE_ESCAPE, "PM", _("Display/Hide Pause Menu") }, + { Common::KEYCODE_e, "WTF", _("???") } // easter egg key (without being completely upfront about it) + }; + + for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) { + Common::Action *const act = new Common::Action(engineKeyMap, keyActionEntries[i].id, keyActionEntries[i].description); + act->addKeyEvent(keyActionEntries[i].ks); + } + + mapper->addGameKeymap(engineKeyMap); + mapper->pushKeymap(kKeymapName, true); +#endif +} + } // End of namespace Pegasus diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index 2a8ba22470..246414a9d0 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -30,6 +30,7 @@ #include "common/macresman.h" #include "common/rect.h" #include "common/scummsys.h" +#include "common/str-array.h" #include "common/system.h" #include "common/util.h" @@ -195,6 +196,7 @@ public: bool saveRequested() const { return _saveRequested; } void requestLoad() { _loadRequested = true; } bool loadRequested() const { return _loadRequested; } + static Common::StringArray listSaveFiles(); protected: Common::Error run(); @@ -265,6 +267,7 @@ private: void doSubChase(); uint getNeighborhoodCD(const NeighborhoodID neighborhood) const; uint _currentCD; + void initKeymap(); // Menu GameMenu *_gameMenu; diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp index 3b875038cc..50cc9bc6d8 100644 --- a/engines/pegasus/timers.cpp +++ b/engines/pegasus/timers.cpp @@ -73,13 +73,8 @@ TimeBase::TimeBase(const TimeScale preferredScale) { } TimeBase::~TimeBase() { - if (_master) - _master->_slaves.remove(this); - ((PegasusEngine *)g_engine)->removeTimeBase(this); disposeAllCallBacks(); - - // TODO: Remove slaves? Make them remove themselves? } void TimeBase::setTime(const TimeValue time, const TimeScale scale) { @@ -88,20 +83,23 @@ void TimeBase::setTime(const TimeValue time, const TimeScale scale) { } TimeValue TimeBase::getTime(const TimeScale scale) { + // HACK: Emulate the master TimeBase code here for the one case that needs it in the + // game. Note that none of the master TimeBase code in this file should actually be + // used as a reference for anything ever. + if (_master) + return _master->getTime(scale); + return _time.getNumerator() * ((scale == 0) ? _preferredScale : scale) / _time.getDenominator(); } void TimeBase::setRate(const Common::Rational rate) { _rate = rate; + _lastMillis = 0; if (_rate == 0) _paused = false; } -Common::Rational TimeBase::getEffectiveRate() const { - return _rate * ((_master == 0) ? 1 : _master->getEffectiveRate()); -} - void TimeBase::start() { if (_paused) _pausedRate = 1; @@ -192,18 +190,15 @@ TimeValue TimeBase::getDuration(const TimeScale scale) const { } void TimeBase::setMasterTimeBase(TimeBase *tb) { - // TODO: We're just ignoring the master (except for effective rate) - // for now to simplify things - if (_master) - _master->_slaves.remove(this); - _master = tb; - - if (_master) - _master->_slaves.push_back(this); } void TimeBase::updateTime() { + if (_master) { + _master->updateTime(); + return; + } + if (_lastMillis == 0) { _lastMillis = g_system->getMillis(); } else { @@ -211,7 +206,7 @@ void TimeBase::updateTime() { if (_lastMillis == curTime) // No change return; - _time += Common::Rational(curTime - _lastMillis, 1000) * getEffectiveRate(); + _time += Common::Rational(curTime - _lastMillis, 1000) * getRate(); _lastMillis = curTime; } } @@ -233,8 +228,6 @@ void TimeBase::checkCallBacks() { else if (_time <= startTime) _time = startTime; - // TODO: Update the slaves? - Common::Rational time = Common::Rational(getTime(), getScale()); // Check if we've triggered any callbacks diff --git a/engines/pegasus/timers.h b/engines/pegasus/timers.h index bcdca6e860..944930d21b 100644 --- a/engines/pegasus/timers.h +++ b/engines/pegasus/timers.h @@ -26,7 +26,6 @@ #ifndef PEGASUS_TIMERS_H #define PEGASUS_TIMERS_H -#include "common/list.h" #include "common/rational.h" #include "common/func.h" @@ -122,11 +121,6 @@ protected: Common::Rational _time; uint32 _lastMillis, _pauseStart; - -private: - Common::Rational getEffectiveRate() const; - - Common::List<TimeBase *> _slaves; }; // Type passed to initCallBack() diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp index cd9a1075fa..d7b20c203e 100644 --- a/engines/queen/display.cpp +++ b/engines/queen/display.cpp @@ -29,6 +29,7 @@ #include "graphics/cursorman.h" #include "graphics/palette.h" #include "graphics/surface.h" +#include "graphics/decoders/iff.h" #include "graphics/decoders/pcx.h" #include "queen/display.h" @@ -701,7 +702,7 @@ void Display::setupPanel() { uint8 *data = _vm->resource()->loadFile(dataName, 0, &dataSize); if (_vm->resource()->getPlatform() == Common::kPlatformAmiga) { - decodeLBM(data, dataSize, _panelBuf, PANEL_W, &panelWidth, &panelHeight, _pal.panel, 0, 32, 144); + decodeIFF(data, dataSize, _panelBuf, PANEL_W, &panelWidth, &panelHeight, _pal.panel, 0, 32, 144); } else { WRITE_LE_UINT16(data + 14, PANEL_H - 10); decodePCX(data, dataSize, _panelBuf + PANEL_W * 10, PANEL_W, &panelWidth, &panelHeight, _pal.panel, 144, 256); @@ -720,7 +721,7 @@ void Display::setupNewRoom(const char *name, uint16 room) { uint8 *data = _vm->resource()->loadFile(dataName, 0, &dataSize); if (_vm->resource()->getPlatform() == Common::kPlatformAmiga) { - decodeLBM(data, dataSize, _backdropBuf, BACKDROP_W, &_bdWidth, &_bdHeight, _pal.room, 0, 32); + decodeIFF(data, dataSize, _backdropBuf, BACKDROP_W, &_bdWidth, &_bdHeight, _pal.room, 0, 32); if (_bdHeight < BACKDROP_H) { memset(_backdropBuf + _bdHeight * BACKDROP_W, 0, (BACKDROP_H - _bdHeight) * BACKDROP_W); } @@ -828,73 +829,22 @@ void Display::decodePCX(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dst memcpy(dst + y * dstPitch, pcxSurface->getBasePtr(0, y), pcxSurface->w); } -void Display::decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase) { - int planeCount = 0, planePitch = 0; - const uint8 *srcEnd = src + srcSize; - src += 12; - while (src < srcEnd) { - uint32 type = READ_BE_UINT32(src); - uint32 size = READ_BE_UINT32(src + 4); - src += 8; - switch (type) { - case MKTAG('B','M','H','D'): { - *w = READ_BE_UINT16(src + 0); - *h = READ_BE_UINT16(src + 2); - planeCount = src[8]; - planePitch = ((*w + 15) >> 4) * 2; - } - break; - case MKTAG('C','M','A','P'): { - assert(palStart <= palEnd && palEnd <= size / 3); - memcpy(pal, src + palStart * 3, (palEnd - palStart) * 3); - } - break; - case MKTAG('B','O','D','Y'): { - uint32 planarSize = (*h) * planeCount * planePitch; - uint8 *planarBuf = new uint8[planarSize]; - uint8 *dstPlanar = planarBuf; - for (int y = 0; y < *h; ++y) { - for (int p = 0; p < planeCount; ++p) { - const uint8 *end = dstPlanar + planePitch; - while (dstPlanar < end) { - int code = (int8)*src++; - if (code != -128) { - if (code < 0) { - code = -code + 1; - memset(dstPlanar, *src++, code); - } else { - ++code; - memcpy(dstPlanar, src, code); - src += code; - } - dstPlanar += code; - } - } - } - } - src = planarBuf; - for (int y = 0; y < *h; ++y) { - for (int x = 0; x < *w / 8; ++x) { - for (int b = 0; b < 8; ++b) { - const uint8 mask = (1 << (7 - b)); - uint8 color = 0; - for (int p = 0; p < planeCount; ++p) { - if (src[planePitch * p + x] & mask) { - color |= 1 << p; - } - } - dst[x * 8 + b] = colorBase + color; - } - } - src += planeCount * planePitch; - dst += dstPitch; - } - delete[] planarBuf; - } - return; - } - src += size; - } +void Display::decodeIFF(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase) { + Common::MemoryReadStream str(src, srcSize); + + ::Graphics::IFFDecoder iff; + if (!iff.loadStream(str)) + error("Error while reading IFF image"); + + const ::Graphics::Surface *iffSurface = iff.getSurface(); + *w = iffSurface->w; + *h = iffSurface->h; + + assert(palStart <= palEnd && palEnd <= 256); + memcpy(pal, iff.getPalette() + palStart * 3, (palEnd - palStart) * 3); + for (uint16 y = 0; y < iffSurface->h; y++) + for(uint16 x = 0; x < iffSurface->w; x++) + dst[(y * dstPitch) + x] = *(const byte *)iffSurface->getBasePtr(x, y) + colorBase; } void Display::horizontalScrollUpdate(int16 xCamera) { diff --git a/engines/queen/display.h b/engines/queen/display.h index 4256b19d72..8a8aaef5a6 100644 --- a/engines/queen/display.h +++ b/engines/queen/display.h @@ -116,8 +116,8 @@ public: //! decode PCX picture data void decodePCX(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd); - //! decode ILBM picture data - void decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase = 0); + //! decode IFF picture data + void decodeIFF(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase = 0); void horizontalScrollUpdate(int16 xCamera); void horizontalScroll(int16 scroll); diff --git a/engines/queen/journal.cpp b/engines/queen/journal.cpp index 704019641b..474f72eca5 100644 --- a/engines/queen/journal.cpp +++ b/engines/queen/journal.cpp @@ -400,7 +400,7 @@ static void removeLeadingAndTrailingSpaces(char *dst, size_t dstSize, const char while (src[lastNonSpaceIndex] == ' ') --lastNonSpaceIndex; - size_t newLen = lastNonSpaceIndex - firstNonSpaceIndex + 1; + uint newLen = lastNonSpaceIndex - firstNonSpaceIndex + 1; assert(newLen < dstSize); for (size_t i = 0; i < newLen; ++i) { dst[i] = src[firstNonSpaceIndex + i]; @@ -559,7 +559,7 @@ void Journal::updateTextField(uint16 ascii, int keycode) { } break; default: - if (isprint((char)ascii) && + if (Common::isPrint((char)ascii) && _textField.textCharsCount < (sizeof(_textField.text) - 1) && _vm->display()->textWidth(_textField.text) < _textField.w) { _textField.text[_textField.textCharsCount] = (char)ascii; diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp index ac58dda728..6731a51e04 100644 --- a/engines/queen/sound.cpp +++ b/engines/queen/sound.cpp @@ -246,8 +246,8 @@ void PCSound::playSong(int16 songNum) { if (!musicOn()) return; - int override = (_vm->resource()->isDemo()) ? _songDemo[songNum - 1].override : _song[songNum - 1].override; - switch (override) { + int overrideCmd = (_vm->resource()->isDemo()) ? _songDemo[songNum - 1].overrideCmd : _song[songNum - 1].overrideCmd; + switch (overrideCmd) { // Override all songs case 1: break; @@ -771,4 +771,4 @@ bool AmigaSound::playSpecialSfx(int16 sfx) { return true; } -} //End of namespace Queen +} // End of namespace Queen diff --git a/engines/queen/sound.h b/engines/queen/sound.h index 371500f356..6a5dfc2c28 100644 --- a/engines/queen/sound.h +++ b/engines/queen/sound.h @@ -39,7 +39,7 @@ struct SongData { int16 volume; int16 tempo; int16 reverb; - int16 override; + int16 overrideCmd; int16 ignore; }; diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp index 94bc105bb0..1531510ba4 100644 --- a/engines/queen/talk.cpp +++ b/engines/queen/talk.cpp @@ -96,7 +96,6 @@ void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) { } int16 oldLevel = 0; - bool personWalking = false; // FIXME: unused // Lines 828-846 in talk.c for (i = 1; i <= 4; i++) { @@ -174,8 +173,7 @@ void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) { if (1 == choicesLeft) { // Automatically run the final dialogue option - if (speak(_talkString[0], &person, otherVoiceFilePrefix)) - personWalking = true; + speak(_talkString[0], &person, otherVoiceFilePrefix); if (_vm->input()->talkQuit()) break; @@ -251,8 +249,7 @@ void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) { findDialogueString(_person1PtrOff, head, _pMax, _talkString[0]); if (_talkString[0][0] != '\0') { sprintf(otherVoiceFilePrefix, "%2d%4xP", _talkKey, head); - if (speak(_talkString[0], &person, otherVoiceFilePrefix)) - personWalking = true; + speak(_talkString[0], &person, otherVoiceFilePrefix); } } } diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index 9c178559f2..f6872c41ad 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -156,7 +156,8 @@ bool SagaMetaEngine::hasFeature(MetaEngineFeature f) const { (f == kSupportsDeleteSave) || (f == kSavesSupportMetaInfo) || (f == kSavesSupportThumbnail) || - (f == kSavesSupportCreationDate); + (f == kSavesSupportCreationDate) || + (f == kSavesSupportPlayTime); } bool Saga::SagaEngine::hasFeature(EngineFeature f) const { @@ -270,7 +271,10 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s desc.setSaveTime(hour, minutes); - // TODO: played time + if (version >= 8) { + uint32 playTime = in->readUint32BE(); + desc.setPlayTime(playTime * 1000); + } } delete in; diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp index ec3ef2f6f9..d98cef0740 100644 --- a/engines/saga/events.cpp +++ b/engines/saga/events.cpp @@ -332,13 +332,22 @@ int Events::handleOneShot(Event *event) { #ifdef ENABLE_IHNM if (_vm->getGameId() == GID_IHNM) { + PalEntry portraitBgColor = _vm->_interface->_portraitBgColor; + byte portraitColor = (_vm->getLanguage() == Common::ES_ESP) ? 253 : 254; + + // Set the portrait bg color, in case a saved state is restored from the + // launcher. In this case, sfSetPortraitBgColor is not called, thus the + // portrait color will always be 0 (black). + if (portraitBgColor.red == 0 && portraitBgColor.green == 0 && portraitBgColor.blue == 0) + portraitBgColor.green = 255; + if (_vm->_spiritualBarometer > 255) - _vm->_gfx->setPaletteColor(kIHNMColorPortrait, 0xff, 0xff, 0xff); + _vm->_gfx->setPaletteColor(portraitColor, 0xff, 0xff, 0xff); else - _vm->_gfx->setPaletteColor(kIHNMColorPortrait, - _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.red / 256, - _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.green / 256, - _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.blue / 256); + _vm->_gfx->setPaletteColor(portraitColor, + _vm->_spiritualBarometer * portraitBgColor.red / 256, + _vm->_spiritualBarometer * portraitBgColor.green / 256, + _vm->_spiritualBarometer * portraitBgColor.blue / 256); } #endif diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 13850a0b6d..0eebf3f175 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -30,6 +30,7 @@ #include "audio/audiostream.h" #include "audio/mididrv.h" #include "audio/midiparser.h" +#include "audio/midiparser_qt.h" #include "audio/decoders/raw.h" #include "common/config-manager.h" #include "common/file.h" @@ -76,19 +77,14 @@ void MusicDriver::play(SagaEngine *vm, ByteArray *buffer, bool loop) { } // Check if the game is using XMIDI or SMF music - if (vm->getGameId() == GID_IHNM && vm->isMacResources()) { - // Just set an XMIDI parser for Mac IHNM for now + if (!memcmp(buffer->getBuffer(), "FORM", 4)) { _parser = MidiParser::createParser_XMIDI(); + // ITE had MT32 mapped instruments + _isGM = (vm->getGameId() != GID_ITE); } else { - if (!memcmp(buffer->getBuffer(), "FORM", 4)) { - _parser = MidiParser::createParser_XMIDI(); - // ITE had MT32 mapped instruments - _isGM = (vm->getGameId() != GID_ITE); - } else { - _parser = MidiParser::createParser_SMF(); - // ITE with standalone MIDI files is General MIDI - _isGM = (vm->getGameId() == GID_ITE); - } + _parser = MidiParser::createParser_SMF(); + // ITE with standalone MIDI files is General MIDI + _isGM = (vm->getGameId() == GID_ITE); } if (!_parser->loadMusic(buffer->getBuffer(), buffer->size())) @@ -107,6 +103,27 @@ void MusicDriver::play(SagaEngine *vm, ByteArray *buffer, bool loop) { _isPlaying = true; } +void MusicDriver::playQuickTime(const Common::String &musicName, bool loop) { + // IHNM Mac uses QuickTime MIDI + _parser = MidiParser::createParser_QT(); + _isGM = true; + + if (!((MidiParser_QT *)_parser)->loadFromContainerFile(musicName)) + error("MusicDriver::playQuickTime(): Failed to load file '%s'", musicName.c_str()); + + _parser->setTrack(0); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); + _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + _parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); + + // Handle music looping + _parser->property(MidiParser::mpAutoLoop, loop); +// _isLooping = loop; + + _isPlaying = true; +} + void MusicDriver::pause() { _isPlaying = false; } @@ -343,31 +360,19 @@ void Music::play(uint32 resourceId, MusicFlags flags) { // Load MIDI/XMI resource data if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { - // Load the external music file for Mac IHNM -#if 0 - Common::File musicFile; - char musicFileName[40]; - sprintf(musicFileName, "Music/Music%02x", resourceId); - musicFile.open(musicFileName); - resourceSize = musicFile.size(); - resourceData = new byte[resourceSize]; - musicFile.read(resourceData, resourceSize); - musicFile.close(); - - // TODO: The Mac music format is unsupported (QuickTime MIDI) - // so stop here -#endif - return; + // Load the external music file for Mac IHNM + _player->playQuickTime(Common::String::format("Music/Music%02x", resourceId), flags & MUSIC_LOOP); } else { if (_currentMusicBuffer == &_musicBuffer[1]) { _currentMusicBuffer = &_musicBuffer[0]; } else { _currentMusicBuffer = &_musicBuffer[1]; } + _vm->_resource->loadResource(_musicContext, resourceId, *_currentMusicBuffer); + _player->play(_vm, _currentMusicBuffer, (flags & MUSIC_LOOP)); } - _player->play(_vm, _currentMusicBuffer, (flags & MUSIC_LOOP)); setVolume(_vm->_musicVolume); } diff --git a/engines/saga/music.h b/engines/saga/music.h index 5a4e662af4..081fab21f6 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -46,6 +46,7 @@ public: MusicDriver(); void play(SagaEngine *vm, ByteArray *buffer, bool loop); + void playQuickTime(const Common::String &musicName, bool loop); virtual void pause(); virtual void resume(); diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp index 1b0dfa2f22..8025a949d4 100644 --- a/engines/saga/resource.cpp +++ b/engines/saga/resource.cpp @@ -200,15 +200,15 @@ bool Resource::createContexts() { //// Detect and add voice files ///////////////////////////////////////////// SoundFileInfo voiceFiles[] = { - { GID_ITE, "voices.rsc", false , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, - { GID_ITE, "voices.cmp", true , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, - { GID_ITE, "voicesd.rsc", false , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, - { GID_ITE, "voicesd.cmp", true , (_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, + { GID_ITE, "voices.rsc", false , (uint16)((_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0)}, + { GID_ITE, "voices.cmp", true , (uint16)((_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0)}, + { GID_ITE, "voicesd.rsc", false , (uint16)((_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0)}, + { GID_ITE, "voicesd.cmp", true , (uint16)((_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0)}, // The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but // the voice file is big endian. If we got such a version with mixed files, mark this voice file // as big endian - { GID_ITE, "inherit the earth voices", false , _vm->isBigEndian() ? 0 : GAME_SWAPENDIAN}, - { GID_ITE, "inherit the earth voices.cmp", true , _vm->isBigEndian() ? 0 : GAME_SWAPENDIAN}, + { GID_ITE, "inherit the earth voices", false , (uint16)(_vm->isBigEndian() ? 0 : GAME_SWAPENDIAN)}, + { GID_ITE, "inherit the earth voices.cmp", true , (uint16)(_vm->isBigEndian() ? 0 : GAME_SWAPENDIAN)}, { GID_ITE, "ite voices.bin", false , GAME_MACBINARY}, #ifdef ENABLE_IHNM { GID_IHNM, "voicess.res", false , 0}, diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index 6e272d37c0..239a3be9db 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -202,6 +202,8 @@ SagaEngine::~SagaEngine() { } Common::Error SagaEngine::run() { + setTotalPlayTime(0); + // Assign default values to the config manager, in case settings are missing ConfMan.registerDefault("talkspeed", "255"); ConfMan.registerDefault("subtitles", "true"); diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 829425aeaf..01cab21f5d 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -395,9 +395,7 @@ enum ColorId { kITEColorBlue = 0x93, kITEColorLightBlue94 = 0x94, kITEColorLightBlue96 = 0x96, - kITEColorGreen = 0xba, - - kIHNMColorPortrait = 0xfe + kITEColorGreen = 0xba }; enum KnownColor { diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp index 6a5a7d8e14..3cd44eba40 100644 --- a/engines/saga/saveload.cpp +++ b/engines/saga/saveload.cpp @@ -34,7 +34,7 @@ #include "saga/scene.h" #include "saga/script.h" -#define CURRENT_SAGA_VER 7 +#define CURRENT_SAGA_VER 8 namespace Saga { @@ -204,10 +204,11 @@ void SagaEngine::save(const char *fileName, const char *saveName) { uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); uint16 saveTime = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); + uint32 playTime = g_engine->getTotalPlayTime() / 1000; out->writeUint32BE(saveDate); out->writeUint16BE(saveTime); - // TODO: played time + out->writeUint32BE(playTime); // Surrounding scene out->writeSint32LE(_scene->getOutsetSceneNumber()); @@ -299,7 +300,11 @@ void SagaEngine::load(const char *fileName) { in->readUint32BE(); // save date in->readUint16BE(); // save time - // TODO: played time + + if (_saveHeader.version >= 8) { + uint32 playTime = in->readUint32BE(); + g_engine->setTotalPlayTime(playTime * 1000); + } } // Clear pending events here, and don't process queued music events diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 35d923f821..75876b1c90 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -41,9 +41,10 @@ #include "saga/actor.h" #include "saga/resource.h" -#include "graphics/iff.h" #include "common/util.h" +#include "graphics/decoders/iff.h" + namespace Saga { static int initSceneDoors[SCENE_DOORS_MAX] = { @@ -450,11 +451,11 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy debug(5, "Scene::changeScene(%d, %d, %d, %d)", sceneNumber, actorsEntrance, transitionType, chapter); // This is used for latter ITE demos where all places on world map except - // Tent Faire are substituted with LBM picture and short description + // Tent Faire are substituted with IFF picture and short description if (_vm->_hasITESceneSubstitutes) { for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++) { if (sceneSubstitutes[i].sceneId == sceneNumber) { - byte *pal, colors[768]; + const byte *pal; Common::File file; Rect rect; PalEntry cPal[PAL_ENTRIES]; @@ -462,12 +463,12 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy _vm->_interface->setMode(kPanelSceneSubstitute); if (file.open(sceneSubstitutes[i].image)) { - Graphics::Surface bbmBuffer; - Graphics::decodePBM(file, bbmBuffer, colors); - pal = colors; - rect.setWidth(bbmBuffer.w); - rect.setHeight(bbmBuffer.h); - _vm->_gfx->drawRegion(rect, (const byte*)bbmBuffer.pixels); + Graphics::IFFDecoder decoder; + decoder.loadStream(file); + pal = decoder.getPalette(); + rect.setWidth(decoder.getSurface()->w); + rect.setHeight(decoder.getSurface()->h); + _vm->_gfx->drawRegion(rect, (const byte *)decoder.getSurface()->pixels); for (int j = 0; j < PAL_ENTRIES; j++) { cPal[j].red = *pal++; cPal[j].green = *pal++; diff --git a/engines/saga/sfuncs_ihnm.cpp b/engines/saga/sfuncs_ihnm.cpp index 3fbf3b6e67..fdfd0fdf2c 100644 --- a/engines/saga/sfuncs_ihnm.cpp +++ b/engines/saga/sfuncs_ihnm.cpp @@ -168,17 +168,25 @@ void Script::sfSetChapterPoints(SCRIPTFUNC_PARAMS) { _vm->_ethicsPoints[chapter] = thread->pop(); int16 barometer = thread->pop(); static PalEntry cur_pal[PAL_ENTRIES]; + PalEntry portraitBgColor = _vm->_interface->_portraitBgColor; + byte portraitColor = (_vm->getLanguage() == Common::ES_ESP) ? 253 : 254; _vm->_spiritualBarometer = _vm->_ethicsPoints[chapter] * 256 / barometer; _vm->_scene->setChapterPointsChanged(true); // don't save this music when saving in IHNM + // Set the portrait bg color, in case a saved state is restored from the + // launcher. In this case, sfSetPortraitBgColor is not called, thus the + // portrait color will always be 0 (black). + if (portraitBgColor.red == 0 && portraitBgColor.green == 0 && portraitBgColor.blue == 0) + portraitBgColor.green = 255; + if (_vm->_spiritualBarometer > 255) - _vm->_gfx->setPaletteColor(kIHNMColorPortrait, 0xff, 0xff, 0xff); + _vm->_gfx->setPaletteColor(portraitColor, 0xff, 0xff, 0xff); else - _vm->_gfx->setPaletteColor(kIHNMColorPortrait, - _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.red / 256, - _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.green / 256, - _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.blue / 256); + _vm->_gfx->setPaletteColor(portraitColor, + _vm->_spiritualBarometer * portraitBgColor.red / 256, + _vm->_spiritualBarometer * portraitBgColor.green / 256, + _vm->_spiritualBarometer * portraitBgColor.blue / 256); _vm->_gfx->getCurrentPal(cur_pal); _vm->_gfx->setPalette(cur_pal); diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 5ae8245e5a..1bf3323a7b 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -3633,6 +3633,8 @@ bool Console::cmdAddresses(int argc, const char **argv) { DebugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n"); DebugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n"); DebugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n"); + DebugPrintf(" Underscores are used as substitute characters for spaces in object names.\n"); + DebugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n"); return true; } @@ -3764,6 +3766,8 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV charsCountObject++; if ((*strLoop >= 'I') && (*strLoop <= 'Z')) charsCountObject++; + if (*strLoop == '_') // underscores are used as substitutes for spaces in object names + charsCountObject++; } strLoop++; } @@ -3836,10 +3840,16 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV index = strtol(tmp + 1, &endptr, 16); if (*endptr) return -1; - // Chop of the index + // Chop off the index str_objname = Common::String(str_objname.c_str(), tmp); } + // Replace all underscores in the name with spaces + for (uint i = 0; i < str_objname.size(); i++) { + if (str_objname[i] == '_') + str_objname.setChar(' ', i); + } + // Now all values are available; iterate over all objects. *dest = s->_segMan->findObjectByName(str_objname, index); if (dest->isNull()) diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp index 82af6eca43..306825008d 100644 --- a/engines/sci/decompressor.cpp +++ b/engines/sci/decompressor.cpp @@ -590,6 +590,8 @@ void DecompressorLZW::reorderView(byte *src, byte *dest) { if (celindex < cel_total) { warning("View decompression generated too few (%d / %d) headers", celindex, cel_total); + free(cc_pos); + free(cc_lengths); return; } diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 8e8b818854..5640319e3f 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -581,6 +581,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Freddy Pharkas - French DOS Floppy (supplied by misterhands in bug report #3589449) + // Executable scanning reports "1.cfs.081" + {"freddypharkas", "Floppy", { + {"resource.map", 0, "a32674e7fbf7b213b4a066c8037f16b6", 5816}, + {"resource.000", 0, "fed4808fdb72486908ac7ad0044b14d8", 5233230}, + {"resource.msg", 0, "4dc478f5c73b57e5d690bdfffdcf1c44", 816518}, + AD_LISTEND}, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Freddy Pharkas - Windows (supplied by abevi in bug report #2612718) // Executable scanning reports "1.cfs.081" // SCI interpreter version 1.001.132 (just a guess) @@ -3121,6 +3130,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 3 - French DOS v1.1 (supplied by misterhands in bug report #3586214) + // Executable scanning reports "L.rry.083" + {"qfg3", "", { + {"resource.map", 0, "19e2bf9b693932b5e2bb59b9f9ab86c9", 5958}, + {"resource.000", 0, "6178ad2e83e58e4671ca03315f7a6498", 5868000}, + {"resource.msg", 0, "0fa1047002df904b8d1807bb7bab4fab", 267210}, + AD_LISTEND}, + Common::FR_FRA, Common::kPlatformPC, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 3 - Spanish DOS CD (from jvprat) // Executable scanning reports "L.rry.083", VERSION file reports "1.000.000, June 30, 1994" {"qfg3", "", { @@ -3281,7 +3299,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.msg", 0, "1aeafe2b495de288d002109650b66614", 1364}, {"resource.000", 0, "8e10d4f05c1fd9f883384fa38a898489", 377394}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Slater & Charlie Go Camping - English DOS/Windows {"slater", "", { @@ -3289,7 +3307,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044}, {"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Slater & Charlie Go Camping - English DOS/Windows (Sierra Originals) @@ -3298,7 +3316,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "21f85414124dc23e54544a5536dc35cd", 4044}, {"resource.msg", 0, "c44f51fb955eae266fecf360ebcd5ad2", 1132}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Slater & Charlie Go Camping - English Macintosh {"slater", "", { @@ -3628,7 +3646,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ed90a8e3ccc53af6633ff6ab58392bae", 7054}, {"resource.000", 0, "63247e3901ab8963d4eece73747832e0", 5157378}, AD_LISTEND}, - Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO5(GUIO_MIDIGM, GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + Common::EN_ANY, Common::kPlatformPC, ADGF_CD, GUIO4(GAMEOPTION_SQ4_SILVER_CURSORS, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Space Quest 4 - English Windows CD (from the Space Quest Collection) // Executable scanning reports "1.001.064", VERSION file reports "1.0" diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index f985a69ebc..e3ebce80fb 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -427,18 +427,23 @@ reg_t kUpdatePlane(EngineState *s, int argc, reg_t *argv); reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv); reg_t kGetHighPlanePri(EngineState *s, int argc, reg_t *argv); reg_t kFrameOut(EngineState *s, int argc, reg_t *argv); + reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv); // kOnMe for SCI2, kIsOnMe for SCI2.1 +reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); +reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv); + reg_t kListIndexOf(EngineState *s, int argc, reg_t *argv); reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv); reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv); reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv); -reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); -reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv); + reg_t kEditText(EngineState *s, int argc, reg_t *argv); reg_t kMakeSaveCatName(EngineState *s, int argc, reg_t *argv); reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv); reg_t kSetScroll(EngineState *s, int argc, reg_t *argv); reg_t kPalCycle(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryUnknown2(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions reg_t kText(EngineState *s, int argc, reg_t *argv); @@ -513,7 +518,6 @@ reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv); -reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv); reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv); reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index d0c9b9b1cf..d7858180f1 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -156,7 +156,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { // signature for SCI21 should be "o" { SIG_SOUNDSCI21, 9, MAP_CALL(DoSoundStop), NULL, NULL }, { SIG_SOUNDSCI21, 10, MAP_CALL(DoSoundPause), NULL, NULL }, - { SIG_SOUNDSCI21, 11, MAP_CALL(DoSoundFade), NULL, NULL }, + { SIG_SOUNDSCI21, 11, MAP_CALL(DoSoundFade), NULL, kDoSoundFade_workarounds }, { SIG_SOUNDSCI21, 12, MAP_CALL(DoSoundSetHold), NULL, NULL }, { SIG_SOUNDSCI21, 13, MAP_CALL(DoSoundDummy), NULL, NULL }, { SIG_SOUNDSCI21, 14, MAP_CALL(DoSoundSetVolume), NULL, NULL }, @@ -202,7 +202,10 @@ static const SciKernelMapSubEntry kPalVary_subops[] = { { SIG_SCIALL, 4, MAP_CALL(PalVaryChangeTarget), "i", NULL }, { SIG_SCIALL, 5, MAP_CALL(PalVaryChangeTicks), "i", NULL }, { SIG_SCIALL, 6, MAP_CALL(PalVaryPauseResume), "i", NULL }, +#ifdef ENABLE_SCI32 { SIG_SCI32, 8, MAP_CALL(PalVaryUnknown), "i", NULL }, + { SIG_SCI32, 9, MAP_CALL(PalVaryUnknown2), "i", NULL }, +#endif SCI_SUBOPENTRY_TERMINATOR }; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index da377319c0..a65bcc215e 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -722,11 +722,6 @@ reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } -reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv) { - // Unknown (seems to be SCI32 exclusive) - return NULL_REG; -} - reg_t kAssertPalette(EngineState *s, int argc, reg_t *argv) { GuiResourceId paletteId = argv[0].toUint16(); diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 8b3afeef99..cd735d1233 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -323,19 +323,29 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { uint16 op = argv[0].toUint16(); switch (op) { case 0: // Init + // TODO: Init reads the nsLeft, nsTop, nsRight, nsBottom, + // borderColor, fore, back, mode, font, plane selectors + // from the window in argv[1]. g_sci->_gfxFrameout->initScrollText(argv[2].toUint16()); // maxItems g_sci->_gfxFrameout->clearScrollTexts(); return argv[1]; // kWindow case 1: // Show message, called by ScrollableWindow::addString case 14: // Modify message, called by ScrollableWindow::modifyString - // 5 or 6 parameters - // Seems to be called with 5 parameters when the narrator speaks, and - // with 6 when Roger speaks + // TODO: The parameters in Modify are shifted by one: the first + // argument is the handle of the text to modify. The others + // are as Add. { Common::String text = s->_segMan->getString(argv[2]); - uint16 x = 0;//argv[3].toUint16(); // TODO: can't be x (values are all wrong) - uint16 y = 0;//argv[4].toUint16(); // TODO: can't be y (values are all wrong) - // TODO: argv[5] is an optional unknown parameter (an integer set to 0) + uint16 x = 0; + uint16 y = 0; + // TODO: argv[3] is font + // TODO: argv[4] is color + // TODO: argv[5] is alignment (0 = left, 1 = center, 2 = right) + // font,color,alignment may also be -1. (Maybe same as previous?) + // TODO: argv[6] is an optional bool, defaulting to true if not present. + // If true, the old contents are scrolled out of view. + // TODO: Return a handle of the inserted text. (Used for modify/insert) + // This handle looks like it should also be usable by kString. g_sci->_gfxFrameout->addScrollTextEntry(text, kWindow, x, y, (op == 14)); } break; @@ -363,22 +373,27 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxFrameout->lastScrollText(); break; case 9: // Resize, called by ScrollableWindow::resize and ScrollerWindow::resize - // TODO + // TODO: This reads the nsLeft, nsTop, nsRight, nsBottom + // selectors from the SCI object passed in argv[2]. kStub(s, argc, argv); break; case 10: // Where, called by ScrollableWindow::where - // TODO - // argv[2] is an unknown integer + // TODO: + // Gives the current relative scroll location as a fraction + // with argv[2] as the denominator. (Return value is the numerator.) // Silenced the warnings because of the high amount of console spam //kStub(s, argc, argv); break; case 11: // Go, called by ScrollableWindow::scrollTo - // 2 extra parameters here - // TODO + // TODO: + // Two arguments provide a fraction: argv[2] is num., argv[3] is denom. + // Scrolls to the relative location given by the fraction. kStub(s, argc, argv); break; case 12: // Insert, called by ScrollableWindow::insertString - // 3 extra parameters here + // 5 extra parameters here: + // handle of insert location (new string takes that position). + // text, font, color, alignment // TODO kStub(s, argc, argv); break; @@ -668,6 +683,22 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) { return kStub(s, argc, argv); } +reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv) { + // TODO: Unknown (seems to be SCI32 exclusive) + return kStub(s, argc, argv); +} + +reg_t kPalVaryUnknown2(EngineState *s, int argc, reg_t *argv) { + // TODO: Unknown (seems to be SCI32 exclusive) + // It seems to be related to the day/night palette effects in QFG4, and + // accepts a palette resource ID. It is triggered right when the night + // effect is initially applied (when exiting the caves). + // In QFG4, there are two scene palettes: 790 for night, and 791 for day. + // Initially, the game starts at night time, but this is called with the + // ID of the day time palette (i.e. 791). + return kStub(s, argc, argv); +} + reg_t kPalCycle(EngineState *s, int argc, reg_t *argv) { // Examples: GK1 room 480 (Bayou ritual), LSL6 room 100 (title screen) diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index 4b8fadbb84..b2aaa01b45 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -77,18 +77,7 @@ reg_t kSqrt(EngineState *s, int argc, reg_t *argv) { return make_reg(0, (int16) sqrt((float) ABS(argv[0].toSint16()))); } -/** - * Returns the angle (in degrees) between the two points determined by (x1, y1) - * and (x2, y2). The angle ranges from 0 to 359 degrees. - * What this function does is pretty simple but apparently the original is not - * accurate. - */ -uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { - // SCI1 games (QFG2 and newer) use a simple atan implementation. SCI0 games - // use a somewhat less accurate calculation (below). - if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) - return (int16)(360 - atan2((double)(x1 - x2), (double)(y1 - y2)) * 57.2958) % 360; - +uint16 kGetAngle_SCI0(int16 x1, int16 y1, int16 x2, int16 y2) { int16 xRel = x2 - x1; int16 yRel = y1 - y2; // y-axis is mirrored. int16 angle; @@ -118,6 +107,75 @@ uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { return angle; } +// atan2 for first octant, x >= y >= 0. Returns [0,45] (inclusive) +int kGetAngle_SCI1_atan2_base(int y, int x) { + if (x == 0) + return 0; + + // fixed point tan(a) + int tan_fp = 10000 * y / x; + + if ( tan_fp >= 1000 ) { + // For tan(a) >= 0.1, interpolate between multiples of 5 degrees + + // 10000 * tan([5, 10, 15, 20, 25, 30, 35, 40, 45]) + const int tan_table[] = { 875, 1763, 2679, 3640, 4663, 5774, + 7002, 8391, 10000 }; + + // Look up tan(a) in our table + int i = 1; + while (tan_fp > tan_table[i]) ++i; + + // The angle a is between 5*i and 5*(i+1). We linearly interpolate. + int dist = tan_table[i] - tan_table[i-1]; + int interp = (5 * (tan_fp - tan_table[i-1]) + dist/2) / dist; + return 5*i + interp; + } else { + // for tan(a) < 0.1, tan(a) is approximately linear in a. + // tan'(0) = 1, so in degrees the slope of atan is 180/pi = 57.29... + return (57 * y + x/2) / x; + } +} + +int kGetAngle_SCI1_atan2(int y, int x) { + if (y < 0) { + int a = kGetAngle_SCI1_atan2(-y, -x); + if (a == 180) + return 0; + else + return 180 + a; + } + if (x < 0) + return 90 + kGetAngle_SCI1_atan2(-x, y); + if (y > x) + return 90 - kGetAngle_SCI1_atan2_base(x, y); + else + return kGetAngle_SCI1_atan2_base(y, x); + +} + +uint16 kGetAngle_SCI1(int16 x1, int16 y1, int16 x2, int16 y2) { + // We flip things around to get into the standard atan2 coordinate system + return kGetAngle_SCI1_atan2(x2 - x1, y1 - y2); + +} + +/** + * Returns the angle (in degrees) between the two points determined by (x1, y1) + * and (x2, y2). The angle ranges from 0 to 359 degrees. + * What this function does is pretty simple but apparently the original is not + * accurate. + */ + +uint16 kGetAngleWorker(int16 x1, int16 y1, int16 x2, int16 y2) { + if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) + return kGetAngle_SCI1(x1, y1, x2, y2); + else + return kGetAngle_SCI0(x1, y1, x2, y2); +} + + + reg_t kGetAngle(EngineState *s, int argc, reg_t *argv) { // Based on behavior observed with a test program created with // SCI Studio. diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index c4db0b891c..65e139e1ee 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -155,30 +155,47 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) { source++; /* Skip whitespace */ int16 result = 0; + int16 sign = 1; + if (*source == '-') { + sign = -1; + source++; + } if (*source == '$') { // Hexadecimal input - result = (int16)strtol(source + 1, NULL, 16); + source++; + char c; + while ((c = *source++) != 0) { + int16 x = 0; + if ((c >= '0') && (c <= '9')) + x = c - '0'; + else if ((c >= 'a') && (c <= 'f')) + x = c - 'a' + 10; + else if ((c >= 'A') && (c <= 'F')) + x = c - 'A' + 10; + else + // Stop if we encounter anything other than a digit (like atoi) + break; + result *= 16; + result += x; + } } else { // Decimal input. We can not use strtol/atoi in here, because while // Sierra used atoi, it was a non standard compliant atoi, that didn't // do clipping. In SQ4 we get the door code in here and that's even // larger than uint32! - if (*source == '-') { - // FIXME: Setting result to -1 does _not_ negate the output. - result = -1; - source++; - } - while (*source) { - if ((*source < '0') || (*source > '9')) + char c; + while ((c = *source++) != 0) { + if ((c < '0') || (c > '9')) // Stop if we encounter anything other than a digit (like atoi) break; result *= 10; - result += *source - 0x30; - source++; + result += c - '0'; } } + result *= sign; + return make_reg(0, result); } @@ -489,6 +506,7 @@ reg_t kGetMessage(EngineState *s, int argc, reg_t *argv) { reg_t kMessage(EngineState *s, int argc, reg_t *argv) { uint func = argv[0].toUint16(); + uint16 module = (argc >= 2) ? argv[1].toUint16() : 0; #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { @@ -518,19 +536,44 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { if (argc >= 6) tuple = MessageTuple(argv[2].toUint16(), argv[3].toUint16(), argv[4].toUint16(), argv[5].toUint16()); + // WORKAROUND for a script bug in Pepper. When using objects together, + // there is code inside script 894 that shows appropriate messages. + // In the case of the jar of cabbage (noun 26), the relevant message + // shown when using any object with it is missing. This leads to the + // script code being triggered, which modifies the jar's noun and + // message selectors, and renders it useless. Thus, when using any + // object with the jar of cabbage, it's effectively corrupted, and + // can't be used on the goat to empty it, therefore the game reaches + // an unsolvable state. It's almost impossible to patch the offending + // script, as it is used in many cases. But we can prevent the + // corruption of the jar here: if the message is found, the offending + // code is never reached and the jar is never corrupted. To do this, + // we substitute all verbs on the cabbage jar with the default verb, + // which shows the "Cannot use this object with the jar" message, and + // never triggers the offending script code that corrupts the object. + // This only affects the jar of cabbage - any other object, including + // the empty jar has a different noun, thus it's unaffected. + // Fixes bug #3601090. + // NOTE: To fix a corrupted jar object, type "send Glass_Jar message 52" + // in the debugger. + if (g_sci->getGameId() == GID_PEPPER && func == 0 && argc >= 6 && module == 894 && + tuple.noun == 26 && tuple.cond == 0 && tuple.seq == 1 && + !s->_msgState->getMessage(module, tuple, NULL_REG)) + tuple.verb = 0; + switch (func) { case K_MESSAGE_GET: - return make_reg(0, s->_msgState->getMessage(argv[1].toUint16(), tuple, (argc == 7 ? argv[6] : NULL_REG))); + return make_reg(0, s->_msgState->getMessage(module, tuple, (argc == 7 ? argv[6] : NULL_REG))); case K_MESSAGE_NEXT: return make_reg(0, s->_msgState->nextMessage((argc == 2 ? argv[1] : NULL_REG))); case K_MESSAGE_SIZE: - return make_reg(0, s->_msgState->messageSize(argv[1].toUint16(), tuple)); + return make_reg(0, s->_msgState->messageSize(module, tuple)); case K_MESSAGE_REFCOND: case K_MESSAGE_REFVERB: case K_MESSAGE_REFNOUN: { MessageTuple t; - if (s->_msgState->messageRef(argv[1].toUint16(), tuple, t)) { + if (s->_msgState->messageRef(module, tuple, t)) { switch (func) { case K_MESSAGE_REFCOND: return make_reg(0, t.cond); @@ -545,9 +588,9 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { } case K_MESSAGE_LASTMESSAGE: { MessageTuple msg; - int module; + int lastModule; - s->_msgState->lastQuery(module, msg); + s->_msgState->lastQuery(lastModule, msg); bool ok = false; @@ -556,7 +599,7 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { if (buffer) { ok = true; - WRITE_LE_UINT16(buffer, module); + WRITE_LE_UINT16(buffer, lastModule); WRITE_LE_UINT16(buffer + 2, msg.noun); WRITE_LE_UINT16(buffer + 4, msg.verb); WRITE_LE_UINT16(buffer + 6, msg.cond); @@ -567,7 +610,7 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { if (buffer) { ok = true; - buffer[0] = make_reg(0, module); + buffer[0] = make_reg(0, lastModule); buffer[1] = make_reg(0, msg.noun); buffer[2] = make_reg(0, msg.verb); buffer[3] = make_reg(0, msg.cond); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index ff3f19b53d..b2d95c599e 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -696,8 +696,9 @@ void GfxPalette::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_palVaryPaused); } + _palVarySignal = 0; + if (s.isLoading() && _palVaryResourceId != -1) { - _palVarySignal = 0; palVaryInstallTimer(); } } diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 8639b6ef71..c928cf3569 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -883,12 +883,38 @@ const uint16 qfg1vgaPatchDialogHeader[] = { PATCH_END }; +// When clicking on the crusher in room 331, Ego approaches him to talk to him, +// an action that is handled by moveToCrusher::changeState in script 331. The +// scripts set Ego to move close to the crusher, but when Ego is running instead +// of walking, the target coordinates specified by script 331 are never reached, +// as Ego is making larger steps, and never reaches the required spot. This is an +// edge case that can occur when Ego is set to run. Normally, when clicking on +// the crusher, ego is supposed to move close to position 79, 165. We change it +// to 85, 165, which is not an edge case thus the freeze is avoided. +// Fixes bug #3585189. +const byte qfg1vgaSignatureMoveToCrusher[] = { + 9, + 0x51, 0x1f, // class Motion + 0x36, // push + 0x39, 0x4f, // pushi 4f (79 - x) + 0x38, 0xa5, 0x00, // pushi 00a5 (165 - y) + 0x7c, // pushSelf + 0 +}; + +const uint16 qfg1vgaPatchMoveToCrusher[] = { + PATCH_ADDTOOFFSET | +3, + 0x39, 0x55, // pushi 55 (85 - x) + PATCH_END +}; + // script, description, magic DWORD, adjust const SciScriptSignature qfg1vgaSignatures[] = { { 215, "fight event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, { 216, "weapon master event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents }, { 814, "window text temp space", 1, PATCH_MAGICDWORD(0x3f, 0xba, 0x87, 0x00), 0, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace }, { 814, "dialog header offset", 3, PATCH_MAGICDWORD(0x5b, 0x04, 0x80, 0x36), 0, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader }, + { 331, "moving to crusher", 1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39), 0, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher }, SCI_SIGNATUREENTRY_TERMINATOR }; diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index db510c2545..ff7e601fcb 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -140,7 +140,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_QFG2, 260, 260, 0, "jabbarS", "changeState",0x2d22, -1, { WORKAROUND_FAKE, 0 } }, // During the thief's first mission (in the house), just before Jabbar is about to enter the house (where you have to hide in the wardrobe), bug #3040469, temps 1 and 2 { GID_QFG2, 500, 500, 0, "lightNextCandleS", "changeState", -1, -1, { WORKAROUND_FAKE, 0 } }, // Inside the last room, while Ad Avis performs the ritual to summon the genie - bug #3148418 { GID_QFG2, -1, 700, 0, NULL, "showSign", -1, 10, { WORKAROUND_FAKE, 0 } }, // Occurs sometimes when reading a sign in Raseir, Shapeir et al - bugs #3272735, #3275413 - { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #3049435 + { GID_QFG3, 510, 510, 0, "awardPrize", "changeState", -1, 0, { WORKAROUND_FAKE, 1 } }, // Simbani warrior challenge, after throwing the spears and retrieving the ring - bug #3049435. Must be non-zero, otherwise the prize is awarded twice - bug #3575570. { GID_QFG3, 140, 140, 0, "rm140", "init", 0x1008, 0, { WORKAROUND_FAKE, 0 } }, // when importing a character and selecting the previous profession - bug #3040460 { GID_QFG3, 330, 330, -1, "Teller", "doChild", -1, -1, { WORKAROUND_FAKE, 0 } }, // when talking to King Rajah about "Rajah" (bug #3036390, temp 1) or "Tarna" (temp 0), or when clicking on yourself and saying "Greet" (bug #3039774, temp 1) { GID_QFG3, 700, 700, -1, "monsterIsDead", "changeState", -1, 0, { WORKAROUND_FAKE, 0 } }, // in the jungle, after winning any fight, bug #3040624 @@ -151,6 +151,8 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_QFG4, -1, 15, -1, "charInitScreen", "dispatchEvent", -1, 5, { WORKAROUND_FAKE, 0 } }, // floppy version, when viewing the character screen { GID_QFG4, -1, 64917, -1, "controlPlane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, when entering the game menu { GID_QFG4, -1, 64917, -1, "Plane", "setBitmap", -1, 3, { WORKAROUND_FAKE, 0 } }, // floppy version, happens sometimes in fight scenes + { GID_QFG4, 520, 64950, 0, "fLake2", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD version, at the lake, when meeting the Rusalka and attempting to leave + { GID_QFG4, 800, 64950, 0, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // CD version, in the room with the spider pillar, when climbing on the pillar { GID_RAMA, 12, 64950, -1, "InterfaceFeature", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts { GID_RAMA, 12, 64950, -1, "hiliteOptText", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts { GID_RAMA, 12, 64950, -1, "View", "handleEvent", -1, 0, { WORKAROUND_FAKE, 0 } }, // Demo, right when it starts @@ -246,6 +248,7 @@ const SciWorkaroundEntry kDoSoundFade_workarounds[] = { { GID_KQ5, 213, 989, 0, "globalSound3", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #3037594 { GID_KQ6, 105, 989, 0, "globalSound", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // floppy: during intro, parameter 4 is an object { GID_KQ6, 460, 989, 0, "globalSound2", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // after pulling the black widow's web on the isle of wonder, parameter 4 is an object - bug #3034567 + { GID_QFG4, -1, 64989, 0, "longSong", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // CD version: many places, parameter 4 is an object (longSong) SCI_WORKAROUNDENTRY_TERMINATOR }; diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 14443db1e2..7318fe2f68 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -160,9 +160,15 @@ SciEvent EventManager::getScummVMEvent() { noEvent.mousePos = input.mousePos = mousePos; - if (!found || ev.type == Common::EVENT_MOUSEMOVE) - return noEvent; + if (!found || ev.type == Common::EVENT_MOUSEMOVE) { + int modifiers = em->getModifierState(); + noEvent.modifiers = + ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) | + ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) | + ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0); + return noEvent; + } if (ev.type == Common::EVENT_QUIT) { input.type = SCI_EVENT_QUIT; return input; diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index 5e2e39ea1a..52da7d6ec6 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -51,7 +51,6 @@ enum ViewScaleSignals { kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY) kScaleSignalGlobalScaling = 0x0002, // means that global scaling shall get applied on that cel (sets scaleX/scaleY) kScaleSignalHoyle4SpecialHandling = 0x0004 // HOYLE4-exclusive: special handling inside kAnimate, is used when giving out cards - }; struct AnimateEntry { diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 8b7fa2c384..e251bd3dc0 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -349,6 +349,36 @@ void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) { } } +// Adapted from GfxAnimate::applyGlobalScaling() +void GfxFrameout::applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight) { + // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY + int16 maxScale = readSelectorValue(_segMan, itemEntry->object, SELECTOR(maxScale)); + int16 maxCelHeight = (maxScale * celHeight) >> 7; + reg_t globalVar2 = g_sci->getEngineState()->variables[VAR_GLOBAL][2]; // current room object + int16 vanishingY = readSelectorValue(_segMan, globalVar2, SELECTOR(vanishingY)); + + int16 fixedPortY = planeRect.bottom - vanishingY; + int16 fixedEntryY = itemEntry->y - vanishingY; + if (!fixedEntryY) + fixedEntryY = 1; + + if ((celHeight == 0) || (fixedPortY == 0)) + error("global scaling panic"); + + itemEntry->scaleY = (maxCelHeight * fixedEntryY) / fixedPortY; + itemEntry->scaleY = (itemEntry->scaleY * maxScale) / celHeight; + + // Make sure that the calculated value is sane + if (itemEntry->scaleY < 1 /*|| itemEntry->scaleY > 128*/) + itemEntry->scaleY = 128; + + itemEntry->scaleX = itemEntry->scaleY; + + // and set objects scale selectors + //writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleX), itemEntry->scaleX); + //writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleY), itemEntry->scaleY); +} + void GfxFrameout::kernelAddScreenItem(reg_t object) { // Ignore invalid items if (!_segMan->isObject(object)) { @@ -390,8 +420,15 @@ void GfxFrameout::kernelUpdateScreenItem(reg_t object) { itemEntry->priority = itemEntry->y; itemEntry->signal = readSelectorValue(_segMan, object, SELECTOR(signal)); - itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX)); - itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY)); + itemEntry->scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal)); + + if (itemEntry->scaleSignal & kScaleSignalDoScaling32) { + itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX)); + itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY)); + } else { + itemEntry->scaleX = 128; + itemEntry->scaleY = 128; + } itemEntry->visible = true; // Check if the entry can be hidden @@ -650,7 +687,13 @@ void GfxFrameout::kernelFrameout() { _paint32->fillRect(it->planeRect, it->planeBack); _coordAdjuster->pictureSetDisplayArea(it->planeRect); - _palette->drewPicture(it->pictureId); + // Invoking drewPicture() with an invalid picture ID in SCI32 results in + // invalidating the palVary palette when a palVary effect is active. This + // is quite obvious in QFG4, where the day time palette is incorrectly + // shown when exiting the caves, and the correct night time palette + // flashes briefly each time that kPalVaryInit is called. + if (it->pictureId != 0xFFFF) + _palette->drewPicture(it->pictureId); FrameoutList itemList; @@ -699,6 +742,14 @@ void GfxFrameout::kernelFrameout() { // TODO: maybe we should clip the cels rect with this, i'm not sure // the only currently known usage is game menu of gk1 } else if (view) { + // Process global scaling, if needed. + // TODO: Seems like SCI32 always processes global scaling for scaled objects + // TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY) + if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) && + !(itemEntry->scaleSignal & kScaleSignalDisableGlobalScaling32) && + (itemEntry->scaleX == itemEntry->scaleY)) + applyGlobalScaling(itemEntry, it->planeRect, view->getHeight(itemEntry->loopNo, itemEntry->celNo)); + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); @@ -726,7 +777,12 @@ void GfxFrameout::kernelFrameout() { continue; } - g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); + // FIXME: We should not update the object's NS rect here. + // This breaks the sliders in the control panel screen in + // QFG4, but disabling it does not change any functionality, + // as the object(s) will be drawn on screen with the + // calculated coordinates. + //g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); } // Don't attempt to draw sprites that are outside the visible diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 5fd2824224..5ef770486f 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -97,11 +97,18 @@ struct ScrollTextEntry { typedef Common::Array<ScrollTextEntry> ScrollTextList; +enum ViewScaleSignals32 { + kScaleSignalDoScaling32 = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY) + kScaleSignalUnk1 = 0x0002, // unknown + kScaleSignalDisableGlobalScaling32 = 0x0004 +}; + class GfxCache; class GfxCoordAdjuster32; class GfxPaint32; class GfxPalette; class GfxScreen; + /** * Frameout class, kFrameout and relevant functions for SCI32 games */ @@ -113,6 +120,7 @@ public: void kernelAddPlane(reg_t object); void kernelUpdatePlane(reg_t object); void kernelDeletePlane(reg_t object); + void applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight); void kernelAddScreenItem(reg_t object); void kernelUpdateScreenItem(reg_t object); void kernelDeleteScreenItem(reg_t object); diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 53d69cdcca..9b6eff6edc 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -386,9 +386,9 @@ void GfxPalette::setRemappingPercentGray(byte color, byte percent) { // Note: This is not what the original does, but the results are the same visually for (int i = 0; i < 256; i++) { - byte rComponent = _sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100; - byte gComponent = _sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100; - byte bComponent = _sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100; + byte rComponent = (byte)(_sysPalette.colors[i].r * _remappingPercentToSet * 0.30 / 100); + byte gComponent = (byte)(_sysPalette.colors[i].g * _remappingPercentToSet * 0.59 / 100); + byte bComponent = (byte)(_sysPalette.colors[i].b * _remappingPercentToSet * 0.11 / 100); byte luminosity = rComponent + gComponent + bComponent; _remappingByPercent[i] = kernelFindColor(luminosity, luminosity, luminosity); } @@ -722,11 +722,6 @@ void GfxPalette::kernelRestore(reg_t memoryHandle) { } void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { - // Sometimes invalid viewIds are asked for, ignore those (e.g. qfg1vga) - //if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId))) - // return; - // maybe we took the wrong parameter before, if this causes invalid view again, enable to commented out code again - GfxView *view = g_sci->_gfxCache->getView(resourceId); Palette *viewPalette = view->getPalette(); if (viewPalette) { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 15b18ce8e6..1f5c354d1f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -699,9 +699,11 @@ void SciEngine::runGame() { patchGameSaveRestore(); setLauncherLanguage(); _gamestate->gameIsRestarting = GAMEISRESTARTING_RESTART; + _gamestate->_throttleLastTime = 0; if (_gfxMenu) _gfxMenu->reset(); _gamestate->abortScriptProcessing = kAbortNone; + _gamestate->_syncedAudioOptions = false; } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { _gamestate->abortScriptProcessing = kAbortNone; _gamestate->_executionStack.clear(); @@ -713,6 +715,7 @@ void SciEngine::runGame() { syncSoundSettings(); syncIngameAudioOptions(); + // Games do not set their audio settings when loading } else { break; // exit loop } diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 7782ab4e48..a76b3b3876 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -116,7 +116,7 @@ void SoundCommandParser::processInitSound(reg_t obj) { newSound->resourceId = resourceId; newSound->soundObj = obj; newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); - newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF; + newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)) & 0xFF; if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); newSound->reverb = -1; // initialize to SCI invalid, it'll be set correctly in soundInitSnd() below @@ -441,7 +441,7 @@ reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) { int16 objVol = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, 255); if (objVol != musicSlot->volume) _music->soundSetVolume(musicSlot, objVol); - uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri)); + uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority)); if (objPrio != musicSlot->priority) _music->soundSetPriority(musicSlot, objPrio); return acc; diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index dc5acbdb7d..9b6dd1e687 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -741,10 +741,6 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { "Silence", "Shaping", "Unmaking", "Transcendence" }; - int odds[] = { - 15162, 15676, 16190, 64, 16961, 17475, 17989, 18503, - 73, 19274, 76, 77, 20302, 20816, 21330, 84 - }; const char *notes = "cdefgabC"; int i, base, draft; @@ -754,9 +750,9 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { return true; } - // There are 16 drafts, stored from variable 50 or 100 and upwards. - // Each draft occupies two variables. Even-numbered variables contain - // the notes for each draft, and a number of flags: + // There are 16 drafts, stored from variable 50, 55 or 100 and upwards. + // Each draft occupies two variables, the first of which contains the + // notes for the draft and a number of flags. // // +---+---+---+---+-----+-----+-----+-----+ // | A | B | C | D | 444 | 333 | 222 | 111 | @@ -771,13 +767,16 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { // 222 The second note // 111 The first note // - // I don't yet know what the odd-numbered variables are used for. - // Possibly they store information on where and/or how the draft can - // be used. They appear to remain constant throughout the game. + // I don't yet know what the second variable is used for. Possibly to + // store information on where and/or how the draft can be used. They + // appear to remain constant throughout the game. if (_vm->_game.version == 4 || _vm->_game.platform == Common::kPlatformPCEngine) { // DOS CD version / PC-Engine version base = 100; + } else if (_vm->_game.platform == Common::kPlatformMacintosh) { + // Macintosh version + base = 55; } else { // All (?) other versions base = 50; @@ -801,28 +800,13 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { DebugPrintf("Learned all drafts and notes.\n"); return true; } - - // During the testing of EGA Loom we had some trouble with the - // drafts data structure being overwritten. I don't expect - // this command is particularly useful any more, but it will - // attempt to repair the (probably) static part of it. - - if (strcmp(argv[1], "fix") == 0) { - for (i = 0; i < 16; i++) - _vm->_scummVars[base + 2 * i + 1] = odds[i]; - DebugPrintf( - "An attempt has been made to repair\n" - "the internal drafts data structure.\n" - "Continue on your own risk.\n"); - return true; - } } // Probably the most useful command for ordinary use: list the drafts. for (i = 0; i < 16; i++) { draft = _vm->_scummVars[base + i * 2]; - DebugPrintf("%d %-13s %c%c%c%c %c%c %5d %c\n", + DebugPrintf("%d %-13s %c%c%c%c %c%c\n", base + 2 * i, names[i], notes[draft & 0x0007], @@ -830,9 +814,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { notes[(draft & 0x01c0) >> 6], notes[(draft & 0x0e00) >> 9], (draft & 0x2000) ? 'K' : ' ', - (draft & 0x4000) ? 'U' : ' ', - _vm->_scummVars[base + 2 * i + 1], - (_vm->_scummVars[base + 2 * i + 1] != odds[i]) ? '!' : ' '); + (draft & 0x4000) ? 'U' : ' '); } return true; diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index ffff329036..50ff0b3988 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -3609,7 +3609,7 @@ void Gdi::unkDecode9(byte *dst, int dstPitch, const byte *src, int height) const int i; uint buffer = 0, mask = 128; int h = height; - i = run = 0; + run = 0; int x = 8; for (;;) { diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp index f94b74ac45..1afb1b4074 100644 --- a/engines/scumm/he/sound_he.cpp +++ b/engines/scumm/he/sound_he.cpp @@ -804,7 +804,7 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { byte *snd1Ptr, *snd2Ptr; byte *sbng1Ptr, *sbng2Ptr; byte *sdat1Ptr, *sdat2Ptr; - byte *src, *dst, *tmp; + byte *src, *dst; int len, offs, size; int sdat1size, sdat2size; @@ -844,6 +844,7 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { if (sbng1Ptr != NULL && sbng2Ptr != NULL) { if (chan != -1 && ((SoundHE *)_sound)->_heChannel[chan].codeOffs > 0) { + // Copy any code left over to the beginning of the code block int curOffs = ((SoundHE *)_sound)->_heChannel[chan].codeOffs; src = snd1Ptr + curOffs; @@ -851,29 +852,33 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { size = READ_BE_UINT32(sbng1Ptr + 4); len = sbng1Ptr - snd1Ptr + size - curOffs; - byte *data = (byte *)malloc(len); - memcpy(data, src, len); - memcpy(dst, data, len); - free(data); + memmove(dst, src, len); + // Now seek to the end of this code block dst = sbng1Ptr + 8; while ((size = READ_LE_UINT16(dst)) != 0) dst += size; } else { + // We're going to overwrite the code block completely dst = sbng1Ptr + 8; } - ((SoundHE *)_sound)->_heChannel[chan].codeOffs = sbng1Ptr - snd1Ptr + 8; + // Reset the current code offset to the beginning of the code block + if (chan >= 0) + ((SoundHE *)_sound)->_heChannel[chan].codeOffs = sbng1Ptr - snd1Ptr + 8; - tmp = sbng2Ptr + 8; + // Seek to the end of the code block for sound 2 + byte *tmp = sbng2Ptr + 8; while ((offs = READ_LE_UINT16(tmp)) != 0) { tmp += offs; } + // Copy the code block for sound 2 to the code block for sound 1 src = sbng2Ptr + 8; len = tmp - sbng2Ptr - 6; memcpy(dst, src, len); + // Rewrite the time for this new code block to be after the sound 1 code block int32 time; while ((size = READ_LE_UINT16(dst)) != 0) { time = READ_LE_UINT32(dst + 2); @@ -883,6 +888,7 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { } } + // Find the data pointers and sizes if (findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) { sdat1Ptr = findSoundTag(MKTAG('d','a','t','a'), snd1Ptr); assert(sdat1Ptr); @@ -906,6 +912,8 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { sdat1size = _sndDataSize - _sndPtrOffs; if (sdat2size < sdat1size) { + // We have space leftover at the end of sound 1 + // -> Just append sound 2 src = sdat2Ptr + 8; dst = sdat1Ptr + 8 + _sndPtrOffs; len = sdat2size; @@ -915,6 +923,8 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { _sndPtrOffs += sdat2size; _sndTmrOffs += sdat2size; } else { + // We might not have enough space leftover at the end of sound 1 + // -> Append as much of possible of sound 2 to sound 1 src = sdat2Ptr + 8; dst = sdat1Ptr + 8 + _sndPtrOffs; len = sdat1size; @@ -922,6 +932,8 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { memcpy(dst, src, len); if (sdat2size != sdat1size) { + // We don't have enough space + // -> Start overwriting the beginning of the sound again src = sdat2Ptr + 8 + sdat1size; dst = sdat1Ptr + 8; len = sdat2size - sdat1size; diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 016ba89e7b..b69ce552bc 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -363,7 +363,7 @@ void IMuseInternal::pause(bool paused) { _paused = paused; } -int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm) { +int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad) { Common::StackLock lock(_mutex, "IMuseInternal::save_or_load()"); const SaveLoadEntry mainEntries[] = { MKLINE(IMuseInternal, _queue_end, sleUint8, VER(8)), @@ -440,7 +440,16 @@ int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm) { for (i = 0; i < 8; ++i) ser->saveLoadEntries(0, volumeFaderEntries); - if (ser->isLoading()) { + // Normally, we have to fix up the data structures after loading a + // saved game. But there are cases where we don't. For instance, The + // Macintosh version of Monkey Island 1 used to convert the Mac0 music + // resources to General MIDI and play it through iMUSE as a rough + // approximation. Now it has its own player, but old savegame still + // have the iMUSE data in them. We have to skip that data, using a + // dummy iMUSE object, but since the resource is no longer recognizable + // to iMUSE, the fixup fails hard. So yes, this is a bit of a hack. + + if (ser->isLoading() && fixAfterLoad) { // Load all sounds that we need fix_players_after_load(scumm); fix_parts_after_load(); diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h index 23449e470b..cce5309229 100644 --- a/engines/scumm/imuse/imuse.h +++ b/engines/scumm/imuse/imuse.h @@ -62,7 +62,7 @@ public: public: virtual void on_timer(MidiDriver *midi) = 0; virtual void pause(bool paused) = 0; - virtual int save_or_load(Serializer *ser, ScummEngine *scumm) = 0; + virtual int save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad = true) = 0; virtual bool get_sound_active(int sound) const = 0; virtual int32 doCommand(int numargs, int args[]) = 0; virtual int clear_queue() = 0; diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index 846e2d7545..6be564a517 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -518,7 +518,7 @@ protected: public: // IMuse interface void pause(bool paused); - int save_or_load(Serializer *ser, ScummEngine *scumm); + int save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad = true); bool get_sound_active(int sound) const; int32 doCommand(int numargs, int args[]); uint32 property(int prop, uint32 value); diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 89c16a8bb5..5e928f3d44 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -111,8 +111,19 @@ void Part::saveLoadWithSerializer(Serializer *ser) { } void Part::set_detune(int8 detune) { - _detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127); - sendPitchBend(); + // Sam&Max does not have detune, so we just ignore this here. We still get + // this called, since Sam&Max uses the same controller for a different + // purpose. + if (_se->_game_id == GID_SAMNMAX) { +#if 0 + if (_mc) { + _mc->controlChange(17, detune + 0x40); + } +#endif + } else { + _detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127); + sendPitchBend(); + } } void Part::pitchBend(int16 value) { diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index 8499c9bad3..28884d7f78 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -36,6 +36,7 @@ MODULE_OBJS := \ object.o \ palette.o \ player_apple2.o \ + player_mac.o \ player_mod.o \ player_nes.o \ player_pce.o \ @@ -47,7 +48,9 @@ MODULE_OBJS := \ player_v2base.o \ player_v2cms.o \ player_v3a.o \ + player_v3m.o \ player_v4a.o \ + player_v5m.o \ resource_v2.o \ resource_v3.o \ resource_v4.o \ diff --git a/engines/scumm/music.h b/engines/scumm/music.h index a527c77b72..9fd14d830e 100644 --- a/engines/scumm/music.h +++ b/engines/scumm/music.h @@ -24,6 +24,7 @@ #define SCUMM_MUSIC_H #include "common/scummsys.h" +#include "engines/scumm/saveload.h" namespace Scumm { @@ -78,6 +79,11 @@ public: * @return the music timer */ virtual int getMusicTimer() { return 0; } + + /** + * Save or load the music state. + */ + virtual void saveLoadWithSerializer(Serializer *ser) {} }; } // End of namespace Scumm diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index 77c75c4ad6..ed77a863cd 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -433,10 +433,14 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) { y = od.y_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].y); } } else if (_game.version <= 2) { - if (od.actordir) { - x = od.walk_x; - y = od.walk_y; - } else { + x = od.walk_x; + y = od.walk_y; + + // Adjust x, y when no actor direction is set, but only perform this + // adjustment for V0 games (e.g. MM C64), otherwise certain scenes in + // newer games are affected as well (e.g. the interior of the Shuttle + // Bus scene in Zak V2, where no actor is present). Refer to bug #3526089. + if (!od.actordir && _game.version == 0) { x = od.x_pos + od.width / 2; y = od.y_pos + od.height / 2; } diff --git a/engines/scumm/player_mac.cpp b/engines/scumm/player_mac.cpp new file mode 100644 index 0000000000..c16c85bff3 --- /dev/null +++ b/engines/scumm/player_mac.cpp @@ -0,0 +1,415 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/macresman.h" +#include "common/translation.h" +#include "engines/engine.h" +#include "gui/message.h" +#include "scumm/player_mac.h" +#include "scumm/resource.h" +#include "scumm/scumm.h" +#include "scumm/imuse/imuse.h" + +namespace Scumm { + +Player_Mac::Player_Mac(ScummEngine *scumm, Audio::Mixer *mixer, int numberOfChannels, int channelMask, bool fadeNoteEnds) + : _vm(scumm), + _mixer(mixer), + _sampleRate(_mixer->getOutputRate()), + _soundPlaying(-1), + _numberOfChannels(numberOfChannels), + _channelMask(channelMask), + _fadeNoteEnds(fadeNoteEnds) { + assert(scumm); + assert(mixer); +} + +void Player_Mac::init() { + _channel = new Player_Mac::Channel[_numberOfChannels]; + + int i; + + for (i = 0; i < _numberOfChannels; i++) { + _channel[i]._looped = false; + _channel[i]._length = 0; + _channel[i]._data = NULL; + _channel[i]._pos = 0; + _channel[i]._pitchModifier = 0; + _channel[i]._velocity = 0; + _channel[i]._remaining = 0; + _channel[i]._notesLeft = false; + _channel[i]._instrument._data = NULL; + _channel[i]._instrument._size = 0; + _channel[i]._instrument._rate = 0; + _channel[i]._instrument._loopStart = 0; + _channel[i]._instrument._loopEnd = 0; + _channel[i]._instrument._baseFreq = 0; + _channel[i]._instrument._pos = 0; + _channel[i]._instrument._subPos = 0; + } + + _pitchTable[116] = 1664510; + _pitchTable[117] = 1763487; + _pitchTable[118] = 1868350; + _pitchTable[119] = 1979447; + _pitchTable[120] = 2097152; + _pitchTable[121] = 2221855; + _pitchTable[122] = 2353973; + _pitchTable[123] = 2493948; + _pitchTable[124] = 2642246; + _pitchTable[125] = 2799362; + _pitchTable[126] = 2965820; + _pitchTable[127] = 3142177; + for (i = 115; i >= 0; --i) { + _pitchTable[i] = _pitchTable[i + 12] / 2; + } + + setMusicVolume(255); + + if (!checkMusicAvailable()) { + return; + } + + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +Player_Mac::~Player_Mac() { + Common::StackLock lock(_mutex); + _mixer->stopHandle(_soundHandle); + stopAllSounds_Internal(); + delete[] _channel; +} + +void Player_Mac::saveLoadWithSerializer(Serializer *ser) { + Common::StackLock lock(_mutex); + if (ser->getVersion() < VER(94)) { + if (_vm->_game.id == GID_MONKEY && ser->isLoading()) { + IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL); + dummyImuse->save_or_load(ser, _vm, false); + delete dummyImuse; + } + } else { + static const SaveLoadEntry musicEntries[] = { + MKLINE(Player_Mac, _sampleRate, sleUint32, VER(94)), + MKLINE(Player_Mac, _soundPlaying, sleInt16, VER(94)), + MKEND() + }; + + static const SaveLoadEntry channelEntries[] = { + MKLINE(Channel, _pos, sleUint16, VER(94)), + MKLINE(Channel, _pitchModifier, sleInt32, VER(94)), + MKLINE(Channel, _velocity, sleUint8, VER(94)), + MKLINE(Channel, _remaining, sleUint32, VER(94)), + MKLINE(Channel, _notesLeft, sleUint8, VER(94)), + MKEND() + }; + + static const SaveLoadEntry instrumentEntries[] = { + MKLINE(Instrument, _pos, sleUint32, VER(94)), + MKLINE(Instrument, _subPos, sleUint32, VER(94)), + MKEND() + }; + + uint32 mixerSampleRate = _sampleRate; + int i; + + ser->saveLoadEntries(this, musicEntries); + + if (ser->isLoading() && _soundPlaying != -1) { + const byte *ptr = _vm->getResourceAddress(rtSound, _soundPlaying); + assert(ptr); + loadMusic(ptr); + } + + ser->saveLoadArrayOf(_channel, _numberOfChannels, sizeof(Channel), channelEntries); + for (i = 0; i < _numberOfChannels; i++) { + ser->saveLoadEntries(&_channel[i], instrumentEntries); + } + + if (ser->isLoading()) { + // If necessary, adjust the channel data to fit the + // current sample rate. + if (_soundPlaying != -1 && _sampleRate != mixerSampleRate) { + double mult = (double)_sampleRate / (double)mixerSampleRate; + for (i = 0; i < _numberOfChannels; i++) { + _channel[i]._pitchModifier = (int)((double)_channel[i]._pitchModifier * mult); + _channel[i]._remaining = (int)((double)_channel[i]._remaining / mult); + } + } + _sampleRate = mixerSampleRate; + } + } +} + +void Player_Mac::setMusicVolume(int vol) { + debug(5, "Player_Mac::setMusicVolume(%d)", vol); +} + +void Player_Mac::stopAllSounds_Internal() { + if (_soundPlaying != -1) { + _vm->_res->unlock(rtSound, _soundPlaying); + } + _soundPlaying = -1; + for (int i = 0; i < _numberOfChannels; i++) { + // The channel data is managed by the resource manager, so + // don't delete that. + delete[] _channel[i]._instrument._data; + _channel[i]._instrument._data = NULL; + + _channel[i]._remaining = 0; + _channel[i]._notesLeft = false; + } +} + +void Player_Mac::stopAllSounds() { + Common::StackLock lock(_mutex); + debug(5, "Player_Mac::stopAllSounds()"); + stopAllSounds_Internal(); +} + +void Player_Mac::stopSound(int nr) { + Common::StackLock lock(_mutex); + debug(5, "Player_Mac::stopSound(%d)", nr); + + if (nr == _soundPlaying) { + stopAllSounds(); + } +} + +void Player_Mac::startSound(int nr) { + Common::StackLock lock(_mutex); + debug(5, "Player_Mac::startSound(%d)", nr); + + stopAllSounds_Internal(); + + const byte *ptr = _vm->getResourceAddress(rtSound, nr); + assert(ptr); + + if (!loadMusic(ptr)) { + return; + } + + _vm->_res->lock(rtSound, nr); + _soundPlaying = nr; +} + +bool Player_Mac::Channel::loadInstrument(Common::SeekableReadStream *stream) { + uint16 soundType = stream->readUint16BE(); + if (soundType != 1) { + warning("Player_Mac::loadInstrument: Unsupported sound type %d", soundType); + return false; + } + uint16 typeCount = stream->readUint16BE(); + if (typeCount != 1) { + warning("Player_Mac::loadInstrument: Unsupported data type count %d", typeCount); + return false; + } + uint16 dataType = stream->readUint16BE(); + if (dataType != 5) { + warning("Player_Mac::loadInstrument: Unsupported data type %d", dataType); + return false; + } + + stream->readUint32BE(); // initialization option + + uint16 cmdCount = stream->readUint16BE(); + if (cmdCount != 1) { + warning("Player_Mac::loadInstrument: Unsupported command count %d", cmdCount); + return false; + } + uint16 command = stream->readUint16BE(); + if (command != 0x8050 && command != 0x8051) { + warning("Player_Mac::loadInstrument: Unsupported command 0x%04X", command); + return false; + } + + stream->readUint16BE(); // 0 + uint32 soundHeaderOffset = stream->readUint32BE(); + + stream->seek(soundHeaderOffset); + + uint32 soundDataOffset = stream->readUint32BE(); + uint32 size = stream->readUint32BE(); + uint32 rate = stream->readUint32BE() >> 16; + uint32 loopStart = stream->readUint32BE(); + uint32 loopEnd = stream->readUint32BE(); + byte encoding = stream->readByte(); + byte baseFreq = stream->readByte(); + + if (encoding != 0) { + warning("Player_Mac::loadInstrument: Unsupported encoding %d", encoding); + return false; + } + + stream->skip(soundDataOffset); + + byte *data = new byte[size]; + stream->read(data, size); + + _instrument._data = data; + _instrument._size = size; + _instrument._rate = rate; + _instrument._loopStart = loopStart; + _instrument._loopEnd = loopEnd; + _instrument._baseFreq = baseFreq; + + return true; +} + +int Player_Mac::getMusicTimer() { + return 0; +} + +int Player_Mac::getSoundStatus(int nr) const { + return _soundPlaying == nr; +} + +uint32 Player_Mac::durationToSamples(uint16 duration) { + // The correct formula should be: + // + // (duration * 473 * _sampleRate) / (4 * 480 * 480) + // + // But that's likely to cause integer overflow, so we do it in two + // steps and hope that the rounding error won't be noticeable. + // + // The original code is a bit unclear on if it should be 473 or 437, + // but since the comments indicated 473 I'm assuming 437 was a typo. + uint32 samples = (duration * _sampleRate) / (4 * 480); + samples = (samples * 473) / 480; + return samples; +} + +int Player_Mac::noteToPitchModifier(byte note, Instrument *instrument) { + if (note > 0) { + const int pitchIdx = note + 60 - instrument->_baseFreq; + // I don't want to use floating-point arithmetics here, but I + // ran into overflow problems with the church music in Monkey + // Island. It's only once per note, so it should be ok. + double mult = (double)instrument->_rate / (double)_sampleRate; + return (int)(mult * _pitchTable[pitchIdx]); + } else { + return 0; + } +} + +int Player_Mac::readBuffer(int16 *data, const int numSamples) { + Common::StackLock lock(_mutex); + + memset(data, 0, numSamples * 2); + if (_soundPlaying == -1) { + return numSamples; + } + + bool notesLeft = false; + + for (int i = 0; i < _numberOfChannels; i++) { + if (!(_channelMask & (1 << i))) { + continue; + } + + uint samplesLeft = numSamples; + int16 *ptr = data; + + while (samplesLeft > 0) { + int generated; + if (_channel[i]._remaining == 0) { + uint32 samples; + int pitchModifier; + byte velocity; + if (getNextNote(i, samples, pitchModifier, velocity)) { + _channel[i]._remaining = samples; + _channel[i]._pitchModifier = pitchModifier; + _channel[i]._velocity = velocity; + + } else { + _channel[i]._pitchModifier = 0; + _channel[i]._velocity = 0; + _channel[i]._remaining = samplesLeft; + } + } + generated = MIN<uint32>(_channel[i]._remaining, samplesLeft); + if (_channel[i]._velocity != 0) { + _channel[i]._instrument.generateSamples(ptr, _channel[i]._pitchModifier, _channel[i]._velocity, generated, _channel[i]._remaining, _fadeNoteEnds); + } + ptr += generated; + samplesLeft -= generated; + _channel[i]._remaining -= generated; + } + + if (_channel[i]._notesLeft) { + notesLeft = true; + } + } + + if (!notesLeft) { + stopAllSounds_Internal(); + } + + return numSamples; +} + +void Player_Mac::Instrument::generateSamples(int16 *data, int pitchModifier, int volume, int numSamples, int remainingSamplesOnNote, bool fadeNoteEnds) { + int samplesLeft = numSamples; + while (samplesLeft) { + _subPos += pitchModifier; + while (_subPos >= 0x10000) { + _subPos -= 0x10000; + _pos++; + if (_pos >= _loopEnd) { + _pos = _loopStart; + } + } + + int newSample = (((int16)((_data[_pos] << 8) ^ 0x8000)) * volume) / 255; + + if (fadeNoteEnds) { + // Fade out the last 100 samples on each note. Even at + // low output sample rates this is just a fraction of a + // second, but it gets rid of distracting "pops" at the + // end when the sample would otherwise go abruptly from + // something to nothing. This was particularly + // noticeable on the distaff notes in Loom. + // + // The reason it's conditional is that Monkey Island + // appears to have a "hold current note" command, and + // if we fade out the current note in that case we + // will actually introduce new "pops". + + remainingSamplesOnNote--; + if (remainingSamplesOnNote < 100) { + newSample = (newSample * remainingSamplesOnNote) / 100; + } + } + + int sample = *data + newSample; + if (sample > 32767) { + sample = 32767; + } else if (sample < -32768) { + sample = -32768; + } + + *data++ = sample; + samplesLeft--; + } +} + +} // End of namespace Scumm diff --git a/engines/scumm/player_mac.h b/engines/scumm/player_mac.h new file mode 100644 index 0000000000..09307b4e57 --- /dev/null +++ b/engines/scumm/player_mac.h @@ -0,0 +1,133 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCUMM_PLAYER_MAC_H +#define SCUMM_PLAYER_MAC_H + +#include "common/scummsys.h" +#include "common/util.h" +#include "common/mutex.h" +#include "scumm/music.h" +#include "scumm/saveload.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" + +#define RES_SND MKTAG('s', 'n', 'd', ' ') + +class Mixer; + +namespace Scumm { + +class ScummEngine; + +/** + * Scumm Macintosh music driver, base class. + */ +class Player_Mac : public Audio::AudioStream, public MusicEngine { +public: + Player_Mac(ScummEngine *scumm, Audio::Mixer *mixer, int numberOfChannels, int channelMask, bool fadeNoteEnds); + virtual ~Player_Mac(); + + void init(); + + // MusicEngine API + virtual void setMusicVolume(int vol); + virtual void startSound(int sound); + virtual void stopSound(int sound); + virtual void stopAllSounds(); + virtual int getMusicTimer(); + virtual int getSoundStatus(int sound) const; + + // AudioStream API + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return false; } + virtual bool endOfData() const { return false; } + virtual int getRate() const { return _sampleRate; } + + virtual void saveLoadWithSerializer(Serializer *ser); + +private: + Common::Mutex _mutex; + Audio::Mixer *const _mixer; + Audio::SoundHandle _soundHandle; + uint32 _sampleRate; + int _soundPlaying; + + void stopAllSounds_Internal(); + + struct Instrument { + byte *_data; + uint32 _size; + uint32 _rate; + uint32 _loopStart; + uint32 _loopEnd; + byte _baseFreq; + + uint _pos; + uint _subPos; + + void newNote() { + _pos = 0; + _subPos = 0; + } + + void generateSamples(int16 *data, int pitchModifier, int volume, int numSamples, int remainingSamplesOnNote, bool fadeNoteEnds); + }; + + int _pitchTable[128]; + int _numberOfChannels; + int _channelMask; + bool _fadeNoteEnds; + + virtual bool checkMusicAvailable() { return false; } + virtual bool loadMusic(const byte *ptr) { return false; } + virtual bool getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) { return false; } + +protected: + struct Channel { + virtual ~Channel() {} + + Instrument _instrument; + bool _looped; + uint32 _length; + const byte *_data; + + uint _pos; + int _pitchModifier; + byte _velocity; + uint32 _remaining; + + bool _notesLeft; + + bool loadInstrument(Common::SeekableReadStream *stream); + }; + + ScummEngine *const _vm; + Channel *_channel; + + uint32 durationToSamples(uint16 duration); + int noteToPitchModifier(byte note, Instrument *instrument); +}; + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/player_v3m.cpp b/engines/scumm/player_v3m.cpp new file mode 100644 index 0000000000..0f222d84fe --- /dev/null +++ b/engines/scumm/player_v3m.cpp @@ -0,0 +1,214 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + We have the following information from Lars Christensen (lechimp) and + Jamieson Christian (jamieson630): + + RESOURCE DATA + LE 2 bytes Resource size + 2 bytes Unknown + 2 bytes 'so' + 14 bytes Unknown + BE 2 bytes Instrument for Stream 1 + BE 2 bytes Instrument for Stream 2 + BE 2 bytes Instrument for Stream 3 + BE 2 bytes Instrument for Stream 4 + BE 2 bytes Instrument for Stream 5 + BE 2 bytes Offset to Stream 1 + BE 2 bytes Offset to Stream 2 + BE 2 bytes Offset to Stream 3 + BE 2 bytes Offset to Stream 4 + BE 2 bytes Offset to Stream 5 + ? bytes The streams + + STREAM DATA + BE 2 bytes Unknown (always 1?) + 2 bytes Unknown (always 0?) + BE 2 bytes Number of events in stream + ? bytes Stream data + + Each stream event is exactly 3 bytes, therefore one can + assert that numEvents == (streamSize - 6) / 3. The + polyphony of a stream appears to be 1; in other words, only + one note at a time can be playing in each stream. The next + event is not executed until the current note (or rest) is + finished playing; therefore, note duration also serves as the + time delta between events. + + FOR EACH EVENTS + BE 2 bytes Note duration + 1 byte Note number to play (0 = rest/silent) + + Oh, and quick speculation -- Stream 1 may be used for a + single-voice interleaved version of the music, where Stream 2- + 5 represent a version of the music in up to 4-voice + polyphony, one voice per stream. I postulate thus because + the first stream of the Mac Loom theme music contains + interleaved voices, whereas the second stream seemed to + contain only the pizzicato bottom-end harp. Stream 5, in this + example, is empty, so if my speculation is correct, this + particular musical number supports 3-voice polyphony at + most. I must check out Streams 3 and 4 to see what they + contain. + + ========== + + The instruments appear to be identified by their resource IDs: + + 1000 Dual Harp + 10895 harp1 + 11445 strings1 + 11548 silent + 13811 staff1 + 15703 brass1 + 16324 flute1 + 25614 accordian 1 + 28110 f horn1 + 29042 bassoon1 +*/ + +#include "common/macresman.h" +#include "common/translation.h" +#include "engines/engine.h" +#include "gui/message.h" +#include "scumm/player_v3m.h" +#include "scumm/scumm.h" + +namespace Scumm { + +Player_V3M::Player_V3M(ScummEngine *scumm, Audio::Mixer *mixer) + : Player_Mac(scumm, mixer, 5, 0x1E, true) { + assert(_vm->_game.id == GID_LOOM); + + // Channel 0 seems to be what was played on low-end macs, that couldn't + // handle multi-channel music and play the game at the same time. I'm + // not sure if stream 4 is ever used, but let's use it just in case. +} + +// \xAA is a trademark glyph in Mac OS Roman. We try that, but also the Windows +// version, the UTF-8 version, and just plain without in case the file system +// can't handle exotic characters like that. + +static const char *loomFileNames[] = { + "Loom\xAA", + "Loom\x99", + "Loom\xE2\x84\xA2", + "Loom" +}; + +bool Player_V3M::checkMusicAvailable() { + Common::MacResManager resource; + + for (int i = 0; i < ARRAYSIZE(loomFileNames); i++) { + if (resource.exists(loomFileNames[i])) { + return true; + } + } + + GUI::MessageDialog dialog(_( + "Could not find the 'Loom' Macintosh executable to read the\n" + "instruments from. Music will be disabled."), _("OK")); + dialog.runModal(); + return false; +} + +bool Player_V3M::loadMusic(const byte *ptr) { + Common::MacResManager resource; + bool found = false; + + for (int i = 0; i < ARRAYSIZE(loomFileNames); i++) { + if (resource.open(loomFileNames[i])) { + found = true; + break; + } + } + + if (!found) { + return false; + } + + if (ptr[4] != 's' || ptr[5] != 'o') { + // Like the original we ignore all sound resources which do not have + // a 'so' tag in them. + // See bug #3602239 ("Mac Loom crashes using opening spell on + // gravestone") for a case where this is required. Loom Mac tries to + // play resource 11 here. This resource is no Mac sound resource + // though, it is a PC Speaker resource. A test with the original + // interpreter also has shown that no sound is played while the + // screen is shaking. + debug(5, "Player_V3M::loadMusic: Skipping unknown music type %02X%02X", ptr[4], ptr[5]); + resource.close(); + return false; + } + + uint i; + for (i = 0; i < 5; i++) { + int instrument = READ_BE_UINT16(ptr + 20 + 2 * i); + int offset = READ_BE_UINT16(ptr + 30 + 2 * i); + + _channel[i]._looped = false; + _channel[i]._length = READ_BE_UINT16(ptr + offset + 4) * 3; + _channel[i]._data = ptr + offset + 6; + _channel[i]._pos = 0; + _channel[i]._pitchModifier = 0; + _channel[i]._velocity = 0; + _channel[i]._remaining = 0; + _channel[i]._notesLeft = true; + + Common::SeekableReadStream *stream = resource.getResource(RES_SND, instrument); + if (_channel[i].loadInstrument(stream)) { + debug(6, "Player_V3M::loadMusic: Channel %d - Loaded Instrument %d (%s)", i, instrument, resource.getResName(RES_SND, instrument).c_str()); + } else { + resource.close(); + return false; + } + } + + resource.close(); + return true; +} + +bool Player_V3M::getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) { + _channel[ch]._instrument.newNote(); + if (_channel[ch]._pos >= _channel[ch]._length) { + if (!_channel[ch]._looped) { + _channel[ch]._notesLeft = false; + return false; + } + _channel[ch]._pos = 0; + } + uint16 duration = READ_BE_UINT16(&_channel[ch]._data[_channel[ch]._pos]); + byte note = _channel[ch]._data[_channel[ch]._pos + 2]; + samples = durationToSamples(duration); + if (note > 0) { + pitchModifier = noteToPitchModifier(note, &_channel[ch]._instrument); + velocity = 127; + } else { + pitchModifier = 0; + velocity = 0; + } + _channel[ch]._pos += 3; + return true; +} + +} // End of namespace Scumm diff --git a/engines/scumm/player_v3m.h b/engines/scumm/player_v3m.h new file mode 100644 index 0000000000..359bab32a9 --- /dev/null +++ b/engines/scumm/player_v3m.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCUMM_PLAYER_V3M_H +#define SCUMM_PLAYER_V3M_H + +#include "common/scummsys.h" +#include "common/util.h" +#include "common/mutex.h" +#include "scumm/music.h" +#include "scumm/player_mac.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" + +class Mixer; + +namespace Scumm { + +class ScummEngine; + +/** + * Scumm V3 Macintosh music driver. + */ +class Player_V3M : public Player_Mac { +public: + Player_V3M(ScummEngine *scumm, Audio::Mixer *mixer); + + virtual bool checkMusicAvailable(); + virtual bool loadMusic(const byte *ptr); + virtual bool getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity); +}; + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/player_v5m.cpp b/engines/scumm/player_v5m.cpp new file mode 100644 index 0000000000..500f3bbc40 --- /dev/null +++ b/engines/scumm/player_v5m.cpp @@ -0,0 +1,246 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + From Markus Magnuson (superqult) we got this information: + Mac0 + --- + 4 bytes - 'SOUN' + BE 4 bytes - block length + + 4 bytes - 'Mac0' + BE 4 bytes - (blockLength - 27) + 28 bytes - ??? + + do this three times (once for each channel): + 4 bytes - 'Chan' + BE 4 bytes - channel length + 4 bytes - instrument name (e.g. 'MARI') + + do this for ((chanLength-24)/4) times: + 2 bytes - note duration + 1 byte - note value + 1 byte - note velocity + + 4 bytes - ??? + 4 bytes - 'Loop'/'Done' + 4 bytes - ??? + + 1 byte - 0x09 + --- + + The instruments presumably correspond to the snd resource names in the + Monkey Island executable: + + Instruments + "MARI" - MARIMBA + "PLUC" - PLUCK + "HARM" - HARMONIC + "PIPE" - PIPEORGAN + "TROM" - TROMBONE + "STRI" - STRINGS + "HORN" - HORN + "VIBE" - VIBES + "SHAK" - SHAKUHACHI + "PANP" - PANPIPE + "WHIS" - WHISTLE + "ORGA" - ORGAN3 + "BONG" - BONGO + "BASS" - BASS + + --- + + Note values <= 1 are silent. +*/ + +#include "common/macresman.h" +#include "common/translation.h" +#include "engines/engine.h" +#include "gui/message.h" +#include "scumm/player_v5m.h" +#include "scumm/scumm.h" + +namespace Scumm { + +Player_V5M::Player_V5M(ScummEngine *scumm, Audio::Mixer *mixer) + : Player_Mac(scumm, mixer, 3, 0x07, false) { + assert(_vm->_game.id == GID_MONKEY); +} + +// Try both with and without underscore in the filename, because hfsutils may +// turn the space into an underscore. At least, it did for me. + +static const char *monkeyIslandFileNames[] = { + "Monkey Island", + "Monkey_Island" +}; + +bool Player_V5M::checkMusicAvailable() { + Common::MacResManager resource; + + for (int i = 0; i < ARRAYSIZE(monkeyIslandFileNames); i++) { + if (resource.exists(monkeyIslandFileNames[i])) { + return true; + } + } + + GUI::MessageDialog dialog(_( + "Could not find the 'Monkey Island' Macintosh executable to read the\n" + "instruments from. Music will be disabled."), _("OK")); + dialog.runModal(); + return false; +} + +bool Player_V5M::loadMusic(const byte *ptr) { + Common::MacResManager resource; + bool found = false; + uint i; + + for (i = 0; i < ARRAYSIZE(monkeyIslandFileNames); i++) { + if (resource.open(monkeyIslandFileNames[i])) { + found = true; + break; + } + } + + if (!found) { + return false; + } + + ptr += 8; + // TODO: Decipher the unknown bytes in the header. For now, skip 'em + ptr += 28; + + Common::MacResIDArray idArray = resource.getResIDArray(RES_SND); + + // Load the three channels and their instruments + for (i = 0; i < 3; i++) { + assert(READ_BE_UINT32(ptr) == MKTAG('C', 'h', 'a', 'n')); + uint32 len = READ_BE_UINT32(ptr + 4); + uint32 instrument = READ_BE_UINT32(ptr + 8); + + _channel[i]._length = len - 20; + _channel[i]._data = ptr + 12; + _channel[i]._looped = (READ_BE_UINT32(ptr + len - 8) == MKTAG('L', 'o', 'o', 'p')); + _channel[i]._pos = 0; + _channel[i]._pitchModifier = 0; + _channel[i]._velocity = 0; + _channel[i]._remaining = 0; + _channel[i]._notesLeft = true; + + for (uint j = 0; j < idArray.size(); j++) { + Common::String name = resource.getResName(RES_SND, idArray[j]); + if (instrument == READ_BE_UINT32(name.c_str())) { + debug(6, "Player_V5M::loadMusic: Channel %d: Loading instrument '%s'", i, name.c_str()); + Common::SeekableReadStream *stream = resource.getResource(RES_SND, idArray[j]); + + if (!_channel[i].loadInstrument(stream)) { + resource.close(); + return false; + } + + break; + } + } + + ptr += len; + } + + resource.close(); + + // The last note of each channel is just zeroes. We will adjust this + // note so that all the channels end at the same time. + + uint32 samples[3]; + uint32 maxSamples = 0; + for (i = 0; i < 3; i++) { + samples[i] = 0; + for (uint j = 0; j < _channel[i]._length; j += 4) { + samples[i] += durationToSamples(READ_BE_UINT16(&_channel[i]._data[j])); + } + if (samples[i] > maxSamples) { + maxSamples = samples[i]; + } + } + + for (i = 0; i < 3; i++) { + _lastNoteSamples[i] = maxSamples - samples[i]; + } + + return true; +} + +bool Player_V5M::getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) { + if (_channel[ch]._pos >= _channel[ch]._length) { + if (!_channel[ch]._looped) { + _channel[ch]._notesLeft = false; + return false; + } + // FIXME: Jamieson630: The jump seems to be happening + // too quickly! There should maybe be a pause after + // the last Note Off? But I couldn't find one in the + // MI1 Lookout music, where I was hearing problems. + _channel[ch]._pos = 0; + } + uint16 duration = READ_BE_UINT16(&_channel[ch]._data[_channel[ch]._pos]); + byte note = _channel[ch]._data[_channel[ch]._pos + 2]; + samples = durationToSamples(duration); + + if (note != 1) { + _channel[ch]._instrument.newNote(); + } + + if (note > 1) { + pitchModifier = noteToPitchModifier(note, &_channel[ch]._instrument); + velocity = _channel[ch]._data[_channel[ch]._pos + 3]; + } else if (note == 1) { + // This is guesswork, but Monkey Island uses two different + // "special" note values: 0, which is clearly a rest, and 1 + // which is... I thought at first it was a "soft" key off, to + // fade out the note, but listening to the music in a Mac + // emulator (which unfortunately doesn't work all that well), + // I hear no trace of fading out. + // + // It could mean "change the volume on the current note", but + // I can't hear that either, and it always seems to use the + // exact same velocity on this note. + // + // So it appears it really just is a "hold the current note", + // but why? Couldn't they just have made the original note + // longer? + + pitchModifier = _channel[ch]._pitchModifier; + velocity = _channel[ch]._velocity; + } else { + pitchModifier = 0; + velocity = 0; + } + + _channel[ch]._pos += 4; + + if (_channel[ch]._pos >= _channel[ch]._length) { + samples = _lastNoteSamples[ch]; + } + return true; +} + +} // End of namespace Scumm diff --git a/engines/scumm/player_v5m.h b/engines/scumm/player_v5m.h new file mode 100644 index 0000000000..b2079ee331 --- /dev/null +++ b/engines/scumm/player_v5m.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SCUMM_PLAYER_V5M_H +#define SCUMM_PLAYER_V5M_H + +#include "common/scummsys.h" +#include "common/util.h" +#include "common/mutex.h" +#include "scumm/music.h" +#include "scumm/player_mac.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" + +class Mixer; + +namespace Scumm { + +class ScummEngine; + +/** + * Scumm V5 Macintosh music driver. + */ +class Player_V5M : public Player_Mac { +public: + Player_V5M(ScummEngine *scumm, Audio::Mixer *mixer); + + virtual bool checkMusicAvailable(); + virtual bool loadMusic(const byte *ptr); + virtual bool getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity); + +private: + uint32 _lastNoteSamples[3]; +}; + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 72896e097a..3453e53a18 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -1477,9 +1477,13 @@ void ScummEngine::saveOrLoad(Serializer *s) { } - // Save/load FM-Towns audio status - if (_townsPlayer) - _townsPlayer->saveLoadWithSerializer(s); + // + // Save/load music engine status + // + if (_musicEngine) { + _musicEngine->saveLoadWithSerializer(s); + } + // // Save/load the charset renderer state diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index a640bc1e17..7b2ff91ad3 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -47,7 +47,7 @@ namespace Scumm { * only saves/loads those which are valid for the version of the savegame * which is being loaded/saved currently. */ -#define CURRENT_VER 93 +#define CURRENT_VER 94 /** * An auxillary macro, used to specify savegame versions. We use this instead @@ -74,7 +74,7 @@ namespace Scumm { * what POD means refer to <http://en.wikipedia.org/wiki/Plain_Old_Data_Structures> or * to <http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=32&rl=1>) */ -#define OFFS(type,item) (((ptrdiff_t)(&((type *)42)->type::item))-42) +#define OFFS(type,item) ((uint32)(((ptrdiff_t)(&((type *)42)->type::item))-42)) /** * Similar to the OFFS macro, this macro computes the size (in bytes) of a @@ -84,19 +84,19 @@ namespace Scumm { // Any item that is still in use automatically gets a maxVersion equal to CURRENT_VER #define MKLINE(type,item,saveas,minVer) {OFFS(type,item),saveas,SIZE(type,item),minVer,CURRENT_VER} -#define MKARRAY(type,item,saveas,dim,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {dim,1,0,0,0} -#define MKARRAY2(type,item,saveas,dim,dim2,rowlen,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {dim,dim2,rowlen,0,0} +#define MKARRAY(type,item,saveas,dim,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {(uint32)(dim),1,0,0,0} +#define MKARRAY2(type,item,saveas,dim,dim2,rowlen,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {(uint32)(dim),(uint32)(dim2),(uint16)(rowlen),0,0} // Use this if you have an entry that used to be smaller: #define MKLINE_OLD(type,item,saveas,minVer,maxVer) {OFFS(type,item),saveas,SIZE(type,item),minVer,maxVer} -#define MKARRAY_OLD(type,item,saveas,dim,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {dim,1,0,0,0} -#define MKARRAY2_OLD(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {dim,dim2,rowlen,0,0} +#define MKARRAY_OLD(type,item,saveas,dim,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {(uint32)(dim),1,0,0,0} +#define MKARRAY2_OLD(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {(uint32)(dim),(uint32)(dim2),(uint16)(rowlen),0,0} // An obsolete item/array, to be ignored upon load. We retain the type/item params to make it easier to debug. // Obsolete items have size == 0. #define MK_OBSOLETE(type,item,saveas,minVer,maxVer) {0,saveas,0,minVer,maxVer} -#define MK_OBSOLETE_ARRAY(type,item,saveas,dim,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {dim,1,0,0,0} -#define MK_OBSOLETE_ARRAY2(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {dim,dim2,rowlen,0,0} +#define MK_OBSOLETE_ARRAY(type,item,saveas,dim,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {(uint32)(dim),1,0,0,0} +#define MK_OBSOLETE_ARRAY2(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {(uint32)(dim),(uint32)(dim2),(uint16)(rowlen),0,0} // End marker #define MKEND() {0xFFFF,0xFF,0xFF,0,0} diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index d8c4948ea8..8587fb8092 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -1366,9 +1366,15 @@ void ScummEngine::runInputScript(int clickArea, int val, int mode) { // Clicks are handled differently in Indy3 mac: param 2 of the // input script is set to 0 for normal clicks, and to 1 for double clicks. + // The EGA DOS version of Loom also checks that the second click happens + // close enough to the first one, but that seems like overkill. uint32 time = _system->getMillis(); args[2] = (time < _lastInputScriptTime + 500); // 500 ms double click delay _lastInputScriptTime = time; + } else if (_game.id == GID_LOOM && _game.platform == Common::kPlatformMacintosh) { + uint32 time = _system->getMillis(); + VAR(52) = (time < _lastInputScriptTime + 500); // 500 ms double click delay + _lastInputScriptTime = time; } if (verbScript) diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 2c79fb8de0..3afeeda13d 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -61,7 +61,9 @@ #include "scumm/player_v2cms.h" #include "scumm/player_v2a.h" #include "scumm/player_v3a.h" +#include "scumm/player_v3m.h" #include "scumm/player_v4a.h" +#include "scumm/player_v5m.h" #include "scumm/resource.h" #include "scumm/he/resource_he.h" #include "scumm/scumm_v0.h" @@ -1819,6 +1821,12 @@ void ScummEngine::setupMusic(int midi) { #endif } else if (_game.platform == Common::kPlatformAmiga && _game.version <= 4) { _musicEngine = new Player_V4A(this, _mixer); + } else if (_game.platform == Common::kPlatformMacintosh && _game.id == GID_LOOM) { + _musicEngine = new Player_V3M(this, _mixer); + ((Player_V3M *)_musicEngine)->init(); + } else if (_game.platform == Common::kPlatformMacintosh && _game.id == GID_MONKEY) { + _musicEngine = new Player_V5M(this, _mixer); + ((Player_V5M *)_musicEngine)->init(); } else if (_game.id == GID_MANIAC && _game.version == 1) { _musicEngine = new Player_V1(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if (_game.version <= 2) { @@ -1858,6 +1866,8 @@ void ScummEngine::setupMusic(int midi) { if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS || multi_midi) { adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_sound->_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB)); adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0); + // Try to use OPL3 mode for Sam&Max when possible. + adlibMidiDriver->property(MidiDriver::PROP_SCUMM_OPL3, (_game.id == GID_SAMNMAX) ? 1 : 0); } else if (_sound->_musicType == MDT_PCSPK) { adlibMidiDriver = new PcSpkDriver(_mixer); } diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index a1cecfa0b3..2fe16c5441 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -346,29 +346,6 @@ void Sound::playSound(int soundID) { warning("Scumm::Sound::playSound: encountered audio resoure with chunk type 'SOUN' and sound type %d", type); } } - else if ((_vm->_game.id == GID_LOOM) && (_vm->_game.platform == Common::kPlatformMacintosh)) { - // Mac version of Loom uses yet another sound format - /* - playSound #9 (room 70) - 000000: 55 00 00 45 73 6f 00 64 01 00 00 00 00 00 00 00 |U..Eso.d........| - 000010: 00 05 00 8e 2a 8f 2d 1c 2a 8f 2a 8f 2d 1c 00 28 |....*.-.*.*.-..(| - 000020: 00 31 00 3a 00 43 00 4c 00 01 00 00 00 01 00 64 |.1.:.C.L.......d| - 000030: 5a 00 01 00 00 00 01 00 64 00 00 01 00 00 00 01 |Z.......d.......| - 000040: 00 64 5a 00 01 00 00 00 01 00 64 5a 00 01 00 00 |.dZ.......dZ....| - 000050: 00 01 00 64 00 00 00 00 00 00 00 07 00 00 00 64 |...d...........d| - 000060: 64 00 00 4e 73 6f 00 64 01 00 00 00 00 00 00 00 |d..Nso.d........| - 000070: 00 05 00 89 3d 57 2d 1c 3d 57 3d 57 2d 1c 00 28 |....=W-.=W=W-..(| - playSound #16 (room 69) - 000000: dc 00 00 a5 73 6f 00 64 01 00 00 00 00 00 00 00 |....so.d........| - 000010: 00 05 00 00 2a 8f 03 e8 03 e8 03 e8 03 e8 00 28 |....*..........(| - 000020: 00 79 00 7f 00 85 00 d6 00 01 00 00 00 19 01 18 |.y..............| - 000030: 2f 00 18 00 01 18 32 00 18 00 01 18 36 00 18 00 |/.....2.....6...| - 000040: 01 18 3b 00 18 00 01 18 3e 00 18 00 01 18 42 00 |..;.....>.....B.| - 000050: 18 00 01 18 47 00 18 00 01 18 4a 00 18 00 01 18 |....G.....J.....| - 000060: 4e 00 10 00 01 18 53 00 10 00 01 18 56 00 10 00 |N.....S.....V...| - 000070: 01 18 5a 00 10 00 02 28 5f 00 01 00 00 00 00 00 |..Z....(_.......| - */ - } else if ((_vm->_game.platform == Common::kPlatformMacintosh) && (_vm->_game.id == GID_INDY3) && READ_BE_UINT16(ptr + 8) == 0x1C) { // Sound format as used in Indy3 EGA Mac. // It seems to be closely related to the Amiga format, see player_v3a.cpp @@ -414,8 +391,7 @@ void Sound::playSound(int soundID) { } else { - if (_vm->_game.id == GID_MONKEY_VGA || _vm->_game.id == GID_MONKEY_EGA - || (_vm->_game.id == GID_MONKEY && _vm->_game.platform == Common::kPlatformMacintosh)) { + if (_vm->_game.id == GID_MONKEY_VGA || _vm->_game.id == GID_MONKEY_EGA) { // Works around the fact that in some places in MonkeyEGA/VGA, // the music is never explicitly stopped. // Rather it seems that starting a new music is supposed to @@ -1086,9 +1062,6 @@ void Sound::saveLoadWithSerializer(Serializer *ser) { #pragma mark --- Sound resource handling --- #pragma mark - -static void convertMac0Resource(ResourceManager *res, ResId idx, byte *src_ptr, int size); - - /* * TODO: The way we handle sound/music resources really is one huge hack. * We probably should reconsider how we do this, and maybe come up with a @@ -1208,11 +1181,9 @@ int ScummEngine::readSoundResource(ResId idx) { case MKTAG('M','a','c','0'): _fileHandle->seek(-12, SEEK_CUR); total_size = _fileHandle->readUint32BE() - 8; - ptr = (byte *)calloc(total_size, 1); + ptr = _res->createResource(rtSound, idx, total_size); _fileHandle->read(ptr, total_size); //dumpResource("sound-", idx, ptr); - convertMac0Resource(_res, idx, ptr, total_size); - free(ptr); return 1; case MKTAG('M','a','c','1'): @@ -1445,219 +1416,6 @@ static byte *writeVLQ(byte *ptr, int value) { return ptr; } -static byte Mac0ToGMInstrument(uint32 type, int &transpose) { - transpose = 0; - switch (type) { - case MKTAG('M','A','R','I'): return 12; - case MKTAG('P','L','U','C'): return 45; - case MKTAG('H','A','R','M'): return 22; - case MKTAG('P','I','P','E'): return 19; - case MKTAG('T','R','O','M'): transpose = -12; return 57; - case MKTAG('S','T','R','I'): return 48; - case MKTAG('H','O','R','N'): return 60; - case MKTAG('V','I','B','E'): return 11; - case MKTAG('S','H','A','K'): return 77; - case MKTAG('P','A','N','P'): return 75; - case MKTAG('W','H','I','S'): return 76; - case MKTAG('O','R','G','A'): return 17; - case MKTAG('B','O','N','G'): return 115; - case MKTAG('B','A','S','S'): transpose = -24; return 35; - default: - error("Unknown Mac0 instrument %s found", tag2str(type)); - } -} - -static void convertMac0Resource(ResourceManager *res, ResId idx, byte *src_ptr, int size) { - /* - From Markus Magnuson (superqult) we got this information: - Mac0 - --- - 4 bytes - 'SOUN' - BE 4 bytes - block length - - 4 bytes - 'Mac0' - BE 4 bytes - (blockLength - 27) - 28 bytes - ??? - - do this three times (once for each channel): - 4 bytes - 'Chan' - BE 4 bytes - channel length - 4 bytes - instrument name (e.g. 'MARI') - - do this for ((chanLength-24)/4) times: - 2 bytes - note duration - 1 byte - note value - 1 byte - note velocity - - 4 bytes - ??? - 4 bytes - 'Loop'/'Done' - 4 bytes - ??? - - 1 byte - 0x09 - --- - - Instruments (General Midi): - "MARI" - Marimba (12) - "PLUC" - Pizzicato Strings (45) - "HARM" - Harmonica (22) - "PIPE" - Church Organ? (19) or Flute? (73) or Bag Pipe (109) - "TROM" - Trombone (57) - "STRI" - String Ensemble (48 or 49) - "HORN" - French Horn? (60) or English Horn? (69) - "VIBE" - Vibraphone (11) - "SHAK" - Shakuhachi? (77) - "PANP" - Pan Flute (75) - "WHIS" - Whistle (78) / Bottle (76) - "ORGA" - Drawbar Organ (16; but could also be 17-20) - "BONG" - Woodblock? (115) - "BASS" - Bass (32-39) - - - Now the task could be to convert this into MIDI, to be fed into iMuse. - Or we do something similiar to what is done in Player_V3, assuming - we can identify SFX in the MI datafiles for each of the instruments - listed above. - */ - -#if 0 - byte *ptr = _res->createResource(rtSound, idx, size); - memcpy(ptr, src_ptr, size); -#else - const int ppqn = 480; - byte *ptr, *start_ptr; - - int total_size = 0; - total_size += kMIDIHeaderSize; // Header - total_size += 7; // Tempo META - total_size += 3 * 3; // Three program change mesages - total_size += 22; // Possible jump SysEx - total_size += 5; // EOT META - - int i, len; - byte track_instr[3]; - byte *track_data[3]; - int track_len[3]; - int track_transpose[3]; - bool looped = false; - - src_ptr += 8; - // TODO: Decipher the unknown bytes in the header. For now, skip 'em - src_ptr += 28; - - // Parse the three channels - for (i = 0; i < 3; i++) { - assert(READ_BE_UINT32(src_ptr) == MKTAG('C','h','a','n')); - len = READ_BE_UINT32(src_ptr + 4); - track_len[i] = len - 24; - track_instr[i] = Mac0ToGMInstrument(READ_BE_UINT32(src_ptr + 8), track_transpose[i]); - track_data[i] = src_ptr + 12; - src_ptr += len; - looped = (READ_BE_UINT32(src_ptr - 8) == MKTAG('L','o','o','p')); - - // For each note event, we need up to 6 bytes for the - // Note On (3 VLQ, 3 event), and 6 bytes for the Note - // Off (3 VLQ, 3 event). So 12 bytes total. - total_size += 12 * track_len[i]; - } - assert(*src_ptr == 0x09); - - // Create sound resource - start_ptr = res->createResource(rtSound, idx, total_size); - - // Insert MIDI header - ptr = writeMIDIHeader(start_ptr, "GMD ", ppqn, total_size); - - // Write a tempo change Meta event - // 473 / 4 Hz, convert to micro seconds. - uint32 dw = 1000000 * 437 / 4 / ppqn; // 1000000 * ppqn * 4 / 473; - memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4; - *ptr++ = (byte)((dw >> 16) & 0xFF); - *ptr++ = (byte)((dw >> 8) & 0xFF); - *ptr++ = (byte)(dw & 0xFF); - - // Insert program change messages - *ptr++ = 0; // VLQ - *ptr++ = 0xC0; - *ptr++ = track_instr[0]; - *ptr++ = 0; // VLQ - *ptr++ = 0xC1; - *ptr++ = track_instr[1]; - *ptr++ = 0; // VLQ - *ptr++ = 0xC2; - *ptr++ = track_instr[2]; - - // And now, the actual composition. Please turn all cell phones - // and pagers off during the performance. Thank you. - uint16 nextTime[3] = { 1, 1, 1 }; - int stage[3] = { 0, 0, 0 }; - - while (track_len[0] | track_len[1] | track_len[2]) { - int best = -1; - uint16 bestTime = 0xFFFF; - for (i = 0; i < 3; ++i) { - if (track_len[i] && nextTime[i] < bestTime) { - bestTime = nextTime[i]; - best = i; - } - } - assert (best != -1); - - if (!stage[best]) { - // We are STARTING this event. - if (track_data[best][2] > 1) { - // Note On - ptr = writeVLQ(ptr, nextTime[best]); - *ptr++ = 0x90 | best; - *ptr++ = track_data[best][2] + track_transpose[best]; - *ptr++ = track_data[best][3] * 127 / 100; // Scale velocity - for (i = 0; i < 3; ++i) - nextTime[i] -= bestTime; - } - nextTime[best] += READ_BE_UINT16 (track_data[best]); - stage[best] = 1; - } else { - // We are ENDING this event. - if (track_data[best][2] > 1) { - // There was a Note On, so do a Note Off - ptr = writeVLQ(ptr, nextTime[best]); - *ptr++ = 0x80 | best; - *ptr++ = track_data[best][2] + track_transpose[best]; - *ptr++ = track_data[best][3] * 127 / 100; // Scale velocity - for (i = 0; i < 3; ++i) - nextTime[i] -= bestTime; - } - track_data[best] += 4; - track_len[best] -= 4; - stage[best] = 0; - } - } - - // Is this a looped song? If so, effect a loop by - // using the S&M maybe_jump SysEx command. - // FIXME: Jamieson630: The jump seems to be happening - // too quickly! There should maybe be a pause after - // the last Note Off? But I couldn't find one in the - // MI1 Lookout music, where I was hearing problems. - if (looped) { - memcpy(ptr, "\x00\xf0\x13\x7d\x30\00", 6); ptr += 6; // maybe_jump - memcpy(ptr, "\x00\x00", 2); ptr += 2; // cmd -> 0 means always jump - memcpy(ptr, "\x00\x00\x00\x00", 4); ptr += 4; // track -> 0 (only track) - memcpy(ptr, "\x00\x00\x00\x01", 4); ptr += 4; // beat -> 1 (first beat) - memcpy(ptr, "\x00\x00\x00\x01", 4); ptr += 4; // tick -> 1 - memcpy(ptr, "\x00\xf7", 2); ptr += 2; // SysEx end marker - } - - // Insert end of song META - memcpy(ptr, "\x00\xff\x2f\x00\x00", 5); ptr += 5; - - assert(ptr <= start_ptr + total_size); - - // Rewrite MIDI header, this time with true size - total_size = ptr - start_ptr; - ptr = writeMIDIHeader(start_ptr, "GMD ", ppqn, total_size); -#endif -} - static void convertADResource(ResourceManager *res, const GameSettings& game, ResId idx, byte *src_ptr, int size) { // We will ignore the PPQN in the original resource, because // it's invalid anyway. We use a constant PPQN of 480. diff --git a/engines/sky/compact.cpp b/engines/sky/compact.cpp index cf9bd55b1a..ee165934a0 100644 --- a/engines/sky/compact.cpp +++ b/engines/sky/compact.cpp @@ -34,7 +34,7 @@ namespace Sky { #define SKY_CPT_SIZE 419427 -#define OFFS(type,item) (((ptrdiff_t)(&((type *)42)->item))-42) +#define OFFS(type,item) ((uint32)(((ptrdiff_t)(&((type *)42)->item))-42)) #define MK32(type,item) OFFS(type, item),0,0,0 #define MK16(type,item) OFFS(type, item),0 #define MK32_A5(type, item) MK32(type, item[0]), MK32(type, item[1]), \ diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp index 5662e4672b..f3af04c81d 100644 --- a/engines/sword1/detection.cpp +++ b/engines/sword1/detection.cpp @@ -143,9 +143,24 @@ GameDescriptor SwordMetaEngine::findGame(const char *gameid) const { return GameDescriptor(); } -void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound) { +void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound, bool recursion = false) { for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { + // The required game data files can be located in the game directory, or in + // a subdirectory called "clusters". In the latter case, we don't want to + // detect the game in that subdirectory, as this will detect the game twice + // when mass add is searching inside a directory. In this case, the first + // result (the game directory) will be correct, but the second result (the + // clusters subdirectory) will be wrong, as the optional speech, music and + // video data files will be ignored. Note that this fix will skip the game + // data files if the user has placed them inside a "clusters" subdirectory, + // or if he/she points ScummVM directly to the "clusters" directory of the + // game CD. Fixes bug #3049346. + Common::String directory = file->getParent().getName(); + directory.toLowercase(); + if (directory.hasPrefix("clusters") && directory.size() <= 9 && !recursion) + continue; + const char *fileName = file->getName().c_str(); for (int cnt = 0; cnt < NUM_FILES_TO_CHECK; cnt++) if (scumm_stricmp(fileName, g_filesToCheck[cnt]) == 0) @@ -155,7 +170,7 @@ void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound) { if (scumm_stricmp(file->getName().c_str(), g_dirNames[cnt]) == 0) { Common::FSList fslist2; if (file->getChildren(fslist2, Common::FSNode::kListFilesOnly)) - Sword1CheckDirectory(fslist2, filesFound); + Sword1CheckDirectory(fslist2, filesFound, true); } } } diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 458a2d33ed..dfa6a23320 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -144,22 +144,52 @@ GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const { return GameDescriptor(g->gameid, g->description); } -GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { +bool isFullGame(const Common::FSList &fslist) { + Common::FSList::const_iterator file; + + // We distinguish between the two versions by the presense of paris.clu + for (file = fslist.begin(); file != fslist.end(); ++file) { + if (!file->isDirectory()) { + if (file->getName().equalsIgnoreCase("paris.clu")) + return true; + } + } + + return false; +} + +GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) { GameList detectedGames; const Sword2::GameSettings *g; Common::FSList::const_iterator file; - - // TODO: It would be nice if we had code here which distinguishes - // between the 'sword2' and 'sword2demo' targets. The current code - // can't do that since they use the same detectname. + bool isFullVersion = isFullGame(fslist); for (g = Sword2::sword2_settings; g->gameid; ++g) { // Iterate over all files in the given directory for (file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { - const char *fileName = file->getName().c_str(); + // The required game data files can be located in the game directory, or in + // a subdirectory called "clusters". In the latter case, we don't want to + // detect the game in that subdirectory, as this will detect the game twice + // when mass add is searching inside a directory. In this case, the first + // result (the game directory) will be correct, but the second result (the + // clusters subdirectory) will be wrong, as the optional speech, music and + // video data files will be ignored. Note that this fix will skip the game + // data files if the user has placed them inside a "clusters" subdirectory, + // or if he/she points ScummVM directly to the "clusters" directory of the + // game CD. Fixes bug #3049336. + Common::String directory = file->getParent().getName(); + directory.toLowercase(); + if (directory.hasPrefix("clusters") && directory.size() <= 9 && !recursion) + continue; + + if (file->getName().equalsIgnoreCase(g->detectname)) { + // Make sure that the sword2 demo is not mixed up with the + // full version, since they use the same filename for detection + if ((g->features == Sword2::GF_DEMO && isFullVersion) || + (g->features == 0 && !isFullVersion)) + continue; - if (0 == scumm_stricmp(g->detectname, fileName)) { // Match found, add to list of candidates, then abort inner loop. detectedGames.push_back(GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT))); break; @@ -174,12 +204,10 @@ GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { // present e.g. if the user copied the data straight from CD. for (file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { - const char *fileName = file->getName().c_str(); - - if (0 == scumm_stricmp("clusters", fileName)) { + if (file->getName().equalsIgnoreCase("clusters")) { Common::FSList recList; if (file->getChildren(recList, Common::FSNode::kListAll)) { - GameList recGames(detectGames(recList)); + GameList recGames(detectGamesImpl(recList, true)); if (!recGames.empty()) { detectedGames.push_back(recGames); break; @@ -194,6 +222,10 @@ GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { return detectedGames; } +GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const { + return detectGamesImpl(fslist); +} + SaveStateList Sword2MetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp index 6f5da32bc4..216d801f3e 100644 --- a/engines/sword25/gfx/graphicengine.cpp +++ b/engines/sword25/gfx/graphicengine.cpp @@ -376,10 +376,10 @@ bool GraphicEngine::saveThumbnailScreenshot(const Common::String &filename) { void GraphicEngine::ARGBColorToLuaColor(lua_State *L, uint color) { lua_Number components[4] = { - (color >> 16) & 0xff, // Rot - (color >> 8) & 0xff, // Grün - color & 0xff, // Blau - color >> 24, // Alpha + (lua_Number)((color >> 16) & 0xff), // Rot + (lua_Number)((color >> 8) & 0xff), // Grün + (lua_Number)(color & 0xff), // Blau + (lua_Number)(color >> 24), // Alpha }; lua_newtable(L); diff --git a/engines/sword25/util/lua/ldo.cpp b/engines/sword25/util/lua/ldo.cpp index 5d9667f4f0..c162a62e98 100644 --- a/engines/sword25/util/lua/ldo.cpp +++ b/engines/sword25/util/lua/ldo.cpp @@ -6,12 +6,10 @@ // FIXME: LUAI_THROW and LUAI_TRY use either throw/catch or setjmp/longjmp. -// Neither of these is supported in ScummVM. So we need to come up -// with a replacement. The most simple, direct and crude approach: -// Replace "throw" with an "error()" call. Of course we only -// would want to do that if this actually never happens... -#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp -#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp +// Neither of these is supported in ScummVM. Calls to LUAI_THROW have been +// replaced with error() in ScummVM, but the calls to LUAI_TRY remain +#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp // for LUAI_TRY, i.e. try() +#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp // for LUAI_TRY and LUAI_THROW, i.e. throw() #include "common/textconsole.h" @@ -103,12 +101,10 @@ static void resetstack (lua_State *L, int status) { void luaD_throw (lua_State *L, int errcode) { if (L->errorJmp) { L->errorJmp->status = errcode; - // FIXME: LUAI_THROW and LUAI_TRY use either throw/catch or setjmp/longjmp. - // Neither of these is supported in ScummVM. So we need to come up - // with a replacement. The most simple, direct and crude approach: - // Replace "throw" with an "error()" call. Of course we only - // would want to do that if this actually never happens... - LUAI_THROW(L, L->errorJmp); + // LUAI_THROW has been replaced with an error message in ScummVM, together + // with the LUA error code and description + //LUAI_THROW(L, L->errorJmp); + error("LUA error occured, error code is %d (%s)", errcode, luaErrorDescription[errcode]); } else { L->status = cast_byte(errcode); @@ -129,9 +125,8 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { L->errorJmp = &lj; // FIXME: LUAI_THROW and LUAI_TRY use either throw/catch or setjmp/longjmp. // Neither of these is supported in ScummVM. So we need to come up - // with a replacement. The most simple, direct and crude approach: - // Replace "throw" with an "error()" call. Of course we only - // would want to do that if this actually never happens... + // with a replacement. Calls to LUAI_THROW have been replaced with error() + // in ScummVM, but the calls to LUAI_TRY remain LUAI_TRY(L, &lj, (*f)(L, ud); ); diff --git a/engines/sword25/util/lua/llex.cpp b/engines/sword25/util/lua/llex.cpp index f8433d3afa..423f0285ca 100644 --- a/engines/sword25/util/lua/llex.cpp +++ b/engines/sword25/util/lua/llex.cpp @@ -4,6 +4,8 @@ ** See Copyright Notice in lua.h */ +// FIXME: Do not directly use iscntrl from ctype.h. +#define FORBIDDEN_SYMBOL_EXCEPTION_iscntrl #include "common/util.h" diff --git a/engines/sword25/util/lua/lua.h b/engines/sword25/util/lua/lua.h index 08ad80d70f..768ec1ad74 100644 --- a/engines/sword25/util/lua/lua.h +++ b/engines/sword25/util/lua/lua.h @@ -48,6 +48,15 @@ #define LUA_ERRMEM 4 #define LUA_ERRERR 5 +// Added in ScummVM. Refer to http://www.lua.org/manual/5.1/manual.html +static const char* luaErrorDescription[] = { + "No error", + "Coroutine yield", // not an actual error, see lua_resume + "Runtime error", + "Syntax error during pre-compilation", // refer to lua_load + "Memory allocation error", + "Error while running the error handler function" +}; typedef struct lua_State lua_State; diff --git a/engines/sword25/util/lua/luaconf.h b/engines/sword25/util/lua/luaconf.h index 53d0f55290..fb85983998 100644 --- a/engines/sword25/util/lua/luaconf.h +++ b/engines/sword25/util/lua/luaconf.h @@ -621,7 +621,7 @@ union luai_Cast { double l_d; long l_l; }; #else /* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) +//#define LUAI_THROW(L,c) longjmp((c)->b, 1) // replaced with error() in ScummVM #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } #define luai_jmpbuf jmp_buf diff --git a/engines/testbed/config-params.cpp b/engines/testbed/config-params.cpp index d7ead48f63..e89da0b07f 100644 --- a/engines/testbed/config-params.cpp +++ b/engines/testbed/config-params.cpp @@ -69,4 +69,4 @@ void ConfigParams::deleteWriteStream() { } } -} // End of namespace Testbed +} // End of namespace Testbed diff --git a/engines/testbed/config.cpp b/engines/testbed/config.cpp index 6bd4c82b41..6b56616c9b 100644 --- a/engines/testbed/config.cpp +++ b/engines/testbed/config.cpp @@ -304,4 +304,4 @@ void TestbedConfigManager::selectTestsuites() { _configFileInterface.clear(); } -} // End of namespace Testbed +} // End of namespace Testbed diff --git a/engines/testbed/sound.cpp b/engines/testbed/sound.cpp index bb7ae2c055..5af1d8ca31 100644 --- a/engines/testbed/sound.cpp +++ b/engines/testbed/sound.cpp @@ -277,4 +277,4 @@ SoundSubsystemTestSuite::SoundSubsystemTestSuite() { addTest("SampleRates", &SoundSubsystem::sampleRates, true); } -} // End of namespace Testbed +} // End of namespace Testbed diff --git a/engines/tinsel/actors.cpp b/engines/tinsel/actors.cpp index 0ba8b7cdba..531a8e3d12 100644 --- a/engines/tinsel/actors.cpp +++ b/engines/tinsel/actors.cpp @@ -406,7 +406,7 @@ void ActorEvent(CORO_PARAM, int ano, TINSEL_EVENT tEvent, bool bWait, int myEsca * @param bRunScript Flag for whether to run actor's script for the scene */ void StartActor(const T1_ACTOR_STRUC *as, bool bRunScript) { - SCNHANDLE hActorId = FROM_LE_32(as->hActorId); + SCNHANDLE hActorId = FROM_32(as->hActorId); // Zero-out many things actorInfo[hActorId - 1].bHidden = false; @@ -418,15 +418,15 @@ void StartActor(const T1_ACTOR_STRUC *as, bool bRunScript) { actorInfo[hActorId - 1].presObj = NULL; // Store current scene's parameters for this actor - actorInfo[hActorId - 1].mtype = FROM_LE_32(as->masking); - actorInfo[hActorId - 1].actorCode = FROM_LE_32(as->hActorCode); + actorInfo[hActorId - 1].mtype = FROM_32(as->masking); + actorInfo[hActorId - 1].actorCode = FROM_32(as->hActorCode); // Run actor's script for this scene if (bRunScript) { if (bActorsOn) actorInfo[hActorId - 1].bAlive = true; - if (actorInfo[hActorId - 1].bAlive && FROM_LE_32(as->hActorCode)) + if (actorInfo[hActorId - 1].bAlive && FROM_32(as->hActorCode)) ActorEvent(hActorId, STARTUP, PLR_NOEVENT); } } @@ -465,11 +465,11 @@ void StartTaggedActors(SCNHANDLE ah, int numActors, bool bRunScript) { assert(as->hActorCode); // Store current scene's parameters for this tagged actor - taggedActors[i].id = FROM_LE_32(as->hActorId); - taggedActors[i].hTagText = FROM_LE_32(as->hTagText); - taggedActors[i].tagPortionV = FROM_LE_32(as->tagPortionV); - taggedActors[i].tagPortionH = FROM_LE_32(as->tagPortionH); - taggedActors[i].hActorCode = FROM_LE_32(as->hActorCode); + taggedActors[i].id = FROM_32(as->hActorId); + taggedActors[i].hTagText = FROM_32(as->hTagText); + taggedActors[i].tagPortionV = FROM_32(as->tagPortionV); + taggedActors[i].tagPortionH = FROM_32(as->tagPortionH); + taggedActors[i].hActorCode = FROM_32(as->hActorCode); // Run actor's script for this scene if (bRunScript) { @@ -1310,9 +1310,9 @@ void SetActorRGB(int ano, COLORREF color) { assert(ano >= 0 && ano <= NumActors); if (ano) - actorInfo[ano - 1].textColor = TO_LE_32(color); + actorInfo[ano - 1].textColor = TO_32(color); else - defaultColor = TO_LE_32(color); + defaultColor = TO_32(color); } /** diff --git a/engines/tinsel/anim.cpp b/engines/tinsel/anim.cpp index 034296ccc7..a1ec02186c 100644 --- a/engines/tinsel/anim.cpp +++ b/engines/tinsel/anim.cpp @@ -44,9 +44,9 @@ SCRIPTSTATE DoNextFrame(ANIM *pAnim) { while (1) { // repeat until a real image debugC(DEBUG_DETAILED, kTinselDebugAnimations, "DoNextFrame %ph index=%d, op=%xh", (byte *)pAnim, pAnim->scriptIndex, - FROM_LE_32(pAni[pAnim->scriptIndex].op)); + FROM_32(pAni[pAnim->scriptIndex].op)); - switch ((int32)FROM_LE_32(pAni[pAnim->scriptIndex].op)) { + switch ((int32)FROM_32(pAni[pAnim->scriptIndex].op)) { case ANI_END: // end of animation script // move to next opcode @@ -61,7 +61,7 @@ SCRIPTSTATE DoNextFrame(ANIM *pAnim) { pAnim->scriptIndex++; // jump to new frame position - pAnim->scriptIndex += (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op); + pAnim->scriptIndex += (int32)FROM_32(pAni[pAnim->scriptIndex].op); // go fetch a real image break; @@ -101,7 +101,7 @@ SCRIPTSTATE DoNextFrame(ANIM *pAnim) { // move to x adjustment operand pAnim->scriptIndex++; - MultiAdjustXY(pAnim->pObject, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op), 0); + MultiAdjustXY(pAnim->pObject, (int32)FROM_32(pAni[pAnim->scriptIndex].op), 0); // next opcode pAnim->scriptIndex++; @@ -114,7 +114,7 @@ SCRIPTSTATE DoNextFrame(ANIM *pAnim) { // move to y adjustment operand pAnim->scriptIndex++; - MultiAdjustXY(pAnim->pObject, 0, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op)); + MultiAdjustXY(pAnim->pObject, 0, (int32)FROM_32(pAni[pAnim->scriptIndex].op)); // next opcode pAnim->scriptIndex++; @@ -128,11 +128,11 @@ SCRIPTSTATE DoNextFrame(ANIM *pAnim) { // move to x adjustment operand pAnim->scriptIndex++; - x = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op); + x = (int32)FROM_32(pAni[pAnim->scriptIndex].op); // move to y adjustment operand pAnim->scriptIndex++; - y = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op); + y = (int32)FROM_32(pAni[pAnim->scriptIndex].op); MultiAdjustXY(pAnim->pObject, x, y); @@ -189,7 +189,7 @@ SCRIPTSTATE DoNextFrame(ANIM *pAnim) { default: // must be an actual animation frame handle // set objects new animation frame - pAnim->pObject->hShape = FROM_LE_32(pAni[pAnim->scriptIndex].hFrame); + pAnim->pObject->hShape = FROM_32(pAni[pAnim->scriptIndex].hFrame); // re-shape the object MultiReshape(pAnim->pObject); @@ -273,7 +273,7 @@ void SkipFrames(ANIM *pAnim, int numFrames) { while (1) { // repeat until a real image - switch ((int32)FROM_LE_32(pAni[pAnim->scriptIndex].op)) { + switch ((int32)FROM_32(pAni[pAnim->scriptIndex].op)) { case ANI_END: // end of animation script // going off the end is probably a error, but only in Tinsel 1 if (!TinselV2) @@ -286,7 +286,7 @@ void SkipFrames(ANIM *pAnim, int numFrames) { pAnim->scriptIndex++; // jump to new frame position - pAnim->scriptIndex += (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op); + pAnim->scriptIndex += (int32)FROM_32(pAni[pAnim->scriptIndex].op); if (TinselV2) // Done if skip to jump @@ -323,7 +323,7 @@ void SkipFrames(ANIM *pAnim, int numFrames) { // move to x adjustment operand pAnim->scriptIndex++; - MultiAdjustXY(pAnim->pObject, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op), 0); + MultiAdjustXY(pAnim->pObject, (int32)FROM_32(pAni[pAnim->scriptIndex].op), 0); // next opcode pAnim->scriptIndex++; @@ -334,7 +334,7 @@ void SkipFrames(ANIM *pAnim, int numFrames) { // move to y adjustment operand pAnim->scriptIndex++; - MultiAdjustXY(pAnim->pObject, 0, (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op)); + MultiAdjustXY(pAnim->pObject, 0, (int32)FROM_32(pAni[pAnim->scriptIndex].op)); // next opcode pAnim->scriptIndex++; @@ -346,11 +346,11 @@ void SkipFrames(ANIM *pAnim, int numFrames) { // move to x adjustment operand pAnim->scriptIndex++; - x = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op); + x = (int32)FROM_32(pAni[pAnim->scriptIndex].op); // move to y adjustment operand pAnim->scriptIndex++; - y = (int32)FROM_LE_32(pAni[pAnim->scriptIndex].op); + y = (int32)FROM_32(pAni[pAnim->scriptIndex].op); MultiAdjustXY(pAnim->pObject, x, y); @@ -389,7 +389,7 @@ void SkipFrames(ANIM *pAnim, int numFrames) { pAnim->scriptIndex++; } else { // set objects new animation frame - pAnim->pObject->hShape = FROM_LE_32(pAni[pAnim->scriptIndex].hFrame); + pAnim->pObject->hShape = FROM_32(pAni[pAnim->scriptIndex].hFrame); // re-shape the object MultiReshape(pAnim->pObject); @@ -414,7 +414,7 @@ bool AboutToJumpOrEnd(PANIM pAnim) { for (;;) { // repeat until a real image - switch (FROM_LE_32(pAni[zzz].op)) { + switch (FROM_32(pAni[zzz].op)) { case ANI_END: // end of animation script case ANI_JUMP: // do animation jump return true; diff --git a/engines/tinsel/bg.cpp b/engines/tinsel/bg.cpp index a3e21a8227..ed15bfef2a 100644 --- a/engines/tinsel/bg.cpp +++ b/engines/tinsel/bg.cpp @@ -124,28 +124,28 @@ static void BGmainProcess(CORO_PARAM, const void *param) { pReel = (const FREEL *)param; // Get the MULTI_INIT structure - pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pReel->mobj)); + pmi = (const MULTI_INIT *)LockMem(FROM_32(pReel->mobj)); // Initialize and insert the object, and initialize its script. g_pBG[0] = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_WORLD), g_pBG[0]); - InitStepAnimScript(&g_thisAnim[0], g_pBG[0], FROM_LE_32(pReel->script), g_BGspeed); + InitStepAnimScript(&g_thisAnim[0], g_pBG[0], FROM_32(pReel->script), g_BGspeed); g_bgReels = 1; } else { /*** At start of scene ***/ pFilm = (const FILM *)LockMem(g_hBackground); - g_bgReels = FROM_LE_32(pFilm->numreels); + g_bgReels = FROM_32(pFilm->numreels); int i; for (i = 0; i < g_bgReels; i++) { // Get the MULTI_INIT structure - pmi = (PMULTI_INIT) LockMem(FROM_LE_32(pFilm->reels[i].mobj)); + pmi = (PMULTI_INIT) LockMem(FROM_32(pFilm->reels[i].mobj)); // Initialize and insert the object, and initialize its script. g_pBG[i] = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_WORLD), g_pBG[i]); MultiSetZPosition(g_pBG[i], 0); - InitStepAnimScript(&g_thisAnim[i], g_pBG[i], FROM_LE_32(pFilm->reels[i].script), g_BGspeed); + InitStepAnimScript(&g_thisAnim[i], g_pBG[i], FROM_32(pFilm->reels[i].script), g_BGspeed); if (i > 0) g_pBG[i-1]->pSlave = g_pBG[i]; @@ -170,11 +170,11 @@ static void BGmainProcess(CORO_PARAM, const void *param) { // New background during scene if (!TinselV2) { pReel = (const FREEL *)param; - InitStepAnimScript(&g_thisAnim[0], g_pBG[0], FROM_LE_32(pReel->script), g_BGspeed); + InitStepAnimScript(&g_thisAnim[0], g_pBG[0], FROM_32(pReel->script), g_BGspeed); StepAnimScript(&g_thisAnim[0]); } else { pFilm = (const FILM *)LockMem(g_hBackground); - assert(g_bgReels == (int32)FROM_LE_32(pFilm->numreels)); + assert(g_bgReels == (int32)FROM_32(pFilm->numreels)); // Just re-initialize the scripts. for (int i = 0; i < g_bgReels; i++) { @@ -198,7 +198,7 @@ static void BGotherProcess(CORO_PARAM, const void *param) { CORO_END_CONTEXT(_ctx); const FREEL *pReel = (const FREEL *)param; - const MULTI_INIT *pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pReel->mobj)); + const MULTI_INIT *pmi = (const MULTI_INIT *)LockMem(FROM_32(pReel->mobj)); CORO_BEGIN_CODE(_ctx); @@ -206,7 +206,7 @@ static void BGotherProcess(CORO_PARAM, const void *param) { _ctx->pObj = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_WORLD), _ctx->pObj); - InitStepAnimScript(&_ctx->anim, g_pBG[0], FROM_LE_32(pReel->script), g_BGspeed); + InitStepAnimScript(&_ctx->anim, g_pBG[0], FROM_32(pReel->script), g_BGspeed); while (StepAnimScript(&_ctx->anim) != ScriptFinished) CORO_SLEEP(1); @@ -249,16 +249,16 @@ void StartupBackground(CORO_PARAM, SCNHANDLE hFilm) { pim = GetImageFromFilm(hFilm, 0, NULL, NULL, &pfilm); - SetBackPal(FROM_LE_32(pim->hImgPal)); + SetBackPal(FROM_32(pim->hImgPal)); // Extract the film speed - g_BGspeed = ONE_SECOND / FROM_LE_32(pfilm->frate); + g_BGspeed = ONE_SECOND / FROM_32(pfilm->frate); // Start display process for each reel in the film CoroScheduler.createProcess(PID_REEL, BGmainProcess, &pfilm->reels[0], sizeof(FREEL)); if (TinselV0) { - for (uint i = 1; i < FROM_LE_32(pfilm->numreels); ++i) + for (uint i = 1; i < FROM_32(pfilm->numreels); ++i) CoroScheduler.createProcess(PID_REEL, BGotherProcess, &pfilm->reels[i], sizeof(FREEL)); } diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp index 438fd52a81..106e1542d5 100644 --- a/engines/tinsel/bmv.cpp +++ b/engines/tinsel/bmv.cpp @@ -529,9 +529,9 @@ int BMVPlayer::MovieCommand(char cmd, int commandOffset) { if (cmd & CD_PRINT) { PRINT_CMD *pCmd = (PRINT_CMD *)(bigBuffer + commandOffset); - MovieText(Common::nullContext, (int16)READ_LE_UINT16(&pCmd->stringId), - (int16)READ_LE_UINT16(&pCmd->x), - (int16)READ_LE_UINT16(&pCmd->y), + MovieText(Common::nullContext, (int16)READ_16(&pCmd->stringId), + (int16)READ_16(&pCmd->x), + (int16)READ_16(&pCmd->y), pCmd->fontId, NULL, pCmd->duration); @@ -542,9 +542,9 @@ int BMVPlayer::MovieCommand(char cmd, int commandOffset) { TALK_CMD *pCmd = (TALK_CMD *)(bigBuffer + commandOffset); talkColor = TINSEL_RGB(pCmd->r, pCmd->g, pCmd->b); - MovieText(Common::nullContext, (int16)READ_LE_UINT16(&pCmd->stringId), - (int16)READ_LE_UINT16(&pCmd->x), - (int16)READ_LE_UINT16(&pCmd->y), + MovieText(Common::nullContext, (int16)READ_16(&pCmd->stringId), + (int16)READ_16(&pCmd->x), + (int16)READ_16(&pCmd->y), 0, &talkColor, pCmd->duration); @@ -622,7 +622,7 @@ int BMVPlayer::FollowingPacket(int thisPacket, bool bReallyImportant) { if (nextReadSlot*SLOT_SIZE >= thisPacket && thisPacket+3 >= nextReadSlot*SLOT_SIZE) return thisPacket + 3; } - length = (int32)READ_LE_UINT32(bigBuffer + thisPacket + 1); + length = (int32)READ_32(bigBuffer + thisPacket + 1); length &= 0x00ffffff; return thisPacket + length + 4; } @@ -886,7 +886,7 @@ bool BMVPlayer::DoBMVFrame() { return true; default: - length = (int32)READ_LE_UINT32(data + 1); + length = (int32)READ_32(data + 1); length &= 0x00ffffff; graphOffset = nextUseOffset + 4; // Skip command byte and length @@ -922,7 +922,7 @@ bool BMVPlayer::DoBMVFrame() { } if (*data & CD_XSCR) { - xscr = (int16)READ_LE_UINT16(bigBuffer + graphOffset); + xscr = (int16)READ_16(bigBuffer + graphOffset); graphOffset += sz_XSCR_pkt; // Skip scroll offset length -= sz_XSCR_pkt; } else if (*data & BIT0) diff --git a/engines/tinsel/cursor.cpp b/engines/tinsel/cursor.cpp index bf901c03b6..a83e7cd9ca 100644 --- a/engines/tinsel/cursor.cpp +++ b/engines/tinsel/cursor.cpp @@ -125,7 +125,7 @@ static void InitCurTrailObj(int i, int x, int y) { pim = GetImageFromFilm(g_hCursorFilm, i+1, &pfr, &pmi, &pfilm);// Get pointer to image assert(BgPal()); // No background palette - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); // Initialize and insert the object, set its Z-pos, and hide it g_ntrailData[i].trailObj = MultiInitObject(pmi); @@ -134,7 +134,7 @@ static void InitCurTrailObj(int i, int x, int y) { MultiSetAniXY(g_ntrailData[i].trailObj, x, y); // Initialize the animation script - InitStepAnimScript(&g_ntrailData[i].trailAnim, g_ntrailData[i].trailObj, FROM_LE_32(pfr->script), ONE_SECOND / FROM_LE_32(pfilm->frate)); + InitStepAnimScript(&g_ntrailData[i].trailAnim, g_ntrailData[i].trailObj, FROM_32(pfr->script), ONE_SECOND / FROM_32(pfilm->frate)); StepAnimScript(&g_ntrailData[i].trailAnim); } @@ -237,7 +237,7 @@ void RestoreMainCursor() { if (g_McurObj != NULL) { pfilm = (const FILM *)LockMem(g_hCursorFilm); - InitStepAnimScript(&g_McurAnim, g_McurObj, FROM_LE_32(pfilm->reels->script), ONE_SECOND / FROM_LE_32(pfilm->frate)); + InitStepAnimScript(&g_McurAnim, g_McurObj, FROM_32(pfilm->reels->script), ONE_SECOND / FROM_32(pfilm->frate)); StepAnimScript(&g_McurAnim); } g_bHiddenCursor = false; @@ -324,14 +324,14 @@ IMAGE *GetImageFromReel(const FREEL *pfr, const MULTI_INIT **ppmi) { const MULTI_INIT *pmi; const FRAME *pFrame; - pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pfr->mobj)); + pmi = (const MULTI_INIT *)LockMem(FROM_32(pfr->mobj)); if (ppmi) *ppmi = pmi; - pFrame = (const FRAME *)LockMem(FROM_LE_32(pmi->hMulFrame)); + pFrame = (const FRAME *)LockMem(FROM_32(pmi->hMulFrame)); // get pointer to image - return (IMAGE *)LockMem(READ_LE_UINT32(pFrame)); + return (IMAGE *)LockMem(READ_32(pFrame)); } /** @@ -379,18 +379,18 @@ void SetAuxCursor(SCNHANDLE hFilm) { pim = GetImageFromFilm(hFilm, 0, &pfr, &pmi, &pfilm);// Get pointer to image assert(BgPal()); // no background palette - pim->hImgPal = TO_LE_32(BgPal()); // Poke in the background palette + pim->hImgPal = TO_32(BgPal()); // Poke in the background palette - g_ACoX = (short)(FROM_LE_16(pim->imgWidth)/2 - ((int16) FROM_LE_16(pim->anioffX))); - g_ACoY = (short)((FROM_LE_16(pim->imgHeight) & ~C16_FLAG_MASK)/2 - - ((int16) FROM_LE_16(pim->anioffY))); + g_ACoX = (short)(FROM_16(pim->imgWidth)/2 - ((int16) FROM_16(pim->anioffX))); + g_ACoY = (short)((FROM_16(pim->imgHeight) & ~C16_FLAG_MASK)/2 - + ((int16) FROM_16(pim->anioffY))); // Initialize and insert the auxillary cursor object g_AcurObj = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_STATUS), g_AcurObj); // Initialize the animation and set its position - InitStepAnimScript(&g_AcurAnim, g_AcurObj, FROM_LE_32(pfr->script), ONE_SECOND / FROM_LE_32(pfilm->frate)); + InitStepAnimScript(&g_AcurAnim, g_AcurObj, FROM_32(pfr->script), ONE_SECOND / FROM_32(pfilm->frate)); MultiSetAniXY(g_AcurObj, x - g_ACoX, y - g_ACoY); MultiSetZPosition(g_AcurObj, Z_ACURSOR); @@ -481,14 +481,14 @@ static void InitCurObj() { if (TinselV2) { pFilm = (const FILM *)LockMem(g_hCursorFilm); pfr = (const FREEL *)&pFilm->reels[0]; - pmi = (MULTI_INIT *)LockMem(FROM_LE_32(pfr->mobj)); + pmi = (MULTI_INIT *)LockMem(FROM_32(pfr->mobj)); PokeInPalette(pmi); } else { assert(BgPal()); // no background palette pim = GetImageFromFilm(g_hCursorFilm, 0, &pfr, &pmi, &pFilm);// Get pointer to image - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); g_AcurObj = NULL; // No auxillary cursor } @@ -496,7 +496,7 @@ static void InitCurObj() { g_McurObj = MultiInitObject(pmi); MultiInsertObject(GetPlayfieldList(FIELD_STATUS), g_McurObj); - InitStepAnimScript(&g_McurAnim, g_McurObj, FROM_LE_32(pfr->script), ONE_SECOND / FROM_LE_32(pFilm->frate)); + InitStepAnimScript(&g_McurAnim, g_McurObj, FROM_32(pfr->script), ONE_SECOND / FROM_32(pFilm->frate)); } /** @@ -620,7 +620,7 @@ void DwInitCursor(SCNHANDLE bfilm) { g_hCursorFilm = bfilm; pfilm = (const FILM *)LockMem(g_hCursorFilm); - g_numTrails = FROM_LE_32(pfilm->numreels) - 1; + g_numTrails = FROM_32(pfilm->numreels) - 1; assert(g_numTrails <= MAX_TRAILERS); } diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h index 631c2dce14..f6b1487561 100644 --- a/engines/tinsel/detection_tables.h +++ b/engines/tinsel/detection_tables.h @@ -69,7 +69,7 @@ static const TinselGameDescription gameDescriptions[] = { 0, TINSEL_V1, }, -#if 0 + { // Macintosh CD Demo V1 version, with *.scn files, see tracker #3110936 { "dw", @@ -89,7 +89,7 @@ static const TinselGameDescription gameDescriptions[] = { GF_SCNFILES, TINSEL_V1, }, -#endif + { // Multilingual Floppy V1 with *.gra files. // Note: It contains no english subtitles. { @@ -474,7 +474,6 @@ static const TinselGameDescription gameDescriptions[] = { }, #endif -#if 0 { // Mac multilanguage CD { "dw", @@ -491,12 +490,10 @@ static const TinselGameDescription gameDescriptions[] = { }, GID_DW1, 0, - GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + GF_SCNFILES, TINSEL_V1, }, -#endif - { // German CD re-release "Neon Edition" // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT { diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index 56ee2ea752..d0c99f7830 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -234,8 +234,8 @@ enum PARTS_INDEX { #define NM_RS_R_INSET 4 #define NM_RS_THICKNESS 5 #define NM_MOVE_AREA_B_Y 30 -#define NM_SLIDE_INSET (TinselV2 ? 18 : 15) // X offset (from right) of left of scroll region -#define NM_SLIDE_THICKNESS (TinselV2 ? 13 : 4) // thickness of scroll region +#define NM_SLIDE_INSET (TinselV2 ? 18 : 9) // X offset (from right) of left of scroll region +#define NM_SLIDE_THICKNESS (TinselV2 ? 13 : 7) // thickness of scroll region #define NM_UP_ARROW_TOP 34 // Y offset of top of up arrow #define NM_UP_ARROW_BOTTOM 49 // Y offset of bottom of up arrow #define NM_DN_ARROW_TOP 22 // Y offset (from bottom) of top of down arrow @@ -1143,7 +1143,7 @@ static void FirstScene(int first) { // Fill in the rest for (i = 0; i < NUM_RGROUP_BOXES && i + first < g_numScenes; i++) { cd.box[i].textMethod = TM_STRINGNUM; - cd.box[i].ixText = FROM_LE_32(g_pHopper[i + first].hSceneDesc); + cd.box[i].ixText = FROM_32(g_pHopper[i + first].hSceneDesc); } // Blank out the spare ones (if any) while (i < NUM_RGROUP_BOXES) { @@ -1166,10 +1166,10 @@ static void SetChosenScene() { static void FirstEntry(int first) { int i; - g_InvD[INV_MENU].hInvTitle = FROM_LE_32(g_pChosenScene->hSceneDesc); + g_InvD[INV_MENU].hInvTitle = FROM_32(g_pChosenScene->hSceneDesc); // get number of entrances - g_numEntries = FROM_LE_32(g_pChosenScene->numEntries); + g_numEntries = FROM_32(g_pChosenScene->numEntries); // Force first to a sensible value if (first > g_numEntries-NUM_RGROUP_BOXES) @@ -1179,7 +1179,7 @@ static void FirstEntry(int first) { for (i = 0; i < NUM_RGROUP_BOXES && i < g_numEntries; i++) { cd.box[i].textMethod = TM_STRINGNUM; - cd.box[i].ixText = FROM_LE_32(g_pEntries[FROM_LE_32(g_pChosenScene->entryIndex) + i + first].hDesc); + cd.box[i].ixText = FROM_32(g_pEntries[FROM_32(g_pChosenScene->entryIndex) + i + first].hDesc); } // Blank out the spare ones (if any) while (i < NUM_RGROUP_BOXES) { @@ -1191,17 +1191,17 @@ static void FirstEntry(int first) { } static void HopAction() { - PHOPENTRY pEntry = g_pEntries + FROM_LE_32(g_pChosenScene->entryIndex) + cd.selBox + cd.extraBase; + PHOPENTRY pEntry = g_pEntries + FROM_32(g_pChosenScene->entryIndex) + cd.selBox + cd.extraBase; - uint32 hScene = FROM_LE_32(g_pChosenScene->hScene); - uint32 eNumber = FROM_LE_32(pEntry->eNumber); + uint32 hScene = FROM_32(g_pChosenScene->hScene); + uint32 eNumber = FROM_32(pEntry->eNumber); debugC(DEBUG_BASIC, kTinselDebugAnimations, "Scene hopper chose scene %xh,%d\n", hScene, eNumber); - if (FROM_LE_32(pEntry->flags) & fCall) { + if (FROM_32(pEntry->flags) & fCall) { SaveScene(Common::nullContext); NewScene(Common::nullContext, g_pChosenScene->hScene, pEntry->eNumber, TRANS_FADE); } - else if (FROM_LE_32(pEntry->flags) & fHook) + else if (FROM_32(pEntry->flags) & fHook) HookScene(hScene, eNumber, TRANS_FADE); else NewScene(Common::nullContext, hScene, eNumber, TRANS_CUT); @@ -2568,7 +2568,7 @@ static OBJECT *AddInvObject(int num, const FREEL **pfreel, const FILM **pfilm) { pim = GetImageFromFilm(invObj->hIconFilm, 0, pfreel, &pmi, pfilm); // Poke in the background palette - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); // Set up the multi-object pPlayObj = MultiInitObject(pmi); @@ -2609,7 +2609,7 @@ static void FillInInventory() { MultiSetAniXY(g_iconArray[n], g_InvD[g_ino].inventoryX + xpos , g_InvD[g_ino].inventoryY + ypos); MultiSetZPosition(g_iconArray[n], Z_INV_ICONS); - InitStepAnimScript(&g_iconAnims[n], g_iconArray[n], FROM_LE_32(pfr->script), ONE_SECOND / FROM_LE_32(pfilm->frate)); + InitStepAnimScript(&g_iconAnims[n], g_iconArray[n], FROM_32(pfr->script), ONE_SECOND / FROM_32(pfilm->frate)); n++; } @@ -2697,17 +2697,17 @@ static OBJECT *AddObject(const FREEL *pfreel, int num) { pim = GetImageFromReel(pfreel, &pmi); // Poke in the background palette - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); // Horrible bodge involving global variables to save // width and/or height of some window frame components if (num == g_TL) { - g_TLwidth = FROM_LE_16(pim->imgWidth); - g_TLheight = FROM_LE_16(pim->imgHeight) & ~C16_FLAG_MASK; + g_TLwidth = FROM_16(pim->imgWidth); + g_TLheight = FROM_16(pim->imgHeight) & ~C16_FLAG_MASK; } else if (num == g_TR) { - g_TRwidth = FROM_LE_16(pim->imgWidth); + g_TRwidth = FROM_16(pim->imgWidth); } else if (num == g_BL) { - g_BLheight = FROM_LE_16(pim->imgHeight) & ~C16_FLAG_MASK; + g_BLheight = FROM_16(pim->imgHeight) & ~C16_FLAG_MASK; } // Set up and insert the multi-object @@ -2723,7 +2723,7 @@ static OBJECT *AddObject(const FREEL *pfreel, int num) { static void AddSlider(OBJECT **slide, const FILM *pfilm) { g_SlideObject = *slide = AddObject(&pfilm->reels[IX_SLIDE], -1); - MultiSetAniXY(*slide, MultiRightmost(g_RectObject) + (TinselV2 ? NM_SLX : -M_SXOFF + 2) - 1, + MultiSetAniXY(*slide, MultiRightmost(g_RectObject) + (TinselV2 ? NM_SLX : -M_SXOFF + 2), g_InvD[g_ino].inventoryY + g_sliderYpos); MultiSetZPosition(*slide, Z_INV_MFRAME); } @@ -3318,7 +3318,7 @@ static void ConstructInventory(InventoryType filling) { } } } else if (g_InvD[g_ino].NoofItems > g_InvD[g_ino].NoofHicons*g_InvD[g_ino].NoofVicons) { - g_sliderYmin = g_TLheight - (TinselV2 ? 2 : 1); + g_sliderYmin = g_TLheight - (TinselV2 ? 1 : 2); g_sliderYmax = g_TLheight + eV + (TinselV2 ? 12 : 10); AddSlider(&retObj[n++], pfilm); } @@ -3406,9 +3406,9 @@ static void AlterCursor(int num) { pim = GetImageFromFilm(g_hWinParts, num, &pfreel); // Poke in the background palette - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); - SetTempCursor(FROM_LE_32(pfreel->script)); + SetTempCursor(FROM_32(pfreel->script)); } enum InvCursorFN {IC_AREA, IC_DROP}; @@ -4861,50 +4861,101 @@ static void InvDragEnd() { g_Xchange = g_Ychange = 0; // Probably no need, but does no harm! } -static void MenuPageDown() { +static bool MenuDown(int lines) { if (cd.box == loadBox || cd.box == saveBox) { - if (cd.extraBase < MAX_SAVED_FILES-NUM_RGROUP_BOXES) { - FirstFile(cd.extraBase+(NUM_RGROUP_BOXES - 1)); + if (cd.extraBase < MAX_SAVED_FILES - NUM_RGROUP_BOXES) { + FirstFile(cd.extraBase + lines); AddBoxes(true); - cd.selBox = NUM_RGROUP_BOXES - 1; - Select(cd.selBox, true); + return true; } } else if (cd.box == hopperBox1) { if (cd.extraBase < g_numScenes - NUM_RGROUP_BOXES) { - FirstScene(cd.extraBase + (NUM_RGROUP_BOXES - 1)); + FirstScene(cd.extraBase + lines); AddBoxes(true); - if (cd.selBox) - cd.selBox = NUM_RGROUP_BOXES - 1; - Select(cd.selBox, true); + return true; } } else if (cd.box == hopperBox2) { if (cd.extraBase < g_numEntries - NUM_RGROUP_BOXES) { - FirstEntry(cd.extraBase+(NUM_RGROUP_BOXES - 1)); + FirstEntry(cd.extraBase + lines); AddBoxes(true); - if (cd.selBox) - cd.selBox = NUM_RGROUP_BOXES - 1; - Select(cd.selBox, true); + return true; } } + return false; } -static void MenuPageUp() { +static bool MenuUp(int lines) { if (cd.extraBase > 0) { if (cd.box == loadBox || cd.box == saveBox) - FirstFile(cd.extraBase-(NUM_RGROUP_BOXES - 1)); + FirstFile(cd.extraBase - lines); else if (cd.box == hopperBox1) - FirstScene(cd.extraBase-(NUM_RGROUP_BOXES - 1)); + FirstScene(cd.extraBase - lines); else if (cd.box == hopperBox2) - FirstEntry(cd.extraBase-(NUM_RGROUP_BOXES - 1)); + FirstEntry(cd.extraBase - lines); else - return; + return false; AddBoxes(true); + return true; + } + return false; +} + +static void MenuRollDown() { + if (MenuDown(1)) { + if (cd.selBox > 0) + cd.selBox--; + Select(cd.selBox, true); + } +} + +static void MenuRollUp() { + if (MenuUp(1)) { + if (cd.selBox < NUM_RGROUP_BOXES - 1) + cd.selBox++; + Select(cd.selBox, true); + } +} + +static void MenuPageDown() { + if (MenuDown(NUM_RGROUP_BOXES - 1)) { + cd.selBox = NUM_RGROUP_BOXES - 1; + Select(cd.selBox, true); + } +} + +static void MenuPageUp() { + if (MenuUp(NUM_RGROUP_BOXES - 1)) { cd.selBox = 0; Select(cd.selBox, true); } } +static void InventoryDown() { + // This code is a copy of the IB_SLIDE_DOWN case in InvWalkTo + // TODO: So share this duplicate code + if (g_InvD[g_ino].NoofVicons == 1) + if (g_InvD[g_ino].FirstDisp + g_InvD[g_ino].NoofHicons*g_InvD[g_ino].NoofVicons < g_InvD[g_ino].NoofItems) + g_InvD[g_ino].FirstDisp += g_InvD[g_ino].NoofHicons; + for (int i = 1; i < g_InvD[g_ino].NoofVicons; i++) { + if (g_InvD[g_ino].FirstDisp + g_InvD[g_ino].NoofHicons*g_InvD[g_ino].NoofVicons < g_InvD[g_ino].NoofItems) + g_InvD[g_ino].FirstDisp += g_InvD[g_ino].NoofHicons; + } + g_ItemsChanged = true; +} + +static void InventoryUp() { + // This code is a copy of the I_SLIDE_UP case in InvWalkTo + // TODO: So share this duplicate code + if (g_InvD[g_ino].NoofVicons == 1) + g_InvD[g_ino].FirstDisp -= g_InvD[g_ino].NoofHicons; + for (int i = 1; i < g_InvD[g_ino].NoofVicons; i++) + g_InvD[g_ino].FirstDisp -= g_InvD[g_ino].NoofHicons; + if (g_InvD[g_ino].FirstDisp < 0) + g_InvD[g_ino].FirstDisp = 0; + g_ItemsChanged = true; +} + /**************************************************************************/ /************** Incoming events - further processing **********************/ /**************************************************************************/ @@ -5399,42 +5450,47 @@ extern void EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) { case PLR_PGDN: if (g_ino == INV_MENU) { - // Only act if load or save screen + // Load or Save screen MenuPageDown(); } else { - // This code is a copy of the IB_SLIDE_DOWN case in InvWalkTo - // TODO: So share this duplicate code - if (g_InvD[g_ino].NoofVicons == 1) - if (g_InvD[g_ino].FirstDisp + g_InvD[g_ino].NoofHicons*g_InvD[g_ino].NoofVicons < g_InvD[g_ino].NoofItems) - g_InvD[g_ino].FirstDisp += g_InvD[g_ino].NoofHicons; - for (int i = 1; i < g_InvD[g_ino].NoofVicons; i++) { - if (g_InvD[g_ino].FirstDisp + g_InvD[g_ino].NoofHicons*g_InvD[g_ino].NoofVicons < g_InvD[g_ino].NoofItems) - g_InvD[g_ino].FirstDisp += g_InvD[g_ino].NoofHicons; - } - g_ItemsChanged = true; + // Inventory window + InventoryDown(); } break; case PLR_PGUP: if (g_ino == INV_MENU) { - // Only act if load or save screen + // Load or Save screen MenuPageUp(); } else { - // This code is a copy of the I_SLIDE_UP case in InvWalkTo - // TODO: So share this duplicate code - if (g_InvD[g_ino].NoofVicons == 1) - g_InvD[g_ino].FirstDisp -= g_InvD[g_ino].NoofHicons; - for (int i = 1; i < g_InvD[g_ino].NoofVicons; i++) - g_InvD[g_ino].FirstDisp -= g_InvD[g_ino].NoofHicons; - if (g_InvD[g_ino].FirstDisp < 0) - g_InvD[g_ino].FirstDisp = 0; - g_ItemsChanged = true; + // Inventory window + InventoryUp(); + } + break; + + case PLR_WHEEL_DOWN: + if (g_ino == INV_MENU) { + // Load or Save screen + MenuRollDown(); + } else { + // Inventory window + InventoryDown(); + } + break; + + case PLR_WHEEL_UP: + if (g_ino == INV_MENU) { + // Load or Save screen + MenuRollUp(); + } else { + // Inventory window + InventoryUp(); } break; case PLR_HOME: if (g_ino == INV_MENU) { - // Only act if load or save screen + // Load or Save screen if (cd.box == loadBox || cd.box == saveBox) FirstFile(0); else if (cd.box == hopperBox1) @@ -5448,6 +5504,7 @@ extern void EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) { cd.selBox = 0; Select(cd.selBox, true); } else { + // Inventory window g_InvD[g_ino].FirstDisp = 0; g_ItemsChanged = true; } @@ -5455,6 +5512,7 @@ extern void EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) { case PLR_END: if (g_ino == INV_MENU) { + // Load or Save screen if (cd.box == loadBox || cd.box == saveBox) FirstFile(MAX_SAVED_FILES); // Will get reduced to appropriate value else if (cd.box == hopperBox1) @@ -5468,6 +5526,7 @@ extern void EventToInventory(PLR_EVENT pEvent, const Common::Point &coOrds) { cd.selBox = 0; Select(cd.selBox, true); } else { + // Inventory window g_InvD[g_ino].FirstDisp = g_InvD[g_ino].NoofItems - g_InvD[g_ino].NoofHicons*g_InvD[g_ino].NoofVicons; if (g_InvD[g_ino].FirstDisp < 0) g_InvD[g_ino].FirstDisp = 0; @@ -5560,21 +5619,6 @@ extern void RegisterIcons(void *cptr, int num) { memmove(destP, srcP, 12); destP->attribute = 0; } - } else if (TinselV1Mac) { - // Macintosh version has BE encoded resources, so the values need to be byte swapped - MEM_NODE *node = MemoryAllocFixed(g_numObjects * sizeof(INV_OBJECT)); - assert(node); - g_invObjects = (INV_OBJECT *)MemoryDeref(node); - assert(g_invObjects); - INV_OBJECT *srcP = (INV_OBJECT *)cptr; - INV_OBJECT *destP = (INV_OBJECT *)g_invObjects; - - for (int i = 0; i < num; ++i, ++destP, ++srcP) { - destP->id = FROM_BE_32(srcP->id); - destP->hIconFilm = FROM_BE_32(srcP->hIconFilm); - destP->hScript = FROM_BE_32(srcP->hScript); - destP->attribute = FROM_BE_32(srcP->attribute); - } } else if (TinselV2) { if (g_invFilms == NULL) { // First time - allocate memory @@ -5613,7 +5657,7 @@ extern void setInvWinParts(SCNHANDLE hf) { #ifdef DEBUG pfilm = (const FILM *)LockMem(hf); - assert(FROM_LE_32(pfilm->numreels) >= (uint32)(TinselV2 ? T2_HOPEDFORREELS : T1_HOPEDFORREELS)); // not as many reels as expected + assert(FROM_32(pfilm->numreels) >= (uint32)(TinselV2 ? T2_HOPEDFORREELS : T1_HOPEDFORREELS)); // not as many reels as expected #endif } @@ -5630,7 +5674,7 @@ extern void setFlagFilms(SCNHANDLE hf) { #ifdef DEBUG pfilm = (const FILM *)LockMem(hf); - assert(FROM_LE_32(pfilm->numreels) >= HOPEDFORFREELS); // not as many reels as expected + assert(FROM_32(pfilm->numreels) >= HOPEDFORFREELS); // not as many reels as expected #endif } diff --git a/engines/tinsel/events.cpp b/engines/tinsel/events.cpp index 1aa4d34227..61d3903f1a 100644 --- a/engines/tinsel/events.cpp +++ b/engines/tinsel/events.cpp @@ -389,7 +389,8 @@ void PlayerEvent(PLR_EVENT pEvent, const Common::Point &coOrds) { "PLR_PROV_WALKTO", "PLR_WALKTO", "PLR_LOOK", "PLR_ACTION", "PLR_ESCAPE", "PLR_MENU", "PLR_QUIT", "PLR_PGUP", "PLR_PGDN", "PLR_HOME", "PLR_END", "PLR_DRAG1_START", "PLR_DRAG1_END", "PLR_DRAG2_START", "PLR_DRAG2_END", - "PLR_JUMP", "PLR_NOEVENT"}; + "PLR_JUMP", "PLR_NOEVENT", "PLR_SAVE", "PLR_LOAD", "PLR_WHEEL_UP", + "PLR_WHEEL_DOWN"}; debugC(DEBUG_BASIC, kTinselDebugActions, "%s - (%d,%d)", actionList[pEvent], coOrds.x, coOrds.y); static uint32 lastRealAction = 0; // FIXME: Avoid non-const global vars diff --git a/engines/tinsel/events.h b/engines/tinsel/events.h index cdf5ae2ae4..51669e4680 100644 --- a/engines/tinsel/events.h +++ b/engines/tinsel/events.h @@ -65,6 +65,8 @@ enum PLR_EVENT { PLR_NOEVENT = 16, PLR_SAVE = 17, PLR_LOAD = 18, + PLR_WHEEL_UP = 19, + PLR_WHEEL_DOWN = 20, // Aliases used for DW1 actions PLR_SLEFT = PLR_WALKTO, diff --git a/engines/tinsel/faders.cpp b/engines/tinsel/faders.cpp index c1574ff963..e9517103a9 100644 --- a/engines/tinsel/faders.cpp +++ b/engines/tinsel/faders.cpp @@ -106,7 +106,7 @@ static void FadeProcess(CORO_PARAM, const void *param) { FadingPalette(pFade->pPalQ, true); // get pointer to palette - reduce pointer indirection a bit - _ctx->pPalette = (PALETTE *)LockMem(pFade->pPalQ->hPal); + _ctx->pPalette = (PALETTE *)LockMem(FROM_32(pFade->pPalQ->hPal)); for (_ctx->pColMult = pFade->pColorMultTable; *_ctx->pColMult >= 0; _ctx->pColMult++) { // go through all multipliers in table - until a negative entry @@ -117,10 +117,10 @@ static void FadeProcess(CORO_PARAM, const void *param) { pFade->pPalQ->numColors, (uint32) *_ctx->pColMult); else FadePalette(_ctx->fadeRGB, _ctx->pPalette->palRGB, - FROM_LE_32(_ctx->pPalette->numColors), (uint32) *_ctx->pColMult); + FROM_32(_ctx->pPalette->numColors), (uint32) *_ctx->pColMult); // send new palette to video DAC - UpdateDACqueue(pFade->pPalQ->posInDAC, FROM_LE_32(_ctx->pPalette->numColors), _ctx->fadeRGB); + UpdateDACqueue(pFade->pPalQ->posInDAC, FROM_32(_ctx->pPalette->numColors), _ctx->fadeRGB); // allow time for video DAC to be updated CORO_SLEEP(1); diff --git a/engines/tinsel/font.cpp b/engines/tinsel/font.cpp index 54aa7cc15f..3dba56468b 100644 --- a/engines/tinsel/font.cpp +++ b/engines/tinsel/font.cpp @@ -102,16 +102,16 @@ void FettleFontPal(SCNHANDLE fontPal) { assert(g_hTalkFont); // Talk font not declared pFont = (const FONT *)LockMem(g_hTagFont); - pImg = (IMAGE *)LockMem(FROM_LE_32(pFont->fontInit.hObjImg)); // get image for char 0 + pImg = (IMAGE *)LockMem(FROM_32(pFont->fontInit.hObjImg)); // get image for char 0 if (!TinselV2) - pImg->hImgPal = TO_LE_32(fontPal); + pImg->hImgPal = TO_32(fontPal); else pImg->hImgPal = 0; pFont = (const FONT *)LockMem(g_hTalkFont); - pImg = (IMAGE *)LockMem(FROM_LE_32(pFont->fontInit.hObjImg)); // get image for char 0 + pImg = (IMAGE *)LockMem(FROM_32(pFont->fontInit.hObjImg)); // get image for char 0 if (!TinselV2) - pImg->hImgPal = TO_LE_32(fontPal); + pImg->hImgPal = TO_32(fontPal); else pImg->hImgPal = 0; diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp index 9b06b1a501..b917775360 100644 --- a/engines/tinsel/graphics.cpp +++ b/engines/tinsel/graphics.cpp @@ -73,7 +73,7 @@ uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) { while (remainingBlocks) { // Repeat until all blocks are decompressed if (!controlBits) { - controlData = READ_LE_UINT16(srcIdx); + controlData = READ_16(srcIdx); srcIdx += 2; // If bit 15 of controlData is enabled, compression data is type 1. @@ -92,7 +92,7 @@ uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) { // If there is compression, we need to fetch an index // to be treated as "base" for compression. if (compressionType != 0) { - controlData = READ_LE_UINT16(srcIdx); + controlData = READ_16(srcIdx); srcIdx += 2; baseIndex = controlData; } @@ -114,7 +114,7 @@ uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) { switch (compressionType) { case 0: // No compression, plain copy of indexes while (decremTiles) { - WRITE_LE_UINT16(dstIdx, READ_LE_UINT16(srcIdx)); + WRITE_LE_UINT16(dstIdx, READ_16(srcIdx)); srcIdx += 2; dstIdx += 2; decremTiles--; @@ -212,6 +212,82 @@ static void t0WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply } /** + * Straight rendering with transparency support, Mac variant + */ +static void MacDrawTiles(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClipping) { + int yClip = 0; + + if (applyClipping) { + // Adjust the height down to skip any bottom clipping + pObj->height -= pObj->botClip; + yClip = pObj->topClip; + } + + // Simple RLE-like scheme: the two first bytes of each data chunk determine + // if bytes should be repeated or copied. + // Example: 10 00 00 20 will repeat byte 0x0 0x10 times, and will copy 0x20 + // bytes from the input stream afterwards + + // Vertical loop + for (int y = 0; y < pObj->height; ++y) { + // Get the start of the next line output + uint8 *tempDest = destP; + + int leftClip = applyClipping ? pObj->leftClip : 0; + int rightClip = applyClipping ? pObj->rightClip : 0; + + // Horizontal loop + for (int x = 0; x < pObj->width; ) { + byte repeatBytes = *srcP++; + + if (repeatBytes) { + uint clipAmount = MIN<int>(repeatBytes, leftClip); + leftClip -= clipAmount; + x += clipAmount; + + // Repeat of a given color + byte color = *srcP++; + int runLength = repeatBytes - clipAmount; + int rptLength = MAX(MIN(runLength, pObj->width - rightClip - x), 0); + if (yClip == 0) { + if (color != 0) + memset(tempDest, color, rptLength); + tempDest += rptLength; + } + + x += runLength; + } else { + // Copy a specified sequence length of pixels + byte copyBytes = *srcP++; + + uint clipAmount = MIN<int>(copyBytes, leftClip); + leftClip -= clipAmount; + x += clipAmount; + srcP += clipAmount; + + int runLength = copyBytes - clipAmount; + int rptLength = MAX(MIN(runLength, pObj->width - rightClip - x), 0); + if (yClip == 0) { + memmove(tempDest, srcP, rptLength); + tempDest += rptLength; + } + + int overflow = (copyBytes % 2) == 0 ? 0 : 2 - (copyBytes % 2); + x += runLength; + srcP += runLength + overflow; + } + } // horizontal loop + + // Move to next line + if (yClip > 0) + --yClip; + else + destP += SCREEN_WIDTH; + } // vertical loop +} + + +/** * Straight rendering with transparency support, PSX variant supporting also 4-BIT clut data */ static void PsxDrawTiles(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClipping, bool fourBitClut, uint32 psxSkipBytes, byte *psxMapperTable, bool transparency) { @@ -822,120 +898,59 @@ void DrawObject(DRAWOBJECT *pObj) { // Handle various draw types uint8 typeId = pObj->flags & 0xff; + int packType = pObj->flags >> 14; // TinselV2 - if (TinselV2) { - // Tinsel v2 decoders - // Initial switch statement for the different bit packing types - int packType = pObj->flags >> 14; - - if (packType == 0) { - // No color packing - switch (typeId) { - case 0x01: - case 0x11: - case 0x41: - case 0x51: - case 0x81: - case 0xC1: - t2WrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40, (typeId & 0x10) != 0); - break; - case 0x02: - case 0x42: - // This renderer called 'RlWrtAll', but is the same as t2WrtNonZero - t2WrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40, false); - break; - case 0x04: - case 0x44: - // WrtConst with/without clipping - WrtConst(pObj, destPtr, typeId == 0x44); - break; - case 0x08: - case 0x48: - WrtAll(pObj, srcPtr, destPtr, typeId >= 0x40); - break; - case 0x84: - case 0xC4: - // WrtTrans with/without clipping - WrtTrans(pObj, destPtr, typeId == 0xC4); - break; - default: - error("Unknown drawing type %d", typeId); - } - } else { - // 1 = 16 from 240 - // 2 = 16 from 224 - // 3 = variable color - if (packType == 1) pObj->baseCol = 0xF0; - else if (packType == 2) pObj->baseCol = 0xE0; - - PackedWrtNonZero(pObj, srcPtr, destPtr, (pObj->flags & DMA_CLIP) != 0, - (pObj->flags & DMA_FLIPH), packType); - } + if (TinselV2 && packType != 0) { + // Color packing for TinselV2 + + if (packType == 1) + pObj->baseCol = 0xF0; // 16 from 240 + else if (packType == 2) + pObj->baseCol = 0xE0; // 16 from 224 + // 3 = variable color - } else if (TinselV1PSX) { - // Tinsel v1 decoders, PSX specific variants + PackedWrtNonZero(pObj, srcPtr, destPtr, (pObj->flags & DMA_CLIP) != 0, + (pObj->flags & DMA_FLIPH), packType); + } else { switch (typeId) { - case 0x01: - case 0x41: - PsxDrawTiles(pObj, srcPtr, destPtr, typeId >= 0x40, psxFourBitClut, psxSkipBytes, psxMapperTable, true); - break; - case 0x08: - case 0x48: - PsxDrawTiles(pObj, srcPtr, destPtr, typeId >= 0x40, psxFourBitClut, psxSkipBytes, psxMapperTable, false); - break; - case 0x84: - case 0xC4: - // WrtTrans with/without clipping - WrtTrans(pObj, destPtr, typeId == 0xC4); - break; - case 0x04: - case 0x44: - // WrtConst with/without clipping - WrtConst(pObj, destPtr, typeId == 0x44); + case 0x01: // all versions, draw sprite without clipping + case 0x41: // all versions, draw sprite with clipping + case 0x02: // TinselV2, draw sprite without clipping + case 0x11: // TinselV2, draw sprite without clipping, flipped horizontally + case 0x42: // TinselV2, draw sprite with clipping + case 0x51: // TinselV2, draw sprite with clipping, flipped horizontally + case 0x81: // TinselV2, draw sprite with clipping + case 0xC1: // TinselV2, draw sprite with clipping + assert(TinselV2 || (typeId == 0x01 || typeId == 0x41)); + + if (TinselV2) + t2WrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40, (typeId & 0x10) != 0); + else if (TinselV1PSX) + PsxDrawTiles(pObj, srcPtr, destPtr, typeId == 0x41, psxFourBitClut, psxSkipBytes, psxMapperTable, true); + else if (TinselV1Mac) + MacDrawTiles(pObj, srcPtr, destPtr, typeId == 0x41); + else if (TinselV1) + WrtNonZero(pObj, srcPtr, destPtr, typeId == 0x41); + else if (TinselV0) + t0WrtNonZero(pObj, srcPtr, destPtr, typeId == 0x41); break; - default: - error("Unknown drawing type %d", typeId); - } - } else if (TinselV1) { - // Tinsel v1 decoders - switch (typeId) { - case 0x01: - case 0x08: - case 0x41: - case 0x48: - WrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40); + case 0x08: // draw background without clipping + case 0x48: // draw background with clipping + if (TinselV2 || TinselV1Mac || TinselV0) + WrtAll(pObj, srcPtr, destPtr, typeId == 0x48); + else if (TinselV1PSX) + PsxDrawTiles(pObj, srcPtr, destPtr, typeId == 0x48, psxFourBitClut, psxSkipBytes, psxMapperTable, false); + else if (TinselV1) + WrtNonZero(pObj, srcPtr, destPtr, typeId == 0x48); break; - - case 0x04: - case 0x44: - // WrtConst with/without clipping + case 0x04: // fill with constant color without clipping + case 0x44: // fill with constant color with clipping WrtConst(pObj, destPtr, typeId == 0x44); break; - - case 0x84: - case 0xC4: - // WrtTrans with/without clipping + case 0x84: // draw transparent surface without clipping + case 0xC4: // draw transparent surface with clipping WrtTrans(pObj, destPtr, typeId == 0xC4); break; - - default: - error("Unknown drawing type %d", typeId); - } - } else { - // Tinsel v0 decoders - switch (typeId) { - case 0x01: - case 0x41: - t0WrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40); - break; - case 0x08: - case 0x48: - WrtAll(pObj, srcPtr, destPtr, typeId >= 0x40); - break; - case 0x84: - case 0xC4: - WrtTrans(pObj, destPtr, (typeId & 0x40) != 0); - break; default: error("Unknown drawing type %d", typeId); } diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 14d588dcec..3921414b01 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -30,6 +30,7 @@ #include "tinsel/dw.h" #include "tinsel/handle.h" #include "tinsel/heapmem.h" // heap memory manager +#include "tinsel/scn.h" // for the DW1 Mac resource handler #include "tinsel/timers.h" // for DwGetCurrentTime() #include "tinsel/tinsel.h" #include "tinsel/scene.h" @@ -85,7 +86,6 @@ static char g_szCdPlayFile[100]; static void LoadFile(MEMHANDLE *pH); // load a memory block as a file - /** * Loads the graphics handle table index file and preloads all the * permanent graphics etc. @@ -300,7 +300,7 @@ void LoadFile(MEMHANDLE *pH) { // discardable - unlock the memory MemoryUnlock(pH->_node); - + // set the loaded flag pH->filesize |= fLoaded; @@ -322,6 +322,7 @@ void LoadFile(MEMHANDLE *pH) { */ byte *LockMem(SCNHANDLE offset) { uint32 handle = offset >> SCNHANDLE_SHIFT; // calc memory handle to use + //debug("Locking offset of type %d (%x), offset %d, handle %d", (offset & HANDLEMASK) >> SCNHANDLE_SHIFT, (offset & HANDLEMASK) >> SCNHANDLE_SHIFT, offset & OFFSETMASK, handle); MEMHANDLE *pH; // points to table entry // range check the memory handle diff --git a/engines/tinsel/multiobj.cpp b/engines/tinsel/multiobj.cpp index c48fefdd22..37769a7819 100644 --- a/engines/tinsel/multiobj.cpp +++ b/engines/tinsel/multiobj.cpp @@ -40,22 +40,22 @@ OBJECT *MultiInitObject(const MULTI_INIT *pInitTbl) { OBJECT *pFirst, *pObj; // object pointers FRAME *pFrame; // list of images for the multi-part object - if (FROM_LE_32(pInitTbl->hMulFrame)) { + if (FROM_32(pInitTbl->hMulFrame)) { // we have a frame handle - pFrame = (FRAME *)LockMem(FROM_LE_32(pInitTbl->hMulFrame)); + pFrame = (FRAME *)LockMem(FROM_32(pInitTbl->hMulFrame)); - obj_init.hObjImg = READ_LE_UINT32(pFrame); // first objects shape + obj_init.hObjImg = READ_32(pFrame); // first objects shape } else { // this must be a animation list for a NULL object pFrame = NULL; obj_init.hObjImg = 0; // first objects shape } // init the object init table - obj_init.objFlags = (int)FROM_LE_32(pInitTbl->mulFlags); // all objects have same flags - obj_init.objID = (int)FROM_LE_32(pInitTbl->mulID); // all objects have same ID - obj_init.objX = (int)FROM_LE_32(pInitTbl->mulX); // all objects have same X ani pos - obj_init.objY = (int)FROM_LE_32(pInitTbl->mulY); // all objects have same Y ani pos - obj_init.objZ = (int)FROM_LE_32(pInitTbl->mulZ); // all objects have same Z pos + obj_init.objFlags = (int)FROM_32(pInitTbl->mulFlags); // all objects have same flags + obj_init.objID = (int)FROM_32(pInitTbl->mulID); // all objects have same ID + obj_init.objX = (int)FROM_32(pInitTbl->mulX); // all objects have same X ani pos + obj_init.objY = (int)FROM_32(pInitTbl->mulY); // all objects have same Y ani pos + obj_init.objZ = (int)FROM_32(pInitTbl->mulZ); // all objects have same Z pos // create and init the first object pObj = pFirst = InitObject(&obj_init); @@ -65,9 +65,9 @@ OBJECT *MultiInitObject(const MULTI_INIT *pInitTbl) { pFrame++; - while (READ_LE_UINT32(pFrame) != 0) { + while (READ_32(pFrame) != 0) { // set next objects shape - obj_init.hObjImg = READ_LE_UINT32(pFrame); + obj_init.hObjImg = READ_32(pFrame); // create next object and link to previous pObj = pObj->pSlave = InitObject(&obj_init); @@ -378,9 +378,9 @@ void MultiReshape(OBJECT *pMultiObj) { // update previous pMultiObj->hMirror = hFrame; - while (READ_LE_UINT32(pFrame) != 0 && pMultiObj != NULL) { + while (READ_32(pFrame) != 0 && pMultiObj != NULL) { // a normal image - update the current object with this image - AnimateObject(pMultiObj, READ_LE_UINT32(pFrame)); + AnimateObject(pMultiObj, READ_32(pFrame)); // move to next image for this frame pFrame++; diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index b3bfbcc5dc..dab2a897fc 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -135,6 +135,10 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) { if (ConfMan.hasKey("mute")) mute = ConfMan.getBool("mute"); + // The Macintosh version of DW1 uses raw PCM for music + if (TinselV1Mac) + return _vm->_sound->playDW1MacMusic(dwFileOffset); + SetMidiVolume(mute ? 0 : _vm->_config->_musicVolume); // the index and length of the last tune loaded @@ -281,6 +285,11 @@ void OpenMidiFiles() { if (TinselV0 || TinselV2) return; + // The Macintosh version of DW1 does not use MIDI for music. + // It uses PCM music instead, which is quite big to be preloaded here. + if (TinselV1Mac) + return; + if (g_midiBuffer.pDat) // already allocated return; @@ -784,8 +793,8 @@ bool PCMMusicPlayer::getNextChunk() { // Set parameters for this chunk of music id = _scriptNum; while (id--) - script = scriptBuffer + READ_LE_UINT32(script); - snum = FROM_LE_32(script[_scriptIndex++]); + script = scriptBuffer + READ_32(script); + snum = FROM_32(script[_scriptIndex++]); if (snum == MUSIC_JUMP || snum == MUSIC_END) { // Let usual code sort it out! @@ -797,11 +806,11 @@ bool PCMMusicPlayer::getNextChunk() { musicSegments = (MusicSegment *) LockMem(_hSegment); - assert(FROM_LE_32(musicSegments[snum].numChannels) == 1); - assert(FROM_LE_32(musicSegments[snum].bitsPerSample) == 16); + assert(FROM_32(musicSegments[snum].numChannels) == 1); + assert(FROM_32(musicSegments[snum].bitsPerSample) == 16); - sampleOffset = FROM_LE_32(musicSegments[snum].sampleOffset); - sampleLength = FROM_LE_32(musicSegments[snum].sampleLength); + sampleOffset = FROM_32(musicSegments[snum].sampleOffset); + sampleLength = FROM_32(musicSegments[snum].sampleLength); sampleCLength = (((sampleLength + 63) & ~63)*33)/64; if (!file.open(_filename)) @@ -839,14 +848,14 @@ bool PCMMusicPlayer::getNextChunk() { id = _scriptNum; while (id--) - script = scriptBuffer + READ_LE_UINT32(script); - snum = FROM_LE_32(script[_scriptIndex]); + script = scriptBuffer + READ_32(script); + snum = FROM_32(script[_scriptIndex]); if (snum == MUSIC_END) { _state = S_END2; } else { if (snum == MUSIC_JUMP) - _scriptIndex = FROM_LE_32(script[_scriptIndex+1]); + _scriptIndex = FROM_32(script[_scriptIndex+1]); _state = _forcePlay ? S_NEW : S_NEXT; _forcePlay = false; diff --git a/engines/tinsel/object.cpp b/engines/tinsel/object.cpp index cbe5b0a88f..cbf1c86649 100644 --- a/engines/tinsel/object.cpp +++ b/engines/tinsel/object.cpp @@ -302,23 +302,23 @@ void GetAniOffset(SCNHANDLE hImg, int flags, int *pAniX, int *pAniY) { const IMAGE *pImg = (const IMAGE *)LockMem(hImg); // set ani X - *pAniX = (int16) FROM_LE_16(pImg->anioffX); + *pAniX = (int16) FROM_16(pImg->anioffX); // set ani Y - *pAniY = (int16) FROM_LE_16(pImg->anioffY); + *pAniY = (int16) FROM_16(pImg->anioffY); if (flags & DMA_FLIPH) { // we are flipped horizontally // set ani X = -ani X + width - 1 - *pAniX = -*pAniX + FROM_LE_16(pImg->imgWidth) - 1; + *pAniX = -*pAniX + FROM_16(pImg->imgWidth) - 1; } if (flags & DMA_FLIPV) { // we are flipped vertically // set ani Y = -ani Y + height - 1 - *pAniY = -*pAniY + (FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK) - 1; + *pAniY = -*pAniY + (FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK) - 1; } } else // null image @@ -385,13 +385,13 @@ OBJECT *InitObject(const OBJ_INIT *pInitTbl) { pObj->pPal = pPalQ; // set objects size - pObj->width = FROM_LE_16(pImg->imgWidth); - pObj->height = FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK; + pObj->width = FROM_16(pImg->imgWidth); + pObj->height = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; pObj->flags &= ~C16_FLAG_MASK; - pObj->flags |= FROM_LE_16(pImg->imgHeight) & C16_FLAG_MASK; + pObj->flags |= FROM_16(pImg->imgHeight) & C16_FLAG_MASK; // set objects bitmap definition - pObj->hBits = FROM_LE_32(pImg->hImgBits); + pObj->hBits = FROM_32(pImg->hImgBits); // get animation offset of object GetAniOffset(pObj->hImg, pInitTbl->objFlags, &aniX, &aniY); @@ -442,13 +442,13 @@ void AnimateObjectFlags(OBJECT *pAniObj, int newflags, SCNHANDLE hNewImg) { const IMAGE *pNewImg = (IMAGE *)LockMem(hNewImg); // setup new shape - pAniObj->width = FROM_LE_16(pNewImg->imgWidth); - pAniObj->height = FROM_LE_16(pNewImg->imgHeight) & ~C16_FLAG_MASK; + pAniObj->width = FROM_16(pNewImg->imgWidth); + pAniObj->height = FROM_16(pNewImg->imgHeight) & ~C16_FLAG_MASK; newflags &= ~C16_FLAG_MASK; - newflags |= FROM_LE_16(pNewImg->imgHeight) & C16_FLAG_MASK; + newflags |= FROM_16(pNewImg->imgHeight) & C16_FLAG_MASK; // set objects bitmap definition - pAniObj->hBits = FROM_LE_32(pNewImg->hImgBits); + pAniObj->hBits = FROM_32(pNewImg->hImgBits); } else { // null image pAniObj->width = 0; pAniObj->height = 0; @@ -494,7 +494,7 @@ OBJECT *RectangleObject(SCNHANDLE hPal, int color, int width, int height) { OBJECT *pRect = InitObject(&rectObj); // allocate a palette for this object - pPalQ = AllocPalette(hPal); + pPalQ = AllocPalette(FROM_32(hPal)); // make sure palette allocated assert(pPalQ != NULL); diff --git a/engines/tinsel/palette.cpp b/engines/tinsel/palette.cpp index e6c9467fab..04018172c0 100644 --- a/engines/tinsel/palette.cpp +++ b/engines/tinsel/palette.cpp @@ -102,7 +102,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) { memset(mapperTable, 0, 16); for (int j = 1; j < 16; j++) { - clutEntry = READ_LE_UINT16(psxClut + (sizeof(uint16) * j)); + clutEntry = READ_16(psxClut + (sizeof(uint16) * j)); if (clutEntry) { if (clutEntry == 0x7EC0) { // This is an already known value, used by the in-game text mapperTable[j] = 232; @@ -110,7 +110,7 @@ void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) { } // Check for correspondent color - for (uint i = 0; (i < FROM_LE_32(pal->numColors)) && !colorFound; i++) { + for (uint i = 0; (i < FROM_32(pal->numColors)) && !colorFound; i++) { // get R G B values in the same way as psx format converters uint16 psxEquivalent = TINSEL_PSX_RGB(TINSEL_GetRValue(pal->palRGB[i]) >> 3, TINSEL_GetGValue(pal->palRGB[i]) >> 3, TINSEL_GetBValue(pal->palRGB[i]) >> 3); @@ -152,7 +152,7 @@ void PalettesToVideoDAC() { // we are using a palette handle // get hardware palette pointer - pPalette = (const PALETTE *)LockMem(pDACtail->pal.hRGBarray); + pPalette = (const PALETTE *)LockMem(FROM_32(pDACtail->pal.hRGBarray)); // get RGB pointer pColors = pPalette->palRGB; @@ -170,6 +170,12 @@ void PalettesToVideoDAC() { pal[i * 3 + 2] = TINSEL_GetBValue(pColors[i]); } + // In DW1 Mac, color 254 should be black, like in the PC version. + // We fix it here. + if (TinselV1Mac) { + pal[254 * 3 + 0] = pal[254 * 3 + 1] = pal[254 * 3 + 2] = 0; + } + // update the system palette g_system->getPaletteManager()->setPalette(pal, pDACtail->destDACindex, pDACtail->numColors); @@ -298,7 +304,7 @@ PALQ *AllocPalette(SCNHANDLE hNewPal) { PALETTE *pNewPal; // get pointer to new palette - pNewPal = (PALETTE *)LockMem(hNewPal); + pNewPal = (PALETTE *)LockMem(FROM_32(hNewPal)); // search all structs in palette allocator - see if palette already allocated for (p = g_palAllocData; p < g_palAllocData + NUM_PALETTES; p++) { @@ -318,7 +324,7 @@ PALQ *AllocPalette(SCNHANDLE hNewPal) { p->objCount = 1; // init number of objects using palette p->posInDAC = iDAC; // set palettes start pos in video DAC p->hPal = hNewPal; // set hardware palette data - p->numColors = FROM_LE_32(pNewPal->numColors); // set number of colors in palette + p->numColors = FROM_32(pNewPal->numColors); // set number of colors in palette if (TinselV2) // Copy all the colors @@ -430,24 +436,24 @@ void SwapPalette(PALQ *pPalQ, SCNHANDLE hNewPal) { // validate palette Q pointer assert(pPalQ >= g_palAllocData && pPalQ <= g_palAllocData + NUM_PALETTES - 1); - if (pPalQ->numColors >= (int)FROM_LE_32(pNewPal->numColors)) { + if (pPalQ->numColors >= (int)FROM_32(pNewPal->numColors)) { // new palette will fit the slot // install new palette pPalQ->hPal = hNewPal; if (TinselV2) { - pPalQ->numColors = FROM_LE_32(pNewPal->numColors); + pPalQ->numColors = FROM_32(pNewPal->numColors); // Copy all the colors - memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_LE_32(pNewPal->numColors) * sizeof(COLORREF)); + memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_32(pNewPal->numColors) * sizeof(COLORREF)); if (!pPalQ->bFading) // Q the change to the video DAC - UpdateDACqueue(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColors), pPalQ->palRGB); + UpdateDACqueue(pPalQ->posInDAC, FROM_32(pNewPal->numColors), pPalQ->palRGB); } else { // Q the change to the video DAC - UpdateDACqueueHandle(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColors), hNewPal); + UpdateDACqueueHandle(pPalQ->posInDAC, FROM_32(pNewPal->numColors), hNewPal); } } else { // # colors are different - will have to update all following palette entries @@ -546,7 +552,7 @@ void CreateTranslucentPalette(SCNHANDLE hPalette) { // leave background color alone g_transPalette[0] = 0; - for (uint i = 0; i < FROM_LE_32(pPal->numColors); i++) { + for (uint i = 0; i < FROM_32(pPal->numColors); i++) { // get the RGB color model values uint8 red = TINSEL_GetRValue(pPal->palRGB[i]); uint8 green = TINSEL_GetGValue(pPal->palRGB[i]); @@ -574,7 +580,7 @@ void CreateGhostPalette(SCNHANDLE hPalette) { // leave background color alone g_ghostPalette[0] = 0; - for (i = 0; i < (int)FROM_LE_32(pPal->numColors); i++) { + for (i = 0; i < (int)FROM_32(pPal->numColors); i++) { // get the RGB color model values uint8 red = TINSEL_GetRValue(pPal->palRGB[i]); uint8 green = TINSEL_GetGValue(pPal->palRGB[i]); diff --git a/engines/tinsel/palette.h b/engines/tinsel/palette.h index af58a7ffbd..49a78ae236 100644 --- a/engines/tinsel/palette.h +++ b/engines/tinsel/palette.h @@ -30,11 +30,11 @@ namespace Tinsel { typedef uint32 COLORREF; -#define TINSEL_RGB(r,g,b) ((COLORREF)TO_LE_32(((uint8)(r)|((uint16)(g)<<8))|(((uint32)(uint8)(b))<<16))) +#define TINSEL_RGB(r,g,b) ((COLORREF)TO_32(((uint8)(r)|((uint16)(g)<<8))|(((uint32)(uint8)(b))<<16))) -#define TINSEL_GetRValue(rgb) ((uint8)(FROM_LE_32(rgb))) -#define TINSEL_GetGValue(rgb) ((uint8)(((uint16)(FROM_LE_32(rgb)))>>8)) -#define TINSEL_GetBValue(rgb) ((uint8)((FROM_LE_32(rgb))>>16)) +#define TINSEL_GetRValue(rgb) ((uint8)(FROM_32(rgb))) +#define TINSEL_GetGValue(rgb) ((uint8)(((uint16)(FROM_32(rgb)))>>8)) +#define TINSEL_GetBValue(rgb) ((uint8)((FROM_32(rgb))>>16)) #define TINSEL_PSX_RGB(r,g,b) ((uint16)(((uint8)(r))|((uint16)(g)<<5)|(((uint16)(b))<<10))) diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp index 04bc2856ca..7e439e83a9 100644 --- a/engines/tinsel/pcode.cpp +++ b/engines/tinsel/pcode.cpp @@ -420,7 +420,7 @@ void RegisterGlobals(int num) { g_numGlobals = num; g_hMasterScript = !TinselV2 ? 0 : - READ_LE_UINT32(FindChunk(MASTER_SCNHANDLE, CHUNK_MASTER_SCRIPT)); + READ_32(FindChunk(MASTER_SCNHANDLE, CHUNK_MASTER_SCRIPT)); // Allocate RAM for pGlobals and make sure it's allocated g_pGlobals = (int32 *)calloc(g_numGlobals, sizeof(int32)); diff --git a/engines/tinsel/play.cpp b/engines/tinsel/play.cpp index 9e0baa749e..e202278953 100644 --- a/engines/tinsel/play.cpp +++ b/engines/tinsel/play.cpp @@ -81,9 +81,9 @@ static void PokeInPalette(SCNHANDLE hMulFrame) { pFrame = (const FRAME *)LockMem(hMulFrame); // get pointer to image - pim = (IMAGE *)LockMem(READ_LE_UINT32(pFrame)); // handle to image + pim = (IMAGE *)LockMem(READ_32(pFrame)); // handle to image - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); } } @@ -96,12 +96,12 @@ void PokeInPalette(const MULTI_INIT *pmi) { // Could be an empty column if (pmi->hMulFrame) { - pFrame = (FRAME *)LockMem(FROM_LE_32(pmi->hMulFrame)); + pFrame = (FRAME *)LockMem(FROM_32(pmi->hMulFrame)); // get pointer to image - pim = (IMAGE *)LockMem(READ_LE_UINT32(pFrame)); // handle to image + pim = (IMAGE *)LockMem(READ_32(pFrame)); // handle to image - pim->hImgPal = TO_LE_32(BgPal()); + pim->hImgPal = TO_32(BgPal()); } } @@ -234,8 +234,8 @@ static void SoundReel(CORO_PARAM, SCNHANDLE hFilm, int column, int speed, PMULTI_INIT pmi; // MULTI_INIT structure pReel = GetReel(hFilm, actorCol - 1); - pmi = (PMULTI_INIT) LockMem(FROM_LE_32(pReel->mobj)); - _ctx->reelActor = (int32)FROM_LE_32(pmi->mulID); + pmi = (PMULTI_INIT) LockMem(FROM_32(pReel->mobj)); + _ctx->reelActor = (int32)FROM_32(pmi->mulID); } else _ctx->reelActor = 0; @@ -251,27 +251,27 @@ static void SoundReel(CORO_PARAM, SCNHANDLE hFilm, int column, int speed, pFilm = (FILM *)LockMem(hFilm); pReel = &pFilm->reels[column]; - pAni = (ANI_SCRIPT *)LockMem(FROM_LE_32(pReel->script)); + pAni = (ANI_SCRIPT *)LockMem(FROM_32(pReel->script)); if (_ctx->speed == -1) { - _ctx->speed = (ONE_SECOND/FROM_LE_32(pFilm->frate)); + _ctx->speed = (ONE_SECOND/FROM_32(pFilm->frate)); // Restored reel for (;;) { - if (FROM_LE_32(pAni[_ctx->frameNumber].op) == ANI_END) + if (FROM_32(pAni[_ctx->frameNumber].op) == ANI_END) break; - else if (FROM_LE_32(pAni[_ctx->frameNumber].op) == ANI_JUMP) { + else if (FROM_32(pAni[_ctx->frameNumber].op) == ANI_JUMP) { _ctx->frameNumber++; - _ctx->frameNumber += FROM_LE_32(pAni[_ctx->frameNumber].op); + _ctx->frameNumber += FROM_32(pAni[_ctx->frameNumber].op); break; } // Could check for the other stuff here // but they really dont happen // OH YES THEY DO - else if (FROM_LE_32(pAni[_ctx->frameNumber].op) == ANI_ADJUSTX - || FROM_LE_32(pAni[_ctx->frameNumber].op) == ANI_ADJUSTY) { + else if (FROM_32(pAni[_ctx->frameNumber].op) == ANI_ADJUSTX + || FROM_32(pAni[_ctx->frameNumber].op) == ANI_ADJUSTY) { _ctx->frameNumber += 2; - } else if (FROM_LE_32(pAni[_ctx->frameNumber].op) == ANI_ADJUSTXY) { + } else if (FROM_32(pAni[_ctx->frameNumber].op) == ANI_ADJUSTXY) { _ctx->frameNumber += 3; } else { // ANI_STOP, ANI_HIDE, ANI_HFLIP, @@ -281,7 +281,7 @@ static void SoundReel(CORO_PARAM, SCNHANDLE hFilm, int column, int speed, } } - switch (FROM_LE_32(pAni[_ctx->frameNumber].op)) { + switch (FROM_32(pAni[_ctx->frameNumber].op)) { case ANI_END: // Stop this sample if repeating if (_ctx->sampleNumber && _ctx->bLooped) @@ -292,9 +292,9 @@ static void SoundReel(CORO_PARAM, SCNHANDLE hFilm, int column, int speed, case ANI_JUMP: _ctx->frameNumber++; - assert((int32)FROM_LE_32(pAni[_ctx->frameNumber].op) < 0); + assert((int32)FROM_32(pAni[_ctx->frameNumber].op) < 0); - _ctx->frameNumber += FROM_LE_32(pAni[_ctx->frameNumber].op); + _ctx->frameNumber += FROM_32(pAni[_ctx->frameNumber].op); assert(_ctx->frameNumber >= 0); continue; @@ -329,15 +329,15 @@ static void SoundReel(CORO_PARAM, SCNHANDLE hFilm, int column, int speed, if (_ctx->sampleNumber) _vm->_sound->stopSpecSample(_ctx->sampleNumber, 0); - _ctx->sampleNumber = FROM_LE_32(pAni[_ctx->frameNumber++].op); + _ctx->sampleNumber = FROM_32(pAni[_ctx->frameNumber++].op); if (_ctx->sampleNumber > 0) _ctx->bLooped = false; else { _ctx->sampleNumber = ~_ctx->sampleNumber; _ctx->bLooped = true; } - x = (short)(FROM_LE_32(pAni[_ctx->frameNumber].op) >> 16); - y = (short)(FROM_LE_32(pAni[_ctx->frameNumber].op) & 0xffff); + x = (short)(FROM_32(pAni[_ctx->frameNumber].op) >> 16); + y = (short)(FROM_32(pAni[_ctx->frameNumber].op) & 0xffff); if (x == 0) x = -1; @@ -451,10 +451,10 @@ static void t1PlayReel(CORO_PARAM, const PPINIT *ppi) { _ctx->pfreel = &pfilm->reels[ppi->column]; // Get the MULTI_INIT structure - pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(_ctx->pfreel->mobj)); + pmi = (const MULTI_INIT *)LockMem(FROM_32(_ctx->pfreel->mobj)); // Save actor's ID - _ctx->reelActor = (int32)FROM_LE_32(pmi->mulID); + _ctx->reelActor = (int32)FROM_32(pmi->mulID); /**** New (experimental? bit 5/1/95 ****/ if (!TinselV0 && !actorAlive(_ctx->reelActor)) @@ -488,7 +488,7 @@ static void t1PlayReel(CORO_PARAM, const PPINIT *ppi) { return; // Poke in the background palette - PokeInPalette(FROM_LE_32(pmi->hMulFrame)); + PokeInPalette(FROM_32(pmi->hMulFrame)); // Set up and insert the multi-object _ctx->pPlayObj = MultiInitObject(pmi); @@ -534,7 +534,7 @@ static void t1PlayReel(CORO_PARAM, const PPINIT *ppi) { if (ppi->actorid == 0 && !actorAlive(_ctx->reelActor)) _ctx->lifeNoMatter = true; - InitStepAnimScript(&_ctx->thisAnim, _ctx->pPlayObj, FROM_LE_32(_ctx->pfreel->script), ppi->speed); + InitStepAnimScript(&_ctx->thisAnim, _ctx->pPlayObj, FROM_32(_ctx->pfreel->script), ppi->speed); // If first column, set Z position as per // Otherwise, column 0's + column number @@ -706,16 +706,16 @@ static void t2PlayReel(CORO_PARAM, int x, int y, bool bRestore, int speed, SCNHA // Get the reel and MULTI_INIT structure _ctx->pFreel = GetReel(hFilm, column); - _ctx->pmi = (MULTI_INIT *)LockMem(FROM_LE_32(_ctx->pFreel->mobj)); + _ctx->pmi = (MULTI_INIT *)LockMem(FROM_32(_ctx->pFreel->mobj)); - if ((int32)FROM_LE_32(_ctx->pmi->mulID) == -2) { + if ((int32)FROM_32(_ctx->pmi->mulID) == -2) { CORO_INVOKE_ARGS(SoundReel, (CORO_SUBCTX, hFilm, column, speed, myescEvent, - FROM_LE_32(_ctx->pmi->otherFlags) & OTH_RELATEDACTOR)); + FROM_32(_ctx->pmi->otherFlags) & OTH_RELATEDACTOR)); return; } // Save actor's ID - _ctx->reelActor = FROM_LE_32(_ctx->pmi->mulID); + _ctx->reelActor = FROM_32(_ctx->pmi->mulID); UpdateActorEsc(_ctx->reelActor, myescEvent); @@ -759,8 +759,8 @@ static void t2PlayReel(CORO_PARAM, int x, int y, bool bRestore, int speed, SCNHA // Set ghost bit if wanted if (ActorIsGhost(_ctx->reelActor)) { - assert(FROM_LE_32(_ctx->pmi->mulFlags) == DMA_WNZ || FROM_LE_32(_ctx->pmi->mulFlags) == (DMA_WNZ | DMA_GHOST)); - _ctx->pmi->mulFlags = TO_LE_32(FROM_LE_32(_ctx->pmi->mulFlags) | DMA_GHOST); + assert(FROM_32(_ctx->pmi->mulFlags) == DMA_WNZ || FROM_32(_ctx->pmi->mulFlags) == (DMA_WNZ | DMA_GHOST)); + _ctx->pmi->mulFlags = TO_32(FROM_32(_ctx->pmi->mulFlags) | DMA_GHOST); } // Set up and insert the multi-object @@ -793,10 +793,10 @@ static void t2PlayReel(CORO_PARAM, int x, int y, bool bRestore, int speed, SCNHA /* * Sort out x and y */ - assert( ((FROM_LE_32(_ctx->pmi->otherFlags) & OTH_RELATIVE) && !(FROM_LE_32(_ctx->pmi->otherFlags) & OTH_ABSOLUTE)) - || ((FROM_LE_32(_ctx->pmi->otherFlags) & OTH_ABSOLUTE) && !(FROM_LE_32(_ctx->pmi->otherFlags) & OTH_RELATIVE)) ); + assert( ((FROM_32(_ctx->pmi->otherFlags) & OTH_RELATIVE) && !(FROM_32(_ctx->pmi->otherFlags) & OTH_ABSOLUTE)) + || ((FROM_32(_ctx->pmi->otherFlags) & OTH_ABSOLUTE) && !(FROM_32(_ctx->pmi->otherFlags) & OTH_RELATIVE)) ); - _ctx->bRelative = FROM_LE_32(_ctx->pmi->otherFlags) & OTH_RELATIVE; + _ctx->bRelative = FROM_32(_ctx->pmi->otherFlags) & OTH_RELATIVE; if (_ctx->bRelative) { // Use actor's position. If (x, y) specified, move the actor. @@ -808,7 +808,7 @@ static void t2PlayReel(CORO_PARAM, int x, int y, bool bRestore, int speed, SCNHA x = y = 0; // Use (0,0) if no specified // Add embedded co-ords - MultiSetAniXY(_ctx->pPlayObj, x + FROM_LE_32(_ctx->pmi->mulX), y + FROM_LE_32(_ctx->pmi->mulY)); + MultiSetAniXY(_ctx->pPlayObj, x + FROM_32(_ctx->pmi->mulX), y + FROM_32(_ctx->pmi->mulY)); /* * Sort out z @@ -824,10 +824,10 @@ static void t2PlayReel(CORO_PARAM, int x, int y, bool bRestore, int speed, SCNHA // N.B. It HAS been ensured that the first column gets here first - if ((int32)FROM_LE_32(_ctx->pmi->mulZ) != -1) { + if ((int32)FROM_32(_ctx->pmi->mulZ) != -1) { // Z override in script - baseZfact = FROM_LE_32(_ctx->pmi->mulZ); + baseZfact = FROM_32(_ctx->pmi->mulZ); baseZposn = (baseZfact << ZSHIFT) + MultiLowest(_ctx->pPlayObj); if (bTop) baseZposn += Z_TOPPLAY; @@ -850,7 +850,7 @@ static void t2PlayReel(CORO_PARAM, int x, int y, bool bRestore, int speed, SCNHA * another reel starts up for this actor, * or the actor gets killed. */ - InitStepAnimScript(&_ctx->thisAnim, _ctx->pPlayObj, FROM_LE_32(_ctx->pFreel->script), speed); + InitStepAnimScript(&_ctx->thisAnim, _ctx->pPlayObj, FROM_32(_ctx->pFreel->script), speed); if (bRestore || (ActorEsc(_ctx->reelActor) == true && ActorEev(_ctx->reelActor) != GetEscEvents())) { @@ -952,10 +952,10 @@ void NewestFilm(SCNHANDLE film, const FREEL *reel) { const MULTI_INIT *pmi; // MULTI_INIT structure // Get the MULTI_INIT structure - pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(reel->mobj)); + pmi = (const MULTI_INIT *)LockMem(FROM_32(reel->mobj)); - if (!TinselV2 || ((int32)FROM_LE_32(pmi->mulID) != -2)) - SetActorLatestFilm((int32)FROM_LE_32(pmi->mulID), film); + if (!TinselV2 || ((int32)FROM_32(pmi->mulID) != -2)) + SetActorLatestFilm((int32)FROM_32(pmi->mulID), film); } // ******************************************************* @@ -988,7 +988,7 @@ void PlayFilm(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool splay ppi.y = y; ppi.z = 0; ppi.bRestore = false; - ppi.speed = (ONE_SECOND / FROM_LE_32(pFilm->frate)); + ppi.speed = (ONE_SECOND / FROM_32(pFilm->frate)); ppi.actorid = actorid; ppi.splay = splay; ppi.bTop = bTop; @@ -997,7 +997,7 @@ void PlayFilm(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool splay ppi.myescEvent = myescEvent; // Start display process for each reel in the film - for (int i = FROM_LE_32(pFilm->numreels) - 1; i >= 0; i--) { + for (int i = FROM_32(pFilm->numreels) - 1; i >= 0; i--) { NewestFilm(hFilm, &pFilm->reels[i]); ppi.column = i; @@ -1049,7 +1049,7 @@ void PlayFilmc(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool spla _ctx->ppi.y = y; _ctx->ppi.z = 0; _ctx->ppi.bRestore = false; - _ctx->ppi.speed = (ONE_SECOND / FROM_LE_32(pFilm->frate)); + _ctx->ppi.speed = (ONE_SECOND / FROM_32(pFilm->frate)); _ctx->ppi.actorid = actorid; _ctx->ppi.splay = splay; _ctx->ppi.bTop = bTop; @@ -1059,7 +1059,7 @@ void PlayFilmc(CORO_PARAM, SCNHANDLE hFilm, int x, int y, int actorid, bool spla // Start display process for each secondary reel in the film in Tinsel 1, // or all of them in Tinsel 2 - for (int i = FROM_LE_32(pFilm->numreels) - 1; i >= (TinselV2 ? 0 : 1); i--) { + for (int i = FROM_32(pFilm->numreels) - 1; i >= (TinselV2 ? 0 : 1); i--) { NewestFilm(hFilm, &pFilm->reels[i]); _ctx->ppi.column = i; @@ -1109,7 +1109,7 @@ void RestoreActorReels(SCNHANDLE hFilm, short reelnum, short z, int x, int y) { ppi.x = x; ppi.y = y; ppi.z = z; - ppi.speed = (ONE_SECOND / FROM_LE_32(pfilm->frate)); + ppi.speed = (ONE_SECOND / FROM_32(pfilm->frate)); ppi.actorid = 0; ppi.splay = false; ppi.bTop = false; @@ -1147,15 +1147,15 @@ void RestoreActorReels(SCNHANDLE hFilm, int actor, int x, int y) { ppi.x = (short)x; ppi.y = (short)y; ppi.bRestore = true; - ppi.speed = (short)(ONE_SECOND/FROM_LE_32(pFilm->frate)); + ppi.speed = (short)(ONE_SECOND/FROM_32(pFilm->frate)); ppi.bTop = false; ppi.myescEvent = 0; // Search backwards for now as later column will be the one - for (i = (int)FROM_LE_32(pFilm->numreels) - 1; i >= 0; i--) { + for (i = (int)FROM_32(pFilm->numreels) - 1; i >= 0; i--) { pFreel = &pFilm->reels[i]; - pmi = (PMULTI_INIT) LockMem(FROM_LE_32(pFreel->mobj)); - if ((int32)FROM_LE_32(pmi->mulID) == actor) { + pmi = (PMULTI_INIT) LockMem(FROM_32(pFreel->mobj)); + if ((int32)FROM_32(pmi->mulID) == actor) { ppi.column = (short)i; NewestFilm(hFilm, &pFilm->reels[i]); @@ -1173,8 +1173,8 @@ void RestoreActorReels(SCNHANDLE hFilm, int actor, int x, int y) { int ExtractActor(SCNHANDLE hFilm) { const FILM *pFilm = (const FILM *)LockMem(hFilm); const FREEL *pReel = &pFilm->reels[0]; - const MULTI_INIT *pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pReel->mobj)); - return (int)FROM_LE_32(pmi->mulID); + const MULTI_INIT *pmi = (const MULTI_INIT *)LockMem(FROM_32(pReel->mobj)); + return (int)FROM_32(pmi->mulID); } } // End of namespace Tinsel diff --git a/engines/tinsel/polygons.cpp b/engines/tinsel/polygons.cpp index d8c1cef0b6..8a984c78f9 100644 --- a/engines/tinsel/polygons.cpp +++ b/engines/tinsel/polygons.cpp @@ -154,13 +154,13 @@ public: void setIndex(int index); - POLY_TYPE getType() const { return (POLY_TYPE)FROM_LE_32(type); } - int getNodecount() const { return (int)FROM_LE_32(nodecount); } - int getNodeX(int i) const { return (int)FROM_LE_32(nlistx[i]); } - int getNodeY(int i) const { return (int)FROM_LE_32(nlisty[i]); } + POLY_TYPE getType() const { return (POLY_TYPE)FROM_32(type); } + int getNodecount() const { return (int)FROM_32(nodecount); } + int getNodeX(int i) const { return (int)FROM_32(nlistx[i]); } + int getNodeY(int i) const { return (int)FROM_32(nlisty[i]); } // get Inter-node line structure - const LINEINFO *getLineinfo(int i) const { return ((const LINEINFO *)(_pStart + (int)FROM_LE_32(plinelist))) + i; } + const LINEINFO *getLineinfo(int i) const { return ((const LINEINFO *)(_pStart + (int)FROM_32(plinelist))) + i; } protected: POLY_TYPE type; ///< type of polygon @@ -230,8 +230,8 @@ void Poly::nextPoly() { const byte *pRecord = _pData; int typeVal = nextLong(_pData); - if ((FROM_LE_32(typeVal) == 5) && TinselV2) - typeVal = TO_LE_32(6); + if ((FROM_32(typeVal) == 5) && TinselV2) + typeVal = TO_32(6); type = (POLY_TYPE)typeVal; for (int i = 0; i < 4; ++i) @@ -275,8 +275,8 @@ void Poly::nextPoly() { pnodelisty = nextLong(_pData); plinelist = nextLong(_pData); - nlistx = (const int32 *)(_pStart + (int)FROM_LE_32(pnodelistx)); - nlisty = (const int32 *)(_pStart + (int)FROM_LE_32(pnodelisty)); + nlistx = (const int32 *)(_pStart + (int)FROM_32(pnodelistx)); + nlisty = (const int32 *)(_pStart + (int)FROM_32(pnodelisty)); if (TinselV0) // Skip to the last 4 bytes of the record for the hScript value @@ -591,16 +591,16 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) { for (int i = 0; i < ptp.getNodecount() - 1; i++) { const LINEINFO *line = ptp.getLineinfo(i); - const int32 a = (int)FROM_LE_32(line->a); - const int32 b = (int)FROM_LE_32(line->b); - const int32 c = (int)FROM_LE_32(line->c); + const int32 a = (int)FROM_32(line->a); + const int32 b = (int)FROM_32(line->b); + const int32 c = (int)FROM_32(line->c); #if 1 // TODO: If the comments of the LINEINFO struct are correct, then it contains mostly // duplicate data, probably in an effort to safe CPU cycles. Even on the slowest devices // we support, calculating a product of two ints is not an issue. // So we can just load & endian convert a,b,c, then replace stuff like - // (int)FROM_LE_32(line->ab) + // (int)FROM_32(line->ab) // by simply a*b, which makes it easier to understand what the code does, too. // Just in case there is some bugged data, I leave this code here for verifying it. // Let's leave it in for some time. @@ -608,14 +608,14 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) { // One bad thing: We use sqrt to compute a square root. Might not be a good idea, // speed wise. Maybe we should take Vicent's fp_sqroot. But that's a problem for later. - int32 a2 = (int)FROM_LE_32(line->a2); ///< a squared - int32 b2 = (int)FROM_LE_32(line->b2); ///< b squared - int32 a2pb2 = (int)FROM_LE_32(line->a2pb2); ///< a squared + b squared - int32 ra2pb2 = (int)FROM_LE_32(line->ra2pb2); ///< root(a squared + b squared) + int32 a2 = (int)FROM_32(line->a2); ///< a squared + int32 b2 = (int)FROM_32(line->b2); ///< b squared + int32 a2pb2 = (int)FROM_32(line->a2pb2); ///< a squared + b squared + int32 ra2pb2 = (int)FROM_32(line->ra2pb2); ///< root(a squared + b squared) - int32 ab = (int)FROM_LE_32(line->ab); - int32 ac = (int)FROM_LE_32(line->ac); - int32 bc = (int)FROM_LE_32(line->bc); + int32 ab = (int)FROM_32(line->ab); + int32 ac = (int)FROM_32(line->ac); + int32 bc = (int)FROM_32(line->bc); assert(a*a == a2); assert(b*b == b2); @@ -676,9 +676,9 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) { // A point on a line is nearest const LINEINFO *line = ptp.getLineinfo(nearestL); - const int32 a = (int)FROM_LE_32(line->a); - const int32 b = (int)FROM_LE_32(line->b); - const int32 c = (int)FROM_LE_32(line->c); + const int32 a = (int)FROM_32(line->a); + const int32 b = (int)FROM_32(line->b); + const int32 c = (int)FROM_32(line->c); dropX = ((b*b * h) - (a*b * k) - a*c) / (a*a + b*b); dropY = ((a*a * k) - (a*b * h) - b*c) / (a*a + b*b); *x = dropX; @@ -994,15 +994,15 @@ int GetScale(HPOLYGON hPath, int y) { Poly ptp(LockMem(pHandle), Polys[hPath]->pIndex); // Path is of a constant scale? - if (FROM_LE_32(ptp.scale2) == 0) - return FROM_LE_32(ptp.scale1); + if (FROM_32(ptp.scale2) == 0) + return FROM_32(ptp.scale1); - assert(FROM_LE_32(ptp.scale1) >= FROM_LE_32(ptp.scale2)); + assert(FROM_32(ptp.scale1) >= FROM_32(ptp.scale2)); - zones = FROM_LE_32(ptp.scale1) - FROM_LE_32(ptp.scale2) + 1; + zones = FROM_32(ptp.scale1) - FROM_32(ptp.scale2) + 1; zlen = (Polys[hPath]->pbottom - Polys[hPath]->ptop) / zones; - scale = FROM_LE_32(ptp.scale1); + scale = FROM_32(ptp.scale1); top = Polys[hPath]->ptop; do { @@ -1011,7 +1011,7 @@ int GetScale(HPOLYGON hPath, int y) { return scale; } while (--scale); - return FROM_LE_32(ptp.scale2); + return FROM_32(ptp.scale2); } /** @@ -1033,15 +1033,15 @@ int GetBrightness(HPOLYGON hPath, int y) { Poly ptp(LockMem(pHandle), Polys[hPath]->pIndex); // Path is of a constant brightness? - if (FROM_LE_32(ptp.bright1) == FROM_LE_32(ptp.bright2)) - return FROM_LE_32(ptp.bright1); + if (FROM_32(ptp.bright1) == FROM_32(ptp.bright2)) + return FROM_32(ptp.bright1); - assert(FROM_LE_32(ptp.bright1) >= FROM_LE_32(ptp.bright2)); + assert(FROM_32(ptp.bright1) >= FROM_32(ptp.bright2)); - zones = FROM_LE_32(ptp.bright1) - FROM_LE_32(ptp.bright2) + 1; + zones = FROM_32(ptp.bright1) - FROM_32(ptp.bright2) + 1; zlen = (Polys[hPath]->pbottom - Polys[hPath]->ptop) / zones; - brightness = FROM_LE_32(ptp.bright1); + brightness = FROM_32(ptp.bright1); top = Polys[hPath]->ptop; do { @@ -1050,7 +1050,7 @@ int GetBrightness(HPOLYGON hPath, int y) { return brightness; } while (--brightness); - return FROM_LE_32(ptp.bright2); + return FROM_32(ptp.bright2); } @@ -1079,9 +1079,9 @@ void GetTagTag(HPOLYGON hp, SCNHANDLE *hTagText, int *tagx, int *tagy) { Poly ptp(LockMem(pHandle), Polys[hp]->pIndex); - *tagx = (int)FROM_LE_32(ptp.tagx) + (TinselV2 ? volatileStuff[hp].xoff : 0); - *tagy = (int)FROM_LE_32(ptp.tagy) + (TinselV2 ? volatileStuff[hp].yoff : 0); - *hTagText = FROM_LE_32(ptp.hTagtext); + *tagx = (int)FROM_32(ptp.tagx) + (TinselV2 ? volatileStuff[hp].xoff : 0); + *tagy = (int)FROM_32(ptp.tagy) + (TinselV2 ? volatileStuff[hp].yoff : 0); + *hTagText = FROM_32(ptp.hTagtext); } /** @@ -1092,7 +1092,7 @@ SCNHANDLE GetPolyFilm(HPOLYGON hp) { Poly ptp(LockMem(pHandle), Polys[hp]->pIndex); - return FROM_LE_32(ptp.hFilm); + return FROM_32(ptp.hFilm); } /** @@ -1103,7 +1103,7 @@ SCNHANDLE GetPolyScript(HPOLYGON hp) { Poly ptp(LockMem(pHandle), Polys[hp]->pIndex); - return FROM_LE_32(ptp.hScript); + return FROM_32(ptp.hScript); } REEL GetPolyReelType(HPOLYGON hp) { @@ -1115,7 +1115,7 @@ REEL GetPolyReelType(HPOLYGON hp) { Poly ptp(LockMem(pHandle), Polys[hp]->pIndex); - return (REEL)FROM_LE_32(ptp.reel); + return (REEL)FROM_32(ptp.reel); } int32 GetPolyZfactor(HPOLYGON hp) { @@ -1124,7 +1124,7 @@ int32 GetPolyZfactor(HPOLYGON hp) { Poly ptp(LockMem(pHandle), Polys[hp]->pIndex); - return (int)FROM_LE_32(ptp.zFactor); + return (int)FROM_32(ptp.zFactor); } int numNodes(HPOLYGON hp) { @@ -1319,11 +1319,11 @@ static bool MatchingLevels(PPOLYGON p1, PPOLYGON p2) { Poly pp1(pps, p1->pIndex); // This polygon 1 Poly pp2(pps, p2->pIndex); // This polygon 2 - assert((int32)FROM_LE_32(pp1.level1) <= (int32)FROM_LE_32(pp1.level2)); - assert((int32)FROM_LE_32(pp2.level1) <= (int32)FROM_LE_32(pp2.level2)); + assert((int32)FROM_32(pp1.level1) <= (int32)FROM_32(pp1.level2)); + assert((int32)FROM_32(pp2.level1) <= (int32)FROM_32(pp2.level2)); - for (int pl = (int32)FROM_LE_32(pp1.level1); pl <= (int32)FROM_LE_32(pp1.level2); pl++) { - if (pl >= (int32)FROM_LE_32(pp2.level1) && pl <= (int32)FROM_LE_32(pp2.level2)) + for (int pl = (int32)FROM_32(pp1.level1); pl <= (int32)FROM_32(pp1.level2); pl++) { + if (pl >= (int32)FROM_32(pp2.level1) && pl <= (int32)FROM_32(pp2.level2)) return true; } @@ -1604,17 +1604,17 @@ static PPOLYGON CommonInits(PTYPE polyType, int pno, const Poly &ptp, bool bRest p->pIndex = pno; for (i = 0; i < 4; i++) { // Polygon definition - p->cx[i] = (short)FROM_LE_32(ptp.x[i]); - p->cy[i] = (short)FROM_LE_32(ptp.y[i]); + p->cx[i] = (short)FROM_32(ptp.x[i]); + p->cy[i] = (short)FROM_32(ptp.y[i]); } if (!bRestart) { hp = PolygonIndex(p); - volatileStuff[hp].xoff = (short)FROM_LE_32(ptp.xoff); - volatileStuff[hp].yoff = (short)FROM_LE_32(ptp.yoff); + volatileStuff[hp].xoff = (short)FROM_32(ptp.xoff); + volatileStuff[hp].yoff = (short)FROM_32(ptp.yoff); } - p->polyID = FROM_LE_32(ptp.id); // Identifier + p->polyID = FROM_32(ptp.id); // Identifier FiddlyBit(p); @@ -1731,7 +1731,7 @@ static void InitEffect(const Poly &ptp, int pno, bool bRestart) { static void InitRefer(const Poly &ptp, int pno, bool bRestart) { PPOLYGON p = CommonInits(REFER, pno, ptp, bRestart); - p->subtype = FROM_LE_32(ptp.reftype); // Refer type + p->subtype = FROM_32(ptp.reftype); // Refer type } @@ -1990,8 +1990,8 @@ void GetPolyNode(HPOLYGON hp, int *pNodeX, int *pNodeY) { *pNodeX = 480; *pNodeY = 408; } else { - *pNodeX = FROM_LE_32(ptp.nodex); - *pNodeY = FROM_LE_32(ptp.nodey); + *pNodeX = FROM_32(ptp.nodex); + *pNodeY = FROM_32(ptp.nodey); } if (TinselV2) { diff --git a/engines/tinsel/rince.cpp b/engines/tinsel/rince.cpp index ba8f47f9cf..3e6334f583 100644 --- a/engines/tinsel/rince.cpp +++ b/engines/tinsel/rince.cpp @@ -550,7 +550,7 @@ void AlterMover(PMOVER pMover, SCNHANDLE film, AR_FUNCTION fn) { pfilm = (const FILM *)LockMem(film); assert(pfilm != NULL); - InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_LE_32(pfilm->reels[0].script), ONE_SECOND / FROM_LE_32(pfilm->frate)); + InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_32(pfilm->reels[0].script), ONE_SECOND / FROM_32(pfilm->frate)); if (!TinselV2) pMover->stepCount = 0; @@ -643,7 +643,7 @@ void SetMoverWalkReel(PMOVER pMover, DIRECTION reel, int scale, bool force) { pfilm = (const FILM *)LockMem(whichReel); assert(pfilm != NULL); // no film - InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_LE_32(pfilm->reels[0].script), 1); + InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_32(pfilm->reels[0].script), 1); // Synchronised walking reels assert(pMover->stepCount >= 0); @@ -704,14 +704,14 @@ static void MoverProcessHelper(int X, int Y, int id, PMOVER pMover) { InitialPathChecks(pMover, X, Y); pfilm = (const FILM *)LockMem(pMover->walkReels[0][FORWARD]); - pmi = (const MULTI_INIT *)LockMem(FROM_LE_32(pfilm->reels[0].mobj)); + pmi = (const MULTI_INIT *)LockMem(FROM_32(pfilm->reels[0].mobj)); //--- - pFrame = (const FRAME *)LockMem(FROM_LE_32(pmi->hMulFrame)); + pFrame = (const FRAME *)LockMem(FROM_32(pmi->hMulFrame)); // get pointer to image - pim = (IMAGE *)LockMem(READ_LE_UINT32(pFrame)); // handle to image - pim->hImgPal = TO_LE_32(BgPal()); + pim = (IMAGE *)LockMem(READ_32(pFrame)); // handle to image + pim->hImgPal = TO_32(BgPal()); //--- pMover->actorObj = MultiInitObject(pmi); @@ -722,7 +722,7 @@ static void MoverProcessHelper(int X, int Y, int id, PMOVER pMover) { MultiInsertObject(GetPlayfieldList(FIELD_WORLD), pMover->actorObj); storeActorReel(id, NULL, 0, pMover->actorObj, 0, 0, 0); - InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_LE_32(pfilm->reels[0].script), ONE_SECOND / FROM_LE_32(pfilm->frate)); + InitStepAnimScript(&pMover->actorAnim, pMover->actorObj, FROM_32(pfilm->reels[0].script), ONE_SECOND / FROM_32(pfilm->frate)); pMover->stepCount = 0; MultiSetAniXY(pMover->actorObj, pMover->objX, pMover->objY); @@ -802,7 +802,7 @@ void T2MoverProcess(CORO_PARAM, const void *param) { InitialPathChecks(pMover, rpos->X, rpos->Y); pFilm = (FILM *)LockMem(pMover->walkReels[i][FORWARD]); // Any old reel - pmi = (PMULTI_INIT)LockMem(FROM_LE_32(pFilm->reels[0].mobj)); + pmi = (PMULTI_INIT)LockMem(FROM_32(pFilm->reels[0].mobj)); // Poke in the background palette PokeInPalette(pmi); diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp index 2ef92d853f..acff196916 100644 --- a/engines/tinsel/saveload.cpp +++ b/engines/tinsel/saveload.cpp @@ -540,8 +540,8 @@ static void SaveFailure(Common::OutSaveFile *f) { if (f) { delete f; _vm->getSaveFileMan()->removeSavefile(g_SaveSceneName); - g_SaveSceneName = NULL; // Invalidate save name } + g_SaveSceneName = NULL; // Invalidate save name GUI::MessageDialog dialog(_("Failed to save game state to file.")); dialog.runModal(); } diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp index c5444517f1..9181f85afb 100644 --- a/engines/tinsel/scene.cpp +++ b/engines/tinsel/scene.cpp @@ -86,8 +86,8 @@ struct SCENE_STRUC { SCNHANDLE hTaggedActor; // handle to table of tagged actors int32 numProcess; // number of processes in this scene SCNHANDLE hProcess; // handle to table of processes - SCNHANDLE hMusicScript; // handle to music script data - SCNHANDLE hMusicSegment;// handle to music segments + SCNHANDLE hMusicScript; // handle to music script data - Tinsel 2 only + SCNHANDLE hMusicSegment;// handle to music segments - Tinsel 2 only } PACKED_STRUCT; /** entrance structure - one per entrance */ @@ -130,15 +130,15 @@ const SCENE_STRUC *GetSceneStruc(const byte *pStruc) { const byte *p = pStruc; memset(&g_tempStruc, 0, sizeof(SCENE_STRUC)); - g_tempStruc.numEntrance = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.numPoly = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.numTaggedActor = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.defRefer = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.hSceneScript = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.hEntrance = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.hPoly = READ_UINT32(p); p += sizeof(uint32); - g_tempStruc.hTaggedActor = READ_UINT32(p); p += sizeof(uint32); - + g_tempStruc.numEntrance = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.numPoly = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.numTaggedActor = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.defRefer = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.hSceneScript = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.hEntrance = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.hPoly = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + g_tempStruc.hTaggedActor = FROM_LE_32(READ_32(p)); p += sizeof(uint32); + return &g_tempStruc; } @@ -159,7 +159,8 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) { // The following myEscape value setting is used for enabling title screen skipping in DW1 if (TinselV1 && (g_sceneCtr == 1)) g_initialMyEscape = GetEscEvents(); // DW1 PSX has its own scene skipping script code for scenes 2 and 3 (bug #3541542). - _ctx->myEscape = (TinselV1 && (g_sceneCtr < (TinselV1PSX ? 2 : 4))) ? g_initialMyEscape : 0; + // Same goes for DW1 Mac. + _ctx->myEscape = (TinselV1 && (g_sceneCtr < ((TinselV1PSX || TinselV1Mac) ? 2 : 4))) ? g_initialMyEscape : 0; // get the stuff copied to process when it was created _ctx->pInit = (const TP_INIT *)param; @@ -167,7 +168,7 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) { assert(_ctx->pInit->hTinselCode); // Must have some code to run _ctx->pic = InitInterpretContext(GS_SCENE, - READ_LE_UINT32(&_ctx->pInit->hTinselCode), + _ctx->pInit->hTinselCode, TinselV2 ? _ctx->pInit->event : NOEVENT, NOPOLY, // No polygon 0, // No actor @@ -209,7 +210,7 @@ void SendSceneTinselProcess(TINSEL_EVENT event) { */ static void LoadScene(SCNHANDLE scene, int entry) { - uint i; + int32 i; TP_INIT init; const SCENE_STRUC *ss; const ENTRANCE_STRUC *es; @@ -223,7 +224,7 @@ static void LoadScene(SCNHANDLE scene, int entry) { // CdPlay() stuff byte *cptr = FindChunk(scene, CHUNK_CDPLAY_FILENUM); assert(cptr); - i = READ_LE_UINT32(cptr); + i = READ_32(cptr); assert(i < 512); cptr = FindChunk(scene, CHUNK_CDPLAY_FILENAME); assert(cptr); @@ -238,18 +239,17 @@ static void LoadScene(SCNHANDLE scene, int entry) { // Music stuff char *cptr = (char *)FindChunk(scene, CHUNK_MUSIC_FILENAME); assert(cptr); - _vm->_pcmMusic->setMusicSceneDetails(FROM_LE_32(ss->hMusicScript), - FROM_LE_32(ss->hMusicSegment), cptr); + _vm->_pcmMusic->setMusicSceneDetails(ss->hMusicScript, ss->hMusicSegment, cptr); } if (entry == NO_ENTRY_NUM) { // Restoring scene // Initialize all the polygons for this scene - InitPolygons(FROM_LE_32(ss->hPoly), FROM_LE_32(ss->numPoly), true); + InitPolygons(ss->hPoly, ss->numPoly, true); // Initialize the actors for this scene - StartTaggedActors(FROM_LE_32(ss->hTaggedActor), FROM_LE_32(ss->numTaggedActor), false); + StartTaggedActors(ss->hTaggedActor, ss->numTaggedActor, false); if (TinselV2) // Returning from cutscene @@ -259,18 +259,18 @@ static void LoadScene(SCNHANDLE scene, int entry) { // Genuine new scene // Initialize all the polygons for this scene - InitPolygons(FROM_LE_32(ss->hPoly), FROM_LE_32(ss->numPoly), false); + InitPolygons(ss->hPoly, ss->numPoly, false); // Initialize the actors for this scene - StartTaggedActors(FROM_LE_32(ss->hTaggedActor), FROM_LE_32(ss->numTaggedActor), true); + StartTaggedActors(ss->hTaggedActor, ss->numTaggedActor, true); // Run the appropriate entrance code (if any) - es = (const ENTRANCE_STRUC *)LockMem(FROM_LE_32(ss->hEntrance)); - for (i = 0; i < FROM_LE_32(ss->numEntrance); i++) { - if (FROM_LE_32(es->eNumber) == (uint)entry) { + es = (const ENTRANCE_STRUC *)LockMem(ss->hEntrance); + for (i = 0; i < ss->numEntrance; i++) { + if (FROM_32(es->eNumber) == (uint)entry) { if (es->hScript) { init.event = STARTUP; - init.hTinselCode = es->hScript; + init.hTinselCode = FROM_32(es->hScript); CoroScheduler.createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); } @@ -285,7 +285,7 @@ static void LoadScene(SCNHANDLE scene, int entry) { } - if (i == FROM_LE_32(ss->numEntrance)) + if (i == ss->numEntrance) error("Non-existant scene entry number"); if (ss->hSceneScript) { @@ -297,10 +297,10 @@ static void LoadScene(SCNHANDLE scene, int entry) { } // Default refer type - SetDefaultRefer(FROM_LE_32(ss->defRefer)); + SetDefaultRefer(ss->defRefer); // Scene's processes - SceneProcesses(FROM_LE_32(ss->numProcess), FROM_LE_32(ss->hProcess)); + SceneProcesses(ss->numProcess, ss->hProcess); } diff --git a/engines/tinsel/sched.cpp b/engines/tinsel/sched.cpp index 4bf356ba36..a73b4b9b97 100644 --- a/engines/tinsel/sched.cpp +++ b/engines/tinsel/sched.cpp @@ -109,7 +109,7 @@ void RestoreSceneProcess(INT_CONTEXT *pic) { pStruc = (PROCESS_STRUC *)LockMem(g_hSceneProcess); for (i = 0; i < g_numSceneProcess; i++) { - if (FROM_LE_32(pStruc[i].hProcessCode) == pic->hCode) { + if (FROM_32(pStruc[i].hProcessCode) == pic->hCode) { CoroScheduler.createProcess(PID_PROCESS + i, RestoredProcessProcess, &pic, sizeof(pic)); break; @@ -137,11 +137,11 @@ void SceneProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait _ctx->pStruc = (PROCESS_STRUC *)LockMem(g_hSceneProcess); for (i = 0; i < g_numSceneProcess; i++) { - if (FROM_LE_32(_ctx->pStruc[i].processId) == procID) { + if (FROM_32(_ctx->pStruc[i].processId) == procID) { assert(_ctx->pStruc[i].hProcessCode); // Must have some code to run _ctx->pic = InitInterpretContext(GS_PROCESS, - FROM_LE_32(_ctx->pStruc[i].hProcessCode), + FROM_32(_ctx->pStruc[i].hProcessCode), event, NOPOLY, // No polygon 0, // No actor @@ -176,7 +176,7 @@ void KillSceneProcess(uint32 procID) { pStruc = (PROCESS_STRUC *) LockMem(g_hSceneProcess); for (i = 0; i < g_numSceneProcess; i++) { - if (FROM_LE_32(pStruc[i].processId) == procID) { + if (FROM_32(pStruc[i].processId) == procID) { CoroScheduler.killMatchingProcess(PID_PROCESS + i, -1); break; } @@ -293,8 +293,8 @@ void GlobalProcesses(uint32 numProcess, byte *pProcess) { byte *p = pProcess; for (uint i = 0; i < numProcess; ++i, p += 8) { - g_pGlobalProcess[i].processId = READ_LE_UINT32(p); - g_pGlobalProcess[i].hProcessCode = READ_LE_UINT32(p + 4); + g_pGlobalProcess[i].processId = READ_32(p); + g_pGlobalProcess[i].hProcessCode = READ_32(p + 4); } } diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp index e052302cfd..03aa3767c4 100644 --- a/engines/tinsel/sound.cpp +++ b/engines/tinsel/sound.cpp @@ -74,7 +74,7 @@ SoundManager::~SoundManager() { */ // playSample for DiscWorld 1 bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { - // Floppy version has no sample file + // Floppy version has no sample file. if (!_vm->isCD()) return false; @@ -102,7 +102,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); // read the length of the sample - uint32 sampleLen = _sampleStream.readUint32(); + uint32 sampleLen = _sampleStream.readUint32LE(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); @@ -177,6 +177,48 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound return true; } +bool SoundManager::playDW1MacMusic(int dwFileOffset) { + Common::File s; + + if (!s.open("midi.dat")) + error(CANNOT_FIND_FILE, "midi.dat"); + + s.seek(dwFileOffset); + uint32 length = s.readUint32BE(); + + // TODO: It's a bad idea to load the music track in a buffer. + // We should use a SubReadStream instead, and keep midi.dat open. + // However, the track lengths aren't that big (about 1-4MB), + // so this shouldn't be a major issue. + byte *soundData = (byte *)malloc(length); + assert(soundData); + + // read all of the sample + if (s.read(soundData, length) != length) + error(FILE_IS_CORRUPT, "midi.dat"); + + Common::SeekableReadStream *memStream = new Common::MemoryReadStream(soundData, length); + + Audio::SoundHandle *handle = &_channels[kChannelDW1MacMusic].handle; + //_channels[kChannelDW1MacMusic].sampleNum = dwFileOffset; + + // Stop any previously playing music track + _vm->_mixer->stopHandle(*handle); + + // FIXME: Should set this in a different place ;) + _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _vm->_config->_musicVolume); + + // TODO: Compression support (MP3/OGG/FLAC) for midi.dat in DW1 Mac + Audio::RewindableAudioStream *musicStream = Audio::makeRawStream(memStream, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); + + if (musicStream) + _vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, handle, Audio::makeLoopingAudioStream(musicStream, 0)); + + s.close(); + + return true; +} + // playSample for DiscWorld 2 bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int priority, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { @@ -257,7 +299,7 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); // read the length of the sample - uint32 sampleLen = _sampleStream.readUint32(); + uint32 sampleLen = _sampleStream.readUint32LE(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); @@ -270,12 +312,12 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p // Skipping for (int32 i = 0; i < sub; i++) { - sampleLen = _sampleStream.readUint32(); + sampleLen = _sampleStream.readUint32LE(); _sampleStream.skip(sampleLen); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); } - sampleLen = _sampleStream.readUint32(); + sampleLen = _sampleStream.readUint32LE(); if (_sampleStream.eos() || _sampleStream.err()) error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); } @@ -369,7 +411,6 @@ bool SoundManager::offscreenChecks(int x, int &y) { } int8 SoundManager::getPan(int x) { - if (x == -1) return 0; @@ -416,14 +457,13 @@ bool SoundManager::sampleExists(int id) { /** * Returns true if a sample is currently playing. */ -bool SoundManager::sampleIsPlaying(int id) { +bool SoundManager::sampleIsPlaying() { if (!TinselV2) return _vm->_mixer->isSoundHandleActive(_channels[kChannelTinsel1].handle); for (int i = 0; i < kNumChannels; i++) - if (_channels[i].sampleNum == id) - if (_vm->_mixer->isSoundHandleActive(_channels[i].handle)) - return true; + if (_vm->_mixer->isSoundHandleActive(_channels[i].handle)) + return true; return false; } @@ -432,8 +472,6 @@ bool SoundManager::sampleIsPlaying(int id) { * Stops any currently playing sample. */ void SoundManager::stopAllSamples() { - // stop currently playing sample - if (!TinselV2) { _vm->_mixer->stopHandle(_channels[kChannelTinsel1].handle); return; @@ -466,12 +504,21 @@ void SoundManager::setSFXVolumes(uint8 volume) { _vm->_mixer->setChannelVolume(_channels[i].handle, volume); } +void SoundManager::showSoundError(const char *errorMsg, const char *soundFile) { + Common::String msg; + msg = Common::String::format(errorMsg, soundFile); + GUI::MessageDialog dialog(msg, "OK"); + dialog.runModal(); + + error("%s", msg.c_str()); +} + /** * Opens and inits all sound sample files. */ void SoundManager::openSampleFiles() { // Floppy and demo versions have no sample files, except for the Discworld 2 demo - if (!_vm->isCD() || TinselV0) + if (!_vm->isCD()) return; TinselFile f; @@ -480,42 +527,26 @@ void SoundManager::openSampleFiles() { // already allocated return; - // open sample index file in binary mode + // Open sample index (*.idx) in binary mode if (f.open(_vm->getSampleIndex(g_sampleLanguage))) { - // get length of index file - f.seek(0, SEEK_END); // move to end of file - _sampleIndexLen = f.pos(); // get file pointer - f.seek(0, SEEK_SET); // back to beginning - + uint32 fileSize = f.size(); + _sampleIndex = (uint32 *)malloc(fileSize); if (_sampleIndex == NULL) { - // allocate a buffer for the indices - _sampleIndex = (uint32 *)malloc(_sampleIndexLen); - - // make sure memory allocated - if (_sampleIndex == NULL) { - // disable samples if cannot alloc buffer for indices - // TODO: Disabled sound if we can't load the sample index? - return; - } + showSoundError(NO_MEM, _vm->getSampleIndex(g_sampleLanguage)); + return; } - // load data - if (f.read(_sampleIndex, _sampleIndexLen) != (uint32)_sampleIndexLen) - // file must be corrupt if we get to here - error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); + _sampleIndexLen = fileSize / 4; // total sample of indices (DWORDs) - // close the file - f.close(); - - // convert file size to size in DWORDs - _sampleIndexLen /= sizeof(uint32); - -#ifdef SCUMM_BIG_ENDIAN - // Convert all ids from LE to native format + // Load data for (int i = 0; i < _sampleIndexLen; ++i) { - _sampleIndex[i] = SWAP_BYTES_32(_sampleIndex[i]); + _sampleIndex[i] = f.readUint32LE(); + if (f.err()) { + showSoundError(FILE_READ_ERROR, _vm->getSampleIndex(g_sampleLanguage)); + } } -#endif + + f.close(); // Detect format of soundfile by looking at 1st sample-index switch (TO_BE_32(_sampleIndex[0])) { @@ -523,48 +554,31 @@ void SoundManager::openSampleFiles() { debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected MP3 sound-data"); _soundMode = kMP3Mode; break; - case MKTAG('O','G','G',' '): debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected OGG sound-data"); _soundMode = kVorbisMode; break; - case MKTAG('F','L','A','C'): debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected FLAC sound-data"); _soundMode = kFLACMode; break; - default: debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected original sound-data"); break; } - // Normally the 1st sample-index points to nothing at all + + // Normally the 1st sample index points to nothing at all. We use it to + // determine if the game's sample files have been compressed, thus restore + // it here _sampleIndex[0] = 0; } else { - char buf[50]; - sprintf(buf, CANNOT_FIND_FILE, _vm->getSampleIndex(g_sampleLanguage)); - GUI::MessageDialog dialog(buf, "OK"); - dialog.runModal(); - - error(CANNOT_FIND_FILE, _vm->getSampleIndex(g_sampleLanguage)); + showSoundError(FILE_READ_ERROR, _vm->getSampleIndex(g_sampleLanguage)); } - // open sample file in binary mode + // Open sample file (*.smp) in binary mode if (!_sampleStream.open(_vm->getSampleFile(g_sampleLanguage))) { - char buf[50]; - sprintf(buf, CANNOT_FIND_FILE, _vm->getSampleFile(g_sampleLanguage)); - GUI::MessageDialog dialog(buf, "OK"); - dialog.runModal(); - - error(CANNOT_FIND_FILE, _vm->getSampleFile(g_sampleLanguage)); + showSoundError(FILE_READ_ERROR, _vm->getSampleFile(g_sampleLanguage)); } - -/* - // gen length of the largest sample - sampleBuffer.size = _sampleStream.readUint32LE(); - if (_sampleStream.eos() || _sampleStream.err()) - error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage)); -*/ } void SoundManager::closeSampleStream() { diff --git a/engines/tinsel/sound.h b/engines/tinsel/sound.h index d7083b3b21..8510c1618f 100644 --- a/engines/tinsel/sound.h +++ b/engines/tinsel/sound.h @@ -51,7 +51,8 @@ protected: enum { kChannelTalk = 0, kChannelTinsel1 = 0, // Always using this channel for DW1 - kChannelSFX = 1 + kChannelSFX = 1, + kChannelDW1MacMusic = 2 }; static const int kNumChannels = kChannelSFX + kNumSFX; @@ -108,6 +109,7 @@ public: bool playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle = 0); bool playSample(int id, int sub, bool bLooped, int x, int y, int priority, Audio::Mixer::SoundType type, Audio::SoundHandle *handle = 0); + bool playDW1MacMusic(int dwFileOffset); void stopAllSamples(); // Stops any currently playing sample void stopSpecSample(int id, int sub = 0); // Stops a specific sample @@ -115,11 +117,13 @@ public: void setSFXVolumes(uint8 volume); bool sampleExists(int id); - bool sampleIsPlaying(int id = -1); + bool sampleIsPlaying(); - // TODO: Internal method, make this protected? void openSampleFiles(); void closeSampleStream(); + +private: + void showSoundError(const char *errorMsg, const char *soundFile); }; } // End of namespace Tinsel diff --git a/engines/tinsel/strres.cpp b/engines/tinsel/strres.cpp index 5a29a4d2cd..19a1ee94d6 100644 --- a/engines/tinsel/strres.cpp +++ b/engines/tinsel/strres.cpp @@ -165,15 +165,15 @@ static byte *FindStringBase(int id) { // skip to the correct chunk while (chunkSkip-- != 0) { // make sure chunk id is correct - assert(READ_LE_UINT32(pText + index) == CHUNK_STRING || READ_LE_UINT32(pText + index) == CHUNK_MBSTRING); + assert(READ_32(pText + index) == CHUNK_STRING || READ_32(pText + index) == CHUNK_MBSTRING); - if (READ_LE_UINT32(pText + index + sizeof(uint32)) == 0) { + if (READ_32(pText + index + sizeof(uint32)) == 0) { // string does not exist return NULL; } // get index to next chunk - index = READ_LE_UINT32(pText + index + sizeof(uint32)); + index = READ_32(pText + index + sizeof(uint32)); } // skip over chunk id and offset diff --git a/engines/tinsel/text.cpp b/engines/tinsel/text.cpp index 5eb092d00d..150eb2bdde 100644 --- a/engines/tinsel/text.cpp +++ b/engines/tinsel/text.cpp @@ -46,24 +46,24 @@ int StringLengthPix(char *szStr, const FONT *pFont) { if (c & 0x80) c = ((c & ~0x80) << 8) + *++szStr; } - hImg = FROM_LE_32(pFont->fontDef[c]); + hImg = FROM_32(pFont->fontDef[c]); if (hImg) { // there is a IMAGE for this character const IMAGE *pChar = (const IMAGE *)LockMem(hImg); // add width of font bitmap - strLen += FROM_LE_16(pChar->imgWidth); + strLen += FROM_16(pChar->imgWidth); } else // use width of space character - strLen += FROM_LE_32(pFont->spaceSize); + strLen += FROM_32(pFont->spaceSize); // finally add the inter-character spacing - strLen += FROM_LE_32(pFont->xSpacing); + strLen += FROM_32(pFont->xSpacing); } // return length of line in pixels - minus inter-char spacing for last character - strLen -= FROM_LE_32(pFont->xSpacing); + strLen -= FROM_32(pFont->xSpacing); return (strLen > 0) ? strLen : 0; } @@ -125,10 +125,10 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color, // get image for capital W assert(pFont->fontDef[(int)'W']); - pImg = (const IMAGE *)LockMem(FROM_LE_32(pFont->fontDef[(int)'W'])); + pImg = (const IMAGE *)LockMem(FROM_32(pFont->fontDef[(int)'W'])); // get height of capital W for offset to next line - yOffset = FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK; + yOffset = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; while (*szStr) { // x justify the text according to the mode flags @@ -140,24 +140,24 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color, if (c & 0x80) c = ((c & ~0x80) << 8) + *++szStr; } - hImg = FROM_LE_32(pFont->fontDef[c]); + hImg = FROM_32(pFont->fontDef[c]); if (hImg == 0) { // no image for this character // add font spacing for a space character - xJustify += FROM_LE_32(pFont->spaceSize); + xJustify += FROM_32(pFont->spaceSize); } else { // printable character int aniX, aniY; // char image animation offsets OBJ_INIT oi; - oi.hObjImg = FROM_LE_32(pFont->fontInit.hObjImg); - oi.objFlags = FROM_LE_32(pFont->fontInit.objFlags); - oi.objID = FROM_LE_32(pFont->fontInit.objID); - oi.objX = FROM_LE_32(pFont->fontInit.objX); - oi.objY = FROM_LE_32(pFont->fontInit.objY); - oi.objZ = FROM_LE_32(pFont->fontInit.objZ); + oi.hObjImg = FROM_32(pFont->fontInit.hObjImg); + oi.objFlags = FROM_32(pFont->fontInit.objFlags); + oi.objID = FROM_32(pFont->fontInit.objID); + oi.objX = FROM_32(pFont->fontInit.objX); + oi.objY = FROM_32(pFont->fontInit.objY); + oi.objZ = FROM_32(pFont->fontInit.objZ); // allocate and init a character object if (pFirst == NULL) @@ -172,9 +172,9 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color, // fill in character object pChar->hImg = hImg; // image def - pChar->width = FROM_LE_16(pImg->imgWidth); // width of chars bitmap - pChar->height = FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK; // height of chars bitmap - pChar->hBits = FROM_LE_32(pImg->hImgBits); // bitmap + pChar->width = FROM_16(pImg->imgWidth); // width of chars bitmap + pChar->height = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; // height of chars bitmap + pChar->hBits = FROM_32(pImg->hImgBits); // bitmap // check for absolute positioning if (mode & TXT_ABSOLUTE) @@ -203,8 +203,8 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color, CopyObject(pShad, pChar); // add shadow offsets to characters position - pShad->xPos += intToFrac(FROM_LE_32(pFont->xShadow)); - pShad->yPos += intToFrac(FROM_LE_32(pFont->yShadow)); + pShad->xPos += intToFrac(FROM_32(pFont->xShadow)); + pShad->yPos += intToFrac(FROM_32(pFont->yShadow)); // shadow is behind the character pShad->zPos--; @@ -232,18 +232,18 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color, pChar = pChar->pSlave; // add character spacing - xJustify += FROM_LE_16(pImg->imgWidth); + xJustify += FROM_16(pImg->imgWidth); } // finally add the inter-character spacing - xJustify += FROM_LE_32(pFont->xSpacing); + xJustify += FROM_32(pFont->xSpacing); // next character in string ++szStr; } // adjust the text y position and add the inter-line spacing - yPos += yOffset + FROM_LE_32(pFont->ySpacing); + yPos += yOffset + FROM_32(pFont->ySpacing); // check for newline if (c == LF_CHAR) diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index 058f8eb6fd..6a396b9b01 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -3684,7 +3684,7 @@ static void TranslucentIndex(unsigned index) { } /** - * Play a sample. + * Play a sample (DW1 only). */ static void TryPlaySample(CORO_PARAM, int sample, bool bComplete, bool escOn, int myEscape) { CORO_BEGIN_CONTEXT; diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index e09e2c1dcf..e836fdff1f 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -430,6 +430,14 @@ static void MouseProcess(CORO_PARAM, const void *) { ProcessButEvent(PLR_DRAG2_END); break; + case Common::EVENT_WHEELUP: + PlayerEvent(PLR_WHEEL_UP, mousePos); + break; + + case Common::EVENT_WHEELDOWN: + PlayerEvent(PLR_WHEEL_DOWN, mousePos); + break; + default: break; } @@ -722,21 +730,20 @@ void LoadBasicChunks() { cptr = FindChunk(INV_OBJ_SCNHANDLE, CHUNK_OBJECTS); -#ifdef SCUMM_BIG_ENDIAN - //convert to native endianness + // Convert to native endianness INV_OBJECT *io = (INV_OBJECT *)cptr; for (int i = 0; i < numObjects; i++, io++) { - io->id = FROM_LE_32(io->id); - io->hIconFilm = FROM_LE_32(io->hIconFilm); - io->hScript = FROM_LE_32(io->hScript); - io->attribute = FROM_LE_32(io->attribute); + io->id = FROM_32(io->id); + io->hIconFilm = FROM_32(io->hIconFilm); + io->hScript = FROM_32(io->hScript); + io->attribute = FROM_32(io->attribute); } -#endif RegisterIcons(cptr, numObjects); cptr = FindChunk(MASTER_SCNHANDLE, CHUNK_TOTAL_POLY); - if (cptr != NULL) + // Max polygons are 0 in DW1 Mac (both in the demo and the full version) + if (cptr != NULL && *cptr != 0) MaxPolygons(*cptr); if (TinselV2) { @@ -1046,6 +1053,8 @@ bool TinselEngine::pollEvent() { case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONDOWN: case Common::EVENT_RBUTTONUP: + case Common::EVENT_WHEELUP: + case Common::EVENT_WHEELDOWN: // Add button to queue for the mouse process _mouseButtons.push_back(event.type); break; @@ -1053,7 +1062,7 @@ bool TinselEngine::pollEvent() { case Common::EVENT_MOUSEMOVE: { // This fragment takes care of Tinsel 2 when it's been compiled with - // blank areas at the top and bottom of thes creen + // blank areas at the top and bottom of the screen int ySkip = TinselV2 ? (g_system->getHeight() - _vm->screen().h) / 2 : 0; if ((event.mouse.y >= ySkip) && (event.mouse.y < (g_system->getHeight() - ySkip))) _mousePos = Common::Point(event.mouse.x, event.mouse.y - ySkip); diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index 123249125e..ec504b69cd 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -78,7 +78,7 @@ enum TinselGameFeatures { /** * The following is the ScummVM definitions of the various Tinsel versions: * TINSEL_V0 - This was an early engine version that was only used in the Discworld 1 - * demo. It is not currently supported. + * demo. * TINSEL_V1 - This was the engine version used by Discworld 1. Note that there were two * major releases: an earlier version that used *.gra files, and a later one that * used *.scn files, and contained certain script and engine bugfixes. In ScummVM, @@ -135,6 +135,9 @@ typedef bool (*KEYFPTR)(const Common::KeyState &); #define READ_16(v) (TinselV1Mac ? READ_BE_UINT16(v) : READ_LE_UINT16(v)) #define READ_32(v) (TinselV1Mac ? READ_BE_UINT32(v) : READ_LE_UINT32(v)) +#define FROM_16(v) (TinselV1Mac ? FROM_BE_16(v) : FROM_LE_16(v)) +#define FROM_32(v) (TinselV1Mac ? FROM_BE_32(v) : FROM_LE_32(v)) +#define TO_32(v) (TinselV1Mac ? TO_BE_32(v) : TO_LE_32(v)) // Global reference to the TinselEngine object extern TinselEngine *_vm; diff --git a/engines/toltecs/console.cpp b/engines/toltecs/console.cpp new file mode 100644 index 0000000000..f3394909ed --- /dev/null +++ b/engines/toltecs/console.cpp @@ -0,0 +1,79 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gui/debugger.h" + +#include "toltecs/console.h" +//#include "toltecs/palette.h" +#include "toltecs/resource.h" +//#include "toltecs/sound.h" +#include "toltecs/toltecs.h" + +namespace Toltecs { + +Console::Console(ToltecsEngine *vm) : GUI::Debugger(), _vm(vm) { + DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); + DCmd_Register("dump", WRAP_METHOD(Console, Cmd_Dump)); +} + +Console::~Console() { +} + +bool Console::Cmd_Room(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Current room number is %d\n", _vm->_sceneResIndex); +#if 0 + DebugPrintf("Calling this command with the room number changes the room\n"); + DebugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n"); +#endif + return true; +#if 0 + } else { + int roomNum = atoi(argv[1]); + + // sfClearPaletteFragments + _vm->_palette->clearFragments(); + + // sfLoadScene + _vm->_sound->stopAll(); + _vm->_res->purgeCache(); + _vm->loadScene(roomNum); +#endif + } + + return false; +} + +bool Console::Cmd_Dump(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: dump <resource number>\n"); + return true; + } + + int resNum = atoi(argv[1]); + _vm->_arc->dump(resNum); + DebugPrintf("Resource %d has been dumped to disk\n", resNum); + + return true; +} + +} // End of namespace Toltecs diff --git a/engines/toltecs/console.h b/engines/toltecs/console.h new file mode 100644 index 0000000000..bcdfd0cf04 --- /dev/null +++ b/engines/toltecs/console.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef TOLTECS_CONSOLE_H +#define TOLTECS_CONSOLE_H + +#include "gui/debugger.h" + +namespace Toltecs { + +class ToltecsEngine; + +class Console : public GUI::Debugger { +public: + Console(ToltecsEngine *vm); + virtual ~Console(void); + +private: + ToltecsEngine *_vm; + + bool Cmd_Dump(int argc, const char **argv); + bool Cmd_Room(int argc, const char **argv); +}; + +} // End of namespace Toltecs +#endif diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp index c1a57638c2..788f813762 100644 --- a/engines/toltecs/detection.cpp +++ b/engines/toltecs/detection.cpp @@ -24,6 +24,8 @@ #include "base/plugins.h" #include "engines/advancedDetector.h" + +#include "common/translation.h" #include "common/savefile.h" #include "common/str-array.h" #include "common/system.h" @@ -97,19 +99,6 @@ static const ToltecsGameDescription gameDescriptions[] = { }, { - // 3 Skulls of the Toltecs German Demo version - { - "toltecs", - 0, - AD_ENTRY1s("WESTERN", "1c85e82712d24f1d5c1ea2a66ddd75c2", 47730038), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO1(GUIO_NONE) - }, - }, - - { // 3 Skulls of the Toltecs French version { "toltecs", @@ -149,11 +138,44 @@ static const ToltecsGameDescription gameDescriptions[] = { }, }, + { + // 3 Skulls of the Toltecs English Demo version + { + "toltecs", + 0, + AD_ENTRY1s("WESTERN", "53a0abd1c0bc5cad8ba18f0e56877705", 46241833), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + GUIO1(GUIO_NONE) + }, + }, + + { + // 3 Skulls of the Toltecs German Demo version + { + "toltecs", + 0, + AD_ENTRY1s("WESTERN", "1c85e82712d24f1d5c1ea2a66ddd75c2", 47730038), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DEMO, + GUIO1(GUIO_NONE) + }, + }, + { AD_TABLE_END_MARKER } }; } // End of namespace Toltecs +static const ExtraGuiOption toltecsExtraGuiOption = { + _s("Use original save/load screens"), + _s("Use the original save/load screens, instead of the ScummVM ones"), + "originalsaveload", + false +}; + class ToltecsMetaEngine : public AdvancedMetaEngine { public: ToltecsMetaEngine() : AdvancedMetaEngine(Toltecs::gameDescriptions, sizeof(Toltecs::ToltecsGameDescription), toltecsGames) { @@ -170,6 +192,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; void removeSaveState(const char *target, int slot) const; @@ -202,6 +225,12 @@ bool ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADG return gd != 0; } +const ExtraGuiOptions ToltecsMetaEngine::getExtraGuiOptions(const Common::String &target) const { + ExtraGuiOptions options; + options.push_back(toltecsExtraGuiOption); + return options; +} + SaveStateList ToltecsMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Toltecs::ToltecsEngine::SaveHeader header; @@ -295,7 +324,7 @@ SaveStateDescriptor ToltecsMetaEngine::querySaveMetaInfos(const char *target, in } return SaveStateDescriptor(); -} // End of namespace Toltecs +} // End of namespace Toltecs #if PLUGIN_ENABLED_DYNAMIC(TOLTECS) REGISTER_PLUGIN_DYNAMIC(TOLTECS, PLUGIN_TYPE_ENGINE, ToltecsMetaEngine); diff --git a/engines/toltecs/menu.cpp b/engines/toltecs/menu.cpp index 6e23ff988f..b52d7dad82 100644 --- a/engines/toltecs/menu.cpp +++ b/engines/toltecs/menu.cpp @@ -22,9 +22,12 @@ */ #include "audio/mixer.h" -#include "common/savefile.h" +#include "common/savefile.h" #include "common/config-manager.h" +#include "common/translation.h" + +#include "gui/saveload.h" #include "toltecs/toltecs.h" #include "toltecs/menu.h" @@ -41,9 +44,6 @@ MenuSystem::~MenuSystem() { } int MenuSystem::run(MenuID menuId) { - - //debug("MenuSystem::run()"); - _background = new Graphics::Surface(); _background->create(640, 400, Graphics::PixelFormat::createFormatCLUT8()); @@ -62,13 +62,12 @@ int MenuSystem::run(MenuID menuId) { _needRedraw = false; - // TODO: buildColorTransTable2 _vm->_palette->buildColorTransTable(0, 16, 7); _vm->_screen->_renderQueue->clear(); // Draw the menu background and frame _vm->_screen->blastSprite(0x140 + _vm->_cameraX, 0x175 + _vm->_cameraY, 0, 1, 0x4000); - shadeRect(60, 39, 520, 246, 30, 94); + shadeRect(60, 39, 520, 247, 225, 229); memcpy(_background->pixels, _vm->_screen->_frontScreen, 640 * 400); @@ -91,7 +90,6 @@ int MenuSystem::run(MenuID menuId) { } void MenuSystem::update() { - if (_currMenuID != _newMenuID) { _currMenuID = _newMenuID; //debug("_currMenuID = %d", _currMenuID); @@ -103,16 +101,13 @@ void MenuSystem::update() { if (_needRedraw) { //_vm->_system->copyRectToScreen(_vm->_screen->_frontScreen + 39 * 640 + 60, 640, 60, 39, 520, 247); _vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, _top, 640, 400 - _top); - //debug("redraw"); _needRedraw = false; } _vm->_system->delayMillis(5); - } void MenuSystem::handleEvents() { - Common::Event event; Common::EventManager *eventMan = _vm->_system->getEventManager(); while (eventMan->pollEvent(event)) { @@ -126,18 +121,18 @@ void MenuSystem::handleEvents() { case Common::EVENT_MOUSEMOVE: handleMouseMove(event.mouse.x, event.mouse.y); break; - case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: handleMouseClick(event.mouse.x, event.mouse.y); break; default: break; } } - } void MenuSystem::addClickTextItem(ItemID id, int x, int y, int w, uint fontNum, const char *caption, byte defaultColor, byte activeColor) { Item item; + item.enabled = true; item.id = id; item.defaultColor = defaultColor; item.activeColor = activeColor; @@ -202,7 +197,7 @@ void MenuSystem::handleKeyDown(const Common::KeyState& kbd) { ItemID MenuSystem::findItemAt(int x, int y) { for (Common::Array<Item>::iterator iter = _items.begin(); iter != _items.end(); iter++) { - if ((*iter).rect.contains(x, y - _top)) + if ((*iter).enabled && (*iter).rect.contains(x, y - _top)) return (*iter).id; } return kItemIdNone; @@ -220,6 +215,8 @@ void MenuSystem::setItemCaption(Item *item, const char *caption) { Font font(_vm->_res->load(_vm->_screen->getFontResIndex(item->fontNum))->data); int width = font.getTextWidth((const byte*)caption); int height = font.getHeight(); + if (width & 1) + width++; item->rect = Common::Rect(item->x, item->y - height, item->x + width, item->y); if (item->w) { item->rect.translate(item->w - width / 2, 0); @@ -236,59 +233,87 @@ void MenuSystem::initMenu(MenuID menuID) { switch (menuID) { case kMenuIdMain: - drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrWhatCanIDoForYou)); - addClickTextItem(kItemIdLoad, 0, 115, 320, 0, _vm->getSysString(kStrLoad), 229, 255); - addClickTextItem(kItemIdSave, 0, 135, 320, 0, _vm->getSysString(kStrSave), 229, 255); - addClickTextItem(kItemIdToggleText, 0, 165, 320, 0, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff), 229, 255); - addClickTextItem(kItemIdToggleVoices, 0, 185, 320, 0, _vm->getSysString(_vm->_cfgVoices ? kStrVoicesOn : kStrVoicesOff), 229, 255); - addClickTextItem(kItemIdVolumesMenu, 0, 215, 320, 0, _vm->getSysString(kStrVolume), 229, 255); - addClickTextItem(kItemIdPlay, 0, 245, 320, 0, _vm->getSysString(kStrPlay), 229, 255); - addClickTextItem(kItemIdQuit, 0, 275, 320, 0, _vm->getSysString(kStrQuit), 229, 255); + drawString(0, 75, 320, 1, 229, _vm->getSysString(kStrWhatCanIDoForYou)); + addClickTextItem(kItemIdLoad, 0, 116, 320, 0, _vm->getSysString(kStrLoad), 253, 255); + addClickTextItem(kItemIdSave, 0, 136, 320, 0, _vm->getSysString(kStrSave), 253, 255); + addClickTextItem(kItemIdToggleText, 0, 166, 320, 0, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff), 253, 255); + addClickTextItem(kItemIdToggleVoices, 0, 186, 320, 0, _vm->getSysString(_vm->_cfgVoices ? kStrVoicesOn : kStrVoicesOff), 253, 255); + addClickTextItem(kItemIdVolumesMenu, 0, 216, 320, 0, _vm->getSysString(kStrVolume), 253, 255); + addClickTextItem(kItemIdPlay, 0, 246, 320, 0, _vm->getSysString(kStrPlay), 253, 255); + addClickTextItem(kItemIdQuit, 0, 276, 320, 0, _vm->getSysString(kStrQuit), 253, 255); break; case kMenuIdLoad: - drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrLoadGame)); - addClickTextItem(kItemIdSavegameUp, 0, 155, 545, 1, "^", 255, 253); - addClickTextItem(kItemIdSavegameDown, 0, 195, 545, 1, "\\", 255, 253); - addClickTextItem(kItemIdCancel, 0, 275, 320, 0, _vm->getSysString(kStrCancel), 255, 253); - for (int i = 1; i <= 7; i++) { - Common::String saveDesc = Common::String::format("SAVEGAME %d", i); - addClickTextItem((ItemID)(kItemIdSavegame1 + i - 1), 0, 115 + 20 * (i - 1), 300, 0, saveDesc.c_str(), 231, 234); + if (ConfMan.getBool("originalsaveload")) { + shadeRect(80, 92, 440, 141, 226, 225); + drawString(0, 75, 320, 1, 229, _vm->getSysString(kStrLoadGame)); + addClickTextItem(kItemIdSavegameUp, 0, 156, 545, 1, "^", 253, 255); + addClickTextItem(kItemIdSavegameDown, 0, 196, 545, 1, "\\", 253, 255); + addClickTextItem(kItemIdCancel, 0, 276, 320, 0, _vm->getSysString(kStrCancel), 253, 255); + for (int i = 1; i <= 7; i++) { + Common::String saveDesc = Common::String::format("SAVEGAME %d", i); + addClickTextItem((ItemID)(kItemIdSavegame1 + i - 1), 0, 116 + 20 * (i - 1), 300, 0, saveDesc.c_str(), 231, 234); + } + loadSavegamesList(); + setSavegameCaptions(true); + } else { + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + int slot = dialog->runModalWithCurrentTarget(); + delete dialog; + + if (slot >= 0) + _vm->requestLoadgame(slot); + + _running = false; } - loadSavegamesList(); - setSavegameCaptions(); break; case kMenuIdSave: - drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrSaveGame)); - addClickTextItem(kItemIdSavegameUp, 0, 155, 545, 1, "^", 255, 253); - addClickTextItem(kItemIdSavegameDown, 0, 195, 545, 1, "\\", 255, 253); - addClickTextItem(kItemIdCancel, 0, 275, 320, 0, _vm->getSysString(kStrCancel), 255, 253); - for (int i = 1; i <= 7; i++) { - Common::String saveDesc = Common::String::format("SAVEGAME %d", i); - addClickTextItem((ItemID)(kItemIdSavegame1 + i - 1), 0, 115 + 20 * (i - 1), 300, 0, saveDesc.c_str(), 231, 234); + if (ConfMan.getBool("originalsaveload")) { + shadeRect(80, 92, 440, 141, 226, 225); + drawString(0, 75, 320, 1, 229, _vm->getSysString(kStrSaveGame)); + addClickTextItem(kItemIdSavegameUp, 0, 156, 545, 1, "^", 253, 255); + addClickTextItem(kItemIdSavegameDown, 0, 196, 545, 1, "\\", 253, 255); + addClickTextItem(kItemIdCancel, 0, 276, 320, 0, _vm->getSysString(kStrCancel), 253, 255); + for (int i = 1; i <= 7; i++) { + Common::String saveDesc = Common::String::format("SAVEGAME %d", i); + addClickTextItem((ItemID)(kItemIdSavegame1 + i - 1), 0, 116 + 20 * (i - 1), 300, 0, saveDesc.c_str(), 231, 234); + } + newSlotNum = loadSavegamesList() + 1; + _savegames.push_back(SavegameItem(newSlotNum, Common::String::format("GAME %04d", _savegames.size()))); + setSavegameCaptions(true); + } else { + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + int slot = dialog->runModalWithCurrentTarget(); + Common::String desc = dialog->getResultString(); + if (desc.empty()) { + // Create our own description for the saved game, the user didn't enter one + desc = dialog->createDefaultSaveDescription(slot); + } + + if (slot >= 0) + _vm->requestSavegame(slot, desc); + + _running = false; } - newSlotNum = loadSavegamesList() + 1; - _savegames.push_back(SavegameItem(newSlotNum, Common::String::format("GAME %03d", _savegames.size() + 1))); - setSavegameCaptions(); break; case kMenuIdVolumes: - drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrAdjustVolume)); - drawString(0, 130, 200, 0, 246, _vm->getSysString(kStrMaster)); - drawString(0, 155, 200, 0, 244, _vm->getSysString(kStrVoices)); - drawString(0, 180, 200, 0, 244, _vm->getSysString(kStrMusic)); - drawString(0, 205, 200, 0, 244, _vm->getSysString(kStrSoundFx)); - drawString(0, 230, 200, 0, 244, _vm->getSysString(kStrBackground)); - addClickTextItem(kItemIdDone, 0, 275, 200, 0, _vm->getSysString(kStrDone), 229, 253); - addClickTextItem(kItemIdCancel, 0, 275, 440, 0, _vm->getSysString(kStrCancel), 229, 253); - addClickTextItem(kItemIdMasterDown, 0, 130 + 25 * 0, 348, 1, "[", 229, 253); - addClickTextItem(kItemIdVoicesDown, 0, 130 + 25 * 1, 348, 1, "[", 229, 253); - addClickTextItem(kItemIdMusicDown, 0, 130 + 25 * 2, 348, 1, "[", 229, 253); - addClickTextItem(kItemIdSoundFXDown, 0, 130 + 25 * 3, 348, 1, "[", 229, 253); - addClickTextItem(kItemIdBackgroundDown, 0, 130 + 25 * 4, 348, 1, "[", 229, 253); - addClickTextItem(kItemIdMasterUp, 0, 130 + 25 * 0, 372, 1, "]", 229, 253); - addClickTextItem(kItemIdVoicesUp, 0, 130 + 25 * 1, 372, 1, "]", 229, 253); - addClickTextItem(kItemIdMusicUp, 0, 130 + 25 * 2, 372, 1, "]", 229, 253); - addClickTextItem(kItemIdSoundFXUp, 0, 130 + 25 * 3, 372, 1, "]", 229, 253); - addClickTextItem(kItemIdBackgroundUp, 0, 130 + 25 * 4, 372, 1, "]", 229, 253); + drawString(0, 75, 320, 1, 229, _vm->getSysString(kStrAdjustVolume)); + drawString(0, 131, 200, 0, 246, _vm->getSysString(kStrMaster)); + drawString(0, 156, 200, 0, 244, _vm->getSysString(kStrVoices)); + drawString(0, 181, 200, 0, 244, _vm->getSysString(kStrMusic)); + drawString(0, 206, 200, 0, 244, _vm->getSysString(kStrSoundFx)); + drawString(0, 231, 200, 0, 244, _vm->getSysString(kStrBackground)); + addClickTextItem(kItemIdDone, 0, 276, 200, 0, _vm->getSysString(kStrDone), 253, 255); + addClickTextItem(kItemIdCancel, 0, 276, 440, 0, _vm->getSysString(kStrCancel), 253, 255); + addClickTextItem(kItemIdMasterDown, 0, 131 + 25 * 0, 348, 1, "[", 243, 246); + addClickTextItem(kItemIdVoicesDown, 0, 131 + 25 * 1, 348, 1, "[", 243, 246); + addClickTextItem(kItemIdMusicDown, 0, 131 + 25 * 2, 348, 1, "[", 243, 246); + addClickTextItem(kItemIdSoundFXDown, 0, 131 + 25 * 3, 348, 1, "[", 243, 246); + addClickTextItem(kItemIdBackgroundDown, 0, 131 + 25 * 4, 348, 1, "[", 243, 246); + addClickTextItem(kItemIdMasterUp, 0, 131 + 25 * 0, 372, 1, "]", 243, 246); + addClickTextItem(kItemIdVoicesUp, 0, 131 + 25 * 1, 372, 1, "]", 243, 246); + addClickTextItem(kItemIdMusicUp, 0, 131 + 25 * 2, 372, 1, "]", 243, 246); + addClickTextItem(kItemIdSoundFXUp, 0, 131 + 25 * 3, 372, 1, "]", 243, 246); + addClickTextItem(kItemIdBackgroundUp, 0, 131 + 25 * 4, 372, 1, "]", 243, 246); drawVolumeBar(kItemIdMaster); drawVolumeBar(kItemIdVoices); drawVolumeBar(kItemIdMusic); @@ -300,9 +325,36 @@ void MenuSystem::initMenu(MenuID menuID) { } for (Common::Array<Item>::iterator iter = _items.begin(); iter != _items.end(); iter++) { - drawItem((*iter).id, false); + if ((*iter).enabled) + drawItem((*iter).id, false); } + // Check if the mouse is already over an item + _currItemID = kItemIdNone; + Common::Point mousePos = _vm->_system->getEventManager()->getMousePos(); + handleMouseMove(mousePos.x, mousePos.y); +} + +void MenuSystem::enableItem(ItemID id) { + Item *item = getItem(id); + if (item) { + item->enabled = true; + drawItem(id, false); + _currItemID = kItemIdNone; + Common::Point mousePos = _vm->_system->getEventManager()->getMousePos(); + handleMouseMove(mousePos.x, mousePos.y); + } +} + +void MenuSystem::disableItem(ItemID id) { + Item *item = getItem(id); + if (item) { + item->enabled = false; + restoreRect(item->rect.left, item->rect.top, item->rect.width(), item->rect.height()); + if (_currItemID == id) { + _currItemID = kItemIdNone; + } + } } void MenuSystem::enterItem(ItemID id) { @@ -433,14 +485,16 @@ void MenuSystem::drawString(int16 x, int16 y, int w, uint fontNum, byte color, c fontNum = _vm->_screen->getFontResIndex(fontNum); Font font(_vm->_res->load(fontNum)->data); if (w) { - x = x + w - font.getTextWidth((const byte*)text) / 2; + int width = font.getTextWidth((const byte*)text); + if (width & 1) + width++; + x = x + w - width / 2; } _vm->_screen->drawString(x, y - font.getHeight(), color, fontNum, (const byte*)text, -1, NULL, true); _needRedraw = true; } int MenuSystem::loadSavegamesList() { - int maxSlotNum = -1; _savegameListTopIndex = 0; @@ -483,17 +537,32 @@ MenuSystem::SavegameItem *MenuSystem::getSavegameItemByID(ItemID id) { return NULL; } -void MenuSystem::setSavegameCaptions() { - uint index = _savegameListTopIndex; +void MenuSystem::setSavegameCaptions(bool scrollToBottom) { + int size = _savegames.size(); + if (scrollToBottom && size > 0) { + while (_savegameListTopIndex + 7 <= size) + _savegameListTopIndex += 6; + } + int index = _savegameListTopIndex; for (int i = 1; i <= 7; i++) - setItemCaption(getItem((ItemID)(kItemIdSavegame1 + i - 1)), index < _savegames.size() ? _savegames[index++]._description.c_str() : ""); + setItemCaption(getItem((ItemID)(kItemIdSavegame1 + i - 1)), index < size ? _savegames[index++]._description.c_str() : ""); + if (_savegameListTopIndex == 0) { + disableItem(kItemIdSavegameUp); + } else { + enableItem(kItemIdSavegameUp); + } + if (_savegameListTopIndex + 7 > size) { + disableItem(kItemIdSavegameDown); + } else { + enableItem(kItemIdSavegameDown); + } } void MenuSystem::scrollSavegames(int delta) { int newPos = CLIP<int>(_savegameListTopIndex + delta, 0, _savegames.size() - 1); _savegameListTopIndex = newPos; restoreRect(80, 92, 440, 140); - setSavegameCaptions(); + setSavegameCaptions(false); for (int i = 1; i <= 7; i++) drawItem((ItemID)(kItemIdSavegame1 + i - 1), false); } @@ -574,7 +643,6 @@ void MenuSystem::drawVolumeBar(ItemID itemID) { text[volume] = 0; drawString(0, y, w, 0, 246, text); - } void MenuSystem::changeVolumeBar(ItemID itemID, int delta) { diff --git a/engines/toltecs/menu.h b/engines/toltecs/menu.h index a72205c2e5..a5eca7c8ff 100644 --- a/engines/toltecs/menu.h +++ b/engines/toltecs/menu.h @@ -84,6 +84,7 @@ public: protected: struct Item { + bool enabled; Common::Rect rect; ItemID id; Common::String caption; @@ -130,6 +131,9 @@ protected: void initMenu(MenuID menuID); + void enableItem(ItemID id); + void disableItem(ItemID id); + void enterItem(ItemID id); void leaveItem(ItemID id); void clickItem(ItemID id); @@ -141,7 +145,7 @@ protected: SavegameItem *getSavegameItemByID(ItemID id); int loadSavegamesList(); - void setSavegameCaptions(); + void setSavegameCaptions(bool scrollToBottom); void scrollSavegames(int delta); void clickSavegameItem(ItemID id); void setCfgText(bool value, bool active); diff --git a/engines/toltecs/microtiles.cpp b/engines/toltecs/microtiles.cpp index 60e65bdaf3..9181480351 100644 --- a/engines/toltecs/microtiles.cpp +++ b/engines/toltecs/microtiles.cpp @@ -119,8 +119,6 @@ Common::Rect * MicroTileArray::getRectangles(int *num_rects, int min_x, int min_ for (y = 0; y < _tilesH; ++y) { for (x = 0; x < _tilesW; ++x) { - - int start; int finish = 0; BoundingBox boundingBox; @@ -141,8 +139,6 @@ Common::Rect * MicroTileArray::getRectangles(int *num_rects, int min_x, int min_ // FIXME: Why is the following code in an #if block? #if 1 - start = i; - if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) { // check if the tile continues while (!finish) { ++x; diff --git a/engines/toltecs/module.mk b/engines/toltecs/module.mk index aa4a6f376b..0de1eef733 100644 --- a/engines/toltecs/module.mk +++ b/engines/toltecs/module.mk @@ -2,6 +2,7 @@ MODULE := engines/toltecs MODULE_OBJS = \ animation.o \ + console.o \ detection.o \ menu.o \ microtiles.o \ diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp index 35accb5d93..8bc00511e9 100644 --- a/engines/toltecs/movie.cpp +++ b/engines/toltecs/movie.cpp @@ -45,14 +45,13 @@ enum ChunkTypes { kChunkStopSubtitles = 8 }; -MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm) { +MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm), _isPlaying(false) { } MoviePlayer::~MoviePlayer() { } void MoviePlayer::playMovie(uint resIndex) { - const uint32 subtitleSlot = kMaxScriptSlots - 1; int16 savedSceneWidth = _vm->_sceneWidth; int16 savedSceneHeight = _vm->_sceneHeight; @@ -62,6 +61,7 @@ void MoviePlayer::playMovie(uint resIndex) { int16 savedGuiHeight = _vm->_guiHeight; byte moviePalette[768]; + _isPlaying = true; _vm->_isSaveAllowed = false; memset(moviePalette, 0, sizeof(moviePalette)); @@ -99,15 +99,16 @@ void MoviePlayer::playMovie(uint resIndex) { byte *chunkBuffer = NULL; uint32 chunkBufferSize = 0; uint32 frame = 0; + bool abortMovie = false; - while (_chunkCount--) { + while (_chunkCount-- && !abortMovie) { byte chunkType = _vm->_arc->readByte(); uint32 chunkSize = _vm->_arc->readUint32LE(); debug(0, "chunkType = %d; chunkSize = %d", chunkType, chunkSize); // Skip audio chunks - we've already queued them in - // fetchAudioChunks() above + // fetchAudioChunks() if (chunkType == kChunkAudio) { _vm->_arc->skip(chunkSize); } else { @@ -136,7 +137,8 @@ void MoviePlayer::playMovie(uint resIndex) { if (_vm->_screen->_shakeActive && _vm->_screen->updateShakeScreen()) { _vm->_screen->_fullRefresh = true; } - _vm->updateInput(); + if (!handleInput()) + abortMovie = true; _vm->drawScreen(); // Note: drawScreen() calls delayMillis() } @@ -153,10 +155,11 @@ void MoviePlayer::playMovie(uint resIndex) { // Already processed break; case kChunkShowSubtitle: - if (_vm->_cfgText) { - memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize); - _vm->_screen->updateTalkText(subtitleSlot, 0); - } + memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize); + // The last character of the subtitle determines if it should + // always be displayed or not. If it's 0xFF, it should always be + // displayed, otherwise, if it's 0xFE, it can be toggled. + _vm->_screen->updateTalkText(subtitleSlot, 0, (chunkBuffer[chunkSize - 1] == 0xFF)); break; case kChunkShakeScreen: // start/stop shakescreen effect if (chunkBuffer[0] == 0xFF) @@ -180,7 +183,7 @@ void MoviePlayer::playMovie(uint resIndex) { } if (!handleInput()) - break; + abortMovie = true; } delete[] chunkBuffer; @@ -200,10 +203,10 @@ void MoviePlayer::playMovie(uint resIndex) { _vm->_guiHeight = savedGuiHeight; _vm->_isSaveAllowed = true; + _isPlaying = false; } void MoviePlayer::fetchAudioChunks() { - uint32 startOfs = _vm->_arc->pos(); uint32 chunkCount = _chunkCount; uint prefetchChunkCount = 0; @@ -214,7 +217,7 @@ void MoviePlayer::fetchAudioChunks() { while (chunkCount-- && prefetchChunkCount < _framesPerSoundChunk / 2) { byte chunkType = _vm->_arc->readByte(); uint32 chunkSize = _vm->_arc->readUint32LE(); - if (chunkType == 4) { + if (chunkType == kChunkAudio) { byte *chunkBuffer = (byte *)malloc(chunkSize); _vm->_arc->read(chunkBuffer, chunkSize); _audioStream->queueBuffer(chunkBuffer, chunkSize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED); @@ -229,7 +232,6 @@ void MoviePlayer::fetchAudioChunks() { _lastPrefetchOfs = _vm->_arc->pos(); _vm->_arc->seek(startOfs, SEEK_SET); - } void MoviePlayer::unpackPalette(byte *source, byte *dest, int elemCount, int elemSize) { @@ -249,10 +251,12 @@ void MoviePlayer::unpackPalette(byte *source, byte *dest, int elemCount, int ele } void MoviePlayer::unpackRle(byte *source, byte *dest) { - int size = 256000; + int size = 256000; // 640x400 + //int packedSize = 0; while (size > 0) { byte a = *source++; byte b = *source++; + //packedSize += 2; if (a == 0) { dest += b; size -= b; @@ -262,6 +266,7 @@ void MoviePlayer::unpackRle(byte *source, byte *dest) { size -= a; } } + //debug("Packed RLE size: %d", packedSize); } bool MoviePlayer::handleInput() { @@ -272,12 +277,15 @@ bool MoviePlayer::handleInput() { case Common::EVENT_KEYDOWN: if (event.kbd.keycode == Common::KEYCODE_ESCAPE) return false; + if (event.kbd.keycode == Common::KEYCODE_F10) { + // TODO: The original would bring up a stripped down + // main menu dialog, without the save/restore options. + } break; case Common::EVENT_LBUTTONDOWN: case Common::EVENT_RBUTTONDOWN: return false; case Common::EVENT_QUIT: - _vm->quitGame(); return false; default: break; diff --git a/engines/toltecs/movie.h b/engines/toltecs/movie.h index 8fa48975d7..c1ed6d7ba0 100644 --- a/engines/toltecs/movie.h +++ b/engines/toltecs/movie.h @@ -37,11 +37,15 @@ public: void playMovie(uint resIndex); + bool isPlaying() { return _isPlaying; } + protected: ToltecsEngine *_vm; Audio::QueuingAudioStream *_audioStream; Audio::SoundHandle _audioStreamHandle; + bool _isPlaying; + uint32 _chunkCount, _frameCount, _lastPrefetchOfs; uint32 _soundChunkFramesLeft, _framesPerSoundChunk; diff --git a/engines/toltecs/palette.cpp b/engines/toltecs/palette.cpp index 74683c6d7a..b93bb8b510 100644 --- a/engines/toltecs/palette.cpp +++ b/engines/toltecs/palette.cpp @@ -32,6 +32,8 @@ namespace Toltecs { Palette::Palette(ToltecsEngine *vm) : _vm(vm) { clearFragments(); + memset(_mainPalette, 0, sizeof(_mainPalette)); + memset(_animPalette, 0, sizeof(_animPalette)); memset(_colorTransTable, 0, sizeof(_colorTransTable)); } @@ -138,52 +140,48 @@ void Palette::clearFragments() { _fragments.clear(); } +byte Palette::getMatchingColor(byte r, byte g, byte b) { + int bestIndex = 0; + uint16 bestMatch = 0xFFFF; + + for (int j = 0; j < 256; j++) { + byte distance = ABS(_mainPalette[j * 3 + 0] - r) + ABS(_mainPalette[j * 3 + 1] - g) + ABS(_mainPalette[j * 3 + 2] - b); + byte maxColor = MAX(_mainPalette[j * 3 + 0], MAX(_mainPalette[j * 3 + 1], _mainPalette[j * 3 + 2])); + uint16 match = (distance << 8) | maxColor; + if (match < bestMatch) { + bestMatch = match; + bestIndex = j; + } + } + + return bestIndex; +} + void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) { byte r = 0, g = 0, b = 0; mask &= 7; - for (int i = 0; i < 256; i++) { - - if (deltaValue < 0) { - // TODO (probably unused) - warning("Palette::buildColorTransTable(%d, %d, %02X) not yet implemented!", limit, deltaValue, mask); - } else { - r = _mainPalette[i * 3 + 0]; - g = _mainPalette[i * 3 + 1]; - b = _mainPalette[i * 3 + 2]; - if (MAX(r, MAX(b, g)) >= limit) { - if ((mask & 1) && r >= deltaValue) - r -= deltaValue; - if ((mask & 2) && g >= deltaValue) - g -= deltaValue; - if ((mask & 4) && b >= deltaValue) - b -= deltaValue; - } - } + if (deltaValue < 0) // unused + error("buildColorTransTable called with a negative delta value(limit %d, delta %d, mask %02X)", limit, deltaValue, mask); - int bestIndex = 0; - uint16 bestMatch = 0xFFFF; - - for (int j = 0; j < 256; j++) { - byte distance = ABS(_mainPalette[j * 3 + 0] - r) + ABS(_mainPalette[j * 3 + 1] - g) + ABS(_mainPalette[j * 3 + 2] - b); - byte maxColor = MAX(_mainPalette[j * 3 + 0], MAX(_mainPalette[j * 3 + 1], _mainPalette[j * 3 + 2])); - uint16 match = (distance << 8) | maxColor; - if (match < bestMatch) { - bestMatch = match; - bestIndex = j; - } + for (int i = 0; i < 256; i++) { + r = _mainPalette[i * 3 + 0]; + g = _mainPalette[i * 3 + 1]; + b = _mainPalette[i * 3 + 2]; + if (MAX(r, MAX(b, g)) >= limit) { + if ((mask & 1) && r >= deltaValue) + r -= deltaValue; + if ((mask & 2) && g >= deltaValue) + g -= deltaValue; + if ((mask & 4) && b >= deltaValue) + b -= deltaValue; } - _colorTransTable[i] = bestIndex; - + _colorTransTable[i] = getMatchingColor(r, g, b); } } -void Palette::buildColorTransTable2(byte limit, int8 deltaValue, byte mask) { - // TODO -} - void Palette::saveState(Common::WriteStream *out) { // Save currently active palette byte palette[768]; diff --git a/engines/toltecs/palette.h b/engines/toltecs/palette.h index 570f51777e..4777a82699 100644 --- a/engines/toltecs/palette.h +++ b/engines/toltecs/palette.h @@ -50,8 +50,8 @@ public: uint16 findFragment(int16 id); void clearFragments(); + byte getMatchingColor(byte r, byte g, byte b); void buildColorTransTable(byte limit, int8 deltaValue, byte mask); - void buildColorTransTable2(byte limit, int8 deltaValue, byte mask); byte getColorTransPixel(byte pixel) const { return _colorTransTable[pixel]; } byte *getMainPalette() { return _mainPalette; } diff --git a/engines/toltecs/resource.cpp b/engines/toltecs/resource.cpp index 0b9f7c8fcd..d66075004b 100644 --- a/engines/toltecs/resource.cpp +++ b/engines/toltecs/resource.cpp @@ -61,16 +61,11 @@ uint32 ArchiveReader::getResourceSize(uint resIndex) { return _offsets[resIndex + 1] - _offsets[resIndex]; } -void ArchiveReader::dump(uint resIndex, const char *prefix) { +void ArchiveReader::dump(uint resIndex) { int32 resourceSize = getResourceSize(resIndex); byte *data = new byte[resourceSize]; - Common::String fn; - - if (prefix) - fn = Common::String::format("%s_%04X.0", prefix, resIndex); - else - fn = Common::String::format("%04X.0", resIndex); + Common::String fn = Common::String::format("toltecs_res.%03d", resIndex); openResource(resIndex); read(data, resourceSize); @@ -112,11 +107,13 @@ Resource *ResourceCache::load(uint resIndex) { } else { debug(1, "ResourceCache::load(%d) From disk", resIndex); + int32 curPos = _vm->_arc->pos(); Resource *resItem = new Resource(); resItem->size = _vm->_arc->openResource(resIndex); resItem->data = new byte[resItem->size]; _vm->_arc->read(resItem->data, resItem->size); _vm->_arc->closeResource(); + _vm->_arc->seek(curPos); _cache[resIndex] = resItem; diff --git a/engines/toltecs/resource.h b/engines/toltecs/resource.h index 3fed2e11ca..3d45d9fb1b 100644 --- a/engines/toltecs/resource.h +++ b/engines/toltecs/resource.h @@ -50,7 +50,7 @@ public: // Returns the size of the resource uint32 getResourceSize(uint resIndex); - void dump(uint resIndex, const char *prefix = NULL); + void dump(uint resIndex); protected: uint32 *_offsets; diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp index c8d6740b02..be91130c0a 100644 --- a/engines/toltecs/screen.cpp +++ b/engines/toltecs/screen.cpp @@ -33,7 +33,6 @@ namespace Toltecs { Screen::Screen(ToltecsEngine *vm) : _vm(vm) { - _frontScreen = new byte[268800]; _backScreen = new byte[870400]; @@ -68,16 +67,13 @@ Screen::Screen(ToltecsEngine *vm) : _vm(vm) { _renderQueue = new RenderQueue(_vm); _fullRefresh = false; _guiRefresh = false; - } Screen::~Screen() { - delete[] _frontScreen; delete[] _backScreen; delete _renderQueue; - } void Screen::unpackRle(byte *source, byte *dest, uint16 width, uint16 height) { @@ -120,7 +116,6 @@ void Screen::loadMouseCursor(uint resIndex) { } void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) { - byte *imageData = _vm->_res->load(resIndex)->data; int16 headerSize = READ_LE_UINT16(imageData); int16 width = imageData[2]; @@ -153,7 +148,6 @@ void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) { } _guiRefresh = true; - } void Screen::startShakeScreen(int16 shakeCounter) { @@ -185,7 +179,6 @@ bool Screen::updateShakeScreen() { } void Screen::addStaticSprite(byte *spriteItem) { - DrawRequest drawRequest; memset(&drawRequest, 0, sizeof(drawRequest)); @@ -200,11 +193,9 @@ void Screen::addStaticSprite(byte *spriteItem) { debug(0, "Screen::addStaticSprite() x = %d; y = %d; baseColor = %d; resIndex = %d; flags = %04X", drawRequest.x, drawRequest.y, drawRequest.baseColor, drawRequest.resIndex, drawRequest.flags); addDrawRequest(drawRequest); - } void Screen::addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode) { - //debug(0, "Screen::addAnimatedSprite(%d, %d, %d)", x, y, fragmentId); DrawRequest drawRequest; @@ -257,9 +248,7 @@ void Screen::addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, i WRITE_LE_UINT16(spriteItem + 0, loopNum); WRITE_LE_UINT16(spriteItem + 4, frameNum); - } - } void Screen::clearSprites() { @@ -267,7 +256,6 @@ void Screen::clearSprites() { } void Screen::blastSprite(int16 x, int16 y, int16 fragmentId, int16 resIndex, uint16 flags) { - DrawRequest drawRequest; SpriteDrawItem sprite; @@ -283,11 +271,9 @@ void Screen::blastSprite(int16 x, int16 y, int16 fragmentId, int16 resIndex, uin sprite.y -= _vm->_cameraY; drawSprite(sprite); } - } void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) { - debug(0, "Screen::updateVerbLine() _verbLineNum = %d; _verbLineX = %d; _verbLineY = %d; _verbLineWidth = %d; _verbLineCount = %d", _verbLineNum, _verbLineX, _verbLineY, _verbLineWidth, _verbLineCount); @@ -339,7 +325,7 @@ void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) { wrapState.len1 -= len; wrapState.len2 = len + 1; - drawGuiText(_verbLineX - 1 - (wrapState.width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0], wrapState); + drawGuiText(_verbLineX - 1 - (wrapState.width / 2), y - 1, 0xF9, 0xFF, _fontResIndexArray[0], wrapState); wrapState.destString = wrapState.textBuffer; wrapState.width = 0; @@ -354,14 +340,12 @@ void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) { wrapState.len1 -= len; wrapState.len2 = len; - drawGuiText(_verbLineX - 1 - (wrapState.width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0], wrapState); + drawGuiText(_verbLineX - 1 - (wrapState.width / 2), y - 1, 0xF9, 0xFF, _fontResIndexArray[0], wrapState); _guiRefresh = true; - } -void Screen::updateTalkText(int16 slotIndex, int16 slotOffset) { - +void Screen::updateTalkText(int16 slotIndex, int16 slotOffset, bool alwaysDisplayed) { int16 x, y, maxWidth, width, length; byte durationModifier = 1; byte *textData = _vm->_script->getSlotData(slotIndex) + slotOffset; @@ -370,6 +354,7 @@ void Screen::updateTalkText(int16 slotIndex, int16 slotOffset) { item->fontNum = 0; item->color = _talkTextFontColor; + item->alwaysDisplayed = alwaysDisplayed; x = CLIP<int16>(_talkTextX - _vm->_cameraX, 120, _talkTextMaxWidth); y = CLIP<int16>(_talkTextY - _vm->_cameraY, 4, _vm->_cameraHeight - 16); @@ -455,11 +440,9 @@ void Screen::updateTalkText(int16 slotIndex, int16 slotOffset) { textDurationMultiplier += 100; } item->duration = 4 * textDurationMultiplier * durationModifier; - } void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item) { - if (width > 0) { TextRect *textRect = &item->lines[item->lineCount]; width = width + 1 - font.getSpacing(); @@ -472,7 +455,6 @@ void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 } y += font.getHeight() - 1; - } void Screen::addTalkTextItemsToRenderQueue() { @@ -488,7 +470,7 @@ void Screen::addTalkTextItemsToRenderQueue() { if (item->duration < 0) item->duration = 0; - if (!_vm->_cfgText) + if (!_vm->_cfgText && !item->alwaysDisplayed) return; for (byte j = 0; j < item->lineCount; j++) { @@ -499,6 +481,15 @@ void Screen::addTalkTextItemsToRenderQueue() { } } +bool Screen::isTalkTextActive(int16 slotIndex) { + for (int16 i = 0; i <= _talkTextItemNum; i++) { + if (_talkTextItems[i].slotIndex == slotIndex && _talkTextItems[i].duration > 0) + return true; + } + + return false; +} + int16 Screen::getTalkTextDuration() { return _talkTextItems[_talkTextItemNum].duration; } @@ -524,7 +515,6 @@ void Screen::registerFont(uint fontIndex, uint resIndex) { } void Screen::drawGuiTextMulti(byte *textData) { - int16 x = 0, y = 0; // Really strange stuff. @@ -554,12 +544,11 @@ void Screen::drawGuiTextMulti(byte *textData) { wrapState.width = 0; wrapState.len1 = 0; wrapState.len2 = wrapGuiText(_fontResIndexArray[1], 640, wrapState); - drawGuiText(x - wrapState.width / 2, y, _fontColor1, _fontColor2, _fontResIndexArray[1], wrapState); + drawGuiText(x - wrapState.width / 2, y - 1, _fontColor1, _fontColor2, _fontResIndexArray[1], wrapState); } } while (*wrapState.sourceString != 0xFF); _guiRefresh = true; - } int16 Screen::wrapGuiText(uint fontResIndex, int maxWidth, GuiTextWrapState &wrapState) { @@ -582,7 +571,6 @@ int16 Screen::wrapGuiText(uint fontResIndex, int maxWidth, GuiTextWrapState &wra } return len; - } void Screen::drawGuiText(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex, GuiTextWrapState &wrapState) { @@ -593,11 +581,9 @@ void Screen::drawGuiText(int16 x, int16 y, byte fontColor1, byte fontColor2, uin x = drawString(x + 1, y + _vm->_cameraHeight, fontColor1, fontResIndex, wrapState.textBuffer, wrapState.len1, &ywobble, false); x = drawString(x, y + _vm->_cameraHeight, fontColor2, fontResIndex, wrapState.textBuffer + wrapState.len1, wrapState.len2, &ywobble, false); - } int16 Screen::drawString(int16 x, int16 y, byte color, uint fontResIndex, const byte *text, int len, int16 *ywobble, bool outline) { - //debug(0, "Screen::drawString(%d, %d, %d, %d)", x, y, color, fontResIndex); Font font(_vm->_res->load(fontResIndex)->data); @@ -614,7 +600,7 @@ int16 Screen::drawString(int16 x, int16 y, byte color, uint fontResIndex, const if (ch <= 0x20) { x += font.getWidth(); } else { - drawChar(font, _frontScreen, x, y - yadd, ch, color, outline); + drawChar(font, _frontScreen, x, y + yadd, ch, color, outline); x += font.getCharWidth(ch) + font.getSpacing() - 1; yadd = -yadd; } @@ -624,11 +610,9 @@ int16 Screen::drawString(int16 x, int16 y, byte color, uint fontResIndex, const *ywobble = yadd; return x; - } void Screen::drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, byte color, bool outline) { - int16 charWidth, charHeight; byte *charData; @@ -657,11 +641,9 @@ void Screen::drawChar(const Font &font, byte *dest, int16 x, int16 y, byte ch, b } dest += 640 - charWidth; } - } void Screen::drawSurface(int16 x, int16 y, Graphics::Surface *surface) { - int16 skipX = 0; int16 width = surface->w; int16 height = surface->h; @@ -706,11 +688,9 @@ void Screen::drawSurface(int16 x, int16 y, Graphics::Surface *surface) { frontScreen += 640 - width; surfacePixels += surface->w - width - skipX; } - } void Screen::saveState(Common::WriteStream *out) { - // Save verb line out->writeUint16LE(_verbLineNum); out->writeUint16LE(_verbLineX); @@ -757,11 +737,9 @@ void Screen::saveState(Common::WriteStream *out) { out->writeUint32LE(_fontResIndexArray[i]); out->writeByte(_fontColor1); out->writeByte(_fontColor2); - } void Screen::loadState(Common::ReadStream *in) { - // Load verb line _verbLineNum = in->readUint16LE(); _verbLineX = in->readUint16LE(); @@ -786,6 +764,7 @@ void Screen::loadState(Common::ReadStream *in) { _talkTextItems[i].fontNum = in->readUint16LE(); _talkTextItems[i].color = in->readByte(); _talkTextItems[i].lineCount = in->readByte(); + _talkTextItems[i].alwaysDisplayed = false; for (int j = 0; j < _talkTextItems[i].lineCount; j++) { _talkTextItems[i].lines[j].x = in->readUint16LE(); _talkTextItems[i].lines[j].y = in->readUint16LE(); @@ -809,7 +788,6 @@ void Screen::loadState(Common::ReadStream *in) { _fontResIndexArray[i] = in->readUint32LE(); _fontColor1 = in->readByte(); _fontColor2 = in->readByte(); - } } // End of namespace Toltecs diff --git a/engines/toltecs/screen.h b/engines/toltecs/screen.h index 788cde50c6..ee565e1882 100644 --- a/engines/toltecs/screen.h +++ b/engines/toltecs/screen.h @@ -136,6 +136,7 @@ struct TalkTextItem { byte color; byte lineCount; TextRect lines[15]; + bool alwaysDisplayed; }; struct GuiTextWrapState { @@ -177,10 +178,11 @@ public: void updateVerbLine(int16 slotIndex, int16 slotOffset); // Talk text - void updateTalkText(int16 slotIndex, int16 slotOffset); + void updateTalkText(int16 slotIndex, int16 slotOffset, bool alwaysDisplayed); void addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item); void addTalkTextItemsToRenderQueue(); int16 getTalkTextDuration(); + bool isTalkTextActive(int16 slotIndex); void finishTalkTextItems(); void keepTalkTextItemsAlive(); diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp index 5e8617bc43..9ea95a2cd1 100644 --- a/engines/toltecs/script.cpp +++ b/engines/toltecs/script.cpp @@ -40,6 +40,22 @@ namespace Toltecs { +static const VarType varTypes[] = { + vtByte, vtWord, vtWord, vtByte, vtWord, // 0 - 4 + vtWord, vtWord, vtWord, vtWord, vtWord, // 5 - 9 + vtWord, vtWord, vtByte, vtWord, vtWord, // 10 - 14 + vtWord, vtWord, vtWord, vtWord, vtWord, // 15 - 19 + vtWord, vtWord // 20 - 21 +}; + +static const char *varNames[] = { + "mouseDisabled", "mouseY", "mouseX", "mouseButton", "verbLineY", // 0 - 4 + "verbLineX", "verbLineWidth", "verbLineCount", "verbLineNum", "talkTextItemNum", // 5 - 9 + "talkTextY", "talkTextX", "talkTextFontColor", "cameraY", "cameraX", // 10 - 14 + "walkSpeedY", "walkSpeedX", "flag01", "sceneResIndex", "guiHeight", // 15 - 19 + "sceneHeight", "sceneWidth" // 20 - 21 +}; + ScriptInterpreter::ScriptInterpreter(ToltecsEngine *vm) : _vm(vm) { _stack = new byte[kScriptStackSize]; @@ -154,7 +170,6 @@ void ScriptInterpreter::setupScriptFunctions() { } void ScriptInterpreter::loadScript(uint resIndex, uint slotIndex) { - delete[] _slots[slotIndex].data; _slots[slotIndex].resIndex = resIndex; @@ -162,7 +177,6 @@ void ScriptInterpreter::loadScript(uint resIndex, uint slotIndex) { _slots[slotIndex].size = scriptResource->size; _slots[slotIndex].data = new byte[_slots[slotIndex].size]; memcpy(_slots[slotIndex].data, scriptResource->data, _slots[slotIndex].size); - } void ScriptInterpreter::setMainScript(uint slotIndex) { @@ -228,10 +242,9 @@ int16 ScriptInterpreter::readInt16() { } void ScriptInterpreter::execOpcode(byte opcode) { - int16 ofs; - debug(1, "opcode = %d", opcode); + debug(2, "opcode = %d", opcode); switch (opcode) { case 0: @@ -239,35 +252,32 @@ void ScriptInterpreter::execOpcode(byte opcode) { // ok _subCode = _code; byte length = readByte(); - debug(1, "length = %d", length); + if (length == 0) { + warning("Possible script bug detected - opcode length is 0 when calling script function"); + return; + } + debug(2, "length = %d", length); uint16 index = readInt16(); - debug(1, "callScriptFunction %d", index); execScriptFunction(index); _code += length - 2; break; } case 1: - // ok _regs.reg0 = readInt16(); break; case 2: - // ok _regs.reg1 = readInt16(); break; case 3: - // ok _regs.reg3 = readInt16(); break; case 4: - // ok _regs.reg5 = _regs.reg0; break; case 5: - // ok _regs.reg3 = _regs.reg0; break; case 6: - // ok _regs.reg1 = _regs.reg0; break; case 7: @@ -468,72 +478,14 @@ void ScriptInterpreter::execOpcode(byte opcode) { } void ScriptInterpreter::execScriptFunction(uint16 index) { - debug(4, "execScriptFunction(%d)", index); if (index >= _scriptFuncs.size()) error("ScriptInterpreter::execScriptFunction() Invalid script function index %d", index); - debug(4, "%s", _scriptFuncNames[index]); + debug(1, "execScriptFunction %s (%d)", _scriptFuncNames[index], index); (*_scriptFuncs[index])(); } -VarType ScriptInterpreter::getGameVarType(uint variable) { - switch (variable) { - case 0: return vtByte; - case 1: return vtWord; - case 2: return vtWord; - case 3: return vtByte; - case 4: return vtWord; - case 5: return vtWord; - case 6: return vtWord; - case 7: return vtWord; - case 8: return vtWord; - case 9: return vtWord; - case 10: return vtWord; - case 11: return vtWord; - case 12: return vtByte; - case 13: return vtWord; - case 14: return vtWord; - case 15: return vtWord; - case 16: return vtWord; - case 17: return vtWord; - case 18: return vtWord; - case 19: return vtWord; - case 20: return vtWord; - case 21: return vtWord; - default: - error("Invalid game variable"); - } -} - -const char *getVarName(uint variable) { - switch (variable) { - case 0: return "mouseDisabled"; - case 1: return "mouseY"; - case 2: return "mouseX"; - case 3: return "mouseButton"; - case 4: return "verbLineY"; - case 5: return "verbLineX"; - case 6: return "verbLineWidth"; - case 7: return "verbLineCount"; - case 8: return "verbLineNum"; - case 9: return "talkTextItemNum"; - case 10: return "talkTextY"; - case 11: return "talkTextX"; - case 12: return "talkTextFontColor"; - case 13: return "cameraY"; - case 14: return "cameraX"; - case 15: return "walkSpeedY"; - case 16: return "walkSpeedX"; - case 17: return "flag01"; - case 18: return "sceneResIndex"; - case 19: return "guiHeight"; - case 20: return "sceneHeight"; - case 21: return "sceneWidth"; - } - return "(invalid)"; -} - int16 ScriptInterpreter::getGameVar(uint variable) { - debug(0, "ScriptInterpreter::getGameVar(%d{%s})", variable, getVarName(variable)); + debug(2, "ScriptInterpreter::getGameVar(%d{%s})", variable, varNames[variable]); switch (variable) { case 0: return _vm->_mouseDisabled; @@ -559,13 +511,13 @@ int16 ScriptInterpreter::getGameVar(uint variable) { case 20: return _vm->_sceneHeight; case 21: return _vm->_sceneWidth; default: - warning("Getting unimplemented game variable %s (%d)", getVarName(variable), variable); + warning("Getting unimplemented game variable %s (%d)", varNames[variable], variable); return 0; } } void ScriptInterpreter::setGameVar(uint variable, int16 value) { - debug(0, "ScriptInterpreter::setGameVar(%d{%s}, %d)", variable, getVarName(variable), value); + debug(2, "ScriptInterpreter::setGameVar(%d{%s}, %d)", variable, varNames[variable], value); switch (variable) { case 0: @@ -632,10 +584,9 @@ void ScriptInterpreter::setGameVar(uint variable, int16 value) { case 1: case 2: default: - warning("Setting unimplemented game variable %s (%d) to %d", getVarName(variable), variable, value); + warning("Setting unimplemented game variable %s (%d) to %d", varNames[variable], variable, value); break; } - } byte ScriptInterpreter::arg8(int16 offset) { @@ -657,32 +608,31 @@ int16 ScriptInterpreter::popInt16() { } void ScriptInterpreter::localWrite8(int16 offset, byte value) { - //debug(1, "localWrite8(%d, %d)", offset, value); + //debug(2, "localWrite8(%d, %d)", offset, value); _localData[offset] = value; } byte ScriptInterpreter::localRead8(int16 offset) { - //debug(1, "localRead8(%d) -> %d", offset, _localData[offset]); + //debug(2, "localRead8(%d) -> %d", offset, _localData[offset]); return _localData[offset]; } void ScriptInterpreter::localWrite16(int16 offset, int16 value) { - //debug(1, "localWrite16(%d, %d)", offset, value); + //debug(2, "localWrite16(%d, %d)", offset, value); WRITE_LE_UINT16(&_localData[offset], value); } int16 ScriptInterpreter::localRead16(int16 offset) { - //debug(1, "localRead16(%d) -> %d", offset, (int16)READ_LE_UINT16(&_localData[offset])); + //debug(2, "localRead16(%d) -> %d", offset, (int16)READ_LE_UINT16(&_localData[offset])); return (int16)READ_LE_UINT16(&_localData[offset]); } byte *ScriptInterpreter::localPtr(int16 offset) { - //debug(1, "localPtr(%d)", offset); + //debug(2, "localPtr(%d)", offset); return &_localData[offset]; } void ScriptInterpreter::saveState(Common::WriteStream *out) { - // Save registers out->writeUint16LE(_regs.reg0); out->writeUint16LE(_regs.reg1); @@ -708,11 +658,9 @@ void ScriptInterpreter::saveState(Common::WriteStream *out) { // Save IP out->writeUint16LE((int16)(_code - getSlotData(_regs.reg4))); - } void ScriptInterpreter::loadState(Common::ReadStream *in) { - // Load registers _regs.reg0 = in->readUint16LE(); _regs.reg1 = in->readUint16LE(); @@ -741,7 +689,6 @@ void ScriptInterpreter::loadState(Common::ReadStream *in) { // Load IP _code = getSlotData(_regs.reg4) + in->readUint16LE(); - } void ScriptInterpreter::sfNop() { @@ -755,7 +702,9 @@ void ScriptInterpreter::sfGetGameVar() { void ScriptInterpreter::sfSetGameVar() { int16 varIndex = arg16(3); - VarType varType = getGameVarType(varIndex); + assert(varIndex <= 21); + + VarType varType = varTypes[varIndex]; int16 value = 0; if (varType == vtByte) value = arg8(5); @@ -810,8 +759,7 @@ void ScriptInterpreter::sfSetDeltaAnimPalette() { } void ScriptInterpreter::sfSetUnkPaletteEffect() { - // TODO - debug("ScriptInterpreter::sfSetUnkPaletteEffect"); + error("ScriptInterpreter::sfSetUnkPaletteEffect called"); // unused } void ScriptInterpreter::sfBuildColorTransTable() { @@ -992,7 +940,8 @@ void ScriptInterpreter::sfStopShakeScreen() { void ScriptInterpreter::sfStartSequence() { int16 sequenceResIndex = arg16(3); - //debug("ScriptInterpreter::sfStartSequence(%d)", sequenceResIndex); + debug(1, "ScriptInterpreter::sfStartSequence(%d)", sequenceResIndex); + if (sequenceResIndex >= 0) { //_vm->_arc->dump(sequenceResIndex, "music"); // DEBUG: Dump music so we know what's in there @@ -1001,7 +950,6 @@ void ScriptInterpreter::sfStartSequence() { } void ScriptInterpreter::sfEndSequence() { - //debug("ScriptInterpreter::sfEndSequence"); _vm->_music->stopSequence(); } @@ -1029,9 +977,8 @@ void ScriptInterpreter::sfHandleInput() { if (_vm->_rightButtonDown) { keyCode = 1; } else { - /* Convert keyboard scancode to IBM PC scancode - Only scancodes known to be used (so far) are converted - */ + // Convert keyboard scancode to IBM PC scancode. + // Only scancodes known to be used (so far) are converted. switch (_vm->_keyState.keycode) { case Common::KEYCODE_ESCAPE: keyCode = 1; @@ -1050,11 +997,13 @@ void ScriptInterpreter::sfRunOptionsScreen() { _vm->showMenu(kMenuIdMain); } -/* NOTE: The opcodes sfPrecacheSprites, sfPrecacheSounds1, sfPrecacheSounds2 and - sfDeletePrecachedFiles were used by the original engine to handle precaching - of data so the game doesn't stall while playing (due to the slow speed of - CD-Drives back then). This is not needed in ScummVM since all supported - systems are fast enough to load data in-game. */ +/** + * NOTE: The opcodes sfPrecacheSprites, sfPrecacheSounds1, sfPrecacheSounds2 and + * sfDeletePrecachedFiles were used by the original engine to handle precaching + * of data so the game doesn't stall while playing (due to the slow speed of + * CD-Drives back then). This is not needed in ScummVM since all supported + * systems are fast enough to load data in-game. + */ void ScriptInterpreter::sfPrecacheSprites() { // See note above diff --git a/engines/toltecs/script.h b/engines/toltecs/script.h index 89dca4598f..4c880dfef5 100644 --- a/engines/toltecs/script.h +++ b/engines/toltecs/script.h @@ -49,7 +49,6 @@ public: byte *getSlotData(int slotIndex) const { return _slots[slotIndex].data; } - VarType getGameVarType(uint variable); int16 getGameVar(uint variable); void setGameVar(uint variable, int16 value); diff --git a/engines/toltecs/sound.cpp b/engines/toltecs/sound.cpp index 4b281392e5..8afc0e7890 100644 --- a/engines/toltecs/sound.cpp +++ b/engines/toltecs/sound.cpp @@ -103,8 +103,7 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa } } } else { - - if (type == -3) { + if (type == kChannelTypeSpeech) { // Stop speech and play new sound stopSpeech(); } @@ -137,10 +136,8 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa _vm->_mixer->playStream(soundType, &channels[freeChannel].handle, stream, -1, volume, panning); - } - - } - + } // if (freeChannel >= 0) + } // resIndex } void Sound::updateSpeech() { diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp index 9f3a10a03b..1a399dacc0 100644 --- a/engines/toltecs/toltecs.cpp +++ b/engines/toltecs/toltecs.cpp @@ -39,6 +39,7 @@ #include "toltecs/toltecs.h" #include "toltecs/animation.h" +#include "toltecs/console.h" #include "toltecs/menu.h" #include "toltecs/movie.h" #include "toltecs/music.h" @@ -62,6 +63,9 @@ struct GameSettings { }; ToltecsEngine::ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + // Assign default values to the config manager, in case settings are missing + ConfMan.registerDefault("originalsaveload", "false"); + _rnd = new Common::RandomSource("toltecs"); } @@ -123,6 +127,7 @@ Common::Error ToltecsEngine::run() { _menuSystem = new MenuSystem(this); _sound = new Sound(this); + _console = new Console(this); _cfgText = ConfMan.getBool("subtitles"); _cfgVoices = !ConfMan.getBool("speech_mute"); @@ -176,6 +181,7 @@ Common::Error ToltecsEngine::run() { _music->stopSequence(); _sound->stopAll(); + delete _console; delete _arc; delete _res; delete _screen; @@ -215,7 +221,6 @@ void ToltecsEngine::requestLoadgame(int slotNum) { } void ToltecsEngine::loadScene(uint resIndex) { - Resource *sceneResource = _res->load(resIndex); byte *scene = sceneResource->data; @@ -250,13 +255,10 @@ void ToltecsEngine::loadScene(uint resIndex) { _screen->_fullRefresh = true; _screen->_renderQueue->clear(); - } void ToltecsEngine::updateScreen() { - _sound->updateSpeech(); - _screen->updateShakeScreen(); // TODO: Set quit flag @@ -289,7 +291,6 @@ void ToltecsEngine::updateScreen() { _counter02 = (currUpdateTime - prevUpdateTime) / 13; } while (_counter02 == 0); prevUpdateTime = currUpdateTime; - } void ToltecsEngine::drawScreen() { @@ -310,6 +311,7 @@ void ToltecsEngine::drawScreen() { _screen->_guiRefresh = false; } + _console->onFrame(); _system->updateScreen(); _system->delayMillis(10); @@ -317,7 +319,6 @@ void ToltecsEngine::drawScreen() { } void ToltecsEngine::updateInput() { - Common::Event event; Common::EventManager *eventMan = _system->getEventManager(); while (eventMan->pollEvent(event)) { @@ -327,6 +328,9 @@ void ToltecsEngine::updateInput() { //debug("key: flags = %02X; keycode = %d", _keyState.flags, _keyState.keycode); + if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) + _console->attach(); + switch (event.kbd.keycode) { case Common::KEYCODE_F5: showMenu(kMenuIdSave); @@ -350,9 +354,6 @@ void ToltecsEngine::updateInput() { case Common::EVENT_KEYUP: _keyState.reset(); break; - case Common::EVENT_QUIT: - quitGame(); - break; case Common::EVENT_MOUSEMOVE: _mouseX = event.mouse.x; _mouseY = event.mouse.y; @@ -408,9 +409,7 @@ void ToltecsEngine::updateInput() { _mouseWaitForRelease = false; _mouseButton = 0; } - } - } void ToltecsEngine::setGuiHeight(int16 guiHeight) { @@ -478,7 +477,6 @@ void ToltecsEngine::scrollCameraRight(int16 delta) { } void ToltecsEngine::updateCamera() { - if (_cameraX != _newCameraX) { _cameraX = _newCameraX; _screen->_fullRefresh = true; @@ -492,13 +490,16 @@ void ToltecsEngine::updateCamera() { } //debug(0, "ToltecsEngine::updateCamera() _cameraX = %d; _cameraY = %d", _cameraX, _cameraY); - } void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) { - byte *scanData = _script->getSlotData(slotIndex) + slotOffset; + // If there's another talk text at the requested slot and it's still + // active, don't overwrite it. Fixes bug #3600166. + if (_screen->isTalkTextActive(slotIndex)) + return; + while (*scanData < 0xF0) { if (*scanData == 0x19) { scanData++; @@ -518,19 +519,18 @@ void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) { debug(0, "ToltecsEngine::talk() playSound(resIndex: %d)", resIndex); _sound->playSpeech(resIndex); } + if (_doText) { - _screen->updateTalkText(slotIndex, slotOffset); + _screen->updateTalkText(slotIndex, slotOffset, false); } else { _screen->keepTalkTextItemsAlive(); } } else { - _screen->updateTalkText(slotIndex, slotOffset); + _screen->updateTalkText(slotIndex, slotOffset, true); } - } void ToltecsEngine::walk(byte *walkData) { - int16 xdelta, ydelta, v8, v10, v11; int16 xstep, ystep; ScriptWalk walkInfo; @@ -613,7 +613,6 @@ void ToltecsEngine::walk(byte *walkData) { WRITE_LE_UINT16(walkData + 14, walkInfo.xerror); WRITE_LE_UINT16(walkData + 16, walkInfo.mulValue); WRITE_LE_UINT16(walkData + 18, walkInfo.scaling); - } int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize, diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h index b95a4f77cb..0be2d2a646 100644 --- a/engines/toltecs/toltecs.h +++ b/engines/toltecs/toltecs.h @@ -42,6 +42,7 @@ struct ToltecsGameDescription; class AnimationPlayer; class ArchiveReader; +class Console; class Input; class MenuSystem; class MoviePlayer; @@ -144,6 +145,7 @@ public: AnimationPlayer *_anim; ArchiveReader *_arc; + Console *_console; Input *_input; MenuSystem *_menuSystem; MoviePlayer *_moviePlayer; diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp index 23c655e35a..f5c580c8c5 100644 --- a/engines/tony/custom.cpp +++ b/engines/tony/custom.cpp @@ -154,7 +154,6 @@ void rightToMe(CORO_PARAM, uint32, uint32, uint32, uint32) { GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDRIGHT); } - void tonySetPerorate(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) { g_vm->getEngine()->setPerorate(bStatus); } @@ -176,7 +175,6 @@ void setAlwaysDisplay(CORO_PARAM, uint32 val, uint32, uint32, uint32) { GLOBALS._bAlwaysDisplay = (val != 0); } - void setPointer(CORO_PARAM, uint32 dwPointer, uint32, uint32, uint32) { switch (dwPointer) { case 1: @@ -215,7 +213,6 @@ VoiceHeader *searchVoiceHeader(uint32 codehi, uint32 codelo) { return NULL; } - void sendTonyMessage(CORO_PARAM, uint32 dwMessage, uint32 nX, uint32 nY, uint32) { CORO_BEGIN_CONTEXT; RMMessage msg; @@ -337,7 +334,6 @@ void changeBoxStatus(CORO_PARAM, uint32 nLoc, uint32 nBox, uint32 nStatus, uint3 GLOBALS._boxes->changeBoxStatus(nLoc, nBox, nStatus); } - void custLoadLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { CORO_BEGIN_CONTEXT; uint32 h; @@ -360,7 +356,6 @@ void custLoadLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUse CORO_END_CODE; } - void sendFullscreenMsgStart(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) { CORO_BEGIN_CONTEXT; RMMessage *msg; @@ -485,7 +480,6 @@ void closeLocation(CORO_PARAM, uint32, uint32, uint32, uint32) { CORO_END_CODE; } - void changeLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { CORO_BEGIN_CONTEXT; uint32 h; @@ -639,12 +633,10 @@ void tonyGenericPut2(CORO_PARAM, uint32 nDirection) { CORO_END_CODE; } - void tonyTakeUp1(CORO_PARAM, uint32, uint32, uint32, uint32) { tonyGenericTake1(coroParam, 0); } - void tonyTakeMid1(CORO_PARAM, uint32, uint32, uint32, uint32) { tonyGenericTake1(coroParam, 1); } @@ -657,7 +649,6 @@ void tonyTakeUp2(CORO_PARAM, uint32, uint32, uint32, uint32) { tonyGenericTake2(coroParam, 0); } - void tonyTakeMid2(CORO_PARAM, uint32, uint32, uint32, uint32) { tonyGenericTake2(coroParam, 1); } @@ -690,7 +681,6 @@ void tonyPutDown2(CORO_PARAM, uint32, uint32, uint32, uint32) { tonyGenericPut2(coroParam, 2); } - void tonyOnTheFloor(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) { if (dwParte == 0) GLOBALS._tony->setPattern(GLOBALS._tony->PAT_ONTHEFLOORLEFT); @@ -1032,7 +1022,6 @@ void tonyScaredEnd(CORO_PARAM, uint32, uint32, uint32, uint32) { CORO_END_CODE; } - void tonyDisgusted(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) { tonySetNumTexts(dwText); GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_DISGUSTED; @@ -1101,7 +1090,6 @@ void tonyMacbeth(CORO_PARAM, uint32 nPos, uint32, uint32, uint32) { } } - void enableTony(CORO_PARAM, uint32, uint32, uint32, uint32) { GLOBALS._tony->show(); } @@ -1125,7 +1113,6 @@ void waitForPatternEnd(CORO_PARAM, uint32 nItem, uint32, uint32, uint32) { CORO_END_CODE; } - void setTonyPosition(CORO_PARAM, uint32 nX, uint32 nY, uint32 nLoc, uint32) { GLOBALS._tony->setPosition(RMPoint(nX, nY), nLoc); } @@ -1252,17 +1239,14 @@ void syncScrollLocation(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) _ctx->pt._y += (_ctx->dimy * _ctx->dwCurTime) / _ctx->dwTotalTime; else _ctx->pt._y -= (_ctx->dimy * _ctx->dwCurTime) / _ctx->dwTotalTime; - } CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE); GLOBALS._loc->setScrollPosition(_ctx->pt); GLOBALS._tony->setScrollPosition(_ctx->pt); - } - // Set the position finale if (sX) { if (_ctx->lx > 0) @@ -1282,7 +1266,6 @@ void syncScrollLocation(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) CORO_END_CODE; } - void changeHotspot(CORO_PARAM, uint32 dwCode, uint32 nX, uint32 nY, uint32) { int i; @@ -1304,13 +1287,13 @@ void changeHotspot(CORO_PARAM, uint32 dwCode, uint32 nX, uint32 nY, uint32) { GLOBALS._loc->getItemFromCode(dwCode)->changeHotspot(RMPoint(nX, nY)); } - void autoSave(CORO_PARAM, uint32, uint32, uint32, uint32) { g_vm->autoSave(coroParam); } void abortGame(CORO_PARAM, uint32, uint32, uint32, uint32) { - error("script called abortGame"); + debug(1, "script called abortGame"); + g_vm->quitGame(); } void shakeScreen(CORO_PARAM, uint32 nScosse, uint32, uint32, uint32) { @@ -1476,7 +1459,6 @@ void charSendMessage(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, _ctx->voice = NULL; } - GLOBALS._curBackText = NULL; delete _ctx->text; } @@ -1504,7 +1486,6 @@ void changeInventoryStatus(CORO_PARAM, uint32 dwCode, uint32 dwStatus, uint32, u GLOBALS._inventory->changeItemStatus(dwCode, dwStatus); } - /* * Master Characters */ @@ -1535,7 +1516,6 @@ void mCharResetCode(CORO_PARAM, uint32 nChar, uint32, uint32, uint32) { GLOBALS._mCharacter[nChar]._item = GLOBALS._loc->getItemFromCode(GLOBALS._mCharacter[nChar]._code); } - void mCharSetPosition(CORO_PARAM, uint32 nChar, uint32 nX, uint32 nY, uint32) { assert(nChar < 10); GLOBALS._mCharacter[nChar]._x = nX; @@ -1879,7 +1859,6 @@ void sendDialogMessage(CORO_PARAM, uint32 nPers, uint32 nMsg, uint32, uint32) { CORO_END_CODE; } - // @@@@ This cannot be skipped!!!!!!!!!!!!!!!!!!! void startDialog(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) { @@ -1960,7 +1939,6 @@ void startDialog(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) CORO_END_CODE; } - /* * Sync between idle and mpal */ @@ -2270,7 +2248,6 @@ void doCredits(CORO_PARAM, uint32 nMsg, uint32 dwTime, uint32, uint32) { _ctx->text[_ctx->i].setPosition(RMPoint(260, 70 + _ctx->i * 26)); } - // Set the position _ctx->text[_ctx->i].setAlwaysDisplay(); _ctx->text[_ctx->i].setForcedTime(dwTime * 1000); @@ -2521,8 +2498,6 @@ void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation GLOBALS._ambiance[58] = AMBIANCE_WIND; GLOBALS._ambiance[60] = AMBIANCE_WIND; - - // Create an event for the idle skipping GLOBALS._hSkipIdle = CoroScheduler.createEvent(true, false); } diff --git a/engines/tony/debugger.cpp b/engines/tony/debugger.cpp index 85d9469519..84f05b0d25 100644 --- a/engines/tony/debugger.cpp +++ b/engines/tony/debugger.cpp @@ -77,7 +77,6 @@ void DebugChangeScene(CORO_PARAM, const void *param) { CORO_END_CODE; } - /** * This command loads up the specified new scene number */ diff --git a/engines/tony/detection.cpp b/engines/tony/detection.cpp index 8e6d5a64c3..1094950e2c 100644 --- a/engines/tony/detection.cpp +++ b/engines/tony/detection.cpp @@ -90,7 +90,7 @@ public: bool TonyMetaEngine::hasFeature(MetaEngineFeature f) const { return - (f == kSupportsListSaves) || + (f == kSupportsListSaves) || (f == kSupportsLoadingDuringStartup) || (f == kSupportsDeleteSave) || (f == kSavesSupportMetaInfo) || @@ -186,7 +186,6 @@ SaveStateDescriptor TonyMetaEngine::querySaveMetaInfos(const char *target, int s return SaveStateDescriptor(); } - #if PLUGIN_ENABLED_DYNAMIC(TONY) REGISTER_PLUGIN_DYNAMIC(TONY, PLUGIN_TYPE_ENGINE, TonyMetaEngine); #else diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h index ce3ab01a9f..ee137927dc 100644 --- a/engines/tony/detection_tables.h +++ b/engines/tony/detection_tables.h @@ -75,6 +75,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough French "Collection Aventure" provided by Strangerke { @@ -91,6 +92,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough German "Shoe Box" provided by Strangerke { @@ -107,6 +109,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough Italian provided by Fabio Barzagli { @@ -123,6 +126,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough Italian provided by Giovanni Bajo { @@ -139,6 +143,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough Polish provided by Fabio Barzagli { @@ -155,6 +160,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough German "Gamestar" provided in bug #3566035 { @@ -171,6 +177,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { // Tony Tough Czech provided in bug #3565765 { @@ -188,6 +195,7 @@ static const TonyGameDescription gameDescriptions[] = { GUIO1(GUIO_NONE) }, }, + { AD_TABLE_END_MARKER } }; diff --git a/engines/tony/font.cpp b/engines/tony/font.cpp index fa018b4464..1729052d42 100644 --- a/engines/tony/font.cpp +++ b/engines/tony/font.cpp @@ -81,7 +81,6 @@ void RMFont::unload() { } } - RMGfxPrimitive *RMFont::makeLetterPrimitive(byte bChar, int &nLength) { RMFontPrimitive *prim; @@ -223,7 +222,6 @@ void RMFontDialog::init() { } } - /***************************************************************************\ * RMFontMacc Methods \****************************************************************************/ @@ -278,8 +276,6 @@ void RMFontCredits::init() { } } - - /***************************************************************************\ * RMFontObj Methods \****************************************************************************/ @@ -544,7 +540,6 @@ void RMText::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { else if (_aHorType == HRIGHT) prim->getDst().topLeft() -= RMPoint(_dimx, 0); - // Vertically if (_aVerType == VTOP) { @@ -627,7 +622,6 @@ void RMTextDialog::writeText(const Common::String &text, RMFontColor *font, int *time = _time; } - void RMTextDialog::setSkipStatus(bool bEnabled) { _bSkipStatus = bEnabled; } @@ -685,6 +679,7 @@ void RMTextDialog::removeThis(CORO_PARAM, bool &result) { } } } + // Erase the background else if (!(GLOBALS._bCfgDubbing && _hCustomSkip2 != CORO_INVALID_PID_VALUE)) { if (!_bForceNoTime) { @@ -805,7 +800,6 @@ void RMTextDialogScrolling::clipOnScreen(RMGfxPrimitive *prim) { // We must not do anything! } - /****************************************************************************\ * RMTextItemName Methods \****************************************************************************/ @@ -866,7 +860,6 @@ void RMTextItemName::doFrame(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMLocation & CORO_END_CODE; } - void RMTextItemName::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -952,7 +945,6 @@ void RMDialogChoice::init() { setPriority(140); } - void RMDialogChoice::close() { if (_drawedStrings != NULL) { delete[] _drawedStrings; @@ -1116,7 +1108,6 @@ void RMDialogChoice::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive CORO_END_CODE; } - void RMDialogChoice::hide(CORO_PARAM) { CORO_BEGIN_CONTEXT; int deltay; @@ -1145,7 +1136,6 @@ void RMDialogChoice::hide(CORO_PARAM) { CORO_END_CODE; } - void RMDialogChoice::removeThis(CORO_PARAM, bool &result) { result = _bRemoveFromOT; } diff --git a/engines/tony/font.h b/engines/tony/font.h index 13c1ddf268..9ef50b99ec 100644 --- a/engines/tony/font.h +++ b/engines/tony/font.h @@ -104,7 +104,6 @@ public: int stringLen(char bChar, char bNext = 0); }; - class RMFontColor : public virtual RMFont { private: byte _fontR, _fontG, _fontB; @@ -115,7 +114,6 @@ public: virtual void setBaseColor(byte r, byte g, byte b); }; - class RMFontWithTables : public virtual RMFont { protected: int _cTable[256]; @@ -136,7 +134,6 @@ public: virtual ~RMFontWithTables() {} }; - class RMFontDialog : public RMFontColor, public RMFontWithTables { public: void init(); @@ -175,16 +172,16 @@ private: public: enum HorAlign { - HLEFT, - HLEFTPAR, - HCENTER, - HRIGHT + HLEFT, + HLEFTPAR, + HCENTER, + HRIGHT }; enum VerAlign { - VTOP, - VCENTER, - VBOTTOM + VTOP, + VCENTER, + VBOTTOM }; private: @@ -293,7 +290,6 @@ public: virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim); }; - /** * Manages the name of a selected item on the screen */ @@ -319,7 +315,6 @@ public: virtual void removeThis(CORO_PARAM, bool &result); }; - /** * Manages the selection of screen items in a box */ diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp index 42ace987b4..501a588ff5 100644 --- a/engines/tony/game.cpp +++ b/engines/tony/game.cpp @@ -164,7 +164,6 @@ RMOptionSlide::RMOptionSlide(const RMPoint &pt, int nRange, int nStartValue, int _pushRight = new RMOptionButton(RMRect(pt._x + _nSlideSize, pt._y, pt._x + _nSlideSize + 5 + 22, pt._y + 26)); } - RMOptionSlide::~RMOptionSlide() { delete _sliderCenter; _sliderCenter = NULL; @@ -973,7 +972,6 @@ void RMOptionScreen::doFrame(CORO_PARAM, RMInput *input) { CORO_BEGIN_CODE(_ctx); - // If it is not fully open, do nothing if (_fadeStep != 6) return; @@ -1043,8 +1041,8 @@ void RMOptionScreen::doFrame(CORO_PARAM, RMInput *input) { } } -#define KEYPRESS(c) (g_vm->getEngine()->getInput().getAsyncKeyState(c)) -#define PROCESS_CHAR(cod, c) if (KEYPRESS(cod)) { \ +#define KEYPRESS(c) (g_vm->getEngine()->getInput().getAsyncKeyState(c)) +#define PROCESS_CHAR(cod, c) if (KEYPRESS(cod)) { \ _editName[strlen(_editName) + 1] = '\0'; _editName[strlen(_editName)] = c; _ctx->bRefresh = true; } // State Buttons @@ -1058,7 +1056,7 @@ void RMOptionScreen::doFrame(CORO_PARAM, RMInput *input) { for (_ctx->i = 0; _ctx->i < 26 && strlen(_editName) < 12; _ctx->i++) { if (KEYPRESS(Common::KEYCODE_LSHIFT) || - KEYPRESS(Common::KEYCODE_RSHIFT)) { + KEYPRESS(Common::KEYCODE_RSHIFT)) { PROCESS_CHAR((Common::KeyCode)((int)'a' + _ctx->i), _ctx->i + 'A'); } else { PROCESS_CHAR((Common::KeyCode)((int)'a' + _ctx->i), _ctx->i + 'a'); @@ -1222,7 +1220,6 @@ void RMOptionScreen::doFrame(CORO_PARAM, RMInput *input) { CORO_END_CODE; } - void RMOptionScreen::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { CORO_BEGIN_CONTEXT; int curTime; @@ -1233,7 +1230,7 @@ void RMOptionScreen::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive _ctx->curTime = g_vm->getTime(); #define FADE_SPEED 20 -#define SYNC (_ctx->curTime - _fadeTime) / 25 +#define SYNC (_ctx->curTime - _fadeTime) / 25 if (_bExit) return; @@ -1334,7 +1331,6 @@ void RMOptionScreen::removeThis(CORO_PARAM, bool &result) { result = false; } - bool RMOptionScreen::loadThumbnailFromSaveState(int nState, byte *lpDestBuf, Common::String &name, byte &diff) { char namebuf[256]; Common::InSaveFile *f; diff --git a/engines/tony/game.h b/engines/tony/game.h index 83a1ddaea1..fdf62a2a5d 100644 --- a/engines/tony/game.h +++ b/engines/tony/game.h @@ -324,7 +324,6 @@ public: static bool loadThumbnailFromSaveState(int numState, byte *lpDestBuf, Common::String &name, byte &diff); protected: - // Initialization and state change void initState(CORO_PARAM); void closeState(); diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp index 04ce01b0ed..dc82c78ee5 100644 --- a/engines/tony/gfxcore.cpp +++ b/engines/tony/gfxcore.cpp @@ -69,7 +69,6 @@ void RMGfxTaskSetPrior::setPriority(int nPrior) { _nPrior = nPrior; } - /****************************************************************************\ * RMGfxBuffer Methods \****************************************************************************/ @@ -109,7 +108,6 @@ void RMGfxBuffer::offsetY(int nLines, int nBpp) { _buf += nLines * getDimx() * nBpp / 8; } - RMGfxBuffer::operator byte *() { return _buf; } @@ -130,7 +128,6 @@ int RMGfxBuffer::getDimy() { return _dimy; } - /****************************************************************************\ * RMGfxSourceBuffer Methods \****************************************************************************/ @@ -223,7 +220,6 @@ void RMGfxSourceBuffer::offsetY(int nLines) { \****************************************************************************/ RMGfxWoodyBuffer::~RMGfxWoodyBuffer() { - } void RMGfxWoodyBuffer::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { @@ -242,7 +238,6 @@ void RMGfxWoodyBuffer::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitiv } RMGfxWoodyBuffer::RMGfxWoodyBuffer() { - } RMGfxWoodyBuffer::RMGfxWoodyBuffer(int dimx, int dimy) @@ -487,7 +482,6 @@ bool RMGfxTargetBuffer::getTrackDirtyRects() const { \****************************************************************************/ RMGfxSourceBufferPal::~RMGfxSourceBufferPal() { - } int RMGfxSourceBufferPal::loadPaletteWA(const byte *buf, bool bSwapped) { @@ -567,7 +561,6 @@ RMGfxSourceBuffer4::RMGfxSourceBuffer4(int dimx, int dimy) setPriority(0); } - /** * Returns the number of bits per pixel of the surface * @@ -586,11 +579,10 @@ void RMGfxSourceBuffer4::create(int dimx, int dimy) { \****************************************************************************/ RMGfxSourceBuffer8::~RMGfxSourceBuffer8() { - } void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { - int width, height, u, v; + int width = 0, height = 0, u = 0, v = 0; int bufx = bigBuf.getDimx(); uint16 *buf = bigBuf; byte *raw = _buf; @@ -659,7 +651,6 @@ RMGfxSourceBuffer8::RMGfxSourceBuffer8(bool bTrasp0) { _bTrasp0 = bTrasp0; } - /** * Returns the number of bits per pixel of the surface * @@ -677,13 +668,11 @@ void RMGfxSourceBuffer8::create(int dimx, int dimy) { #define GETGREEN(x) (((x) >> 5) & 0x1F) #define GETBLUE(x) ((x) & 0x1F) - /****************************************************************************\ * RMGfxSourceBuffer8AB Methods \****************************************************************************/ RMGfxSourceBuffer8AB::~RMGfxSourceBuffer8AB() { - } int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) { @@ -703,9 +692,8 @@ int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) { return (r << 10) | (g << 5) | b; } - void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { - int width, height, u, v; + int width = 0, height = 0, u = 0, v = 0; int bufx = bigBuf.getDimx(); uint16 *buf = bigBuf; byte *raw = _buf; @@ -765,8 +753,6 @@ void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrim bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height)); } - - /****************************************************************************\ * RMGfxSourceBuffer8RLE Methods \****************************************************************************/ @@ -792,7 +778,6 @@ RMGfxSourceBuffer8RLE::~RMGfxSourceBuffer8RLE() { } } - int RMGfxSourceBuffer8RLE::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) { return RMGfxSourceBufferPal::init(buf, dimx, dimy, bLoadPalette); } @@ -967,7 +952,6 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri } } - /****************************************************************************\ * RMGfxSourceBuffer8RLEByte Methods \****************************************************************************/ @@ -1050,7 +1034,6 @@ void RMGfxSourceBuffer8RLEByte::rleDecompressLine(uint16 *dst, byte *src, int nS src += n; } - while (1) { RLEByteDoTrasp: // Get the trasp of s**t @@ -1155,7 +1138,6 @@ void RMGfxSourceBuffer8RLEByte::rleDecompressLineFlipped(uint16 *dst, byte *src, src += n; } - while (1) { RLEByteFlippedDoTrasp: // Get the trasp of s**t @@ -1212,13 +1194,11 @@ RLEByteFlippedDoCopy2: } } - /****************************************************************************\ * RMGfxSourceBuffer8RLEWord Methods \****************************************************************************/ RMGfxSourceBuffer8RLEWord::~RMGfxSourceBuffer8RLEWord() { - } void RMGfxSourceBuffer8RLEWord::rleWriteTrasp(byte *&cur, int rep) { @@ -1299,7 +1279,6 @@ void RMGfxSourceBuffer8RLEWord::rleDecompressLine(uint16 *dst, byte *src, int nS src += n; } - while (1) { RLEWordDoTrasp: // Get the trasp of s**t @@ -1321,7 +1300,6 @@ RLEWordDoAlpha: src += 2; RLEWordDoAlpha2: - if (n > nLength) n = nLength; @@ -1360,7 +1338,6 @@ RLEWordDoCopy2: return; assert(nLength > 0); - } } @@ -1416,7 +1393,6 @@ void RMGfxSourceBuffer8RLEWord::rleDecompressLineFlipped(uint16 *dst, byte *src, src += n; } - while (1) { RLEWordFlippedDoTrasp: // Get the trasp of s**t @@ -1438,7 +1414,6 @@ RLEWordFlippedDoAlpha: src += 2; RLEWordFlippedDoAlpha2: - if (n > nLength) n = nLength; @@ -1485,7 +1460,6 @@ RLEWordFlippedDoCopy2: \****************************************************************************/ RMGfxSourceBuffer8RLEWordAB::~RMGfxSourceBuffer8RLEWordAB() { - } void RMGfxSourceBuffer8RLEWordAB::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) { @@ -1545,7 +1519,6 @@ void RMGfxSourceBuffer8RLEWordAB::rleDecompressLine(uint16 *dst, byte *src, int src += n; } - while (1) { RLEWordDoTrasp: // Get the trasp of s**t @@ -1567,7 +1540,6 @@ RLEWordDoAlpha: src += 2; RLEWordDoAlpha2: - if (n > nLength) n = nLength; @@ -1651,9 +1623,9 @@ void RMGfxSourceBuffer8AA::calculateAA() { for (int x = 0; x < _dimx; x++) { if (*src == 0) { if ((y > 0 && src[-_dimx] != 0) || - (y < _dimy - 1 && src[_dimx] != 0) || - (x > 0 && src[-1] != 0) || - (x < _dimx - 1 && src[1] != 0)) + (y < _dimy - 1 && src[_dimx] != 0) || + (x > 0 && src[-1] != 0) || + (x < _dimx - 1 && src[1] != 0)) *srcaa = 1; } @@ -1668,9 +1640,9 @@ void RMGfxSourceBuffer8AA::calculateAA() { for (int x = 0; x < _dimx; x++) { if (*src != 0) { if ((y > 0 && srcaa[-_dimx] == 1) || - (y < _dimy - 1 && srcaa[_dimx] == 1) || - (x > 0 && srcaa[-1] == 1) || - (x < _dimx - 1 && srcaa[1] == 1)) + (y < _dimy - 1 && srcaa[_dimx] == 1) || + (x > 0 && srcaa[-1] == 1) || + (x < _dimx - 1 && srcaa[1] == 1)) *srcaa = 2; } @@ -1713,7 +1685,6 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri src += READ_LE_UINT16(src); // Eliminate horizontal clipping - if (prim->isFlipped()) { u = _dimx - (width + u); x1 = (prim->getDst()._x1 + _dimx - 1) - u; @@ -1728,9 +1699,8 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height)); } -// width = _dimx; -// x1 = prim->Dst().x1; - + //width = _dimx; + //x1 = prim->Dst().x1; // Position into the destination buffer buf = bigBuf; @@ -1821,8 +1791,6 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri } } - - void RMGfxSourceBuffer8AA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -1911,7 +1879,6 @@ void RMGfxSourceBuffer8RLEWordAA::init(Common::ReadStream &ds, int dimx, int dim } } - /****************************************************************************\ * RMGfxSourceBuffer16 Methods \****************************************************************************/ @@ -1984,7 +1951,7 @@ void RMGfxSourceBuffer16::prepareImage() { uint16 *buf = (uint16 *)_buf; for (int i = 0; i < _dimx * _dimy; i++) - WRITE_LE_UINT16(&buf[i], FROM_LE_16(buf[i]) & 0x7FFF); + buf[i] = FROM_LE_16(buf[i]) & 0x7FFF; } RMGfxSourceBuffer16::RMGfxSourceBuffer16(int dimx, int dimy) @@ -2041,7 +2008,6 @@ void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) bigBuf.addDirtyRect(rcDst); } - /****************************************************************************\ * RMGfxClearTask Methods \****************************************************************************/ diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h index f0deed83ee..1bacf7e5a9 100644 --- a/engines/tony/gfxcore.h +++ b/engines/tony/gfxcore.h @@ -52,7 +52,6 @@ class RMGfxSourceBuffer16; // Source class RMGfxWoodyBuffer; // Source16+Target class RMGfxClearTask; // Task - /** * Graphics buffer */ @@ -126,7 +125,6 @@ public: virtual RMGfxPrimitive *duplicate(); }; - /** * Graphic drawing task */ @@ -149,7 +147,6 @@ public: virtual void unregister(); }; - /** * Graphic drawing with priority */ @@ -159,7 +156,6 @@ public: void setPriority(int nPrior); }; - /** * Task that cleans the destination buffer */ @@ -172,7 +168,6 @@ public: virtual void removeThis(CORO_PARAM, bool &result); }; - /** * Task that draws a colored box */ @@ -188,7 +183,6 @@ public: virtual void removeThis(CORO_PARAM, bool &result); }; - /** * Buffer source for the design, which is a task. This is an abstract base. */ @@ -210,7 +204,6 @@ public: virtual int getBpp() = 0; }; - /** * 16-bit color source */ @@ -231,7 +224,6 @@ public: virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim); }; - /** * Buffer source with palette */ @@ -256,7 +248,6 @@ public: int loadPalette(const byte *buf); }; - /** * Buffer source with a 256 color palette */ @@ -276,7 +267,6 @@ public: virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim); }; - /** * Buffer source with a 256 color palette, and alpha blending */ @@ -289,7 +279,6 @@ public: virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim); }; - /** * Buffer source with a 256 color palette, RLE compressed */ @@ -370,7 +359,6 @@ public: virtual ~RMGfxSourceBuffer8RLEWordAB(); }; - /** * Buffer source with a 256 color palette, with anti-aliasing */ @@ -397,7 +385,6 @@ public: virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim); }; - class RMGfxSourceBuffer8RLEByteAA : public RMGfxSourceBuffer8RLEByte, public RMGfxSourceBuffer8AA { protected: void prepareImage(); @@ -426,7 +413,6 @@ public: virtual ~RMGfxSourceBuffer8RLEWordAA(); }; - /** * Source buffer with 16 colors */ @@ -442,7 +428,6 @@ public: virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim); }; - /** * Destination buffer which manages its own internal list of tasks */ @@ -464,7 +449,7 @@ private: void mergeDirtyRects(); private: -// OSystem::MutexRef csModifyingOT; + //OSystem::MutexRef csModifyingOT; protected: OTList *_otlist; @@ -498,7 +483,6 @@ public: bool getTrackDirtyRects() const; }; - /** * Ring buffer, which is both source and by destination */ diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp index c81e553770..cb27e20ab1 100644 --- a/engines/tony/gfxengine.cpp +++ b/engines/tony/gfxengine.cpp @@ -35,7 +35,6 @@ namespace Tony { - /****************************************************************************\ * RMGfxEngine Methods \****************************************************************************/ @@ -261,7 +260,6 @@ SKIPCLICKSINISTRO: } } - // Right Release // ************* if (_input.mouseRightReleased()) { diff --git a/engines/tony/globals.h b/engines/tony/globals.h index d8d8d3eba5..0ff243b374 100644 --- a/engines/tony/globals.h +++ b/engines/tony/globals.h @@ -63,6 +63,7 @@ struct CharacterStruct { f->writeUint32LE(_endTalkPattern); f->writeUint32LE(_numTexts); } + void load(Common::InSaveFile *f) { _code = f->readUint32LE(); f->readUint32LE(); @@ -106,6 +107,7 @@ struct MCharacterStruct { f->writeUint32LE(_curTalk); f->writeByte(_bAlwaysBack); } + void load(Common::InSaveFile *f) { _code = f->readUint32LE(); f->readUint32LE(); @@ -134,6 +136,7 @@ struct ChangedHotspotStruct { f->writeUint32LE(_nX); f->writeUint32LE(_nY); } + void load(Common::InSaveFile *f) { _dwCode = f->readUint32LE(); _nX = f->readUint32LE(); @@ -141,7 +144,6 @@ struct ChangedHotspotStruct { } }; - /** * Description of a call to a custom function. */ @@ -150,7 +152,7 @@ typedef struct { int _arg1, _arg2, _arg3, _arg4; } CfCall; -typedef CfCall *LpCfCall; +typedef CfCall *LpCfCall; struct CoroutineMutex { CoroutineMutex() : _eventId(0), _ownerPid(0), _lockCount(0) { } @@ -173,20 +175,20 @@ public: Common::String _nextMusic; bool _nextLoop; - int _nextChannel; - int _nextSync; - int _curChannel; - int _flipflop; + int _nextChannel; + int _nextSync; + int _curChannel; + int _flipflop; CharacterStruct _character[16]; MCharacterStruct _mCharacter[10]; ChangedHotspotStruct _changedHotspot[256]; bool _isMChar[16]; bool _bAlwaysDisplay; RMPoint _saveTonyPos; - int _saveTonyLoc; + int _saveTonyLoc; RMTextDialog *_curBackText; bool _bTonyIsSpeaking; - int _curChangedHotspot; + int _curChangedHotspot; bool _bCfgInvLocked; bool _bCfgInvNoScroll; bool _bCfgTimerizedText; @@ -199,16 +201,16 @@ public: bool _bCfgDubbing; bool _bCfgMusic; bool _bCfgSFX; - int _nCfgTonySpeed; - int _nCfgTextSpeed; - int _nCfgDubbingVolume; - int _nCfgMusicVolume; - int _nCfgSFXVolume; + int _nCfgTonySpeed; + int _nCfgTextSpeed; + int _nCfgDubbingVolume; + int _nCfgMusicVolume; + int _nCfgSFXVolume; bool _bSkipSfxNoLoop; bool _bIdleExited; bool _bNoBullsEye; - int _curDialog; - int _curSoundEffect; + int _curDialog; + int _curSoundEffect; bool _bFadeOutStop; RMTony *_tony; diff --git a/engines/tony/input.cpp b/engines/tony/input.cpp index b96ccaf842..e84da04d97 100644 --- a/engines/tony/input.cpp +++ b/engines/tony/input.cpp @@ -32,20 +32,8 @@ namespace Tony { RMInput::RMInput() { - // Setup mouse fields - _clampMouse = false; - _mousePos.set(0, 0); - _leftButton = _rightButton = false; _leftClickMouse = _leftReleaseMouse = false; _rightClickMouse = _rightReleaseMouse = false; - - Common::fill((byte *)&_event, (byte *)&_event + sizeof(Common::Event), 0); - - // Setup keyboard fields - Common::fill(&_keyDown[0], &_keyDown[350], 0); -} - -RMInput::~RMInput() { } void RMInput::poll() { @@ -59,19 +47,15 @@ void RMInput::poll() { case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONDOWN: case Common::EVENT_RBUTTONUP: - _mousePos.set(_event.mouse.x, _event.mouse.y); + _mousePos = _event.mouse; if (_event.type == Common::EVENT_LBUTTONDOWN) { - _leftButton = true; _leftClickMouse = true; } else if (_event.type == Common::EVENT_LBUTTONUP) { - _leftButton = false; _leftReleaseMouse = true; } else if (_event.type == Common::EVENT_RBUTTONDOWN) { - _rightButton = true; _rightClickMouse = true; } else if (_event.type == Common::EVENT_RBUTTONUP) { - _rightButton = false; _rightReleaseMouse = true; } else continue; @@ -87,12 +71,17 @@ void RMInput::poll() { g_vm->_debugger->onFrame(); } else { // Flag the given key as being down - _keyDown[(int)_event.kbd.keycode] = true; + _keyDown.push_back(_event.kbd.keycode); } return; case Common::EVENT_KEYUP: - _keyDown[(int)_event.kbd.keycode] = false; + for (uint i = 0; i < _keyDown.size(); i++) { + if (_keyDown[i] == _event.kbd.keycode) { + _keyDown.remove_at(i); + break; + } + } return; default: @@ -101,30 +90,27 @@ void RMInput::poll() { } } -bool RMInput::mouseLeft() { - return _leftButton; -} - -bool RMInput::mouseRight() { - return _rightButton; -} - /** * Return true if a key has been pressed */ bool RMInput::getAsyncKeyState(Common::KeyCode kc) { // The act of testing for a particular key automatically clears the state, to prevent // the same key being registered in multiple different frames - bool result = _keyDown[(int)kc]; - _keyDown[(int)kc] = false; - return result; + for (uint i = 0; i < _keyDown.size(); i++) { + if (_keyDown[i] == kc) { + _keyDown.remove_at(i); + return true; + } + } + return false; } /** * Reading of the mouse */ RMPoint RMInput::mousePos() { - return _mousePos; + RMPoint p(_mousePos.x, _mousePos.y); + return p; } /** @@ -138,10 +124,6 @@ bool RMInput::mouseRightClicked() { return _rightClickMouse; } -bool RMInput::mouseBothClicked() { - return _leftClickMouse && _rightClickMouse; -} - bool RMInput::mouseLeftReleased() { return _leftReleaseMouse; } @@ -150,8 +132,4 @@ bool RMInput::mouseRightReleased() { return _rightReleaseMouse; } -bool RMInput::mouseBothReleased() { - return _leftReleaseMouse && _rightReleaseMouse; -} - } // End of namespace Tony diff --git a/engines/tony/input.h b/engines/tony/input.h index d07eaefe34..274aa8c491 100644 --- a/engines/tony/input.h +++ b/engines/tony/input.h @@ -30,6 +30,9 @@ #define TONY_INPUT_H #include "common/events.h" +#include "common/rect.h" +#include "common/array.h" +#include "common/keyboard.h" #include "tony/utils.h" namespace Tony { @@ -39,17 +42,14 @@ private: Common::Event _event; // Mouse related fields - RMPoint _mousePos; - bool _clampMouse; - bool _leftButton, _rightButton; + Common::Point _mousePos; bool _leftClickMouse, _leftReleaseMouse, _rightClickMouse, _rightReleaseMouse; // Keyboard related fields - bool _keyDown[350]; + Common::Array<Common::KeyCode> _keyDown; public: RMInput(); - ~RMInput(); /** * Polling (must be performed once per frame) @@ -62,20 +62,12 @@ public: RMPoint mousePos(); /** - * Current status of the mouse buttons - */ - bool mouseLeft(); - bool mouseRight(); - - /** * Events of mouse clicks */ bool mouseLeftClicked(); bool mouseRightClicked(); - bool mouseBothClicked(); bool mouseLeftReleased(); bool mouseRightReleased(); - bool mouseBothReleased(); /** * Returns true if the given key is pressed diff --git a/engines/tony/inventory.cpp b/engines/tony/inventory.cpp index 12540e5b7f..6b023d5990 100644 --- a/engines/tony/inventory.cpp +++ b/engines/tony/inventory.cpp @@ -34,7 +34,6 @@ namespace Tony { - /****************************************************************************\ * RMInventory Methods \****************************************************************************/ @@ -71,7 +70,6 @@ bool RMInventory::checkPointInside(const RMPoint &pt) { return pt._y < 70; } - void RMInventory::init() { // Create the main buffer create(RM_SX, 68); @@ -143,10 +141,9 @@ void RMInventory::init() { RMMessage msg2(13); RMMessage msg3(14); - _hints[0].writeText(msg1[0], 1); // Examine - _hints[1].writeText(msg2[0], 1); // Take - _hints[2].writeText(msg3[0], 1); // Use - + _hints[0].writeText(msg1[0], 1); // Examine + _hints[1].writeText(msg2[0], 1); // Take + _hints[2].writeText(msg3[0], 1); // Use // Prepare initial inventory prepare(); @@ -280,7 +277,6 @@ void RMInventory::changeItemStatus(uint32 code, uint32 dwStatus) { } } - void RMInventory::prepare() { for (int i = 1; i < RM_SX / 64 - 1; i++) { if (i - 1 + _curPos < _nInv) @@ -353,6 +349,7 @@ bool RMInventory::leftClick(const RMPoint &mpos, int &nCombineObj) { clearOT(); g_system->unlockMutex(_csModifyInterface); } + // Click the left arrow else if ((_state == OPENED) && _bBlinkingLeft) { assert(_curPos > 0); @@ -375,7 +372,6 @@ bool RMInventory::leftClick(const RMPoint &mpos, int &nCombineObj) { g_system->unlockMutex(_csModifyInterface); } - return false; } @@ -458,7 +454,7 @@ bool RMInventory::rightRelease(const RMPoint &mpos, RMTonyAction &curAction) { return false; } -#define INVSPEED 20 +#define INVSPEED 20 void RMInventory::doFrame(RMGfxTargetBuffer &bigBuf, RMPointer &ptr, RMPoint mpos, bool bCanOpen) { bool bNeedRedraw = false; @@ -517,7 +513,7 @@ void RMInventory::doFrame(RMGfxTargetBuffer &bigBuf, RMPointer &ptr, RMPoint mpo GLOBALS._bCfgInvLocked = !GLOBALS._bCfgInvLocked; } - if (_bCombining) {//m_state == COMBINING) + if (_bCombining) { // m_state == COMBINING) ptr.setCustomPointer(&_items[_nCombine]._pointer[_items[_nCombine]._status - 1]); ptr.setSpecialPointer(RMPointer::PTR_CUSTOM); } @@ -677,8 +673,10 @@ int RMInventory::getSaveStateSize() { void RMInventory::saveState(byte *state) { WRITE_LE_UINT32(state, _nInv); state += 4; - Common::copy(_inv, _inv + 256, (uint32 *)state); - state += 256 * 4; + for (int i = 0; i < 256; ++i) { + WRITE_LE_UINT32(state, _inv[i]); + state += 4; + } int x; for (int i = 0; i < 256; i++) { @@ -695,8 +693,10 @@ void RMInventory::saveState(byte *state) { int RMInventory::loadState(byte *state) { _nInv = READ_LE_UINT32(state); state += 4; - Common::copy((uint32 *)state, (uint32 *)state + 256, _inv); - state += 256 * 4; + for (int i = 0; i < 256; ++i) { + _inv[i] = READ_LE_UINT32(state); + state += 4; + } int x; for (int i = 0; i < 256; i++) { @@ -863,7 +863,7 @@ bool RMInterface::released(const RMPoint &mousepos, RMTonyAction &action) { action = TA_PERORATE; break; - default: // No verb + default: // No verb return false; } @@ -898,8 +898,8 @@ void RMInterface::init() { _hotzone[i].loadPaletteWA(pal); } - _hotbbox[0].setRect(126, 123, 159, 208); // Take - _hotbbox[1].setRect(90, 130, 125, 186); // About + _hotbbox[0].setRect(126, 123, 159, 208); // Take + _hotbbox[1].setRect(90, 130, 125, 186); // About _hotbbox[2].setRect(110, 60, 152, 125); _hotbbox[3].setRect(56, 51, 93, 99); _hotbbox[4].setRect(51, 105, 82, 172); @@ -917,11 +917,11 @@ void RMInterface::init() { RMMessage msg3(15); RMMessage msg4(16); - _hints[0].writeText(msg0[0], 1); // Take - _hints[1].writeText(msg1[0], 1); // Talk - _hints[2].writeText(msg2[0], 1); // Use - _hints[3].writeText(msg3[0], 1); // Examine - _hints[4].writeText(msg4[0], 1); // Show Yourself + _hints[0].writeText(msg0[0], 1); // Take + _hints[1].writeText(msg1[0], 1); // Talk + _hints[2].writeText(msg2[0], 1); // Use + _hints[3].writeText(msg3[0], 1); // Examine + _hints[4].writeText(msg4[0], 1); // Show Yourself _bActive = false; _bPerorate = false; diff --git a/engines/tony/inventory.h b/engines/tony/inventory.h index ce94c86c1b..1d660d51cd 100644 --- a/engines/tony/inventory.h +++ b/engines/tony/inventory.h @@ -174,7 +174,6 @@ public: int loadState(byte *state); }; - class RMInterface : public RMGfxSourceBuffer8RLEByte { private: bool _bActive; diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp index 18470aa6fc..5beac842f9 100644 --- a/engines/tony/loc.cpp +++ b/engines/tony/loc.cpp @@ -37,7 +37,6 @@ namespace Tony { using namespace ::Tony::MPAL; - /****************************************************************************\ * RMPalette Methods \****************************************************************************/ @@ -65,7 +64,6 @@ void RMPattern::RMSlot::readFromStream(Common::ReadStream &ds, bool bLOX) { _flag = ds.readByte(); } - /****************************************************************************\ * RMPattern Methods \****************************************************************************/ @@ -329,7 +327,6 @@ RMSprite::~RMSprite() { } } - /****************************************************************************\ * RMSfx Methods \****************************************************************************/ @@ -391,8 +388,6 @@ void RMSfx::stop() { } } - - /****************************************************************************\ * RMItem Methods \****************************************************************************/ @@ -553,7 +548,6 @@ void RMItem::readFromStream(Common::SeekableReadStream &ds, bool bLOX) { _bIsActive = mpalQueryItemIsActive(_mpalCode); } - RMGfxPrimitive *RMItem::newItemPrimitive() { return new RMGfxPrimitive(this); } @@ -648,7 +642,6 @@ void RMItem::removeThis(CORO_PARAM, bool &result) { result = (_nCurSprite == -1); } - void RMItem::setStatus(int nStatus) { _bIsActive = (nStatus > 0); } @@ -745,7 +738,6 @@ RMItem::~RMItem() { CoroScheduler.closeEvent(_hEndPattern); } - void RMItem::waitForEndPattern(CORO_PARAM, uint32 hCustomSkip) { CORO_BEGIN_CONTEXT; uint32 h[2]; @@ -784,12 +776,10 @@ void RMItem::pauseSound(bool bPause) { _sfx[i].pause(bPause); } - /****************************************************************************\ * RMWipe Methods \****************************************************************************/ - RMWipe::RMWipe() { _hUnregistered = CoroScheduler.createEvent(false, false); _hEndOfFade = CoroScheduler.createEvent(false, false); @@ -799,7 +789,6 @@ RMWipe::RMWipe() { _bEndFade = false; _bFading = false; _nFadeStep = 0; - } RMWipe::~RMWipe() { @@ -904,10 +893,10 @@ void RMWipe::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { /****************************************************************************/ short RMCharacter::findPath(short source, short destination) { - static RMBox box[MAXBOXES]; // Matrix of adjacent boxes - static short nodeCost[MAXBOXES]; // Cost per node - static short valid[MAXBOXES]; // 0:Invalid 1:Valid 2:Saturated - static short nextNode[MAXBOXES]; // Next node + static RMBox box[MAXBOXES]; // Matrix of adjacent boxes + static short nodeCost[MAXBOXES]; // Cost per node + static short valid[MAXBOXES]; // 0:Invalid 1:Valid 2:Saturated + static short nextNode[MAXBOXES]; // Next node short minCost, error = 0; RMBoxLoc *cur; @@ -936,19 +925,19 @@ short RMCharacter::findPath(short source, short destination) { // Find the shortest path while (!finish) { - minCost = 32000; // Reset the minimum cost - error = 1; // Possible error + minCost = 32000; // Reset the minimum cost + error = 1; // Possible error // 1st cycle: explore possible new nodes for (int i = 0; i < cur->_numbBox; i++) { if (valid[i] == 1) { - error = 0; // Failure de-bunked + error = 0; // Failure de-bunked int j = 0; while (((box[i]._adj[j]) != 1) && (j < cur->_numbBox)) j++; if (j >= cur->_numbBox) - valid[i] = 2; // nodo saturated? + valid[i] = 2; // nodo saturated? else { nextNode[i] = j; if (nodeCost[i] + 1 < minCost) @@ -958,7 +947,7 @@ short RMCharacter::findPath(short source, short destination) { } if (error) - finish = true; // All nodes saturated + finish = true; // All nodes saturated // 2nd cycle: adding new nodes that were found, saturate old nodes for (int i = 0; i < cur->_numbBox; i++) { @@ -998,7 +987,6 @@ short RMCharacter::findPath(short source, short destination) { return !error; } - void RMCharacter::goTo(CORO_PARAM, RMPoint destcoord, bool bReversed) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -1068,7 +1056,6 @@ void RMCharacter::goTo(CORO_PARAM, RMPoint destcoord, bool bReversed) { CORO_END_CODE; } - RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoint point) { short steps; RMPoint newPt, foundPt; @@ -1082,9 +1069,9 @@ RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoin steps++; } if ((inWhichBox(newPt) != -1) && (steps < minStep) && - findPath(inWhichBox(_pos), inWhichBox(newPt))) { + findPath(inWhichBox(_pos), inWhichBox(newPt))) { minStep = steps; - newPt._y--; // to avoid error? + newPt._y--; // to avoid error? foundPt = newPt; } } @@ -1097,9 +1084,9 @@ RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoin steps++; } if ((inWhichBox(newPt) != -1) && (steps < minStep) && - findPath(inWhichBox(_pos), inWhichBox(newPt))) { + findPath(inWhichBox(_pos), inWhichBox(newPt))) { minStep = steps; - newPt._y++; // to avoid error? + newPt._y++; // to avoid error? foundPt = newPt; } } @@ -1112,9 +1099,9 @@ RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoin steps++; } if ((inWhichBox(newPt) != -1) && (steps < minStep) && - findPath(inWhichBox(_pos), inWhichBox(newPt))) { + findPath(inWhichBox(_pos), inWhichBox(newPt))) { minStep = steps; - newPt._x++; // to avoid error? + newPt._x++; // to avoid error? foundPt = newPt; } } @@ -1127,9 +1114,9 @@ RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoin steps++; } if ((inWhichBox(newPt) != -1) && (steps < minStep) && - findPath(inWhichBox(_pos), inWhichBox(newPt))) { + findPath(inWhichBox(_pos), inWhichBox(newPt))) { minStep = steps; - newPt._x--; // to avoid error? + newPt._x--; // to avoid error? foundPt = newPt; } } @@ -1140,12 +1127,10 @@ RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoin return foundPt; } - RMPoint RMCharacter::nearestPoint(const RMPoint &point) { return searching(1, 1, 1, 1, point); } - short RMCharacter::scanLine(const RMPoint &point) { int Ldx, Ldy, Lcount; float Lfx, Lfy, Lslope; @@ -1175,7 +1160,7 @@ short RMCharacter::scanLine(const RMPoint &point) { Lstatus = 0; } - Lscan = Lstart; // Start scanning + Lscan = Lstart; // Start scanning while (inWhichBox(Lscan) != -1) { Lcount++; if (Lstatus) { @@ -1200,8 +1185,8 @@ short RMCharacter::scanLine(const RMPoint &point) { * Calculates intersections between the straight line and the closest BBOX */ RMPoint RMCharacter::invScanLine(const RMPoint &point) { - RMPoint lStart = point; // Exchange! - RMPoint lEnd = _pos; // :-) + RMPoint lStart = point; // Exchange! + RMPoint lEnd = _pos; // :-) int lDx = lStart._x - lEnd._x; int lDy = lStart._y - lEnd._y; float lFx = lDx; @@ -1256,7 +1241,6 @@ RMPoint RMCharacter::invScanLine(const RMPoint &point) { } } - /** * Returns the HotSpot coordinate closest to the player */ @@ -1510,7 +1494,6 @@ inline int RMCharacter::inWhichBox(const RMPoint &pt) { return _theBoxes->whichBox(_curLocation, pt); } - void RMCharacter::move(CORO_PARAM, RMPoint pt, bool *result) { CORO_BEGIN_CONTEXT; RMPoint dest; @@ -1807,7 +1790,7 @@ bool RMGameBoxes::isInBox(int nLoc, int nBox, const RMPoint &pt) { RMBoxLoc *cur = getBoxes(nLoc); if ((pt._x >= cur->_boxes[nBox]._left) && (pt._x <= cur->_boxes[nBox]._right) && - (pt._y >= cur->_boxes[nBox]._top) && (pt._y <= cur->_boxes[nBox]._bottom)) + (pt._y >= cur->_boxes[nBox]._top) && (pt._y <= cur->_boxes[nBox]._bottom)) return true; else return false; @@ -1822,7 +1805,7 @@ int RMGameBoxes::whichBox(int nLoc, const RMPoint &punto) { for (int i = 0; i < cur->_numbBox; i++) { if (cur->_boxes[i]._bActive) { if ((punto._x >= cur->_boxes[i]._left) && (punto._x <= cur->_boxes[i]._right) && - (punto._y >= cur->_boxes[i]._top) && (punto._y <= cur->_boxes[i]._bottom)) + (punto._y >= cur->_boxes[i]._top) && (punto._y <= cur->_boxes[i]._bottom)) return i; } } @@ -1976,7 +1959,7 @@ bool RMLocation::load(Common::SeekableReadStream &ds) { _buf->init(ds, dimx, dimy, true); // Check the size of the location -// assert(dimy!=512); + //assert(dimy!=512); // Number of objects _nItems = ds.readSint32LE(); @@ -1994,7 +1977,6 @@ bool RMLocation::load(Common::SeekableReadStream &ds) { return ds.err(); } - bool RMLocation::loadLOX(Common::SeekableReadStream &ds) { // Version byte ver = ds.readByte(); @@ -2033,7 +2015,6 @@ bool RMLocation::loadLOX(Common::SeekableReadStream &ds) { return ds.err(); } - /** * Draw method overloaded from RMGfxSourceBUffer8 */ @@ -2070,7 +2051,6 @@ void RMLocation::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri CORO_END_CODE; } - /** * Prepare a frame, adding the location to the OT list, and all the items that have changed animation frame. */ @@ -2084,7 +2064,6 @@ void RMLocation::doFrame(RMGfxTargetBuffer *bigBuf) { _items[i].doFrame(bigBuf); } - RMItem *RMLocation::getItemFromCode(uint32 dwCode) { for (int i = 0; i < _nItems; i++) { if (_items[i].mpalCode() == (int)dwCode) diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 04ba772458..1306316136 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -49,7 +49,6 @@ typedef enum { CM_65K } RMColorMode; - /****************************************************************************\ * Class declarations \****************************************************************************/ @@ -65,7 +64,6 @@ public: void readFromStream(Common::ReadStream &ds); }; - /** * Sound effect of an object */ @@ -87,7 +85,6 @@ public: void readFromStream(Common::ReadStream &ds, bool bLOX = false); }; - /** * Object pattern */ @@ -126,8 +123,8 @@ public: private: int _speed; - RMPoint _pos; // Parent coordinates - RMPoint _curPos; // Parent + child coordinates + RMPoint _pos; // Parent coordinates + RMPoint _curPos; // Parent + child coordinates int _bLoop; int _nSlots; int _nCurSlot; @@ -160,7 +157,6 @@ private: void updateCoord(); }; - /** * Sprite (frame) animation of an item */ @@ -185,7 +181,6 @@ public: void readFromStream(Common::SeekableReadStream &ds, bool bLOX = false); }; - /** * Data on an item */ @@ -195,7 +190,7 @@ public: protected: int _z; - RMPoint _pos; // Coordinate ancestor + RMPoint _pos; // Coordinate ancestor RMColorMode _cm; RMPoint _curScroll; @@ -285,15 +280,14 @@ protected: virtual RMGfxSourceBuffer *newItemSpriteBuffer(int dimx, int dimy, bool bPreRLE); }; - -#define MAXBOXES 50 // Maximum number of allowed boxes -#define MAXHOTSPOT 20 // Maximum nimber of allowed hotspots +#define MAXBOXES 50 // Maximum number of allowed boxes +#define MAXHOTSPOT 20 // Maximum nimber of allowed hotspots class RMBox { public: struct Hotspot { - int _hotx, _hoty; // Hotspot coordinates - int _destination; // Hotspot destination + int _hotx, _hoty; // Hotspot coordinates + int _destination; // Hotspot destination }; public: @@ -309,7 +303,6 @@ public: void readFromStream(Common::ReadStream &ds); }; - class RMBoxLoc { public: int _numbBox; @@ -454,7 +447,6 @@ public: void setSpeed(int speed); }; - class RMWipe : public RMGfxTask { private: bool _bFading; @@ -483,25 +475,24 @@ public: virtual int priority(); }; - /** * Location */ class RMLocation : public RMGfxTaskSetPrior { public: - Common::String _name; // Name + Common::String _name; // Name private: - RMColorMode _cmode; // Color mode - RMGfxSourceBuffer *_buf; // Location picture + RMColorMode _cmode; // Color mode + RMGfxSourceBuffer *_buf; // Location picture - int _nItems; // Number of objects - RMItem *_items; // Objects + int _nItems; // Number of objects + RMItem *_items; // Objects - RMPoint _curScroll; // Current scroll position + RMPoint _curScroll; // Current scroll position RMPoint _fixedScroll; - RMPoint _prevScroll; // Previous scroll position + RMPoint _prevScroll; // Previous scroll position RMPoint _prevFixedScroll; public: @@ -552,7 +543,6 @@ public: void pauseSound(bool bPause); }; - /** * MPAL message, composed of more ASCIIZ */ diff --git a/engines/tony/mpal/expr.cpp b/engines/tony/mpal/expr.cpp index 824cd91651..7dc640ba7c 100644 --- a/engines/tony/mpal/expr.cpp +++ b/engines/tony/mpal/expr.cpp @@ -35,7 +35,6 @@ namespace Tony { namespace MPAL { - /** * Duplicate a mathematical expression. * @@ -140,7 +139,6 @@ static void solve(LpExpression one, int num) { } } - /** * Calculates the result of a mathematical expression, replacing the current * value of any variable. @@ -178,7 +176,6 @@ static int evaluateAndFreeExpression(byte *expr) { return val; } - /** * Parses a mathematical expression from the MPC file * @@ -249,7 +246,6 @@ const byte *parseExpression(const byte *lpBuf, MpalHandle *h) { return lpBuf; } - /** * Calculate the value of a mathamatical expression * diff --git a/engines/tony/mpal/expr.h b/engines/tony/mpal/expr.h index 405624b4fe..256d09bb9b 100644 --- a/engines/tony/mpal/expr.h +++ b/engines/tony/mpal/expr.h @@ -70,16 +70,16 @@ namespace MPAL { * Mathamatical framework to manage operations */ typedef struct { - byte _type; // Object Type (see enum ExprListTypes) + byte _type; // Object Type (see enum ExprListTypes) union { - int _num; // Identifier (if type == ELT_NUMBER) - char *_name; // Variable name (if type == ELT_VAR) - MpalHandle _son; // Handle expressions (if type == ELT_PARENTH) - byte *_pson; // Handle lockato (if type == ELT_PARENTH2) + int _num; // Identifier (if type == ELT_NUMBER) + char *_name; // Variable name (if type == ELT_VAR) + MpalHandle _son; // Handle expressions (if type == ELT_PARENTH) + byte *_pson; // Handle lockato (if type == ELT_PARENTH2) } _val; - byte _symbol; // Mathematic symbols (see #define OP_*) + byte _symbol; // Mathematic symbols (see #define OP_*) } Expression; typedef Expression *LpExpression; diff --git a/engines/tony/mpal/loadmpc.cpp b/engines/tony/mpal/loadmpc.cpp index 9c45cdf982..4eb84d1406 100644 --- a/engines/tony/mpal/loadmpc.cpp +++ b/engines/tony/mpal/loadmpc.cpp @@ -90,7 +90,7 @@ static const byte *ParseScript(const byte *lpBuf, LpMpalScript lpmsScript) { lpBuf += 4; break; - case 2: { // Variable assign + case 2: { // Variable assign int len = *lpBuf; lpBuf++; lpmsScript->_command[curCmd]._lpszVarName = (char *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, len + 1); @@ -216,6 +216,7 @@ static const byte *parseDialog(const byte *lpBuf, LpMpalDialog lpmdDialog) { return NULL; break; } + // Do Choice case 3: lpmdDialog->_command[curCmd]._nChoice = READ_LE_UINT16(lpBuf); @@ -317,7 +318,6 @@ static const byte *parseDialog(const byte *lpBuf, LpMpalDialog lpmdDialog) { return lpBuf; } - /** * Parses an item from the MPC file, and inserts its data into a structure * @@ -384,7 +384,7 @@ static const byte *parseItem(const byte *lpBuf, LpMpalItem lpmiItem) { lpmiItem->_command[curCmd]._type = *lpBuf; lpBuf++; switch (lpmiItem->_command[curCmd]._type) { - case 1: // Call custom function + case 1: // Call custom function lpmiItem->_command[curCmd]._nCf = READ_LE_UINT16(lpBuf); lpBuf += 2; lpmiItem->_command[curCmd]._arg1 = (int32)READ_LE_UINT32(lpBuf); @@ -397,7 +397,7 @@ static const byte *parseItem(const byte *lpBuf, LpMpalItem lpmiItem) { lpBuf += 4; break; - case 2: // Variable assign + case 2: // Variable assign len = *lpBuf; lpBuf++; lpmiItem->_command[curCmd]._lpszVarName = (char *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, len + 1); @@ -498,7 +498,6 @@ static const byte *ParseLocation(const byte *lpBuf, LpMpalLocation lpmlLocation) return lpBuf; } - /****************************************************************************\ * Exported functions \****************************************************************************/ @@ -539,7 +538,7 @@ bool parseMpc(const byte *lpBuf) { GLOBALS._lpmvVars->_dwVal = READ_LE_UINT32(lpBuf); lpBuf += 4; - lpBuf++; // Skip 'ext' + lpBuf++; // Skip 'ext' GLOBALS._lpmvVars++; } diff --git a/engines/tony/mpal/lzo.cpp b/engines/tony/mpal/lzo.cpp index 3d0751a5ca..a04a769528 100644 --- a/engines/tony/mpal/lzo.cpp +++ b/engines/tony/mpal/lzo.cpp @@ -69,440 +69,440 @@ namespace Tony { namespace MPAL { -#define pd(a, b) ((uint32) ((a) - (b))) +#define pd(a, b) ((uint32) ((a) - (b))) -#define TEST_IP (ip < ip_end) -#define TEST_OP 1 -#define NEED_IP(x) ((void) 0) -#define NEED_OP(x) ((void) 0) -#define TEST_LB(m_pos) ((void) 0) +#define TEST_IP (ip < ip_end) +#define TEST_OP 1 +#define NEED_IP(x) ((void) 0) +#define NEED_OP(x) ((void) 0) +#define TEST_LB(m_pos) ((void) 0) -#define M2_MAX_OFFSET 0x0800 +#define M2_MAX_OFFSET 0x0800 #define LZO1X /** * Decompresses an LZO compressed resource */ int lzo1x_decompress(const byte *in, uint32 in_len, byte *out, uint32 *out_len) { - register byte *op; - register const byte *ip; - register uint32 t = 0; + register byte *op; + register const byte *ip; + register uint32 t = 0; #if defined(COPY_DICT) - uint32 m_off; - const byte *dict_end; + uint32 m_off; + const byte *dict_end; #else - register const byte *m_pos; + register const byte *m_pos; #endif - const byte * const ip_end = in + in_len; + const byte * const ip_end = in + in_len; #if defined(HAVE_ANY_OP) - byte * const op_end = out + *out_len; + byte * const op_end = out + *out_len; #endif #if defined(LZO1Z) - uint32 last_m_off = 0; + uint32 last_m_off = 0; #endif #if defined(COPY_DICT) - if (dict) - { - if (dict_len > M4_MAX_OFFSET) - { - dict += dict_len - M4_MAX_OFFSET; - dict_len = M4_MAX_OFFSET; - } - dict_end = dict + dict_len; - } - else - { - dict_len = 0; - dict_end = NULL; - } -#endif - - *out_len = 0; - - op = out; - ip = in; - - if (*ip > 17) - { - t = *ip++ - 17; - if (t < 4) - goto match_next; - assert(t > 0); NEED_OP(t); NEED_IP(t+1); - do *op++ = *ip++; while (--t > 0); - goto first_literal_run; - } - - while (TEST_IP && TEST_OP) - { - t = *ip++; - if (t >= 16) - goto match; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 15 + *ip++; - } - assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); #if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) - t += 3; - if (t >= 8) do - { - UA_COPY64(op, ip); - op += 8; ip += 8; t -= 8; - } while (t >= 8); - if (t >= 4) - { - UA_COPY32(op, ip); - op += 4; ip += 4; t -= 4; - } - if (t > 0) - { - *op++ = *ip++; - if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } - } + t += 3; + if (t >= 8) do + { + UA_COPY64(op, ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op, ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } #elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) - if (PTR_ALIGNED2_4(op, ip)) - { -#endif - UA_COPY32(op, ip); - op += 4; ip += 4; - if (--t > 0) - { - if (t >= 4) - { - do { - UA_COPY32(op, ip); - op += 4; ip += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *ip++; while (--t > 0); - } - else - do *op++ = *ip++; while (--t > 0); - } + if (PTR_ALIGNED2_4(op, ip)) + { +#endif + UA_COPY32(op, ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY32(op, ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } #if !defined(LZO_UNALIGNED_OK_4) - } - else + } + else #endif #endif #if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) - { - *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; - do *op++ = *ip++; while (--t > 0); - } + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } #endif first_literal_run: - t = *ip++; - if (t >= 16) - goto match; + t = *ip++; + if (t >= 16) + goto match; #if defined(COPY_DICT) #if defined(LZO1Z) - m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; #else - m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif - NEED_OP(3); - t = 3; COPY_DICT(t, m_off) + NEED_OP(3); + t = 3; COPY_DICT(t, m_off) #else #if defined(LZO1Z) - t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; #else - m_pos = op - (1 + M2_MAX_OFFSET); - m_pos -= t >> 2; - m_pos -= *ip++ << 2; + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; #endif - TEST_LB(m_pos); NEED_OP(3); - *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif - goto match_done; + goto match_done; - do { + do { match: - if (t >= 64) - { + if (t >= 64) + { #if defined(COPY_DICT) #if defined(LZO1X) - m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); - t = (t >> 5) - 1; + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; #elif defined(LZO1Y) - m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); - t = (t >> 4) - 3; + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; #elif defined(LZO1Z) - m_off = t & 0x1f; - if (m_off >= 0x1c) - m_off = last_m_off; - else - { - m_off = 1 + (m_off << 6) + (*ip++ >> 2); - last_m_off = m_off; - } - t = (t >> 5) - 1; + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; #endif #else #if defined(LZO1X) - m_pos = op - 1; - m_pos -= (t >> 2) & 7; - m_pos -= *ip++ << 3; - t = (t >> 5) - 1; + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; #elif defined(LZO1Y) - m_pos = op - 1; - m_pos -= (t >> 2) & 3; - m_pos -= *ip++ << 2; - t = (t >> 4) - 3; + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; #elif defined(LZO1Z) - { - uint32 off = t & 0x1f; - m_pos = op; - if (off >= 0x1c) - { - assert(last_m_off > 0); - m_pos -= last_m_off; - } - else - { - off = 1 + (off << 6) + (*ip++ >> 2); - m_pos -= off; - last_m_off = off; - } - } - t = (t >> 5) - 1; -#endif - TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); - goto copy_match; -#endif - } - else if (t >= 32) - { - t &= 31; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 31 + *ip++; - } + { + uint32 off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } #if defined(COPY_DICT) #if defined(LZO1Z) - m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); - last_m_off = m_off; + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; #else - m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) - { - uint32 off = 1 + (ip[0] << 6) + (ip[1] >> 2); - m_pos = op - off; - last_m_off = off; - } + { + uint32 off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos = op - 1; - m_pos -= UA_GET16(ip) >> 2; + m_pos = op - 1; + m_pos -= UA_GET16(ip) >> 2; #else - m_pos = op - 1; - m_pos -= (ip[0] >> 2) + (ip[1] << 6); + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif - ip += 2; - } - else if (t >= 16) - { + ip += 2; + } + else if (t >= 16) + { #if defined(COPY_DICT) - m_off = (t & 8) << 11; + m_off = (t & 8) << 11; #else - m_pos = op; - m_pos -= (t & 8) << 11; -#endif - t &= 7; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 7 + *ip++; - } + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } #if defined(COPY_DICT) #if defined(LZO1Z) - m_off += (ip[0] << 6) + (ip[1] >> 2); + m_off += (ip[0] << 6) + (ip[1] >> 2); #else - m_off += (ip[0] >> 2) + (ip[1] << 6); + m_off += (ip[0] >> 2) + (ip[1] << 6); #endif - ip += 2; - if (m_off == 0) - goto eof_found; - m_off += 0x4000; + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; #if defined(LZO1Z) - last_m_off = m_off; + last_m_off = m_off; #endif #else #if defined(LZO1Z) - m_pos -= (ip[0] << 6) + (ip[1] >> 2); + m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos -= UA_GET16(ip) >> 2; + m_pos -= UA_GET16(ip) >> 2; #else - m_pos -= (ip[0] >> 2) + (ip[1] << 6); + m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif - ip += 2; - if (m_pos == op) - goto eof_found; - m_pos -= 0x4000; + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; #if defined(LZO1Z) - last_m_off = pd((const byte *)op, m_pos); + last_m_off = pd((const byte *)op, m_pos); #endif #endif - } - else - { + } + else + { #if defined(COPY_DICT) #if defined(LZO1Z) - m_off = 1 + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; #else - m_off = 1 + (t >> 2) + (*ip++ << 2); + m_off = 1 + (t >> 2) + (*ip++ << 2); #endif - NEED_OP(2); - t = 2; COPY_DICT(t, m_off) + NEED_OP(2); + t = 2; COPY_DICT(t, m_off) #else #if defined(LZO1Z) - t = 1 + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; #else - m_pos = op - 1; - m_pos -= t >> 2; - m_pos -= *ip++ << 2; + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; #endif - TEST_LB(m_pos); NEED_OP(2); - *op++ = *m_pos++; *op++ = *m_pos; + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; #endif - goto match_done; - } + goto match_done; + } #if defined(COPY_DICT) - NEED_OP(t+3-1); - t += 3-1; COPY_DICT(t, m_off) + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t, m_off) #else - TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); #if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) - if (op - m_pos >= 8) - { - t += (3 - 1); - if (t >= 8) do - { - UA_COPY64(op, m_pos); - op += 8; m_pos += 8; t -= 8; - } while (t >= 8); - if (t >= 4) - { - UA_COPY32(op, m_pos); - op += 4; m_pos += 4; t -= 4; - } - if (t > 0) - { - *op++ = m_pos[0]; - if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } - } - } - else + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY64(op, m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op, m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else #elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) - if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op, m_pos)) - { - assert((op - m_pos) >= 4); + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op, m_pos)) + { + assert((op - m_pos) >= 4); #else - if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) - { -#endif - UA_COPY32(op, m_pos); - op += 4; m_pos += 4; t -= 4 - (3 - 1); - do { - UA_COPY32(op, m_pos); - op += 4; m_pos += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *m_pos++; while (--t > 0); - } - else -#endif - { + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY32(op, m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY32(op, m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { copy_match: - *op++ = *m_pos++; *op++ = *m_pos++; - do *op++ = *m_pos++; while (--t > 0); - } + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } #endif match_done: #if defined(LZO1Z) - t = ip[-1] & 3; + t = ip[-1] & 3; #else - t = ip[-2] & 3; + t = ip[-2] & 3; #endif - if (t == 0) - break; + if (t == 0) + break; match_next: - assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); #if 0 - do *op++ = *ip++; while (--t > 0); + do *op++ = *ip++; while (--t > 0); #else - *op++ = *ip++; - if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif - t = *ip++; - } while (TEST_IP && TEST_OP); - } + t = *ip++; + } while (TEST_IP && TEST_OP); + } #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) - *out_len = pd(op, out); - return LZO_E_EOF_NOT_FOUND; + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; #endif eof_found: - assert(t == 1); - *out_len = pd(op, out); - return (ip == ip_end ? LZO_E_OK : - (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: - *out_len = pd(op, out); - return LZO_E_INPUT_OVERRUN; + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: - *out_len = pd(op, out); - return LZO_E_OUTPUT_OVERRUN; + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) lookbehind_overrun: - *out_len = pd(op, out); - return LZO_E_LOOKBEHIND_OVERRUN; + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; #endif } diff --git a/engines/tony/mpal/memory.cpp b/engines/tony/mpal/memory.cpp index dfbf16e789..9737fe0abf 100644 --- a/engines/tony/mpal/memory.cpp +++ b/engines/tony/mpal/memory.cpp @@ -121,7 +121,6 @@ void MemoryManager::unlockItem(MpalHandle handle) { --item->_lockCount; } - } // end of namespace MPAL } // end of namespace Tony diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index 8d83363c24..1a24c5a576 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -196,7 +196,6 @@ static int locGetOrderFromNum(uint32 nLoc) { return -1; } - /** * Find the index of a message within the messages array * @param nMsg Message number to search for @@ -233,7 +232,6 @@ static int itemGetOrderFromNum(uint32 nItem) { return -1; } - /** * Find the index of a script within the scripts array * @param nScript Script number to search for @@ -252,7 +250,6 @@ static int scriptGetOrderFromNum(uint32 nScript) { return -1; } - /** * Find the index of a dialog within the dialogs array * @param nDialog Dialog number to search for @@ -271,7 +268,6 @@ static int dialogGetOrderFromNum(uint32 nDialog) { return -1; } - /** * Duplicates a message * @param nMsgOrd Index of the message inside the messages array @@ -302,7 +298,6 @@ static char *DuplicateMessage(uint32 nMsgOrd) { return clonemsg; } - /** * Duplicate a sentence of a dialog * @param nDlgOrd Index of the dialog in the dialogs array @@ -340,7 +335,6 @@ static char *duplicateDialogPeriod(uint32 nPeriod) { return NULL; } - /** * Load a resource from the MPR file * @@ -461,16 +455,16 @@ static LpItem getItemData(uint32 nOrdItem) { dat = (char *)globalLock(hDat); if (dat[0] == 'D' && dat[1] == 'A' && dat[2] == 'T') { - int i = dat[3]; // For version 1.0!! + int i = dat[3]; // For version 1.0!! dat += 4; - if (i >= 0x10) { // From 1.0, there's a destination point for each object + if (i >= 0x10) { // From 1.0, there's a destination point for each object ret->_destX = (int16)READ_LE_UINT16(dat); ret->_destY = (int16)READ_LE_UINT16(dat + 2); dat += 4; } - if (i >= 0x11) { // From 1.1, there's animation speed + if (i >= 0x11) { // From 1.1, there's animation speed ret->_speed = READ_LE_UINT16(dat); dat += 2; } else @@ -511,7 +505,7 @@ static LpItem getItemData(uint32 nOrdItem) { for (int i = 1; i < ret->_numpattern; i++) { for (int j = 0; j < patlength[i]; j++) ret->_pattern[i][j] = dat[j]; - ret->_pattern[i][(int)patlength[i]] = 255; // Terminate pattern + ret->_pattern[i][(int)patlength[i]] = 255; // Terminate pattern dat += patlength[i]; } @@ -538,7 +532,6 @@ static LpItem getItemData(uint32 nOrdItem) { return ret; } - /** * Thread that calls a custom function. It is used in scripts, so that each script * function is executed without delaying the others. @@ -562,7 +555,6 @@ void CustomThread(CORO_PARAM, const void *param) { CORO_END_CODE; } - /** * Main process for running a script. * @@ -587,7 +579,7 @@ void ScriptThread(CORO_PARAM, const void *param) { _ctx->dwStartTime = g_vm->getTime(); _ctx->numHandles = 0; -// debugC(DEBUG_BASIC, kTonyDebugMPAL, "PlayScript(): Moments: %u\n", s->_nMoments); + //debugC(DEBUG_BASIC, kTonyDebugMPAL, "PlayScript(): Moments: %u\n", s->_nMoments); for (_ctx->i = 0; _ctx->i < s->_nMoments; _ctx->i++) { // Sleep for the required time if (s->_moment[_ctx->i]._dwTime == -1) { @@ -596,7 +588,7 @@ void ScriptThread(CORO_PARAM, const void *param) { } else { _ctx->dwCurTime = g_vm->getTime(); if (_ctx->dwCurTime < _ctx->dwStartTime + (s->_moment[_ctx->i]._dwTime * 100)) { - // debugC(DEBUG_BASIC, kTonyDebugMPAL, "PlayScript(): Sleeping %lums\n",_ctx->dwStartTime + (s->_moment[_ctx->i]._dwTime*100) - _ctx->dwCurTime); + //debugC(DEBUG_BASIC, kTonyDebugMPAL, "PlayScript(): Sleeping %lums\n",_ctx->dwStartTime + (s->_moment[_ctx->i]._dwTime*100) - _ctx->dwCurTime); CORO_INVOKE_1(CoroScheduler.sleep, _ctx->dwStartTime + (s->_moment[_ctx->i]._dwTime * 100) - _ctx->dwCurTime); } } @@ -655,7 +647,6 @@ void ScriptThread(CORO_PARAM, const void *param) { CORO_END_CODE; } - /** * Thread that performs an action on an item. the thread always executes the action, * so it should create a new item in which the action is the one required. @@ -752,11 +743,9 @@ void ShutUpActionThread(CORO_PARAM, const void *param) { CORO_INVOKE_1(g_vm->loadState, _ctx->slotNumber); } - CORO_END_CODE; } - /** * Polls one location (starting point of a process) * @@ -764,14 +753,14 @@ void ShutUpActionThread(CORO_PARAM, const void *param) { */ void LocationPollThread(CORO_PARAM, const void *param) { typedef struct { - uint32 _nItem, _nAction; + uint32 _nItem, _nAction; - uint16 _wTime; - byte _perc; + uint16 _wTime; + byte _perc; MpalHandle _when; - byte _nCmds; - uint16 _cmdNum[MAX_COMMANDS_PER_ACTION]; - uint32 _dwLastTime; + byte _nCmds; + uint16 _cmdNum[MAX_COMMANDS_PER_ACTION]; + uint32 _dwLastTime; } MYACTION; typedef struct { @@ -862,7 +851,6 @@ void LocationPollThread(CORO_PARAM, const void *param) { return; } - // We have established that there is at least one item that contains idle actions. // Now we created the mirrored copies of the idle actions. _ctx->myActions = (MYACTION *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, _ctx->nIdleActions * sizeof(MYACTION)); @@ -905,7 +893,6 @@ void LocationPollThread(CORO_PARAM, const void *param) { // We don't need the item list anymore globalDestroy(_ctx->il); - // Here's the main loop while (1) { // Searching for idle actions requiring time to execute @@ -944,7 +931,7 @@ void LocationPollThread(CORO_PARAM, const void *param) { if (_ctx->curTime >= _ctx->myActions[_ctx->k]._dwLastTime + _ctx->myActions[_ctx->k]._wTime) { _ctx->myActions[_ctx->k]._dwLastTime += _ctx->myActions[_ctx->k]._wTime; - // It's time to check to see if fortune is on the side of the idle action + // It's time to check to see if fortune is on the side of the idle action byte randomVal = (byte)g_vm->_randomSource.getRandomNumber(99); if (randomVal < _ctx->myActions[_ctx->k]._perc) { // Check if there is an action running on the item @@ -1016,7 +1003,6 @@ void LocationPollThread(CORO_PARAM, const void *param) { } } - // Set idle skip on CORO_INVOKE_4(GLOBALS._lplpFunctions[200], 0, 0, 0, 0); @@ -1038,7 +1024,6 @@ void LocationPollThread(CORO_PARAM, const void *param) { CORO_END_CODE; } - /** * Wait for the end of the dialog execution thread, and then restore global * variables indicating that the dialogue has finished. @@ -1071,7 +1056,6 @@ void ShutUpDialogThread(CORO_PARAM, const void *param) { void doChoice(CORO_PARAM, uint32 nChoice); - /** * Executes a group of the current dialog. Can 'be the Starting point of a process. * @parm nGroup Number of the group to perform @@ -1149,7 +1133,6 @@ void GroupThread(CORO_PARAM, const void *param) { CORO_END_CODE; } - /** * Make a choice in the current dialog. * @@ -1247,7 +1230,6 @@ void doChoice(CORO_PARAM, uint32 nChoice) { CORO_END_CODE; } - /** * Perform an action on a certain item. * @@ -1353,7 +1335,6 @@ static uint32 doDialog(uint32 nDlgOrd, uint32 nGroup) { return h; } - /** * Takes note of the selection chosen by the user, and warns the process that was running * the box that it can continue. @@ -1379,7 +1360,6 @@ bool doSelection(uint32 i, uint32 dwData) { return true; } - /** * @defgroup Exported functions */ @@ -1502,6 +1482,8 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName, lzo1x_decompress((const byte *)cmpbuf, dwSizeComp, (byte *)GLOBALS._lpResources, (uint32 *)&nBytesRead); if (nBytesRead != (uint32)GLOBALS._nResources * 8) return false; + for (int i = 0; i < 2*GLOBALS._nResources; ++i) + GLOBALS._lpResources[i] = FROM_LE_32(GLOBALS._lpResources[i]); globalDestroy(cmpbuf); @@ -1884,7 +1866,6 @@ MpalHandle mpalQueryHANDLE(uint16 wQueryType, ...) { return hRet; } - /** * This is a general function to communicate with the library, to request information * about what is in the .MPC file @@ -2005,7 +1986,6 @@ bool mpalStartIdlePoll(int nLoc) { return false; } - /** * Stop processing the idle actions of the items on one location. * @@ -2063,7 +2043,6 @@ void mpalSaveState(byte *buf) { unlockVar(); } - /** * Load a save state from a buffer. * diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h index 5e1b02b3fc..779bdd6188 100644 --- a/engines/tony/mpal/mpal.h +++ b/engines/tony/mpal/mpal.h @@ -26,7 +26,6 @@ * Copyright (c) 1997-2003 Nayma Software */ - /****************************************************************************\ * General Introduction \****************************************************************************/ @@ -56,7 +55,6 @@ * */ - /****************************************************************************\ * Custom Functions \****************************************************************************/ @@ -96,11 +94,11 @@ namespace MPAL { \****************************************************************************/ // OK value for the error codes -#define OK 0 +#define OK 0 -#define MAXFRAMES 400 // frame animation of an object -#define MAXPATTERN 40 // pattern of animation of an object -#define MAXPOLLINGLOCATIONS 64 +#define MAXFRAMES 400 // frame animation of an object +#define MAXPATTERN 40 // pattern of animation of an object +#define MAXPOLLINGLOCATIONS 64 #define GETARG(type) va_arg(v, type) @@ -108,8 +106,8 @@ namespace MPAL { * Macro for use with queries that may refer to X and Y co-ordinates */ enum QueryCoordinates { - MPQ_X, - MPQ_Y + MPQ_X, + MPQ_Y }; /** @@ -117,55 +115,54 @@ enum QueryCoordinates { * that can do at the library */ enum QueryTypes { - // General Query - MPQ_VERSION = 10, - - MPQ_GLOBAL_VAR = 50, - MPQ_RESOURCE, - MPQ_MESSAGE, - - // Query on leases - MPQ_LOCATION_IMAGE = 100, - MPQ_LOCATION_SIZE, - - // Queries about items - MPQ_ITEM_LIST = 200, - MPQ_ITEM_DATA, - MPQ_ITEM_PATTERN, - MPQ_ITEM_NAME, + // General Query + MPQ_VERSION = 10, + + MPQ_GLOBAL_VAR = 50, + MPQ_RESOURCE, + MPQ_MESSAGE, + + // Query on leases + MPQ_LOCATION_IMAGE = 100, + MPQ_LOCATION_SIZE, + + // Queries about items + MPQ_ITEM_LIST = 200, + MPQ_ITEM_DATA, + MPQ_ITEM_PATTERN, + MPQ_ITEM_NAME, MPQ_ITEM_IS_ACTIVE, - // Query dialog - MPQ_DIALOG_PERIOD = 300, - MPQ_DIALOG_WAITFORCHOICE, - MPQ_DIALOG_SELECTLIST, - MPQ_DIALOG_SELECTION, + // Query dialog + MPQ_DIALOG_PERIOD = 300, + MPQ_DIALOG_WAITFORCHOICE, + MPQ_DIALOG_SELECTLIST, + MPQ_DIALOG_SELECTION, - // Query execution - MPQ_DO_ACTION = 400, - MPQ_DO_DIALOG + // Query execution + MPQ_DO_ACTION = 400, + MPQ_DO_DIALOG }; /** * Framework to manage the animation of an item */ typedef struct { - char *_frames[MAXFRAMES]; - Common::Rect _frameslocations[MAXFRAMES]; - Common::Rect _bbox[MAXFRAMES]; - short _pattern[MAXPATTERN][MAXFRAMES]; - short _speed; - char _numframe; - char _numpattern; - char _curframe; - char _curpattern; - short _destX, _destY; - signed char _destZ; - short _objectID; + char *_frames[MAXFRAMES]; + Common::Rect _frameslocations[MAXFRAMES]; + Common::Rect _bbox[MAXFRAMES]; + short _pattern[MAXPATTERN][MAXFRAMES]; + short _speed; + char _numframe; + char _numpattern; + char _curframe; + char _curpattern; + short _destX, _destY; + signed char _destZ; + short _objectID; } Item; typedef Item *LpItem; - /** * Define a custom function, to use the language MPAL to perform various controls as a result of an action */ @@ -206,7 +203,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryGlobalVar(lpszVarName) \ mpalQueryDWORD(MPQ_GLOBAL_VAR, (const char *)(lpszVarName)) - /** * Provides access to a resource inside the .MPC file * @@ -216,7 +212,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryResource(dwResId) \ mpalQueryHANDLE(MPQ_RESOURCE, (uint32)(dwResId)) - /** * Returns a message. * @@ -228,7 +223,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryMessage(nMsg) \ (char *)mpalQueryHANDLE(MPQ_MESSAGE, (uint32)(nMsg)) - /** * Provides a location image * @return Returns a picture handle @@ -236,7 +230,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryLocationImage(nLoc) \ mpalQueryHANDLE(MPQ_LOCATION_IMAGE, (uint32)(nLoc)) - /** * Request the x or y size of a location in pixels * @@ -247,7 +240,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryLocationSize(nLoc, dwCoord) \ mpalQueryDWORD(MPQ_LOCATION_SIZE, (uint32)(nLoc), (uint32)(dwCoord)) - /** * Provides the list of objects in a location. * @@ -258,7 +250,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryItemList(nLoc) \ (uint32 *)mpalQueryHANDLE(MPQ_ITEM_LIST, (uint32)(nLoc)) - /** * Provides information on an item * @@ -268,7 +259,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryItemData(nItem) \ (LpItem)mpalQueryHANDLE(MPQ_ITEM_DATA, (uint32)(nItem)) - /** * Provides the current pattern of an item * @@ -279,7 +269,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryItemPattern(nItem) \ mpalQueryDWORD(MPQ_ITEM_PATTERN, (uint32)(nItem)) - /** * Returns true if an item is active * @@ -289,7 +278,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryItemIsActive(nItem) \ (bool)mpalQueryDWORD(MPQ_ITEM_IS_ACTIVE, (uint32)(nItem)) - /** * Returns the name of an item * @@ -302,7 +290,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryItemName(nItem, lpszName) \ mpalQueryHANDLE(MPQ_ITEM_NAME, (uint32)(nItem), (char *)(lpszName)) - /** * Returns a sentence of dialog. * @@ -316,7 +303,6 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; #define mpalQueryDialogPeriod(nPeriod) \ (char *)mpalQueryHANDLE(MPQ_DIALOG_PERIOD, (uint32)(nPeriod)) - /** * Wait until the moment in which the need is signaled to make a choice by the user. * @returns Number of choice to be made, or -1 if the dialogue is finished. @@ -393,7 +379,7 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION; * @returns TRUE if all OK, FALSE on failure */ bool mpalInit(const char *lpszFileName, const char *lpszMprFileName, - LPLPCUSTOMFUNCTION lplpcfArray, Common::String *lpcfStrings); + LPLPCUSTOMFUNCTION lplpcfArray, Common::String *lpcfStrings); /** * Frees resources allocated by the MPAL subsystem @@ -476,7 +462,6 @@ bool mpalStartIdlePoll(int nLoc); */ void mpalEndIdlePoll(CORO_PARAM, int nLoc, bool *result); - /** * Load a save state from a buffer. * diff --git a/engines/tony/mpal/mpaldll.h b/engines/tony/mpal/mpaldll.h index 8897096f51..92ddf8fc5a 100644 --- a/engines/tony/mpal/mpaldll.h +++ b/engines/tony/mpal/mpaldll.h @@ -73,7 +73,7 @@ namespace MPAL { * MPAL global variables */ struct MpalVar { - uint32 _dwVal; // Variable value + uint32 _dwVal; // Variable value char _lpszVarName[33]; // Variable name } PACKED_STRUCT; typedef MpalVar *LpMpalVar; @@ -82,8 +82,8 @@ typedef MpalVar *LpMpalVar; * MPAL Messages */ struct MpalMsg { - MpalHandle _hText; // Handle to the message text - uint16 _wNum; // Message number + MpalHandle _hText; // Handle to the message text + uint16 _wNum; // Message number } PACKED_STRUCT; typedef MpalMsg *LpMpalMsg; @@ -91,9 +91,9 @@ typedef MpalMsg *LpMpalMsg; * MPAL Locations */ struct MpalLocation { - uint32 _nObj; // Location number - uint32 _dwXlen, _dwYlen; // Dimensions - uint32 _dwPicRes; // Resource that contains the image + uint32 _nObj; // Location number + uint32 _dwXlen, _dwYlen; // Dimensions + uint32 _dwPicRes; // Resource that contains the image } PACKED_STRUCT; typedef MpalLocation *LpMpalLocation; @@ -110,34 +110,33 @@ struct Command { * #3 -> Making a choice (DIALOG) * */ - byte _type; // Type of control + byte _type; // Type of control union { - int32 _nCf; // Custom function call [#1] - char *_lpszVarName; // Variable name [#2] - int32 _nChoice; // Number of choice you make [#3] + int32 _nCf; // Custom function call [#1] + char *_lpszVarName; // Variable name [#2] + int32 _nChoice; // Number of choice you make [#3] }; union { - int32 _arg1; // Argument for custom function [#1] - MpalHandle _expr; // Expression to assign to a variable [#2] + int32 _arg1; // Argument for custom function [#1] + MpalHandle _expr; // Expression to assign to a variable [#2] }; - int32 _arg2, _arg3, _arg4; // Arguments for custom function [#1] + int32 _arg2, _arg3, _arg4; // Arguments for custom function [#1] } PACKED_STRUCT; - /** * MPAL dialog */ struct MpalDialog { - uint32 _nObj; // Dialog number + uint32 _nObj; // Dialog number struct Command _command[MAX_COMMANDS_PER_DIALOG]; struct { uint16 _num; - byte _nCmds; + byte _nCmds; uint16 _cmdNum[MAX_COMMANDS_PER_GROUP]; } _group[MAX_GROUPS_PER_DIALOG]; @@ -152,7 +151,7 @@ struct MpalDialog { uint32 _dwData; uint16 _wPlayGroup[MAX_PLAYGROUPS_PER_SELECT]; - // Bit 0=endchoice Bit 1=enddialog + // Bit 0=endchoice Bit 1=enddialog byte _attr; // Modified at run-time: 0 if the select is currently disabled, @@ -172,23 +171,22 @@ typedef MpalDialog *LpMpalDialog; * MPAL Item */ struct ItemAction { - byte _num; // Action number - uint16 _wTime; // If idle, the time which must pass - byte _perc; // Percentage of the idle run - MpalHandle _when; // Expression to compute. If != 0, then - // action can be done - uint16 _wParm; // Parameter for action - - byte _nCmds; // Number of commands to be executed - uint32 _cmdNum[MAX_COMMANDS_PER_ACTION]; // Commands to execute + byte _num; // Action number + uint16 _wTime; // If idle, the time which must pass + byte _perc; // Percentage of the idle run + MpalHandle _when; // Expression to compute. If != 0, then action can be done + uint16 _wParm; // Parameter for action + + byte _nCmds; // Number of commands to be executed + uint32 _cmdNum[MAX_COMMANDS_PER_ACTION]; // Commands to execute } PACKED_STRUCT; struct MpalItem { - uint32 _nObj; // Item number + uint32 _nObj; // Item number byte _lpszDescribe[MAX_DESCRIBE_SIZE]; // Name - byte _nActions; // Number of managed actions - uint32 _dwRes; // Resource that contains frames and patterns + byte _nActions; // Number of managed actions + uint32 _dwRes; // Resource that contains frames and patterns struct Command _command[MAX_COMMANDS_PER_ITEM]; @@ -209,14 +207,14 @@ struct MpalScript { struct Command _command[MAX_COMMANDS_PER_SCRIPT]; struct { - int32 _dwTime; - byte _nCmds; + int32 _dwTime; + byte _nCmds; uint32 _cmdNum[MAX_COMMANDS_PER_MOMENT]; } _moment[MAX_MOMENTS_PER_SCRIPT]; } PACKED_STRUCT; -typedef MpalScript *LpMpalScript; +typedef MpalScript *LpMpalScript; #include "common/pack-end.h" @@ -235,7 +233,6 @@ typedef MpalScript *LpMpalScript; */ extern int32 varGetValue(const char *lpszVarName); - /** * Sets the value of a MPAL global variable * @param lpszVarName Name of the variable diff --git a/engines/tony/mpal/mpalutils.h b/engines/tony/mpal/mpalutils.h index d92bb6f9a2..f351f22196 100644 --- a/engines/tony/mpal/mpalutils.h +++ b/engines/tony/mpal/mpalutils.h @@ -38,19 +38,19 @@ namespace MPAL { class RMRes { protected: MpalHandle _h; - byte *_buf; + byte *_buf; public: RMRes(uint32 resID); - virtual ~RMRes(); + virtual ~RMRes(); - // Attributes + // Attributes unsigned int size(); - const byte *dataPointer(); + const byte *dataPointer(); bool isValid(); - // Casting for access to data - operator const byte*(); + // Casting for access to data + operator const byte*(); Common::SeekableReadStream *getReadStream(); }; diff --git a/engines/tony/resid.h b/engines/tony/resid.h index f4d2c9a4fa..0d601b7dd6 100644 --- a/engines/tony/resid.h +++ b/engines/tony/resid.h @@ -30,7 +30,6 @@ #ifndef TONY_RESID_H #define TONY_RESID_H - #define RES_I_INTERFACE 10300 #define RES_I_INTERPAL 10301 #define RES_I_INTERPPAL 10302 @@ -40,16 +39,16 @@ #define RES_I_INTERP4 10306 #define RES_I_INTERP5 10307 -#define RES_I_DLGTEXT 10350 +#define RES_I_DLGTEXT 10350 #define RES_I_DLGTEXTLINE 10351 -#define RES_I_DLGTEXTPAL 10352 +#define RES_I_DLGTEXTPAL 10352 #define RES_I_MINIINTER 10360 -#define RES_P_PAL 10410 -#define RES_P_GO 10400 +#define RES_P_PAL 10410 +#define RES_P_GO 10400 #define RES_P_TAKE 10401 -#define RES_P_USE 10402 +#define RES_P_USE 10402 #define RES_P_EXAM 10403 #define RES_P_TALK 10404 diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp index 20386d6353..90ae241db0 100644 --- a/engines/tony/sound.cpp +++ b/engines/tony/sound.cpp @@ -36,6 +36,19 @@ namespace Tony { +/* + * Tony uses a [0,63] volume scale (where 0 is silent and 63 is loudest). + * The original game engine linearly mapped this scale into DirectSound's + * [-10000, 0] scale (where -10000 is silent), which is a logarithmic scale. + * + * This means that Tony's scale is logarithmic as well, and must be converted + * to the linear scale used by the mixer. + */ +static int remapVolume(int volume) { + double dsvol = (double)(63 - volume) * -10000.0 / 63.0; + return (int)((double)Audio::Mixer::kMaxChannelVolume * pow(10.0, dsvol / 2000.0) + 0.5); +} + /****************************************************************************\ * FPSOUND Methods \****************************************************************************/ @@ -62,7 +75,6 @@ bool FPSound::init() { * Destroy the object and free the memory * */ - FPSound::~FPSound() { } @@ -73,7 +85,6 @@ FPSound::~FPSound() { * * @returns True is everything is OK, False otherwise */ - bool FPSound::createStream(FPStream **streamPtr) { (*streamPtr) = new FPStream(_soundSupported); @@ -87,7 +98,6 @@ bool FPSound::createStream(FPStream **streamPtr) { * * @returns True is everything is OK, False otherwise */ - bool FPSound::createSfx(FPSfx **sfxPtr) { (*sfxPtr) = new FPSfx(_soundSupported); @@ -99,11 +109,13 @@ bool FPSound::createSfx(FPSfx **sfxPtr) { * * @param volume Volume to set (0-63) */ - void FPSound::setMasterVolume(int volume) { if (!_soundSupported) return; + // WORKAROUND: We don't use remapVolume() here, so that the main option screen exposes + // a linear scale to the user. This is an improvement over the original game + // where the user had to deal with a logarithmic volume scale. g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, CLIP<int>(volume, 0, 63) * Audio::Mixer::kMaxChannelVolume / 63); } @@ -112,7 +124,6 @@ void FPSound::setMasterVolume(int volume) { * * @param volumePtr Variable that will contain the volume (0-63) */ - void FPSound::getMasterVolume(int *volumePtr) { if (!_soundSupported) return; @@ -127,7 +138,6 @@ void FPSound::getMasterVolume(int *volumePtr) { * create it using FPSound::CreateSfx() * */ - FPSfx::FPSfx(bool soundOn) { _soundSupported = soundOn; _fileLoaded = false; @@ -148,7 +158,6 @@ FPSfx::FPSfx(bool soundOn) { * currently played, and free the memory it uses. * */ - FPSfx::~FPSfx() { if (!_soundSupported) return; @@ -173,7 +182,6 @@ FPSfx::~FPSfx() { * FPSound::CreateStream(). * Object pointers are no longer valid after this call. */ - void FPSfx::release() { delete this; } @@ -215,7 +223,6 @@ bool FPSfx::loadVoiceFromVDB(Common::File &vdbFP) { * * @returns True is everything is OK, False otherwise */ - bool FPSfx::loadFile(const char *fileName, uint32 codec) { if (!_soundSupported) return true; @@ -256,7 +263,6 @@ bool FPSfx::loadFile(const char *fileName, uint32 codec) { * * @returns True is everything is OK, False otherwise */ - bool FPSfx::play() { stop(); // sanity check @@ -291,7 +297,6 @@ bool FPSfx::play() { * * @returns True is everything is OK, False otherwise */ - bool FPSfx::stop() { if (_fileLoaded) { g_system->getMixer()->stopHandle(_handle); @@ -310,7 +315,6 @@ bool FPSfx::stop() { * playing. Any changes made during the play will have * no effect until the sfx is stopped then played again. */ - void FPSfx::setLoop(bool loop) { _loop = loop; } @@ -319,7 +323,6 @@ void FPSfx::setLoop(bool loop) { * Pauses a Sfx. * */ - void FPSfx::setPause(bool pause) { if (_fileLoaded) { if (g_system->getMixer()->isSoundHandleActive(_handle) && (pause ^ _paused)) @@ -335,7 +338,6 @@ void FPSfx::setPause(bool pause) { * @param volume Volume to be set (0-63) * */ - void FPSfx::setVolume(int volume) { if (volume > 63) volume = 63; @@ -364,7 +366,7 @@ void FPSfx::setVolume(int volume) { } if (g_system->getMixer()->isSoundHandleActive(_handle)) - g_system->getMixer()->setChannelVolume(_handle, volume * Audio::Mixer::kMaxChannelVolume / 63); + g_system->getMixer()->setChannelVolume(_handle, remapVolume(volume)); } /** @@ -373,10 +375,9 @@ void FPSfx::setVolume(int volume) { * @param volumePtr Will contain the current Sfx volume * */ - void FPSfx::getVolume(int *volumePtr) { if (g_system->getMixer()->isSoundHandleActive(_handle)) - *volumePtr = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume; + *volumePtr = _lastVolume; else *volumePtr = 0; } @@ -384,7 +385,6 @@ void FPSfx::getVolume(int *volumePtr) { /** * Returns true if the underlying sound has ended */ - bool FPSfx::endOfBuffer() const { return !g_system->getMixer()->isSoundHandleActive(_handle) && (!_rewindableStream || _rewindableStream->endOfData()); } @@ -440,7 +440,6 @@ FPStream::FPStream(bool soundOn) { * * @remarks It calls CloseFile() if needed. */ - FPStream::~FPStream() { if (!_soundSupported) return; @@ -583,7 +582,6 @@ bool FPStream::play() { * @returns True is everything is OK, False otherwise * */ - bool FPStream::stop() { if (!_soundSupported) return true; @@ -650,7 +648,6 @@ void FPStream::setPause(bool pause) { * @param volume Volume to be set (0-63) * */ - void FPStream::setVolume(int volume) { if (volume > 63) volume = 63; @@ -669,7 +666,7 @@ void FPStream::setVolume(int volume) { } if (g_system->getMixer()->isSoundHandleActive(_handle)) - g_system->getMixer()->setChannelVolume(_handle, volume * Audio::Mixer::kMaxChannelVolume / 63); + g_system->getMixer()->setChannelVolume(_handle, remapVolume(volume)); } /** @@ -678,10 +675,9 @@ void FPStream::setVolume(int volume) { * @param volumePtr Variable that will contain the current volume * */ - void FPStream::getVolume(int *volumePtr) { if (g_system->getMixer()->isSoundHandleActive(_handle)) - *volumePtr = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume; + *volumePtr = _lastVolume; else *volumePtr = 0; } diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index 86740c6fe5..43a2f639d9 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -732,6 +732,7 @@ uint32 TonyEngine::getTime() { bool TonyEngine::canLoadGameStateCurrently() { return GLOBALS._gfxEngine != NULL && GLOBALS._gfxEngine->canLoadSave(); } + bool TonyEngine::canSaveGameStateCurrently() { return GLOBALS._gfxEngine != NULL && GLOBALS._gfxEngine->canLoadSave(); } diff --git a/engines/tony/tony.h b/engines/tony/tony.h index 332b122923..750673061d 100644 --- a/engines/tony/tony.h +++ b/engines/tony/tony.h @@ -69,7 +69,7 @@ enum { struct TonyGameDescription; -#define MAX_SFX_CHANNELS 32 +#define MAX_SFX_CHANNELS 32 #define TONY_DAT_VER_MAJ 0 #define TONY_DAT_VER_MIN 3 diff --git a/engines/tony/tonychar.cpp b/engines/tony/tonychar.cpp index c7fa1e4a7b..46c018728e 100644 --- a/engines/tony/tonychar.cpp +++ b/engines/tony/tonychar.cpp @@ -120,7 +120,7 @@ void RMTony::init() { void RMTony::close() { // Deallocation of missing item -// _shadow.destroy(); + //_shadow.destroy(); } void RMTony::doFrame(CORO_PARAM, RMGfxTargetBuffer *bigBuf, int curLoc) { @@ -165,7 +165,6 @@ void RMTony::hide(bool bShowShadow) { _bShowShadow = bShowShadow; } - void RMTony::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -231,7 +230,6 @@ void RMTony::moveAndDoAction(CORO_PARAM, RMPoint dst, RMItem *item, int nAction, CORO_END_CODE; } - void RMTony::executeAction(int nAction, int nActionItem, int nParm) { uint32 pid; @@ -281,7 +279,6 @@ void RMTony::executeAction(int nAction, int nActionItem, int nParm) { } } - void RMTony::stopNoAction(CORO_PARAM) { CORO_BEGIN_CONTEXT; CORO_END_CONTEXT(_ctx); @@ -332,7 +329,6 @@ void RMTony::stop(CORO_PARAM) { CORO_END_CODE; } - int RMTony::getCurPattern() { int nPatt = RMCharacter::getCurPattern(); @@ -394,7 +390,6 @@ void RMTony::setPattern(int nPatt, bool bPlayP0) { RMCharacter::setPattern(nPatt, bPlayP0); } - void RMTony::take(int nWhere, int nPart) { if (nPart == 0) { switch (getCurPattern()) { @@ -469,7 +464,6 @@ void RMTony::take(int nWhere, int nPart) { } } - void RMTony::put(int nWhere, int nPart) { if (nPart == 0) { switch (getCurPattern()) { @@ -543,7 +537,6 @@ void RMTony::put(int nWhere, int nPart) { } } - bool RMTony::startTalkCalculate(CharacterTalkType nTalkType, int &headStartPat, int &bodyStartPat, int &headLoopPat, int &bodyLoopPat) { assert(!_bIsTalking); @@ -1132,7 +1125,6 @@ void RMTony::startTalk(CORO_PARAM, CharacterTalkType nTalkType) { CORO_END_CODE; } - bool RMTony::endTalkCalculate(int &headStandPat, int &headEndPat, int &bodyEndPat, int &finalPat, bool &bStatic) { bodyEndPat = 0; headEndPat = 0; diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp index c9c450424f..61497a8066 100644 --- a/engines/tony/window.cpp +++ b/engines/tony/window.cpp @@ -35,7 +35,6 @@ namespace Tony { - /****************************************************************************\ * RMWindow Methods \****************************************************************************/ @@ -111,7 +110,7 @@ void RMWindow::repaint() { */ void RMWindow::wipeEffect(Common::Rect &rcBoundEllipse) { if ((rcBoundEllipse.left == 0) && (rcBoundEllipse.top == 0) && - (rcBoundEllipse.right == RM_SX) && (rcBoundEllipse.bottom == RM_SY)) { + (rcBoundEllipse.right == RM_SX) && (rcBoundEllipse.bottom == RM_SY)) { // Full screen clear wanted, so use shortcut method g_system->fillScreen(0); } else { diff --git a/engines/tony/window.h b/engines/tony/window.h index 2e8769707f..3874652f64 100644 --- a/engines/tony/window.h +++ b/engines/tony/window.h @@ -46,7 +46,6 @@ public: void grabScreenshot(byte *lpBuf, int dezoom = 1, uint16 *lpDestBuf = NULL); }; - class RMWindow { private: void plotSplices(const byte *lpBuf, const Common::Point ¢er, int x, int y); diff --git a/engines/toon/toon.h b/engines/toon/toon.h index d40c489011..0ff351804f 100644 --- a/engines/toon/toon.h +++ b/engines/toon/toon.h @@ -316,12 +316,11 @@ public: } Common::Error saveGameState(int slot, const Common::String &desc) { - - return (saveGame(slot, desc) ? Common::kWritingFailed : Common::kNoError); + return (saveGame(slot, desc) ? Common::kNoError : Common::kWritingFailed); } Common::Error loadGameState(int slot) { - return (loadGame(slot) ? Common::kReadingFailed : Common::kNoError); + return (loadGame(slot) ? Common::kNoError : Common::kReadingFailed); } bool hasFeature(EngineFeature f) const { diff --git a/engines/touche/console.cpp b/engines/touche/console.cpp index 51ef5fc639..2c4c6a0da1 100644 --- a/engines/touche/console.cpp +++ b/engines/touche/console.cpp @@ -26,9 +26,28 @@ namespace Touche { ToucheConsole::ToucheConsole(ToucheEngine *vm) : GUI::Debugger(), _vm(vm) { + DCmd_Register("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic)); + DCmd_Register("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic)); } ToucheConsole::~ToucheConsole() { } +bool ToucheConsole::Cmd_StartMusic(int argc, const char **argv) { + if (argc != 2) { + DebugPrintf("Usage: startMusic <num>\n"); + return true; + } + + int num = atoi(argv[1]); + + _vm->startMusic(num); + return false; +} + +bool ToucheConsole::Cmd_StopMusic(int argc, const char **argv) { + _vm->stopMusic(); + return false; +} + } // End of namespace Touche diff --git a/engines/touche/console.h b/engines/touche/console.h index e3cdc9d48b..43a303ad77 100644 --- a/engines/touche/console.h +++ b/engines/touche/console.h @@ -36,6 +36,9 @@ public: private: ToucheEngine *_vm; + + bool Cmd_StartMusic(int argc, const char **argv); + bool Cmd_StopMusic(int argc, const char **argv); }; } // End of namespace Touche diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp index c58e2f1a33..85ca519f05 100644 --- a/engines/touche/menu.cpp +++ b/engines/touche/menu.cpp @@ -103,7 +103,7 @@ struct MenuData { void addCharToDescription(int slot, char chr) { char *description = saveLoadDescriptionsTable[slot]; int descriptionLen = strlen(description); - if (descriptionLen < 32 && isprint(static_cast<unsigned char>(chr))) { + if (descriptionLen < 32 && Common::isPrint(chr)) { description[descriptionLen] = chr; description[descriptionLen + 1] = 0; } @@ -260,7 +260,7 @@ void ToucheEngine::redrawMenu(void *menu) { Graphics::drawRect(_offscreenBuffer, kScreenWidth, 106, 118, 340, 164, 0xF9, 0xF7); switch (menuData->mode) { case kMenuSettingsMode: - drawVolumeSlideBar(_offscreenBuffer, kScreenWidth, _midiPlayer->getVolume()); + drawVolumeSlideBar(_offscreenBuffer, kScreenWidth, getMusicVolume()); menuData->buttonsTable[5].data = 0; menuData->buttonsTable[6].data = 0; menuData->buttonsTable[7].data = 0; @@ -307,10 +307,10 @@ void ToucheEngine::handleMenuAction(void *menu, int actionId) { _talkTextMode = kTalkModeVoiceAndText; break; case kActionLowerVolume: - _midiPlayer->adjustVolume(-16); + adjustMusicVolume(-16); break; case kActionUpperVolume: - _midiPlayer->adjustVolume(+16); + adjustMusicVolume(+16); break; case kActionScrollUpSaves: --_saveLoadCurrentPage; diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp index 0790d726b7..9625224316 100644 --- a/engines/touche/resource.cpp +++ b/engines/touche/resource.cpp @@ -610,10 +610,7 @@ void ToucheEngine::res_stopSound() { void ToucheEngine::res_loadMusic(int num) { debugC(9, kDebugResource, "ToucheEngine::res_loadMusic() num=%d", num); - uint32 size; - const uint32 offs = res_getDataOffset(kResourceTypeMusic, num, &size); - _fData.seek(offs); - _midiPlayer->play(_fData, size, true); + startMusic(num); } void ToucheEngine::res_loadSpeech(int num) { diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 4b989963f6..5c133ccbc6 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -32,6 +32,8 @@ #include "common/keyboard.h" #include "common/textconsole.h" +#include "audio/mixer.h" + #include "engines/util.h" #include "graphics/cursorman.h" #include "graphics/palette.h" @@ -58,6 +60,8 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _playSoundCounter = 0; + _musicVolume = 0; + _processRandomPaletteCounter = 0; _fastWalkMode = false; @@ -90,6 +94,7 @@ ToucheEngine::~ToucheEngine() { DebugMan.clearAllDebugChannels(); delete _console; + stopMusic(); delete _midiPlayer; } @@ -100,7 +105,7 @@ Common::Error ToucheEngine::run() { setupOpcodes(); - _midiPlayer = new MidiPlayer; + initMusic(); // Setup mixer syncSoundSettings(); @@ -120,7 +125,7 @@ Common::Error ToucheEngine::run() { } void ToucheEngine::restart() { - _midiPlayer->stop(); + stopMusic(); _gameState = kGameStateGameLoop; _displayQuitDialog = false; @@ -216,7 +221,7 @@ void ToucheEngine::readConfigurationSettings() { _talkTextMode = kTalkModeVoiceOnly; } } - _midiPlayer->setVolume(ConfMan.getInt("music_volume")); + setMusicVolume(ConfMan.getInt("music_volume")); } void ToucheEngine::writeConfigurationSettings() { @@ -234,7 +239,7 @@ void ToucheEngine::writeConfigurationSettings() { ConfMan.setBool("subtitles", true); break; } - ConfMan.setInt("music_volume", _midiPlayer->getVolume()); + ConfMan.setInt("music_volume", getMusicVolume()); ConfMan.flushToDisk(); } @@ -3307,4 +3312,80 @@ bool ToucheEngine::canSaveGameStateCurrently() { return _gameState == kGameStateGameLoop && _flagsTable[618] == 0 && !_hideInventoryTexts; } +void ToucheEngine::initMusic() { + // Detect External Music Files + bool extMusic = true; + for (int num = 0; num < 26 && extMusic; num++) { + Common::String extMusicFilename = Common::String::format("track%02d", num+1); + Audio::SeekableAudioStream *musicStream = Audio::SeekableAudioStream::openStreamFile(extMusicFilename); + if (!musicStream) + extMusic = false; + delete musicStream; + } + + if (!extMusic) { + _midiPlayer = new MidiPlayer; + debug(1, "initMusic(): Using midi music!"); + } else + debug(1, "initMusic(): Using external digital music!"); +} + +void ToucheEngine::startMusic(int num) { + debug(1, "startMusic(%d)", num); + uint32 size; + + stopMusic(); + + if (_midiPlayer) { + const uint32 offs = res_getDataOffset(kResourceTypeMusic, num, &size); + _fData.seek(offs); + _midiPlayer->play(_fData, size, true); + } else { + Common::String extMusicFilename = Common::String::format("track%02d", num); + Audio::SeekableAudioStream *extMusicFileStream = Audio::SeekableAudioStream::openStreamFile(extMusicFilename); + if (!extMusicFileStream) { + error("Unable to open %s for reading", extMusicFilename.c_str()); + } + Audio::LoopingAudioStream *loopStream = new Audio::LoopingAudioStream(extMusicFileStream, 0); + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, loopStream, -1, _musicVolume); + } +} + +void ToucheEngine::stopMusic() { + debug(1, "stopMusic()"); + if (_midiPlayer) + _midiPlayer->stop(); + else { + _mixer->stopHandle(_musicHandle); + } +} + +int ToucheEngine::getMusicVolume() { + if (_midiPlayer) + _musicVolume = _midiPlayer->getVolume(); + return _musicVolume; +} + +void ToucheEngine::setMusicVolume(int volume) { + debug(1, "setMusicVolume(%d)", volume); + _musicVolume = CLIP(volume, 0, 255); + + if (_midiPlayer) + _midiPlayer->setVolume(_musicVolume); + else { + _mixer->setChannelVolume(_musicHandle, _musicVolume); + } +} + +void ToucheEngine::adjustMusicVolume(int diff) { + debug(1, "adjustMusicVolume(%d)", diff); + _musicVolume = CLIP(_musicVolume + diff, 0, 255); + + if (_midiPlayer) + _midiPlayer->adjustVolume(diff); + else { + _mixer->setChannelVolume(_musicHandle, _musicVolume); + } +} + } // namespace Touche diff --git a/engines/touche/touche.h b/engines/touche/touche.h index 949727b665..6ac43e7dfe 100644 --- a/engines/touche/touche.h +++ b/engines/touche/touche.h @@ -31,6 +31,7 @@ #include "common/util.h" #include "audio/mixer.h" +#include "audio/audiostream.h" #include "engines/engine.h" @@ -646,6 +647,18 @@ protected: MidiPlayer *_midiPlayer; + int _musicVolume; + Audio::SoundHandle _musicHandle; + + void initMusic(); +public: // To allow access from console + void startMusic(int num); + void stopMusic(); +protected: + int getMusicVolume(); + void setMusicVolume(int volume); + void adjustMusicVolume(int diff); + Common::Language _language; Common::RandomSource _rnd; diff --git a/engines/tsage/events.h b/engines/tsage/events.h index 475db47315..a1e9da3477 100644 --- a/engines/tsage/events.h +++ b/engines/tsage/events.h @@ -32,7 +32,7 @@ namespace TsAGE { enum EventType {EVENT_NONE = 0, EVENT_BUTTON_DOWN = 1, EVENT_BUTTON_UP = 2, EVENT_KEYPRESS = 4, - EVENT_MOUSE_MOVE = 8}; + EVENT_MOUSE_MOVE = 8, EVENT_UNK27 = 27}; enum ButtonShiftFlags {BTNSHIFT_LEFT = 0, BTNSHIFT_RIGHT = 3, BTNSHIFT_MIDDLE = 4}; diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp index 4c98fcf00a..3b7d283e44 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp @@ -61,14 +61,10 @@ void Scene50::postInit(SceneObjectList *OwnerList) { } void Scene50::process(Event &event) { - if ((event.eventType != EVENT_BUTTON_DOWN) && (event.eventType != EVENT_KEYPRESS) && (event.eventType == 27)) { + if ((event.eventType != EVENT_BUTTON_DOWN) && (event.eventType != EVENT_KEYPRESS) && (event.eventType == EVENT_UNK27)) { event.handled = true; - warning("TODO: incomplete Scene50::process()"); - // CursorType _oldCursorId = _cursorId; g_globals->_events.setCursor(CURSOR_ARROW); - // _cursorManager.sub_1D474(2, 0); - // sub_5566A(1); - // _cursorManager._fieldE = _oldCursorId; + HelpDialog::show(); R2_GLOBALS._sceneManager.changeScene(100); } } diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp index d175855d1e..1346a090f6 100644 --- a/engines/wintermute/ad/ad_actor.cpp +++ b/engines/wintermute/ad/ad_actor.cpp @@ -57,15 +57,15 @@ AdActor::AdActor(BaseGame *inGame) : AdTalkHolder(inGame) { _type = OBJECT_ACTOR; _dir = DI_LEFT; - _walkSprite = NULL; - _standSprite = NULL; - _turnLeftSprite = NULL; - _turnRightSprite = NULL; + _walkSprite = nullptr; + _standSprite = nullptr; + _turnLeftSprite = nullptr; + _turnRightSprite = nullptr; _targetPoint = new BasePoint; _afterWalkDir = DI_NONE; - _animSprite2 = NULL; + _animSprite2 = nullptr; setDefaultAnimNames(); } @@ -84,19 +84,19 @@ bool AdActor::setDefaultAnimNames() { AdActor::~AdActor() { delete _path; delete _targetPoint; - _path = NULL; - _targetPoint = NULL; + _path = nullptr; + _targetPoint = nullptr; delete _walkSprite; delete _standSprite; delete _turnLeftSprite; delete _turnRightSprite; - _walkSprite = NULL; - _standSprite = NULL; - _turnLeftSprite = NULL; - _turnRightSprite = NULL; + _walkSprite = nullptr; + _standSprite = nullptr; + _turnLeftSprite = nullptr; + _turnRightSprite = nullptr; - _animSprite2 = NULL; // ref only + _animSprite2 = nullptr; // ref only for (uint32 i = 0; i < _talkSprites.size(); i++) { delete _talkSprites[i]; @@ -110,7 +110,7 @@ AdActor::~AdActor() { for (uint32 i = 0; i < _anims.size(); i++) { delete _anims[i]; - _anims[i] = NULL; + _anims[i] = nullptr; } _anims.clear(); @@ -120,7 +120,7 @@ AdActor::~AdActor() { ////////////////////////////////////////////////////////////////////////// bool AdActor::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdActor::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -232,7 +232,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { } AdGame *adGame = (AdGame *)_gameRef; - AdSpriteSet *spr = NULL; + AdSpriteSet *spr = nullptr; int ar = 0, ag = 0, ab = 0, alpha = 0; while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { switch (cmd) { @@ -287,7 +287,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { case TOKEN_WALK: delete _walkSprite; - _walkSprite = NULL; + _walkSprite = nullptr; spr = new AdSpriteSet(_gameRef, this); if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texWalkLifeTime, CACHE_HALF))) { cmd = PARSERR_GENERIC; @@ -316,7 +316,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { case TOKEN_STAND: delete _standSprite; - _standSprite = NULL; + _standSprite = nullptr; spr = new AdSpriteSet(_gameRef, this); if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texStandLifeTime))) { cmd = PARSERR_GENERIC; @@ -327,7 +327,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { case TOKEN_TURN_LEFT: delete _turnLeftSprite; - _turnLeftSprite = NULL; + _turnLeftSprite = nullptr; spr = new AdSpriteSet(_gameRef, this); if (!spr || DID_FAIL(spr->loadBuffer(params, true))) { cmd = PARSERR_GENERIC; @@ -338,7 +338,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { case TOKEN_TURN_RIGHT: delete _turnRightSprite; - _turnRightSprite = NULL; + _turnRightSprite = nullptr; spr = new AdSpriteSet(_gameRef, this); if (!spr || DID_FAIL(spr->loadBuffer(params, true))) { cmd = PARSERR_GENERIC; @@ -356,7 +356,7 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -392,15 +392,15 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { case TOKEN_BLOCKED_REGION: { delete _blockRegion; delete _currentBlockRegion; - _blockRegion = NULL; - _currentBlockRegion = NULL; + _blockRegion = nullptr; + _currentBlockRegion = nullptr; BaseRegion *rgn = new BaseRegion(_gameRef); BaseRegion *crgn = new BaseRegion(_gameRef); if (!rgn || !crgn || DID_FAIL(rgn->loadBuffer(params, false))) { delete _blockRegion; delete _currentBlockRegion; - _blockRegion = NULL; - _currentBlockRegion = NULL; + _blockRegion = nullptr; + _currentBlockRegion = nullptr; cmd = PARSERR_GENERIC; } else { _blockRegion = rgn; @@ -413,15 +413,15 @@ bool AdActor::loadBuffer(byte *buffer, bool complete) { case TOKEN_WAYPOINTS: { delete _wptGroup; delete _currentWptGroup; - _wptGroup = NULL; - _currentWptGroup = NULL; + _wptGroup = nullptr; + _currentWptGroup = nullptr; AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); AdWaypointGroup *cwpt = new AdWaypointGroup(_gameRef); if (!wpt || !cwpt || DID_FAIL(wpt->loadBuffer(params, false))) { delete _wptGroup; delete _currentWptGroup; - _wptGroup = NULL; - _currentWptGroup = NULL; + _wptGroup = nullptr; + _currentWptGroup = nullptr; cmd = PARSERR_GENERIC; } else { _wptGroup = wpt; @@ -502,7 +502,7 @@ void AdActor::turnTo(TDirection dir) { _targetDir = dir; _state = delta < 0 ? STATE_TURNING_LEFT : STATE_TURNING_RIGHT; - _tempSprite2 = NULL; + _tempSprite2 = nullptr; } @@ -566,7 +566,7 @@ bool AdActor::display() { _currentSprite->display(_posX, _posY, - reg ? _registerAlias : NULL, + reg ? _registerAlias : nullptr, scaleX, scaleY, alpha, @@ -589,26 +589,26 @@ bool AdActor::display() { ////////////////////////////////////////////////////////////////////////// bool AdActor::update() { - _currentSprite = NULL; + _currentSprite = nullptr; if (_state == STATE_READY) { if (_animSprite) { delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; } if (_animSprite2) { - _animSprite2 = NULL; + _animSprite2 = nullptr; } } // finished playing animation? - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->isFinished()) { + if (_state == STATE_PLAYING_ANIM && _animSprite != nullptr && _animSprite->isFinished()) { _state = _nextState; _nextState = STATE_READY; _currentSprite = _animSprite; } - if (_state == STATE_PLAYING_ANIM_SET && _animSprite2 != NULL && _animSprite2->isFinished()) { + if (_state == STATE_PLAYING_ANIM_SET && _animSprite2 != nullptr && _animSprite2->isFinished()) { _state = _nextState; _nextState = STATE_READY; _currentSprite = _animSprite2; @@ -649,7 +649,7 @@ bool AdActor::update() { ////////////////////////////////////////////////////////////////////////// case STATE_TURNING_LEFT: - if (_tempSprite2 == NULL || _tempSprite2->isFinished()) { + if (_tempSprite2 == nullptr || _tempSprite2->isFinished()) { if (_dir > 0) { _dir = (TDirection)(_dir - 1); } else { @@ -657,7 +657,7 @@ bool AdActor::update() { } if (_dir == _targetDir) { - _tempSprite2 = NULL; + _tempSprite2 = nullptr; _state = _nextState; _nextState = STATE_READY; } else { @@ -686,7 +686,7 @@ bool AdActor::update() { ////////////////////////////////////////////////////////////////////////// case STATE_TURNING_RIGHT: - if (_tempSprite2 == NULL || _tempSprite2->isFinished()) { + if (_tempSprite2 == nullptr || _tempSprite2->isFinished()) { _dir = (TDirection)(_dir + 1); if ((int)_dir >= (int)NUM_DIRECTIONS) { @@ -694,7 +694,7 @@ bool AdActor::update() { } if (_dir == _targetDir) { - _tempSprite2 = NULL; + _tempSprite2 = nullptr; _state = _nextState; _nextState = STATE_READY; } else { @@ -753,10 +753,10 @@ bool AdActor::update() { } bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); - if (_tempSprite2 == NULL || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) { + if (_tempSprite2 == nullptr || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) { if (timeIsUp) { _sentence->finish(); - _tempSprite2 = NULL; + _tempSprite2 = nullptr; _state = _nextState; _nextState = STATE_READY; } else { @@ -821,7 +821,7 @@ bool AdActor::update() { void AdActor::followPath() { // skip current position _path->getFirst(); - while (_path->getCurrent() != NULL) { + while (_path->getCurrent() != nullptr) { if (_path->getCurrent()->x != _posX || _path->getCurrent()->y != _posY) { break; } @@ -829,7 +829,7 @@ void AdActor::followPath() { } // are there points to follow? - if (_path->getCurrent() != NULL) { + if (_path->getCurrent() != nullptr) { _state = STATE_FOLLOWING_PATH; initLine(BasePoint(_posX, _posY), *_path->getCurrent()); } else { @@ -896,7 +896,7 @@ void AdActor::getNextStep() { if (_pFCount == 0) { - if (_path->getNext() == NULL) { + if (_path->getNext() == nullptr) { _posX = _targetPoint->x; _posY = _targetPoint->y; @@ -963,16 +963,16 @@ bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, return STATUS_OK; } AdObject *obj = (AdObject *)val->getNative(); - if (!obj || obj->_type != OBJECT_ENTITY) { + if (!obj || obj->getType() != OBJECT_ENTITY) { script->runtimeError("actor.%s method accepts an entity refrence only", name); stack->pushNULL(); return STATUS_OK; } AdEntity *ent = (AdEntity *)obj; - if (ent->_walkToX == 0 && ent->_walkToY == 0) { + if (ent->getWalkToX() == 0 && ent->getWalkToY() == 0) { goTo(ent->_posX, ent->_posY); } else { - goTo(ent->_walkToX, ent->_walkToY, ent->_walkToDir); + goTo(ent->getWalkToX(), ent->getWalkToY(), ent->getWalkToDir()); } if (strcmp(name, "GoToObjectAsync") != 0) { script->waitForExclusive(this); @@ -1040,17 +1040,17 @@ bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, if (scumm_stricmp(_anims[i]->getName(), animName) == 0) { // invalidate sprites in use if (_anims[i]->containsSprite(_tempSprite2)) { - _tempSprite2 = NULL; + _tempSprite2 = nullptr; } if (_anims[i]->containsSprite(_currentSprite)) { - _currentSprite = NULL; + _currentSprite = nullptr; } if (_anims[i]->containsSprite(_animSprite2)) { - _animSprite2 = NULL; + _animSprite2 = nullptr; } delete _anims[i]; - _anims[i] = NULL; + _anims[i] = nullptr; _anims.remove_at(i); i--; found = true; @@ -1066,7 +1066,7 @@ bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, else if (strcmp(name, "HasAnim") == 0) { stack->correctParams(1); const char *animName = stack->pop()->getString(); - stack->pushBool(getAnimByName(animName) != NULL); + stack->pushBool(getAnimByName(animName) != nullptr); return STATUS_OK; } else { return AdTalkHolder::scCallMethod(script, stack, thisStack, name); @@ -1231,7 +1231,7 @@ BaseSprite *AdActor::getTalkStance(const char *stance) { if (DID_FAIL(res)) { _gameRef->LOG(res, "AdActor::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", getName(), _forcedTalkAnimName); delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; } else { return _animSprite; } @@ -1244,7 +1244,7 @@ BaseSprite *AdActor::getTalkStance(const char *stance) { } // new way - BaseSprite *ret = NULL; + BaseSprite *ret = nullptr; // do we have an animation with this name? AdSpriteSet *anim = getAnimByName(stance); @@ -1280,9 +1280,9 @@ BaseSprite *AdActor::getTalkStance(const char *stance) { ////////////////////////////////////////////////////////////////////////// BaseSprite *AdActor::getTalkStanceOld(const char *stance) { - BaseSprite *ret = NULL; + BaseSprite *ret = nullptr; - if (stance != NULL) { + if (stance != nullptr) { // search special stances for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { if (scumm_stricmp(_talkSpritesEx[i]->getName(), stance) == 0) { @@ -1290,7 +1290,7 @@ BaseSprite *AdActor::getTalkStanceOld(const char *stance) { break; } } - if (ret == NULL) { + if (ret == nullptr) { // search generic stances for (uint32 i = 0; i < _talkSprites.size(); i++) { if (scumm_stricmp(_talkSprites[i]->getName(), stance) == 0) { @@ -1302,7 +1302,7 @@ BaseSprite *AdActor::getTalkStanceOld(const char *stance) { } // not a valid stance? get a random one - if (ret == NULL) { + if (ret == nullptr) { if (_talkSprites.size() < 1) { ret = _standSprite->getSprite(_dir); } else { @@ -1378,7 +1378,7 @@ TDirection AdActor::angleToDirection(int angle) { ////////////////////////////////////////////////////////////////////////// int AdActor::getHeight() { // if no current sprite is set, set some - if (_currentSprite == NULL) { + if (_currentSprite == nullptr) { if (_standSprite) { _currentSprite = _standSprite->getSprite(_dir); } else { @@ -1400,7 +1400,7 @@ AdSpriteSet *AdActor::getAnimByName(const Common::String &animName) { return _anims[i]; } } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -1411,7 +1411,7 @@ bool AdActor::mergeAnims(const char *animsFilename) { byte *fileBuffer = BaseFileManager::getEngineInstance()->readWholeFile(animsFilename); - if (fileBuffer == NULL) { + if (fileBuffer == nullptr) { _gameRef->LOG(0, "AdActor::MergeAnims failed for file '%s'", animsFilename); return STATUS_FAILED; } diff --git a/engines/wintermute/ad/ad_actor.h b/engines/wintermute/ad/ad_actor.h index 543c9d063a..bcec9db319 100644 --- a/engines/wintermute/ad/ad_actor.h +++ b/engines/wintermute/ad/ad_actor.h @@ -54,7 +54,7 @@ public: virtual bool update(); virtual bool display(); virtual void turnTo(TDirection dir); - AdActor(BaseGame *inGame/*=NULL*/); + AdActor(BaseGame *inGame/*=nullptr*/); virtual ~AdActor(); bool loadFile(const char *filename); bool loadBuffer(byte *buffer, bool complete = true); diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp index 9af7e034ca..259b68f291 100644 --- a/engines/wintermute/ad/ad_entity.cpp +++ b/engines/wintermute/ad/ad_entity.cpp @@ -61,13 +61,13 @@ IMPLEMENT_PERSISTENT(AdEntity, false) AdEntity::AdEntity(BaseGame *inGame) : AdTalkHolder(inGame) { _type = OBJECT_ENTITY; _subtype = ENTITY_NORMAL; - _region = NULL; - _item = NULL; + _region = nullptr; + _item = nullptr; _walkToX = _walkToY = 0; _walkToDir = DI_NONE; - _theora = NULL; + _theora = nullptr; } @@ -76,17 +76,32 @@ AdEntity::~AdEntity() { _gameRef->unregisterObject(_region); delete _theora; - _theora = NULL; + _theora = nullptr; delete[] _item; - _item = NULL; + _item = nullptr; } +int32 AdEntity::getWalkToX() const { + return _walkToX; +} + +int32 AdEntity::getWalkToY() const { + return _walkToY; +} + +TDirection AdEntity::getWalkToDir() const { + return _walkToDir; +} + +const char *AdEntity::getItemName() const { + return _item; +} ////////////////////////////////////////////////////////////////////////// bool AdEntity::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdEntity::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -210,7 +225,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { } AdGame *adGame = (AdGame *)_gameRef; - BaseSprite *spr = NULL; + BaseSprite *spr = nullptr; int ar = 0, ag = 0, ab = 0, alpha = 0; while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { switch (cmd) { @@ -230,7 +245,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { case TOKEN_SPRITE: { delete _sprite; - _sprite = NULL; + _sprite = nullptr; spr = new BaseSprite(_gameRef, this); if (!spr || DID_FAIL(spr->loadFile((char *)params))) { cmd = PARSERR_GENERIC; @@ -320,7 +335,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -333,7 +348,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { if (_region) { _gameRef->unregisterObject(_region); } - _region = NULL; + _region = nullptr; BaseRegion *rgn = new BaseRegion(_gameRef); if (!rgn || DID_FAIL(rgn->loadBuffer(params, false))) { cmd = PARSERR_GENERIC; @@ -346,16 +361,16 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { case TOKEN_BLOCKED_REGION: { delete _blockRegion; - _blockRegion = NULL; + _blockRegion = nullptr; delete _currentBlockRegion; - _currentBlockRegion = NULL; + _currentBlockRegion = nullptr; BaseRegion *rgn = new BaseRegion(_gameRef); BaseRegion *crgn = new BaseRegion(_gameRef); if (!rgn || !crgn || DID_FAIL(rgn->loadBuffer(params, false))) { delete _blockRegion; - _blockRegion = NULL; + _blockRegion = nullptr; delete _currentBlockRegion; - _currentBlockRegion = NULL; + _currentBlockRegion = nullptr; cmd = PARSERR_GENERIC; } else { _blockRegion = rgn; @@ -367,16 +382,16 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { case TOKEN_WAYPOINTS: { delete _wptGroup; - _wptGroup = NULL; + _wptGroup = nullptr; delete _currentWptGroup; - _currentWptGroup = NULL; + _currentWptGroup = nullptr; AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); AdWaypointGroup *cwpt = new AdWaypointGroup(_gameRef); if (!wpt || !cwpt || DID_FAIL(wpt->loadBuffer(params, false))) { delete _wptGroup; - _wptGroup = NULL; + _wptGroup = nullptr; delete _currentWptGroup; - _currentWptGroup = NULL; + _currentWptGroup = nullptr; cmd = PARSERR_GENERIC; } else { _wptGroup = wpt; @@ -393,7 +408,7 @@ bool AdEntity::loadBuffer(byte *buffer, bool complete) { case TOKEN_SUBTYPE: { if (scumm_stricmp((char *)params, "sound") == 0) { delete _sprite; - _sprite = NULL; + _sprite = nullptr; if (_gameRef->_editorMode) { spr = new BaseSprite(_gameRef, this); if (!spr || DID_FAIL(spr->loadFile("entity_sound.sprite"))) { @@ -550,7 +565,7 @@ bool AdEntity::display() { } else if (_currentSprite) { _currentSprite->display(_posX, _posY, - (reg || _editorAlwaysRegister) ? _registerAlias : NULL, + (reg || _editorAlwaysRegister) ? _registerAlias : nullptr, scaleX, scaleY, alpha, @@ -570,15 +585,15 @@ bool AdEntity::display() { ////////////////////////////////////////////////////////////////////////// bool AdEntity::update() { - _currentSprite = NULL; + _currentSprite = nullptr; if (_state == STATE_READY && _animSprite) { delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; } // finished playing animation? - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->isFinished()) { + if (_state == STATE_PLAYING_ANIM && _animSprite != nullptr && _animSprite->isFinished()) { _state = STATE_READY; _currentSprite = _animSprite; } @@ -613,10 +628,10 @@ bool AdEntity::update() { } bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); - if (_tempSprite2 == NULL || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) { + if (_tempSprite2 == nullptr || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) { if (timeIsUp) { _sentence->finish(); - _tempSprite2 = NULL; + _tempSprite2 = nullptr; _state = STATE_READY; } else { _tempSprite2 = getTalkStance(_sentence->getNextStance()); @@ -658,7 +673,7 @@ bool AdEntity::update() { if (_theora->isFinished()) { _theora->stop(); delete _theora; - _theora = NULL; + _theora = nullptr; } } @@ -722,7 +737,7 @@ bool AdEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack if (_theora) { _theora->stop(); delete _theora; - _theora = NULL; + _theora = nullptr; stack->pushBool(true); } else { stack->pushBool(false); @@ -815,7 +830,7 @@ bool AdEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->correctParams(0); if (_region) { _gameRef->unregisterObject(_region); - _region = NULL; + _region = nullptr; stack->pushBool(true); } else { stack->pushBool(false); @@ -1056,7 +1071,7 @@ int AdEntity::getHeight() { if (_region && !_sprite) { return _region->_rect.bottom - _region->_rect.top; } else { - if (_currentSprite == NULL) { + if (_currentSprite == nullptr) { _currentSprite = _sprite; } return AdObject::getHeight(); @@ -1102,15 +1117,15 @@ void AdEntity::setItem(const char *itemName) { ////////////////////////////////////////////////////////////////////////// bool AdEntity::setSprite(const char *filename) { if (_currentSprite == _sprite) { - _currentSprite = NULL; + _currentSprite = nullptr; } delete _sprite; - _sprite = NULL; + _sprite = nullptr; BaseSprite *spr = new BaseSprite(_gameRef, this); if (!spr || DID_FAIL(spr->loadFile(filename))) { delete _sprite; - _sprite = NULL; + _sprite = nullptr; return STATUS_FAILED; } else { _sprite = spr; diff --git a/engines/wintermute/ad/ad_entity.h b/engines/wintermute/ad/ad_entity.h index 415987e50a..94921aaa27 100644 --- a/engines/wintermute/ad/ad_entity.h +++ b/engines/wintermute/ad/ad_entity.h @@ -37,11 +37,7 @@ class AdEntity : public AdTalkHolder { public: VideoTheoraPlayer *_theora; bool setSprite(const char *filename); - int _walkToX; - int _walkToY; - TDirection _walkToDir; void setItem(const char *itemName); - char *_item; DECLARE_PERSISTENT(AdEntity, AdTalkHolder) void updatePosition(); virtual int getHeight(); @@ -53,14 +49,23 @@ public: virtual ~AdEntity(); bool loadFile(const char *filename); bool loadBuffer(byte *buffer, bool complete = true); - TEntityType _subtype; + + int32 getWalkToX() const; + int32 getWalkToY() const; + TDirection getWalkToDir() const; + const char* getItemName() const; // scripting interface virtual ScValue *scGetProperty(const Common::String &name); virtual bool scSetProperty(const char *name, ScValue *value); virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); virtual const char *scToString(); - +private: + int32 _walkToX; + int32 _walkToY; + TDirection _walkToDir; + char *_item; + TEntityType _subtype; }; } // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_game.cpp b/engines/wintermute/ad/ad_game.cpp index 4481b774c1..b9775ba7d1 100644 --- a/engines/wintermute/ad/ad_game.cpp +++ b/engines/wintermute/ad/ad_game.cpp @@ -69,22 +69,22 @@ IMPLEMENT_PERSISTENT(AdGame, true) ////////////////////////////////////////////////////////////////////////// AdGame::AdGame(const Common::String &gameId) : BaseGame(gameId) { - _responseBox = NULL; - _inventoryBox = NULL; + _responseBox = nullptr; + _inventoryBox = nullptr; _scene = new AdScene(_gameRef); _scene->setName(""); registerObject(_scene); - _prevSceneName = NULL; - _prevSceneFilename = NULL; - _scheduledScene = NULL; + _prevSceneName = nullptr; + _prevSceneFilename = nullptr; + _scheduledScene = nullptr; _scheduledFadeIn = false; _stateEx = GAME_NORMAL; - _selectedItem = NULL; + _selectedItem = nullptr; _texItemLifeTime = 10000; @@ -94,17 +94,17 @@ AdGame::AdGame(const Common::String &gameId) : BaseGame(gameId) { _talkSkipButton = TALK_SKIP_LEFT; - _sceneViewport = NULL; + _sceneViewport = nullptr; _initialScene = true; - _debugStartupScene = NULL; - _startupScene = NULL; + _debugStartupScene = nullptr; + _startupScene = nullptr; _invObject = new AdObject(this); _inventoryOwner = _invObject; _tempDisableSaveState = false; - _itemsFile = NULL; + _itemsFile = nullptr; _smartItemCursor = false; @@ -122,7 +122,7 @@ AdGame::~AdGame() { bool AdGame::cleanup() { for (uint32 i = 0; i < _objects.size(); i++) { unregisterObject(_objects[i]); - _objects[i] = NULL; + _objects[i] = nullptr; } _objects.clear(); @@ -139,7 +139,7 @@ bool AdGame::cleanup() { unregisterObject(_scene); - _scene = NULL; + _scene = nullptr; // remove items for (uint32 i = 0; i < _items.size(); i++) { @@ -150,7 +150,7 @@ bool AdGame::cleanup() { // clear remaining inventories delete _invObject; - _invObject = NULL; + _invObject = nullptr; for (uint32 i = 0; i < _inventories.size(); i++) { delete _inventories[i]; @@ -160,12 +160,12 @@ bool AdGame::cleanup() { if (_responseBox) { _gameRef->unregisterObject(_responseBox); - _responseBox = NULL; + _responseBox = nullptr; } if (_inventoryBox) { _gameRef->unregisterObject(_inventoryBox); - _inventoryBox = NULL; + _inventoryBox = nullptr; } delete[] _prevSceneName; @@ -173,15 +173,15 @@ bool AdGame::cleanup() { delete[] _scheduledScene; delete[] _debugStartupScene; delete[] _itemsFile; - _prevSceneName = NULL; - _prevSceneFilename = NULL; - _scheduledScene = NULL; - _debugStartupScene = NULL; - _startupScene = NULL; - _itemsFile = NULL; + _prevSceneName = nullptr; + _prevSceneFilename = nullptr; + _scheduledScene = nullptr; + _debugStartupScene = nullptr; + _startupScene = nullptr; + _itemsFile = nullptr; delete _sceneViewport; - _sceneViewport = NULL; + _sceneViewport = nullptr; for (uint32 i = 0; i < _sceneStates.size(); i++) { delete _sceneStates[i]; @@ -207,9 +207,9 @@ bool AdGame::initLoop() { if (_scheduledScene && _transMgr->isReady()) { changeScene(_scheduledScene, _scheduledFadeIn); delete[] _scheduledScene; - _scheduledScene = NULL; + _scheduledScene = nullptr; - _gameRef->_activeObject = NULL; + _gameRef->_activeObject = nullptr; } @@ -258,7 +258,7 @@ bool AdGame::removeObject(AdObject *object) { ////////////////////////////////////////////////////////////////////////// bool AdGame::changeScene(const char *filename, bool fadeIn) { - if (_scene == NULL) { + if (_scene == nullptr) { _scene = new AdScene(_gameRef); registerObject(_scene); } else { @@ -297,7 +297,7 @@ bool AdGame::changeScene(const char *filename, bool fadeIn) { // invalidate references to the original scene for (uint32 i = 0; i < _objects.size(); i++) { _objects[i]->invalidateCurrRegions(); - _objects[i]->_stickRegion = NULL; + _objects[i]->_stickRegion = nullptr; } _scene->loadState(); @@ -385,7 +385,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->pushNative(act, true); } else { delete act; - act = NULL; + act = nullptr; stack->pushNULL(); } return STATUS_OK; @@ -402,7 +402,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->pushNative(ent, true); } else { delete ent; - ent = NULL; + ent = nullptr; stack->pushNULL(); } return STATUS_OK; @@ -463,7 +463,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->correctParams(1); ScValue *val = stack->pop(); - AdItem *item = NULL; + AdItem *item = nullptr; if (val->isNative()) { item = (AdItem *)val->getNative(); } else { @@ -485,7 +485,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->correctParams(1); ScValue *val = stack->pop(); - AdItem *item = NULL; + AdItem *item = nullptr; if (val->isInt()) { int index = val->getInt(); if (index >= 0 && index < (int32)_items.size()) { @@ -542,7 +542,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, res->_responseType = RESPONSE_ONCE_GAME; } - _responseBox->_responses.add(res); + _responseBox->addResponse(res); } } else { script->runtimeError("Game.AddResponse: response box is not defined"); @@ -584,15 +584,15 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, if (_responseBox) { _responseBox->weedResponses(); - if (_responseBox->_responses.size() == 0) { + if (_responseBox->getNumResponses() == 0) { stack->pushNULL(); return STATUS_OK; } - if (_responseBox->_responses.size() == 1 && autoSelectLast) { - stack->pushInt(_responseBox->_responses[0]->_iD); - _responseBox->handleResponse(_responseBox->_responses[0]); + if (_responseBox->getNumResponses() == 1 && autoSelectLast) { + stack->pushInt(_responseBox->getIdForResponseNum(0)); + _responseBox->handleResponseNum(0); _responseBox->clearResponses(); return STATUS_OK; } @@ -617,7 +617,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->correctParams(0); if (_responseBox) { _responseBox->weedResponses(); - stack->pushInt(_responseBox->_responses.size()); + stack->pushInt(_responseBox->getNumResponses()); } else { script->runtimeError("Game.GetNumResponses: response box is not defined"); stack->pushNULL(); @@ -639,7 +639,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, branchName = val->getString(); } - startDlgBranch(branchName.c_str(), script->_filename == NULL ? "" : script->_filename, script->_threadEvent == NULL ? "" : script->_threadEvent); + startDlgBranch(branchName.c_str(), script->_filename == nullptr ? "" : script->_filename, script->_threadEvent == nullptr ? "" : script->_threadEvent); stack->pushNULL(); return STATUS_OK; @@ -651,12 +651,12 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, else if (strcmp(name, "EndDlgBranch") == 0) { stack->correctParams(1); - const char *branchName = NULL; + const char *branchName = nullptr; ScValue *val = stack->pop(); if (!val->isNULL()) { branchName = val->getString(); } - endDlgBranch(branchName, script->_filename == NULL ? "" : script->_filename, script->_threadEvent == NULL ? "" : script->_threadEvent); + endDlgBranch(branchName, script->_filename == nullptr ? "" : script->_filename, script->_threadEvent == nullptr ? "" : script->_threadEvent); stack->pushNULL(); @@ -754,8 +754,8 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "GetResponsesWindow") == 0 || strcmp(name, "GetResponseWindow") == 0) { stack->correctParams(0); - if (_responseBox && _responseBox->_window) { - stack->pushNative(_responseBox->_window, true); + if (_responseBox && _responseBox->getResponseWindow()) { + stack->pushNative(_responseBox->getResponseWindow(), true); } else { stack->pushNULL(); } @@ -777,7 +777,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->pushBool(true); } else { delete _responseBox; - _responseBox = NULL; + _responseBox = nullptr; stack->pushBool(false); } return STATUS_OK; @@ -797,7 +797,7 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->pushBool(true); } else { delete _inventoryBox; - _inventoryBox = NULL; + _inventoryBox = nullptr; stack->pushBool(false); } return STATUS_OK; @@ -983,10 +983,10 @@ ScValue *AdGame::scGetProperty(const Common::String &name) { // LastResponse (RO) ////////////////////////////////////////////////////////////////////////// else if (name == "LastResponse") { - if (!_responseBox || !_responseBox->_lastResponseText) { + if (!_responseBox || !_responseBox->getLastResponseText()) { _scValue->setString(""); } else { - _scValue->setString(_responseBox->_lastResponseText); + _scValue->setString(_responseBox->getLastResponseText()); } return _scValue; } @@ -995,10 +995,10 @@ ScValue *AdGame::scGetProperty(const Common::String &name) { // LastResponseOrig (RO) ////////////////////////////////////////////////////////////////////////// else if (name == "LastResponseOrig") { - if (!_responseBox || !_responseBox->_lastResponseTextOrig) { + if (!_responseBox || !_responseBox->getLastResponseTextOrig()) { _scValue->setString(""); } else { - _scValue->setString(_responseBox->_lastResponseTextOrig); + _scValue->setString(_responseBox->getLastResponseTextOrig()); } return _scValue; } @@ -1036,7 +1036,7 @@ ScValue *AdGame::scGetProperty(const Common::String &name) { // ChangingScene ////////////////////////////////////////////////////////////////////////// else if (name == "ChangingScene") { - _scValue->setBool(_scheduledScene != NULL); + _scValue->setBool(_scheduledScene != nullptr); return _scValue; } @@ -1066,10 +1066,10 @@ bool AdGame::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// if (strcmp(name, "SelectedItem") == 0) { if (value->isNULL()) { - _selectedItem = NULL; + _selectedItem = nullptr; } else { if (value->isNative()) { - _selectedItem = NULL; + _selectedItem = nullptr; for (uint32 i = 0; i < _items.size(); i++) { if (_items[i] == value->getNative()) { _selectedItem = (AdItem *)value->getNative(); @@ -1158,9 +1158,9 @@ bool AdGame::scSetProperty(const char *name, ScValue *value) { // StartupScene ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "StartupScene") == 0) { - if (value == NULL) { + if (value == nullptr) { delete[] _startupScene; - _startupScene = NULL; + _startupScene = nullptr; } else { BaseUtils::setString(&_startupScene, value->getString()); } @@ -1242,7 +1242,7 @@ bool AdGame::showCursor() { ////////////////////////////////////////////////////////////////////////// bool AdGame::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdGame::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -1316,7 +1316,7 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) { registerObject(_responseBox); } else { delete _responseBox; - _responseBox = NULL; + _responseBox = nullptr; cmd = PARSERR_GENERIC; } break; @@ -1328,7 +1328,7 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) { registerObject(_inventoryBox); } else { delete _inventoryBox; - _inventoryBox = NULL; + _inventoryBox = nullptr; cmd = PARSERR_GENERIC; } break; @@ -1338,7 +1338,7 @@ bool AdGame::loadBuffer(byte *buffer, bool complete) { BaseUtils::setString(&_itemsFile, (char *)params2); if (DID_FAIL(loadItemsFile(_itemsFile))) { delete[] _itemsFile; - _itemsFile = NULL; + _itemsFile = nullptr; cmd = PARSERR_GENERIC; } break; @@ -1456,7 +1456,7 @@ bool AdGame::persist(BasePersistenceManager *persistMgr) { ////////////////////////////////////////////////////////////////////////// void AdGame::setPrevSceneName(const char *name) { delete[] _prevSceneName; - _prevSceneName = NULL; + _prevSceneName = nullptr; if (name) { _prevSceneName = new char[strlen(name) + 1]; if (_prevSceneName) { @@ -1469,7 +1469,7 @@ void AdGame::setPrevSceneName(const char *name) { ////////////////////////////////////////////////////////////////////////// void AdGame::setPrevSceneFilename(const char *name) { delete[] _prevSceneFilename; - _prevSceneFilename = NULL; + _prevSceneFilename = nullptr; if (name) { _prevSceneFilename = new char[strlen(name) + 1]; if (_prevSceneFilename) { @@ -1482,7 +1482,7 @@ void AdGame::setPrevSceneFilename(const char *name) { ////////////////////////////////////////////////////////////////////////// bool AdGame::scheduleChangeScene(const char *filename, bool fadeIn) { delete[] _scheduledScene; - _scheduledScene = NULL; + _scheduledScene = nullptr; if (_scene && !_scene->_initialized) { return changeScene(filename, fadeIn); @@ -1499,7 +1499,7 @@ bool AdGame::scheduleChangeScene(const char *filename, bool fadeIn) { ////////////////////////////////////////////////////////////////////////// bool AdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor) { - BaseGame::getVersion(verMajor, verMinor, NULL, NULL); + BaseGame::getVersion(verMajor, verMinor, nullptr, nullptr); if (extMajor) { *extMajor = 0; @@ -1515,7 +1515,7 @@ bool AdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *ex ////////////////////////////////////////////////////////////////////////// bool AdGame::loadItemsFile(const char *filename, bool merge) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdGame::LoadItemsFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -1567,7 +1567,7 @@ bool AdGame::loadItemsBuffer(byte *buffer, bool merge) { addItem(item); } else { delete item; - item = NULL; + item = nullptr; cmd = PARSERR_GENERIC; } } @@ -1599,7 +1599,7 @@ AdSceneState *AdGame::getSceneState(const char *filename, bool saving) { } for (uint32 i = 0; i < _sceneStates.size(); i++) { - if (scumm_stricmp(_sceneStates[i]->_filename, filenameCor) == 0) { + if (scumm_stricmp(_sceneStates[i]->getFilename(), filenameCor) == 0) { delete[] filenameCor; return _sceneStates[i]; } @@ -1615,7 +1615,7 @@ AdSceneState *AdGame::getSceneState(const char *filename, bool saving) { return ret; } else { delete[] filenameCor; - return NULL; + return nullptr; } } @@ -1635,7 +1635,7 @@ bool AdGame::windowLoadHook(UIWindow *win, char **buffer, char **params) { UIEntity *ent = new UIEntity(_gameRef); if (!ent || DID_FAIL(ent->loadBuffer((byte *)*params, false))) { delete ent; - ent = NULL; + ent = nullptr; cmd = PARSERR_GENERIC; } else { ent->_parent = win; @@ -1689,12 +1689,12 @@ bool AdGame::startDlgBranch(const char *branchName, const char *scriptName, cons ////////////////////////////////////////////////////////////////////////// bool AdGame::endDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { - char *name = NULL; + char *name = nullptr; bool deleteName = false; - if (branchName == NULL && _dlgPendingBranches.size() > 0) { + if (branchName == nullptr && _dlgPendingBranches.size() > 0) { name = _dlgPendingBranches[_dlgPendingBranches.size() - 1]; } else { - if (branchName != NULL) { + if (branchName != nullptr) { name = new char[strlen(branchName) + 1 + strlen(scriptName) + 1 + strlen(eventName) + 1]; if (name) { sprintf(name, "%s.%s.%s", branchName, scriptName, eventName); @@ -1703,7 +1703,7 @@ bool AdGame::endDlgBranch(const char *branchName, const char *scriptName, const } } - if (name == NULL) { + if (name == nullptr) { return STATUS_OK; } @@ -1719,7 +1719,7 @@ bool AdGame::endDlgBranch(const char *branchName, const char *scriptName, const for (uint32 i = startIndex; i < _dlgPendingBranches.size(); i++) { //ClearBranchResponses(_dlgPendingBranches[i]); delete[] _dlgPendingBranches[i]; - _dlgPendingBranches[i] = NULL; + _dlgPendingBranches[i] = nullptr; } _dlgPendingBranches.remove_at(startIndex, _dlgPendingBranches.size() - startIndex); } @@ -1760,7 +1760,7 @@ bool AdGame::addBranchResponse(int id) { } AdResponseContext *r = new AdResponseContext(_gameRef); r->_id = id; - r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL); + r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : nullptr); _responsesBranch.add(r); return STATUS_OK; } @@ -1768,10 +1768,10 @@ bool AdGame::addBranchResponse(int id) { ////////////////////////////////////////////////////////////////////////// bool AdGame::branchResponseUsed(int id) { - char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; + char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : nullptr; for (uint32 i = 0; i < _responsesBranch.size(); i++) { if (_responsesBranch[i]->_id == id) { - if ((context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { + if ((context == nullptr && _responsesBranch[i]->_context == nullptr) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { return true; } } @@ -1787,7 +1787,7 @@ bool AdGame::addGameResponse(int id) { } AdResponseContext *r = new AdResponseContext(_gameRef); r->_id = id; - r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL); + r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : nullptr); _responsesGame.add(r); return STATUS_OK; } @@ -1795,11 +1795,11 @@ bool AdGame::addGameResponse(int id) { ////////////////////////////////////////////////////////////////////////// bool AdGame::gameResponseUsed(int id) { - char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; + char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : nullptr; for (uint32 i = 0; i < _responsesGame.size(); i++) { AdResponseContext *respContext = _responsesGame[i]; if (respContext->_id == id) { - if ((context == NULL && respContext->_context == NULL) || ((context != NULL && respContext->_context != NULL) && scumm_stricmp(context, respContext->_context) == 0)) { + if ((context == nullptr && respContext->_context == nullptr) || ((context != nullptr && respContext->_context != nullptr) && scumm_stricmp(context, respContext->_context) == 0)) { return true; } } @@ -1810,11 +1810,11 @@ bool AdGame::gameResponseUsed(int id) { ////////////////////////////////////////////////////////////////////////// bool AdGame::resetResponse(int id) { - char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; + char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : nullptr; for (uint32 i = 0; i < _responsesGame.size(); i++) { if (_responsesGame[i]->_id == id) { - if ((context == NULL && _responsesGame[i]->_context == NULL) || scumm_stricmp(context, _responsesGame[i]->_context) == 0) { + if ((context == nullptr && _responsesGame[i]->_context == nullptr) || scumm_stricmp(context, _responsesGame[i]->_context) == 0) { delete _responsesGame[i]; _responsesGame.remove_at(i); break; @@ -1824,7 +1824,7 @@ bool AdGame::resetResponse(int id) { for (uint32 i = 0; i < _responsesBranch.size(); i++) { if (_responsesBranch[i]->_id == id) { - if ((context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { + if ((context == nullptr && _responsesBranch[i]->_context == nullptr) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { delete _responsesBranch[i]; _responsesBranch.remove_at(i); break; @@ -1863,7 +1863,7 @@ bool AdGame::displayContent(bool doUpdate, bool displayAll) { } if (_theoraPlayer->isFinished()) { delete _theoraPlayer; - _theoraPlayer = NULL; + _theoraPlayer = nullptr; } } else { @@ -1912,7 +1912,7 @@ bool AdGame::displayContent(bool doUpdate, bool displayAll) { _loadingIcon->display(_loadingIconX, _loadingIconY); if (!_loadingIconPersistent) { delete _loadingIcon; - _loadingIcon = NULL; + _loadingIcon = nullptr; } } @@ -1965,7 +1965,7 @@ AdItem *AdGame::getItemByName(const char *name) { return _items[i]; } } - return NULL; + return nullptr; } @@ -2026,7 +2026,7 @@ bool AdGame::deleteItem(AdItem *item) { } if (_selectedItem == item) { - _selectedItem = NULL; + _selectedItem = nullptr; } _scene->handleItemAssociations(item->getName(), false); @@ -2115,7 +2115,7 @@ char *AdGame::findSpeechFile(char *stringID) { } } delete[] ret; - return NULL; + return nullptr; } @@ -2145,14 +2145,14 @@ bool AdGame::onMouseLeftDown() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("LeftClick"); } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { _scene->applyEvent("LeftClick"); } } - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _gameRef->_capturedObject = _gameRef->_activeObject; } _mouseLeftDown = true; @@ -2168,12 +2168,12 @@ bool AdGame::onMouseLeftUp() { } BasePlatform::releaseCapture(); - _capturedObject = NULL; + _capturedObject = nullptr; _mouseLeftDown = false; bool handled = /*_state==GAME_RUNNING &&*/ DID_SUCCEED(applyEvent("LeftRelease")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("LeftRelease"); } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { _scene->applyEvent("LeftRelease"); @@ -2198,7 +2198,7 @@ bool AdGame::onMouseLeftDblClick() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftDoubleClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("LeftDoubleClick"); } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { _scene->applyEvent("LeftDoubleClick"); @@ -2229,7 +2229,7 @@ bool AdGame::onMouseRightDown() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("RightClick"); } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { _scene->applyEvent("RightClick"); @@ -2246,7 +2246,7 @@ bool AdGame::onMouseRightUp() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightRelease")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("RightRelease"); } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { _scene->applyEvent("RightRelease"); @@ -2272,7 +2272,7 @@ bool AdGame::displayDebugInfo() { ////////////////////////////////////////////////////////////////////////// bool AdGame::onScriptShutdown(ScScript *script) { if (_responseBox && _responseBox->_waitingScript == script) { - _responseBox->_waitingScript = NULL; + _responseBox->_waitingScript = nullptr; } return STATUS_OK; diff --git a/engines/wintermute/ad/ad_inventory.cpp b/engines/wintermute/ad/ad_inventory.cpp index 72f8fa0fb4..e9b6e56f16 100644 --- a/engines/wintermute/ad/ad_inventory.cpp +++ b/engines/wintermute/ad/ad_inventory.cpp @@ -50,12 +50,12 @@ AdInventory::~AdInventory() { ////////////////////////////////////////////////////////////////////////// bool AdInventory::insertItem(const char *name, const char *insertAfter) { - if (name == NULL) { + if (name == nullptr) { return STATUS_FAILED; } AdItem *item = ((AdGame *)_gameRef)->getItemByName(name); - if (item == NULL) { + if (item == nullptr) { return STATUS_FAILED; } @@ -84,14 +84,14 @@ bool AdInventory::insertItem(const char *name, const char *insertAfter) { ////////////////////////////////////////////////////////////////////////// bool AdInventory::removeItem(const char *name) { - if (name == NULL) { + if (name == nullptr) { return STATUS_FAILED; } for (uint32 i = 0; i < _takenItems.size(); i++) { if (scumm_stricmp(_takenItems[i]->getName(), name) == 0) { if (((AdGame *)_gameRef)->_selectedItem == _takenItems[i]) { - ((AdGame *)_gameRef)->_selectedItem = NULL; + ((AdGame *)_gameRef)->_selectedItem = nullptr; } _takenItems.remove_at(i); return STATUS_OK; @@ -105,14 +105,14 @@ bool AdInventory::removeItem(const char *name) { ////////////////////////////////////////////////////////////////////////// bool AdInventory::removeItem(AdItem *item) { - if (item == NULL) { + if (item == nullptr) { return STATUS_FAILED; } for (uint32 i = 0; i < _takenItems.size(); i++) { if (_takenItems[i] == item) { if (((AdGame *)_gameRef)->_selectedItem == _takenItems[i]) { - ((AdGame *)_gameRef)->_selectedItem = NULL; + ((AdGame *)_gameRef)->_selectedItem = nullptr; } _takenItems.remove_at(i); return STATUS_OK; diff --git a/engines/wintermute/ad/ad_inventory.h b/engines/wintermute/ad/ad_inventory.h index 4017d914bc..f226a65612 100644 --- a/engines/wintermute/ad/ad_inventory.h +++ b/engines/wintermute/ad/ad_inventory.h @@ -40,7 +40,7 @@ public: DECLARE_PERSISTENT(AdInventory, BaseObject) bool removeItem(const char *name); bool removeItem(AdItem *Item); - bool insertItem(const char *name, const char *insertAfter = NULL); + bool insertItem(const char *name, const char *insertAfter = nullptr); AdInventory(BaseGame *inGame); virtual ~AdInventory(); BaseArray<AdItem *> _takenItems; diff --git a/engines/wintermute/ad/ad_inventory_box.cpp b/engines/wintermute/ad/ad_inventory_box.cpp index 7ae8ff8d69..194d975155 100644 --- a/engines/wintermute/ad/ad_inventory_box.cpp +++ b/engines/wintermute/ad/ad_inventory_box.cpp @@ -54,8 +54,8 @@ AdInventoryBox::AdInventoryBox(BaseGame *inGame) : BaseObject(inGame) { _itemWidth = _itemHeight = 50; _scrollBy = 1; - _window = NULL; - _closeButton = NULL; + _window = nullptr; + _closeButton = nullptr; _hideSelected = false; @@ -67,10 +67,10 @@ AdInventoryBox::AdInventoryBox(BaseGame *inGame) : BaseObject(inGame) { ////////////////////////////////////////////////////////////////////////// AdInventoryBox::~AdInventoryBox() { _gameRef->unregisterObject(_window); - _window = NULL; + _window = nullptr; delete _closeButton; - _closeButton = NULL; + _closeButton = nullptr; } @@ -166,7 +166,7 @@ bool AdInventoryBox::display() { ////////////////////////////////////////////////////////////////////////// bool AdInventoryBox::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdInventoryBox::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -256,7 +256,7 @@ bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) { _window = new UIWindow(_gameRef); if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { delete _window; - _window = NULL; + _window = nullptr; cmd = PARSERR_GENERIC; } else { _gameRef->registerObject(_window); diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp index 427b1c7db4..8534956120 100644 --- a/engines/wintermute/ad/ad_item.cpp +++ b/engines/wintermute/ad/ad_item.cpp @@ -49,8 +49,8 @@ IMPLEMENT_PERSISTENT(AdItem, false) ////////////////////////////////////////////////////////////////////////// AdItem::AdItem(BaseGame *inGame) : AdTalkHolder(inGame) { - _spriteHover = NULL; - _cursorNormal = _cursorHover = NULL; + _spriteHover = nullptr; + _cursorNormal = _cursorHover = nullptr; _cursorCombined = true; _inInventory = false; @@ -60,7 +60,7 @@ AdItem::AdItem(BaseGame *inGame) : AdTalkHolder(inGame) { _amountOffsetX = 0; _amountOffsetY = 0; _amountAlign = TAL_RIGHT; - _amountString = NULL; + _amountString = nullptr; _state = STATE_READY; @@ -73,19 +73,19 @@ AdItem::~AdItem() { delete _spriteHover; delete _cursorNormal; delete _cursorHover; - _spriteHover = NULL; - _cursorNormal = NULL; - _cursorHover = NULL; + _spriteHover = nullptr; + _cursorNormal = nullptr; + _cursorHover = nullptr; delete[] _amountString; - _amountString = NULL; + _amountString = nullptr; } ////////////////////////////////////////////////////////////////////////// bool AdItem::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdItem::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -272,7 +272,7 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) { _cursorNormal = new BaseSprite(_gameRef); if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { delete _cursorNormal; - _cursorNormal = NULL; + _cursorNormal = nullptr; cmd = PARSERR_GENERIC; } break; @@ -282,7 +282,7 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) { _cursorHover = new BaseSprite(_gameRef); if (!_cursorHover || DID_FAIL(_cursorHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { delete _cursorHover; - _cursorHover = NULL; + _cursorHover = nullptr; cmd = PARSERR_GENERIC; } break; @@ -332,15 +332,15 @@ bool AdItem::loadBuffer(byte *buffer, bool complete) { ////////////////////////////////////////////////////////////////////////// bool AdItem::update() { - _currentSprite = NULL; + _currentSprite = nullptr; if (_state == STATE_READY && _animSprite) { delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; } // finished playing animation? - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->isFinished()) { + if (_state == STATE_PLAYING_ANIM && _animSprite != nullptr && _animSprite->isFinished()) { _state = STATE_READY; _currentSprite = _animSprite; } @@ -379,10 +379,10 @@ bool AdItem::update() { } bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); - if (_tempSprite2 == NULL || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) { + if (_tempSprite2 == nullptr || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) { if (timeIsUp) { _sentence->finish(); - _tempSprite2 = NULL; + _tempSprite2 = nullptr; _state = STATE_READY; } else { _tempSprite2 = getTalkStance(_sentence->getNextStance()); @@ -435,7 +435,7 @@ bool AdItem::display(int x, int y) { } amountX += _amountOffsetX; - BaseFont *font = _font ? _font : _gameRef->_systemFont; + BaseFont *font = _font ? _font : _gameRef->getSystemFont(); if (font) { if (_amountString) { font->drawText((byte *)_amountString, amountX, amountY, width, _amountAlign); @@ -469,7 +469,7 @@ bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *filename = stack->pop()->getString(); delete _spriteHover; - _spriteHover = NULL; + _spriteHover = nullptr; BaseSprite *spr = new BaseSprite(_gameRef, this); if (!spr || DID_FAIL(spr->loadFile(filename))) { stack->pushBool(false); @@ -520,7 +520,7 @@ bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *filename = stack->pop()->getString(); delete _cursorNormal; - _cursorNormal = NULL; + _cursorNormal = nullptr; BaseSprite *spr = new BaseSprite(_gameRef); if (!spr || DID_FAIL(spr->loadFile(filename))) { stack->pushBool(false); @@ -569,7 +569,7 @@ bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *filename = stack->pop()->getString(); delete _cursorHover; - _cursorHover = NULL; + _cursorHover = nullptr; BaseSprite *spr = new BaseSprite(_gameRef); if (!spr || DID_FAIL(spr->loadFile(filename))) { stack->pushBool(false); @@ -753,7 +753,7 @@ bool AdItem::scSetProperty(const char *name, ScValue *value) { else if (strcmp(name, "AmountString") == 0) { if (value->isNULL()) { delete[] _amountString; - _amountString = NULL; + _amountString = nullptr; } else { BaseUtils::setString(&_amountString, value->getString()); } diff --git a/engines/wintermute/ad/ad_layer.cpp b/engines/wintermute/ad/ad_layer.cpp index 209c12b7a2..7bf79e4ae5 100644 --- a/engines/wintermute/ad/ad_layer.cpp +++ b/engines/wintermute/ad/ad_layer.cpp @@ -63,7 +63,7 @@ AdLayer::~AdLayer() { ////////////////////////////////////////////////////////////////////////// bool AdLayer::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdLayer::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -174,8 +174,8 @@ bool AdLayer::loadBuffer(byte *buffer, bool complete) { cmd = PARSERR_GENERIC; delete region; delete node; - region = NULL; - node = NULL; + region = nullptr; + node = nullptr; } else { node->setRegion(region); _nodes.add(node); @@ -193,8 +193,8 @@ bool AdLayer::loadBuffer(byte *buffer, bool complete) { cmd = PARSERR_GENERIC; delete entity; delete node; - entity = NULL; - node = NULL; + entity = nullptr; + node = nullptr; } else { node->setEntity(entity); _nodes.add(node); @@ -339,7 +339,7 @@ bool AdLayer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->correctParams(1); ScValue *val = stack->pop(); - AdSceneNode *toDelete = NULL; + AdSceneNode *toDelete = nullptr; if (val->isNative()) { BaseScriptable *temp = val->getNative(); for (uint32 i = 0; i < _nodes.size(); i++) { @@ -354,7 +354,7 @@ bool AdLayer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, toDelete = _nodes[index]; } } - if (toDelete == NULL) { + if (toDelete == nullptr) { stack->pushBool(false); return STATUS_OK; } @@ -362,7 +362,7 @@ bool AdLayer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, for (uint32 i = 0; i < _nodes.size(); i++) { if (_nodes[i] == toDelete) { delete _nodes[i]; - _nodes[i] = NULL; + _nodes[i] = nullptr; _nodes.remove_at(i); break; } diff --git a/engines/wintermute/ad/ad_node_state.cpp b/engines/wintermute/ad/ad_node_state.cpp index 493156c750..34e220569f 100644 --- a/engines/wintermute/ad/ad_node_state.cpp +++ b/engines/wintermute/ad/ad_node_state.cpp @@ -42,14 +42,14 @@ IMPLEMENT_PERSISTENT(AdNodeState, false) ////////////////////////////////////////////////////////////////////////// AdNodeState::AdNodeState(BaseGame *inGame) : BaseClass(inGame) { - _name = NULL; + _name = nullptr; _active = false; for (int i = 0; i < 7; i++) { - _caption[i] = NULL; + _caption[i] = nullptr; } _alphaColor = 0; - _filename = NULL; - _cursor = NULL; + _filename = nullptr; + _cursor = nullptr; } @@ -58,12 +58,12 @@ AdNodeState::~AdNodeState() { delete[] _name; delete[] _filename; delete[] _cursor; - _name = NULL; - _filename = NULL; - _cursor = NULL; + _name = nullptr; + _filename = nullptr; + _cursor = nullptr; for (int i = 0; i < 7; i++) { delete[] _caption[i]; - _caption[i] = NULL; + _caption[i] = nullptr; } } @@ -71,7 +71,7 @@ AdNodeState::~AdNodeState() { ////////////////////////////////////////////////////////////////////////// void AdNodeState::setName(const char *name) { delete[] _name; - _name = NULL; + _name = nullptr; BaseUtils::setString(&_name, name); } @@ -79,7 +79,7 @@ void AdNodeState::setName(const char *name) { ////////////////////////////////////////////////////////////////////////// void AdNodeState::setFilename(const char *filename) { delete[] _filename; - _filename = NULL; + _filename = nullptr; BaseUtils::setString(&_filename, filename); } @@ -87,7 +87,7 @@ void AdNodeState::setFilename(const char *filename) { ////////////////////////////////////////////////////////////////////////// void AdNodeState::setCursor(const char *filename) { delete[] _cursor; - _cursor = NULL; + _cursor = nullptr; BaseUtils::setString(&_cursor, filename); } @@ -132,7 +132,7 @@ const char *AdNodeState::getCaption(int caseVal) { if (caseVal == 0) { caseVal = 1; } - if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) { + if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == nullptr) { return ""; } else { return _caption[caseVal - 1]; diff --git a/engines/wintermute/ad/ad_object.cpp b/engines/wintermute/ad/ad_object.cpp index 7b91daab2e..a41ed9fbc3 100644 --- a/engines/wintermute/ad/ad_object.cpp +++ b/engines/wintermute/ad/ad_object.cpp @@ -65,27 +65,27 @@ AdObject::AdObject(BaseGame *inGame) : BaseObject(inGame) { _active = true; _drawn = false; - _currentSprite = NULL; - _animSprite = NULL; - _tempSprite2 = NULL; + _currentSprite = nullptr; + _animSprite = nullptr; + _tempSprite2 = nullptr; - _font = NULL; + _font = nullptr; - _sentence = NULL; + _sentence = nullptr; - _forcedTalkAnimName = NULL; + _forcedTalkAnimName = nullptr; _forcedTalkAnimUsed = false; - _blockRegion = NULL; - _wptGroup = NULL; + _blockRegion = nullptr; + _wptGroup = nullptr; - _currentBlockRegion = NULL; - _currentWptGroup = NULL; + _currentBlockRegion = nullptr; + _currentWptGroup = nullptr; _ignoreItems = false; _sceneIndependent = false; - _stickRegion = NULL; + _stickRegion = nullptr; _subtitlesModRelative = true; _subtitlesModX = 0; @@ -93,13 +93,13 @@ AdObject::AdObject(BaseGame *inGame) : BaseObject(inGame) { _subtitlesWidth = 0; _subtitlesModXCenter = true; - _inventory = NULL; + _inventory = nullptr; for (int i = 0; i < MAX_NUM_REGIONS; i++) { - _currentRegions[i] = NULL; + _currentRegions[i] = nullptr; } - _partEmitter = NULL; + _partEmitter = nullptr; _partFollowParent = false; _partOffsetX = _partOffsetY = 0; @@ -109,26 +109,26 @@ AdObject::AdObject(BaseGame *inGame) : BaseObject(inGame) { ////////////////////////////////////////////////////////////////////////// AdObject::~AdObject() { - _currentSprite = NULL; // reference only, don't delete + _currentSprite = nullptr; // reference only, don't delete delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; delete _sentence; - _sentence = NULL; + _sentence = nullptr; delete[] _forcedTalkAnimName; - _forcedTalkAnimName = NULL; + _forcedTalkAnimName = nullptr; delete _blockRegion; - _blockRegion = NULL; + _blockRegion = nullptr; delete _wptGroup; - _wptGroup = NULL; + _wptGroup = nullptr; delete _currentBlockRegion; - _currentBlockRegion = NULL; + _currentBlockRegion = nullptr; delete _currentWptGroup; - _currentWptGroup = NULL; + _currentWptGroup = nullptr; - _tempSprite2 = NULL; // reference only - _stickRegion = NULL; + _tempSprite2 = nullptr; // reference only + _stickRegion = nullptr; if (_font) { _gameRef->_fontStorage->removeFont(_font); @@ -136,7 +136,7 @@ AdObject::~AdObject() { if (_inventory) { ((AdGame *)_gameRef)->unregisterInventory(_inventory); - _inventory = NULL; + _inventory = nullptr; } if (_partEmitter) { @@ -159,7 +159,7 @@ AdObject::~AdObject() { ////////////////////////////////////////////////////////////////////////// bool AdObject::playAnim(const char *filename) { delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; _animSprite = new BaseSprite(_gameRef, this); if (!_animSprite) { _gameRef->LOG(0, "AdObject::PlayAnim: error creating temp sprite (object:\"%s\" sprite:\"%s\")", getName(), filename); @@ -169,7 +169,7 @@ bool AdObject::playAnim(const char *filename) { if (DID_FAIL(res)) { _gameRef->LOG(res, "AdObject::PlayAnim: error loading temp sprite (object:\"%s\" sprite:\"%s\")", getName(), filename); delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; return res; } _state = STATE_PLAYING_ANIM; @@ -274,7 +274,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack int duration = stack->pop()->getInt(); ScValue *valStances = stack->pop(); - const char *stances = valStances->isNULL() ? NULL : valStances->getString(); + const char *stances = valStances->isNULL() ? nullptr : valStances->getString(); int align = 0; ScValue *val = stack->pop(); @@ -286,7 +286,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack align = MIN(MAX(0, align), NUM_TEXT_ALIGN - 1); - const char *sound = soundVal->isNULL() ? NULL : soundVal->getString(); + const char *sound = soundVal->isNULL() ? nullptr : soundVal->getString(); talk(text, sound, duration, stances, (TTextAlign)align); if (strcmp(name, "TalkAsync") != 0) { @@ -309,7 +309,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack uint32 i; ScValue *val = stack->pop(); if (val->isNULL() || !main) { - _stickRegion = NULL; + _stickRegion = nullptr; regFound = true; } else if (val->isString()) { const char *regionName = val->getString(); @@ -334,7 +334,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack } if (!regFound) { - _stickRegion = NULL; + _stickRegion = nullptr; } stack->pushBool(regFound); return STATUS_OK; @@ -348,7 +348,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack ScValue *val = stack->pop(); if (val->isNULL()) { - setFont(NULL); + setFont(nullptr); } else { setFont(val->getString()); } @@ -385,7 +385,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack if (!val->isNULL()) { const char *itemName = val->getString(); val = stack->pop(); - const char *insertAfter = val->isNULL() ? NULL : val->getString(); + const char *insertAfter = val->isNULL() ? nullptr : val->getString(); if (DID_FAIL(_inventory->insertItem(itemName, insertAfter))) { script->runtimeError("Cannot add item '%s' to inventory", itemName); } else { @@ -512,7 +512,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->correctParams(0); if (_partEmitter) { _gameRef->unregisterObject(_partEmitter); - _partEmitter = NULL; + _partEmitter = nullptr; } stack->pushNULL(); @@ -533,7 +533,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack AdEntity *ent = new AdEntity(_gameRef); if (DID_FAIL(res = ent->loadFile(filename))) { delete ent; - ent = NULL; + ent = nullptr; script->runtimeError("AddAttachment() failed loading entity '%s'", filename); stack->pushBool(false); } else { @@ -611,7 +611,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->correctParams(1); ScValue *val = stack->pop(); - AdObject *ret = NULL; + AdObject *ret = nullptr; if (val->isInt()) { int index = val->getInt(); int currIndex = 0; @@ -645,7 +645,7 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack } } - if (ret != NULL) { + if (ret != nullptr) { stack->pushNative(ret, true); } else { stack->pushNULL(); @@ -851,9 +851,9 @@ bool AdObject::setFont(const char *filename) { } if (filename) { _font = _gameRef->_fontStorage->addFont(filename); - return _font == NULL ? STATUS_FAILED : STATUS_OK; + return _font == nullptr ? STATUS_FAILED : STATUS_OK; } else { - _font = NULL; + _font = nullptr; return STATUS_OK; } } @@ -878,6 +878,9 @@ int AdObject::getHeight() { } } +TObjectType AdObject::getType() const { + return _type; +} ////////////////////////////////////////////////////////////////////////// void AdObject::talk(const char *text, const char *sound, uint32 duration, const char *stances, TTextAlign Align) { @@ -890,12 +893,12 @@ void AdObject::talk(const char *text, const char *sound, uint32 duration, const if (_forcedTalkAnimName && _forcedTalkAnimUsed) { delete[] _forcedTalkAnimName; - _forcedTalkAnimName = NULL; + _forcedTalkAnimName = nullptr; _forcedTalkAnimUsed = false; } delete(_sentence->_sound); - _sentence->_sound = NULL; + _sentence->_sound = nullptr; _sentence->setText(text); _gameRef->_stringTable->expand(&_sentence->_text); @@ -904,7 +907,7 @@ void AdObject::talk(const char *text, const char *sound, uint32 duration, const _sentence->_align = Align; _sentence->_startTime = _gameRef->_timer; _sentence->_currentStance = -1; - _sentence->_font = _font == NULL ? _gameRef->_systemFont : _font; + _sentence->_font = _font == nullptr ? _gameRef->getSystemFont() : _font; _sentence->_freezable = _freezable; // try to locate speech file automatically @@ -1009,9 +1012,9 @@ void AdObject::talk(const char *text, const char *sound, uint32 duration, const ////////////////////////////////////////////////////////////////////////// bool AdObject::reset() { - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL) { + if (_state == STATE_PLAYING_ANIM && _animSprite != nullptr) { delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; } else if (_state == STATE_TALKING && _sentence) { _sentence->finish(); } @@ -1154,7 +1157,7 @@ bool AdObject::afterMove() { bool regFound = false; for (int j = 0; j < MAX_NUM_REGIONS; j++) { if (_currentRegions[j] == newRegions[i]) { - _currentRegions[j] = NULL; + _currentRegions[j] = nullptr; regFound = true; break; } @@ -1177,7 +1180,7 @@ bool AdObject::afterMove() { ////////////////////////////////////////////////////////////////////////// bool AdObject::invalidateCurrRegions() { for (int i = 0; i < MAX_NUM_REGIONS; i++) { - _currentRegions[i] = NULL; + _currentRegions[i] = nullptr; } return STATUS_OK; } diff --git a/engines/wintermute/ad/ad_object.h b/engines/wintermute/ad/ad_object.h index d1a20908e1..39480e3446 100644 --- a/engines/wintermute/ad/ad_object.h +++ b/engines/wintermute/ad/ad_object.h @@ -46,77 +46,81 @@ class PartEmitter; class AdObject : public BaseObject { public: - PartEmitter *_partEmitter; virtual PartEmitter *createParticleEmitter(bool followParent = false, int offsetX = 0, int offsetY = 0); virtual bool updatePartEmitter(); - bool _partFollowParent; - int _partOffsetX; - int _partOffsetY; bool invalidateCurrRegions(); - bool _subtitlesModRelative; - bool _subtitlesModXCenter; - int _subtitlesModX; - int _subtitlesModY; - int _subtitlesWidth; AdRegion *_stickRegion; bool _sceneIndependent; - bool _ignoreItems; + bool updateBlockRegion(); - bool _forcedTalkAnimUsed; - char *_forcedTalkAnimName; + virtual bool getExtendedFlag(const char *flagName); virtual bool resetSoundPan(); virtual bool updateSounds(); bool reset(); DECLARE_PERSISTENT(AdObject, BaseObject) - virtual void talk(const char *text, const char *sound = NULL, uint32 duration = 0, const char *stances = NULL, TTextAlign align = TAL_CENTER); + virtual void talk(const char *text, const char *sound = nullptr, uint32 duration = 0, const char *stances = nullptr, TTextAlign align = TAL_CENTER); virtual int getHeight(); - AdSentence *_sentence; + bool setFont(const char *filename); virtual bool update(); virtual bool display(); + bool _drawn; bool _active; virtual bool playAnim(const char *filename); - BaseSprite *_animSprite; - BaseSprite *_currentSprite; - TObjectState _state; - TObjectState _nextState; - TObjectType _type; + + TObjectType getType() const; AdObject(BaseGame *inGame); virtual ~AdObject(); - BaseFont *_font; - BaseSprite *_tempSprite2; - BaseRegion *_blockRegion; - AdWaypointGroup *_wptGroup; + BaseRegion *_currentBlockRegion; AdWaypointGroup *_currentWptGroup; AdInventory *getInventory(); virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - virtual bool afterMove(); - AdRegion *_currentRegions[MAX_NUM_REGIONS]; // scripting interface virtual ScValue *scGetProperty(const Common::String &name); virtual bool scSetProperty(const char *name, ScValue *value); virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); virtual const char *scToString(); - - BaseArray<AdObject *> _attachmentsPre; - BaseArray<AdObject *> _attachmentsPost; - bool updateSpriteAttachments(); bool displaySpriteAttachments(bool preDisplay); + +protected: + PartEmitter *_partEmitter; + bool _ignoreItems; + bool _forcedTalkAnimUsed; + char *_forcedTalkAnimName; + BaseSprite *_animSprite; + BaseSprite *_currentSprite; + AdSentence *_sentence; + TObjectState _state; + TObjectState _nextState; + TObjectType _type; + BaseFont *_font; + BaseSprite *_tempSprite2; + BaseRegion *_blockRegion; + AdWaypointGroup *_wptGroup; AdObject *_registerAlias; + bool getScale(float *scaleX, float *scaleY); private: + bool _partFollowParent; + int _partOffsetX; + int _partOffsetY; + bool _subtitlesModRelative; + bool _subtitlesModXCenter; + int _subtitlesModX; + int _subtitlesModY; + int _subtitlesWidth; + AdRegion *_currentRegions[MAX_NUM_REGIONS]; + BaseArray<AdObject *> _attachmentsPre; + BaseArray<AdObject *> _attachmentsPost; bool displaySpriteAttachment(AdObject *attachment); AdInventory *_inventory; - -protected: - bool getScale(float *scaleX, float *scaleY); }; } // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_path.cpp b/engines/wintermute/ad/ad_path.cpp index c931213456..afdd29828c 100644 --- a/engines/wintermute/ad/ad_path.cpp +++ b/engines/wintermute/ad/ad_path.cpp @@ -64,7 +64,7 @@ BasePoint *AdPath::getFirst() { _currIndex = 0; return _points[_currIndex]; } else { - return NULL; + return nullptr; } } @@ -75,7 +75,7 @@ BasePoint *AdPath::getNext() { if (_currIndex < (int32)_points.size()) { return _points[_currIndex]; } else { - return NULL; + return nullptr; } } @@ -85,7 +85,7 @@ BasePoint *AdPath::getCurrent() { if (_currIndex >= 0 && _currIndex < (int32)_points.size()) { return _points[_currIndex]; } else { - return NULL; + return nullptr; } } diff --git a/engines/wintermute/ad/ad_path_point.cpp b/engines/wintermute/ad/ad_path_point.cpp index a36648eb69..f3ccd264b1 100644 --- a/engines/wintermute/ad/ad_path_point.cpp +++ b/engines/wintermute/ad/ad_path_point.cpp @@ -39,7 +39,7 @@ AdPathPoint::AdPathPoint() { _distance = 0; _marked = false; - _origin = NULL; + _origin = nullptr; } @@ -50,13 +50,13 @@ AdPathPoint::AdPathPoint(int initX, int initY, int initDistance) { _distance = initDistance; _marked = false; - _origin = NULL; + _origin = nullptr; } ////////////////////////////////////////////////////////////////////////// AdPathPoint::~AdPathPoint() { - _origin = NULL; + _origin = nullptr; } diff --git a/engines/wintermute/ad/ad_region.cpp b/engines/wintermute/ad/ad_region.cpp index c9f1553c9a..acd5f13397 100644 --- a/engines/wintermute/ad/ad_region.cpp +++ b/engines/wintermute/ad/ad_region.cpp @@ -51,11 +51,26 @@ AdRegion::AdRegion(BaseGame *inGame) : BaseRegion(inGame) { AdRegion::~AdRegion() { } +uint32 AdRegion::getAlpha() const { + return _alpha; +} + +float AdRegion::getZoom() const { + return _zoom; +} + +bool AdRegion::isBlocked() const { + return _blocked; +} + +bool AdRegion::hasDecoration() const { + return _decoration; +} ////////////////////////////////////////////////////////////////////////// bool AdRegion::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdRegion::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } diff --git a/engines/wintermute/ad/ad_region.h b/engines/wintermute/ad/ad_region.h index 6112900361..960dde5f15 100644 --- a/engines/wintermute/ad/ad_region.h +++ b/engines/wintermute/ad/ad_region.h @@ -36,21 +36,27 @@ namespace Wintermute { class AdRegion : public BaseRegion { public: DECLARE_PERSISTENT(AdRegion, BaseRegion) - uint32 _alpha; - float _zoom; - bool _blocked; - bool _decoration; + AdRegion(BaseGame *inGame); virtual ~AdRegion(); bool loadFile(const char *filename); bool loadBuffer(byte *buffer, bool complete = true); virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + bool hasDecoration() const; + bool isBlocked() const; + uint32 getAlpha() const; + float getZoom() const; // scripting interface virtual ScValue *scGetProperty(const Common::String &name); virtual bool scSetProperty(const char *name, ScValue *value); virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); virtual const char *scToString(); +private: + uint32 _alpha; + float _zoom; + bool _blocked; + bool _decoration; }; } // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response.cpp b/engines/wintermute/ad/ad_response.cpp index a2225f2632..e4993b9ad4 100644 --- a/engines/wintermute/ad/ad_response.cpp +++ b/engines/wintermute/ad/ad_response.cpp @@ -38,10 +38,10 @@ IMPLEMENT_PERSISTENT(AdResponse, false) ////////////////////////////////////////////////////////////////////////// AdResponse::AdResponse(BaseGame *inGame) : BaseObject(inGame) { - _text = NULL; - _textOrig = NULL; - _icon = _iconHover = _iconPressed = NULL; - _font = NULL; + _text = nullptr; + _textOrig = nullptr; + _icon = _iconHover = _iconPressed = nullptr; + _font = nullptr; _iD = 0; _responseType = RESPONSE_ALWAYS; } @@ -54,11 +54,11 @@ AdResponse::~AdResponse() { delete _icon; delete _iconHover; delete _iconPressed; - _text = NULL; - _textOrig = NULL; - _icon = NULL; - _iconHover = NULL; - _iconPressed = NULL; + _text = nullptr; + _textOrig = nullptr; + _icon = nullptr; + _iconHover = nullptr; + _iconPressed = nullptr; if (_font) { _gameRef->_fontStorage->removeFont(_font); } @@ -79,7 +79,7 @@ bool AdResponse::setIcon(const char *filename) { if (!_icon || DID_FAIL(_icon->loadFile(filename))) { _gameRef->LOG(0, "AdResponse::setIcon failed for file '%s'", filename); delete _icon; - _icon = NULL; + _icon = nullptr; return STATUS_FAILED; } return STATUS_OK; @@ -105,7 +105,7 @@ bool AdResponse::setIconHover(const char *filename) { if (!_iconHover || DID_FAIL(_iconHover->loadFile(filename))) { _gameRef->LOG(0, "AdResponse::setIconHover failed for file '%s'", filename); delete _iconHover; - _iconHover = NULL; + _iconHover = nullptr; return STATUS_FAILED; } return STATUS_OK; @@ -119,7 +119,7 @@ bool AdResponse::setIconPressed(const char *filename) { if (!_iconPressed || DID_FAIL(_iconPressed->loadFile(filename))) { _gameRef->LOG(0, "AdResponse::setIconPressed failed for file '%s'", filename); delete _iconPressed; - _iconPressed = NULL; + _iconPressed = nullptr; return STATUS_FAILED; } return STATUS_OK; diff --git a/engines/wintermute/ad/ad_response.h b/engines/wintermute/ad/ad_response.h index 0ba88cf2e8..2119067d3e 100644 --- a/engines/wintermute/ad/ad_response.h +++ b/engines/wintermute/ad/ad_response.h @@ -43,7 +43,7 @@ public: bool setIconHover(const char *filename); bool setIconPressed(const char *filename); void setText(const char *text); - int _iD; + int32 _iD; BaseSprite *_icon; BaseSprite *_iconHover; BaseSprite *_iconPressed; diff --git a/engines/wintermute/ad/ad_response_box.cpp b/engines/wintermute/ad/ad_response_box.cpp index fb31aa0bb8..c891d2a019 100644 --- a/engines/wintermute/ad/ad_response_box.cpp +++ b/engines/wintermute/ad/ad_response_box.cpp @@ -52,9 +52,9 @@ IMPLEMENT_PERSISTENT(AdResponseBox, false) ////////////////////////////////////////////////////////////////////////// AdResponseBox::AdResponseBox(BaseGame *inGame) : BaseObject(inGame) { - _font = _fontHover = NULL; + _font = _fontHover = nullptr; - _window = NULL; + _window = nullptr; _shieldWindow = new UIWindow(_gameRef); _horizontal = false; @@ -62,9 +62,9 @@ AdResponseBox::AdResponseBox(BaseGame *inGame) : BaseObject(inGame) { _scrollOffset = 0; _spacing = 0; - _waitingScript = NULL; - _lastResponseText = NULL; - _lastResponseTextOrig = NULL; + _waitingScript = nullptr; + _lastResponseText = nullptr; + _lastResponseTextOrig = nullptr; _verticalAlign = VAL_BOTTOM; _align = TAL_LEFT; @@ -75,13 +75,13 @@ AdResponseBox::AdResponseBox(BaseGame *inGame) : BaseObject(inGame) { AdResponseBox::~AdResponseBox() { delete _window; - _window = NULL; + _window = nullptr; delete _shieldWindow; - _shieldWindow = NULL; + _shieldWindow = nullptr; delete[] _lastResponseText; - _lastResponseText = NULL; + _lastResponseText = nullptr; delete[] _lastResponseTextOrig; - _lastResponseTextOrig = NULL; + _lastResponseTextOrig = nullptr; if (_font) { _gameRef->_fontStorage->removeFont(_font); @@ -93,9 +93,12 @@ AdResponseBox::~AdResponseBox() { clearResponses(); clearButtons(); - _waitingScript = NULL; + _waitingScript = nullptr; } +uint32 AdResponseBox::getNumResponses() const { + return _responses.size(); +} ////////////////////////////////////////////////////////////////////////// void AdResponseBox::clearResponses() { @@ -118,11 +121,11 @@ void AdResponseBox::clearButtons() { ////////////////////////////////////////////////////////////////////////// bool AdResponseBox::invalidateButtons() { for (uint32 i = 0; i < _respButtons.size(); i++) { - _respButtons[i]->_image = NULL; - _respButtons[i]->_cursor = NULL; - _respButtons[i]->_font = NULL; - _respButtons[i]->_fontHover = NULL; - _respButtons[i]->_fontPress = NULL; + _respButtons[i]->_image = nullptr; + _respButtons[i]->_cursor = nullptr; + _respButtons[i]->_font = nullptr; + _respButtons[i]->_fontHover = nullptr; + _respButtons[i]->_fontPress = nullptr; _respButtons[i]->setText(""); } return STATUS_OK; @@ -160,8 +163,8 @@ bool AdResponseBox::createButtons() { // textual else { btn->setText(_responses[i]->_text); - btn->_font = (_font == NULL) ? _gameRef->_systemFont : _font; - btn->_fontHover = (_fontHover == NULL) ? _gameRef->_systemFont : _fontHover; + btn->_font = (_font == nullptr) ? _gameRef->getSystemFont() : _font; + btn->_fontHover = (_fontHover == nullptr) ? _gameRef->getSystemFont() : _fontHover; btn->_fontPress = btn->_fontHover; btn->_align = _align; @@ -207,7 +210,7 @@ bool AdResponseBox::createButtons() { ////////////////////////////////////////////////////////////////////////// bool AdResponseBox::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdResponseBox::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -284,7 +287,7 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) { _window = new UIWindow(_gameRef); if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { delete _window; - _window = NULL; + _window = nullptr; cmd = PARSERR_GENERIC; } else if (_shieldWindow) { _shieldWindow->_parent = _window; @@ -352,7 +355,7 @@ bool AdResponseBox::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -548,7 +551,7 @@ bool AdResponseBox::listen(BaseScriptHolder *param1, uint32 param2) { _waitingScript->_stack->pushInt(_responses[param2]->_iD); } handleResponse(_responses[param2]); - _waitingScript = NULL; + _waitingScript = nullptr; _gameRef->_state = GAME_RUNNING; ((AdGame *)_gameRef)->_stateEx = GAME_NORMAL; _ready = true; @@ -627,6 +630,30 @@ void AdResponseBox::setLastResponseText(const char *text, const char *textOrig) BaseUtils::setString(&_lastResponseTextOrig, textOrig); } +const char *AdResponseBox::getLastResponseText() const { + return _lastResponseText; +} + +const char *AdResponseBox::getLastResponseTextOrig() const { + return _lastResponseTextOrig; +} + +UIWindow *AdResponseBox::getResponseWindow() { + return _window; +} + +void AdResponseBox::addResponse(AdResponse *response) { + _responses.add(response); +} + +int32 AdResponseBox::getIdForResponseNum(uint32 num) const { + assert(num < _responses.size()); + return _responses[num]->_iD; +} + +bool AdResponseBox::handleResponseNum(uint32 num) { + return handleResponse(_responses[num]); +} ////////////////////////////////////////////////////////////////////////// bool AdResponseBox::handleResponse(AdResponse *response) { @@ -656,9 +683,9 @@ BaseObject *AdResponseBox::getNextAccessObject(BaseObject *currObject) { getObjects(objects, true); if (objects.size() == 0) { - return NULL; + return nullptr; } else { - if (currObject != NULL) { + if (currObject != nullptr) { for (uint32 i = 0; i < objects.size(); i++) { if (objects[i] == currObject) { if (i < objects.size() - 1) { @@ -671,7 +698,7 @@ BaseObject *AdResponseBox::getNextAccessObject(BaseObject *currObject) { } return objects[0]; } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -680,9 +707,9 @@ BaseObject *AdResponseBox::getPrevAccessObject(BaseObject *currObject) { getObjects(objects, true); if (objects.size() == 0) { - return NULL; + return nullptr; } else { - if (currObject != NULL) { + if (currObject != nullptr) { for (int i = objects.size() - 1; i >= 0; i--) { if (objects[i] == currObject) { if (i > 0) { @@ -695,7 +722,7 @@ BaseObject *AdResponseBox::getPrevAccessObject(BaseObject *currObject) { } return objects[objects.size() - 1]; } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/ad/ad_response_box.h b/engines/wintermute/ad/ad_response_box.h index 35f8cb6347..3b180062b6 100644 --- a/engines/wintermute/ad/ad_response_box.h +++ b/engines/wintermute/ad/ad_response_box.h @@ -44,10 +44,14 @@ public: BaseObject *getPrevAccessObject(BaseObject *CurrObject); bool getObjects(BaseArray<UIObject *> &objects, bool interactiveOnly); + void addResponse(AdResponse* response); bool handleResponse(AdResponse *response); + bool handleResponseNum(uint32 num); + int32 getIdForResponseNum(uint32 num) const; void setLastResponseText(const char *text, const char *textOrig); - char *_lastResponseText; - char *_lastResponseTextOrig; + const char *getLastResponseText() const; + const char *getLastResponseTextOrig() const; + DECLARE_PERSISTENT(AdResponseBox, BaseObject) ScScript *_waitingScript; virtual bool listen(BaseScriptHolder *param1, uint32 param2); @@ -59,27 +63,35 @@ public: bool weedResponses(); bool display(); - int _spacing; - int _scrollOffset; - BaseFont *_fontHover; - BaseFont *_font; + bool createButtons(); bool invalidateButtons(); void clearButtons(); void clearResponses(); AdResponseBox(BaseGame *inGame); virtual ~AdResponseBox(); - BaseArray<AdResponse *> _responses; - BaseArray<UIButton *> _respButtons; - UIWindow *_window; - UIWindow *_shieldWindow; + + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + + UIWindow *getResponseWindow(); + uint32 getNumResponses() const; +private: + int _spacing; + int _scrollOffset; + BaseFont *_fontHover; + BaseFont *_font; bool _horizontal; Rect32 _responseArea; int _verticalAlign; TTextAlign _align; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + BaseArray<UIButton *> _respButtons; + BaseArray<AdResponse *> _responses; + UIWindow *_shieldWindow; + char *_lastResponseText; + char *_lastResponseTextOrig; + UIWindow *_window; }; } // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response_context.cpp b/engines/wintermute/ad/ad_response_context.cpp index ebfa03feea..d87651c178 100644 --- a/engines/wintermute/ad/ad_response_context.cpp +++ b/engines/wintermute/ad/ad_response_context.cpp @@ -36,14 +36,14 @@ IMPLEMENT_PERSISTENT(AdResponseContext, false) ////////////////////////////////////////////////////////////////////////// AdResponseContext::AdResponseContext(BaseGame *inGame) : BaseClass(inGame) { _id = 0; - _context = NULL; + _context = nullptr; } ////////////////////////////////////////////////////////////////////////// AdResponseContext::~AdResponseContext() { delete[] _context; - _context = NULL; + _context = nullptr; } @@ -59,7 +59,7 @@ bool AdResponseContext::persist(BasePersistenceManager *persistMgr) { ////////////////////////////////////////////////////////////////////////// void AdResponseContext::setContext(const char *context) { delete[] _context; - _context = NULL; + _context = nullptr; if (context) { _context = new char [strlen(context) + 1]; if (_context) { diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp index fb9a4a47b9..4d7f27aec7 100644 --- a/engines/wintermute/ad/ad_rot_level.cpp +++ b/engines/wintermute/ad/ad_rot_level.cpp @@ -54,7 +54,7 @@ AdRotLevel::~AdRotLevel() { ////////////////////////////////////////////////////////////////////////// bool AdRotLevel::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdRotLevel::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } diff --git a/engines/wintermute/ad/ad_scale_level.cpp b/engines/wintermute/ad/ad_scale_level.cpp index 4e9293d875..e80f38bd0f 100644 --- a/engines/wintermute/ad/ad_scale_level.cpp +++ b/engines/wintermute/ad/ad_scale_level.cpp @@ -48,11 +48,14 @@ AdScaleLevel::~AdScaleLevel() { } +float AdScaleLevel::getScale() const { + return _scale; +} ////////////////////////////////////////////////////////////////////////// bool AdScaleLevel::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdScaleLevel::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } diff --git a/engines/wintermute/ad/ad_scale_level.h b/engines/wintermute/ad/ad_scale_level.h index 628a385eb4..5c206423cf 100644 --- a/engines/wintermute/ad/ad_scale_level.h +++ b/engines/wintermute/ad/ad_scale_level.h @@ -37,12 +37,14 @@ namespace Wintermute { class AdScaleLevel : public BaseObject { public: DECLARE_PERSISTENT(AdScaleLevel, BaseObject) - float _scale; AdScaleLevel(BaseGame *inGame); virtual ~AdScaleLevel(); virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); bool loadFile(const char *filename); bool loadBuffer(byte *buffer, bool complete = true); + float getScale() const; +private: + float _scale; }; } // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp index 8e9beca0c0..f305c2f60e 100644 --- a/engines/wintermute/ad/ad_scene.cpp +++ b/engines/wintermute/ad/ad_scene.cpp @@ -77,7 +77,7 @@ AdScene::~AdScene() { cleanup(); _gameRef->unregisterObject(_fader); delete _pfTarget; - _pfTarget = NULL; + _pfTarget = nullptr; } @@ -85,9 +85,9 @@ AdScene::~AdScene() { void AdScene::setDefaults() { _initialized = false; _pfReady = true; - _pfTargetPath = NULL; - _pfRequester = NULL; - _mainLayer = NULL; + _pfTargetPath = nullptr; + _pfRequester = nullptr; + _mainLayer = nullptr; _pfPointsNum = 0; _persistentState = false; @@ -127,12 +127,12 @@ void AdScene::setDefaults() { _editorShowEntities = true; _editorShowScale = true; - _shieldWindow = NULL; + _shieldWindow = nullptr; _fader = new BaseFader(_gameRef); _gameRef->registerObject(_fader); - _viewport = NULL; + _viewport = nullptr; } @@ -140,13 +140,13 @@ void AdScene::setDefaults() { void AdScene::cleanup() { BaseObject::cleanup(); - _mainLayer = NULL; // reference only + _mainLayer = nullptr; // reference only delete _shieldWindow; - _shieldWindow = NULL; + _shieldWindow = nullptr; _gameRef->unregisterObject(_fader); - _fader = NULL; + _fader = nullptr; for (uint32 i = 0; i < _layers.size(); i++) { _gameRef->unregisterObject(_layers[i]); @@ -182,7 +182,7 @@ void AdScene::cleanup() { _objects.clear(); delete _viewport; - _viewport = NULL; + _viewport = nullptr; setDefaults(); } @@ -287,9 +287,9 @@ float AdScene::getZoomAt(int x, int y) { if (_mainLayer) { for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_blocked && node->_region->pointInRegion(x, y)) { - if (node->_region->_zoom != 0) { - ret = node->_region->_zoom; + if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->isBlocked() && node->_region->pointInRegion(x, y)) { + if (node->_region->getZoom() != 0) { + ret = node->_region->getZoom(); found = true; break; } @@ -320,9 +320,9 @@ uint32 AdScene::getAlphaAt(int x, int y, bool colorCheck) { if (_mainLayer) { for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && (colorCheck || !node->_region->_blocked) && node->_region->pointInRegion(x, y)) { - if (!node->_region->_blocked) { - ret = node->_region->_alpha; + if (node->_type == OBJECT_REGION && node->_region->_active && (colorCheck || !node->_region->isBlocked()) && node->_region->pointInRegion(x, y)) { + if (!node->_region->isBlocked()) { + ret = node->_region->getAlpha(); } break; } @@ -365,8 +365,8 @@ bool AdScene::isBlockedAt(int x, int y, bool checkFreeObjects, BaseObject *reque break; } */ - if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) { - if (node->_region->_blocked) { + if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->hasDecoration() && node->_region->pointInRegion(x, y)) { + if (node->_region->isBlocked()) { ret = true; break; } else { @@ -405,8 +405,8 @@ bool AdScene::isWalkableAt(int x, int y, bool checkFreeObjects, BaseObject *requ if (_mainLayer) { for (uint32 i = 0; i < _mainLayer->_nodes.size(); i++) { AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) { - if (node->_region->_blocked) { + if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->hasDecoration() && node->_region->pointInRegion(x, y)) { + if (node->_region->isBlocked()) { ret = false; break; } else { @@ -473,7 +473,7 @@ void AdScene::pathFinderStep() { int i; // get lowest unmarked int lowestDist = INT_MAX; - AdPathPoint *lowestPt = NULL; + AdPathPoint *lowestPt = nullptr; for (i = 0; i < _pfPointsNum; i++) if (!_pfPath[i]->_marked && _pfPath[i]->_distance < lowestDist) { @@ -481,7 +481,7 @@ void AdScene::pathFinderStep() { lowestPt = _pfPath[i]; } - if (lowestPt == NULL) { // no path -> terminate PathFinder + if (lowestPt == nullptr) { // no path -> terminate PathFinder _pfReady = true; _pfTargetPath->setReady(true); return; @@ -491,7 +491,7 @@ void AdScene::pathFinderStep() { // target point marked, generate path and terminate if (lowestPt->x == _pfTarget->x && lowestPt->y == _pfTarget->y) { - while (lowestPt != NULL) { + while (lowestPt != nullptr) { _pfTargetPath->_points.insert_at(0, new BasePoint(lowestPt->x, lowestPt->y)); lowestPt = lowestPt->_origin; } @@ -539,7 +539,7 @@ bool AdScene::initLoop() { ////////////////////////////////////////////////////////////////////////// bool AdScene::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdScene::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -680,7 +680,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { if (!layer || DID_FAIL(layer->loadBuffer(params, false))) { cmd = PARSERR_GENERIC; delete layer; - layer = NULL; + layer = nullptr; } else { _gameRef->registerObject(layer); _layers.add(layer); @@ -698,7 +698,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { if (!wpt || DID_FAIL(wpt->loadBuffer(params, false))) { cmd = PARSERR_GENERIC; delete wpt; - wpt = NULL; + wpt = nullptr; } else { _gameRef->registerObject(wpt); _waypointGroups.add(wpt); @@ -711,7 +711,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { if (!sl || DID_FAIL(sl->loadBuffer(params, false))) { cmd = PARSERR_GENERIC; delete sl; - sl = NULL; + sl = nullptr; } else { _gameRef->registerObject(sl); _scaleLevels.add(sl); @@ -724,7 +724,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { if (!rl || DID_FAIL(rl->loadBuffer(params, false))) { cmd = PARSERR_GENERIC; delete rl; - rl = NULL; + rl = nullptr; } else { _gameRef->registerObject(rl); _rotLevels.add(rl); @@ -737,7 +737,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { if (!entity || DID_FAIL(entity->loadBuffer(params, false))) { cmd = PARSERR_GENERIC; delete entity; - entity = NULL; + entity = nullptr; } else { addObject(entity); } @@ -749,7 +749,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -884,7 +884,7 @@ bool AdScene::loadBuffer(byte *buffer, bool complete) { return STATUS_FAILED; } - if (_mainLayer == NULL) { + if (_mainLayer == nullptr) { _gameRef->LOG(0, "Warning: scene '%s' has no main layer.", getFilename()); } @@ -923,7 +923,7 @@ bool AdScene::traverseNodes(bool doUpdate) { // *** adjust scroll offset if (doUpdate) { /* - if (_autoScroll && _gameRef->_mainObject != NULL) + if (_autoScroll && _gameRef->_mainObject != nullptr) { ScrollToObject(_gameRef->_mainObject); } @@ -932,24 +932,34 @@ bool AdScene::traverseNodes(bool doUpdate) { if (_autoScroll) { // adjust horizontal scroll if (_gameRef->_timer - _lastTimeH >= _scrollTimeH) { + int timesMissed = (_gameRef->_timer - _lastTimeH) / _scrollTimeH; + // Cap the amount of catch-up to avoid jittery characters. + if (timesMissed > 2) { + timesMissed = 2; + } _lastTimeH = _gameRef->_timer; if (_offsetLeft < _targetOffsetLeft) { - _offsetLeft += _scrollPixelsH; + _offsetLeft += _scrollPixelsH * timesMissed; _offsetLeft = MIN(_offsetLeft, _targetOffsetLeft); } else if (_offsetLeft > _targetOffsetLeft) { - _offsetLeft -= _scrollPixelsH; + _offsetLeft -= _scrollPixelsH * timesMissed; _offsetLeft = MAX(_offsetLeft, _targetOffsetLeft); } } // adjust vertical scroll if (_gameRef->_timer - _lastTimeV >= _scrollTimeV) { + int timesMissed = (_gameRef->_timer - _lastTimeV) / _scrollTimeV; + // Cap the amount of catch-up to avoid jittery characters. + if (timesMissed > 2) { + timesMissed = 2; + } _lastTimeV = _gameRef->_timer; if (_offsetTop < _targetOffsetTop) { - _offsetTop += _scrollPixelsV; + _offsetTop += _scrollPixelsV * timesMissed; _offsetTop = MIN(_offsetTop, _targetOffsetTop); } else if (_offsetTop > _targetOffsetTop) { - _offsetTop -= _scrollPixelsV; + _offsetTop -= _scrollPixelsV * timesMissed; _offsetTop = MAX(_offsetTop, _targetOffsetTop); } } @@ -1045,10 +1055,10 @@ bool AdScene::traverseNodes(bool doUpdate) { break; case OBJECT_REGION: { - if (node->_region->_blocked) { + if (node->_region->isBlocked()) { break; } - if (node->_region->_decoration) { + if (node->_region->hasDecoration()) { break; } @@ -1068,7 +1078,7 @@ bool AdScene::traverseNodes(bool doUpdate) { if (doUpdate) { updateFreeObjects(); } else { - displayRegionContent(NULL); + displayRegionContent(nullptr); } } } // each layer @@ -1128,8 +1138,8 @@ bool AdScene::updateFreeObjects() { } - if (_autoScroll && _gameRef->_mainObject != NULL) { - scrollToObject(_gameRef->_mainObject); + if (_autoScroll && _gameRef->getMainObject() != nullptr) { + scrollToObject(_gameRef->getMainObject()); } @@ -1140,22 +1150,22 @@ bool AdScene::updateFreeObjects() { ////////////////////////////////////////////////////////////////////////// bool AdScene::displayRegionContent(AdRegion *region, bool display3DOnly) { AdGame *adGame = (AdGame *)_gameRef; - BaseArray<AdObject *> objects; + Common::Array<AdObject *> objects; AdObject *obj; // global objects for (uint32 i = 0; i < adGame->_objects.size(); i++) { obj = adGame->_objects[i]; - if (obj->_active && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { - objects.add(obj); + if (obj->_active && !obj->_drawn && (obj->_stickRegion == region || region == nullptr || (obj->_stickRegion == nullptr && region->pointInRegion(obj->_posX, obj->_posY)))) { + objects.push_back(obj); } } // scene objects for (uint32 i = 0; i < _objects.size(); i++) { obj = _objects[i]; - if (obj->_active && !obj->_editorOnly && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { - objects.add(obj); + if (obj->_active && !obj->_editorOnly && !obj->_drawn && (obj->_stickRegion == region || region == nullptr || (obj->_stickRegion == nullptr && region->pointInRegion(obj->_posX, obj->_posY)))) { + objects.push_back(obj); } } @@ -1181,7 +1191,7 @@ bool AdScene::displayRegionContent(AdRegion *region, bool display3DOnly) { // display design only objects if (!display3DOnly) { - if (_gameRef->_editorMode && region == NULL) { + if (_gameRef->_editorMode && region == nullptr) { for (uint32 i = 0; i < _objects.size(); i++) { if (_objects[i]->_active && _objects[i]->_editorOnly) { _objects[i]->display(); @@ -1195,16 +1205,11 @@ bool AdScene::displayRegionContent(AdRegion *region, bool display3DOnly) { } ////////////////////////////////////////////////////////////////////////// -int AdScene::compareObjs(const void *obj1, const void *obj2) { - const AdObject *object1 = *(const AdObject *const *)obj1; - const AdObject *object2 = *(const AdObject *const *)obj2; - - if (object1->_posY < object2->_posY) { - return -1; - } else if (object1->_posY > object2->_posY) { - return 1; +bool AdScene::compareObjs(const AdObject *obj1, const AdObject *obj2) { + if (obj1->_posY < obj2->_posY) { + return true; } else { - return 0; + return false; } } @@ -1215,12 +1220,12 @@ bool AdScene::displayRegionContentOld(AdRegion *region) { // display all objects in region sorted by _posY do { - obj = NULL; + obj = nullptr; int minY = INT_MAX; // global objects for (uint32 i = 0; i < adGame->_objects.size(); i++) { - if (adGame->_objects[i]->_active && !adGame->_objects[i]->_drawn && adGame->_objects[i]->_posY < minY && (adGame->_objects[i]->_stickRegion == region || region == NULL || (adGame->_objects[i]->_stickRegion == NULL && region->pointInRegion(adGame->_objects[i]->_posX, adGame->_objects[i]->_posY)))) { + if (adGame->_objects[i]->_active && !adGame->_objects[i]->_drawn && adGame->_objects[i]->_posY < minY && (adGame->_objects[i]->_stickRegion == region || region == nullptr || (adGame->_objects[i]->_stickRegion == nullptr && region->pointInRegion(adGame->_objects[i]->_posX, adGame->_objects[i]->_posY)))) { obj = adGame->_objects[i]; minY = adGame->_objects[i]->_posY; } @@ -1228,14 +1233,14 @@ bool AdScene::displayRegionContentOld(AdRegion *region) { // scene objects for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && !_objects[i]->_editorOnly && !_objects[i]->_drawn && _objects[i]->_posY < minY && (_objects[i]->_stickRegion == region || region == NULL || (_objects[i]->_stickRegion == NULL && region->pointInRegion(_objects[i]->_posX, _objects[i]->_posY)))) { + if (_objects[i]->_active && !_objects[i]->_editorOnly && !_objects[i]->_drawn && _objects[i]->_posY < minY && (_objects[i]->_stickRegion == region || region == nullptr || (_objects[i]->_stickRegion == nullptr && region->pointInRegion(_objects[i]->_posX, _objects[i]->_posY)))) { obj = _objects[i]; minY = _objects[i]->_posY; } } - if (obj != NULL) { + if (obj != nullptr) { _gameRef->_renderer->setup2D(); if (_gameRef->_editorMode || !obj->_editorOnly) { @@ -1243,11 +1248,11 @@ bool AdScene::displayRegionContentOld(AdRegion *region) { } obj->_drawn = true; } - } while (obj != NULL); + } while (obj != nullptr); // design only objects - if (_gameRef->_editorMode && region == NULL) { + if (_gameRef->_editorMode && region == nullptr) { for (uint32 i = 0; i < _objects.size(); i++) { if (_objects[i]->_active && _objects[i]->_editorOnly) { _objects[i]->display(); @@ -1280,7 +1285,7 @@ void AdScene::scrollTo(int offsetX, int offsetY) { _targetOffsetTop = MIN(_targetOffsetTop, _height - viewportHeight); - if (_gameRef->_mainObject && _gameRef->_mainObject->_is3D) { + if (_gameRef->getMainObject() && _gameRef->getMainObject()->_is3D) { if (abs(origOffsetLeft - _targetOffsetLeft) < 5) { _targetOffsetLeft = origOffsetLeft; } @@ -1341,7 +1346,7 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->pushNative(act, true); } else { delete act; - act = NULL; + act = nullptr; stack->pushNULL(); } return STATUS_OK; @@ -1358,7 +1363,7 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->pushNative(ent, true); } else { delete ent; - ent = NULL; + ent = nullptr; stack->pushNULL(); } return STATUS_OK; @@ -1499,7 +1504,7 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->correctParams(1); ScValue *val = stack->pop(); - AdObject *ret = NULL; + AdObject *ret = nullptr; if (val->isInt()) { int index = val->getInt(); if (index >= 0 && index < (int32)_objects.size()) { @@ -1541,7 +1546,7 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { AdSceneNode *node = _mainLayer->_nodes[i]; if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) { - if (node->_region->_decoration && !includeDecors) { + if (node->_region->hasDecoration() && !includeDecors) { continue; } @@ -1767,7 +1772,7 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, stack->correctParams(1); ScValue *val = stack->pop(); - AdLayer *toDelete = NULL; + AdLayer *toDelete = nullptr; if (val->isNative()) { BaseScriptable *temp = val->getNative(); for (uint32 i = 0; i < _layers.size(); i++) { @@ -1782,7 +1787,7 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, toDelete = _layers[index]; } } - if (toDelete == NULL) { + if (toDelete == nullptr) { stack->pushBool(false); return STATUS_OK; } @@ -1873,7 +1878,7 @@ ScValue *AdScene::scGetProperty(const Common::String &name) { ////////////////////////////////////////////////////////////////////////// else if (name == "MouseY") { int viewportY; - getViewportOffset(NULL, &viewportY); + getViewportOffset(nullptr, &viewportY); _scValue->setInt(_gameRef->_mousePos.y + _offsetTop - viewportY); return _scValue; @@ -2202,7 +2207,7 @@ bool AdScene::saveAsText(BaseDynamicBuffer *buffer, int indent) { // free entities buffer->putTextIndent(indent + 2, "; ----- free entities\n"); for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY) { + if (_objects[i]->getType() == OBJECT_ENTITY) { _objects[i]->saveAsText(buffer, indent + 2); } @@ -2263,8 +2268,8 @@ bool AdScene::sortRotLevels() { ////////////////////////////////////////////////////////////////////////// float AdScene::getScaleAt(int Y) { - AdScaleLevel *prev = NULL; - AdScaleLevel *next = NULL; + AdScaleLevel *prev = nullptr; + AdScaleLevel *next = nullptr; for (uint32 i = 0; i < _scaleLevels.size(); i++) { /* AdScaleLevel *xxx = _scaleLevels[i];*/ @@ -2277,16 +2282,16 @@ float AdScene::getScaleAt(int Y) { } } - if (prev == NULL || next == NULL) { + if (prev == nullptr || next == nullptr) { return 100; } int delta_y = next->_posY - prev->_posY; - float delta_scale = next->_scale - prev->_scale; + float delta_scale = next->getScale() - prev->getScale(); Y -= prev->_posY; float percent = (float)Y / ((float)delta_y / 100.0f); - return prev->_scale + delta_scale / 100 * percent; + return prev->getScale() + delta_scale / 100 * percent; } @@ -2509,7 +2514,7 @@ void AdScene::pfPointsAdd(int x, int y, int distance) { _pfPath[_pfPointsNum]->y = y; _pfPath[_pfPointsNum]->_distance = distance; _pfPath[_pfPointsNum]->_marked = false; - _pfPath[_pfPointsNum]->_origin = NULL; + _pfPath[_pfPointsNum]->_origin = nullptr; } _pfPointsNum++; @@ -2586,7 +2591,7 @@ int AdScene::getOffsetLeft() { ////////////////////////////////////////////////////////////////////////// int AdScene::getOffsetTop() { int viewportY; - getViewportOffset(NULL, &viewportY); + getViewportOffset(nullptr, &viewportY); return _offsetTop - viewportY; } @@ -2612,7 +2617,7 @@ void AdScene::setOffset(int offsetLeft, int offsetTop) { ////////////////////////////////////////////////////////////////////////// BaseObject *AdScene::getNodeByName(const char *name) { - BaseObject *ret = NULL; + BaseObject *ret = nullptr; // dependent objects for (uint32 i = 0; i < _layers.size(); i++) { @@ -2629,7 +2634,7 @@ BaseObject *AdScene::getNodeByName(const char *name) { ret = node->_region; break; default: - ret = NULL; + ret = nullptr; } return ret; } @@ -2638,7 +2643,7 @@ BaseObject *AdScene::getNodeByName(const char *name) { // free entities for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->getName())) { + if (_objects[i]->getType() == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->getName())) { return _objects[i]; } } @@ -2650,7 +2655,7 @@ BaseObject *AdScene::getNodeByName(const char *name) { } } - return NULL; + return nullptr; } @@ -2722,7 +2727,7 @@ bool AdScene::persistState(bool saving) { if (!_objects[i]->_saveState) { continue; } - if (_objects[i]->_type == OBJECT_ENTITY) { + if (_objects[i]->getType() == OBJECT_ENTITY) { nodeState = state->getNodeState(_objects[i]->getName(), saving); if (nodeState) { nodeState->transferEntity((AdEntity *)_objects[i], _persistentStateSprites, saving); @@ -2750,8 +2755,8 @@ bool AdScene::persistState(bool saving) { ////////////////////////////////////////////////////////////////////////// float AdScene::getRotationAt(int x, int y) { - AdRotLevel *prev = NULL; - AdRotLevel *next = NULL; + AdRotLevel *prev = nullptr; + AdRotLevel *next = nullptr; for (uint32 i = 0; i < _rotLevels.size(); i++) { /* AdRotLevel *xxx = _rotLevels[i]; @@ -2764,7 +2769,7 @@ float AdScene::getRotationAt(int x, int y) { } } - if (prev == NULL || next == NULL) { + if (prev == nullptr || next == nullptr) { return 0; } @@ -2785,7 +2790,7 @@ bool AdScene::handleItemAssociations(const char *itemName, bool show) { if (layer->_nodes[j]->_type == OBJECT_ENTITY) { AdEntity *ent = layer->_nodes[j]->_entity; - if (ent->_item && strcmp(ent->_item, itemName) == 0) { + if (ent->getItemName() && strcmp(ent->getItemName(), itemName) == 0) { ent->_active = show; } } @@ -2793,9 +2798,9 @@ bool AdScene::handleItemAssociations(const char *itemName, bool show) { } for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY) { + if (_objects[i]->getType() == OBJECT_ENTITY) { AdEntity *ent = (AdEntity *)_objects[i]; - if (ent->_item && strcmp(ent->_item, itemName) == 0) { + if (ent->getItemName() && strcmp(ent->getItemName(), itemName) == 0) { ent->_active = show; } } @@ -2822,7 +2827,7 @@ bool AdScene::getRegionsAt(int x, int y, AdRegion **regionList, int numRegions) } } for (int i = numUsed; i < numRegions; i++) { - regionList[i] = NULL; + regionList[i] = nullptr; } return STATUS_OK; @@ -2840,9 +2845,9 @@ BaseObject *AdScene::getNextAccessObject(BaseObject *currObject) { getSceneObjects(objects, true); if (objects.size() == 0) { - return NULL; + return nullptr; } else { - if (currObject != NULL) { + if (currObject != nullptr) { for (uint32 i = 0; i < objects.size(); i++) { if (objects[i] == currObject) { if (i < objects.size() - 1) { @@ -2855,7 +2860,7 @@ BaseObject *AdScene::getNextAccessObject(BaseObject *currObject) { } return objects[0]; } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -2864,9 +2869,9 @@ BaseObject *AdScene::getPrevAccessObject(BaseObject *currObject) { getSceneObjects(objects, true); if (objects.size() == 0) { - return NULL; + return nullptr; } else { - if (currObject != NULL) { + if (currObject != nullptr) { for (int i = objects.size() - 1; i >= 0; i--) { if (objects[i] == currObject) { if (i > 0) { @@ -2879,7 +2884,7 @@ BaseObject *AdScene::getPrevAccessObject(BaseObject *currObject) { } return objects[objects.size() - 1]; } - return NULL; + return nullptr; } @@ -2957,7 +2962,7 @@ bool AdScene::getRegionObjects(AdRegion *region, BaseArray<AdObject *> &objects, // global objects for (uint32 i = 0; i < adGame->_objects.size(); i++) { obj = adGame->_objects[i]; - if (obj->_active && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { + if (obj->_active && (obj->_stickRegion == region || region == nullptr || (obj->_stickRegion == nullptr && region->pointInRegion(obj->_posX, obj->_posY)))) { if (interactiveOnly && !obj->_registrable) { continue; } @@ -2969,7 +2974,7 @@ bool AdScene::getRegionObjects(AdRegion *region, BaseArray<AdObject *> &objects, // scene objects for (uint32 i = 0; i < _objects.size(); i++) { obj = _objects[i]; - if (obj->_active && !obj->_editorOnly && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { + if (obj->_active && !obj->_editorOnly && (obj->_stickRegion == region || region == nullptr || (obj->_stickRegion == nullptr && region->pointInRegion(obj->_posX, obj->_posY)))) { if (interactiveOnly && !obj->_registrable) { continue; } diff --git a/engines/wintermute/ad/ad_scene.h b/engines/wintermute/ad/ad_scene.h index 3b482403b5..9cc8135889 100644 --- a/engines/wintermute/ad/ad_scene.h +++ b/engines/wintermute/ad/ad_scene.h @@ -67,20 +67,20 @@ public: bool pointInViewport(int x, int y); int getOffsetTop(); int getOffsetLeft(); - bool getViewportSize(int *width = NULL, int *height = NULL); - bool getViewportOffset(int *offsetX = NULL, int *offsetY = NULL); + bool getViewportSize(int *width = nullptr, int *height = nullptr); + bool getViewportOffset(int *offsetX = nullptr, int *offsetY = nullptr); BaseViewport *_viewport; BaseFader *_fader; int _pfPointsNum; void pfPointsAdd(int x, int y, int distance); void pfPointsStart(); bool _initialized; - bool correctTargetPoint(int startX, int startY, int *x, int *y, bool checkFreeObjects = false, BaseObject *requester = NULL); + bool correctTargetPoint(int startX, int startY, int *x, int *y, bool checkFreeObjects = false, BaseObject *requester = nullptr); bool correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, BaseObject *requester); DECLARE_PERSISTENT(AdScene, BaseObject) - bool displayRegionContent(AdRegion *region = NULL, bool display3DOnly = false); - bool displayRegionContentOld(AdRegion *region = NULL); - static int compareObjs(const void *obj1, const void *obj2); + bool displayRegionContent(AdRegion *region = nullptr, bool display3DOnly = false); + bool displayRegionContentOld(AdRegion *region = nullptr); + static bool compareObjs(const AdObject *obj1, const AdObject *obj2); bool updateFreeObjects(); bool traverseNodes(bool update = false); @@ -113,11 +113,11 @@ public: uint32 _pfMaxTime; bool initLoop(); void pathFinderStep(); - bool isBlockedAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = NULL); - bool isWalkableAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = NULL); + bool isBlockedAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = nullptr); + bool isWalkableAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = nullptr); AdLayer *_mainLayer; float getZoomAt(int x, int y); - bool getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester = NULL); + bool getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester = nullptr); AdScene(BaseGame *inGame); virtual ~AdScene(); BaseArray<AdLayer *> _layers; @@ -153,7 +153,7 @@ public: BaseArray<AdRotLevel *> _rotLevels; virtual bool restoreDeviceObjects(); - int getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester = NULL); + int getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester = nullptr); // scripting interface virtual ScValue *scGetProperty(const Common::String &name); @@ -164,7 +164,7 @@ public: private: bool persistState(bool saving = true); - void pfAddWaypointGroup(AdWaypointGroup *Wpt, BaseObject *requester = NULL); + void pfAddWaypointGroup(AdWaypointGroup *Wpt, BaseObject *requester = nullptr); bool _pfReady; BasePoint *_pfTarget; AdPath *_pfTargetPath; diff --git a/engines/wintermute/ad/ad_scene_node.cpp b/engines/wintermute/ad/ad_scene_node.cpp index d0202236fd..f84e9212e5 100644 --- a/engines/wintermute/ad/ad_scene_node.cpp +++ b/engines/wintermute/ad/ad_scene_node.cpp @@ -36,18 +36,18 @@ IMPLEMENT_PERSISTENT(AdSceneNode, false) ////////////////////////////////////////////////////////////////////////// AdSceneNode::AdSceneNode(BaseGame *inGame) : BaseObject(inGame) { _type = OBJECT_NONE; - _region = NULL; - _entity = NULL; + _region = nullptr; + _entity = nullptr; } ////////////////////////////////////////////////////////////////////////// AdSceneNode::~AdSceneNode() { _gameRef->unregisterObject(_region); - _region = NULL; + _region = nullptr; _gameRef->unregisterObject(_entity); - _entity = NULL; + _entity = nullptr; } diff --git a/engines/wintermute/ad/ad_scene_state.cpp b/engines/wintermute/ad/ad_scene_state.cpp index 6b34f1af53..8e022ab115 100644 --- a/engines/wintermute/ad/ad_scene_state.cpp +++ b/engines/wintermute/ad/ad_scene_state.cpp @@ -38,14 +38,14 @@ IMPLEMENT_PERSISTENT(AdSceneState, false) ////////////////////////////////////////////////////////////////////////// AdSceneState::AdSceneState(BaseGame *inGame) : BaseClass(inGame) { - _filename = NULL; + _filename = nullptr; } ////////////////////////////////////////////////////////////////////////// AdSceneState::~AdSceneState() { delete[] _filename; - _filename = NULL; + _filename = nullptr; for (uint32 i = 0; i < _nodeStates.size(); i++) { delete _nodeStates[i]; @@ -72,6 +72,9 @@ void AdSceneState::setFilename(const char *filename) { } } +const char *AdSceneState::getFilename() const { + return _filename; +} ////////////////////////////////////////////////////////////////////////// AdNodeState *AdSceneState::getNodeState(const char *name, bool saving) { @@ -88,7 +91,7 @@ AdNodeState *AdSceneState::getNodeState(const char *name, bool saving) { return ret; } else { - return NULL; + return nullptr; } } diff --git a/engines/wintermute/ad/ad_scene_state.h b/engines/wintermute/ad/ad_scene_state.h index 2b25393c5a..600aa4b581 100644 --- a/engines/wintermute/ad/ad_scene_state.h +++ b/engines/wintermute/ad/ad_scene_state.h @@ -39,9 +39,11 @@ class AdSceneState : public BaseClass { public: AdNodeState *getNodeState(const char *name, bool saving); void setFilename(const char *filename); + const char *getFilename() const; DECLARE_PERSISTENT(AdSceneState, BaseClass) AdSceneState(BaseGame *inGame); virtual ~AdSceneState(); +private: char *_filename; BaseArray<AdNodeState *> _nodeStates; }; diff --git a/engines/wintermute/ad/ad_sentence.cpp b/engines/wintermute/ad/ad_sentence.cpp index cfe4191b07..47b22a1ab3 100644 --- a/engines/wintermute/ad/ad_sentence.cpp +++ b/engines/wintermute/ad/ad_sentence.cpp @@ -45,27 +45,27 @@ IMPLEMENT_PERSISTENT(AdSentence, false) ////////////////////////////////////////////////////////////////////////// AdSentence::AdSentence(BaseGame *inGame) : BaseClass(inGame) { - _text = NULL; - _stances = NULL; - _tempStance = NULL; + _text = nullptr; + _stances = nullptr; + _tempStance = nullptr; _duration = 0; _startTime = 0; _currentStance = 0; - _font = NULL; + _font = nullptr; _pos.x = _pos.y = 0; _width = _gameRef->_renderer->_width; _align = (TTextAlign)TAL_CENTER; - _sound = NULL; + _sound = nullptr; _soundStarted = false; - _talkDef = NULL; - _currentSprite = NULL; - _currentSkelAnim = NULL; + _talkDef = nullptr; + _currentSprite = nullptr; + _currentSkelAnim = nullptr; _fixedPos = false; _freezable = true; } @@ -78,15 +78,15 @@ AdSentence::~AdSentence() { delete[] _stances; delete[] _tempStance; delete _talkDef; - _sound = NULL; - _text = NULL; - _stances = NULL; - _tempStance = NULL; - _talkDef = NULL; - - _currentSprite = NULL; // ref only - _currentSkelAnim = NULL; - _font = NULL; // ref only + _sound = nullptr; + _text = nullptr; + _stances = nullptr; + _tempStance = nullptr; + _talkDef = nullptr; + + _currentSprite = nullptr; // ref only + _currentSkelAnim = nullptr; + _font = nullptr; // ref only } @@ -113,7 +113,7 @@ void AdSentence::setStances(const char *stances) { strcpy(_stances, stances); } } else { - _stances = NULL; + _stances = nullptr; } } @@ -133,14 +133,14 @@ char *AdSentence::getNextStance() { ////////////////////////////////////////////////////////////////////////// char *AdSentence::getStance(int stance) { - if (_stances == NULL) { - return NULL; + if (_stances == nullptr) { + return nullptr; } if (_tempStance) { delete[] _tempStance; } - _tempStance = NULL; + _tempStance = nullptr; char *start; char *curr; @@ -150,7 +150,7 @@ char *AdSentence::getStance(int stance) { start = _stances; } else { pos = 0; - start = NULL; + start = nullptr; curr = _stances; while (pos < stance) { if (*curr == '\0') { @@ -166,8 +166,8 @@ char *AdSentence::getStance(int stance) { } } - if (start == NULL) { - return NULL; + if (start == nullptr) { + return nullptr; } while (*start == ' ' && *start != ',' && *start != '\0') { @@ -274,8 +274,8 @@ bool AdSentence::persist(BasePersistenceManager *persistMgr) { ////////////////////////////////////////////////////////////////////////// bool AdSentence::setupTalkFile(const char *soundFilename) { delete _talkDef; - _talkDef = NULL; - _currentSprite = NULL; + _talkDef = nullptr; + _currentSprite = nullptr; if (!soundFilename) { return STATUS_OK; @@ -294,7 +294,7 @@ bool AdSentence::setupTalkFile(const char *soundFilename) { _talkDef = new AdTalkDef(_gameRef); if (!_talkDef || DID_FAIL(_talkDef->loadFile(talkDefFileName.c_str()))) { delete _talkDef; - _talkDef = NULL; + _talkDef = nullptr; return STATUS_FAILED; } //_gameRef->LOG(0, "Using .talk file: %s", TalkDefFile); @@ -345,7 +345,7 @@ bool AdSentence::update(TDirection dir) { } _currentSprite = newSprite; } else { - _currentSprite = NULL; + _currentSprite = nullptr; } } diff --git a/engines/wintermute/ad/ad_sprite_set.cpp b/engines/wintermute/ad/ad_sprite_set.cpp index 345b483a8f..ffa7bb2530 100644 --- a/engines/wintermute/ad/ad_sprite_set.cpp +++ b/engines/wintermute/ad/ad_sprite_set.cpp @@ -42,7 +42,7 @@ AdSpriteSet::AdSpriteSet(BaseGame *inGame, BaseObject *owner) : BaseObject(inGam _owner = owner; for (int i = 0; i < NUM_DIRECTIONS; i++) { - _sprites[i] = NULL; + _sprites[i] = nullptr; } } @@ -51,17 +51,17 @@ AdSpriteSet::AdSpriteSet(BaseGame *inGame, BaseObject *owner) : BaseObject(inGam AdSpriteSet::~AdSpriteSet() { for (int i = 0; i < NUM_DIRECTIONS; i++) { delete _sprites[i]; - _sprites[i] = NULL; + _sprites[i] = nullptr; } - _owner = NULL; + _owner = nullptr; } ////////////////////////////////////////////////////////////////////////// bool AdSpriteSet::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdSpriteSet::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -121,7 +121,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC buffer = params; } - BaseSprite *spr = NULL; + BaseSprite *spr = nullptr; while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { switch (cmd) { case TOKEN_TEMPLATE: @@ -136,7 +136,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_LEFT: delete _sprites[DI_LEFT]; - _sprites[DI_LEFT] = NULL; + _sprites[DI_LEFT] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -147,7 +147,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_RIGHT: delete _sprites[DI_RIGHT]; - _sprites[DI_RIGHT] = NULL; + _sprites[DI_RIGHT] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -158,7 +158,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_UP: delete _sprites[DI_UP]; - _sprites[DI_UP] = NULL; + _sprites[DI_UP] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -169,7 +169,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_DOWN: delete _sprites[DI_DOWN]; - _sprites[DI_DOWN] = NULL; + _sprites[DI_DOWN] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -180,7 +180,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_UP_LEFT: delete _sprites[DI_UPLEFT]; - _sprites[DI_UPLEFT] = NULL; + _sprites[DI_UPLEFT] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -191,7 +191,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_UP_RIGHT: delete _sprites[DI_UPRIGHT]; - _sprites[DI_UPRIGHT] = NULL; + _sprites[DI_UPRIGHT] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -202,7 +202,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_DOWN_LEFT: delete _sprites[DI_DOWNLEFT]; - _sprites[DI_DOWNLEFT] = NULL; + _sprites[DI_DOWNLEFT] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -213,7 +213,7 @@ bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteC case TOKEN_DOWN_RIGHT: delete _sprites[DI_DOWNRIGHT]; - _sprites[DI_DOWNRIGHT] = NULL; + _sprites[DI_DOWNRIGHT] = nullptr; spr = new BaseSprite(_gameRef, _owner); if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { cmd = PARSERR_GENERIC; @@ -268,12 +268,12 @@ BaseSprite *AdSpriteSet::getSprite(TDirection direction) { dir = NUM_DIRECTIONS - 1; } - BaseSprite *ret = NULL; + BaseSprite *ret = nullptr; // find nearest set sprite int numSteps = 0; for (int i = dir; i >= 0; i--) { - if (_sprites[i] != NULL) { + if (_sprites[i] != nullptr) { ret = _sprites[i]; numSteps = dir - i; break; @@ -281,8 +281,8 @@ BaseSprite *AdSpriteSet::getSprite(TDirection direction) { } for (int i = dir; i < NUM_DIRECTIONS; i++) { - if (_sprites[i] != NULL) { - if (ret == NULL || numSteps > i - dir) { + if (_sprites[i] != nullptr) { + if (ret == nullptr || numSteps > i - dir) { return _sprites[i]; } else { return ret; diff --git a/engines/wintermute/ad/ad_sprite_set.h b/engines/wintermute/ad/ad_sprite_set.h index ba5da0ff2e..3960b5dcc7 100644 --- a/engines/wintermute/ad/ad_sprite_set.h +++ b/engines/wintermute/ad/ad_sprite_set.h @@ -41,7 +41,7 @@ public: BaseSprite *getSprite(TDirection direction); DECLARE_PERSISTENT(AdSpriteSet, BaseObject) BaseObject *_owner; - AdSpriteSet(BaseGame *inGame, BaseObject *owner = NULL); + AdSpriteSet(BaseGame *inGame, BaseObject *owner = nullptr); virtual ~AdSpriteSet(); bool loadFile(const char *filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); bool loadBuffer(byte *buffer, bool complete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); diff --git a/engines/wintermute/ad/ad_talk_def.cpp b/engines/wintermute/ad/ad_talk_def.cpp index a85cd7f986..4ad5d2ccc6 100644 --- a/engines/wintermute/ad/ad_talk_def.cpp +++ b/engines/wintermute/ad/ad_talk_def.cpp @@ -42,11 +42,11 @@ IMPLEMENT_PERSISTENT(AdTalkDef, false) ////////////////////////////////////////////////////////////////////////// AdTalkDef::AdTalkDef(BaseGame *inGame) : BaseObject(inGame) { - _defaultSpriteFilename = NULL; - _defaultSprite = NULL; + _defaultSpriteFilename = nullptr; + _defaultSprite = nullptr; - _defaultSpriteSetFilename = NULL; - _defaultSpriteSet = NULL; + _defaultSpriteSetFilename = nullptr; + _defaultSpriteSet = nullptr; } @@ -59,20 +59,20 @@ AdTalkDef::~AdTalkDef() { delete[] _defaultSpriteFilename; delete _defaultSprite; - _defaultSpriteFilename = NULL; - _defaultSprite = NULL; + _defaultSpriteFilename = nullptr; + _defaultSprite = nullptr; delete[] _defaultSpriteSetFilename; delete _defaultSpriteSet; - _defaultSpriteSetFilename = NULL; - _defaultSpriteSet = NULL; + _defaultSpriteSetFilename = nullptr; + _defaultSpriteSet = nullptr; } ////////////////////////////////////////////////////////////////////////// bool AdTalkDef::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdTalkDef::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -138,7 +138,7 @@ bool AdTalkDef::loadBuffer(byte *buffer, bool complete) { _nodes.add(node); } else { delete node; - node = NULL; + node = nullptr; cmd = PARSERR_GENERIC; } } @@ -157,7 +157,7 @@ bool AdTalkDef::loadBuffer(byte *buffer, bool complete) { _defaultSpriteSet = new AdSpriteSet(_gameRef); if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadBuffer(params, false))) { delete _defaultSpriteSet; - _defaultSpriteSet = NULL; + _defaultSpriteSet = nullptr; cmd = PARSERR_GENERIC; } } @@ -181,8 +181,8 @@ bool AdTalkDef::loadBuffer(byte *buffer, bool complete) { delete _defaultSprite; delete _defaultSpriteSet; - _defaultSprite = NULL; - _defaultSpriteSet = NULL; + _defaultSprite = nullptr; + _defaultSpriteSet = nullptr; if (_defaultSpriteFilename) { _defaultSprite = new BaseSprite(_gameRef); @@ -250,7 +250,7 @@ bool AdTalkDef::loadDefaultSprite() { _defaultSprite = new BaseSprite(_gameRef); if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) { delete _defaultSprite; - _defaultSprite = NULL; + _defaultSprite = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -259,7 +259,7 @@ bool AdTalkDef::loadDefaultSprite() { _defaultSpriteSet = new AdSpriteSet(_gameRef); if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { delete _defaultSpriteSet; - _defaultSpriteSet = NULL; + _defaultSpriteSet = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -278,7 +278,7 @@ BaseSprite *AdTalkDef::getDefaultSprite(TDirection dir) { } else if (_defaultSpriteSet) { return _defaultSpriteSet->getSprite(dir); } else { - return NULL; + return nullptr; } } diff --git a/engines/wintermute/ad/ad_talk_holder.cpp b/engines/wintermute/ad/ad_talk_holder.cpp index cca4fdc2cb..ed2333a345 100644 --- a/engines/wintermute/ad/ad_talk_holder.cpp +++ b/engines/wintermute/ad/ad_talk_holder.cpp @@ -43,14 +43,14 @@ IMPLEMENT_PERSISTENT(AdTalkHolder, false) ////////////////////////////////////////////////////////////////////////// AdTalkHolder::AdTalkHolder(BaseGame *inGame) : AdObject(inGame) { - _sprite = NULL; + _sprite = nullptr; } ////////////////////////////////////////////////////////////////////////// AdTalkHolder::~AdTalkHolder() { delete _sprite; - _sprite = NULL; + _sprite = nullptr; for (uint32 i = 0; i < _talkSprites.size(); i++) { delete _talkSprites[i]; @@ -65,7 +65,7 @@ AdTalkHolder::~AdTalkHolder() { ////////////////////////////////////////////////////////////////////////// BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { - BaseSprite *ret = NULL; + BaseSprite *ret = nullptr; // forced stance? @@ -78,7 +78,7 @@ BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { if (DID_FAIL(res)) { _gameRef->LOG(res, "AdTalkHolder::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", getName(), _forcedTalkAnimName); delete _animSprite; - _animSprite = NULL; + _animSprite = nullptr; } else { return _animSprite; } @@ -86,7 +86,7 @@ BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { } - if (stance != NULL) { + if (stance != nullptr) { // search special talk stances for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { if (scumm_stricmp(_talkSpritesEx[i]->getName(), stance) == 0) { @@ -94,7 +94,7 @@ BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { break; } } - if (ret == NULL) { + if (ret == nullptr) { // serach generic talk stances for (uint32 i = 0; i < _talkSprites.size(); i++) { if (scumm_stricmp(_talkSprites[i]->getName(), stance) == 0) { @@ -106,7 +106,7 @@ BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { } // not a valid stance? get a random one - if (ret == NULL) { + if (ret == nullptr) { if (_talkSprites.size() < 1) { ret = _sprite; } else { @@ -138,12 +138,12 @@ bool AdTalkHolder::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisS } delete _sprite; - _sprite = NULL; + _sprite = nullptr; if (val->isNULL()) { - _sprite = NULL; + _sprite = nullptr; if (setCurrent) { - _currentSprite = NULL; + _currentSprite = nullptr; } stack->pushBool(true); } else { @@ -355,7 +355,7 @@ bool AdTalkHolder::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// // Item ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Item")==0){ + if (strcmp(name, "Item")==0) { SetItem(value->getString()); return STATUS_OK; } diff --git a/engines/wintermute/ad/ad_talk_node.cpp b/engines/wintermute/ad/ad_talk_node.cpp index c909ee27ff..2e0985ed99 100644 --- a/engines/wintermute/ad/ad_talk_node.cpp +++ b/engines/wintermute/ad/ad_talk_node.cpp @@ -39,11 +39,11 @@ IMPLEMENT_PERSISTENT(AdTalkNode, false) ////////////////////////////////////////////////////////////////////////// AdTalkNode::AdTalkNode(BaseGame *inGame) : BaseClass(inGame) { - _sprite = NULL; - _spriteFilename = NULL; - _spriteSet = NULL; - _spriteSetFilename = NULL; - _comment = NULL; + _sprite = nullptr; + _spriteFilename = nullptr; + _spriteSet = nullptr; + _spriteSetFilename = nullptr; + _comment = nullptr; _startTime = _endTime = 0; _playToEnd = false; @@ -58,11 +58,11 @@ AdTalkNode::~AdTalkNode() { delete[] _spriteSetFilename; delete _spriteSet; delete _comment; - _spriteFilename = NULL; - _sprite = NULL; - _spriteSetFilename = NULL; - _spriteSet = NULL; - _comment = NULL; + _spriteFilename = nullptr; + _sprite = nullptr; + _spriteSetFilename = nullptr; + _spriteSet = nullptr; + _comment = nullptr; } @@ -123,7 +123,7 @@ bool AdTalkNode::loadBuffer(byte *buffer, bool complete) { _spriteSet = new AdSpriteSet(_gameRef); if (!_spriteSet || DID_FAIL(_spriteSet->loadBuffer(params, false))) { delete _spriteSet; - _spriteSet = NULL; + _spriteSet = nullptr; cmd = PARSERR_GENERIC; } } @@ -240,7 +240,7 @@ bool AdTalkNode::loadSprite() { _sprite = new BaseSprite(_gameRef); if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) { delete _sprite; - _sprite = NULL; + _sprite = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -249,7 +249,7 @@ bool AdTalkNode::loadSprite() { _spriteSet = new AdSpriteSet(_gameRef); if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { delete _spriteSet; - _spriteSet = NULL; + _spriteSet = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -264,9 +264,9 @@ bool AdTalkNode::loadSprite() { bool AdTalkNode::isInTimeInterval(uint32 time, TDirection dir) { if (time >= _startTime) { if (_playToEnd) { - if ((_spriteFilename && _sprite == NULL) || (_sprite && _sprite->isFinished() == false)) { + if ((_spriteFilename && _sprite == nullptr) || (_sprite && _sprite->isFinished() == false)) { return true; - } else if ((_spriteSetFilename && _spriteSet == NULL) || (_spriteSet && _spriteSet->getSprite(dir) && _spriteSet->getSprite(dir)->isFinished() == false)) { + } else if ((_spriteSetFilename && _spriteSet == nullptr) || (_spriteSet && _spriteSet->getSprite(dir) && _spriteSet->getSprite(dir)->isFinished() == false)) { return true; } else { return false; @@ -288,7 +288,7 @@ BaseSprite *AdTalkNode::getSprite(TDirection dir) { } else if (_spriteSet) { return _spriteSet->getSprite(dir); } else { - return NULL; + return nullptr; } } diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp index 81493ce769..96dece34b8 100644 --- a/engines/wintermute/ad/ad_waypoint_group.cpp +++ b/engines/wintermute/ad/ad_waypoint_group.cpp @@ -67,7 +67,7 @@ void AdWaypointGroup::cleanup() { ////////////////////////////////////////////////////////////////////////// bool AdWaypointGroup::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "AdWaypointGroup::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } diff --git a/engines/wintermute/ad/ad_waypoint_group.h b/engines/wintermute/ad/ad_waypoint_group.h index 13d6bbadd7..7e427313e6 100644 --- a/engines/wintermute/ad/ad_waypoint_group.h +++ b/engines/wintermute/ad/ad_waypoint_group.h @@ -35,22 +35,25 @@ namespace Wintermute { class BasePoint; class AdWaypointGroup : public BaseObject { public: - float _lastMimicScale; - int _lastMimicX; - int _lastMimicY; void cleanup(); bool mimic(AdWaypointGroup *wpt, float scale = 100.0f, int x = 0, int y = 0); DECLARE_PERSISTENT(AdWaypointGroup, BaseObject) virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - bool _active; AdWaypointGroup(BaseGame *inGame); bool loadFile(const char *filename); bool loadBuffer(byte *buffer, bool complete = true); virtual ~AdWaypointGroup(); + + bool _active; BaseArray<BasePoint *> _points; - int _editorSelectedPoint; + virtual ScValue *scGetProperty(const Common::String &name); virtual bool scSetProperty(const char *name, ScValue *value); +private: + int _editorSelectedPoint; + float _lastMimicScale; + int _lastMimicX; + int _lastMimicY; }; } // end of namespace Wintermute diff --git a/engines/wintermute/base/base.cpp b/engines/wintermute/base/base.cpp index e351792e61..c0459b0ce5 100644 --- a/engines/wintermute/base/base.cpp +++ b/engines/wintermute/base/base.cpp @@ -42,7 +42,7 @@ BaseClass::BaseClass(BaseGame *gameOwner) { ////////////////////////////////////////////////////////////////////////// BaseClass::BaseClass() { - _gameRef = NULL; + _gameRef = nullptr; _persistable = true; } @@ -111,8 +111,8 @@ bool BaseClass::parseEditorProperty(byte *buffer, bool complete) { buffer = params; } - char *propName = NULL; - char *propValue = NULL; + char *propName = nullptr; + char *propValue = nullptr; while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { switch (cmd) { @@ -141,16 +141,16 @@ bool BaseClass::parseEditorProperty(byte *buffer, bool complete) { if (cmd == PARSERR_TOKENNOTFOUND) { delete[] propName; delete[] propValue; - propName = NULL; - propValue = NULL; + propName = nullptr; + propValue = nullptr; _gameRef->LOG(0, "Syntax error in EDITOR_PROPERTY definition"); return STATUS_FAILED; } - if (cmd == PARSERR_GENERIC || propName == NULL || propValue == NULL) { + if (cmd == PARSERR_GENERIC || propName == nullptr || propValue == nullptr) { delete[] propName; delete[] propValue; - propName = NULL; - propValue = NULL; + propName = nullptr; + propValue = nullptr; _gameRef->LOG(0, "Error loading EDITOR_PROPERTY definition"); return STATUS_FAILED; } @@ -160,8 +160,8 @@ bool BaseClass::parseEditorProperty(byte *buffer, bool complete) { delete[] propName; delete[] propValue; - propName = NULL; - propValue = NULL; + propName = nullptr; + propValue = nullptr; return STATUS_OK; } diff --git a/engines/wintermute/base/base.h b/engines/wintermute/base/base.h index 24820c748a..7f2796c6e0 100644 --- a/engines/wintermute/base/base.h +++ b/engines/wintermute/base/base.h @@ -44,7 +44,7 @@ class BaseClass { public: bool _persistable; bool setEditorProp(const Common::String &propName, const Common::String &propValue); - Common::String getEditorProp(const Common::String &propName, const Common::String &initVal = NULL); + Common::String getEditorProp(const Common::String &propName, const Common::String &initVal = nullptr); BaseClass(TDynamicConstructor, TDynamicConstructor) {} bool parseEditorProperty(byte *buffer, bool complete = true); virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); diff --git a/engines/wintermute/base/base_active_rect.cpp b/engines/wintermute/base/base_active_rect.cpp index 4addf15be8..4c62cf9561 100644 --- a/engines/wintermute/base/base_active_rect.cpp +++ b/engines/wintermute/base/base_active_rect.cpp @@ -37,9 +37,9 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////// BaseActiveRect::BaseActiveRect(BaseGame *inGame) : BaseClass(inGame) { BasePlatform::setRectEmpty(&_rect); - _owner = NULL; - _frame = NULL; - _region = NULL; + _owner = nullptr; + _frame = nullptr; + _region = nullptr; _zoomX = 100; _zoomY = 100; _offsetX = _offsetY = 0; @@ -55,7 +55,7 @@ BaseActiveRect::BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseSubFrame _zoomX = zoomX; _zoomY = zoomY; _precise = precise; - _region = NULL; + _region = nullptr; _offsetX = _offsetY = 0; clipRect(); } @@ -69,7 +69,7 @@ BaseActiveRect::BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseRegion * _zoomX = 100; _zoomY = 100; _precise = true; - _frame = NULL; + _frame = nullptr; clipRect(); _offsetX = offsetX; _offsetY = offsetY; @@ -78,9 +78,9 @@ BaseActiveRect::BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseRegion * ////////////////////////////////////////////////////////////////////// BaseActiveRect::~BaseActiveRect() { - _owner = NULL; - _frame = NULL; - _region = NULL; + _owner = nullptr; + _frame = nullptr; + _region = nullptr; } diff --git a/engines/wintermute/base/base_active_rect.h b/engines/wintermute/base/base_active_rect.h index fcd2619b03..7ef8374814 100644 --- a/engines/wintermute/base/base_active_rect.h +++ b/engines/wintermute/base/base_active_rect.h @@ -48,7 +48,7 @@ public: int _offsetX; int _offsetY; Rect32 _rect; - BaseActiveRect(BaseGame *inGameOwner = NULL); + BaseActiveRect(BaseGame *inGameOwner = nullptr); BaseActiveRect(BaseGame *inGameOwner, BaseObject *owner, BaseSubFrame *frame, int x, int y, int width, int height, float zoomX = 100, float zoomY = 100, bool precise = true); BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseRegion *region, int offsetX, int offsetY); virtual ~BaseActiveRect(); diff --git a/engines/wintermute/base/base_dynamic_buffer.cpp b/engines/wintermute/base/base_dynamic_buffer.cpp index fc48e93c2b..f684420b1e 100644 --- a/engines/wintermute/base/base_dynamic_buffer.cpp +++ b/engines/wintermute/base/base_dynamic_buffer.cpp @@ -33,7 +33,7 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////////// BaseDynamicBuffer::BaseDynamicBuffer(BaseGame *inGame, uint32 initSize, uint32 growBy) { - _buffer = NULL; + _buffer = nullptr; _size = 0; _realSize = 0; @@ -56,7 +56,7 @@ void BaseDynamicBuffer::cleanup() { if (_buffer) { free(_buffer); } - _buffer = NULL; + _buffer = nullptr; _size = 0; _realSize = 0; _offset = 0; @@ -65,7 +65,7 @@ void BaseDynamicBuffer::cleanup() { ////////////////////////////////////////////////////////////////////////// -uint32 BaseDynamicBuffer::getSize() { +uint32 BaseDynamicBuffer::getSize() const { return _size; } @@ -164,7 +164,7 @@ char *BaseDynamicBuffer::getString() { _offset += len; if (!strcmp(ret, "(null)")) { - return NULL; + return nullptr; } else { return ret; } diff --git a/engines/wintermute/base/base_dynamic_buffer.h b/engines/wintermute/base/base_dynamic_buffer.h index 2d1a7fbe48..ad78ebad00 100644 --- a/engines/wintermute/base/base_dynamic_buffer.h +++ b/engines/wintermute/base/base_dynamic_buffer.h @@ -43,7 +43,7 @@ public: void putString(const char *val); bool getBytes(byte *buffer, uint32 size); bool putBytes(const byte *buffer, uint32 size); - uint32 getSize(); + uint32 getSize() const; bool init(uint32 initSize = 0); void cleanup(); BaseDynamicBuffer(BaseGame *inGame, uint32 initSize = 1000, uint32 growBy = 1000); diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp index 8146d14beb..a13ca4d919 100644 --- a/engines/wintermute/base/base_engine.cpp +++ b/engines/wintermute/base/base_engine.cpp @@ -39,10 +39,10 @@ DECLARE_SINGLETON(Wintermute::BaseEngine); namespace Wintermute { BaseEngine::BaseEngine() { - _fileManager = NULL; - _gameRef = NULL; - _classReg = NULL; - _rnd = NULL; + _fileManager = nullptr; + _gameRef = nullptr; + _classReg = nullptr; + _rnd = nullptr; _gameId = ""; } diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h index 1ed0e3ab01..f04c594699 100644 --- a/engines/wintermute/base/base_engine.h +++ b/engines/wintermute/base/base_engine.h @@ -57,7 +57,7 @@ public: Common::RandomSource *getRandomSource() { return _rnd; } uint32 randInt(int from, int to); - SystemClassRegistry *getClassRegistry(){ return _classReg; } + SystemClassRegistry *getClassRegistry() { return _classReg; } BaseGame *getGameRef() { return _gameRef; } BaseFileManager *getFileManager() { return _fileManager; } static void LOG(bool res, const char *fmt, ...); diff --git a/engines/wintermute/base/base_fader.cpp b/engines/wintermute/base/base_fader.cpp index 985718fcab..8f74d71caf 100644 --- a/engines/wintermute/base/base_fader.cpp +++ b/engines/wintermute/base/base_fader.cpp @@ -164,7 +164,7 @@ bool BaseFader::fadeOut(uint32 targetColor, uint32 duration, bool system) { ////////////////////////////////////////////////////////////////////////// -uint32 BaseFader::getCurrentColor() { +uint32 BaseFader::getCurrentColor() const { return BYTETORGBA(_red, _green, _blue, _currentAlpha); } diff --git a/engines/wintermute/base/base_fader.h b/engines/wintermute/base/base_fader.h index 116c8c963d..845ce2f244 100644 --- a/engines/wintermute/base/base_fader.h +++ b/engines/wintermute/base/base_fader.h @@ -36,7 +36,7 @@ namespace Wintermute { class BaseFader : public BaseObject { public: - uint32 getCurrentColor(); + uint32 getCurrentColor() const; bool fadeOut(uint32 targetColor, uint32 duration, bool system = false); bool fadeIn(uint32 sourceColor, uint32 duration, bool system = false); bool deactivate(); diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp index b726c0c66f..08358f9033 100644 --- a/engines/wintermute/base/base_file_manager.cpp +++ b/engines/wintermute/base/base_file_manager.cpp @@ -31,7 +31,6 @@ #include "engines/wintermute/base/file/base_disk_file.h" #include "engines/wintermute/base/file/base_save_thumb_file.h" #include "engines/wintermute/base/file/base_package.h" -#include "engines/wintermute/base/file/base_resources.h" #include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/wintermute.h" #include "common/debug.h" @@ -45,6 +44,7 @@ #include "common/file.h" #include "common/savefile.h" #include "common/fs.h" +#include "common/unzip.h" namespace Wintermute { @@ -55,6 +55,8 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////// BaseFileManager::BaseFileManager(Common::Language lang) { _language = lang; + _resources = nullptr; + initResources(); initPaths(); registerPackages(); } @@ -79,37 +81,41 @@ bool BaseFileManager::cleanup() { // delete packages _packages.clear(); + // get rid of the resources: + delete _resources; + _resources = NULL; + return STATUS_OK; } ////////////////////////////////////////////////////////////////////// byte *BaseFileManager::readWholeFile(const Common::String &filename, uint32 *size, bool mustExist) { - byte *buffer = NULL; + byte *buffer = nullptr; Common::SeekableReadStream *file = openFile(filename); if (!file) { if (mustExist) { debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Error opening file '%s'", filename.c_str()); } - return NULL; + return nullptr; } buffer = new byte[file->size() + 1]; - if (buffer == NULL) { + if (buffer == nullptr) { debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Error allocating buffer for file '%s' (%d bytes)", filename.c_str(), file->size() + 1); closeFile(file); - return NULL; + return nullptr; } if (file->read(buffer, (uint32)file->size()) != (uint32)file->size()) { debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Error reading file '%s'", filename.c_str()); closeFile(file); delete[] buffer; - return NULL; + return nullptr; }; buffer[file->size()] = '\0'; - if (size != NULL) { + if (size != nullptr) { *size = file->size(); } closeFile(file); @@ -224,11 +230,21 @@ bool BaseFileManager::registerPackage(Common::FSNode file, const Common::String return STATUS_OK; } +void BaseFileManager::initResources() { + _resources = Common::makeZipArchive("wintermute.zip"); + if (!_resources) { + error("Couldn't load wintermute.zip"); + } + assert(_resources->hasFile("syste_font.bmp")); + assert(_resources->hasFile("invalid.bmp")); + assert(_resources->hasFile("invalid_debug.bmp")); +} + ////////////////////////////////////////////////////////////////////////// Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &filename) { Common::String upcName = filename; upcName.toUppercase(); - Common::SeekableReadStream *file = NULL; + Common::SeekableReadStream *file = nullptr; char fileName[MAX_PATH_LENGTH]; strcpy(fileName, upcName.c_str()); @@ -240,7 +256,7 @@ Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &f } Common::ArchiveMemberPtr entry = _packages.getMember(upcName); if (!entry) { - return NULL; + return nullptr; } file = entry->createReadStream(); return file; @@ -261,7 +277,7 @@ bool BaseFileManager::hasFile(const Common::String &filename) { if (_packages.hasFile(filename)) { return true; // We don't bother checking if the file can actually be opened, something bigger is wrong if that is the case. } - if (BaseResources::hasFile(filename)) { + if (_resources->hasFile(filename)) { return true; } return false; @@ -270,7 +286,7 @@ bool BaseFileManager::hasFile(const Common::String &filename) { ////////////////////////////////////////////////////////////////////////// Common::SeekableReadStream *BaseFileManager::openFile(const Common::String &filename, bool absPathWarning, bool keepTrackOf) { if (strcmp(filename.c_str(), "") == 0) { - return NULL; + return nullptr; } debugC(kWintermuteDebugFileAccess, "Open file %s", filename.c_str()); @@ -297,7 +313,7 @@ bool BaseFileManager::closeFile(Common::SeekableReadStream *File) { ////////////////////////////////////////////////////////////////////////// Common::SeekableReadStream *BaseFileManager::openFileRaw(const Common::String &filename) { - Common::SeekableReadStream *ret = NULL; + Common::SeekableReadStream *ret = nullptr; if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) { if (!BaseEngine::instance().getGameRef()) { @@ -321,20 +337,20 @@ Common::SeekableReadStream *BaseFileManager::openFileRaw(const Common::String &f return ret; } - ret = BaseResources::getFile(filename); + ret = _resources->createReadStreamForMember(filename); if (ret) { return ret; } debugC(kWintermuteDebugFileAccess ,"BFileManager::OpenFileRaw - Failed to open %s", filename.c_str()); - return NULL; + return nullptr; } BaseFileManager *BaseFileManager::getEngineInstance() { if (BaseEngine::instance().getFileManager()) { return BaseEngine::instance().getFileManager(); } - return NULL; + return nullptr; } } // end of namespace Wintermute diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h index 70aff49bbb..5fc626a314 100644 --- a/engines/wintermute/base/base_file_manager.h +++ b/engines/wintermute/base/base_file_manager.h @@ -43,7 +43,7 @@ public: bool closeFile(Common::SeekableReadStream *File); bool hasFile(const Common::String &filename); Common::SeekableReadStream *openFile(const Common::String &filename, bool absPathWarning = true, bool keepTrackOf = true); - byte *readWholeFile(const Common::String &filename, uint32 *size = NULL, bool mustExist = true); + byte *readWholeFile(const Common::String &filename, uint32 *size = nullptr, bool mustExist = true); BaseFileManager(Common::Language lang); virtual ~BaseFileManager(); @@ -59,6 +59,7 @@ private: bool initPaths(); bool addPath(TPathType type, const Common::FSNode &path); bool registerPackages(); + void initResources(); Common::SeekableReadStream *openFileRaw(const Common::String &filename); Common::SeekableReadStream *openPkgFile(const Common::String &filename); Common::FSList _packagePaths; @@ -67,6 +68,7 @@ private: Common::SearchSet _packages; Common::Array<Common::SeekableReadStream *> _openFiles; Common::Language _language; + Common::Archive *_resources; // This class is intentionally not a subclass of Base, as it needs to be used by // the detector too, without launching the entire engine: }; diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp index 7c64144480..8a190c729b 100644 --- a/engines/wintermute/base/base_frame.cpp +++ b/engines/wintermute/base/base_frame.cpp @@ -48,7 +48,7 @@ BaseFrame::BaseFrame(BaseGame *inGame) : BaseScriptable(inGame, true) { _delay = 0; _moveX = _moveY = 0; - _sound = NULL; + _sound = nullptr; _killSound = false; _editorExpanded = false; @@ -59,7 +59,7 @@ BaseFrame::BaseFrame(BaseGame *inGame) : BaseScriptable(inGame, true) { ////////////////////////////////////////////////////////////////////// BaseFrame::~BaseFrame() { delete _sound; - _sound = NULL; + _sound = nullptr; for (uint32 i = 0; i < _subframes.size(); i++) { delete _subframes[i]; @@ -68,7 +68,7 @@ BaseFrame::~BaseFrame() { for (uint32 i = 0; i < _applyEvent.size(); i++) { delete[] _applyEvent[i]; - _applyEvent[i] = NULL; + _applyEvent[i] = nullptr; } _applyEvent.clear(); } @@ -181,7 +181,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { bool mirrorX = false; bool mirrorY = false; BasePlatform::setRectEmpty(&rect); - char *surface_file = NULL; + char *surface_file = nullptr; while ((cmd = parser.getCommand((char **)&buffer, commands, ¶ms)) > 0) { switch (cmd) { @@ -260,7 +260,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { case TOKEN_SOUND: { if (_sound) { delete _sound; - _sound = NULL; + _sound = nullptr; } _sound = new BaseSound(_gameRef); if (!_sound || DID_FAIL(_sound->setSound(params, Audio::Mixer::kSFXSoundType, false))) { @@ -268,7 +268,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { _gameRef->LOG(0, "Error loading sound '%s'.", params); } delete _sound; - _sound = NULL; + _sound = nullptr; } } break; @@ -305,7 +305,7 @@ bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { BaseSubFrame *sub = new BaseSubFrame(_gameRef); - if (surface_file != NULL) { + if (surface_file != nullptr) { if (custoTrans) { sub->setSurface(surface_file, false, r, g, b, lifeTime, keepLoaded); } else { @@ -452,14 +452,14 @@ bool BaseFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStac stack->correctParams(1); ScValue *val = stack->pop(); delete _sound; - _sound = NULL; + _sound = nullptr; if (!val->isNULL()) { _sound = new BaseSound(_gameRef); if (!_sound || DID_FAIL(_sound->setSound(val->getString(), Audio::Mixer::kSFXSoundType, false))) { stack->pushBool(false); delete _sound; - _sound = NULL; + _sound = nullptr; } else { stack->pushBool(true); } @@ -516,13 +516,13 @@ bool BaseFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStac else if (strcmp(name, "AddSubframe") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); - const char *filename = NULL; + const char *filename = nullptr; if (!val->isNULL()) { filename = val->getString(); } BaseSubFrame *sub = new BaseSubFrame(_gameRef); - if (filename != NULL) { + if (filename != nullptr) { sub->setSurface(filename); sub->setDefaultRect(); } @@ -543,13 +543,13 @@ bool BaseFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStac } ScValue *val = stack->pop(); - const char *filename = NULL; + const char *filename = nullptr; if (!val->isNULL()) { filename = val->getString(); } BaseSubFrame *sub = new BaseSubFrame(_gameRef); - if (filename != NULL) { + if (filename != nullptr) { sub->setSurface(filename); } diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h index 7c5d893e70..5ed0b92bba 100644 --- a/engines/wintermute/base/base_frame.h +++ b/engines/wintermute/base/base_frame.h @@ -51,7 +51,7 @@ public: int _moveX; uint32 _delay; BaseArray<BaseSubFrame *> _subframes; - bool draw(int x, int y, BaseObject *registerOwner = NULL, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); + bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded); BaseFrame(BaseGame *inGame); diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp index b6886b7a33..0248c349e7 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -29,17 +29,15 @@ #include "engines/wintermute/dcgf.h" #include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_game_music.h" #include "engines/wintermute/base/base_fader.h" #include "engines/wintermute/base/base_file_manager.h" #include "engines/wintermute/base/font/base_font.h" #include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/gfx/base_image.h" -#include "engines/wintermute/base/gfx/base_surface.h" #include "engines/wintermute/base/gfx/base_renderer.h" #include "engines/wintermute/base/base_keyboard_state.h" #include "engines/wintermute/base/base_parser.h" #include "engines/wintermute/base/base_quick_msg.h" -#include "engines/wintermute/base/sound/base_sound.h" #include "engines/wintermute/base/sound/base_sound_manager.h" #include "engines/wintermute/base/base_sprite.h" #include "engines/wintermute/base/base_sub_frame.h" @@ -54,7 +52,7 @@ #include "engines/wintermute/base/scriptables/script_engine.h" #include "engines/wintermute/base/scriptables/script_stack.h" #include "engines/wintermute/base/scriptables/script.h" -#include "engines/wintermute/base/scriptables/script_ext_math.h" +#include "engines/wintermute/base/sound/base_sound.h" #include "engines/wintermute/video/video_player.h" #include "engines/wintermute/video/video_theora_player.h" #include "engines/wintermute/utils/utils.h" @@ -93,30 +91,30 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _interactive = true; _origInteractive = false; - _surfaceStorage = NULL; - _fontStorage = NULL; - _renderer = NULL; - _soundMgr = NULL; - _transMgr = NULL; - _scEngine = NULL; - _keyboardState = NULL; + _surfaceStorage = nullptr; + _fontStorage = nullptr; + _renderer = nullptr; + _soundMgr = nullptr; + _transMgr = nullptr; + _scEngine = nullptr; + _keyboardState = nullptr; - _mathClass = NULL; + _mathClass = nullptr; - _debugLogFile = NULL; + _debugLogFile = nullptr; _debugDebugMode = false; _debugShowFPS = false; - _systemFont = NULL; - _videoFont = NULL; + _systemFont = nullptr; + _videoFont = nullptr; - _videoPlayer = NULL; - _theoraPlayer = NULL; + _videoPlayer = nullptr; + _theoraPlayer = nullptr; - _mainObject = NULL; - _activeObject = NULL; + _mainObject = nullptr; + _activeObject = nullptr; - _fader = NULL; + _fader = nullptr; _offsetX = _offsetY = 0; _offsetPercentX = _offsetPercentY = 0.0f; @@ -136,21 +134,18 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _mousePos.x = _mousePos.y = 0; _mouseLeftDown = _mouseRightDown = _mouseMidlleDown = false; - _capturedObject = NULL; + _capturedObject = nullptr; // FPS counters _lastTime = _fpsTime = _deltaTime = _framesRendered = _fps = 0; - _cursorNoninteractive = NULL; + _cursorNoninteractive = nullptr; _useD3D = false; _stringTable = new BaseStringTable(this); - for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { - _music[i] = NULL; - _musicStartTime[i] = 0; - } + _musicSystem = new BaseGameMusic(this); _settingsResWidth = 800; _settingsResHeight = 600; @@ -158,7 +153,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _settingsRequireSound = false; _settingsTLMode = 0; _settingsAllowWindowed = true; - _settingsGameFile = NULL; + _settingsGameFile = nullptr; _settingsAllowAdvanced = false; _settingsAllowAccessTab = true; _settingsAllowAboutTab = true; @@ -167,7 +162,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _editorForceScripts = false; _editorAlwaysRegister = false; - _focusedWindow = NULL; + _focusedWindow = nullptr; _loadInProgress = false; @@ -181,8 +176,8 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _editorMode = false; //_doNotExpandStrings = false; - _engineLogCallback = NULL; - _engineLogCallbackData = NULL; + _engineLogCallback = nullptr; + _engineLogCallbackData = nullptr; _smartCache = false; _surfaceGCCycleTime = 10000; @@ -198,21 +193,12 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _thumbnailWidth = _thumbnailHeight = 0; _richSavedGames = false; - _savedGameExt = NULL; - BaseUtils::setString(&_savedGameExt, "dsv"); - - _musicCrossfadeRunning = false; - _musicCrossfadeStartTime = 0; - _musicCrossfadeLength = 0; - _musicCrossfadeChannel1 = -1; - _musicCrossfadeChannel2 = -1; - _musicCrossfadeSwap = false; - - _localSaveDir = NULL; - BaseUtils::setString(&_localSaveDir, "saves"); + _savedGameExt = "dsv"; + _localSaveDir = "saves"; + _saveDirChecked = false; - _loadingIcon = NULL; + _loadingIcon = nullptr; _loadingIconX = _loadingIconY = 0; _loadingIconPersistent = false; @@ -222,8 +208,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _soundBufferSizeSec = 3; _suspendedRendering = false; - _lastCursor = NULL; - + _lastCursor = nullptr; BasePlatform::setRectEmpty(&_mouseLockRect); @@ -231,7 +216,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam _lastMiniUpdate = 0; _miniUpdateEnabled = false; - _cachedThumbnail = NULL; + _cachedThumbnail = nullptr; _autorunDisabled = false; @@ -268,9 +253,7 @@ BaseGame::~BaseGame() { cleanup(); - delete[] _localSaveDir; delete[] _settingsGameFile; - delete[] _savedGameExt; delete _cachedThumbnail; @@ -287,25 +270,25 @@ BaseGame::~BaseGame() { delete _renderer; delete _stringTable; + delete _musicSystem; - _localSaveDir = NULL; - _settingsGameFile = NULL; - _savedGameExt = NULL; + _settingsGameFile = nullptr; - _cachedThumbnail = NULL; + _cachedThumbnail = nullptr; - _mathClass = NULL; + _mathClass = nullptr; - _transMgr = NULL; - _scEngine = NULL; - _fontStorage = NULL; - _surfaceStorage = NULL; - _videoPlayer = NULL; - _theoraPlayer = NULL; - _soundMgr = NULL; + _transMgr = nullptr; + _scEngine = nullptr; + _fontStorage = nullptr; + _surfaceStorage = nullptr; + _videoPlayer = nullptr; + _theoraPlayer = nullptr; + _soundMgr = nullptr; - _renderer = NULL; - _stringTable = NULL; + _renderer = nullptr; + _stringTable = nullptr; + _musicSystem = nullptr; DEBUG_DebugDisable(); debugC(kWintermuteDebugLog, "--- shutting down normally ---\n"); @@ -315,52 +298,48 @@ BaseGame::~BaseGame() { ////////////////////////////////////////////////////////////////////////// bool BaseGame::cleanup() { delete _loadingIcon; - _loadingIcon = NULL; + _loadingIcon = nullptr; - _engineLogCallback = NULL; - _engineLogCallbackData = NULL; + _engineLogCallback = nullptr; + _engineLogCallbackData = nullptr; - for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { - delete _music[i]; - _music[i] = NULL; - _musicStartTime[i] = 0; - } + _musicSystem->cleanup(); unregisterObject(_fader); - _fader = NULL; + _fader = nullptr; for (uint32 i = 0; i < _regObjects.size(); i++) { delete _regObjects[i]; - _regObjects[i] = NULL; + _regObjects[i] = nullptr; } _regObjects.clear(); _windows.clear(); // refs only - _focusedWindow = NULL; // ref only + _focusedWindow = nullptr; // ref only delete _cursorNoninteractive; delete _cursor; delete _activeCursor; - _cursorNoninteractive = NULL; - _cursor = NULL; - _activeCursor = NULL; + _cursorNoninteractive = nullptr; + _cursor = nullptr; + _activeCursor = nullptr; delete _scValue; delete _sFX; - _scValue = NULL; - _sFX = NULL; + _scValue = nullptr; + _sFX = nullptr; for (uint32 i = 0; i < _scripts.size(); i++) { - _scripts[i]->_owner = NULL; + _scripts[i]->_owner = nullptr; _scripts[i]->finish(); } _scripts.clear(); _fontStorage->removeFont(_systemFont); - _systemFont = NULL; + _systemFont = nullptr; _fontStorage->removeFont(_videoFont); - _videoFont = NULL; + _videoFont = nullptr; for (uint32 i = 0; i < _quickMessages.size(); i++) { delete _quickMessages[i]; @@ -370,17 +349,17 @@ bool BaseGame::cleanup() { _viewportStack.clear(); _viewportSP = -1; - setName(NULL); - setFilename(NULL); + setName(nullptr); + setFilename(nullptr); for (int i = 0; i < 7; i++) { delete[] _caption[i]; - _caption[i] = NULL; + _caption[i] = nullptr; } - _lastCursor = NULL; + _lastCursor = nullptr; delete _keyboardState; - _keyboardState = NULL; + _keyboardState = nullptr; return STATUS_OK; } @@ -391,47 +370,47 @@ bool BaseGame::initialize1() { bool loaded = false; // Not really a loop, but a goto-replacement. while (!loaded) { _surfaceStorage = new BaseSurfaceStorage(this); - if (_surfaceStorage == NULL) { + if (_surfaceStorage == nullptr) { break; } _fontStorage = new BaseFontStorage(this); - if (_fontStorage == NULL) { + if (_fontStorage == nullptr) { break; } _soundMgr = new BaseSoundMgr(this); - if (_soundMgr == NULL) { + if (_soundMgr == nullptr) { break; } - _mathClass = new SXMath(this); - if (_mathClass == NULL) { + _mathClass = makeSXMath(this); + if (_mathClass == nullptr) { break; } _scEngine = new ScEngine(this); - if (_scEngine == NULL) { + if (_scEngine == nullptr) { break; } _videoPlayer = new VideoPlayer(this); - if (_videoPlayer == NULL) { + if (_videoPlayer == nullptr) { break; } _transMgr = new BaseTransitionMgr(this); - if (_transMgr == NULL) { + if (_transMgr == nullptr) { break; } _keyboardState = new BaseKeyboardState(this); - if (_keyboardState == NULL) { + if (_keyboardState == nullptr) { break; } _fader = new BaseFader(this); - if (_fader == NULL) { + if (_fader == nullptr) { break; } registerObject(_fader); @@ -457,7 +436,7 @@ bool BaseGame::initialize1() { ////////////////////////////////////////////////////////////////////// bool BaseGame::initialize2() { // we know whether we are going to be accelerated _renderer = makeOSystemRenderer(this); - if (_renderer == NULL) { + if (_renderer == nullptr) { return STATUS_FAILED; } @@ -500,10 +479,10 @@ void BaseGame::DEBUG_DebugEnable(const char *filename) { ////////////////////////////////////////////////////////////////////// void BaseGame::DEBUG_DebugDisable() { - if (_debugLogFile != NULL) { + if (_debugLogFile != nullptr) { LOG(0, "********** DEBUG LOG CLOSED ********************************************"); //fclose((FILE *)_debugLogFile); - _debugLogFile = NULL; + _debugLogFile = nullptr; } _debugDebugMode = false; } @@ -552,13 +531,13 @@ bool BaseGame::initLoop() { _currentTime = g_system->getMillis(); _renderer->initLoop(); - updateMusicCrossfade(); + _musicSystem->updateMusicCrossfade(); _surfaceStorage->initLoop(); _fontStorage->initLoop(); - //_activeObject = NULL; + //_activeObject = nullptr; // count FPS _deltaTime = _currentTime - _lastTime; @@ -587,7 +566,7 @@ bool BaseGame::initLoop() { getMousePos(&_mousePos); - _focusedWindow = NULL; + _focusedWindow = nullptr; for (int i = _windows.size() - 1; i >= 0; i--) { if (_windows[i]->_visible) { _focusedWindow = _windows[i]; @@ -625,10 +604,10 @@ void BaseGame::setOffset(int offsetX, int offsetY) { ////////////////////////////////////////////////////////////////////////// void BaseGame::getOffset(int *offsetX, int *offsetY) { - if (offsetX != NULL) { + if (offsetX != nullptr) { *offsetX = _offsetX; } - if (offsetY != NULL) { + if (offsetY != nullptr) { *offsetY = _offsetY; } } @@ -637,7 +616,7 @@ void BaseGame::getOffset(int *offsetX, int *offsetY) { ////////////////////////////////////////////////////////////////////////// bool BaseGame::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "BaseGame::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -788,7 +767,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) { if (_systemFont) { _fontStorage->removeFont(_systemFont); } - _systemFont = NULL; + _systemFont = nullptr; _systemFont = _gameRef->_fontStorage->addFont((char *)params); break; @@ -797,7 +776,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) { if (_videoFont) { _fontStorage->removeFont(_videoFont); } - _videoFont = NULL; + _videoFont = nullptr; _videoFont = _gameRef->_fontStorage->addFont((char *)params); break; @@ -808,18 +787,18 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; case TOKEN_ACTIVE_CURSOR: delete _activeCursor; - _activeCursor = NULL; + _activeCursor = nullptr; _activeCursor = new BaseSprite(_gameRef); if (!_activeCursor || DID_FAIL(_activeCursor->loadFile((char *)params))) { delete _activeCursor; - _activeCursor = NULL; + _activeCursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -829,7 +808,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) { _cursorNoninteractive = new BaseSprite(_gameRef); if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile((char *)params))) { delete _cursorNoninteractive; - _cursorNoninteractive = NULL; + _cursorNoninteractive = nullptr; cmd = PARSERR_GENERIC; } break; @@ -918,7 +897,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) { break; case TOKEN_LOCAL_SAVE_DIR: - BaseUtils::setString(&_localSaveDir, (char *)params); + _localSaveDir = (char *)params; break; case TOKEN_COMPAT_KILL_METHOD_THREADS: @@ -1077,7 +1056,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->pushNative(win, true); } else { delete win; - win = NULL; + win = nullptr; stack->pushNULL(); } return STATUS_OK; @@ -1097,272 +1076,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack return STATUS_OK; } - ////////////////////////////////////////////////////////////////////////// - // PlayMusic / PlayMusicChannel - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PlayMusic") == 0 || strcmp(name, "PlayMusicChannel") == 0) { - int channel = 0; - if (strcmp(name, "PlayMusic") == 0) { - stack->correctParams(3); - } else { - stack->correctParams(4); - channel = stack->pop()->getInt(); - } - - const char *filename = stack->pop()->getString(); - ScValue *valLooping = stack->pop(); - bool looping = valLooping->isNULL() ? true : valLooping->getBool(); - - ScValue *valLoopStart = stack->pop(); - uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt()); - - - if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // StopMusic / StopMusicChannel - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) { - int channel = 0; - - if (strcmp(name, "StopMusic") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - - if (DID_FAIL(stopMusic(channel))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PauseMusic / PauseMusicChannel - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) { - int channel = 0; - - if (strcmp(name, "PauseMusic") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - - if (DID_FAIL(pauseMusic(channel))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ResumeMusic / ResumeMusicChannel - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ResumeMusic") == 0 || strcmp(name, "ResumeMusicChannel") == 0) { - int channel = 0; - if (strcmp(name, "ResumeMusic") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - - if (DID_FAIL(resumeMusic(channel))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetMusic / GetMusicChannel - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetMusic") == 0 || strcmp(name, "GetMusicChannel") == 0) { - int channel = 0; - if (strcmp(name, "GetMusic") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - if (channel < 0 || channel >= NUM_MUSIC_CHANNELS) { - stack->pushNULL(); - } else { - if (!_music[channel] || !_music[channel]->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_music[channel]->getFilename()); - } - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetMusicPosition / SetMusicChannelPosition - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetMusicPosition") == 0 || strcmp(name, "SetMusicChannelPosition") == 0 || strcmp(name, "SetMusicPositionChannel") == 0) { - int channel = 0; - if (strcmp(name, "SetMusicPosition") == 0) { - stack->correctParams(1); - } else { - stack->correctParams(2); - channel = stack->pop()->getInt(); - } - - uint32 time = stack->pop()->getInt(); - - if (DID_FAIL(setMusicStartTime(channel, time))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetMusicPosition / GetMusicChannelPosition - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetMusicPosition") == 0 || strcmp(name, "GetMusicChannelPosition") == 0) { - int channel = 0; - if (strcmp(name, "GetMusicPosition") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - - if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { - stack->pushInt(0); - } else { - stack->pushInt(_music[channel]->getPositionTime()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsMusicPlaying / IsMusicChannelPlaying - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsMusicPlaying") == 0 || strcmp(name, "IsMusicChannelPlaying") == 0) { - int channel = 0; - if (strcmp(name, "IsMusicPlaying") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - - if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { - stack->pushBool(false); - } else { - stack->pushBool(_music[channel]->isPlaying()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetMusicVolume / SetMusicChannelVolume - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetMusicVolume") == 0 || strcmp(name, "SetMusicChannelVolume") == 0) { - int channel = 0; - if (strcmp(name, "SetMusicVolume") == 0) { - stack->correctParams(1); - } else { - stack->correctParams(2); - channel = stack->pop()->getInt(); - } - - int volume = stack->pop()->getInt(); - if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { - stack->pushBool(false); - } else { - if (DID_FAIL(_music[channel]->setVolumePercent(volume))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetMusicVolume / GetMusicChannelVolume - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetMusicVolume") == 0 || strcmp(name, "GetMusicChannelVolume") == 0) { - int channel = 0; - if (strcmp(name, "GetMusicVolume") == 0) { - stack->correctParams(0); - } else { - stack->correctParams(1); - channel = stack->pop()->getInt(); - } - - if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { - stack->pushInt(0); - } else { - stack->pushInt(_music[channel]->getVolumePercent()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MusicCrossfade - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MusicCrossfade") == 0) { - stack->correctParams(4); - int channel1 = stack->pop()->getInt(0); - int channel2 = stack->pop()->getInt(0); - uint32 fadeLength = (uint32)stack->pop()->getInt(0); - bool swap = stack->pop()->getBool(true); - - if (_musicCrossfadeRunning) { - script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress."); - stack->pushBool(false); - return STATUS_OK; - } - - _musicCrossfadeStartTime = _liveTimer; - _musicCrossfadeChannel1 = channel1; - _musicCrossfadeChannel2 = channel2; - _musicCrossfadeLength = fadeLength; - _musicCrossfadeSwap = swap; - - _musicCrossfadeRunning = true; - - stack->pushBool(true); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetSoundLength - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetSoundLength") == 0) { - stack->correctParams(1); - - int length = 0; - const char *filename = stack->pop()->getString(); - - BaseSound *sound = new BaseSound(_gameRef); - if (sound && DID_SUCCEED(sound->setSound(filename, Audio::Mixer::kMusicSoundType, true))) { - length = sound->getLength(); - delete sound; - sound = NULL; - } - stack->pushInt(length); + else if (_musicSystem->scCallMethod(script, stack, thisStack, name) == STATUS_OK) { return STATUS_OK; } @@ -1432,7 +1146,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack bool freezeMusic = stack->pop()->getBool(true); ScValue *valSub = stack->pop(); - const char *subtitleFile = valSub->isNULL() ? NULL : valSub->getString(); + const char *subtitleFile = valSub->isNULL() ? nullptr : valSub->getString(); if (type < (int)VID_PLAY_POS || type > (int)VID_PLAY_CENTER) { type = (int)VID_PLAY_STRETCH; @@ -1472,7 +1186,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack bool dropFrames = stack->pop()->getBool(true); ScValue *valSub = stack->pop(); - const char *subtitleFile = valSub->isNULL() ? NULL : valSub->getString(); + const char *subtitleFile = valSub->isNULL() ? nullptr : valSub->getString(); if (type < (int)VID_PLAY_POS || type > (int)VID_PLAY_CENTER) { type = (int)VID_PLAY_STRETCH; @@ -1491,7 +1205,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack } else { stack->pushBool(false); delete _theoraPlayer; - _theoraPlayer = NULL; + _theoraPlayer = nullptr; } return STATUS_OK; @@ -1543,7 +1257,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->correctParams(2); const char *key = stack->pop()->getString(); const char *val = stack->pop()->getString(); - Common::String privKey = "priv_" + StringUtil::encodeSetting(key); + Common::String privKey = "wme_" + StringUtil::encodeSetting(key); Common::String privVal = StringUtil::encodeSetting(val); ConfMan.set(privKey, privVal); stack->pushNULL(); @@ -1557,7 +1271,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->correctParams(2); const char *key = stack->pop()->getString(); const char *initVal = stack->pop()->getString(); - Common::String privKey = "priv_" + StringUtil::encodeSetting(key); + Common::String privKey = "wme_" + StringUtil::encodeSetting(key); Common::String result = initVal; if (ConfMan.hasKey(privKey)) { result = StringUtil::decodeSetting(ConfMan.get(key)); @@ -1756,7 +1470,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack else if (strcmp(name, "RemoveActiveCursor") == 0) { stack->correctParams(0); delete _activeCursor; - _activeCursor = NULL; + _activeCursor = nullptr; stack->pushNULL(); return STATUS_OK; @@ -1862,14 +1576,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack fileNum++; } - bool ret = false; - BaseImage *image = _gameRef->_renderer->takeScreenshot(); - if (image) { - ret = DID_SUCCEED(image->saveBMPFile(filename)); - delete image; - } else { - ret = false; - } + bool ret = _gameRef->_renderer->saveScreenShot(filename); stack->pushBool(ret); return STATUS_OK; @@ -1884,17 +1591,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack int sizeX = stack->pop()->getInt(_renderer->_width); int sizeY = stack->pop()->getInt(_renderer->_height); - bool ret = false; - BaseImage *image = _gameRef->_renderer->takeScreenshot(); - if (image) { - ret = DID_SUCCEED(image->resize(sizeX, sizeY)); - if (ret) { - ret = DID_SUCCEED(image->saveBMPFile(filename)); - } - delete image; - } else { - ret = false; - } + bool ret = _gameRef->_renderer->saveScreenShot(filename, sizeX, sizeY); stack->pushBool(ret); return STATUS_OK; @@ -2009,7 +1706,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack else if (strcmp(name, "RemoveWaitCursor") == 0) { stack->correctParams(0); delete _cursorNoninteractive; - _cursorNoninteractive = NULL; + _cursorNoninteractive = nullptr; stack->pushNULL(); @@ -2068,7 +1765,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _loadingIcon = new BaseSprite(this); if (!_loadingIcon || DID_FAIL(_loadingIcon->loadFile(filename))) { delete _loadingIcon; - _loadingIcon = NULL; + _loadingIcon = nullptr; } else { displayContent(false, true); _gameRef->_renderer->flip(); @@ -2085,7 +1782,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack else if (strcmp(name, "HideLoadingIcon") == 0) { stack->correctParams(0); delete _loadingIcon; - _loadingIcon = NULL; + _loadingIcon = nullptr; stack->pushNULL(); return STATUS_OK; } @@ -2125,7 +1822,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _cachedThumbnail = new BaseSaveThumbHelper(this); if (DID_FAIL(_cachedThumbnail->storeThumbnail())) { delete _cachedThumbnail; - _cachedThumbnail = NULL; + _cachedThumbnail = nullptr; stack->pushBool(false); } else { stack->pushBool(true); @@ -2140,7 +1837,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack else if (strcmp(name, "DeleteSaveThumbnail") == 0) { stack->correctParams(0); delete _cachedThumbnail; - _cachedThumbnail = NULL; + _cachedThumbnail = nullptr; stack->pushNULL(); return STATUS_OK; @@ -2179,7 +1876,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack } BaseFileManager::getEngineInstance()->closeFile(file); - file = NULL; + file = nullptr; } else { stack->pushNULL(); } @@ -2682,7 +2379,7 @@ bool BaseGame::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "MainObject") == 0) { BaseScriptable *obj = value->getNative(); - if (obj == NULL || validObject((BaseObject *)obj)) { + if (obj == nullptr || validObject((BaseObject *)obj)) { _mainObject = (BaseObject *)obj; } return STATUS_OK; @@ -2918,7 +2615,7 @@ bool BaseGame::unregisterObject(BaseObject *object) { // get new focused window if (_focusedWindow == object) { - _focusedWindow = NULL; + _focusedWindow = nullptr; } break; @@ -2927,12 +2624,12 @@ bool BaseGame::unregisterObject(BaseObject *object) { // is it active object? if (_activeObject == object) { - _activeObject = NULL; + _activeObject = nullptr; } // is it main object? if (_mainObject == object) { - _mainObject = NULL; + _mainObject = nullptr; } // destroy object @@ -2958,7 +2655,7 @@ void BaseGame::invalidateValues(void *value, void *data) { if (!val->_persistent && ((BaseScriptable *)data)->_refCount == 1) { ((BaseScriptable *)data)->_refCount++; } - val->setNative(NULL); + val->setNative(nullptr); val->setNULL(); } } @@ -3321,8 +3018,8 @@ bool BaseGame::displayWindows(bool inGame) { bool res; // did we lose focus? focus topmost window - if (_focusedWindow == NULL || !_focusedWindow->_visible || _focusedWindow->_disable) { - _focusedWindow = NULL; + if (_focusedWindow == nullptr || !_focusedWindow->_visible || _focusedWindow->_disable) { + _focusedWindow = nullptr; for (int i = _windows.size() - 1; i >= 0; i--) { if (_windows[i]->_visible && !_windows[i]->_disable) { _focusedWindow = _windows[i]; @@ -3345,99 +3042,6 @@ bool BaseGame::displayWindows(bool inGame) { return STATUS_OK; } - -////////////////////////////////////////////////////////////////////////// -bool BaseGame::playMusic(int channel, const char *filename, bool looping, uint32 loopStart) { - if (channel >= NUM_MUSIC_CHANNELS) { - _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); - return STATUS_FAILED; - } - - delete _music[channel]; - _music[channel] = NULL; - - _music[channel] = new BaseSound(_gameRef); - if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) { - if (_musicStartTime[channel]) { - _music[channel]->setPositionTime(_musicStartTime[channel]); - _musicStartTime[channel] = 0; - } - if (loopStart) { - _music[channel]->setLoopStart(loopStart); - } - return _music[channel]->play(looping); - } else { - delete _music[channel]; - _music[channel] = NULL; - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseGame::stopMusic(int channel) { - if (channel >= NUM_MUSIC_CHANNELS) { - _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); - return STATUS_FAILED; - } - - if (_music[channel]) { - _music[channel]->stop(); - delete _music[channel]; - _music[channel] = NULL; - return STATUS_OK; - } else { - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseGame::pauseMusic(int channel) { - if (channel >= NUM_MUSIC_CHANNELS) { - _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); - return STATUS_FAILED; - } - - if (_music[channel]) { - return _music[channel]->pause(); - } else { - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseGame::resumeMusic(int channel) { - if (channel >= NUM_MUSIC_CHANNELS) { - _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); - return STATUS_FAILED; - } - - if (_music[channel]) { - return _music[channel]->resume(); - } else { - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool BaseGame::setMusicStartTime(int channel, uint32 time) { - if (channel >= NUM_MUSIC_CHANNELS) { - _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); - return STATUS_FAILED; - } - - _musicStartTime[channel] = time; - if (_music[channel] && _music[channel]->isPlaying()) { - return _music[channel]->setPositionTime(time); - } else { - return STATUS_OK; - } -} - - ////////////////////////////////////////////////////////////////////////// bool BaseGame::loadSettings(const char *filename) { TOKEN_TABLE_START(commands) @@ -3461,7 +3065,7 @@ bool BaseGame::loadSettings(const char *filename) { byte *origBuffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (origBuffer == NULL) { + if (origBuffer == nullptr) { _gameRef->LOG(0, "BaseGame::LoadSettings failed for file '%s'", filename); return STATUS_FAILED; } @@ -3539,7 +3143,7 @@ bool BaseGame::loadSettings(const char *filename) { break; case TOKEN_SAVED_GAME_EXT: - BaseUtils::setString(&_savedGameExt, (char *)params); + _savedGameExt = (char *)params; break; case TOKEN_GUID: @@ -3584,10 +3188,8 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_keyboardState)); persistMgr->transfer(TMEMBER(_lastTime)); persistMgr->transfer(TMEMBER(_mainObject)); - for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { - persistMgr->transfer(TMEMBER(_music[i])); - persistMgr->transfer(TMEMBER(_musicStartTime[i])); - } + _musicSystem->persistChannels(persistMgr); + _musicSystem->persistCrossfadeSettings(persistMgr); persistMgr->transfer(TMEMBER(_offsetX)); persistMgr->transfer(TMEMBER(_offsetY)); @@ -3619,13 +3221,6 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_liveTimerDelta)); persistMgr->transfer(TMEMBER(_liveTimerLast)); - persistMgr->transfer(TMEMBER(_musicCrossfadeRunning)); - persistMgr->transfer(TMEMBER(_musicCrossfadeStartTime)); - persistMgr->transfer(TMEMBER(_musicCrossfadeLength)); - persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1)); - persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2)); - persistMgr->transfer(TMEMBER(_musicCrossfadeSwap)); - _renderer->persistSaveLoadImages(persistMgr); persistMgr->transfer(TMEMBER_INT(_textEncoding)); @@ -3730,7 +3325,7 @@ bool BaseGame::handleKeypress(Common::Event *event, bool printable) { // TODO if (_focusedWindow) { - if (!_gameRef->_focusedWindow->handleKeypress(event, _keyboardState->_currentPrintable)) { + if (!_gameRef->_focusedWindow->handleKeypress(event, _keyboardState->isCurrentPrintable())) { /*if (event->type != SDL_TEXTINPUT) {*/ if (_gameRef->_focusedWindow->canHandleEvent("Keypress")) { _gameRef->_focusedWindow->applyEvent("Keypress"); @@ -3832,7 +3427,7 @@ void BaseGame::setWindowTitle() { bool BaseGame::setActiveObject(BaseObject *obj) { // not-active when game is frozen if (obj && !_gameRef->_interactive && !obj->_nonIntMouseEvents) { - obj = NULL; + obj = nullptr; } if (obj == _activeObject) { @@ -3887,7 +3482,7 @@ bool BaseGame::popViewport() { ////////////////////////////////////////////////////////////////////////// bool BaseGame::getCurrentViewportRect(Rect32 *rect, bool *custom) { - if (rect == NULL) { + if (rect == nullptr) { return STATUS_FAILED; } else { if (_viewportSP >= 0) { @@ -3979,69 +3574,6 @@ bool BaseGame::displayContentSimple() { } ////////////////////////////////////////////////////////////////////////// -bool BaseGame::updateMusicCrossfade() { - /* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */ - - if (!_musicCrossfadeRunning) { - return STATUS_OK; - } - if (_state == GAME_FROZEN) { - return STATUS_OK; - } - - if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) { - _musicCrossfadeRunning = false; - return STATUS_OK; - } - if (_musicCrossfadeChannel2 < 0 || _musicCrossfadeChannel2 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel2]) { - _musicCrossfadeRunning = false; - return STATUS_OK; - } - - if (!_music[_musicCrossfadeChannel1]->isPlaying()) { - _music[_musicCrossfadeChannel1]->play(); - } - if (!_music[_musicCrossfadeChannel2]->isPlaying()) { - _music[_musicCrossfadeChannel2]->play(); - } - - uint32 currentTime = _gameRef->_liveTimer - _musicCrossfadeStartTime; - - if (currentTime >= _musicCrossfadeLength) { - _musicCrossfadeRunning = false; - //_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol); - _music[_musicCrossfadeChannel2]->setVolumePercent(100); - - _music[_musicCrossfadeChannel1]->stop(); - //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol); - _music[_musicCrossfadeChannel1]->setVolumePercent(100); - - - if (_musicCrossfadeSwap) { - // swap channels - BaseSound *dummy = _music[_musicCrossfadeChannel1]; - int dummyInt = _musicStartTime[_musicCrossfadeChannel1]; - - _music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2]; - _musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2]; - - _music[_musicCrossfadeChannel2] = dummy; - _musicStartTime[_musicCrossfadeChannel2] = dummyInt; - } - } else { - //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol - (float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol); - //_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol); - _music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f)); - _music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f)); - - //_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume()); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// bool BaseGame::resetContent() { _scEngine->clearGlobals(); //_timer = 0; @@ -4084,12 +3616,12 @@ bool BaseGame::restoreDeviceObjects() { ////////////////////////////////////////////////////////////////////////// bool BaseGame::setWaitCursor(const char *filename) { delete _cursorNoninteractive; - _cursorNoninteractive = NULL; + _cursorNoninteractive = nullptr; _cursorNoninteractive = new BaseSprite(_gameRef); if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile(filename))) { delete _cursorNoninteractive; - _cursorNoninteractive = NULL; + _cursorNoninteractive = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -4115,7 +3647,7 @@ bool BaseGame::stopVideo() { if (_theoraPlayer && _theoraPlayer->isPlaying()) { _theoraPlayer->stop(); delete _theoraPlayer; - _theoraPlayer = NULL; + _theoraPlayer = nullptr; } return STATUS_OK; } @@ -4166,12 +3698,12 @@ bool BaseGame::onMouseLeftDown() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("LeftClick"); } } - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _capturedObject = _activeObject; } _mouseLeftDown = true; @@ -4187,12 +3719,12 @@ bool BaseGame::onMouseLeftUp() { } BasePlatform::releaseCapture(); - _capturedObject = NULL; + _capturedObject = nullptr; _mouseLeftDown = false; bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftRelease")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("LeftRelease"); } } @@ -4211,7 +3743,7 @@ bool BaseGame::onMouseLeftDblClick() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftDoubleClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("LeftDoubleClick"); } } @@ -4230,7 +3762,7 @@ bool BaseGame::onMouseRightDblClick() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightDoubleClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("RightDoubleClick"); } } @@ -4245,7 +3777,7 @@ bool BaseGame::onMouseRightDown() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("RightClick"); } } @@ -4260,7 +3792,7 @@ bool BaseGame::onMouseRightUp() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightRelease")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("RightRelease"); } } @@ -4279,7 +3811,7 @@ bool BaseGame::onMouseMiddleDown() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("MiddleClick")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("MiddleClick"); } } @@ -4294,7 +3826,7 @@ bool BaseGame::onMouseMiddleUp() { bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("MiddleRelease")); if (!handled) { - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _activeObject->applyEvent("MiddleRelease"); } } @@ -4356,7 +3888,7 @@ bool BaseGame::displayDebugInfo() { sprintf(str, "Timer: %d", _timer); _gameRef->_systemFont->drawText((byte *)str, 0, 130, _renderer->_width, TAL_RIGHT); - if (_activeObject != NULL) { + if (_activeObject != nullptr) { _systemFont->drawText((const byte *)_activeObject->getName(), 0, 150, _renderer->_width, TAL_RIGHT); } diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h index 0f764b3d03..5666fb818c 100644 --- a/engines/wintermute/base/base_game.h +++ b/engines/wintermute/base/base_game.h @@ -46,6 +46,7 @@ class BaseFileManager; class BaseTransitionMgr; class ScEngine; class BaseFontStorage; +class BaseGameMusic; class BaseStringTable; class BaseQuickMsg; class UIWindow; @@ -59,8 +60,6 @@ class BaseKeyboardState; class VideoPlayer; class VideoTheoraPlayer; -#define NUM_MUSIC_CHANNELS 5 - class BaseGame: public BaseObject { public: DECLARE_PERSISTENT(BaseGame, BaseObject) @@ -120,14 +119,15 @@ public: int _offsetX; float _offsetPercentX; float _offsetPercentY; - BaseObject *_mainObject; + + inline BaseObject *getMainObject() { return _mainObject; } + inline BaseFont *getSystemFont() { return _systemFont; } bool initInput(); bool initLoop(); uint32 _currentTime; uint32 _deltaTime; - BaseFont *_systemFont; - BaseFont *_videoFont; + bool initialize1(); bool initialize2(); bool initialize3(); @@ -138,14 +138,14 @@ public: BaseRenderer *_renderer; BaseSoundMgr *_soundMgr; ScEngine *_scEngine; - SXMath *_mathClass; + BaseScriptable *_mathClass; BaseSurfaceStorage *_surfaceStorage; BaseFontStorage *_fontStorage; BaseGame(const Common::String &gameId); virtual ~BaseGame(); void DEBUG_DebugDisable(); - void DEBUG_DebugEnable(const char *filename = NULL); + void DEBUG_DebugEnable(const char *filename = nullptr); bool _debugDebugMode; void *_debugLogFile; @@ -237,8 +237,8 @@ public: void setInteractive(bool state); virtual bool windowLoadHook(UIWindow *win, char **buf, char **params); virtual bool windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name); - bool getCurrentViewportOffset(int *offsetX = NULL, int *offsetY = NULL); - bool getCurrentViewportRect(Rect32 *rect, bool *custom = NULL); + bool getCurrentViewportOffset(int *offsetX = nullptr, int *offsetY = nullptr); + bool getCurrentViewportRect(Rect32 *rect, bool *custom = nullptr); bool popViewport(); bool pushViewport(BaseViewport *Viewport); bool setActiveObject(BaseObject *Obj); @@ -250,6 +250,9 @@ public: bool _touchInterface; bool _constrainedMemory; protected: + BaseFont *_systemFont; + BaseFont *_videoFont; + BaseSprite *_loadingIcon; int _loadingIconX; int _loadingIconY; @@ -261,6 +264,8 @@ protected: VideoPlayer *_videoPlayer; VideoTheoraPlayer *_theoraPlayer; private: + BaseObject *_mainObject; + bool _mouseRightDown; bool _mouseMidlleDown; bool _settingsRequireAcceleration; @@ -274,10 +279,11 @@ private: virtual bool invalidateDeviceObjects(); virtual bool restoreDeviceObjects(); - char *_localSaveDir; + // TODO: This can probably be removed completely: bool _saveDirChecked; bool _richSavedGames; - char *_savedGameExt; + Common::String _localSaveDir; + Common::String _savedGameExt; bool _reportTextureFormat; @@ -287,36 +293,22 @@ private: uint32 _framesRendered; Common::String _gameId; - void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = NULL, void *data = NULL); + void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = nullptr, void *data = nullptr); ENGINE_LOG_CALLBACK _engineLogCallback; void *_engineLogCallbackData; bool _videoSubtitles; - uint32 _musicStartTime[NUM_MUSIC_CHANNELS]; bool _compressedSavegames; bool _personalizedSave; void setWindowTitle(); - bool resumeMusic(int channel); - bool setMusicStartTime(int channel, uint32 time); - bool pauseMusic(int channel); - bool stopMusic(int channel); - bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0); - BaseSound *_music[NUM_MUSIC_CHANNELS]; - bool _musicCrossfadeRunning; - bool _musicCrossfadeSwap; - uint32 _musicCrossfadeStartTime; - uint32 _musicCrossfadeLength; - int _musicCrossfadeChannel1; - int _musicCrossfadeChannel2; - BaseSprite *_cursorNoninteractive; BaseKeyboardState *_keyboardState; uint32 _fps; - bool updateMusicCrossfade(); + BaseGameMusic *_musicSystem; bool isVideoPlaying(); bool stopVideo(); diff --git a/engines/wintermute/base/base_game_music.cpp b/engines/wintermute/base/base_game_music.cpp new file mode 100644 index 0000000000..8dff41d854 --- /dev/null +++ b/engines/wintermute/base/base_game_music.cpp @@ -0,0 +1,506 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/base/base_game_music.h" +#include "engines/wintermute/base/base_engine.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_persistence_manager.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/sound/base_sound.h" + +namespace Wintermute { + +BaseGameMusic::BaseGameMusic(BaseGame *gameRef) : _gameRef(gameRef) { + for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { + _music[i] = nullptr; + _musicStartTime[i] = 0; + } + + _musicCrossfadeRunning = false; + _musicCrossfadeStartTime = 0; + _musicCrossfadeLength = 0; + _musicCrossfadeChannel1 = -1; + _musicCrossfadeChannel2 = -1; + _musicCrossfadeSwap = false; +} + +void BaseGameMusic::cleanup() { + for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { + delete _music[i]; + _music[i] = nullptr; + _musicStartTime[i] = 0; + } +} + +////////////////////////////////////////////////////////////////////////// +bool BaseGameMusic::playMusic(int channel, const char *filename, bool looping, uint32 loopStart) { + if (channel >= NUM_MUSIC_CHANNELS) { + BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); + return STATUS_FAILED; + } + + delete _music[channel]; + _music[channel] = nullptr; + + _music[channel] = new BaseSound(_gameRef); + if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) { + if (_musicStartTime[channel]) { + _music[channel]->setPositionTime(_musicStartTime[channel]); + _musicStartTime[channel] = 0; + } + if (loopStart) { + _music[channel]->setLoopStart(loopStart); + } + return _music[channel]->play(looping); + } else { + delete _music[channel]; + _music[channel] = nullptr; + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseGameMusic::stopMusic(int channel) { + if (channel >= NUM_MUSIC_CHANNELS) { + BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); + return STATUS_FAILED; + } + + if (_music[channel]) { + _music[channel]->stop(); + delete _music[channel]; + _music[channel] = nullptr; + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseGameMusic::pauseMusic(int channel) { + if (channel >= NUM_MUSIC_CHANNELS) { + BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); + return STATUS_FAILED; + } + + if (_music[channel]) { + return _music[channel]->pause(); + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseGameMusic::resumeMusic(int channel) { + if (channel >= NUM_MUSIC_CHANNELS) { + BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); + return STATUS_FAILED; + } + + if (_music[channel]) { + return _music[channel]->resume(); + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) { + if (channel >= NUM_MUSIC_CHANNELS) { + BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); + return STATUS_FAILED; + } + + _musicStartTime[channel] = time; + if (_music[channel] && _music[channel]->isPlaying()) { + return _music[channel]->setPositionTime(time); + } else { + return STATUS_OK; + } +} + +////////////////////////////////////////////////////////////////////////// +bool BaseGameMusic::updateMusicCrossfade() { + /* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */ + + if (!_musicCrossfadeRunning) { + return STATUS_OK; + } + if (_gameRef->_state == GAME_FROZEN) { + return STATUS_OK; + } + + if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) { + _musicCrossfadeRunning = false; + return STATUS_OK; + } + if (_musicCrossfadeChannel2 < 0 || _musicCrossfadeChannel2 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel2]) { + _musicCrossfadeRunning = false; + return STATUS_OK; + } + + if (!_music[_musicCrossfadeChannel1]->isPlaying()) { + _music[_musicCrossfadeChannel1]->play(); + } + if (!_music[_musicCrossfadeChannel2]->isPlaying()) { + _music[_musicCrossfadeChannel2]->play(); + } + + uint32 currentTime = _gameRef->_liveTimer - _musicCrossfadeStartTime; + + if (currentTime >= _musicCrossfadeLength) { + _musicCrossfadeRunning = false; + //_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol); + _music[_musicCrossfadeChannel2]->setVolumePercent(100); + + _music[_musicCrossfadeChannel1]->stop(); + //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol); + _music[_musicCrossfadeChannel1]->setVolumePercent(100); + + + if (_musicCrossfadeSwap) { + // swap channels + BaseSound *dummy = _music[_musicCrossfadeChannel1]; + int dummyInt = _musicStartTime[_musicCrossfadeChannel1]; + + _music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2]; + _musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2]; + + _music[_musicCrossfadeChannel2] = dummy; + _musicStartTime[_musicCrossfadeChannel2] = dummyInt; + } + } else { + //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol - (float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol); + //_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol); + _music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f)); + _music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f)); + + //_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume()); + } + + return STATUS_OK; +} + +bool BaseGameMusic::persistChannels(BasePersistenceManager *persistMgr) { + for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { + persistMgr->transfer(TMEMBER(_music[i])); + persistMgr->transfer(TMEMBER(_musicStartTime[i])); + } + return true; +} + +bool BaseGameMusic::persistCrossfadeSettings(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_musicCrossfadeRunning)); + persistMgr->transfer(TMEMBER(_musicCrossfadeStartTime)); + persistMgr->transfer(TMEMBER(_musicCrossfadeLength)); + persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1)); + persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2)); + persistMgr->transfer(TMEMBER(_musicCrossfadeSwap)); + return true; +} + +bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // PlayMusic / PlayMusicChannel + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "PlayMusic") == 0 || strcmp(name, "PlayMusicChannel") == 0) { + int channel = 0; + if (strcmp(name, "PlayMusic") == 0) { + stack->correctParams(3); + } else { + stack->correctParams(4); + channel = stack->pop()->getInt(); + } + + const char *filename = stack->pop()->getString(); + ScValue *valLooping = stack->pop(); + bool looping = valLooping->isNULL() ? true : valLooping->getBool(); + + ScValue *valLoopStart = stack->pop(); + uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt()); + + + if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StopMusic / StopMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) { + int channel = 0; + + if (strcmp(name, "StopMusic") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + + if (DID_FAIL(stopMusic(channel))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PauseMusic / PauseMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) { + int channel = 0; + + if (strcmp(name, "PauseMusic") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + + if (DID_FAIL(pauseMusic(channel))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ResumeMusic / ResumeMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ResumeMusic") == 0 || strcmp(name, "ResumeMusicChannel") == 0) { + int channel = 0; + if (strcmp(name, "ResumeMusic") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + + if (DID_FAIL(resumeMusic(channel))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetMusic / GetMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetMusic") == 0 || strcmp(name, "GetMusicChannel") == 0) { + int channel = 0; + if (strcmp(name, "GetMusic") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS) { + stack->pushNULL(); + } else { + if (!_music[channel] || !_music[channel]->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_music[channel]->getFilename()); + } + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetMusicPosition / SetMusicChannelPosition + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetMusicPosition") == 0 || strcmp(name, "SetMusicChannelPosition") == 0 || strcmp(name, "SetMusicPositionChannel") == 0) { + int channel = 0; + if (strcmp(name, "SetMusicPosition") == 0) { + stack->correctParams(1); + } else { + stack->correctParams(2); + channel = stack->pop()->getInt(); + } + + uint32 time = stack->pop()->getInt(); + + if (DID_FAIL(setMusicStartTime(channel, time))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetMusicPosition / GetMusicChannelPosition + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetMusicPosition") == 0 || strcmp(name, "GetMusicChannelPosition") == 0) { + int channel = 0; + if (strcmp(name, "GetMusicPosition") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { + stack->pushInt(0); + } else { + stack->pushInt(_music[channel]->getPositionTime()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsMusicPlaying / IsMusicChannelPlaying + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsMusicPlaying") == 0 || strcmp(name, "IsMusicChannelPlaying") == 0) { + int channel = 0; + if (strcmp(name, "IsMusicPlaying") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { + stack->pushBool(false); + } else { + stack->pushBool(_music[channel]->isPlaying()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetMusicVolume / SetMusicChannelVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetMusicVolume") == 0 || strcmp(name, "SetMusicChannelVolume") == 0) { + int channel = 0; + if (strcmp(name, "SetMusicVolume") == 0) { + stack->correctParams(1); + } else { + stack->correctParams(2); + channel = stack->pop()->getInt(); + } + + int volume = stack->pop()->getInt(); + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { + stack->pushBool(false); + } else { + if (DID_FAIL(_music[channel]->setVolumePercent(volume))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetMusicVolume / GetMusicChannelVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetMusicVolume") == 0 || strcmp(name, "GetMusicChannelVolume") == 0) { + int channel = 0; + if (strcmp(name, "GetMusicVolume") == 0) { + stack->correctParams(0); + } else { + stack->correctParams(1); + channel = stack->pop()->getInt(); + } + + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { + stack->pushInt(0); + } else { + stack->pushInt(_music[channel]->getVolumePercent()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MusicCrossfade + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MusicCrossfade") == 0) { + stack->correctParams(4); + int channel1 = stack->pop()->getInt(0); + int channel2 = stack->pop()->getInt(0); + uint32 fadeLength = (uint32)stack->pop()->getInt(0); + bool swap = stack->pop()->getBool(true); + + if (_musicCrossfadeRunning) { + script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress."); + stack->pushBool(false); + return STATUS_OK; + } + + _musicCrossfadeStartTime = _gameRef->_liveTimer; + _musicCrossfadeChannel1 = channel1; + _musicCrossfadeChannel2 = channel2; + _musicCrossfadeLength = fadeLength; + _musicCrossfadeSwap = swap; + + _musicCrossfadeRunning = true; + + stack->pushBool(true); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetSoundLength + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetSoundLength") == 0) { + stack->correctParams(1); + + int length = 0; + const char *filename = stack->pop()->getString(); + + BaseSound *sound = new BaseSound(_gameRef); + if (sound && DID_SUCCEED(sound->setSound(filename, Audio::Mixer::kMusicSoundType, true))) { + length = sound->getLength(); + delete sound; + sound = nullptr; + } + stack->pushInt(length); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/base_game_music.h b/engines/wintermute/base/base_game_music.h new file mode 100644 index 0000000000..058a8cadef --- /dev/null +++ b/engines/wintermute/base/base_game_music.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BASE_GAME_MUSIC_H +#define WINTERMUTE_BASE_GAME_MUSIC_H + +#include "common/scummsys.h" + + +namespace Wintermute { + +#define NUM_MUSIC_CHANNELS 5 +class BasePersistenceManager; +class BaseSound; +class ScStack; +class ScScript; +class BaseGame; +class BaseGameMusic { +public: + BaseGameMusic(BaseGame *gameRef); + void cleanup(); + + bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + + bool resumeMusic(int channel); + bool setMusicStartTime(int channel, uint32 time); + bool pauseMusic(int channel); + bool stopMusic(int channel); + bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0); + bool updateMusicCrossfade(); + + bool persistChannels(BasePersistenceManager *persistMgr); + bool persistCrossfadeSettings(BasePersistenceManager *persistMgr); +private: + BaseGame *_gameRef; + BaseSound *_music[NUM_MUSIC_CHANNELS]; + uint32 _musicStartTime[NUM_MUSIC_CHANNELS]; + bool _musicCrossfadeRunning; + bool _musicCrossfadeSwap; + uint32 _musicCrossfadeStartTime; + uint32 _musicCrossfadeLength; + int _musicCrossfadeChannel1; + int _musicCrossfadeChannel2; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp index da7baafd2d..072a1bb71b 100644 --- a/engines/wintermute/base/base_keyboard_state.cpp +++ b/engines/wintermute/base/base_keyboard_state.cpp @@ -200,9 +200,8 @@ const char *BaseKeyboardState::scToString() { bool BaseKeyboardState::readKey(Common::Event *event) { //_currentPrintable = (event->type == SDL_TEXTINPUT); // TODO _currentCharCode = keyCodeToVKey(event); - if ((_currentCharCode <= Common::KEYCODE_z && _currentCharCode >= Common::KEYCODE_a) || - (_currentCharCode <= Common::KEYCODE_9 && _currentCharCode >= Common::KEYCODE_0) || - (_currentCharCode == Common::KEYCODE_SPACE)) { + // Verify that this is a printable ISO-8859-character (including the upper charset) + if ((_currentCharCode <= 0x7E && _currentCharCode >= 0x20) || (_currentCharCode <= 0xFF && _currentCharCode >= 0xA0)) { _currentPrintable = true; } else { _currentPrintable = false; @@ -258,6 +257,11 @@ bool BaseKeyboardState::isAltDown() { } ////////////////////////////////////////////////////////////////////////// +bool BaseKeyboardState::isCurrentPrintable() const { + return _currentPrintable; +} + +////////////////////////////////////////////////////////////////////////// uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) { if (event->type != Common::EVENT_KEYDOWN) { return 0; @@ -267,7 +271,7 @@ uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) { case Common::KEYCODE_KP_ENTER: return Common::KEYCODE_RETURN; default: - return (uint32)event->kbd.keycode; + return (uint32)event->kbd.ascii; } } diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h index dfd0efdec0..b62ece02b7 100644 --- a/engines/wintermute/base/base_keyboard_state.h +++ b/engines/wintermute/base/base_keyboard_state.h @@ -39,14 +39,6 @@ namespace Wintermute { class BaseKeyboardState : public BaseScriptable { public: - uint32 _currentKeyData; - uint32 _currentCharCode; - bool _currentPrintable; - - bool _currentShift; - bool _currentAlt; - bool _currentControl; - DECLARE_PERSISTENT(BaseKeyboardState, BaseScriptable) BaseKeyboardState(BaseGame *inGame); virtual ~BaseKeyboardState(); @@ -57,6 +49,7 @@ public: static bool isShiftDown(); static bool isControlDown(); static bool isAltDown(); + bool isCurrentPrintable() const; // scripting interface virtual ScValue *scGetProperty(const Common::String &name); @@ -65,6 +58,14 @@ public: virtual const char *scToString(); private: + bool _currentPrintable; + uint32 _currentKeyData; + uint32 _currentCharCode; + + bool _currentShift; + bool _currentAlt; + bool _currentControl; + uint8 *_keyStates; uint32 keyCodeToVKey(Common::Event *event); Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend diff --git a/engines/wintermute/base/base_named_object.cpp b/engines/wintermute/base/base_named_object.cpp index 915bf24d7f..f99ec2f5db 100644 --- a/engines/wintermute/base/base_named_object.cpp +++ b/engines/wintermute/base/base_named_object.cpp @@ -32,38 +32,38 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////////// BaseNamedObject::BaseNamedObject(BaseGame *inGame) : BaseClass(inGame) { - _name = NULL; + _name = nullptr; } ////////////////////////////////////////////////////////////////////////// BaseNamedObject::BaseNamedObject() : BaseClass() { - _name = NULL; + _name = nullptr; } ////////////////////////////////////////////////////////////////////////// BaseNamedObject::BaseNamedObject(TDynamicConstructor, TDynamicConstructor) { - _name = NULL; + _name = nullptr; } ////////////////////////////////////////////////////////////////////////// BaseNamedObject::~BaseNamedObject(void) { delete[] _name; - _name = NULL; + _name = nullptr; } ////////////////////////////////////////////////////////////////////// void BaseNamedObject::setName(const char *name) { delete[] _name; - _name = NULL; + _name = nullptr; - if (name == NULL) { + if (name == nullptr) { return; } _name = new char [strlen(name) + 1]; - if (_name != NULL) { + if (_name != nullptr) { strcpy(_name, name); } } diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp index eba8416485..898c0497a2 100644 --- a/engines/wintermute/base/base_object.cpp +++ b/engines/wintermute/base/base_object.cpp @@ -60,18 +60,18 @@ BaseObject::BaseObject(BaseGame *inGame) : BaseScriptHolder(inGame) { _ready = true; - _soundEvent = NULL; + _soundEvent = nullptr; _iD = _gameRef->getSequence(); BasePlatform::setRectEmpty(&_rect); _rectSet = false; - _cursor = NULL; - _activeCursor = NULL; + _cursor = nullptr; + _activeCursor = nullptr; _sharedCursors = false; - _sFX = NULL; + _sFX = nullptr; _sFXStart = 0; _sFXVolume = 100; _autoSoundPanning = true; @@ -86,7 +86,7 @@ BaseObject::BaseObject(BaseGame *inGame) : BaseScriptHolder(inGame) { _relativeRotate = 0.0f; for (int i = 0; i < 7; i++) { - _caption[i] = NULL; + _caption[i] = nullptr; } _saveState = true; @@ -109,25 +109,25 @@ BaseObject::~BaseObject() { ////////////////////////////////////////////////////////////////////////// bool BaseObject::cleanup() { if (_gameRef && _gameRef->_activeObject == this) { - _gameRef->_activeObject = NULL; + _gameRef->_activeObject = nullptr; } BaseScriptHolder::cleanup(); delete[] _soundEvent; - _soundEvent = NULL; + _soundEvent = nullptr; if (!_sharedCursors) { delete _cursor; delete _activeCursor; - _cursor = NULL; - _activeCursor = NULL; + _cursor = nullptr; + _activeCursor = nullptr; } delete _sFX; - _sFX = NULL; + _sFX = nullptr; for (int i = 0; i < 7; i++) { delete[] _caption[i]; - _caption[i] = NULL; + _caption[i] = nullptr; } _sFXType = SFX_NONE; @@ -160,7 +160,7 @@ const char *BaseObject::getCaption(int caseVal) { if (caseVal == 0) { caseVal = 1; } - if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) { + if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == nullptr) { return ""; } else { return _caption[caseVal - 1]; @@ -223,9 +223,9 @@ bool BaseObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta stack->correctParams(0); if (!_sharedCursors) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; } else { - _cursor = NULL; + _cursor = nullptr; } stack->pushNULL(); @@ -317,12 +317,12 @@ bool BaseObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta ScValue *val3 = stack->pop(); if (val1->_type == VAL_BOOL) { - filename = NULL; + filename = nullptr; looping = val1->getBool(); loopStart = val2->getInt(); } else { if (val1->isNULL()) { - filename = NULL; + filename = nullptr; } else { filename = val1->getString(); } @@ -351,7 +351,7 @@ bool BaseObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta ScValue *val2 = stack->pop(); if (val2->isNULL()) { - filename = NULL; + filename = nullptr; eventName = val1->getString(); } else { filename = val1->getString(); @@ -1010,14 +1010,14 @@ bool BaseObject::persist(BasePersistenceManager *persistMgr) { bool BaseObject::setCursor(const char *filename) { if (!_sharedCursors) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; } _sharedCursors = false; _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile(filename))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -1031,7 +1031,7 @@ bool BaseObject::setActiveCursor(const char *filename) { _activeCursor = new BaseSprite(_gameRef); if (!_activeCursor || DID_FAIL(_activeCursor->loadFile(filename))) { delete _activeCursor; - _activeCursor = NULL; + _activeCursor = nullptr; return STATUS_FAILED; } else { return STATUS_OK; @@ -1066,7 +1066,7 @@ bool BaseObject::handleMouseWheel(int delta) { ////////////////////////////////////////////////////////////////////////// bool BaseObject::playSFX(const char *filename, bool looping, bool playNow, const char *eventName, uint32 loopStart) { // just play loaded sound - if (filename == NULL && _sFX) { + if (filename == nullptr && _sFX) { if (_gameRef->_editorMode || _sFXStart) { _sFX->setVolumePercent(_sFXVolume); _sFX->setPositionTime(_sFXStart); @@ -1085,7 +1085,7 @@ bool BaseObject::playSFX(const char *filename, bool looping, bool playNow, const } } - if (filename == NULL) { + if (filename == nullptr) { return STATUS_FAILED; } @@ -1111,7 +1111,7 @@ bool BaseObject::playSFX(const char *filename, bool looping, bool playNow, const } } else { delete _sFX; - _sFX = NULL; + _sFX = nullptr; return STATUS_FAILED; } } @@ -1123,7 +1123,7 @@ bool BaseObject::stopSFX(bool deleteSound) { _sFX->stop(); if (deleteSound) { delete _sFX; - _sFX = NULL; + _sFX = nullptr; } return STATUS_OK; } else { @@ -1179,7 +1179,7 @@ bool BaseObject::updateSounds() { if (_soundEvent) { if (_sFX && !_sFX->isPlaying()) { applyEvent(_soundEvent); - setSoundEvent(NULL); + setSoundEvent(nullptr); } } @@ -1229,7 +1229,7 @@ bool BaseObject::isReady() { ////////////////////////////////////////////////////////////////////////// void BaseObject::setSoundEvent(const char *eventName) { delete[] _soundEvent; - _soundEvent = NULL; + _soundEvent = nullptr; if (eventName) { _soundEvent = new char[strlen(eventName) + 1]; if (_soundEvent) { diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h index d7d91a25f6..c8491c2cf6 100644 --- a/engines/wintermute/base/base_object.h +++ b/engines/wintermute/base/base_object.h @@ -52,7 +52,7 @@ protected: bool resumeSFX(); bool pauseSFX(); bool stopSFX(bool deleteSound = true); - bool playSFX(const char *filename, bool looping = false, bool playNow = true, const char *eventName = NULL, uint32 loopStart = 0); + bool playSFX(const char *filename, bool looping = false, bool playNow = true, const char *eventName = nullptr, uint32 loopStart = 0); BaseSound *_sFX; TSFXType _sFXType; float _sFXParam1; @@ -110,8 +110,8 @@ public: bool _movable; bool _zoomable; bool _shadowable; - int _posY; - int _posX; + int32 _posY; + int32 _posX; bool _registrable; char *_caption[7]; bool _saveState; diff --git a/engines/wintermute/base/base_parser.cpp b/engines/wintermute/base/base_parser.cpp index 9a0e9e3ad9..7f18c1f0cf 100644 --- a/engines/wintermute/base/base_parser.cpp +++ b/engines/wintermute/base/base_parser.cpp @@ -51,7 +51,7 @@ BaseParser::BaseParser() { ////////////////////////////////////////////////////////////////////// BaseParser::~BaseParser() { - if (_whiteSpace != NULL) { + if (_whiteSpace != nullptr) { delete[] _whiteSpace; } } @@ -136,7 +136,7 @@ void BaseParser::skipCharacters(char **buf, const char *toSkip) { if (ch == '\n') { _parserLine++; } - if (strchr(toSkip, ch) == NULL) { + if (strchr(toSkip, ch) == nullptr) { return; } ++*buf; // skip this character @@ -250,10 +250,10 @@ Common::String BaseParser::getToken(char **buf) { *t++ = 0; } else if (*b == 0) { *buf = b; - return NULL; + return nullptr; } else { // Error. - return NULL; + return nullptr; } *buf = b; diff --git a/engines/wintermute/base/base_parser.h b/engines/wintermute/base/base_parser.h index 76ca8ea856..87a936c624 100644 --- a/engines/wintermute/base/base_parser.h +++ b/engines/wintermute/base/base_parser.h @@ -70,7 +70,7 @@ public: virtual ~BaseParser(); private: char *getLastOffender(); - void skipToken(char **buf, char *tok, char *msg = NULL); + void skipToken(char **buf, char *tok, char *msg = nullptr); int getTokenInt(char **buf); float getTokenFloat(char **buf); Common::String getToken(char **buf); diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp index 4cb67b87e1..84a1c2ec67 100644 --- a/engines/wintermute/base/base_persistence_manager.cpp +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -36,8 +36,10 @@ #include "engines/wintermute/math/vector2.h" #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/graphics/transparent_surface.h" #include "engines/wintermute/wintermute.h" #include "graphics/decoders/bmp.h" +#include "graphics/scaler.h" #include "common/memstream.h" #include "common/str.h" #include "common/system.h" @@ -45,37 +47,40 @@ namespace Wintermute { -#define SAVE_BUFFER_INIT_SIZE 100000 -#define SAVE_BUFFER_GROW_BY 50000 - -#define SAVE_MAGIC 0x45564153 -#define SAVE_MAGIC_2 0x32564153 +// The original WME-Lite savegames had the following: +//#define SAVE_MAGIC 0x45564153 +//#define SAVE_MAGIC_2 0x32564153 +// In case anyone tries to load original savegames, or for that matter +// in case we ever want to attempt to support original savegames, we +// avoid those numbers, and use this instead: +#define SAVE_MAGIC_3 0x12564154 ////////////////////////////////////////////////////////////////////////// BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool deleteSingleton) { _saving = false; -// _buffer = NULL; -// _bufferSize = 0; _offset = 0; - _saveStream = NULL; - _loadStream = NULL; + _saveStream = nullptr; + _loadStream = nullptr; _deleteSingleton = deleteSingleton; if (BaseEngine::instance().getGameRef()) { _gameRef = BaseEngine::instance().getGameRef(); } else { - _gameRef = NULL; + _gameRef = nullptr; } - _richBuffer = NULL; + _richBuffer = nullptr; _richBufferSize = 0; - _savedDescription = NULL; + _scummVMThumbnailData = nullptr; + _scummVMThumbSize = 0; + + _savedDescription = nullptr; // _savedTimestamp = 0; _savedVerMajor = _savedVerMinor = _savedVerBuild = 0; _savedExtMajor = _savedExtMinor = 0; _thumbnailDataSize = 0; - _thumbnailData = NULL; + _thumbnailData = nullptr; if (savePrefix) { _savePrefix = savePrefix; } else if (_gameRef) { @@ -89,28 +94,21 @@ BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool dele ////////////////////////////////////////////////////////////////////////// BasePersistenceManager::~BasePersistenceManager() { cleanup(); - if (_deleteSingleton && BaseEngine::instance().getGameRef() == NULL) + if (_deleteSingleton && BaseEngine::instance().getGameRef() == nullptr) BaseEngine::destroy(); } ////////////////////////////////////////////////////////////////////////// void BasePersistenceManager::cleanup() { - /* if (_buffer) { - if (_saving) free(_buffer); - else delete[] _buffer; // allocated by file manager - } - _buffer = NULL; - - _bufferSize = 0;*/ _offset = 0; delete[] _richBuffer; - _richBuffer = NULL; + _richBuffer = nullptr; _richBufferSize = 0; delete[] _savedDescription; - _savedDescription = NULL; // ref to buffer + _savedDescription = nullptr; // ref to buffer // _savedTimestamp = 0; _savedVerMajor = _savedVerMinor = _savedVerBuild = 0; _savedExtMajor = _savedExtMinor = 0; @@ -118,25 +116,31 @@ void BasePersistenceManager::cleanup() { _thumbnailDataSize = 0; if (_thumbnailData) { delete[] _thumbnailData; - _thumbnailData = NULL; + _thumbnailData = nullptr; + } + + _scummVMThumbSize = 0; + if (_scummVMThumbnailData) { + delete[] _scummVMThumbnailData; + _scummVMThumbnailData = nullptr; } delete _loadStream; delete _saveStream; - _loadStream = NULL; - _saveStream = NULL; + _loadStream = nullptr; + _saveStream = nullptr; } Common::String BasePersistenceManager::getFilenameForSlot(int slot) const { // 3 Digits, to allow for one save-slot for autosave + slot 1 - 100 (which will be numbered 0-99 filename-wise) - return Common::String::format("%s-save%03d.wsv", _savePrefix.c_str(), slot); + return Common::String::format("%s.%03d", _savePrefix.c_str(), slot); } void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &desc) { Common::String filename = getFilenameForSlot(slot); debugC(kWintermuteDebugSaveGame, "Trying to list savegame %s in slot %d", filename.c_str(), slot); if (DID_FAIL(readHeader(filename))) { - warning("getSavedDesc(%d) - Failed for %s", slot, filename.c_str()); + debugC(kWintermuteDebugSaveGame, "getSavedDesc(%d) - Failed for %s", slot, filename.c_str()); return; } desc.setSaveSlot(slot); @@ -144,13 +148,28 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des desc.setDeletableFlag(true); desc.setWriteProtectedFlag(false); - if (_thumbnailDataSize > 0) { - Common::MemoryReadStream thumbStream(_thumbnailData, _thumbnailDataSize); + int thumbSize = 0; + byte *thumbData = nullptr; + if (_scummVMThumbSize > 0) { + thumbSize = _scummVMThumbSize; + thumbData = _scummVMThumbnailData; + } else if (_thumbnailDataSize > 0) { + thumbSize = _thumbnailDataSize; + thumbData = _thumbnailData; + } + + if (thumbSize > 0) { + Common::MemoryReadStream thumbStream(thumbData, thumbSize, DisposeAfterUse::NO); Graphics::BitmapDecoder bmpDecoder; if (bmpDecoder.loadStream(thumbStream)) { - Graphics::Surface *surf = new Graphics::Surface; - surf = bmpDecoder.getSurface()->convertTo(g_system->getOverlayFormat()); - desc.setThumbnail(surf); + const Graphics::Surface *bmpSurface = bmpDecoder.getSurface(); + TransparentSurface *scaleableSurface = new TransparentSurface(*bmpSurface, false); + Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2); + Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat()); + desc.setThumbnail(thumb); + delete scaleableSurface; + scaled->free(); + delete scaled; } } @@ -165,13 +184,13 @@ void BasePersistenceManager::deleteSaveSlot(int slot) { } uint32 BasePersistenceManager::getMaxUsedSlot() { - Common::String saveMask = Common::String::format("%s-save???.wsv", _savePrefix.c_str()); + Common::String saveMask = Common::String::format("%s.???", _savePrefix.c_str()); Common::StringArray saves = g_system->getSavefileManager()->listSavefiles(saveMask); Common::StringArray::iterator it = saves.begin(); int ret = -1; for (; it != saves.end(); ++it) { int num = -1; - sscanf(it->c_str(), "save%d", &num); + sscanf(it->c_str(), ".%d", &num); ret = MAX(ret, num); } return ret; @@ -202,19 +221,18 @@ bool BasePersistenceManager::initSave(const char *desc) { _gameRef->_cachedThumbnail = new BaseSaveThumbHelper(_gameRef); if (DID_FAIL(_gameRef->_cachedThumbnail->storeThumbnail(true))) { delete _gameRef->_cachedThumbnail; - _gameRef->_cachedThumbnail = NULL; + _gameRef->_cachedThumbnail = nullptr; } } uint32 magic = DCGF_MAGIC; putDWORD(magic); - magic = SAVE_MAGIC_2; + magic = SAVE_MAGIC_3; putDWORD(magic); byte verMajor, verMinor, extMajor, extMinor; _gameRef->getVersion(&verMajor, &verMinor, &extMajor, &extMinor); - //uint32 version = MAKELONG(MAKEWORD(VerMajor, VerMinor), MAKEWORD(ExtMajor, ExtMinor)); _saveStream->writeByte(verMajor); _saveStream->writeByte(verMinor); _saveStream->writeByte(extMajor); @@ -243,10 +261,29 @@ bool BasePersistenceManager::initSave(const char *desc) { if (!thumbnailOK) { putDWORD(0); } + thumbnailOK = false; + // Again for the ScummVM-thumb: + if (_gameRef->_cachedThumbnail) { + if (_gameRef->_cachedThumbnail->_scummVMThumb) { + Common::MemoryWriteStreamDynamic scummVMthumbStream(DisposeAfterUse::YES); + if (_gameRef->_cachedThumbnail->_scummVMThumb->writeBMPToStream(&scummVMthumbStream)) { + _saveStream->writeUint32LE(scummVMthumbStream.size()); + _saveStream->write(scummVMthumbStream.getData(), scummVMthumbStream.size()); + } else { + _saveStream->writeUint32LE(0); + } + + thumbnailOK = true; + } + } + if (!thumbnailOK) { + putDWORD(0); + } + // in any case, destroy the cached thumbnail once used delete _gameRef->_cachedThumbnail; - _gameRef->_cachedThumbnail = NULL; + _gameRef->_cachedThumbnail = nullptr; uint32 dataOffset = _offset + sizeof(uint32) + // data offset @@ -270,7 +307,7 @@ bool BasePersistenceManager::readHeader(const Common::String &filename) { _saving = false; _loadStream = g_system->getSavefileManager()->openForLoading(filename); - //_buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &_bufferSize); + if (_loadStream) { uint32 magic; magic = getDWORD(); @@ -282,28 +319,32 @@ bool BasePersistenceManager::readHeader(const Common::String &filename) { magic = getDWORD(); - if (magic == SAVE_MAGIC || magic == SAVE_MAGIC_2) { + if (magic == SAVE_MAGIC_3) { _savedVerMajor = _loadStream->readByte(); _savedVerMinor = _loadStream->readByte(); _savedExtMajor = _loadStream->readByte(); _savedExtMinor = _loadStream->readByte(); - if (magic == SAVE_MAGIC_2) { - _savedVerBuild = (byte)getDWORD(); - _savedName = getStringObj(); - - // load thumbnail - _thumbnailDataSize = getDWORD(); - if (_thumbnailDataSize > 0) { - _thumbnailData = new byte[_thumbnailDataSize]; - if (_thumbnailData) { - getBytes(_thumbnailData, _thumbnailDataSize); - } else { - _thumbnailDataSize = 0; - } + _savedVerBuild = (byte)getDWORD(); + _savedName = getStringObj(); + + // load thumbnail + _thumbnailDataSize = getDWORD(); + if (_thumbnailDataSize > 0) { + _thumbnailData = new byte[_thumbnailDataSize]; + if (_thumbnailData) { + getBytes(_thumbnailData, _thumbnailDataSize); + } else { + _thumbnailDataSize = 0; } + } + + _scummVMThumbSize = getDWORD(); + _scummVMThumbnailData = new byte[_scummVMThumbSize]; + if (_scummVMThumbnailData) { + getBytes(_scummVMThumbnailData, _scummVMThumbSize); } else { - _savedVerBuild = 35; // last build with ver1 savegames + _scummVMThumbSize = 0; } uint32 dataOffset = getDWORD(); @@ -448,7 +489,7 @@ char *BasePersistenceManager::getString() { if (!strcmp(ret, "(null)")) { delete[] ret; - return NULL; + return nullptr; } else { return ret; } @@ -461,7 +502,7 @@ bool BasePersistenceManager::putTimeDate(const TimeDate &t) { _saveStream->writeSint32LE(t.tm_mday); _saveStream->writeSint32LE(t.tm_mon); _saveStream->writeSint32LE(t.tm_year); - // _saveStream->writeSint32LE(t.tm_wday); //TODO: Add this in when merging next + _saveStream->writeSint32LE(t.tm_wday); if (_saveStream->err()) { return STATUS_FAILED; @@ -477,20 +518,26 @@ TimeDate BasePersistenceManager::getTimeDate() { t.tm_mday = _loadStream->readSint32LE(); t.tm_mon = _loadStream->readSint32LE(); t.tm_year = _loadStream->readSint32LE(); - // t.tm_wday = _loadStream->readSint32LE(); //TODO: Add this in when merging next + t.tm_wday = _loadStream->readSint32LE(); return t; } void BasePersistenceManager::putFloat(float val) { - Common::String str = Common::String::format("F%f", val); + int32 exponent = 0; + float significand = frexp(val, &exponent); + Common::String str = Common::String::format("FS%f", significand); _saveStream->writeUint32LE(str.size()); _saveStream->writeString(str); + _saveStream->writeSint32LE(exponent); } float BasePersistenceManager::getFloat() { char *str = getString(); float value = 0.0f; - int ret = sscanf(str, "F%f", &value); + float significand = 0.0f; + int32 exponent = _loadStream->readSint32LE(); + int ret = sscanf(str, "FS%f", &significand); + value = ldexp(significand, exponent); if (ret != 1) { warning("%s not parsed as float", str); } @@ -499,16 +546,21 @@ float BasePersistenceManager::getFloat() { } void BasePersistenceManager::putDouble(double val) { - Common::String str = Common::String::format("D%f", val); - str.format("D%f", val); + int32 exponent = 0; + double significand = frexp(val, &exponent); + Common::String str = Common::String::format("DS%f", significand); _saveStream->writeUint32LE(str.size()); _saveStream->writeString(str); + _saveStream->writeSint32LE(exponent); } double BasePersistenceManager::getDouble() { char *str = getString(); - float value = 0.0f; // TODO: Do we ever really need to carry a full double-precision number? - int ret = sscanf(str, "D%f", &value); + double value = 0.0f; + float significand = 0.0f; + int32 exponent = _loadStream->readSint32LE(); + int ret = sscanf(str, "DS%f", &significand); + value = ldexp(significand, exponent); if (ret != 1) { warning("%s not parsed as double", str); } @@ -791,7 +843,7 @@ bool BasePersistenceManager::transfer(const char *name, void *val) { if (_saving) { SystemClassRegistry::getInstance()->getPointerID(*(void **)val, &classID, &instanceID); - if (*(void **)val != NULL && (classID == -1 || instanceID == -1)) { + if (*(void **)val != nullptr && (classID == -1 || instanceID == -1)) { debugC(kWintermuteDebugSaveGame, "Warning: invalid instance '%s'", name); } diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h index a262c92a0b..8cc21b353b 100644 --- a/engines/wintermute/base/base_persistence_manager.h +++ b/engines/wintermute/base/base_persistence_manager.h @@ -87,12 +87,14 @@ public: bool transfer(const char *name, Common::String *val); bool transfer(const char *name, Vector2 *val); bool transfer(const char *name, AnsiStringArray &Val); - BasePersistenceManager(const char *savePrefix = NULL, bool deleteSingleton = false); + BasePersistenceManager(const char *savePrefix = nullptr, bool deleteSingleton = false); virtual ~BasePersistenceManager(); bool checkVersion(byte verMajor, byte verMinor, byte verBuild); uint32 _thumbnailDataSize; byte *_thumbnailData; + uint32 _scummVMThumbSize; + byte *_scummVMThumbnailData; Common::String getFilenameForSlot(int slot) const; private: bool _deleteSingleton; diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp index 0bc5975e51..a3a23f770a 100644 --- a/engines/wintermute/base/base_region.cpp +++ b/engines/wintermute/base/base_region.cpp @@ -103,7 +103,7 @@ bool BaseRegion::pointInRegion(int x, int y) { ////////////////////////////////////////////////////////////////////////// bool BaseRegion::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "BaseRegion::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -289,7 +289,7 @@ bool BaseRegion::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta if (index >= 0 && index < (int32)_points.size()) { delete _points[index]; - _points[index] = NULL; + _points[index] = nullptr; _points.remove_at(index); createRegion(); diff --git a/engines/wintermute/base/base_region.h b/engines/wintermute/base/base_region.h index 464f25be2f..6b7905fe53 100644 --- a/engines/wintermute/base/base_region.h +++ b/engines/wintermute/base/base_region.h @@ -51,7 +51,7 @@ public: bool loadBuffer(byte *buffer, bool complete = true); Rect32 _rect; BaseArray<BasePoint *> _points; - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) { return saveAsText(buffer, indent, NULL); } + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) { return saveAsText(buffer, indent, nullptr); } virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent, const char *nameOverride); // scripting interface diff --git a/engines/wintermute/base/base_save_thumb_helper.cpp b/engines/wintermute/base/base_save_thumb_helper.cpp index b4205c21c4..76d703a697 100644 --- a/engines/wintermute/base/base_save_thumb_helper.cpp +++ b/engines/wintermute/base/base_save_thumb_helper.cpp @@ -30,50 +30,79 @@ #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/gfx/base_renderer.h" #include "engines/wintermute/base/base_game.h" +#include "graphics/scaler.h" namespace Wintermute { ////////////////////////////////////////////////////////////////////////// BaseSaveThumbHelper::BaseSaveThumbHelper(BaseGame *inGame) : BaseClass(inGame) { - _thumbnail = NULL; + _thumbnail = nullptr; + _scummVMThumb = nullptr; } ////////////////////////////////////////////////////////////////////////// BaseSaveThumbHelper::~BaseSaveThumbHelper(void) { delete _thumbnail; - _thumbnail = NULL; + _thumbnail = nullptr; + delete _scummVMThumb; + _scummVMThumb = nullptr; } -////////////////////////////////////////////////////////////////////////// -bool BaseSaveThumbHelper::storeThumbnail(bool doFlip) { - delete _thumbnail; - _thumbnail = NULL; - +BaseImage *BaseSaveThumbHelper::storeThumb(bool doFlip, int width, int height) { + BaseImage *thumbnail = nullptr; if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) { if (doFlip) { // when using opengl on windows it seems to be necessary to do this twice // works normally for direct3d _gameRef->displayContent(false); _gameRef->_renderer->flip(); - + _gameRef->displayContent(false); _gameRef->_renderer->flip(); } - + BaseImage *screenshot = _gameRef->_renderer->takeScreenshot(); if (!screenshot) { - return STATUS_FAILED; + return nullptr; } - + // normal thumbnail if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) { - _thumbnail = new BaseImage(); - _thumbnail->copyFrom(screenshot, _gameRef->_thumbnailWidth, _gameRef->_thumbnailHeight); + thumbnail = new BaseImage(); + thumbnail->copyFrom(screenshot, width, height); } + + + delete screenshot; + screenshot = nullptr; + } + return thumbnail; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSaveThumbHelper::storeThumbnail(bool doFlip) { + delete _thumbnail; + _thumbnail = nullptr; + if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) { - delete screenshot; - screenshot = NULL; + _thumbnail = storeThumb(doFlip, _gameRef->_thumbnailWidth, _gameRef->_thumbnailHeight); + if (!_thumbnail) { + return STATUS_FAILED; + } + } + storeScummVMThumbNail(); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseSaveThumbHelper::storeScummVMThumbNail(bool doFlip) { + delete _scummVMThumb; + _scummVMThumb = nullptr; + + _scummVMThumb = storeThumb(doFlip, kThumbnailWidth, kThumbnailHeight2); + if (!_scummVMThumb) { + return STATUS_FAILED; } return STATUS_OK; } diff --git a/engines/wintermute/base/base_save_thumb_helper.h b/engines/wintermute/base/base_save_thumb_helper.h index 8863508ac9..8e8a7183c2 100644 --- a/engines/wintermute/base/base_save_thumb_helper.h +++ b/engines/wintermute/base/base_save_thumb_helper.h @@ -40,9 +40,12 @@ public: BaseSaveThumbHelper(BaseGame *inGame); virtual ~BaseSaveThumbHelper(void); bool storeThumbnail(bool doFlip = false); + bool storeScummVMThumbNail(bool doFlip = false); BaseImage *_thumbnail; + BaseImage *_scummVMThumb; private: + BaseImage *storeThumb(bool doFlip, int width, int height); BaseImage *_richThumbnail; }; diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp index c5d5e82f76..d1a9d4aa46 100644 --- a/engines/wintermute/base/base_script_holder.cpp +++ b/engines/wintermute/base/base_script_holder.cpp @@ -43,7 +43,7 @@ BaseScriptHolder::BaseScriptHolder(BaseGame *inGame) : BaseScriptable(inGame) { setName("<unnamed>"); _freezable = true; - _filename = NULL; + _filename = nullptr; } @@ -56,11 +56,11 @@ BaseScriptHolder::~BaseScriptHolder() { ////////////////////////////////////////////////////////////////////////// bool BaseScriptHolder::cleanup() { delete[] _filename; - _filename = NULL; + _filename = nullptr; for (uint32 i = 0; i < _scripts.size(); i++) { _scripts[i]->finish(true); - _scripts[i]->_owner = NULL; + _scripts[i]->_owner = nullptr; } _scripts.clear(); @@ -69,15 +69,15 @@ bool BaseScriptHolder::cleanup() { ////////////////////////////////////////////////////////////////////// void BaseScriptHolder::setFilename(const char *filename) { - if (_filename != NULL) { + if (_filename != nullptr) { delete[] _filename; - _filename = NULL; + _filename = nullptr; } - if (filename == NULL) { + if (filename == nullptr) { return; } _filename = new char [strlen(filename) + 1]; - if (_filename != NULL) { + if (_filename != nullptr) { strcpy(_filename, filename); } } @@ -342,7 +342,7 @@ bool BaseScriptHolder::removeScript(ScScript *script) { } ////////////////////////////////////////////////////////////////////////// -bool BaseScriptHolder::canHandleEvent(const char *EventName) { +bool BaseScriptHolder::canHandleEvent(const char *EventName) const { for (uint32 i = 0; i < _scripts.size(); i++) { if (!_scripts[i]->_thread && _scripts[i]->canHandleEvent(EventName)) { return true; @@ -353,7 +353,7 @@ bool BaseScriptHolder::canHandleEvent(const char *EventName) { ////////////////////////////////////////////////////////////////////////// -bool BaseScriptHolder::canHandleMethod(const char *MethodName) { +bool BaseScriptHolder::canHandleMethod(const char *MethodName) const { for (uint32 i = 0; i < _scripts.size(); i++) { if (!_scripts[i]->_thread && _scripts[i]->canHandleMethod(MethodName)) { return true; @@ -388,8 +388,8 @@ bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) { buffer = params; } - char *propName = NULL; - char *propValue = NULL; + char *propName = nullptr; + char *propValue = nullptr; while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { switch (cmd) { @@ -418,16 +418,16 @@ bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) { if (cmd == PARSERR_TOKENNOTFOUND) { delete[] propName; delete[] propValue; - propName = NULL; - propValue = NULL; + propName = nullptr; + propValue = nullptr; _gameRef->LOG(0, "Syntax error in PROPERTY definition"); return STATUS_FAILED; } - if (cmd == PARSERR_GENERIC || propName == NULL || propValue == NULL) { + if (cmd == PARSERR_GENERIC || propName == nullptr || propValue == nullptr) { delete[] propName; delete[] propValue; - propName = NULL; - propValue = NULL; + propName = nullptr; + propValue = nullptr; _gameRef->LOG(0, "Error loading PROPERTY definition"); return STATUS_FAILED; } @@ -440,8 +440,8 @@ bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) { delete val; delete[] propName; delete[] propValue; - propName = NULL; - propValue = NULL; + propName = nullptr; + propValue = nullptr; return STATUS_OK; } @@ -474,7 +474,7 @@ ScScript *BaseScriptHolder::invokeMethodThread(const char *methodName) { } } } - return NULL; + return nullptr; } diff --git a/engines/wintermute/base/base_script_holder.h b/engines/wintermute/base/base_script_holder.h index 5fd0dbec9c..320f0fb07a 100644 --- a/engines/wintermute/base/base_script_holder.h +++ b/engines/wintermute/base/base_script_holder.h @@ -43,8 +43,8 @@ public: virtual ~BaseScriptHolder(); virtual ScScript *invokeMethodThread(const char *methodName); virtual void makeFreezable(bool freezable); - bool canHandleEvent(const char *eventName); - virtual bool canHandleMethod(const char *eventMethod); + bool canHandleEvent(const char *eventName) const; + virtual bool canHandleMethod(const char *eventMethod) const; bool cleanup(); bool removeScript(ScScript *script); bool addScript(const char *filename); diff --git a/engines/wintermute/base/base_scriptable.cpp b/engines/wintermute/base/base_scriptable.cpp index a2dd8b00e7..7dbcd72200 100644 --- a/engines/wintermute/base/base_scriptable.cpp +++ b/engines/wintermute/base/base_scriptable.cpp @@ -39,14 +39,14 @@ BaseScriptable::BaseScriptable(BaseGame *inGame, bool noValue, bool persistable) _refCount = 0; if (noValue) { - _scValue = NULL; + _scValue = nullptr; } else { _scValue = new ScValue(_gameRef); } _persistable = persistable; - _scProp = NULL; + _scProp = nullptr; } @@ -55,8 +55,8 @@ BaseScriptable::~BaseScriptable() { //if (_refCount>0) _gameRef->LOG(0, "Warning: Destroying object, _refCount=%d", _refCount); delete _scValue; delete _scProp; - _scValue = NULL; - _scProp = NULL; + _scValue = nullptr; + _scProp = nullptr; } @@ -83,7 +83,7 @@ ScValue *BaseScriptable::scGetProperty(const Common::String &name) { if (_scProp) { return _scProp->getProp(name.c_str()); // TODO: Change to Common::String } else { - return NULL; + return nullptr; } } @@ -178,14 +178,14 @@ void BaseScriptable::scDebuggerDesc(char *buf, int bufSize) { } ////////////////////////////////////////////////////////////////////////// -bool BaseScriptable::canHandleMethod(const char *eventMethod) { +bool BaseScriptable::canHandleMethod(const char *eventMethod) const { return false; } ////////////////////////////////////////////////////////////////////////// ScScript *BaseScriptable::invokeMethodThread(const char *methodName) { - return NULL; + return nullptr; } } // end of namespace Wintermute diff --git a/engines/wintermute/base/base_scriptable.h b/engines/wintermute/base/base_scriptable.h index fbe14fc299..b0b4e77ed2 100644 --- a/engines/wintermute/base/base_scriptable.h +++ b/engines/wintermute/base/base_scriptable.h @@ -48,7 +48,7 @@ public: virtual ~BaseScriptable(); // high level scripting interface - virtual bool canHandleMethod(const char *eventMethod); + virtual bool canHandleMethod(const char *eventMethod) const; virtual bool scSetProperty(const char *name, ScValue *value); virtual ScValue *scGetProperty(const Common::String &name); virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp index 468af1bd75..4f55e47c05 100644 --- a/engines/wintermute/base/base_sprite.cpp +++ b/engines/wintermute/base/base_sprite.cpp @@ -64,7 +64,7 @@ void BaseSprite::setDefaults() { _currentFrame = -1; _looping = false; _lastFrameTime = 0; - setFilename(NULL); + setFilename(nullptr); _finished = false; _changed = false; _paused = false; @@ -72,7 +72,7 @@ void BaseSprite::setDefaults() { _moveX = _moveY = 0; _editorMuted = false; - _editorBgFile = NULL; + _editorBgFile = nullptr; _editorBgOffsetX = _editorBgOffsetY = 0; _editorBgAlpha = 0xFF; _streamed = false; @@ -94,7 +94,7 @@ void BaseSprite::cleanup() { _frames.clear(); delete[] _editorBgFile; - _editorBgFile = NULL; + _editorBgFile = nullptr; setDefaults(); } @@ -141,7 +141,7 @@ bool BaseSprite::loadFile(const Common::String &filename, int lifeTime, TSpriteC } } else { BaseFileManager::getEngineInstance()->closeFile(file); - file = NULL; + file = nullptr; } bool ret = STATUS_FAILED; @@ -154,7 +154,7 @@ bool BaseSprite::loadFile(const Common::String &filename, int lifeTime, TSpriteC BaseFrame *frame = new BaseFrame(_gameRef); BaseSubFrame *subframe = new BaseSubFrame(_gameRef); subframe->setSurface(filename, true, 0, 0, 0, lifeTime, true); - if (subframe->_surface == NULL) { + if (subframe->_surface == nullptr) { _gameRef->LOG(0, "Error loading simple sprite '%s'", filename.c_str()); ret = STATUS_FAILED; delete frame; @@ -440,7 +440,7 @@ bool BaseSprite::display(int x, int y, BaseObject *registerVal, float zoomX, flo BaseSurface *BaseSprite::getSurface() { // only used for animated textures for 3D models if (_currentFrame < 0 || _currentFrame >= (int32)_frames.size()) { - return NULL; + return nullptr; } BaseFrame *frame = _frames[_currentFrame]; if (frame && frame->_subframes.size() > 0) { @@ -448,10 +448,10 @@ BaseSurface *BaseSprite::getSurface() { if (subframe) { return subframe->_surface; } else { - return NULL; + return nullptr; } } else { - return NULL; + return nullptr; } } @@ -611,13 +611,13 @@ bool BaseSprite::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta else if (strcmp(name, "AddFrame") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); - const char *filename = NULL; + const char *filename = nullptr; if (!val->isNULL()) { filename = val->getString(); } BaseFrame *frame = new BaseFrame(_gameRef); - if (filename != NULL) { + if (filename != nullptr) { BaseSubFrame *sub = new BaseSubFrame(_gameRef); if (DID_SUCCEED(sub->setSurface(filename))) { sub->setDefaultRect(); @@ -643,13 +643,13 @@ bool BaseSprite::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta } ScValue *val = stack->pop(); - const char *filename = NULL; + const char *filename = nullptr; if (!val->isNULL()) { filename = val->getString(); } BaseFrame *frame = new BaseFrame(_gameRef); - if (filename != NULL) { + if (filename != nullptr) { BaseSubFrame *sub = new BaseSubFrame(_gameRef); if (DID_SUCCEED(sub->setSurface(filename))) { frame->_subframes.add(sub); @@ -740,7 +740,7 @@ ScValue *BaseSprite::scGetProperty(const Common::String &name) { // Owner (RO) ////////////////////////////////////////////////////////////////////////// else if (name == "Owner") { - if (_owner == NULL) { + if (_owner == nullptr) { _scValue->setNULL(); } else { _scValue->setNative(_owner, true); diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h index 1d244c3a52..ac1a0e919b 100644 --- a/engines/wintermute/base/base_sprite.h +++ b/engines/wintermute/base/base_sprite.h @@ -47,18 +47,18 @@ public: bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100); int _moveY; int _moveX; - bool display(int x, int y, BaseObject *registerOwner = NULL, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); + bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); bool getCurrentFrame(float zoomX = 100, float zoomY = 100); void reset(); bool isChanged(); bool isFinished(); bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - bool draw(int x, int y, BaseObject *Register = NULL, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF); + bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF); bool _looping; int _currentFrame; - bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = NULL); - BaseSprite(BaseGame *inGame, BaseObject *owner = NULL); + bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = nullptr); + BaseSprite(BaseGame *inGame, BaseObject *owner = nullptr); virtual ~BaseSprite(); BaseArray<BaseFrame *> _frames; bool saveAsText(BaseDynamicBuffer *buffer, int indent); diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp index 2f890beea1..11ec7b094f 100644 --- a/engines/wintermute/base/base_string_table.cpp +++ b/engines/wintermute/base/base_string_table.cpp @@ -50,7 +50,7 @@ BaseStringTable::~BaseStringTable() { ////////////////////////////////////////////////////////////////////////// bool BaseStringTable::addString(const char *key, const char *val, bool reportDuplicities) { - if (key == NULL || val == NULL) { + if (key == nullptr || val == nullptr) { return STATUS_FAILED; } @@ -74,13 +74,13 @@ bool BaseStringTable::addString(const char *key, const char *val, bool reportDup ////////////////////////////////////////////////////////////////////////// char *BaseStringTable::getKey(const char *str) const { - if (str == NULL || str[0] != '/') { - return NULL; + if (str == nullptr || str[0] != '/') { + return nullptr; } const char *value = strchr(str + 1, '/'); - if (value == NULL) { - return NULL; + if (value == nullptr) { + return nullptr; } char *key = new char[value - str]; @@ -110,12 +110,12 @@ char *BaseStringTable::getKey(const char *str) const { ////////////////////////////////////////////////////////////////////////// void BaseStringTable::expand(char **str) const { - if (str == NULL || *str == NULL || *str[0] != '/') { + if (str == nullptr || *str == nullptr || *str[0] != '/') { return; } char *value = strchr(*str + 1, '/'); - if (value == NULL) { + if (value == nullptr) { return; } @@ -149,12 +149,12 @@ void BaseStringTable::expand(char **str) const { ////////////////////////////////////////////////////////////////////////// const char *BaseStringTable::expandStatic(const char *string) const { - if (string == NULL || string[0] == '\0' || string[0] != '/') { + if (string == nullptr || string[0] == '\0' || string[0] != '/') { return string; } const char *value = strchr(string + 1, '/'); - if (value == NULL) { + if (value == nullptr) { return string; } @@ -193,7 +193,7 @@ bool BaseStringTable::loadFile(const char *filename, bool clearOld) { uint32 size; byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &size); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "BaseStringTable::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -222,12 +222,12 @@ bool BaseStringTable::loadFile(const char *filename, bool clearOld) { char *line = new char[realLength + 1]; Common::strlcpy(line, (char *)&buffer[pos], realLength + 1); char *value = strchr(line, '\t'); - if (value == NULL) { + if (value == nullptr) { value = strchr(line, ' '); } if (line[0] != ';') { - if (value != NULL) { + if (value != nullptr) { value[0] = '\0'; value++; for (uint32 i = 0; i < strlen(value); i++) { diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp index 77cc522ae7..a06d7f50eb 100644 --- a/engines/wintermute/base/base_sub_frame.cpp +++ b/engines/wintermute/base/base_sub_frame.cpp @@ -44,7 +44,7 @@ IMPLEMENT_PERSISTENT(BaseSubFrame, false) ////////////////////////////////////////////////////////////////////////// BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) { - _surface = NULL; + _surface = nullptr; _hotspotX = _hotspotY = 0; _alpha = 0xFFFFFFFF; _transparent = 0xFFFF00FF; @@ -54,7 +54,7 @@ BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) { _editorSelected = false; - _surfaceFilename = NULL; + _surfaceFilename = nullptr; _cKDefault = true; _cKRed = _cKBlue = _cKGreen = 0; _lifeTime = -1; @@ -73,7 +73,7 @@ BaseSubFrame::~BaseSubFrame() { _gameRef->_surfaceStorage->removeSurface(_surface); } delete[] _surfaceFilename; - _surfaceFilename = NULL; + _surfaceFilename = nullptr; } @@ -118,10 +118,10 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { int ar = 255, ag = 255, ab = 255, alpha = 255; bool custoTrans = false; BasePlatform::setRectEmpty(&rect); - char *surfaceFile = NULL; + char *surfaceFile = nullptr; delete _surface; - _surface = NULL; + _surface = nullptr; while ((cmd = parser.getCommand((char **)&buffer, commands, ¶ms)) > 0) { switch (cmd) { @@ -184,7 +184,7 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { return STATUS_FAILED; } - if (surfaceFile != NULL) { + if (surfaceFile != nullptr) { if (custoTrans) { setSurface(surfaceFile, false, r, g, b, lifeTime, keepLoaded); } else { @@ -198,7 +198,7 @@ bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) { } /* - if (_surface == NULL) + if (_surface == nullptr) { _gameRef->LOG(0, "Error parsing sub-frame. Image not set."); return STATUS_FAILED; @@ -236,7 +236,7 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl return STATUS_OK; } - if (registerOwner != NULL && !_decoration) { + if (registerOwner != nullptr && !_decoration) { if (zoomX == 100 && zoomY == 100) { _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, x - _hotspotX + getRect().left, y - _hotspotY + getRect().top, getRect().right - getRect().left, getRect().bottom - getRect().top, zoomX, zoomY, precise)); } else { @@ -426,7 +426,7 @@ bool BaseSubFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisS _gameRef->_surfaceStorage->removeSurface(_surface); } delete[] _surfaceFilename; - _surfaceFilename = NULL; + _surfaceFilename = nullptr; stack->pushBool(true); } else { const char *filename = val->getString(); @@ -617,11 +617,11 @@ const char *BaseSubFrame::scToString() { bool BaseSubFrame::setSurface(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) { if (_surface) { _gameRef->_surfaceStorage->removeSurface(_surface); - _surface = NULL; + _surface = nullptr; } delete[] _surfaceFilename; - _surfaceFilename = NULL; + _surfaceFilename = nullptr; _surface = _gameRef->_surfaceStorage->addSurface(filename, defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded); if (_surface) { @@ -645,7 +645,7 @@ bool BaseSubFrame::setSurface(const Common::String &filename, bool defaultCK, by ////////////////////////////////////////////////////////////////////////// bool BaseSubFrame::setSurfaceSimple() { if (!_surfaceFilename) { - _surface = NULL; + _surface = nullptr; return STATUS_OK; } _surface = _gameRef->_surfaceStorage->addSurface(_surfaceFilename, _cKDefault, _cKRed, _cKGreen, _cKBlue, _lifeTime, _keepLoaded); diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h index c173ae69d1..2888761bb3 100644 --- a/engines/wintermute/base/base_sub_frame.h +++ b/engines/wintermute/base/base_sub_frame.h @@ -52,7 +52,7 @@ public: BaseSubFrame(BaseGame *inGame); virtual ~BaseSubFrame(); bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded); - bool draw(int x, int y, BaseObject *registerOwner = NULL, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); + bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100); const char* getSurfaceFilename(); diff --git a/engines/wintermute/base/base_surface_storage.cpp b/engines/wintermute/base/base_surface_storage.cpp index 4e795ca813..08d2d2f767 100644 --- a/engines/wintermute/base/base_surface_storage.cpp +++ b/engines/wintermute/base/base_surface_storage.cpp @@ -124,12 +124,12 @@ BaseSurface *BaseSurfaceStorage::addSurface(const Common::String &filename, bool surface = _gameRef->_renderer->createSurface(); if (!surface) { - return NULL; + return nullptr; } if (DID_FAIL(surface->create(filename, defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded))) { delete surface; - return NULL; + return nullptr; } else { surface->_referenceCount = 1; _surfaces.push_back(surface); @@ -176,32 +176,29 @@ bool BaseSurfaceStorage::sortSurfaces() { ////////////////////////////////////////////////////////////////////////// -int BaseSurfaceStorage::surfaceSortCB(const void *arg1, const void *arg2) { - const BaseSurface *s1 = *((const BaseSurface *const *)arg1); - const BaseSurface *s2 = *((const BaseSurface *const *)arg2); - +bool BaseSurfaceStorage::surfaceSortCB(const BaseSurface *s1, const BaseSurface *s2) { // sort by life time if (s1->_lifeTime <= 0 && s2->_lifeTime > 0) { - return 1; + return false; } else if (s1->_lifeTime > 0 && s2->_lifeTime <= 0) { - return -1; + return true; } // sort by validity if (s1->_valid && !s2->_valid) { - return -1; + return true; } else if (!s1->_valid && s2->_valid) { - return 1; + return false; } // sort by time else if (s1->_lastUsedTime > s2->_lastUsedTime) { - return 1; + return false; } else if (s1->_lastUsedTime < s2->_lastUsedTime) { - return -1; + return true; } else { - return 0; + return false; } } diff --git a/engines/wintermute/base/base_surface_storage.h b/engines/wintermute/base/base_surface_storage.h index aef8ad23f9..61738e69a2 100644 --- a/engines/wintermute/base/base_surface_storage.h +++ b/engines/wintermute/base/base_surface_storage.h @@ -39,7 +39,7 @@ public: uint32 _lastCleanupTime; bool initLoop(); bool sortSurfaces(); - static int surfaceSortCB(const void *arg1, const void *arg2); + static bool surfaceSortCB(const BaseSurface *arg1, const BaseSurface *arg2); bool cleanup(bool warn = false); //DECLARE_PERSISTENT(BaseSurfaceStorage, BaseClass); diff --git a/engines/wintermute/base/base_transition_manager.cpp b/engines/wintermute/base/base_transition_manager.cpp index 7785f3d5af..6ae51d8e83 100644 --- a/engines/wintermute/base/base_transition_manager.cpp +++ b/engines/wintermute/base/base_transition_manager.cpp @@ -51,7 +51,7 @@ BaseTransitionMgr::~BaseTransitionMgr() { ////////////////////////////////////////////////////////////////////////// -bool BaseTransitionMgr::isReady() { +bool BaseTransitionMgr::isReady() const { return (_state == TRANS_MGR_READY); } diff --git a/engines/wintermute/base/base_transition_manager.h b/engines/wintermute/base/base_transition_manager.h index d16a44c88e..edb3045a58 100644 --- a/engines/wintermute/base/base_transition_manager.h +++ b/engines/wintermute/base/base_transition_manager.h @@ -41,7 +41,7 @@ public: bool _preserveInteractive; bool update(); bool start(TTransitionType type, bool nonInteractive = false); - bool isReady(); + bool isReady() const; TTransMgrState _state; BaseTransitionMgr(BaseGame *inGame); virtual ~BaseTransitionMgr(); diff --git a/engines/wintermute/base/base_viewport.cpp b/engines/wintermute/base/base_viewport.cpp index 7ec995449f..5a488b707f 100644 --- a/engines/wintermute/base/base_viewport.cpp +++ b/engines/wintermute/base/base_viewport.cpp @@ -38,7 +38,7 @@ IMPLEMENT_PERSISTENT(BaseViewport, false) ////////////////////////////////////////////////////////////////////////// BaseViewport::BaseViewport(BaseGame *inGame) : BaseClass(inGame) { BasePlatform::setRectEmpty(&_rect); - _mainObject = NULL; + _mainObject = nullptr; _offsetX = _offsetY = 0; } @@ -86,13 +86,13 @@ Rect32 *BaseViewport::getRect() { ////////////////////////////////////////////////////////////////////////// -int BaseViewport::getWidth() { +int BaseViewport::getWidth() const { return _rect.right - _rect.left; } ////////////////////////////////////////////////////////////////////////// -int BaseViewport::getHeight() { +int BaseViewport::getHeight() const { return _rect.bottom - _rect.top; } diff --git a/engines/wintermute/base/base_viewport.h b/engines/wintermute/base/base_viewport.h index 98ad1c1e14..c69682da62 100644 --- a/engines/wintermute/base/base_viewport.h +++ b/engines/wintermute/base/base_viewport.h @@ -36,15 +36,15 @@ namespace Wintermute { class BaseObject; class BaseViewport : public BaseClass { public: - int getHeight(); - int getWidth(); + int getHeight() const; + int getWidth() const; Rect32 *getRect(); bool setRect(int left, int top, int right, int bottom, bool noCheck = false); DECLARE_PERSISTENT(BaseViewport, BaseClass) int _offsetY; int _offsetX; BaseObject *_mainObject; - BaseViewport(BaseGame *inGame = NULL); + BaseViewport(BaseGame *inGame = nullptr); virtual ~BaseViewport(); private: Rect32 _rect; diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp index 25be3dad2d..3c1ecc7a73 100644 --- a/engines/wintermute/base/file/base_disk_file.cpp +++ b/engines/wintermute/base/file/base_disk_file.cpp @@ -39,10 +39,10 @@ namespace Wintermute { -void correctSlashes(char *fileName) { - for (size_t i = 0; i < strlen(fileName); i++) { +void correctSlashes(Common::String &fileName) { + for (size_t i = 0; i < fileName.size(); i++) { if (fileName[i] == '\\') { - fileName[i] = '/'; + fileName.setChar('/', i); } } } @@ -66,6 +66,12 @@ static Common::FSNode getNodeForRelativePath(const Common::String &filename) { const Common::FSNode gameDataDir(ConfMan.get("path")); Common::FSNode curNode = gameDataDir; + Common::String fixedPath = ""; + while (!path.empty()) { + fixedPath += path.nextToken() + "/"; + } + fixedPath.deleteLastChar(); + // Parse all path-elements while (!path.empty()) { // Get the next path-component by slicing on '\\' @@ -109,13 +115,14 @@ bool diskFileExists(const Common::String &filename) { Common::SeekableReadStream *openDiskFile(const Common::String &filename) { uint32 prefixSize = 0; - Common::SeekableReadStream *file = NULL; + Common::SeekableReadStream *file = nullptr; Common::String fixedFilename = filename; + correctSlashes(fixedFilename); // Absolute path: TODO: Add specific fallbacks here. - if (filename.contains(':')) { - if (filename.hasPrefix("c:\\windows\\fonts\\")) { // East Side Story refers to "c:\windows\fonts\framd.ttf" - fixedFilename = filename.c_str() + 17; + if (fixedFilename.contains(':')) { + if (fixedFilename.hasPrefix("c:/windows/fonts/")) { // East Side Story refers to "c:\windows\fonts\framd.ttf" + fixedFilename = filename.c_str() + 14; } else { error("openDiskFile::Absolute path or invalid filename used in %s", filename.c_str()); } @@ -125,7 +132,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) { SearchMan.listMatchingMembers(files, fixedFilename); for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) { - if ((*it)->getName() == filename) { + if ((*it)->getName().equalsIgnoreCase(lastPathComponent(fixedFilename,'/'))) { file = (*it)->createReadStream(); break; } @@ -157,7 +164,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) { if (!compBuffer) { error("Error allocating memory for compressed file '%s'", filename.c_str()); delete file; - return NULL; + return nullptr; } byte *data = new byte[uncompSize]; @@ -165,7 +172,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) { error("Error allocating buffer for file '%s'", filename.c_str()); delete[] compBuffer; delete file; - return NULL; + return nullptr; } file->seek(dataOffset + prefixSize, SEEK_SET); file->read(compBuffer, compSize); @@ -174,7 +181,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) { error("Error uncompressing file '%s'", filename.c_str()); delete[] compBuffer; delete file; - return NULL; + return nullptr; } delete[] compBuffer; @@ -188,7 +195,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) { return file; } - return NULL; + return nullptr; } } // end of namespace Wintermute diff --git a/engines/wintermute/base/file/base_file.h b/engines/wintermute/base/file/base_file.h index 82f6ce3554..8eda6d51d9 100644 --- a/engines/wintermute/base/file/base_file.h +++ b/engines/wintermute/base/file/base_file.h @@ -45,10 +45,10 @@ protected: uint32 _pos; uint32 _size; public: - virtual uint32 getSize() { + virtual uint32 getSize() const { return _size; }; - virtual uint32 getPos() { + virtual uint32 getPos() const { return _pos; }; virtual bool seek(uint32 pos, int whence = SEEK_SET) = 0; diff --git a/engines/wintermute/base/file/base_file_entry.cpp b/engines/wintermute/base/file/base_file_entry.cpp index b9805d78dd..1968da6f47 100644 --- a/engines/wintermute/base/file/base_file_entry.cpp +++ b/engines/wintermute/base/file/base_file_entry.cpp @@ -37,7 +37,7 @@ namespace Wintermute { Common::SeekableReadStream *BaseFileEntry::createReadStream() const { Common::SeekableReadStream *file = _package->getFilePointer(); if (!file) { - return NULL; + return nullptr; } bool compressed = (_compressedLength != 0); @@ -55,7 +55,7 @@ Common::SeekableReadStream *BaseFileEntry::createReadStream() const { ////////////////////////////////////////////////////////////////////////// BaseFileEntry::BaseFileEntry() { - _package = NULL; + _package = nullptr; _length = _compressedLength = _offset = _flags = 0; _filename = ""; @@ -67,7 +67,7 @@ BaseFileEntry::BaseFileEntry() { ////////////////////////////////////////////////////////////////////////// BaseFileEntry::~BaseFileEntry() { - _package = NULL; // ref only + _package = nullptr; // ref only } } // end of namespace Wintermute diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp index 51a1558a7c..4434ed3951 100644 --- a/engines/wintermute/base/file/base_package.cpp +++ b/engines/wintermute/base/file/base_package.cpp @@ -157,7 +157,7 @@ PackageSet::PackageSet(Common::FSNode file, const Common::String &filename, bool pkg->_cd = stream->readByte(); pkg->_priority = hdr._priority; delete[] pkgName; - pkgName = NULL; + pkgName = nullptr; if (!hdr._masterIndex) { pkg->_cd = 0; // override CD to fixed disk @@ -186,7 +186,7 @@ PackageSet::PackageSet(Common::FSNode file, const Common::String &filename, bool Common::String upcName = name; upcName.toUppercase(); delete[] name; - name = NULL; + name = nullptr; offset = stream->readUint32LE(); offset += absoluteOffset; @@ -270,7 +270,7 @@ Common::SeekableReadStream *PackageSet::createReadStreamForMember(const Common:: if (it != _files.end()) { return it->_value->createReadStream(); } - return NULL; + return nullptr; } } // end of namespace Wintermute diff --git a/engines/wintermute/base/file/base_resources.cpp b/engines/wintermute/base/file/base_resources.cpp deleted file mode 100644 index 0b32cb0c4f..0000000000 --- a/engines/wintermute/base/file/base_resources.cpp +++ /dev/null @@ -1,2830 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#include "engines/wintermute/base/file/base_resources.h" -#include "common/str.h" -#include "common/memstream.h" - -namespace Wintermute { - -unsigned char invalid[] = { - 0x42, 0x4d, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -} ; - -unsigned char invaliddebug[] = { - 0x42, 0x4d, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, - 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xdc, 0xc0, 0x00, 0xf0, 0xca, 0xa6, 0x00, 0x00, 0x20, - 0x40, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x00, 0x20, - 0xc0, 0x00, 0x00, 0x20, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, - 0x40, 0x00, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40, - 0xc0, 0x00, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x60, - 0x40, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x60, 0xa0, 0x00, 0x00, 0x60, - 0xc0, 0x00, 0x00, 0x60, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, - 0x40, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80, - 0xc0, 0x00, 0x00, 0x80, 0xe0, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x20, 0x00, 0x00, 0xa0, - 0x40, 0x00, 0x00, 0xa0, 0x60, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0xa0, 0xa0, 0x00, 0x00, 0xa0, - 0xc0, 0x00, 0x00, 0xa0, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, - 0x40, 0x00, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0, - 0xc0, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0x00, 0xe0, - 0x40, 0x00, 0x00, 0xe0, 0x60, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x00, 0xe0, 0xa0, 0x00, 0x00, 0xe0, - 0xc0, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, - 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xa0, 0x00, 0x40, 0x00, - 0xc0, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x20, 0x20, 0x00, 0x40, 0x20, - 0x40, 0x00, 0x40, 0x20, 0x60, 0x00, 0x40, 0x20, 0x80, 0x00, 0x40, 0x20, 0xa0, 0x00, 0x40, 0x20, - 0xc0, 0x00, 0x40, 0x20, 0xe0, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x40, 0x40, - 0x40, 0x00, 0x40, 0x40, 0x60, 0x00, 0x40, 0x40, 0x80, 0x00, 0x40, 0x40, 0xa0, 0x00, 0x40, 0x40, - 0xc0, 0x00, 0x40, 0x40, 0xe0, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x60, 0x20, 0x00, 0x40, 0x60, - 0x40, 0x00, 0x40, 0x60, 0x60, 0x00, 0x40, 0x60, 0x80, 0x00, 0x40, 0x60, 0xa0, 0x00, 0x40, 0x60, - 0xc0, 0x00, 0x40, 0x60, 0xe0, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0x80, 0x20, 0x00, 0x40, 0x80, - 0x40, 0x00, 0x40, 0x80, 0x60, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0xa0, 0x00, 0x40, 0x80, - 0xc0, 0x00, 0x40, 0x80, 0xe0, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40, 0xa0, 0x20, 0x00, 0x40, 0xa0, - 0x40, 0x00, 0x40, 0xa0, 0x60, 0x00, 0x40, 0xa0, 0x80, 0x00, 0x40, 0xa0, 0xa0, 0x00, 0x40, 0xa0, - 0xc0, 0x00, 0x40, 0xa0, 0xe0, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x40, 0xc0, 0x20, 0x00, 0x40, 0xc0, - 0x40, 0x00, 0x40, 0xc0, 0x60, 0x00, 0x40, 0xc0, 0x80, 0x00, 0x40, 0xc0, 0xa0, 0x00, 0x40, 0xc0, - 0xc0, 0x00, 0x40, 0xc0, 0xe0, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x40, 0xe0, 0x20, 0x00, 0x40, 0xe0, - 0x40, 0x00, 0x40, 0xe0, 0x60, 0x00, 0x40, 0xe0, 0x80, 0x00, 0x40, 0xe0, 0xa0, 0x00, 0x40, 0xe0, - 0xc0, 0x00, 0x40, 0xe0, 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00, - 0x40, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xa0, 0x00, 0x80, 0x00, - 0xc0, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, 0x20, 0x20, 0x00, 0x80, 0x20, - 0x40, 0x00, 0x80, 0x20, 0x60, 0x00, 0x80, 0x20, 0x80, 0x00, 0x80, 0x20, 0xa0, 0x00, 0x80, 0x20, - 0xc0, 0x00, 0x80, 0x20, 0xe0, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x80, 0x40, - 0x40, 0x00, 0x80, 0x40, 0x60, 0x00, 0x80, 0x40, 0x80, 0x00, 0x80, 0x40, 0xa0, 0x00, 0x80, 0x40, - 0xc0, 0x00, 0x80, 0x40, 0xe0, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x60, 0x20, 0x00, 0x80, 0x60, - 0x40, 0x00, 0x80, 0x60, 0x60, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0xa0, 0x00, 0x80, 0x60, - 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x20, 0x00, 0x80, 0x80, - 0x40, 0x00, 0x80, 0x80, 0x60, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0xa0, 0x00, 0x80, 0x80, - 0xc0, 0x00, 0x80, 0x80, 0xe0, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80, 0xa0, 0x20, 0x00, 0x80, 0xa0, - 0x40, 0x00, 0x80, 0xa0, 0x60, 0x00, 0x80, 0xa0, 0x80, 0x00, 0x80, 0xa0, 0xa0, 0x00, 0x80, 0xa0, - 0xc0, 0x00, 0x80, 0xa0, 0xe0, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x00, 0x80, 0xc0, - 0x40, 0x00, 0x80, 0xc0, 0x60, 0x00, 0x80, 0xc0, 0x80, 0x00, 0x80, 0xc0, 0xa0, 0x00, 0x80, 0xc0, - 0xc0, 0x00, 0x80, 0xc0, 0xe0, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x80, 0xe0, 0x20, 0x00, 0x80, 0xe0, - 0x40, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x80, 0xe0, 0x80, 0x00, 0x80, 0xe0, 0xa0, 0x00, 0x80, 0xe0, - 0xc0, 0x00, 0x80, 0xe0, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x20, 0x00, 0xc0, 0x00, - 0x40, 0x00, 0xc0, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xa0, 0x00, 0xc0, 0x00, - 0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, 0x20, 0x20, 0x00, 0xc0, 0x20, - 0x40, 0x00, 0xc0, 0x20, 0x60, 0x00, 0xc0, 0x20, 0x80, 0x00, 0xc0, 0x20, 0xa0, 0x00, 0xc0, 0x20, - 0xc0, 0x00, 0xc0, 0x20, 0xe0, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x20, 0x00, 0xc0, 0x40, - 0x40, 0x00, 0xc0, 0x40, 0x60, 0x00, 0xc0, 0x40, 0x80, 0x00, 0xc0, 0x40, 0xa0, 0x00, 0xc0, 0x40, - 0xc0, 0x00, 0xc0, 0x40, 0xe0, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x60, 0x20, 0x00, 0xc0, 0x60, - 0x40, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x80, 0x00, 0xc0, 0x60, 0xa0, 0x00, 0xc0, 0x60, - 0xc0, 0x00, 0xc0, 0x60, 0xe0, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0x80, 0x20, 0x00, 0xc0, 0x80, - 0x40, 0x00, 0xc0, 0x80, 0x60, 0x00, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0x80, 0xa0, 0x00, 0xc0, 0x80, - 0xc0, 0x00, 0xc0, 0x80, 0xe0, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0, 0xa0, 0x20, 0x00, 0xc0, 0xa0, - 0x40, 0x00, 0xc0, 0xa0, 0x60, 0x00, 0xc0, 0xa0, 0x80, 0x00, 0xc0, 0xa0, 0xa0, 0x00, 0xc0, 0xa0, - 0xc0, 0x00, 0xc0, 0xa0, 0xe0, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0x20, 0x00, 0xc0, 0xc0, - 0x40, 0x00, 0xc0, 0xc0, 0x60, 0x00, 0xc0, 0xc0, 0x80, 0x00, 0xc0, 0xc0, 0xa0, 0x00, 0xf0, 0xfb, - 0xff, 0x00, 0xa4, 0xa0, 0xa0, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, - 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0xf9, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, - 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9 -} ; - -unsigned char systemfont[] = { - 0x42, 0x4d, 0x36, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x70, 0x0b, 0x00, 0x00, 0x70, 0x0b, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x80, 0x80, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, - 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, - 0x02, 0x00, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, - 0x02, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, - 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, - 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, - 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -} ; - -Common::SeekableReadStream *BaseResources::getFile(const Common::String &filename) { - if (scumm_stricmp(filename.c_str(), "invalid.bmp") == 0) { - return new Common::MemoryReadStream(invalid, sizeof(invalid), DisposeAfterUse::NO); - } else if (scumm_stricmp(filename.c_str(), "invalid_debug.bmp") == 0) { - return new Common::MemoryReadStream(invaliddebug, sizeof(invalid), DisposeAfterUse::NO); - } else if (scumm_stricmp(filename.c_str(), "syste_font.bmp") == 0) { - return new Common::MemoryReadStream(systemfont, sizeof(invalid), DisposeAfterUse::NO); - } - return NULL; -} - -bool BaseResources::hasFile(const Common::String &filename) { - if (scumm_stricmp(filename.c_str(), "invalid.bmp") == 0) { - return true; - } else if (scumm_stricmp(filename.c_str(), "invalid_debug.bmp") == 0) { - return true; - } else if (scumm_stricmp(filename.c_str(), "syste_font.bmp") == 0) { - return true; - } - return false; -} - -} // end of namespace Wintermute diff --git a/engines/wintermute/base/file/base_save_thumb_file.cpp b/engines/wintermute/base/file/base_save_thumb_file.cpp index 94d3e5a94e..2c4ddf4875 100644 --- a/engines/wintermute/base/file/base_save_thumb_file.cpp +++ b/engines/wintermute/base/file/base_save_thumb_file.cpp @@ -38,7 +38,7 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////////// BaseSaveThumbFile::BaseSaveThumbFile() { - _data = NULL; + _data = nullptr; } @@ -99,7 +99,7 @@ bool BaseSaveThumbFile::open(const Common::String &filename) { ////////////////////////////////////////////////////////////////////////// bool BaseSaveThumbFile::close() { delete[] _data; - _data = NULL; + _data = nullptr; _pos = 0; _size = 0; diff --git a/engines/wintermute/base/font/base_font.cpp b/engines/wintermute/base/font/base_font.cpp index 87dd3da5a3..e3c8827254 100644 --- a/engines/wintermute/base/font/base_font.cpp +++ b/engines/wintermute/base/font/base_font.cpp @@ -89,7 +89,7 @@ BaseFont *BaseFont::createFromFile(BaseGame *gameRef, const Common::String &file if (font) { if (DID_FAIL(font->loadFile(filename))) { delete font; - return NULL; + return nullptr; } } return font; @@ -98,7 +98,7 @@ BaseFont *BaseFont::createFromFile(BaseGame *gameRef, const Common::String &file if (font) { if (DID_FAIL(font->loadFile(filename))) { delete font; - return NULL; + return nullptr; } } return font; @@ -119,7 +119,7 @@ bool BaseFont::isTrueType(BaseGame *gameRef, const Common::String &filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { return false; } diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp index 55f46c476b..af66cbb89f 100644 --- a/engines/wintermute/base/font/base_font_bitmap.cpp +++ b/engines/wintermute/base/font/base_font_bitmap.cpp @@ -49,8 +49,8 @@ IMPLEMENT_PERSISTENT(BaseFontBitmap, false) ////////////////////////////////////////////////////////////////////// BaseFontBitmap::BaseFontBitmap(BaseGame *inGame) : BaseFont(inGame) { - _subframe = NULL; - _sprite = NULL; + _subframe = nullptr; + _sprite = nullptr; _widthsFrame = 0; memset(_widths, 0, NUM_CHARACTERS); _tileWidth = _tileHeight = _numColumns = 0; @@ -64,8 +64,8 @@ BaseFontBitmap::BaseFontBitmap(BaseGame *inGame) : BaseFont(inGame) { BaseFontBitmap::~BaseFontBitmap() { delete _subframe; delete _sprite; - _subframe = NULL; - _sprite = NULL; + _subframe = nullptr; + _sprite = nullptr; } @@ -112,7 +112,7 @@ int BaseFontBitmap::textHeightDraw(const byte *text, int x, int y, int width, TT return 0; } - if (text == NULL || text[0] == '\0') { + if (text == nullptr || text[0] == '\0') { return _tileHeight; } @@ -273,7 +273,7 @@ void BaseFontBitmap::drawChar(byte c, int x, int y) { ////////////////////////////////////////////////////////////////////// bool BaseFontBitmap::loadFile(const Common::String &filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "BaseFontBitmap::LoadFile failed for file '%s'", filename.c_str()); return STATUS_FAILED; } @@ -347,8 +347,8 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) { int i; int r = 255, g = 255, b = 255; bool custoTrans = false; - char *surfaceFile = NULL; - char *spriteFile = NULL; + char *surfaceFile = nullptr; + char *spriteFile = nullptr; bool autoWidth = false; int spaceWidth = 0; @@ -428,16 +428,16 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) { return STATUS_FAILED; } - if (spriteFile != NULL) { + if (spriteFile != nullptr) { delete _sprite; _sprite = new BaseSprite(_gameRef, this); if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) { delete _sprite; - _sprite = NULL; + _sprite = nullptr; } } - if (surfaceFile != NULL && !_sprite) { + if (surfaceFile != nullptr && !_sprite) { _subframe = new BaseSubFrame(_gameRef); if (custoTrans) { _subframe->setSurface(surfaceFile, false, r, g, b); @@ -447,7 +447,7 @@ bool BaseFontBitmap::loadBuffer(byte *buffer) { } - if (((_subframe == NULL || _subframe->_surface == NULL) && _sprite == NULL) || _numColumns == 0 || _tileWidth == 0 || _tileHeight == 0) { + if (((_subframe == nullptr || _subframe->_surface == nullptr) && _sprite == nullptr) || _numColumns == 0 || _tileWidth == 0 || _tileHeight == 0) { _gameRef->LOG(0, "Incomplete font definition"); return STATUS_FAILED; } @@ -530,7 +530,7 @@ int BaseFontBitmap::getCharWidth(byte index) { ////////////////////////////////////////////////////////////////////////// bool BaseFontBitmap::getWidths() { - BaseSurface *surf = NULL; + BaseSurface *surf = nullptr; if (_sprite) { if (_widthsFrame >= 0 && _widthsFrame < (int32)_sprite->_frames.size()) { @@ -539,7 +539,7 @@ bool BaseFontBitmap::getWidths() { } } } - if (surf == NULL && _subframe) { + if (surf == nullptr && _subframe) { surf = _subframe->_surface; } if (!surf || DID_FAIL(surf->startPixelOp())) { diff --git a/engines/wintermute/base/font/base_font_storage.cpp b/engines/wintermute/base/font/base_font_storage.cpp index 8128ffe897..6a625f30ae 100644 --- a/engines/wintermute/base/font/base_font_storage.cpp +++ b/engines/wintermute/base/font/base_font_storage.cpp @@ -72,7 +72,7 @@ bool BaseFontStorage::initLoop() { ////////////////////////////////////////////////////////////////////////// BaseFont *BaseFontStorage::addFont(const Common::String &filename) { if (!filename.size()) { - return NULL; + return nullptr; } for (uint32 i = 0; i < _fonts.size(); i++) { @@ -84,11 +84,11 @@ BaseFont *BaseFontStorage::addFont(const Common::String &filename) { /* BaseFont* font = new BaseFont(_gameRef); - if (!font) return NULL; + if (!font) return nullptr; if (DID_FAIL(font->loadFile(filename))) { delete font; - return NULL; + return nullptr; } else { font->_refCount = 1; diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp index f236329fcd..7f1ff340d2 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -38,6 +38,7 @@ #include "engines/wintermute/wintermute.h" #include "graphics/fonts/ttf.h" #include "graphics/fontman.h" +#include "common/unzip.h" #include <limits.h> namespace Wintermute { @@ -49,13 +50,13 @@ BaseFontTT::BaseFontTT(BaseGame *inGame) : BaseFont(inGame) { _fontHeight = 12; _isBold = _isItalic = _isUnderline = _isStriked = false; - _fontFile = NULL; - _font = NULL; - _fallbackFont = NULL; - _deletableFont = NULL; + _fontFile = nullptr; + _font = nullptr; + _fallbackFont = nullptr; + _deletableFont = nullptr; for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - _cachedTexts[i] = NULL; + _cachedTexts[i] = nullptr; } _lineHeight = 0; @@ -72,10 +73,10 @@ BaseFontTT::~BaseFontTT(void) { _layers.clear(); delete[] _fontFile; - _fontFile = NULL; + _fontFile = nullptr; delete _deletableFont; - _font = NULL; + _font = nullptr; } @@ -85,7 +86,7 @@ void BaseFontTT::clearCache() { if (_cachedTexts[i]) { delete _cachedTexts[i]; } - _cachedTexts[i] = NULL; + _cachedTexts[i] = nullptr; } } @@ -95,13 +96,13 @@ void BaseFontTT::initLoop() { if (_gameRef->_constrainedMemory) { // purge all cached images not used in the last frame for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - if (_cachedTexts[i] == NULL) { + if (_cachedTexts[i] == nullptr) { continue; } if (!_cachedTexts[i]->_marked) { delete _cachedTexts[i]; - _cachedTexts[i] = NULL; + _cachedTexts[i] = nullptr; } else { _cachedTexts[i]->_marked = false; } @@ -150,7 +151,7 @@ int BaseFontTT::getTextHeight(byte *text, int width) { ////////////////////////////////////////////////////////////////////////// void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) { - if (text == NULL || strcmp((const char *)text, "") == 0) { + if (text == nullptr || strcmp((const char *)text, "") == 0) { return; } @@ -162,7 +163,7 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign // HACK: J.U.L.I.A. uses CP1252, we need to fix that, // And we still don't have any UTF8-support. if (_gameRef->_textEncoding != TEXT_UTF8) { - textStr = StringUtil::ansiToWide((char *)text); + textStr = StringUtil::ansiToWide((const char *)text); } if (maxLength >= 0 && textStr.size() > (uint32)maxLength) { @@ -173,25 +174,25 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign BaseRenderer *renderer = _gameRef->_renderer; // find cached surface, if exists - int minPriority = INT_MAX; + uint32 minUseTime = UINT_MAX; int minIndex = -1; - BaseSurface *surface = NULL; + BaseSurface *surface = nullptr; int textOffset = 0; for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - if (_cachedTexts[i] == NULL) { - minPriority = 0; + if (_cachedTexts[i] == nullptr) { + minUseTime = 0; minIndex = i; } else { if (_cachedTexts[i]->_text == textStr && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight && _cachedTexts[i]->_maxLength == maxLength) { surface = _cachedTexts[i]->_surface; textOffset = _cachedTexts[i]->_textOffset; - _cachedTexts[i]->_priority++; _cachedTexts[i]->_marked = true; + _cachedTexts[i]->_lastUsed = g_system->getMillis(); break; } else { - if (_cachedTexts[i]->_priority < minPriority) { - minPriority = _cachedTexts[i]->_priority; + if (_cachedTexts[i]->_lastUsed < minUseTime) { + minUseTime = _cachedTexts[i]->_lastUsed; minIndex = i; } } @@ -204,7 +205,7 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign surface = renderTextToTexture(textStr, width, align, maxHeight, textOffset); if (surface) { // write surface to cache - if (_cachedTexts[minIndex] != NULL) { + if (_cachedTexts[minIndex] != nullptr) { delete _cachedTexts[minIndex]; } _cachedTexts[minIndex] = new BaseCachedTTFontText; @@ -214,10 +215,10 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign _cachedTexts[minIndex]->_width = width; _cachedTexts[minIndex]->_maxHeight = maxHeight; _cachedTexts[minIndex]->_maxLength = maxLength; - _cachedTexts[minIndex]->_priority = 1; _cachedTexts[minIndex]->_text = textStr; _cachedTexts[minIndex]->_textOffset = textOffset; _cachedTexts[minIndex]->_marked = true; + _cachedTexts[minIndex]->_lastUsed = g_system->getMillis(); } } @@ -254,7 +255,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, lines.pop_back(); } if (lines.size() == 0) { - return NULL; + return nullptr; } Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; @@ -303,7 +304,7 @@ int BaseFontTT::getLetterHeight() { ////////////////////////////////////////////////////////////////////// bool BaseFontTT::loadFile(const Common::String &filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "BaseFontTT::LoadFile failed for file '%s'", filename.c_str()); return STATUS_FAILED; } @@ -421,7 +422,7 @@ bool BaseFontTT::loadBuffer(byte *buffer) { _layers.add(layer); } else { delete layer; - layer = NULL; + layer = nullptr; cmd = PARSERR_TOKENNOTFOUND; } } @@ -527,9 +528,9 @@ bool BaseFontTT::persist(BasePersistenceManager *persistMgr) { if (!persistMgr->getIsSaving()) { for (int i = 0; i < NUM_CACHED_TEXTS; i++) { - _cachedTexts[i] = NULL; + _cachedTexts[i] = nullptr; } - _fallbackFont = _font = _deletableFont = NULL; + _fallbackFont = _font = _deletableFont = nullptr; } return STATUS_OK; @@ -546,26 +547,52 @@ bool BaseFontTT::initFont() { if (!_fontFile) { return STATUS_FAILED; } - +#ifdef USE_FREETYPE2 Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(_fontFile); if (!file) { - //TODO: Try to fallback from Arial to FreeSans - /* - // the requested font file is not in wme file space; try loading a system font - AnsiString fontFileName = PathUtil::combine(BasePlatform::getSystemFontPath(), PathUtil::getFileName(_fontFile)); - file = BaseFileManager::getEngineInstance()->openFile(fontFileName.c_str(), false); - if (!file) { - _gameRef->LOG(0, "Error loading TrueType font '%s'", _fontFile); - //return STATUS_FAILED; - }*/ + if (Common::String(_fontFile) != "arial.ttf") { + warning("%s has no replacement font yet, using FreeSans for now (if available)", _fontFile); + } + // Fallback1: Try to find FreeSans.ttf + file = SearchMan.createReadStreamForMember("FreeSans.ttf"); } if (file) { -#ifdef USE_FREETYPE2 _deletableFont = Graphics::loadTTFFont(*file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72). _font = _deletableFont; -#endif + BaseFileManager::getEngineInstance()->closeFile(file); + file = nullptr; + } + + // Fallback2: Try to find ScummModern.zip, and get the font from there: + if (!_font) { + Common::SeekableReadStream *themeFile = SearchMan.createReadStreamForMember("scummmodern.zip"); + if (themeFile) { + Common::Archive *themeArchive = Common::makeZipArchive(themeFile); + if (themeArchive->hasFile("FreeSans.ttf")) { + file = nullptr; + file = themeArchive->createReadStreamForMember("FreeSans.ttf"); + _deletableFont = Graphics::loadTTFFont(*file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72). + _font = _deletableFont; + } + // We're not using BaseFileManager, so clean up after ourselves: + delete file; + file = nullptr; + delete themeArchive; + themeArchive = nullptr; + } } + + // Fallback3: Try to ask FontMan for the FreeSans.ttf ScummModern.zip uses: + if (!_font) { + // Really not desireable, as we will get a font with dpi-72 then + Common::String fontName = Common::String::format("%s-%s@%d", "FreeSans.ttf", "ASCII", _fontHeight); + warning("Looking for %s", fontName.c_str()); + _font = FontMan.getFontByName(fontName); + } +#endif // USE_FREETYPE2 + + // Fallback4: Just use the Big GUI-font. (REALLY undesireable) if (!_font) { _font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); warning("BaseFontTT::InitFont - Couldn't load font: %s", _fontFile); @@ -600,7 +627,7 @@ void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight TextLine *line = (*it); textWidth = MAX(textWidth, line->GetWidth()); delete line; - line = NULL; + line = nullptr; }*/ } diff --git a/engines/wintermute/base/font/base_font_truetype.h b/engines/wintermute/base/font/base_font_truetype.h index 02dca7439f..ba4aac9380 100644 --- a/engines/wintermute/base/font/base_font_truetype.h +++ b/engines/wintermute/base/font/base_font_truetype.h @@ -54,15 +54,16 @@ private: int _priority; int _textOffset; bool _marked; + uint32 _lastUsed; BaseCachedTTFontText() { //_text = L""; _text = ""; _width = _maxHeight = _maxLength = -1; _align = TAL_LEFT; - _surface = NULL; - _priority = -1; + _surface = nullptr; _textOffset = 0; + _lastUsed = 0; _marked = false; } diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp index 4b15d563ed..75de95128f 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -43,10 +43,10 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////// BaseImage::BaseImage() { _fileManager = BaseFileManager::getEngineInstance(); - _palette = NULL; - _surface = NULL; - _decoder = NULL; - _deletableSurface = NULL; + _palette = nullptr; + _surface = nullptr; + _decoder = nullptr; + _deletableSurface = nullptr; } @@ -105,7 +105,7 @@ void BaseImage::copyFrom(const Graphics::Surface *surface) { } ////////////////////////////////////////////////////////////////////////// -bool BaseImage::saveBMPFile(const char *filename) const { +bool BaseImage::saveBMPFile(const Common::String &filename) const { warning("BaseImage::saveBMPFile - stubbed"); // TODO return false; } @@ -118,7 +118,7 @@ bool BaseImage::resize(int newWidth, int newHeight) { if (_deletableSurface) { _deletableSurface->free(); delete _deletableSurface; - _deletableSurface = NULL; + _deletableSurface = nullptr; } _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); temp.free(); @@ -222,7 +222,7 @@ bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) { if (_deletableSurface) { _deletableSurface->free(); delete _deletableSurface; - _deletableSurface = NULL; + _deletableSurface = nullptr; } _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight); return true; diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h index 6d01b84184..017305e5d0 100644 --- a/engines/wintermute/base/gfx/base_image.h +++ b/engines/wintermute/base/gfx/base_image.h @@ -55,7 +55,7 @@ public: byte getAlphaAt(int x, int y) const; bool writeBMPToStream(Common::WriteStream *stream) const; bool resize(int newWidth, int newHeight); - bool saveBMPFile(const char *filename) const; + bool saveBMPFile(const Common::String &filename) const; bool copyFrom(BaseImage *origImage, int newWidth = 0, int newHeight = 0); void copyFrom(const Graphics::Surface *surface); private: diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp index e7ffc14c25..c20881e425 100644 --- a/engines/wintermute/base/gfx/base_renderer.cpp +++ b/engines/wintermute/base/gfx/base_renderer.cpp @@ -29,6 +29,7 @@ #include "engines/wintermute/base/base_active_rect.h" #include "engines/wintermute/base/gfx/base_renderer.h" #include "engines/wintermute/base/gfx/base_surface.h" +#include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/base_sub_frame.h" #include "engines/wintermute/base/base_region.h" #include "engines/wintermute/platform_osystem.h" @@ -56,7 +57,7 @@ BaseRenderer::BaseRenderer(BaseGame *inGame) : BaseClass(inGame) { _loadImageName = ""; _saveImageName = ""; - _saveLoadImage = NULL; + _saveLoadImage = nullptr; _loadInProgress = false; _hasDrawnSaveLoadImage = false; @@ -132,24 +133,24 @@ void BaseRenderer::initSaveLoad(bool isSaving, bool quickSave) { if (isSaving && !quickSave) { delete _saveLoadImage; - _saveLoadImage = NULL; + _saveLoadImage = nullptr; if (_saveImageName.size()) { _saveLoadImage = createSurface(); if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) { delete _saveLoadImage; - _saveLoadImage = NULL; + _saveLoadImage = nullptr; } } } else { delete _saveLoadImage; - _saveLoadImage = NULL; + _saveLoadImage = nullptr; if (_loadImageName.size()) { _saveLoadImage = createSurface(); if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) { delete _saveLoadImage; - _saveLoadImage = NULL; + _saveLoadImage = nullptr; } } _loadInProgress = true; @@ -162,7 +163,7 @@ void BaseRenderer::endSaveLoad() { _indicatorWidthDrawn = 0; delete _saveLoadImage; - _saveLoadImage = NULL; + _saveLoadImage = nullptr; } void BaseRenderer::persistSaveLoadImages(BasePersistenceManager *persistMgr) { @@ -214,7 +215,7 @@ BaseObject *BaseRenderer::getObjectAt(int x, int y) { } } - return (BaseObject *)NULL; + return (BaseObject *)nullptr; } @@ -317,7 +318,7 @@ bool BaseRenderer::clipCursor() { ////////////////////////////////////////////////////////////////////////// bool BaseRenderer::unclipCursor() { /* - if (!_windowed) ::ClipCursor(NULL); + if (!_windowed) ::ClipCursor(nullptr); */ return STATUS_OK; } @@ -344,6 +345,22 @@ void BaseRenderer::addRectToList(BaseActiveRect *rect) { _rectList.push_back(rect); } +bool BaseRenderer::saveScreenShot(const Common::String &filename, int sizeX, int sizeY) { + BaseImage *image = takeScreenshot(); + if (image) { + if (sizeX != 0 && sizeY != 0) { + if (!DID_SUCCEED(image->resize(sizeX, sizeY))) { + delete image; + return false; + } + } + image->saveBMPFile(filename); + delete image; + return true; + } + return false; +} + ////////////////////////////////////////////////////////////////////////// bool BaseRenderer::displayIndicator() { if (!_indicatorDisplay || !_indicatorProgress) { diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h index 0475824464..5a24e0179a 100644 --- a/engines/wintermute/base/gfx/base_renderer.h +++ b/engines/wintermute/base/gfx/base_renderer.h @@ -61,6 +61,7 @@ public: * @return a BaseImage containing the current screen-buffer. */ virtual BaseImage *takeScreenshot() = 0; + virtual bool saveScreenShot(const Common::String &filename, int sizeX = 0, int sizeY = 0); virtual bool setViewport(int left, int top, int right, int bottom); virtual bool setViewport(Rect32 *rect); virtual Rect32 getViewPort() = 0; @@ -81,12 +82,13 @@ public: * @param g the green component to fade too. * @param b the blue component to fade too. * @param a the alpha component to fade too. - * @param rect the portion of the screen to fade (if NULL, the entire screen will be faded). + * @param rect the portion of the screen to fade (if nullptr, the entire screen will be faded). */ - virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL) = 0; - virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color); - virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1); - BaseRenderer(BaseGame *inGame = NULL); + virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = nullptr) = 0; + + virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color); // Unused outside indicator-display + virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1); // Unused outside indicator-display + BaseRenderer(BaseGame *inGame = nullptr); virtual ~BaseRenderer(); virtual bool setProjection() { return STATUS_OK; @@ -100,7 +102,7 @@ public: * @param g the green component to fill with. * @param b the blue component to fill with. */ - virtual bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL) = 0; + virtual bool fill(byte r, byte g, byte b, Common::Rect *rect = nullptr) = 0; virtual void onWindowChange(); virtual bool initRenderer(int width, int height, bool windowed); /** @@ -179,7 +181,7 @@ public: void setIndicator(int width, int height, int x, int y, uint32 color); void persistSaveLoadImages(BasePersistenceManager *persistMgr); void initSaveLoad(bool isSaving, bool quickSave = false); - void endSaveLoad(); + virtual void endSaveLoad(); void setLoadingScreen(const char *filename, int x, int y); void setSaveImage(const char *filename, int x, int y); diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index ee53c03e77..1ada900161 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -55,6 +55,7 @@ public: virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) = 0; virtual bool restore(); virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; virtual bool create(int width, int height); @@ -62,7 +63,7 @@ public: return STATUS_FAILED; } virtual bool putPixel(int x, int y, byte r, byte g, byte b, int a = -1); - virtual bool getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a = NULL); + virtual bool getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a = nullptr); virtual bool comparePixel(int x, int y, byte r, byte g, byte b, int a = -1); virtual bool startPixelOp(); virtual bool endPixelOp(); @@ -79,7 +80,7 @@ public: } Common::String getFileNameStr() { return _filename; } const char* getFileName() { return _filename.c_str(); } - //void SetWidth(int Width){ _width = Width; } + //void SetWidth(int Width) { _width = Width; } //void SetHeight(int Height){ _height = Height; } protected: bool _ckDefault; diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index 7970a25300..061f52776e 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -28,6 +28,7 @@ #include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" #include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" +#include "engines/wintermute/base/gfx/osystem/render_ticket.h" #include "engines/wintermute/base/base_surface_storage.h" #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/math/math_util.h" @@ -40,56 +41,6 @@ namespace Wintermute { -RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner), - _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) { - _colorMod = 0; - _mirror = TransparentSurface::FLIP_NONE; - if (mirrorX) { - _mirror |= TransparentSurface::FLIP_V; - } - if (mirrorY) { - _mirror |= TransparentSurface::FLIP_H; - } - if (surf) { - _surface = new Graphics::Surface(); - _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format); - assert(_surface->format.bytesPerPixel == 4); - // Get a clipped copy of the surface - for (int i = 0; i < _surface->h; i++) { - memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); - } - // Then scale it if necessary - if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { - TransparentSurface src(*_surface, false); - Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); - _surface->free(); - delete _surface; - _surface = temp; - } - } else { - _surface = NULL; - } -} - -RenderTicket::~RenderTicket() { - if (_surface) { - _surface->free(); - delete _surface; - } -} - -bool RenderTicket::operator==(RenderTicket &t) { - if ((t._srcRect != _srcRect) || - (t._dstRect != _dstRect) || - (t._mirror != _mirror) || - (t._owner != _owner) || - (t._hasAlpha != _hasAlpha) || - (t._colorMod != _colorMod)) { - return false; - } - return true; -} - BaseRenderer *makeOSystemRenderer(BaseGame *inGame) { return new BaseRenderOSystem(inGame); } @@ -100,16 +51,33 @@ BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { _blankSurface = new Graphics::Surface(); _drawNum = 1; _needsFlip = true; + _spriteBatch = false; + _batchNum = 0; + _skipThisFrame = false; + _previousTicket = nullptr; _borderLeft = _borderRight = _borderTop = _borderBottom = 0; _ratioX = _ratioY = 1.0f; setAlphaMod(255); setColorMod(255, 255, 255); - _dirtyRect = NULL; + _dirtyRect = nullptr; + _disableDirtyRects = false; + if (ConfMan.hasKey("dirty_rects")) { + _disableDirtyRects = !ConfMan.getBool("dirty_rects"); + } } ////////////////////////////////////////////////////////////////////////// BaseRenderOSystem::~BaseRenderOSystem() { + RenderQueueIterator it = _renderQueue.begin(); + while (it != _renderQueue.end()) { + RenderTicket *ticket = *it; + it = _renderQueue.erase(it); + delete ticket; + } + + delete _dirtyRect; + _renderSurface->free(); delete _renderSurface; _blankSurface->free(); @@ -198,6 +166,14 @@ bool BaseRenderOSystem::indicatorFlip() { } bool BaseRenderOSystem::flip() { + if (_skipThisFrame) { + _skipThisFrame = false; + delete _dirtyRect; + _dirtyRect = nullptr; + g_system->updateScreen(); + _needsFlip = false; + return true; + } if (!_disableDirtyRects) { drawTickets(); } else { @@ -220,7 +196,7 @@ bool BaseRenderOSystem::flip() { } // g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); delete _dirtyRect; - _dirtyRect = NULL; + _dirtyRect = nullptr; g_system->updateScreen(); _needsFlip = false; } @@ -259,14 +235,6 @@ void BaseRenderOSystem::fade(uint16 alpha) { ////////////////////////////////////////////////////////////////////////// void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) { - // This particular warning is rather messy, as this function is called a ton, - // thus we avoid printing it more than once. - - // TODO: Add fading with dirty rects. - if (!_disableDirtyRects) { - warning("BaseRenderOSystem::FadeToColor - Breaks when using dirty rects"); - } - Common::Rect fillRect; if (rect) { @@ -294,7 +262,7 @@ void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect Common::Rect sizeRect(fillRect); sizeRect.translate(-fillRect.top, -fillRect.left); surf.fillRect(fillRect, col); - drawSurface(NULL, &surf, &sizeRect, &fillRect, false, false); + drawSurface(nullptr, &surf, &sizeRect, &fillRect, false, false); surf.free(); //SDL_SetRenderDrawColor(_renderer, r, g, b, a); @@ -307,22 +275,38 @@ Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const { } void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) { + // Start searching from the beginning for the first and second items (since it's empty the first time around + // then keep incrementing the start-position, to avoid comparing against already used tickets. + if (_drawNum == 0 || _drawNum == 1) { + _lastAddedTicket = _renderQueue.begin(); + } + // Skip rects that are completely outside the screen: if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) { return; } if (owner) { // Fade-tickets are owner-less - RenderTicket compare(owner, NULL, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); + RenderTicket compare(owner, nullptr, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); + compare._batchNum = _batchNum; + if (_spriteBatch) { + _batchNum++; + } compare._colorMod = _colorMod; RenderQueueIterator it; - for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { - if ((*it)->_owner == owner && *(*it) == compare && (*it)->_isValid) { - (*it)->_colorMod = _colorMod; + // Avoid calling end() and operator* every time, when potentially going through + // LOTS of tickets. + RenderQueueIterator endIterator = _renderQueue.end(); + RenderTicket *compareTicket = nullptr; + for (it = _lastAddedTicket; it != endIterator; ++it) { + compareTicket = *it; + if (*(compareTicket) == compare && compareTicket->_isValid) { + compareTicket->_colorMod = _colorMod; if (_disableDirtyRects) { - drawFromSurface(*it, NULL); + drawFromSurface(compareTicket); } else { - drawFromTicket(*it); + drawFromTicket(compareTicket); + _previousTicket = compareTicket; } return; } @@ -332,10 +316,50 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S ticket->_colorMod = _colorMod; if (!_disableDirtyRects) { drawFromTicket(ticket); + _previousTicket = ticket; } else { ticket->_wantsDraw = true; _renderQueue.push_back(ticket); - drawFromSurface(ticket, NULL); + } +} + +void BaseRenderOSystem::repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY) { + if (_previousTicket && _lastAddedTicket != _renderQueue.end()) { + RenderTicket *origTicket = _previousTicket; + + // Make sure drawSurface WILL start from the correct _lastAddedTicket + if (*_lastAddedTicket != origTicket) { + RenderQueueIterator it; + RenderQueueIterator endIterator = _renderQueue.end(); + for (it = _renderQueue.begin(); it != endIterator; ++it) { + if ((*it) == _previousTicket) { + _lastAddedTicket = it; + break; + } + } + } + Common::Rect srcRect(0, 0, 0, 0); + srcRect.setWidth(origTicket->getSrcRect()->width()); + srcRect.setHeight(origTicket->getSrcRect()->height()); + + Common::Rect dstRect = origTicket->_dstRect; + int initLeft = dstRect.left; + int initRight = dstRect.right; + + for (int i = 0; i < numTimesY; i++) { + if (i == 0) { + dstRect.translate(offsetX, 0); + } + for (int j = (i == 0 ? 1 : 0); j < numTimesX; j++) { + drawSurface(origTicket->_owner, origTicket->getSurface(), &srcRect, &dstRect, false, false); + dstRect.translate(offsetX, 0); + } + dstRect.left = initLeft; + dstRect.right = initRight; + dstRect.translate(0, offsetY); + } + } else { + error("Repeat-draw failed (did you forget to draw something before this?)"); } } @@ -363,28 +387,31 @@ void BaseRenderOSystem::drawFromTicket(RenderTicket *renderTicket) { renderTicket->_drawNum = _drawNum++; _renderQueue.push_back(renderTicket); addDirtyRect(renderTicket->_dstRect); + ++_lastAddedTicket; } else { // Before something - Common::List<RenderTicket *>::iterator pos; + RenderQueueIterator pos; for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) { if ((*pos)->_drawNum >= _drawNum) { break; } } _renderQueue.insert(pos, renderTicket); - Common::List<RenderTicket *>::iterator it; renderTicket->_drawNum = _drawNum++; // Increment the following tickets, so they still are in line + RenderQueueIterator it; for (it = pos; it != _renderQueue.end(); ++it) { (*it)->_drawNum++; (*it)->_wantsDraw = false; } addDirtyRect(renderTicket->_dstRect); + _lastAddedTicket = pos; } } else { // Was drawn last round, still in the same order if (_drawNum == renderTicket->_drawNum) { _drawNum++; + ++_lastAddedTicket; } else { // Remove the ticket from the list RenderQueueIterator it = _renderQueue.begin(); @@ -421,9 +448,12 @@ void BaseRenderOSystem::addDirtyRect(const Common::Rect &rect) { void BaseRenderOSystem::drawTickets() { RenderQueueIterator it = _renderQueue.begin(); // Clean out the old tickets - int decrement = 0; + // Note: We draw invalid tickets too, otherwise we wouldn't be honouring + // the draw request they obviously made BEFORE becoming invalid, either way + // we have a copy of their data, so their invalidness won't affect us. + uint32 decrement = 0; while (it != _renderQueue.end()) { - if ((*it)->_wantsDraw == false || (*it)->_isValid == false) { + if ((*it)->_wantsDraw == false) { RenderTicket *ticket = *it; addDirtyRect((*it)->_dstRect); it = _renderQueue.erase(it); @@ -435,6 +465,12 @@ void BaseRenderOSystem::drawTickets() { } } if (!_dirtyRect || _dirtyRect->width() == 0 || _dirtyRect->height() == 0) { + it = _renderQueue.begin(); + while (it != _renderQueue.end()) { + RenderTicket *ticket = *it; + ticket->_wantsDraw = false; + ++it; + } return; } // The color-mods are stored in the RenderTickets on add, since we set that state again during @@ -447,7 +483,7 @@ void BaseRenderOSystem::drawTickets() { for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { RenderTicket *ticket = *it; assert(ticket->_drawNum == _drawNum++); - if (ticket->_isValid && ticket->_dstRect.intersects(*_dirtyRect)) { + if (ticket->_dstRect.intersects(*_dirtyRect)) { // dstClip is the area we want redrawn. Common::Rect dstClip(ticket->_dstRect); // reduce it to the dirty rect @@ -460,7 +496,7 @@ void BaseRenderOSystem::drawTickets() { dstClip.translate(-offsetX, -offsetY); _colorMod = ticket->_colorMod; - drawFromSurface(ticket->getSurface(), &ticket->_srcRect, &pos, &dstClip, ticket->_mirror); + drawFromSurface(ticket, &pos, &dstClip); _needsFlip = true; } // Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldnt become clear-color) @@ -470,46 +506,40 @@ void BaseRenderOSystem::drawTickets() { // Revert the colorMod-state. _colorMod = oldColorMod; + + it = _renderQueue.begin(); + // Clean out the old tickets + decrement = 0; + while (it != _renderQueue.end()) { + if ((*it)->_isValid == false) { + RenderTicket *ticket = *it; + addDirtyRect((*it)->_dstRect); + it = _renderQueue.erase(it); + delete ticket; + decrement++; + } else { + (*it)->_drawNum -= decrement; + ++it; + } + } + } // Replacement for SDL2's SDL_RenderCopy -void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect) { - TransparentSurface src(*ticket->getSurface(), false); - bool doDelete = false; - if (!clipRect) { - doDelete = true; - clipRect = new Common::Rect(); - clipRect->setWidth(ticket->getSurface()->w); - clipRect->setHeight(ticket->getSurface()->h); - } - - src._enableAlphaBlit = ticket->_hasAlpha; - src.blit(*_renderSurface, ticket->_dstRect.left, ticket->_dstRect.top, ticket->_mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); - if (doDelete) { - delete clipRect; - } +void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket) { + ticket->drawToSurface(_renderSurface); } -void BaseRenderOSystem::drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror) { - TransparentSurface src(*surf, false); - bool doDelete = false; - if (!clipRect) { - doDelete = true; - clipRect = new Common::Rect(); - clipRect->setWidth(surf->w); - clipRect->setHeight(surf->h); - } - src.blit(*_renderSurface, dstRect->left, dstRect->top, mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); - if (doDelete) { - delete clipRect; - } +void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *dstRect, Common::Rect *clipRect) { + ticket->drawToSurface(_renderSurface, dstRect, clipRect); } ////////////////////////////////////////////////////////////////////////// bool BaseRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) { - - if (!_disableDirtyRects) { - warning("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet"); + // This function isn't used outside of indicator-displaying, and thus quite unused in + // BaseRenderOSystem when dirty-rects are enabled. + if (!_disableDirtyRects && !_indicatorDisplay) { + error("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet"); } byte r = RGBCOLGetR(color); @@ -606,4 +636,36 @@ BaseSurface *BaseRenderOSystem::createSurface() { return new BaseSurfaceOSystem(_gameRef); } +void BaseRenderOSystem::endSaveLoad() { + BaseRenderer::endSaveLoad(); + + // Clear the scale-buffered tickets as we just loaded. + RenderQueueIterator it = _renderQueue.begin(); + while (it != _renderQueue.end()) { + RenderTicket *ticket = *it; + it = _renderQueue.erase(it); + delete ticket; + } + // HACK: After a save the buffer will be drawn before the scripts get to update it, + // so just skip this single frame. + _skipThisFrame = true; + _drawNum = 1; + + _renderSurface->fillRect(Common::Rect(0, 0, _renderSurface->h, _renderSurface->w), _renderSurface->format.ARGBToColor(255, 0, 0, 0)); + g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); + g_system->updateScreen(); +} + +bool BaseRenderOSystem::startSpriteBatch() { + _spriteBatch = true; + _batchNum = 1; + return STATUS_OK; +} + +bool BaseRenderOSystem::endSpriteBatch() { + _spriteBatch = false; + _batchNum = 0; + return STATUS_OK; +} + } // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index 1e72508cd0..cc2ed57f9b 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -36,27 +36,7 @@ namespace Wintermute { class BaseSurfaceOSystem; -class RenderTicket { - Graphics::Surface *_surface; -public: - RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false); - RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {} - ~RenderTicket(); - const Graphics::Surface *getSurface() { return _surface; } - Common::Rect _srcRect; - Common::Rect _dstRect; - uint32 _mirror; - bool _hasAlpha; - - bool _isValid; - bool _wantsDraw; - uint32 _drawNum; - uint32 _colorMod; - - BaseSurfaceOSystem *_owner; - bool operator==(RenderTicket &a); -}; - +class RenderTicket; class BaseRenderOSystem : public BaseRenderer { public: BaseRenderOSystem(BaseGame *inGame); @@ -64,17 +44,17 @@ public: Common::String getName() const; - bool initRenderer(int width, int height, bool windowed); - bool flip(); + bool initRenderer(int width, int height, bool windowed) override; + bool flip() override; virtual bool indicatorFlip(); - bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL); - Graphics::PixelFormat getPixelFormat() const; - void fade(uint16 alpha); - void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL); + bool fill(byte r, byte g, byte b, Common::Rect *rect = nullptr) override; + Graphics::PixelFormat getPixelFormat() const override; + void fade(uint16 alpha) override; + void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = nullptr) override; - bool drawLine(int x1, int y1, int x2, int y2, uint32 color); + bool drawLine(int x1, int y1, int x2, int y2, uint32 color) override; - BaseImage *takeScreenshot(); + BaseImage *takeScreenshot() override; void setAlphaMod(byte alpha); void setColorMod(byte r, byte g, byte b); @@ -82,32 +62,40 @@ public: void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf); void drawFromTicket(RenderTicket *renderTicket); - bool setViewport(int left, int top, int right, int bottom); - bool setViewport(Rect32 *rect) { return BaseRenderer::setViewport(rect); } - Rect32 getViewPort(); + bool setViewport(int left, int top, int right, int bottom) override; + bool setViewport(Rect32 *rect) override { return BaseRenderer::setViewport(rect); } + Rect32 getViewPort() override; void modTargetRect(Common::Rect *rect); - void pointFromScreen(Point32 *point); + void pointFromScreen(Point32 *point) ; void pointToScreen(Point32 *point); - void dumpData(const char *filename); + void dumpData(const char *filename) override; - float getScaleRatioX() const { + float getScaleRatioX() const override { return _ratioX; } - float getScaleRatioY() const { + float getScaleRatioY() const override { return _ratioY; } - - void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false); - BaseSurface *createSurface(); + virtual bool startSpriteBatch() override; + virtual bool endSpriteBatch() override; + void endSaveLoad(); + void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false) ; + void repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY); + BaseSurface *createSurface() override; private: - void addDirtyRect(const Common::Rect &rect); + void addDirtyRect(const Common::Rect &rect) ; void drawTickets(); - void drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect); - void drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror); + // Non-dirty-rects: + void drawFromSurface(RenderTicket *ticket); + // Dirty-rects: + void drawFromSurface(RenderTicket *ticket, Common::Rect *dstRect, Common::Rect *clipRect); typedef Common::List<RenderTicket *>::iterator RenderQueueIterator; Common::Rect *_dirtyRect; Common::List<RenderTicket *> _renderQueue; + RenderQueueIterator _lastAddedTicket; + RenderTicket *_previousTicket; + bool _needsFlip; uint32 _drawNum; Common::Rect _renderRect; @@ -119,11 +107,15 @@ private: int _borderRight; int _borderBottom; - static const bool _disableDirtyRects = true; + bool _disableDirtyRects; + bool _spriteBatch; + uint32 _batchNum; float _ratioX; float _ratioY; uint32 _colorMod; uint32 _clearColor; + + bool _skipThisFrame; }; } // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index bee876bb65..e3e4884fbb 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -47,9 +47,9 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////////// BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) { _surface = new Graphics::Surface(); - _alphaMask = NULL; + _alphaMask = nullptr; _hasAlpha = true; - _lockPixels = NULL; + _lockPixels = nullptr; _lockPitch = 0; _loaded = false; } @@ -59,11 +59,11 @@ BaseSurfaceOSystem::~BaseSurfaceOSystem() { if (_surface) { _surface->free(); delete _surface; - _surface = NULL; + _surface = nullptr; } delete[] _alphaMask; - _alphaMask = NULL; + _alphaMask = nullptr; _gameRef->addMem(-_width * _height * 4); BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); @@ -140,23 +140,32 @@ bool BaseSurfaceOSystem::finishLoad() { // Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow. _surface->free(); delete _surface; + + bool needsColorKey = false; + bool replaceAlpha = true; if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) { _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette()); - TransparentSurface trans(*_surface); - trans.applyColorKey(_ckRed, _ckGreen, _ckBlue); + needsColorKey = true; + replaceAlpha = false; } else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) { _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette()); - TransparentSurface trans(*_surface); - trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true); + needsColorKey = true; } else if (image->getSurface()->format.bytesPerPixel >= 3 && image->getSurface()->format != g_system->getScreenFormat()) { _surface = image->getSurface()->convertTo(g_system->getScreenFormat()); if (image->getSurface()->format.bytesPerPixel == 3) { - TransparentSurface trans(*_surface); - trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true); + needsColorKey = true; } } else { _surface = new Graphics::Surface(); _surface->copyFrom(*image->getSurface()); + if (_surface->format.aBits() == 0) { + needsColorKey = true; + } + } + + if (needsColorKey) { + TransparentSurface trans(*_surface); + trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha); } _hasAlpha = hasTransparency(_surface); @@ -177,7 +186,7 @@ void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) { return; // TODO: Reimplement this delete[] _alphaMask; - _alphaMask = NULL; + _alphaMask = nullptr; if (!surface) { return; } @@ -214,7 +223,7 @@ void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) { if (!hasTransparency) { delete[] _alphaMask; - _alphaMask = NULL; + _alphaMask = nullptr; } } @@ -293,7 +302,7 @@ bool BaseSurfaceOSystem::isTransparentAtLite(int x, int y) { ////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::startPixelOp() { - //SDL_LockTexture(_texture, NULL, &_lockPixels, &_lockPitch); + //SDL_LockTexture(_texture, nullptr, &_lockPixels, &_lockPitch); // Any pixel-op makes the caching useless: BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); renderer->invalidateTicketsFromSurface(this); @@ -414,6 +423,12 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, flo return STATUS_OK; } +bool BaseSurfaceOSystem::repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) { + BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); + renderer->repeatLastDraw(offsetX, offsetY, numTimesX, numTimesY); + return STATUS_OK; +} + bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { _loaded = true; _surface->free(); diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index 43422ef4e7..9091ec65b1 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -41,27 +41,28 @@ public: BaseSurfaceOSystem(BaseGame *inGame); ~BaseSurfaceOSystem(); - bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false); - bool create(int width, int height); + bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) override; + bool create(int width, int height) override; - bool isTransparentAt(int x, int y); - bool isTransparentAtLite(int x, int y); + bool isTransparentAt(int x, int y) override; + bool isTransparentAtLite(int x, int y) override; - bool startPixelOp(); - bool endPixelOp(); + bool startPixelOp() override; + bool endPixelOp() override; - bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0); - bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false); - virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false); + bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override; + bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) override; + virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override; /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin); static long DLL_CALLCONV TellProc(fi_handle handle);*/ - virtual int getWidth() { + virtual int getWidth() override { if (!_loaded) { finishLoad(); } @@ -70,7 +71,7 @@ public: } return _width; } - virtual int getHeight() { + virtual int getHeight() override { if (!_loaded) { finishLoad(); } diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp new file mode 100644 index 0000000000..d253ddca4b --- /dev/null +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -0,0 +1,115 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/graphics/transparent_surface.h" +#include "engines/wintermute/base/gfx/osystem/render_ticket.h" + +namespace Wintermute { + +RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner), +_srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) { + _colorMod = 0; + _batchNum = 0; + _mirror = TransparentSurface::FLIP_NONE; + if (mirrorX) { + _mirror |= TransparentSurface::FLIP_V; + } + if (mirrorY) { + _mirror |= TransparentSurface::FLIP_H; + } + if (surf) { + _surface = new Graphics::Surface(); + _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format); + assert(_surface->format.bytesPerPixel == 4); + // Get a clipped copy of the surface + for (int i = 0; i < _surface->h; i++) { + memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); + } + // Then scale it if necessary + if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { + TransparentSurface src(*_surface, false); + Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); + _surface->free(); + delete _surface; + _surface = temp; + } + } else { + _surface = nullptr; + } +} + +RenderTicket::~RenderTicket() { + if (_surface) { + _surface->free(); + delete _surface; + } +} + +bool RenderTicket::operator==(RenderTicket &t) { + if ((t._owner != _owner) || + (t._batchNum != t._batchNum) || + (t._hasAlpha != _hasAlpha) || + (t._mirror != _mirror) || + (t._colorMod != _colorMod) || + (t._dstRect != _dstRect) || + (t._srcRect != _srcRect)) { + return false; + } + return true; +} + +// Replacement for SDL2's SDL_RenderCopy +void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) { + TransparentSurface src(*getSurface(), false); + + Common::Rect clipRect; + clipRect.setWidth(getSurface()->w); + clipRect.setHeight(getSurface()->h); + + src._enableAlphaBlit = _hasAlpha; + src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _mirror, &clipRect, _colorMod, clipRect.width(), clipRect.height()); +} + +void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) { + TransparentSurface src(*getSurface(), false); + bool doDelete = false; + if (!clipRect) { + doDelete = true; + clipRect = new Common::Rect(); + clipRect->setWidth(getSurface()->w); + clipRect->setHeight(getSurface()->h); + } + + src._enableAlphaBlit = _hasAlpha; + src.blit(*_targetSurface, dstRect->left, dstRect->top, _mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); + if (doDelete) { + delete clipRect; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h new file mode 100644 index 0000000000..968b42b5e1 --- /dev/null +++ b/engines/wintermute/base/gfx/osystem/render_ticket.h @@ -0,0 +1,69 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_RENDER_TICKET_H +#define WINTERMUTE_RENDER_TICKET_H + +#include "graphics/surface.h" +#include "common/rect.h" + +namespace Wintermute { + +class BaseSurfaceOSystem; +class RenderTicket { +public: + RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false); + RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {} + ~RenderTicket(); + const Graphics::Surface *getSurface() { return _surface; } + // Non-dirty-rects: + void drawToSurface(Graphics::Surface *_targetSurface); + // Dirty-rects: + void drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect); + + Common::Rect _dstRect; + uint32 _batchNum; + + bool _isValid; + bool _wantsDraw; + uint32 _drawNum; + uint32 _colorMod; + + BaseSurfaceOSystem *_owner; + bool operator==(RenderTicket &a); + const Common::Rect *getSrcRect() { return &_srcRect; } +private: + Graphics::Surface *_surface; + Common::Rect _srcRect; + bool _hasAlpha; + uint32 _mirror; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp index bab4d4609e..1026969055 100644 --- a/engines/wintermute/base/particles/part_emitter.cpp +++ b/engines/wintermute/base/particles/part_emitter.cpp @@ -88,7 +88,7 @@ PartEmitter::PartEmitter(BaseGame *inGame, BaseScriptHolder *owner) : BaseObject _useRegion = false; - _emitEvent = NULL; + _emitEvent = nullptr; _owner = owner; } @@ -112,7 +112,7 @@ PartEmitter::~PartEmitter(void) { _sprites.clear(); delete[] _emitEvent; - _emitEvent = NULL; + _emitEvent = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -325,7 +325,7 @@ bool PartEmitter::display(BaseRegion *region) { } for (uint32 i = 0; i < _particles.size(); i++) { - if (region != NULL && _useRegion) { + if (region != nullptr && _useRegion) { if (!region->pointInRegion((int)_particles[i]->_pos.x, (int)_particles[i]->_pos.y)) { continue; } @@ -373,16 +373,13 @@ bool PartEmitter::sortParticlesByZ() { } ////////////////////////////////////////////////////////////////////////// -int PartEmitter::compareZ(const void *obj1, const void *obj2) { - const PartParticle *p1 = *(const PartParticle *const *)obj1; - const PartParticle *p2 = *(const PartParticle *const *)obj2; - +bool PartEmitter::compareZ(const PartParticle *p1, const PartParticle *p2) { if (p1->_posZ < p2->_posZ) { - return -1; + return true; } else if (p1->_posZ > p2->_posZ) { - return 1; + return false; } else { - return 0; + return false; } } @@ -405,7 +402,7 @@ bool PartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int ////////////////////////////////////////////////////////////////////////// PartForce *PartEmitter::addForceByName(const Common::String &name) { - PartForce *force = NULL; + PartForce *force = nullptr; for (uint32 i = 0; i < _forces.size(); i++) { if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) { @@ -1136,7 +1133,7 @@ bool PartEmitter::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "EmitEvent") == 0) { delete[] _emitEvent; - _emitEvent = NULL; + _emitEvent = nullptr; if (!value->isNULL()) { BaseUtils::setString(&_emitEvent, value->getString()); } diff --git a/engines/wintermute/base/particles/part_emitter.h b/engines/wintermute/base/particles/part_emitter.h index f2c8f139f1..54a49df230 100644 --- a/engines/wintermute/base/particles/part_emitter.h +++ b/engines/wintermute/base/particles/part_emitter.h @@ -48,7 +48,7 @@ public: bool start(); bool update(); - bool display() { return display(NULL); } // To avoid shadowing the inherited display-function. + bool display() { return display(nullptr); } // To avoid shadowing the inherited display-function. bool display(BaseRegion *region); bool sortParticlesByZ(); @@ -127,7 +127,7 @@ private: BaseScriptHolder *_owner; PartForce *addForceByName(const Common::String &name); - int static compareZ(const void *obj1, const void *obj2); + bool static compareZ(const PartParticle *p1, const PartParticle *p2); bool initParticle(PartParticle *particle, uint32 currentTime, uint32 timerDelta); bool updateInternal(uint32 currentTime, uint32 timerDelta); uint32 _lastGenTime; diff --git a/engines/wintermute/base/particles/part_particle.cpp b/engines/wintermute/base/particles/part_particle.cpp index 0b850d9618..f1aba114de 100644 --- a/engines/wintermute/base/particles/part_particle.cpp +++ b/engines/wintermute/base/particles/part_particle.cpp @@ -41,7 +41,7 @@ PartParticle::PartParticle(BaseGame *inGame) : BaseClass(inGame) { _posZ = 0.0f; _velocity = Vector2(0.0f, 0.0f); _scale = 100.0f; - _sprite = NULL; + _sprite = nullptr; _creationTime = 0; _lifeTime = 0; _isDead = true; @@ -65,7 +65,7 @@ PartParticle::PartParticle(BaseGame *inGame) : BaseClass(inGame) { ////////////////////////////////////////////////////////////////////////// PartParticle::~PartParticle(void) { delete _sprite; - _sprite = NULL; + _sprite = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -76,7 +76,7 @@ bool PartParticle::setSprite(const Common::String &filename) { } delete _sprite; - _sprite = NULL; + _sprite = nullptr; SystemClassRegistry::getInstance()->_disabled = true; _sprite = new BaseSprite(_gameRef, (BaseObject*)_gameRef); @@ -85,7 +85,7 @@ bool PartParticle::setSprite(const Common::String &filename) { return STATUS_OK; } else { delete _sprite; - _sprite = NULL; + _sprite = nullptr; SystemClassRegistry::getInstance()->_disabled = false; return STATUS_FAILED; } @@ -199,7 +199,7 @@ bool PartParticle::display(PartEmitter *emitter) { _sprite->getCurrentFrame(); return _sprite->display((int)_pos.x, (int)_pos.y, - NULL, + nullptr, _scale, _scale, BYTETORGBA(255, 255, 255, _currentAlpha), _rotation, @@ -260,7 +260,7 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) { setSprite(filename); SystemClassRegistry::getInstance()->_disabled = false; delete[] filename; - filename = NULL; + filename = nullptr; } return STATUS_OK; diff --git a/engines/wintermute/base/saveload.cpp b/engines/wintermute/base/saveload.cpp index 12204e1b35..465684a7a3 100644 --- a/engines/wintermute/base/saveload.cpp +++ b/engines/wintermute/base/saveload.cpp @@ -78,7 +78,7 @@ bool SaveLoad::loadGame(const Common::String &filename, BaseGame *gameRef) { //_gameRef->LOG(0, "Load end %d", BaseUtils::GetUsedMemMB()); // AdGame: if (DID_SUCCEED(ret)) { - SystemClassRegistry::getInstance()->enumInstances(SaveLoad::afterLoadRegion, "AdRegion", NULL); + SystemClassRegistry::getInstance()->enumInstances(SaveLoad::afterLoadRegion, "AdRegion", nullptr); } return ret; } @@ -114,13 +114,13 @@ bool SaveLoad::saveGame(int slot, const char *desc, bool quickSave, BaseGame *ga ////////////////////////////////////////////////////////////////////////// bool SaveLoad::initAfterLoad() { - SystemClassRegistry::getInstance()->enumInstances(afterLoadRegion, "BaseRegion", NULL); - SystemClassRegistry::getInstance()->enumInstances(afterLoadSubFrame, "BaseSubFrame", NULL); - SystemClassRegistry::getInstance()->enumInstances(afterLoadSound, "BaseSound", NULL); - SystemClassRegistry::getInstance()->enumInstances(afterLoadFont, "BaseFontTT", NULL); - SystemClassRegistry::getInstance()->enumInstances(afterLoadScript, "ScScript", NULL); + SystemClassRegistry::getInstance()->enumInstances(afterLoadRegion, "BaseRegion", nullptr); + SystemClassRegistry::getInstance()->enumInstances(afterLoadSubFrame, "BaseSubFrame", nullptr); + SystemClassRegistry::getInstance()->enumInstances(afterLoadSound, "BaseSound", nullptr); + SystemClassRegistry::getInstance()->enumInstances(afterLoadFont, "BaseFontTT", nullptr); + SystemClassRegistry::getInstance()->enumInstances(afterLoadScript, "ScScript", nullptr); // AdGame: - SystemClassRegistry::getInstance()->enumInstances(afterLoadScene, "AdScene", NULL); + SystemClassRegistry::getInstance()->enumInstances(afterLoadScene, "AdScene", nullptr); return STATUS_OK; } diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp index 9469bd46a7..23c452b73c 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -39,58 +39,58 @@ IMPLEMENT_PERSISTENT(ScScript, false) ////////////////////////////////////////////////////////////////////////// ScScript::ScScript(BaseGame *inGame, ScEngine *engine) : BaseClass(inGame) { - _buffer = NULL; + _buffer = nullptr; _bufferSize = _iP = 0; - _scriptStream = NULL; - _filename = NULL; + _scriptStream = nullptr; + _filename = nullptr; _currentLine = 0; - _symbols = NULL; + _symbols = nullptr; _numSymbols = 0; _engine = engine; - _globals = NULL; + _globals = nullptr; - _scopeStack = NULL; - _callStack = NULL; - _thisStack = NULL; - _stack = NULL; + _scopeStack = nullptr; + _callStack = nullptr; + _thisStack = nullptr; + _stack = nullptr; - _operand = NULL; - _reg1 = NULL; + _operand = nullptr; + _reg1 = nullptr; - _functions = NULL; + _functions = nullptr; _numFunctions = 0; - _methods = NULL; + _methods = nullptr; _numMethods = 0; - _events = NULL; + _events = nullptr; _numEvents = 0; - _externals = NULL; + _externals = nullptr; _numExternals = 0; _state = SCRIPT_FINISHED; _origState = SCRIPT_FINISHED; - _waitObject = NULL; + _waitObject = nullptr; _waitTime = 0; _waitFrozen = false; - _waitScript = NULL; + _waitScript = nullptr; _timeSlice = 0; _thread = false; _methodThread = false; - _threadEvent = NULL; + _threadEvent = nullptr; _freezable = true; - _owner = NULL; + _owner = nullptr; _unbreakable = false; - _parentScript = NULL; + _parentScript = nullptr; _tracingMode = false; } @@ -242,7 +242,7 @@ bool ScScript::create(const char *filename, byte *buffer, uint32 size, BaseScrip _methodThread = false; delete[] _threadEvent; - _threadEvent = NULL; + _threadEvent = nullptr; _filename = new char[strlen(filename) + 1]; if (_filename) { @@ -383,52 +383,52 @@ void ScScript::cleanup() { if (_buffer) { delete[] _buffer; } - _buffer = NULL; + _buffer = nullptr; if (_filename) { delete[] _filename; } - _filename = NULL; + _filename = nullptr; if (_symbols) { delete[] _symbols; } - _symbols = NULL; + _symbols = nullptr; _numSymbols = 0; if (_globals && !_thread) { delete _globals; } - _globals = NULL; + _globals = nullptr; delete _scopeStack; - _scopeStack = NULL; + _scopeStack = nullptr; delete _callStack; - _callStack = NULL; + _callStack = nullptr; delete _thisStack; - _thisStack = NULL; + _thisStack = nullptr; delete _stack; - _stack = NULL; + _stack = nullptr; if (_functions) { delete[] _functions; } - _functions = NULL; + _functions = nullptr; _numFunctions = 0; if (_methods) { delete[] _methods; } - _methods = NULL; + _methods = nullptr; _numMethods = 0; if (_events) { delete[] _events; } - _events = NULL; + _events = nullptr; _numEvents = 0; @@ -440,25 +440,25 @@ void ScScript::cleanup() { } delete[] _externals; } - _externals = NULL; + _externals = nullptr; _numExternals = 0; delete _operand; delete _reg1; - _operand = NULL; - _reg1 = NULL; + _operand = nullptr; + _reg1 = nullptr; delete[] _threadEvent; - _threadEvent = NULL; + _threadEvent = nullptr; _state = SCRIPT_FINISHED; - _waitObject = NULL; + _waitObject = nullptr; _waitTime = 0; _waitFrozen = false; - _waitScript = NULL; + _waitScript = nullptr; - _parentScript = NULL; // ref only + _parentScript = nullptr; // ref only delete _scriptStream; } @@ -511,7 +511,7 @@ bool ScScript::executeInstruction() { bool ret = STATUS_OK; uint32 dw; - const char *str = NULL; + const char *str = nullptr; //ScValue* op = new ScValue(_gameRef); _operand->cleanup(); @@ -622,11 +622,11 @@ bool ScScript::executeInstruction() { } /* ScValue* val = var->getProp(MethodName); - if (val){ + if (val) { dw = GetFuncPos(val->getString()); - if (dw==0){ + if (dw==0) { TExternalFunction* f = GetExternal(val->getString()); - if (f){ + if (f) { ExternalCall(_stack, _thisStack, f); } else{ @@ -787,7 +787,7 @@ bool ScScript::executeInstruction() { ScValue *var = _stack->pop(); ScValue *val = _stack->pop(); - if (val == NULL) { + if (val == nullptr) { runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum."); var->setNULL(); } else { @@ -928,7 +928,7 @@ bool ScScript::executeInstruction() { case II_AND: op2 = _stack->pop(); op1 = _stack->pop(); - if (op1 == NULL || op2 == NULL) { + if (op1 == nullptr || op2 == nullptr) { runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?"); _operand->setBool(false); } else { @@ -940,7 +940,7 @@ bool ScScript::executeInstruction() { case II_OR: op2 = _stack->pop(); op1 = _stack->pop(); - if (op1 == NULL || op2 == NULL) { + if (op1 == nullptr || op2 == nullptr) { runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?"); _operand->setBool(false); } else { @@ -955,13 +955,13 @@ bool ScScript::executeInstruction() { /* if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(false); - else if (op1->isNative() && op2->isNative()){ + else if (op1->isNative() && op2->isNative()) { _operand->setBool(op1->getNative() == op2->getNative()); } - else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){ + else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING) { _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())==0); } - else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) { _operand->setBool(op1->getFloat() == op2->getFloat()); } else{ @@ -979,13 +979,13 @@ bool ScScript::executeInstruction() { /* if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(true); - else if (op1->isNative() && op2->isNative()){ + else if (op1->isNative() && op2->isNative()) { _operand->setBool(op1->getNative() != op2->getNative()); } - else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){ + else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING) { _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())!=0); } - else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) { _operand->setBool(op1->getFloat() != op2->getFloat()); } else{ @@ -1002,7 +1002,7 @@ bool ScScript::executeInstruction() { op1 = _stack->pop(); /* - if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) { _operand->setBool(op1->getFloat() < op2->getFloat()); } else _operand->setBool(op1->getInt() < op2->getInt()); @@ -1017,7 +1017,7 @@ bool ScScript::executeInstruction() { op1 = _stack->pop(); /* - if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) { _operand->setBool(op1->getFloat() > op2->getFloat()); } else _operand->setBool(op1->getInt() > op2->getInt()); @@ -1032,7 +1032,7 @@ bool ScScript::executeInstruction() { op1 = _stack->pop(); /* - if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) { _operand->setBool(op1->getFloat() <= op2->getFloat()); } else _operand->setBool(op1->getInt() <= op2->getInt()); @@ -1047,7 +1047,7 @@ bool ScScript::executeInstruction() { op1 = _stack->pop(); /* - if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) { _operand->setBool(op1->getFloat() >= op2->getFloat()); } else _operand->setBool(op1->getInt() >= op2->getInt()); @@ -1108,7 +1108,7 @@ uint32 ScScript::getFuncPos(const Common::String &name) { ////////////////////////////////////////////////////////////////////////// -uint32 ScScript::getMethodPos(const Common::String &name) { +uint32 ScScript::getMethodPos(const Common::String &name) const { for (uint32 i = 0; i < _numMethods; i++) { if (name == _methods[i].name) { return _methods[i].pos; @@ -1120,7 +1120,7 @@ uint32 ScScript::getMethodPos(const Common::String &name) { ////////////////////////////////////////////////////////////////////////// ScValue *ScScript::getVar(char *name) { - ScValue *ret = NULL; + ScValue *ret = nullptr; // scope locals if (_scopeStack->_sP >= 0) { @@ -1130,20 +1130,20 @@ ScValue *ScScript::getVar(char *name) { } // script globals - if (ret == NULL) { + if (ret == nullptr) { if (_globals->propExists(name)) { ret = _globals->getProp(name); } } // engine globals - if (ret == NULL) { + if (ret == nullptr) { if (_engine->_globals->propExists(name)) { ret = _engine->_globals->getProp(name); } } - if (ret == NULL) { + if (ret == nullptr) { //RuntimeError("Variable '%s' is inaccessible in the current block. Consider changing the script.", name); _gameRef->LOG(0, "Warning: variable '%s' is inaccessible in the current block. Consider changing the script (script:%s, line:%d)", name, _filename, _currentLine); ScValue *val = new ScValue(_gameRef); @@ -1263,8 +1263,8 @@ bool ScScript::persist(BasePersistenceManager *persistMgr) { _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize); initTables(); } else { - _buffer = NULL; - _scriptStream = NULL; + _buffer = nullptr; + _scriptStream = nullptr; } } @@ -1306,11 +1306,11 @@ bool ScScript::persist(BasePersistenceManager *persistMgr) { ////////////////////////////////////////////////////////////////////////// ScScript *ScScript::invokeEventHandler(const Common::String &eventName, bool unbreakable) { - //if (_state!=SCRIPT_PERSISTENT) return NULL; + //if (_state!=SCRIPT_PERSISTENT) return nullptr; uint32 pos = getEventPos(eventName); if (!pos) { - return NULL; + return nullptr; } ScScript *thread = new ScScript(_gameRef, _engine); @@ -1322,17 +1322,17 @@ ScScript *ScScript::invokeEventHandler(const Common::String &eventName, bool unb return thread; } else { delete thread; - return NULL; + return nullptr; } } else { - return NULL; + return nullptr; } } ////////////////////////////////////////////////////////////////////////// -uint32 ScScript::getEventPos(const Common::String &name) { +uint32 ScScript::getEventPos(const Common::String &name) const { for (int i = _numEvents - 1; i >= 0; i--) { if (scumm_stricmp(name.c_str(), _events[i].name) == 0) { return _events[i].pos; @@ -1343,13 +1343,13 @@ uint32 ScScript::getEventPos(const Common::String &name) { ////////////////////////////////////////////////////////////////////////// -bool ScScript::canHandleEvent(const Common::String &eventName) { +bool ScScript::canHandleEvent(const Common::String &eventName) const { return getEventPos(eventName) != 0; } ////////////////////////////////////////////////////////////////////////// -bool ScScript::canHandleMethod(const Common::String &methodName) { +bool ScScript::canHandleMethod(const Common::String &methodName) const { return getMethodPos(methodName) != 0; } @@ -1390,7 +1390,7 @@ ScScript::TExternalFunction *ScScript::getExternal(char *name) { return &_externals[i]; } } - return NULL; + return nullptr; } @@ -1446,7 +1446,7 @@ const char *ScScript::dbgGetFilename() { ////////////////////////////////////////////////////////////////////////// void ScScript::afterLoad() { - if (_buffer == NULL) { + if (_buffer == nullptr) { byte *buffer = _engine->getCompiledScript(_filename, &_bufferSize); if (!buffer) { _gameRef->LOG(0, "Error reinitializing script '%s' after load. Script will be terminated.", _filename); diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h index 0616bce58a..428eb9a17e 100644 --- a/engines/wintermute/base/scriptables/script.h +++ b/engines/wintermute/base/scriptables/script.h @@ -57,8 +57,8 @@ public: bool _freezable; bool resume(); bool pause(); - bool canHandleEvent(const Common::String &eventName); - bool canHandleMethod(const Common::String &methodName); + bool canHandleEvent(const Common::String &eventName) const; + bool canHandleMethod(const Common::String &methodName) const; bool createThread(ScScript *original, uint32 initIP, const Common::String &eventName); bool createMethodThread(ScScript *original, const Common::String &methodName); ScScript *invokeEventHandler(const Common::String &eventName, bool unbreakable = false); @@ -78,8 +78,8 @@ public: TScriptState _origState; ScValue *getVar(char *name); uint32 getFuncPos(const Common::String &name); - uint32 getEventPos(const Common::String &name); - uint32 getMethodPos(const Common::String &name); + uint32 getEventPos(const Common::String &name) const; + uint32 getMethodPos(const Common::String &name) const; typedef struct { uint32 magic; uint32 version; diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp index 3d1863946e..d5c5797a39 100644 --- a/engines/wintermute/base/scriptables/script_engine.cpp +++ b/engines/wintermute/base/scriptables/script_engine.cpp @@ -30,7 +30,6 @@ #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/base/scriptables/script.h" #include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/scriptables/script_ext_math.h" #include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/base_file_manager.h" @@ -70,10 +69,10 @@ ScEngine::ScEngine(BaseGame *inGame) : BaseClass(inGame) { // prepare script cache for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { - _cachedScripts[i] = NULL; + _cachedScripts[i] = nullptr; } - _currentScript = NULL; + _currentScript = nullptr; _isProfiling = false; _profilingStartTime = 0; @@ -106,11 +105,11 @@ bool ScEngine::cleanup() { _scripts.clear(); delete _globals; - _globals = NULL; + _globals = nullptr; emptyScriptCache(); - _currentScript = NULL; // ref only + _currentScript = nullptr; // ref only return STATUS_OK; } @@ -141,7 +140,7 @@ ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) { // get script from cache compBuffer = getCompiledScript(filename, &compSize); if (!compBuffer) { - return NULL; + return nullptr; } // add new script @@ -150,7 +149,7 @@ ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) { if (DID_FAIL(ret)) { _gameRef->LOG(ret, "Error running script '%s'...", filename); delete script; - return NULL; + return nullptr; } else { // publish the "self" pseudo-variable ScValue val(_gameRef); @@ -192,7 +191,7 @@ byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ig byte *buffer = BaseEngine::instance().getFileManager()->readWholeFile(filename, &size); if (!buffer) { _gameRef->LOG(0, "ScEngine::GetCompiledScript - error opening script '%s'", filename); - return NULL; + return nullptr; } // needs to be compiled? @@ -203,14 +202,14 @@ byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ig if (!_compilerAvailable) { _gameRef->LOG(0, "ScEngine::GetCompiledScript - script '%s' needs to be compiled but compiler is not available", filename); delete[] buffer; - return NULL; + return nullptr; } // This code will never be called, since _compilerAvailable is const false. // It's only here in the event someone would want to reinclude the compiler. error("Script needs compilation, ScummVM does not contain a WME compiler"); } - byte *ret = NULL; + byte *ret = nullptr; // add script to cache CScCachedScript *cachedScript = new CScCachedScript(filename, compBuffer, compSize); @@ -218,7 +217,7 @@ byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ig int index = 0; uint32 minTime = g_system->getMillis(); for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { - if (_cachedScripts[i] == NULL) { + if (_cachedScripts[i] == nullptr) { index = i; break; } else if (_cachedScripts[i]->_timestamp <= minTime) { @@ -227,7 +226,7 @@ byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ig } } - if (_cachedScripts[index] != NULL) { + if (_cachedScripts[index] != nullptr) { delete _cachedScripts[index]; } _cachedScripts[index] = cachedScript; @@ -297,7 +296,7 @@ bool ScEngine::tick() { if (!isValidScript(_scripts[i]->_waitScript) || _scripts[i]->_waitScript->_state == SCRIPT_ERROR) { // fake return value _scripts[i]->_stack->pushNULL(); - _scripts[i]->_waitScript = NULL; + _scripts[i]->_waitScript = nullptr; _scripts[i]->run(); } else { if (_scripts[i]->_waitScript->_state == SCRIPT_THREAD_FINISHED) { @@ -305,7 +304,7 @@ bool ScEngine::tick() { _scripts[i]->_stack->push(_scripts[i]->_waitScript->_stack->pop()); _scripts[i]->run(); _scripts[i]->_waitScript->finish(); - _scripts[i]->_waitScript = NULL; + _scripts[i]->_waitScript = nullptr; } } break; @@ -352,7 +351,7 @@ bool ScEngine::tick() { addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime); } } - _currentScript = NULL; + _currentScript = nullptr; } removeFinishedScripts(); @@ -374,7 +373,7 @@ bool ScEngine::tickUnbreakable() { _scripts[i]->executeInstruction(); } _scripts[i]->finish(); - _currentScript = NULL; + _currentScript = nullptr; } removeFinishedScripts(); @@ -445,7 +444,7 @@ bool ScEngine::emptyScriptCache() { for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { if (_cachedScripts[i]) { delete _cachedScripts[i]; - _cachedScripts[i] = NULL; + _cachedScripts[i] = nullptr; } } return STATUS_OK; @@ -497,7 +496,7 @@ bool ScEngine::persist(BasePersistenceManager *persistMgr) { ////////////////////////////////////////////////////////////////////////// void ScEngine::editorCleanup() { for (uint32 i = 0; i < _scripts.size(); i++) { - if (_scripts[i]->_owner == NULL && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) { + if (_scripts[i]->_owner == nullptr && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) { delete _scripts[i]; _scripts.remove_at(i); i--; diff --git a/engines/wintermute/base/scriptables/script_engine.h b/engines/wintermute/base/scriptables/script_engine.h index 1a023326eb..639875ffb6 100644 --- a/engines/wintermute/base/scriptables/script_engine.h +++ b/engines/wintermute/base/scriptables/script_engine.h @@ -96,10 +96,10 @@ public: byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false); DECLARE_PERSISTENT(ScEngine, BaseClass) bool cleanup(); - int getNumScripts(int *running = NULL, int *waiting = NULL, int *persistent = NULL); + int getNumScripts(int *running = nullptr, int *waiting = nullptr, int *persistent = nullptr); bool tick(); ScValue *_globals; - ScScript *runScript(const char *filename, BaseScriptHolder *owner = NULL); + ScScript *runScript(const char *filename, BaseScriptHolder *owner = nullptr); static const bool _compilerAvailable = false; ScEngine(BaseGame *inGame); diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp index 613cbd0758..892d0674ff 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.cpp +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -69,7 +69,7 @@ SXArray::SXArray(BaseGame *inGame) : BaseScriptable(inGame) { ////////////////////////////////////////////////////////////////////////// SXArray::~SXArray() { delete _values; - _values = NULL; + _values = nullptr; } diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp index 5aa069d0b2..53a1d36b81 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.cpp +++ b/engines/wintermute/base/scriptables/script_ext_date.cpp @@ -224,7 +224,7 @@ bool SXDate::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// // Name ////////////////////////////////////////////////////////////////////////// - if (name == "Name")==0){ + if (name == "Name")==0) { setName(value->getString()); return STATUS_OK; } diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp index a1d39c5d0a..29e032a759 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.cpp +++ b/engines/wintermute/base/scriptables/script_ext_file.cpp @@ -52,13 +52,13 @@ SXFile::SXFile(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { stack->correctParams(1); ScValue *val = stack->pop(); - _filename = NULL; + _filename = nullptr; if (!val->isNULL()) { BaseUtils::setString(&_filename, val->getString()); } - _readFile = NULL; - _writeFile = NULL; + _readFile = nullptr; + _writeFile = nullptr; _mode = 0; _textMode = false; @@ -73,7 +73,7 @@ SXFile::~SXFile() { ////////////////////////////////////////////////////////////////////////// void SXFile::cleanup() { delete[] _filename; - _filename = NULL; + _filename = nullptr; close(); } @@ -82,12 +82,12 @@ void SXFile::cleanup() { void SXFile::close() { if (_readFile) { BaseFileManager::getEngineInstance()->closeFile(_readFile); - _readFile = NULL; + _readFile = nullptr; } if (_writeFile) { _writeFile->finalize(); delete _writeFile; - _writeFile = NULL; + _writeFile = nullptr; } _mode = 0; _textMode = false; @@ -701,13 +701,13 @@ bool SXFile::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// // Length ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Length")==0){ + if (strcmp(name, "Length")==0) { int origLength = _length; _length = max(value->getInt(0), 0); char propName[20]; - if (_length < OrigLength){ - for(int i=_length; i<OrigLength; i++){ + if (_length < OrigLength) { + for(int i=_length; i<OrigLength; i++) { sprintf(PropName, "%d", i); _values->DeleteProp(PropName); } @@ -778,8 +778,8 @@ bool SXFile::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(pos)); // try to re-open file if needed - _writeFile = NULL; - _readFile = NULL; + _writeFile = nullptr; + _readFile = nullptr; if (_mode != 0) { // open for reading diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp index 8f05b7bff6..9de9905fea 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp @@ -44,7 +44,7 @@ BaseScriptable *makeSXMemBuffer(BaseGame *inGame, ScStack *stack) { ////////////////////////////////////////////////////////////////////////// SXMemBuffer::SXMemBuffer(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { stack->correctParams(1); - _buffer = NULL; + _buffer = nullptr; _size = 0; int newSize = stack->pop()->getInt(); @@ -73,7 +73,7 @@ void SXMemBuffer::cleanup() { if (_size) { free(_buffer); } - _buffer = NULL; + _buffer = nullptr; _size = 0; } @@ -109,7 +109,7 @@ bool SXMemBuffer::resize(int newSize) { ////////////////////////////////////////////////////////////////////////// bool SXMemBuffer::checkBounds(ScScript *script, int start, int length) { - if (_buffer == NULL) { + if (_buffer == nullptr) { script->runtimeError("Cannot use Set/Get methods on an uninitialized memory buffer"); return false; } @@ -476,15 +476,15 @@ bool SXMemBuffer::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// // Length ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Length")==0){ + if (strcmp(name, "Length")==0) { int origLength = _length; _length = max(value->getInt(0), 0); char propName[20]; - if (_length < OrigLength){ - for(int i=_length; i<OrigLength; i++){ - sprintf(PropName, "%d", i); - _values->DeleteProp(PropName); + if (_length < origLength) { + for(int i=_length; i < origLength; i++) { + sprintf(propName, "%d", i); + _values->DeleteProp(propName); } } return STATUS_OK; @@ -509,7 +509,7 @@ bool SXMemBuffer::persist(BasePersistenceManager *persistMgr) { _buffer = malloc(_size); persistMgr->getBytes((byte *)_buffer, _size); } else { - _buffer = NULL; + _buffer = nullptr; } } diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp index 5f7da1c2dd..6b4a615509 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.cpp +++ b/engines/wintermute/base/scriptables/script_ext_string.cpp @@ -45,7 +45,7 @@ BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack) { ////////////////////////////////////////////////////////////////////////// SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { - _string = NULL; + _string = nullptr; _capacity = 0; stack->correctParams(1); @@ -81,7 +81,7 @@ void SXString::setStringVal(const char *val) { if (len >= _capacity) { _capacity = len + 1; delete[] _string; - _string = NULL; + _string = nullptr; _string = new char[_capacity]; memset(_string, 0, _capacity); } @@ -331,7 +331,7 @@ bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack array->push(val); delete val; - val = NULL; + val = nullptr; } stack->pushNative(array, false); @@ -420,7 +420,7 @@ bool SXString::persist(BasePersistenceManager *persistMgr) { _string = new char[_capacity]; persistMgr->getBytes((byte *)_string, _capacity); } else { - _string = NULL; + _string = nullptr; } } diff --git a/engines/wintermute/base/scriptables/script_stack.cpp b/engines/wintermute/base/scriptables/script_stack.cpp index 77367045c2..3239decae8 100644 --- a/engines/wintermute/base/scriptables/script_stack.cpp +++ b/engines/wintermute/base/scriptables/script_stack.cpp @@ -58,7 +58,7 @@ ScStack::~ScStack() { ScValue *ScStack::pop() { if (_sP < 0) { _gameRef->LOG(0, "Fatal: Stack underflow"); - return NULL; + return nullptr; } return _values[_sP--]; @@ -97,7 +97,7 @@ ScValue *ScStack::getPushValue() { ////////////////////////////////////////////////////////////////////////// ScValue *ScStack::getTop() { if (_sP < 0 || _sP >= (int32)_values.size()) { - return NULL; + return nullptr; } else { return _values[_sP]; } @@ -108,7 +108,7 @@ ScValue *ScStack::getTop() { ScValue *ScStack::getAt(int index) { index = _sP - index; if (index < 0 || index >= (int32)_values.size()) { - return NULL; + return nullptr; } else { return _values[index]; } @@ -147,73 +147,36 @@ void ScStack::correctParams(uint32 expectedParams) { ////////////////////////////////////////////////////////////////////////// void ScStack::pushNULL() { - /* - ScValue* val = new ScValue(_gameRef); - val->setNULL(); - Push(val); - delete val; - */ getPushValue()->setNULL(); } ////////////////////////////////////////////////////////////////////////// void ScStack::pushInt(int val) { - /* - ScValue* val = new ScValue(_gameRef); - val->setInt(Val); - Push(val); - delete val; - */ getPushValue()->setInt(val); } ////////////////////////////////////////////////////////////////////////// void ScStack::pushFloat(double val) { - /* - ScValue* val = new ScValue(_gameRef); - val->setFloat(Val); - Push(val); - delete val; - */ getPushValue()->setFloat(val); } ////////////////////////////////////////////////////////////////////////// void ScStack::pushBool(bool val) { - /* - ScValue* val = new ScValue(_gameRef); - val->setBool(Val); - Push(val); - delete val; - */ getPushValue()->setBool(val); } ////////////////////////////////////////////////////////////////////////// void ScStack::pushString(const char *val) { - /* - ScValue* val = new ScValue(_gameRef); - val->setString(Val); - Push(val); - delete val; - */ getPushValue()->setString(val); } ////////////////////////////////////////////////////////////////////////// void ScStack::pushNative(BaseScriptable *val, bool persistent) { - /* - ScValue* val = new ScValue(_gameRef); - val->setNative(Val, Persistent); - Push(val); - delete val; - */ - getPushValue()->setNative(val, persistent); } diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp index 0bc7ab5807..46d6c25d44 100644 --- a/engines/wintermute/base/scriptables/script_value.cpp +++ b/engines/wintermute/base/scriptables/script_value.cpp @@ -49,9 +49,9 @@ ScValue::ScValue(BaseGame *inGame) : BaseClass(inGame) { _valBool = false; _valInt = 0; _valFloat = 0.0f; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; + _valNative = nullptr; + _valString = nullptr; + _valRef = nullptr; _persistent = false; _isConstVar = false; } @@ -64,9 +64,9 @@ ScValue::ScValue(BaseGame *inGame, bool val) : BaseClass(inGame) { _valInt = 0; _valFloat = 0.0f; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; + _valNative = nullptr; + _valString = nullptr; + _valRef = nullptr; _persistent = false; _isConstVar = false; } @@ -79,9 +79,9 @@ ScValue::ScValue(BaseGame *inGame, int val) : BaseClass(inGame) { _valFloat = 0.0f; _valBool = false; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; + _valNative = nullptr; + _valString = nullptr; + _valRef = nullptr; _persistent = false; _isConstVar = false; } @@ -94,9 +94,9 @@ ScValue::ScValue(BaseGame *inGame, double val) : BaseClass(inGame) { _valInt = 0; _valBool = false; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; + _valNative = nullptr; + _valString = nullptr; + _valRef = nullptr; _persistent = false; _isConstVar = false; } @@ -105,14 +105,14 @@ ScValue::ScValue(BaseGame *inGame, double val) : BaseClass(inGame) { ////////////////////////////////////////////////////////////////////////// ScValue::ScValue(BaseGame *inGame, const char *val) : BaseClass(inGame) { _type = VAL_STRING; - _valString = NULL; + _valString = nullptr; setStringVal(val); _valBool = false; _valInt = 0; _valFloat = 0.0f; - _valNative = NULL; - _valRef = NULL; + _valNative = nullptr; + _valRef = nullptr; _persistent = false; _isConstVar = false; } @@ -131,7 +131,7 @@ void ScValue::cleanup(bool ignoreNatives) { _valNative->_refCount--; if (_valNative->_refCount <= 0) { delete _valNative; - _valNative = NULL; + _valNative = nullptr; } } } @@ -142,9 +142,9 @@ void ScValue::cleanup(bool ignoreNatives) { _valBool = false; _valInt = 0; _valFloat = 0.0f; - _valNative = NULL; - _valString = NULL; - _valRef = NULL; + _valNative = nullptr; + _valString = nullptr; + _valRef = nullptr; _persistent = false; _isConstVar = false; } @@ -176,13 +176,13 @@ ScValue *ScValue::getProp(const char *name) { return _gameRef->_scValue; } - ScValue *ret = NULL; + ScValue *ret = nullptr; if (_type == VAL_NATIVE && _valNative) { ret = _valNative->scGetProperty(name); } - if (ret == NULL) { + if (ret == nullptr) { _valIter = _valObject.find(name); if (_valIter != _valObject.end()) { ret = _valIter->_value; @@ -200,7 +200,7 @@ bool ScValue::deleteProp(const char *name) { _valIter = _valObject.find(name); if (_valIter != _valObject.end()) { delete _valIter->_value; - _valIter->_value = NULL; + _valIter->_value = nullptr; } return STATUS_OK; @@ -220,7 +220,7 @@ bool ScValue::setProp(const char *name, ScValue *val, bool copyWhole, bool setAs } if (DID_FAIL(ret)) { - ScValue *newVal = NULL; + ScValue *newVal = nullptr; _valIter = _valObject.find(name); if (_valIter != _valObject.end()) { @@ -242,9 +242,9 @@ bool ScValue::setProp(const char *name, ScValue *val, bool copyWhole, bool setAs /* _valIter = _valObject.find(Name); - if (_valIter != _valObject.end()){ + if (_valIter != _valObject.end()) { delete _valIter->_value; - _valIter->_value = NULL; + _valIter->_value = nullptr; } ScValue* val = new ScValue(_gameRef); val->Copy(Val, CopyWhole); @@ -451,11 +451,11 @@ void ScValue::setString(const Common::String &val) { void ScValue::setStringVal(const char *val) { if (_valString) { delete[] _valString; - _valString = NULL; + _valString = nullptr; } - if (val == NULL) { - _valString = NULL; + if (val == nullptr) { + _valString = nullptr; return; } @@ -479,7 +479,7 @@ void ScValue::setNULL() { delete _valNative; } } - _valNative = NULL; + _valNative = nullptr; deleteProps(); _type = VAL_NULL; @@ -493,7 +493,7 @@ void ScValue::setNative(BaseScriptable *val, bool persistent) { return; } - if (val == NULL) { + if (val == nullptr) { setNULL(); } else { if (_valNative && !_persistent) { @@ -502,7 +502,7 @@ void ScValue::setNative(BaseScriptable *val, bool persistent) { if (_valNative != val) { delete _valNative; } - _valNative = NULL; + _valNative = nullptr; } } @@ -693,7 +693,7 @@ BaseScriptable *ScValue::getNative() { if (_type == VAL_NATIVE) { return _valNative; } else { - return NULL; + return nullptr; } } @@ -714,7 +714,7 @@ void ScValue::copy(ScValue *orig, bool copyWhole) { if (_valNative != orig->_valNative) { delete _valNative; } - _valNative = NULL; + _valNative = nullptr; } } @@ -827,7 +827,7 @@ bool ScValue::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_valRef)); persistMgr->transfer(TMEMBER(_valString)); - /* + /* // TODO: Convert to Debug-statements. FILE* f = fopen("c:\\val.log", "a+"); switch(_type) { diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp index 00d07cd3c2..f246c03fe1 100644 --- a/engines/wintermute/base/sound/base_sound.cpp +++ b/engines/wintermute/base/sound/base_sound.cpp @@ -36,7 +36,7 @@ namespace Wintermute { IMPLEMENT_PERSISTENT(BaseSound, false) BaseSound::BaseSound(BaseGame *inGame) : BaseClass(inGame) { - _sound = NULL; + _sound = nullptr; _soundFilename = ""; _soundType = Audio::Mixer::kSFXSoundType; @@ -57,13 +57,13 @@ BaseSound::~BaseSound() { if (_sound) { _gameRef->_soundMgr->removeSound(_sound); } - _sound = NULL; + _sound = nullptr; } bool BaseSound::setSound(const Common::String &filename, Audio::Mixer::SoundType type, bool streamed) { if (_sound) { _gameRef->_soundMgr->removeSound(_sound); - _sound = NULL; + _sound = nullptr; } _soundFilename = Common::String(); // Set empty diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp index 250570f2b8..9c919abac6 100644 --- a/engines/wintermute/base/sound/base_sound_buffer.cpp +++ b/engines/wintermute/base/sound/base_sound_buffer.cpp @@ -49,13 +49,13 @@ namespace Wintermute { ////////////////////////////////////////////////////////////////////////// BaseSoundBuffer::BaseSoundBuffer(BaseGame *inGame) : BaseClass(inGame) { - _stream = NULL; - _handle = NULL; -// _sync = NULL; + _stream = nullptr; + _handle = nullptr; +// _sync = nullptr; _streamed = false; _filename = ""; - _file = NULL; + _file = nullptr; _privateVolume = 255; _volume = 255; @@ -76,10 +76,10 @@ BaseSoundBuffer::~BaseSoundBuffer() { if (_handle) { g_system->getMixer()->stopHandle(*_handle); delete _handle; - _handle = NULL; + _handle = nullptr; } delete _stream; - _stream = NULL; + _stream = nullptr; } @@ -111,7 +111,7 @@ bool BaseSoundBuffer::loadFromFile(const Common::String &filename, bool forceRel if (Audio::loadWAVFromStream(*_file, waveSize, waveRate, waveFlags, &waveType)) { if (waveType == 1) { // We need to wrap the file in a substream to make sure the size is right. - _file = new Common::SeekableSubReadStream(_file, 0, waveSize); + _file = new Common::SeekableSubReadStream(_file, _file->pos(), waveSize + _file->pos(), DisposeAfterUse::YES); _stream = Audio::makeRawStream(_file, waveRate, waveFlags, DisposeAfterUse::YES); } else { error("BSoundBuffer::LoadFromFile - WAVE not supported yet for %s with type %d", filename.c_str(), waveType); @@ -134,7 +134,7 @@ bool BaseSoundBuffer::play(bool looping, uint32 startSample) { if (_handle) { g_system->getMixer()->stopHandle(*_handle); delete _handle; - _handle = NULL; + _handle = nullptr; } // Store the loop-value for save-games. setLooping(looping); diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp index 441793144d..c6eb871a85 100644 --- a/engines/wintermute/base/sound/base_sound_manager.cpp +++ b/engines/wintermute/base/sound/base_sound_manager.cpp @@ -50,6 +50,7 @@ namespace Wintermute { BaseSoundMgr::BaseSoundMgr(BaseGame *inGame) : BaseClass(inGame) { _soundAvailable = false; _volumeMaster = 255; + _volumeMasterPercent = 100; } @@ -72,7 +73,7 @@ bool BaseSoundMgr::cleanup() { ////////////////////////////////////////////////////////////////////////// void BaseSoundMgr::saveSettings() { if (_soundAvailable) { - ConfMan.setInt("master_volume", _volumeMaster); + ConfMan.setInt("master_volume_percent", _volumeMasterPercent); } } @@ -83,7 +84,8 @@ bool BaseSoundMgr::initialize() { if (!g_system->getMixer()->isReady()) { return STATUS_FAILED; } - _volumeMaster = (ConfMan.hasKey("master_volume") ? ConfMan.getInt("master_volume") : 255); + byte volumeMasterPercent = (ConfMan.hasKey("master_volume_percent") ? ConfMan.getInt("master_volume_percent") : 100); + setMasterVolumePercent(volumeMasterPercent); _soundAvailable = true; return STATUS_OK; @@ -92,7 +94,7 @@ bool BaseSoundMgr::initialize() { ////////////////////////////////////////////////////////////////////////// BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::Mixer::SoundType type, bool streamed) { if (!_soundAvailable) { - return NULL; + return nullptr; } BaseSoundBuffer *sound; @@ -112,7 +114,7 @@ BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::M sound = new BaseSoundBuffer(_gameRef); if (!sound) { - return NULL; + return nullptr; } sound->setStreaming(streamed); @@ -123,7 +125,7 @@ BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::M if (DID_FAIL(res)) { _gameRef->LOG(res, "Error loading sound '%s'", useFilename.c_str()); delete sound; - return NULL; + return nullptr; } // Make sure the master-volume is applied to the sound. @@ -134,7 +136,7 @@ BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::M return sound; - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -217,6 +219,11 @@ byte BaseSoundMgr::getVolumePercent(Audio::Mixer::SoundType type) { ////////////////////////////////////////////////////////////////////////// bool BaseSoundMgr::setMasterVolume(byte value) { + // This function intentionally doesn't touch _volumeMasterPercent, + // as that variable keeps track of what the game actually wanted, + // and this gives a close approximation, while letting the game + // be none the wiser about round-off-errors. This function should thus + // ONLY be called by setMasterVolumePercent. _volumeMaster = value; for (uint32 i = 0; i < _sounds.size(); i++) { _sounds[i]->updateVolume(); @@ -226,14 +233,15 @@ bool BaseSoundMgr::setMasterVolume(byte value) { ////////////////////////////////////////////////////////////////////////// bool BaseSoundMgr::setMasterVolumePercent(byte percent) { - setMasterVolume(percent * 255 / 100); + _volumeMasterPercent = percent; + setMasterVolume((int)ceil(percent * 255.0 / 100.0)); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// byte BaseSoundMgr::getMasterVolumePercent() { - return getMasterVolume() * 100 / 255; + return _volumeMasterPercent; } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/base/sound/base_sound_manager.h b/engines/wintermute/base/sound/base_sound_manager.h index 36a729b5ae..1ee3c13fdb 100644 --- a/engines/wintermute/base/sound/base_sound_manager.h +++ b/engines/wintermute/base/sound/base_sound_manager.h @@ -45,7 +45,6 @@ public: //DECLARE_PERSISTENT(BaseSoundMgr, BaseClass); byte getMasterVolumePercent(); byte getMasterVolume(); - bool setMasterVolume(byte percent); bool setMasterVolumePercent(byte percent); byte getVolumePercent(Audio::Mixer::SoundType type); bool setVolumePercent(Audio::Mixer::SoundType type, byte percent); @@ -61,6 +60,9 @@ public: virtual ~BaseSoundMgr(); Common::Array<BaseSoundBuffer *> _sounds; void saveSettings(); +private: + int _volumeMasterPercent; // Necessary to avoid round-offs. + bool setMasterVolume(byte percent); }; } // end of namespace Wintermute diff --git a/engines/wintermute/dcgf.h b/engines/wintermute/dcgf.h index fc4174094b..4f8e96e0ac 100644 --- a/engines/wintermute/dcgf.h +++ b/engines/wintermute/dcgf.h @@ -34,10 +34,10 @@ #define DCGF_VER_MAJOR 1 #define DCGF_VER_MINOR 1 #define DCGF_VER_BUILD 1 -#define DCGF_VER_SUFFIX "beta" +#define DCGF_VER_SUFFIX "ScummVM" #define DCGF_VER_BETA true -#define DCGF_NAME "WME Lite" +#define DCGF_NAME "WME-ScummVM" #define DCGF_MAGIC 0xDEC0ADDE // minimal saved game version we support diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp new file mode 100644 index 0000000000..1160a16d37 --- /dev/null +++ b/engines/wintermute/debugger.cpp @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "engines/wintermute/debugger.h" +#include "engines/wintermute/wintermute.h" +#include "engines/wintermute/base/base_game.h" + +namespace Wintermute { + +Console::Console(WintermuteEngine *vm) : GUI::Debugger(), _engineRef(vm) { + DCmd_Register("show_fps", WRAP_METHOD(Console, Cmd_ShowFps)); +} + +Console::~Console(void) { + +} + +bool Console::Cmd_ShowFps(int argc, const char **argv) { + if (argc > 1) { + if (Common::String(argv[1]) == "true") { + _engineRef->_game->_debugShowFPS = true; + } else if (Common::String(argv[1]) == "false") { + _engineRef->_game->_debugShowFPS = false; + } + } + return true; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/file/base_resources.h b/engines/wintermute/debugger.h index 91c30bcfa7..069980385e 100644 --- a/engines/wintermute/base/file/base_resources.h +++ b/engines/wintermute/debugger.h @@ -8,38 +8,36 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_BASE_RESOURCES_H -#define WINTERMUTE_BASE_RESOURCES_H +#ifndef WINTERMUTE_DEBUGGER_H +#define WINTERMUTE_DEBUGGER_H -#include "common/stream.h" -#include "common/str.h" +#include "gui/debugger.h" namespace Wintermute { -class BaseResources { +class WintermuteEngine; +class Console : public GUI::Debugger { public: - static Common::SeekableReadStream *getFile(const Common::String &filename); - static bool hasFile(const Common::String &filename); + Console(WintermuteEngine *vm); + virtual ~Console(); + + bool Cmd_ShowFps(int argc, const char **argv); +private: + WintermuteEngine *_engineRef; }; -} // end of namespace Wintermute +} -#endif +#endif // WINTERMUTE_DEBUGGER_H diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index 04f7f3b112..1bf2c76a50 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -28,6 +28,7 @@ #include "common/error.h" #include "common/fs.h" #include "common/util.h" +#include "common/translation.h" #include "engines/metaengine.h" @@ -49,6 +50,20 @@ static ADGameDescription s_fallbackDesc = { ADGF_UNSTABLE, GUIO0() }; + +static const ADExtraGuiOptionsMap gameGuiOptions[] = { + { + GAMEOPTION_SHOW_FPS, + { + _s("Show FPS-counter"), + _s("Show the current number of frames per second in the upper left corner"), + "show_fps", + false + } + }, + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + static char s_fallbackGameIdBuf[256]; static const char *directoryGlobs[] = { @@ -58,8 +73,9 @@ static const char *directoryGlobs[] = { class WintermuteMetaEngine : public AdvancedMetaEngine { public: - WintermuteMetaEngine() : AdvancedMetaEngine(Wintermute::gameDescriptions, sizeof(ADGameDescription), Wintermute::wintermuteGames) { + WintermuteMetaEngine() : AdvancedMetaEngine(Wintermute::gameDescriptions, sizeof(ADGameDescription), Wintermute::wintermuteGames, gameGuiOptions) { _singleid = "wintermute"; + _guioptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_SHOW_FPS); _maxScanDepth = 2; _directoryGlobs = directoryGlobs; } diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h index 4f8a962591..6b6dec635d 100644 --- a/engines/wintermute/detection_tables.h +++ b/engines/wintermute/detection_tables.h @@ -22,6 +22,8 @@ namespace Wintermute { +#define GAMEOPTION_SHOW_FPS GUIO_GAMEOPTIONS1 + static const PlainGameDescriptor wintermuteGames[] = { {"5ld", "Five Lethal Demons"}, {"5ma", "Five Magical Amulets"}, @@ -84,6 +86,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Chivalry is Not Dead (Version from deirdrakai.com) + { + "chivalry", + "", + AD_ENTRY1s("data.dcp", "ae6d91b9517f4d2851a8ad94c96951c8", 7278302), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // Dead City (English) { "deadcity", diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp index 9319899495..11aeb26821 100644 --- a/engines/wintermute/graphics/transparent_surface.cpp +++ b/engines/wintermute/graphics/transparent_surface.cpp @@ -29,11 +29,11 @@ namespace Wintermute { -byte *TransparentSurface::_lookup = NULL; +byte *TransparentSurface::_lookup = nullptr; void TransparentSurface::destroyLookup() { - delete _lookup; - _lookup = NULL; + delete[] _lookup; + _lookup = nullptr; } TransparentSurface::TransparentSurface() : Surface(), _enableAlphaBlit(true) {} @@ -219,8 +219,8 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p #endif Graphics::Surface *img; - Graphics::Surface *imgScaled = NULL; - byte *savedPixels = NULL; + Graphics::Surface *imgScaled = nullptr; + byte *savedPixels = nullptr; if ((width != srcImage.w) || (height != srcImage.h)) { // Scale the image img = imgScaled = srcImage.scale(width, height); @@ -394,6 +394,8 @@ TransparentSurface *TransparentSurface::scale(const Common::Rect &srcRect, const // dstRect(x, y) = srcRect(x * srcW / dstW, y * srcH / dstH); TransparentSurface *target = new TransparentSurface(); + assert(format.bytesPerPixel == 4); + int srcW = srcRect.width(); int srcH = srcRect.height(); int dstW = dstRect.width(); diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h index 8b00dccbd9..dc079a1fbc 100644 --- a/engines/wintermute/graphics/transparent_surface.h +++ b/engines/wintermute/graphics/transparent_surface.h @@ -98,7 +98,7 @@ struct TransparentSurface : public Graphics::Surface { Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0, int flipping = FLIP_NONE, - Common::Rect *pPartRect = NULL, + Common::Rect *pPartRect = nullptr, uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1); void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk index 7b5b1b1a3a..5c0406b353 100644 --- a/engines/wintermute/module.mk +++ b/engines/wintermute/module.mk @@ -42,7 +42,6 @@ MODULE_OBJS := \ base/file/base_file.o \ base/file/base_file_entry.o \ base/file/base_package.o \ - base/file/base_resources.o \ base/file/base_save_thumb_file.o \ base/font/base_font_bitmap.o \ base/font/base_font_truetype.o \ @@ -53,6 +52,7 @@ MODULE_OBJS := \ base/gfx/base_surface.o \ base/gfx/osystem/base_surface_osystem.o \ base/gfx/osystem/base_render_osystem.o \ + base/gfx/osystem/render_ticket.o \ base/particles/part_particle.o \ base/particles/part_emitter.o \ base/particles/part_force.o \ @@ -67,6 +67,7 @@ MODULE_OBJS := \ base/base_file_manager.o \ base/base_frame.o \ base/base_game.o \ + base/base_game_music.o \ base/base_keyboard_state.o \ base/base_named_object.o \ base/base_object.o \ @@ -108,6 +109,7 @@ MODULE_OBJS := \ utils/utils.o \ video/video_player.o \ video/video_theora_player.o \ + debugger.o \ wintermute.o \ persistent.o diff --git a/engines/wintermute/persistent.h b/engines/wintermute/persistent.h index c862df5d6b..ca9281f798 100644 --- a/engines/wintermute/persistent.h +++ b/engines/wintermute/persistent.h @@ -36,53 +36,53 @@ class BasePersistenceManager; // persistence support typedef void *(*PERSISTBUILD)(void); typedef bool(*PERSISTLOAD)(void *, BasePersistenceManager *); -typedef void (*SYS_INSTANCE_CALLBACK)(void *Instance, void *Data); +typedef void(*SYS_INSTANCE_CALLBACK)(void *instance, void *data); } // end of namespace Wintermute #include "engines/wintermute/system/sys_class_registry.h" namespace Wintermute { -#define DECLARE_PERSISTENT(class_name, parent_class)\ +#define DECLARE_PERSISTENT(className, parentClass)\ static const char _className[];\ - static void* persistBuild(void);\ - virtual const char* getClassName();\ + static void *persistBuild(void);\ + virtual const char *getClassName();\ static bool persistLoad(void* Instance, BasePersistenceManager* PersistMgr);\ - class_name(TDynamicConstructor p1, TDynamicConstructor p2) :parent_class(p1, p2){ /*memset(this, 0, sizeof(class_name));*/ };\ - virtual bool persist(BasePersistenceManager* PersistMgr);\ + className(TDynamicConstructor p1, TDynamicConstructor p2) : parentClass(p1, p2) { /*memset(this, 0, sizeof(class_name));*/ };\ + virtual bool persist(BasePersistenceManager *persistMgr);\ void* operator new (size_t size);\ void operator delete(void* p);\ -#define IMPLEMENT_PERSISTENT(class_name, persistent_class)\ - const char class_name::_className[] = #class_name;\ - void* class_name::persistBuild(){\ - return ::new class_name(DYNAMIC_CONSTRUCTOR, DYNAMIC_CONSTRUCTOR);\ +#define IMPLEMENT_PERSISTENT(className, persistentClass)\ + const char className::_className[] = #className;\ + void* className::persistBuild() {\ + return ::new className(DYNAMIC_CONSTRUCTOR, DYNAMIC_CONSTRUCTOR);\ }\ \ - bool class_name::persistLoad(void* Instance, BasePersistenceManager* PersistMgr){\ - return ((class_name*)Instance)->persist(PersistMgr);\ + bool className::persistLoad(void *instance, BasePersistenceManager *persistMgr) {\ + return ((className*)instance)->persist(persistMgr);\ }\ \ - const char* class_name::getClassName(){\ - return #class_name;\ + const char *className::getClassName() {\ + return #className;\ }\ \ /*SystemClass Register##class_name(class_name::_className, class_name::PersistBuild, class_name::PersistLoad, persistent_class);*/\ \ - void* class_name::operator new (size_t size){\ + void* className::operator new(size_t size) {\ void* ret = ::operator new(size);\ - SystemClassRegistry::getInstance()->registerInstance(#class_name, ret);\ + SystemClassRegistry::getInstance()->registerInstance(#className, ret);\ return ret;\ }\ \ - void class_name::operator delete (void* p){\ - SystemClassRegistry::getInstance()->unregisterInstance(#class_name, p);\ + void className::operator delete(void *p) {\ + SystemClassRegistry::getInstance()->unregisterInstance(#className, p);\ ::operator delete(p);\ }\ -#define TMEMBER(member_name) #member_name, &member_name -#define TMEMBER_INT(member_name) #member_name, (int*)&member_name +#define TMEMBER(memberName) #memberName, &memberName +#define TMEMBER_INT(memberName) #memberName, (int*)&memberName } // end of namespace Wintermute diff --git a/engines/wintermute/platform_osystem.cpp b/engines/wintermute/platform_osystem.cpp index 0bd99b11cd..362c0da624 100644 --- a/engines/wintermute/platform_osystem.cpp +++ b/engines/wintermute/platform_osystem.cpp @@ -26,6 +26,7 @@ * Copyright (c) 2011 Jan Nedoma */ +#include "engines/wintermute/wintermute.h" #include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" #include "engines/wintermute/platform_osystem.h" @@ -35,14 +36,21 @@ namespace Wintermute { -BaseGame *BasePlatform::_gameRef = NULL; +BaseGame *BasePlatform::_gameRef = nullptr; +WintermuteEngine *BasePlatform::_engineRef = nullptr; #define CLASS_NAME "GF_FRAME" -int BasePlatform::initialize(BaseGame *inGame, int argc, char *argv[]) { +int BasePlatform::initialize(WintermuteEngine *engineRef, BaseGame *inGame, int argc, char *argv[]) { _gameRef = inGame; + _engineRef = engineRef; return true; } +void BasePlatform::deinit() { + _gameRef = nullptr; + _engineRef = nullptr; +} + ////////////////////////////////////////////////////////////////////////// void BasePlatform::handleEvent(Common::Event *event) { switch (event->type) { @@ -86,6 +94,11 @@ void BasePlatform::handleEvent(Common::Event *event) { } break; case Common::EVENT_KEYDOWN: + if (event->kbd.flags & Common::KBD_CTRL) { + if (event->kbd.keycode == Common::KEYCODE_d) { + _engineRef->trigDebugger(); + } + } if (_gameRef) { _gameRef->handleKeypress(event); } @@ -234,7 +247,7 @@ bool BasePlatform::unionRect(Rect32 *lprcDst, Rect32 *lprcSrc1, Rect32 *lprcSrc2 ////////////////////////////////////////////////////////////////////////// bool BasePlatform::copyRect(Rect32 *lprcDst, Rect32 *lprcSrc) { - if (lprcDst == NULL || lprcSrc == NULL) { + if (lprcDst == nullptr || lprcSrc == nullptr) { return false; } diff --git a/engines/wintermute/platform_osystem.h b/engines/wintermute/platform_osystem.h index 21a77e0a0e..8c39b29ea9 100644 --- a/engines/wintermute/platform_osystem.h +++ b/engines/wintermute/platform_osystem.h @@ -36,11 +36,12 @@ namespace Wintermute { class BaseGame; - +class WintermuteEngine; ////////////////////////////////////////////////////////////////////////// class BasePlatform { public: - static int initialize(BaseGame *inGame, int argc, char *argv[]); + static int initialize(WintermuteEngine *engineRef, BaseGame *inGame, int argc, char *argv[]); + static void deinit(); static void handleEvent(Common::Event *event); static AnsiString getPlatformName(); @@ -66,6 +67,7 @@ public: private: // Set by initialize on game-startup, the object referred to is also deleted by deinit in WintermuteEngine static BaseGame *_gameRef; + static WintermuteEngine *_engineRef; }; } // end of namespace Wintermute diff --git a/engines/wintermute/system/sys_class.cpp b/engines/wintermute/system/sys_class.cpp index 06b36b84de..cda58bbb48 100644 --- a/engines/wintermute/system/sys_class.cpp +++ b/engines/wintermute/system/sys_class.cpp @@ -41,7 +41,7 @@ SystemClass::SystemClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD _build = build; _load = load; - _next = NULL; + _next = nullptr; _savedID = -1; _persistent = persistentClass; _numInst = 0; @@ -119,7 +119,7 @@ void *SystemClass::idToPointer(int savedID) { return (it->_value)->getInstance(); } } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/system/sys_class_registry.cpp b/engines/wintermute/system/sys_class_registry.cpp index 7c1911c2bf..3e2b8665ee 100644 --- a/engines/wintermute/system/sys_class_registry.cpp +++ b/engines/wintermute/system/sys_class_registry.cpp @@ -115,7 +115,7 @@ bool SystemClassRegistry::registerInstance(const char *className, void *instance } SystemInstance *inst = (*mapIt)._value->addInstance(instance, _count++); - return (inst != NULL); + return (inst != nullptr); } ////////////////////////////////////////////////////////////////////////// @@ -152,7 +152,7 @@ bool SystemClassRegistry::unregisterInstance(const char *className, void *instan ////////////////////////////////////////////////////////////////////////// bool SystemClassRegistry::getPointerID(void *pointer, int *classID, int *instanceID) { - if (pointer == NULL) { + if (pointer == nullptr) { return true; } @@ -173,7 +173,7 @@ bool SystemClassRegistry::getPointerID(void *pointer, int *classID, int *instanc void *SystemClassRegistry::idToPointer(int classID, int instanceID) { SavedInstanceMap::iterator it = _savedInstanceMap.find(instanceID); if (it == _savedInstanceMap.end()) { - return NULL; + return nullptr; } else { return (*it)._value->getInstance(); } diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp index 7967d566f9..6ee577f009 100644 --- a/engines/wintermute/ui/ui_button.cpp +++ b/engines/wintermute/ui/ui_button.cpp @@ -48,11 +48,11 @@ IMPLEMENT_PERSISTENT(UIButton, false) ////////////////////////////////////////////////////////////////////////// UIButton::UIButton(BaseGame *inGame) : UIObject(inGame) { - _backPress = _backHover = _backDisable = _backFocus = NULL; + _backPress = _backHover = _backDisable = _backFocus = nullptr; - _fontHover = _fontPress = _fontDisable = _fontFocus = NULL; + _fontHover = _fontPress = _fontDisable = _fontFocus = nullptr; - _imageDisable = _imagePress = _imageHover = _imageFocus = NULL; + _imageDisable = _imagePress = _imageHover = _imageFocus = nullptr; _align = TAL_CENTER; @@ -104,7 +104,7 @@ UIButton::~UIButton() { ////////////////////////////////////////////////////////////////////////// bool UIButton::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "UIButton::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -235,7 +235,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _back = new UITiledImage(_gameRef); if (!_back || DID_FAIL(_back->loadFile((char *)params))) { delete _back; - _back = NULL; + _back = nullptr; cmd = PARSERR_GENERIC; } break; @@ -245,7 +245,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _backHover = new UITiledImage(_gameRef); if (!_backHover || DID_FAIL(_backHover->loadFile((char *)params))) { delete _backHover; - _backHover = NULL; + _backHover = nullptr; cmd = PARSERR_GENERIC; } break; @@ -255,7 +255,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _backPress = new UITiledImage(_gameRef); if (!_backPress || DID_FAIL(_backPress->loadFile((char *)params))) { delete _backPress; - _backPress = NULL; + _backPress = nullptr; cmd = PARSERR_GENERIC; } break; @@ -265,7 +265,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _backDisable = new UITiledImage(_gameRef); if (!_backDisable || DID_FAIL(_backDisable->loadFile((char *)params))) { delete _backDisable; - _backDisable = NULL; + _backDisable = nullptr; cmd = PARSERR_GENERIC; } break; @@ -275,7 +275,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _backFocus = new UITiledImage(_gameRef); if (!_backFocus || DID_FAIL(_backFocus->loadFile((char *)params))) { delete _backFocus; - _backFocus = NULL; + _backFocus = nullptr; cmd = PARSERR_GENERIC; } break; @@ -285,7 +285,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _image = new BaseSprite(_gameRef); if (!_image || DID_FAIL(_image->loadFile((char *)params))) { delete _image; - _image = NULL; + _image = nullptr; cmd = PARSERR_GENERIC; } break; @@ -295,7 +295,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _imageHover = new BaseSprite(_gameRef); if (!_imageHover || DID_FAIL(_imageHover->loadFile((char *)params))) { delete _imageHover; - _imageHover = NULL; + _imageHover = nullptr; cmd = PARSERR_GENERIC; } break; @@ -305,7 +305,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _imagePress = new BaseSprite(_gameRef); if (!_imagePress || DID_FAIL(_imagePress->loadFile((char *)params))) { delete _imagePress; - _imagePress = NULL; + _imagePress = nullptr; cmd = PARSERR_GENERIC; } break; @@ -315,7 +315,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _imageDisable = new BaseSprite(_gameRef); if (!_imageDisable || DID_FAIL(_imageDisable->loadFile((char *)params))) { delete _imageDisable; - _imageDisable = NULL; + _imageDisable = nullptr; cmd = PARSERR_GENERIC; } break; @@ -325,7 +325,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _imageFocus = new BaseSprite(_gameRef); if (!_imageFocus || DID_FAIL(_imageFocus->loadFile((char *)params))) { delete _imageFocus; - _imageFocus = NULL; + _imageFocus = nullptr; cmd = PARSERR_GENERIC; } break; @@ -416,7 +416,7 @@ bool UIButton::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -592,7 +592,7 @@ bool UIButton::saveAsText(BaseDynamicBuffer *buffer, int indent) { void UIButton::correctSize() { Rect32 rect; - BaseSprite *img = NULL; + BaseSprite *img = nullptr; if (_image) { img = _image; } else if (_imageDisable) { @@ -622,15 +622,15 @@ void UIButton::correctSize() { } if (_text) { - int text_height; + int textHeight; if (_font) { - text_height = _font->getTextHeight((byte *)_text, _width); + textHeight = _font->getTextHeight((byte *)_text, _width); } else { - text_height = _gameRef->_systemFont->getTextHeight((byte *)_text, _width); + textHeight = _gameRef->getSystemFont()->getTextHeight((byte *)_text, _width); } - if (text_height > _height) { - _height = text_height; + if (textHeight > _height) { + _height = textHeight; } } @@ -650,8 +650,8 @@ bool UIButton::display(int offsetX, int offsetY) { return STATUS_OK; } - UITiledImage *back = NULL; - BaseSprite *image = NULL; + UITiledImage *back = nullptr; + BaseSprite *image = nullptr; BaseFont *font = 0; //RECT rect; @@ -717,7 +717,7 @@ bool UIButton::display(int offsetX, int offsetY) { if (_font) { font = _font; } else { - font = _gameRef->_systemFont; + font = _gameRef->getSystemFont(); } } @@ -734,9 +734,9 @@ bool UIButton::display(int offsetX, int offsetY) { if (back) { back->display(offsetX + _posX, offsetY + _posY, _width, _height); } - //if (image) image->Draw(ImageX +((_press||_oneTimePress)&&back?1:0), ImageY +((_press||_oneTimePress)&&back?1:0), NULL); + //if (image) image->Draw(ImageX +((_press||_oneTimePress)&&back?1:0), ImageY +((_press||_oneTimePress)&&back?1:0), nullptr); if (image) { - image->draw(imageX + ((_press || _oneTimePress) && back ? 1 : 0), imageY + ((_press || _oneTimePress) && back ? 1 : 0), _pixelPerfect ? this : NULL); + image->draw(imageX + ((_press || _oneTimePress) && back ? 1 : 0), imageY + ((_press || _oneTimePress) && back ? 1 : 0), _pixelPerfect ? this : nullptr); } if (font && _text) { @@ -745,7 +745,7 @@ bool UIButton::display(int offsetX, int offsetY) { } if (!_pixelPerfect || !_image) { - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, nullptr, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); } // reset unused sprites @@ -800,11 +800,11 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _gameRef->_fontStorage->removeFont(_fontDisable); } if (val->isNULL()) { - _fontDisable = NULL; + _fontDisable = nullptr; stack->pushBool(true); } else { _fontDisable = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontDisable != NULL); + stack->pushBool(_fontDisable != nullptr); } return STATUS_OK; } @@ -820,11 +820,11 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _gameRef->_fontStorage->removeFont(_fontHover); } if (val->isNULL()) { - _fontHover = NULL; + _fontHover = nullptr; stack->pushBool(true); } else { _fontHover = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontHover != NULL); + stack->pushBool(_fontHover != nullptr); } return STATUS_OK; } @@ -840,11 +840,11 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _gameRef->_fontStorage->removeFont(_fontPress); } if (val->isNULL()) { - _fontPress = NULL; + _fontPress = nullptr; stack->pushBool(true); } else { _fontPress = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontPress != NULL); + stack->pushBool(_fontPress != nullptr); } return STATUS_OK; } @@ -860,11 +860,11 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _gameRef->_fontStorage->removeFont(_fontFocus); } if (val->isNULL()) { - _fontFocus = NULL; + _fontFocus = nullptr; stack->pushBool(true); } else { _fontFocus = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontFocus != NULL); + stack->pushBool(_fontFocus != nullptr); } return STATUS_OK; } @@ -880,7 +880,7 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack const char *filename = stack->pop()->getString(); if (!_imageDisable || DID_FAIL(_imageDisable->loadFile(filename))) { delete _imageDisable; - _imageDisable = NULL; + _imageDisable = nullptr; stack->pushBool(false); } else { stack->pushBool(true); @@ -929,7 +929,7 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack const char *filename = stack->pop()->getString(); if (!_imageHover || DID_FAIL(_imageHover->loadFile(filename))) { delete _imageHover; - _imageHover = NULL; + _imageHover = nullptr; stack->pushBool(false); } else { stack->pushBool(true); @@ -977,7 +977,7 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack const char *filename = stack->pop()->getString(); if (!_imagePress || DID_FAIL(_imagePress->loadFile(filename))) { delete _imagePress; - _imagePress = NULL; + _imagePress = nullptr; stack->pushBool(false); } else { stack->pushBool(true); @@ -1025,7 +1025,7 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack const char *filename = stack->pop()->getString(); if (!_imageFocus || DID_FAIL(_imageFocus->loadFile(filename))) { delete _imageFocus; - _imageFocus = NULL; + _imageFocus = nullptr; stack->pushBool(false); } else { stack->pushBool(true); diff --git a/engines/wintermute/ui/ui_button.h b/engines/wintermute/ui/ui_button.h index 93333a2534..fea264976f 100644 --- a/engines/wintermute/ui/ui_button.h +++ b/engines/wintermute/ui/ui_button.h @@ -62,7 +62,7 @@ public: UITiledImage *_backHover; UITiledImage *_backDisable; UITiledImage *_backFocus; - UIButton(BaseGame *inGame = NULL); + UIButton(BaseGame *inGame = nullptr); virtual ~UIButton(); bool loadFile(const char *filename); bool loadBuffer(byte *buffer, bool complete = true); diff --git a/engines/wintermute/ui/ui_edit.cpp b/engines/wintermute/ui/ui_edit.cpp index a3283d5a01..0a2e6f13bc 100644 --- a/engines/wintermute/ui/ui_edit.cpp +++ b/engines/wintermute/ui/ui_edit.cpp @@ -56,12 +56,12 @@ IMPLEMENT_PERSISTENT(UIEdit, false) UIEdit::UIEdit(BaseGame *inGame) : UIObject(inGame) { _type = UI_EDIT; - _fontSelected = NULL; + _fontSelected = nullptr; _selStart = _selEnd = 10000; _scrollOffset = 0; - _cursorChar = NULL; + _cursorChar = nullptr; setCursorChar("|"); _cursorBlinkRate = 600; @@ -88,14 +88,14 @@ UIEdit::~UIEdit() { } delete[] _cursorChar; - _cursorChar = NULL; + _cursorChar = nullptr; } ////////////////////////////////////////////////////////////////////////// bool UIEdit::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "UIEdit::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -194,7 +194,7 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) { _back = new UITiledImage(_gameRef); if (!_back || DID_FAIL(_back->loadFile((char *)params))) { delete _back; - _back = NULL; + _back = nullptr; cmd = PARSERR_GENERIC; } break; @@ -204,7 +204,7 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) { _image = new BaseSprite(_gameRef); if (!_image || DID_FAIL(_image->loadFile((char *)params))) { delete _image; - _image = NULL; + _image = nullptr; cmd = PARSERR_GENERIC; } break; @@ -263,7 +263,7 @@ bool UIEdit::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -388,7 +388,7 @@ bool UIEdit::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, _gameRef->_fontStorage->removeFont(_fontSelected); } _fontSelected = _gameRef->_fontStorage->addFont(stack->pop()->getString()); - stack->pushBool(_fontSelected != NULL); + stack->pushBool(_fontSelected != nullptr); return STATUS_OK; } else { @@ -579,7 +579,7 @@ bool UIEdit::display(int offsetX, int offsetY) { _back->display(offsetX + _posX, offsetY + _posY, _width, _height); } if (_image) { - _image->draw(offsetX + _posX, offsetY + _posY, NULL); + _image->draw(offsetX + _posX, offsetY + _posY, nullptr); } // prepare fonts @@ -589,7 +589,7 @@ bool UIEdit::display(int offsetX, int offsetY) { if (_font) { font = _font; } else { - font = _gameRef->_systemFont; + font = _gameRef->getSystemFont(); } if (_fontSelected) { @@ -726,7 +726,7 @@ bool UIEdit::display(int offsetX, int offsetY) { } - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, nullptr, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); _gameRef->_textEncoding = OrigEncoding; diff --git a/engines/wintermute/ui/ui_entity.cpp b/engines/wintermute/ui/ui_entity.cpp index 1cb4e0926b..00d442e895 100644 --- a/engines/wintermute/ui/ui_entity.cpp +++ b/engines/wintermute/ui/ui_entity.cpp @@ -43,7 +43,7 @@ IMPLEMENT_PERSISTENT(UIEntity, false) ////////////////////////////////////////////////////////////////////////// UIEntity::UIEntity(BaseGame *inGame) : UIObject(inGame) { _type = UI_CUSTOM; - _entity = NULL; + _entity = nullptr; } @@ -52,14 +52,14 @@ UIEntity::~UIEntity() { if (_entity) { _gameRef->unregisterObject(_entity); } - _entity = NULL; + _entity = nullptr; } ////////////////////////////////////////////////////////////////////////// bool UIEntity::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "UIEntity::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -223,7 +223,7 @@ bool UIEntity::setEntity(const char *filename) { _entity = new AdEntity(_gameRef); if (!_entity || DID_FAIL(_entity->loadFile(filename))) { delete _entity; - _entity = NULL; + _entity = nullptr; return STATUS_FAILED; } else { _entity->_nonIntMouseEvents = true; diff --git a/engines/wintermute/ui/ui_object.cpp b/engines/wintermute/ui/ui_object.cpp index 8e5bae993c..9dea3dadf9 100644 --- a/engines/wintermute/ui/ui_object.cpp +++ b/engines/wintermute/ui/ui_object.cpp @@ -43,27 +43,27 @@ IMPLEMENT_PERSISTENT(UIObject, false) ////////////////////////////////////////////////////////////////////////// UIObject::UIObject(BaseGame *inGame) : BaseObject(inGame) { - _back = NULL; - _image = NULL; - _font = NULL; - _text = NULL; + _back = nullptr; + _image = nullptr; + _font = nullptr; + _text = nullptr; _sharedFonts = _sharedImages = false; _width = _height = 0; - _listenerObject = NULL; - _listenerParamObject = NULL; + _listenerObject = nullptr; + _listenerParamObject = nullptr; _listenerParamDWORD = 0; _disable = false; _visible = true; _type = UI_UNKNOWN; - _parent = NULL; + _parent = nullptr; _parentNotify = false; - _focusedWidget = NULL; + _focusedWidget = nullptr; _canFocus = false; _nonIntMouseEvents = true; @@ -91,7 +91,7 @@ UIObject::~UIObject() { delete[] _text; } - _focusedWidget = NULL; // ref only + _focusedWidget = nullptr; // ref only } @@ -168,11 +168,11 @@ bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _gameRef->_fontStorage->removeFont(_font); } if (val->isNULL()) { - _font = NULL; + _font = nullptr; stack->pushBool(true); } else { _font = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_font != NULL); + stack->pushBool(_font != nullptr); } return STATUS_OK; } @@ -187,7 +187,7 @@ bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack /* const char *filename = */ val->getString(); delete _image; - _image = NULL; + _image = nullptr; if (val->isNULL()) { stack->pushBool(true); return STATUS_OK; @@ -196,7 +196,7 @@ bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _image = new BaseSprite(_gameRef); if (!_image || DID_FAIL(_image->loadFile(val->getString()))) { delete _image; - _image = NULL; + _image = nullptr; stack->pushBool(false); } else { stack->pushBool(true); diff --git a/engines/wintermute/ui/ui_object.h b/engines/wintermute/ui/ui_object.h index ec2ea33de1..c77acfef41 100644 --- a/engines/wintermute/ui/ui_object.h +++ b/engines/wintermute/ui/ui_object.h @@ -60,7 +60,7 @@ public: bool _visible; UITiledImage *_back; bool _disable; - UIObject(BaseGame *inGame = NULL); + UIObject(BaseGame *inGame = nullptr); virtual ~UIObject(); int _width; int _height; diff --git a/engines/wintermute/ui/ui_text.cpp b/engines/wintermute/ui/ui_text.cpp index 2c10f176c7..3b5adf07b7 100644 --- a/engines/wintermute/ui/ui_text.cpp +++ b/engines/wintermute/ui/ui_text.cpp @@ -69,14 +69,14 @@ bool UIText::display(int offsetX, int offsetY) { BaseFont *font = _font; if (!font) { - font = _gameRef->_systemFont; + font = _gameRef->getSystemFont(); } if (_back) { _back->display(offsetX + _posX, offsetY + _posY, _width, _height); } if (_image) { - _image->draw(offsetX + _posX, offsetY + _posY, NULL); + _image->draw(offsetX + _posX, offsetY + _posY, nullptr); } if (font && _text) { @@ -104,7 +104,7 @@ bool UIText::display(int offsetX, int offsetY) { ////////////////////////////////////////////////////////////////////////// bool UIText::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "UIText::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -203,7 +203,7 @@ bool UIText::loadBuffer(byte *buffer, bool complete) { _back = new UITiledImage(_gameRef); if (!_back || DID_FAIL(_back->loadFile((char *)params))) { delete _back; - _back = NULL; + _back = nullptr; cmd = PARSERR_GENERIC; } break; @@ -213,7 +213,7 @@ bool UIText::loadBuffer(byte *buffer, bool complete) { _image = new BaseSprite(_gameRef); if (!_image || DID_FAIL(_image->loadFile((char *)params))) { delete _image; - _image = NULL; + _image = nullptr; cmd = PARSERR_GENERIC; } break; @@ -274,7 +274,7 @@ bool UIText::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; diff --git a/engines/wintermute/ui/ui_text.h b/engines/wintermute/ui/ui_text.h index da4d113500..11dcdb166d 100644 --- a/engines/wintermute/ui/ui_text.h +++ b/engines/wintermute/ui/ui_text.h @@ -40,7 +40,7 @@ private: public: virtual bool display(int offsetX, int offsetY); DECLARE_PERSISTENT(UIText, UIObject) - UIText(BaseGame *inGame = NULL); + UIText(BaseGame *inGame = nullptr); virtual ~UIText(); TTextAlign _textAlign; TVerticalAlign _verticalAlign; diff --git a/engines/wintermute/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp index 2b337330c7..be9f87cf58 100644 --- a/engines/wintermute/ui/ui_tiled_image.cpp +++ b/engines/wintermute/ui/ui_tiled_image.cpp @@ -42,7 +42,7 @@ IMPLEMENT_PERSISTENT(UITiledImage, false) ////////////////////////////////////////////////////////////////////////// UITiledImage::UITiledImage(BaseGame *inGame) : BaseObject(inGame) { - _image = NULL; + _image = nullptr; BasePlatform::setRectEmpty(&_upLeft); BasePlatform::setRectEmpty(&_upMiddle); @@ -59,7 +59,7 @@ UITiledImage::UITiledImage(BaseGame *inGame) : BaseObject(inGame) { ////////////////////////////////////////////////////////////////////////// UITiledImage::~UITiledImage() { delete _image; - _image = NULL; + _image = nullptr; } @@ -104,14 +104,11 @@ bool UITiledImage::display(int x, int y, int width, int height) { } // tiles - yyy = y + (_upMiddle.bottom - _upMiddle.top); - for (row = 0; row < nuRows; row++) { + if (nuRows > 0 && nuColumns > 0) { + yyy = y + (_upMiddle.bottom - _upMiddle.top); xxx = x + (_upLeft.right - _upLeft.left); - for (col = 0; col < nuColumns; col++) { - _image->_surface->displayTrans(xxx, yyy, _middleMiddle); - xxx += tileWidth; - } - yyy += tileWidth; + _image->_surface->displayTrans(xxx, yyy, _middleMiddle); + _image->_surface->repeatLastDisplayOp(tileWidth, tileWidth, nuColumns, nuRows); } _gameRef->_renderer->endSpriteBatch(); @@ -123,7 +120,7 @@ bool UITiledImage::display(int x, int y, int width, int height) { ////////////////////////////////////////////////////////////////////////// bool UITiledImage::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "UITiledImage::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -208,7 +205,7 @@ bool UITiledImage::loadBuffer(byte *buffer, bool complete) { _image = new BaseSubFrame(_gameRef); if (!_image || DID_FAIL(_image->setSurface((char *)params))) { delete _image; - _image = NULL; + _image = nullptr; cmd = PARSERR_GENERIC; } break; diff --git a/engines/wintermute/ui/ui_tiled_image.h b/engines/wintermute/ui/ui_tiled_image.h index c413e7f129..ded7a285dd 100644 --- a/engines/wintermute/ui/ui_tiled_image.h +++ b/engines/wintermute/ui/ui_tiled_image.h @@ -44,8 +44,9 @@ public: virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); bool display(int x, int y, int width, int height); - UITiledImage(BaseGame *inGame = NULL); + UITiledImage(BaseGame *inGame = nullptr); virtual ~UITiledImage(); +private: BaseSubFrame *_image; Rect32 _upLeft; Rect32 _upMiddle; diff --git a/engines/wintermute/ui/ui_window.cpp b/engines/wintermute/ui/ui_window.cpp index 9606486efb..39bc1bdcfe 100644 --- a/engines/wintermute/ui/ui_window.cpp +++ b/engines/wintermute/ui/ui_window.cpp @@ -59,9 +59,9 @@ UIWindow::UIWindow(BaseGame *inGame) : UIObject(inGame) { _titleAlign = TAL_LEFT; _transparent = false; - _backInactive = NULL; - _fontInactive = NULL; - _imageInactive = NULL; + _backInactive = nullptr; + _fontInactive = nullptr; + _imageInactive = nullptr; _type = UI_WINDOW; _canFocus = true; @@ -70,8 +70,8 @@ UIWindow::UIWindow(BaseGame *inGame) : UIObject(inGame) { _dragFrom.x = _dragFrom.y = 0; _mode = WINDOW_NORMAL; - _shieldWindow = NULL; - _shieldButton = NULL; + _shieldWindow = nullptr; + _shieldButton = nullptr; _fadeColor = 0x00000000; _fadeBackground = false; @@ -81,7 +81,7 @@ UIWindow::UIWindow(BaseGame *inGame) : UIObject(inGame) { _inGame = false; _clipContents = false; - _viewport = NULL; + _viewport = nullptr; _pauseMusic = true; } @@ -99,9 +99,9 @@ void UIWindow::cleanup() { delete _shieldWindow; delete _shieldButton; delete _viewport; - _shieldWindow = NULL; - _shieldButton = NULL; - _viewport = NULL; + _shieldWindow = nullptr; + _shieldButton = nullptr; + _viewport = nullptr; delete _backInactive; if (!_sharedFonts && _fontInactive) { @@ -210,7 +210,7 @@ bool UIWindow::display(int offsetX, int offsetY) { back->display(_posX + offsetX, _posY + offsetY, _width, _height); } if (image) { - image->draw(_posX + offsetX, _posY + offsetY, _transparent ? NULL : this); + image->draw(_posX + offsetX, _posY + offsetY, _transparent ? nullptr : this); } if (!BasePlatform::isRectEmpty(&_titleRect) && font && _text) { @@ -218,7 +218,7 @@ bool UIWindow::display(int offsetX, int offsetY) { } if (!_transparent && !image) { - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, nullptr, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); } for (uint32 i = 0; i < _widgets.size(); i++) { @@ -240,7 +240,7 @@ bool UIWindow::display(int offsetX, int offsetY) { ////////////////////////////////////////////////////////////////////////// bool UIWindow::loadFile(const char *filename) { byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { + if (buffer == nullptr) { _gameRef->LOG(0, "UIWindow::LoadFile failed for file '%s'", filename); return STATUS_FAILED; } @@ -374,7 +374,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { _back = new UITiledImage(_gameRef); if (!_back || DID_FAIL(_back->loadFile((char *)params))) { delete _back; - _back = NULL; + _back = nullptr; cmd = PARSERR_GENERIC; } break; @@ -384,7 +384,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { _backInactive = new UITiledImage(_gameRef); if (!_backInactive || DID_FAIL(_backInactive->loadFile((char *)params))) { delete _backInactive; - _backInactive = NULL; + _backInactive = nullptr; cmd = PARSERR_GENERIC; } break; @@ -394,7 +394,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { _image = new BaseSprite(_gameRef); if (!_image || DID_FAIL(_image->loadFile((char *)params))) { delete _image; - _image = NULL; + _image = nullptr; cmd = PARSERR_GENERIC; } break; @@ -404,7 +404,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { _imageInactive = new BaseSprite(_gameRef); if (!_imageInactive || DID_FAIL(_imageInactive->loadFile((char *)params))) { delete _imageInactive; - _imageInactive = NULL; + _imageInactive = nullptr; cmd = PARSERR_GENERIC; } break; @@ -473,7 +473,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { _cursor = new BaseSprite(_gameRef); if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) { delete _cursor; - _cursor = NULL; + _cursor = nullptr; cmd = PARSERR_GENERIC; } break; @@ -482,7 +482,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { UIButton *btn = new UIButton(_gameRef); if (!btn || DID_FAIL(btn->loadBuffer(params, false))) { delete btn; - btn = NULL; + btn = nullptr; cmd = PARSERR_GENERIC; } else { btn->_parent = this; @@ -495,7 +495,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { UIText *text = new UIText(_gameRef); if (!text || DID_FAIL(text->loadBuffer(params, false))) { delete text; - text = NULL; + text = nullptr; cmd = PARSERR_GENERIC; } else { text->_parent = this; @@ -508,7 +508,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { UIEdit *edit = new UIEdit(_gameRef); if (!edit || DID_FAIL(edit->loadBuffer(params, false))) { delete edit; - edit = NULL; + edit = nullptr; cmd = PARSERR_GENERIC; } else { edit->_parent = this; @@ -521,7 +521,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { UIWindow *win = new UIWindow(_gameRef); if (!win || DID_FAIL(win->loadBuffer(params, false))) { delete win; - win = NULL; + win = nullptr; cmd = PARSERR_GENERIC; } else { win->_parent = this; @@ -616,7 +616,7 @@ bool UIWindow::loadBuffer(byte *buffer, bool complete) { _fadeColor = BYTETORGBA(fadeR, fadeG, fadeB, fadeA); } - _focusedWidget = NULL; + _focusedWidget = nullptr; return STATUS_OK; } @@ -795,7 +795,7 @@ bool UIWindow::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack _gameRef->_fontStorage->removeFont(_fontInactive); } _fontInactive = _gameRef->_fontStorage->addFont(stack->pop()->getString()); - stack->pushBool(_fontInactive != NULL); + stack->pushBool(_fontInactive != nullptr); return STATUS_OK; } @@ -811,7 +811,7 @@ bool UIWindow::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack const char *filename = stack->pop()->getString(); if (!_imageInactive || DID_FAIL(_imageInactive->loadFile(filename))) { delete _imageInactive; - _imageInactive = NULL; + _imageInactive = nullptr; stack->pushBool(false); } else { stack->pushBool(true); @@ -1294,7 +1294,7 @@ bool UIWindow::moveFocus(bool forward) { } } if (!found) { - _focusedWidget = NULL; + _focusedWidget = nullptr; } if (!_focusedWidget) { diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp index 7b3b0e1297..9fffad85cd 100644 --- a/engines/wintermute/utils/string_util.cpp +++ b/engines/wintermute/utils/string_util.cpp @@ -205,7 +205,7 @@ bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) { ////////////////////////////////////////////////////////////////////////// int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) { const char *index = strstr(str.c_str(), toFind.c_str()); - if (index == NULL) { + if (index == nullptr) { return -1; } else { return index - str.c_str(); @@ -213,8 +213,10 @@ int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t } Common::String StringUtil::encodeSetting(const Common::String &str) { - if (str.contains('=')) { - error("Setting contains '='"); + for (uint32 i = 0; i < str.size(); i++) { + if ((str[i] < 33) || (str[i] == '=') || (str[i] > 126)) { + error("Setting contains illegal characters: %s", str.c_str()); + } } return str; } diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp index 824b16ccdb..6e0d69edbe 100644 --- a/engines/wintermute/utils/utils.cpp +++ b/engines/wintermute/utils/utils.cpp @@ -96,7 +96,7 @@ char *BaseUtils::setString(char **string, const char *value) { char *BaseUtils::strEntry(int entry, const char *str, const char delim) { int numEntries = 0; - const char *start = NULL; + const char *start = nullptr; int len = 0; for (uint32 i = 0; i <= strlen(str); i++) { @@ -117,7 +117,7 @@ char *BaseUtils::strEntry(int entry, const char *str, const char delim) { } } } - return NULL; + return nullptr; } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/video/video_player.cpp b/engines/wintermute/video/video_player.cpp index 2577b8aedc..42857b5c1b 100644 --- a/engines/wintermute/video/video_player.cpp +++ b/engines/wintermute/video/video_player.cpp @@ -50,7 +50,7 @@ bool VideoPlayer::setDefaults() { _playPosX = _playPosY = 0; _playZoom = 0.0f; - _filename = NULL; + _filename = nullptr; _slowRendering = false; diff --git a/engines/wintermute/video/video_player.h b/engines/wintermute/video/video_player.h index d5466da679..a49e910b0c 100644 --- a/engines/wintermute/video/video_player.h +++ b/engines/wintermute/video/video_player.h @@ -58,7 +58,7 @@ public: bool _playing; bool display(); bool update(); - bool initialize(const char *inFilename, const char *subtitleFile = NULL); + bool initialize(const char *inFilename, const char *subtitleFile = nullptr); bool cleanup(); VideoPlayer(BaseGame *inGame); virtual ~VideoPlayer(); diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp index d14c807e11..1f6842c416 100644 --- a/engines/wintermute/video/video_theora_player.cpp +++ b/engines/wintermute/video/video_theora_player.cpp @@ -51,7 +51,7 @@ VideoTheoraPlayer::VideoTheoraPlayer(BaseGame *inGame) : BaseClass(inGame) { ////////////////////////////////////////////////////////////////////////// void VideoTheoraPlayer::SetDefaults() { - _file = NULL; + _file = nullptr; _filename = ""; _startTime = 0; _looping = false; @@ -68,8 +68,8 @@ void VideoTheoraPlayer::SetDefaults() { _playbackStarted = false; _dontDropFrames = false; - _texture = NULL; - _alphaImage = NULL; + _texture = nullptr; + _alphaImage = nullptr; _alphaFilename = ""; _frameRendered = false; @@ -84,10 +84,10 @@ void VideoTheoraPlayer::SetDefaults() { _savedState = THEORA_STATE_NONE; _savedPos = 0; _volume = 100; - _theoraDecoder = NULL; + _theoraDecoder = nullptr; // TODO: Add subtitles-support - //_subtitler = NULL; + //_subtitler = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -100,7 +100,7 @@ VideoTheoraPlayer::~VideoTheoraPlayer(void) { void VideoTheoraPlayer::cleanup() { if (_file) { BaseFileManager::getEngineInstance()->closeFile(_file); - _file = NULL; + _file = nullptr; } _surface.free(); @@ -108,11 +108,11 @@ void VideoTheoraPlayer::cleanup() { _theoraDecoder->close(); } delete _theoraDecoder; - _theoraDecoder = NULL; + _theoraDecoder = nullptr; delete _alphaImage; - _alphaImage = NULL; + _alphaImage = nullptr; delete _texture; - _texture = NULL; + _texture = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -157,7 +157,7 @@ bool VideoTheoraPlayer::resetStream() { _theoraDecoder->close(); } delete _theoraDecoder; - _theoraDecoder = NULL; + _theoraDecoder = nullptr; _file = BaseFileManager::getEngineInstance()->openFile(_filename, true, false); if (!_file) { @@ -419,7 +419,7 @@ bool VideoTheoraPlayer::setAlphaImage(const Common::String &filename) { _alphaImage = new BaseImage(); if (!_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) { delete _alphaImage; - _alphaImage = NULL; + _alphaImage = nullptr; _alphaFilename = ""; return STATUS_FAILED; } diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h index 593c1b9666..7a6742271c 100644 --- a/engines/wintermute/video/video_theora_player.h +++ b/engines/wintermute/video/video_theora_player.h @@ -62,7 +62,7 @@ public: //CVidSubtitler *_subtitler; // control methods - bool initialize(const Common::String &filename, const Common::String &subtitleFile = NULL); + bool initialize(const Common::String &filename, const Common::String &subtitleFile = nullptr); bool initializeSimple(); bool update(); bool play(TVideoPlayback type = VID_PLAY_CENTER, int x = 0, int y = 0, bool freezeGame = false, bool freezeMusic = true, bool looping = false, uint32 startTime = 0, float forceZoom = -1.0f, int volume = -1); diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp index c9726e150a..f33452d11c 100644 --- a/engines/wintermute/wintermute.cpp +++ b/engines/wintermute/wintermute.cpp @@ -34,6 +34,7 @@ #include "engines/util.h" #include "engines/wintermute/ad/ad_game.h" #include "engines/wintermute/wintermute.h" +#include "engines/wintermute/debugger.h" #include "engines/wintermute/platform_osystem.h" #include "engines/wintermute/base/base_engine.h" @@ -48,6 +49,8 @@ namespace Wintermute { // This might not be the prettiest solution WintermuteEngine::WintermuteEngine() : Engine(g_system) { _game = new AdGame(""); + _debugger = nullptr; + _trigDebug = false; } WintermuteEngine::WintermuteEngine(OSystem *syst, const ADGameDescription *desc) @@ -55,6 +58,7 @@ WintermuteEngine::WintermuteEngine(OSystem *syst, const ADGameDescription *desc) // Put your engine in a sane state, but do nothing big yet; // in particular, do not load data from files; rather, if you // need to do such things, do them from init(). + ConfMan.registerDefault("show_fps","false"); // Do not initialize graphics here @@ -70,14 +74,16 @@ WintermuteEngine::WintermuteEngine(OSystem *syst, const ADGameDescription *desc) DebugMan.addDebugChannel(kWintermuteDebugAudio, "audio", "audio-playback-related issues"); DebugMan.addDebugChannel(kWintermuteDebugGeneral, "general", "various issues not covered by any of the above"); - _game = NULL; + _game = nullptr; + _debugger = nullptr; + _trigDebug = false; } WintermuteEngine::~WintermuteEngine() { // Dispose your resources here deinit(); delete _game; - delete _console; + delete _debugger; // Remove all of our debug levels here DebugMan.clearAllDebugChannels(); @@ -106,7 +112,7 @@ Common::Error WintermuteEngine::run() { } // Create debugger console. It requires GFX to be initialized - _console = new Console(this); + _debugger = new Console(this); // DebugMan.enableDebugChannel("enginelog"); debugC(1, kWintermuteDebugLog, "Engine Debug-LOG enabled"); @@ -133,7 +139,7 @@ int WintermuteEngine::init() { return 1; } BaseEngine::instance().setGameRef(_game); - BasePlatform::initialize(_game, 0, NULL); + BasePlatform::initialize(this, _game, 0, nullptr); bool windowedMode = !ConfMan.getBool("fullscreen"); @@ -168,7 +174,7 @@ int WintermuteEngine::init() { if (DID_FAIL(_game->loadSettings("startup.settings"))) { _game->LOG(0, "Error loading game settings."); delete _game; - _game = NULL; + _game = nullptr; warning("Some of the essential files are missing. Please reinstall."); return 2; @@ -184,7 +190,7 @@ int WintermuteEngine::init() { _game->LOG(ret, "Error initializing renderer. Exiting."); delete _game; - _game = NULL; + _game = nullptr; return 3; } @@ -203,7 +209,7 @@ int WintermuteEngine::init() { if (DID_FAIL(_game->loadFile(_game->_settingsGameFile ? _game->_settingsGameFile : "default.game"))) { _game->LOG(ret, "Error loading game file. Exiting."); delete _game; - _game = NULL; + _game = nullptr; return false; } @@ -230,13 +236,20 @@ int WintermuteEngine::messageLoop() { uint32 diff = 0; const uint32 maxFPS = 60; - const uint32 frameTime = (uint32)((1.0 / maxFPS) * 1000); + const uint32 frameTime = 2 * (uint32)((1.0 / maxFPS) * 1000); while (!done) { + _debugger->onFrame(); + Common::Event event; while (_system->getEventManager()->pollEvent(event)) { BasePlatform::handleEvent(&event); } + if (_trigDebug) { + _debugger->attach(); + _trigDebug = false; + } + if (_game && _game->_renderer->_active && _game->_renderer->_ready) { _game->displayContent(); _game->displayQuickMsg(); @@ -265,13 +278,14 @@ int WintermuteEngine::messageLoop() { if (_game) { delete _game; - _game = NULL; + _game = nullptr; } return 0; } void WintermuteEngine::deinit() { BaseEngine::destroy(); + BasePlatform::deinit(); } Common::Error WintermuteEngine::loadGameState(int slot) { @@ -295,7 +309,7 @@ bool WintermuteEngine::canLoadGameStateCurrently() { bool WintermuteEngine::getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption) { bool retVal = false; caption = name = "(invalid)"; - Common::SeekableReadStream *stream = NULL; + Common::SeekableReadStream *stream = nullptr; // Quick-fix, instead of possibly breaking the persistence-system, let's just roll with it BaseFileManager *fileMan = new BaseFileManager(Common::UNK_LANG); fileMan->registerPackages(fslist); diff --git a/engines/wintermute/wintermute.h b/engines/wintermute/wintermute.h index d24b120658..fcaa2840a9 100644 --- a/engines/wintermute/wintermute.h +++ b/engines/wintermute/wintermute.h @@ -48,6 +48,9 @@ public: WintermuteEngine(); ~WintermuteEngine(); + virtual GUI::Debugger *getDebugger() { return _debugger; } + void trigDebugger() { _trigDebug = true; } + virtual Common::Error run(); virtual bool hasFeature(EngineFeature f) const; Common::SaveFileManager *getSaveFileMan() { return _saveFileMan; } @@ -58,19 +61,15 @@ public: // For detection-purposes: static bool getGameInfo(const Common::FSList &fslist, Common::String &name, Common::String &caption); private: + bool _trigDebug; int init(); void deinit(); int messageLoop(); - Console *_console; + GUI::Debugger *_debugger; BaseGame *_game; const ADGameDescription *_gameDescription; -}; -// Example console class -class Console : public GUI::Debugger { -public: - Console(WintermuteEngine *vm) {} - virtual ~Console(void) {} + friend class Console; }; } // End of namespace Wintermute |