diff options
| -rw-r--r-- | engines/sci/engine/gc.cpp | 14 | ||||
| -rw-r--r-- | engines/sci/engine/script_patches.cpp | 201 | ||||
| -rw-r--r-- | engines/sci/engine/seg_manager.cpp | 2 | ||||
| -rw-r--r-- | engines/sci/engine/segment.cpp | 5 | ||||
| -rw-r--r-- | engines/sci/engine/segment.h | 13 | ||||
| -rw-r--r-- | engines/sci/engine/workarounds.cpp | 6 | ||||
| -rw-r--r-- | engines/sci/graphics/paint16.cpp | 17 | ||||
| -rw-r--r-- | engines/sci/graphics/ports.h | 15 | 
8 files changed, 39 insertions, 234 deletions
| diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 7692613ee5..e080ad6e4b 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -25,6 +25,7 @@  #include "sci/engine/gc.h"  #include "common/array.h" +#include "sci/graphics/ports.h"  namespace Sci { @@ -84,6 +85,18 @@ static void processWorkList(SegManager *segMan, WorklistManager &wm, const Commo  	}  } +static void processEngineHunkList(WorklistManager &wm) { +	PortList windowList = g_sci->_gfxPorts->_windowList; + +	for (PortList::const_iterator it = windowList.begin(); it != windowList.end(); ++it) { +		// FIXME: We also store Port objects in the window list. +		// We should add a check that we really only pass windows here... +		Window *wnd = ((Window *)*it); +		wm.push(wnd->hSaved1); +		wm.push(wnd->hSaved2); +	} +} +  AddrSet *findAllActiveReferences(EngineState *s) {  	assert(!s->_executionStack.empty()); @@ -142,6 +155,7 @@ AddrSet *findAllActiveReferences(EngineState *s) {  	debugC(kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set");  	processWorkList(s->_segMan, wm, heap); +	processEngineHunkList(wm);  	return normalizeAddresses(s->_segMan, wm._map);  } diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 33ec5ef5ea..7431707e69 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -60,55 +60,6 @@ struct SciScriptSignature {  //  - if not EOS, an adjust offset and the actual bytes  //  - rinse and repeat -#if 0 - -// =========================================================================== -// Castle of Dr. Brain -// cipher::init (script 391) is called on room 380 init. This resets the word -//  cipher puzzle. The puzzle sadly operates on some hep strings, which aren't -//  saved in our sci. So saving/restoring in this room will break the puzzle -//  Because of this issue, we just init the puzzle each time it's accessed. -//  this is not 100% sierra behaviour, in fact we will actually reset the puzzle -//  during each access which makes it impossible to cheat. -const byte castlebrainSignatureCipherPuzzle[] = { -	22, -	0x35, 0x00,        // ldi 00 -	0xa3, 0x26,        // sal local[26] -	0xa3, 0x25,        // sal local[25] -	0x35, 0x00,        // ldi 00 -	0xa3, 0x2a,        // sal local[2a] (local is not used) -	0xa3, 0x29,        // sal local[29] (local is not used) -	0x35, 0xff,        // ldi ff -	0xa3, 0x2c,        // sal local[2c] -	0xa3, 0x2b,        // sal local[2b] -	0x35, 0x00,        // ldi 00 -	0x65, 0x16,        // aTop highlightedIcon -	0 -}; - -const uint16 castlebrainPatchCipherPuzzle[] = { -	0x39, 0x6b,        // pushi 6b (selector init) -	0x76,              // push0 -	0x55, 0x04,        // self 04 -	0x35, 0x00,        // ldi 00 -	0xa3, 0x25,        // sal local[25] -	0xa3, 0x26,        // sal local[26] -	0xa3, 0x29,        // sal local[29] -	0x65, 0x16,        // aTop highlightedIcon -	0x34, 0xff, 0xff,  // ldi ffff -	0xa3, 0x2b,        // sal local[2b] -	0xa3, 0x2c,        // sal local[2c] -	PATCH_END -}; - -//    script, description,                                      magic DWORD,                             adjust -const SciScriptSignature castlebrainSignatures[] = { -	{    391, "cipher puzzle save/restore break",            1, PATCH_MAGICDWORD(0xa3, 0x26, 0xa3, 0x25),    -2, castlebrainSignatureCipherPuzzle, castlebrainPatchCipherPuzzle }, -	SCI_SIGNATUREENTRY_TERMINATOR -}; - -#endif -  // ===========================================================================  // stayAndHelp::changeState (0) is called when ego swims to the left or right  //  boundaries of room 660. Normally a textbox is supposed to get on screen @@ -497,74 +448,6 @@ const SciScriptSignature gk1Signatures[] = {  	SCI_SIGNATUREENTRY_TERMINATOR  }; -#if 0 - -// =========================================================================== -// this here gets called on entry and when going out of game windows -//  uEvt::port will not get changed after kDisposeWindow but a bit later, so -//  we would get an invalid port handle to a kSetPort call. We just patch in -//  resetting of the port selector. We destroy the stop/fade code in there, -//  it seems it isn't used at all in the game. -const byte hoyle4SignaturePortFix[] = { -	28, -	0x39, 0x09,        // pushi 09 -	0x89, 0x0b,        // lsg 0b -	0x39, 0x64,        // pushi 64 -	0x38, 0xc8, 0x00,  // pushi 00c8 -	0x38, 0x2c, 0x01,  // pushi 012c -	0x38, 0x90, 0x01,  // pushi 0190 -	0x38, 0xf4, 0x01,  // pushi 01f4 -	0x38, 0x58, 0x02,  // pushi 0258 -	0x38, 0xbc, 0x02,  // pushi 02bc -	0x38, 0x20, 0x03,  // pushi 0320 -	0x46,              // calle [xxxx] [xxxx] [xx] -	+5, 43,            // [skip 5 bytes] -	0x30, 0x27, 0x00,  // bnt 0027 -> end of routine -	0x87, 0x00,        // lap 00 -	0x30, 0x19, 0x00,  // bnt 0019 -> fade out -	0x87, 0x01,        // lap 01 -	0x30, 0x14, 0x00,  // bnt 0014 -> fade out -	0x38, 0xa7, 0x00,  // pushi 00a7 -	0x76,              // push0 -	0x80, 0x29, 0x01,  // lag 0129 -	0x4a, 0x04,        // send 04 - call song::stop -	0x39, 0x27,        // pushi 27 -	0x78,              // push1 -	0x8f, 0x01,        // lsp 01 -	0x51, 0x54,        // class 54 -	0x4a, 0x06,        // send 06 - call PlaySong::play -	0x33, 0x09,        // jmp 09 -> end of routine -	0x38, 0xaa, 0x00,  // pushi 00aa -	0x76,              // push0 -	0x80, 0x29, 0x01,  // lag 0129 -	0x4a, 0x04,        // send 04 -	0x48,              // ret -	0 -}; - -const uint16 hoyle4PatchPortFix[] = { -	PATCH_ADDTOOFFSET | +33, -	0x38, 0x31, 0x01,  // pushi 0131 (selector curEvent) -	0x76,              // push0 -	0x80, 0x50, 0x00,  // lag 0050 (global var 80h, "User") -	0x4a, 0x04,        // send 04 - read User::curEvent - -	0x38, 0x93, 0x00,  // pushi 0093 (selector port) -	0x78,              // push1 -	0x76,              // push0 -	0x4a, 0x06,        // send 06 - write 0 to that object::port -	0x48,              // ret -	PATCH_END -}; - -//    script, description,                                   magic DWORD,                                 adjust -const SciScriptSignature hoyle4Signatures[] = { -    {      0, "port fix when disposing windows",             PATCH_MAGICDWORD(0x64, 0x38, 0xC8, 0x00),    -5, hoyle4SignaturePortFix,   hoyle4PatchPortFix }, -    {      0, NULL,                                          0,                                            0, NULL,                     NULL } -}; - -#endif -  // ===========================================================================  // at least during harpy scene export 29 of script 0 is called in kq5cd and  //  has an issue for those calls, where temp 3 won't get inititialized, but @@ -826,50 +709,10 @@ const uint16 qfg1vgaPatchFightEvents[] = {  	PATCH_END  }; -// FIXME: -// When QFG1VGA and QFG3 dispose of a child window. For example, when choosing -// a spell (parent window), if the spell can't be casted, a subsequent window -// opens, notifying that it can't be casted. When showing the child window, the -// scripts restore the area below the parent window, draw the child window, and -// then attempt to redraw the parent window, which leads to the background -// picture (which has just been restored) overwriting the child window. -// -// This faulty redraw is caused by a used and freed SaveBits handle that is -// still stored in spellWin::pUnderBits being re-assigned with a SaveBits -// call for the child window. We should ensure that invalidated SaveBits handles -// can't (soon?) become valid again. -// -// However, we can just remove the window redraw and update calls when the -// window is supposed to be disposed, and the window is disposed of correctly. -// This is a workaround for bug #3053093. -const byte qfg1vgaWindowDispose[] = { -	17, -	0x39, 0x05,       // pushi 05 -	0x39, 0x0d,       // pushi 0d -	0x67, 0x2e,       // pTos 2e -	0x67, 0x30,       // pTos 30 -	0x67, 0x32,       // pTos 32 -	0x67, 0x34,       // pTos 34 -	0x43, 0x6c, 0x0a, // callk kGraph 10 -	0x39, 0x06,       // pushi 06 -	0 -}; - -const uint16 qfg1vgaPatchWindowDispose[] = { -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x33, 0x3e,       // jmp 0x3e (skip 62 bytes - this skips the subsequent 2 kGraph(update) calls, before kDisposeWindow is invoked) -	PATCH_END -}; -  //    script, description,                                      magic DWORD,                                  adjust  const SciScriptSignature qfg1vgaSignatures[] = {  	{    215, "fight event issue",                           1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07),    -1, qfg1vgaSignatureFightEvents,       qfg1vgaPatchFightEvents },  	{    216, "weapon master event issue",                   1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07),    -1, qfg1vgaSignatureFightEvents,       qfg1vgaPatchFightEvents }, -	{    559, "window dispose",                              1, PATCH_MAGICDWORD(0x39, 0x05, 0x39, 0x0d),     0,        qfg1vgaWindowDispose,     qfg1vgaPatchWindowDispose },  	SCI_SIGNATUREENTRY_TERMINATOR  }; @@ -933,37 +776,6 @@ const uint16 qfg3PatchImportDialog[] = {  	PATCH_END  }; -// When QFG1VGA and QFG3 dispose of a child window. For example, when choosing -// a spell (parent window), if the spell can't be casted, a subsequent window -// opens, notifying that it can't be casted. When showing the child window, the -// scripts restore the area below the parent window, draw the child window, and -// then attempt to redraw the parent window, which leads to the background -// picture (which has just been restored) overwriting the child window. It -// appers that kGraph(redrawBox) is different in QFG1VGA and QFG3. However, we -// can just remove the window redraw and update calls when the window is -// supposed to be disposed, and the window is disposed of correctly. Fixes bug -// #3053093. -const byte qfg3WindowDispose[] = { -	15, -	0x39, 0x05,       // pushi 05 -	0x39, 0x0d,       // pushi 0d -	0x67, 0x2e,       // pTos 2e -	0x67, 0x30,       // pTos 30 -	0x67, 0x32,       // pTos 32 -	0x67, 0x34,       // pTos 34 -	0x43, 0x6c, 0x0a, // callk kGraph 10 -	0 -}; - -const uint16 qfg3PatchWindowDispose[] = { -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	0x34, 0x00, 0x00, // ldi 0000 (dummy) -	PATCH_END -}; -  // Script 23 in QFG3 has a typo/bug which makes it loop endlessly and  // read garbage. Fixes bug #3040722.  const byte qfg3DialogCrash[] = { @@ -982,7 +794,6 @@ const uint16 qfg3PatchDialogCrash[] = {  //    script, description,                                      magic DWORD,                                  adjust  const SciScriptSignature qfg3Signatures[] = { -	{     22, "window dispose",                                 1, PATCH_MAGICDWORD(0x39, 0x05, 0x39, 0x0d),   0,         qfg3WindowDispose,        qfg3PatchWindowDispose },  	{     23, "dialog crash",                                   1, PATCH_MAGICDWORD(0xe7, 0x03, 0x22, 0x33),  -1,           qfg3DialogCrash,          qfg3PatchDialogCrash },  	{    944, "import dialog continuous calls",                 1, PATCH_MAGICDWORD(0x2a, 0x31, 0x0b, 0x7a),  -1, qfg3SignatureImportDialog,         qfg3PatchImportDialog },  	SCI_SIGNATUREENTRY_TERMINATOR @@ -1242,12 +1053,6 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr  void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {  	const SciScriptSignature *signatureTable = NULL;  	switch (g_sci->getGameId()) { -	// Dr. Brain now works because we properly maintain the state of the string heap in savegames -#if 0 -	case GID_CASTLEBRAIN: -		signatureTable = castlebrainSignatures; -		break; -#endif  	case GID_ECOQUEST:  		signatureTable = ecoquest1Signatures;  		break; @@ -1263,12 +1068,6 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin  	case GID_GK1:  		signatureTable = gk1Signatures;  		break; -	// hoyle4 now works due to workaround inside GfxPorts -#if 0 -	case GID_HOYLE4: -		signatureTable = hoyle4Signatures; -		break; -#endif  	case GID_KQ5:  		signatureTable = kq5Signatures;  		break; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index ffc81f0fde..f77bdf684e 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -403,7 +403,7 @@ void SegManager::freeHunkEntry(reg_t addr) {  		return;  	} -	ht->freeEntry(addr.offset); +	ht->freeEntryContents(addr.offset);  }  reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) { diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 05d914cffb..d1f56f0da2 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -275,6 +275,11 @@ Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const {  } +//-------------------- hunk --------------------- +void HunkTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { +	freeEntry(sub_addr.offset); +} +  //-------------------- lists --------------------  void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {  	freeEntry(sub_addr.offset); diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 9aaa3a4b08..56a6c71590 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -315,15 +315,18 @@ struct ListTable : public Table<List> {  struct HunkTable : public Table<Hunk> {  	HunkTable() : Table<Hunk>(SEG_TYPE_HUNK) {} -	virtual void freeEntry(int idx) { -		Table<Hunk>::freeEntry(idx); - -		if (!_table[idx].mem) -			warning("Attempt to free an already freed hunk"); +	void freeEntryContents(int idx) {  		free(_table[idx].mem);  		_table[idx].mem = 0;  	} +	virtual void freeEntry(int idx) { +		Table<Hunk>::freeEntry(idx); +		freeEntryContents(idx); +	} + +	virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); +  	virtual void saveLoadWithSerializer(Common::Serializer &ser);  }; diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 64cbc5ec90..c87ab59f8f 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -386,10 +386,7 @@ const SciWorkaroundEntry kStrLen_workarounds[] = {  //    gameID,           room,script,lvl,          object-name, method-name,    call,index,                workaround  const SciWorkaroundEntry kUnLoad_workarounds[] = { -	{ GID_CAMELOT,       921,   921,  1,             "Script", "changeState",  0x36,    0, { WORKAROUND_IGNORE, 0 } }, // DEMO: While showing Camelot (and other places), the reference is invalid - bug #3035000 -	{ GID_CAMELOT,       921,   921,  1,             "Script", "init",         0x36,    0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When being attacked by the boar (and other places), the reference is invalid - bug #3035000 -	{ GID_CASTLEBRAIN,   320,   377,  0,              "SWord", "upDate",         -1,    0, { WORKAROUND_IGNORE, 0 } }, // after solving the cross-word-puzzle, trying to unload invalid reference -	{ GID_CASTLEBRAIN,   320,   377,  0,            "theWord", "show",           -1,    0, { WORKAROUND_IGNORE, 0 } }, // 2nd word puzzle, when exiting before solving, trying to unload invalid reference - bug #3034473 +	// TODO: Some of these workarounds for invalid references can now be removed, test which ones  	{ GID_ECOQUEST,      380,    61,  0,              "gotIt", "changeState",    -1,    0, { WORKAROUND_IGNORE, 0 } }, // after talking to the dolphin the first time  	{ GID_ECOQUEST,      380,    69,  0,   "lookAtBlackBoard", "changeState",    -1,    0, { WORKAROUND_IGNORE, 0 } }, // German version, when closing the blackboard closeup in the dolphin room - bug #3098353  	{ GID_LAURABOW2,       1,     1,  0,           "sCartoon", "changeState",    -1,    0, { WORKAROUND_IGNORE, 0 } }, // DEMO: during the intro, a 3rd parameter is passed by accident - bug #3034902 @@ -400,7 +397,6 @@ const SciWorkaroundEntry kUnLoad_workarounds[] = {  	{ GID_LSL6,          130,   130,  0,    "recruitLarryScr", "changeState",    -1,    0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident  	{ GID_LSL6,          740,   740,  0,        "showCartoon", "changeState",    -1,    0, { WORKAROUND_IGNORE, 0 } }, // during ending, 4 additional parameters are passed by accident  	{ GID_LSL6HIRES,     130,   130,  0,    "recruitLarryScr", "changeState",    -1,    0, { WORKAROUND_IGNORE, 0 } }, // during intro, a 3rd parameter is passed by accident -	{ GID_PQ3,           877,   998,  0,               "View", "delete",         -1,    0, { WORKAROUND_IGNORE, 0 } }, // when getting run over on the freeway, the reference is invalid  	{ GID_SQ1,            43,   303,  0,            "slotGuy", "dispose",        -1,    0, { WORKAROUND_IGNORE, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error  	{ GID_SQ3,             2,   998,  0,               "View", "delete",         -1,    0, { WORKAROUND_IGNORE, 0 } }, // clicking the mouse button during the intro, after the escape pod gets pulled into the garbage freighter, the reference is invalid - bug #3050856  	SCI_WORKAROUNDENTRY_TERMINATOR diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 935dd4e62e..53c43d94c3 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -360,7 +360,7 @@ void GfxPaint16::bitsRestore(reg_t memoryHandle) {  		if (memoryPtr) {  			_screen->bitsRestore(memoryPtr); -			_segMan->freeHunkEntry(memoryHandle); +			bitsFree(memoryHandle);  		}  	}  } @@ -532,20 +532,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {  		case SCI_DISPLAY_RESTOREUNDER:  			bitsGetRect(argv[0], &rect);  			rect.translate(-_ports->getPort()->left, -_ports->getPort()->top); -			if (g_sci->getGameId() == GID_PQ3 && g_sci->getEngineState()->currentRoomNumber() == 29) { -				// WORKAROUND: PQ3 calls this without calling the associated -				// kDisplay(SCI_DISPLAY_SAVEUNDER) call before. Theoretically, -				// this would result in no rect getting restored. However, we -				// still maintain a pointer from the previous room, resulting -				// in invalidated content being restored on screen, and causing -				// graphics glitches. Thus, we simply don't restore a rect in -				// that room. The correct fix for this would be to erase hunk -				// pointers when changing rooms, but this will suffice for now, -				// as restoring from a totally invalid pointer is very rare. -				// Fixes bug #3037945. -			} else { -				bitsRestore(argv[0]); -			} +			bitsRestore(argv[0]);  			kernelGraphRedrawBox(rect);  			// finishing loop  			argc = 0; diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h index 21c6d31ebd..b94d54ab10 100644 --- a/engines/sci/graphics/ports.h +++ b/engines/sci/graphics/ports.h @@ -49,6 +49,9 @@ enum {  	SCI_WINDOWMGR_STYLE_USER        = (1 << 7)  }; +typedef Common::List<Port *> PortList; +typedef Common::Array<Port *> PortArray; +  /**   * Ports class, includes all port managment for SCI0->SCI1.1 games. Ports are some sort of windows in SCI   *  this class also handles adjusting coordinates to a specific port @@ -115,8 +118,12 @@ public:  	virtual void saveLoadWithSerializer(Common::Serializer &ser); +	/** The list of open 'windows' (and ports), in visual order. */ +	PortList _windowList; +  private: -	typedef Common::List<Port *> PortList; +	/** The list of all open 'windows' (and ports), ordered by their id. */ +	PortArray _windowsById;  	SegManager *_segMan;  	GfxPaint16 *_paint16; @@ -130,12 +137,6 @@ private:  	// counts windows that got disposed but are not freed yet  	uint16 _freeCounter; -	/** The list of open 'windows' (and ports), in visual order. */ -	PortList _windowList; - -	/** The list of all open 'windows' (and ports), ordered by their id. */ -	Common::Array<Port *> _windowsById; -  	Common::Rect _bounds;  	// Priority Bands related variables | 
