From 63b1de562801d93919a3241c3525466d2a24754f Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Sat, 22 Mar 2008 09:46:25 +0000 Subject: Add support for room states in Waxworks (DOS). svn-id: r31218 --- engines/agos/agos.cpp | 3 +- engines/agos/agos.h | 5 +-- engines/agos/intern.h | 8 +++++ engines/agos/res.cpp | 13 ++++--- engines/agos/res_snd.cpp | 4 +++ engines/agos/rooms.cpp | 86 ++++++++++++++++++++++++++++++++++++++++------- engines/agos/saveload.cpp | 69 +++++++++++++++++++++++++++++++++---- 7 files changed, 161 insertions(+), 27 deletions(-) (limited to 'engines/agos') diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 47a4c7c9aa..015aff3458 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -146,11 +146,12 @@ AGOSEngine::AGOSEngine(OSystem *syst) _stringIdLocalMin = 0; _stringIdLocalMax = 0; - _stateList = 0; + _roomStates = 0; _numRoomStates = 0; _menuBase = 0; _roomsList = 0; + _roomsListPtr = 0; _xtblList = 0; _xtablesHeapPtrOrg = 0; diff --git a/engines/agos/agos.h b/engines/agos/agos.h index c690bc668d..d2b4b73f43 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -240,11 +240,12 @@ protected: byte **_localStringtable; uint _stringIdLocalMin, _stringIdLocalMax; - byte *_stateList; - uint _numRoomStates; + RoomState *_roomStates; + uint16 _numRoomStates; byte *_menuBase; byte *_roomsList; + byte *_roomsListPtr; byte *_xtblList; byte *_xtablesHeapPtrOrg; diff --git a/engines/agos/intern.h b/engines/agos/intern.h index 6becd8fc73..54cf4dba16 100644 --- a/engines/agos/intern.h +++ b/engines/agos/intern.h @@ -115,6 +115,14 @@ enum { SubObject_SIZE = sizeof(SubObject) - sizeof(int16) }; +struct RoomState { + uint16 state; + uint16 classFlags; + uint16 roomExitStates; + + RoomState() { memset(this, 0, sizeof(*this)); } +}; + struct Item { uint16 parent; uint16 child; diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp index d74563226f..4aca390f3b 100644 --- a/engines/agos/res.cpp +++ b/engines/agos/res.cpp @@ -221,14 +221,17 @@ void AGOSEngine::loadGamePcFile() { _numRoomStates = in.size() / 8; - _stateList = (byte *)malloc(_numRoomStates * 6); - if (_stateList == NULL) + _roomStates = (RoomState *)calloc(_numRoomStates, sizeof(RoomState)); + if (_roomStates == NULL) error("loadGamePcFile: Out of memory for room state list"); - _numRoomStates *= 3; - - // TODO Load room state resources + for (uint s = 0; s < _numRoomStates; s++) { + uint16 num = in.readUint16BE() - (_itemArrayInited - 2); + _roomStates[num].state = in.readUint16BE(); + _roomStates[num].classFlags = in.readUint16BE(); + _roomStates[num].roomExitStates = in.readUint16BE(); + } in.close(); } diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp index 738de98342..091a254fbc 100644 --- a/engines/agos/res_snd.cpp +++ b/engines/agos/res_snd.cpp @@ -285,6 +285,10 @@ void AGOSEngine_Simon1::playMusic(uint16 music, uint16 track) { void AGOSEngine::playMusic(uint16 music, uint16 track) { stopMusic(); + // FIXME: Music too unstable, when switching locations. + if (getPlatform() == Common::kPlatformPC && getGameType() == GType_WW) + return; + if (getPlatform() == Common::kPlatformAmiga) { playModule(music); } else if (getPlatform() == Common::kPlatformAtariST) { diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp index e1e6b11d0e..aa63fe535b 100644 --- a/engines/agos/rooms.cpp +++ b/engines/agos/rooms.cpp @@ -351,19 +351,43 @@ void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) { } // Waxworks specific -bool AGOSEngine::loadRoomItems(uint16 item) { +bool AGOSEngine::loadRoomItems(uint16 room) { byte *p; - uint i, min_num, max_num; + uint i, minNum, maxNum; char filename[30]; File in; + Item *item, *itemTmp; - p = _roomsList; - if (p == NULL) + if (_roomsList == NULL) return 0; - _currentRoom = item; - item -= 2; + _currentRoom = room; + room -= 2; + + if (_roomsListPtr) { + p = _roomsListPtr; + for (;;) { + minNum = READ_BE_UINT16(p); p += 2; + if (minNum == 0) + break; + + maxNum = READ_BE_UINT16(p); p += 2; + + for (uint16 z = minNum; z <= maxNum; z++) { + uint16 itemNum = z + 2; + item = derefItem(itemNum); + item->parent = 0; + uint16 num = (itemNum - _itemArrayInited); + _roomStates[num].state = item->state; + _roomStates[num].classFlags = item->classFlags; + SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType); + _roomStates[num].roomExitStates = subRoom->roomExitStates; + } + } + } + + p = _roomsList; while (*p) { for (i = 0; *p; p++, i++) filename[i] = *p; @@ -371,21 +395,57 @@ bool AGOSEngine::loadRoomItems(uint16 item) { p++; for (;;) { - min_num = READ_BE_UINT16(p); p += 2; - if (min_num == 0) + _roomsListPtr = p; + + minNum = READ_BE_UINT16(p); p += 2; + if (minNum == 0) break; - max_num = READ_BE_UINT16(p); p += 2; + maxNum = READ_BE_UINT16(p); p += 2; - if (item >= min_num && item <= max_num) { + if (room >= minNum && room <= maxNum) { in.open(filename); if (in.isOpen() == false) { error("loadRoomItems: Can't load rooms file '%s'", filename); } while ((i = in.readUint16BE()) != 0) { - _itemArrayPtr[i + 2] = (Item *)allocateItem(sizeof(Item)); - readItemFromGamePc(&in, _itemArrayPtr[i + 2]); + uint16 itemNum = i + 2; + + _itemArrayPtr[itemNum] = (Item *)allocateItem(sizeof(Item)); + readItemFromGamePc(&in, _itemArrayPtr[itemNum]); + + item = derefItem(itemNum); + item->parent = 0; + item->child = 0; + + for (uint16 z = _itemArrayInited - 1; z; z--) { + itemTmp = _itemArrayPtr[z]; + + if (itemTmp->parent == 0) + continue; + if (itemTmp->parent != itemNum) + continue; + if (item->child == 0) { + item->child = z; + continue; + } + uint16 child = item->child; + while (itemTmp->next != 0) { + if (itemTmp->next == child) { + item->child = z; + break; + } + + itemTmp = _itemArrayPtr[itemTmp->next]; + } + } + + uint16 num = (itemNum - _itemArrayInited); + item->state = _roomStates[num].state; + item->classFlags = _roomStates[num].classFlags; + SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType); + subRoom->roomExitStates = _roomStates[num].roomExitStates; } in.close(); @@ -394,7 +454,7 @@ bool AGOSEngine::loadRoomItems(uint16 item) { } } - debug(1,"loadRoomItems: didn't find %d", item); + debug(1,"loadRoomItems: didn't find %d", room); return 0; } diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp index 65b35a426a..1957d6ec10 100644 --- a/engines/agos/saveload.cpp +++ b/engines/agos/saveload.cpp @@ -1196,11 +1196,43 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) { } if (getGameType() == GType_WW && getPlatform() == Common::kPlatformPC) { - // TODO Load room state data - for (uint s = 0; s <= _numRoomStates; s++) { - f->readUint16BE(); + for (uint s = 0; s < _numRoomStates; s++) { + _roomStates[s].state = f->readUint16BE(); + _roomStates[s].classFlags = f->readUint16BE(); + _roomStates[s].roomExitStates = f->readUint16BE(); } f->readUint16BE(); + + uint16 room = _currentRoom; + _currentRoom = f->readUint16BE(); + + if (_roomsListPtr) { + byte *p = _roomsListPtr; + for (;;) { + uint16 minNum = READ_BE_UINT16(p); p += 2; + if (minNum == 0) + break; + + uint16 maxNum = READ_BE_UINT16(p); p += 2; + + for (uint16 z = minNum; z <= maxNum; z++) { + uint16 itemNum = z + 2; + Item *item = derefItem(itemNum); + item->parent = 0; + + num = (itemNum - _itemArrayInited); + item->state = _roomStates[num].state; + item->classFlags = _roomStates[num].classFlags; + SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType); + subRoom->roomExitStates = _roomStates[num].roomExitStates; + } + } + } + + if (room != _currentRoom) { + _roomsListPtr = 0; + loadRoomItems(_currentRoom); + } } item_index = 1; @@ -1354,10 +1386,35 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { } if (getGameType() == GType_WW && getPlatform() == Common::kPlatformPC) { - // TODO Save room state data - for (uint s = 0; s <= _numRoomStates; s++) { - f->writeUint16BE(0); + if (_roomsListPtr) { + byte *p = _roomsListPtr; + for (;;) { + uint16 minNum = READ_BE_UINT16(p); p += 2; + if (minNum == 0) + break; + + uint16 maxNum = READ_BE_UINT16(p); p += 2; + + for (uint16 z = minNum; z <= maxNum; z++) { + uint16 itemNum = z + 2; + Item *item = derefItem(itemNum); + item->parent = 0; + + uint16 num = (itemNum - _itemArrayInited); + _roomStates[num].state = item->state; + _roomStates[num].classFlags = item->classFlags; + SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType); + _roomStates[num].roomExitStates = subRoom->roomExitStates; + } + } + } + + for (uint s = 0; s < _numRoomStates; s++) { + f->writeUint16BE(_roomStates[s].state); + f->writeUint16BE(_roomStates[s].classFlags); + f->writeUint16BE(_roomStates[s].roomExitStates); } + f->writeUint16BE(0); f->writeUint16BE(_currentRoom); } -- cgit v1.2.3