[Scummvm-git-logs] scummvm master -> 9238ed99032ed5de4de498cbca353b3c93e584c5

a-yyg 76591232+a-yyg at users.noreply.github.com
Sat Jul 10 18:25:55 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:
b919df6bcb SAGA2: Implement Tasks save/loading
9238ed9903 SAGA2: Add error check on TaskStacks loading


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

Commit Message:
SAGA2: Implement Tasks save/loading

Changed paths:
    engines/saga2/loadsave.cpp
    engines/saga2/patrol.cpp
    engines/saga2/patrol.h
    engines/saga2/task.cpp
    engines/saga2/task.h


diff --git a/engines/saga2/loadsave.cpp b/engines/saga2/loadsave.cpp
index 1a4ef5cf5d..89f077c025 100644
--- a/engines/saga2/loadsave.cpp
+++ b/engines/saga2/loadsave.cpp
@@ -158,9 +158,9 @@ Common::Error saveGameState(int16 saveNo, char *saveName) {
 	saveSAGAThreads(out);
 	saveMotionTasks(out);
 	saveTaskStacks(out);
+	saveTasks(out);
 
 #if 0
-	saveTasks(saveGame);
 	saveTileTasks(saveGame);
 	saveSpeechTasks(saveGame);
 	saveActiveRegions(saveGame);
@@ -322,15 +322,15 @@ void loadSavedGameState(int16 saveNo) {
 			} else
 				error("TaskStacks loaded prematurely");
 			break;
-#if 0
 
 		case MKTAG('T', 'A', 'S', 'K'):
 			if (loadFlags & loadTaskStacksFlag) {
-				loadTasks(saveGame);
+				loadTasks(in, chunkSize);
 				loadFlags |= loadTasksFlag;
 			} else
 				error("Tasks loaded prematurely");
 			break;
+#if 0
 
 		case MKTAG('T', 'A', 'C', 'T'):
 			if (loadFlags & loadWorldsFlag) {
diff --git a/engines/saga2/patrol.cpp b/engines/saga2/patrol.cpp
index cefe2f7007..4e53bbddd6 100644
--- a/engines/saga2/patrol.cpp
+++ b/engines/saga2/patrol.cpp
@@ -103,6 +103,20 @@ PatrolRouteIterator::PatrolRouteIterator(uint8 map, int16 rte, uint8 type, int16
 	_vertexNo = clamp(0, startingPoint, route.vertices() - 1);
 }
 
+void PatrolRouteIterator::read(Common::InSaveFile *in) {
+	_routeNo = in->readSint16LE();
+	_vertexNo = in->readSint16LE();
+	_mapNum = in->readByte();
+	_flags = in->readByte();
+}
+
+void PatrolRouteIterator::write(Common::OutSaveFile *out) const {
+	out->writeSint16LE(_routeNo);
+	out->writeSint16LE(_vertexNo);
+	out->writeByte(_mapNum);
+	out->writeByte(_flags);
+}
+
 //-----------------------------------------------------------------------
 //	Increment the waypoint index
 void PatrolRouteIterator::increment(void) {
diff --git a/engines/saga2/patrol.h b/engines/saga2/patrol.h
index 7bfedf4097..178d55fc64 100644
--- a/engines/saga2/patrol.h
+++ b/engines/saga2/patrol.h
@@ -124,6 +124,9 @@ public:
 	PatrolRouteIterator(uint8 map, int16 rte, uint8 type);
 	PatrolRouteIterator(uint8 map, int16 rte, uint8 type, int16 startingPoint);
 
+	void read(Common::InSaveFile *in);
+	void write(Common::OutSaveFile *out) const;
+
 private:
 	void increment(void);		// Increment waypoint index
 	void decrement(void);		// Decrement waypoint index
diff --git a/engines/saga2/task.cpp b/engines/saga2/task.cpp
index 00250fe9f1..c202220083 100644
--- a/engines/saga2/task.cpp
+++ b/engines/saga2/task.cpp
@@ -48,6 +48,7 @@ bool actorTasksPaused;
 
 //  Reconstruct a Task from an archive buffer
 void *constructTask(TaskID id, void *buf);
+void readTask(TaskID id, Common::InSaveFile *in);
 
 //  Return the number of bytes necessary to create an archive of the
 //  specified Task
@@ -55,6 +56,7 @@ int32 taskArchiveSize(Task *t);
 
 //  Create an archive of the specified Task in the specified buffer
 void *archiveTask(Task *t, void *buf);
+void writeTask(Task *t, Common::OutSaveFile *out);
 
 #if DEBUG
 //  Debugging function used to check the integrity of the global task
@@ -540,6 +542,8 @@ public:
 	//  Reconstruct from an archive buffer
 	void *restore(void *buf);
 
+	void read(Common::InSaveFile *in);
+
 	//  Return the number of bytes necessary to archive this task list
 	//  in a buffer
 	int32 archiveSize(void);
@@ -547,6 +551,8 @@ public:
 	//  Create an archive of the task list in an archive buffer
 	void *archive(void *buf);
 
+	void write(Common::OutSaveFile *out);
+
 	//  Place a Task from the inactive list into the active
 	//  list.
 	void newTask(Task *t);
@@ -585,6 +591,13 @@ TaskList::TaskList(void) {
 //	TaskList destructor
 
 TaskList::~TaskList(void) {
+	for (int i = 0; i < numTasks; i++) {
+		if (_list[i] == nullptr)
+			continue;
+
+		delete _list[i];
+		_list[i] = nullptr;
+	}
 }
 
 //----------------------------------------------------------------------
@@ -623,6 +636,25 @@ void *TaskList::restore(void *buf) {
 	return buf;
 }
 
+void TaskList::read(Common::InSaveFile *in) {
+	int16 taskCount;
+
+	//  Get the count of tasks and increment the buffer pointer
+	taskCount = in->readSint16LE();
+	debugC(3, kDebugSaveload, "... taskCount = %d", taskCount);
+
+	//  Iterate through the archive data, reconstructing the Tasks
+	for (int i = 0; i < taskCount; i++) {
+		TaskID id;
+
+		//  Retreive the Task's id number
+		id = in->readSint16LE();
+		debugC(3, kDebugSaveload, "Loading Task %d", i);
+
+		readTask(id, in);
+	}
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes necessary to archive this TaskList
 
@@ -674,6 +706,29 @@ void *TaskList::archive(void *buf) {
 	return buf;
 }
 
+void TaskList::write(Common::OutSaveFile *out) {
+	int16 taskCount = 0;
+
+	//  Count the active tasks
+	for (int i = 0 ; i < numTasks; ++i)
+		if (_list[i])
+			taskCount++;
+
+	//  Store the task count in the archive buffer
+	out->writeSint16LE(taskCount);
+	debugC(3, kDebugSaveload, "... taskCount = %d", taskCount);
+
+	for (int i = 0; i < numTasks; ++i) {
+		if (_list[i] == nullptr)
+			continue;
+
+		debugC(3, kDebugSaveload, "Saving Task %d", i);
+
+		out->writeSint16LE(i);
+		writeTask(_list[i], out);
+	}
+}
+
 void TaskList::newTask(Task *t) {
 	debugC(1, kDebugTasks, "List: %p Adding task %p (total %d)", (void *)this, (void *)t, ++_size);
 	for (int i = 0; i < numTasks; i++)
@@ -782,6 +837,19 @@ void saveTasks(SaveFileConstructor &saveGame) {
 	free(archiveBuffer);
 }
 
+void saveTasks(Common::OutSaveFile *out) {
+	debugC(2, kDebugSaveload, "Saving Tasks");
+
+	int32 archiveBufSize;
+
+	archiveBufSize = taskList.archiveSize();
+
+	out->write("TASK", 4);
+	out->writeUint32LE(archiveBufSize);
+
+	taskList.write(out);
+}
+
 //----------------------------------------------------------------------
 //	Load the taskList from a save file
 
@@ -815,6 +883,18 @@ void loadTasks(SaveFileReader &saveGame) {
 	free(archiveBuffer);
 }
 
+void loadTasks(Common::InSaveFile *in, int32 chunkSize) {
+	debugC(2, kDebugSaveload, "Loading Tasks");
+
+	//  If there is no saved data, simply call the default constructor
+	if (chunkSize == 0) {
+		return;
+	}
+
+	//  Reconstruct taskList from archived data
+	taskList.read(in);
+}
+
 //----------------------------------------------------------------------
 //	Cleanup the taskList
 
@@ -911,6 +991,88 @@ void *constructTask(TaskID id, void *buf) {
 	return buf;
 }
 
+void readTask(TaskID id, Common::InSaveFile *in) {
+	int16 type;
+
+	//  Get the Task type
+	type = in->readSint16LE();
+
+	//  Reconstruct the Task based upon the type
+	switch (type) {
+	case wanderTask:
+		new WanderTask(in, id);
+		break;
+
+	case tetheredWanderTask:
+		new TetheredWanderTask(in, id);
+		break;
+
+	case gotoLocationTask:
+		new GotoLocationTask(in, id);
+		break;
+
+	case gotoRegionTask:
+		new GotoRegionTask(in, id);
+		break;
+
+	case gotoObjectTask:
+		new GotoObjectTask(in, id);
+		break;
+
+	case gotoActorTask:
+		new GotoActorTask(in, id);
+		break;
+
+	case goAwayFromObjectTask:
+		new GoAwayFromObjectTask(in, id);
+		break;
+
+	case goAwayFromActorTask:
+		new GoAwayFromActorTask(in, id);
+		break;
+
+	case huntToBeNearLocationTask:
+		new HuntToBeNearLocationTask(in, id);
+		break;
+
+	case huntToBeNearObjectTask:
+		new HuntToBeNearObjectTask(in, id);
+		break;
+
+	case huntToPossessTask:
+		new HuntToPossessTask(in, id);
+		break;
+
+	case huntToBeNearActorTask:
+		new HuntToBeNearActorTask(in, id);
+		break;
+
+	case huntToKillTask:
+		new HuntToKillTask(in, id);
+		break;
+
+	case huntToGiveTask:
+		new HuntToGiveTask(in, id);
+		break;
+
+	case bandTask:
+		new BandTask(in, id);
+		break;
+
+	case bandAndAvoidEnemiesTask:
+		new BandAndAvoidEnemiesTask(in, id);
+		break;
+
+	case followPatrolRouteTask:
+		new FollowPatrolRouteTask(in, id);
+		break;
+
+	case attendTask:
+		new AttendTask(in, id);
+		break;
+	}
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes necessary to create an archive of the
 //	specified Task
@@ -934,6 +1096,14 @@ void *archiveTask(Task *t, void *buf) {
 	return buf;
 }
 
+void writeTask(Task *t, Common::OutSaveFile *out) {
+	//  Store the task's type
+	out->writeSint16LE(t->getType());
+
+	//  Store the task
+	t->write(out);
+}
+
 /* ===================================================================== *
    Task member functions
  * ===================================================================== */
@@ -950,12 +1120,11 @@ Task::Task(void **buf, TaskID id) {
 	*buf = (TaskStackID *)bufferPtr + 1;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the Task pointers
-
-void Task::fixup(void) {
-	//  Convert the stack ID to a stack pointer
-	stack = getTaskStackAddress(*((TaskStackID *)&stack));
+Task::Task(Common::InSaveFile *in, TaskID id) {
+	//  Place the stack ID into the stack pointer field
+	int16 stackID = in->readSint16LE();
+	stack = getTaskStackAddress(stackID);
+	newTask(this, id);
 }
 
 //----------------------------------------------------------------------
@@ -975,6 +1144,10 @@ void *Task::archive(void *buf) const {
 	return (TaskStackID *)buf + 1;
 }
 
+void Task::write(Common::OutSaveFile *out) const {
+	out->writeSint16LE(getTaskStackID(stack));
+}
+
 /* ===================================================================== *
    WanderTask member functions
  * ===================================================================== */
@@ -996,6 +1169,14 @@ WanderTask::WanderTask(void **buf, TaskID id) : Task(buf, id) {
 	*buf = bufferPtr;
 }
 
+WanderTask::WanderTask(Common::InSaveFile *in, TaskID id) : Task(in, id) {
+	//  Restore the paused flag
+	paused = in->readByte();
+
+	//  Restore the counter
+	counter = in->readSint16LE();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -1024,6 +1205,17 @@ void *WanderTask::archive(void *buf) const {
 	return buf;
 }
 
+void WanderTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	Task::write(out);
+
+	//  Store the paused flag
+	out->writeByte(paused);
+
+	//  Store the counter
+	out->writeSint16LE(counter);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -1125,19 +1317,20 @@ TetheredWanderTask::TetheredWanderTask(void **buf, TaskID id) : WanderTask(buf,
 	*buf = bufferPtr;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointers
-
-void TetheredWanderTask::fixup(void) {
-	//  Let the base class fixup it's pointers
-	WanderTask::fixup();
+TetheredWanderTask::TetheredWanderTask(Common::InSaveFile *in, TaskID id) : WanderTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading TetheredWanderTask");
 
-	TaskID      gotoTetherID = *((TaskID *)&gotoTether);
+	//  Restore the tether coordinates
+	minU = in->readSint16LE();
+	minV = in->readSint16LE();
+	maxU = in->readSint16LE();
+	maxV = in->readSint16LE();
 
-	//  Restore the gotoTether pointer
-	gotoTether =    gotoTetherID != NoTask
-	                ? (GotoRegionTask *)getTaskAddress(gotoTetherID)
-	                :   NULL;
+	//  Put the gotoTether ID into the gotoTether pointer field
+	int gotoTetherID = in->readSint16LE();
+	gotoTether = gotoTetherID != NoTask
+	             ? (GotoRegionTask *)getTaskAddress(gotoTetherID)
+	             :   NULL;
 }
 
 //----------------------------------------------------------------------
@@ -1175,6 +1368,25 @@ void *TetheredWanderTask::archive(void *buf) const {
 	return (TaskID *)bufferPtr + 1;
 }
 
+void TetheredWanderTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving TetheredWanderTask");
+
+	//  Let the base class archive its data
+	WanderTask::write(out);
+
+	//  Archive tether coordinates
+	out->writeSint16LE(minU);
+	out->writeSint16LE(minV);
+	out->writeSint16LE(maxU);
+	out->writeSint16LE(maxV);
+
+	//  Archive gotoTether ID
+	if (gotoTether != NULL)
+		out->writeSint16LE(getTaskID(gotoTether));
+	else
+		out->writeSint16LE(NoTask);
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -1304,19 +1516,15 @@ GotoTask::GotoTask(void **buf, TaskID id) : Task(buf, id) {
 	*buf = (bool *)bufferPtr + 1;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointers
-
-void GotoTask::fixup(void) {
-	//  Let the base class fixup its pointers
-	Task::fixup();
-
-	TaskID  wanderID = *((TaskID *)&wander);
+GotoTask::GotoTask(Common::InSaveFile *in, TaskID id) : Task(in, id) {
+	//  Get the wander TaskID
+	TaskID wanderID = in->readSint16LE();
+	wander = wanderID != NoTask
+	         ? (WanderTask *)getTaskAddress(wanderID)
+	         :   NULL;
 
-	//  Convert wanderID to a Task pointer
-	wander =    wanderID != NoTask
-	            ? (WanderTask *)getTaskAddress(wanderID)
-	            :   NULL;
+	//  Restore prevRunState
+	prevRunState = in->readByte();
 }
 
 //----------------------------------------------------------------------
@@ -1348,6 +1556,21 @@ void *GotoTask::archive(void *buf) const {
 	return buf;
 }
 
+void GotoTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	Task::write(out);
+
+	//  Convert the wander Task pointer to a TaskID and store it
+	//  in the buffer
+	if (wander != NULL)
+		out->writeSint16LE(getTaskID(wander));
+	else
+		out->writeSint16LE(NoTask);
+
+	//  Store prevRunState
+	out->writeByte(prevRunState);
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -1489,6 +1712,16 @@ GotoLocationTask::GotoLocationTask(void **buf, TaskID id) : GotoTask(buf, id) {
 	*buf = bufferPtr;
 }
 
+GotoLocationTask::GotoLocationTask(Common::InSaveFile *in, TaskID id) : GotoTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading GotoLocationTask");
+
+	//  Restore the target location
+	targetLoc.load(in);
+
+	//  Restore the runThreshold
+	runThreshold = in->readByte();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -1517,6 +1750,19 @@ void *GotoLocationTask::archive(void *buf) const {
 	return buf;
 }
 
+void GotoLocationTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving GotoLocationTask");
+
+	//  Let the base class archive its data
+	GotoTask::write(out);
+
+	//  Archive the target location
+	targetLoc.write(out);
+
+	//  Archive the run threshold
+	out->writeByte(runThreshold);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -1588,6 +1834,16 @@ GotoRegionTask::GotoRegionTask(void **buf, TaskID id) : GotoTask(buf, id) {
 	*buf = bufferPtr;
 }
 
+GotoRegionTask::GotoRegionTask(Common::InSaveFile *in, TaskID id) : GotoTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading GotoRegionTask");
+
+	//  Restore the region coordinates
+	regionMinU = in->readSint16LE();
+	regionMinV = in->readSint16LE();
+	regionMaxU = in->readSint16LE();
+	regionMaxV = in->readSint16LE();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -1618,6 +1874,18 @@ void *GotoRegionTask::archive(void *buf) const {
 	return bufferPtr;
 }
 
+void GotoRegionTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving GotoRegionTask");
+
+	//  Let the base class archive its data
+	GotoTask::write(out);
+	//  Archive the region coordinates
+	out->writeSint16LE(regionMinU);
+	out->writeSint16LE(regionMinV);
+	out->writeSint16LE(regionMaxU);
+	out->writeSint16LE(regionMaxV);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -1694,6 +1962,20 @@ GotoObjectTargetTask::GotoObjectTargetTask(void **buf, TaskID id) : GotoTask(buf
 	*buf = (TilePoint *)bufferPtr + 1;
 }
 
+GotoObjectTargetTask::GotoObjectTargetTask(Common::InSaveFile *in, TaskID id) : GotoTask(in, id) {
+	//  Restore lastTestedLoc and increment pointer
+	lastTestedLoc.load(in);
+
+	//  Restore sightCtr and increment pointer
+	sightCtr = in->readSint16LE();
+
+	//  Restore the flags and increment pointer
+	flags = in->readByte();
+
+	//  Restore lastKnownLoc
+	lastKnownLoc.load(in);
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -1731,6 +2013,23 @@ void *GotoObjectTargetTask::archive(void *buf) const {
 	return (TilePoint *)buf + 1;
 }
 
+void GotoObjectTargetTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	GotoTask::write(out);
+
+	//  Archive lastTestedLoc and increment pointer
+	lastTestedLoc.write(out);
+
+	//  Archive sightCtr and increment pointer
+	out->writeSint16LE(sightCtr);
+
+	//  Archive the flags and increment pointer
+	out->writeByte(flags);
+
+	//  Archive lastKnownLoc
+	lastKnownLoc.write(out);
+}
+
 //----------------------------------------------------------------------
 
 TilePoint GotoObjectTargetTask::destination(void) {
@@ -1835,6 +2134,18 @@ GotoObjectTask::GotoObjectTask(void **buf, TaskID id) :
 	*buf = bufferPtr + 1;
 }
 
+GotoObjectTask::GotoObjectTask(Common::InSaveFile *in, TaskID id) :
+	GotoObjectTargetTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading GotoObjectTask");
+
+	ObjectID targetID = in->readUint16LE();
+
+	//  Restore the targetObj pointer
+	targetObj = targetID != Nothing
+	            ?   GameObject::objectAddress(targetID)
+	            :   NULL;
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -1857,6 +2168,18 @@ void *GotoObjectTask::archive(void *buf) const {
 	return (ObjectID *)buf + 1;
 }
 
+void GotoObjectTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving GotoObjectTask");
+
+	//  Let the base class archive its data
+	GotoObjectTargetTask::write(out);
+
+	if (targetObj != NULL)
+		out->writeUint16LE(targetObj->thisID());
+	else
+		out->writeUint16LE(Nothing);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -1909,6 +2232,16 @@ GotoActorTask::GotoActorTask(void **buf, TaskID id) :
 	*buf = bufferPtr + 1;
 }
 
+GotoActorTask::GotoActorTask(Common::InSaveFile *in, TaskID id) :
+	GotoObjectTargetTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading GotoActorTask");
+	//  Restore the targetObj pointer
+	ObjectID targetID = in->readUint16LE();
+	targetActor =   targetID != Nothing
+	                ? (Actor *)GameObject::objectAddress(targetID)
+	                :   NULL;
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -1931,6 +2264,18 @@ void *GotoActorTask::archive(void *buf) const {
 	return (ObjectID *)buf + 1;
 }
 
+void GotoActorTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving GotoActorTask");
+
+	//  Let the base class archive its data
+	GotoObjectTargetTask::write(out);
+
+	if (targetActor != NULL)
+		out->writeUint16LE(targetActor->thisID());
+	else
+		out->writeUint16LE(Nothing);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -1987,22 +2332,15 @@ GoAwayFromTask::GoAwayFromTask(void **buf, TaskID id) : Task(buf, id) {
 	*buf = bufferPtr;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointer
-
-void GoAwayFromTask::fixup(void) {
-	//  Let the base class fixup its pointers
-	Task::fixup();
-
-	TaskID      goTaskID;
-
+GoAwayFromTask::GoAwayFromTask(Common::InSaveFile *in, TaskID id) : Task(in, id) {
 	//  Get the subtask ID
-	goTaskID = *((TaskID *)&goTask);
+	TaskID goTaskID = in->readSint16LE();
+	goTask = goTaskID != NoTask
+	         ? (GotoLocationTask *)getTaskAddress(goTaskID)
+	         :   NULL;
 
-	//  Convert the subtask ID to a pointer
-	goTask =    goTaskID != NoTask
-	            ? (GotoLocationTask *)getTaskAddress(goTaskID)
-	            :   NULL;
+	//  Restore the flags
+	flags = in->readByte();
 }
 
 //----------------------------------------------------------------------
@@ -2031,6 +2369,20 @@ void *GoAwayFromTask::archive(void *buf) const {
 	return buf;
 }
 
+void GoAwayFromTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	Task::write(out);
+
+	//  Store the subTask's ID
+	if (goTask != NULL)
+		out->writeSint16LE(getTaskID(goTask));
+	else
+		out->writeSint16LE(NoTask);
+
+	//  Store the flags
+	out->writeByte(flags);
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -2130,6 +2482,19 @@ GoAwayFromObjectTask::GoAwayFromObjectTask(void **buf, TaskID id) :
 	*buf = bufferPtr;
 }
 
+GoAwayFromObjectTask::GoAwayFromObjectTask(Common::InSaveFile *in, TaskID id) :
+	GoAwayFromTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading GoAwayFromObjectTask");
+
+	//  Get the object's ID
+	ObjectID objectID = in->readUint16LE();
+
+	//  Convert the ID to an object pointer
+	obj = objectID != Nothing
+		? GameObject::objectAddress(objectID)
+		: NULL;
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2157,6 +2522,19 @@ void *GoAwayFromObjectTask::archive(void *buf) const {
 	return buf;
 }
 
+void GoAwayFromObjectTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving GoAwayFromObjectTask");
+
+	//  Let the base class archive its data
+	GoAwayFromTask::write(out);
+
+	//  Store the object's ID
+	if (obj != NULL)
+		out->writeUint16LE(obj->thisID());
+	else
+		out->writeUint16LE(Nothing);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -2218,6 +2596,13 @@ GoAwayFromActorTask::GoAwayFromActorTask(void **buf, TaskID id) : GoAwayFromTask
 	*buf = constructTarget(targetMem, *buf);
 }
 
+GoAwayFromActorTask::GoAwayFromActorTask(Common::InSaveFile *in, TaskID id) : GoAwayFromTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading GoAwayFromActorTask");
+
+	//  Restore the target
+	readTarget(targetMem, in);
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2239,6 +2624,16 @@ void *GoAwayFromActorTask::archive(void *buf) const {
 	return buf;
 }
 
+void GoAwayFromActorTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving GoAwayFromActorTask");
+
+	//  Let the base class archive its data
+	GoAwayFromTask::write(out);
+
+	//  Store the target
+	writeTarget(getTarget(), out);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -2310,15 +2705,13 @@ HuntTask::HuntTask(void **buf, TaskID id) : Task(buf, id) {
 	*buf = bufferPtr;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointers
-
-void HuntTask::fixup(void) {
-	//  Let the base class fixup its pointers
-	Task::fixup();
+HuntTask::HuntTask(Common::InSaveFile *in, TaskID id) : Task(in, id) {
+	//  Restore the flags
+	huntFlags = in->readByte();
 
+	//  If the flags say we have a sub task, restore it too
 	if (huntFlags & (huntGoto | huntWander)) {
-		TaskID  subTaskID = *((TaskID *)&subTask);
+		TaskID subTaskID = in->readSint16LE();
 		subTask = getTaskAddress(subTaskID);
 	}
 }
@@ -2356,6 +2749,18 @@ void *HuntTask::archive(void *buf) const {
 	return buf;
 }
 
+void HuntTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	Task::write(out);
+
+	//  Store the flags
+	out->writeByte(huntFlags);
+
+	//  If the flags say we have a sub task, store it too
+	if (huntFlags & (huntGoto | huntWander))
+		out->writeSint16LE(getTaskID(subTask));
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -2496,6 +2901,14 @@ HuntLocationTask::HuntLocationTask(void **buf, TaskID id) : HuntTask(buf, id) {
 	*buf = constructTarget(targetMem, bufferPtr);
 }
 
+HuntLocationTask::HuntLocationTask(Common::InSaveFile *in, TaskID id) : HuntTask(in, id) {
+	//  Restore the currentTarget location
+	currentTarget.load(in);
+
+	//  Restore the target
+	readTarget(targetMem, in);
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2521,6 +2934,17 @@ void *HuntLocationTask::archive(void *buf) const {
 	return archiveTarget(getTarget(), buf);
 }
 
+void HuntLocationTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	HuntTask::write(out);
+
+	//  Store the current target location
+	currentTarget.write(out);
+
+	//  Store the target
+	writeTarget(getTarget(), out);
+}
+
 //----------------------------------------------------------------------
 
 bool HuntLocationTask::targetHasChanged(GotoTask *gotoTarget) {
@@ -2566,6 +2990,17 @@ HuntToBeNearLocationTask::HuntToBeNearLocationTask(void **buf, TaskID id) :
 	*buf = (uint8 *)bufferPtr + 1;
 }
 
+HuntToBeNearLocationTask::HuntToBeNearLocationTask(Common::InSaveFile *in, TaskID id) :
+	HuntLocationTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading HuntToBeNearLocationTask");
+
+	//  Restore the range
+	range = in->readUint16LE();
+
+	//  Restore the evaluation counter
+	targetEvaluateCtr = in->readByte();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2593,6 +3028,19 @@ void *HuntToBeNearLocationTask::archive(void *buf) const {
 	return (uint8 *)buf + 1;
 }
 
+void HuntToBeNearLocationTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving HuntToBeNearLocationTask");
+
+	//  Let the base class archive its data
+	HuntLocationTask::write(out);
+
+	//  Store the range
+	out->writeUint16LE(range);
+
+	//  Store the evaluation counter
+	out->writeByte(targetEvaluateCtr);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -2692,6 +3140,19 @@ HuntObjectTask::HuntObjectTask(void **buf, TaskID id) : HuntTask(buf, id) {
 	*buf = constructTarget(targetMem, bufferPtr);
 }
 
+HuntObjectTask::HuntObjectTask(Common::InSaveFile *in, TaskID id) : HuntTask(in, id) {
+	//  Restore the current target ID
+	ObjectID currentTargetID = in->readUint16LE();
+
+	//  Convert the ID to a GameObject pointer
+	currentTarget = currentTargetID != Nothing
+	                ?   GameObject::objectAddress(currentTargetID)
+	                :   NULL;
+
+	//  Reconstruct the object target
+	readTarget(targetMem, in);
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2724,6 +3185,20 @@ void *HuntObjectTask::archive(void *buf) const {
 	return archiveTarget(getTarget(), buf);
 }
 
+void HuntObjectTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	HuntTask::write(out);
+
+	//  Store the ID
+	if (currentTarget != NULL)
+		out->writeByte(currentTarget->thisID());
+	else
+		out->writeByte(Nothing);
+
+	//  Store the object target
+	writeTarget(getTarget(), out);
+}
+
 //----------------------------------------------------------------------
 
 bool HuntObjectTask::targetHasChanged(GotoTask *gotoTarget) {
@@ -2772,6 +3247,17 @@ HuntToBeNearObjectTask::HuntToBeNearObjectTask(void **buf, TaskID id) :
 	*buf = (uint8 *)bufferPtr + 1;
 }
 
+HuntToBeNearObjectTask::HuntToBeNearObjectTask(Common::InSaveFile *in, TaskID id) :
+	HuntObjectTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading HuntToBeNearObjectTask");
+
+	//  Restore the range
+	range = in->readUint16LE();
+
+	//  Restore the evaluation counter
+	targetEvaluateCtr = in->readByte();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2799,6 +3285,19 @@ void *HuntToBeNearObjectTask::archive(void *buf) const {
 	return (uint8 *)buf + 1;
 }
 
+void HuntToBeNearObjectTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving HuntToBeNearObjectTask");
+
+	//  Let the base class archive its data
+	HuntObjectTask::write(out);
+
+	//  Store the range
+	out->writeUint16LE(range);
+
+	//  Store the evaluation counter
+	out->writeByte(targetEvaluateCtr);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -2912,6 +3411,16 @@ HuntToPossessTask::HuntToPossessTask(void **buf, TaskID id) : HuntObjectTask(buf
 	*buf = (bool *)bufferPtr + 1;
 }
 
+HuntToPossessTask::HuntToPossessTask(Common::InSaveFile *in, TaskID id) : HuntObjectTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading HuntToPossessTask");
+
+	//  Restore evaluation counter
+	targetEvaluateCtr = in->readByte();
+
+	//  Restore grab flag
+	grabFlag = in->readByte();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -2939,6 +3448,19 @@ void *HuntToPossessTask::archive(void *buf) const {
 	return (bool *)buf + 1;
 }
 
+void HuntToPossessTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving HuntToPossessTask");
+
+	//  Let the base class archive its data
+	HuntObjectTask::write(out);
+
+	//  Store the evaluation counter
+	out->writeByte(targetEvaluateCtr);
+
+	//  Store the grab flag
+	out->writeByte(grabFlag);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -3075,6 +3597,22 @@ HuntActorTask::HuntActorTask(void **buf, TaskID id) : HuntTask(buf, id) {
 	*buf = constructTarget(targetMem, bufferPtr);
 }
 
+HuntActorTask::HuntActorTask(Common::InSaveFile *in, TaskID id) : HuntTask(in, id) {
+	//  Restore the flags
+	flags = in->readByte();
+
+	//  Restore the current target ID
+	ObjectID currentTargetID = in->readUint16LE();
+
+	//  Convert the ID to a GameObject pointer
+	currentTarget = currentTargetID != Nothing
+	                ? (Actor *)GameObject::objectAddress(currentTargetID)
+	                :   NULL;
+
+	//  Reconstruct the object target
+	readTarget(targetMem, in);
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -3112,6 +3650,23 @@ void *HuntActorTask::archive(void *buf) const {
 	return archiveTarget(getTarget(), buf);
 }
 
+void HuntActorTask::write(Common::OutSaveFile *out) const {
+	//  Let the base class archive its data
+	HuntTask::write(out);
+
+	//  Store the flags
+	out->writeByte(flags);
+
+	//  Store the ID
+	if (currentTarget != NULL)
+		out->writeUint16LE(currentTarget->thisID());
+	else
+		out->writeUint16LE(Nothing);
+
+	//  Store the object target
+	writeTarget(getTarget(), out);
+}
+
 //----------------------------------------------------------------------
 
 bool HuntActorTask::targetHasChanged(GotoTask *gotoTarget) {
@@ -3173,19 +3728,23 @@ HuntToBeNearActorTask::HuntToBeNearActorTask(void **buf, TaskID id) :
 	*buf = (uint8 *)bufferPtr + 1;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointers
-
-void HuntToBeNearActorTask::fixup(void) {
-	//  Let the base class fixup its pointers
-	HuntActorTask::fixup();
+HuntToBeNearActorTask::HuntToBeNearActorTask(Common::InSaveFile *in, TaskID id) :
+	HuntActorTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading HuntToBeNearActorTask");
 
-	TaskID      goAwayID = *((TaskID *)&goAway);
+	//  Get the goAway task ID
+	TaskID goAwayID = in->readSint16LE();
 
 	//  Convert the task ID to a task pointer
-	goAway =    goAwayID != NoTask
-	            ? (GoAwayFromObjectTask *)getTaskAddress(goAwayID)
-	            :   NULL;
+	goAway = goAwayID != NoTask
+	         ? (GoAwayFromObjectTask *)getTaskAddress(goAwayID)
+	         :   NULL;
+
+	//  Restore the range
+	range = in->readUint16LE();
+
+	//  Restore the evaluation counter
+	targetEvaluateCtr = in->readByte();
 }
 
 //----------------------------------------------------------------------
@@ -3225,6 +3784,25 @@ void *HuntToBeNearActorTask::archive(void *buf) const {
 	return (uint8 *)buf + 1;
 }
 
+void HuntToBeNearActorTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving HuntToBeNearActorTask");
+
+	//  Let the base class archive its data
+	HuntActorTask::write(out);
+
+	//  Store the task ID
+	if (goAway != NULL)
+		out->writeSint16LE(getTaskID(goAway));
+	else
+		out->writeSint16LE(NoTask);
+
+	//  Store the range
+	out->writeUint16LE(range);
+
+	//  Store the evaluation counter
+	out->writeByte(targetEvaluateCtr);
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -3418,6 +3996,15 @@ HuntToKillTask::HuntToKillTask(void **buf, TaskID id) : HuntActorTask(buf, id) {
 	*buf = bufferPtr;
 }
 
+HuntToKillTask::HuntToKillTask(Common::InSaveFile *in, TaskID id) : HuntActorTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading HuntToKillTask");
+
+	//  Restore the evaluation counter
+	targetEvaluateCtr = in->readByte();
+	specialAttackCtr = in->readByte();
+	flags = in->readByte();
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -3445,6 +4032,18 @@ void *HuntToKillTask::archive(void *buf) const {
 	return buf;
 }
 
+void HuntToKillTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving HuntToKillTask");
+
+	//  Let the base class archive its data
+	HuntActorTask::write(out);
+
+	//  Store the evaluation counter
+	out->writeByte(targetEvaluateCtr);
+	out->writeByte(specialAttackCtr);
+	out->writeByte(flags);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -3788,6 +4387,18 @@ HuntToGiveTask::HuntToGiveTask(void **buf, TaskID id) : HuntActorTask(buf, id) {
 	*buf = bufferPtr;
 }
 
+HuntToGiveTask::HuntToGiveTask(Common::InSaveFile *in, TaskID id) : HuntActorTask(in, id) {
+	debugC(3, kDebugSaveload, "... Loading HuntToGiveTask");
+
+	//  Get the object ID
+	ObjectID objToGiveID = in->readUint16LE();
+
+	//  Convert the object ID to a pointer
+	objToGive = objToGiveID != Nothing
+	            ?   GameObject::objectAddress(objToGiveID)
+	            :   NULL;
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -3815,6 +4426,19 @@ void *HuntToGiveTask::archive(void *buf) const {
 	return (ObjectID *)buf + 1;
 }
 
+void HuntToGiveTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving HuntToGiveTask");
+
+	//  Let base class archive its data
+	HuntActorTask::write(out);
+
+	//  Store the ID
+	if (objToGive != NULL)
+		out->writeUint16LE(objToGive->thisID());
+	else
+		out->writeUint16LE(Nothing);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
@@ -3937,19 +4561,21 @@ BandTask::BandTask(void **buf, TaskID id) : HuntTask(buf, id) {
 	*buf = bufferPtr;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointers
-
-void BandTask::fixup(void) {
-	//  Let the base class fixup its pointers
-	HuntTask::fixup();
+BandTask::BandTask(Common::InSaveFile *in, TaskID id) : HuntTask(in, id) {
+	TaskID attendID = in->readSint16LE();
+	debugC(3, kDebugSaveload, "... Loading BandTask");
 
-	TaskID      attendID = *((TaskID *)&attend);
 
 	//  Convert the TaskID to a Task pointer
-	attend =    attendID != NoTask
-	            ? (AttendTask *)getTaskAddress(attendID)
-	            :   NULL;
+	attend = attendID != NoTask
+	         ? (AttendTask *)getTaskAddress(attendID)
+	         :   NULL;
+
+	//  Restore the current target location
+	currentTarget.load(in);
+
+	//  Restore the target evaluation counter
+	targetEvaluateCtr = in->readByte();
 }
 
 //----------------------------------------------------------------------
@@ -3985,6 +4611,25 @@ void *BandTask::archive(void *buf) const {
 	return buf;
 }
 
+void BandTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving BandTask");
+
+	//  Let the base class archive its data
+	HuntTask::write(out);
+
+	//  Store the attend task ID
+	if (attend != NULL)
+		out->writeSint16LE(getTaskID(attend));
+	else
+		out->writeSint16LE(NoTask);
+
+	//  Store the current target location
+	currentTarget.write(out);
+
+	//  Store the target evaluation counter
+	out->writeByte(targetEvaluateCtr);
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -4332,19 +4977,28 @@ FollowPatrolRouteTask::FollowPatrolRouteTask(void **buf, TaskID id) : Task(buf,
 	*buf = bufferPtr;
 }
 
-//----------------------------------------------------------------------
-//	Fixup the subtask pointers
-
-void FollowPatrolRouteTask::fixup(void) {
-	//  Let the base class fixup its pointers
-	Task::fixup();
+FollowPatrolRouteTask::FollowPatrolRouteTask(Common::InSaveFile *in, TaskID id) : Task(in, id) {
+	debugC(3, kDebugSaveload, "... Loading FollowPatrolRouteTask");
 
-	TaskID      gotoWayPointID = *((TaskID *)&gotoWayPoint);
+	//  Get the gotoWayPoint TaskID
+	TaskID gotoWayPointID = in->readSint16LE();
 
 	//  Convert the TaskID to a Task pointer
-	gotoWayPoint =  gotoWayPointID != NoTask
-	                ? (GotoLocationTask *)getTaskAddress(gotoWayPointID)
-	                :   NULL;
+	gotoWayPoint = gotoWayPointID != NoTask
+	               ? (GotoLocationTask *)getTaskAddress(gotoWayPointID)
+	               :   NULL;
+
+	//  Restore the patrol route iterator
+	patrolIter.read(in);
+
+	//  Restore the last waypoint number
+	lastWayPointNum = in->readSint16LE();
+
+	//  Restore the paused flag
+	paused = in->readByte();
+
+	//  Restore the paused counter
+	counter = in->readSint16LE();
 }
 
 //----------------------------------------------------------------------
@@ -4397,6 +5051,31 @@ void *FollowPatrolRouteTask::archive(void *buf) const {
 	return buf;
 }
 
+void FollowPatrolRouteTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving FollowPatrolRouteTask");
+
+	//  Let the base class archive its data
+	Task::write(out);
+
+	//  Store the gotoWayPoint ID
+	if (gotoWayPoint != NULL)
+		out->writeSint16LE(getTaskID(gotoWayPoint));
+	else
+		out->writeSint16LE(NoTask);
+
+	//  Store the PatrolRouteIterator
+	patrolIter.write(out);
+
+	//  Store the last waypoint number
+	out->writeSint16LE(lastWayPointNum);
+
+	//  Store the paused flag
+	out->writeByte(paused);
+
+	//  Store the paused counter
+	out->writeSint16LE(counter);
+}
+
 #if DEBUG
 //----------------------------------------------------------------------
 //	Debugging function used to mark this task and any sub tasks as being
@@ -4550,6 +5229,18 @@ AttendTask::AttendTask(void **buf, TaskID id) : Task(buf, id) {
 	*buf = bufferPtr;
 }
 
+AttendTask::AttendTask(Common::InSaveFile *in, TaskID id) : Task(in, id) {
+	debugC(3, kDebugSaveload, "... Loading AttendTask");
+
+	//  Get the object ID
+	ObjectID objID = in->readUint16LE();
+
+	//  Convert the object ID to a pointer
+	obj = objID != Nothing
+		? GameObject::objectAddress(objID)
+		: NULL;
+}
+
 //----------------------------------------------------------------------
 //	Return the number of bytes needed to archive this object in
 //	a buffer
@@ -4576,6 +5267,19 @@ void *AttendTask::archive(void *buf) const {
 	return (ObjectID *)buf + 1;
 }
 
+void AttendTask::write(Common::OutSaveFile *out) const {
+	debugC(3, kDebugSaveload, "... Saving AttendTask");
+
+	//  Let the base class archive its data
+	Task::write(out);
+
+	//  Store the object ID
+	if (obj != NULL)
+		out->writeUint16LE(obj->thisID());
+	else
+		out->writeUint16LE(Nothing);
+}
+
 //----------------------------------------------------------------------
 //	Return an integer representing the type of this task
 
diff --git a/engines/saga2/task.h b/engines/saga2/task.h
index 4e049309ec..6456ea1a88 100644
--- a/engines/saga2/task.h
+++ b/engines/saga2/task.h
@@ -115,9 +115,11 @@ void initTasks(void);
 
 //  Save the task list to a save file
 void saveTasks(SaveFileConstructor &saveGame);
+void saveTasks(Common::OutSaveFile *out);
 
 //  Load the task list from a save file
 void loadTasks(SaveFileReader &saveGame);
+void loadTasks(Common::InSaveFile *in, int32 chunkSize);
 
 //  Cleanup the task list
 void cleanupTasks(void);
@@ -149,14 +151,13 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	Task(void **buf, TaskID id);
 
+	Task(Common::InSaveFile *in, TaskID id);
+
 	//  Virtual destructor -- do nothing
 	virtual ~Task(void) {
 		deleteTask(this);
 	}
 
-	//  Fixup any subtask pointers
-	virtual void fixup(void);
-
 	//  Return the number of bytes necessary to archive this Task
 	//  in a buffer
 	virtual int32 archiveSize(void) const;
@@ -164,6 +165,8 @@ public:
 	//  Create an archive of this task in a buffer
 	virtual void *archive(void *buf) const;
 
+	virtual void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	virtual int16 getType(void) const = 0;
 
@@ -199,6 +202,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	WanderTask(void **buf, TaskID id);
 
+	WanderTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -206,6 +211,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -271,8 +278,7 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	TetheredWanderTask(void **buf, TaskID id);
 
-	//  Fixup the subtask pointers
-	void fixup(void);
+	TetheredWanderTask(Common::InSaveFile *in, TaskID id);
 
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
@@ -281,6 +287,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -320,6 +328,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GotoTask(void **buf, TaskID id);
 
+	GotoTask(Common::InSaveFile *in, TaskID id);
+
 	//  Fixup the subtask pointer
 	void fixup(void);
 
@@ -330,6 +340,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -371,6 +383,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GotoLocationTask(void **buf, TaskID id);
 
+	GotoLocationTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -378,6 +392,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -429,6 +445,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GotoRegionTask(void **buf, TaskID id);
 
+	GotoRegionTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -436,6 +454,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -488,6 +508,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GotoObjectTargetTask(void **buf, TaskID id);
 
+	GotoObjectTargetTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -495,6 +517,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 private:
 	TilePoint destination(void);
 	TilePoint intermediateDest(void);
@@ -535,6 +559,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GotoObjectTask(void **buf, TaskID id);
 
+	GotoObjectTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -542,6 +568,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -575,6 +603,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GotoActorTask(void **buf, TaskID id);
 
+	GotoActorTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -582,6 +612,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -631,8 +663,7 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GoAwayFromTask(void **buf, TaskID id);
 
-	//  Fixup the subtask pointer
-	void fixup(void);
+	GoAwayFromTask(Common::InSaveFile *in, TaskID id);
 
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
@@ -641,6 +672,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -674,6 +707,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GoAwayFromObjectTask(void **buf, TaskID id);
 
+	GoAwayFromObjectTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -681,6 +716,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -712,6 +749,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	GoAwayFromActorTask(void **buf, TaskID id);
 
+	GoAwayFromActorTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -719,6 +758,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -759,8 +800,7 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntTask(void **buf, TaskID id);
 
-	//  Fixup the subtask pointer
-	void fixup(void);
+	HuntTask(Common::InSaveFile *in, TaskID id);
 
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
@@ -769,6 +809,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -813,6 +855,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntLocationTask(void **buf, TaskID id);
 
+	HuntLocationTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -820,6 +864,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 protected:
 	bool targetHasChanged(GotoTask *gotoTarget);
 	GotoTask *setupGoto(void);
@@ -858,6 +904,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntToBeNearLocationTask(void **buf, TaskID id);
 
+	HuntToBeNearLocationTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -865,6 +913,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -904,6 +954,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntObjectTask(void **buf, TaskID id);
 
+	HuntObjectTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -911,6 +963,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 protected:
 	bool targetHasChanged(GotoTask *gotoTarget);
 	GotoTask *setupGoto(void);
@@ -951,6 +1005,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntToBeNearObjectTask(void **buf, TaskID id);
 
+	HuntToBeNearObjectTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -958,6 +1014,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -1007,6 +1065,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntToPossessTask(void **buf, TaskID id);
 
+	HuntToPossessTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -1014,6 +1074,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -1056,6 +1118,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntActorTask(void **buf, TaskID id);
 
+	HuntActorTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -1063,6 +1127,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 protected:
 	bool targetHasChanged(GotoTask *gotoTarget);
 	GotoTask *setupGoto(void);
@@ -1115,8 +1181,7 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntToBeNearActorTask(void **buf, TaskID id);
 
-	//  Fixup the subtask pointer
-	void fixup(void);
+	HuntToBeNearActorTask(Common::InSaveFile *in, TaskID id);
 
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
@@ -1125,6 +1190,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -1186,6 +1253,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntToKillTask(void **buf, TaskID id);
 
+	HuntToKillTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -1193,6 +1262,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -1244,6 +1315,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	HuntToGiveTask(void **buf, TaskID id);
 
+	HuntToGiveTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -1251,6 +1324,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -1367,8 +1442,7 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	BandTask(void **buf, TaskID id);
 
-	//  Fixup the subtask pointer
-	void fixup(void);
+	BandTask(Common::InSaveFile *in, TaskID id);
 
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
@@ -1377,6 +1451,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -1452,6 +1528,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	BandAndAvoidEnemiesTask(void **buf, TaskID id) : BandTask(buf, id) {}
 
+	BandAndAvoidEnemiesTask(Common::InSaveFile *in, TaskID id) : BandTask(in, id) {}
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 
@@ -1496,8 +1574,7 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	FollowPatrolRouteTask(void **buf, TaskID id);
 
-	//  Fixup the subtask pointer
-	void fixup(void);
+	FollowPatrolRouteTask(Common::InSaveFile *in, TaskID id);
 
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
@@ -1506,6 +1583,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 #if DEBUG
 	//  Debugging function used to mark this task and any sub tasks as
 	//  being used.  This is used to find task leaks.
@@ -1554,6 +1633,8 @@ public:
 	//  Constructor -- reconstruct from archive buffer
 	AttendTask(void **buf, TaskID id);
 
+	AttendTask(Common::InSaveFile *in, TaskID id);
+
 	//  Return the number of bytes needed to archive this object in
 	//  a buffer
 	int32 archiveSize(void) const;
@@ -1561,6 +1642,8 @@ public:
 	//  Create an archive of this object in a buffer
 	void *archive(void *buf) const;
 
+	void write(Common::OutSaveFile *out) const;
+
 	//  Return an integer representing the type of this task
 	int16 getType(void) const;
 


Commit: 9238ed99032ed5de4de498cbca353b3c93e584c5
    https://github.com/scummvm/scummvm/commit/9238ed99032ed5de4de498cbca353b3c93e584c5
Author: a/ (yuri.kgpps at gmail.com)
Date: 2021-07-11T03:23:26+09:00

Commit Message:
SAGA2: Add error check on TaskStacks loading

Changed paths:
    engines/saga2/task.cpp


diff --git a/engines/saga2/task.cpp b/engines/saga2/task.cpp
index c202220083..b6580c4d56 100644
--- a/engines/saga2/task.cpp
+++ b/engines/saga2/task.cpp
@@ -135,6 +135,8 @@ public:
 	//  list.
 	void newTaskStack(TaskStack *p);
 
+	void newTaskStack(TaskStack *p, TaskID id);
+
 	//  Place a TaskStack back into the inactive list.
 	void deleteTaskStack(TaskStack *p);
 
@@ -229,7 +231,7 @@ void TaskStackList::read(Common::InSaveFile *in) {
 		debugC(3, kDebugSaveload, "Loading Task Stack %d", id);
 
 		ts = new TaskStack;
-		_list[id] = ts;
+		newTaskStack(ts, id);
 
 		ts->read(in);
 
@@ -326,6 +328,12 @@ void TaskStackList::newTaskStack(TaskStack *p) {
 		}
 }
 
+void TaskStackList::newTaskStack(TaskStack *p, TaskID id) {
+	if (_list[id])
+		error("Task already exists");
+	_list[id] = p;
+}
+
 //----------------------------------------------------------------------
 //	Remove the specified TaskStack from the active list and place it
 //	back into the inactive list
@@ -498,7 +506,7 @@ void loadTaskStacks(SaveFileReader &saveGame) {
 }
 
 void loadTaskStacks(Common::InSaveFile *in, int32 chunkSize) {
-	debugC(2, kDebugSaveload, "Saving Task Stacks");
+	debugC(2, kDebugSaveload, "Loading Task Stacks");
 
 	//  If there is no saved data, simply call the default constructor
 	if (chunkSize == 0) {




More information about the Scummvm-git-logs mailing list