aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorTravis Howell2009-06-06 00:10:40 +0000
committerTravis Howell2009-06-06 00:10:40 +0000
commit8ff3a568fa8fe564749080a9af5e20b897933d93 (patch)
tree3136763937adc1fb6bcd30993b00d1476f490b6f /engines
parentd65bbe1d7a5efbcf04831dbb68a45ca833db1ae1 (diff)
parentda36901b0751b9d4faaae30dce230b67d75e04e6 (diff)
downloadscummvm-rg350-8ff3a568fa8fe564749080a9af5e20b897933d93.tar.gz
scummvm-rg350-8ff3a568fa8fe564749080a9af5e20b897933d93.tar.bz2
scummvm-rg350-8ff3a568fa8fe564749080a9af5e20b897933d93.zip
Merged revisions 41154-41156,41160,41163-41181,41185-41186,41188-41189,41196-41202 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk ........ r41154 | thebluegr | 2009-06-04 18:25:48 +1000 (Thu, 04 Jun 2009) | 1 line Turned debug_weak_validations on by default again, as apparently some games like SQ3 fail in some validations (e.g. when loading). Also, fixed a potential out of bounds access when copying the value of __FILE__ into a buffer (as its value can be quite long in some cases). ........ r41155 | thebluegr | 2009-06-04 18:28:20 +1000 (Thu, 04 Jun 2009) | 1 line Reordered the numpad keys so that they make more sense, and simplified the code which returns the values of shifted function keys ........ r41156 | djwillis | 2009-06-04 18:30:31 +1000 (Thu, 04 Jun 2009) | 1 line Initial import of the GP2XWiz backend (based on the GP2X and SDL backends). Includes configure changes and one #ifdef to SDL backend. Also updates NEWS. ........ r41160 | strangerke | 2009-06-04 19:48:56 +1000 (Thu, 04 Jun 2009) | 1 line gob : _spriteBottom incorrectly saved and restored in Draw_v2::spriteOperation ........ r41163 | fingolfin | 2009-06-04 21:28:05 +1000 (Thu, 04 Jun 2009) | 1 line SCI: Renamed various debug related global variables to have a g_ prefix; and moved any 'extern' decls of them into a new header file ........ r41164 | waltervn | 2009-06-04 21:35:17 +1000 (Thu, 04 Jun 2009) | 2 lines SCI: Support for 16-bit DPCM. ........ r41165 | fingolfin | 2009-06-04 21:44:55 +1000 (Thu, 04 Jun 2009) | 1 line SCI: cleanup ........ r41166 | fingolfin | 2009-06-04 21:45:17 +1000 (Thu, 04 Jun 2009) | 1 line SCI: Moved MemObject code into a separate source file ........ r41167 | fingolfin | 2009-06-04 21:45:34 +1000 (Thu, 04 Jun 2009) | 1 line Code formatting in the gp2xwiz backend ........ r41168 | thebluegr | 2009-06-04 22:47:11 +1000 (Thu, 04 Jun 2009) | 1 line Updated the MSVC project files of the SCI engine ........ r41169 | waltervn | 2009-06-05 00:29:20 +1000 (Fri, 05 Jun 2009) | 2 lines SCI: Message: Added support for escape sequences. ........ r41170 | waltervn | 2009-06-05 01:56:11 +1000 (Fri, 05 Jun 2009) | 2 lines SCI: Added support for early SCI1.1 audio maps. ........ r41171 | waltervn | 2009-06-05 02:18:35 +1000 (Fri, 05 Jun 2009) | 2 lines SCI: Audio: Fixed bug in reading of SOL header. ........ r41172 | fingolfin | 2009-06-05 06:50:51 +1000 (Fri, 05 Jun 2009) | 1 line SCI: Added FIXME comment to not_register() ........ r41173 | fingolfin | 2009-06-05 06:51:09 +1000 (Fri, 05 Jun 2009) | 1 line SCI: cleanup ........ r41174 | fingolfin | 2009-06-05 06:51:24 +1000 (Fri, 05 Jun 2009) | 1 line SCI: Slightly modified kAddAfter so that it does not modify its arguments needlessly ........ r41175 | fingolfin | 2009-06-05 06:51:40 +1000 (Fri, 05 Jun 2009) | 1 line SCI: Added MemObject::isValidOffset method; use it to simplify determine_reg_type ........ r41176 | fingolfin | 2009-06-05 07:42:24 +1000 (Fri, 05 Jun 2009) | 1 line SCI: Renamed _kfuncTable -> _kernelFuncs; and simplified/streamlined the kernel func map in kernel.cpp a bit ........ r41177 | fingolfin | 2009-06-05 07:44:39 +1000 (Fri, 05 Jun 2009) | 1 line SCI: Renamed EngineState::flags and version to _flags and _version (following our conventions); also slightly changed the EngineState constructor to init _version & _flags, and used this to make them constant ........ r41178 | fingolfin | 2009-06-05 07:53:45 +1000 (Fri, 05 Jun 2009) | 1 line oops ........ r41179 | athrxx | 2009-06-05 08:12:13 +1000 (Fri, 05 Jun 2009) | 1 line LOL: implemented Vaelan's cube ........ r41180 | fingolfin | 2009-06-05 08:16:31 +1000 (Fri, 05 Jun 2009) | 1 line SCI: Made some members of class Resource protected; some cleanup ........ r41181 | waltervn | 2009-06-05 09:55:08 +1000 (Fri, 05 Jun 2009) | 3 lines SCI: Fixed some endian bugs related to speech handling. READ_UINT* are not LE, but use native endianness. Thanks to clone2727 for pointing this out. ........ r41185 | Kirben | 2009-06-05 10:57:58 +1000 (Fri, 05 Jun 2009) | 1 line Update sound code in HE80+ games, for sound rate differences. ........ r41186 | waltervn | 2009-06-05 11:12:52 +1000 (Fri, 05 Jun 2009) | 2 lines SCI: Audio: Fixed bug in sample length computation. ........ r41188 | Kirben | 2009-06-05 12:35:38 +1000 (Fri, 05 Jun 2009) | 1 line Fix issues selecting some items in arttime and football. ........ r41189 | Kirben | 2009-06-05 14:16:32 +1000 (Fri, 05 Jun 2009) | 1 line Minor cleanup. ........ r41196 | dreammaster | 2009-06-05 22:20:42 +1000 (Fri, 05 Jun 2009) | 1 line Tweaks to the code that pauses for a mouse press when displaying many text messages ........ r41197 | thebluegr | 2009-06-06 04:05:45 +1000 (Sat, 06 Jun 2009) | 1 line Removed some unused code and performed some cleanup ........ r41198 | thebluegr | 2009-06-06 05:04:14 +1000 (Sat, 06 Jun 2009) | 1 line Moved some more debug commands to ScummVM's coneole and removed some unused code ........ r41199 | athrxx | 2009-06-06 07:34:18 +1000 (Sat, 06 Jun 2009) | 1 line LOL: implemented another opcode ........ r41200 | mthreepwood | 2009-06-06 08:35:13 +1000 (Sat, 06 Jun 2009) | 1 line Make the PlayStation's abbreviation to all lower-case for consistency and change the description from Playstation to Sony PlayStation ........ r41201 | athrxx | 2009-06-06 08:53:36 +1000 (Sat, 06 Jun 2009) | 1 line LOL: minor bug fix ........ r41202 | thebluegr | 2009-06-06 09:08:35 +1000 (Sat, 06 Jun 2009) | 1 line Cleanup ........ svn-id: r41206
Diffstat (limited to 'engines')
-rw-r--r--engines/cruise/cruise_main.cpp44
-rw-r--r--engines/cruise/gfxModule.cpp7
-rw-r--r--engines/gob/draw_v2.cpp4
-rw-r--r--engines/kyra/lol.cpp108
-rw-r--r--engines/kyra/lol.h28
-rw-r--r--engines/kyra/saveload_lol.cpp4
-rw-r--r--engines/kyra/screen_lol.cpp10
-rw-r--r--engines/kyra/script_lol.cpp27
-rw-r--r--engines/sci/console.cpp268
-rw-r--r--engines/sci/console.h2
-rw-r--r--engines/sci/debug.h47
-rw-r--r--engines/sci/engine/game.cpp19
-rw-r--r--engines/sci/engine/kernel.cpp165
-rw-r--r--engines/sci/engine/kernel.h17
-rw-r--r--engines/sci/engine/kernel_types.h48
-rw-r--r--engines/sci/engine/kevent.cpp25
-rw-r--r--engines/sci/engine/kfile.cpp2
-rw-r--r--engines/sci/engine/kgraphics.cpp36
-rw-r--r--engines/sci/engine/klists.cpp9
-rw-r--r--engines/sci/engine/kmisc.cpp7
-rw-r--r--engines/sci/engine/kmovement.cpp6
-rw-r--r--engines/sci/engine/kscripts.cpp2
-rw-r--r--engines/sci/engine/ksound.cpp8
-rw-r--r--engines/sci/engine/kstring.cpp12
-rw-r--r--engines/sci/engine/memobj.cpp413
-rw-r--r--engines/sci/engine/memobj.h572
-rw-r--r--engines/sci/engine/message.cpp56
-rw-r--r--engines/sci/engine/message.h2
-rw-r--r--engines/sci/engine/savegame.cpp12
-rw-r--r--engines/sci/engine/scriptdebug.cpp390
-rw-r--r--engines/sci/engine/seg_manager.cpp368
-rw-r--r--engines/sci/engine/seg_manager.h1
-rw-r--r--engines/sci/engine/state.cpp11
-rw-r--r--engines/sci/engine/state.h18
-rw-r--r--engines/sci/engine/vm.cpp82
-rw-r--r--engines/sci/engine/vm.h557
-rw-r--r--engines/sci/gfx/gfx_driver.cpp16
-rw-r--r--engines/sci/gfx/gfx_driver.h34
-rw-r--r--engines/sci/gfx/gfx_widgets.cpp12
-rw-r--r--engines/sci/gfx/gfx_widgets.h2
-rw-r--r--engines/sci/gfx/operations.cpp57
-rw-r--r--engines/sci/gfx/operations.h9
-rw-r--r--engines/sci/module.mk1
-rw-r--r--engines/sci/resource.cpp293
-rw-r--r--engines/sci/resource.h19
-rw-r--r--engines/sci/sci.cpp36
-rw-r--r--engines/sci/sfx/core.cpp6
-rw-r--r--engines/sci/uinput.h36
-rw-r--r--engines/sci/vocabulary.cpp6
-rw-r--r--engines/sci/vocabulary.h2
-rw-r--r--engines/scumm/he/script_v100he.cpp2
-rw-r--r--engines/scumm/he/script_v90he.cpp2
-rw-r--r--engines/scumm/he/sound_he.cpp10
-rw-r--r--engines/scumm/he/sound_he.h1
-rw-r--r--engines/scumm/he/sprite_he.cpp1
-rw-r--r--engines/scumm/he/wiz_he.cpp2
-rw-r--r--engines/scumm/he/wiz_he.h2
57 files changed, 2101 insertions, 1835 deletions
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index bdbf257b32..649cc72cb8 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -40,6 +40,8 @@ unsigned int timer = 0;
gfxEntryStruct* linkedMsgList = NULL;
+extern bool isBlack;
+
void drawBlackSolidBoxSmall() {
// gfxModuleData.drawSolidBox(64,100,256,117,0);
drawSolidBox(64, 100, 256, 117, 0);
@@ -1712,6 +1714,8 @@ void CruiseEngine::mainLoop(void) {
//int32 t_start,t_left;
//uint32 t_end;
//int32 q=0; /* Dummy */
+ int16 mouseX, mouseY;
+ int16 mouseButton;
int enableUser = 0;
@@ -1793,13 +1797,15 @@ void CruiseEngine::mainLoop(void) {
enableUser = 0;
}
- manageScripts(&relHead);
- manageScripts(&procHead);
+ if (userWait < 1) {
+ manageScripts(&relHead);
+ manageScripts(&procHead);
- removeFinishedScripts(&relHead);
- removeFinishedScripts(&procHead);
+ removeFinishedScripts(&relHead);
+ removeFinishedScripts(&procHead);
- processAnimation();
+ processAnimation();
+ }
if (remdo) {
// ASSERT(0);
@@ -1824,17 +1830,13 @@ void CruiseEngine::mainLoop(void) {
PCFadeFlag = 0;
/*if (!PCFadeFlag)*/
- if (userWait != 2) {
+ if (!isUserWait) {
mainDraw(0);
flipScreen();
}
if (userEnabled && !userWait && !autoTrack) {
if (currentActiveMenu == -1) {
- int16 mouseX;
- int16 mouseY;
- int16 mouseButton;
-
static int16 oldMouseX = -1;
static int16 oldMouseY = -1;
@@ -1869,9 +1871,14 @@ void CruiseEngine::mainLoop(void) {
// User Wait handling
if (userWait == 1) {
// Initial step
+ do {
+ // Make sure any previous mouse press is released
+ getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY);
+ } while (mouseButton != 0);
+
++userWait;
- mainDraw(0);
- flipScreen();
+// mainDraw(0);
+// flipScreen();
} else {
// Standard handling
@@ -1881,9 +1888,16 @@ void CruiseEngine::mainLoop(void) {
removeFinishedScripts(&relHead);
removeFinishedScripts(&procHead);
- // Draw the next screen
- processAnimation();
- gfxModuleData_flipScreen();
+ if (isBlack) {
+ // This is a bit of a hack to ensure that user waits directly after a palette fade
+ // have time to restore the palette before waiting starts
+ mainDraw(0);
+ flipScreen();
+ } else {
+ // Draw the next screen
+ processAnimation();
+ gfxModuleData_flipScreen();
+ }
}
continue;
}
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index 47d3f49204..50e6587d90 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -40,6 +40,7 @@ palEntry lpalette[256];
int palDirtyMin = 256;
int palDirtyMax = -1;
+bool isBlack = false;
gfxModuleDataStruct gfxModuleData = {
0, // use Tandy
@@ -237,6 +238,12 @@ void flip() {
g_system->setPalette(paletteRGBA + palDirtyMin*4, palDirtyMin, palDirtyMax - palDirtyMin + 1);
palDirtyMin = 256;
palDirtyMax = -1;
+
+ isBlack = true;
+ for (i = 0; i < 256; ++i) {
+ isBlack = (lpalette[i].R == 0) && (lpalette[i].G == 0) && (lpalette[i].B == 0);
+ if (!isBlack) break;
+ }
}
g_system->copyRectToScreen(globalScreen, 320, 0, 0, 320, 200);
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index 5e307d760e..852e0b51fb 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -649,7 +649,7 @@ void Draw_v2::spriteOperation(int16 operation) {
int16 spriteLeft = _spriteLeft;
int16 spriteTop = _spriteTop;
int16 spriteRight = _spriteRight;
- int16 spriteBottom = _spriteLeft;
+ int16 spriteBottom = _spriteBottom;
int16 destSpriteX = _destSpriteX;
int16 destSpriteY = _destSpriteY;
int16 destSurface = _destSurface;
@@ -913,7 +913,7 @@ void Draw_v2::spriteOperation(int16 operation) {
_spriteLeft = spriteLeft;
_spriteTop = spriteTop;
_spriteRight = spriteRight;
- _spriteLeft = spriteBottom;
+ _spriteBottom = spriteBottom;
_destSpriteX = destSpriteX;
_destSpriteY = destSpriteY;
_destSurface = destSurface;
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 564e64c8d7..5c494b5180 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -536,7 +536,7 @@ Common::Error LoLEngine::init() {
_spellProcs.push_back(new SpellProc(this, &LoLEngine::castSwarm));
_spellProcs.push_back(new SpellProc(this, 0));
_spellProcs.push_back(new SpellProc(this, 0));
- _spellProcs.push_back(new SpellProc(this, &LoLEngine::castUnk));
+ _spellProcs.push_back(new SpellProc(this, &LoLEngine::castVaelansCube));
_spellProcs.push_back(new SpellProc(this, 0));
_spellProcs.push_back(new SpellProc(this, 0));
_spellProcs.push_back(new SpellProc(this, 0));
@@ -1910,13 +1910,12 @@ int LoLEngine::castSwarm(ActiveSpell *a) {
return 1;
}
-int LoLEngine::castUnk(ActiveSpell *a) {
- return 1;
+int LoLEngine::castVaelansCube(ActiveSpell *a) {
+ return processMagicVaelansCube();
}
int LoLEngine::castGuardian(ActiveSpell *a) {
- processMagicGuardian(a->charNum);
- return 1;
+ return processMagicGuardian(a->charNum);
}
int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) {
@@ -1924,7 +1923,7 @@ int LoLEngine::castHealOnSingleCharacter(ActiveSpell *a) {
return 1;
}
-void LoLEngine::processMagicSpark(int charNum, int spellLevel) {
+int LoLEngine::processMagicSpark(int charNum, int spellLevel) {
WSAMovie_v2 *mov = new WSAMovie_v2(this, _screen);
_screen->copyPage(0, 12);
@@ -1994,16 +1993,18 @@ void LoLEngine::processMagicSpark(int charNum, int spellLevel) {
_sceneUpdateRequired = true;
delete mov;
+ return 1;
}
-void LoLEngine::processMagicHealSelectTarget() {
+int LoLEngine::processMagicHealSelectTarget() {
_txt->printMessage(0, getLangString(0x4040));
gui_resetButtonList();
gui_setFaceFramesControlButtons(81, 0);
gui_initButtonsFromList(_buttonList8);
+ return 1;
}
-void LoLEngine::processMagicHeal(int charNum, int spellLevel) {
+int LoLEngine::processMagicHeal(int charNum, int spellLevel) {
if (!_healOverlay) {
_healOverlay = new uint8[256];
_screen->generateGrayOverlay(_screen->getPalette(1), _healOverlay, 52, 22, 20, 0, 256, true);
@@ -2113,9 +2114,10 @@ void LoLEngine::processMagicHeal(int charNum, int spellLevel) {
_screen->setCurPage(cp);
updateDrawPage2();
+ return 1;
}
-void LoLEngine::processMagicIce(int charNum, int spellLevel) {
+int LoLEngine::processMagicIce(int charNum, int spellLevel) {
int cp = _screen->setCurPage(2);
disableSysTimer(2);
@@ -2261,9 +2263,10 @@ void LoLEngine::processMagicIce(int charNum, int spellLevel) {
delete[] swampCol;
delete[] tpal;
_screen->setCurPage(cp);
+ return 1;
}
-void LoLEngine::processMagicFireball(int charNum, int spellLevel) {
+int LoLEngine::processMagicFireball(int charNum, int spellLevel) {
int fbCnt = 0;
int d = 1;
@@ -2412,9 +2415,10 @@ void LoLEngine::processMagicFireball(int charNum, int spellLevel) {
updateDrawPage2();
snd_playQueuedEffects();
runLevelScriptCustom(bl, 0x20, charNum, 3, 0, 0);
+ return 1;
}
-void LoLEngine::processMagicHandOfFate(int spellLevel) {
+int LoLEngine::processMagicHandOfFate(int spellLevel) {
int cp = _screen->setCurPage(2);
_screen->copyPage(0, 12);
@@ -2491,9 +2495,10 @@ void LoLEngine::processMagicHandOfFate(int spellLevel) {
gui_drawScene(2);
updateDrawPage2();
+ return 1;
}
-void LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) {
+int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) {
static const uint8 mistDamage[] = { 30, 70, 110, 200 };
_envSfxUseQueue = true;
@@ -2525,10 +2530,11 @@ void LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) {
_screen->copyPage(12, 0);
updateDrawPage2();
- this->snd_playQueuedEffects();
+ this->snd_playQueuedEffects();
+ return 1;
}
-void LoLEngine::processMagicLightning(int charNum, int spellLevel) {
+int LoLEngine::processMagicLightning(int charNum, int spellLevel) {
_screen->hideMouse();
_screen->copyPage(0, 2);
gui_drawScene(2);
@@ -2562,9 +2568,10 @@ void LoLEngine::processMagicLightning(int charNum, int spellLevel) {
_sceneUpdateRequired = true;
gui_drawScene(0);
_screen->showMouse();
+ return 1;
}
-void LoLEngine::processMagicFog() {
+int LoLEngine::processMagicFog() {
int cp = _screen->setCurPage(2);
_screen->copyPage(0, 12);
@@ -2598,9 +2605,10 @@ void LoLEngine::processMagicFog() {
}
gui_drawScene(0);
+ return 1;
}
-void LoLEngine::processMagicSwarm(int charNum, int damage) {
+int LoLEngine::processMagicSwarm(int charNum, int damage) {
int cp = _screen->setCurPage(2);
_screen->copyPage(0, 12);
snd_playSoundEffect(74, -1);
@@ -2662,12 +2670,71 @@ void LoLEngine::processMagicSwarm(int charNum, int damage) {
_screen->setCurPage(cp);
delete mov;
+ return 1;
}
-void LoLEngine::processMagicGuardian(int charNum) {
- //uint16 targetBlock = 0;
- //int dist = getSpellTargetBlock(_currentBlock, _currentDirection, 3, targetBlock);
+int LoLEngine::processMagicVaelansCube() {
+ uint8 *tmpPal1 = new uint8[768];
+ uint8 *tmpPal2 = new uint8[768];
+ uint8 *sp1 = _screen->getPalette(1);
+
+ memcpy(tmpPal1, sp1, 768);
+ memcpy(tmpPal2, sp1, 768);
+
+ for (int i = 0; i < 128; i++) {
+ uint16 a = sp1[i * 3] + 16;
+ tmpPal2[i * 3] = (a > 60) ? 60 : a;
+ tmpPal2[i * 3 + 1] = sp1[i * 3 + 1];
+ a = sp1[i * 3 + 2] + 19;
+ tmpPal2[i * 3 + 2] = (a > 60) ? 60 : a;
+ }
+
+ snd_playSoundEffect(146, -1);
+
+ uint32 ctime = _system->getMillis();
+ uint32 endTime = _system->getMillis() + 70 * _tickLength;
+
+ while (_system->getMillis() < endTime) {
+ _screen->fadePaletteStep(tmpPal1, tmpPal2, _system->getMillis() - ctime, 70 * _tickLength);
+ updateInput();
+ }
+ uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection);
+ uint8 s = _levelBlockProperties[bl].walls[_currentDirection ^ 2];
+ uint8 flg = _wllWallFlags[s];
+
+ int v = (s == 47 && (_currentLevel == 17 || _currentLevel == 24)) ? 1 : 0;
+ if ((_wllVmpMap[s] == 1 || _wllVmpMap[s] == 2) && (flg & 1) && (_currentLevel == 22)) {
+ memset(_levelBlockProperties[bl].walls, 0, 4);
+ gui_drawScene(0);
+ v = 1;
+ }
+
+ uint16 o = _levelBlockProperties[bl].assignedObjects;
+ while (o & 0x8000) {
+ MonsterInPlay *m = &_monsters[o & 0x7fff];
+ o = m->nextAssignedObject;
+ if (m->properties->flags & 0x1000) {
+ inflictDamage(o, 100, 0xffff, 0, 0x80);
+ v = 1;
+ }
+ }
+
+ ctime = _system->getMillis();
+ endTime = _system->getMillis() + 70 * _tickLength;
+
+ while (_system->getMillis() < endTime) {
+ _screen->fadePaletteStep(tmpPal2, tmpPal1, _system->getMillis() - ctime, 70 * _tickLength);
+ updateInput();
+ }
+
+ delete[] tmpPal1;
+ delete[] tmpPal2;
+
+ return v;
+}
+
+int LoLEngine::processMagicGuardian(int charNum) {
int cp = _screen->setCurPage(2);
_screen->copyPage(0, 2);
_screen->copyPage(2, 12);
@@ -2682,7 +2749,7 @@ void LoLEngine::processMagicGuardian(int charNum) {
_screen->copyPage(2, 12);
uint16 bl = calcNewBlockPosition(_currentBlock, _currentDirection);
- //bool a = (_levelBlockProperties[bl].assignedObjects & 0x8000) ? true : false;
+ int res = (_levelBlockProperties[bl].assignedObjects & 0x8000) ? 1 : 0;
inflictMagicalDamageForBlock(bl, charNum, 200, 0x80);
_screen->copyPage(12, 2);
@@ -2699,6 +2766,7 @@ void LoLEngine::processMagicGuardian(int charNum) {
_screen->setCurPage(cp);
gui_drawPlayField();
updateDrawPage2();
+ return res;
}
void LoLEngine::callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y) {
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index 4e9b39b88d..be734d083c 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -69,7 +69,7 @@ struct LoLCharacter {
int16 nextAnimUpdateCountdown;
uint16 items[11];
uint8 skillLevels[3];
- uint8 skillModifiers[3];
+ int8 skillModifiers[3];
int32 experiencePts[3];
uint8 characterUpdateEvents[5];
uint8 characterUpdateDelay[5];
@@ -771,6 +771,7 @@ private:
int olol_getNextActiveCharacter(EMCState *script);
int olol_paralyzePoisonCharacter(EMCState *script);
int olol_drawCharPortrait(EMCState *script);
+ int olol_removeInventoryItem(EMCState *script);
int olol_getAnimationLastPart(EMCState *script);
int olol_assignSpecialGuiShape(EMCState *script);
int olol_findInventoryItem(EMCState *script);
@@ -1326,21 +1327,22 @@ private:
int castLightning(ActiveSpell *a);
int castFog(ActiveSpell *a);
int castSwarm(ActiveSpell *a);
- int castUnk(ActiveSpell *a);
+ int castVaelansCube(ActiveSpell *a);
int castGuardian(ActiveSpell *a);
int castHealOnSingleCharacter(ActiveSpell *a);
- void processMagicSpark(int charNum, int spellLevel);
- void processMagicHealSelectTarget();
- void processMagicHeal(int charNum, int spellLevel);
- void processMagicIce(int charNum, int spellLevel);
- void processMagicFireball(int charNum, int spellLevel);
- void processMagicHandOfFate(int spellLevel);
- void processMagicMistOfDoom(int charNum, int spellLevel);
- void processMagicLightning(int charNum, int spellLevel);
- void processMagicFog();
- void processMagicSwarm(int charNum, int damage);
- void processMagicGuardian(int charNum);
+ int processMagicSpark(int charNum, int spellLevel);
+ int processMagicHealSelectTarget();
+ int processMagicHeal(int charNum, int spellLevel);
+ int processMagicIce(int charNum, int spellLevel);
+ int processMagicFireball(int charNum, int spellLevel);
+ int processMagicHandOfFate(int spellLevel);
+ int processMagicMistOfDoom(int charNum, int spellLevel);
+ int processMagicLightning(int charNum, int spellLevel);
+ int processMagicFog();
+ int processMagicSwarm(int charNum, int damage);
+ int processMagicVaelansCube();
+ int processMagicGuardian(int charNum);
void callbackProcessMagicSwarm(WSAMovie_v2 *mov, int x, int y);
void callbackProcessMagicLightning(WSAMovie_v2 *mov, int x, int y);
diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp
index 4998795f73..248c46c2a3 100644
--- a/engines/kyra/saveload_lol.cpp
+++ b/engines/kyra/saveload_lol.cpp
@@ -85,7 +85,7 @@ Common::Error LoLEngine::loadGameState(int slot) {
for (int ii = 0; ii < 3; ii++)
c->skillLevels[ii] = in.readByte();
for (int ii = 0; ii < 3; ii++)
- c->skillModifiers[ii] = in.readByte();
+ c->skillModifiers[ii] = in.readSByte();
for (int ii = 0; ii < 3; ii++)
c->experiencePts[ii] = in.readUint32BE();
for (int ii = 0; ii < 5; ii++)
@@ -294,7 +294,7 @@ Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Gra
for (int ii = 0; ii < 3; ii++)
out->writeByte(c->skillLevels[ii]);
for (int ii = 0; ii < 3; ii++)
- out->writeByte(c->skillModifiers[ii]);
+ out->writeSByte(c->skillModifiers[ii]);
for (int ii = 0; ii < 3; ii++)
out->writeUint32BE(c->experiencePts[ii]);
for (int ii = 0; ii < 5; ii++)
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index b834123d2f..5f64a1cddd 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -589,6 +589,16 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in
va_end(args);
}
+ // _internDimH: h0
+// _internDimW: w0
+// _internDimDstX: x1
+// _internDimDstY: y1
+// _internBlockWidth: w1
+// _internBlockHeight: h1
+// _internDimU5: x2
+// _internDimU6: y2
+// _internBlockWidth2: w2
+
_internDimX = _internDimY = 0;
_internDimW = w1;
_internDimH = h1;
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index 75651a2a9a..33edfa0e24 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -1896,6 +1896,31 @@ int LoLEngine::olol_drawCharPortrait(EMCState *script) {
return 1;
}
+int LoLEngine::olol_removeInventoryItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_removeInventoryItem(%p) (%d)", (const void *)script, stackPos(0));
+ int itemType = stackPos(0);
+ for (int i = 0; i < 48; i++) {
+ if (!_inventory[i] || _itemsInPlay[_inventory[i]].itemPropertyIndex != itemType)
+ continue;
+ _inventory[i] = 0;
+ gui_drawInventory();
+ return 1;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if (!(_characters[i].flags & 1))
+ continue;
+
+ for (int ii = 0; ii < 11; ii++) {
+ if (!_characters[i].items[ii] || _itemsInPlay[_characters[i].items[ii]].itemPropertyIndex != itemType)
+ continue;
+ _characters[i].items[ii] = 0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
int LoLEngine::olol_getAnimationLastPart(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getAnimationLastPart(%p) (%d)", (const void *)script, stackPos(0));
return _tim->resetAnimationLastPart(stackPos(0));
@@ -2730,7 +2755,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_drawCharPortrait);
// 0xA0
- OpcodeUnImpl();
+ Opcode(olol_removeInventoryItem);
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_getAnimationLastPart);
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 67e324f078..26ff08d065 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -27,6 +27,7 @@
#include "sci/sci.h"
#include "sci/console.h"
+#include "sci/debug.h"
#include "sci/resource.h"
#include "sci/vocabulary.h"
#include "sci/engine/savegame.h"
@@ -47,21 +48,22 @@ namespace Sci {
extern EngineState *g_EngineState;
-int debug_sleeptime_factor = 1;
-int debug_simulated_key = 0;
-bool debug_track_mouse_clicks = false;
-bool debug_weak_validations = false;
+int g_debug_sleeptime_factor = 1;
+int g_debug_simulated_key = 0;
+bool g_debug_track_mouse_clicks = false;
+bool g_debug_weak_validations = true;
Console::Console(SciEngine *vm) : GUI::Debugger() {
_vm = vm;
// Variables
- DVar_Register("sleeptime_factor", &debug_sleeptime_factor, DVAR_INT, 0);
+ DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0);
DVar_Register("gc_interval", &script_gc_interval, DVAR_INT, 0);
- DVar_Register("simulated_key", &debug_simulated_key, DVAR_INT, 0);
- DVar_Register("track_mouse_clicks", &debug_track_mouse_clicks, DVAR_BOOL, 0);
- DVar_Register("weak_validations", &debug_weak_validations, DVAR_BOOL, 0);
+ DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0);
+ DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0);
+ DVar_Register("weak_validations", &g_debug_weak_validations, DVAR_BOOL, 0);
+ DVar_Register("script_abort_flag", &script_abort_flag, DVAR_INT, 0);
// General
DCmd_Register("help", WRAP_METHOD(Console, cmdHelp));
@@ -114,6 +116,9 @@ Console::Console(SciEngine *vm) : GUI::Debugger() {
DCmd_Register("dynamic_views", WRAP_METHOD(Console, cmdDynamicViews));
DCmd_Register("dropped_views", WRAP_METHOD(Console, cmdDroppedViews));
DCmd_Register("status_bar", WRAP_METHOD(Console, cmdStatusBarColors));
+#ifdef GFXW_DEBUG_WIDGETS
+ DCmd_Register("print_widget", WRAP_METHOD(Console, cmdPrintWidget));
+#endif
// Segments
DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable));
DCmd_Register("segment_info", WRAP_METHOD(Console, cmdSegmentInfo));
@@ -181,6 +186,14 @@ void Console::postEnter() {
_vm->_mixer->pauseAll(false);
}
+
+#if 0
+// Unused
+#define LOOKUP_SPECIES(species) (\
+ (species >= 1000) ? species : *(s->_classtable[species].scriptposp) \
+ + s->_classtable[species].class_offset)
+#endif
+
bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf("\n");
DebugPrintf("Variables\n");
@@ -190,6 +203,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf("simulated_key: Add a key with the specified scan code to the event list\n");
DebugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n");
DebugPrintf("weak_validations: Turns some validation errors into warnings\n");
+ DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n");
DebugPrintf("\n");
DebugPrintf("Commands\n");
DebugPrintf("--------\n");
@@ -247,6 +261,9 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" dynamic_views - Lists active dynamic views\n");
DebugPrintf(" dropped_views - Lists dropped dynamic views\n");
DebugPrintf(" status_bar - Sets the colors of the status bar\n");
+#ifdef GFXW_DEBUG_WIDGETS
+ DebugPrintf(" print_widget - Shows active widgets (no params) or information on the specified widget indices\n");
+#endif
DebugPrintf("\n");
DebugPrintf("Segments:\n");
DebugPrintf(" segment_table - Lists all segments\n");
@@ -666,8 +683,8 @@ bool Console::cmdRestoreGame(int argc, const char **argv) {
if (newstate) {
g_EngineState->successor = newstate; // Set successor
- script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game
- _debugstate_valid = 0;
+ script_abort_flag = 2; // Abort current game with replay
+ g_debugstate_valid = 0;
shrink_execution_stack(g_EngineState, g_EngineState->execution_stack_base + 1);
return 0;
@@ -698,7 +715,7 @@ bool Console::cmdRestartGame(int argc, const char **argv) {
g_EngineState->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
script_abort_flag = 1;
- _debugstate_valid = 0;
+ g_debugstate_valid = 0;
return false;
}
@@ -1645,7 +1662,7 @@ bool Console::cmdValueType(int argc, const char **argv) {
return true;
}
- int t = determine_reg_type(g_EngineState, val, 1);
+ int t = determine_reg_type(g_EngineState, val, true);
int invalid = t & KSIG_INVALID;
switch (t & ~KSIG_INVALID) {
@@ -2347,9 +2364,9 @@ bool Console::cmdExit(int argc, const char **argv) {
if (!scumm_stricmp(argv[1], "game")) {
// Quit gracefully
script_abort_flag = 1; // Terminate VM
- _debugstate_valid = 0;
- _debug_seeking = 0;
- _debug_step_running = 0;
+ g_debugstate_valid = 0;
+ g_debug_seeking = 0;
+ g_debug_step_running = 0;
} else if (!scumm_stricmp(argv[1], "now")) {
// Quit ungracefully
@@ -2677,4 +2694,225 @@ int printObject(EngineState *s, reg_t pos) {
return 0;
}
+#define GETRECT(ll, rr, tt, bb) \
+ ll = GET_SELECTOR(pos, ll); \
+ rr = GET_SELECTOR(pos, rr); \
+ tt = GET_SELECTOR(pos, tt); \
+ bb = GET_SELECTOR(pos, bb);
+
+#if 0
+// TODO Re-implement this
+static void viewobjinfo(EngineState *s, HeapPtr pos) {
+ char *signals[16] = {
+ "stop_update",
+ "updated",
+ "no_update",
+ "hidden",
+ "fixed_priority",
+ "always_update",
+ "force_update",
+ "remove",
+ "frozen",
+ "is_extra",
+ "hit_obstacle",
+ "doesnt_turn",
+ "no_cycler",
+ "ignore_horizon",
+ "ignore_actor",
+ "dispose!"
+ };
+
+ int x, y, z, priority;
+ int cel, loop, view, signal;
+ int nsLeft, nsRight, nsBottom, nsTop;
+ int lsLeft, lsRight, lsBottom, lsTop;
+ int brLeft, brRight, brBottom, brTop;
+ int i;
+ int have_rects = 0;
+ Common::Rect nsrect, nsrect_clipped, brrect;
+
+ if (lookup_selector(s, pos, s->_kernel->_selectorMap.nsBottom, NULL) == kSelectorVariable) {
+ GETRECT(nsLeft, nsRight, nsBottom, nsTop);
+ GETRECT(lsLeft, lsRight, lsBottom, lsTop);
+ GETRECT(brLeft, brRight, brBottom, brTop);
+ have_rects = 1;
+ }
+
+ GETRECT(view, loop, signal, cel);
+
+ sciprintf("\n-- View information:\ncel %d/%d/%d at ", view, loop, cel);
+
+ x = GET_SELECTOR(pos, x);
+ y = GET_SELECTOR(pos, y);
+ priority = GET_SELECTOR(pos, priority);
+ if (s->_kernel->_selectorMap.z > 0) {
+ z = GET_SELECTOR(pos, z);
+ sciprintf("(%d,%d,%d)\n", x, y, z);
+ } else
+ sciprintf("(%d,%d)\n", x, y);
+
+ if (priority == -1)
+ sciprintf("No priority.\n\n");
+ else
+ sciprintf("Priority = %d (band starts at %d)\n\n", priority, PRIORITY_BAND_FIRST(priority));
+
+ if (have_rects) {
+ sciprintf("nsRect: [%d..%d]x[%d..%d]\n", nsLeft, nsRight, nsTop, nsBottom);
+ sciprintf("lsRect: [%d..%d]x[%d..%d]\n", lsLeft, lsRight, lsTop, lsBottom);
+ sciprintf("brRect: [%d..%d]x[%d..%d]\n", brLeft, brRight, brTop, brBottom);
+ }
+
+ nsrect = get_nsrect(s, pos, 0);
+ nsrect_clipped = get_nsrect(s, pos, 1);
+ brrect = set_base(s, pos);
+ sciprintf("new nsRect: [%d..%d]x[%d..%d]\n", nsrect.x, nsrect.xend, nsrect.y, nsrect.yend);
+ sciprintf("new clipped nsRect: [%d..%d]x[%d..%d]\n", nsrect_clipped.x, nsrect_clipped.xend, nsrect_clipped.y, nsrect_clipped.yend);
+ sciprintf("new brRect: [%d..%d]x[%d..%d]\n", brrect.x, brrect.xend, brrect.y, brrect.yend);
+ sciprintf("\n signals = %04x:\n", signal);
+
+ for (i = 0; i < 16; i++)
+ if (signal & (1 << i))
+ sciprintf(" %04x: %s\n", 1 << i, signals[i]);
+}
+#endif
+#undef GETRECT
+
+#define GETRECT(ll, rr, tt, bb) \
+ ll = GET_SELECTOR(pos, ll); \
+ rr = GET_SELECTOR(pos, rr); \
+ tt = GET_SELECTOR(pos, tt); \
+ bb = GET_SELECTOR(pos, bb);
+
+#if 0
+// Draws the nsRect and brRect of a dynview object. nsRect is green, brRect is blue.
+// TODO: Re-implement this
+static int c_gfx_draw_viewobj(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
+ HeapPtr pos = (HeapPtr)(cmdParams[0].val);
+ int is_view;
+ int x, y, priority;
+ int nsLeft, nsRight, nsBottom, nsTop;
+ int brLeft, brRight, brBottom, brTop;
+
+ if (!s) {
+ sciprintf("Not in debug state!\n");
+ return 1;
+ }
+
+ if ((pos < 4) || (pos > 0xfff0)) {
+ sciprintf("Invalid address.\n");
+ return 1;
+ }
+
+ if (((int16)READ_LE_UINT16(s->heap + pos + SCRIPT_OBJECT_MAGIC_OFFSET)) != SCRIPT_OBJECT_MAGIC_NUMBER) {
+ sciprintf("Not an object.\n");
+ return 0;
+ }
+
+
+ is_view = (lookup_selector(s, pos, s->_kernel->_selectorMap.x, NULL) == kSelectorVariable) &&
+ (lookup_selector(s, pos, s->_kernel->_selectorMap.brLeft, NULL) == kSelectorVariable) &&
+ (lookup_selector(s, pos, s->_kernel->_selectorMap.signal, NULL) == kSelectorVariable) &&
+ (lookup_selector(s, pos, s->_kernel->_selectorMap.nsTop, NULL) == kSelectorVariable);
+
+ if (!is_view) {
+ sciprintf("Not a dynamic View object.\n");
+ return 0;
+ }
+
+ x = GET_SELECTOR(pos, x);
+ y = GET_SELECTOR(pos, y);
+ priority = GET_SELECTOR(pos, priority);
+ GETRECT(brLeft, brRight, brBottom, brTop);
+ GETRECT(nsLeft, nsRight, nsBottom, nsTop);
+ gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen);
+
+ brTop += 10;
+ brBottom += 10;
+ nsTop += 10;
+ nsBottom += 10;
+
+ gfxop_fill_box(s->gfx_state, gfx_rect(nsLeft, nsTop, nsRight - nsLeft + 1, nsBottom - nsTop + 1), s->ega_colors[2]);
+ gfxop_fill_box(s->gfx_state, gfx_rect(brLeft, brTop, brRight - brLeft + 1, brBottom - brTop + 1), s->ega_colors[1]);
+ gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y - 1, 3, 3), s->ega_colors[0]);
+ gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y, 3, 1), s->ega_colors[priority]);
+ gfxop_fill_box(s->gfx_state, gfx_rect(x, y - 1, 1, 3), s->ega_colors[priority]);
+ gfxop_update(s->gfx_state);
+
+ return 0;
+}
+#endif
+#undef GETRECT
+
+#if 0
+// Executes one operation skipping over sends
+// TODO Re-implement this
+int c_stepover(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
+ int opcode, opnumber;
+
+ if (!g_debugstate_valid) {
+ sciprintf("Not in debug state\n");
+ return 1;
+ }
+
+ g_debugstate_valid = 0;
+ opcode = s->_heap[*p_pc];
+ opnumber = opcode >> 1;
+ if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ ||
+ opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) {
+ g_debug_seeking = _DEBUG_SEEK_SO;
+ s_debug_seek_level = s->_executionStack.size()-1;
+ // Store in s_debug_seek_special the offset of the next command after send
+ switch (opcode) {
+ case 0x46: // calle W
+ s_debug_seek_special = *p_pc + 5;
+ break;
+
+ case 0x44: // callb W
+ case 0x47: // calle B
+ case 0x56: // super W
+ s_debug_seek_special = *p_pc + 4;
+ break;
+
+ case 0x45: // callb B
+ case 0x57: // super B
+ case 0x4A: // send W
+ case 0x54: // self W
+ s_debug_seek_special = *p_pc + 3;
+ break;
+
+ default:
+ s_debug_seek_special = *p_pc + 2;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef GFXW_DEBUG_WIDGETS
+extern GfxWidget *debug_widgets[];
+extern int debug_widget_pos;
+
+// If called with no parameters, it shows which widgets are active
+// With parameters, it lists the widget corresponding to the numerical index specified (for each parameter).
+bool Console::cmdPrintWidget(int argc, const char **argv) {
+ if (argc > 1) {
+ for (int i = 0; i < argc; i++) {
+ int widget_nr = atoi(argv[1]);
+
+ DebugPrintf("===== Widget #%d:\n", widget_nr);
+ debug_widgets[widget_nr]->print(0);
+ }
+ } else if (debug_widget_pos > 1) {
+ DebugPrintf("Widgets 0-%d are active\n", debug_widget_pos - 1);
+ } else if (debug_widget_pos == 1) {
+ DebugPrintf("Widget 0 is active\n");
+ } else {
+ DebugPrintf("No widgets are active\n");
+ }
+
+ return true;
+}
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/console.h b/engines/sci/console.h
index f0975837df..b2e66daa0f 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -33,6 +33,7 @@
namespace Sci {
class SciEngine;
+struct List;
// Refer to the "addresses" command on how to pass address parameters
int parse_reg_t(EngineState *s, const char *str, reg_t *dest);
@@ -97,6 +98,7 @@ private:
bool cmdDynamicViews(int argc, const char **argv);
bool cmdDroppedViews(int argc, const char **argv);
bool cmdStatusBarColors(int argc, const char **argv);
+ bool cmdPrintWidget(int argc, const char **argv);
// Segments
bool cmdPrintSegmentTable(int argc, const char **argv);
bool cmdSegmentInfo(int argc, const char **argv);
diff --git a/engines/sci/debug.h b/engines/sci/debug.h
new file mode 100644
index 0000000000..ec44838826
--- /dev/null
+++ b/engines/sci/debug.h
@@ -0,0 +1,47 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SCI_DEBUG_H
+#define SCI_DEBUG_H
+
+namespace Sci {
+
+// Various global variables used for debugging are declared here
+
+extern int g_stop_on_event;
+
+extern int g_debugstate_valid;
+extern int g_debug_seeking;
+extern int g_debug_step_running;
+
+extern int g_debug_sleeptime_factor;
+extern int g_debug_simulated_key;
+extern bool g_debug_track_mouse_clicks;
+extern bool g_debug_weak_validations;
+
+
+} // End of namespace Sci
+
+#endif
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
index 6aba9b3f10..bfd38f2c1b 100644
--- a/engines/sci/engine/game.cpp
+++ b/engines/sci/engine/game.cpp
@@ -43,7 +43,7 @@ int _reset_graphics_input(EngineState *s) {
gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
debug(2, "Initializing graphics");
- if (s->resmgr->_sciVersion <= SCI_VERSION_01 || (s->flags & GF_SCI1_EGA)) {
+ if (s->resmgr->_sciVersion <= SCI_VERSION_01 || (s->_flags & GF_SCI1_EGA)) {
int i;
for (i = 0; i < 16; i++) {
@@ -66,7 +66,7 @@ int _reset_graphics_input(EngineState *s) {
} else {
resource = s->resmgr->findResource(kResourceTypePalette, 999, 1);
if (resource) {
- if (s->version < SCI_VERSION_1_1)
+ if (s->_version < SCI_VERSION_1_1)
s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal1(999, resource->data, resource->size));
else
s->gfx_state->gfxResMan->setStaticPalette(gfxr_read_pal11(999, resource->data, resource->size));
@@ -89,7 +89,7 @@ int _reset_graphics_input(EngineState *s) {
s->priority_first = 42; // Priority zone 0 ends here
- if (s->flags & GF_SCI0_OLDGFXFUNCS)
+ if (s->_flags & GF_SCI0_OLDGFXFUNCS)
s->priority_last = 200;
else
s->priority_last = 190;
@@ -259,7 +259,7 @@ static int create_class_table_sci0(EngineState *s) {
Resource *script = s->resmgr->findResource(kResourceTypeScript, scriptnr, 0);
if (script) {
- if (s->flags & GF_SCI0_OLD)
+ if (s->_flags & GF_SCI0_OLD)
magic_offset = seeker = 2;
else
magic_offset = seeker = 0;
@@ -324,13 +324,12 @@ static int create_class_table_sci0(EngineState *s) {
}
// Architectural stuff: Init/Unintialize engine
-int script_init_engine(EngineState *s, sci_version_t version) {
+int script_init_engine(EngineState *s) {
int result;
s->kernel_opt_flags = 0;
- s->version = version;
- if (s->version >= SCI_VERSION_1_1)
+ if (s->_version >= SCI_VERSION_1_1)
result = create_class_table_sci11(s);
else
result = create_class_table_sci0(s);
@@ -340,7 +339,7 @@ int script_init_engine(EngineState *s, sci_version_t version) {
return 1;
}
- s->seg_manager = new SegManager(s->version >= SCI_VERSION_1_1);
+ s->seg_manager = new SegManager(s->_version >= SCI_VERSION_1_1);
s->gc_countdown = GC_INTERVAL - 1;
SegmentId script_000_segment = script_get_segment(s, 0, SCRIPT_GET_LOCK);
@@ -370,7 +369,7 @@ int script_init_engine(EngineState *s, sci_version_t version) {
s->_executionStack.clear(); // Start without any execution stack
s->execution_stack_base = -1; // No vm is running yet
- s->_kernel = new Kernel(s->resmgr, (s->flags & GF_SCI0_OLD));
+ s->_kernel = new Kernel(s->resmgr, (s->_flags & GF_SCI0_OLD));
s->_vocabulary = new Vocabulary(s->resmgr);
s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING;
@@ -378,7 +377,7 @@ int script_init_engine(EngineState *s, sci_version_t version) {
s->bp_list = NULL; // No breakpoints defined
s->have_bp = 0;
- if ((s->flags & GF_SCI1_LOFSABSOLUTE) && s->version < SCI_VERSION_1_1)
+ if ((s->_flags & GF_SCI1_LOFSABSOLUTE) && s->_version < SCI_VERSION_1_1)
s->seg_manager->setExportWidth(1);
else
s->seg_manager->setExportWidth(0);
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 719ff16334..3b998c7092 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -298,21 +298,14 @@ static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = {
/*0x88*/ "DbugStr"
};
-enum KernelFunctionType {
- KF_NEW = 1,
- KF_NONE = -1, /**< No mapping, but name is known */
- KF_TERMINATOR = -42 /**< terminates kfunct_mappers */
-};
-
struct SciKernelFunction {
- KernelFunctionType type;
const char *name;
- kfunct *fun; /* The actual function */
+ KernelFunc *fun; /* The actual function */
const char *signature; /* kfunct signature */
};
-#define DEFUN(nm, cname, sig) {KF_NEW, nm, cname, sig}
-#define NOFUN(nm) {KF_NONE, nm, NULL, NULL}
+#define DEFUN(name, fun, sig) {name, fun, sig}
+#define NOFUN(name) {name, NULL, NULL}
SciKernelFunction kfunct_mappers[] = {
/*00*/ DEFUN("Load", kLoad, "iii*"),
@@ -434,8 +427,8 @@ SciKernelFunction kfunct_mappers[] = {
/*6f*/ DEFUN("6f", kTimesCos, "ii"),
/*70*/ DEFUN("Graph", kGraph, ".*"),
/*71*/ DEFUN("Joystick", kJoystick, ".*"),
- /*72*/ NOFUN(NULL),
- /*73*/ NOFUN(NULL),
+ /*72*/ NOFUN("unknown72"),
+ /*73*/ NOFUN("unknown73"),
// Experimental functions
/*74*/ DEFUN("FileIO", kFileIO, "i.*"),
@@ -464,12 +457,19 @@ SciKernelFunction kfunct_mappers[] = {
DEFUN("SetVideoMode", kSetVideoMode, "i"),
// Special and NOP stuff
- {KF_NEW, NULL, k_Unknown, NULL},
+ {NULL, k_Unknown, NULL},
- {KF_TERMINATOR, NULL, NULL, NULL} // Terminator
+ {NULL, NULL, NULL} // Terminator
};
-static const char *argtype_description[] = { "Undetermined", "List", "Node", "Object", "Reference", "Arithmetic" };
+static const char *argtype_description[] = {
+ "Undetermined",
+ "List",
+ "Node",
+ "Object",
+ "Reference",
+ "Arithmetic"
+};
Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) {
memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t
@@ -490,10 +490,6 @@ Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) {
}
Kernel::~Kernel() {
- _selectorNames.clear();
- _opcodes.clear();
- _kernelNames.clear();
- _kfuncTable.clear();
}
bool Kernel::loadSelectorNames(bool isOldSci0) {
@@ -577,7 +573,7 @@ int kfree(EngineState *s, reg_t handle) {
return 0;
}
-void kernel_compile_signature(const char **s) {
+static void kernel_compile_signature(const char **s) {
const char *src = *s;
char *result;
int ellipsis = 0;
@@ -670,50 +666,49 @@ void Kernel::mapFunctions() {
functions_nr = max_functions_nr;
}
- _kfuncTable.resize(functions_nr);
+ _kernelFuncs.resize(functions_nr);
for (uint functnr = 0; functnr < functions_nr; functnr++) {
- int seeker, found = -1;
- Common::String sought_name;
+ int found = -1;
+ // First, get the name, if known, of the kernel function with number functnr
+ Common::String sought_name;
if (functnr < getKernelNamesSize())
sought_name = getKernelName(functnr);
- if (!sought_name.empty())
- for (seeker = 0; (found == -1) && kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++)
- if (kfunct_mappers[seeker].name && sought_name == kfunct_mappers[seeker].name)
- found = seeker; // Found a kernel function with the same name!
+ // If the name is known, look it up in kfunct_mappers. This table
+ // maps kernel func names to actual function (pointers).
+ if (!sought_name.empty()) {
+ for (uint seeker = 0; (found == -1) && kfunct_mappers[seeker].name; seeker++)
+ if (sought_name == kfunct_mappers[seeker].name)
+ found = seeker; // Found a kernel function with the correct name!
+ }
+
+ // Reset the table entry
+ _kernelFuncs[functnr].fun = NULL;
+ _kernelFuncs[functnr].signature = NULL;
+ _kernelFuncs[functnr].orig_name = sought_name;
if (found == -1) {
if (!sought_name.empty()) {
- warning("Kernel function %s[%x] unmapped", getKernelName(functnr).c_str(), functnr);
- _kfuncTable[functnr].fun = kNOP;
+ // No match but a name was given -> NOP
+ warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functnr);
+ _kernelFuncs[functnr].fun = kNOP;
} else {
+ // No match and no name was given -> must be an unknown opcode
warning("Flagging kernel function %x as unknown", functnr);
- _kfuncTable[functnr].fun = k_Unknown;
+ _kernelFuncs[functnr].fun = k_Unknown;
}
-
- _kfuncTable[functnr].signature = NULL;
- _kfuncTable[functnr].orig_name = sought_name;
- } else
- switch (kfunct_mappers[found].type) {
- case KF_NONE:
- _kfuncTable[functnr].signature = NULL;
- ++ignored;
- break;
-
- case KF_NEW:
- _kfuncTable[functnr].fun = kfunct_mappers[found].fun;
- _kfuncTable[functnr].signature = kfunct_mappers[found].signature;
- _kfuncTable[functnr].orig_name.clear();
- kernel_compile_signature(&(_kfuncTable[functnr].signature));
+ } else {
+ // A match in kfunct_mappers was found
+ if (kfunct_mappers[found].fun) {
+ _kernelFuncs[functnr].fun = kfunct_mappers[found].fun;
+ _kernelFuncs[functnr].signature = kfunct_mappers[found].signature;
+ kernel_compile_signature(&(_kernelFuncs[functnr].signature));
++mapped;
- break;
- case KF_TERMINATOR:
- error("Unexpectedly encountered KF_TERMINATOR");
- break;
- }
-
+ } else
+ ++ignored;
+ }
} // for all functions requesting to be mapped
sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, getKernelNamesSize(), mapped);
@@ -724,14 +719,16 @@ void Kernel::mapFunctions() {
return;
}
-int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) {
+int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid) {
MemObject *mobj;
+ int type = 0;
if (!reg.segment) {
+ type = KSIG_ARITHMETIC;
if (!reg.offset)
- return KSIG_ARITHMETIC | KSIG_NULL;
+ type |= KSIG_NULL;
- return KSIG_ARITHMETIC;
+ return type;
}
if ((reg.segment >= s->seg_manager->_heap.size()) || !s->seg_manager->_heap[reg.segment])
@@ -752,52 +749,31 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) {
return KSIG_REF;
case MEM_OBJ_CLONES:
- if (allow_invalid || ((CloneTable *)mobj)->isValidEntry(reg.offset))
- return KSIG_OBJECT;
- else
- return KSIG_OBJECT | KSIG_INVALID;
+ type = KSIG_OBJECT;
+ break;
case MEM_OBJ_LOCALS:
- if (allow_invalid || reg.offset < (*(LocalVariables *)mobj)._locals.size() * sizeof(reg_t))
- return KSIG_REF;
- else
- return KSIG_REF | KSIG_INVALID;
-
case MEM_OBJ_STACK:
- if (allow_invalid || reg.offset < (*(DataStack *)mobj).nr * sizeof(reg_t))
- return KSIG_REF;
- else
- return KSIG_REF | KSIG_INVALID;
-
case MEM_OBJ_SYS_STRINGS:
- if (allow_invalid || (reg.offset < SYS_STRINGS_MAX
- && (*(SystemStrings *)mobj).strings[reg.offset].name))
- return KSIG_REF;
- else
- return KSIG_REF | KSIG_INVALID;
+ case MEM_OBJ_DYNMEM:
+ type = KSIG_REF;
+ break;
case MEM_OBJ_LISTS:
- if (allow_invalid || ((ListTable *)mobj)->isValidEntry(reg.offset))
- return KSIG_LIST;
- else
- return KSIG_LIST | KSIG_INVALID;
+ type = KSIG_LIST;
+ break;
case MEM_OBJ_NODES:
- if (allow_invalid || ((NodeTable *)mobj)->isValidEntry(reg.offset))
- return KSIG_NODE;
- else
- return KSIG_NODE | KSIG_INVALID;
-
- case MEM_OBJ_DYNMEM:
- if (allow_invalid || reg.offset < (*(DynMem *)mobj)._size)
- return KSIG_REF;
- else
- return KSIG_REF | KSIG_INVALID;
+ type = KSIG_NODE;
+ break;
default:
return 0;
-
}
+
+ if (!allow_invalid && !mobj->isValidOffset(reg.offset))
+ type |= KSIG_INVALID;
+ return type;
}
const char *kernel_argtype_description(int type) {
@@ -806,9 +782,10 @@ const char *kernel_argtype_description(int type) {
return argtype_description[sci_ffs(type)];
}
-int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *argv) {
+bool kernel_matches_signature(EngineState *s, const char *sig, int argc, const reg_t *argv) {
+ // Always "match" if no signature is given
if (!sig)
- return 1;
+ return true;
while (*sig && argc) {
if ((*sig & KSIG_ANY) != KSIG_ANY) {
@@ -816,17 +793,17 @@ int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *a
if (!type) {
sciprintf("[KERN] Could not determine type of ref %04x:%04x; failing signature check\n", PRINT_REG(*argv));
- return 0;
+ return false;
}
if (type & KSIG_INVALID) {
sciprintf("[KERN] ref %04x:%04x was determined to be a %s, but the reference itself is invalid\n",
PRINT_REG(*argv), kernel_argtype_description(type));
- return 0;
+ return false;
}
if (!(type & *sig))
- return 0;
+ return false;
}
if (!(*sig & KSIG_ELLIPSIS))
@@ -836,7 +813,7 @@ int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *a
}
if (argc)
- return 0; // Too many arguments
+ return false; // Too many arguments
else
return (*sig == 0 || (*sig & KSIG_ELLIPSIS));
}
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 862ca2514e..ddc3f93cb7 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -38,11 +38,6 @@ namespace Sci {
struct Node; // from vm.h
struct List; // from vm.h
-extern int stop_on_event;
-
-extern int _debug_seeking;
-extern int _debug_step_running;
-
#define AVOIDPATH_DYNMEM_STRING "AvoidPath polyline"
//#define DEBUG_PARSER // enable for parser debugging
@@ -52,12 +47,12 @@ struct opcode {
};
/* Generic description: */
-typedef reg_t kfunct(EngineState *s, int funct_nr, int argc, reg_t *argv);
+typedef reg_t KernelFunc(EngineState *s, int funct_nr, int argc, reg_t *argv);
-struct kfunct_sig_pair_t {
- kfunct *fun; /* The actual function */
- const char *signature; /* kfunct signature */
- Common::String orig_name; /* Original name, in case we couldn't map it */
+struct KernelFuncWithSignature {
+ KernelFunc *fun; /**< The actual function */
+ const char *signature; /**< KernelFunc signature */
+ Common::String orig_name; /**< Original name, in case we couldn't map it */
};
class Kernel {
@@ -93,7 +88,7 @@ public:
void dumpScriptClass(char *data, int seeker, int objsize);
selector_map_t _selectorMap; /**< Shortcut list for important selectors */
- Common::Array<kfunct_sig_pair_t> _kfuncTable; /**< Table of kernel functions */
+ Common::Array<KernelFuncWithSignature> _kernelFuncs; /**< Table of kernel functions */
private:
/**
diff --git a/engines/sci/engine/kernel_types.h b/engines/sci/engine/kernel_types.h
index 24478c9119..8927586a8e 100644
--- a/engines/sci/engine/kernel_types.h
+++ b/engines/sci/engine/kernel_types.h
@@ -64,30 +64,36 @@ namespace Sci {
#define KSIG_ALLOW_INV 0x20
#define KSIG_INVALID KSIG_ALLOW_INV
-int kernel_matches_signature(EngineState *s, const char *sig, int argc, reg_t *argv);
-/* Determines whether a list of registers matches a given signature
-** Parameters: (EngineState *) s: The state to operate on
-** (char *) sig: The signature to test against
-** (int) argc: Number of arguments to test
-** (reg_t *) argv: Argument list
-** Returns : (int) 0 iff the signature was not matched
-*/
+/**
+ * Determines whether a list of registers matches a given signature.
+ * If no signature is given (i.e., if sig is NULL), this is always
+ * treated as a match.
+ *
+ * @param s state to operate on
+ * @param sig signature to test against
+ * @param argc number of arguments to test
+ * @param argv argument list
+ * @return true if the signature was matched, false otherwise
+ */
+bool kernel_matches_signature(EngineState *s, const char *sig, int argc, const reg_t *argv);
-int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid);
-/* Determines the type of the object indicated by reg
-** Parameters: (EngineState *) s: The state to operate on
-** (reg_t) reg: The register to check
-** (int) allow_invalid: Allow invalid pointer values
-** Returns : one of KSIG_* below KSIG_NULL.
-** KSIG_INVALID set if the type of reg can be determined, but is invalid.
-** 0 on error.
-*/
+/**
+ * Determines the type of the object indicated by reg.
+ * @param s state to operate on
+ * @param reg register to check
+ * @param allow_invalid determines whether invalid pointer (=offset) values are allowed
+ * @return one of KSIG_* below KSIG_NULL.
+ * KSIG_INVALID set if the type of reg can be determined, but is invalid.
+ * 0 on error.
+ */
+int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid);
+/**
+ * Returns a textual description of the type of an object.
+ * @param type type value to describe
+ * @return pointer to a (static) descriptive string
+ */
const char *kernel_argtype_description(int type);
-/* Returns a textual description of the type of an object
-** Parameters: (int) type: The type value to describe
-** Returns: (const char *) Pointer to a (static) descriptive string
-*/
} // End of namespace Sci
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index c0a137469e..66395035c8 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -28,13 +28,12 @@
#include "sci/engine/kernel.h"
#include "sci/gfx/gfx_widgets.h"
#include "sci/gfx/gfx_state_internal.h" // required for GfxPort, GfxVisual
-#include "sci/console.h" // for debug_simulated_key
+#include "sci/console.h"
+#include "sci/debug.h" // for g_debug_simulated_key
namespace Sci {
-int stop_on_event = 0;
-extern int debug_simulated_key;
-extern bool debug_track_mouse_clicks;
+int g_stop_on_event = 0;
#define SCI_VARIABLE_GAME_SPEED 3
@@ -43,7 +42,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
reg_t obj = argv[1];
sci_event_t e;
int oldx, oldy;
- int modifier_mask = s->version <= SCI_VERSION_0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK;
+ int modifier_mask = s->_version <= SCI_VERSION_0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK;
if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) {
// Penalty time- too many requests to this function without waiting!
@@ -53,13 +52,13 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
// If there's a simkey pending, and the game wants a keyboard event, use the
// simkey instead of a normal event
- if (debug_simulated_key && (mask & SCI_EVT_KEYBOARD)) {
+ if (g_debug_simulated_key && (mask & SCI_EVT_KEYBOARD)) {
PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event
- PUT_SEL32V(obj, message, debug_simulated_key);
+ PUT_SEL32V(obj, message, g_debug_simulated_key);
PUT_SEL32V(obj, modifiers, SCI_EVM_NUMLOCK); // Numlock on
PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x);
PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y);
- debug_simulated_key = 0;
+ g_debug_simulated_key = 0;
return make_reg(0, 1);
}
@@ -91,10 +90,10 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
case SCI_EVT_KEYBOARD:
if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) {
sciprintf("Debug mode activated\n");
- _debug_seeking = _debug_step_running = 0;
+ g_debug_seeking = g_debug_step_running = 0;
} else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) {
sciprintf("Debug mode activated\n");
- _debug_seeking = _debug_step_running = 0;
+ g_debug_seeking = g_debug_step_running = 0;
} else {
PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event
s->r_acc = make_reg(0, 1);
@@ -110,7 +109,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int extra_bits = 0;
// track left buttton clicks, if requested
- if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && debug_track_mouse_clicks) {
+ if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && g_debug_track_mouse_clicks) {
((SciEngine *)g_engine)->getDebugger()->DebugPrintf("Mouse clicked at %d, %d\n",
s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y);
}
@@ -138,8 +137,8 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
s->r_acc = NULL_REG; // Unknown or no event
}
- if ((s->r_acc.offset) && (stop_on_event)) {
- stop_on_event = 0;
+ if ((s->r_acc.offset) && (g_stop_on_event)) {
+ g_stop_on_event = 0;
}
return s->r_acc;
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 11d1cb457e..87ddb46e50 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -654,7 +654,7 @@ reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if (newstate) {
s->successor = newstate;
- script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game
+ script_abort_flag = 2; // Abort current game with replay
shrink_execution_stack(s, s->execution_stack_base + 1);
} else {
s->r_acc = make_reg(0, 1);
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 4c4be0242c..1e0e675603 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -27,7 +27,7 @@
#include "common/events.h"
#include "sci/sci.h"
-#include "sci/console.h" // for debug_sleeptime_factor
+#include "sci/debug.h" // for g_debug_sleeptime_factor
#include "sci/resource.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
@@ -163,7 +163,7 @@ int _find_view_priority(EngineState *s, int y) {
return j;
return 14; // Maximum
} else {
- if (!(s->flags & GF_SCI0_OLDGFXFUNCS))
+ if (!(s->_flags & GF_SCI0_OLDGFXFUNCS))
return SCI0_VIEW_PRIORITY_14_ZONES(y);
else
return SCI0_VIEW_PRIORITY(y) == 15 ? 14 : SCI0_VIEW_PRIORITY(y);
@@ -171,7 +171,7 @@ int _find_view_priority(EngineState *s, int y) {
}
int _find_priority_band(EngineState *s, int nr) {
- if (!(s->flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 14)) {
+ if (!(s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 14)) {
if (nr == 15)
return 0xffff;
else {
@@ -180,7 +180,7 @@ int _find_priority_band(EngineState *s, int nr) {
return 0;
}
- if ((s->flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 15)) {
+ if ((s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 15)) {
warning("Attempt to get priority band %d", nr);
return 0;
}
@@ -190,7 +190,7 @@ int _find_priority_band(EngineState *s, int nr) {
else {
int retval;
- if (!(s->flags & GF_SCI0_OLDGFXFUNCS))
+ if (!(s->_flags & GF_SCI0_OLDGFXFUNCS))
retval = SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr);
else
retval = SCI0_PRIORITY_BAND_FIRST(nr);
@@ -303,8 +303,8 @@ static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int
reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
switch (argc) {
case 1 :
- if (s->version < SCI_VERSION_1_1) {
- if (SKPV(0) == 0 || SKPV(0) == 1 || SKPV(0) == -1) {
+ if (s->_version < SCI_VERSION_1_1) {
+ if (SKPV(0) <= 1) {
// Newer (SCI1.1) semantics: show/hide cursor
g_system->showMouse(SKPV(0) != 0);
} else {
@@ -317,7 +317,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
break;
case 2 :
- if (s->version < SCI_VERSION_1_1) {
+ if (s->_version < SCI_VERSION_1_1) {
// Pre-SCI1.1: set cursor according to the first parameter, and toggle its
// visibility based on the second parameter
// Some late SCI1 games actually use the SCI1.1 version of this call (EcoQuest 1
@@ -329,7 +329,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
// this would open the menu on top. LSL5 is an exception, as the game can open
// the menu when the player presses a button during the intro, but the cursor is
// not placed on (x, 0) or (x, 1)
- if (SKPV(1) == 0 || SKPV(1) == 1 || SKPV(1) == -1) {
+ if (SKPV(1) <= 1) {
GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state,
SKPV(1) == 0 ? GFXOP_NO_POINTER : SKPV(0)));
} else { // newer (SCI1.1) semantics: set pointer position
@@ -369,8 +369,6 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc;
}
-extern int oldx, oldy;
-
reg_t kMoveCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
Common::Point newpos;
@@ -647,8 +645,6 @@ reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc;
}
-extern int debug_sleeptime_factor;
-
reg_t kWait(EngineState *s, int funct_nr, int argc, reg_t *argv) {
uint32 time;
int sleep_time = UKPV(0);
@@ -660,7 +656,7 @@ reg_t kWait(EngineState *s, int funct_nr, int argc, reg_t *argv) {
// Reset optimization flags: Game is playing along nicely anyway
s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT);
- sleep_time *= debug_sleeptime_factor;
+ sleep_time *= g_debug_sleeptime_factor;
GFX_ASSERT(gfxop_sleep(s->gfx_state, sleep_time * 1000 / 60));
return s->r_acc;
@@ -689,7 +685,7 @@ void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int funct_nr, int argc,
angle %= 360;
- if (!(s->flags & GF_SCI0_OLD)) {
+ if (!(s->_flags & GF_SCI0_OLD)) {
if (angle < 45)
loop = 3;
else if (angle < 136)
@@ -773,7 +769,7 @@ static int collides_with(EngineState *s, Common::Rect area, reg_t other_obj, int
return 0;
}
-reg_t kCanBeHere(EngineState *s, int funct_nr, int argc, reg_t * argv) {
+reg_t kCanBeHere(EngineState *s, int funct_nr, int argc, reg_t *argv) {
reg_t obj = argv[0];
reg_t cliplist_ref = KP_ALT(1, NULL_REG);
List *cliplist = NULL;
@@ -1001,7 +997,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if ((argc > 1) && (UKPV(1) & K_DRAWPIC_FLAG_MIRRORED))
picFlags |= DRAWPIC1_FLAG_MIRRORED;
- if (s->flags & GF_SCI0_OLDGFXFUNCS) {
+ if (s->_flags & GF_SCI0_OLDGFXFUNCS) {
if (!SKPV_OR_ALT(2, 0))
add_to_pic = 0;
} else {
@@ -1054,7 +1050,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) {
s->priority_first = 42;
- if (s->flags & GF_SCI0_OLDGFXFUNCS)
+ if (s->_flags & GF_SCI0_OLDGFXFUNCS)
s->priority_last = 200;
else
s->priority_last = 190;
@@ -1139,7 +1135,7 @@ void _k_base_setter(EngineState *s, reg_t object) {
// does not exist (earliest one was KQ4 SCI, version 0.000.274). This code is left here
// for reference only
#if 0
- if (s->version <= SCI_VERSION_0)
+ if (s->_version <= SCI_VERSION_0)
--absrect.top; // Compensate for early SCI OB1 'bug'
#endif
@@ -1350,7 +1346,7 @@ static void _k_disable_delete_for_now(EngineState *s, reg_t obj) {
* that game - bringing the save/load dialog on a par with SCI0.
*/
if (type == K_CONTROL_BUTTON && text && (s->_gameName == "sq4") &&
- s->version < SCI_VERSION_1_1 && !strcmp(text, " Delete ")) {
+ s->_version < SCI_VERSION_1_1 && !strcmp(text, " Delete ")) {
PUT_SEL32V(obj, state, (state | kControlStateDisabled) & ~kControlStateEnabled);
}
}
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 029954d00f..43d1f25e01 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -310,7 +310,7 @@ reg_t kAddToFront(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
reg_t kAddAfter(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- List *l =lookup_list(s, argv[0]);
+ List *l = lookup_list(s, argv[0]);
Node *firstnode = argv[1].isNull() ? NULL : lookup_node(s, argv[1]);
Node *newnode = lookup_node(s, argv[2]);
@@ -341,12 +341,11 @@ reg_t kAddAfter(EngineState *s, int funct_nr, int argc, reg_t *argv) {
else
lookup_node(s, oldnext)->pred = argv[2];
- return s->r_acc;
} else { // !firstnode
- // Prepare call to AddToFront...
- argv[1] = argv[0];
- return kAddToFront(s, funct_nr, 2, argv + 1); // Set as initial list node
+ _k_add_to_front(s, argv[0], argv[2]); // Set as initial list node
}
+
+ return s->r_acc;
}
reg_t kAddToEnd(EngineState *s, int funct_nr, int argc, reg_t *argv) {
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 34d8b5397c..2e86362404 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -28,6 +28,7 @@
#include <time.h> // FIXME: For struct tm
#include "sci/sci.h"
+#include "sci/debug.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/gc.h"
@@ -95,7 +96,7 @@ reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) {
reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) {
sciprintf("Debug mode activated\n");
- _debug_seeking = _debug_step_running = 0;
+ g_debug_seeking = g_debug_step_running = 0;
return s->r_acc;
}
@@ -120,7 +121,7 @@ reg_t kGetTime(EngineState *s, int funct_nr, int argc, reg_t *argv) {
g_system->getTimeAndDate(loc_time);
start_time = g_system->getMillis() - s->game_start_time;
- if ((s->flags & GF_SCI0_OLDGETTIME) && argc) { // Use old semantics
+ if ((s->_flags & GF_SCI0_OLDGETTIME) && argc) { // Use old semantics
retval = (loc_time.tm_hour % 12) * 3600 + loc_time.tm_min * 60 + loc_time.tm_sec;
debugC(2, kDebugLevelTime, "GetTime(timeofday) returns %d", retval);
return make_reg(0, retval);
@@ -248,7 +249,7 @@ reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
reg_t kNOP(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- warning("Kernel function 0x%02x (%s) invoked: unmapped", funct_nr, s->_kernel->_kfuncTable[funct_nr].orig_name.c_str());
+ warning("Kernel function 0x%02x (%s) invoked: unmapped", funct_nr, s->_kernel->_kernelFuncs[funct_nr].orig_name.c_str());
return NULL_REG;
}
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index cd4307678b..b116fa4093 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -273,7 +273,7 @@ static void bresenham_autodetect(EngineState *s) {
}
buf = s->seg_manager->getScript(fptr.segment)->buf + fptr.offset;
- handle_movecnt = (s->version <= SCI_VERSION_0 || checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT;
+ handle_movecnt = (s->_version <= SCI_VERSION_0 || checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT;
sciprintf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ? "ignore" : "increment");
} else {
warning("bresenham_autodetect failed");
@@ -292,7 +292,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int completed = 0;
int max_movcnt = GET_SEL32V(client, moveSpeed);
- if (s->version > SCI_VERSION_0)
+ if (s->_version > SCI_VERSION_0)
signal &= ~_K_VIEW_SIG_FLAG_HIT_OBSTACLE;
if (handle_movecnt == UNINITIALIZED)
@@ -379,7 +379,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) {
completed = 1;
}
- if (s->version > SCI_VERSION_0)
+ if (s->_version > SCI_VERSION_0)
if (completed)
invoke_selector(INV_SEL(mover, moveDone, kStopOnInvalidSelector), 0);
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index abdf2b0447..e400cb0827 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -169,7 +169,7 @@ reg_t kResCheck(EngineState *s, int funct_nr, int argc, reg_t *argv) {
uint seq = UKPV(5);
warning("ResCheck: checking for currently unsupported %s resource: module %i; tuple (%i, %i, %i, %i)",
getResourceTypeName(restype), module, noun, verb, cond, seq);
- return NULL_REG;
+ return make_reg(0, 1);
}
default:
Resource *res = s->resmgr->testResource(restype, UKPV(1));
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 3586b6b1ed..b0fbda36f9 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -154,7 +154,7 @@ void process_sound_events(EngineState *s) { /* Get all sound events, apply their
song_handle_t handle;
int cue;
- if (s->version >= SCI_VERSION_01)
+ if (s->_version >= SCI_VERSION_01)
return;
/* SCI01 and later explicitly poll for everything */
@@ -964,9 +964,9 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) {
}
reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) {
- if (s->version >= SCI_VERSION_1_1 || s->flags & GF_SCI1_NEWDOSOUND)
+ if (s->_version >= SCI_VERSION_1_1 || s->_flags & GF_SCI1_NEWDOSOUND)
return kDoSound_SCI1(s, funct_nr, argc, argv);
- else if (s->version >= SCI_VERSION_01)
+ else if (s->_version >= SCI_VERSION_01)
return kDoSound_SCI01(s, funct_nr, argc, argv);
else
return kDoSound_SCI0(s, funct_nr, argc, argv);
@@ -978,7 +978,7 @@ reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int sampleLen = 0;
if (!s->_sound._audioResource)
- s->_sound._audioResource = new AudioResource(s->resmgr, s->version);
+ s->_sound._audioResource = new AudioResource(s->resmgr, s->_version);
switch (UKPV(0)) {
case kSciAudioWPlay:
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 20f0f4793b..3898664921 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -713,7 +713,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
case K_MESSAGE_NEXT: {
reg_t bufferReg;
char *buffer = NULL;
- const char *str;
+ Common::String str;
reg_t retval;
if (func == K_MESSAGE_GET) {
@@ -735,18 +735,18 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
else
retval = make_reg(0, s->_msgState.getTalker());
} else {
- str = DUMMY_MESSAGE;
+ str = Common::String(DUMMY_MESSAGE);
retval = NULL_REG;
}
if (!bufferReg.isNull()) {
- int len = strlen(str) + 1;
+ int len = str.size() + 1;
buffer = kernel_dereference_char_pointer(s, bufferReg, len);
if (buffer) {
- strcpy(buffer, str);
+ strcpy(buffer, str.c_str());
} else {
- warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str);
+ warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str.c_str());
// Set buffer to empty string if possible
buffer = kernel_dereference_char_pointer(s, bufferReg, 1);
@@ -763,7 +763,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) {
MessageState tempState;
if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple) && tempState.getMessage())
- return make_reg(0, strlen(tempState.getText()) + 1);
+ return make_reg(0, tempState.getText().size() + 1);
else
return NULL_REG;
}
diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp
new file mode 100644
index 0000000000..c0775ae51e
--- /dev/null
+++ b/engines/sci/engine/memobj.cpp
@@ -0,0 +1,413 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "sci/sci.h"
+#include "sci/engine/memobj.h"
+#include "sci/engine/intmap.h"
+#include "sci/engine/seg_manager.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+
+namespace Sci {
+
+MemObject *MemObject::createMemObject(MemObjectType type) {
+ MemObject *mem = 0;
+ switch (type) {
+ case MEM_OBJ_SCRIPT:
+ mem = new Script();
+ break;
+ case MEM_OBJ_CLONES:
+ mem = new CloneTable();
+ break;
+ case MEM_OBJ_LOCALS:
+ mem = new LocalVariables();
+ break;
+ case MEM_OBJ_SYS_STRINGS:
+ mem = new SystemStrings();
+ break;
+ case MEM_OBJ_STACK:
+ mem = new DataStack();
+ break;
+ case MEM_OBJ_HUNK:
+ mem = new HunkTable();
+ break;
+ case MEM_OBJ_STRING_FRAG:
+ mem = new StringFrag();
+ break;
+ case MEM_OBJ_LISTS:
+ mem = new ListTable();
+ break;
+ case MEM_OBJ_NODES:
+ mem = new NodeTable();
+ break;
+ case MEM_OBJ_DYNMEM:
+ mem = new DynMem();
+ break;
+ default:
+ error("Unknown MemObject type %d", type);
+ break;
+ }
+
+ assert(mem);
+ mem->_type = type;
+ return mem;
+}
+
+void Script::freeScript() {
+ free(buf);
+ buf = NULL;
+ buf_size = 0;
+
+ _objects.clear();
+
+ delete obj_indices;
+ obj_indices = 0;
+ _codeBlocks.clear();
+}
+
+void Script::incrementLockers() {
+ lockers++;
+}
+
+void Script::decrementLockers() {
+ if (lockers > 0)
+ lockers--;
+}
+
+int Script::getLockers() const {
+ return lockers;
+}
+
+void Script::setLockers(int lockers_) {
+ lockers = lockers_;
+}
+
+void Script::setExportTableOffset(int offset) {
+ if (offset) {
+ export_table = (uint16 *)(buf + offset + 2);
+ exports_nr = READ_LE_UINT16((byte *)(export_table - 1));
+ } else {
+ export_table = NULL;
+ exports_nr = 0;
+ }
+}
+
+void Script::setSynonymsOffset(int offset) {
+ synonyms = buf + offset;
+}
+
+byte *Script::getSynonyms() const {
+ return synonyms;
+}
+
+void Script::setSynonymsNr(int n) {
+ synonyms_nr = n;
+}
+
+int Script::getSynonymsNr() const {
+ return synonyms_nr;
+}
+
+// memory operations
+
+void Script::mcpyInOut(int dst, const void *src, size_t n) {
+ if (buf) {
+ assert(dst + n <= buf_size);
+ memcpy(buf + dst, src, n);
+ }
+}
+
+int16 Script::getHeap(uint16 offset) const {
+ assert(offset + 1 < (int)buf_size);
+ return READ_LE_UINT16(buf + offset);
+// return (buf[offset] | (buf[offset+1]) << 8);
+}
+
+byte *MemObject::dereference(reg_t pointer, int *size) {
+ error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
+ PRINT_REG(pointer));
+ return NULL;
+}
+
+bool Script::isValidOffset(uint16 offset) const {
+ return offset < buf_size;
+}
+
+byte *Script::dereference(reg_t pointer, int *size) {
+ if (pointer.offset > buf_size) {
+ sciprintf("Error: Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n",
+ PRINT_REG(pointer), (uint)buf_size);
+ return NULL;
+ }
+ if (size)
+ *size = buf_size - pointer.offset;
+ return buf + pointer.offset;
+}
+
+bool LocalVariables::isValidOffset(uint16 offset) const {
+ return offset < _locals.size() * sizeof(reg_t);
+}
+
+byte *LocalVariables::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = _locals.size() * sizeof(reg_t);
+
+ // FIXME: The following doesn't seem to be endian safe.
+ // To fix this, we'd have to always treat the reg_t
+ // values stored here as in the little endian format.
+ byte *base = (byte *)&_locals[0];
+ return base + pointer.offset;
+}
+
+bool DataStack::isValidOffset(uint16 offset) const {
+ return offset < nr * sizeof(reg_t);
+}
+
+byte *DataStack::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = nr * sizeof(reg_t);
+
+ byte *base = (byte *)entries;
+ return base + pointer.offset;
+}
+
+bool DynMem::isValidOffset(uint16 offset) const {
+ return offset < _size;
+}
+
+byte *DynMem::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = _size;
+
+ byte *base = (byte *)_buf;
+ return base + pointer.offset;
+}
+
+bool SystemStrings::isValidOffset(uint16 offset) const {
+ return offset < SYS_STRINGS_MAX && strings[offset].name;
+}
+
+byte *SystemStrings::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = strings[pointer.offset].max_size;
+ if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name)
+ return (byte *)(strings[pointer.offset].value);
+
+ // This occurs in KQ5CD when interacting with certain objects
+ warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
+ return NULL;
+}
+
+
+//-------------------- script --------------------
+reg_t Script::findCanonicAddress(SegManager *segmgr, reg_t addr) {
+ addr.offset = 0;
+ return addr;
+}
+
+void Script::freeAtAddress(SegManager *segmgr, reg_t addr) {
+ /*
+ sciprintf("[GC] Freeing script %04x:%04x\n", PRINT_REG(addr));
+ if (locals_segment)
+ sciprintf("[GC] Freeing locals %04x:0000\n", locals_segment);
+ */
+
+ if (_markedAsDeleted)
+ segmgr->deallocateScript(nr);
+}
+
+void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ (*note)(param, make_reg(segId, 0));
+}
+
+void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
+ Script *script = this;
+
+ if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) {
+ int idx = RAW_GET_CLASS_INDEX(script, addr);
+ if (idx >= 0 && (uint)idx < script->_objects.size()) {
+ // Note all local variables, if we have a local variable environment
+ if (script->locals_segment)
+ (*note)(param, make_reg(script->locals_segment, 0));
+
+ Object &obj = script->_objects[idx];
+ for (uint i = 0; i < obj._variables.size(); i++)
+ (*note)(param, obj._variables[i]);
+ } else {
+ warning("Request for outgoing script-object reference at %04x:%04x yielded invalid index %d", PRINT_REG(addr), idx);
+ }
+ } else {
+ /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
+ /* Happens e.g. when we're looking into strings */
+ }
+}
+
+
+//-------------------- clones --------------------
+
+template<typename T>
+void Table<T>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ for (uint i = 0; i < _table.size(); i++)
+ if (isValidEntry(i))
+ (*note)(param, make_reg(segId, i));
+}
+
+void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
+ CloneTable *clone_table = this;
+ Clone *clone;
+
+// assert(addr.segment == _segId);
+
+ if (!clone_table->isValidEntry(addr.offset)) {
+ warning("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr));
+// BREAKPOINT();
+ return;
+ }
+
+ clone = &(clone_table->_table[addr.offset]);
+
+ // Emit all member variables (including references to the 'super' delegate)
+ for (uint i = 0; i < clone->_variables.size(); i++)
+ (*note)(param, clone->_variables[i]);
+
+ // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals.
+ (*note)(param, clone->pos);
+ //sciprintf("[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos));
+}
+
+void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) {
+ CloneTable *clone_table = this;
+ Object *victim_obj;
+
+// assert(addr.segment == _segId);
+
+ victim_obj = &(clone_table->_table[addr.offset]);
+
+#ifdef GC_DEBUG
+ if (!(victim_obj->flags & OBJECT_FLAG_FREED))
+ sciprintf("[GC] Warning: Clone %04x:%04x not reachable and not freed (freeing now)\n", PRINT_REG(addr));
+#ifdef GC_DEBUG_VERBOSE
+ else
+ sciprintf("[GC-DEBUG] Clone %04x:%04x: Freeing\n", PRINT_REG(addr));
+#endif
+#endif
+ /*
+ sciprintf("[GC] Clone %04x:%04x: Freeing\n", PRINT_REG(addr));
+ sciprintf("[GC] Clone had pos %04x:%04x\n", PRINT_REG(victim_obj->pos));
+ */
+ clone_table->freeEntry(addr.offset);
+}
+
+
+//-------------------- locals --------------------
+reg_t LocalVariables::findCanonicAddress(SegManager *segmgr, reg_t addr) {
+ // Reference the owning script
+ SegmentId owner_seg = segmgr->segGet(script_id);
+
+ assert(owner_seg >= 0);
+
+ return make_reg(owner_seg, 0);
+}
+
+void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
+// assert(addr.segment == _segId);
+
+ for (uint i = 0; i < _locals.size(); i++)
+ (*note)(param, _locals[i]);
+}
+
+
+//-------------------- stack --------------------
+reg_t DataStack::findCanonicAddress(SegManager *segmgr, reg_t addr) {
+ addr.offset = 0;
+ return addr;
+}
+
+void DataStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
+ fprintf(stderr, "Emitting %d stack entries\n", nr);
+ for (int i = 0; i < nr; i++)
+ (*note)(param, entries[i]);
+ fprintf(stderr, "DONE");
+}
+
+
+//-------------------- lists --------------------
+void ListTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+}
+
+void ListTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
+ if (!isValidEntry(addr.offset)) {
+ warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
+ return;
+ }
+
+ List *list = &(_table[addr.offset]);
+
+ note(param, list->first);
+ note(param, list->last);
+ // We could probably get away with just one of them, but
+ // let's be conservative here.
+}
+
+
+//-------------------- nodes --------------------
+void NodeTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+}
+
+void NodeTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
+ if (!isValidEntry(addr.offset)) {
+ warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
+ return;
+ }
+ Node *node = &(_table[addr.offset]);
+
+ // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us
+ // to walk around from any given node
+ note(param, node->pred);
+ note(param, node->succ);
+ note(param, node->key);
+ note(param, node->value);
+}
+
+
+//-------------------- hunk --------------------
+
+//-------------------- dynamic memory --------------------
+
+reg_t DynMem::findCanonicAddress(SegManager *segmgr, reg_t addr) {
+ addr.offset = 0;
+ return addr;
+}
+
+void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ (*note)(param, make_reg(segId, 0));
+}
+
+
+} // End of namespace Sci
diff --git a/engines/sci/engine/memobj.h b/engines/sci/engine/memobj.h
new file mode 100644
index 0000000000..c006caaddc
--- /dev/null
+++ b/engines/sci/engine/memobj.h
@@ -0,0 +1,572 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SCI_ENGINE_MEMOBJ_H
+#define SCI_ENGINE_MEMOBJ_H
+
+#include "common/serializer.h"
+#include "sci/engine/vm_types.h" // for reg_t
+
+//#include "common/util.h"
+
+namespace Sci {
+
+enum MemObjectType {
+ MEM_OBJ_INVALID = 0,
+ MEM_OBJ_SCRIPT = 1,
+ MEM_OBJ_CLONES = 2,
+ MEM_OBJ_LOCALS = 3,
+ MEM_OBJ_STACK = 4,
+ MEM_OBJ_SYS_STRINGS = 5,
+ MEM_OBJ_LISTS = 6,
+ MEM_OBJ_NODES = 7,
+ MEM_OBJ_HUNK = 8,
+ MEM_OBJ_DYNMEM = 9,
+ MEM_OBJ_STRING_FRAG = 10,
+
+ MEM_OBJ_MAX // For sanity checking
+};
+
+struct MemObject : public Common::Serializable {
+ MemObjectType _type;
+ int _segmgrId; /**< Internal value used by the seg_manager's hash map */
+
+ typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
+
+public:
+ static MemObject *createMemObject(MemObjectType type);
+
+public:
+ virtual ~MemObject() {}
+
+ inline MemObjectType getType() const { return _type; }
+ inline int getSegMgrId() const { return _segmgrId; }
+
+ /**
+ * Check whether the given offset into this memory object is valid,
+ * i.e., suitable for passing to dereference.
+ */
+ virtual bool isValidOffset(uint16 offset) const = 0;
+
+ /**
+ * Dereferences a raw memory pointer.
+ * @param reg reference to dereference
+ * @param size if not NULL, set to the theoretical maximum size of the referenced data block
+ * @return the data block referenced
+ */
+ virtual byte *dereference(reg_t pointer, int *size);
+
+ /**
+ * Finds the canonic address associated with sub_reg.
+ *
+ * For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)).
+ * This address "governs" a in the sense that deallocating c(a) will deallocate a.
+ *
+ * @param sub_addr base address whose canonic address is to be found
+ */
+ virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr) { return sub_addr; }
+
+ /**
+ * Deallocates all memory associated with the specified address.
+ * @param sub_addr address (within the given segment) to deallocate
+ */
+ virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr) {}
+
+ /**
+ * Iterates over and reports all addresses within the current segment.
+ * @param note Invoked for each address on which free_at_address() makes sense
+ * @param param parameter passed to 'note'
+ */
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {}
+
+ /**
+ * Iterates over all references reachable from the specified object.
+ * @param object object (within the current segment) to analyse
+ * @param param parameter passed to 'note'
+ * @param note Invoked for each outgoing reference within the object
+ * Note: This function may also choose to report numbers (segment 0) as adresses
+ */
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note) {}
+};
+
+
+// TODO: Implement the following class
+struct StringFrag : public MemObject {
+ virtual bool isValidOffset(uint16 offset) const { return false; }
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+struct IntMapper;
+
+enum {
+ SYS_STRINGS_MAX = 4,
+
+ SYS_STRING_SAVEDIR = 0,
+ SYS_STRING_PARSER_BASE = 1,
+
+ MAX_PARSER_BASE = 64
+};
+
+struct SystemString {
+ char *name;
+ int max_size;
+ reg_t *value;
+};
+
+struct SystemStrings : public MemObject {
+ SystemString strings[SYS_STRINGS_MAX];
+
+public:
+ SystemStrings() {
+ memset(strings, 0, sizeof(strings));
+ }
+ ~SystemStrings() {
+ for (int i = 0; i < SYS_STRINGS_MAX; i++) {
+ SystemString *str = &strings[i];
+ if (str->name) {
+ free(str->name);
+ str->name = NULL;
+
+ free(str->value);
+ str->value = NULL;
+
+ str->max_size = 0;
+ }
+ }
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+/** This struct is used to buffer the list of send calls in send_selector() */
+struct CallsStruct {
+ union {
+ reg_t func;
+ reg_t *var;
+ } address;
+ StackPtr argp;
+ int argc;
+ Selector selector;
+ StackPtr sp; /**< Stack pointer */
+ int type; /**< Same as ExecStack.type */
+};
+
+struct LocalVariables : public MemObject {
+ int script_id; /**< Script ID this local variable block belongs to */
+ Common::Array<reg_t> _locals;
+
+public:
+ LocalVariables() {
+ script_id = 0;
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+/** Clone has been marked as 'freed' */
+#define OBJECT_FLAG_FREED (0x1 << 0)
+
+struct Object {
+ int flags;
+ reg_t pos; /**< Object offset within its script; for clones, this is their base */
+ int variable_names_nr; /**< Number of variable names, may be less than variables_nr */
+ int methods_nr;
+ byte *base; /**< Points to a buffer all relative references (code, strings) point to */
+ byte *base_obj; /**< base + object offset within base */
+ uint16 *base_method; /**< Pointer to the method selector area for this object */
+ uint16 *base_vars; /**< Pointer to the varselector area for this object */
+ Common::Array<reg_t> _variables;
+};
+
+struct CodeBlock {
+ reg_t pos;
+ int size;
+};
+
+#define VM_OBJECT_GET_VARSELECTOR(obj, i) \
+ (s->_version < SCI_VERSION_1_1 ? \
+ READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \
+ *(obj->base_vars + i))
+#define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i])
+#define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \
+ (s->_version < SCI_VERSION_1_1 ? \
+ READ_LE_UINT16((byte *) (obj->base_method + i)) : \
+ READ_LE_UINT16((byte *) (obj->base_method + i*2 + 1)))
+#define VM_OBJECT_READ_FUNCTION(obj, i) \
+ (s->_version < SCI_VERSION_1_1 ? \
+ make_reg(obj->pos.segment, \
+ READ_LE_UINT16((byte *) (obj->base_method \
+ + obj->methods_nr + 1 \
+ + i))) : \
+ make_reg(obj->pos.segment, \
+ READ_LE_UINT16((byte *) (obj->base_method \
+ + i * 2 + 2))))
+
+
+
+
+struct Script : public MemObject {
+ int nr; /**< Script number */
+ byte *buf; /**< Static data buffer, or NULL if not used */
+ size_t buf_size;
+ size_t script_size;
+ size_t heap_size;
+
+ byte *synonyms; /**< Synonyms block or 0 if not present*/
+ byte *heap_start; /**< Start of heap if SCI1.1, NULL otherwise */
+ uint16 *export_table; /**< Abs. offset of the export table or 0 if not present */
+
+ IntMapper *obj_indices;
+
+ int exports_nr; /**< Number of entries in the exports table */
+ int synonyms_nr; /**< Number of entries in the synonyms block */
+ int lockers; /**< Number of classes and objects that require this script */
+
+ /**
+ * Table for objects, contains property variables.
+ * Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET,
+ * see VM_OBJECT_[GS]ET_INDEX()
+ */
+ Common::Array<Object> _objects;
+
+ int locals_offset;
+ int locals_segment; /**< The local variable segment */
+ LocalVariables *locals_block;
+
+ Common::Array<CodeBlock> _codeBlocks;
+ int relocated;
+ bool _markedAsDeleted;
+
+public:
+ Script() {
+ nr = 0;
+ buf = NULL;
+ buf_size = 0;
+ script_size = 0;
+ heap_size = 0;
+
+ synonyms = NULL;
+ heap_start = NULL;
+ export_table = NULL;
+
+ obj_indices = NULL;
+
+ locals_offset = 0;
+ locals_segment = 0;
+ locals_block = NULL;
+
+ relocated = 0;
+ _markedAsDeleted = 0;
+ }
+
+ ~Script() {
+ freeScript();
+ }
+
+ void freeScript();
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+
+ // script lock operations
+
+ /** Increments the number of lockers of this script by one. */
+ void incrementLockers();
+
+ /** Decrements the number of lockers of this script by one. */
+ void decrementLockers();
+
+ /**
+ * Retrieves the number of locks held on this script.
+ * @return the number of locks held on the previously identified script
+ */
+ int getLockers() const;
+
+ /** Sets the number of locks held on this script. */
+ void setLockers(int lockers);
+
+ /**
+ * Retrieves a pointer to the synonyms associated with this script
+ * @return pointer to the synonyms, in non-parsed format.
+ */
+ byte *getSynonyms() const;
+
+ /**
+ * Retrieves the number of synonyms associated with this script.
+ * @return the number of synonyms associated with this script
+ */
+ int getSynonymsNr() const;
+
+
+ /**
+ * Sets the script-relative offset of the exports table.
+ * @param offset script-relative exports table offset
+ */
+ void setExportTableOffset(int offset);
+
+ /**
+ * Sets the script-relative offset of the synonyms associated with this script.
+ * @param offset script-relative offset of the synonyms block
+ */
+ void setSynonymsOffset(int offset);
+
+ /**
+ * Sets the number of synonyms associated with this script,
+ * @param nr number of synonyms, as to be stored within the script
+ */
+ void setSynonymsNr(int nr);
+
+
+ /**
+ * Marks the script as deleted.
+ * This will not actually delete the script. If references remain present on the
+ * heap or the stack, the script will stay in memory in a quasi-deleted state until
+ * either unreachable (resulting in its eventual deletion) or reloaded (resulting
+ * in its data being updated).
+ */
+ void markDeleted() {
+ _markedAsDeleted = true;
+ }
+
+ /**
+ * Marks the script as not deleted.
+ */
+ void unmarkDeleted() {
+ _markedAsDeleted = false;
+ }
+
+ /**
+ * Determines whether the script is marked as being deleted.
+ */
+ bool isMarkedAsDeleted() const {
+ return _markedAsDeleted;
+ }
+
+ /**
+ * Copies a byte string into a script's heap representation.
+ * @param dst script-relative offset of the destination area
+ * @param src pointer to the data source location
+ * @param n number of bytes to copy
+ */
+ void mcpyInOut(int dst, const void *src, size_t n);
+
+
+ /**
+ * Retrieves a 16 bit value from within a script's heap representation.
+ * @param offset offset to read from
+ * @return the value read from the specified location
+ */
+ int16 getHeap(uint16 offset) const;
+};
+
+/** Data stack */
+struct DataStack : MemObject {
+ int nr; /**< Number of stack entries */
+ reg_t *entries;
+
+public:
+ DataStack() {
+ nr = 0;
+ entries = NULL;
+ }
+ ~DataStack() {
+ free(entries);
+ entries = NULL;
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+#define CLONE_USED -1
+#define CLONE_NONE -1
+
+typedef Object Clone;
+
+struct Node {
+ reg_t pred; /**< Predecessor node */
+ reg_t succ; /**< Successor node */
+ reg_t key;
+ reg_t value;
+}; /* List nodes */
+
+struct List {
+ reg_t first;
+ reg_t last;
+};
+
+struct Hunk {
+ void *mem;
+ unsigned int size;
+ const char *type;
+};
+
+template<typename T>
+struct Table : public MemObject {
+ typedef T value_type;
+ struct Entry : public T {
+ int next_free; /* Only used for free entries */
+ };
+ enum { HEAPENTRY_INVALID = -1 };
+
+
+ int first_free; /**< Beginning of a singly linked list for entries */
+ int entries_used; /**< Statistical information */
+
+ Common::Array<Entry> _table;
+
+public:
+ Table() {
+ initTable();
+ }
+
+ void initTable() {
+ entries_used = 0;
+ first_free = HEAPENTRY_INVALID;
+ _table.clear();
+ }
+
+ int allocEntry() {
+ entries_used++;
+ if (first_free != HEAPENTRY_INVALID) {
+ int oldff = first_free;
+ first_free = _table[oldff].next_free;
+
+ _table[oldff].next_free = oldff;
+ return oldff;
+ } else {
+ uint newIdx = _table.size();
+ _table.push_back(Entry());
+ _table[newIdx].next_free = newIdx; // Tag as 'valid'
+ return newIdx;
+ }
+ }
+
+ virtual bool isValidOffset(uint16 offset) const {
+ return isValidEntry(offset);
+ }
+
+ bool isValidEntry(int idx) const {
+ return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx;
+ }
+
+ virtual void freeEntry(int idx) {
+ if (idx < 0 || (uint)idx >= _table.size())
+ ::error("Table::freeEntry: Attempt to release invalid table index %d", idx);
+
+ _table[idx].next_free = first_free;
+ first_free = idx;
+ entries_used--;
+ }
+
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+};
+
+
+/* CloneTable */
+struct CloneTable : public Table<Clone> {
+ virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+/* NodeTable */
+struct NodeTable : public Table<Node> {
+ virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+/* ListTable */
+struct ListTable : public Table<List> {
+ virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+/* HunkTable */
+struct HunkTable : public Table<Hunk> {
+ virtual void freeEntry(int idx) {
+ Table<Hunk>::freeEntry(idx);
+
+ free(_table[idx].mem);
+ }
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+// Free-style memory
+struct DynMem : public MemObject {
+ int _size;
+ char *_description;
+ byte *_buf;
+
+public:
+ DynMem() : _size(0), _description(0), _buf(0) {}
+ ~DynMem() {
+ free(_description);
+ _description = NULL;
+ free(_buf);
+ _buf = NULL;
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+} // End of namespace Sci
+
+#endif // SCI_ENGINE_VM_H
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index 61151e3218..4f5efa106c 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -153,9 +153,59 @@ int MessageState::getLastModule() {
return _lastReturnedModule;
}
-char *MessageState::getText() {
- int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
- return (char *)_currentResource->data + offset;
+Common::String MessageState::getText() {
+ char *str = (char *)_currentResource->data + READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5));
+
+ Common::String strippedStr;
+ Common::String skippedSubstr;
+ bool skipping = false;
+
+ for (uint i = 0; i < strlen(str); i++) {
+ if (skipping) {
+ // Skip stage direction
+ skippedSubstr += str[i];
+
+ // Hopefully these locale-dependant functions are good enough
+ if (islower(str[i]) || isdigit(str[i])) {
+ // Lowercase or digit found, this is not a stage direction
+ strippedStr += skippedSubstr;
+ skipping = false;
+ } else if (str[i] == ')') {
+ // End of stage direction, skip trailing white space
+ while ((i + 1 < strlen(str)) && isspace(str[i + 1]))
+ i++;
+ skipping = false;
+ }
+ } else {
+ if (str[i] == '(') {
+ // Start skipping stage direction
+ skippedSubstr = str[i];
+ skipping = true;
+ } else if (str[i] == '\\') {
+ // Escape sequence
+ if ((i + 2 < strlen(str)) && isdigit(str[i + 1]) && isdigit(str[i + 2])) {
+ // Hex escape sequence
+ char hexStr[3];
+
+ hexStr[0] = str[++i];
+ hexStr[1] = str[++i];
+ hexStr[2] = 0;
+
+ char *endptr;
+ int hexNr = strtol(hexStr, &endptr, 16);
+ if (*endptr == 0)
+ strippedStr += hexNr;
+ } else if (i + 1 < strlen(str)) {
+ // Literal escape sequence
+ strippedStr += str[++i];
+ }
+ } else {
+ strippedStr += str[i];
+ }
+ }
+ }
+
+ return strippedStr;
}
void MessageState::gotoNext() {
diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h
index b1cdb8ad99..5e30095a0c 100644
--- a/engines/sci/engine/message.h
+++ b/engines/sci/engine/message.h
@@ -54,7 +54,7 @@ public:
MessageTuple getRefTuple();
int getMessage();
void gotoNext();
- char *getText();
+ Common::String getText();
int getTalker();
int getLength();
MessageTuple &getLastTuple();
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index bf099816e3..a69e96eb3d 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -458,7 +458,7 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename
SavegameMetadata meta;
meta.savegame_version = CURRENT_SAVEGAME_VERSION;
meta.savegame_name = savename;
- meta.version = s->version;
+ meta.version = s->_version;
meta.game_version = s->game_version;
meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF);
@@ -497,7 +497,7 @@ static SegmentId find_unique_seg_by_type(SegManager *self, int type) {
}
static byte *find_unique_script_block(EngineState *s, byte *buf, int type) {
- if (s->flags & GF_SCI0_OLD)
+ if (s->_flags & GF_SCI0_OLD)
buf += 2;
do {
@@ -545,7 +545,7 @@ static void load_script(EngineState *s, SegmentId seg) {
assert(scr->buf);
script = s->resmgr->findResource(kResourceTypeScript, scr->nr, 0);
- if (s->version >= SCI_VERSION_1_1)
+ if (s->_version >= SCI_VERSION_1_1)
heap = s->resmgr->findResource(kResourceTypeHeap, scr->nr, 0);
memcpy(scr->buf, script->data, script->size);
@@ -759,11 +759,9 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
}
// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch.
- retval = new EngineState();
+ retval = new EngineState(s->resmgr, s->_version, s->_flags);
// Copy some old data
- retval->version = s->version;
- retval->flags = s->flags;
retval->gfx_state = s->gfx_state;
retval->sound_mute = s->sound_mute;
retval->sound_volume = s->sound_volume;
@@ -781,8 +779,6 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
retval->gfx_state = s->gfx_state;
retval->old_screen = 0;
- retval->resmgr = s->resmgr;
-
temp = retval->_sound._songlib;
retval->_sound.sfx_init(retval->resmgr, s->sfx_init_flags);
retval->sfx_init_flags = s->sfx_init_flags;
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 1f750abe58..26ba01b440 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -26,6 +26,7 @@
// Script debugger functionality. Absolutely not threadsafe.
#include "sci/sci.h"
+#include "sci/debug.h"
#include "sci/engine/state.h"
#include "sci/engine/gc.h"
#include "sci/engine/kernel_types.h"
@@ -46,13 +47,12 @@
namespace Sci {
-int _debugstate_valid = 0; // Set to 1 while script_debug is running
-int _debug_step_running = 0; // Set to >0 to allow multiple stepping
-int _debug_commands_not_hooked = 1; // Commands not hooked to the console yet?
-int _debug_seeking = 0; // Stepping forward until some special condition is met
-int _debug_seek_level = 0; // Used for seekers that want to check their exec stack depth
-int _debug_seek_special = 0; // Used for special seeks(1)
-reg_t _debug_seek_reg = NULL_REG; // Used for special seeks(2)
+int g_debugstate_valid = 0; // Set to 1 while script_debug is running
+int g_debug_step_running = 0; // Set to >0 to allow multiple stepping
+static bool s_debug_commands_hooked = false; // Commands hooked to the console yet?
+int g_debug_seeking = 0; // Stepping forward until some special condition is met
+static int s_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth
+static int s_debug_seek_special = 0; // Used for special seeks(1)
#define _DEBUG_SEEK_NOTHING 0
#define _DEBUG_SEEK_CALLK 1 // Step forward until callk is found
@@ -91,88 +91,20 @@ struct cmd_command_t : public cmd_mm_entry_t {
const char *param;
};
-#if 0
-// Unused
-#define LOOKUP_SPECIES(species) (\
- (species >= 1000) ? species : *(s->_classtable[species].scriptposp) \
- + s->_classtable[species].class_offset)
-#endif
-
// Dummy function, so that it compiles
int con_hook_command(ConCommand command, const char *name, const char *param, const char *description) {
return 0;
}
-static const char *_debug_get_input() {
- char newinpbuf[256];
-
- printf("> ");
- if (!fgets(newinpbuf, 254, stdin))
- return NULL;
-
- size_t l = strlen(newinpbuf);
- if (l > 0 && newinpbuf[0] != '\n') {
- if (newinpbuf[l-1] == '\n') newinpbuf[l-1] = 0;
- memcpy(inputbuf, newinpbuf, 256);
- }
-
- return inputbuf;
-}
-
int c_step(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- _debugstate_valid = 0;
+ g_debugstate_valid = 0;
if (cmdParams.size() && (cmdParams[0].val > 0))
- _debug_step_running = cmdParams[0].val - 1;
+ g_debug_step_running = cmdParams[0].val - 1;
return 0;
}
-#if 0
-// TODO Re-implement con:so
-int c_stepover(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- int opcode, opnumber;
-
- if (!_debugstate_valid) {
- sciprintf("Not in debug state\n");
- return 1;
- }
-
- _debugstate_valid = 0;
- opcode = s->_heap[*p_pc];
- opnumber = opcode >> 1;
- if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ ||
- opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) {
- _debug_seeking = _DEBUG_SEEK_SO;
- _debug_seek_level = s->_executionStack.size()-1;
- // Store in _debug_seek_special the offset of the next command after send
- switch (opcode) {
- case 0x46: // calle W
- _debug_seek_special = *p_pc + 5;
- break;
-
- case 0x44: // callb W
- case 0x47: // calle B
- case 0x56: // super W
- _debug_seek_special = *p_pc + 4;
- break;
-
- case 0x45: // callb B
- case 0x57: // super B
- case 0x4A: // send W
- case 0x54: // self W
- _debug_seek_special = *p_pc + 3;
- break;
-
- default:
- _debug_seek_special = *p_pc + 2;
- }
- }
-
- return 0;
-}
-#endif
-
enum {
_parse_eoi,
_parse_token_pareno,
@@ -270,7 +202,7 @@ int prop_ofs_to_id(EngineState *s, int prop_ofs, reg_t objp) {
selectors = obj->_variables.size();
- if (s->version < SCI_VERSION_1_1)
+ if (s->_version < SCI_VERSION_1_1)
selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
else {
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) {
@@ -319,7 +251,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
opsize = scr[pos.offset];
opcode = opsize >> 1;
- if (!_debugstate_valid) {
+ if (!g_debugstate_valid) {
sciprintf("Not in debug state\n");
return retval;
}
@@ -410,7 +342,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
}
if (opcode == op_callk)
- sciprintf(" %s[%x]", (param_value < s->_kernel->_kfuncTable.size()) ?
+ sciprintf(" %s[%x]", (param_value < s->_kernel->_kernelFuncs.size()) ?
((param_value < s->_kernel->getKernelNamesSize()) ? s->_kernel->getKernelName(param_value).c_str() : "[Unknown(postulated)]")
: "<invalid>", param_value);
else
@@ -465,7 +397,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
int stackframe = (scr[pos.offset + 2] >> 1) + (*p_restadjust);
int argc = ((*p_sp)[- stackframe - 1]).offset;
- if (!(s->flags & GF_SCI0_OLD))
+ if (!(s->_flags & GF_SCI0_OLD))
argc += (*p_restadjust);
sciprintf(" Kernel params: (");
@@ -535,103 +467,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
return retval;
}
-#ifdef GFXW_DEBUG_WIDGETS
-extern GfxWidget *debug_widgets[];
-extern int debug_widget_pos;
-
-static int c_gfx_print_widget(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- if (!_debugstate_valid) {
- sciprintf("Not in debug state\n");
- return 1;
- }
-
- if (cmdParams.size()) {
- unsigned int i;
- for (i = 0; i < cmdParams.size() ; i++) {
- int widget_nr = cmdParams[i].val;
-
- sciprintf("===== Widget #%d:\n", widget_nr);
- debug_widgets[widget_nr]->print(0);
- }
-
- } else if (debug_widget_pos > 1)
- sciprintf("Widgets 0-%d are active\n", debug_widget_pos - 1);
- else if (debug_widget_pos == 1)
- sciprintf("Widget 0 is active\n");
- else
- sciprintf("No widgets are active\n");
-
- return 0;
-}
-#endif
-
-#define GETRECT(ll, rr, tt, bb) \
- ll = GET_SELECTOR(pos, ll); \
- rr = GET_SELECTOR(pos, rr); \
- tt = GET_SELECTOR(pos, tt); \
- bb = GET_SELECTOR(pos, bb);
-
-#if 0
-// Unreferenced - removed
-static int c_gfx_draw_viewobj(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
-// TODO: Re-implement gfx_draw_viewobj
-#if 0
- HeapPtr pos = (HeapPtr)(cmdParams[0].val);
- int is_view;
- int x, y, priority;
- int nsLeft, nsRight, nsBottom, nsTop;
- int brLeft, brRight, brBottom, brTop;
-
- if (!s) {
- sciprintf("Not in debug state!\n");
- return 1;
- }
-
- if ((pos < 4) || (pos > 0xfff0)) {
- sciprintf("Invalid address.\n");
- return 1;
- }
-
- if (((int16)READ_LE_UINT16(s->heap + pos + SCRIPT_OBJECT_MAGIC_OFFSET)) != SCRIPT_OBJECT_MAGIC_NUMBER) {
- sciprintf("Not an object.\n");
- return 0;
- }
-
-
- is_view = (lookup_selector(s, pos, s->_kernel->_selectorMap.x, NULL) == kSelectorVariable) &&
- (lookup_selector(s, pos, s->_kernel->_selectorMap.brLeft, NULL) == kSelectorVariable) &&
- (lookup_selector(s, pos, s->_kernel->_selectorMap.signal, NULL) == kSelectorVariable) &&
- (lookup_selector(s, pos, s->_kernel->_selectorMap.nsTop, NULL) == kSelectorVariable);
-
- if (!is_view) {
- sciprintf("Not a dynamic View object.\n");
- return 0;
- }
-
- x = GET_SELECTOR(pos, x);
- y = GET_SELECTOR(pos, y);
- priority = GET_SELECTOR(pos, priority);
- GETRECT(brLeft, brRight, brBottom, brTop);
- GETRECT(nsLeft, nsRight, nsBottom, nsTop);
- gfxop_set_clip_zone(s->gfx_state, gfx_rect_fullscreen);
-
- brTop += 10;
- brBottom += 10;
- nsTop += 10;
- nsBottom += 10;
-
- gfxop_fill_box(s->gfx_state, gfx_rect(nsLeft, nsTop, nsRight - nsLeft + 1, nsBottom - nsTop + 1), s->ega_colors[2]);
- gfxop_fill_box(s->gfx_state, gfx_rect(brLeft, brTop, brRight - brLeft + 1, brBottom - brTop + 1), s->ega_colors[1]);
- gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y - 1, 3, 3), s->ega_colors[0]);
- gfxop_fill_box(s->gfx_state, gfx_rect(x - 1, y, 3, 1), s->ega_colors[priority]);
- gfxop_fill_box(s->gfx_state, gfx_rect(x, y - 1, 1, 3), s->ega_colors[priority]);
- gfxop_update(s->gfx_state);
-
- return 0;
-#endif
-}
-#endif
-
static int c_disasm_addr(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
reg_t vpc = cmdParams[0].reg;
int op_count = 1;
@@ -695,9 +530,9 @@ static int c_disasm(EngineState *s, const Common::Array<cmd_param_t> &cmdParams)
}
static int c_sg(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- _debug_seeking = _DEBUG_SEEK_GLOBAL;
- _debug_seek_special = cmdParams[0].val;
- _debugstate_valid = 0;
+ g_debug_seeking = _DEBUG_SEEK_GLOBAL;
+ s_debug_seek_special = cmdParams[0].val;
+ g_debugstate_valid = 0;
return 0;
}
@@ -706,7 +541,7 @@ static int c_snk(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
int callk_index;
char *endptr;
- if (!_debugstate_valid) {
+ if (!g_debugstate_valid) {
sciprintf("Not in debug state\n");
return 1;
}
@@ -730,27 +565,27 @@ static int c_snk(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
}
}
- _debug_seeking = _DEBUG_SEEK_SPECIAL_CALLK;
- _debug_seek_special = callk_index;
- _debugstate_valid = 0;
+ g_debug_seeking = _DEBUG_SEEK_SPECIAL_CALLK;
+ s_debug_seek_special = callk_index;
+ g_debugstate_valid = 0;
} else {
- _debug_seeking = _DEBUG_SEEK_CALLK;
- _debugstate_valid = 0;
+ g_debug_seeking = _DEBUG_SEEK_CALLK;
+ g_debugstate_valid = 0;
}
return 0;
}
static int c_sret(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- _debug_seeking = _DEBUG_SEEK_LEVEL_RET;
- _debug_seek_level = s->_executionStack.size()-1;
- _debugstate_valid = 0;
+ g_debug_seeking = _DEBUG_SEEK_LEVEL_RET;
+ s_debug_seek_level = s->_executionStack.size()-1;
+ g_debugstate_valid = 0;
return 0;
}
static int c_go(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- _debug_seeking = 0;
- _debugstate_valid = 0;
+ g_debug_seeking = 0;
+ g_debugstate_valid = 0;
return 0;
}
@@ -810,97 +645,11 @@ static int c_send(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
return 0;
}
-
-#define GETRECT(ll, rr, tt, bb) \
- ll = GET_SELECTOR(pos, ll); \
- rr = GET_SELECTOR(pos, rr); \
- tt = GET_SELECTOR(pos, tt); \
- bb = GET_SELECTOR(pos, bb);
-
-#if 0
-#ifdef __GNUC__
-#warning "Re-implement viewobjinfo"
-#endif
-static void viewobjinfo(EngineState *s, HeapPtr pos) {
- char *signals[16] = {
- "stop_update",
- "updated",
- "no_update",
- "hidden",
- "fixed_priority",
- "always_update",
- "force_update",
- "remove",
- "frozen",
- "is_extra",
- "hit_obstacle",
- "doesnt_turn",
- "no_cycler",
- "ignore_horizon",
- "ignore_actor",
- "dispose!"
- };
-
- int x, y, z, priority;
- int cel, loop, view, signal;
- int nsLeft, nsRight, nsBottom, nsTop;
- int lsLeft, lsRight, lsBottom, lsTop;
- int brLeft, brRight, brBottom, brTop;
- int i;
- int have_rects = 0;
- Common::Rect nsrect, nsrect_clipped, brrect;
-
- if (lookup_selector(s, pos, s->_kernel->_selectorMap.nsBottom, NULL) == kSelectorVariable) {
- GETRECT(nsLeft, nsRight, nsBottom, nsTop);
- GETRECT(lsLeft, lsRight, lsBottom, lsTop);
- GETRECT(brLeft, brRight, brBottom, brTop);
- have_rects = 1;
- }
-
- GETRECT(view, loop, signal, cel);
-
- sciprintf("\n-- View information:\ncel %d/%d/%d at ", view, loop, cel);
-
- x = GET_SELECTOR(pos, x);
- y = GET_SELECTOR(pos, y);
- priority = GET_SELECTOR(pos, priority);
- if (s->_kernel->_selectorMap.z > 0) {
- z = GET_SELECTOR(pos, z);
- sciprintf("(%d,%d,%d)\n", x, y, z);
- } else
- sciprintf("(%d,%d)\n", x, y);
-
- if (priority == -1)
- sciprintf("No priority.\n\n");
- else
- sciprintf("Priority = %d (band starts at %d)\n\n", priority, PRIORITY_BAND_FIRST(priority));
-
- if (have_rects) {
- sciprintf("nsRect: [%d..%d]x[%d..%d]\n", nsLeft, nsRight, nsTop, nsBottom);
- sciprintf("lsRect: [%d..%d]x[%d..%d]\n", lsLeft, lsRight, lsTop, lsBottom);
- sciprintf("brRect: [%d..%d]x[%d..%d]\n", brLeft, brRight, brTop, brBottom);
- }
-
- nsrect = get_nsrect(s, pos, 0);
- nsrect_clipped = get_nsrect(s, pos, 1);
- brrect = set_base(s, pos);
- sciprintf("new nsRect: [%d..%d]x[%d..%d]\n", nsrect.x, nsrect.xend, nsrect.y, nsrect.yend);
- sciprintf("new clipped nsRect: [%d..%d]x[%d..%d]\n", nsrect_clipped.x, nsrect_clipped.xend, nsrect_clipped.y, nsrect_clipped.yend);
- sciprintf("new brRect: [%d..%d]x[%d..%d]\n", brrect.x, brrect.xend, brrect.y, brrect.yend);
- sciprintf("\n signals = %04x:\n", signal);
-
- for (i = 0; i < 16; i++)
- if (signal & (1 << i))
- sciprintf(" %04x: %s\n", 1 << i, signals[i]);
-}
-#endif
-#undef GETRECT
-
// Breakpoint commands
int c_se(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) {
- stop_on_event = 1;
- _debugstate_valid = 0;
+ g_stop_on_event = 1;
+ g_debugstate_valid = 0;
return 0;
}
@@ -909,7 +658,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) {
// Do we support a separate console?
- int old_debugstate = _debugstate_valid;
+ int old_debugstate = g_debugstate_valid;
p_var_segs = segids;
p_vars = variables;
@@ -921,15 +670,15 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
p_objp = objp;
p_restadjust = restadjust;
sciprintf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc));
- _debugstate_valid = 1;
+ g_debugstate_valid = 1;
disassemble(s, *pc, 0, 1);
- if (_debug_seeking == _DEBUG_SEEK_GLOBAL)
- sciprintf("Global %d (0x%x) = %04x:%04x\n", _debug_seek_special,
- _debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[_debug_seek_special]));
+ if (g_debug_seeking == _DEBUG_SEEK_GLOBAL)
+ sciprintf("Global %d (0x%x) = %04x:%04x\n", s_debug_seek_special,
+ s_debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[s_debug_seek_special]));
- _debugstate_valid = old_debugstate;
+ g_debugstate_valid = old_debugstate;
- if (_debug_seeking && !bp) { // Are we looking for something special?
+ if (g_debug_seeking && !bp) { // Are we looking for something special?
MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT);
if (mobj) {
@@ -941,9 +690,9 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
int paramb1 = pc->offset + 1 >= code_buf_size ? 0 : code_buf[pc->offset + 1];
int paramf1 = (opcode & 1) ? paramb1 : (pc->offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + pc->offset + 1));
- switch (_debug_seeking) {
+ switch (g_debug_seeking) {
case _DEBUG_SEEK_SPECIAL_CALLK:
- if (paramb1 != _debug_seek_special)
+ if (paramb1 != s_debug_seek_special)
return;
case _DEBUG_SEEK_CALLK: {
@@ -953,38 +702,32 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
}
case _DEBUG_SEEK_LEVEL_RET: {
- if ((op != op_ret) || (_debug_seek_level < (int)s->_executionStack.size()-1))
+ if ((op != op_ret) || (s_debug_seek_level < (int)s->_executionStack.size()-1))
return;
break;
}
- case _DEBUG_SEEK_SO:
- if ((*pc != _debug_seek_reg) || (int)s->_executionStack.size()-1 != _debug_seek_level)
- return;
- break;
-
case _DEBUG_SEEK_GLOBAL:
-
if (op < op_sag)
return;
if ((op & 0x3) > 1)
return; // param or temp
if ((op & 0x3) && s->_executionStack.back().local_segment > 0)
return; // locals and not running in script.000
- if (paramf1 != _debug_seek_special)
+ if (paramf1 != s_debug_seek_special)
return; // CORRECT global?
break;
}
- _debug_seeking = _DEBUG_SEEK_NOTHING;
+ g_debug_seeking = _DEBUG_SEEK_NOTHING;
// OK, found whatever we were looking for
}
}
- _debugstate_valid = (_debug_step_running == 0);
+ g_debugstate_valid = (g_debug_step_running == 0);
- if (_debugstate_valid) {
+ if (g_debugstate_valid) {
p_pc = pc;
p_sp = sp;
p_pp = pp;
@@ -998,15 +741,11 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
sciprintf("Step #%d\n", script_step_counter);
disassemble(s, *pc, 0, 1);
- if (_debug_commands_not_hooked) {
- _debug_commands_not_hooked = 0;
+ if (!s_debug_commands_hooked) {
+ s_debug_commands_hooked = true;
con_hook_command(c_step, "s", "i*", "Executes one or several operations\n\nEXAMPLES\n\n"
" s 4\n\n Execute 4 commands\n\n s\n\n Execute next command");
-#if 0
- // TODO Re-implement con:so
- con_hook_command(c_stepover, "so", "", "Executes one operation skipping over sends");
-#endif
con_hook_command(c_disasm_addr, "disasm-addr", "!as*", "Disassembles one or more commands\n\n"
"USAGE\n\n disasm-addr [startaddr] <options>\n\n"
" Valid options are:\n"
@@ -1022,50 +761,15 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
con_hook_command(c_go, "go", "", "Executes the script.\n");
con_hook_command(c_set_parse_nodes, "set_parse_nodes", "s*", "Sets the contents of all parse nodes.\n"
" Input token must be separated by\n blanks.");
-
-#ifdef GFXW_DEBUG_WIDGETS
- con_hook_command(c_gfx_print_widget, "gfx_print_widget", "i*", "If called with no parameters, it\n shows which widgets are active.\n"
- " With parameters, it lists the\n widget corresponding to the\n numerical index specified (for\n each parameter).");
-#endif
-
-#if 0
- // TODO: Re-enable con:draw_viewobj
- con_hook_command(c_gfx_draw_viewobj, "draw_viewobj", "i", "Draws the nsRect and brRect of a\n dynview object.\n\n nsRect is green, brRect\n"
- " is blue.\n");
-#endif
con_hook_command(c_sg, "sg", "!i",
"Steps until the global variable with the\n"
"specified index is modified.\n\nSEE ALSO\n\n"
" s.1, snk.1, so.1, bpx.1");
-/*
- con_hook_int(&script_abort_flag, "script_abort_flag", "Set != 0 to abort execution\n");
-*/
} // If commands were not hooked up
}
- if (_debug_step_running)
- _debug_step_running--;
-
- while (_debugstate_valid) {
- int skipfirst = 0;
- const char *commandstring;
-
- // Suspend music playing
- s->_sound.sfx_suspend(true);
-
- commandstring = _debug_get_input();
-
- // Check if a specific destination has been given
- if (commandstring && (commandstring[0] == '.' || commandstring[0] == ':'))
- skipfirst = 1;
-
- //if (commandstring && commandstring[0] != ':')
- // con_parse(s, commandstring + skipfirst);
- sciprintf("\n");
-
- // Resume music playing
- s->_sound.sfx_suspend(false);
- }
+ if (g_debug_step_running)
+ g_debug_step_running--;
}
} // End of namespace Sci
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 69a939dae9..dcf7180501 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -135,13 +135,13 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) {
scr.script_size = script->size;
scr.heap_size = 0; // Set later
- if (!script || (s->version >= SCI_VERSION_1_1 && !heap)) {
+ if (!script || (s->_version >= SCI_VERSION_1_1 && !heap)) {
error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
}
- if (s->flags & GF_SCI0_OLD) {
+ if (s->_flags & GF_SCI0_OLD) {
scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2;
//locals_size = READ_LE_UINT16(script->data) * 2;
- } else if (s->version < SCI_VERSION_1_1) {
+ } else if (s->_version < SCI_VERSION_1_1) {
scr.buf_size = script->size;
} else {
scr.buf_size = script->size + heap->size;
@@ -189,7 +189,7 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) {
scr.obj_indices = new IntMapper();
- if (s->version >= SCI_VERSION_1_1)
+ if (s->_version >= SCI_VERSION_1_1)
scr.heap_start = scr.buf + scr.script_size;
else
scr.heap_start = scr.buf;
@@ -232,49 +232,6 @@ int SegManager::deallocateScript(int script_nr) {
return 1;
}
-MemObject *MemObject::createMemObject(MemObjectType type) {
- MemObject *mem = 0;
- switch (type) {
- case MEM_OBJ_SCRIPT:
- mem = new Script();
- break;
- case MEM_OBJ_CLONES:
- mem = new CloneTable();
- break;
- case MEM_OBJ_LOCALS:
- mem = new LocalVariables();
- break;
- case MEM_OBJ_SYS_STRINGS:
- mem = new SystemStrings();
- break;
- case MEM_OBJ_STACK:
- mem = new DataStack();
- break;
- case MEM_OBJ_HUNK:
- mem = new HunkTable();
- break;
- case MEM_OBJ_STRING_FRAG:
- mem = new StringFrag();
- break;
- case MEM_OBJ_LISTS:
- mem = new ListTable();
- break;
- case MEM_OBJ_NODES:
- mem = new NodeTable();
- break;
- case MEM_OBJ_DYNMEM:
- mem = new DynMem();
- break;
- default:
- error("Unknown MemObject type %d", type);
- break;
- }
-
- assert(mem);
- mem->_type = type;
- return mem;
-}
-
MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectType type) {
MemObject *mem = MemObject::createMemObject(type);
if (!mem) {
@@ -294,33 +251,6 @@ MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectTyp
return mem;
}
-void Script::freeScript() {
- free(buf);
- buf = NULL;
- buf_size = 0;
-
- _objects.clear();
-
- delete obj_indices;
- obj_indices = 0;
- _codeBlocks.clear();
-}
-
-// memory operations
-
-void Script::mcpyInOut(int dst, const void *src, size_t n) {
- if (buf) {
- assert(dst + n <= buf_size);
- memcpy(buf + dst, src, n);
- }
-}
-
-int16 Script::getHeap(uint16 offset) const {
- VERIFY(offset + 1 < (int)buf_size, "invalid offset\n");
- return READ_LE_UINT16(buf + offset);
-// return (buf[offset] | (buf[offset+1]) << 8);
-}
-
// return the seg if script_id is valid and in the map, else -1
SegmentId SegManager::segGet(int script_id) const {
return id_seg_map->lookupKey(script_id);
@@ -367,53 +297,10 @@ bool SegManager::scriptIsLoaded(SegmentId seg) {
return getScriptIfLoaded(seg) != 0;
}
-void Script::incrementLockers() {
- lockers++;
-}
-
-void Script::decrementLockers() {
- if (lockers > 0)
- lockers--;
-}
-
-int Script::getLockers() const {
- return lockers;
-}
-
-void Script::setLockers(int lockers_) {
- lockers = lockers_;
-}
-
-void Script::setExportTableOffset(int offset) {
- if (offset) {
- export_table = (uint16 *)(buf + offset + 2);
- exports_nr = READ_LE_UINT16((byte *)(export_table - 1));
- } else {
- export_table = NULL;
- exports_nr = 0;
- }
-}
-
void SegManager::setExportWidth(int flag) {
exports_wide = flag;
}
-void Script::setSynonymsOffset(int offset) {
- synonyms = buf + offset;
-}
-
-byte *Script::getSynonyms() const {
- return synonyms;
-}
-
-void Script::setSynonymsNr(int n) {
- synonyms_nr = n;
-}
-
-int Script::getSynonymsNr() const {
- return synonyms_nr;
-}
-
int SegManager::relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location) {
int rel = location - block_location;
@@ -925,67 +812,6 @@ Hunk *SegManager::alloc_Hunk(reg_t *addr) {
return &(table->_table[offset]);
}
-byte *MemObject::dereference(reg_t pointer, int *size) {
- error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
- PRINT_REG(pointer));
- return NULL;
-}
-
-byte *Script::dereference(reg_t pointer, int *size) {
- if (pointer.offset > buf_size) {
- sciprintf("Error: Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n",
- PRINT_REG(pointer), (uint)buf_size);
- return NULL;
- }
- if (size)
- *size = buf_size - pointer.offset;
- return (byte *)(buf + pointer.offset);
-}
-
-byte *LocalVariables::dereference(reg_t pointer, int *size) {
- // FIXME: The following doesn't seem to be endian safe.
- // To fix this, we'd have to always treat the reg_t
- // values stored here as in the little endian format.
- int count = _locals.size() * sizeof(reg_t);
- byte *base = (byte *)&_locals[0];
-
- if (size)
- *size = count;
-
- return base + pointer.offset;
-}
-
-byte *DataStack::dereference(reg_t pointer, int *size) {
- int count = nr * sizeof(reg_t);
- byte *base = (byte *)entries;
-
- if (size)
- *size = count;
-
- return base + pointer.offset;
-}
-
-byte *DynMem::dereference(reg_t pointer, int *size) {
- int count = _size;
- byte *base = (byte *)_buf;
-
- if (size)
- *size = count;
-
- return base + pointer.offset;
-}
-
-byte *SystemStrings::dereference(reg_t pointer, int *size) {
- if (size)
- *size = strings[pointer.offset].max_size;
- if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name)
- return (byte *)(strings[pointer.offset].value);
-
- // This occurs in KQ5CD when interacting with certain objects
- warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
- return NULL;
-}
-
byte *SegManager::dereference(reg_t pointer, int *size) {
if (!pointer.segment || (pointer.segment >= _heap.size()) || !_heap[pointer.segment]) {
// This occurs in KQ5CD when interacting with certain objects
@@ -1048,191 +874,5 @@ void SegManager::dbgPrint(const char* msg, void *i) {
}
-//-------------------- script --------------------
-reg_t Script::findCanonicAddress(SegManager *segmgr, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void Script::freeAtAddress(SegManager *segmgr, reg_t addr) {
- /*
- sciprintf("[GC] Freeing script %04x:%04x\n", PRINT_REG(addr));
- if (locals_segment)
- sciprintf("[GC] Freeing locals %04x:0000\n", locals_segment);
- */
-
- if (_markedAsDeleted)
- segmgr->deallocateScript(nr);
-}
-
-void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- (*note)(param, make_reg(segId, 0));
-}
-
-void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
- Script *script = this;
-
- if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) {
- int idx = RAW_GET_CLASS_INDEX(script, addr);
- if (idx >= 0 && (uint)idx < script->_objects.size()) {
- // Note all local variables, if we have a local variable environment
- if (script->locals_segment)
- (*note)(param, make_reg(script->locals_segment, 0));
-
- Object &obj = script->_objects[idx];
- for (uint i = 0; i < obj._variables.size(); i++)
- (*note)(param, obj._variables[i]);
- } else {
- warning("Request for outgoing script-object reference at %04x:%04x yielded invalid index %d", PRINT_REG(addr), idx);
- }
- } else {
- /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
- /* Happens e.g. when we're looking into strings */
- }
-}
-
-
-//-------------------- clones --------------------
-
-template<typename T>
-void Table<T>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- for (uint i = 0; i < _table.size(); i++)
- if (isValidEntry(i))
- (*note)(param, make_reg(segId, i));
-}
-
-void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
- CloneTable *clone_table = this;
- Clone *clone;
-
-// assert(addr.segment == _segId);
-
- if (!clone_table->isValidEntry(addr.offset)) {
- warning("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr));
-// BREAKPOINT();
- return;
- }
-
- clone = &(clone_table->_table[addr.offset]);
-
- // Emit all member variables (including references to the 'super' delegate)
- for (uint i = 0; i < clone->_variables.size(); i++)
- (*note)(param, clone->_variables[i]);
-
- // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals.
- (*note)(param, clone->pos);
- //sciprintf("[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos));
-}
-
-void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) {
- CloneTable *clone_table = this;
- Object *victim_obj;
-
-// assert(addr.segment == _segId);
-
- victim_obj = &(clone_table->_table[addr.offset]);
-
-#ifdef GC_DEBUG
- if (!(victim_obj->flags & OBJECT_FLAG_FREED))
- sciprintf("[GC] Warning: Clone %04x:%04x not reachable and not freed (freeing now)\n", PRINT_REG(addr));
-#ifdef GC_DEBUG_VERBOSE
- else
- sciprintf("[GC-DEBUG] Clone %04x:%04x: Freeing\n", PRINT_REG(addr));
-#endif
-#endif
- /*
- sciprintf("[GC] Clone %04x:%04x: Freeing\n", PRINT_REG(addr));
- sciprintf("[GC] Clone had pos %04x:%04x\n", PRINT_REG(victim_obj->pos));
- */
- clone_table->freeEntry(addr.offset);
-}
-
-
-//-------------------- locals --------------------
-reg_t LocalVariables::findCanonicAddress(SegManager *segmgr, reg_t addr) {
- // Reference the owning script
- SegmentId owner_seg = segmgr->segGet(script_id);
-
- assert(owner_seg >= 0);
-
- return make_reg(owner_seg, 0);
-}
-
-void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
-// assert(addr.segment == _segId);
-
- for (uint i = 0; i < _locals.size(); i++)
- (*note)(param, _locals[i]);
-}
-
-
-//-------------------- stack --------------------
-reg_t DataStack::findCanonicAddress(SegManager *segmgr, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void DataStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
- fprintf(stderr, "Emitting %d stack entries\n", nr);
- for (int i = 0; i < nr; i++)
- (*note)(param, entries[i]);
- fprintf(stderr, "DONE");
-}
-
-
-//-------------------- lists --------------------
-void ListTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
-
-void ListTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
- if (!isValidEntry(addr.offset)) {
- warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
- }
-
- List *list = &(_table[addr.offset]);
-
- note(param, list->first);
- note(param, list->last);
- // We could probably get away with just one of them, but
- // let's be conservative here.
-}
-
-
-//-------------------- nodes --------------------
-void NodeTable::freeAtAddress(SegManager *segmgr, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
-
-void NodeTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
- if (!isValidEntry(addr.offset)) {
- warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
- }
- Node *node = &(_table[addr.offset]);
-
- // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us
- // to walk around from any given node
- note(param, node->pred);
- note(param, node->succ);
- note(param, node->key);
- note(param, node->value);
-}
-
-
-//-------------------- hunk --------------------
-
-//-------------------- dynamic memory --------------------
-
-reg_t DynMem::findCanonicAddress(SegManager *segmgr, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- (*note)(param, make_reg(segId, 0));
-}
-
} // End of namespace Sci
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 643385fd74..dc91d60e69 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -29,6 +29,7 @@
#include "common/scummsys.h"
#include "common/serializer.h"
#include "sci/engine/vm.h"
+#include "sci/engine/memobj.h"
namespace Sci {
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 5936c4fedb..0e4b63acee 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -27,11 +27,10 @@
namespace Sci {
-EngineState::EngineState() : _dirseeker(this) {
+EngineState::EngineState(ResourceManager *res, sci_version_t version, uint32 flags)
+: resmgr(res), _version(version), _flags(flags), _dirseeker(this) {
widget_serial_counter = 0;
- resmgr = 0;
-
game_version = 0;
gfx_state = 0;
@@ -80,9 +79,6 @@ EngineState::EngineState() : _dirseeker(this) {
last_wait_time = 0;
- version = 0;
- flags = 0;
-
kernel_opt_flags = 0;
_fileHandles.resize(5);
@@ -126,5 +122,8 @@ EngineState::EngineState() : _dirseeker(this) {
EngineState::~EngineState() {
}
+uint16 EngineState::currentRoomNumber() const {
+ return KP_UINT(script_000->locals_block->_locals[13]);
+}
} // End of namespace Sci
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index 0623aa35fd..15c1c2e63e 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -48,7 +48,6 @@ namespace Common {
namespace Sci {
class Menubar;
-struct kfunct_sig_pair_t; // from kernel.h
struct GfxState;
struct GfxPort;
@@ -110,7 +109,7 @@ public:
struct EngineState : public Common::Serializable {
public:
- EngineState();
+ EngineState(ResourceManager *res, sci_version_t version, uint32 flags);
virtual ~EngineState();
virtual void saveLoadWithSerializer(Common::Serializer &ser);
@@ -119,6 +118,9 @@ public:
ResourceManager *resmgr; /**< The resource manager */
+ const sci_version_t _version; /**< The approximated patchlevel of the version to emulate */
+ const uint32 _flags; /**< Specific game flags */
+
Common::String _gameName; /**< Designation of the primary object (which inherits from Game) */
char *game_version;
@@ -175,9 +177,6 @@ public:
uint32 game_start_time; /**< The time at which the interpreter was started */
uint32 last_wait_time; /**< The last time the game invoked Wait() */
- sci_version_t version; /**< The approximated patchlevel of the version to emulate */
- uint32 flags; /**< Specific game flags */
-
unsigned int kernel_opt_flags; /**< Kernel optimization flags- used for performance tweaking */
/* Kernel File IO stuff */
@@ -208,7 +207,7 @@ public:
reg_t parser_event; /**< The event passed to Parse() and later used by Said() */
Script *script_000; /**< script 000, e.g. for globals */
- uint16 currentRoomNumber() const { return KP_UINT(script_000->locals_block->_locals[13]); }
+ uint16 currentRoomNumber() const;
/* Debugger data: */
Breakpoint *bp_list; /**< List of breakpoints */
@@ -250,6 +249,13 @@ public:
*/
PaletteEntry get_pic_color(EngineState *s, int color);
+// FIXME: Document this strange function.
+// It seems to negate the given register but only if the "cantBeHere" exists.
+// My guess: Since some SCI versions have cantBeHere and some have canBeHere,
+// this function allows unifying the code, making it look identical for both
+// kinds of SCI games. That's fine, but the name not_register is rather
+// misleading. A different name (and a different place for declaring this)
+// would be highly welcome.
static inline reg_t not_register(EngineState *s, reg_t r) {
if (s->_kernel->_selectorMap.cantBeHere != -1)
return make_reg(0, !r.offset);
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 18e1ef7866..fd8ce33f51 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -27,7 +27,7 @@
#include "common/stack.h"
#include "sci/sci.h"
-#include "sci/console.h" // for debug_weak_validations
+#include "sci/debug.h" // for g_debug_weak_validations
#include "sci/resource.h"
#include "sci/engine/state.h"
#include "sci/engine/intmap.h"
@@ -46,17 +46,13 @@ reg_t NULL_REG = {0, 0};
#undef STRICT_READ // Disallows reading from out-of-bounds parameters and locals
-int script_abort_flag = 0; // Set to 1 to abort execution
-int script_step_counter = 0; // Counts the number of steps executed
-int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs
+int script_abort_flag = 0; // Set to 1 to abort execution. Set to 2 to force a replay afterwards // FIXME: Avoid non-const global vars
+int script_step_counter = 0; // Counts the number of steps executed // FIXME: Avoid non-const global vars
+int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME: Avoid non-const global vars
-extern int _debug_step_running;
-extern int _debug_seeking;
-extern bool debug_weak_validations;
-
-static bool breakpointFlag = false;
-static reg_t _dummy_register;
+static bool breakpointFlag = false; // FIXME: Avoid non-const global vars
+static reg_t _dummy_register; // FIXME: Avoid non-const global vars
// validation functionality
@@ -90,7 +86,7 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) {
static int validate_arithmetic(reg_t reg) {
if (reg.segment) {
- if (debug_weak_validations)
+ if (g_debug_weak_validations)
warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment);
else
error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment);
@@ -102,7 +98,7 @@ static int validate_arithmetic(reg_t reg) {
static int signed_validate_arithmetic(reg_t reg) {
if (reg.segment) {
- if (debug_weak_validations)
+ if (g_debug_weak_validations)
warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment);
else
error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]\n", reg.segment);
@@ -121,17 +117,15 @@ static int validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int
if (index < 0 || index >= max) {
char txt[200];
char tmp[40];
- sprintf(txt, "[VM] Attempt to use invalid %s variable %04x ", names[type], index);
+ sprintf(txt, "[VM] validate_variable(): Attempt to use invalid %s variable %04x ", names[type], index);
if (max == 0)
strcat(txt, "(variable type invalid)");
else {
sprintf(tmp, "(out of range [%d..%d])", 0, max - 1);
strcat(txt, tmp);
}
- sprintf(tmp, " in %s, line %d\n", __FILE__, line);
- strcat(txt, tmp);
- if (debug_weak_validations)
+ if (g_debug_weak_validations)
warning(txt);
else
error(txt);
@@ -402,7 +396,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
default:
sciprintf("Send error: Variable selector %04x in %04x:%04x called with %04x params\n", selector, PRINT_REG(send_obj), argc);
script_debug_flag = 1; // Enter debug mode
- _debug_seeking = _debug_step_running = 0;
+ g_debug_seeking = g_debug_step_running = 0;
#endif
}
break;
@@ -977,24 +971,24 @@ void run_vm(EngineState *s, int restoring) {
gc_countdown(s);
xs->sp -= (opparams[1] >> 1) + 1;
- if (!(s->flags & GF_SCI0_OLD)) {
+ if (!(s->_flags & GF_SCI0_OLD)) {
xs->sp -= restadjust;
s->r_amp_rest = 0; // We just used up the restadjust, remember?
}
- if (opparams[0] >= (int)s->_kernel->_kfuncTable.size()) {
+ if (opparams[0] >= (int)s->_kernel->_kernelFuncs.size()) {
error("Invalid kernel function 0x%x requested\n", opparams[0]);
} else {
int argc = ASSERT_ARITHMETIC(xs->sp[0]);
- if (!(s->flags & GF_SCI0_OLD))
+ if (!(s->_flags & GF_SCI0_OLD))
argc += restadjust;
- if (s->_kernel->_kfuncTable[opparams[0]].signature
- && !kernel_matches_signature(s, s->_kernel->_kfuncTable[opparams[0]].signature, argc, xs->sp + 1)) {
+ if (s->_kernel->_kernelFuncs[opparams[0]].signature
+ && !kernel_matches_signature(s, s->_kernel->_kernelFuncs[opparams[0]].signature, argc, xs->sp + 1)) {
error("[VM] Invalid arguments to kernel call %x\n", opparams[0]);
} else {
- s->r_acc = s->_kernel->_kfuncTable[opparams[0]].fun(s, opparams[0], argc, xs->sp + 1);
+ s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], argc, xs->sp + 1);
}
// Call kernel function
@@ -1004,7 +998,7 @@ void run_vm(EngineState *s, int restoring) {
xs_new = &(s->_executionStack.back());
s->_executionStackPosChanged = true;
- if (!(s->flags & GF_SCI0_OLD))
+ if (!(s->_flags & GF_SCI0_OLD))
restadjust = s->r_amp_rest;
}
@@ -1207,10 +1201,10 @@ void run_vm(EngineState *s, int restoring) {
case 0x39: // lofsa
s->r_acc.segment = xs->addr.pc.segment;
- if (s->version >= SCI_VERSION_1_1) {
+ if (s->_version >= SCI_VERSION_1_1) {
s->r_acc.offset = opparams[0] + local_script->script_size;
} else {
- if (s->flags & GF_SCI1_LOFSABSOLUTE)
+ if (s->_flags & GF_SCI1_LOFSABSOLUTE)
s->r_acc.offset = opparams[0];
else
s->r_acc.offset = xs->addr.pc.offset + opparams[0];
@@ -1227,7 +1221,7 @@ void run_vm(EngineState *s, int restoring) {
case 0x3a: // lofss
r_temp.segment = xs->addr.pc.segment;
- if (s->flags & GF_SCI1_LOFSABSOLUTE)
+ if (s->_flags & GF_SCI1_LOFSABSOLUTE)
r_temp.offset = opparams[0];
else
r_temp.offset = xs->addr.pc.offset + opparams[0];
@@ -1433,8 +1427,8 @@ void run_vm(EngineState *s, int restoring) {
#if 0
if (script_error_flag) {
- _debug_step_running = 0; // Stop multiple execution
- _debug_seeking = 0; // Stop special seeks
+ g_debug_step_running = 0; // Stop multiple execution
+ g_debug_seeking = 0; // Stop special seeks
xs->addr.pc.offset = old_pc_offset;
xs->sp = old_sp;
} else
@@ -1447,7 +1441,7 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {
// Determines if obj explicitly defines slc as a varselector
// Returns -1 if not found
- if (s->version < SCI_VERSION_1_1) {
+ if (s->_version < SCI_VERSION_1_1) {
int varnum = obj->variable_names_nr;
int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET;
int i;
@@ -1520,7 +1514,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle, meaning that we must remove it for selector lookup.
- if (s->flags & GF_SCI0_OLD)
+ if (s->_flags & GF_SCI0_OLD)
selector_id &= ~1;
if (!obj) {
@@ -1614,12 +1608,12 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script,
*was_new = 1;
*script = s->resmgr->findResource(kResourceTypeScript, script_nr, 0);
- if (s->version >= SCI_VERSION_1_1)
+ if (s->_version >= SCI_VERSION_1_1)
*heap = s->resmgr->findResource(kResourceTypeHeap, script_nr, 0);
- if (!*script || (s->version >= SCI_VERSION_1_1 && !heap)) {
+ if (!*script || (s->_version >= SCI_VERSION_1_1 && !heap)) {
sciprintf("Script 0x%x requested but not found\n", script_nr);
- if (s->version >= SCI_VERSION_1_1) {
+ if (s->_version >= SCI_VERSION_1_1) {
if (*heap)
sciprintf("Inconsistency: heap resource WAS found\n");
else if (*script)
@@ -1686,7 +1680,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
Script *scr = s->seg_manager->getScript(seg_id);
- if (s->flags & GF_SCI0_OLD) {
+ if (s->_flags & GF_SCI0_OLD) {
//
int locals_nr = READ_LE_UINT16(script->data);
@@ -1855,14 +1849,14 @@ int script_instantiate_sci11(EngineState *s, int script_nr) {
}
int script_instantiate(EngineState *s, int script_nr) {
- if (s->version >= SCI_VERSION_1_1)
+ if (s->_version >= SCI_VERSION_1_1)
return script_instantiate_sci11(s, script_nr);
else
return script_instantiate_sci0(s, script_nr);
}
void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
- reg_t reg = make_reg(seg, (s->flags & GF_SCI0_OLD) ? 2 : 0);
+ reg_t reg = make_reg(seg, (s->_flags & GF_SCI0_OLD) ? 2 : 0);
int objtype, objlength;
Script *scr = s->seg_manager->getScript(seg);
@@ -1906,7 +1900,7 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
}
void script_uninstantiate(EngineState *s, int script_nr) {
- reg_t reg = make_reg(0, (s->flags & GF_SCI0_OLD) ? 2 : 0);
+ reg_t reg = make_reg(0, (s->_flags & GF_SCI0_OLD) ? 2 : 0);
reg.segment = s->seg_manager->segGet(script_nr);
Script *scr = script_locate_by_segment(s, reg.segment);
@@ -1927,7 +1921,7 @@ void script_uninstantiate(EngineState *s, int script_nr) {
if (s->_classtable[i].reg.segment == reg.segment)
s->_classtable[i].reg = NULL_REG;
- if (s->version < SCI_VERSION_1_1)
+ if (s->_version < SCI_VERSION_1_1)
script_uninstantiate_sci0(s, script_nr, reg.segment);
else
sciprintf("FIXME: Add proper script uninstantiation for SCI 1.1\n");
@@ -1965,7 +1959,7 @@ static EngineState *_game_run(EngineState *s, int restoring) {
game_exit(s);
script_free_engine(s);
- script_init_engine(s, s->version);
+ script_init_engine(s);
game_init(s);
sfx_reset_player();
_init_stack_base_with_selector(s, s->_kernel->_selectorMap.play);
@@ -1984,7 +1978,7 @@ static EngineState *_game_run(EngineState *s, int restoring) {
s = successor;
g_EngineState = s;
- if (script_abort_flag == SCRIPT_ABORT_WITH_REPLAY) {
+ if (script_abort_flag == 2) {
sciprintf("Restarting with replay()\n");
s->_executionStack.clear(); // Restart with replay
@@ -2067,9 +2061,9 @@ const char *obj_get_name(EngineState *s, reg_t pos) {
void quit_vm() {
script_abort_flag = 1; // Terminate VM
- _debugstate_valid = 0;
- _debug_seeking = 0;
- _debug_step_running = 0;
+ g_debugstate_valid = 0;
+ g_debug_seeking = 0;
+ g_debug_step_running = 0;
}
void shrink_execution_stack(EngineState *s, uint size) {
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 84e6cc4923..5bfbe71ce9 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -28,7 +28,6 @@
/* VM and kernel declarations */
-#include "common/serializer.h"
#include "sci/engine/vm_types.h" // for reg_t
#include "common/util.h"
@@ -38,128 +37,8 @@ namespace Sci {
class SegManager;
struct EngineState;
typedef int sci_version_t;
-
-enum MemObjectType {
- MEM_OBJ_INVALID = 0,
- MEM_OBJ_SCRIPT = 1,
- MEM_OBJ_CLONES = 2,
- MEM_OBJ_LOCALS = 3,
- MEM_OBJ_STACK = 4,
- MEM_OBJ_SYS_STRINGS = 5,
- MEM_OBJ_LISTS = 6,
- MEM_OBJ_NODES = 7,
- MEM_OBJ_HUNK = 8,
- MEM_OBJ_DYNMEM = 9,
- MEM_OBJ_STRING_FRAG = 10,
-
- MEM_OBJ_MAX // For sanity checking
-};
-
-struct MemObject : public Common::Serializable {
- MemObjectType _type;
- int _segmgrId; /**< Internal value used by the seg_manager's hash map */
-
- typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
-
-public:
- static MemObject *createMemObject(MemObjectType type);
-
-public:
- virtual ~MemObject() {}
-
- inline MemObjectType getType() const { return _type; }
- inline int getSegMgrId() const { return _segmgrId; }
-
- /**
- * Dereferences a raw memory pointer.
- * @param reg reference to dereference
- * @param size if not NULL, set to the theoretical maximum size of the referenced data block
- * @return the data block referenced
- */
- virtual byte *dereference(reg_t pointer, int *size);
-
- /**
- * Finds the canonic address associated with sub_reg.
- *
- * For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)).
- * This address "governs" a in the sense that deallocating c(a) will deallocate a.
- *
- * @param sub_addr base address whose canonic address is to be found
- */
- virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr) { return sub_addr; }
-
- /**
- * Deallocates all memory associated with the specified address.
- * @param sub_addr address (within the given segment) to deallocate
- */
- virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr) {}
-
- /**
- * Iterates over and reports all addresses within the current segment.
- * @param note Invoked for each address on which free_at_address() makes sense
- * @param param parameter passed to 'note'
- */
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {}
-
- /**
- * Iterates over all references reachable from the specified object.
- * @param object object (within the current segment) to analyse
- * @param param parameter passed to 'note'
- * @param note Invoked for each outgoing reference within the object
- * Note: This function may also choose to report numbers (segment 0) as adresses
- */
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note) {}
-};
-
-
-// TODO: Implement the following class
-struct StringFrag : public MemObject {
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
struct IntMapper;
-
-enum {
- SYS_STRINGS_MAX = 4,
-
- SYS_STRING_SAVEDIR = 0,
- SYS_STRING_PARSER_BASE = 1,
-
- MAX_PARSER_BASE = 64
-};
-
-struct SystemString {
- char *name;
- int max_size;
- reg_t *value;
-};
-
-struct SystemStrings : public MemObject {
- SystemString strings[SYS_STRINGS_MAX];
-
-public:
- SystemStrings() {
- memset(strings, 0, sizeof(strings));
- }
- ~SystemStrings() {
- for (int i = 0; i < SYS_STRINGS_MAX; i++) {
- SystemString *str = &strings[i];
- if (str->name) {
- free(str->name);
- str->name = NULL;
-
- free(str->value);
- str->value = NULL;
-
- str->max_size = 0;
- }
- }
- }
-
- virtual byte *dereference(reg_t pointer, int *size);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
+struct Object;
/** Number of bytes to be allocated for the stack */
#define VM_STACK_SIZE 0x1000
@@ -188,12 +67,12 @@ public:
#define SCRIPT_FUNCTAREAPTR_MAGIC 8 -8
/** Offset of the name pointer */
-#define SCRIPT_NAME_OFFSET (s->version < SCI_VERSION_1_1 ? 14 -8 : 16)
-#define SCRIPT_NAME_SELECTOR (s->version < SCI_VERSION_1_1 ? 3 : 8)
+#define SCRIPT_NAME_OFFSET (s->_version < SCI_VERSION_1_1 ? 14 -8 : 16)
+#define SCRIPT_NAME_SELECTOR (s->_version < SCI_VERSION_1_1 ? 3 : 8)
/** Object-relative offset of the -info- selector */
-#define SCRIPT_INFO_OFFSET (s->version < SCI_VERSION_1_1 ? 12 -8 : 14)
-#define SCRIPT_INFO_SELECTOR (s->version < SCI_VERSION_1_1 ? 2 : 7)
+#define SCRIPT_INFO_OFFSET (s->_version < SCI_VERSION_1_1 ? 12 -8 : 14)
+#define SCRIPT_INFO_SELECTOR (s->_version < SCI_VERSION_1_1 ? 2 : 7)
/** Flag fo the -info- selector */
#define SCRIPT_INFO_CLONE 0x0001
@@ -205,18 +84,18 @@ public:
/** Magical object identifier */
#define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234
/** Offset of this identifier */
-#define SCRIPT_OBJECT_MAGIC_OFFSET (s->version < SCI_VERSION_1_1 ? -8 : 0)
+#define SCRIPT_OBJECT_MAGIC_OFFSET (s->_version < SCI_VERSION_1_1 ? -8 : 0)
/** Script-relative offset of the species ID */
#define SCRIPT_SPECIES_OFFSET 8 -8
-#define SCRIPT_SUPERCLASS_OFFSET (s->version < SCI_VERSION_1_1 ? 10 -8 : 12)
+#define SCRIPT_SUPERCLASS_OFFSET (s->_version < SCI_VERSION_1_1 ? 10 -8 : 12)
/*---------------------------------*/
/* Script selector index variables */
/*---------------------------------*/
-#define SCRIPT_SPECIES_SELECTOR (s->version < SCI_VERSION_1_1 ? 0 : 5)
-#define SCRIPT_SUPERCLASS_SELECTOR (s->version < SCI_VERSION_1_1 ? 1 : 6)
+#define SCRIPT_SPECIES_SELECTOR (s->_version < SCI_VERSION_1_1 ? 0 : 5)
+#define SCRIPT_SUPERCLASS_SELECTOR (s->_version < SCI_VERSION_1_1 ? 1 : 6)
#define SCRIPT_CLASSSCRIPT_SELECTOR 4
/** Magic adjustment value for lofsa and lofss */
@@ -243,400 +122,6 @@ struct Class {
#define IS_CLASS(obj) (obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)
-/** This struct is used to buffer the list of send calls in send_selector() */
-struct CallsStruct {
- union {
- reg_t func;
- reg_t *var;
- } address;
- StackPtr argp;
- int argc;
- Selector selector;
- StackPtr sp; /**< Stack pointer */
- int type; /**< Same as ExecStack.type */
-};
-
-struct LocalVariables : public MemObject {
- int script_id; /**< Script ID this local variable block belongs to */
- Common::Array<reg_t> _locals;
-
-public:
- LocalVariables() {
- script_id = 0;
- }
-
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-/** Clone has been marked as 'freed' */
-#define OBJECT_FLAG_FREED (0x1 << 0)
-
-struct Object {
- int flags;
- reg_t pos; /**< Object offset within its script; for clones, this is their base */
- int variable_names_nr; /**< Number of variable names, may be less than variables_nr */
- int methods_nr;
- byte *base; /**< Points to a buffer all relative references (code, strings) point to */
- byte *base_obj; /**< base + object offset within base */
- uint16 *base_method; /**< Pointer to the method selector area for this object */
- uint16 *base_vars; /**< Pointer to the varselector area for this object */
- Common::Array<reg_t> _variables;
-};
-
-struct CodeBlock {
- reg_t pos;
- int size;
-};
-
-#define VM_OBJECT_GET_VARSELECTOR(obj, i) \
- (s->version < SCI_VERSION_1_1 ? \
- READ_LE_UINT16(obj->base_obj + obj->_variables.size() * 2 + i*2) : \
- *(obj->base_vars + i))
-#define VM_OBJECT_READ_PROPERTY(obj, i) (obj->_variables[i])
-#define VM_OBJECT_GET_FUNCSELECTOR(obj, i) \
- (s->version < SCI_VERSION_1_1 ? \
- READ_LE_UINT16((byte *) (obj->base_method + i)) : \
- READ_LE_UINT16((byte *) (obj->base_method + i*2 + 1)))
-#define VM_OBJECT_READ_FUNCTION(obj, i) \
- (s->version < SCI_VERSION_1_1 ? \
- make_reg(obj->pos.segment, \
- READ_LE_UINT16((byte *) (obj->base_method \
- + obj->methods_nr + 1 \
- + i))) : \
- make_reg(obj->pos.segment, \
- READ_LE_UINT16((byte *) (obj->base_method \
- + i * 2 + 2))))
-
-
-
-
-struct Script : public MemObject {
- int nr; /**< Script number */
- byte *buf; /**< Static data buffer, or NULL if not used */
- size_t buf_size;
- size_t script_size;
- size_t heap_size;
-
- byte *synonyms; /**< Synonyms block or 0 if not present*/
- byte *heap_start; /**< Start of heap if SCI1.1, NULL otherwise */
- uint16 *export_table; /**< Abs. offset of the export table or 0 if not present */
-
- IntMapper *obj_indices;
-
- int exports_nr; /**< Number of entries in the exports table */
- int synonyms_nr; /**< Number of entries in the synonyms block */
- int lockers; /**< Number of classes and objects that require this script */
-
- /**
- * Table for objects, contains property variables.
- * Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET,
- * see VM_OBJECT_[GS]ET_INDEX()
- */
- Common::Array<Object> _objects;
-
- int locals_offset;
- int locals_segment; /**< The local variable segment */
- LocalVariables *locals_block;
-
- Common::Array<CodeBlock> _codeBlocks;
- int relocated;
- bool _markedAsDeleted;
-
-public:
- Script() {
- nr = 0;
- buf = NULL;
- buf_size = 0;
- script_size = 0;
- heap_size = 0;
-
- synonyms = NULL;
- heap_start = NULL;
- export_table = NULL;
-
- obj_indices = NULL;
-
- locals_offset = 0;
- locals_segment = 0;
- locals_block = NULL;
-
- relocated = 0;
- _markedAsDeleted = 0;
- }
-
- ~Script() {
- freeScript();
- }
-
- void freeScript();
-
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-
- // script lock operations
-
- /** Increments the number of lockers of this script by one. */
- void incrementLockers();
-
- /** Decrements the number of lockers of this script by one. */
- void decrementLockers();
-
- /**
- * Retrieves the number of locks held on this script.
- * @return the number of locks held on the previously identified script
- */
- int getLockers() const;
-
- /** Sets the number of locks held on this script. */
- void setLockers(int lockers);
-
- /**
- * Retrieves a pointer to the synonyms associated with this script
- * @return pointer to the synonyms, in non-parsed format.
- */
- byte *getSynonyms() const;
-
- /**
- * Retrieves the number of synonyms associated with this script.
- * @return the number of synonyms associated with this script
- */
- int getSynonymsNr() const;
-
-
- /**
- * Sets the script-relative offset of the exports table.
- * @param offset script-relative exports table offset
- */
- void setExportTableOffset(int offset);
-
- /**
- * Sets the script-relative offset of the synonyms associated with this script.
- * @param offset script-relative offset of the synonyms block
- */
- void setSynonymsOffset(int offset);
-
- /**
- * Sets the number of synonyms associated with this script,
- * @param nr number of synonyms, as to be stored within the script
- */
- void setSynonymsNr(int nr);
-
-
- /**
- * Copies a byte string into a script's heap representation.
- * @param dst script-relative offset of the destination area
- * @param src pointer to the data source location
- * @param n number of bytes to copy
- */
- void mcpyInOut(int dst, const void *src, size_t n);
-
-
- /**
- * Marks the script as deleted.
- * This will not actually delete the script. If references remain present on the
- * heap or the stack, the script will stay in memory in a quasi-deleted state until
- * either unreachable (resulting in its eventual deletion) or reloaded (resulting
- * in its data being updated).
- */
- void markDeleted() {
- _markedAsDeleted = true;
- }
-
- /**
- * Marks the script as not deleted.
- */
- void unmarkDeleted() {
- _markedAsDeleted = false;
- }
-
- /**
- * Determines whether the script is marked as being deleted.
- */
- bool isMarkedAsDeleted() const {
- return _markedAsDeleted;
- }
-
- /**
- * Retrieves a 16 bit value from within a script's heap representation.
- * @param offset offset to read from
- * @return the value read from the specified location
- */
- int16 getHeap(uint16 offset) const;
-
-};
-
-/** Data stack */
-struct DataStack : MemObject {
- int nr; /**< Number of stack entries */
- reg_t *entries;
-
-public:
- DataStack() {
- nr = 0;
- entries = NULL;
- }
- ~DataStack() {
- free(entries);
- entries = NULL;
- }
-
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-#define CLONE_USED -1
-#define CLONE_NONE -1
-
-typedef Object Clone;
-
-struct Node {
- reg_t pred; /**< Predecessor node */
- reg_t succ; /**< Successor node */
- reg_t key;
- reg_t value;
-}; /* List nodes */
-
-struct List {
- reg_t first;
- reg_t last;
-};
-
-struct Hunk {
- void *mem;
- unsigned int size;
- const char *type;
-};
-
-template<typename T>
-struct Table : public MemObject {
- typedef T value_type;
- struct Entry : public T {
- int next_free; /* Only used for free entries */
- };
- enum { HEAPENTRY_INVALID = -1 };
-
-
- int first_free; /**< Beginning of a singly linked list for entries */
- int entries_used; /**< Statistical information */
-
- Common::Array<Entry> _table;
-
-public:
- Table() {
- initTable();
- }
-
- void initTable() {
- entries_used = 0;
- first_free = HEAPENTRY_INVALID;
- _table.clear();
- }
-
- int allocEntry() {
- entries_used++;
- if (first_free != HEAPENTRY_INVALID) {
- int oldff = first_free;
- first_free = _table[oldff].next_free;
-
- _table[oldff].next_free = oldff;
- return oldff;
- } else {
- uint newIdx = _table.size();
- _table.push_back(Entry());
- _table[newIdx].next_free = newIdx; // Tag as 'valid'
- return newIdx;
- }
- }
-
- bool isValidEntry(int idx) {
- return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx;
- }
-
- virtual void freeEntry(int idx) {
- if (idx < 0 || (uint)idx >= _table.size())
- ::error("Table::freeEntry: Attempt to release invalid table index %d", idx);
-
- _table[idx].next_free = first_free;
- first_free = idx;
- entries_used--;
- }
-
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
-};
-
-
-/* CloneTable */
-struct CloneTable : public Table<Clone> {
- virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-/* NodeTable */
-struct NodeTable : public Table<Node> {
- virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-/* ListTable */
-struct ListTable : public Table<List> {
- virtual void freeAtAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-/* HunkTable */
-struct HunkTable : public Table<Hunk> {
- virtual void freeEntry(int idx) {
- Table<Hunk>::freeEntry(idx);
-
- free(_table[idx].mem);
- }
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-// Free-style memory
-struct DynMem : public MemObject {
- int _size;
- char *_description;
- byte *_buf;
-
-public:
- DynMem() : _size(0), _description(0), _buf(0) {}
- ~DynMem() {
- free(_description);
- _description = NULL;
- free(_buf);
- _buf = NULL;
- }
-
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segmgr, reg_t sub_addr);
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
/** Contains selector IDs for a few selected selectors */
struct selector_map_t {
@@ -769,13 +254,13 @@ enum BreakpointType {
* Break when selector is executed. data contains (char *) selector name
* (in the format Object::Method)
*/
- BREAK_SELECTOR = 1,
+ BREAK_SELECTOR,
/**
* Break when an exported function is called. data contains
* script_no << 16 | export_no.
*/
- BREAK_EXPORT = 2
+ BREAK_EXPORT
};
struct Breakpoint {
@@ -787,17 +272,17 @@ struct Breakpoint {
Breakpoint *next;
};
-#define SCRIPT_ABORT_WITH_REPLAY 1025
-
/**
* Set this to 1 to abort script execution immediately. Aborting will leave the
* debug exec stack intact.
- * Set it to SCRIPT_ABORT_WITH_REPLAY to force a replay afterwards.
+ * Set it to 2 to force a replay afterwards.
*/
extern int script_abort_flag;
/** Number of kernel calls in between gcs; should be < 50000 */
-#define GC_INTERVAL 32768
+enum {
+ GC_INTERVAL = 32768
+};
/** Initially GC_DELAY, can be set at runtime */
extern int script_gc_interval;
@@ -806,16 +291,6 @@ extern int script_gc_interval;
extern int script_step_counter;
-extern int _debugstate_valid;
-extern int _debug_seeking;
-extern int _debug_step_running;
-
-
-typedef int kernel_function(struct EngineState *s);
-
-extern kernel_function* kfuncs[];
-extern int max_instance;
-
/**
* Executes function pubfunct of the specified script.
* Parameters: (EngineState *) s: The state which is to be executed with
@@ -925,7 +400,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *
** Returns : (void)
*/
-int script_init_engine(EngineState *s, sci_version_t version);
+int script_init_engine(EngineState *s);
/* Initializes a EngineState block
** Parameters: (EngineState *) s: The state to initialize
** Returns : 0 on success, 1 if vocab.996 (the class table) is missing or corrupted
diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp
index 2418f45824..fcac77245e 100644
--- a/engines/sci/gfx/gfx_driver.cpp
+++ b/engines/sci/gfx/gfx_driver.cpp
@@ -36,7 +36,6 @@ namespace Sci {
struct _scummvm_driver_state {
gfx_pixmap_t *priority[2];
byte *visual[2];
- uint8 *pointer_data;
int xsize, ysize;
};
@@ -53,7 +52,6 @@ static int scummvm_init(gfx_driver_t *drv, int xfact, int yfact, int bytespp) {
S->xsize = xfact * 320;
S->ysize = yfact * 200;
- S->pointer_data = NULL;
//S->buckystate = 0;
for (i = 0; i < 2; i++) {
@@ -94,9 +92,6 @@ static void scummvm_exit(gfx_driver_t *drv) {
S->visual[i] = NULL;
}
- delete[] S->pointer_data;
- S->pointer_data = NULL;
-
delete S;
}
}
@@ -284,8 +279,7 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common:
if ((pointer == NULL) || (hotspot == NULL)) {
g_system->showMouse(false);
} else {
- delete[] S->pointer_data;
- S->pointer_data = create_cursor(drv, pointer, 1);
+ uint8 *cursorData = create_cursor(drv, pointer, 1);
// FIXME: The palette size check is a workaround for cursors using non-palette colour GFX_CURSOR_TRANSPARENT
// Note that some cursors don't have a palette in SQ5
@@ -297,8 +291,11 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common:
if (!pointer->palette)
color_key = 63;
- g_system->setMouseCursor(S->pointer_data, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key);
+ g_system->setMouseCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key);
g_system->showMouse(true);
+
+ delete[] cursorData;
+ cursorData = 0;
}
return GFX_OK;
@@ -306,9 +303,6 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common:
gfx_driver_t gfx_driver_scummvm = {
NULL,
- 0, 0,
- 0,
- NULL,
scummvm_init,
scummvm_exit,
scummvm_draw_line,
diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h
index 254f619b34..47b5e7de21 100644
--- a/engines/sci/gfx/gfx_driver.h
+++ b/engines/sci/gfx/gfx_driver.h
@@ -38,10 +38,6 @@ enum gfx_buffer_t {
};
-/* graphics driver hints */
-#define GFX_CAPABILITY_SHADING (1<<0)
-#define GFX_CAPABILITY_STIPPLED_LINES (1<<6)
-
/* Principial graphics driver architecture
** ---------------------------------------
**
@@ -71,38 +67,8 @@ struct gfx_driver_t { /* Graphics driver */
gfx_mode_t *mode; /* Currently active mode, NULL if no mode is active */
- int pointer_x, pointer_y; /* Mouse pointer position */
-
- int capabilities; /* The driver's capabilities: A list of flags that may
- ** be pre-defined or set after a successful initialization.
- */
- /* Capability flags:
- **
- ** The words MUST, SHOULD and MAY are to be interpreted as described in
- ** the IETF RFC 1123.
- **
- ** GFX_CAPABILITY_SHADING: draw_filled_rect() supports drawing shaded
- ** rectangles.
- ** GFX_CAPABILITY_STIPPLED_LINES: The driver is able to draw stippled lines
- ** horizontally and vertically (xl = 0 or yl = 0).
- */
-
/*** Initialization ***/
- int (*set_parameter)(gfx_driver_t *drv, char *attribute, char *value);
- /* Sets a driver-specific parameter
- ** Parameters: (gfx_driver_t *) drv: Pointer to the affected driver
- ** (char *) attribute: Name of the attribute/parameter to set
- ** (char *) value: The value to set, or NULL to query the value
- ** Returns : (int) GFX_OK or GFX_FATAL, which signals a fatal error
- ** condition.
- ** This function should make extensive use of sciprintf() to signal invalid
- ** values or unapplicable attributes.
- ** Note that it may be called either before initialization (to interpret
- ** config file or command line parameters) or afterwars (from the command
- ** console).
- */
-
int (*init)(gfx_driver_t *drv, int xres, int yres,
int bytespp);
/* Attempts to initialize a specific graphics mode
diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp
index ad9464811e..e17ffae6f1 100644
--- a/engines/sci/gfx/gfx_widgets.cpp
+++ b/engines/sci/gfx/gfx_widgets.cpp
@@ -49,10 +49,8 @@ GfxWidget *debug_widgets[GFXW_DEBUG_WIDGETS];
int debug_widget_pos = 0;
static void _gfxw_debug_add_widget(GfxWidget *widget) {
- if (debug_widget_pos == GFXW_DEBUG_WIDGETS) {
- GFXERROR("WIDGET DEBUG: Allocated the maximum number of %d widgets- Aborting!\n", GFXW_DEBUG_WIDGETS);
- BREAKPOINT();
- }
+ if (debug_widget_pos == GFXW_DEBUG_WIDGETS)
+ error("WIDGET DEBUG: Allocated the maximum number of %d widgets- Aborting!\n", GFXW_DEBUG_WIDGETS);
debug_widgets[debug_widget_pos++] = widget;
}
@@ -68,13 +66,11 @@ static void _gfxw_debug_remove_widget(GfxWidget *widget) {
}
if (found > 1) {
- GFXERROR("While removing widget: Found it %d times!\n", found);
- BREAKPOINT();
+ error("While removing widget: Found it %d times!\n", found);
}
if (found == 0) {
- GFXERROR("Attempted removal of unregistered widget!\n");
- BREAKPOINT();
+ error("Attempted removal of unregistered widget!\n");
}
}
#else // !GFXW_DEBUG_WIDGETS
diff --git a/engines/sci/gfx/gfx_widgets.h b/engines/sci/gfx/gfx_widgets.h
index 5b43c2cad6..6c8e848664 100644
--- a/engines/sci/gfx/gfx_widgets.h
+++ b/engines/sci/gfx/gfx_widgets.h
@@ -51,7 +51,7 @@ struct GfxWidget;
/* Enable the next line to keep a list of pointers to all widgets, with up to the specified amount
** of members (/SLOW/) */
-/* #define GFXW_DEBUG_WIDGETS 2048 */
+//#define GFXW_DEBUG_WIDGETS 2048
/* Our strategy for dirty rectangle management */
#define GFXW_DIRTY_STRATEGY GFXOP_DIRTY_FRAMES_CLUSTERS
diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp
index 7ab1bc28cd..d9dc539c79 100644
--- a/engines/sci/gfx/operations.cpp
+++ b/engines/sci/gfx/operations.cpp
@@ -265,8 +265,9 @@ static int _gfxop_draw_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm, int prior
}
static void _gfxop_full_pointer_refresh(GfxState *state) {
- state->pointer_pos.x = state->driver->pointer_x / state->driver->mode->xfact;
- state->pointer_pos.y = state->driver->pointer_y / state->driver->mode->yfact;
+ Common::Point mousePoint = g_system->getEventManager()->getMousePos();
+ state->pointer_pos.x = mousePoint.x / state->driver->mode->xfact;
+ state->pointer_pos.y = mousePoint.y / state->driver->mode->yfact;
}
static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer);
@@ -450,12 +451,6 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options,
return GFX_OK;
}
-int gfxop_set_parameter(GfxState *state, char *attribute, char *value) {
- BASIC_CHECKS(GFX_FATAL);
-
- return state->driver->set_parameter(state->driver, attribute, value);
-}
-
int gfxop_exit(GfxState *state) {
BASIC_CHECKS(GFX_ERROR);
@@ -822,8 +817,7 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common
GFXWARN("Attempt to draw stippled line which is neither an hbar nor a vbar: (%d,%d) -- (%d,%d)\n", start.x, start.y, end.x, end.y);
return GFX_ERROR;
}
- if (!(state->driver->capabilities & GFX_CAPABILITY_STIPPLED_LINES))
- return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode);
+ return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode);
}
if ((retval = state->driver->draw_line(state->driver, start, end, color, line_mode, line_style))) {
@@ -923,8 +917,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t
BASIC_CHECKS(GFX_FATAL);
_gfxop_full_pointer_refresh(state);
- if (PALETTE_MODE || !(state->driver->capabilities & GFX_CAPABILITY_SHADING))
- shade_type = GFX_BOX_SHADE_FLAT;
+ shade_type = GFX_BOX_SHADE_FLAT;
_gfxop_add_dirty(state, box);
@@ -1244,9 +1237,7 @@ int gfxop_set_pointer_position(GfxState *state, Common::Point pos) {
return 0; // Not fatal
}
- state->driver->pointer_x = pos.x * state->driver->mode->xfact;
- state->driver->pointer_y = pos.y * state->driver->mode->yfact;
- g_system->warpMouse(state->driver->pointer_x, state->driver->pointer_y);
+ g_system->warpMouse(pos.x * state->driver->mode->xfact, pos.y * state->driver->mode->yfact);
_gfxop_full_pointer_refresh(state);
return 0;
@@ -1326,28 +1317,8 @@ int _gfxop_shiftify(int c) {
}
}
- switch (c) {
- case SCI_K_F1 :
- return SCI_K_SHIFT_F1;
- case SCI_K_F2 :
- return SCI_K_SHIFT_F2;
- case SCI_K_F3 :
- return SCI_K_SHIFT_F3;
- case SCI_K_F4 :
- return SCI_K_SHIFT_F4;
- case SCI_K_F5 :
- return SCI_K_SHIFT_F5;
- case SCI_K_F6 :
- return SCI_K_SHIFT_F6;
- case SCI_K_F7 :
- return SCI_K_SHIFT_F7;
- case SCI_K_F8 :
- return SCI_K_SHIFT_F8;
- case SCI_K_F9 :
- return SCI_K_SHIFT_F9;
- case SCI_K_F10 :
- return SCI_K_SHIFT_F10;
- }
+ if (c >= SCI_K_F1 && c <= SCI_K_F10)
+ return c + 25;
return c;
}
@@ -1393,8 +1364,6 @@ static sci_event_t scummvm_get_event(gfx_driver_t *drv) {
// Don't generate events for mouse movement
while (found && ev.type == Common::EVENT_MOUSEMOVE) {
- drv->pointer_x = ev.mouse.x;
- drv->pointer_y = ev.mouse.y;
found = em->pollEvent(ev);
}
@@ -1488,7 +1457,7 @@ static sci_event_t scummvm_get_event(gfx_driver_t *drv) {
// SCI_K_SHIFT_F1 == 84 << 8
input.data = SCI_K_F1 + ((input.data - Common::KEYCODE_F1)<<8);
if (input.buckybits & (SCI_EVM_LSHIFT | SCI_EVM_RSHIFT))
- input.character = input.data + SCI_K_SHIFT_F1 - SCI_K_F1;
+ input.character = input.data + 25;
else
input.character = input.data;
} else {
@@ -1558,26 +1527,18 @@ static sci_event_t scummvm_get_event(gfx_driver_t *drv) {
case Common::EVENT_LBUTTONDOWN:
input.type = SCI_EVT_MOUSE_PRESS;
input.data = 1;
- drv->pointer_x = p.x;
- drv->pointer_y = p.y;
break;
case Common::EVENT_RBUTTONDOWN:
input.type = SCI_EVT_MOUSE_PRESS;
input.data = 2;
- drv->pointer_x = p.x;
- drv->pointer_y = p.y;
break;
case Common::EVENT_LBUTTONUP:
input.type = SCI_EVT_MOUSE_RELEASE;
input.data = 1;
- drv->pointer_x = p.x;
- drv->pointer_y = p.y;
break;
case Common::EVENT_RBUTTONUP:
input.type = SCI_EVT_MOUSE_RELEASE;
input.data = 2;
- drv->pointer_x = p.x;
- drv->pointer_y = p.y;
break;
// Misc events
diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h
index 2f4a443509..88af32c624 100644
--- a/engines/sci/gfx/operations.h
+++ b/engines/sci/gfx/operations.h
@@ -152,15 +152,6 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options,
** to provide any useful graphics support
*/
-int gfxop_set_parameter(GfxState *state, char *attribute, char *value);
-/* Sets a driver-specific parameter
-** Parameters: (GfxState *) state: The state, encapsulating the driver object to manipulate
-** (char *) attribute: The attribute to set
-** (char *) value: The value the attribute should be set to
-** Returns : (int) GFX_OK on success, GFX_FATAL on fatal error conditions triggered
-** by the command
-*/
-
int gfxop_exit(GfxState *state);
/* Deinitializes a currently active driver
** Parameters: (GfxState *) state: The state encapsulating the driver in question
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index f67d81e6e9..f2c58bcd8d 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -27,6 +27,7 @@ MODULE_OBJS = \
engine/ksound.o \
engine/kstring.o \
engine/message.o \
+ engine/memobj.o \
engine/said.o \
engine/savegame.o \
engine/script.o \
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index f9ae45b6cd..24b4d9beed 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -63,7 +63,7 @@ enum SolFlags {
kSolFlagIsSigned = 1 << 3
};
-const char *sci_error_types[] = {
+static const char *sci_error_types[] = {
"No error",
"I/O error",
"Resource is empty (size 0)",
@@ -78,7 +78,7 @@ const char *sci_error_types[] = {
};
// These are the 20 resource types supported by SCI1.1
-const char *resourceTypeNames[] = {
+static const char *resourceTypeNames[] = {
"view", "pic", "script", "text", "sound",
"memory", "vocab", "font", "cursor",
"patch", "bitmap", "palette", "cdaudio",
@@ -86,7 +86,7 @@ const char *resourceTypeNames[] = {
"audio36", "sync36"
};
-const char *resourceTypeSuffixes[] = {
+static const char *resourceTypeSuffixes[] = {
"v56", "p56", "scr", "tex", "snd",
" ", "voc", "fon", "cur", "pat",
"bit", "pal", "cda", "aud", "syn",
@@ -97,13 +97,6 @@ const char *getResourceTypeName(ResourceType restype) {
return resourceTypeNames[restype];
}
-const char *getResourceTypeSuffix(ResourceType restype) {
- return resourceTypeSuffixes[restype];
-}
-
-typedef int decomp_funct(Resource *result, Common::ReadStream &stream, int sci_version);
-typedef void patch_sprintf_funct(char *string, Resource *res);
-
//-- Resource main functions --
Resource::Resource() {
data = NULL;
@@ -290,7 +283,7 @@ int sci0_get_compression_method(Common::ReadStream &stream) {
return compressionMethod;
}
-int sci_test_view_type(ResourceManager *mgr) {
+int ResourceManager::guessSciVersion() {
Common::File file;
char filename[MAXPATHLEN];
int compression;
@@ -298,7 +291,7 @@ int sci_test_view_type(ResourceManager *mgr) {
int i;
for (i = 0; i < 1000; i++) {
- res = mgr->testResource(kResourceTypeView, i);
+ res = testResource(kResourceTypeView, i);
if (!res)
continue;
@@ -322,7 +315,7 @@ int sci_test_view_type(ResourceManager *mgr) {
// Try the same thing with pics
for (i = 0; i < 1000; i++) {
- res = mgr->testResource(kResourceTypePic, i);
+ res = testResource(kResourceTypePic, i);
if (!res)
continue;
@@ -442,14 +435,14 @@ ResourceManager::ResourceManager(int version, int maxMemory) {
switch (_mapVersion) {
case SCI_VERSION_0:
if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) {
- version = sci_test_view_type(this) ? SCI_VERSION_01_VGA : SCI_VERSION_0;
+ version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0;
} else if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) {
- version = sci_test_view_type(this);
+ version = guessSciVersion();
if (version != SCI_VERSION_01_VGA) {
version = testResource(kResourceTypeVocab, 912) ? SCI_VERSION_0 : SCI_VERSION_01;
}
} else {
- version = sci_test_view_type(this) ? SCI_VERSION_01_VGA : SCI_VERSION_0;
+ version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0;
}
break;
case SCI_VERSION_01_VGA_ODD:
@@ -586,7 +579,7 @@ void ResourceManager::freeOldResources(int last_invulnerable) {
}
}
-Resource *ResourceManager::findResource(ResourceType type, int number, int lock) {
+Resource *ResourceManager::findResource(ResourceType type, int number, bool lock) {
Resource *retval;
if (number >= sci_max_resource_nr[_sciVersion]) {
@@ -863,7 +856,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) {
SearchMan.listMatchingMembers(files, mask);
// SCI1 and later naming - nnn.typ
mask = "*.";
- mask += getResourceTypeSuffix((ResourceType)i);
+ mask += resourceTypeSuffixes[i];
SearchMan.listMatchingMembers(files, mask);
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); x++) {
bAdd = false;
@@ -1178,7 +1171,7 @@ void ResourceSync::stopSync() {
AudioResource::AudioResource(ResourceManager *resMgr, int sciVersion) {
_resMgr = resMgr;
_sciVersion = sciVersion;
- _audioRate = 0;
+ _audioRate = 11025;
_lang = 0;
_audioMapSCI1 = 0;
_audioMapSCI11 = 0;
@@ -1238,7 +1231,7 @@ bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &o
return false;
byte *ptr = _audioMapSCI1;
- while ((n = READ_UINT16(ptr)) != 0xFFFF) {
+ while ((n = READ_LE_UINT16(ptr)) != 0xFFFF) {
if (n == audioNumber) {
off = READ_LE_UINT32(ptr + 2);
size = READ_LE_UINT32(ptr + 6);
@@ -1252,14 +1245,8 @@ bool AudioResource::findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &o
return false;
}
-bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) {
- // 65535.MAP structure:
- // =========
- // 6 byte entries:
- // w nEntry
- // dw offset
-
- // Other map files:
+bool AudioResource::findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size) {
+ // Map structure:
// ===============
// Header:
// dw baseOffset
@@ -1269,8 +1256,116 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32
// b cond
// b seq
// tb cOffset (cumulative offset)
- // w syncSize (iff seq has bits 7 and 6 set)
- // w syncAscSize (iff seq has bits 7 and 6 set)
+ // w syncSize (iff seq has bit 7 set)
+ // w syncAscSize (iff seq has bit 6 set)
+
+ uint32 n;
+ offset = 0;
+
+ byte *ptr = _audioMapSCI11->data;
+
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+
+ while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) {
+ n = READ_BE_UINT32(ptr);
+ ptr += 4;
+
+ if (n == 0xffffffff)
+ break;
+
+ offset += READ_LE_UINT24(ptr);
+ ptr += 3;
+
+ int syncSkip = 0;
+
+ if (n & 0x80) {
+ n ^= 0x80;
+
+ if (getSync) {
+ if (size)
+ *size = READ_LE_UINT16(ptr);
+ } else {
+ syncSkip = READ_LE_UINT16(ptr);
+ }
+
+ ptr += 2;
+
+ if (n & 0x40) {
+ n ^= 0x40;
+
+ if (!getSync)
+ syncSkip += READ_LE_UINT16(ptr);
+
+ ptr += 2;
+ }
+
+ offset += syncSkip;
+
+ if (n == audioNumber)
+ return true;
+
+ } else {
+ if (n == audioNumber)
+ return !getSync;
+ }
+
+ offset -= syncSkip;
+ }
+
+ return false;
+}
+
+bool AudioResource::findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size) {
+ // Map structure:
+ // ===============
+ // 10-byte entries:
+ // b noun
+ // b verb
+ // b cond
+ // b seq
+ // dw offset
+ // w syncSize + syncAscSize
+
+ uint32 n;
+ offset = 0;
+
+ byte *ptr = _audioMapSCI11->data;
+
+ while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) {
+ n = READ_BE_UINT32(ptr);
+ ptr += 4;
+
+ if (n == 0xffffffff)
+ break;
+
+ offset = READ_LE_UINT32(ptr);
+ ptr += 4;
+
+ int syncSize = READ_LE_UINT16(ptr);
+ ptr += 2;
+
+ if (n == audioNumber) {
+ if (getSync) {
+ if (size)
+ *size = syncSize;
+ return true;
+ } else {
+ offset += syncSize;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) {
+ // 65535.MAP structure:
+ // =========
+ // 6 byte entries:
+ // w nEntry
+ // dw offset
uint32 n;
offset = 0;
@@ -1288,65 +1383,93 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32
if (volume == 65535) {
while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) {
- n = READ_UINT16(ptr);
+ n = READ_LE_UINT16(ptr);
ptr += 2;
if (n == 0xffff)
break;
- offset = READ_UINT32(ptr);
+ offset = READ_LE_UINT32(ptr);
ptr += 4;
if (n == audioNumber)
return true;
}
} else {
- offset = READ_UINT32(ptr);
- ptr += 4;
+ // In early SCI1.1 the map is terminated with 10x 0xff, in late SCI1.1
+ // with 11x 0xff. If we look at the 11th last byte in an early SCI1.1
+ // map, this will be the high byte of the Sync length of the last entry.
+ // As Sync resources are relative small, we should never encounter a
+ // Sync with a size of 0xffnn. As such, the following heuristic should be
+ // sufficient to tell these map formats apart.
+ if (_audioMapSCI11->size >= 11 && (ptr[_audioMapSCI11->size - 11] == 0xff))
+ return findAudEntrySCI11Late(audioNumber, offset, getSync, size);
+ else {
+ return findAudEntrySCI11Early(audioNumber, offset, getSync, size);
+ }
+ }
- while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) {
- n = READ_BE_UINT32(ptr);
- ptr += 4;
+ return false;
+}
- if (n == 0xffffffff)
- break;
+// FIXME: Move this to sound/adpcm.cpp?
+// Note that the 16-bit version is also used in coktelvideo.cpp
+static const uint16 tableDPCM16[128] = {
+ 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
+ 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
+ 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
+ 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
+ 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
+ 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
+ 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
+ 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
+ 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
+ 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
+ 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
+ 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
+ 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
+};
- offset += (READ_UINT16(ptr) | (ptr[2] << 16));
- ptr += 3;
+static const byte tableDPCM8[8] = {0, 1, 2, 3, 6, 10, 15, 21};
- int syncSkip = 0;
+static void deDPCM16(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) {
+ int16 *out = (int16 *) soundBuf;
- if ((n & 0xc0) == 0xc0) {
- n ^= 0xc0;
+ int32 s = 0;
+ for (uint32 i = 0; i < n; i++) {
+ byte b = audioStream.readByte();
+ if (b & 0x80)
+ s -= tableDPCM16[b & 0x7f];
+ else
+ s += tableDPCM16[b];
- if (getSync) {
- if (size)
- *size = READ_UINT16(ptr);
- } else {
- syncSkip = READ_UINT16(ptr) + READ_UINT16(ptr + 2);
- offset += syncSkip;
- }
+ s = CLIP<int32>(s, -32768, 32767);
+ *out++ = TO_BE_16(s);
+ }
+}
- if (n == audioNumber)
- return true;
+static void deDPCM8Nibble(byte *soundBuf, int32 &s, byte b) {
+ if (b & 8)
+ s -= tableDPCM8[7 - (b & 7)];
+ else
+ s += tableDPCM8[b & 7];
+ s = CLIP<int32>(s, 0, 255);
+ *soundBuf = s;
+}
- ptr += 4;
- } else {
- if (n == audioNumber)
- return !getSync;
- }
+static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uint32 n) {
+ int32 s = 0x80;
- offset -= syncSkip;
- }
- }
+ for (uint i = 0; i < n; i++) {
+ byte b = audioStream.readByte();
- return false;
+ deDPCM8Nibble(soundBuf++, s, b >> 4);
+ deDPCM8Nibble(soundBuf++, s, b & 0xf);
+ }
}
// Sierra SOL audio file reader
// Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio
-// TODO: improve this for later versions of the format, as this currently only reads
-// raw PCM encoded files (not ADPCM compressed ones)
byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 *audioRate, byte *flags) {
byte audioFlags;
byte type = audioStream->readByte();
@@ -1357,6 +1480,12 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16
}
int headerSize = audioStream->readByte();
+
+ if (headerSize != 11 && headerSize != 12) {
+ warning("SOL audio header of size %i not supported", headerSize);
+ return NULL;
+ }
+
audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes)
*audioRate = audioStream->readUint16LE();
audioFlags = audioStream->readByte();
@@ -1365,36 +1494,25 @@ byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16
*flags = 0;
if (audioFlags & kSolFlag16Bit)
*flags |= Audio::Mixer::FLAG_16BITS;
- if ((audioFlags & kSolFlagCompressed) || !(audioFlags & kSolFlagIsSigned))
+ if (!(audioFlags & kSolFlagIsSigned))
*flags |= Audio::Mixer::FLAG_UNSIGNED;
- *size = audioStream->readUint16LE();
+ *size = audioStream->readUint32LE();
- if (headerSize == 12)
- *size |= audioStream->readByte() << 16;
+ if (headerSize == 12) {
+ // Unknown byte
+ audioStream->readByte();
+ }
byte *buffer;
if (audioFlags & kSolFlagCompressed) {
- if (audioFlags & kSolFlag16Bit) {
- warning("Unsupported DPCM mode");
- return NULL;
- }
-
buffer = new byte[*size * 2];
- byte sample = 0x80;
-
- for (uint i = 0; i < *size; i++) {
- const int delta[] = {0, 1, 2, 3, 6, 10, 15, 21, -21, -15, -10, -6, -3, -2, -1, -0};
-
- byte b = audioStream->readByte();
-
- sample += delta[b >> 4];
- buffer[i * 2] = sample;
- sample += delta[b & 0xf];
- buffer[i * 2 + 1] = sample;
- }
+ if (audioFlags & kSolFlag16Bit)
+ deDPCM16(buffer, *audioStream, *size);
+ else
+ deDPCM8(buffer, *audioStream, *size);
*size *= 2;
} else {
@@ -1498,7 +1616,10 @@ Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 vol
}
}
- *sampleLen = size * 60 / _audioRate;
+ *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate;
+ } else {
+ warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff,
+ (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff);
}
return audioStream;
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index a693f696db..eade4acbd0 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -88,7 +88,6 @@ enum ResSourceType {
#define SCI1_RESMAP_ENTRIES_SIZE 6
#define SCI11_RESMAP_ENTRIES_SIZE 5
-extern const char *sci_error_types[];
extern const char *sci_version_types[];
extern const int sci_max_resource_nr[]; /**< Highest possible resource numbers */
@@ -118,8 +117,6 @@ enum ResourceType {
};
const char *getResourceTypeName(ResourceType restype);
-// Suffixes for SCI1 patch files
-const char *getResourceTypeSuffix(ResourceType restype);
#define sci0_last_resource kResourceTypePatch
#define sci1_last_resource kResourceTypeHeap
@@ -141,8 +138,11 @@ struct ResourceSource {
ResourceSource *next;
};
+class ResourceManager;
+
/** Class for storing resources in memory */
class Resource {
+ friend class ResourceManager;
public:
Resource();
~Resource();
@@ -155,10 +155,11 @@ public:
uint16 number;
ResourceType type;
uint32 id; //!< contains number and type.
- unsigned int size;
- unsigned int file_offset; /**< Offset in file */
+ uint32 size;
+protected:
+ uint32 file_offset; /**< Offset in file */
ResourceStatus status;
- unsigned short lockers; /**< Number of places where this resource was locked */
+ uint16 lockers; /**< Number of places where this resource was locked */
ResourceSource *source;
};
@@ -191,7 +192,7 @@ public:
* @note Locked resources are guaranteed not to have their contents freed until
* they are unlocked explicitly (by unlockResource).
*/
- Resource *findResource(ResourceType type, int number, int lock);
+ Resource *findResource(ResourceType type, int number, bool lock);
/* Unlocks a previously locked resource
** (Resource *) res: The resource to free
@@ -291,6 +292,8 @@ protected:
void printLRU();
void addToLRU(Resource *res);
void removeFromLRU(Resource *res);
+
+ int guessSciVersion();
};
/**
@@ -343,6 +346,8 @@ private:
bool findAudEntrySCI1(uint16 audioNumber, byte &volume, uint32 &offset, uint32 &size);
bool findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync = false, uint32 *size = NULL);
+ bool findAudEntrySCI11Late(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size);
+ bool findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, bool getSync, uint32 *size);
};
} // End of namespace Sci
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index eb75beab8f..8083ddad73 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -124,11 +124,10 @@ Common::Error SciEngine::run() {
// FIXME/TODO: Move some of the stuff below to init()
- sci_version_t version;
+ const sci_version_t version = getVersion();
+ const uint32 flags = getFlags();
int res_version = getResourceVersion();
- version = getVersion();
-
_resmgr = new ResourceManager(res_version, 256 * 1024);
if (!_resmgr) {
@@ -144,37 +143,34 @@ Common::Error SciEngine::run() {
map_MIDI_instruments(_resmgr);
#endif
- _gamestate = new EngineState();
- _gamestate->resmgr = _resmgr;
- _gamestate->gfx_state = NULL;
- _gamestate->flags = getFlags();
+ _gamestate = new EngineState(_resmgr, version, flags);
// Verify that we haven't got an invalid game detection entry
if (version < SCI_VERSION_1_EARLY) {
// SCI0/SCI01
- if (_gamestate->flags & GF_SCI1_EGA ||
- _gamestate->flags & GF_SCI1_LOFSABSOLUTE ||
- _gamestate->flags & GF_SCI1_NEWDOSOUND) {
+ if (flags & GF_SCI1_EGA ||
+ flags & GF_SCI1_LOFSABSOLUTE ||
+ flags & GF_SCI1_NEWDOSOUND) {
error("This game entry is erroneous. It's marked as SCI0/SCI01, but it has SCI1 flags set");
}
} else if (version >= SCI_VERSION_1_EARLY && version <= SCI_VERSION_1_LATE) {
// SCI1
- if (_gamestate->flags & GF_SCI0_OLD ||
- _gamestate->flags & GF_SCI0_OLDGFXFUNCS ||
- _gamestate->flags & GF_SCI0_OLDGETTIME) {
+ if (flags & GF_SCI0_OLD ||
+ flags & GF_SCI0_OLDGFXFUNCS ||
+ flags & GF_SCI0_OLDGETTIME) {
error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set");
}
} else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) {
- if (_gamestate->flags & GF_SCI1_EGA ||
- _gamestate->flags & GF_SCI1_LOFSABSOLUTE ||
- _gamestate->flags & GF_SCI1_NEWDOSOUND) {
+ if (flags & GF_SCI1_EGA ||
+ flags & GF_SCI1_LOFSABSOLUTE ||
+ flags & GF_SCI1_NEWDOSOUND) {
error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI1 flags set");
}
- if (_gamestate->flags & GF_SCI0_OLD ||
- _gamestate->flags & GF_SCI0_OLDGFXFUNCS ||
- _gamestate->flags & GF_SCI0_OLDGETTIME) {
+ if (flags & GF_SCI0_OLD ||
+ flags & GF_SCI0_OLDGFXFUNCS ||
+ flags & GF_SCI0_OLDGETTIME) {
error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set");
}
@@ -183,7 +179,7 @@ Common::Error SciEngine::run() {
error ("Unknown SCI version in game entry");
}
- if (script_init_engine(_gamestate, version))
+ if (script_init_engine(_gamestate))
return Common::kUnknownError;
diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp
index f4e07d3b84..7e3395b7d3 100644
--- a/engines/sci/sfx/core.cpp
+++ b/engines/sci/sfx/core.cpp
@@ -807,14 +807,14 @@ void SfxState::sfx_add_song(SongIterator *it, int priority, song_handle_t handle
setSongStatus( song, SOUND_STATUS_STOPPED);
fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle);
- if (song->status == SOUND_STATUS_PLAYING
- || song->status == SOUND_STATUS_SUSPENDED) {
+ if (song->status == SOUND_STATUS_PLAYING || song->status == SOUND_STATUS_SUSPENDED) {
delete it;
error("Unexpected (error): Song %ld still playing/suspended (%d)",
handle, song->status);
return;
- } else
+ } else {
song_lib_remove(_songlib, handle); /* No duplicates */
+ }
}
diff --git a/engines/sci/uinput.h b/engines/sci/uinput.h
index 165396a889..062265186b 100644
--- a/engines/sci/uinput.h
+++ b/engines/sci/uinput.h
@@ -72,17 +72,20 @@ struct sci_event_t {
#define SCI_K_TAB '\t'
#define SCI_K_SHIFT_TAB (0xf << 8)
-#define SCI_K_END (79 << 8)
-#define SCI_K_DOWN (80 << 8)
-#define SCI_K_PGDOWN (81 << 8)
-#define SCI_K_LEFT (75 << 8)
-#define SCI_K_CENTER (76 << 8)
-#define SCI_K_RIGHT (77 << 8)
-#define SCI_K_HOME (71 << 8)
-#define SCI_K_UP (72 << 8)
-#define SCI_K_PGUP (73 << 8)
-#define SCI_K_INSERT (82 << 8)
-#define SCI_K_DELETE (83 << 8)
+#define SCI_K_HOME (71 << 8) // 7
+#define SCI_K_UP (72 << 8) // 8
+#define SCI_K_PGUP (73 << 8) // 9
+//
+#define SCI_K_LEFT (75 << 8) // 4
+#define SCI_K_CENTER (76 << 8) // 5
+#define SCI_K_RIGHT (77 << 8) // 6
+//
+#define SCI_K_END (79 << 8) // 1
+#define SCI_K_DOWN (80 << 8) // 2
+#define SCI_K_PGDOWN (81 << 8) // 3
+//
+#define SCI_K_INSERT (82 << 8) // 0
+#define SCI_K_DELETE (83 << 8) // .
#define SCI_K_F1 (59<<8)
#define SCI_K_F2 (60<<8)
@@ -95,17 +98,6 @@ struct sci_event_t {
#define SCI_K_F9 (67<<8)
#define SCI_K_F10 (68<<8)
-#define SCI_K_SHIFT_F1 (84<<8)
-#define SCI_K_SHIFT_F2 (85<<8)
-#define SCI_K_SHIFT_F3 (86<<8)
-#define SCI_K_SHIFT_F4 (87<<8)
-#define SCI_K_SHIFT_F5 (88<<8)
-#define SCI_K_SHIFT_F6 (89<<8)
-#define SCI_K_SHIFT_F7 (90<<8)
-#define SCI_K_SHIFT_F8 (91<<8)
-#define SCI_K_SHIFT_F9 (92<<8)
-#define SCI_K_SHIFT_F10 (93<<8)
-
/*Values for buckybits */
#define SCI_EVM_RSHIFT (1<<0)
#define SCI_EVM_LSHIFT (1<<1)
diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp
index 216ab211be..b12114d845 100644
--- a/engines/sci/vocabulary.cpp
+++ b/engines/sci/vocabulary.cpp
@@ -93,7 +93,7 @@ Vocabulary::Vocabulary(ResourceManager *resmgr) : _resmgr(resmgr) {
if (_resmgr->_sciVersion < SCI_VERSION_01_VGA && loadParserWords()) {
loadSuffixes();
- if (getBranches())
+ if (loadBranches())
// Now build a GNF grammar out of this
_parserRules = buildGNF();
} else {
@@ -241,13 +241,13 @@ void Vocabulary::freeSuffixes() {
else
resource = _resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB, 0);
- if (resource && resource->status == kResStatusLocked)
+ if (resource)
_resmgr->unlockResource(resource, resource->number, kResourceTypeVocab);
_parserSuffixes.clear();
}
-bool Vocabulary::getBranches() {
+bool Vocabulary::loadBranches() {
Resource *resource = NULL;
if (_vocabVersion == kVocabularySCI0)
diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h
index c8ed146917..9f0d277ef2 100644
--- a/engines/sci/vocabulary.h
+++ b/engines/sci/vocabulary.h
@@ -278,7 +278,7 @@ private:
* @param branches The rules are stored into this Array
* @return true on success, false on error
*/
- bool getBranches();
+ bool loadBranches();
/* Frees a parser rule list as returned by vocab_build_gnf()
** Parameters: (parse_rule_list_t *) rule_list: The rule list to free
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index 90f2764b3d..fc27c338b2 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -2507,7 +2507,7 @@ void ScummEngine_v100he::o100_getWizData() {
x = pop();
state = pop();
resId = pop();
- push(_wiz->getWizPixelColor(resId, state, x, y, 0));
+ push(_wiz->getWizPixelColor(resId, state, x, y));
break;
case 26:
resId = pop();
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index c6b919f554..7a7a1ff58b 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -1300,7 +1300,7 @@ void ScummEngine_v90he::o90_getWizData() {
x = pop();
state = pop();
resId = pop();
- push(_wiz->getWizPixelColor(resId, state, x, y, 0));
+ push(_wiz->getWizPixelColor(resId, state, x, y));
break;
case 130:
h = pop();
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index c5a8988edb..67248f4c22 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -158,6 +158,7 @@ void SoundHE::stopSound(int sound) {
if (_heChannel[i].sound == sound) {
_heChannel[i].sound = 0;
_heChannel[i].priority = 0;
+ _heChannel[i].rate = 0;
_heChannel[i].timer = 0;
_heChannel[i].sbngBlock = 0;
_heChannel[i].codeOffs = 0;
@@ -196,6 +197,7 @@ void SoundHE::stopSoundChannel(int chan) {
_heChannel[chan].sound = 0;
_heChannel[chan].priority = 0;
+ _heChannel[chan].rate = 0;
_heChannel[chan].timer = 0;
_heChannel[chan].sbngBlock = 0;
_heChannel[chan].codeOffs = 0;
@@ -254,7 +256,7 @@ int SoundHE::getSoundPos(int sound) {
}
if (_mixer->isSoundHandleActive(_heSoundChannels[chan]) && chan != -1) {
- int time = _vm->getHETimer(chan + 4) * 11025 / 1000;
+ int time = _vm->getHETimer(chan + 4) * _heChannel[chan].rate / 1000;
return time;
} else {
return 0;
@@ -360,7 +362,7 @@ void SoundHE::processSoundCode() {
continue;
}
- tmr = _vm->getHETimer(chan + 4) * 11025 / 1000;
+ tmr = _vm->getHETimer(chan + 4) * _heChannel[chan].rate / 1000;
tmr += _vm->VAR(_vm->VAR_SOUNDCODE_TMR);
if (tmr < 0)
tmr = 0;
@@ -407,6 +409,7 @@ void SoundHE::processSoundCode() {
_heChannel[chan].sound = 0;
_heChannel[chan].priority = 0;
+ _heChannel[chan].rate = 0;
_heChannel[chan].timer = 0;
_heChannel[chan].sbngBlock = 0;
_heChannel[chan].codeOffs = 0;
@@ -625,6 +628,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
_vm->setHETimer(heChannel + 4);
_heChannel[heChannel].sound = soundID;
_heChannel[heChannel].priority = priority;
+ _heChannel[heChannel].rate = rate;
_heChannel[heChannel].sbngBlock = (codeOffs != -1) ? 1 : 0;
_heChannel[heChannel].codeOffs = codeOffs;
memset(_heChannel[heChannel].soundVars, 0, sizeof(_heChannel[heChannel].soundVars));
@@ -646,6 +650,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
size *= 2; // 16bits.
delete voxStream;
+ _heChannel[heChannel].rate = rate;
if (_heChannel[heChannel].timer)
_heChannel[heChannel].timer = size * 1000 / rate;
@@ -696,6 +701,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags)
_vm->setHETimer(heChannel + 4);
_heChannel[heChannel].sound = soundID;
_heChannel[heChannel].priority = priority;
+ _heChannel[heChannel].rate = rate;
_heChannel[heChannel].sbngBlock = (codeOffs != -1) ? 1 : 0;
_heChannel[heChannel].codeOffs = codeOffs;
memset(_heChannel[heChannel].soundVars, 0, sizeof(_heChannel[heChannel].soundVars));
diff --git a/engines/scumm/he/sound_he.h b/engines/scumm/he/sound_he.h
index 47ff145e6b..f3a881972e 100644
--- a/engines/scumm/he/sound_he.h
+++ b/engines/scumm/he/sound_he.h
@@ -53,6 +53,7 @@ public: // Used by createSound()
int sound;
int codeOffs;
int priority;
+ int rate;
int timer;
int sbngBlock;
int soundVars[27];
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 1e694ff067..aed03f746b 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -151,6 +151,7 @@ int Sprite::findSpriteWithClassOf(int x_pos, int y_pos, int spriteGroupId, int t
if (spi->maskImage) {
int32 x1, x2, y1, y2;
+ image = spi->maskImage;
imageState = spi->curImageState % _vm->_wiz->getWizImageStates(spi->maskImage);
pos[0].x = x_pos - spi->pos.x;
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index e91eb48cd4..8bc196ee08 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -2399,7 +2399,7 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags
return ret;
}
-uint8 Wiz::getWizPixelColor(int resNum, int state, int x, int y, int flags) {
+uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) {
uint16 color = 0;
uint8 *data = _vm->getResourceAddress(rtImage, resNum);
assert(data);
diff --git a/engines/scumm/he/wiz_he.h b/engines/scumm/he/wiz_he.h
index 0a320e2426..4a5dd74e38 100644
--- a/engines/scumm/he/wiz_he.h
+++ b/engines/scumm/he/wiz_he.h
@@ -188,7 +188,7 @@ public:
void getWizImageDim(int resNum, int state, int32 &w, int32 &h);
int getWizImageStates(int resnum);
int isWizPixelNonTransparent(int resnum, int state, int x, int y, int flags);
- uint8 getWizPixelColor(int resnum, int state, int x, int y, int flags);
+ uint16 getWizPixelColor(int resnum, int state, int x, int y);
int getWizImageData(int resNum, int state, int type);
void flushWizBuffer();