diff options
author | Max Horn | 2003-07-19 18:18:01 +0000 |
---|---|---|
committer | Max Horn | 2003-07-19 18:18:01 +0000 |
commit | 2fbf782c05bf5ff06e2817e487e152e8739be9ee (patch) | |
tree | c9f09796dea78d0a9fc22125c464b205644ac331 | |
parent | d516f3467cde8fa05ef26732a58e289cd13444e6 (diff) | |
download | scummvm-rg350-2fbf782c05bf5ff06e2817e487e152e8739be9ee.tar.gz scummvm-rg350-2fbf782c05bf5ff06e2817e487e152e8739be9ee.tar.bz2 scummvm-rg350-2fbf782c05bf5ff06e2817e487e152e8739be9ee.zip |
moved some functions out of scummvm.cpp into more appropriate files; rearranged stuff inside scummvm.cpp to be grouped a bit more logical
svn-id: r9083
-rw-r--r-- | scumm/actor.cpp | 19 | ||||
-rw-r--r-- | scumm/boxes.cpp | 44 | ||||
-rw-r--r-- | scumm/charset.cpp | 8 | ||||
-rw-r--r-- | scumm/gfx.cpp | 51 | ||||
-rw-r--r-- | scumm/resource.cpp | 30 | ||||
-rw-r--r-- | scumm/scumm.h | 4 | ||||
-rw-r--r-- | scumm/scummvm.cpp | 1242 | ||||
-rw-r--r-- | scumm/string.cpp | 12 |
8 files changed, 720 insertions, 690 deletions
diff --git a/scumm/actor.cpp b/scumm/actor.cpp index 102f122a25..b51cfe7d4e 100644 --- a/scumm/actor.cpp +++ b/scumm/actor.cpp @@ -812,6 +812,25 @@ void Scumm::playActorSounds() { } } +Actor *Scumm::derefActor(int id, const char *errmsg) const { + if (id < 1 || id >= _numActors || _actors[id].number != id) { + if (errmsg) + error("Invalid actor %d in %s", id, errmsg); + else + error("Invalid actor %d", id); + } + return &_actors[id]; +} + +Actor *Scumm::derefActorSafe(int id, const char *errmsg) const { + if (id < 1 || id >= _numActors || _actors[id].number != id) { + debug(2, "Invalid actor %d in %s (script %d, opcode 0x%x) - This is potentially a BIG problem.", + id, errmsg, vm.slot[_curExecScript].number, _opcode); + return NULL; + } + return &_actors[id]; +} + static int compareDrawOrder(const void* a, const void* b) { const Actor* actor1 = *(const Actor *const*)a; diff --git a/scumm/boxes.cpp b/scumm/boxes.cpp index 6dba4bd827..4a916008b7 100644 --- a/scumm/boxes.cpp +++ b/scumm/boxes.cpp @@ -216,6 +216,50 @@ int Scumm::getBoxScale(int box) { return READ_LE_UINT16(&ptr->old.scale); } +/* + FIXME: It seems that scale items and scale slots are the same thing after + all - they only differ in some details (scale item is used to precompute + a scale table, while for the scale slots the computations are done on the + fly; also for scale slots, the scale along the x axis can vary, too). + + Now, there are various known scale glitches in FT (and apparently also + in The Dig, see FIXME comments in Actor::setupActorScale). In this context + it is very interesting that for V5, there is an opcode which invokes + setScaleItem, and for V8 one that invokes setScaleSlot. But there is no + such opcode to be found for V6/V7 games. + + Hypothesis: we simple are missing this opcode, and implementing it might + fix some or all of the Dig/FT scaling issues. +*/ +void Scumm::setScaleItem(int slot, int y1, int scale1, int y2, int scale2) { + byte *ptr; + int y, tmp; + + if (y1 == y2) + return; + + ptr = createResource(rtScaleTable, slot, 200); + + for (y = 0; y < 200; y++) { + tmp = ((scale2 - scale1) * (y - y1)) / (y2 - y1) + scale1; + if (tmp < 1) + tmp = 1; + if (tmp > 255) + tmp = 255; + *ptr++ = tmp; + } +} + +void Scumm::setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2) { + assert(1 <= slot && slot <= 20); + _scaleSlots[slot-1].x2 = x2; + _scaleSlots[slot-1].y2 = y2; + _scaleSlots[slot-1].scale2 = scale2; + _scaleSlots[slot-1].x1 = x1; + _scaleSlots[slot-1].y1 = y1; + _scaleSlots[slot-1].scale1 = scale1; +} + byte Scumm::getNumBoxes() { byte *ptr = getResourceAddress(rtMatrix, 2); if (!ptr) diff --git a/scumm/charset.cpp b/scumm/charset.cpp index 38237bf42a..be0d4963f0 100644 --- a/scumm/charset.cpp +++ b/scumm/charset.cpp @@ -49,7 +49,7 @@ CharsetRenderer::CharsetRenderer(Scumm *vm) { } void CharsetRendererCommon::setCurID(byte id) { - _vm->checkRange(_vm->_maxCharsets - 1, 0, id, "Printing with bad charset %d"); + checkRange(_vm->_maxCharsets - 1, 0, id, "Printing with bad charset %d"); _curId = id; @@ -64,7 +64,7 @@ void CharsetRendererCommon::setCurID(byte id) { } void CharsetRendererV3::setCurID(byte id) { - _vm->checkRange(_vm->_maxCharsets - 1, 0, id, "Printing with bad charset %d"); + checkRange(_vm->_maxCharsets - 1, 0, id, "Printing with bad charset %d"); _curId = id; @@ -947,7 +947,7 @@ void CharsetRendererV3::printChar(int chr) { int w, h; int drawTop; - _vm->checkRange(_vm->_maxCharsets - 1, 0, _curId, "Printing with bad charset %d"); + checkRange(_vm->_maxCharsets - 1, 0, _curId, "Printing with bad charset %d"); if ((vs = _vm->findVirtScreen(_top)) == NULL) return; @@ -1003,7 +1003,7 @@ void CharsetRendererClassic::printChar(int chr) { const byte *charPtr; int is2byte = (chr >= 0x80 && _vm->_CJKMode) ? 1 : 0; - _vm->checkRange(_vm->_maxCharsets - 1, 1, _curId, "Printing with bad charset %d"); + checkRange(_vm->_maxCharsets - 1, 1, _curId, "Printing with bad charset %d"); if ((vs = _vm->findVirtScreen(_top)) == NULL && (vs = _vm->findVirtScreen(_top + getFontHeight())) == NULL) return; diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index d932f48662..55d31cf51f 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -3319,6 +3319,57 @@ const byte *Scumm::getPalettePtr() { return cptr; } +void Scumm::updatePalette() { + if (_palDirtyMax == -1) + return; + + bool noir_mode = (_gameId == GID_SAMNMAX && readVar(0x8000)); + int first = _palDirtyMin; + int num = _palDirtyMax - first + 1; + int i; + + byte palette_colors[1024]; + byte *p = palette_colors; + + for (i = _palDirtyMin; i <= _palDirtyMax; i++) { + byte *data; + + if (_features & GF_SMALL_HEADER) + data = _currentPalette + _shadowPalette[i] * 3; + else + data = _currentPalette + i * 3; + + // Sam & Max film noir mode. Convert the colours to grayscale + // before uploading them to the backend. + + if (noir_mode) { + int r, g, b; + byte brightness; + + r = data[0]; + g = data[1]; + b = data[2]; + + brightness = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5); + + *p++ = brightness; + *p++ = brightness; + *p++ = brightness; + *p++ = 0; + } else { + *p++ = data[0]; + *p++ = data[1]; + *p++ = data[2]; + *p++ = 0; + } + } + + _system->set_palette(palette_colors, first, num); + + _palDirtyMax = -1; + _palDirtyMin = 256; +} + #pragma mark - #pragma mark --- Cursor --- #pragma mark - diff --git a/scumm/resource.cpp b/scumm/resource.cpp index 9100f9a83f..8fdba761f5 100644 --- a/scumm/resource.cpp +++ b/scumm/resource.cpp @@ -1701,6 +1701,36 @@ bool Scumm::isGlobInMemory(int type, int idx) const{ return res.address[type][idx] != NULL; } +void Scumm::dumpResource(const char *tag, int idx, const byte *ptr, int length) { + char buf[256]; + File out; + + uint32 size; + if (length >= 0) + size = length; + else if (_features & GF_OLD_BUNDLE) + size = READ_LE_UINT16(ptr); + else if (_features & GF_SMALL_HEADER) + size = READ_LE_UINT32(ptr); + else + size = READ_BE_UINT32(ptr + 4); + +#if defined(MACOS_CARBON) + sprintf(buf, ":dumps:%s%d.dmp", tag, idx); +#else + sprintf(buf, "dumps/%s%d.dmp", tag, idx); +#endif + + out.open(buf, "", 1); + if (out.isOpen() == false) { + out.open(buf, "", 2); + if (out.isOpen() == false) + return; + out.write(ptr, size); + } + out.close(); +} + ResourceIterator::ResourceIterator(const byte *searchin, bool smallHeader) : _ptr(searchin), _smallHeader(smallHeader) { assert(searchin); diff --git a/scumm/scumm.h b/scumm/scumm.h index 082514fe54..3cf68ed366 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -366,7 +366,6 @@ public: void clearClickedStatus(); // Misc utility functions - void checkRange(int max, int min, int no, const char *str) const; const char *getExeName() const { return _exe_name; } const char *getGameDataPath() const; @@ -384,7 +383,6 @@ public: void pauseGame(); void restart(); void shutDown(); - void setOptions(void); /** We keep running until this is set to true. */ bool _quit; @@ -1252,5 +1250,7 @@ int normalizeAngle(int angle); int fromSimpleDir(int dirtype, int dir); int toSimpleDir(int dirtype, int dir); +void checkRange(int max, int min, int no, const char *str); + #endif diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index 482e597fbd..2c9ada90ae 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -60,21 +60,6 @@ extern void drawError(char*); Scumm *g_scumm = 0; ScummDebugger *g_debugger; -byte *Scumm::get2byteCharPtr(int idx) { - /* - switch(language) - case korean: - return ( (idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; - case japanese: - ... - case taiwan: - ... - */ - idx = ( (idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; // only for korean - return _2byteFontPtr + 2 * _2byteHeight * idx; -} - - extern NewGui *g_gui; extern uint16 _debugLevel; @@ -753,6 +738,98 @@ Scumm::~Scumm () { delete g_debugger; } +void Scumm::go() { + launch(); + mainRun(); +} + +#pragma mark - +#pragma mark --- Initialization --- +#pragma mark - + +void Scumm::launch() { + gdi._vm = this; + +#ifdef __PALM_OS__ + // PALMOS : check if this value is correct with palm, + // old value 450000 doesn't work anymore (return _fntPtr = NULL in zak256, not tested with others) + // 2500000 is too big and make ScummVM crashes : MemMove to NULL or immediate exit if try to allocate + // memory with new operator + _maxHeapThreshold = 550000; +#else + // Since the new costumes are very big, we increase the heap limit, to avoid having + // to constantly reload stuff from the data files. + if (_features & GF_NEW_COSTUMES) + _maxHeapThreshold = 2500000; + else + _maxHeapThreshold = 550000; +#endif + _minHeapThreshold = 400000; + + _verbRedraw = false; + + allocResTypeData(rtBuffer, MKID('NONE'), 10, "buffer", 0); + initVirtScreen(0, 0, 0, _screenWidth, _screenHeight, false, false); + + setupScummVars(); + + setupOpcodes(); + + if (_version == 8) + _numActors = 80; + else if ((_version == 7) || (_gameId == GID_SAMNMAX)) + _numActors = 30; + else if (_gameId == GID_MANIAC) + _numActors = 25; + else + _numActors = 13; + + if (_version >= 7) + OF_OWNER_ROOM = 0xFF; + else + OF_OWNER_ROOM = 0x0F; + + // if (_gameId==GID_MONKEY2 && _bootParam == 0) + // _bootParam = 10001; + + if (_gameId == GID_INDY4 && _bootParam == 0) { + _bootParam = -7873; + } + + if (_features & GF_OLD_BUNDLE) + _resourceHeaderSize = 4; // FIXME - to be rechecked + else if (_features & GF_SMALL_HEADER) + _resourceHeaderSize = 6; + else + _resourceHeaderSize = 8; + + readIndexFile(); + + scummInit(); + + if (_version > 2) { + if (_version < 7) + VAR(VAR_VERSION) = 21; + + if (_gameId != GID_LOOM && _gameId != GID_INDY3) { + // This is the for the Mac version of Indy3/Loom. TODO: add code to properly + // distinguish the Mac version from the PC (and other) versions. + VAR(VAR_DEBUGMODE) = _debugMode; + } + } + + if (_gameId == GID_MONKEY || _gameId == GID_MONKEY_SEGA) + _scummVars[74] = 1225; + + _sound->setupSound(); + + // If requested, load a save game instead of running the boot script + if (_saveLoadFlag != 2 || !loadState(_saveLoadSlot, _saveLoadCompatible)) { + runScript(1, 0, 0, &_bootParam); + } + _saveLoadFlag = 0; +} + void Scumm::setFeatures (uint32 newFeatures) { bool newCostumes = (_features & GF_NEW_COSTUMES) != 0; bool newNewCostumes = (newFeatures & GF_NEW_COSTUMES) != 0; @@ -998,16 +1075,51 @@ void Scumm::initScummVars() { VAR(VAR_TALK_ACTOR) = 0; } -void Scumm::checkRange(int max, int min, int no, const char *str) const { - if (no < min || no > max) { -#ifdef __PALM_OS__ - char buf[256]; // 1024 is too big overflow the stack -#else - char buf[1024]; -#endif - sprintf(buf, str, no); - error("Value %d is out of bounds (%d,%d) in script %d (%s)", no, min, - max, vm.slot[_curExecScript].number, buf); +#pragma mark - +#pragma mark --- Main loop --- +#pragma mark - + +void Scumm::mainRun() { + int delta = 0; + int diff = _system->get_msecs(); + + while (!_quit) { + + updatePalette(); + _system->update_screen(); + + diff -= _system->get_msecs(); + waitForTimer(delta * 15 + diff); + diff = _system->get_msecs(); + delta = scummLoop(delta); + + if (delta < 1) // Ensure we don't get into a loop + delta = 1; // by not decreasing sleepers. + + if (_quit) { + // TODO: Maybe perform an autosave on exit? + // TODO: Also, we could optionally show a "Do you really want to quit?" dialog here + } + } +} + +void Scumm::waitForTimer(int msec_delay) { + uint32 start_time; + + if (_fastMode & 2) + msec_delay = 0; + else if (_fastMode & 1) + msec_delay = 10; + + start_time = _system->get_msecs(); + + while (!_quit) { + parseEvents(); + + _sound->updateCD(); // Loop CD Audio if needed + if (_system->get_msecs() >= start_time + msec_delay) + break; + _system->delay_msecs(10); } } @@ -1270,7 +1382,315 @@ load_game: } -void Scumm::startScene(int room, Actor * a, int objectNr) { +#pragma mark - +#pragma mark --- Events / Input --- +#pragma mark - + +void Scumm::parseEvents() { + OSystem::Event event; + + while (_system->poll_event(&event)) { + + switch(event.event_code) { + case OSystem::EVENT_KEYDOWN: + if (event.kbd.keycode >= '0' && event.kbd.keycode<='9' + && (event.kbd.flags == OSystem::KBD_ALT || + event.kbd.flags == OSystem::KBD_CTRL)) { + _saveLoadSlot = event.kbd.keycode - '0'; + + // don't overwrite autosave (slot 0) + if (_saveLoadSlot == 0) + _saveLoadSlot = 10; + + sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot); + _saveLoadFlag = (event.kbd.flags == OSystem::KBD_ALT) ? 1 : 2; + _saveLoadCompatible = false; + } else if (event.kbd.flags==OSystem::KBD_CTRL) { + if (event.kbd.keycode == 'f') + _fastMode ^= 1; + else if (event.kbd.keycode == 'g') + _fastMode ^= 2; + else if (event.kbd.keycode == 'd') + g_debugger->attach(this, NULL); + else if (event.kbd.keycode == 's') + resourceStats(); + else + _keyPressed = event.kbd.ascii; // Normal key press, pass on to the game. + } else if (event.kbd.flags & OSystem::KBD_ALT) { + // The result must be 273 for Alt-W + // because that's what MI2 looks for in + // its "instant win" cheat. + _keyPressed = event.kbd.keycode + 154; + } else + _keyPressed = event.kbd.ascii; // Normal key press, pass on to the game. + break; + + case OSystem::EVENT_MOUSEMOVE: + _mouse.x = event.mouse.x; + _mouse.y = event.mouse.y; + _system->set_mouse_pos(event.mouse.x, event.mouse.y); + _system->update_screen(); + break; + + case OSystem::EVENT_LBUTTONDOWN: + _leftBtnPressed |= msClicked|msDown; +#if defined(_WIN32_WCE) || defined(__PALM_OS__) + _mouse.x = event.mouse.x; + _mouse.y = event.mouse.y; +#endif + break; + + case OSystem::EVENT_RBUTTONDOWN: + _rightBtnPressed |= msClicked|msDown; +#if defined(_WIN32_WCE) || defined(__PALM_OS__) + _mouse.x = event.mouse.x; + _mouse.y = event.mouse.y; +#endif + break; + + case OSystem::EVENT_LBUTTONUP: + _leftBtnPressed &= ~msDown; + break; + + case OSystem::EVENT_RBUTTONUP: + _rightBtnPressed &= ~msDown; + break; + + case OSystem::EVENT_QUIT: + _quit = true; + break; + + default: + break; + } + } +} + +void Scumm::clearClickedStatus() { + checkKeyHit(); + _mouseButStat = 0; + _leftBtnPressed &= ~msClicked; + _rightBtnPressed &= ~msClicked; +} + +int Scumm::checkKeyHit() { + int a = _keyPressed; + _keyPressed = 0; + if (_version <= 2 && 315 <= a && a < 315+12) { + // Convert F-Keys + a -= 314; + } + return a; +} + +void Scumm::processKbd() { + int saveloadkey; + getKeyInput(); + + if (_version <= 2) + saveloadkey = 5; // F5 + else if ((_features & GF_OLD256) || (_gameId == GID_CMI) || (_features & GF_16COLOR)) /* FIXME: Support ingame screen ? */ + saveloadkey = 319; // F5 + else + saveloadkey = VAR(VAR_SAVELOADDIALOG_KEY); + + _virtualMouse.x = _mouse.x + virtscr[0].xstart; + + if (_features & GF_NEW_CAMERA) + _virtualMouse.y = _mouse.y + camera._cur.y - (_screenHeight / 2); + else + _virtualMouse.y = _mouse.y; + + _virtualMouse.y -= virtscr[0].topline; + + if (_virtualMouse.y < 0) + _virtualMouse.y = -1; + + if (_virtualMouse.y >= virtscr[0].height) + _virtualMouse.y = -1; + + if (!_lastKeyHit) + return; + + if (_keyScriptNo && (_keyScriptKey == _lastKeyHit)) { + runScript(_keyScriptNo, 0, 0, 0); + return; + } + +#ifdef _WIN32_WCE + if (_lastKeyHit == KEY_SET_OPTIONS) { + //_newgui->optionsDialog(); + return; + } + + if (_lastKeyHit == KEY_ALL_SKIP) { + // Skip cutscene + if (_insaneState) { + _videoFinished = true; + return; + } + else + if (vm.cutScenePtr[vm.cutSceneStackPointer]) + _lastKeyHit = (uint16)VAR(VAR_CUTSCENEEXIT_KEY); + else + // Skip talk + if (_talkDelay > 0) + _lastKeyHit = (uint16)VAR(VAR_TALKSTOP_KEY); + else + // Escape + _lastKeyHit = 27; + } +#endif + + if (VAR_RESTART_KEY != 0xFF && _lastKeyHit == VAR(VAR_RESTART_KEY)) { + warning("Restart not implemented"); + //restart(); + return; + } + + if ((VAR_PAUSE_KEY != 0xFF && _lastKeyHit == VAR(VAR_PAUSE_KEY)) || + (VAR_PAUSE_KEY == 0xFF && _lastKeyHit == ' ')) { + pauseGame(); + return; + } + + if (_lastKeyHit == VAR(VAR_CUTSCENEEXIT_KEY) || + (VAR(VAR_CUTSCENEEXIT_KEY) == 4 && _lastKeyHit == 27)) { + if (_insaneState) { + _videoFinished = true; + } else + abortCutscene(); + } else if (_lastKeyHit == saveloadkey && _currentRoom != 0) { + if (VAR_SAVELOAD_SCRIPT != 0xFF) + runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0); + + saveloadDialog(); // Display NewGui + + if (VAR_SAVELOAD_SCRIPT2 != 0xFF) + runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0); + return; + } else if (VAR_TALKSTOP_KEY != 0xFF && _lastKeyHit == VAR(VAR_TALKSTOP_KEY)) { + _talkDelay = 0; + if (_sound->_sfxMode & 2) + stopTalk(); + return; + } else if (_lastKeyHit == '[') { // [ Music volume down + int vol = _sound->_sound_volume_music; + if (!(vol & 0xF) && vol) + vol -= 16; + vol = vol & 0xF0; + _sound->_sound_volume_music = vol; + if (_imuse) + _imuse->set_music_volume (vol); + } else if (_lastKeyHit == ']') { // ] Music volume up + int vol = _sound->_sound_volume_music; + vol = (vol + 16) & 0xFF0; + if (vol > 255) vol = 255; + _sound->_sound_volume_music = vol; + if (_imuse) + _imuse->set_music_volume (vol); + } else if (_lastKeyHit == '-') { // - text speed down + _defaultTalkDelay += 5; + if (_defaultTalkDelay > 90) + _defaultTalkDelay = 90; + + VAR(VAR_CHARINC) = _defaultTalkDelay / 20; + } else if (_lastKeyHit == '+') { // + text speed up + _defaultTalkDelay -= 5; + if (_defaultTalkDelay < 5) + _defaultTalkDelay = 5; + + VAR(VAR_CHARINC) = _defaultTalkDelay / 20; + } else if (_lastKeyHit == '~' || _lastKeyHit == '#') { // Debug console + g_debugger->attach(this, NULL); + } else if (_version <= 2) { + // Store the input type. So far we can't distinguish + // between 1, 3 and 5. + // 1) Verb 2) Scene 3) Inv. 4) Key + // 5) Sentence Bar + + if (_lastKeyHit) { // Key Input + VAR(VAR_KEYPRESS) = _lastKeyHit; + } + } + + _mouseButStat = _lastKeyHit; +} + +int Scumm::getKeyInput() { + _mouseButStat = 0; + + _lastKeyHit = checkKeyHit(); + convertKeysToClicks(); + + if (_mouse.x < 0) + _mouse.x = 0; + if (_mouse.x > _screenWidth-1) + _mouse.x = _screenWidth-1; + if (_mouse.y < 0) + _mouse.y = 0; + if (_mouse.y > _screenHeight-1) + _mouse.y = _screenHeight-1; + + if (_leftBtnPressed & msClicked && _rightBtnPressed & msClicked) { + _mouseButStat = 0; + _lastKeyHit = (uint)VAR(VAR_CUTSCENEEXIT_KEY); + } else if (_leftBtnPressed & msClicked) { + _mouseButStat = MBS_LEFT_CLICK; + } else if (_rightBtnPressed & msClicked) { + _mouseButStat = MBS_RIGHT_CLICK; + } + + if (_version == 8) { + VAR(VAR_MOUSE_BUTTONS) = 0; + VAR(VAR_MOUSE_HOLD) = 0; + VAR(VAR_RIGHTBTN_HOLD) = 0; + + if (_leftBtnPressed & msClicked) + VAR(VAR_MOUSE_BUTTONS) += 1; + + if (_rightBtnPressed & msClicked) + VAR(VAR_MOUSE_BUTTONS) += 2; + + if (_leftBtnPressed & msDown) + VAR(VAR_MOUSE_HOLD) += 1; + + if (_rightBtnPressed & msDown) { + VAR(VAR_RIGHTBTN_HOLD) = 1; + VAR(VAR_MOUSE_HOLD) += 2; + } + } else if (_version == 7) { + VAR(VAR_LEFTBTN_HOLD) = (_leftBtnPressed & msDown) != 0; + VAR(VAR_RIGHTBTN_HOLD) = (_rightBtnPressed & msDown) != 0; + } + + _leftBtnPressed &= ~msClicked; + _rightBtnPressed &= ~msClicked; + + return _lastKeyHit; +} + +void Scumm::convertKeysToClicks() { + if (_lastKeyHit && _cursor.state > 0) { + if (_lastKeyHit == 9) { + _mouseButStat = MBS_RIGHT_CLICK; + } else if (_lastKeyHit == 13) { + _mouseButStat = MBS_LEFT_CLICK; + } else + return; + _lastKeyHit = 0; + } +} + +#pragma mark - +#pragma mark --- SCUMM --- +#pragma mark - + +/** + * Start a 'scene' by loading the specified room with the given main actor. + * The actor is placed next to the object indicated by objectNr. + */ +void Scumm::startScene(int room, Actor *a, int objectNr) { int i, where; CHECK_HEAP; @@ -1427,7 +1847,7 @@ void Scumm::startScene(int room, Actor * a, int objectNr) { // The DIG; and nothing like this is done there. Also I am pretty // sure this used to work in 0.3.1. So apparently something broke // down here, and I have no clue what that might be :-/ - a-> adjustActorPos(); + a->adjustActorPos(); } if (camera._follows) { a = derefActor(camera._follows, "startScene: follows"); @@ -1783,105 +2203,54 @@ void Scumm::initRoomSubBlocks() { initBGBuffers(_roomHeight); } -/* - FIXME: It seems that scale items and scale slots are the same thing after - all - they only differ in some details (scale item is used to precompute - a scale table, while for the scale slots the computations are done on the - fly; also for scale slots, the scale along the x axis can vary, too). - - Now, there are various known scale glitches in FT (and apparently also - in The Dig, see FIXME comments in Actor::setupActorScale). In this context - it is very interesting that for V5, there is an opcode which invokes - setScaleItem, and for V8 one that invokes setScaleSlot. But there is no - such opcode to be found for V6/V7 games. - - Hypothesis: we simple are missing this opcode, and implementing it might - fix some or all of the Dig/FT scaling issues. -*/ -void Scumm::setScaleItem(int slot, int y1, int scale1, int y2, int scale2) { - byte *ptr; - int y, tmp; - - if (y1 == y2) - return; - - ptr = createResource(rtScaleTable, slot, 200); - - for (y = 0; y < 200; y++) { - tmp = ((scale2 - scale1) * (y - y1)) / (y2 - y1) + scale1; - if (tmp < 1) - tmp = 1; - if (tmp > 255) - tmp = 255; - *ptr++ = tmp; - } +void Scumm::pauseGame() { + pauseDialog(); } -void Scumm::setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2) { - assert(1 <= slot && slot <= 20); - _scaleSlots[slot-1].x2 = x2; - _scaleSlots[slot-1].y2 = y2; - _scaleSlots[slot-1].scale2 = scale2; - _scaleSlots[slot-1].x1 = x1; - _scaleSlots[slot-1].y1 = y1; - _scaleSlots[slot-1].scale1 = scale1; +void Scumm::shutDown() { + _quit = true; } -void Scumm::dumpResource(const char *tag, int idx, const byte *ptr, int length) { - char buf[256]; - File out; +void Scumm::restart() { +// TODO: Check this function - we should probably be reinitting a lot more stuff, and I suspect +// this leaks memory like a sieve - uint32 size; - if (length >= 0) - size = length; - else if (_features & GF_OLD_BUNDLE) - size = READ_LE_UINT16(ptr); - else if (_features & GF_SMALL_HEADER) - size = READ_LE_UINT32(ptr); - else - size = READ_BE_UINT32(ptr + 4); + int i; -#if defined(MACOS_CARBON) - sprintf(buf, ":dumps:%s%d.dmp", tag, idx); -#else - sprintf(buf, "dumps/%s%d.dmp", tag, idx); -#endif + // Reset some stuff + _currentRoom = 0; + _currentScript = 0xFF; + killAllScriptsExceptCurrent(); + setShake(0); + _sound->stopAllSounds(); - out.open(buf, "", 1); - if (out.isOpen() == false) { - out.open(buf, "", 2); - if (out.isOpen() == false) - return; - out.write(ptr, size); - } - out.close(); -} + // Empty variables + for (i=0;i<255;i++) + _scummVars[i] = 0; -void Scumm::clearClickedStatus() { - checkKeyHit(); - _mouseButStat = 0; - _leftBtnPressed &= ~msClicked; - _rightBtnPressed &= ~msClicked; -} + // Empty inventory + for (i=0;i<_numGlobalObjects;i++) + clearOwnerOf(i); -int Scumm::checkKeyHit() { - int a = _keyPressed; - _keyPressed = 0; - if (_version <= 2 && 315 <= a && a < 315+12) { - // Convert F-Keys - a -= 314; - } - return a; -} + // Reinit things + allocateArrays(); // Reallocate arrays + readIndexFile(); // Reread index (reset objectstate etc) + createResource(rtTemp, 6, 500); // Create temp buffer + initScummVars(); // Reinit scumm variables + _sound->setupSound(); // Reinit sound engine -void Scumm::pauseGame() { - pauseDialog(); + // Re-run bootscript + runScript(1, 0, 0, &_bootParam); } -void Scumm::setOptions() { - //_newgui->optionsDialog(); +void Scumm::startManiac() { + warning("stub startManiac()"); } +#pragma mark - +#pragma mark --- GUI --- +#pragma mark - + int Scumm::runDialog(Dialog *dialog) { // Pause sound put bool old_soundsPaused = _sound->_soundsPaused; @@ -1944,336 +2313,24 @@ char Scumm::displayError(bool showCancel, const char *message, ...) { return result; } -void Scumm::shutDown() { - _quit = true; -} - -void Scumm::restart() { -// TODO: Check this function - we should probably be reinitting a lot more stuff, and I suspect -// this leaks memory like a sieve - - int i; - - // Reset some stuff - _currentRoom = 0; - _currentScript = 0xFF; - killAllScriptsExceptCurrent(); - setShake(0); - _sound->stopAllSounds(); - - // Empty variables - for (i=0;i<255;i++) - _scummVars[i] = 0; - - // Empty inventory - for (i=0;i<_numGlobalObjects;i++) - clearOwnerOf(i); - - // Reinit things - allocateArrays(); // Reallocate arrays - readIndexFile(); // Reread index (reset objectstate etc) - createResource(rtTemp, 6, 500); // Create temp buffer - initScummVars(); // Reinit scumm variables - _sound->setupSound(); // Reinit sound engine - - // Re-run bootscript - runScript(1, 0, 0, &_bootParam); -} - -void Scumm::processKbd() { - int saveloadkey; - getKeyInput(); - - if (_version <= 2) - saveloadkey = 5; // F5 - else if ((_features & GF_OLD256) || (_gameId == GID_CMI) || (_features & GF_16COLOR)) /* FIXME: Support ingame screen ? */ - saveloadkey = 319; // F5 - else - saveloadkey = VAR(VAR_SAVELOADDIALOG_KEY); - - _virtualMouse.x = _mouse.x + virtscr[0].xstart; - - if (_features & GF_NEW_CAMERA) - _virtualMouse.y = _mouse.y + camera._cur.y - (_screenHeight / 2); - else - _virtualMouse.y = _mouse.y; - - _virtualMouse.y -= virtscr[0].topline; - - if (_virtualMouse.y < 0) - _virtualMouse.y = -1; - - if (_virtualMouse.y >= virtscr[0].height) - _virtualMouse.y = -1; - - if (!_lastKeyHit) - return; - - if (_keyScriptNo && (_keyScriptKey == _lastKeyHit)) { - runScript(_keyScriptNo, 0, 0, 0); - return; - } - - if (_lastKeyHit == KEY_SET_OPTIONS) { - setOptions(); - return; - } - - if (_lastKeyHit == KEY_ALL_SKIP) { - // Skip cutscene - if (_insaneState) { - _videoFinished = true; - return; - } - else - if (vm.cutScenePtr[vm.cutSceneStackPointer]) - _lastKeyHit = (uint16)VAR(VAR_CUTSCENEEXIT_KEY); - else - // Skip talk - if (_talkDelay > 0) - _lastKeyHit = (uint16)VAR(VAR_TALKSTOP_KEY); - else - // Escape - _lastKeyHit = 27; - } - - if (VAR_RESTART_KEY != 0xFF && _lastKeyHit == VAR(VAR_RESTART_KEY)) { - warning("Restart not implemented"); - //restart(); - return; - } - - if ((VAR_PAUSE_KEY != 0xFF && _lastKeyHit == VAR(VAR_PAUSE_KEY)) || - (VAR_PAUSE_KEY == 0xFF && _lastKeyHit == ' ')) { - pauseGame(); - return; - } - - if (_lastKeyHit == VAR(VAR_CUTSCENEEXIT_KEY) || - (VAR(VAR_CUTSCENEEXIT_KEY) == 4 && _lastKeyHit == 27)) { - if (_insaneState) { - _videoFinished = true; - } else - abortCutscene(); - } else if (_lastKeyHit == saveloadkey && _currentRoom != 0) { - if (VAR_SAVELOAD_SCRIPT != 0xFF) - runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0); - - saveloadDialog(); // Display NewGui - - if (VAR_SAVELOAD_SCRIPT2 != 0xFF) - runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0); - return; - } else if (VAR_TALKSTOP_KEY != 0xFF && _lastKeyHit == VAR(VAR_TALKSTOP_KEY)) { - _talkDelay = 0; - if (_sound->_sfxMode & 2) - stopTalk(); - return; - } else if (_lastKeyHit == '[') { // [ Music volume down - int vol = _sound->_sound_volume_music; - if (!(vol & 0xF) && vol) - vol -= 16; - vol = vol & 0xF0; - _sound->_sound_volume_music = vol; - if (_imuse) - _imuse->set_music_volume (vol); - } else if (_lastKeyHit == ']') { // ] Music volume up - int vol = _sound->_sound_volume_music; - vol = (vol + 16) & 0xFF0; - if (vol > 255) vol = 255; - _sound->_sound_volume_music = vol; - if (_imuse) - _imuse->set_music_volume (vol); - } else if (_lastKeyHit == '-') { // - text speed down - _defaultTalkDelay += 5; - if (_defaultTalkDelay > 90) - _defaultTalkDelay = 90; - - VAR(VAR_CHARINC) = _defaultTalkDelay / 20; - } else if (_lastKeyHit == '+') { // + text speed up - _defaultTalkDelay -= 5; - if (_defaultTalkDelay < 5) - _defaultTalkDelay = 5; - - VAR(VAR_CHARINC) = _defaultTalkDelay / 20; - } else if (_lastKeyHit == '~' || _lastKeyHit == '#') { // Debug console - g_debugger->attach(this, NULL); - } else if (_version <= 2) { - // Store the input type. So far we can't distinguish - // between 1, 3 and 5. - // 1) Verb 2) Scene 3) Inv. 4) Key - // 5) Sentence Bar - - if (_lastKeyHit) { // Key Input - VAR(VAR_KEYPRESS) = _lastKeyHit; - } - } - - _mouseButStat = _lastKeyHit; -} - -int Scumm::getKeyInput() { - _mouseButStat = 0; - - _lastKeyHit = checkKeyHit(); - convertKeysToClicks(); - - if (_mouse.x < 0) - _mouse.x = 0; - if (_mouse.x > _screenWidth-1) - _mouse.x = _screenWidth-1; - if (_mouse.y < 0) - _mouse.y = 0; - if (_mouse.y > _screenHeight-1) - _mouse.y = _screenHeight-1; - - if (_leftBtnPressed & msClicked && _rightBtnPressed & msClicked) { - _mouseButStat = 0; - _lastKeyHit = (uint)VAR(VAR_CUTSCENEEXIT_KEY); - } else if (_leftBtnPressed & msClicked) { - _mouseButStat = MBS_LEFT_CLICK; - } else if (_rightBtnPressed & msClicked) { - _mouseButStat = MBS_RIGHT_CLICK; - } - - if (_version == 8) { - VAR(VAR_MOUSE_BUTTONS) = 0; - VAR(VAR_MOUSE_HOLD) = 0; - VAR(VAR_RIGHTBTN_HOLD) = 0; - - if (_leftBtnPressed & msClicked) - VAR(VAR_MOUSE_BUTTONS) += 1; - - if (_rightBtnPressed & msClicked) - VAR(VAR_MOUSE_BUTTONS) += 2; - - if (_leftBtnPressed & msDown) - VAR(VAR_MOUSE_HOLD) += 1; - - if (_rightBtnPressed & msDown) { - VAR(VAR_RIGHTBTN_HOLD) = 1; - VAR(VAR_MOUSE_HOLD) += 2; - } - } else if (_version == 7) { - VAR(VAR_LEFTBTN_HOLD) = (_leftBtnPressed & msDown) != 0; - VAR(VAR_RIGHTBTN_HOLD) = (_rightBtnPressed & msDown) != 0; - } - - _leftBtnPressed &= ~msClicked; - _rightBtnPressed &= ~msClicked; - - return _lastKeyHit; -} - -void Scumm::convertKeysToClicks() { - if (_lastKeyHit && _cursor.state > 0) { - if (_lastKeyHit == 9) { - _mouseButStat = MBS_RIGHT_CLICK; - } else if (_lastKeyHit == 13) { - _mouseButStat = MBS_LEFT_CLICK; - } else - return; - _lastKeyHit = 0; - } -} - -Actor *Scumm::derefActor(int id, const char *errmsg) const { - if (id < 1 || id >= _numActors || _actors[id].number != id) { - if (errmsg) - error("Invalid actor %d in %s", id, errmsg); - else - error("Invalid actor %d", id); - } - return &_actors[id]; -} - -Actor *Scumm::derefActorSafe(int id, const char *errmsg) const { - if (id < 1 || id >= _numActors || _actors[id].number != id) { - debug(2, "Invalid actor %d in %s (script %d, opcode 0x%x) - This is potentially a BIG problem.", - id, errmsg, vm.slot[_curExecScript].number, _opcode); - return NULL; - } - return &_actors[id]; -} - -void Scumm::setStringVars(int slot) { - StringTab *st = &_string[slot]; - st->xpos = st->t_xpos; - st->ypos = st->t_ypos; - st->center = st->t_center; - st->overhead = st->t_overhead; - st->no_talk_anim = st->t_no_talk_anim; - st->right = st->t_right; - st->color = st->t_color; - st->charset = st->t_charset; -} - -void Scumm::startManiac() { - warning("stub startManiac()"); -} - -// -// Convert an old style direction to a new style one (angle), -// -int newDirToOldDir(int dir) { - if (dir >= 71 && dir <= 109) - return 1; - if (dir >= 109 && dir <= 251) - return 2; - if (dir >= 251 && dir <= 289) - return 0; - return 3; -} - -// -// Convert an new style (angle) direction to an old style one. -// -int oldDirToNewDir(int dir) { - assert(0 <= dir && dir <= 3); - const int new_dir_table[4] = { 270, 90, 180, 0 }; - return new_dir_table[dir]; -} +#pragma mark - +#pragma mark --- Miscellaneous --- +#pragma mark - -// -// Convert an angle to a simple direction. -// -int toSimpleDir(int dirType, int dir) { - if (dirType) { - const int16 directions[] = { 22, 72, 107, 157, 202, 252, 287, 337 }; - for (int i = 0; i < 7; i++) - if (dir >= directions[i] && dir <= directions[i+1]) - return i+1; - } else { - const int16 directions[] = { 71, 109, 251, 289 }; - for (int i = 0; i < 3; i++) - if (dir >= directions[i] && dir <= directions[i+1]) - return i+1; - } - - return 0; +byte *Scumm::get2byteCharPtr(int idx) { + /* + switch(language) + case korean: + return ( (idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; + case japanese: + ... + case taiwan: + ... + */ + idx = ( (idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; // only for korean + return _2byteFontPtr + 2 * _2byteHeight * idx; } -// -// Convert a simple direction to an angle -// -int fromSimpleDir(int dirType, int dir) { - if (dirType) - return dir * 45; - else - return dir * 90; -} - -// -// Normalize the given angle - that means, ensure it is positive, and -// change it to the closest multiple of 45 degree by abusing toSimpleDir. -// -int normalizeAngle(int angle) { - int temp; - - temp = (angle + 360) % 360; - - return toSimpleDir(1, temp) * 45; -} const char *Scumm::getGameDataPath() const { #ifdef MACOSX @@ -2322,265 +2379,82 @@ void Scumm::errorString(const char *buf1, char *buf2) { } } -void Scumm::waitForTimer(int msec_delay) { - uint32 start_time; - - if (_fastMode & 2) - msec_delay = 0; - else if (_fastMode & 1) - msec_delay = 10; - - start_time = _system->get_msecs(); - - while (!_quit) { - parseEvents(); - - _sound->updateCD(); // Loop CD Audio if needed - if (_system->get_msecs() >= start_time + msec_delay) - break; - _system->delay_msecs(10); - } -} - -void Scumm::parseEvents() { - OSystem::Event event; - - while (_system->poll_event(&event)) { - - switch(event.event_code) { - case OSystem::EVENT_KEYDOWN: - if (event.kbd.keycode >= '0' && event.kbd.keycode<='9' - && (event.kbd.flags == OSystem::KBD_ALT || - event.kbd.flags == OSystem::KBD_CTRL)) { - _saveLoadSlot = event.kbd.keycode - '0'; - - // don't overwrite autosave (slot 0) - if (_saveLoadSlot == 0) - _saveLoadSlot = 10; - - sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot); - _saveLoadFlag = (event.kbd.flags == OSystem::KBD_ALT) ? 1 : 2; - _saveLoadCompatible = false; - } else if (event.kbd.flags==OSystem::KBD_CTRL) { - if (event.kbd.keycode == 'f') - _fastMode ^= 1; - else if (event.kbd.keycode == 'g') - _fastMode ^= 2; - else if (event.kbd.keycode == 'd') - g_debugger->attach(this, NULL); - else if (event.kbd.keycode == 's') - resourceStats(); - else - _keyPressed = event.kbd.ascii; // Normal key press, pass on to the game. - } else if (event.kbd.flags & OSystem::KBD_ALT) { - // The result must be 273 for Alt-W - // because that's what MI2 looks for in - // its "instant win" cheat. - _keyPressed = event.kbd.keycode + 154; - } else - _keyPressed = event.kbd.ascii; // Normal key press, pass on to the game. - break; - - case OSystem::EVENT_MOUSEMOVE: - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - _system->set_mouse_pos(event.mouse.x, event.mouse.y); - _system->update_screen(); - break; - - case OSystem::EVENT_LBUTTONDOWN: - _leftBtnPressed |= msClicked|msDown; -#if defined(_WIN32_WCE) || defined(__PALM_OS__) - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; -#endif - break; +#pragma mark - +#pragma mark --- Utilities --- +#pragma mark - - case OSystem::EVENT_RBUTTONDOWN: - _rightBtnPressed |= msClicked|msDown; -#if defined(_WIN32_WCE) || defined(__PALM_OS__) - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; +void checkRange(int max, int min, int no, const char *str) { + if (no < min || no > max) { +#ifdef __PALM_OS__ + char buf[256]; // 1024 is too big overflow the stack +#else + char buf[1024]; #endif - break; - - case OSystem::EVENT_LBUTTONUP: - _leftBtnPressed &= ~msDown; - break; - - case OSystem::EVENT_RBUTTONUP: - _rightBtnPressed &= ~msDown; - break; - - case OSystem::EVENT_QUIT: - _quit = true; - break; - - default: - break; - } + sprintf(buf, str, no); + error("Value %d is out of bounds (%d,%d) (%s)", no, min, max, buf); } } -void Scumm::updatePalette() { - if (_palDirtyMax == -1) - return; - - bool noir_mode = (_gameId == GID_SAMNMAX && readVar(0x8000)); - int first = _palDirtyMin; - int num = _palDirtyMax - first + 1; - int i; - - byte palette_colors[1024]; - byte *p = palette_colors; - - for (i = _palDirtyMin; i <= _palDirtyMax; i++) { - byte *data; - - if (_features & GF_SMALL_HEADER) - data = _currentPalette + _shadowPalette[i] * 3; - else - data = _currentPalette + i * 3; - - // Sam & Max film noir mode. Convert the colours to grayscale - // before uploading them to the backend. - - if (noir_mode) { - int r, g, b; - byte brightness; - - r = data[0]; - g = data[1]; - b = data[2]; - - brightness = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5); - - *p++ = brightness; - *p++ = brightness; - *p++ = brightness; - *p++ = 0; - } else { - *p++ = data[0]; - *p++ = data[1]; - *p++ = data[2]; - *p++ = 0; - } - } - - _system->set_palette(palette_colors, first, num); - - _palDirtyMax = -1; - _palDirtyMin = 256; +/** + * Convert an old style direction to a new style one (angle), + */ +int newDirToOldDir(int dir) { + if (dir >= 71 && dir <= 109) + return 1; + if (dir >= 109 && dir <= 251) + return 2; + if (dir >= 251 && dir <= 289) + return 0; + return 3; } -void Scumm::mainRun() { - int delta = 0; - int diff = _system->get_msecs(); - - while (!_quit) { - - updatePalette(); - _system->update_screen(); - - diff -= _system->get_msecs(); - waitForTimer(delta * 15 + diff); - diff = _system->get_msecs(); - delta = scummLoop(delta); - - if (delta < 1) // Ensure we don't get into a loop - delta = 1; // by not decreasing sleepers. - - if (_quit) { - // TODO: Maybe perform an autosave on exit? - // TODO: Also, we could optionally show a "Do you really want to quit?" dialog here - } - } +/** + * Convert an new style (angle) direction to an old style one. + */ +int oldDirToNewDir(int dir) { + assert(0 <= dir && dir <= 3); + const int new_dir_table[4] = { 270, 90, 180, 0 }; + return new_dir_table[dir]; } -void Scumm::launch() { - gdi._vm = this; - -#ifdef __PALM_OS__ - // PALMOS : check if this value is correct with palm, - // old value 450000 doesn't work anymore (return _fntPtr = NULL in zak256, not tested with others) - // 2500000 is too big and make ScummVM crashes : MemMove to NULL or immediate exit if try to allocate - // memory with new operator - _maxHeapThreshold = 550000; -#else - // Since the new costumes are very big, we increase the heap limit, to avoid having - // to constantly reload stuff from the data files. - if (_features & GF_NEW_COSTUMES) - _maxHeapThreshold = 2500000; - else - _maxHeapThreshold = 550000; -#endif - _minHeapThreshold = 400000; - - _verbRedraw = false; - - allocResTypeData(rtBuffer, MKID('NONE'), 10, "buffer", 0); - initVirtScreen(0, 0, 0, _screenWidth, _screenHeight, false, false); - - setupScummVars(); - - setupOpcodes(); - - if (_version == 8) - _numActors = 80; - else if ((_version == 7) || (_gameId == GID_SAMNMAX)) - _numActors = 30; - else if (_gameId == GID_MANIAC) - _numActors = 25; - else - _numActors = 13; - - if (_version >= 7) - OF_OWNER_ROOM = 0xFF; - else - OF_OWNER_ROOM = 0x0F; - - // if (_gameId==GID_MONKEY2 && _bootParam == 0) - // _bootParam = 10001; - - if (_gameId == GID_INDY4 && _bootParam == 0) { - _bootParam = -7873; +/** + * Convert an angle to a simple direction. + */ +int toSimpleDir(int dirType, int dir) { + if (dirType) { + const int16 directions[] = { 22, 72, 107, 157, 202, 252, 287, 337 }; + for (int i = 0; i < 7; i++) + if (dir >= directions[i] && dir <= directions[i+1]) + return i+1; + } else { + const int16 directions[] = { 71, 109, 251, 289 }; + for (int i = 0; i < 3; i++) + if (dir >= directions[i] && dir <= directions[i+1]) + return i+1; } - if (_features & GF_OLD_BUNDLE) - _resourceHeaderSize = 4; // FIXME - to be rechecked - else if (_features & GF_SMALL_HEADER) - _resourceHeaderSize = 6; - else - _resourceHeaderSize = 8; - - readIndexFile(); - - scummInit(); + return 0; +} - if (_version > 2) { - if (_version < 7) - VAR(VAR_VERSION) = 21; - - if (_gameId != GID_LOOM && _gameId != GID_INDY3) { - // This is the for the Mac version of Indy3/Loom. TODO: add code to properly - // distinguish the Mac version from the PC (and other) versions. - VAR(VAR_DEBUGMODE) = _debugMode; - } - } +/** + * Convert a simple direction to an angle. + */ +int fromSimpleDir(int dirType, int dir) { + if (dirType) + return dir * 45; + else + return dir * 90; +} - if (_gameId == GID_MONKEY || _gameId == GID_MONKEY_SEGA) - _scummVars[74] = 1225; +/** + * Normalize the given angle - that means, ensure it is positive, and + * change it to the closest multiple of 45 degree by abusing toSimpleDir. + */ +int normalizeAngle(int angle) { + int temp; - _sound->setupSound(); + temp = (angle + 360) % 360; - // If requested, load a save game instead of running the boot script - if (_saveLoadFlag != 2 || !loadState(_saveLoadSlot, _saveLoadCompatible)) { - runScript(1, 0, 0, &_bootParam); - } - _saveLoadFlag = 0; + return toSimpleDir(1, temp) * 45; } -void Scumm::go() { - launch(); - mainRun(); -} diff --git a/scumm/string.cpp b/scumm/string.cpp index 670465345d..2697455bf3 100644 --- a/scumm/string.cpp +++ b/scumm/string.cpp @@ -28,6 +28,18 @@ #include "verbs.h" #include "scumm/sound.h" +void Scumm::setStringVars(int slot) { + StringTab *st = &_string[slot]; + st->xpos = st->t_xpos; + st->ypos = st->t_ypos; + st->center = st->t_center; + st->overhead = st->t_overhead; + st->no_talk_anim = st->t_no_talk_anim; + st->right = st->t_right; + st->color = st->t_color; + st->charset = st->t_charset; +} + void Scumm::unkMessage1() { byte buffer[100]; _msgPtrToAdd = buffer; |