java-topology/defects/scummvm-0002/patch/scummvm-0002.patch
russell@unturf.com 7fa196837a scummvm: 2 CWE-407 defects, vita3k: 1 CWE-407 defect, MOAD 0002-0005 CLEAN
scummvm-0001: crab PathfindingGrid::getNearestOpenNode BFS visited set
  Common::Array<Node*> O(N^2), fix std::unordered_set O(N), 104x speedup

scummvm-0002: tsage WalkRegions::calculateRestOfRoute _disabledRegions
  Common::List<int>::contains O(D) in recursive route loop, fix
  std::unordered_set<int> O(1), 2.5x speedup

vita3k-0001: ngs deliver_data voice_queue std::vector::contains O(V^2*P)
  per audio frame, fix std::unordered_set built once per frame O(V*P),
  9.3x speedup at V=256
2026-03-31 19:37:12 -04:00

73 lines
2.7 KiB
Diff

# UNDF: UNDF-2026-XXXXXXXXX
--- a/engines/tsage/core.h
+++ b/engines/tsage/core.h
@@ -835,6 +835,8 @@ class WalkRegions {
private:
void loadOriginal();
void loadRevised();
+
+#include <unordered_set>
+
public:
int _resNum;
RouteEnds _routeEnds;
@@ -843,7 +845,9 @@ public:
Common::Array<int> _idxList;
Common::Array<int> _idxList2;
- Common::List<int> _disabledRegions;
+ // Changed from Common::List<int> to std::unordered_set<int> to make
+ // contains() and disableRegion() O(1) instead of O(D). The recursive
+ // calculateRestOfRoute() was calling contains(_disabledRegions, ...) on
+ // every connected region per step, producing O(D * R * depth) total work.
+ std::unordered_set<int> _disabledRegions;
public:
WalkRegions() { _resNum = -1; }
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -4302,18 +4302,18 @@ void WalkRegions::synchronize(Serializer &s) {
// Synchronize the list of disabled regions as a list of values terminated with a '-1'
int regionId = 0;
if (s.isLoading()) {
_disabledRegions.clear();
s.syncAsSint16LE(regionId);
while (regionId != -1) {
- _disabledRegions.push_back(regionId);
+ _disabledRegions.insert(regionId);
s.syncAsSint16LE(regionId);
}
} else {
- Common::List<int>::iterator i;
- for (i = _disabledRegions.begin(); i != _disabledRegions.end(); ++i) {
- regionId = *i;
+ for (const int id : _disabledRegions) {
+ regionId = id;
s.syncAsSint16LE(regionId);
}
regionId = -1;
s.syncAsSint16LE(regionId);
}
}
@@ -4325,8 +4325,8 @@ void WalkRegions::synchronize(Serializer &s) {
void WalkRegions::disableRegion(int regionId) {
- if (!contains(_disabledRegions, regionId))
- _disabledRegions.push_back(regionId);
+ _disabledRegions.insert(regionId); // O(1); unordered_set deduplicates automatically
}
void WalkRegions::enableRegion(int regionId) {
- _disabledRegions.remove(regionId);
+ _disabledRegions.erase(regionId); // O(1)
}
--- a/engines/tsage/core.cpp (calculateRestOfRoute change)
+++ b/engines/tsage/core.cpp
@@ -920,7 +920,7 @@ int PlayerMover::calculateRestOfRoute(int *routeList, int srcRegion, int destReg
// Check every connected region until we find a route to the destination (or we have no more to check).
int bestDistance = 31990;
while (((currDest = g_globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + foundIndex]) != 0) && (!foundRoute)) {
// Only check the region if it isn't in the list of explicitly disabled regions
- if (!contains(g_globals->_walkRegions._disabledRegions, (int)currDest)) {
+ if (g_globals->_walkRegions._disabledRegions.find((int)currDest) == g_globals->_walkRegions._disabledRegions.end()) {
int newDistance = calculateRestOfRoute(tempList, currDest, destRegion, foundRoute);