[Scummvm-git-logs] scummvm master -> a9bab56f4421761206e93899999c318746f58736

a-yyg 76591232+a-yyg at users.noreply.github.com
Sun Jul 11 10:02:22 UTC 2021


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
d822b43468 SAGA2: Fix for list traversal in checkTimers
a9bab56f44 SAGA2: Implement Timers save/loading


Commit: d822b43468092611a9e1fed115aace2a4dbc7c98
    https://github.com/scummvm/scummvm/commit/d822b43468092611a9e1fed115aace2a4dbc7c98
Author: a/ (yuri.kgpps at gmail.com)
Date: 2021-07-11T19:01:23+09:00

Commit Message:
SAGA2: Fix for list traversal in checkTimers

Changed paths:
    engines/saga2/objects.cpp
    engines/saga2/timers.cpp
    engines/saga2/timers.h


diff --git a/engines/saga2/objects.cpp b/engines/saga2/objects.cpp
index 9cc0b63a3b..b727bccb64 100644
--- a/engines/saga2/objects.cpp
+++ b/engines/saga2/objects.cpp
@@ -1860,6 +1860,7 @@ bool GameObject::addTimer(TimerID id, int16 frameInterval) {
 		assert((*it)->getObject() == this);
 
 		if (newTimer->thisID() == (*it)->thisID()) {
+			deleteTimer(*it);
 			delete *it;
 			timerList->_timers.erase(it);
 
@@ -1883,7 +1884,7 @@ void GameObject::removeTimer(TimerID id) {
 	if ((timerList = fetchTimerList(this)) != nullptr) {
 		for (Common::List<Timer *>::iterator it = timerList->_timers.begin(); it != timerList->_timers.end(); ++it) {
 			if ((*it)->thisID() == id) {
-				delete *it;
+				(*it)->_active = false;
 				timerList->_timers.erase(it);
 
 				if (timerList->_timers.empty())
@@ -1903,8 +1904,10 @@ void GameObject::removeAllTimers(void) {
 
 	//  Get this object's timer list
 	if ((timerList = fetchTimerList(this)) != nullptr) {
-		for (Common::List<Timer *>::iterator it = timerList->_timers.begin(); it != timerList->_timers.end(); ++it)
+		for (Common::List<Timer *>::iterator it = timerList->_timers.begin(); it != timerList->_timers.end(); ++it) {
+			deleteTimer(*it);
 			delete *it;
+		}
 
 		timerList->_timers.clear();
 
diff --git a/engines/saga2/timers.cpp b/engines/saga2/timers.cpp
index d37b469de8..6ae2228669 100644
--- a/engines/saga2/timers.cpp
+++ b/engines/saga2/timers.cpp
@@ -138,20 +138,30 @@ TimerList *fetchTimerList(GameObject *obj) {
 	return nullptr;
 }
 
+void deleteTimer(Timer *t) {
+	g_vm->_timers.remove(t);
+}
+
 //----------------------------------------------------------------------
 //	Check all active Timers
 void checkTimers(void) {
-	Common::List<Timer *>::iterator nextIt;
+	for (Common::List<Timer *>::iterator it = g_vm->_timers.begin(); it != g_vm->_timers.end(); it++) {
+		if ((*it)->_active == false)
+			continue;
 
-	for (Common::List<Timer *>::iterator it = g_vm->_timers.begin(); it != g_vm->_timers.end(); it = nextIt) {
-		nextIt = it;
-		++nextIt;
 		if ((*it)->check()) {
 			debugC(2, kDebugTimers, "Timer tick for %p (%s): %p (duration %d)", (void *)(*it)->getObject(), (*it)->getObject()->objName(), (void *)(*it), (*it)->getInterval());
 			(*it)->reset();
 			(*it)->getObject()->timerTick((*it)->thisID());
 		}
 	}
+
+	for (Common::List<Timer *>::iterator it = g_vm->_timers.begin(); it != g_vm->_timers.end(); it++) {
+		if ((*it)->_active == false) {
+			delete *it;
+			it = g_vm->_timers.erase(it);
+		}
+	}
 }
 
 //----------------------------------------------------------------------
@@ -387,7 +397,6 @@ Timer::Timer(void **buf) {
 Timer::~Timer() {
 	debugC(1, kDebugTimers, "Deleting timer %p (obj %p)",
 		   (void *)this, (void *)_obj);
-	g_vm->_timers.remove(this);
 }
 
 //----------------------------------------------------------------------
diff --git a/engines/saga2/timers.h b/engines/saga2/timers.h
index 9705f62217..3ca99a2d58 100644
--- a/engines/saga2/timers.h
+++ b/engines/saga2/timers.h
@@ -33,11 +33,14 @@
 
 namespace Saga2 {
 
+class Timer;
 class TimerList;
 
 //  Fetch a specified actor's TimerList
 TimerList *fetchTimerList(GameObject *obj);
 
+void deleteTimer(Timer *t);
+
 //  Check all active Timers
 void checkTimers(void);
 
@@ -93,8 +96,10 @@ class Timer {
 	FrameAlarm _alarm;
 
 public:
+	bool _active;
+
 	//  Constructor -- initial construction
-	Timer(GameObject *o, TimerID timerID, int16 frameInterval) : _obj(o), _id(timerID), _interval(frameInterval) {
+	Timer(GameObject *o, TimerID timerID, int16 frameInterval) : _obj(o), _id(timerID), _interval(frameInterval), _active(true) {
 		_alarm.set(_interval);
 		debugC(1, kDebugTimers, "Creating timer %p for %p (%s)",
 		       (void *)this, (void *)o, o->objName());


Commit: a9bab56f4421761206e93899999c318746f58736
    https://github.com/scummvm/scummvm/commit/a9bab56f4421761206e93899999c318746f58736
Author: a/ (yuri.kgpps at gmail.com)
Date: 2021-07-11T19:01:24+09:00

Commit Message:
SAGA2: Implement Timers save/loading

Changed paths:
    engines/saga2/calender.cpp
    engines/saga2/calender.h
    engines/saga2/loadsave.cpp
    engines/saga2/timers.cpp
    engines/saga2/timers.h


diff --git a/engines/saga2/calender.cpp b/engines/saga2/calender.cpp
index 5a87c0e9a1..7c5a0d944b 100644
--- a/engines/saga2/calender.cpp
+++ b/engines/saga2/calender.cpp
@@ -137,6 +137,16 @@ int CalenderTime::lightLevel(int maxLevel) {
    FrameAlarm member functions
  * ===================================================================== */
 
+void FrameAlarm::write(Common::OutSaveFile *out) {
+	out->writeUint16LE(baseFrame);
+	out->writeUint16LE(duration);
+}
+
+void FrameAlarm::read(Common::InSaveFile *in) {
+	baseFrame = in->readUint16LE();
+	duration = in->readUint16LE();
+}
+
 void FrameAlarm::set(uint16 dur) {
 	baseFrame = calender.frameInDay();
 	duration = dur;
diff --git a/engines/saga2/calender.h b/engines/saga2/calender.h
index b6aa1f58b5..46567ce2a8 100644
--- a/engines/saga2/calender.h
+++ b/engines/saga2/calender.h
@@ -80,6 +80,9 @@ public:
 	void set(uint16 dur);
 	bool check(void);
 	uint16 elapsed(void);
+
+	void write(Common::OutSaveFile *out);
+	void read(Common::InSaveFile *in);
 };
 
 /* ===================================================================== *
diff --git a/engines/saga2/loadsave.cpp b/engines/saga2/loadsave.cpp
index 7cca8bfc7d..b22b1e54b2 100644
--- a/engines/saga2/loadsave.cpp
+++ b/engines/saga2/loadsave.cpp
@@ -162,9 +162,9 @@ Common::Error saveGameState(int16 saveNo, char *saveName) {
 	saveTileTasks(out);
 	saveSpeechTasks(out);
 	saveActiveRegions(out);
+	saveTimers(out);
 
 #if 0
-	saveTimers(saveGame);
 	saveSensors(saveGame);
 	saveTempActorCount(saveGame);
 	saveMissions(saveGame);
@@ -351,15 +351,15 @@ void loadSavedGameState(int16 saveNo) {
 			loadActiveRegions(in);
 			loadFlags |= loadActiveRegionsFlag;
 			break;
-#if 0
 
 		case MKTAG('T', 'I', 'M', 'R'):
 			if (loadFlags & loadActorsFlag) {
-				loadTimers(saveGame);
+				loadTimers(in);
 				loadFlags |= loadTimersFlag;
 			} else
 				error("Timers loaded prematurely");
 			break;
+#if 0
 
 		case MKTAG('S', 'E', 'N', 'S'):
 			if (loadFlags & loadActorsFlag) {
diff --git a/engines/saga2/timers.cpp b/engines/saga2/timers.cpp
index 6ae2228669..c59e89844f 100644
--- a/engines/saga2/timers.cpp
+++ b/engines/saga2/timers.cpp
@@ -241,6 +241,72 @@ void saveTimers(SaveFileConstructor &saveGame) {
 #endif
 }
 
+static int getTimerListID(TimerList *t) {
+	int i = 0;
+	for (Common::List<TimerList *>::iterator it = g_vm->_timerLists.begin(); it != g_vm->_timerLists.end(); it++, i++) {
+		if ((*it) == t)
+			return i;
+	}
+	return -1;
+}
+
+static int getTimerID(Timer *t) {
+	int i = 0;
+	for (Common::List<Timer *>::iterator it = g_vm->_timers.begin(); it != g_vm->_timers.end(); it++, i++) {
+		if ((*it) == t)
+			return i;
+	}
+	return -1;
+}
+
+void saveTimers(Common::OutSaveFile *out) {
+	debugC(2, kDebugSaveload, "Saving Timers");
+
+	int16 timerListCount = 0,
+	      timerCount = 0;
+
+	int32 archiveBufSize = 0;
+
+	//  Add the sizes of the timer list count an timer count
+	archiveBufSize += sizeof(timerListCount) + sizeof(timerCount);
+
+	//  Tally the timer lists
+	timerListCount = g_vm->_timerLists.size();
+
+	//  Add the total archive size of all of the timer lists
+	archiveBufSize += timerListCount * TimerList::archiveSize();
+
+	//  Tally the timers
+	timerCount = g_vm->_timers.size();
+
+	debugC(3, kDebugSaveload, "... timerListCount = %d", timerListCount);
+	debugC(3, kDebugSaveload, "... timerCount = %d", timerCount);
+
+	//  Add the total archive size of all of the timers
+	archiveBufSize += timerCount * Timer::archiveSize();
+
+	out->write("TIMR", 4);
+	out->writeUint32LE(archiveBufSize);
+
+	//  Store the timer list count and timer count
+	out->writeSint16LE(timerListCount);
+	out->writeSint16LE(timerCount);
+
+	//  Archive all timer lists
+	for (Common::List<TimerList *>::iterator it = g_vm->_timerLists.begin(); it != g_vm->_timerLists.end(); it++) {
+		debugC(3, kDebugSaveload, "Saving TimerList %d", getTimerListID(*it));
+		(*it)->write(out);
+	}
+
+	for (Common::List<Timer *>::iterator it = g_vm->_timers.begin(); it != g_vm->_timers.end(); it++) {
+		if ((*it)->_active == false)
+			continue;
+		debugC(3, kDebugSaveload, "Saving Timer %d", getTimerID(*it));
+
+		(*it)->write(out);
+	}
+}
+
 //----------------------------------------------------------------------
 //	Load the Timers from a save file
 
@@ -298,6 +364,46 @@ void loadTimers(SaveFileReader &saveGame) {
 #endif
 }
 
+void loadTimers(Common::InSaveFile *in) {
+	debugC(2, kDebugSaveload, "Loading Timers");
+
+	int16 timerListCount,
+	      timerCount;
+
+	//  Get the timer list count and timer count
+	timerListCount = in->readSint16LE();
+	timerCount = in->readSint16LE();
+
+	debugC(3, kDebugSaveload, "... timerListCount = %d", timerListCount);
+	debugC(3, kDebugSaveload, "... timerCount = %d", timerCount);
+
+	//  Restore all timer lists
+	for (int i = 0; i < timerListCount; i++) {
+		debugC(3, kDebugSaveload, "Loading TimerList %d", i);
+		new TimerList(in);
+	}
+
+	//  Restore all timers
+	for (int i = 0; i < timerCount; i++) {
+		Timer       *timer;
+		TimerList   *timerList;
+
+		debugC(3, kDebugSaveload, "Loading Timer %d", i);
+
+		timer = new Timer(in);
+
+		assert(timer != NULL);
+
+		//  Get the objects's timer list
+		timerList = fetchTimerList(timer->getObject());
+
+		assert(timerList != NULL);
+
+		//  Append this timer to the objects's timer list
+		timerList->_timers.push_back(timer);
+	}
+}
+
 //----------------------------------------------------------------------
 //	Cleanup the active Timers
 
@@ -342,6 +448,17 @@ TimerList::TimerList(void **buf) {
 	g_vm->_timerLists.push_back(this);
 }
 
+TimerList::TimerList(Common::InSaveFile *in) {
+	ObjectID id = in->readUint16LE();
+
+	assert(isObject(id) || isActor(id));
+
+	//  Restore the object pointer
+	_obj = GameObject::objectAddress(id);
+
+	g_vm->_timerLists.push_back(this);
+}
+
 TimerList::~TimerList() {
 	debugC(1, kDebugTimers, "Deleting timer list %p for %p (%s))",
 		   (void *)this, (void *)_obj, _obj->objName());
@@ -359,6 +476,11 @@ void *TimerList::archive(void *buf) {
 	return buf;
 }
 
+void TimerList::write(Common::OutSaveFile *out) {
+	//  Store the object's ID
+	out->writeUint16LE(_obj->thisID());
+}
+
 /* ===================================================================== *
    Timer member functions
  * ===================================================================== */
@@ -394,6 +516,26 @@ Timer::Timer(void **buf) {
 	g_vm->_timers.push_back(this);
 }
 
+Timer::Timer(Common::InSaveFile *in) {
+	ObjectID id = in->readUint16LE();
+
+	assert(isObject(id) || isActor(id));
+
+	//  Restore the object pointer
+	_obj = GameObject::objectAddress(id);
+
+	//  Restore the timer's ID
+	_id = in->readSint16LE();
+
+	//  Restore the frame interval
+	_interval = in->readSint16LE();
+
+	//  Restore the alarm
+	_alarm.read(in);
+
+	g_vm->_timers.push_back(this);
+}
+
 Timer::~Timer() {
 	debugC(1, kDebugTimers, "Deleting timer %p (obj %p)",
 		   (void *)this, (void *)_obj);
@@ -432,4 +574,18 @@ void *Timer::archive(void *buf) {
 	return buf;
 }
 
+void Timer::write(Common::OutSaveFile *out) {
+	//  Store the obj's ID
+	out->writeUint16LE(_obj->thisID());
+
+	//  Store the timer's ID
+	out->writeSint16LE(_id);
+
+	//  Store the frame interval
+	out->writeSint16LE(_interval);
+
+	//  Store the alarm
+	_alarm.write(out);
+}
+
 } // end of namespace Saga2
diff --git a/engines/saga2/timers.h b/engines/saga2/timers.h
index 3ca99a2d58..e9b61f130b 100644
--- a/engines/saga2/timers.h
+++ b/engines/saga2/timers.h
@@ -48,8 +48,10 @@ void checkTimers(void);
 void initTimers(void);
 //  Save the active Timers in a save file
 void saveTimers(SaveFileConstructor &saveGame);
+void saveTimers(Common::OutSaveFile *out);
 //  Load Timers from a save file
 void loadTimers(SaveFileReader &saveGame);
+void loadTimers(Common::InSaveFile *in);
 //  Cleanup the active Timers
 void cleanupTimers(void);
 
@@ -67,6 +69,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	TimerList(void **buf);
 
+	TimerList(Common::InSaveFile *in);
+
 	~TimerList();
 
 	//  Return the number of bytes needed to archive this object in
@@ -78,6 +82,8 @@ public:
 	//  Archive this object in a buffer
 	void *archive(void *buf);
 
+	void write(Common::OutSaveFile *out);
+
 	GameObject *getObject(void) {
 		return _obj;
 	}
@@ -109,6 +115,9 @@ public:
 
 	//  Constructor -- reconstruct from archive buffer
 	Timer(void **buf);
+
+	Timer(Common::InSaveFile *in);
+
 	~Timer();
 
 	//  Return the number of bytes needed to archive this object in
@@ -118,6 +127,8 @@ public:
 	//  Archive this object in a buffer
 	void *archive(void *buf);
 
+	void write(Common::OutSaveFile *out);
+
 	GameObject *getObject(void) {
 		return _obj;
 	}




More information about the Scummvm-git-logs mailing list