diff options
-rw-r--r-- | engines/dm/TODOs/todo.txt | 2 | ||||
-rw-r--r-- | engines/dm/dungeonman.cpp | 13 | ||||
-rw-r--r-- | engines/dm/group.cpp | 13 | ||||
-rw-r--r-- | engines/dm/group.h | 3 |
4 files changed, 13 insertions, 18 deletions
diff --git a/engines/dm/TODOs/todo.txt b/engines/dm/TODOs/todo.txt index d49ec2209f..4aa4d36360 100644 --- a/engines/dm/TODOs/todo.txt +++ b/engines/dm/TODOs/todo.txt @@ -11,7 +11,7 @@ Bugs: Sometimes putting stuff in the player's hand segfaults Footprints are everywhere Object display is a bit mixed up with regards to which cell is it drawn in - Activegroup index segfaults when aknig the stairs + The last resurrected character can't have stuff in their left hand, segfaults if I try to put stuff into it Possible bugs: diff --git a/engines/dm/dungeonman.cpp b/engines/dm/dungeonman.cpp index 063ccd0388..956232bcd7 100644 --- a/engines/dm/dungeonman.cpp +++ b/engines/dm/dungeonman.cpp @@ -1396,19 +1396,16 @@ int16 DungeonMan::f154_getLocationAfterLevelChange(int16 mapIndex, int16 levelDe int16 targetMapIndex; - if (_vm->_dungeonMan->_g309_partyMapIndex == k255_mapIndexEntrance) { + if (_g309_partyMapIndex == k255_mapIndexEntrance) { return kM1_mapIndexNone; } - map = _vm->_dungeonMan->_g277_dungeonMaps + mapIndex; + map = _g277_dungeonMaps + mapIndex; newMapX = map->_offsetMapX + *mapX; newMapY = map->_offsetMapY + *mapY; newLevel = map->_level + levelDelta; - map = _vm->_dungeonMan->_g277_dungeonMaps; - for (targetMapIndex = 0; targetMapIndex < _vm->_dungeonMan->_g278_dungeonFileHeader._mapCount; targetMapIndex++) { - if ((map->_level == newLevel) - && (newMapX >= (offset = map->_offsetMapX)) - && (newMapX <= (offset + map->_width)) - && (newMapY >= (offset = map->_offsetMapY)) && (newMapY <= (offset + map->_height))) { + map = _g277_dungeonMaps; + for (targetMapIndex = 0; targetMapIndex < _g278_dungeonFileHeader._mapCount; targetMapIndex++) { + if ((map->_level == newLevel) && (newMapX >= (offset = map->_offsetMapX)) && (newMapX <= (offset + map->_width)) && (newMapY >= (offset = map->_offsetMapY)) && (newMapY <= (offset + map->_height))) { *mapY = newMapY - offset; *mapX = newMapX - map->_offsetMapX; return targetMapIndex; diff --git a/engines/dm/group.cpp b/engines/dm/group.cpp index 617735e6b6..edb6056aff 100644 --- a/engines/dm/group.cpp +++ b/engines/dm/group.cpp @@ -1691,17 +1691,16 @@ void GroupMan::f183_addActiveGroup(Thing thing, int16 mapX, int16 mapY) { L0344_i_ActiveGroupIndex = 0; while (L0341_ps_ActiveGroup->_groupThingIndex >= 0) { if (++L0344_i_ActiveGroupIndex >= _vm->_groupMan->_g376_maxActiveGroupCount) { - return; /* BUG0_11 Data corruption in memory. Each group located on the same map as the party has additional associated data but there is only provision for 60 instances (_vm->_groupMan->_g376_maxActiveGroupCount). If there are more groups at the same time then some of them do not get their instance and when the game accesses this information it will corrupt other data in memory (either the instance of another group, parts of the timeline or events). This situation cannot occur in the original Dungeon Master and Chaos Strikes Back dungeons for the following reasons (but it may occur in custom dungeons if they are not designed carefully): there is no map with already more than 60 groups in the original dungeons and none of the following 3 possible ways to move a group into a map can increase the number of instances above the maximum of 60: - - A group generator sensor is triggered: the game never generates a group on the party map if there are less than 5 instances available. This limits the actual number of groups on a map to 55 in most cases. - - A group falls through a pit from the map above (the creature type must be allowed on the target map): a group will never willingly move to an open pit square. It may move to a closed pit square and fall if the pit is then open (either automatically or triggered by the party on the map below). There are no such pits in the original dungeons. - - A group is teleported from another map (the creature type must be allowed on the target map): in the original dungeons, all teleporters whose scope include groups and target another map are either inaccessible to groups or the groups are not allowed on the target map. The only exception is for some Gigglers in the Chaos Strikes Back dungeon but there are not enough to use the 5 reserved instances. - - This code returns immediately if all ACTIVE_GROUP entries are already in use, which avoids an out of bounds access into _vm->_groupMan->_g375_activeGroups below (through L0341_ps_ActiveGroup). However in this case the specified group ends up without an associated ACTIVE_GROUP structure which is assumed everywhere in the code to be present for groups on the same map as the party. If there are more than 60 groups on the party map at any given time then this will corrupt memory (in _vm->_timeline->_g370_events and _vm->_timeline->_g371_timeline allocated in _vm->_timeline->f233_initTimeline before _vm->_groupMan->_g375_activeGroups) because of read and write operations at incorrect memory addresses (the 'Cells' value of the GROUP will be used as an index in _vm->_groupMan->_g375_activeGroups even though that value was not replaced by the index of an ACTIVE_GROUP in this function) */ + return; } L0341_ps_ActiveGroup++; } _g377_currActiveGroupCount++; - L0340_ps_Group = ((Group *)_vm->_dungeonMan->_g284_thingData[k4_GroupThingType]) + (L0341_ps_ActiveGroup->_groupThingIndex = (thing).getType()); + + warning(false, "Code differs from the original in GroupMan::f183_addActiveGroup"); + //L0340_ps_Group = ((Group *)_vm->_dungeonMan->_g284_thingData[k4_GroupThingType]) + (L0341_ps_ActiveGroup->_groupThingIndex = (thing).getType()); + L0340_ps_Group = (Group*)_vm->_dungeonMan->f156_getThingData(f175_groupGetThing(mapX, mapY)); + L0341_ps_ActiveGroup->_cells = L0340_ps_Group->_cells; L0340_ps_Group->getActiveGroupIndex() = L0344_i_ActiveGroupIndex; L0341_ps_ActiveGroup->_priorMapX = L0341_ps_ActiveGroup->_homeMapX = mapX; diff --git a/engines/dm/group.h b/engines/dm/group.h index fd7d98afe7..6578a20851 100644 --- a/engines/dm/group.h +++ b/engines/dm/group.h @@ -114,7 +114,6 @@ public: uint16 _type; uint16 _cells; uint16 _health[4]; -private: uint16 _flags; public: explicit Group(uint16 *rawDat) : _nextThing(rawDat[0]), _slot(rawDat[1]), _type(rawDat[2]), @@ -125,7 +124,7 @@ public: _health[3] = rawDat[7]; } - byte &getActiveGroupIndex() { return *(byte*)&_cells; } + uint16 &getActiveGroupIndex() { return _cells; } uint16 getBehaviour() { return _flags & 0xF; } uint16 setBehaviour(uint16 val) { _flags = (_flags & ~0xF) | (val & 0xF); return (val & 0xF); } |