diff options
author | Peter Kohaut | 2017-03-20 00:30:41 +0100 |
---|---|---|
committer | Peter Kohaut | 2017-03-20 00:30:41 +0100 |
commit | 02185fbcf52a406fb6a381ccfdfdd46077c24127 (patch) | |
tree | c29431a4344664c27862d43967d1c9e9f3627ea6 /engines | |
parent | 25e5143f99dab91d53eb52de703ef1b4c9ee2656 (diff) | |
parent | 89d5eeaa5819c10266160fd1bf12f88f6e073a12 (diff) | |
download | scummvm-rg350-02185fbcf52a406fb6a381ccfdfdd46077c24127.tar.gz scummvm-rg350-02185fbcf52a406fb6a381ccfdfdd46077c24127.tar.bz2 scummvm-rg350-02185fbcf52a406fb6a381ccfdfdd46077c24127.zip |
Merge branch 'master' of https://github.com/scummvm/scummvm
Diffstat (limited to 'engines')
83 files changed, 2920 insertions, 961 deletions
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp index 6fbd99278f..65c4a681d6 100644 --- a/engines/chewy/console.cpp +++ b/engines/chewy/console.cpp @@ -35,7 +35,8 @@ namespace Chewy { Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) { registerCmd("dump", WRAP_METHOD(Console, Cmd_Dump)); registerCmd("dump_bg", WRAP_METHOD(Console, Cmd_DumpBg)); - registerCmd("draw", WRAP_METHOD(Console, Cmd_Draw)); + registerCmd("draw_image", WRAP_METHOD(Console, Cmd_DrawImage)); + registerCmd("draw_sprite", WRAP_METHOD(Console, Cmd_DrawSprite)); registerCmd("play_sound", WRAP_METHOD(Console, Cmd_PlaySound)); registerCmd("play_speech", WRAP_METHOD(Console, Cmd_PlaySpeech)); registerCmd("play_music", WRAP_METHOD(Console, Cmd_PlayMusic)); @@ -104,9 +105,9 @@ bool Console::Cmd_DumpBg(int argc, const char **argv) { } -bool Console::Cmd_Draw(int argc, const char **argv) { +bool Console::Cmd_DrawImage(int argc, const char **argv) { if (argc < 3) { - debugPrintf("Usage: draw <file> <resource number>\n"); + debugPrintf("Usage: draw_image <file> <resource number>\n"); return true; } @@ -118,6 +119,22 @@ bool Console::Cmd_Draw(int argc, const char **argv) { return false; } +bool Console::Cmd_DrawSprite(int argc, const char **argv) { + if (argc < 3) { + debugPrintf("Usage: draw_sprite <file> <resource number> [x] [y]\n"); + return true; + } + + Common::String filename = argv[1]; + int spriteNum = atoi(argv[2]); + int x = (argc < 4) ? 0 : atoi(argv[3]); + int y = (argc < 5) ? 0 : atoi(argv[4]); + + _vm->_graphics->drawSprite(filename, spriteNum, x, y); + + return false; +} + bool Console::Cmd_PlaySound(int argc, const char **argv) { if (argc < 2) { debugPrintf("Usage: play_sound <number>\n"); diff --git a/engines/chewy/console.h b/engines/chewy/console.h index ae2be15f30..2ceb1df4e6 100644 --- a/engines/chewy/console.h +++ b/engines/chewy/console.h @@ -39,7 +39,8 @@ private: bool Cmd_Dump(int argc, const char **argv); bool Cmd_DumpBg(int argc, const char **argv); - bool Cmd_Draw(int argc, const char **argv); + bool Cmd_DrawImage(int argc, const char **argv); + bool Cmd_DrawSprite(int argc, const char **argv); bool Cmd_PlaySound(int argc, const char **argv); bool Cmd_PlaySpeech(int argc, const char **argv); bool Cmd_PlayMusic(int argc, const char **argv); diff --git a/engines/chewy/cursor.cpp b/engines/chewy/cursor.cpp index 4795221e44..54496ef848 100644 --- a/engines/chewy/cursor.cpp +++ b/engines/chewy/cursor.cpp @@ -63,6 +63,35 @@ Cursor::~Cursor() { delete _cursorSprites; } +// TODO: This may need to be refactored, since in the original the user +// selects the cursor to use from a pop-up menu +CurrentCursor Cursor::getCurrentCursor() const { + switch (_curCursor) { + case 0: + case 1: + case 2: + case 3: + return kWalk; + case 4: + case 5: + case 6: + case 7: + return kUse; + case 13: + case 14: + case 15: + case 16: + return kLook; + case 17: + case 18: + case 19: + case 20: + return kTalk; + default: + return kOther; + } +} + void Cursor::setCursor(uint num, bool newCursor) { TAFChunk *cursor = _cursorSprites->getSprite(num); if (newCursor) diff --git a/engines/chewy/cursor.h b/engines/chewy/cursor.h index de5a707ca6..bb39abb463 100644 --- a/engines/chewy/cursor.h +++ b/engines/chewy/cursor.h @@ -30,6 +30,14 @@ namespace Chewy { class SpriteResource; class Font; +enum CurrentCursor { + kWalk, + kLook, + kUse, + kTalk, + kOther +}; + class Cursor { public: Cursor(); @@ -40,6 +48,7 @@ public: void hideCursor(); void animateCursor(); void nextCursor(); + CurrentCursor getCurrentCursor() const; private: uint _curCursor; diff --git a/engines/chewy/events.cpp b/engines/chewy/events.cpp index 3da9da2803..532b1acce7 100644 --- a/engines/chewy/events.cpp +++ b/engines/chewy/events.cpp @@ -55,6 +55,8 @@ void Events::processEvents() { default: break; } + } else if (_event.type == Common::EVENT_LBUTTONUP) { + _vm->_scene->mouseClick(_event.mouse); } else if (_event.type == Common::EVENT_RBUTTONUP) { _vm->_cursor->nextCursor(); } else if (_event.type == Common::EVENT_MOUSEMOVE) { diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp index 54a731fd3a..2f7c28ad6c 100644 --- a/engines/chewy/graphics.cpp +++ b/engines/chewy/graphics.cpp @@ -34,12 +34,17 @@ namespace Chewy { +#define DESC_WIDTH 80 +#define DESC_HEIGHT 8 + Graphics::Graphics(ChewyEngine *vm) : _vm(vm) { _font = nullptr; + _descSurface.create(DESC_WIDTH, DESC_HEIGHT, ::Graphics::PixelFormat::createFormatCLUT8()); } Graphics::~Graphics() { delete _font; + _descSurface.free(); } void Graphics::drawSprite(Common::String filename, int spriteNum, uint x, uint y) { @@ -67,6 +72,15 @@ void Graphics::drawImage(Common::String filename, int imageNum) { delete res; } +void Graphics::drawRect(Common::Rect r, byte color) { + ::Graphics::Surface *screen = g_system->lockScreen(); + screen->drawLine(r.left, r.top, r.right, r.top, color); + screen->drawLine(r.right, r.top, r.right, r.bottom, color); + screen->drawLine(r.left, r.bottom, r.right, r.bottom, color); + screen->drawLine(r.left, r.top, r.left, r.bottom, color); + g_system->unlockScreen(); +} + void Graphics::loadFont(Common::String filename) { _font = new Font(filename); } @@ -75,10 +89,12 @@ void Graphics::drawTransparent(uint16 x, uint16 y, byte *data, uint16 width, uin ::Graphics::Surface *screen = g_system->lockScreen(); for (uint curX = 0; curX < width; curX++) { for (uint curY = 0; curY < height; curY++) { - byte *src = data + (curY * width) + curX; - byte *dst = (byte *)screen->getBasePtr(curX + x, curY + y); - if (*src != transparentColor) - *dst = *src; + if (curX + x < 320 && curY + y < 200) { + byte *src = data + (curY * width) + curX; + byte *dst = (byte *)screen->getBasePtr(curX + x, curY + y); + if (*src != transparentColor) + *dst = *src; + } } } g_system->unlockScreen(); @@ -145,4 +161,27 @@ void Graphics::playVideo(uint num) { delete cfoDecoder; } +void Graphics::setDescSurface(Common::Point pos) { + _descPos = pos; + + if (pos.x < 0) + return; + + ::Graphics::Surface *s = g_system->lockScreen(); + Common::Rect r = Common::Rect(pos.x, pos.y, pos.x + _descSurface.w, pos.y + _descSurface.h); + r.clip(Common::Rect(0, 0, 320, 200)); + _descSurface.copyRectToSurface(*s, 0, 0, r); + g_system->unlockScreen(); +} + +void Graphics::restoreDescSurface() { + if (_descPos.x < 0) + return; + + Common::Rect r = Common::Rect(_descPos.x, _descPos.y, _descPos.x + _descSurface.w, _descPos.y + _descSurface.h); + r.clip(Common::Rect(0, 0, 320, 200)); + g_system->copyRectToScreen(_descSurface.getPixels(), _descSurface.pitch, _descPos.x, _descPos.y, r.width(), r.height()); + _descPos = Common::Point(-1, -1); +} + } // End of namespace Chewy diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h index a260311df5..09865711df 100644 --- a/engines/chewy/graphics.h +++ b/engines/chewy/graphics.h @@ -24,6 +24,8 @@ #define CHEWY_GRAPHICS_H #include "chewy/chewy.h" +#include "common/rect.h" +#include "graphics/surface.h" namespace Chewy { @@ -37,15 +39,20 @@ public: void drawImage(Common::String filename, int imageNum); void drawSprite(Common::String filename, int spriteNum, uint x, uint y); + void drawRect(Common::Rect r, byte color); void playVideo(uint num); void loadFont(Common::String filename); void drawText(Common::String text, uint x, uint y); + void setDescSurface(Common::Point pos); + void restoreDescSurface(); private: void drawTransparent(uint16 x, uint16 y, byte *data, uint16 width, uint16 height, byte transparentColor); ChewyEngine *_vm; Font *_font; + Common::Point _descPos; + ::Graphics::Surface _descSurface; }; } // End of namespace Chewy diff --git a/engines/chewy/scene.cpp b/engines/chewy/scene.cpp index 0f12219078..df8dd66148 100644 --- a/engines/chewy/scene.cpp +++ b/engines/chewy/scene.cpp @@ -30,6 +30,7 @@ #include "chewy/graphics.h" #include "chewy/scene.h" #include "chewy/resource.h" +#include "chewy/sound.h" #include "chewy/text.h" #include "chewy/video/cfo_decoder.h" @@ -37,12 +38,28 @@ namespace Chewy { #define MAX_DETAILS 32 #define MAX_HOTSPOTS 50 +#define MAX_AUTOMOVE 20 +#define MAX_SOUNDS 3 // Animated details - scene animations struct AnimatedDetails { - uint16 x; - uint16 y; - // 66 bytes animated details - TODO + int16 x; + int16 y; + byte startFlag; // 0: no animation + byte repeat; + int16 startSprite; + int16 endSprite; + int16 spriteCount; + uint16 delay; + uint16 delayCount; + uint16 reverse; // 0: play normally, 1: play in reverse + uint16 timerStart; // seconds until detail is started (0: no timer) + uint16 zIndex; + byte loadFlag; // 0: load animation in memory immediately, 1: load animation in memory when it is played + byte zoom; + // 2 * 3 * 7 = 42 bytes sound data - TODO + byte showOneFrame; // show a sprite, 0: none, 1: before animation, 2: after animation + byte currentFrame; }; // Static details - scene sprites and props @@ -50,20 +67,18 @@ struct StaticDetails { int16 x; int16 y; int16 spriteNum; - uint16 z; + uint16 zIndex; byte hide; // 1 byte dummy }; -struct SceneInfo { - uint16 staticDetailsCount; - uint16 animatedDetailsCount; - uint32 spritePtr; - AnimatedDetails animatedDetails[MAX_DETAILS]; - StaticDetails staticDetails[MAX_DETAILS]; - Common::Rect hotspot[MAX_HOTSPOTS]; - uint16 hotspotDescRes[MAX_HOTSPOTS]; - Common::String hotspotDesc[MAX_HOTSPOTS]; +struct Hotspot { + Common::Rect rect; + uint16 resource; + Common::String desc; +}; + +struct RoomInfo { byte roomNum; byte picNum; byte autoMoveCount; @@ -71,13 +86,37 @@ struct SceneInfo { Common::String tafName; // 14 bytes byte zoomFactor; // 1 byte dummy - // 6 * 20 = 120 bytes automove coordinates - TODO - // MAX_DETAILS * 3 * 2 = 192 bytes voc - TODO - // MAX_DETAILS * 3 = 96 bytes samples - TODO +}; + +struct AutoMove { + int16 x; + int16 y; + byte spriteNum; // sprite number to draw when the end point is reached + // 1 byte dummy +}; + +struct HotspotSpeech { + int16 look; + int16 use; + int16 talk; +}; + +struct SceneInfo { + uint16 staticDetailsCount; + uint16 animatedDetailsCount; + uint32 spritePtr; + AnimatedDetails animatedDetails[MAX_DETAILS]; + StaticDetails staticDetails[MAX_DETAILS]; + Hotspot hotspot[MAX_HOTSPOTS]; + RoomInfo roomInfo; + AutoMove autoMove[MAX_AUTOMOVE]; + HotspotSpeech hotspotSpeech[MAX_DETAILS]; + byte hotspotSound[MAX_DETAILS][MAX_SOUNDS]; }; Scene::Scene(ChewyEngine *vm) : _vm(vm) { _sceneInfo = new SceneInfo(); + _vm->_graphics->setDescSurface(Common::Point(-1, -1)); } Scene::~Scene() { @@ -97,8 +136,8 @@ void Scene::draw() { // Background _vm->_graphics->drawImage("episode1.tgp", _curScene); - // Static details - for (uint16 i = 0; i < MAX_HOTSPOTS; i++) { + for (uint16 i = 0; i < MAX_DETAILS; i++) { + // Static details StaticDetails s = _sceneInfo->staticDetails[i]; if (s.spriteNum >= 0 && s.x >= 0 && s.y >= 0 && !s.hide) _vm->_graphics->drawSprite(Common::String::format("det%d.taf", _curScene), s.spriteNum, s.x, s.y); @@ -107,23 +146,54 @@ void Scene::draw() { // TODO: These are all hardcoded for now _vm->_graphics->drawSprite("det1.taf", 0, 200, 100); _vm->_graphics->loadFont("6x8.tff"); - _vm->_graphics->drawText("This is a test", 200, 80); + //_vm->_graphics->drawText("This is a test", 200, 80); + + _vm->_graphics->setDescSurface(Common::Point(-1, -1)); } void Scene::updateMouse(Common::Point coords) { - // Animated details - // TODO: handle these + _vm->_graphics->restoreDescSurface(); // Static details for (uint16 i = 0; i < MAX_HOTSPOTS; i++) { - if (_sceneInfo->hotspot[i].contains(coords)) { - // TODO: Draw hotspot description on screen - debug("Coords %d, %d: '%s'", coords.x, coords.y, _sceneInfo->hotspotDesc[i].c_str()); + //_vm->_graphics->drawRect(_sceneInfo->hotspot[i].rect, 0); // debug + if (_sceneInfo->hotspot[i].rect.contains(coords) && _sceneInfo->hotspot[i].resource < kATSTextMax) { + if (coords.y >= 8) { + _vm->_graphics->setDescSurface(Common::Point(coords.x, coords.y - 8)); + _vm->_graphics->drawText(_sceneInfo->hotspot[i].desc, coords.x, coords.y - 8); + } break; } } } +void Scene::mouseClick(Common::Point coords) { + // Static details + for (uint16 i = 0; i < MAX_HOTSPOTS; i++) { + //_vm->_graphics->drawRect(_sceneInfo->hotspot[i].rect, 0); // debug + if (_sceneInfo->hotspot[i].rect.contains(coords)) { + int sample = -1; + + switch (_vm->_cursor->getCurrentCursor()) { + case kLook: + sample = _sceneInfo->hotspotSpeech[i].look; + break; + case kUse: + sample = _sceneInfo->hotspotSpeech[i].use; + break; + case kTalk: + sample = _sceneInfo->hotspotSpeech[i].talk; + break; + default: + break; + } + + if (sample >= 0) + _vm->_sound->playSpeech(sample); + } + } +} + void Scene::loadSceneInfo() { const uint32 sceneInfoSize = 3784; const uint32 headerRDI = MKTAG('R', 'D', 'I', '\0'); @@ -148,9 +218,23 @@ void Scene::loadSceneInfo() { // Animated details for (int i = 0; i < MAX_DETAILS; i++) { - _sceneInfo->animatedDetails[i].x = indexFile.readUint16LE(); - _sceneInfo->animatedDetails[i].y = indexFile.readUint16LE(); - indexFile.skip(66); // animated details info - TODO: read these + _sceneInfo->animatedDetails[i].x = indexFile.readSint16LE(); + _sceneInfo->animatedDetails[i].y = indexFile.readSint16LE(); + _sceneInfo->animatedDetails[i].startFlag = indexFile.readByte(); + _sceneInfo->animatedDetails[i].repeat = indexFile.readByte(); + _sceneInfo->animatedDetails[i].startSprite = indexFile.readSint16LE(); + _sceneInfo->animatedDetails[i].endSprite = indexFile.readSint16LE(); + _sceneInfo->animatedDetails[i].spriteCount = indexFile.readSint16LE(); + _sceneInfo->animatedDetails[i].delay = indexFile.readUint16LE(); + _sceneInfo->animatedDetails[i].delayCount = indexFile.readUint16LE(); + _sceneInfo->animatedDetails[i].reverse = indexFile.readUint16LE(); + _sceneInfo->animatedDetails[i].timerStart = indexFile.readUint16LE(); + _sceneInfo->animatedDetails[i].zIndex = indexFile.readUint16LE(); + _sceneInfo->animatedDetails[i].loadFlag = indexFile.readByte(); + _sceneInfo->animatedDetails[i].zoom = indexFile.readByte(); + indexFile.skip(42); // 2 * 3 * 7 = 42 bytes sound data - TODO + _sceneInfo->animatedDetails[i].showOneFrame = indexFile.readUint16LE(); + _sceneInfo->animatedDetails[i].currentFrame = indexFile.readUint16LE(); } // Static details @@ -158,49 +242,70 @@ void Scene::loadSceneInfo() { _sceneInfo->staticDetails[i].x = indexFile.readSint16LE(); _sceneInfo->staticDetails[i].y = indexFile.readSint16LE(); _sceneInfo->staticDetails[i].spriteNum = indexFile.readSint16LE(); - _sceneInfo->staticDetails[i].z = indexFile.readUint16LE(); + _sceneInfo->staticDetails[i].zIndex = indexFile.readUint16LE(); _sceneInfo->staticDetails[i].hide = indexFile.readByte(); indexFile.readByte(); // padding } // Hotspots for (int i = 0; i < MAX_HOTSPOTS; i++) { - _sceneInfo->hotspot[i].left = indexFile.readUint16LE(); - _sceneInfo->hotspot[i].top = indexFile.readUint16LE(); - _sceneInfo->hotspot[i].right = indexFile.readUint16LE(); - _sceneInfo->hotspot[i].bottom = indexFile.readUint16LE(); - if (!_sceneInfo->hotspot[i].isValidRect()) + _sceneInfo->hotspot[i].rect.left = indexFile.readUint16LE(); + _sceneInfo->hotspot[i].rect.top = indexFile.readUint16LE(); + _sceneInfo->hotspot[i].rect.right = indexFile.readUint16LE(); + _sceneInfo->hotspot[i].rect.bottom = indexFile.readUint16LE(); + if (!_sceneInfo->hotspot[i].rect.isValidRect()) warning("Hotspot %d has an invalid rect", i); } // Hotspot descriptions for (int i = 0; i < MAX_HOTSPOTS; i++) { - _sceneInfo->hotspotDescRes[i] = indexFile.readUint16LE(); - - if (_sceneInfo->hotspotDescRes[i] < 12) { - // TODO: Hotspot description IDs are off... investigate why - _sceneInfo->hotspotDesc[i] = text->getText(_curScene + kADSTextMax, _sceneInfo->hotspotDescRes[i])->text; - } else { - // TODO: Handle these types of hotspot descriptions - warning("Hotspot %d has an invalid description resource (%d)", i, _sceneInfo->hotspotDescRes[i]); - _sceneInfo->hotspotDesc[i] = Common::String::format("Hotspot %d", _sceneInfo->hotspotDescRes[i]); + _sceneInfo->hotspot[i].resource = indexFile.readUint16LE() + 4; + _sceneInfo->hotspot[i].desc = ""; + + if (_sceneInfo->hotspot[i].resource < kATSTextMax) { + TextEntry *entry = text->getText(_curScene + kADSTextMax, _sceneInfo->hotspot[i].resource); + if (entry) + _sceneInfo->hotspot[i].desc = entry->text; } } - _sceneInfo->roomNum = indexFile.readByte(); - _sceneInfo->picNum = indexFile.readByte(); - _sceneInfo->autoMoveCount = indexFile.readByte(); - _sceneInfo->loadTaf = indexFile.readByte(); + // Room info + _sceneInfo->roomInfo.roomNum = indexFile.readByte(); + _sceneInfo->roomInfo.picNum = indexFile.readByte(); + _sceneInfo->roomInfo.autoMoveCount = indexFile.readByte(); + _sceneInfo->roomInfo.loadTaf = indexFile.readByte(); + _sceneInfo->roomInfo.tafName = ""; for (int i = 0; i < 14; i++) - _sceneInfo->tafName += indexFile.readByte(); + _sceneInfo->roomInfo.tafName += indexFile.readByte(); - _sceneInfo->zoomFactor = indexFile.readByte(); + _sceneInfo->roomInfo.zoomFactor = indexFile.readByte(); indexFile.readByte(); // padding - // 6 * 20 = 120 bytes automove coordinates - TODO: read these - // MAX_DETAILS * 3 * 2 = 192 bytes voc - TODO: read these - // MAX_DETAILS * 3 = 96 bytes samples - TODO: read these + for (int i = 0; i < MAX_AUTOMOVE; i++) { + _sceneInfo->autoMove[i].x = indexFile.readSint16LE(); + _sceneInfo->autoMove[i].y = indexFile.readSint16LE(); + _sceneInfo->autoMove[i].spriteNum = indexFile.readByte(); + indexFile.readByte(); // padding + if (i > _sceneInfo->roomInfo.autoMoveCount && !(_sceneInfo->autoMove[i].x <= 0 || _sceneInfo->autoMove[i].y <= 0)) + warning("Auto move %d should be unused, but it isn't (max auto move items are %d)", i, _sceneInfo->roomInfo.autoMoveCount); + } + + for (int i = 0; i < MAX_DETAILS; i++) { + // FIXME: These are all wrong... investigate why + _sceneInfo->hotspotSpeech[i].look = indexFile.readSint16LE(); + _sceneInfo->hotspotSpeech[i].use = indexFile.readSint16LE(); + _sceneInfo->hotspotSpeech[i].talk = indexFile.readSint16LE(); + } + + for (int i = 0; i < MAX_DETAILS; i++) { + _sceneInfo->hotspotSound[i][0] = indexFile.readSint16LE(); + _sceneInfo->hotspotSound[i][1] = indexFile.readSint16LE(); + _sceneInfo->hotspotSound[i][2] = indexFile.readSint16LE(); + } + + // TODO: We seem to be missing a chunk of data (186 bytes) from the end of + // the room info structure delete text; indexFile.close(); diff --git a/engines/chewy/scene.h b/engines/chewy/scene.h index c5b87ac7ae..bcbbf6761e 100644 --- a/engines/chewy/scene.h +++ b/engines/chewy/scene.h @@ -37,6 +37,7 @@ public: void change(uint scene); void draw(); void updateMouse(Common::Point coords); + void mouseClick(Common::Point coords); uint getCurScene() const { return _curScene; } diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp index cf0fb041a7..095b74b290 100644 --- a/engines/chewy/text.cpp +++ b/engines/chewy/text.cpp @@ -112,8 +112,14 @@ TextEntry *Text::getText(uint dialogNum, uint entryNum) { } } while (*ptr); - if (*(ptr + 1) != kEndText || *(ptr + 2) != kEndChunk) - error("Invalid text resource - %d, %d", dialogNum, entryNum); + if (*(ptr + 1) != kEndText || *(ptr + 2) != kEndChunk) { + warning("Invalid text resource - %d, %d", dialogNum, entryNum); + + delete[] data; + delete d; + + return nullptr; + } if (!isText) ptr += 3; // 0, kEndText, kEndChunk diff --git a/engines/director/cast.h b/engines/director/cast.h index 953c94c4c6..f304456e12 100644 --- a/engines/director/cast.h +++ b/engines/director/cast.h @@ -26,6 +26,7 @@ #include "common/rect.h" #include "common/substream.h" #include "director/archive.h" +#include "graphics/surface.h" namespace Director { @@ -44,16 +45,20 @@ enum CastType { kCastLingoScript = 11 }; -struct Cast { +class Cast { +public: CastType type; Common::Rect initialRect; Common::Rect boundingRect; Common::Array<Resource> children; + const Graphics::Surface *surface; + byte modified; }; -struct BitmapCast : Cast { +class BitmapCast : public Cast { +public: BitmapCast(Common::ReadStreamEndian &stream, uint16 version = 2); uint16 regX; @@ -72,7 +77,8 @@ enum ShapeType { kShapeLine }; -struct ShapeCast : Cast { +class ShapeCast : public Cast { +public: ShapeCast(Common::ReadStreamEndian &stream, uint16 version = 2); ShapeType shapeType; @@ -111,7 +117,8 @@ enum SizeType { kSizeLargest }; -struct TextCast : Cast { +class TextCast : public Cast { +public: TextCast(Common::ReadStreamEndian &stream, uint16 version = 2); SizeType borderSize; @@ -135,13 +142,15 @@ enum ButtonType { kTypeRadio }; -struct ButtonCast : TextCast { +class ButtonCast : public TextCast { +public: ButtonCast(Common::ReadStreamEndian &stream, uint16 version = 2); ButtonType buttonType; }; -struct ScriptCast : Cast { +class ScriptCast : public Cast { +public: ScriptCast(Common::ReadStreamEndian &stream, uint16 version = 2); uint32 id; diff --git a/engines/director/director.cpp b/engines/director/director.cpp index edea7ea591..70d5cf3c62 100644 --- a/engines/director/director.cpp +++ b/engines/director/director.cpp @@ -92,7 +92,10 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam _keyCode = 0; _machineType = 9; // Macintosh IIci _playbackPaused = false; - g_director->_skipFrameAdvance = false; + _skipFrameAdvance = false; + + _draggingSprite = false; + _draggingSpriteId = 0; } DirectorEngine::~DirectorEngine() { @@ -141,6 +144,8 @@ Common::Error DirectorEngine::run() { //_mainArchive = new RIFFArchive(); //_mainArchive->openFile("bookshelf_example.mmm"); + _currentScore = new Score(this); + if (getVersion() < 4) { if (getPlatform() == Common::kPlatformWindows) { _sharedCastFile = "SHARDCST.MMM"; @@ -155,7 +160,7 @@ Common::Error DirectorEngine::run() { loadInitialMovie(getEXEName()); - _currentScore = new Score(this, _mainArchive); + _currentScore->setArchive(_mainArchive); debug(0, "Score name %s", _currentScore->getMacName().c_str()); bool loop = true; @@ -176,8 +181,12 @@ Common::Error DirectorEngine::run() { _nextMovie.frameI = -1; } + debugC(1, kDebugEvents, "Starting playback of score '%s'", _currentScore->getMacName().c_str()); + _currentScore->startLoop(); + debugC(1, kDebugEvents, "Finished playback of score '%s'", _currentScore->getMacName().c_str()); + // If a loop was requested, do it if (!_nextMovie.movie.empty()) { _lingo->restartLingo(); @@ -192,8 +201,9 @@ Common::Error DirectorEngine::run() { return Common::kNoError; } - _currentScore = new Score(this, mov); - debug(0, "Score name %s", _currentScore->getMacName().c_str()); + _currentScore = new Score(this); + _currentScore->setArchive(mov); + debug(0, "Switching to score '%s'", _currentScore->getMacName().c_str()); _nextMovie.movie.clear(); loop = true; @@ -233,7 +243,8 @@ Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Commo warning("name: %s", i->getName().c_str()); arc->openFile(i->getName()); - Score *sc = new Score(this, arc); + Score *sc = new Score(this); + sc->setArchive(arc); nameMap->setVal(sc->getMacName(), sc); debugC(2, kDebugLoading, "Movie name: \"%s\"", sc->getMacName().c_str()); @@ -243,11 +254,11 @@ Common::HashMap<Common::String, Score *> *DirectorEngine::scanMovies(const Commo return nameMap; } -Common::HashMap<int, Cast *> *DirectorEngine::getSharedCasts() { +Common::HashMap<int, CastType> *DirectorEngine::getSharedCastTypes() { if (_sharedScore) - return &_sharedScore->_casts; + return &_sharedScore->_castTypes; - return &_dummyCast; + return &_dummyCastType; } } // End of namespace Director diff --git a/engines/director/director.h b/engines/director/director.h index 2f0b65288f..3c3e2e947a 100644 --- a/engines/director/director.h +++ b/engines/director/director.h @@ -28,6 +28,7 @@ #include "common/hashmap.h" #include "engines/engine.h" +#include "director/cast.h" namespace Common { class MacResManager; @@ -50,7 +51,7 @@ struct DirectorGameDescription; class DirectorSound; class Lingo; class Score; -struct Cast; +class Cast; enum { kDebugLingoExec = 1 << 0, @@ -89,6 +90,7 @@ public: Archive *getMainArchive() const { return _mainArchive; } Lingo *getLingo() const { return _lingo; } Score *getCurrentScore() const { return _currentScore; } + Score *getSharedScore() const { return _sharedScore; } void setPalette(byte *palette, uint16 count); bool hasFeature(EngineFeature f) const; const byte *getPalette() const { return _currentPalette; } @@ -103,11 +105,12 @@ public: void cleanupMainArchive(); void processEvents(); // evetns.cpp + void setDraggedSprite(uint16 id); // events.cpp Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedDIB() const { return _sharedDIB; } Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedBMP() const { return _sharedBMP; } Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedSTXT() const { return _sharedSTXT; } - Common::HashMap<int, Cast *> *getSharedCasts(); + Common::HashMap<int, CastType> *getSharedCastTypes(); Common::HashMap<Common::String, Score *> *_movies; @@ -159,7 +162,11 @@ private: Graphics::MacPatterns _director3QuickDrawPatterns; Common::String _sharedCastFile; - Common::HashMap<int, Cast *> _dummyCast; + Common::HashMap<int, CastType> _dummyCastType; + + bool _draggingSprite; + uint16 _draggingSpriteId; + Common::Point _draggingSpritePos; private: void testFontScaling(); diff --git a/engines/director/events.cpp b/engines/director/events.cpp index 613e83c352..e60af2244b 100644 --- a/engines/director/events.cpp +++ b/engines/director/events.cpp @@ -46,51 +46,62 @@ void DirectorEngine::processEvents() { uint endTime = g_system->getMillis() + 200; Score *sc = getCurrentScore(); - int currentFrame = sc->getCurrentFrame(); + Frame *currentFrame = sc->_frames[sc->getCurrentFrame()]; uint16 spriteId = 0; - // TODO: re-instate when we know which script to run. - //if (currentFrame > 0) - // _lingo->processEvent(kEventIdle, currentFrame - 1); + Common::Point pos; while (g_system->getMillis() < endTime) { while (g_system->getEventManager()->pollEvent(event)) { - if (event.type == Common::EVENT_QUIT) + switch (event.type) { + case Common::EVENT_QUIT: sc->_stopPlay = true; + break; - if (event.type == Common::EVENT_LBUTTONDOWN) { - Common::Point pos = g_system->getEventManager()->getMousePos(); + case Common::EVENT_LBUTTONDOWN: + pos = g_system->getEventManager()->getMousePos(); // D3 doesn't have both mouse up and down. // But we still want to know if the mouse is down for press effects. - spriteId = sc->_frames[currentFrame]->getSpriteIDFromPos(pos); + spriteId = currentFrame->getSpriteIDFromPos(pos); sc->_currentMouseDownSpriteId = spriteId; + debugC(3, kDebugEvents, "event: Button Down @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId); + if (getVersion() > 3) { // TODO: check that this is the order of script execution! - _lingo->processEvent(kEventMouseDown, kCastScript, sc->_frames[currentFrame]->_sprites[spriteId]->_castId); - _lingo->processEvent(kEventMouseDown, kSpriteScript, sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventMouseDown, kCastScript, currentFrame->_sprites[spriteId]->_castId); + _lingo->processEvent(kEventMouseDown, kSpriteScript, currentFrame->_sprites[spriteId]->_scriptId); } - } - if (event.type == Common::EVENT_LBUTTONUP) { - Common::Point pos = g_system->getEventManager()->getMousePos(); + if (currentFrame->_sprites[spriteId]->_moveable) { + warning("Moveable"); + } + break; + + case Common::EVENT_LBUTTONUP: + pos = g_system->getEventManager()->getMousePos(); + + spriteId = currentFrame->getSpriteIDFromPos(pos); + + debugC(3, kDebugEvents, "event: Button Up @(%d, %d), sprite id: %d", pos.x, pos.y, spriteId); - spriteId = sc->_frames[currentFrame]->getSpriteIDFromPos(pos); if (getVersion() > 3) { // TODO: check that this is the order of script execution! - _lingo->processEvent(kEventMouseUp, kCastScript, sc->_frames[currentFrame]->_sprites[spriteId]->_castId); - _lingo->processEvent(kEventMouseUp, kSpriteScript, sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventMouseUp, kCastScript, currentFrame->_sprites[spriteId]->_castId); + _lingo->processEvent(kEventMouseUp, kSpriteScript, currentFrame->_sprites[spriteId]->_scriptId); } else { // Frame script overrides sprite script - if (!sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId) - _lingo->processEvent(kEventMouseUp, kSpriteScript, sc->_frames[currentFrame]->_sprites[spriteId]->_castId + 1024); + if (!currentFrame->_sprites[spriteId]->_scriptId) + _lingo->processEvent(kEventMouseUp, kSpriteScript, currentFrame->_sprites[spriteId]->_castId + 1024); else - _lingo->processEvent(kEventMouseUp, kFrameScript, sc->_frames[currentFrame]->_sprites[spriteId]->_scriptId); + _lingo->processEvent(kEventMouseUp, kFrameScript, currentFrame->_sprites[spriteId]->_scriptId); } - } - if (event.type == Common::EVENT_KEYDOWN) { + sc->_currentMouseDownSpriteId = 0; + break; + + case Common::EVENT_KEYDOWN: _keyCode = event.kbd.keycode; _key = (unsigned char)(event.kbd.ascii & 0xff); @@ -111,14 +122,28 @@ void DirectorEngine::processEvents() { warning("Keycode: %d", _keyCode); } - // TODO: is movie script correct? Can this be elsewhere? - _lingo->processEvent(kEventKeyDown, kMovieScript, 0); + _lingo->processEvent(kEventKeyDown, kGlobalScript, 0); + break; + + default: + break; } } g_system->updateScreen(); g_system->delayMillis(10); + + if (sc->getCurrentFrame() > 0) + _lingo->processEvent(kEventIdle, kFrameScript, sc->getCurrentFrame()); } } +void DirectorEngine::setDraggedSprite(uint16 id) { + _draggingSprite = true; + _draggingSpriteId = id; + _draggingSpritePos = g_system->getEventManager()->getMousePos(); + + warning("STUB: DirectorEngine::setDraggedSprite(%d)", id); +} + } // End of namespace Director diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp index 7690a47893..92aa851d06 100644 --- a/engines/director/frame.cpp +++ b/engines/director/frame.cpp @@ -36,6 +36,7 @@ #include "director/score.h" #include "director/sprite.h" #include "director/util.h" +#include "director/lingo/lingo.h" namespace Director { @@ -221,10 +222,14 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) { sprite._unk3 = stream->readUint32(); } - debugC(kDebugLoading, 8, "%03d(%d)[%x,%x,%04x,%d/%d/%d/%d/%d] script:%d", - sprite._castId, sprite._enabled, sprite._x1, sprite._x2, sprite._flags, - sprite._startPoint.x, sprite._startPoint.y, sprite._width, sprite._height, - sprite._lineSize, sprite._scriptId); + if (sprite._castId) { + debugC(kDebugLoading, 4, "CH: %-3d castId: %03d(%s) (e:%d) [%x,%x, flags:%04x, %dx%d@%d,%d linesize: %d] script: %d", + i + 1, sprite._castId, numToCastNum(sprite._castId), sprite._enabled, sprite._x1, sprite._x2, sprite._flags, + sprite._width, sprite._height, sprite._startPoint.x, sprite._startPoint.y, + sprite._lineSize, sprite._scriptId); + } else { + debugC(kDebugLoading, 4, "CH: %-3d castId: 000", i + 1); + } } } @@ -539,6 +544,14 @@ void Frame::playTransition(Score *score) { } } +void Frame::executeImmediateScripts() { + for (uint16 i = 0; i < CHANNEL_COUNT; i++) { + if (_vm->getCurrentScore()->_immediateActions.contains(_sprites[i]->_scriptId)) { + g_lingo->processEvent(kEventMouseUp, kFrameScript, _sprites[i]->_scriptId); + } + } +} + void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { for (uint16 i = 0; i < CHANNEL_COUNT; i++) { if (_sprites[i]->_enabled) { @@ -563,18 +576,17 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { break; } } else { - if (!_vm->getCurrentScore()->_casts.contains(_sprites[i]->_castId)) { - if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) { + if (!_vm->getCurrentScore()->_castTypes.contains(_sprites[i]->_castId)) { + if (!_vm->getSharedCastTypes()->contains(_sprites[i]->_castId)) { warning("Cast id %d not found", _sprites[i]->_castId); continue; } else { warning("Getting cast id %d from shared cast", _sprites[i]->_castId); - cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId); + castType = _vm->getSharedCastTypes()->getVal(_sprites[i]->_castId); } } else { - cast = _vm->getCurrentScore()->_casts[_sprites[i]->_castId]; + castType = _vm->getCurrentScore()->_castTypes[_sprites[i]->_castId]; } - castType = cast->type; } // this needs precedence to be hit first... D3 does something really tricky with cast IDs for shapes. @@ -586,34 +598,15 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { } else if (castType == kCastButton) { renderButton(surface, i, _vm->getVersion() < 4 ? _sprites[i]->_castId + 1024 : cast->children[0].index); } else { - Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId); - - if (!img) { - warning("Image with id %d (%s) not found", _sprites[i]->_castId, numToCastNum(_sprites[i]->_castId)); - continue; - } - - if (!img->getSurface()) { - warning("Frame::renderSprites: Could not load image %d (%s)", _sprites[i]->_castId, numToCastNum(_sprites[i]->_castId)); - continue; - } - - if (!_sprites[i]->_cast) { + if (!_sprites[i]->_bitmapCast) { warning("No cast ID for sprite %d", i); continue; } - BitmapCast *bitmapCast = static_cast<BitmapCast *>(_sprites[i]->_cast); - // TODO: might want a quicker way to determine if cast is from Shared Cast. - if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(_sprites[i]->_castId + 1024)) { - debugC(2, kDebugImages, "Shared cast sprite BMP: id: %d", _sprites[i]->_castId + 1024); - bitmapCast = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(_sprites[i]->_castId)); - } - - uint32 regX = bitmapCast->regX; - uint32 regY = bitmapCast->regY; - uint32 rectLeft = bitmapCast->initialRect.left; - uint32 rectTop = bitmapCast->initialRect.top; + uint32 regX = _sprites[i]->_bitmapCast->regX; + uint32 regY = _sprites[i]->_bitmapCast->regY; + uint32 rectLeft = _sprites[i]->_bitmapCast->initialRect.left; + uint32 rectTop = _sprites[i]->_bitmapCast->initialRect.top; int x = _sprites[i]->_startPoint.x - regX + rectLeft; int y = _sprites[i]->_startPoint.y - regY + rectTop; @@ -621,9 +614,8 @@ void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { int width = _sprites[i]->_width; Common::Rect drawRect(x, y, x + width, y + height); - addDrawRect(i, drawRect); - inkBasedBlit(surface, *img->getSurface(), i, drawRect); + inkBasedBlit(surface, *(_sprites[i]->_bitmapCast->surface), i, drawRect); } } } @@ -667,15 +659,15 @@ void Frame::renderShape(Graphics::ManagedSurface &surface, uint16 spriteId) { void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uint16 textId) { uint16 castId = _sprites[spriteId]->_castId; - ButtonCast *button = static_cast<ButtonCast *>(_vm->getCurrentScore()->_casts[castId]); + ButtonCast *button = _vm->getCurrentScore()->_loadedButtons->getVal(castId); uint32 rectLeft = button->initialRect.left; uint32 rectTop = button->initialRect.top; int x = _sprites[spriteId]->_startPoint.x + rectLeft; int y = _sprites[spriteId]->_startPoint.y + rectTop; - int height = button->initialRect.height(); // _sprites[spriteId]->_height; - int width = button->initialRect.width() + 3; // _sprites[spriteId]->_width; + int height = button->initialRect.height(); + int width = button->initialRect.width() + 3; Common::Rect textRect(0, 0, width, height); // pass the rect of the button into the label. @@ -706,73 +698,6 @@ void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId, uin } } -Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { - uint16 imgId = spriteId + 1024; - - if (_vm->getVersion() >= 4 && _vm->getCurrentScore()->_casts[spriteId]->children.size() > 0) - imgId = _vm->getCurrentScore()->_casts[spriteId]->children[0].index; - - Image::ImageDecoder *img = NULL; - - if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { - img = new DIBDecoder(); - img->loadStream(*_vm->getCurrentScore()->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); - return img; - } - - if (_vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) { - img = new DIBDecoder(); - img->loadStream(*_vm->getSharedDIB()->getVal(imgId)); - return img; - } - - Common::SeekableReadStream *pic = NULL; - BitmapCast *bc = NULL; - - if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) { - debugC(4, kDebugImages, "Shared cast BMP: id: %d", imgId); - pic = _vm->getSharedBMP()->getVal(imgId); - pic->seek(0); // TODO: this actually gets re-read every loop... we need to rewind it! - bc = static_cast<BitmapCast *>(_vm->getSharedCasts()->getVal(spriteId)); - } else if (_vm->getCurrentScore()->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { - pic = _vm->getCurrentScore()->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); - bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]); - } - - if (pic != NULL && bc != NULL) { - if (_vm->getVersion() < 4) { - int w = bc->initialRect.width(), h = bc->initialRect.height(); - - debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", - imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2); - img = new BITDDecoder(w, h); - } else if (_vm->getVersion() < 6) { - bc = static_cast<BitmapCast *>(_vm->getCurrentScore()->_casts[spriteId]); - int w = bc->initialRect.width(), h = bc->initialRect.height(); - - debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", - imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2); - img = new BITDDecoderV4(w, h, bc->bitsPerPixel); - } else { - img = new Image::BitmapDecoder(); - } - - if (debugChannelSet(8, kDebugLoading)) { - Common::SeekableReadStream *s = pic; - byte buf[1024]; - int n = s->read(buf, 1024); - Common::hexdump(buf, n); - s->seek(0); - } - - img->loadStream(*pic); - return img; - } - - warning("Image %d not found", spriteId); - return img; -} - void Frame::inkBasedBlit(Graphics::ManagedSurface &targetSurface, const Graphics::Surface &spriteSurface, uint16 spriteId, Common::Rect drawRect) { switch (_sprites[spriteId]->_ink) { case kInkTypeCopy: @@ -818,7 +743,7 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo return; uint16 castId = _sprites[spriteId]->_castId; - TextCast *textCast = static_cast<TextCast *>(_vm->getCurrentScore()->_casts[castId]); + TextCast *textCast = _vm->getCurrentScore()->_loadedText->getVal(castId); uint32 unk1 = textStream->readUint32(); uint32 strLen = textStream->readUint32(); @@ -906,8 +831,8 @@ void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteId, Commo int x = _sprites[spriteId]->_startPoint.x; // +rectLeft; int y = _sprites[spriteId]->_startPoint.y; // +rectTop; - int height = _sprites[spriteId]->_cast->initialRect.height(); //_sprites[spriteId]->_height; - int width = _sprites[spriteId]->_cast->initialRect.width(); //_sprites[spriteId]->_width; + int height = textCast->initialRect.height(); //_sprites[spriteId]->_height; + int width = textCast->initialRect.width(); //_sprites[spriteId]->_width; if (_vm->getVersion() >= 4 && textSize != NULL) width = textCast->initialRect.right; @@ -1143,4 +1068,13 @@ uint16 Frame::getSpriteIDFromPos(Common::Point pos) { return 0; } +bool Frame::checkSpriteIntersection(uint16 spriteId, Common::Point pos) { + // Find first from front to back + for (int dr = _drawRects.size() - 1; dr >= 0; dr--) + if (_drawRects[dr]->spriteId == spriteId && _drawRects[dr]->rect.contains(pos)) + return true; + + return false; +} + } // End of namespace Director diff --git a/engines/director/frame.h b/engines/director/frame.h index 704319ba0d..e2a4a1f37b 100644 --- a/engines/director/frame.h +++ b/engines/director/frame.h @@ -119,6 +119,9 @@ public: void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); void prepareFrame(Score *score); uint16 getSpriteIDFromPos(Common::Point pos); + bool checkSpriteIntersection(uint16 spriteId, Common::Point pos); + + void executeImmediateScripts(); private: void playTransition(Score *score); diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp index 5322abcedf..46dab0f763 100644 --- a/engines/director/graphics.cpp +++ b/engines/director/graphics.cpp @@ -82,123 +82,126 @@ byte defaultPalette[768] = { 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51, 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255, 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255, - 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; - - -static byte director3Patterns[][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF }, - { 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF }, - { 0xFF, 0xDD, 0xFF, 0x55, 0xFF, 0xDD, 0xFF, 0x55 }, - { 0xFF, 0xD5, 0xFF, 0x55, 0xFF, 0x5D, 0xFF, 0x55 }, - { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, - { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }, - { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 }, - { 0xAA, 0x44, 0xAA, 0x00, 0xAA, 0x44, 0xAA, 0x00 }, - { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, - { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, - { 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 }, - { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, - { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, - { 0x21, 0x42, 0x84, 0x09, 0x12, 0x24, 0x48, 0x90 }, - { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, - { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, - { 0xF6, 0xED, 0xDB, 0xB7, 0x6F, 0xDE, 0xBD, 0x7B }, - { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, - { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, - { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF }, - { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, - { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00 }, - { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, - { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, - { 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82 }, - { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, - { 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94 }, - { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }, - { 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD }, - { 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }, - { 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7 }, - { 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF }, - { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00 }, - { 0x7F, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x00 }, - { 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00 }, - { 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88, 0xFF }, - { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF }, - { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF }, - { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, - { 0x11, 0x82, 0x45, 0xAB, 0xD7, 0xAB, 0x45, 0x82 }, - { 0xF7, 0x7F, 0xBE, 0x5D, 0x2A, 0x5D, 0xBE, 0x7F }, - { 0xFE, 0x7D, 0xBB, 0xD7, 0xEF, 0xD7, 0xBB, 0x7D }, - { 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xDF, 0xBF, 0x7F }, - { 0xEE, 0x77, 0xBB, 0xDD, 0xEE, 0xDD, 0xBB, 0x77 }, - { 0x11, 0x88, 0x44, 0x22, 0x11, 0x22, 0x44, 0x88 }, - { 0x01, 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80 }, - { 0x22, 0x00, 0x01, 0x22, 0x54, 0x88, 0x01, 0x00 }, - { 0xBF, 0xAF, 0xAB, 0xAA, 0xEA, 0xFA, 0xFE, 0xFF }, - { 0xFF, 0xFF, 0xBE, 0x9C, 0xAA, 0xB6, 0xBE, 0xFF } + 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; -static byte director3QuickDrawPatterns[][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF }, - { 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77 }, - { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, - { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, - { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, - { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, - { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, - { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, - { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, - { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, - { 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08 }, - { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, - { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, - { 0x58, 0xDF, 0x00, 0xDF, 0xDF, 0x58, 0x58, 0x58 }, - { 0xB1, 0x36, 0x06, 0x60, 0x63, 0x1B, 0x18, 0x81 }, - { 0x08, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0x08, 0x08 }, - { 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00 }, - { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0x80 }, - { 0x80, 0x10, 0x02, 0x40, 0x04, 0x20, 0x09, 0x00 }, - { 0x80, 0x01, 0x82, 0x44, 0x38, 0x10, 0x20, 0x40 }, - { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, - { 0x22, 0xFF, 0x22, 0x22, 0x22, 0xFF, 0x22, 0x22 }, - { 0x00, 0x08, 0x14, 0x2A, 0x55, 0x2A, 0x14, 0x08 }, - { 0x81, 0xAA, 0x14, 0x08, 0x08, 0xAA, 0x41, 0x80 }, - { 0x3E, 0x1D, 0x88, 0xD1, 0xE3, 0xC5, 0x88, 0x5C }, - { 0xAA, 0x00, 0x80, 0x00, 0x88, 0x00, 0x80, 0x00 }, - { 0x00, 0x11, 0x82, 0x44, 0x28, 0x11, 0x00, 0x55 }, - { 0x7C, 0x10, 0x10, 0x28, 0xC7, 0x01, 0x01, 0x82 }, - { 0xEE, 0x31, 0xF1, 0xF1, 0xEE, 0x13, 0x1F, 0x1F }, - { 0x00, 0x40, 0x20, 0x10, 0x00, 0x01, 0x02, 0x04 }, - { 0x00, 0x00, 0x40, 0xA0, 0x00, 0x04, 0x0A, 0x00 }, - { 0x20, 0x60, 0x90, 0x09, 0x06, 0x81, 0x40, 0x20 }, - { 0x00, 0x7F, 0x43, 0x5F, 0x5F, 0x5F, 0x7F, 0x7F }, - { 0x01, 0x02, 0x45, 0xAA, 0xFF, 0x20, 0x40, 0x80 }, - { 0x00, 0x44, 0x0A, 0x11, 0x11, 0x11, 0x51, 0x24 }, - { 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0 }, - { 0xF8, 0xFC, 0xFA, 0xFC, 0xFA, 0x54, 0x2A, 0x00 }, - { 0x42, 0xC3, 0x3C, 0x3C, 0x3C, 0x3C, 0xC3, 0x42 }, - { 0x10, 0x38, 0x7C, 0xFE, 0x7D, 0x3A, 0x14, 0x08 }, - { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }, - { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, - { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 }, - { 0xBB, 0xDD, 0xAE, 0x77, 0xEE, 0xDD, 0xAB, 0x77 }, - { 0x80, 0x40, 0x40, 0x20, 0x20, 0x18, 0x06, 0x01 }, - { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, - { 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF }, - { 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00 }, - { 0xC3, 0x87, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xE1 }, - { 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0 }, - { 0xFF, 0xFF, 0xE7, 0xC3, 0x81, 0x18, 0x3C, 0x7E }, - { 0x1F, 0x8F, 0xC7, 0xE3, 0xC7, 0x8F, 0x1F, 0x3E }, - { 0xFF, 0x2A, 0xFF, 0xC8, 0xFF, 0x65, 0xFF, 0x9D } + +static byte director3Patterns[][8] = { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0x77, 0xFF, 0xFF, 0xFF, 0x77, 0xFF }, + { 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF }, + { 0xFF, 0xDD, 0xFF, 0x55, 0xFF, 0xDD, 0xFF, 0x55 }, + { 0xFF, 0xD5, 0xFF, 0x55, 0xFF, 0x5D, 0xFF, 0x55 }, + { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, + { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }, + { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 }, + { 0xAA, 0x44, 0xAA, 0x00, 0xAA, 0x44, 0xAA, 0x00 }, + { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, + { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, + { 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, + { 0x21, 0x42, 0x84, 0x09, 0x12, 0x24, 0x48, 0x90 }, + { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, + { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, + { 0xF6, 0xED, 0xDB, 0xB7, 0x6F, 0xDE, 0xBD, 0x7B }, + { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, + { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }, + { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF }, + { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, + { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00 }, + { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, + { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, + { 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82 }, + { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, + { 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94 }, + { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }, + { 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD }, + { 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }, + { 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7 }, + { 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF }, + { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00 }, + { 0x7F, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x00 }, + { 0x77, 0x77, 0x77, 0x00, 0x77, 0x77, 0x77, 0x00 }, + { 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0x88, 0xFF }, + { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0xFF }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF }, + { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, + { 0x11, 0x82, 0x45, 0xAB, 0xD7, 0xAB, 0x45, 0x82 }, + { 0xF7, 0x7F, 0xBE, 0x5D, 0x2A, 0x5D, 0xBE, 0x7F }, + { 0xFE, 0x7D, 0xBB, 0xD7, 0xEF, 0xD7, 0xBB, 0x7D }, + { 0xFE, 0x7F, 0xBF, 0xDF, 0xEF, 0xDF, 0xBF, 0x7F }, + { 0xEE, 0x77, 0xBB, 0xDD, 0xEE, 0xDD, 0xBB, 0x77 }, + { 0x11, 0x88, 0x44, 0x22, 0x11, 0x22, 0x44, 0x88 }, + { 0x01, 0x80, 0x40, 0x20, 0x10, 0x20, 0x40, 0x80 }, + { 0x22, 0x00, 0x01, 0x22, 0x54, 0x88, 0x01, 0x00 }, + { 0xBF, 0xAF, 0xAB, 0xAA, 0xEA, 0xFA, 0xFE, 0xFF }, + { 0xFF, 0xFF, 0xBE, 0x9C, 0xAA, 0xB6, 0xBE, 0xFF } +}; + +static byte director3QuickDrawPatterns[][8] = { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xDD, 0xFF, 0x77, 0xFF, 0xDD, 0xFF, 0x77, 0xFF }, + { 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77 }, + { 0xEE, 0xDD, 0xBB, 0x77, 0xEE, 0xDD, 0xBB, 0x77 }, + { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }, + { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, + { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, + { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, + { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 }, + { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, + { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, + { 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x04, 0x08 }, + { 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, + { 0x58, 0xDF, 0x00, 0xDF, 0xDF, 0x58, 0x58, 0x58 }, + { 0xB1, 0x36, 0x06, 0x60, 0x63, 0x1B, 0x18, 0x81 }, + { 0x08, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0x08, 0x08 }, + { 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00 }, + { 0x80, 0x80, 0x80, 0xFF, 0x80, 0x80, 0x80, 0x80 }, + { 0x80, 0x10, 0x02, 0x40, 0x04, 0x20, 0x09, 0x00 }, + { 0x80, 0x01, 0x82, 0x44, 0x38, 0x10, 0x20, 0x40 }, + { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00 }, + { 0x22, 0xFF, 0x22, 0x22, 0x22, 0xFF, 0x22, 0x22 }, + { 0x00, 0x08, 0x14, 0x2A, 0x55, 0x2A, 0x14, 0x08 }, + { 0x81, 0xAA, 0x14, 0x08, 0x08, 0xAA, 0x41, 0x80 }, + { 0x3E, 0x1D, 0x88, 0xD1, 0xE3, 0xC5, 0x88, 0x5C }, + { 0xAA, 0x00, 0x80, 0x00, 0x88, 0x00, 0x80, 0x00 }, + { 0x00, 0x11, 0x82, 0x44, 0x28, 0x11, 0x00, 0x55 }, + { 0x7C, 0x10, 0x10, 0x28, 0xC7, 0x01, 0x01, 0x82 }, + { 0xEE, 0x31, 0xF1, 0xF1, 0xEE, 0x13, 0x1F, 0x1F }, + { 0x00, 0x40, 0x20, 0x10, 0x00, 0x01, 0x02, 0x04 }, + { 0x00, 0x00, 0x40, 0xA0, 0x00, 0x04, 0x0A, 0x00 }, + { 0x20, 0x60, 0x90, 0x09, 0x06, 0x81, 0x40, 0x20 }, + { 0x00, 0x7F, 0x43, 0x5F, 0x5F, 0x5F, 0x7F, 0x7F }, + { 0x01, 0x02, 0x45, 0xAA, 0xFF, 0x20, 0x40, 0x80 }, + { 0x00, 0x44, 0x0A, 0x11, 0x11, 0x11, 0x51, 0x24 }, + { 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0 }, + { 0xF8, 0xFC, 0xFA, 0xFC, 0xFA, 0x54, 0x2A, 0x00 }, + { 0x42, 0xC3, 0x3C, 0x3C, 0x3C, 0x3C, 0xC3, 0x42 }, + { 0x10, 0x38, 0x7C, 0xFE, 0x7D, 0x3A, 0x14, 0x08 }, + { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }, + { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, + { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 }, + { 0xBB, 0xDD, 0xAE, 0x77, 0xEE, 0xDD, 0xAB, 0x77 }, + { 0x80, 0x40, 0x40, 0x20, 0x20, 0x18, 0x06, 0x01 }, + { 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, + { 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00 }, + { 0xC3, 0x87, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xE1 }, + { 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0 }, + { 0xFF, 0xFF, 0xE7, 0xC3, 0x81, 0x18, 0x3C, 0x7E }, + { 0x1F, 0x8F, 0xC7, 0xE3, 0xC7, 0x8F, 0x1F, 0x3E }, + { 0xFF, 0x2A, 0xFF, 0xC8, 0xFF, 0x65, 0xFF, 0x9D } }; void DirectorEngine::loadPatterns() { diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp index f554f43cd8..cb6a7d67ec 100644 --- a/engines/director/lingo/lingo-builtins.cpp +++ b/engines/director/lingo/lingo-builtins.cpp @@ -21,7 +21,11 @@ */ #include "common/system.h" +#include "common/events.h" + #include "director/lingo/lingo.h" +#include "director/frame.h" +#include "director/sprite.h" namespace Director { @@ -379,7 +383,7 @@ void Lingo::printSTUBWithArglist(const char *funcname, int nargs, const char *pr s += ")"; - warning("%s: %s", prefix, s.c_str()); + warning("%s %s", prefix, s.c_str()); } void Lingo::convertVOIDtoString(int arg, int nargs) { @@ -1163,9 +1167,12 @@ void Lingo::b_move(int nargs) { } void Lingo::b_moveableSprite(int nargs) { - g_lingo->printSTUBWithArglist("b_moveableSprite", nargs); + Frame *frame = g_director->getCurrentScore()->_frames[g_director->getCurrentScore()->getCurrentFrame()]; - g_lingo->dropStack(nargs); + // Will have no effect + frame->_sprites[g_lingo->_currentEntityId]->_moveable = true; + + g_director->setDraggedSprite(frame->_sprites[g_lingo->_currentEntityId]->_castId); } void Lingo::b_pasteClipBoardInto(int nargs) { @@ -1216,9 +1223,26 @@ void Lingo::b_ramNeeded(int nargs) { void Lingo::b_rollOver(int nargs) { Datum d = g_lingo->pop(); - warning("STUB: b_rollOver(%d)", d.u.i); - g_lingo->push(Datum(0)); + d.toInt(); + + int arg = d.u.i; + + d.u.i = 0; // FALSE + + Frame *frame = g_director->getCurrentScore()->_frames[g_director->getCurrentScore()->getCurrentFrame()]; + + if (arg >= frame->_sprites.size()) { + g_lingo->push(d); + return; + } + + Common::Point pos = g_system->getEventManager()->getMousePos(); + + if (frame->checkSpriteIntersection(arg, pos)) + d.u.i = 1; // TRUE + + g_lingo->push(d); } void Lingo::b_spriteBox(int nargs) { diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index 7bc82eddcf..d0d29dd04c 100644 --- a/engines/director/lingo/lingo-code.cpp +++ b/engines/director/lingo/lingo-code.cpp @@ -307,10 +307,14 @@ void Lingo::c_assign() { } if (d1.type == REFERENCE) { - if (!g_director->getCurrentScore()->_castsInfo.contains(d1.u.i)) { - warning("c_assign: Unknown REFERENCE %d", d1.u.i); - g_lingo->pushVoid(); - return; + if (!g_director->getCurrentScore()->_loadedText->contains(d1.u.i)) { + if (!g_director->getCurrentScore()->_loadedText->contains(d1.u.i - 1024)) { + warning("c_assign: Unknown REFERENCE %d", d1.u.i); + g_lingo->pushVoid(); + return; + } else { + d1.u.i -= 1024; + } } warning("STUB: c_assing REFERENCE"); diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp index 8f874435f7..68999f66ef 100644 --- a/engines/director/lingo/lingo-the.cpp +++ b/engines/director/lingo/lingo-the.cpp @@ -332,8 +332,8 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) { switch (field) { case kTheCastNum: - if (_vm->getCurrentScore()->_casts.contains(d.u.i)) { - sprite->_cast = _vm->getCurrentScore()->_casts[d.u.i]; + if (_vm->getCurrentScore()->_castTypes.contains(d.u.i)) { + _vm->getCurrentScore()->loadCastInto(sprite, d.u.i); sprite->_castId = d.u.i; } break; @@ -638,9 +638,9 @@ Datum Lingo::getTheCast(Datum &id1, int field) { return d; } - Cast *cast; + CastType castType; CastInfo *castInfo; - if (!_vm->getCurrentScore()->_casts.contains(id)) { + if (!_vm->getCurrentScore()->_castTypes.contains(id)) { if (field == kTheLoaded) { d.type = INT; d.u.i = 0; @@ -651,14 +651,14 @@ Datum Lingo::getTheCast(Datum &id1, int field) { warning("The cast %d found", id); } - cast = _vm->getCurrentScore()->_casts[id]; + castType = _vm->getCurrentScore()->_castTypes[id]; castInfo = _vm->getCurrentScore()->_castsInfo[id]; d.type = INT; switch (field) { case kTheCastType: - d.u.i = cast->type; + d.u.i = castType; break; case kTheFileName: d.toString(); @@ -673,32 +673,32 @@ Datum Lingo::getTheCast(Datum &id1, int field) { d.u.s = &castInfo->script; break; case kTheWidth: - d.u.i = cast->initialRect.width(); + d.u.i = _vm->getCurrentScore()->getCastMemberInitialRect(id).width(); break; case kTheHeight: - d.u.i = cast->initialRect.height(); + d.u.i = _vm->getCurrentScore()->getCastMemberInitialRect(id).height(); break; case kTheBackColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); d.type = VOID; return d; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); d.u.i = shape->bgCol; } break; case kTheForeColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); d.type = VOID; return d; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); d.u.i = shape->fgCol; } break; @@ -729,18 +729,20 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { return; } - Cast *cast = _vm->getCurrentScore()->_casts[id]; + CastType castType = _vm->getCurrentScore()->_castTypes[id]; CastInfo *castInfo = _vm->getCurrentScore()->_castsInfo[id]; - if (!cast) { + if (!castInfo) { warning("The cast %d found", id); return; } switch (field) { case kTheCastType: - cast->type = static_cast<CastType>(d.u.i); - cast->modified = 1; + // TODO: You can actually switch the cast type!? + warning("Tried to switch cast type of %d", id); + //cast->type = static_cast<CastType>(d.u.i); + //cast->modified = 1; break; case kTheFileName: castInfo->fileName = *d.u.s; @@ -752,30 +754,30 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) { castInfo->script = *d.u.s; break; case kTheWidth: - cast->initialRect.setWidth(d.u.i); - cast->modified = 1; + _vm->getCurrentScore()->getCastMemberInitialRect(id).setWidth(d.u.i); + _vm->getCurrentScore()->setCastMemberModified(id); break; case kTheHeight: - cast->initialRect.setHeight(d.u.i); - cast->modified = 1; + _vm->getCurrentScore()->getCastMemberInitialRect(id).setHeight(d.u.i); + _vm->getCurrentScore()->setCastMemberModified(id); break; case kTheBackColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); shape->bgCol = d.u.i; shape->modified = 1; } break; case kTheForeColor: { - if (cast->type != kCastShape) { + if (castType != kCastShape) { warning("Field %d of cast %d not found", field, id); return; } - ShapeCast *shape = static_cast<ShapeCast *>(_vm->getCurrentScore()->_casts[id]); + ShapeCast *shape = _vm->getCurrentScore()->_loadedShapes->getVal(id); shape->fgCol = d.u.i; shape->modified = 1; } diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index 706f76777d..a51ff222c7 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -299,7 +299,7 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { if (entityId < 0) return; - debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId); + debugC(9, kDebugEvents, "Lingo::processEvent(%s, %s, %d)", _eventHandlerTypes[event], scriptType2str(st), entityId); _currentEntityId = entityId; @@ -307,8 +307,11 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { error("processEvent: Unknown event %d for entity %d", event, entityId); if (_handlers.contains(ENTITY_INDEX(event, entityId))) { + debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), _eventHandler", _eventHandlerTypes[event], scriptType2str(st), entityId); call(_eventHandlerTypes[event], 0); // D4+ Events } else if (_scripts[st].contains(entityId)) { + debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), script", _eventHandlerTypes[event], scriptType2str(st), entityId); + executeScript(st, entityId); // D3 list of scripts. } else { debugC(3, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId); @@ -318,6 +321,13 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) { void Lingo::restartLingo() { warning("STUB: restartLingo()"); + for (int i = 0; i <= kMaxScriptType; i++) { + for (ScriptHash::iterator it = _scripts[i].begin(); it != _scripts[i].end(); ++it) + delete it->_value; + + _scripts[i].clear(); + } + // TODO // // reset the following: @@ -403,6 +413,9 @@ Common::String *Datum::toString() { case VAR: *s = Common::String::format("var: #%s", u.sym->name.c_str()); break; + case REFERENCE: + *s = Common::String::format("field#%d", u.i); + break; default: warning("Incorrect operation toString() for type: %s", type2str()); } diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp index 6dace8bcb2..7dbd5a78a6 100644 --- a/engines/director/resource.cpp +++ b/engines/director/resource.cpp @@ -76,6 +76,7 @@ void DirectorEngine::loadEXE(const Common::String movie) { exeStream->seek(exeStream->readUint32LE()); switch (getVersion()) { + case 2: case 3: loadEXEv3(exeStream); break; @@ -100,12 +101,23 @@ void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) { stream->skip(5); // unknown - stream->readUint32LE(); // Main MMM size + uint32 mmmSize = stream->readUint32LE(); // Main MMM size + Common::String mmmFileName = stream->readPascalString(); Common::String directoryName = stream->readPascalString(); debugC(1, kDebugLoading, "Main MMM: '%s'", mmmFileName.c_str()); debugC(1, kDebugLoading, "Directory Name: '%s'", directoryName.c_str()); + debugC(1, kDebugLoading, "Main mmmSize: %d (0x%x)", mmmSize, mmmSize); + + if (mmmSize) { + uint32 riffOffset = stream->pos(); + + _mainArchive = new RIFFArchive(); + + if (!_mainArchive->openStream(stream, riffOffset)) + error("Failed to load RIFF from EXE"); + } openMainArchive(mmmFileName); @@ -200,19 +212,21 @@ void DirectorEngine::loadMac(const Common::String movie) { void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Archive *shardcst = createArchive(); - debug(0, "Loading Shared cast '%s'", filename.c_str()); + debug(0, "****** Loading Shared cast '%s'", filename.c_str()); + _sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + _sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + _sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + _sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; + + _sharedScore = new Score(this); if (!shardcst->openFile(filename)) { warning("No shared cast %s", filename.c_str()); return; } - _sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; - _sharedScore = new Score(this, shardcst); + _sharedScore->setArchive(shardcst); if (shardcst->hasResource(MKTAG('F', 'O', 'N', 'D'), -1)) { debug("Shared cast has fonts. Loading...."); @@ -227,12 +241,16 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> cast = shardcst->getResourceIDList(MKTAG('C','A','S','t')); if (cast.size() > 0) { + debug(0, "****** Loading %d CASt resources", cast.size()); + for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) _sharedScore->loadCastData(*shardcst->getResource(MKTAG('C','A','S','t'), *iterator), *iterator, NULL); } Common::Array<uint16> vwci = shardcst->getResourceIDList(MKTAG('V', 'W', 'C', 'I')); if (vwci.size() > 0) { + debug(0, "****** Loading %d CastInfo resources", vwci.size()); + for (Common::Array<uint16>::iterator iterator = vwci.begin(); iterator != vwci.end(); ++iterator) _sharedScore->loadCastInfo(*shardcst->getResource(MKTAG('V', 'W', 'C', 'I'), *iterator), *iterator); } @@ -241,7 +259,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' ')); if (dib.size() != 0) { - debugC(3, kDebugLoading, "Loading %d DIBs", dib.size()); + debugC(3, kDebugLoading, "****** Loading %d DIBs", dib.size()); for (Common::Array<uint16>::iterator iterator = dib.begin(); iterator != dib.end(); ++iterator) { debugC(3, kDebugLoading, "Shared DIB %d", *iterator); @@ -251,7 +269,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() != 0) { - debugC(3, kDebugLoading, "Loading %d STXTs", stxt.size()); + debugC(3, kDebugLoading, "****** Loading %d STXTs", stxt.size()); for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { debugC(3, kDebugLoading, "Shared STXT %d", *iterator); @@ -261,7 +279,7 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D')); if (bmp.size() != 0) { - debugC(3, kDebugLoading, "Loading %d BITDs", bmp.size()); + debugC(3, kDebugLoading, "****** Loading %d BITDs", bmp.size()); for (Common::Array<uint16>::iterator iterator = bmp.begin(); iterator != bmp.end(); ++iterator) { debugC(3, kDebugLoading, "Shared BITD %d (%s)", *iterator, numToCastNum(*iterator - 1024)); _sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator)); @@ -270,12 +288,14 @@ void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' ')); if (sound.size() != 0) { - debugC(3, kDebugLoading, "Loading %d SNDs", sound.size()); + debugC(3, kDebugLoading, "****** Loading %d SNDs", sound.size()); for (Common::Array<uint16>::iterator iterator = sound.begin(); iterator != sound.end(); ++iterator) { debugC(3, kDebugLoading, "Shared SND %d", *iterator); _sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator)); } } + + _sharedScore->loadSpriteImages(true); } } // End of namespace Director diff --git a/engines/director/score.cpp b/engines/director/score.cpp index 1ba0ab4683..472bd739c5 100644 --- a/engines/director/score.cpp +++ b/engines/director/score.cpp @@ -30,6 +30,7 @@ #include "graphics/palette.h" #include "graphics/macgui/macfontmanager.h" #include "graphics/macgui/macwindowmanager.h" +#include "image/bmp.h" #include "director/cast.h" #include "director/score.h" @@ -59,11 +60,10 @@ const char *scriptType2str(ScriptType scr) { } -Score::Score(DirectorEngine *vm, Archive *archive) { +Score::Score(DirectorEngine *vm) { _vm = vm; _surface = new Graphics::ManagedSurface; _trailSurface = new Graphics::ManagedSurface; - _movieArchive = archive; _lingo = _vm->getLingo(); _soundManager = _vm->getSoundManager(); _currentMouseDownSpriteId = 0; @@ -87,6 +87,15 @@ Score::Score(DirectorEngine *vm, Archive *archive) { _stopPlay = false; _stageColor = 0; + _loadedBitmaps = new Common::HashMap<int, BitmapCast *>(); + _loadedText = new Common::HashMap<int, TextCast *>(); + _loadedButtons = new Common::HashMap<int, ButtonCast *>(); + _loadedShapes = new Common::HashMap<int, ShapeCast *>(); + _loadedScripts = new Common::HashMap<int, ScriptCast *>(); +} + +void Score::setArchive(Archive *archive) { + _movieArchive = archive; if (archive->hasResource(MKTAG('M', 'C', 'N', 'M'), 0)) { _macName = archive->getName(MKTAG('M', 'C', 'N', 'M'), 0).c_str(); } else { @@ -111,6 +120,7 @@ void Score::loadArchive() { } else { Common::SeekableSubReadStreamEndian *pal = _movieArchive->getResource(MKTAG('C', 'L', 'U', 'T'), clutList[0]); + debugC(2, kDebugLoading, "****** Loading Palette"); loadPalette(*pal); g_system->getPaletteManager()->setPalette(_vm->getPalette(), 0, _vm->getPaletteColorCount()); } @@ -146,12 +156,16 @@ void Score::loadArchive() { Common::Array<uint16> vwci = _movieArchive->getResourceIDList(MKTAG('V', 'W', 'C', 'I')); if (vwci.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d CastInfos", vwci.size()); + for (Common::Array<uint16>::iterator iterator = vwci.begin(); iterator != vwci.end(); ++iterator) loadCastInfo(*_movieArchive->getResource(MKTAG('V', 'W', 'C', 'I'), *iterator), *iterator); } Common::Array<uint16> cast = _movieArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't')); if (cast.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d CASt resources", cast.size()); + for (Common::Array<uint16>::iterator iterator = cast.begin(); iterator != cast.end(); ++iterator) { Common::SeekableSubReadStreamEndian *stream = _movieArchive->getResource(MKTAG('C', 'A', 'S', 't'), *iterator); Resource res = _movieArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), *iterator); @@ -160,11 +174,14 @@ void Score::loadArchive() { } setSpriteCasts(); + loadSpriteImages(false); // Try to load movie script, it sits in resource A11 if (_vm->getVersion() <= 3) { Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() > 0) { + debugC(2, kDebugLoading, "****** Loading %d STXT resources", stxt.size()); + for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *iterator)); } @@ -172,6 +189,65 @@ void Score::loadArchive() { } } +void Score::loadSpriteImages(bool isSharedCast) { + debugC(1, kDebugLoading, "****** Preloading sprite images"); + + Common::HashMap<int, BitmapCast *>::iterator bc; + for (bc = _loadedBitmaps->begin(); bc != _loadedBitmaps->end(); ++bc) { + if (bc->_value) { + uint16 imgId = bc->_key + 1024; + BitmapCast *bitmapCast = bc->_value; + + if (_vm->getVersion() >= 4 && bitmapCast->children.size() > 0) + imgId = bitmapCast->children[0].index; + + Image::ImageDecoder *img = NULL; + + if (_movieArchive->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { + img = new DIBDecoder(); + img->loadStream(*_movieArchive->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); + bitmapCast->surface = img->getSurface(); + } + + if (isSharedCast && _vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) { + img = new DIBDecoder(); + img->loadStream(*_vm->getSharedDIB()->getVal(imgId)); + bitmapCast->surface = img->getSurface(); + } + + Common::SeekableReadStream *pic = NULL; + + if (isSharedCast) { + debugC(4, kDebugImages, "Shared cast BMP: id: %d", imgId); + pic = _vm->getSharedBMP()->getVal(imgId); + if (pic != NULL) + pic->seek(0); // TODO: this actually gets re-read every loop... we need to rewind it! + } else if (_movieArchive->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { + pic = _movieArchive->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); + } + + int w = bitmapCast->initialRect.width(), h = bitmapCast->initialRect.height(); + debugC(4, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", + imgId, w, h, bitmapCast->flags, bitmapCast->someFlaggyThing, bitmapCast->unk1, bitmapCast->unk2); + + if (pic != NULL && bitmapCast != NULL) { + if (_vm->getVersion() < 4) { + img = new BITDDecoder(w, h); + } else if (_vm->getVersion() < 6) { + img = new BITDDecoderV4(w, h, bitmapCast->bitsPerPixel); + } else { + img = new Image::BitmapDecoder(); + } + + img->loadStream(*pic); + bitmapCast->surface = img->getSurface(); + } + + warning("Image %d not found", imgId); + } + } +} + Score::~Score() { if (_surface) _surface->free(); @@ -210,6 +286,8 @@ void Score::loadPalette(Common::SeekableSubReadStreamEndian &stream) { } void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { + debugC(1, kDebugLoading, "****** Loading frames"); + uint32 size = stream.readUint32(); size -= 4; @@ -267,7 +345,7 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { //Common::hexdump(channelData, ARRAYSIZE(channelData)); frame->readChannels(str); - debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size() + 1, frame->_actionId); + debugC(3, kDebugLoading, "Frame %d actionId: %d", _frames.size(), frame->_actionId); delete str; @@ -276,6 +354,8 @@ void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { } void Score::loadConfig(Common::SeekableSubReadStreamEndian &stream) { + debugC(1, kDebugLoading, "****** Loading Config"); + /*uint16 unk1 = */ stream.readUint16(); /*ver1 = */ stream.readUint16(); _movieRect = Score::readRect(stream); @@ -295,7 +375,7 @@ void Score::readVersion(uint32 rid) { } void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) { - debugC(1, kDebugLoading, "Score::loadCastDataVWCR(). start: %d, end: %d", _castArrayStart, _castArrayEnd); + debugC(1, kDebugLoading, "****** Score::loadCastDataVWCR(). start: %d, end: %d", _castArrayStart, _castArrayEnd); for (uint16 id = _castArrayStart; id <= _castArrayEnd; id++) { byte size = stream.readByte(); @@ -309,20 +389,24 @@ void Score::loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream) { switch (castType) { case kCastBitmap: - _casts[id] = new BitmapCast(stream); - _casts[id]->type = kCastBitmap; + debugC(3, kDebugLoading, "CastTypes id: %d BitmapCast", id); + _loadedBitmaps->setVal(id, new BitmapCast(stream)); + _castTypes[id] = kCastBitmap; break; case kCastText: - _casts[id] = new TextCast(stream); - _casts[id]->type = kCastText; + debugC(3, kDebugLoading, "CastTypes id: %d TextCast", id); + _loadedText->setVal(id, new TextCast(stream)); + _castTypes[id] = kCastText; break; case kCastShape: - _casts[id] = new ShapeCast(stream); - _casts[id]->type = kCastShape; + debugC(3, kDebugLoading, "CastTypes id: %d ShapeCast", id); + _loadedShapes->setVal(id, new ShapeCast(stream)); + _castTypes[id] = kCastShape; break; case kCastButton: - _casts[id] = new ButtonCast(stream); - _casts[id]->type = kCastButton; + debugC(3, kDebugLoading, "CastTypes id: %d ButtonCast", id); + _loadedButtons->setVal(id, new ButtonCast(stream)); + _castTypes[id] = kCastButton; break; default: warning("Score::loadCastDataVWCR(): Unhandled cast type: %d", castType); @@ -336,10 +420,34 @@ void Score::setSpriteCasts() { // Set cast pointers to sprites for (uint16 i = 0; i < _frames.size(); i++) { for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) { - byte castId = _frames[i]->_sprites[j]->_castId; + uint16 castId = _frames[i]->_sprites[j]->_castId; + + if (_vm->getSharedScore()->_loadedBitmaps->contains(castId)) { + _frames[i]->_sprites[j]->_bitmapCast = _vm->getSharedScore()->_loadedBitmaps->getVal(castId); + } else if (_loadedBitmaps->contains(castId)) { + _frames[i]->_sprites[j]->_bitmapCast = _loadedBitmaps->getVal(castId); + } + + if (_vm->getSharedScore()->_loadedButtons->contains(castId)) { + _frames[i]->_sprites[j]->_buttonCast = _vm->getSharedScore()->_loadedButtons->getVal(castId); + } else if (_loadedButtons->contains(castId)) { + _frames[i]->_sprites[j]->_buttonCast = _loadedButtons->getVal(castId); + } + + //if (_loadedScripts->contains(castId)) + // _frames[i]->_sprites[j]->_bitmapCast = _loadedBitmaps->getVal(castId); + + if (_vm->getSharedScore()->_loadedText->contains(castId)) { + _frames[i]->_sprites[j]->_textCast = _vm->getSharedScore()->_loadedText->getVal(castId); + } else if (_loadedText->contains(castId)) { + _frames[i]->_sprites[j]->_textCast = _loadedText->getVal(castId); + } - if (_casts.contains(castId)) - _frames[i]->_sprites[j]->_cast = _casts.find(castId)->_value; + if (_vm->getSharedScore()->_loadedShapes->contains(castId)) { + _frames[i]->_sprites[j]->_shapeCast = _vm->getSharedScore()->_loadedShapes->getVal(castId); + } else if (_loadedShapes->contains(castId)) { + _frames[i]->_sprites[j]->_shapeCast = _loadedShapes->getVal(castId); + } } } } @@ -398,35 +506,32 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, switch (castType) { case kCastBitmap: - _casts[id] = new BitmapCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastBitmap; + _loadedBitmaps->setVal(id, new BitmapCast(castStream, _vm->getVersion())); + for (uint child = 0; child < res->children.size(); child++) + _loadedBitmaps->getVal(id)->children.push_back(res->children[child]); + _castTypes[id] = kCastBitmap; break; case kCastText: - _casts[id] = new TextCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastText; + _loadedText->setVal(id, new TextCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastText; break; case kCastShape: - _casts[id] = new ShapeCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastShape; + _loadedShapes->setVal(id, new ShapeCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastShape; break; case kCastButton: - _casts[id] = new ButtonCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastButton; + _loadedButtons->setVal(id, new ButtonCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastButton; break; case kCastLingoScript: - _casts[id] = new ScriptCast(castStream, _vm->getVersion()); - _casts[id]->type = kCastLingoScript; + _loadedScripts->setVal(id, new ScriptCast(castStream, _vm->getVersion())); + _castTypes[id] = kCastLingoScript; break; default: warning("Score::loadCastData(): Unhandled cast type: %d", castType); break; } - if (res != NULL) { - for (uint child = 0; child < res->children.size(); child++) - _casts[id]->children.push_back(res->children[child]); - } - free(data); if (size2) { @@ -467,6 +572,60 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id, warning("size3: %x", size3); } +void Score::loadCastInto(Sprite *sprite, int castId) { + switch (_castTypes[castId]) { + case kCastBitmap: + sprite->_bitmapCast = _loadedBitmaps->getVal(castId); + break; + case kCastShape: + sprite->_shapeCast = _loadedShapes->getVal(castId); + break; + case kCastButton: + sprite->_buttonCast = _loadedButtons->getVal(castId); + break; + case kCastText: + sprite->_textCast = _loadedText->getVal(castId); + break; + default: + warning("Score::loadCastInto(..., %d): Unhandled castType %d", castId, _castTypes[castId]); + } +} + +Common::Rect Score::getCastMemberInitialRect(int castId) { + switch (_castTypes[castId]) { + case kCastBitmap: + return _loadedBitmaps->getVal(castId)->initialRect; + case kCastShape: + return _loadedShapes->getVal(castId)->initialRect; + case kCastButton: + return _loadedButtons->getVal(castId)->initialRect; + case kCastText: + return _loadedText->getVal(castId)->initialRect; + default: + warning("Score::getCastMemberInitialRect(%d): Unhandled castType %d", castId, _castTypes[castId]); + return Common::Rect(0, 0); + } +} + +void Score::setCastMemberModified(int castId) { + switch (_castTypes[castId]) { + case kCastBitmap: + _loadedBitmaps->getVal(castId)->modified = 1; + break; + case kCastShape: + _loadedShapes->getVal(castId)->modified = 1; + break; + case kCastButton: + _loadedButtons->getVal(castId)->modified = 1; + break; + case kCastText: + _loadedText->getVal(castId)->modified = 1; + break; + default: + warning("Score::setCastMemberModified(%d): Unhandled castType %d", castId, _castTypes[castId]); + } +} + void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { _labels = new Common::SortedArray<Label *>(compareLabels); uint16 count = stream.readUint16() + 1; @@ -496,6 +655,7 @@ void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { Common::SortedArray<Label *>::iterator j; + debugC(2, kDebugLoading, "****** Loading labels"); for (j = _labels->begin(); j != _labels->end(); ++j) { debugC(2, kDebugLoading, "Frame %d, Label %s", (*j)->number, (*j)->name.c_str()); } @@ -506,6 +666,8 @@ int Score::compareLabels(const void *a, const void *b) { } void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { + debugC(2, kDebugLoading, "****** Loading Actions"); + uint16 count = stream.readUint16() + 1; uint16 offset = count * 4 + 2; @@ -530,7 +692,7 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { _actions[i + 1] += ch; } - debugC(3, kDebugLoading, "id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str()); + debugC(3, kDebugLoading, "Action id: %d nextId: %d subId: %d, code: %s", id, nextId, subId, _actions[id].c_str()); stream.seek(streamPos); @@ -551,8 +713,22 @@ void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { } for (j = _actions.begin(); j != _actions.end(); ++j) - if (!j->_value.empty()) + if (!j->_value.empty()) { _lingo->addCode(j->_value.c_str(), kFrameScript, j->_key); + + processImmediateFrameScript(j->_value, j->_key); + } +} + +bool Score::processImmediateFrameScript(Common::String s, int id) { + s.trim(); + + // In D2/D3 this specifies immediately the sprite/field properties + if (!s.compareToIgnoreCase("moveableSprite") || !s.compareToIgnoreCase("editableText")) { + _immediateActions[id] = true; + } + + return false; } void Score::loadScriptText(Common::SeekableSubReadStreamEndian &stream) { @@ -621,6 +797,9 @@ void Score::dumpScript(const char *script, ScriptType type, uint16 id) { case kCastScript: typeName = "cast"; break; + case kGlobalScript: + typeName = "global"; + break; } sprintf(buf, "./dumps/%s-%s-%d.txt", _macName.c_str(), typeName.c_str(), id); @@ -776,6 +955,8 @@ Common::String Score::getString(Common::String str) { } void Score::loadFileInfo(Common::SeekableSubReadStreamEndian &stream) { + debugC(2, kDebugLoading, "****** Loading FileInfo"); + Common::Array<Common::String> fileInfoStrings = loadStrings(stream, _flags); _script = fileInfoStrings[0]; @@ -805,6 +986,8 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn uint16 count = stream.readUint16() + 1; + debugC(3, kDebugLoading, "Strings: %d entries", count); + uint32 *entries = (uint32 *)calloc(count, sizeof(uint32)); for (uint i = 0; i < count; i++) @@ -823,6 +1006,8 @@ Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEn entryString += data[j]; strings.push_back(entryString); + + debugC(6, kDebugLoading, "String %d:\n%s\n", i, entryString.c_str()); } free(data); @@ -835,6 +1020,8 @@ void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { if (stream.size() == 0) return; + debugC(2, kDebugLoading, "****** Loading FontMap"); + uint16 count = stream.readUint16(); uint32 offset = (count * 2) + 2; uint16 currentRawPosition = offset; @@ -855,7 +1042,7 @@ void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { _fontMap[id] = font; _vm->_wm->_fontMan->registerFontMapping(id, font); - debug(3, "Fontmap. ID %d Font %s", id, font.c_str()); + debugC(3, kDebugLoading, "Fontmap. ID %d Font %s", id, font.c_str()); currentRawPosition = stream.pos(); stream.seek(positionInfo); } @@ -902,9 +1089,10 @@ void Score::update() { _surface->clear(); _surface->copyFrom(*_trailSurface); + _frames[_currentFrame]->executeImmediateScripts(); + // Enter and exit from previous frame (Director 4) _lingo->processEvent(kEventEnterFrame, kFrameScript, _frames[_currentFrame]->_actionId); - _lingo->processEvent(kEventExitFrame, kFrameScript, _frames[_currentFrame]->_actionId); // TODO Director 6 - another order // TODO Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame @@ -972,6 +1160,8 @@ void Score::update() { } } + _lingo->processEvent(kEventExitFrame, kFrameScript, _frames[_currentFrame]->_actionId); + _nextFrameTime = g_system->getMillis() + (float)_currentFrameRate / 60 * 1000; } diff --git a/engines/director/score.h b/engines/director/score.h index 3e7aa62c4f..021dcb5577 100644 --- a/engines/director/score.h +++ b/engines/director/score.h @@ -26,6 +26,8 @@ #include "common/substream.h" #include "common/rect.h" #include "director/archive.h" +#include "director/cast.h" +#include "director/images.h" namespace Graphics { class ManagedSurface; @@ -48,15 +50,16 @@ enum ScriptType { kSpriteScript = 1, kFrameScript = 2, kCastScript = 3, + kGlobalScript = 4, kNoneScript = -1, - kMaxScriptType = 3 + kMaxScriptType = 4 }; const char *scriptType2str(ScriptType scr); class Score { public: - Score(DirectorEngine *vm, Archive *); + Score(DirectorEngine *vm); ~Score(); static Common::Rect readRect(Common::ReadStreamEndian &stream); @@ -67,6 +70,7 @@ public: void gotoNext(); void gotoPrevious(); void startLoop(); + void setArchive(Archive *archive); Archive *getArchive() const { return _movieArchive; }; void loadConfig(Common::SeekableSubReadStreamEndian &stream); void loadCastDataVWCR(Common::SeekableSubReadStreamEndian &stream); @@ -77,8 +81,13 @@ public: Common::String getMacName() const { return _macName; } Sprite *getSpriteById(uint16 id); void setSpriteCasts(); + void loadSpriteImages(bool isSharedCast); Graphics::ManagedSurface *getSurface() { return _surface; } + void loadCastInto(Sprite *sprite, int castId); + Common::Rect getCastMemberInitialRect(int castId); + void setCastMemberModified(int castId); + int getPreviousLabelNumber(int referenceFrame); int getCurrentLabelNumber(); int getNextLabelNumber(int referenceFrame); @@ -97,13 +106,16 @@ private: Common::String getString(Common::String str); Common::Array<Common::String> loadStrings(Common::SeekableSubReadStreamEndian &stream, uint32 &entryType, bool hasHeader = true); + bool processImmediateFrameScript(Common::String s, int id); + public: Common::Array<Frame *> _frames; - Common::HashMap<int, Cast *> _casts; + Common::HashMap<int, CastType> _castTypes; Common::HashMap<uint16, CastInfo *> _castsInfo; Common::HashMap<Common::String, int> _castsNames; Common::SortedArray<Label *> *_labels; Common::HashMap<uint16, Common::String> _actions; + Common::HashMap<uint16, bool> _immediateActions; Common::HashMap<uint16, Common::String> _fontMap; Graphics::ManagedSurface *_surface; Graphics::ManagedSurface *_trailSurface; @@ -115,6 +127,13 @@ public: bool _stopPlay; uint32 _nextFrameTime; + Common::HashMap<int, ButtonCast *> *_loadedButtons; + Common::HashMap<int, TextCast *> *_loadedText; + //Common::HashMap<int, SoundCast *> _loadedSound; + Common::HashMap<int, BitmapCast *> *_loadedBitmaps; + Common::HashMap<int, ShapeCast *> *_loadedShapes; + Common::HashMap<int, ScriptCast *> *_loadedScripts; + private: uint16 _versionMinor; uint16 _versionMajor; diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp index 019966762e..9d219d6076 100644 --- a/engines/director/sprite.cpp +++ b/engines/director/sprite.cpp @@ -53,7 +53,11 @@ Sprite::Sprite() { _stretch = 0; _type = kInactiveSprite; - _cast = nullptr; + _bitmapCast = nullptr; + _textCast = nullptr; + _buttonCast = nullptr; + _shapeCast = nullptr; + _blend = 0; _lineSize = 1; @@ -90,7 +94,11 @@ Sprite::Sprite(const Sprite &sprite) { _stretch = sprite._stretch; _type = sprite._type; - _cast = sprite._cast; + _bitmapCast = sprite._bitmapCast; + _shapeCast = sprite._shapeCast; + _textCast = sprite._textCast; + _buttonCast = sprite._buttonCast; + _constraint = sprite._constraint; _moveable = sprite._moveable; _blend = sprite._blend; @@ -107,7 +115,14 @@ Sprite::Sprite(const Sprite &sprite) { } Sprite::~Sprite() { - delete _cast; + if (_bitmapCast) + delete _bitmapCast; + if (_shapeCast) + delete _shapeCast; + if (_textCast) + delete _textCast; + if (_buttonCast) + delete _buttonCast; } } // End of namespace Director diff --git a/engines/director/sprite.h b/engines/director/sprite.h index c43418828c..de1965dc2a 100644 --- a/engines/director/sprite.h +++ b/engines/director/sprite.h @@ -110,7 +110,14 @@ public: byte _spriteType; InkType _ink; uint16 _trails; - Cast *_cast; + + BitmapCast *_bitmapCast; + ShapeCast *_shapeCast; + //SoundCast *_soundCast; + TextCast *_textCast; + ButtonCast *_buttonCast; + //ScriptCast *_scriptCast; + uint16 _flags; Common::Point _startPoint; uint16 _width; diff --git a/engines/director/util.cpp b/engines/director/util.cpp index ccde2b3127..dbd1cd351f 100644 --- a/engines/director/util.cpp +++ b/engines/director/util.cpp @@ -48,7 +48,7 @@ char *numToCastNum(int num) { res[3] = '\0'; num--; - if (num > 0 && num <= 512) { + if (num >= 0 && num < 512) { int c = num / 64; res[0] = 'A' + c; num -= 64 * c; diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 9cc52a78b3..7da3c14633 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -48,6 +48,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0, }, + // Myst + // English Windows 3.11, v1.0 + // From vonLeheCreative, #9645 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "0e4b6fcbd2419d4371365314fb7443f8"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUI_OPTIONS_MYST + }, + GType_MYST, + 0, + 0, + }, + // Myst Demo // English Windows 3.11 // From CD-ROM Today July, 1994 diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp index 596180ddb2..267d644b65 100644 --- a/engines/mohawk/myst_scripts.cpp +++ b/engines/mohawk/myst_scripts.cpp @@ -355,7 +355,26 @@ void MystScriptParser::o_changeCardSwitchRtL(uint16 op, uint16 var, uint16 argc, } void MystScriptParser::o_takePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - uint16 cursorId = argv[0]; + // In most game releases, the first opcode argument is the new mouse cursor. + // However, in the original v1.0 English release this opcode takes no argument. + uint16 cursorId; // = argv[0]; + switch (var) { + case 41: // Vault white page + cursorId = kWhitePageCursor; + break; + case 25: // Fireplace red page + case 102: // Red page + cursorId = kRedPageCursor; + break; + case 24: // Fireplace blue page + case 103: // Blue page + cursorId = kBluePageCursor; + break; + default: + warning("Unexpected take page variable '%d'", var); + cursorId = kDefaultMystCursor; + } + uint16 oldPage = _globals.heldPage; debugC(kDebugScript, "Opcode %d: takePage Var %d CursorId %d", op, var, cursorId); diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp index 21c3042359..f006a8e3ea 100644 --- a/engines/mohawk/myst_stacks/channelwood.cpp +++ b/engines/mohawk/myst_stacks/channelwood.cpp @@ -368,6 +368,7 @@ void Channelwood::o_waterTankValveOpen(uint16 op, uint16 var, uint16 argc, uint1 for (uint i = 0; i < 2; i++) for (uint16 imageId = 3601; imageId >= 3595; imageId--) { _vm->_gfx->copyImageToScreen(imageId, rect); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } @@ -699,6 +700,7 @@ void Channelwood::o_waterTankValveClose(uint16 op, uint16 var, uint16 argc, uint for (uint i = 0; i < 2; i++) for (uint16 imageId = 3595; imageId <= 3601; imageId++) { _vm->_gfx->copyImageToScreen(imageId, rect); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index f9ba6a42fa..424dd2f07c 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -864,6 +864,7 @@ void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *a // Unset button for (uint i = 4795; i >= 4779; i--) { _vm->_gfx->copyImageToScreen(i, getInvokingResource<MystArea>()->getRect()); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } _fireplaceLines[var - 17] &= ~bitmask; @@ -871,6 +872,7 @@ void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *a // Set button for (uint i = 4779; i <= 4795; i++) { _vm->_gfx->copyImageToScreen(i, getInvokingResource<MystArea>()->getRect()); + _vm->pollAndDiscardEvents(); _vm->_system->updateScreen(); } _fireplaceLines[var - 17] |= bitmask; diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index c542be7ef2..cf3a981347 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -103,6 +103,7 @@ static const char *const selectorNameTable[] = { "modNum", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support "cycler", // Space Quest 4 / system selector "setLoop", // Laura Bow 1 Colonel's Bequest + "ignoreActors", // Laura Bow 1 Colonel's Bequest #ifdef ENABLE_SCI32 "newWith", // SCI2 array script "scrollSelections", // GK2 @@ -135,7 +136,8 @@ enum ScriptPatcherSelectors { SELECTOR_startAudio, SELECTOR_modNum, SELECTOR_cycler, - SELECTOR_setLoop + SELECTOR_setLoop, + SELECTOR_ignoreActors #ifdef ENABLE_SCI32 , SELECTOR_newWith, @@ -554,14 +556,12 @@ static const uint16 freddypharkasSignatureIntroScaling[] = { static const uint16 freddypharkasPatchIntroScaling[] = { // remove setLoop(), objects in heap are already prepared, saves 5 bytes 0x38, - PATCH_GETORIGINALBYTE(+6), - PATCH_GETORIGINALBYTE(+7), // pushi (setStep) + PATCH_GETORIGINALUINT16(+6), // pushi (setStep) 0x7a, // push2 0x39, 0x05, // pushi 05 0x3c, // dup 0x72, - PATCH_GETORIGINALBYTE(+13), - PATCH_GETORIGINALBYTE(+14), // lofsa (view) + PATCH_GETORIGINALUINT16(+13), // lofsa (view) 0x4a, 0x18, // send 18 - adjusted 0x35, 0x0a, // ldi 0a 0xa3, 0x02, // sal local[2] @@ -1314,8 +1314,7 @@ static const uint16 kq6PatchInventoryStackFix[] = { 0x12, // and 0x65, 0x30, // aTop state 0x38, // pushi "show" - PATCH_GETORIGINALBYTE(+22), - PATCH_GETORIGINALBYTE(+23), + PATCH_GETORIGINALUINT16(+22), 0x78, // push1 0x87, 0x00, // lap param[0] 0x31, 0x04, // bnt [call show using global 0] @@ -1600,8 +1599,7 @@ static const uint16 kq6CDPatchAudioTextSupport3[] = { 0x65, 0x12, // aTop dialog // followed by original addText-calling code 0x38, - PATCH_GETORIGINALBYTE(+95), - PATCH_GETORIGINALBYTE(+96), // pushi addText + PATCH_GETORIGINALUINT16(+95), // pushi (addText) 0x78, // push1 0x8f, 0x02, // lsp param[2] 0x59, 0x03, // &rest 03 @@ -1949,8 +1947,7 @@ static const uint16 kq7PatchSubtitleFix3[] = { PATCH_ADDTOOFFSET(+2), // skip over "pToa initialized code" 0x2f, 0x0c, // bt [skip init code] - saved 1 byte 0x38, - PATCH_GETORIGINALBYTE(+6), - PATCH_GETORIGINALBYTE(+7), // pushi (init) + PATCH_GETORIGINALUINT16(+6), // pushi (init) 0x76, // push0 0x54, PATCH_UINT16(0x0004), // self 04 // additionally set background color here (5 bytes) @@ -2488,12 +2485,79 @@ static const uint16 laurabow1PatchArmorOilingArmFix[] = { PATCH_END }; +// When you tell Lilly about Gertie in room 35, Lilly will then walk to the left and off the screen. +// In case Laura (ego) is in the way, the whole game will basically block and you won't be able +// to do anything except saving + restoring the game. +// +// If this happened already, the player can enter +// "send Lillian ignoreActors 1" inside the debugger to fix this situation. +// +// This issue is very difficult to solve, because Lilly also walks diagonally after walking to the left right +// under the kitchen table. This means that even if we added a few more rectangle checks, there could still be +// spots, where the game would block. +// +// Also the mover "PathOut" is used for Lillian instead of the regular "MoveTo", which would avoid other +// actors by itself. +// +// So instead we set Lilly to ignore other actors during that cutscene, which is the least invasive solution. +// +// Applies to at least: English PC Floppy, English Amiga Floppy, English Atari ST Floppy +// Responsible method: goSee::changeState(1) in script 236 +// Fixes bug: (happened during GOG Let's Play) +static const uint16 laurabow1SignatureTellLillyAboutGerieBlockingFix1[] = { + 0x7a, // puah2 + SIG_MAGICDWORD, + 0x38, SIG_UINT16(0x00c1), // pushi 00C1h + 0x38, SIG_UINT16(0x008f), // pushi 008Fh + 0x38, SIG_SELECTOR16(ignoreActors), // pushi (ignoreActors) + 0x78, // push1 + 0x76, // push0 + SIG_END +}; + +static const uint16 laurabow1PatchTellLillyAboutGertieBlockingFix1[] = { + PATCH_ADDTOOFFSET(+11), // skip over until push0 + 0x78, // push1 (change push0 to push1) + PATCH_END +}; + +// a second patch to call Lillian::ignoreActors(1) on goSee::changeState(9) in script 236 +static const uint16 laurabow1SignatureTellLillyAboutGerieBlockingFix2[] = { + 0x3c, // dup + 0x35, 0x09, // ldi 09 + 0x1a, // eq? + 0x30, SIG_UINT16(0x003f), // bnt [ret] + 0x39, SIG_ADDTOOFFSET(+1), // pushi (view) + 0x78, // push1 + 0x38, SIG_UINT16(0x0203), // pushi 203h (515d) + 0x38, SIG_ADDTOOFFSET(+2), // pushi (posn) + 0x7a, // push2 + 0x38, SIG_UINT16(0x00c9), // pushi C9h (201d) + SIG_MAGICDWORD, + 0x38, SIG_UINT16(0x0084), // pushi 84h (132d) + 0x72, SIG_ADDTOOFFSET(+2), // lofsa Lillian (different offsets for different platforms) + 0x4a, 0x0e, // send 0Eh + SIG_END +}; + +static const uint16 laurabow1PatchTellLillyAboutGertieBlockingFix2[] = { + 0x38, PATCH_SELECTOR16(ignoreActors), // pushi (ignoreActors) + 0x78, // push1 + 0x76, // push0 + 0x33, 0x00, // ldi 00 (waste 2 bytes) + PATCH_ADDTOOFFSET(+19), // skip over until send + 0x4a, 0x14, // send 14h + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry laurabow1Signatures[] = { - { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix }, - { true, 37, "armor open visor fix", 1, laurabow1SignatureArmorOpenVisorFix, laurabow1PatchArmorOpenVisorFix }, - { true, 37, "armor move to fix", 2, laurabow1SignatureArmorMoveToFix, laurabow1PatchArmorMoveToFix }, - { true, 37, "allowing input, after oiling arm", 1, laurabow1SignatureArmorOilingArmFix, laurabow1PatchArmorOilingArmFix }, + { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix }, + { true, 37, "armor open visor fix", 1, laurabow1SignatureArmorOpenVisorFix, laurabow1PatchArmorOpenVisorFix }, + { true, 37, "armor move to fix", 2, laurabow1SignatureArmorMoveToFix, laurabow1PatchArmorMoveToFix }, + { true, 37, "allowing input, after oiling arm", 1, laurabow1SignatureArmorOilingArmFix, laurabow1PatchArmorOilingArmFix }, + { true, 236, "tell Lilly about Gertie blocking fix 1/2", 1, laurabow1SignatureTellLillyAboutGerieBlockingFix1, laurabow1PatchTellLillyAboutGertieBlockingFix1 }, + { true, 236, "tell Lilly about Gertie blocking fix 2/2", 1, laurabow1SignatureTellLillyAboutGerieBlockingFix2, laurabow1PatchTellLillyAboutGertieBlockingFix2 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -2614,6 +2678,98 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = { PATCH_END }; +// When entering the main musem party room (w/ the golden Egyptian head), +// Laura is waslking a bit into the room automatically. +// In case you press a mouse button while this is happening, you will get +// stuck inside that room and won't be able to exit it anymore. +// +// Users, who played the game w/ a previous version of ScummVM can simply +// enter the debugger and then enter "send rm350 script 0:0", which will +// fix the script state. +// +// This is caused by the user controls not being locked at that point. +// Pressing a button will cause the cue from the PolyPath walker to never +// happen, which then causes sEnterSouth to never dispose itself. +// +// User controls are locked in the previous room 335, but controls +// are unlocked by frontDoor::cue. +// We do not want to change this, because it could have side-effects. +// We instead add another LB2::handsOff call inside the script responsible +// for making Laura walk into the room (sEnterSouth::changeState(0). +// +// Applies to at least: English PC-CD, English PC-Floppy, German PC-Floppy +// Responsible method: sEnterSouth::changeState +// Fixes bug: (no bug report, from GOG forum post) +static const uint16 laurabow2SignatureMuseumPartyFixEnteringSouth1[] = { + 0x3c, // dup + 0x35, 0x00, // ldi 00 + 0x1a, // eq? + 0x30, SIG_UINT16(0x0097), // bnt [state 1 code] + SIG_ADDTOOFFSET(+141), // skip to end of follow-up code + 0x32, SIG_ADDTOOFFSET(+2), // jmp [ret] (0x008d for CD, 0x007d for floppy) + 0x35, 0x01, // ldi 01 + 0x65, 0x1a, // aTop cycles + 0x32, SIG_ADDTOOFFSET(+2), // jmp [ret] (0x0086 for CD, 0x0076 for floppy) + // state 1 code + 0x3c, // dup + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + SIG_MAGICDWORD, + 0x31, 0x05, // bnt [state 2 code] + 0x35, 0x00, // ldi 00 + 0x32, SIG_ADDTOOFFSET(+2), // jmp [ret] (0x007b for CD, 0x006b for floppy) + // state 2 code + 0x3c, // dup + SIG_END +}; + +static const uint16 laurabow2PatchMuseumPartyFixEnteringSouth1[] = { + 0x2e, PATCH_UINT16(0x00a6), // bt [state 2 code] (we skip state 1, because it's a NOP anyways) + // state 0 processing + 0x32, PATCH_UINT16(+151), + SIG_ADDTOOFFSET(+149), // skip to end of follow-up code + // save 1 byte by replacing jump to [ret] into straight toss/ret + 0x3a, // toss + 0x48, // ret + + // additional code, that gets called right at the start of step 0 processing + 0x18, // not -- this here is where pushi handsOff will be inserted by the second patch + 0x18, // not offset and handsOff is different for floppy + CD, that's why we do this + 0x18, // not floppy also does not have a selector table, so we can't go by "handsOff" name + 0x18, // not + 0x76, // push0 + 0x81, 0x01, // lag global[1] + 0x4a, 0x04, // send 04 + 0x32, PATCH_UINT16(0xFF5e), // jmp [back to start of step 0 processing] + PATCH_END +}; + +// second patch, which only inserts pushi handsOff inside our new code +// There is no other way to do this except making 2 full patches for floppy + CD, because handsOff/handsOn +// is not the same value between floppy + CD *and* floppy doesn't even have a vocab, so we can't figure out the id +// by ourselves. +static const uint16 laurabow2SignatureMuseumPartyFixEnteringSouth2[] = { + 0x18, // our injected code + 0x18, + 0x18, + SIG_ADDTOOFFSET(+92), // skip to the handsOn code, that we are interested in + 0x38, SIG_ADDTOOFFSET(+2), // pushi handsOn (0x0189 for CD, 0x024b for floppy) + 0x76, // push0 + 0x81, 0x01, // lag global[1] + 0x4a, 0x04, // send 04 + 0x38, SIG_ADDTOOFFSET(+2), // pushi 0274h + SIG_MAGICDWORD, + 0x78, // push1 + 0x38, SIG_UINT16(0x033f), // pushi 033f + SIG_END +}; + +static const uint16 laurabow2PatchMuseumPartyFixEnteringSouth2[] = { + 0x38, // pushi + PATCH_GETORIGINALUINT16ADJUST(+96, -1), // get handsOff code and ubstract 1 from it to get handsOn + PATCH_END +}; + // Opening/Closing the east door in the pterodactyl room doesn't // check, if it's locked and will open/close the door internally // even when it is. @@ -2628,7 +2784,7 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = { // Responsible method (CD): eastDoor::doVerb // Responsible method (Floppy): eastDoor::<noname300> // Fixes bug: #6458 (partly, see additional patch below) -static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = { +static const uint16 laurabow2SignatureFixWiredEastDoor[] = { 0x30, SIG_UINT16(0x0022), // bnt [skip hand action] 0x67, SIG_ADDTOOFFSET(+1), // pTos CD: doorState, Floppy: state 0x35, 0x00, // ldi 00 @@ -2651,7 +2807,7 @@ static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = { SIG_END }; -static const uint16 laurabow2CDPatchFixWiredEastDoor[] = { +static const uint16 laurabow2PatchFixWiredEastDoor[] = { 0x31, 0x23, // bnt [skip hand action] (saves 1 byte) 0x81, 97, // lag 97d (get our eastDoor-wired-global) 0x31, 0x04, // bnt [skip setting locked property] @@ -2780,20 +2936,22 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport2[] = { // script, description, signature patch static const SciScriptPatcherEntry laurabow2Signatures[] = { - { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, - { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, - { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor }, - { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2CDSignatureFixWiredEastDoor, laurabow2CDPatchFixWiredEastDoor }, + { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, + { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, + { true, 350, "CD/Floppy: museum party fix entering south 1/2", 1, laurabow2SignatureMuseumPartyFixEnteringSouth1, laurabow2PatchMuseumPartyFixEnteringSouth1 }, + { true, 350, "CD/Floppy: museum party fix entering south 2/2", 1, laurabow2SignatureMuseumPartyFixEnteringSouth2, laurabow2PatchMuseumPartyFixEnteringSouth2 }, + { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor }, + { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2SignatureFixWiredEastDoor, laurabow2PatchFixWiredEastDoor }, // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support - { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, - { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, - { false, 924, "CD: audio + text support 3", 1, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, - { false, 928, "CD: audio + text support 4", 1, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, - { false, 928, "CD: audio + text support 5", 2, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, - { false, 0, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, - { false, 100, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, - { false, 24, "CD: audio + text support LB2 menu 1", 1, laurabow2CDSignatureAudioTextMenuSupport1, laurabow2CDPatchAudioTextMenuSupport1 }, - { false, 24, "CD: audio + text support LB2 menu 2", 1, laurabow2CDSignatureAudioTextMenuSupport2, laurabow2CDPatchAudioTextMenuSupport2 }, + { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, + { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, + { false, 924, "CD: audio + text support 3", 1, kq6laurabow2CDSignatureAudioTextSupport3, kq6laurabow2CDPatchAudioTextSupport3 }, + { false, 928, "CD: audio + text support 4", 1, kq6laurabow2CDSignatureAudioTextSupport4, kq6laurabow2CDPatchAudioTextSupport4 }, + { false, 928, "CD: audio + text support 5", 2, kq6laurabow2CDSignatureAudioTextSupport5, kq6laurabow2CDPatchAudioTextSupport5 }, + { false, 0, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, + { false, 100, "CD: audio + text support disable mode reset", 1, laurabow2CDSignatureAudioTextSupportModeReset, laurabow2CDPatchAudioTextSupportModeReset }, + { false, 24, "CD: audio + text support LB2 menu 1", 1, laurabow2CDSignatureAudioTextMenuSupport1, laurabow2CDPatchAudioTextMenuSupport1 }, + { false, 24, "CD: audio + text support LB2 menu 2", 1, laurabow2CDSignatureAudioTextMenuSupport2, laurabow2CDPatchAudioTextMenuSupport2 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -3939,8 +4097,7 @@ static const uint16 qfg3PatchMissingPoints1[] = { PATCH_UINT16(0xFFD6), // -42 "Greet" PATCH_UINT16(0xFFB0), // -80 "Say Good-bye" PATCH_UINT16(0x03E7), // 999 END MARKER - PATCH_GETORIGINALBYTE(+28), // local[$aa][0].low - PATCH_GETORIGINALBYTE(+29), // local[$aa][0].high + PATCH_GETORIGINALUINT16(+28), // local[$aa][0] PATCH_END }; @@ -4841,14 +4998,6 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc break; } case PATCH_CODE_GETORIGINALBYTE: { - // get original byte from script - if (patchValue >= orgDataSize) - error("Script-Patcher: can not get requested original byte from script"); - scriptData[offset] = orgData[patchValue]; - offset++; - break; - } - case PATCH_CODE_GETORIGINALBYTEADJUST: { // get original byte from script and adjust it if (patchValue >= orgDataSize) error("Script-Patcher: can not get requested original byte from script"); @@ -4859,6 +5008,30 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc offset++; break; } + case PATCH_CODE_GETORIGINALUINT16: { + // get original byte from script and adjust it + if ((patchValue >= orgDataSize) || (((uint32)patchValue + 1) >= orgDataSize)) + error("Script-Patcher: can not get requested original uint16 from script"); + uint16 orgUINT16; + int16 adjustValue; + + if (!_isMacSci11) { + orgUINT16 = orgData[patchValue] | (orgData[patchValue + 1] << 8); + } else { + orgUINT16 = orgData[patchValue + 1] | (orgData[patchValue] << 8); + } + patchData++; adjustValue = (int16)(*patchData); + orgUINT16 += adjustValue; + if (!_isMacSci11) { + scriptData[offset] = orgUINT16 & 0xFF; + scriptData[offset + 1] = orgUINT16 >> 8; + } else { + scriptData[offset] = orgUINT16 >> 8; + scriptData[offset + 1] = orgUINT16 & 0xFF; + } + offset += 2; + break; + } case PATCH_CODE_UINT16: case PATCH_CODE_SELECTOR16: { byte byte1; @@ -5134,7 +5307,8 @@ void ScriptPatcher::calculateMagicDWordAndVerify(const char *signatureDescriptio } break; } - case PATCH_CODE_GETORIGINALBYTEADJUST: { + case PATCH_CODE_GETORIGINALBYTE: + case PATCH_CODE_GETORIGINALUINT16: { signatureData++; // skip over extra uint16 break; } diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h index f95806a3f3..b5797be847 100644 --- a/engines/sci/engine/script_patches.h +++ b/engines/sci/engine/script_patches.h @@ -44,23 +44,25 @@ namespace Sci { #define SIG_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) #define SIG_CODE_BYTE 0x0000 -#define PATCH_END SIG_END -#define PATCH_COMMANDMASK SIG_COMMANDMASK -#define PATCH_VALUEMASK SIG_VALUEMASK -#define PATCH_BYTEMASK SIG_BYTEMASK -#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET -#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_) -#define PATCH_CODE_GETORIGINALBYTE 0xD000 -#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_) -#define PATCH_CODE_GETORIGINALBYTEADJUST 0xC000 -#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTEADJUST | (_offset_), (uint16)(_adjustValue_) -#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16 -#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_ -#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8 -#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_ -#define PATCH_CODE_UINT16 SIG_CODE_UINT16 -#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) -#define PATCH_CODE_BYTE SIG_CODE_BYTE +#define PATCH_END SIG_END +#define PATCH_COMMANDMASK SIG_COMMANDMASK +#define PATCH_VALUEMASK SIG_VALUEMASK +#define PATCH_BYTEMASK SIG_BYTEMASK +#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET +#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_) +#define PATCH_CODE_GETORIGINALBYTE 0xC000 +#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_), 0 +#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTE | (_offset_), (uint16)(_adjustValue_) +#define PATCH_CODE_GETORIGINALUINT16 0xD000 +#define PATCH_GETORIGINALUINT16(_offset_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), 0 +#define PATCH_GETORIGINALUINT16ADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), (uint16)(_adjustValue_) +#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16 +#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_ +#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8 +#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_ +#define PATCH_CODE_UINT16 SIG_CODE_UINT16 +#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) +#define PATCH_CODE_BYTE SIG_CODE_BYTE // defines maximum scratch area for getting original bytes from unpatched script data #define PATCH_VALUELIMIT 4096 diff --git a/engines/titanic/module.mk b/engines/titanic/module.mk index aaa2a99671..cdb3a64b3c 100644 --- a/engines/titanic/module.mk +++ b/engines/titanic/module.mk @@ -436,10 +436,10 @@ MODULE_OBJS := \ star_control/dvector.o \ star_control/fmatrix.o \ star_control/fpoint.o \ + star_control/frange.o \ star_control/frect.o \ star_control/fvector.o \ star_control/star_control_sub2.o \ - star_control/star_control_sub4.o \ star_control/star_control_sub5.o \ star_control/star_control_sub6.o \ star_control/star_control_sub7.o \ @@ -457,6 +457,7 @@ MODULE_OBJS := \ star_control/star_field.o \ star_control/star_points1.o \ star_control/star_points2.o \ + star_control/star_ref.o \ star_control/star_view.o \ star_control/surface_area.o \ star_control/surface_fader_base.o \ diff --git a/engines/titanic/star_control/base_star.cpp b/engines/titanic/star_control/base_star.cpp index a32263a926..ffe5fd05b4 100644 --- a/engines/titanic/star_control/base_star.cpp +++ b/engines/titanic/star_control/base_star.cpp @@ -22,6 +22,7 @@ #include "titanic/star_control/base_star.h" #include "titanic/star_control/star_control_sub12.h" +#include "titanic/star_control/star_ref.h" #include "titanic/titanic.h" namespace Titanic { @@ -44,6 +45,15 @@ void CBaseStarEntry::load(Common::SeekableReadStream &s) { _data[idx] = s.readUint32LE(); } +bool CBaseStarEntry::operator==(const CBaseStarEntry &s) const { + return _field0 == s._field0 && _field1 == s._field1 + && _field2 == s._field2 && _field3 == s._field3 + && _value == s._value && _position == s._position + && _data[0] == s._data[0] && _data[1] == s._data[1] + && _data[2] == s._data[2] && _data[3] == s._data[3] + && _data[4] == s._data[4]; +} + /*------------------------------------------------------------------------*/ CBaseStar::CBaseStar() : _minVal(0.0), _maxVal(1.0), _range(0.0), @@ -57,11 +67,11 @@ void CBaseStar::clear() { void CBaseStar::initialize() { _minVal = 9.9999998e10; _maxVal = -9.9999998e10; - _sub4.initialize(); + _minMax.reset(); for (uint idx = 0; idx < _data.size(); ++idx) { const CBaseStarEntry *entry = getDataPtr(idx); - _sub4.checkEntry(entry->_position); + _minMax.expand(entry->_position); if (entry->_value < _minVal) _minVal = entry->_value; @@ -191,13 +201,17 @@ void CBaseStar::draw4(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, CStar // TODO } -void CBaseStar::baseFn1(int v1, int v2, int v3, int v4) { - // TODO +int CBaseStar::baseFn1(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, + const Common::Point &pt) { + CStarRef1 ref(this, pt); + ref.process(surfaceArea, sub12); + return ref._index; } int CBaseStar::baseFn2(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12) { - // TODO - return 0; + CStarRef3 ref(this); + ref.process(surfaceArea, sub12); + return ref._index; } } // End of namespace Titanic diff --git a/engines/titanic/star_control/base_star.h b/engines/titanic/star_control/base_star.h index 1450b25bb3..8fc36ba6c7 100644 --- a/engines/titanic/star_control/base_star.h +++ b/engines/titanic/star_control/base_star.h @@ -24,7 +24,7 @@ #define TITANIC_STAR_CONTROL_SUB3_H #include "titanic/support/simple_file.h" -#include "titanic/star_control/star_control_sub4.h" +#include "titanic/star_control/frange.h" #include "titanic/star_control/star_control_sub5.h" #include "titanic/star_control/surface_area.h" @@ -44,7 +44,23 @@ struct CBaseStarEntry { uint _data[5]; CBaseStarEntry(); + + /** + * Loads the data for a star + */ void load(Common::SeekableReadStream &s); + + bool operator==(const CBaseStarEntry &s) const; +}; + +struct CStarPosition : public Common::Point { + int _index1; + int _index2; + CStarPosition() : _index1(0), _index2(0) {} + + bool operator==(const CStarPosition &sp) const { + return x == sp.x && y == sp.y && _index1 == sp._index1 && _index2 == sp._index2; + } }; class CBaseStar { @@ -55,7 +71,7 @@ private: void draw4(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, CStarControlSub5 *sub5); protected: Common::Array<CBaseStarEntry> _data; - CStarControlSub4 _sub4; + FRange _minMax; double _minVal; double _maxVal; double _range; @@ -76,9 +92,6 @@ protected: * Reset the data for an entry */ void resetEntry(CBaseStarEntry &entry); - - void baseFn1(int v1, int v2, int v3, int v4); - int baseFn2(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12); public: CBaseStar(); virtual ~CBaseStar() {} @@ -94,7 +107,7 @@ public: * Selects a star */ virtual bool selectStar(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, - int flags, const Common::Point &pt) { return false; } + const Common::Point &pt, void *handler = nullptr) { return false; } /** * Adds a new star, or removes one if already present at the given co-ordinates @@ -126,6 +139,11 @@ public: * Get a pointer to a data entry */ const CBaseStarEntry *getDataPtr(int index) const; + + int baseFn1(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, + const Common::Point &pt); + + int baseFn2(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/dmatrix.cpp b/engines/titanic/star_control/dmatrix.cpp index 70008054b6..940b34833f 100644 --- a/engines/titanic/star_control/dmatrix.cpp +++ b/engines/titanic/star_control/dmatrix.cpp @@ -29,25 +29,40 @@ namespace Titanic { DMatrix *DMatrix::_static; DMatrix::DMatrix() : - _row1(1.0, 0.0, 0.0), _row2(0.0, 1.0, 0.0), _row3(0.0, 0.0, 1.0) { + _row1(1.875, 0.0, 0.0), _row2(0.0, 1.875, 0.0), _row3(0.0, 0.0, 1.875) { } -DMatrix::DMatrix(int mode, const FMatrix *src) { - assert(!mode); - - _row1._x = 1.0; - _row2._y = 1.0; - _row3._z = 1.0; - _frow1._x = src->_row1._x; - _frow1._y = src->_row1._y; - _frow1._z = src->_row1._z; - _frow2._x = src->_row2._x; - _frow2._y = src->_row2._y; - _frow2._z = src->_row2._z; +DMatrix::DMatrix(int mode, const DVector &src) { + switch (mode) { + case 0: + _row1._x = 1.0; + _row2._y = 1.0; + _row3._z = 1.0; + _row4 = src; + break; + + case 1: + _row1._x = src._x; + _row2._y = src._y; + _row3._z = src._z; + break; + + default: + _row1._x = 1.0; + _row2._y = 1.0; + _row3._z = 1.0; + break; + } } -DMatrix::DMatrix(int mode, double val) { - set(mode, val); +DMatrix::DMatrix(Axis axis, double amount) { + setRotationMatrix(axis, amount); +} + +DMatrix::DMatrix(const FMatrix &src) { + _row1 = src._row1; + _row2 = src._row2; + _row3 = src._row3; } void DMatrix::init() { @@ -59,13 +74,13 @@ void DMatrix::deinit() { _static = nullptr; } -void DMatrix::set(int mode, double amount) { +void DMatrix::setRotationMatrix(Axis axis, double amount) { const double FACTOR = 0.0174532925199433; double sinVal = sin(amount * FACTOR); double cosVal = cos(amount * FACTOR); - switch (mode) { - case 0: + switch (axis) { + case X_AXIS: _row1._x = 1.0; _row2._y = cosVal; _row2._z = sinVal; @@ -73,7 +88,7 @@ void DMatrix::set(int mode, double amount) { _row3._z = cosVal; break; - case 1: + case Y_AXIS: _row1._x = cosVal; _row1._z = sinVal; _row2._y = 1.0; @@ -81,7 +96,7 @@ void DMatrix::set(int mode, double amount) { _row3._z = cosVal; break; - case 2: + case Z_AXIS: _row1._x = cosVal; _row1._y = sinVal; _row2._x = -sinVal; @@ -94,6 +109,10 @@ void DMatrix::set(int mode, double amount) { } } +void DMatrix::fn1(DMatrix &m) { + // TODO +} + void DMatrix::fn3(CStarControlSub26 *sub26) { double v = sub26->fn1(); v = (v < 0.0) ? 0.0 : 2.0 / v; @@ -101,4 +120,9 @@ void DMatrix::fn3(CStarControlSub26 *sub26) { error("TODO: DMatrix::fn3 %d", (int)v); } +const DMatrix *DMatrix::fn4(DMatrix &dest, const DMatrix &m1, const DMatrix &m2) { + // TODO + return nullptr; +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/dmatrix.h b/engines/titanic/star_control/dmatrix.h index 14f6bb0331..c3490770fb 100644 --- a/engines/titanic/star_control/dmatrix.h +++ b/engines/titanic/star_control/dmatrix.h @@ -42,22 +42,25 @@ public: DVector _row1; DVector _row2; DVector _row3; - FVector _frow1; - FVector _frow2; + DVector _row4; public: static void init(); static void deinit(); public: DMatrix(); - DMatrix(int mode, const FMatrix *src); - DMatrix(int mode, double val); + DMatrix(int mode, const DVector &src); + DMatrix(Axis axis, double amount); + DMatrix(const FMatrix &src); /** - * Sets up data for the matrix + * Sets up a matrix for rotating on a given axis by a given amount */ - void set(int mode, double amount); + void setRotationMatrix(Axis axis, double amount); + void fn1(DMatrix &m); void fn3(CStarControlSub26 *sub26); + + const DMatrix *fn4(DMatrix &dest, const DMatrix &m1, const DMatrix &m2); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/dvector.cpp b/engines/titanic/star_control/dvector.cpp index e4c5b15cb0..dc1376537e 100644 --- a/engines/titanic/star_control/dvector.cpp +++ b/engines/titanic/star_control/dvector.cpp @@ -25,7 +25,7 @@ namespace Titanic { -void DVector::fn3() { +void DVector::normalize() { double hyp = sqrt(_x * _x + _y * _y + _z * _z); assert(hyp); @@ -34,4 +34,29 @@ void DVector::fn3() { _z *= 1.0 / hyp; } +double DVector::getDistance(const DVector &src) { + return sqrt((src._x - _x) * (src._x - _x) + (src._y - _y) * (src._y - _y) + (src._z - _z) * (src._z - _z)); +} + +void DVector::fn1(DVector &dest, const DMatrix &m) { + // TODO +} + +void DVector::fn2(double val) { + // TODO +} + +void DVector::fn3(DVector &dest) { + // TODO +} + +const DMatrix *DVector::fn4(const DVector &v, DMatrix &m) { + // TODO + return nullptr; +} + +void DVector::fn5(DMatrix &dest) { + // TODO +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/dvector.h b/engines/titanic/star_control/dvector.h index 7aca407c1c..a216be15fe 100644 --- a/engines/titanic/star_control/dvector.h +++ b/engines/titanic/star_control/dvector.h @@ -23,8 +23,12 @@ #ifndef TITANIC_DVECTOR_H #define TITANIC_DVECTOR_H +#include "titanic/star_control/fvector.h" + namespace Titanic { +class DMatrix; + /** * Double based vector class. * @remarks TODO: See if it can be merged with FVector @@ -35,8 +39,20 @@ public: public: DVector() : _x(0), _y(0), _z(0) {} DVector(double x, double y, double z) : _x(x), _y(y), _z(z) {} + DVector(const FVector &v) : _x(v._x), _y(v._y), _z(v._z) {} + + void normalize(); + + /** + * Returns the distance between this vector and the passed one + */ + double getDistance(const DVector &src); - void fn3(); + void fn1(DVector &dest, const DMatrix &m); + void fn2(double val); + void fn3(DVector &dest); + const DMatrix *fn4(const DVector &v, DMatrix &m); + void fn5(DMatrix &dest); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/fmatrix.cpp b/engines/titanic/star_control/fmatrix.cpp index af15477d04..02da11576c 100644 --- a/engines/titanic/star_control/fmatrix.cpp +++ b/engines/titanic/star_control/fmatrix.cpp @@ -28,17 +28,17 @@ FMatrix::FMatrix() : _row1(1.0, 0.0, 0.0), _row2(0.0, 1.0, 0.0), _row3(0.0, 0.0, 1.0) { } -FMatrix::FMatrix(DMatrix *src) { +FMatrix::FMatrix(const DMatrix &src) { copyFrom(src); } -FMatrix::FMatrix(FMatrix *src) { - _row1 = src->_row1; - _row2 = src->_row2; - _row3 = src->_row3; +FMatrix::FMatrix(const FMatrix &src) { + _row1 = src._row1; + _row2 = src._row2; + _row3 = src._row3; } -void FMatrix::copyFrom(const DMatrix *src) { +void FMatrix::copyFrom(const DMatrix &src) { // TODO } @@ -67,19 +67,25 @@ void FMatrix::save(SimpleFile *file, int indent) { } void FMatrix::clear() { + _row1.clear(); + _row2.clear(); + _row3.clear(); +} + +void FMatrix::identity() { _row1 = FVector(1.0, 0.0, 0.0); _row2 = FVector(0.0, 1.0, 0.0); _row3 = FVector(0.0, 0.0, 1.0); } -void FMatrix::set(FVector *row1, FVector *row2, FVector *row3) { - _row1 = *row1; - _row2 = *row2; - _row3 = *row3; +void FMatrix::set(const FVector &row1, const FVector &row2, const FVector &row3) { + _row1 = row1; + _row2 = row2; + _row3 = row3; } -void FMatrix::fn1(const FVector *v) { - _row3._x = v->_x; +void FMatrix::fn1(const FVector &v) { + _row3._x = v._x; FVector tempVector; _row3.fn1(&tempVector); @@ -88,45 +94,45 @@ void FMatrix::fn1(const FVector *v) { _row2._y = tempVector._y; _row2._z = tempVector._z; - _row3.multiply(&tempVector, &_row2); + _row3.crossProduct(&tempVector, &_row2); _row1._x = _row2._x; _row1._y = _row2._y; _row1._z = _row2._z; - _row1.fn3(); + _row1.normalize(); - _row3.multiply(&tempVector, &_row1); + _row3.crossProduct(&tempVector, &_row1); _row2._x = _row1._x; _row2._y = _row1._y; _row2._z = _row1._z; - _row2.fn3(); + _row2.normalize(); } -void FMatrix::fn2(FMatrix *m) { - double x1 = _row1._y * m->_row2._x + _row1._z * m->_row3._x + _row1._x * m->_row1._x; - double y1 = _row1._x * m->_row1._y + m->_row2._y * _row1._y + m->_row3._y * _row1._z; - double z1 = _row1._x * m->_row1._z + _row1._y * m->_row2._z + _row1._z * m->_row3._z; - double x2 = m->_row1._x * _row2._x + m->_row3._x * _row2._z + m->_row2._x * _row2._y; - double y2 = m->_row3._y * _row2._z + m->_row1._y * _row2._x + m->_row2._y * _row2._y; - double z2 = _row2._z * m->_row3._z + _row2._x * m->_row1._z + _row2._y * m->_row2._z; - double x3 = m->_row1._x * _row3._x + _row3._z * m->_row3._x + _row3._y * m->_row2._x; - double y3 = _row3._y * m->_row2._y + _row3._z * m->_row3._y + _row3._x * m->_row1._y; - double z3 = _row3._x * m->_row1._z + _row3._y * m->_row2._z + _row3._z * m->_row3._z; +void FMatrix::fn2(const FMatrix &m) { + double x1 = _row1._y * m._row2._x + _row1._z * m._row3._x + _row1._x * m._row1._x; + double y1 = _row1._x * m._row1._y + m._row2._y * _row1._y + m._row3._y * _row1._z; + double z1 = _row1._x * m._row1._z + _row1._y * m._row2._z + _row1._z * m._row3._z; + double x2 = m._row1._x * _row2._x + m._row3._x * _row2._z + m._row2._x * _row2._y; + double y2 = m._row3._y * _row2._z + m._row1._y * _row2._x + m._row2._y * _row2._y; + double z2 = _row2._z * m._row3._z + _row2._x * m._row1._z + _row2._y * m._row2._z; + double x3 = m._row1._x * _row3._x + _row3._z * m._row3._x + _row3._y * m._row2._x; + double y3 = _row3._y * m._row2._y + _row3._z * m._row3._y + _row3._x * m._row1._y; + double z3 = _row3._x * m._row1._z + _row3._y * m._row2._z + _row3._z * m._row3._z; _row1 = FVector(x1, y1, z1); _row2 = FVector(x2, y2, z2); _row3 = FVector(x3, y3, z3); } -void FMatrix::fn3(FMatrix *m) { - double x1 = _row2._x * m->_row1._y + m->_row1._z * _row3._x + _row1._x * m->_row1._x; - double y1 = m->_row1._x * _row1._y + _row3._y * m->_row1._z + _row2._y * m->_row1._y; - double z1 = m->_row1._x * _row1._z + m->_row1._y * _row2._z + m->_row1._z * _row3._z; - double x2 = _row1._x * m->_row2._x + _row2._x * m->_row2._y + _row3._x * m->_row2._z; - double y2 = _row3._y * m->_row2._z + _row1._y * m->_row2._x + _row2._y * m->_row2._y; - double z2 = m->_row2._z * _row3._z + m->_row2._x * _row1._z + m->_row2._y * _row2._z; - double x3 = _row1._x * m->_row3._x + m->_row3._z * _row3._x + m->_row3._y * _row2._x; - double y3 = m->_row3._y * _row2._y + m->_row3._z * _row3._y + m->_row3._x * _row1._y; - double z3 = m->_row3._x * _row1._z + m->_row3._y * _row2._z + m->_row3._z * _row3._z; +void FMatrix::fn3(const FMatrix &m) { + double x1 = _row2._x * m._row1._y + m._row1._z * _row3._x + _row1._x * m._row1._x; + double y1 = m._row1._x * _row1._y + _row3._y * m._row1._z + _row2._y * m._row1._y; + double z1 = m._row1._x * _row1._z + m._row1._y * _row2._z + m._row1._z * _row3._z; + double x2 = _row1._x * m._row2._x + _row2._x * m._row2._y + _row3._x * m._row2._z; + double y2 = _row3._y * m._row2._z + _row1._y * m._row2._x + _row2._y * m._row2._y; + double z2 = m._row2._z * _row3._z + m._row2._x * _row1._z + m._row2._y * _row2._z; + double x3 = _row1._x * m._row3._x + m._row3._z * _row3._x + m._row3._y * _row2._x; + double y3 = m._row3._y * _row2._y + m._row3._z * _row3._y + m._row3._x * _row1._y; + double z3 = m._row3._x * _row1._z + m._row3._y * _row2._z + m._row3._z * _row3._z; _row1 = FVector(x1, y1, z1); _row2 = FVector(x2, y2, z2); diff --git a/engines/titanic/star_control/fmatrix.h b/engines/titanic/star_control/fmatrix.h index d7c4acfbdc..6fa847f950 100644 --- a/engines/titanic/star_control/fmatrix.h +++ b/engines/titanic/star_control/fmatrix.h @@ -39,15 +39,15 @@ private: /** * Copys data from a given source */ - void copyFrom(const DMatrix *src); + void copyFrom(const DMatrix &src); public: FVector _row1; FVector _row2; FVector _row3; public: FMatrix(); - FMatrix(DMatrix *src); - FMatrix(FMatrix *src); + FMatrix(const DMatrix &src); + FMatrix(const FMatrix &src); /** * Load the data for the class from file @@ -65,14 +65,18 @@ public: void clear(); /** - * Sets the data for the matrix + * Sets up an identity matrix */ - void set(FVector *row1, FVector *row2, FVector *row3); + void identity(); - void fn1(const FVector *v); + /** + * Sets the data for the matrix + */ + void set(const FVector &row1, const FVector &row2, const FVector &row3); - void fn2(FMatrix *m); - void fn3(FMatrix *m); + void fn1(const FVector &v); + void fn2(const FMatrix &m); + void fn3(const FMatrix &m); /** * Returns true if the passed matrix equals this one @@ -91,4 +95,4 @@ public: } // End of namespace Titanic -#endif /* TITANIC_MATRIX3_H */ +#endif /* TITANIC_FMATRIX_H */ diff --git a/engines/titanic/star_control/star_control_sub4.cpp b/engines/titanic/star_control/frange.cpp index 6ce0795c25..e70976d6cd 100644 --- a/engines/titanic/star_control/star_control_sub4.cpp +++ b/engines/titanic/star_control/frange.cpp @@ -21,19 +21,19 @@ */ #include "common/algorithm.h" -#include "titanic/star_control/star_control_sub4.h" +#include "titanic/star_control/frange.h" namespace Titanic { -CStarControlSub4::CStarControlSub4() { +FRange::FRange() { } -void CStarControlSub4::initialize() { +void FRange::reset() { _min._x = _min._y = _min._z = 9.9999994e27; _max._x = _max._y = _max._z = -9.9999994e27; } -void CStarControlSub4::checkEntry(const FVector &v) { +void FRange::expand(const FVector &v) { _min._x = MIN(_min._x, v._x); _min._y = MIN(_min._y, v._y); _min._z = MIN(_min._z, v._z); diff --git a/engines/titanic/star_control/star_control_sub4.h b/engines/titanic/star_control/frange.h index 43c8ab5f79..f36aa2c538 100644 --- a/engines/titanic/star_control/star_control_sub4.h +++ b/engines/titanic/star_control/frange.h @@ -20,25 +20,31 @@ * */ -#ifndef TITANIC_STAR_CONTROL_SUB4_H -#define TITANIC_STAR_CONTROL_SUB4_H +#ifndef TITANIC_FRANGE_H +#define TITANIC_FRANGE_H #include "titanic/star_control/fvector.h" namespace Titanic { -class CStarControlSub4 { +class FRange { private: FVector _min; FVector _max; public: - CStarControlSub4(); + FRange(); - void initialize(); + /** + * Resets the minimum & maximum vector values + */ + void reset(); - void checkEntry(const FVector &v); + /** + * Expands the minimum & maximum as necessary to encompass the passed vector/ + */ + void expand(const FVector &v); }; } // End of namespace Titanic -#endif /* TITANIC_STAR_CONTROL_SUB4_H */ +#endif /* TITANIC_FRANGE_H */ diff --git a/engines/titanic/star_control/fvector.cpp b/engines/titanic/star_control/fvector.cpp index aa99e8b4d1..92c17a09b4 100644 --- a/engines/titanic/star_control/fvector.cpp +++ b/engines/titanic/star_control/fvector.cpp @@ -34,19 +34,27 @@ void FVector::fn1(FVector *v) { v->_z = _z; } -void FVector::multiply(FVector *dest, const FVector *src) { +void FVector::crossProduct(FVector *dest, const FVector *src) { dest->_x = (src->_z * _y) - (_z * src->_y); dest->_y = (src->_x * _z) - (_x * src->_z); dest->_z = (src->_y * _x) - (_y * src->_x); } -void FVector::fn3() { +double FVector::normalize() { double hyp = sqrt(_x * _x + _y * _y + _z * _z); assert(hyp); _x *= 1.0 / hyp; _y *= 1.0 / hyp; _z *= 1.0 / hyp; + return hyp; +} + +void FVector::addAndNormalize(FVector *dest, const FVector *v1, const FVector *v2) { + FVector tempVector(v1->_x + v2->_x, v1->_y + v2->_y, v1->_z + v2->_z); + tempVector.normalize(); + + *dest = tempVector; } double FVector::getDistance(const FVector *src) const { @@ -57,14 +65,7 @@ double FVector::getDistance(const FVector *src) const { return sqrt(xd * xd + yd * yd + zd * zd); } -void FVector::fn4(FVector *dest, const FVector *v1, const FVector *v2) { - FVector tempVector(v1->_x + v2->_x, v1->_y + v2->_y, v1->_z + v2->_z); - tempVector.fn3(); - - *dest = tempVector; -} - -void FVector::fn5(FVector *dest, const CStarControlSub6 *sub6) const { +FVector FVector::fn5(const CStarControlSub6 *sub6) const { error("TODO: FVector::fn5"); } diff --git a/engines/titanic/star_control/fvector.h b/engines/titanic/star_control/fvector.h index e19419bf20..4582072f50 100644 --- a/engines/titanic/star_control/fvector.h +++ b/engines/titanic/star_control/fvector.h @@ -27,6 +27,8 @@ namespace Titanic { +enum Axis { X_AXIS, Y_AXIS, Z_AXIS }; + class CStarControlSub6; /** @@ -48,16 +50,28 @@ public: } void fn1(FVector *v); - void multiply(FVector *dest, const FVector *src); - void fn3(); + + /** + * Calculates the cross-product between this matrix and a passed one + */ + void crossProduct(FVector *dest, const FVector *src); + + /** + * Normalizes the vector so the length from origin equals 1.0 + */ + double normalize(); + + /** + * Adds two vectors together and then normalizes the result + */ + static void addAndNormalize(FVector *dest, const FVector *v1, const FVector *v2); /** * Returns the distance between a specified point and this one */ double getDistance(const FVector *src) const; - static void fn4(FVector *dest, const FVector *v1, const FVector *v2); - void fn5(FVector *dest, const CStarControlSub6 *sub6) const; + FVector fn5(const CStarControlSub6 *sub6) const; /** * Returns true if the passed vector equals this one diff --git a/engines/titanic/star_control/star_control_sub12.cpp b/engines/titanic/star_control/star_control_sub12.cpp index 79061301d3..4e6a6bc0f2 100644 --- a/engines/titanic/star_control/star_control_sub12.cpp +++ b/engines/titanic/star_control/star_control_sub12.cpp @@ -29,9 +29,8 @@ namespace Titanic { FMatrix *CStarControlSub12::_matrix1; FMatrix *CStarControlSub12::_matrix2; -CStarControlSub12::CStarControlSub12(void *val1, const CStar20Data *data) : - _currentIndex(-1), _handlerP(nullptr), _field108(0), - _sub13(val1) { +CStarControlSub12::CStarControlSub12(const CStar20Data *data) : + _currentIndex(-1), _handlerP(nullptr), _field108(0) { setupHandler(data); } @@ -55,7 +54,7 @@ CStarControlSub12::~CStarControlSub12() { deleteHandler(); } -void CStarControlSub12::proc2(const void *src) { +void CStarControlSub12::proc2(const CStarControlSub13 *src) { _sub13.copyFrom(src); } @@ -114,12 +113,11 @@ void CStarControlSub12::proc13(CStarControlSub13 *dest) { *dest = _sub13; } -void CStarControlSub12::proc14(int v) { - FMatrix matrix; - _sub13.getMatrix(&matrix); +void CStarControlSub12::proc14(FVector &v) { + FMatrix matrix = _sub13.getMatrix(); FVector vector = _sub13._position; - _handlerP->proc9(&vector, v, &matrix); + _handlerP->proc9(vector, v, matrix); } void CStarControlSub12::proc15(CErrorCode *errorCode) { @@ -128,12 +126,12 @@ void CStarControlSub12::proc15(CErrorCode *errorCode) { if (!_matrix2) _matrix2 = new FMatrix(); - _sub13.getMatrix(_matrix1); + *_matrix1 = _sub13.getMatrix(); *_matrix2 = *_matrix1; FVector v1 = _sub13._position; FVector v2 = _sub13._position; - _handlerP->proc11(*errorCode, v2, _matrix2); + _handlerP->proc11(*errorCode, v2, *_matrix2); if (v1 != v2) { _sub13.setPosition(v2); @@ -141,7 +139,7 @@ void CStarControlSub12::proc15(CErrorCode *errorCode) { } if (_matrix1 != _matrix2) { - _sub13.setMatrix(_matrix2); + _sub13.setMatrix(*_matrix2); } } @@ -161,12 +159,12 @@ void CStarControlSub12::proc19() { _handlerP->proc7(); } -void CStarControlSub12::proc20(double v) { +void CStarControlSub12::proc20(double factor) { if (!isLocked()) - _sub13.fn14(v); + _sub13.reposition(factor); } -void CStarControlSub12::proc21(CStarControlSub6 &sub6) { +void CStarControlSub12::proc21(const CStarControlSub6 *sub6) { if (!isLocked()) { _sub13.setPosition(sub6); set108(); @@ -217,8 +215,103 @@ FVector CStarControlSub12::proc31(int index, const FVector &v) { return _sub13.fn18(index, v); } -void CStarControlSub12::setViewportPosition(const FPoint &pt) { - // TODO +void CStarControlSub12::setViewportPosition(const FPoint &angles) { + if (isLocked()) + return; + + if (_currentIndex == -1) { + CStarControlSub6 subX(X_AXIS, angles._x); + CStarControlSub6 subY(Y_AXIS, angles._y); + CStarControlSub6 sub(&subX, &subY); + subY.copyFrom(&sub); + proc22(subY); + } else if (_currentIndex == 0) { + FVector row1 = _matrix._row1; + CStarControlSub6 subX(X_AXIS, angles._x); + CStarControlSub6 subY(Y_AXIS, angles._y); + CStarControlSub6 sub(&subX, &subY); + subX.copyFrom(&sub); + + FMatrix m1 = _sub13.getMatrix(); + FVector tempV1 = _sub13._position; + FVector tempV2, tempV3, tempV4, tempV5, tempV6; + tempV2._y = m1._row1._y * 100000.0; + tempV2._z = m1._row1._z * 100000.0; + tempV3._x = m1._row1._x * 100000.0 + tempV1._x; + tempV4._x = tempV3._x; + tempV3._y = tempV2._y + tempV1._y; + tempV4._y = tempV3._y; + tempV3._z = tempV2._z + tempV1._z; + tempV4._z = tempV3._z; + tempV2._x = m1._row2._x * 100000.0; + tempV2._y = m1._row2._y * 100000.0; + tempV2._z = m1._row2._z * 100000.0; + tempV2._x = m1._row3._x * 100000.0; + tempV2._y = m1._row3._y * 100000.0; + tempV2._z = m1._row3._z * 100000.0; + tempV2._x = tempV2._x + tempV1._x; + tempV2._y = tempV2._y + tempV1._y; + tempV2._z = tempV2._z + tempV1._z; + tempV3._x = tempV2._x + tempV1._x; + tempV3._y = tempV2._y + tempV1._y; + tempV5._x = tempV2._x; + tempV5._y = tempV2._y; + tempV3._z = tempV2._z + tempV1._z; + tempV5._z = tempV2._z; + tempV6._x = tempV3._x; + tempV6._y = tempV3._y; + tempV6._z = tempV3._z; + tempV1._x = tempV1._x - row1._x; + tempV1._y = tempV1._y - row1._y; + tempV1._z = tempV1._z - row1._z; + tempV4._x = tempV3._x - row1._x; + tempV4._y = tempV4._y - row1._y; + tempV4._z = tempV4._z - row1._z; + tempV5._x = tempV2._x - row1._x; + + tempV5._y = tempV5._y - row1._y; + tempV5._z = tempV5._z - row1._z; + tempV6._x = tempV3._x - row1._x; + tempV6._y = tempV6._y - row1._y; + tempV6._z = tempV6._z - row1._z; + + FVector modV1 = tempV1.fn5(&subX); + FVector modV2 = tempV4.fn5(&subX); + FVector modV3 = tempV5.fn5(&subX); + FVector modV4 = tempV6.fn5(&subX); + tempV1 = modV1; + tempV4 = modV2; + tempV5 = modV3; + tempV4 = modV4; + + tempV2._x = tempV4._x - tempV1._x; + tempV2._y = tempV4._y - tempV1._y; + tempV2._z = tempV4._z - tempV1._z; + tempV4._x = tempV2._x; + tempV4._y = tempV2._y; + tempV2._x = tempV5._x - tempV1._x; + tempV4._z = tempV2._z; + tempV5._x = tempV2._x; + tempV2._y = tempV5._y - tempV1._y; + tempV5._y = tempV2._y; + tempV2._z = tempV5._z - tempV1._z; + tempV5._z = tempV2._z; + tempV2._x = tempV6._x - tempV1._x; + tempV2._y = tempV6._y - tempV1._y; + tempV2._z = tempV6._z - tempV1._z; + tempV6 = tempV2; + + tempV4.normalize(); + tempV5.normalize(); + tempV6.normalize(); + tempV1 += row1; + + m1.set(tempV4, tempV5, tempV6); + _sub13.setMatrix(m1); + _sub13.setPosition(tempV1); + } else if (_currentIndex == 1) { + // TODO + } } bool CStarControlSub12::setArrayVector(const FVector &v) { diff --git a/engines/titanic/star_control/star_control_sub12.h b/engines/titanic/star_control/star_control_sub12.h index 5fac6bf11a..b1a25682d7 100644 --- a/engines/titanic/star_control/star_control_sub12.h +++ b/engines/titanic/star_control/star_control_sub12.h @@ -39,7 +39,7 @@ private: static FMatrix *_matrix2; private: int _currentIndex; - FVector _array[3]; + FMatrix _matrix; CStarControlSub20 *_handlerP; CStarControlSub13 _sub13; int _field108; @@ -62,11 +62,11 @@ public: static void init(); static void deinit(); public: - CStarControlSub12(void *val1, const CStar20Data *data); + CStarControlSub12(const CStar20Data *data); CStarControlSub12(CStarControlSub13 *src); virtual ~CStarControlSub12(); - virtual void proc2(const void *src); + virtual void proc2(const CStarControlSub13 *src); virtual void proc3(const CStar20Data *src); virtual void setPosition(const FVector &v); virtual void proc5(const FVector &v); @@ -78,14 +78,14 @@ public: virtual void proc11(); virtual void proc12(StarMode mode, double v2); virtual void proc13(CStarControlSub13 *dest); - virtual void proc14(int v); + virtual void proc14(FVector &v); virtual void proc15(CErrorCode *errorCode); virtual void proc16(); virtual void proc17(); virtual void proc18(); virtual void proc19(); - virtual void proc20(double v); - virtual void proc21(CStarControlSub6 &sub6); + virtual void proc20(double factor); + virtual void proc21(const CStarControlSub6 *sub6); virtual void proc22(FMatrix &m); virtual CStarControlSub6 proc23(); virtual CStarControlSub6 proc24(); @@ -100,7 +100,7 @@ public: /** * Sets the viewport position within the starfield */ - virtual void setViewportPosition(const FPoint &pt); + virtual void setViewportPosition(const FPoint &angles); virtual int getCurrentIndex() const { return _currentIndex; } virtual bool setArrayVector(const FVector &v); diff --git a/engines/titanic/star_control/star_control_sub13.cpp b/engines/titanic/star_control/star_control_sub13.cpp index d70ad55f4a..6512d12232 100644 --- a/engines/titanic/star_control/star_control_sub13.cpp +++ b/engines/titanic/star_control/star_control_sub13.cpp @@ -21,29 +21,27 @@ */ #include "titanic/star_control/star_control_sub13.h" +#include "titanic/titanic.h" namespace Titanic { -CStarControlSub13::CStarControlSub13(void *src) : - _fieldC0(0), _fieldC4(0), _fieldC8(0.0), _fieldCC(0.0), _fieldD0(0.0) { - if (src) { - setup(src); - } else { - _fieldC = 0; - _field10 = 0x44480000; - _field14 = 0x461C4000; - _field18 = 0x41A00000; - _field1C = 0x41A00000; - _width = 600; - _height = 340; - _field24 = 0; - } - - _fieldD4 = 0; +CStarControlSub13::CStarControlSub13() { + _fieldC = 0; + _field10 = 800.0; + _field14 = 10000.0; + _field18 = 20.0; + _field1C = 20.0; + _width = 600; + _height = 340; + _field24 = 0; + _fieldC0 = _fieldC4 = _fieldC8 = 0.0; + _fieldCC = _fieldD0 = 0.0; + _flag = false; + Common::fill(&_valArray[0], &_valArray[5], 0.0); } CStarControlSub13::CStarControlSub13(CStarControlSub13 *src) : - _matrix(&src->_matrix), _sub1(&src->_sub1), _sub2(&src->_sub2) { + _matrix(src->_matrix), _sub1(&src->_sub1), _sub2(&src->_sub2) { _position = src->_position; _fieldC = src->_fieldC; _field10 = src->_field10; @@ -60,26 +58,17 @@ CStarControlSub13::CStarControlSub13(CStarControlSub13 *src) : _fieldC8 = src->_fieldC8; _field24 = src->_field24; - _valArray[0] = src->_valArray[0]; - _valArray[2] = src->_valArray[2]; - _valArray[3] = src->_valArray[3]; - _fieldD4 = 0; -} - -void CStarControlSub13::setup(void *ptr) { - // TODO + Common::copy(&src->_valArray[0], &src->_valArray[4], &_valArray[0]); + _flag = false; } -void CStarControlSub13::copyFrom(const void *src) { - if (!src) - return; -/* - _field0 = src->_field0; - _field4 = src->_field4; - _field8 = src->_field8; - _fieldC = src->_field18; - _field10 = src->_field1C; - */ +void CStarControlSub13::copyFrom(const CStarControlSub13 *src) { + if (src) { + // TODO: Not really certain src is a CStarControlSub13 + _position = src->_position; + _fieldC = src->_field18; + _field10 = src->_field1C; + } } void CStarControlSub13::load(SimpleFile *file, int param) { @@ -101,7 +90,7 @@ void CStarControlSub13::load(SimpleFile *file, int param) { _valArray[idx] = file->readFloat(); _matrix.load(file, param); - _fieldD4 = 0; + _flag = false; } void CStarControlSub13::save(SimpleFile *file, int indent) { @@ -123,53 +112,62 @@ void CStarControlSub13::save(SimpleFile *file, int indent) { void CStarControlSub13::setPosition(const FVector &v) { _position = v; - _fieldD4 = 0; + _flag = false; } -void CStarControlSub13::setPosition(const CStarControlSub6 &sub6) { - FVector vector; - _position.fn5(&vector, &sub6); - _position = sub6._row1; - _fieldD4 = 0; +void CStarControlSub13::setPosition(const CStarControlSub6 *sub6) { + _position.fn5(sub6); + _position = sub6->_row1; + _flag = false; } void CStarControlSub13::setMatrix(const FMatrix &m) { _matrix = m; - _fieldD4 = 0; + _flag = false; } void CStarControlSub13::fn11(const FVector &v) { - _matrix.fn1(&v); - _fieldD4 = 0; + _matrix.fn1(v); + _flag = false; } -void CStarControlSub13::setC(int v) { +void CStarControlSub13::setC(double v) { _fieldC = v; - _fieldD4 = 0; + _flag = false; } -void CStarControlSub13::set10(int v) { +void CStarControlSub13::set10(double v) { _field10 = v; - _fieldD4 = 0; + _flag = false; } -void CStarControlSub13::set14(int v) { +void CStarControlSub13::set14(double v) { _field10 = v; } -void CStarControlSub13::set18(int v) { +void CStarControlSub13::set18(double v) { _field18 = v; - _fieldD4 = 0; + _flag = false; } -void CStarControlSub13::set1C(int v) { +void CStarControlSub13::set1C(double v) { _field1C = v; - _fieldD4 = 0; + _flag = false; } void CStarControlSub13::fn12() { - _matrix.clear(); - error("TODO: CStarControlSub13::fn12"); + _matrix.identity(); + + CStarControlSub6 m1(X_AXIS, g_vm->getRandomNumber(359)); + CStarControlSub6 m2(Y_AXIS, g_vm->getRandomNumber(359)); + CStarControlSub6 m3(Z_AXIS, g_vm->getRandomNumber(359)); + + CStarControlSub6 s1(&m1, &m2); + CStarControlSub6 s2(&s1, &m3); + + m1.copyFrom(s2); + _matrix.fn2(m1); + _flag = false; } void CStarControlSub13::fn13(StarMode mode, double v2) { @@ -185,52 +183,95 @@ void CStarControlSub13::fn13(StarMode mode, double v2) { _field24 = v2 ? 2 : 0; } -void CStarControlSub13::fn14(double v) { - error("TODO: CStarControlSub13::fn14"); +void CStarControlSub13::reposition(double factor) { + _position._x = _matrix._row3._x * factor + _position._x; + _position._y = _matrix._row3._y * factor + _position._y; + _position._z = _matrix._row3._z * factor + _position._z; + _flag = false; } -void CStarControlSub13::fn15(FMatrix &matrix) { - _matrix.fn3(&matrix); - _fieldD4 = 0; +void CStarControlSub13::fn15(const FMatrix &matrix) { + _matrix.fn3(matrix); + _flag = false; } CStarControlSub6 CStarControlSub13::getSub1() { - if (!_fieldD4) + if (!_flag) reset(); return _sub1; } CStarControlSub6 CStarControlSub13::getSub2() { - if (!_fieldD4) + if (!_flag) reset(); return _sub2; } void CStarControlSub13::fn16(int index, const FVector &src, FVector &dest) { - error("TODO: CStarControlSub13::fn16"); + CStarControlSub6 temp = getSub1(); + + dest._x = temp._row3._x * src._z + temp._row2._x * src._y + + src._x * temp._row1._x + temp._vector._x; + dest._y = temp._row3._y * src._z + temp._row2._y * src._y + + src._x * temp._row1._y + temp._vector._y; + dest._z = temp._row3._z * src._z + temp._row2._z * src._y + + src._x * temp._row1._z + temp._vector._z; } -FVector CStarControlSub13::fn17(int index, const FVector &v) { - error("TODO: CStarControlSub13::fn17"); +FVector CStarControlSub13::fn17(int index, const FVector &src) { + FVector dest; + CStarControlSub6 sub6 = getSub1(); + FVector tv = src.fn5(&sub6); + + dest._x = (_valArray[index] + tv._x) + * _fieldC8 / (_fieldCC * tv._z); + dest._y = (tv._y * _fieldC8) / (_fieldD0 * tv._z); + dest._z = tv._z; + return dest; } -FVector CStarControlSub13::fn18(int index, const FVector &v) { - error("TODO: CStarControlSub13::fn17"); +FVector CStarControlSub13::fn18(int index, const FVector &src) { + FVector dest; + CStarControlSub6 sub6 = getSub2(); + FVector tv = src.fn5(&sub6); + + dest._x = (_valArray[index] + tv._x) + * _fieldC8 / (_fieldCC * tv._z); + dest._y = (tv._y * _fieldC8) / (_fieldD0 * tv._z); + dest._z = tv._z; + return dest; } void CStarControlSub13::fn19(double *v1, double *v2, double *v3, double *v4) { - error("TODO: CStarControlSub13::fn19"); + *v1 = _fieldC8 / _fieldCC; + *v2 = _fieldC8 / _fieldD0; + *v3 = _valArray[3]; + *v4 = _valArray[4]; } void CStarControlSub13::reset() { - //const double FACTOR = 3.1415927 * 0.0055555557; - error("TODO: CStarControlSub13::reset"); + const double FACTOR = 2 * M_PI / 360.0; + + _sub2.copyFrom(_matrix); + _sub2._vector._x = _position._x; + _sub2._vector._y = _position._y; + _sub2._vector._z = _position._z; + _sub2.fn4(&_sub1); + + double widthV = (double)_width * 0.5; + double heightV = (double)_height * 0.5; + _fieldC0 = widthV; + _fieldC4 = heightV; + _fieldC8 = MIN(widthV, heightV); + _fieldCC = tan(_field18 * FACTOR); + _fieldD0 = tan(_field1C * FACTOR); + _flag = true; } -void CStarControlSub13::getMatrix(FMatrix *matrix) { - *matrix = _matrix; +const FMatrix &CStarControlSub13::getMatrix() const { + return _matrix; } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub13.h b/engines/titanic/star_control/star_control_sub13.h index 047df987d2..80b2e55c4b 100644 --- a/engines/titanic/star_control/star_control_sub13.h +++ b/engines/titanic/star_control/star_control_sub13.h @@ -42,10 +42,8 @@ private: CStarControlSub6 _sub2; double _fieldC0; double _fieldC4; - int _fieldD4; + bool _flag; private: - void setup(void *ptr); - void reset(); public: FVector _position; @@ -57,10 +55,13 @@ public: double _fieldCC; double _fieldD0; public: - CStarControlSub13(void *ptr); + CStarControlSub13(); CStarControlSub13(CStarControlSub13 *src); - void copyFrom(const void *src); + /** + * Copys the data from another instance + */ + void copyFrom(const CStarControlSub13 *src); /** * Load the data for the class from file @@ -80,7 +81,7 @@ public: /** * Sets the position */ - void setPosition(const CStarControlSub6 &sub6); + void setPosition(const CStarControlSub6 *sub6); /** * Sets the matrix @@ -90,25 +91,25 @@ public: void fn11(const FVector &v); void fn12(); void fn13(StarMode mode, double v2); - void fn14(double v); - void fn15(FMatrix &matrix); + void reposition(double factor); + void fn15(const FMatrix &matrix); CStarControlSub6 getSub1(); CStarControlSub6 getSub2(); void fn16(int index, const FVector &src, FVector &dest); - FVector fn17(int index, const FVector &v); - FVector fn18(int index, const FVector &v); + FVector fn17(int index, const FVector &src); + FVector fn18(int index, const FVector &src); void fn19(double *v1, double *v2, double *v3, double *v4); /** - * Makes a copy of the instance's matrix into the passed matrix + * Returns the instance's matrix */ - void getMatrix(FMatrix *matrix); + const FMatrix &getMatrix() const; - void setC(int v); - void set10(int v); - void set14(int v); - void set18(int v); - void set1C(int v); + void setC(double v); + void set10(double v); + void set14(double v); + void set18(double v); + void set1C(double v); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub2.cpp b/engines/titanic/star_control/star_control_sub2.cpp index cf7190fb34..ebeb9bf239 100644 --- a/engines/titanic/star_control/star_control_sub2.cpp +++ b/engines/titanic/star_control/star_control_sub2.cpp @@ -21,9 +21,15 @@ */ #include "titanic/star_control/star_control_sub2.h" +#include "titanic/star_control/star_control_sub12.h" namespace Titanic { +bool CStarControlSub2::setup() { + loadData("STARFIELD/132"); + return true; +} + bool CStarControlSub2::loadYale(int v1) { clear(); error("Original loadYale not supported"); @@ -31,19 +37,20 @@ bool CStarControlSub2::loadYale(int v1) { } bool CStarControlSub2::selectStar(CSurfaceArea *surfaceArea, - CStarControlSub12 *sub12, int flags, const Common::Point &pt) { - // TODO - return true; + CStarControlSub12 *sub12, const Common::Point &pt, void *handler) { + int index = baseFn1(surfaceArea, sub12, pt); + if (index == -1) { + return false; + } else if (!handler) { + sub12->proc14(_data[index]._position); + return true; + } else { + error("no handler ever passed in original"); + } } bool CStarControlSub2::loadStar() { - // TODO - return true; -} - -bool CStarControlSub2::setup() { - // TODO - return true; + error("loadStar not supported"); } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub2.h b/engines/titanic/star_control/star_control_sub2.h index 9de2da4583..bcf7397fe1 100644 --- a/engines/titanic/star_control/star_control_sub2.h +++ b/engines/titanic/star_control/star_control_sub2.h @@ -37,7 +37,7 @@ public: * Selects a star */ virtual bool selectStar(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, - int flags, const Common::Point &pt); + const Common::Point &pt, void *handler = nullptr); virtual bool loadStar(); diff --git a/engines/titanic/star_control/star_control_sub20.cpp b/engines/titanic/star_control/star_control_sub20.cpp index cc1029896a..ca60cc9948 100644 --- a/engines/titanic/star_control/star_control_sub20.cpp +++ b/engines/titanic/star_control/star_control_sub20.cpp @@ -32,7 +32,7 @@ CStarControlSub20::CStarControlSub20(const CStar20Data *src) { if (src) { copyFrom(src); } else { - _field0 = 0.0; + _size = 0.0; _field4 = 0.0; _field8 = 20.0; _fieldC = 0.0; @@ -56,22 +56,22 @@ void CStarControlSub20::copyTo(CStar20Data *dest) { } void CStarControlSub20::proc4() { - if (!isLocked() && _field0 < _field10) { - _field4 += _field0; + if (!isLocked() && _size < _field10) { + _field4 += _size; if (_field8 == _field4) - _field0 -= _field4; + _size -= _field4; else - _field0 += _field4; + _size += _field4; } } void CStarControlSub20::proc5() { if (!isLocked()) { _field4 -= _field8; - if (_field4 == _field0) - _field0 += _field4; + if (_field4 == _size) + _size += _field4; else - _field0 -= _field4; + _size -= _field4; if (_field4 < 0.0) _field4 = 0.0; @@ -80,19 +80,23 @@ void CStarControlSub20::proc5() { void CStarControlSub20::proc6() { if (!isLocked()) - _field0 = _field10; + _size = _field10; } void CStarControlSub20::proc7() { if (!isLocked()) { - _field0 = 0.0; + _size = 0.0; _field4 = 0.0; } } void CStarControlSub20::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { - if (_field0 > 0.0) { - warning("TODO: CStarControlSub20::proc11"); + if (_size > 0.0) { + v._x += m._row3._x * _size; + v._y += m._row3._y * _size; + v._z += m._row3._z * _size; + + errorCode.set(); } } @@ -110,7 +114,7 @@ void CStarControlSub20::clear() { void CStarControlSub20::load(SimpleFile *file, int val) { if (!val) { - _field0 = file->readFloat(); + _size = file->readFloat(); _field4 = file->readFloat(); _field8 = file->readFloat(); _fieldC = file->readFloat(); @@ -122,7 +126,7 @@ void CStarControlSub20::load(SimpleFile *file, int val) { } void CStarControlSub20::save(SimpleFile *file, int indent) { - file->writeFloatLine(_field0, indent); + file->writeFloatLine(_size, indent); file->writeFloatLine(_field4, indent); file->writeFloatLine(_field8, indent); file->writeFloatLine(_fieldC, indent); diff --git a/engines/titanic/star_control/star_control_sub20.h b/engines/titanic/star_control/star_control_sub20.h index 9dbabbb7f1..49b63d5d5d 100644 --- a/engines/titanic/star_control/star_control_sub20.h +++ b/engines/titanic/star_control/star_control_sub20.h @@ -30,7 +30,7 @@ namespace Titanic { struct CStar20Data { - double _field0; + double _size; double _field4; double _field8; double _fieldC; @@ -54,9 +54,9 @@ public: virtual void proc5(); virtual void proc6(); virtual void proc7(); - virtual void proc8() {} - virtual void proc9(FVector *v, int v2, FMatrix *matrix) {} - virtual void proc10() {} + virtual void proc8(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2) {} + virtual void proc9(FVector &v1, FVector &v2, FMatrix &matrix) {} + virtual void proc10(const FVector &v1, const FVector &v2, const FVector &v3, const FMatrix &m) {} virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); /** diff --git a/engines/titanic/star_control/star_control_sub21.cpp b/engines/titanic/star_control/star_control_sub21.cpp index 41d24d55c0..1e676b7703 100644 --- a/engines/titanic/star_control/star_control_sub21.cpp +++ b/engines/titanic/star_control/star_control_sub21.cpp @@ -21,15 +21,51 @@ */ #include "titanic/star_control/star_control_sub21.h" +#include "titanic/star_control/dmatrix.h" +#include "titanic/star_control/dvector.h" #include "common/textconsole.h" namespace Titanic { CStarControlSub21::CStarControlSub21(const CStar20Data *src) : CStarControlSub20(src) { -#if 0 - _sub24() -#endif +} + +void CStarControlSub21::proc9(FVector &v1, FVector &v2, FMatrix &matrix) { + if (isLocked()) + decLockCount(); + + _sub24.proc4(v1, v2, matrix); +} + +void CStarControlSub21::proc10(const FVector &v1, const FVector &v2, const FVector &v3, const FMatrix &m) { + if (isLocked()) + decLockCount(); + + DVector vector1 = v1; + DVector vector2 = v2; + DMatrix matrix1, matrix2 = m, matrix3; + vector2.fn4(vector1, matrix1); + const DMatrix *matrixP = matrix1.fn4(matrix3, matrix1, matrix2); + + FMatrix matrix4 = *matrixP; + _sub24.proc3(m, matrix4); + incLockCount(); +} + +void CStarControlSub21::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { + if (_sub24.get8()) { + int val = _sub24.proc5(errorCode, v, m); + if (val == 1) + incLockCount(); + if (val == 2) { + proc7(); + error("TODO: _dataP"); + } + } else if (_size != 0.0) { + // TODO + error("TODO"); + } } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub21.h b/engines/titanic/star_control/star_control_sub21.h index 3f47a1a3e1..66ce535993 100644 --- a/engines/titanic/star_control/star_control_sub21.h +++ b/engines/titanic/star_control/star_control_sub21.h @@ -30,11 +30,14 @@ namespace Titanic { class CStarControlSub21 : public CStarControlSub20 { private: -#if 0 CStarControlSub24 _sub24; -#endif public: CStarControlSub21(const CStar20Data *src); + virtual ~CStarControlSub21() {} + + virtual void proc9(FVector &v1, FVector &v2, FMatrix &matrix); + virtual void proc10(const FVector &v1, const FVector &v2, const FVector &v3, const FMatrix &m); + virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub22.cpp b/engines/titanic/star_control/star_control_sub22.cpp index 05a1cec87d..b76d96e47a 100644 --- a/engines/titanic/star_control/star_control_sub22.cpp +++ b/engines/titanic/star_control/star_control_sub22.cpp @@ -27,9 +27,18 @@ namespace Titanic { CStarControlSub22::CStarControlSub22(const CStar20Data *src) : CStarControlSub20(src) { -#if 0 - _sub27() -#endif +} + +void CStarControlSub22::proc8(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2) { + if (isLocked()) + decLockCount(); + + _sub27.proc2(v1, v2, m1, m2); + incLockCount(); +} + +void CStarControlSub22::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { + // TODO } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub22.h b/engines/titanic/star_control/star_control_sub22.h index 4d353aa074..61f60b10f1 100644 --- a/engines/titanic/star_control/star_control_sub22.h +++ b/engines/titanic/star_control/star_control_sub22.h @@ -30,11 +30,13 @@ namespace Titanic { class CStarControlSub22 : public CStarControlSub20 { private: -#if 0 CStarControlSub27 _sub27; -#endif public: CStarControlSub22(const CStar20Data *src); + virtual ~CStarControlSub22() {} + + virtual void proc8(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2); + virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub23.cpp b/engines/titanic/star_control/star_control_sub23.cpp index b009cbc35b..4587fd3e27 100644 --- a/engines/titanic/star_control/star_control_sub23.cpp +++ b/engines/titanic/star_control/star_control_sub23.cpp @@ -25,4 +25,89 @@ namespace Titanic { +CStarControlSub23::CStarControlSub23() : _row1(0.0, 1000000.0, 0.0) { + _field4 = 0; + _field8 = 0; + _field24 = 0.0; + _field34 = 0; + _field38 = 0; + _field3C = 0; + _field40 = 0; + _field44 = 0; + _field48 = 0; + _field4C = 0; + _field54 = 0; + _field58 = 0; + _field5C = 0; + _field60 = 0; + _field64 = 0; +} + +void CStarControlSub23::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2) { + _row1 = v1; + _row2 = v2; + _row3 = _row2 - _row1; + _field24 = _row3.normalize(); + + _field58 = 0; + _field8 = 0; + _field34 = 0; + _field5C = 1.875; + _field40 = -1; + _field44 = -1; + _field48 = -1; + _field4C = 0; +} + +void CStarControlSub23::proc3(const FMatrix &m1, const FMatrix &m2) { + _row1.clear(); + _row2.clear(); + _field58 = 0; + _field24 = 0.0; + _field8 = 0; + _field34 = 0; + _field5C = 1.875; +} + +void CStarControlSub23::proc4(FVector &v1, FVector &v2, FMatrix &m) { + _row1 = v1; + _row2 = v2; + FVector vector = _row2 - _row1; + _row3 = vector; + _field24 = _row3.normalize(); + + _field8 = 0; + _field34 = 0; + _field40 = -1; + _field44 = -1; + _field48 = -1; + _field4C = -1; + _field58 = 0; + _field5C = 1.875; +} + +void CStarControlSub23::proc6(int val1, int val2, float val) { + _field44 = val1; + _field4C = val1 + 62; + _field38 = val / (double)(val1 + val2 * 2); + _field40 = 31; + _field48 = 31; + _field3C = (double)val2 * _field38; + + if (_powers.empty()) + _powers.resize(32); + + // Calculate the powers table + double exponent = 0.0, total = 0.0; + for (int idx = 31; idx >= 0; --idx) { + _powers[idx] = pow(4.0, exponent); + total += _powers[idx]; + exponent += 0.03125; + } + + for (int idx = 0; idx < 32; ++idx) { + _powers[idx] = _powers[idx] * _field3C / total; + } +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub23.h b/engines/titanic/star_control/star_control_sub23.h index 136401e329..9e90e021a2 100644 --- a/engines/titanic/star_control/star_control_sub23.h +++ b/engines/titanic/star_control/star_control_sub23.h @@ -23,9 +23,45 @@ #ifndef TITANIC_STAR_CONTROL_SUB23_H #define TITANIC_STAR_CONTROL_SUB23_H +#include "titanic/star_control/error_code.h" +#include "titanic/star_control/fmatrix.h" +#include "titanic/star_control/fvector.h" +#include "titanic/star_control/star_control_sub25.h" + namespace Titanic { class CStarControlSub23 { +protected: + int _field4; + int _field8; + FVector _row1, _row2; + double _field24; + FVector _row3; + int _field34; + double _field38; + int _field3C; + int _field40; + int _field44; + int _field48; + int _field4C; + Common::Array<double> _powers; + int _field54; + int _field58; + double _field5C; + double _field60; + double _field64; + CStarControlSub25 _sub25; +public: + CStarControlSub23(); + virtual ~CStarControlSub23() {} + + virtual void proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2); + virtual void proc3(const FMatrix &m1, const FMatrix &m2); + virtual void proc4(FVector &v1, FVector &v2, FMatrix &m); + virtual int proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m) { return 2; } + virtual void proc6(int val1, int val2, float val); + + int get8() const { return _field8; } }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub24.cpp b/engines/titanic/star_control/star_control_sub24.cpp index 6f17eb7193..27f29b41ca 100644 --- a/engines/titanic/star_control/star_control_sub24.cpp +++ b/engines/titanic/star_control/star_control_sub24.cpp @@ -25,5 +25,19 @@ namespace Titanic { +void CStarControlSub24::proc3(const FMatrix &m1, const FMatrix &m2) { + +} + +void CStarControlSub24::proc4(FVector &v1, FVector &v2, FMatrix &m) { + CStarControlSub23::proc4(v1, v2, m); + + // TODO +} + +int CStarControlSub24::proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m) { + // TODO + return 0; +} } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub24.h b/engines/titanic/star_control/star_control_sub24.h index e0970fc1de..34b9cf4eac 100644 --- a/engines/titanic/star_control/star_control_sub24.h +++ b/engines/titanic/star_control/star_control_sub24.h @@ -28,6 +28,12 @@ namespace Titanic { class CStarControlSub24 : public CStarControlSub23 { +public: + virtual ~CStarControlSub24() {} + + virtual void proc3(const FMatrix &m1, const FMatrix &m2); + virtual void proc4(FVector &v1, FVector &v2, FMatrix &m); + virtual int proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub25.cpp b/engines/titanic/star_control/star_control_sub25.cpp index f91c75af6a..73c72e6a77 100644 --- a/engines/titanic/star_control/star_control_sub25.cpp +++ b/engines/titanic/star_control/star_control_sub25.cpp @@ -25,4 +25,10 @@ namespace Titanic { +void CStarControlSub25::fn1(const FMatrix &m1, const FMatrix &m2) { + _matrix1 = m1; + _matrix2 = m2; + +} + } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub25.h b/engines/titanic/star_control/star_control_sub25.h index b61569c49d..85692cf62d 100644 --- a/engines/titanic/star_control/star_control_sub25.h +++ b/engines/titanic/star_control/star_control_sub25.h @@ -35,7 +35,7 @@ public: CStarControlSub26 _sub1; CStarControlSub26 _sub2; public: - + void fn1(const FMatrix &m1, const FMatrix &m2); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub26.cpp b/engines/titanic/star_control/star_control_sub26.cpp index 89ff93c347..546a3e9fae 100644 --- a/engines/titanic/star_control/star_control_sub26.cpp +++ b/engines/titanic/star_control/star_control_sub26.cpp @@ -30,5 +30,16 @@ double CStarControlSub26::fn1() const { _sub._v3 * _sub._v3 + _field0 * _field0; } +void CStarControlSub26::setup(double val1, double val2, double val3, double val4) { + _field0 = val1; + _sub._v1 = val2; + _sub._v2 = val3; + _sub._v3 = val4; +} + +void CStarControlSub26::copyFrom(const CStarControlSub26 *src) { + _field0 = src->_field0; + _sub = src->_sub; +} } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub26.h b/engines/titanic/star_control/star_control_sub26.h index 4054a2ba6e..9023da906c 100644 --- a/engines/titanic/star_control/star_control_sub26.h +++ b/engines/titanic/star_control/star_control_sub26.h @@ -39,7 +39,18 @@ public: public: CStarControlSub26() : _field0(1.0) {} + /** + * Sets the field values + */ + void setup(double val1, double val2, double val3, double val4); + + /** + * Copies from another instance + */ + void copyFrom(const CStarControlSub26 *src); + double fn1() const; + }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub27.cpp b/engines/titanic/star_control/star_control_sub27.cpp index 6f17eb7193..706e947a05 100644 --- a/engines/titanic/star_control/star_control_sub27.cpp +++ b/engines/titanic/star_control/star_control_sub27.cpp @@ -20,10 +20,40 @@ * */ -#include "titanic/star_control/star_control_sub24.h" +#include "titanic/star_control/star_control_sub27.h" #include "common/textconsole.h" namespace Titanic { +void CStarControlSub27::proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2) { + CStarControlSub23::proc2(v1, v2, m1, m2); + + int v24 = _field24; + if (_field24 > 0.0) { + _field8 = 1; + _field34 = 1; + proc6(120, 4, _field24); + } + + if (m1 != m2) { + _sub25.fn1(m1, m2); + _field58 = 0; + _field5C = 0.0; + + if (_field4C == 0) { + _field60 = -1.5881868e-23; + _field64 = 1.4499999; + _field8 = 1; + } else { + _field60 = 1.0 / (double)v24; + _field8 = 1; + } + } +} + +int CStarControlSub27::proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m) { + // TODO + return 0; +} } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub27.h b/engines/titanic/star_control/star_control_sub27.h index 01782b69ca..801591294e 100644 --- a/engines/titanic/star_control/star_control_sub27.h +++ b/engines/titanic/star_control/star_control_sub27.h @@ -28,6 +28,11 @@ namespace Titanic { class CStarControlSub27 : public CStarControlSub23 { +public: + virtual ~CStarControlSub27() {} + + virtual void proc2(FVector &v1, FVector &v2, FMatrix &m1, FMatrix &m2); + virtual int proc5(CErrorCode &errorCode, FVector &v, const FMatrix &m); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub5.cpp b/engines/titanic/star_control/star_control_sub5.cpp index 5023a59383..8c332975c6 100644 --- a/engines/titanic/star_control/star_control_sub5.cpp +++ b/engines/titanic/star_control/star_control_sub5.cpp @@ -26,6 +26,8 @@ namespace Titanic { +#define MKTAG_BE(a3,a2,a1,a0) ((uint32)((a3) | ((a2) << 8) | ((a1) << 16) | ((a0) << 24))) + void CStarControlSub5::SubEntry::clear() { _data1.clear(); _data2.clear(); @@ -37,7 +39,7 @@ bool CStarControlSub5::SineTable::setup() { if (_data.empty()) { _data.resize(1024); for (int idx = 0; idx < 1024; ++idx) - _data[idx] = sin((double)idx * 6.283185307179586 * 0.001953125); + _data[idx] = sin((double)idx * 2 * M_PI / 512.0); } return true; @@ -63,7 +65,7 @@ bool CStarControlSub5::setup() { bool CStarControlSub5::setup2(int val1, int val2) { // TODO: Original set an explicit random seed here. Could be // problematic if following random values need to be deterministic - const double FACTOR = 3.1415927 * 0.0055555557; + const double FACTOR = 2 * M_PI / 360.0; const int VALUES1[] = { 0x800, 0xC00, 0x1000, 0x1400, 0x1800 }; const int VALUES2[] = { 0xF95BCD, 0xA505A0, 0xFFAD43, 0x98F4EB, 0xF3EFA5, 0, @@ -76,9 +78,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { for (int idx = 0; idx < 256; ++idx) { if (idx == 0) { e->_field0 = 0x4C8; - e->_field4 = 0x40; - e->_field5 = 0x40; - e->_field6 = 0x40; + e->_pixel1 = 0x40; + e->_pixel2 = 0x40; + e->_pixel3 = 0x40; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 7.0; @@ -86,9 +88,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x574; - e->_field4 = 0x7f; - e->_field5 = 0; - e->_field6 = 0; + e->_pixel1 = 0x7f; + e->_pixel2 = 0; + e->_pixel3 = 0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 3.0; @@ -96,9 +98,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x603; - e->_field4 = 0; - e->_field5 = 0; - e->_field6 = 0xff; + e->_pixel1 = 0; + e->_pixel2 = 0; + e->_pixel3 = 0xff; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = 0; @@ -106,9 +108,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x712; - e->_field4 = 0xff; - e->_field5 = 0; - e->_field6 = 0; + e->_pixel1 = 0xff; + e->_pixel2 = 0; + e->_pixel3 = 0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 2.0; @@ -116,9 +118,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0xe7f; - e->_field4 = 0xe6; - e->_field5 = 0xbe; - e->_field6 = 0; + e->_pixel1 = 0xe6; + e->_pixel2 = 0xbe; + e->_pixel3 = 0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 1.0; @@ -126,9 +128,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x173f; - e->_field4 = 0xf0; - e->_field5 = 0xf0; - e->_field6 = 0xe6; + e->_pixel1 = 0xf0; + e->_pixel2 = 0xf0; + e->_pixel3 = 0xe6; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 3.0; @@ -136,9 +138,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x2ab8; - e->_field4 = 0x28; - e->_field5 = 0x32; - e->_field6 = 0x28; + e->_pixel1 = 0x28; + e->_pixel2 = 0x32; + e->_pixel3 = 0x28; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 1.0; @@ -146,9 +148,9 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x40ac; - e->_field4 = 0x0; - e->_field5 = 0xbe; - e->_field6 = 0xf0; + e->_pixel1 = 0x0; + e->_pixel2 = 0xbe; + e->_pixel3 = 0xf0; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 2.0; @@ -156,27 +158,27 @@ bool CStarControlSub5::setup2(int val1, int val2) { ++e; e->_field0 = 0x539c; - e->_field4 = 0x20; - e->_field5 = 0x20; - e->_field6 = 0x20; + e->_pixel1 = 0x20; + e->_pixel2 = 0x20; + e->_pixel3 = 0x20; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * 17.0; - e->_field14 = 0.00390625; + e->_field14 = 1 / 256.0; } else { for (int ctr = 0; ctr < 5; ++ctr) { e->_field0 = static_cast<int>(g_vm->getRandomFloat() * 1350.0 - 675.0) + VALUES1[idx]; int val = VALUES2[g_vm->getRandomNumber(15)]; - e->_field4 = val & 0xff; - e->_field5 = (val >> 8) & 0xff; - e->_field6 = (val >> 16) & 0xff; + e->_pixel1 = val & 0xff; + e->_pixel2 = (val >> 8) & 0xff; + e->_pixel3 = (val >> 16) & 0xff; e->_field8 = g_vm->getRandomNumber(3) + 3; e->_fieldC = g_vm->getRandomNumber(255); e->_field10 = FACTOR * (double)g_vm->getRandomNumber(15); - e->_field14 = ((double)g_vm->getRandomNumber(0xffffffff) - * 50.0 * 0.000015259022) * 0.00390625; + e->_field14 = ((double)g_vm->getRandomNumber(0xfffffffe) + * 50.0 / 65536.0) / 256.0; } } } @@ -194,13 +196,23 @@ void CStarControlSub5::proc2(CStarControlSub6 *sub6, FVector *vector, double v1, const int VALUES[] = { 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4 }; double val1 = sub12->proc25(); int val2 = sub12->proc27(); + if (!_flag) + return; + + int f1, f3, size2, size1; + double f2, f4, f5, f6, f7, f8, f9; + double f10, f11, f12, f13, f14, f15, f16, f17, f18, f19; + double f20, f21, f22, f23, f24, f25, f26, f27, f28; + double f34, f35, f36, f37, f38, f39, f40; + double f41, f42, f43, f44, f45, f46; + FVector tempV; if (v3 >= 6.0e9) { int count, start; if (vector->_x != 0.0 && (vector->_y != 0.0 || vector->_z != 0.0)) { - // TODO: Non-sensical randSeed((int)vector->_x); + // WORKAROUND: Ignoring non-sensical randSeed((int)vector->_x); count = VALUES[g_vm->getRandomNumber(15)]; - start = g_vm->getRandomNumber(255); + start = 5 * g_vm->getRandomNumber(255); } else { count = 9; start = 0; @@ -208,45 +220,280 @@ void CStarControlSub5::proc2(CStarControlSub6 *sub6, FVector *vector, double v1, Entry *entryP = &_entries[start]; for (; count > 0; --count, ++entryP) { - //eax=sineIndex1, ecx=sineIndex2, - int sineIndex1 = (entryP->_field8 * _multiplier) & 0x1ff; - int sineIndex2 = (entryP->_fieldC * _multiplier + entryP->_fieldC) & 0x1ff; - - double t1 = _sineTable[sineIndex2]; - double t2 = sin(_sineTable[sineIndex1] * entryP->_field10); - double t3 = cos(_sineTable[sineIndex1] * entryP->_field10); - double t4 = _sineTable[sineIndex2 + 512]; - double t5 = t3 * t4; - t3 = t3 * t1; - double t6 = entryP->_field14 * t5; - double t7 = t2 * entryP->_field14; - double t8 = entryP->_field14 * t3; - double t9 = -(t2 * t4 * entryP->_field14); - double t10 = t3 * entryP->_field14; - double t11 = -(t2 * t1 * entryP->_field14); - t4 = -(t1 * entryP->_field14); - t1 = t4 * entryP->_field14; - - _sub1._row1._x = t6; - _sub1._row1._y = t2 * entryP->_field14; - _sub1._row1._z = entryP->_field14 * t3; - _sub1._row2._x = -(t2 * t4 * entryP->_field14); - _sub1._row2._y = t3 * entryP->_field14; - _sub1._row2._z = -(t2 * t1 * entryP->_field14); - _sub1._row3._x = -(t1 * entryP->_field14); - _sub1._row3._z = t4 * entryP->_field14; - - double t12 = entryP->_field0; - _sub1._vector._x = t12 * t5 + vector->_x; - _sub1._vector._y = t12 * t2 + vector->_y; - _sub1._vector._z = t12 * t3 + vector->_z; - - // TODO - warning("TODO: %f %f %f %f %f %f %d", t7, t8, t9, t10, t11, val1, val2); + f1 = _multiplier * entryP->_field8; + f2 = entryP->_field14; + f3 = (f1 + entryP->_fieldC) & 0x1FF; + f4 = _sineTable[f1 & 0x1FF] * entryP->_field10; + f5 = _sineTable[f3]; + f6 = cos(f4); + f7 = sin(f4); + f8 = _sineTable[f3 + 128]; + f9 = f7; + f10 = f6 * f8; + f11 = f6; + f12 = f6 * f5; + f13 = f2 * f10; + f14 = f8 * f2; + f15 = f9 * f2; + f16 = f2 * f12; + f17 = -(f7 * f8 * f2); + f18 = f11 * f2; + f19 = -(f9 * f5 * f2); + f20 = -(f5 * f2); + f21 = f14; + _sub1._row1._x = f13; + _sub1._row1._y = f15; + _sub1._row1._z = f16; + _sub1._row2._x = f17; + _sub1._row2._y = f18; + _sub1._row2._z = f19; + _sub1._row3._x = f20; + _sub1._row3._z = f14; + + f22 = (double)entryP->_field0; + _sub1._vector._x = f22 * f10 + vector->_x; + _sub1._vector._y = f9 * f22 + vector->_y; + _sub1._vector._z = f22 * f12 + vector->_z; + _sub2._row1._x = sub6->_row1._x * f13 + f16 * sub6->_row3._x + f15 * sub6->_row2._x; + _sub2._row1._y = f15 * sub6->_row2._y + f16 * sub6->_row3._y + f13 * sub6->_row1._y; + _sub2._row1._z = f16 * sub6->_row3._z + f13 * sub6->_row1._z + f15 * sub6->_row2._z; + _sub2._row2._x = sub6->_row1._x * f17 + f19 * sub6->_row3._x + f18 * sub6->_row2._x; + _sub2._row2._y = f18 * sub6->_row2._y + f17 * sub6->_row1._y + f19 * sub6->_row3._y; + _sub2._row2._z = f18 * sub6->_row2._z + f19 * sub6->_row3._z + f17 * sub6->_row1._z; + _sub2._row3._x = sub6->_row1._x * f20 + f21 * sub6->_row3._x; + _sub2._row3._y = f20 * sub6->_row1._y + f21 * sub6->_row3._y; + _sub2._row3._z = f20 * sub6->_row1._z + f21 * sub6->_row3._z; + + f23 = _sub1._vector._y; + f24 = _sub1._vector._z; + f25 = _sub1._vector._x; + f26 = _sub1._vector._z; + f27 = _sub1._vector._x; + + f28 = _sub1._vector._y; + _sub2._vector._x = sub6->_row1._x * _sub1._vector._x + + sub6->_row3._x * _sub1._vector._z + + sub6->_row2._x * f28 + + sub6->_vector._x; + _sub2._vector._y = f23 * sub6->_row2._y + + f24 * sub6->_row3._y + + f25 * sub6->_row1._y + + sub6->_vector._y; + _sub2._vector._z = f26 * sub6->_row3._z + + f27 * sub6->_row1._z + + f28 * sub6->_row2._z + + sub6->_vector._z; + + size2 = (int)_array[1]._data2.size(); + size1 = (int)_array[1]._data1.size(); + + if (size2 > 0) { + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + FVector &currVector = _array[1]._data2[ctr2]; + GridEntry &gridEntry = _grid[ctr2]; + + f34 = currVector._x; + f35 = currVector._y; + f36 = f35 * _sub2._row2._x; + f37 = currVector._z; + f38 = f37 * _sub2._row3._x + f36; + f39 = f38 + f34 * _sub2._row1._x; + f40 = f39 + _sub2._vector._x; + + gridEntry._x = f40; + gridEntry._y = f37 * _sub2._row3._y + + f35 * _sub2._row2._y + + f34 * _sub2._row1._y + + _sub2._vector._y; + gridEntry._z = f37 * _sub2._row3._z + + f35 * _sub2._row2._z + + f34 * _sub2._row1._z + + _sub2._vector._z; + } + } + + if (val2 <= 0) { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = MKTAG_BE(entryP->_pixel1, entryP->_pixel2, + entryP->_pixel3, 0); + surfaceArea->setColorFromPixel(); + + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + GridEntry &gridEntry = _grid[ctr2]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x; + gridEntry._position._y = tempV._y + v2; + } + + for (int ctr2 = 0; ctr2 < size1; ++ctr2) { + Data1 &d1 = _array[1]._data1[ctr2]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid1._z > val1 && grid2._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } else { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = entryP->_pixel1; + surfaceArea->setColorFromPixel(); + + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + GridEntry &gridEntry = _grid[ctr2]; + sub12->proc28(0, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (int ctr2 = 0; ctr2 < size1; ++ctr2) { + Data1 &d1 = _array[1]._data1[ctr2]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid1._z > val1 && grid2._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + + surfaceArea->_pixel = entryP->_pixel3; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(SA_MODE2); + + for (int ctr2 = 0; ctr2 < size2; ++ctr2) { + GridEntry &gridEntry = _grid[ctr2]; + sub12->proc28(1, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (int ctr2 = 0; ctr2 < size1; ++ctr2) { + Data1 &d1 = _array[1]._data1[ctr2]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid1._z > val1 && grid2._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } + } + } + + uint pixel1 = 0x81EEF5, pixel2 = 0xF5, pixel3 = 0x810000; + int arrIndex = 0; + + if (v3 >= 200000000.0) { + if (v3 >= 900000000.0) { + if (v3 >= 6000000000.0) { + arrIndex = 3; + if (v3 >= 1.0e10) + arrIndex = 4; + } else { + arrIndex = 2; + } + } else { + arrIndex = 1; } + } else { + arrIndex = 0; } - // TODO + SubEntry &entry = _array[arrIndex]; + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + const FVector &d2v = entry._data2[ctr]; + FVector newV = d2v + *vector; + + f41 = sub6->_row1._x; + f42 = sub6->_row3._x; + f43 = sub6->_row2._x; + f44 = f43 * newV._y; + f45 = f41 * newV._x + f42 * newV._z + f44; + f46 = f45 + sub6->_vector._x; + + gridEntry._x = f46; + gridEntry._y = newV._y * sub6->_row2._y + + newV._z * sub6->_row3._y + + newV._x * sub6->_row1._y + + sub6->_vector._y; + gridEntry._z = newV._z * sub6->_row3._z + + newV._y * sub6->_row2._z + + newV._x * sub6->_row1._z + + sub6->_vector._z; + } + + if (val2 <= 0) { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = pixel1; + surfaceArea->setColorFromPixel(); + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (uint ctr = 0; ctr < entry._data1.size(); ++ctr) { + Data1 &d1 = entry._data1[ctr]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid2._z > val1 && grid1._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } else { + surfaceArea->setMode(SA_NONE); + surfaceArea->_pixel = pixel2; + surfaceArea->setColorFromPixel(); + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (uint ctr = 0; ctr < entry._data1.size(); ++ctr) { + Data1 &d1 = entry._data1[ctr]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid2._z > val1 && grid1._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + + surfaceArea->_pixel = pixel3; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(SA_MODE2); + + for (uint ctr = 0; ctr < entry._data2.size(); ++ctr) { + GridEntry &gridEntry = _grid[ctr]; + sub12->proc28(2, gridEntry, tempV); + gridEntry._position._x = tempV._x + v1; + gridEntry._position._y = tempV._y + v2; + } + + for (uint ctr = 0; ctr < entry._data1.size(); ++ctr) { + Data1 &d1 = entry._data1[ctr]; + GridEntry &grid1 = _grid[d1._index1]; + GridEntry &grid2 = _grid[d1._index2]; + + if (grid2._z > val1 && grid1._z > val1) { + surfaceArea->fn1(FRect(grid1._position._x, grid1._position._y, + grid2._position._x, grid2._position._y)); + } + } + } } void CStarControlSub5::proc3(CErrorCode *errorCode) { @@ -259,40 +506,85 @@ void CStarControlSub5::fn1() { } bool CStarControlSub5::setupEntry(int width, int height, int index, double val) { - /* if (width < 2 || height < 3) return false; SubEntry &entry = _array[index]; entry.clear(); - int height2 = height - 2; - int height1 = height - 1; - entry._data1.resize((2 * height - 3) * width); - entry._data2.resize(width * height2 + 2); - entry._data2[0] = FVector(0.0, val, 0.0); + const double FACTOR = 2 * M_PI / 360.0; + int d1Count, d2Count, size3, height1; + int ctr, ctr2, idx, offset, f11; + double vx, vy, f5, f6, f7, f8, f9, f10; + + d1Count = width * (2 * height - 3); + d2Count = (height - 2) * width + 2; + entry._data1.resize(d1Count); + entry._data2.resize(d2Count); + + height1 = height - 1; + entry._data2[0]._y = val; + + vy = 180.0 / (double)height1; + vx = 360.0 / (double)width; + + for (ctr = height - 2, idx = 0; ctr > 0; --ctr, vy *= 2) { + f5 = 0.0; + f6 = cos(vy * FACTOR); + f7 = sin(vy * FACTOR); - index = 1; - double vy = 180.0 / (double)height1; - double vx = 360.0 / (double)width; - const double FACTOR = 3.1415927 * 0.0055555557; + if (width > 0) { + f8 = f6 * val; - if (height1 > 1) { - double yAmount = vy; - int width12 = width * 12; - for (int yCtr = height1 - 1; yCtr > 0; --yCtr, yAmount += vy) { - double sineVal = sin(yAmount * FACTOR); + for (int xp = width; xp > 0; --xp, ++idx, f5 += vx) { + f9 = f5 * FACTOR; + f10 = cos(f9) * f7 * val; + FVector &tempV = entry._data2[idx]; + tempV._x = sin(f9) * f7 * val; + tempV._y = f8; + tempV._z = f10; + } + } + } + entry._data2[idx] = FVector(0.0, -1.0, 0.0); + + size3 = width * (height - 3) + 1; + offset = 0; + Data1 *data1P = &entry._data1[0]; + for (ctr = 0; ctr < width; ++ctr, ++size3) { + data1P->_index1 = 0; + data1P->_index2 = size3 - width * (height - 3); + ++data1P; + + data1P->_index1 = d2Count - 1; + data1P->_index2 = size3; + ++data1P; + } - | 0.0 * FACTOR | - | cos(yAmount * FACTOR) * val | - | 0.0 | - |yAmount| + f11 = 1; + for (ctr = 1; ctr < height1; ++ctr, f11 += width) { + data1P = &entry._data1[offset]; + + for (ctr2 = 0; ctr2 < width; ++ctr2) { + data1P->_index1 = ctr2 + f11; + if (ctr2 == width - 1) + data1P->_index2 = f11; + else + data1P->_index2 = ctr2 + f11 + 1; + + ++offset; + ++data1P; + + if (ctr < height - 2) { + data1P->_index1 = ctr2 + f11; + ++offset; + data1P->_index2 = width + ctr2 + f11; + ++data1P; + } } } - // TODO - */ return true; } diff --git a/engines/titanic/star_control/star_control_sub5.h b/engines/titanic/star_control/star_control_sub5.h index 32094f5227..b5e5bb1b6a 100644 --- a/engines/titanic/star_control/star_control_sub5.h +++ b/engines/titanic/star_control/star_control_sub5.h @@ -33,8 +33,14 @@ namespace Titanic { class CStarControlSub12; class CStarControlSub5 { + struct Data1 { + int _index1; + int _index2; + Data1() : _index1(0), _index2(0) {} + }; + struct SubEntry { - Common::Array<FPoint> _data1; + Common::Array<Data1> _data1; Common::Array<FVector> _data2; ~SubEntry() { clear(); } @@ -46,28 +52,23 @@ class CStarControlSub5 { struct Entry { int _field0; - byte _field4; - byte _field5; - byte _field6; + byte _pixel1; + byte _pixel2; + byte _pixel3; int _field8; int _fieldC; double _field10; double _field14; - Entry() : _field0(0), _field4(0), _field5(0), _field6(0), _field8(0), + Entry() : _field0(0), _pixel1(0), _pixel2(0), _pixel3(0), _field8(0), _fieldC(0), _field10(0), _field14(0) {} }; - struct GridEntry { - int _field0; - int _field4; - int _field8; - int _fieldC; - int _field10; + struct GridEntry : public FVector { + FPoint _position; int _field14; - GridEntry() : _field0(0), _field4(0), _field8(0), _fieldC(0), - _field10(0), _field14(0) {} + GridEntry() : FVector(), _field14(0) {} }; /** diff --git a/engines/titanic/star_control/star_control_sub6.cpp b/engines/titanic/star_control/star_control_sub6.cpp index 27e2a491f8..0ced3df9fe 100644 --- a/engines/titanic/star_control/star_control_sub6.cpp +++ b/engines/titanic/star_control/star_control_sub6.cpp @@ -30,14 +30,56 @@ CStarControlSub6::CStarControlSub6() { clear(); } -CStarControlSub6::CStarControlSub6(int mode, double val) { - set(mode, val); +CStarControlSub6::CStarControlSub6(Axis axis, double amount) { + setRotationMatrix(axis, amount); } CStarControlSub6::CStarControlSub6(const CStarControlSub6 *src) { copyFrom(src); } +CStarControlSub6::CStarControlSub6(const CStarControlSub6 *s1, const CStarControlSub6 *s2) { + _row1._x = s2->_row1._x * s1->_row1._x + + s1->_row1._z * s2->_row3._x + + s1->_row1._y * s2->_row2._x; + _row1._y = s1->_row1._x * s2->_row1._y + + s2->_row3._y * s1->_row1._z + + s2->_row2._y * s1->_row1._y; + _row1._z = s1->_row1._x * s2->_row1._z + + s2->_row3._z * s1->_row1._z + + s2->_row2._z * s1->_row1._y; + _row2._x = s2->_row1._x * s1->_row2._x + + s1->_row2._y * s2->_row2._x + + s1->_row2._z * s2->_row3._x; + _row2._y = s1->_row2._y * s2->_row2._y + + s1->_row2._z * s2->_row3._y + + s2->_row1._y * s1->_row2._x; + _row2._z = s2->_row1._z * s1->_row2._x + + s1->_row2._y * s2->_row2._z + + s1->_row2._z * s2->_row3._z; + _row3._x = s2->_row1._x * s1->_row3._x + + s1->_row3._y * s2->_row2._x + + s1->_row3._z * s2->_row3._x; + _row3._y = s1->_row3._z * s2->_row3._y + + s1->_row3._y * s2->_row2._y + + s2->_row1._y * s1->_row3._x; + _row3._z = s2->_row3._z * s1->_row3._z + + s2->_row2._z * s1->_row3._y + + s2->_row1._z * s1->_row3._x; + _vector._x = s2->_row1._x * s1->_vector._x + + s1->_vector._y * s2->_row2._x + + s1->_vector._z * s2->_row3._x + + s2->_vector._x; + _vector._y = s1->_vector._z * s2->_row3._y + + s1->_vector._y * s2->_row2._y + + s1->_vector._x * s2->_row1._y + + s2->_vector._y; + _vector._z = s1->_vector._y * s2->_row2._z + + s1->_vector._z * s2->_row3._z + + s1->_vector._x * s2->_row1._z + + s2->_vector._z; +} + void CStarControlSub6::init() { _static = nullptr; } @@ -47,18 +89,18 @@ void CStarControlSub6::deinit() { _static = nullptr; } -void CStarControlSub6::clear() { - FMatrix::clear(); +void CStarControlSub6::identity() { + FMatrix::identity(); _vector.clear(); } -void CStarControlSub6::set(int mode, double amount) { - const double ROTATION = 3.1415927 * 0.0055555557; +void CStarControlSub6::setRotationMatrix(Axis axis, double amount) { + const double ROTATION = 2 * M_PI / 360.0; double sinVal = sin(amount * ROTATION); double cosVal = cos(amount * ROTATION); - switch (mode) { - case 0: + switch (axis) { + case X_AXIS: _row1._x = 1.0; _row1._y = 0.0; _row1._z = 0.0; @@ -70,7 +112,7 @@ void CStarControlSub6::set(int mode, double amount) { _row3._z = cosVal; break; - case 1: + case Y_AXIS: _row1._x = cosVal; _row1._y = 0.0; _row1._z = sinVal; @@ -82,7 +124,7 @@ void CStarControlSub6::set(int mode, double amount) { _row3._z = sinVal; break; - case 2: + case Z_AXIS: _row1._x = cosVal; _row1._y = sinVal; _row1._z = 0.0; @@ -108,52 +150,73 @@ void CStarControlSub6::copyFrom(const CStarControlSub6 *src) { _vector = src->_vector; } -void CStarControlSub6::setup(CStarControlSub6 *dest, const CStarControlSub6 *s2, const CStarControlSub6 *s3) { - CStarControlSub6 &d = *dest; - - d._row1._x = s3->_row1._x * s2->_row1._x - + s2->_row1._z * s3->_row3._x - + s2->_row1._y * s3->_row2._x; - d._row1._y = s2->_row1._x * s3->_row1._y - + s3->_row3._y * s2->_row1._z - + s3->_row2._y * s2->_row1._y; - d._row1._z = s2->_row1._x * s3->_row1._z - + s3->_row3._z * s2->_row1._z - + s3->_row2._z * s2->_row1._y; - d._row2._x = s3->_row1._x * s2->_row2._x - + s2->_row2._y * s3->_row2._x - + s2->_row2._z * s3->_row3._x; - d._row2._y = s2->_row2._y * s3->_row2._y - + s2->_row2._z * s3->_row3._y - + s3->_row1._y * s2->_row2._x; - d._row2._z = s3->_row1._z * s2->_row2._x - + s2->_row2._y * s3->_row2._z - + s2->_row2._z * s3->_row3._z; - d._row3._x = s3->_row1._x * s2->_row3._x - + s2->_row3._y * s3->_row2._x - + s2->_row3._z * s3->_row3._x; - d._row3._y = s2->_row3._z * s3->_row3._y - + s2->_row3._y * s3->_row2._y - + s3->_row1._y * s2->_row3._x; - d._row3._z = s3->_row3._z * s2->_row3._z - + s3->_row2._z * s2->_row3._y - + s3->_row1._z * s2->_row3._x; - d._vector._x = s3->_row1._x * s2->_vector._x - + s2->_vector._y * s3->_row2._x - + s2->_vector._z * s3->_row3._x - + s3->_vector._x; - d._vector._y = s2->_vector._z * s3->_row3._y - + s2->_vector._y * s3->_row2._y - + s2->_vector._x * s3->_row1._y - + s3->_vector._y; - d._vector._z = s2->_vector._y * s3->_row2._z - + s2->_vector._z * s3->_row3._z - + s2->_vector._x * s3->_row1._z - + s3->_vector._z; +void CStarControlSub6::copyFrom(const FMatrix &src) { + _row1 = src._row1; + _row2 = src._row2; + _row3 = src._row3; } -void CStarControlSub6::fn1(CStarControlSub6 *sub6) { - // TODO +void CStarControlSub6::fn4(CStarControlSub6 *sub6) { + double v2, v3, v6, v7, v8, v9, v10, v11; + double v12, v13, v14, v15, v16, v17, v18; + + v16 = _row3._z * _row2._y; + v2 = _row1._x * v16; + v3 = 0.0; + v18 = v2; + if (v2 < 0.0) { + v3 = v18; + v2 = 0.0; + } + v6 = _row3._x * _row1._y * _row2._z; + if (v6 < 0.0) + v3 = v3 + v6; + else + v2 = v2 + v6; + v7 = _row3._y * _row1._z * _row2._x; + if (v7 < 0.0) + v3 = v3 + v7; + else + v2 = v2 + v7; + if (-(_row3._x * _row1._z * _row2._y) < 0.0) + v3 = v3 - _row3._x * _row1._z * _row2._y; + else + v2 = v2 - _row3._x * _row1._z * _row2._y; + if (-(_row1._y * _row2._x * _row3._z) < 0.0) + v3 = v3 - _row1._y * _row2._x * _row3._z; + else + v2 = v2 - _row1._y * _row2._x * _row3._z; + v17 = _row2._z * _row3._y; + if (-(_row1._x * v17) < 0.0) + v3 = v3 - _row1._x * v17; + else + v2 = v2 - _row1._x * v17; + v18 = v3 + v2; + assert(!(v18 == 0.0 || fabs(v18 / (v2 - v3)) < 1.0e-10)); + + v8 = 1.0 / v18; + v18 = v8; + sub6->_row1._x = (v16 - v17) * v8; + sub6->_row2._x = -(_row2._x * _row3._z - _row3._x * _row2._z) * v8; + sub6->_row3._x = (_row3._y * _row2._x - _row3._x * _row2._y) * v8; + sub6->_row1._y = -(_row1._y * _row3._z - _row3._y * _row1._z) * v8; + sub6->_row2._y = (_row1._x * _row3._z - _row3._x * _row1._z) * v8; + sub6->_row3._y = -(_row1._x * _row3._y - _row3._x * _row1._y) * v8; + sub6->_row1._z = (_row1._y * _row2._z - _row1._z * _row2._y) * v8; + sub6->_row2._z = -(_row1._x * _row2._z - _row1._z * _row2._x) * v8; + v9 = sub6->_row1._x; + v10 = sub6->_row2._y; + v11 = sub6->_row3._y; + v12 = sub6->_row1._z; + v13 = sub6->_row2._z; + sub6->_row3._z = (_row1._x * _row2._y - _row1._y * _row2._x) * v18; + v14 = v9; + v15 = sub6->_row3._z; + sub6->_vector._x = -(v14 * _vector._x + + _vector._y * sub6->_row2._x + + _vector._z * sub6->_row3._x); + sub6->_vector._y = -(_vector._x * sub6->_row1._y + v10 * _vector._y + v11 * _vector._z); + sub6->_vector._z = -(v12 * _vector._x + v13 * _vector._y + v15 * _vector._z); } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub6.h b/engines/titanic/star_control/star_control_sub6.h index 16304b8540..91def29973 100644 --- a/engines/titanic/star_control/star_control_sub6.h +++ b/engines/titanic/star_control/star_control_sub6.h @@ -37,27 +37,28 @@ public: FVector _vector; public: CStarControlSub6(); - CStarControlSub6(int mode, double amount); + CStarControlSub6(Axis axis, double amount); CStarControlSub6(const CStarControlSub6 *src); + CStarControlSub6(const CStarControlSub6 *s1, const CStarControlSub6 *s2); /** - * Clear the item + * Sets an identity matrix */ - void clear(); + void identity(); /** - * Sets up a passed instance from the specified two other ones + * Sets a rotation matrix for the given axis for the given amount */ - static void setup(CStarControlSub6 *dest, const CStarControlSub6 *s2, const CStarControlSub6 *s3); + void setRotationMatrix(Axis axis, double val); + + void copyFrom(const CStarControlSub6 *src); /** - * Sets the default data + * Copy from the specified matrix */ - void set(int mode, double val); - - void copyFrom(const CStarControlSub6 *src); + void copyFrom(const FMatrix &src); - void fn1(CStarControlSub6 *sub6); + void fn4(CStarControlSub6 *sub6); }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub7.cpp b/engines/titanic/star_control/star_control_sub7.cpp index 4b694810ad..8386e7305f 100644 --- a/engines/titanic/star_control/star_control_sub7.cpp +++ b/engines/titanic/star_control/star_control_sub7.cpp @@ -21,18 +21,62 @@ */ #include "titanic/star_control/star_control_sub7.h" +#include "titanic/star_control/star_control_sub12.h" namespace Titanic { void CStarControlSub7::draw(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, CStarControlSub5 *sub5) { - // TODO + if (_data.empty()) + return; + + CStarControlSub6 sub6 = sub12->proc23(); + double threshold = sub12->proc25(); + FPoint center((double)surfaceArea->_width * 0.5, + surfaceArea->_height * 0.5); + FVector newV; + + uint savedPixel = surfaceArea->_pixel; + surfaceArea->_pixel = 0xffff; + surfaceArea->setColorFromPixel(); + + for (uint idx = 0; idx < _data.size(); ++idx) { + const CBaseStarEntry &star = _data[idx]; + + newV._x = sub6._row1._x * star._position._x + sub6._row3._x * star._position._z + + sub6._row2._x * star._position._y + sub6._vector._x; + newV._y = sub6._row1._y * star._position._x + sub6._row3._y * star._position._z + + sub6._row2._y * star._position._x + sub6._vector._y; + newV._z = sub6._row1._z * star._position._x + sub6._row3._z * star._position._z + + sub6._row2._z * star._position._y + sub6._vector._z; + + if (newV._z > threshold) { + FVector vTemp; + sub12->proc28(2, newV, vTemp); + + FRect r1(center._x + vTemp._x, center._y + vTemp._y, + center._x + vTemp._x + 4.0, center._y + vTemp._y + 4.0); + surfaceArea->fn1(r1); + + FRect r2(r1.right, r1.bottom, r1.right + 4.0, r1.top); + surfaceArea->fn1(r2); + + FRect r3(r2.right, r1.top, r1.right, r1.top - 4.0); + surfaceArea->fn1(r3); + + FRect r4(r1.right, r1.top - 4.0, r1.left, r1.top); + surfaceArea->fn1(r4); + } + } + + surfaceArea->_pixel = savedPixel; + surfaceArea->setColorFromPixel(); } bool CStarControlSub7::addStar(const CBaseStarEntry *entry) { // iterate through the existing stars for (uint idx = 0; idx < _data.size(); ++idx) { CBaseStarEntry &star = _data[idx]; - if (star._position == entry->_position) { + if (star == *entry) { // Found a matching star at the exact same position, so remove it instead _data.remove_at(idx); return true; diff --git a/engines/titanic/star_control/star_control_sub8.cpp b/engines/titanic/star_control/star_control_sub8.cpp index 50c90d2bc1..bf29b053c5 100644 --- a/engines/titanic/star_control/star_control_sub8.cpp +++ b/engines/titanic/star_control/star_control_sub8.cpp @@ -24,36 +24,102 @@ #include "titanic/star_control/star_control_sub7.h" #include "titanic/star_control/star_control_sub12.h" #include "titanic/star_control/star_field.h" +#include "titanic/star_control/star_ref.h" namespace Titanic { -CStarControlSub8::CStarControlSub8() : _field8(-1), _fieldC(-1) { -#if 0 - _field4(0), _field8(-1) -#endif -} - -bool MouseButtonDown(const Common::Point &pt) { - // TODO - return true; -} - -int CStarControlSub8::findStar(const Common::Point &pt) { - // TODO - return -1; +CStarControlSub8::CStarControlSub8() : _field8(-1), _entryIndex(-1) { } void CStarControlSub8::selectStar(int index, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7) { - // TODO + if (_entryIndex >= 0) { + if (_entryIndex == _field8) { + if (_field8 != 2) { + if (_positions[index] != _positions[_entryIndex + 1]) { + surface->lock(); + + CSurfaceArea surfaceArea(surface); + fn4(index, &surfaceArea); + surface->unlock(); + + ++_entryIndex; + CStarPosition &newP = _positions[_entryIndex + 1]; + newP = _positions[index]; + + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + } + } + } else if (_entryIndex == _field8 + 1) { + if (_positions[index] == _positions[_entryIndex + 1]) { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn6(&surfaceArea); + surface->unlock(); + + --_entryIndex; + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + } else { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn6(&surfaceArea); + fn4(index, &surfaceArea); + surface->unlock(); + + const CBaseStarEntry *starP; + starP = starField->getDataPtr(_positions[_entryIndex]._index1); + sub7->addStar(starP); + starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + + CStarPosition &newP = _positions[_entryIndex + 1]; + newP = _positions[index]; + } + } + } else { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn4(index, &surfaceArea); + surface->unlock(); + + ++_entryIndex; + CStarPosition &newP = _positions[_entryIndex + 1]; + newP = _positions[index]; + + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index]._index1); + sub7->addStar(starP); + } } -void CStarControlSub8::fn1(CStarField *starField, CSurfaceArea *surfaceArea, CStarControlSub12 *sub12) { - // TODO +bool CStarControlSub8::fn1(CStarField *starField, CSurfaceArea *surfaceArea, CStarControlSub12 *sub12) { + int count = starField->baseFn2(surfaceArea, sub12); + + if (count > 0) { + allocate(count); + CStarRef2 starRef(starField, &_positions); + starRef.process(surfaceArea, sub12); + return true; + } else { + clear(); + return false; + } } void CStarControlSub8::fn2(CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7) { - // TODO + if (_field8 <= -1) { + if (_entryIndex > -1) { + fn5(_entryIndex, surface, starField, sub7); + --_entryIndex; + } + } else { + --_field8; + if (_entryIndex - _field8 > 1) { + fn5(_entryIndex, surface, starField, sub7); + --_entryIndex; + } + } } void CStarControlSub8::fn3() { @@ -62,15 +128,97 @@ void CStarControlSub8::fn3() { } FPoint CStarControlSub8::getPosition() const { - return (_fieldC >= 0 && _fieldC <= 2) ? _data[_fieldC]._position : FPoint(); + return (_entryIndex >= 0 && _entryIndex <= 2) ? + FPoint(_entries[_entryIndex]) : FPoint(); } void CStarControlSub8::draw(CSurfaceArea *surfaceArea) { - // TODO + if (!_positions.empty()) { + uint savedPixel = surfaceArea->_pixel; + surfaceArea->_pixel = 0xff; + surfaceArea->setColorFromPixel(); + SurfaceAreaMode savedMode = surfaceArea->setMode(SA_NONE); + + for (int idx = 0; idx < _entryIndex; ++idx) { + const CStarPosition &src = _entries[idx]; + double xp = src.x, yp = src.y; + + surfaceArea->fn1(FRect(xp - 8.0, yp, xp - 4.0, yp)); + surfaceArea->fn1(FRect(xp + 4.0, yp, xp + 8.0, yp)); + surfaceArea->fn1(FRect(xp, yp - 8.0, xp, yp - 4.0)); + surfaceArea->fn1(FRect(xp, yp + 4.0, xp, yp + 8.0)); + } + + surfaceArea->_pixel = savedPixel; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(savedMode); + } +} + +void CStarControlSub8::allocate(int count) { + if (!_positions.empty()) { + if ((int)_positions.size() == count) + return; + + clear(); + } + + _positions.resize(count); } void CStarControlSub8::clear() { - // TODO + _positions.clear(); + _field8 = _entryIndex = -1; +} + +int CStarControlSub8::indexOf(const Common::Point &pt) const { + Common::Rect r(pt.x - 2, pt.y - 2, pt.x + 2, pt.y + 2); + + for (int idx = 0; idx < (int)_positions.size(); ++idx) { + if (r.contains(_positions[idx])) + return idx; + } + + return -1; +} + +void CStarControlSub8::fn4(int index, CSurfaceArea *surfaceArea) { + if (index >= 0 && index < (int)_positions.size()) { + const CStarPosition &pt = _positions[index]; + fn7(pt, surfaceArea); + } +} + +void CStarControlSub8::fn5(int index, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7) { + surface->lock(); + CSurfaceArea surfaceArea(surface); + fn7(_positions[index + 1], &surfaceArea); + surface->unlock(); + + const CBaseStarEntry *starP = starField->getDataPtr(_positions[index + 1]._index1); + sub7->addStar(starP); +} + +void CStarControlSub8::fn6(CSurfaceArea *surfaceArea) { + const CStarPosition &pt = _positions[_entryIndex]; + fn7(pt, surfaceArea); +} + +void CStarControlSub8::fn7(const FPoint &pt, CSurfaceArea *surfaceArea) { + uint savedPixel = surfaceArea->_pixel; + surfaceArea->_pixel = 255; + surfaceArea->setColorFromPixel(); + SurfaceAreaMode savedMode = surfaceArea->setMode(SA_MODE3); + + + surfaceArea->fn1(FRect(pt._x - 8.0, pt._y, pt._x - 4.0, pt._y)); + surfaceArea->fn1(FRect(pt._x - -4.0, pt._y, pt._x + 8.0, pt._y)); + surfaceArea->fn1(FRect(pt._x, pt._y - 8.0, pt._x, pt._y - 4.0)); + surfaceArea->fn1(FRect(pt._x, pt._y + 4.0, pt._x, pt._y + 8.0)); + + surfaceArea->_pixel = savedPixel; + surfaceArea->setColorFromPixel(); + surfaceArea->setMode(savedMode); } } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub8.h b/engines/titanic/star_control/star_control_sub8.h index f7f8ba4fb5..4939179481 100644 --- a/engines/titanic/star_control/star_control_sub8.h +++ b/engines/titanic/star_control/star_control_sub8.h @@ -23,6 +23,9 @@ #ifndef TITANIC_STAR_CONTROL_SUB8_H #define TITANIC_STAR_CONTROL_SUB8_H +#include "common/array.h" +#include "common/rect.h" +#include "titanic/star_control/base_star.h" #include "titanic/star_control/surface_area.h" #include "titanic/star_control/fpoint.h" #include "titanic/support/simple_file.h" @@ -35,19 +38,20 @@ class CStarControlSub7; class CStarControlSub12; class CStarControlSub8 { - struct StructEntry { - FPoint _position; - int _field8; - int _fieldC; - - StructEntry() : _field8(0), _fieldC(0) {} - }; private: -#if 0 - int _field0; - int _field4; -#endif - StructEntry _data[3]; + Common::Array<CStarPosition> _positions; + int _entryIndex; + CStarPosition _entries[3]; +private: + /** + * Allocates space in the _rects array + */ + void allocate(int count); + + /** + * Clears any current data + */ + void clear(); public: int _field8; int _fieldC; @@ -65,19 +69,24 @@ public: */ void save(SimpleFile *file, int indent) {} - int findStar(const Common::Point &pt); - void selectStar(int starNum, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7); void draw(CSurfaceArea *surfaceArea); - void fn1(CStarField *starField, CSurfaceArea *surfaceArea, CStarControlSub12 *sub12); + bool fn1(CStarField *starField, CSurfaceArea *surfaceArea, CStarControlSub12 *sub12); void fn2(CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7); void fn3(); + void fn4(int index, CSurfaceArea *surfaceArea); + void fn5(int index, CVideoSurface *surface, CStarField *starField, CStarControlSub7 *sub7); + void fn6(CSurfaceArea *surfaceArea); + void fn7(const FPoint &pt, CSurfaceArea *surfaceArea); FPoint getPosition() const; - void clear(); + /** + * Returns the index of an entry in the rects list a given point falls within + */ + int indexOf(const Common::Point &pt) const; }; } // End of namespace Titanic diff --git a/engines/titanic/star_control/star_field.cpp b/engines/titanic/star_control/star_field.cpp index 3a09be3e8a..5c22e5e308 100644 --- a/engines/titanic/star_control/star_field.cpp +++ b/engines/titanic/star_control/star_field.cpp @@ -230,9 +230,9 @@ bool CStarField::mouseButtonDown(CVideoSurface *surface, CStarControlSub12 *sub1 int flags, const Common::Point &pt) { if (_mode == MODE_STARFIELD) { CSurfaceArea surfaceArea(surface); - return selectStar(&surfaceArea, sub12, 0, pt); + return selectStar(&surfaceArea, sub12, pt); } else { - int starNum = _sub8.findStar(pt); + int starNum = _sub8.indexOf(pt); if (starNum >= 0) { _sub8.selectStar(starNum, surface, this, &_sub7); return true; diff --git a/engines/titanic/star_control/star_points1.cpp b/engines/titanic/star_control/star_points1.cpp index c72795f11d..ab5da111ac 100644 --- a/engines/titanic/star_control/star_points1.cpp +++ b/engines/titanic/star_control/star_points1.cpp @@ -27,7 +27,7 @@ namespace Titanic { #define ARRAY_COUNT 876 -const double FACTOR = 3.1415927 * 0.0055555557; +const double FACTOR = 2 * M_PI / 360.0; CStarPoints1::CStarPoints1() { } diff --git a/engines/titanic/star_control/star_points2.cpp b/engines/titanic/star_control/star_points2.cpp index 9c4cfe8cf5..7a3e873e90 100644 --- a/engines/titanic/star_control/star_points2.cpp +++ b/engines/titanic/star_control/star_points2.cpp @@ -27,7 +27,7 @@ namespace Titanic { #define ARRAY_COUNT 80 -const double FACTOR = 3.1415927 * 0.0055555557; +const double FACTOR = 2 * M_PI / 360.0; bool CStarPoints2::initialize() { // Get a reference to the starfield points resource @@ -47,7 +47,7 @@ bool CStarPoints2::initialize() { v1 = stream->readSint32LE(); v2 = stream->readSint32LE(); v1 *= 0.015 * FACTOR; - v2 *= 0.0099999998 * FACTOR; + v2 *= FACTOR / 100.0; entry._x = cos(v1) * 3000000.0 * cos(v2); entry._y = sin(v1) * 3000000.0 * cos(v2); diff --git a/engines/titanic/star_control/star_ref.cpp b/engines/titanic/star_control/star_ref.cpp new file mode 100644 index 0000000000..7f36ae7473 --- /dev/null +++ b/engines/titanic/star_control/star_ref.cpp @@ -0,0 +1,63 @@ +/* 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 "titanic/star_control/star_ref.h" + +namespace Titanic { + +void CBaseStarRef::process(CSurfaceArea *surface, CStarControlSub12 *sub12) { + // TODO +} + +/*------------------------------------------------------------------------*/ + +bool CStarRef1::check(const Common::Point &pt, int index) { + Common::Rect r(pt.x - 2, pt.y - 2, pt.x + 2, pt.y + 2); + if (r.contains(_position)) { + _index = index; + return false; + } else { + return true; + } +} + +/*------------------------------------------------------------------------*/ + +bool CStarRef2::check(const Common::Point &pt, int index) { + if (_index >= (int)_positions->size()) + return false; + + CStarPosition &sp = (*_positions)[index]; + sp.x = pt.x; + sp.y = pt.y; + sp._index1 = sp._index2 = index; + return true; +} + +/*------------------------------------------------------------------------*/ + +bool CStarRef3::check(const Common::Point &pt, int index) { + ++_index; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_ref.h b/engines/titanic/star_control/star_ref.h new file mode 100644 index 0000000000..c6fec90fbc --- /dev/null +++ b/engines/titanic/star_control/star_ref.h @@ -0,0 +1,84 @@ +/* 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/rect.h" +#include "titanic/star_control/base_star.h" +#include "titanic/star_control/star_control_sub12.h" +#include "titanic/star_control/surface_area.h" + +#ifndef TITANIC_STAR_REF_H +#define TITANIC_STAR_REF_H + +namespace Titanic { + +class CBaseStarRef { +protected: + CBaseStar *_star; +public: + CBaseStarRef(CBaseStar *star) : _star(star) {} + CBaseStarRef() : _star(nullptr) {} + virtual ~CBaseStarRef() {} + + void process(CSurfaceArea *surface, CStarControlSub12 *sub12); + + virtual bool check(const Common::Point &pt, int index) { return false; } +}; + +class CStarRef1 : public CBaseStarRef { +private: + Common::Point _position; +public: + int _index; +public: + CStarRef1(CBaseStar *star, const Common::Point &pt) : + CBaseStarRef(star), _index(-1) {} + virtual ~CStarRef1() {} + + virtual bool check(const Common::Point &pt, int index); +}; + +class CStarRef2 : public CBaseStarRef { +private: + Common::Array<CStarPosition> *_positions; +public: + int _index; +public: + CStarRef2(CBaseStar *star, Common::Array<CStarPosition> *positions) : + CBaseStarRef(star), _positions(positions), _index(0) {} + virtual ~CStarRef2() {} + + virtual bool check(const Common::Point &pt, int index); +}; + +class CStarRef3 : public CBaseStarRef { +public: + int _index; +public: + CStarRef3(CBaseStar *star) :CBaseStarRef(star), _index(0) {} + virtual ~CStarRef3() {} + + virtual bool check(const Common::Point &pt, int index); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_REF_H */ diff --git a/engines/titanic/star_control/star_view.cpp b/engines/titanic/star_control/star_view.cpp index 23e9325a64..34fd371bac 100644 --- a/engines/titanic/star_control/star_view.cpp +++ b/engines/titanic/star_control/star_view.cpp @@ -30,8 +30,8 @@ namespace Titanic { -CStarView::CStarView() : _sub12(nullptr, nullptr), _sub13((void *)nullptr), - _owner(nullptr), _starField(nullptr), _videoSurface(nullptr), _field118(0), +CStarView::CStarView() : _sub12((const CStar20Data *)nullptr), _owner(nullptr), + _starField(nullptr), _videoSurface(nullptr), _field118(0), _videoSurface2(nullptr), _homePhotoMask(nullptr), _field218(false), _showingPhoto(false) { CStar20Data data = { 0, 0, 100000.0, 0, 20.0, 1.0, 1.0, 1.0 }; @@ -177,7 +177,7 @@ bool CStarView::KeyCharMsg(int key, CErrorCode *errorCode) { case Common::KEYCODE_z: case Common::KEYCODE_c: if (v == -1) { - sub6.set(key == Common::KEYCODE_z ? MODE_PHOTO : MODE_STARFIELD, 1.0); + sub6.setRotationMatrix(key == Common::KEYCODE_z ? Y_AXIS : X_AXIS, 1.0); _sub12.proc22(sub6); _sub12.proc15(errorCode); return true; @@ -210,7 +210,7 @@ bool CStarView::KeyCharMsg(int key, CErrorCode *errorCode) { case Common::KEYCODE_x: if (v == -1) { - sub6.set(MODE_PHOTO, -1.0); + sub6.setRotationMatrix(Y_AXIS, -1.0); _sub12.proc22(sub6); _sub12.proc15(errorCode); return true; @@ -219,7 +219,7 @@ bool CStarView::KeyCharMsg(int key, CErrorCode *errorCode) { case Common::KEYCODE_QUOTE: if (v == -1) { - sub6.set(MODE_STARFIELD, -1.0); + sub6.setRotationMatrix(X_AXIS, -1.0); _sub12.proc22(sub6); _sub12.proc15(errorCode); return true; @@ -450,7 +450,7 @@ void CStarView::randomizeVectors1(FVector &v1, FVector &v2) { v2._x = vx; v2._y = vy; v2._z = -v1._z; - v2.fn3(); + v2.normalize(); } void CStarView::randomizeVectors2(FVector &v1, FVector &v2) { @@ -462,7 +462,7 @@ void CStarView::randomizeVectors2(FVector &v1, FVector &v2) { v2._x = -v1._x; v2._y = -v1._y; v2._z = -v1._z; - v2.fn3(); + v2.normalize(); } void CStarView::randomizeVectors3(FVector &v1, FVector &v2) { @@ -474,7 +474,7 @@ void CStarView::randomizeVectors3(FVector &v1, FVector &v2) { v2._x = -v1._x; v2._y = -v1._y; v2._z = -v1._z; - v2.fn3(); + v2.normalize(); } void CStarView::randomizeVectors4(FVector &v1, FVector &v2) { @@ -486,7 +486,7 @@ void CStarView::randomizeVectors4(FVector &v1, FVector &v2) { v2._x = -v1._x; v2._y = -v1._y; v2._z = -v1._z; - v2.fn3(); + v2.normalize(); } void CStarView::resizeSurface(CScreenManager *scrManager, int width, int height, CVideoSurface **surface) { diff --git a/engines/titanic/star_control/surface_area.cpp b/engines/titanic/star_control/surface_area.cpp index 9b46cf03b7..4cfc4f84d2 100644 --- a/engines/titanic/star_control/surface_area.cpp +++ b/engines/titanic/star_control/surface_area.cpp @@ -28,11 +28,14 @@ CSurfaceArea::CSurfaceArea(CVideoSurface *surface) { _width = surface->getWidth(); _height = surface->getHeight(); _pitch = surface->getPitch(); + _field0 = 0; + _colorMask = _color = 0; + _mode = SA_NONE; // Original supported other pixel depths _bpp = surface->getPixelDepth(); - assert(_bpp == 2); _pixelsPtr = surface->getPixels(); + assert(_bpp == 2 && _pixelsPtr); initialize(); } diff --git a/engines/titanic/titanic.h b/engines/titanic/titanic.h index fdc9402d89..6bc999cd40 100644 --- a/engines/titanic/titanic.h +++ b/engines/titanic/titanic.h @@ -166,7 +166,7 @@ public: /** * Returns a random floating point number between 0.0 to 65535.0 */ - double getRandomFloat() { return getRandomNumber(0xffffffff) * 0.000015259022; } + double getRandomFloat() { return getRandomNumber(0xfffffffe) * 0.000015259022; } /** * Support method that generates a savegame name |