[Scummvm-git-logs] scummvm master -> 8d088114c026ae9b6f7c5f6cc4ac9690efbfbb51

mduggan noreply at scummvm.org
Sat Nov 2 21:36:35 UTC 2024


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

Summary:
5b162cede1 DGDS: Flop back to previous ADS orderring
53c1621408 DGDS: Finally really actually fix ADS exeuction order
8d088114c0 DGDS: Implement stubs for HoC minigames


Commit: 5b162cede16644b8f4984856272fbce31364e652
    https://github.com/scummvm/scummvm/commit/5b162cede16644b8f4984856272fbce31364e652
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-11-03T08:36:25+11:00

Commit Message:
DGDS: Flop back to previous ADS orderring

This is a partial revert of 4bb1410079d8fbe88b45fe6bca5f801365187917 and
36fe1cdff420399b5fd4abb559d12a45b4ea2987.  I can't seem to make up my mind
here, but after looking at Ghidra for a really long time I'm now 99% sure that
0x4000 is move to back and 0x4010 is move to front.  You can tell because the
0x4000 function in the original finishes with setting the next pointer of the
found element to 0.

I confirmed this in both the RotD and HoC Ghidra outputs.

This re-breaks the tap in the apartment in RotD, I will need to fix that again.

On the up-side, it fixes the scroll left/right in the bar at the start of HoC.

Changed paths:
    engines/dgds/ads.cpp


diff --git a/engines/dgds/ads.cpp b/engines/dgds/ads.cpp
index 853540adbae..08b385300a1 100644
--- a/engines/dgds/ads.cpp
+++ b/engines/dgds/ads.cpp
@@ -636,35 +636,53 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 		debug(10, "ADS 0x30FF: random end");
 		error("Unexpected RANDOM END mid-stream (no RANDOM START?).");
 
-	case 0x4000: { // MOVE SEQ TO FRONT
+	case 0x4000: { // MOVE SEQ TO BACK
 		enviro = scr->readUint16LE();
 		seqnum = scr->readUint16LE();
-		debug(10, "ADS 0x%04x: mov seq to front env %d seq %d", code, enviro, seqnum);
+		debug(10, "ADS 0x%04x: mov seq to back env %d seq %d", code, enviro, seqnum);
 		/*uint16 unk = */scr->readUint16LE();
-		if (seqnum < _adsData->_ttmSeqs.size()) {
-			// This is O(N) but the N is small and it's not called often.
-			TTMSeq seq = _adsData->_ttmSeqs.remove_at(seqnum);
-			_adsData->_ttmSeqs.insert_at(0, seq);
-		} else {
-			warning("ADS: 0x4000 Request to move env %d seq %d which doesn't exist", enviro, seqnum);
+		// This is O(N) but the N is small and it's not called often.
+		TTMSeq seq;
+		bool success = false;
+		for (uint i = 0; i < _adsData->_ttmSeqs.size(); i++) {
+			if (_adsData->_ttmSeqs[i]._enviro == enviro && _adsData->_ttmSeqs[i]._seqNum == seqnum) {
+				seq = _adsData->_ttmSeqs[i];
+				_adsData->_ttmSeqs.remove_at(i);
+				success = true;
+				break;
+			}
 		}
 
+		if (success)
+			_adsData->_ttmSeqs.push_back(seq);
+		else
+			warning("ADS: 0x4000 Request to move env %d seq %d which doesn't exist", enviro, seqnum);
+
 		break;
 	}
 
-	case 0x4010: { // MOVE SEQ TO BACK
+	case 0x4010: { // MOVE SEQ TO FRONT
 		enviro = scr->readUint16LE();
 		seqnum = scr->readUint16LE();
-		debug(10, "ADS 0x%04x: mov seq to back env %d seq %d", code, enviro, seqnum);
+		debug(10, "ADS 0x%04x: mov seq to front env %d seq %d", code, enviro, seqnum);
 		/*uint16 unk = */scr->readUint16LE();
-		if (seqnum < _adsData->_ttmSeqs.size()) {
-			// This is O(N) but the N is small and it's not called often.
-			TTMSeq seq = _adsData->_ttmSeqs.remove_at(seqnum);
-			_adsData->_ttmSeqs.push_back(seq);
-		} else {
-			warning("ADS: 0x4010 Request to move env %d seq %d which doesn't exist", enviro, seqnum);
+		// This is O(N) but the N is small and it's not called often.
+		TTMSeq seq;
+		bool success = false;
+		for (uint i = 0; i < _adsData->_ttmSeqs.size(); i++) {
+			if (_adsData->_ttmSeqs[i]._enviro == enviro && _adsData->_ttmSeqs[i]._seqNum == seqnum) {
+				seq = _adsData->_ttmSeqs[i];
+				_adsData->_ttmSeqs.remove_at(i);
+				success = true;
+				break;
+			}
 		}
 
+		if (success)
+			_adsData->_ttmSeqs.insert_at(0, seq);
+		else
+			warning("ADS: 0x4010 Request to move env %d seq %d which doesn't exist", enviro, seqnum);
+
 		break;
 	}
 


Commit: 53c16214080a6bf105704431a029d7660272f1ad
    https://github.com/scummvm/scummvm/commit/53c16214080a6bf105704431a029d7660272f1ad
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-11-03T08:36:25+11:00

Commit Message:
DGDS: Finally really actually fix ADS exeuction order

The underlying issue was that we tracked used sequences for each ADS segment
using sequence pointers, but the 0x4000 and 0x4010 ADS opcodes re-arranged the
array of sequences.  Because arrays don't get re-allocated much this by chance
left the usage pointers valid but now pointing to the wrong sequence, so the
correct sequences were not started and stopped after a re-order operation.

Replaced the array of sequence objects and the used sequence tracker with
shared pointers so we can reorder the sequences without breaking the usage
pointers.

The tap and coat rendering in RotD now both work right and so does the
bar scroll in HoC.

Changed paths:
    engines/dgds/ads.cpp
    engines/dgds/ads.h
    engines/dgds/console.cpp
    engines/dgds/dgds.cpp
    engines/dgds/ttm.cpp
    engines/dgds/ttm.h


diff --git a/engines/dgds/ads.cpp b/engines/dgds/ads.cpp
index 08b385300a1..576f66f51b6 100644
--- a/engines/dgds/ads.cpp
+++ b/engines/dgds/ads.cpp
@@ -47,7 +47,7 @@ Common::Error ADSData::syncState(Common::Serializer &s) {
 		error("Unexpected number of ttm seqeunces (%d in save vs %d in ADS)", nseqs, _ttmSeqs.size());
 
 	for (auto &seq : _ttmSeqs)
-		seq.syncState(s);
+		seq->syncState(s);
 
 	return Common::kNoError;
 }
@@ -125,7 +125,7 @@ bool ADSInterpreter::load(const Common::String &filename) {
 	for (uint i = 0; i < ARRAYSIZE(_adsData->_state); i++)
 		_adsData->_state[i] = 8;
 	for (auto &seq : _adsData->_ttmSeqs)
-		seq.reset();
+		seq->reset();
 
 	return true;
 }
@@ -135,58 +135,60 @@ static const uint16 ADS_SEQ_OPCODES[] = {
 	0x1340, 0x1360, 0x1370, 0x1320, 0x1310, 0x1350
 };
 
-bool ADSInterpreter::updateSeqTimeAndFrame(const TTMEnviro *env, TTMSeq &seq) {
-	if (seq._timeInterval != 0) {
+bool ADSInterpreter::updateSeqTimeAndFrame(const TTMEnviro *env, Common::SharedPtr<TTMSeq> seq) {
+	if (seq->_timeInterval != 0) {
 		uint32 now = g_engine->getTotalPlayTime();
-		if (now < seq._timeNext) {
-			debug(10, "env %d seq %d (%s) not advancing from frame %d (now %d timeNext %d interval %d)", seq._enviro,
-					seq._seqNum, env->_tags.getValOrDefault(seq._seqNum).c_str(), seq._currentFrame, now, seq._timeNext, seq._timeInterval);
+		if (now < seq->_timeNext) {
+			debug(10, "env %d seq %d (%s) not advancing from frame %d (now %d timeNext %d interval %d)", seq->_enviro,
+					seq->_seqNum, env->_tags.getValOrDefault(seq->_seqNum).c_str(), seq->_currentFrame, now, seq->_timeNext, seq->_timeInterval);
 			return false;
 		}
-		seq._timeNext = now + seq._timeInterval;
+		seq->_timeNext = now + seq->_timeInterval;
 	}
 
-	seq._executed = false;
-	if (seq._gotoFrame == -1) {
-		debug(10, "env %d seq %d (%s) advance to frame %d->%d (start %d last %d)", seq._enviro, seq._seqNum,
-				env->_tags.getValOrDefault(seq._seqNum).c_str(), seq._currentFrame, seq._currentFrame + 1, seq._startFrame, seq._lastFrame);
-		seq._currentFrame++;
+	seq->_executed = false;
+	if (seq->_gotoFrame == -1) {
+		debug(10, "env %d seq %d (%s) advance to frame %d->%d (start %d last %d)", seq->_enviro, seq->_seqNum,
+				env->_tags.getValOrDefault(seq->_seqNum).c_str(), seq->_currentFrame, seq->_currentFrame + 1, seq->_startFrame, seq->_lastFrame);
+		seq->_currentFrame++;
 	} else {
-		debug(10, "env %d seq %d (%s) goto to frame %d->%d (start %d last %d)", seq._enviro, seq._seqNum,
-				env->_tags.getValOrDefault(seq._seqNum).c_str(), seq._currentFrame, seq._gotoFrame, seq._startFrame, seq._lastFrame);
-		seq._currentFrame = seq._gotoFrame;
-		seq._gotoFrame = -1;
+		debug(10, "env %d seq %d (%s) goto to frame %d->%d (start %d last %d)", seq->_enviro, seq->_seqNum,
+				env->_tags.getValOrDefault(seq->_seqNum).c_str(), seq->_currentFrame, seq->_gotoFrame, seq->_startFrame, seq->_lastFrame);
+		seq->_currentFrame = seq->_gotoFrame;
+		seq->_gotoFrame = -1;
 	}
 
 	return true;
 }
 
-void ADSInterpreter::findUsedSequencesForSegment(int segno) {
-	_adsData->_usedSeqs[segno].clear();
+void ADSInterpreter::findUsedSequencesForSegment(int idx) {
+	_adsData->_usedSeqs[idx].clear();
 	int64 startoff = _adsData->scr->pos();
 	uint16 opcode = 0;
 	// Skip the segment number.
-	_adsData->scr->readUint16LE();
+	int16 segno = _adsData->scr->readUint16LE();
 	while (opcode != 0xffff && _adsData->scr->pos() < _adsData->scr->size()) {
 		opcode = _adsData->scr->readUint16LE();
 		for (uint16 o : ADS_SEQ_OPCODES) {
 			if (opcode == o) {
 				int16 envno = _adsData->scr->readSint16LE();
 				int16 seqno = _adsData->scr->readSint16LE();
-				TTMSeq *seq = findTTMSeq(envno, seqno);
+				Common::SharedPtr<TTMSeq> seq = findTTMSeq(envno, seqno);
 				if (!seq) {
 					warning("ADS opcode %04x at offset %d references unknown seq %d %d",
 							opcode, (int)_adsData->scr->pos(), envno, seqno);
 				} else {
 					bool already_added = false;
-					for (const TTMSeq *s : _adsData->_usedSeqs[segno]) {
+					for (const Common::SharedPtr<TTMSeq> &s : _adsData->_usedSeqs[idx]) {
 						if (s == seq) {
 							already_added = true;
 							break;
 						}
 					}
-					if (!already_added)
-						_adsData->_usedSeqs[segno].push_back(seq);
+					if (!already_added) {
+						debug("ADS seg no %d (idx %d) uses seq %d %d", segno, idx, envno, seqno);
+						_adsData->_usedSeqs[idx].push_back(seq);
+					}
 				}
 				// Rewind as we will go forward again outside this loop.
 				_adsData->scr->seek(-4, SEEK_CUR);
@@ -289,10 +291,10 @@ TTMEnviro *ADSInterpreter::findTTMEnviro(int16 enviro) {
 	return nullptr;
 }
 
-TTMSeq *ADSInterpreter::findTTMSeq(int16 enviro, int16 seqno) {
+Common::SharedPtr<TTMSeq> ADSInterpreter::findTTMSeq(int16 enviro, int16 seqno) {
 	for (auto &seq : _adsData->_ttmSeqs) {
-		if (seq._enviro == enviro && seq._seqNum == seqno)
-			return &seq;
+		if (seq->_enviro == enviro && seq->_seqNum == seqno)
+			return seq;
 	}
 	return nullptr;
 }
@@ -396,7 +398,7 @@ bool ADSInterpreter::handleLogicOp(uint16 code, Common::SeekableReadStream *scr)
 	while (scr->pos() < scr->size()) {
 		uint16 enviro;
 		uint16 seqnum;
-		TTMSeq *seq = nullptr;
+		Common::SharedPtr<TTMSeq> seq;
 		TTMEnviro *env = nullptr;
 
 		if (code != 0x1380 && code != 0x1390) {
@@ -413,7 +415,7 @@ bool ADSInterpreter::handleLogicOp(uint16 code, Common::SeekableReadStream *scr)
 			enviro = scr->readUint16LE();
 		}
 
-		bool logicResult = logicOpResult(code, env, seq, enviro);
+		bool logicResult = logicOpResult(code, env, seq.get(), enviro);
 
 		if (andor == 0x1420) // AND
 			testval &= logicResult;
@@ -560,7 +562,7 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 		int16 runCount = scr->readSint16LE();
 		uint16 unk = scr->readUint16LE(); // proportion
 
-		TTMSeq *seq = findTTMSeq(enviro, seqnum);
+		Common::SharedPtr<TTMSeq> seq = findTTMSeq(enviro, seqnum);
 		TTMEnviro *env = findTTMEnviro(enviro);
 		if (!seq || !env)
 			error("ADS invalid seq requested %d %d", enviro, seqnum);
@@ -597,7 +599,7 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 			_currentTTMSeq->_runFlag = kRunTypeStopped;
 		break;
 	}
-	case 0x2015: { // SET RUNFLAG 5, 3 params (ttmenv, ttmseq, proportion) (pause)
+	case 0x2015: { // PAUSE SEQ, 3 params (ttmenv, ttmseq, proportion)
 		enviro = scr->readUint16LE();
 		seqnum = scr->readUint16LE();
 		uint16 unk = scr->readUint16LE();
@@ -642,18 +644,16 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 		debug(10, "ADS 0x%04x: mov seq to back env %d seq %d", code, enviro, seqnum);
 		/*uint16 unk = */scr->readUint16LE();
 		// This is O(N) but the N is small and it's not called often.
-		TTMSeq seq;
-		bool success = false;
+		Common::SharedPtr<TTMSeq> seq;
 		for (uint i = 0; i < _adsData->_ttmSeqs.size(); i++) {
-			if (_adsData->_ttmSeqs[i]._enviro == enviro && _adsData->_ttmSeqs[i]._seqNum == seqnum) {
+			if (_adsData->_ttmSeqs[i]->_enviro == enviro && _adsData->_ttmSeqs[i]->_seqNum == seqnum) {
 				seq = _adsData->_ttmSeqs[i];
 				_adsData->_ttmSeqs.remove_at(i);
-				success = true;
 				break;
 			}
 		}
 
-		if (success)
+		if (seq)
 			_adsData->_ttmSeqs.push_back(seq);
 		else
 			warning("ADS: 0x4000 Request to move env %d seq %d which doesn't exist", enviro, seqnum);
@@ -667,18 +667,16 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 		debug(10, "ADS 0x%04x: mov seq to front env %d seq %d", code, enviro, seqnum);
 		/*uint16 unk = */scr->readUint16LE();
 		// This is O(N) but the N is small and it's not called often.
-		TTMSeq seq;
-		bool success = false;
+		Common::SharedPtr<TTMSeq> seq;
 		for (uint i = 0; i < _adsData->_ttmSeqs.size(); i++) {
-			if (_adsData->_ttmSeqs[i]._enviro == enviro && _adsData->_ttmSeqs[i]._seqNum == seqnum) {
+			if (_adsData->_ttmSeqs[i]->_enviro == enviro && _adsData->_ttmSeqs[i]->_seqNum == seqnum) {
 				seq = _adsData->_ttmSeqs[i];
 				_adsData->_ttmSeqs.remove_at(i);
-				success = true;
 				break;
 			}
 		}
 
-		if (success)
+		if (seq)
 			_adsData->_ttmSeqs.insert_at(0, seq);
 		else
 			warning("ADS: 0x4010 Request to move env %d seq %d which doesn't exist", enviro, seqnum);
@@ -692,7 +690,7 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 			_adsData->_state[_adsData->_runningSegmentIdx] = 2;
 		return false;
 
-	case 0xF010: {// FADE_OUT, 1 param
+	case 0xF010: { // FADE_OUT, 1 param
 		int16 segment = scr->readSint16LE();
 		int16 idx = _adsData->_runningSegmentIdx;
 		if (segment >= 0)
@@ -729,7 +727,7 @@ bool ADSInterpreter::handleOperation(uint16 code, Common::SeekableReadStream *sc
 	}
 
 	case 0xffff:	// END
-		debug(10, "ADS 0xFFF: end");
+		debug(10, "ADS 0xFFFF: end");
 		return false;
 
 	//// unknown / to-be-implemented
@@ -754,7 +752,7 @@ int16 ADSInterpreter::getStateForSceneOp(uint16 segnum) {
 	if (idx < 0)
 		return 0;
 	if (!(_adsData->_state[idx] & 4)) {
-		for (auto *seq : _adsData->_usedSeqs[idx]) {
+		for (const Common::SharedPtr<TTMSeq> seq: _adsData->_usedSeqs[idx]) {
 			if (!seq)
 				return 0;
 			if (seq->_runFlag != kRunTypeStopped && !seq->_selfLoop)
@@ -786,9 +784,9 @@ bool ADSInterpreter::run() {
 	if (!_adsData || _adsData->_ttmSeqs.empty())
 		return false;
 
-	for (int i = 0; i < _adsData->_maxSegments; i++) {
-		int16 flag = _adsData->_state[i] & 0xfff7;
-		for (auto seq : _adsData->_usedSeqs[i]) {
+	for (int idx = 0; idx < _adsData->_maxSegments; idx++) {
+		int16 flag = _adsData->_state[idx] & 0xfff7;
+		for (auto seq : _adsData->_usedSeqs[idx]) {
 			if (flag == 3) {
 				seq->reset();
 			} else {
@@ -798,50 +796,50 @@ bool ADSInterpreter::run() {
 	}
 
 	assert(_adsData->scr || !_adsData->_maxSegments);
-	for (int i = 0; i < _adsData->_maxSegments; i++) {
-		int16 state = _adsData->_state[i];
-		int32 offset = _adsData->_segments[i];
+	for (int idx = 0; idx < _adsData->_maxSegments; idx++) {
+		int16 state = _adsData->_state[idx];
+		int32 offset = _adsData->_segments[idx];
 		_adsData->scr->seek(offset);
 		// skip over the segment num
 		offset += 2;
-		/*int16 segnum =*/ _adsData->scr->readSint16LE();
+		int16 segnum = _adsData->scr->readSint16LE();
 		if (state & 8) {
 			state &= 0xfff7;
-			_adsData->_state[i] = state;
+			_adsData->_state[idx] = state;
 		} else {
 			findEndOrInitOp();
 			offset = _adsData->scr->pos();
 		}
 
-		if (_adsData->_charWhile[i])
-			offset = _adsData->_charWhile[i];
+		if (_adsData->_charWhile[idx])
+			offset = _adsData->_charWhile[idx];
 
 		if (state == 3 || state == 4) {
-			_adsData->_state[i] = 1;
+			_adsData->_state[idx] = 1;
 			state = 1;
 		}
 
-		_adsData->_runningSegmentIdx = i;
+		_adsData->_runningSegmentIdx = idx;
 		if (state == 1) {
 			_adsData->scr->seek(offset);
-			//debug("ADS: Run segment %d idx %d/%d", segnum, i, _adsData->_maxSegments);
+			debug(10, "ADS: Run segment %d idx %d/%d", segnum, idx, _adsData->_maxSegments);
 			runUntilBranchOpOrEnd();
 		}
 	}
 
 	bool result = false;
-	for (auto &seq : _adsData->_ttmSeqs) {
-		_currentTTMSeq = &seq;
-		seq._lastFrame = -1;
-		int sflag = seq._scriptFlag;
-		TTMRunType rflag = seq._runFlag;
+	for (Common::SharedPtr<TTMSeq> seq : _adsData->_ttmSeqs) {
+		_currentTTMSeq = seq;
+		seq->_lastFrame = -1;
+		int sflag = seq->_scriptFlag;
+		TTMRunType rflag = seq->_runFlag;
 		if (sflag == 6 || (rflag != kRunType1 && rflag != kRunTypeTimeLimited && rflag != kRunTypeMulti && rflag != kRunTypePaused)) {
 			if (sflag != 6 && sflag != 5 && rflag == kRunTypeFinished) {
-				seq._runFlag = kRunTypeStopped;
+				seq->_runFlag = kRunTypeStopped;
 			}
 		} else {
-			int16 curframe = seq._currentFrame;
-			TTMEnviro *env = findTTMEnviro(seq._enviro);
+			int16 curframe = seq->_currentFrame;
+			TTMEnviro *env = findTTMEnviro(seq->_enviro);
 			_adsData->_hitTTMOp0110 = false;
 			_adsData->_scriptDelay = -1;
 			bool scriptresult = false;
@@ -852,48 +850,48 @@ bool ADSInterpreter::run() {
 			}
 
 			if (scriptresult && sflag != 5) {
-				seq._executed = true;
-				seq._lastFrame = seq._currentFrame;
+				seq->_executed = true;
+				seq->_lastFrame = seq->_currentFrame;
 				result = true;
-				if (_adsData->_scriptDelay != -1 && seq._timeInterval != _adsData->_scriptDelay) {
+				if (_adsData->_scriptDelay != -1 && seq->_timeInterval != _adsData->_scriptDelay) {
 					uint32 now = g_engine->getTotalPlayTime();
-					seq._timeNext = now + _adsData->_scriptDelay;
-					seq._timeInterval = _adsData->_scriptDelay;
+					seq->_timeNext = now + _adsData->_scriptDelay;
+					seq->_timeInterval = _adsData->_scriptDelay;
 				}
 
 				if (!_adsData->_hitTTMOp0110) {
 					if (_adsData->_gotoTarget != -1) {
-						seq._gotoFrame = _adsData->_gotoTarget;
-						if (seq._currentFrame == _adsData->_gotoTarget)
-							seq._selfLoop = true;
+						seq->_gotoFrame = _adsData->_gotoTarget;
+						if (seq->_currentFrame == _adsData->_gotoTarget)
+							seq->_selfLoop = true;
 					}
-					if (seq._runFlag != kRunTypePaused)
+					if (seq->_runFlag != kRunTypePaused)
 						updateSeqTimeAndFrame(env, seq);
 				} else {
-					seq._gotoFrame = seq._startFrame;
-					if (seq._runFlag == kRunTypeMulti && seq._runCount != 0) {
+					seq->_gotoFrame = seq->_startFrame;
+					if (seq->_runFlag == kRunTypeMulti && seq->_runCount != 0) {
 						bool updated = updateSeqTimeAndFrame(env, seq);
 						if (updated) {
-							seq._runCount--;
+							seq->_runCount--;
 						}
-					} else if (seq._runFlag == kRunTypeTimeLimited && seq._timeCut != 0) {
+					} else if (seq->_runFlag == kRunTypeTimeLimited && seq->_timeCut != 0) {
 						updateSeqTimeAndFrame(env, seq);
 					} else {
 						bool updated = updateSeqTimeAndFrame(env, seq);
 						if (updated) {
-							seq._runFlag = kRunTypeFinished;
-							seq._timeInterval = 0;
+							seq->_runFlag = kRunTypeFinished;
+							seq->_timeInterval = 0;
 						}
 					}
 				}
 			} else if (sflag != 5) {
-				seq._gotoFrame = seq._startFrame;
-				seq._runFlag = kRunTypeFinished;
+				seq->_gotoFrame = seq->_startFrame;
+				seq->_runFlag = kRunTypeFinished;
 			}
 		}
 
-		if (rflag == kRunTypeTimeLimited && seq._timeCut <= g_engine->getTotalPlayTime()) {
-			seq._runFlag = kRunTypeFinished;
+		if (rflag == kRunTypeTimeLimited && seq->_timeCut <= g_engine->getTotalPlayTime()) {
+			seq->_runFlag = kRunTypeFinished;
 		}
 	}
 	return result;
diff --git a/engines/dgds/ads.h b/engines/dgds/ads.h
index b39ada32290..9115c46f213 100644
--- a/engines/dgds/ads.h
+++ b/engines/dgds/ads.h
@@ -42,7 +42,7 @@ public:
 	}
 	Common::Array<Common::String> _scriptNames;
 	Common::Array<TTMEnviro> _scriptEnvs;
-	Common::Array<TTMSeq> _ttmSeqs;
+	Common::Array<Common::SharedPtr<TTMSeq>> _ttmSeqs;	// Pointers as we need to shuffle them but keep _usedSeqs below valid
 	int _maxSegments;
 	// TODO: replace these with dynamic arrays - fixed arrays inherited from original.
 	int _state[80];
@@ -50,7 +50,7 @@ public:
 	// note: originals uses char * but we use offsets into script for less pointers. -1 is nullptr
 	int32 _segments[80];
 	int32 _charWhile[80];
-	Common::Array<TTMSeq *> _usedSeqs[80];
+	Common::Array<Common::SharedPtr<TTMSeq>> _usedSeqs[80];
 	int32 _scriptDelay;
 	int32 _gotoTarget;
 	bool _hitTTMOp0110;
@@ -91,12 +91,12 @@ protected:
 	bool skipToEndIf();
 	bool skipToEndWhile();
 	bool skipSceneLogicBranch();
-	TTMSeq *findTTMSeq(int16 enviro, int16 seq);
+	Common::SharedPtr<TTMSeq> findTTMSeq(int16 enviro, int16 seq);
 	TTMEnviro *findTTMEnviro(int16 enviro);
 	bool runUntilBranchOpOrEnd();
 	void findUsedSequencesForSegment(int segno);
 	void findEndOrInitOp();
-	bool updateSeqTimeAndFrame(const TTMEnviro *env, TTMSeq &seq);
+	bool updateSeqTimeAndFrame(const TTMEnviro *env, Common::SharedPtr<TTMSeq> seq);
 	int getArrIndexOfSegNum(uint16 segnum);
 
 	DgdsEngine *_vm;
@@ -105,7 +105,7 @@ protected:
 	Common::HashMap<Common::String, ADSData> _adsTexts;
 	ADSData *_adsData;
 
-	TTMSeq *_currentTTMSeq;
+	Common::SharedPtr<TTMSeq> _currentTTMSeq;
 };
 
 } // end namespace Dgds
diff --git a/engines/dgds/console.cpp b/engines/dgds/console.cpp
index 8930505104b..709aa7bcc17 100644
--- a/engines/dgds/console.cpp
+++ b/engines/dgds/console.cpp
@@ -358,9 +358,6 @@ bool Console::cmdScriptDump(int argc, const char **argv) {
 			if (adsData._tags.contains(tag))
 				debugPrintf("\n%d: %s\n", segno, adsData._tags[tag].c_str());
 			continue;
-		case 0x0003:
-			printOp(indent, "unknown");
-			break;
 		case 0x0005:
 			printOp(indent, "init");
 			break;
@@ -392,10 +389,10 @@ bool Console::cmdScriptDump(int argc, const char **argv) {
 			printOp(indent++, "WHILE ??");
 			break;
 		case 0x1310:
-			printOp(indent++, "IF runtype 5");
+			printOp(indent++, "IF PAUSED");
 			break;
 		case 0x1320:
-			printOp(indent++, "IF not runtype 5");
+			printOp(indent++, "IF NOT_PAUSED");
 			break;
 		case 0x1330:
 			printOp(indent++, "IF NOT_PLAYED");
@@ -437,7 +434,7 @@ bool Console::cmdScriptDump(int argc, const char **argv) {
 			printOp(indent, "STOP SCENE");
 			break;
 		case 0x2015:
-			printOp(indent, "SET RUNFLAG 5");
+			printOp(indent, "PAUSE SEQ");
 			break;
 		case 0x2020:
 			printOp(indent, "RESET SEQ");
diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index bc8d09dd8bd..7aab35a7961 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -845,6 +845,7 @@ Common::Error DgdsEngine::syncGame(Common::Serializer &s) {
 		_storedAreaBuffer.fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
 	}
 
+	debug("%s", _scene->dump("").c_str());
 	_scene->runEnterSceneOps();
 
 	return Common::kNoError;
diff --git a/engines/dgds/ttm.cpp b/engines/dgds/ttm.cpp
index 80e7831e1a4..3bcdebc9752 100644
--- a/engines/dgds/ttm.cpp
+++ b/engines/dgds/ttm.cpp
@@ -372,7 +372,7 @@ static void _doScroll(Graphics::ManagedSurface &compBuf, int16 dir, int16 steps,
 	g_system->unlockScreen();
 }
 
-void TTMInterpreter::doWipeOp(uint16 code, TTMEnviro &env, TTMSeq &seq, const Common::Rect &r) {
+void TTMInterpreter::doWipeOp(uint16 code, const TTMEnviro &env, const TTMSeq &seq, const Common::Rect &r) {
 	//
 	// In the original games, these operations copy certain parts of the buffer on to
 	// the screen, and rely on the system's speed to make it happen faster than a regular
@@ -517,7 +517,7 @@ int16 TTMInterpreter::doOpInitCreditScroll(const Image *img) {
 	return scrollFinished;
 }
 
-void TTMInterpreter::doDrawDialogForStrings(TTMEnviro &env, TTMSeq &seq, int16 x, int16 y, int16 width, int16 height) {
+void TTMInterpreter::doDrawDialogForStrings(const TTMEnviro &env, const TTMSeq &seq, int16 x, int16 y, int16 width, int16 height) {
 	int16 fontno = seq._currentFontId;
 	if (fontno >= (int16)env._fonts.size()) {
 		warning("Trying to draw font no %d but only loaded %d", fontno, env._fonts.size());
@@ -1206,7 +1206,7 @@ bool TTMInterpreter::run(TTMEnviro &env, TTMSeq &seq) {
 	return true;
 }
 
-int32 TTMInterpreter::findGOTOTarget(TTMEnviro &env, TTMSeq &seq, int16 targetFrame) {
+int32 TTMInterpreter::findGOTOTarget(const TTMEnviro &env, const TTMSeq &seq, int16 targetFrame) {
 	int64 startpos = env.scr->pos();
 	int32 retval = -1;
 	for (int32 i = 0; i < (int)env._frameOffsets.size(); i++) {
@@ -1226,7 +1226,7 @@ int32 TTMInterpreter::findGOTOTarget(TTMEnviro &env, TTMSeq &seq, int16 targetFr
 	return retval;
 }
 
-void TTMInterpreter::findAndAddSequences(TTMEnviro &env, Common::Array<TTMSeq> &seqArray) {
+void TTMInterpreter::findAndAddSequences(TTMEnviro &env, Common::Array<Common::SharedPtr<TTMSeq>> &seqArray) {
 	int16 envno = env._enviro;
 	env.scr->seek(0);
 	uint16 op = 0;
@@ -1241,12 +1241,12 @@ void TTMInterpreter::findAndAddSequences(TTMEnviro &env, Common::Array<TTMSeq> &
 				break;
 			case 1:
 				if (op == 0x1111) {
-					TTMSeq newseq;
-					newseq._enviro = envno;
-					newseq._seqNum = env.scr->readUint16LE();
-					newseq._startFrame = frame;
-					newseq._currentFrame = frame;
-					newseq._lastFrame = -1;
+					Common::SharedPtr<TTMSeq> newseq(new TTMSeq());
+					newseq->_enviro = envno;
+					newseq->_seqNum = env.scr->readUint16LE();
+					newseq->_startFrame = frame;
+					newseq->_currentFrame = frame;
+					newseq->_lastFrame = -1;
 					//debug("findAndAddSequences: found env %d seq %d at %d", newseq._enviro, newseq._seqNum, (int)env.scr->pos());
 					seqArray.push_back(newseq);
 				} else {
diff --git a/engines/dgds/ttm.h b/engines/dgds/ttm.h
index d58d99b9214..ab950dc39ad 100644
--- a/engines/dgds/ttm.h
+++ b/engines/dgds/ttm.h
@@ -121,17 +121,17 @@ public:
 	bool load(const Common::String &filename, TTMEnviro &env);
 	void unload();
 	bool run(TTMEnviro &env, TTMSeq &seq);
-	void findAndAddSequences(TTMEnviro &scriptData, Common::Array<TTMSeq> &seqArray);
+	void findAndAddSequences(TTMEnviro &scriptData, Common::Array<Common::SharedPtr<TTMSeq>> &seqArray);
 
 	static Common::String readTTMStringVal(Common::SeekableReadStream *scr);
 
 protected:
 	void handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byte count, const int16 *ivals, const Common::String &sval, const Common::Array<Common::Point> &pts);
-	int32 findGOTOTarget(TTMEnviro &env, TTMSeq &seq, int16 frame);
-	void doWipeOp(uint16 code, TTMEnviro &env, TTMSeq &seq, const Common::Rect &r);
+	int32 findGOTOTarget(const TTMEnviro &env, const TTMSeq &seq, int16 frame);
+	void doWipeOp(uint16 code, const TTMEnviro &env, const TTMSeq &seq, const Common::Rect &r);
 	int16 doOpInitCreditScroll(const Image *img);
 	bool doOpCreditsScroll(const Image *img, int16 ygap, int16 ymax, int16 xoff, int16 measuredWidth, const Common::Rect &clipRect);
-	void doDrawDialogForStrings(TTMEnviro &env, TTMSeq &seq, int16 x, int16 y, int16 width, int16 height);
+	void doDrawDialogForStrings(const TTMEnviro &env, const TTMSeq &seq, int16 x, int16 y, int16 width, int16 height);
 
 	DgdsEngine *_vm;
 	int _stackDepth;


Commit: 8d088114c026ae9b6f7c5f6cc4ac9690efbfbb51
    https://github.com/scummvm/scummvm/commit/8d088114c026ae9b6f7c5f6cc4ac9690efbfbb51
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-11-03T08:36:25+11:00

Commit Message:
DGDS: Implement stubs for HoC minigames

Changed paths:
  A engines/dgds/minigames/china_tank.cpp
  A engines/dgds/minigames/china_tank.h
  A engines/dgds/minigames/china_train.cpp
  A engines/dgds/minigames/china_train.h
    engines/dgds/dgds.cpp
    engines/dgds/dgds.h
    engines/dgds/hoc_intro.cpp
    engines/dgds/hoc_intro.h
    engines/dgds/module.mk
    engines/dgds/scene.cpp
    engines/dgds/scene.h


diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index 7aab35a7961..96fd2e03709 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -63,6 +63,8 @@
 #include "dgds/sound.h"
 #include "dgds/game_palettes.h"
 #include "dgds/minigames/dragon_arcade.h"
+#include "dgds/minigames/china_tank.h"
+#include "dgds/minigames/china_train.h"
 #include "dgds/hoc_intro.h"
 
 // for frame contents debugging
@@ -86,7 +88,7 @@ DgdsEngine::DgdsEngine(OSystem *syst, const ADGameDescription *gameDesc)
 	_detailLevel(kDgdsDetailHigh), _textSpeed(1), _justChangedScene1(false), _justChangedScene2(false),
 	_random("dgds"), _currentCursor(-1), _menuToTrigger(kMenuNone), _isLoading(true), _flipMode(false),
 	_rstFileName(nullptr), _difficulty(1), _menu(nullptr), _adsInterp(nullptr), _isDemo(false),
-	_dragonArcade(nullptr), _skipNextFrame(false), _gameId(GID_INVALID) {
+_dragonArcade(nullptr), _chinaTank(nullptr), _chinaTrain(nullptr), _skipNextFrame(false), _gameId(GID_INVALID) {
 
 	_platform = gameDesc->platform;
 
@@ -131,6 +133,8 @@ DgdsEngine::~DgdsEngine() {
 	delete _shellGame;
 	delete _hocIntro;
 	delete _dragonArcade;
+	delete _chinaTank;
+	delete _chinaTrain;
 
 	_icons.reset();
 	_corners.reset();
@@ -327,6 +331,8 @@ void DgdsEngine::init(bool restarting) {
 		delete _dragonArcade;
 		delete _shellGame;
 		delete _hocIntro;
+		delete _chinaTank;
+		delete _chinaTrain;
 	}
 
 	_gamePals = new GamePalettes(_resource, _decompressor);
@@ -342,6 +348,8 @@ void DgdsEngine::init(bool restarting) {
 	else if (_gameId == GID_HOC) {
 		_shellGame = new ShellGame();
 		_hocIntro = new HocIntro();
+		_chinaTank = new ChinaTank();
+		_chinaTrain = new ChinaTrain();
 	}
 
 	_backgroundBuffer.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
diff --git a/engines/dgds/dgds.h b/engines/dgds/dgds.h
index aec3b6e23b7..0b10322bc7f 100644
--- a/engines/dgds/dgds.h
+++ b/engines/dgds/dgds.h
@@ -61,6 +61,8 @@ class Globals;
 class ShellGame;
 class DragonArcade;
 class HocIntro;
+class ChinaTank;
+class ChinaTrain;
 
 const float MS_PER_FRAME = 16.6667f;
 
@@ -144,6 +146,8 @@ private:
 	// HoC only
 	ShellGame *_shellGame;
 	HocIntro *_hocIntro;
+	ChinaTank *_chinaTank;
+	ChinaTrain *_chinaTrain;
 
 	FontManager *_fontManager;
 	Common::SharedPtr<Image> _corners;
@@ -246,6 +250,8 @@ public:
 	bool isInvButtonVisible() const;
 	ShellGame *getShellGame() { return _shellGame; }
 	HocIntro *getHocIntro() { return _hocIntro; }
+	ChinaTrain *getChinaTrain() { return _chinaTrain; }
+	ChinaTank *getChinaTank() { return _chinaTank; }
 	DragonArcade *getDragonArcade() { return _dragonArcade; }
 	void setSkipNextFrame() { _skipNextFrame = true; }
 
diff --git a/engines/dgds/hoc_intro.cpp b/engines/dgds/hoc_intro.cpp
index 67fdc0adb13..f0e36cc637c 100644
--- a/engines/dgds/hoc_intro.cpp
+++ b/engines/dgds/hoc_intro.cpp
@@ -119,7 +119,7 @@ static int16 _clipXOffset(int16 x1, int16 x2) {
 	return x2;
 }
 
-void HocIntro::leave() {
+void HocIntro::end() {
 	DgdsEngine *engine = DgdsEngine::getInstance();
 	HocGlobals *globals = static_cast<HocGlobals *>(engine->getGameGlobals());
 	if (!globals->getIntroState())
diff --git a/engines/dgds/hoc_intro.h b/engines/dgds/hoc_intro.h
index 0f538f0d534..04e363d68ed 100644
--- a/engines/dgds/hoc_intro.h
+++ b/engines/dgds/hoc_intro.h
@@ -35,7 +35,7 @@ public:
 	HocIntro();
 	void init();
 	void tick();
-	void leave();
+	void end();
 
 private:
 	void clean1(int16 xoff);
diff --git a/engines/dgds/minigames/china_tank.cpp b/engines/dgds/minigames/china_tank.cpp
new file mode 100644
index 00000000000..a213fffb8ac
--- /dev/null
+++ b/engines/dgds/minigames/china_tank.cpp
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+
+#include "dgds/dgds.h"
+#include "dgds/minigames/china_tank.h"
+
+namespace Dgds {
+
+ChinaTank::ChinaTank() {
+}
+
+void ChinaTank::init() {
+}
+
+void ChinaTank::tick() {
+	g_system->displayMessageOnOSD(Common::U32String("Tank minigame not implemented yet!"));
+	DgdsEngine::getInstance()->setMenuToTrigger(kMenuSkipArcade);
+}
+
+void ChinaTank::end() {
+}
+
+} // end namespace Dgds
diff --git a/engines/dgds/minigames/china_tank.h b/engines/dgds/minigames/china_tank.h
new file mode 100644
index 00000000000..e4bc9956b05
--- /dev/null
+++ b/engines/dgds/minigames/china_tank.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DGDS_MINIGAMES_CHINA_TANK_H
+#define DGDS_MINIGAMES_CHINA_TANK_H
+
+namespace Dgds {
+
+/** Tank mini-game for Heart of China */
+class ChinaTank {
+public:
+	ChinaTank();
+
+	void init();
+	void tick();
+	void end();
+
+private:
+	// TODO add private members
+
+};
+
+} // end namespace Dgds
+
+#endif // DGDS_MINIGAMES_CHINA_TANK_H
diff --git a/engines/dgds/minigames/china_train.cpp b/engines/dgds/minigames/china_train.cpp
new file mode 100644
index 00000000000..446bc0949c3
--- /dev/null
+++ b/engines/dgds/minigames/china_train.cpp
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+
+#include "dgds/dgds.h"
+#include "dgds/minigames/china_train.h"
+
+namespace Dgds {
+
+ChinaTrain::ChinaTrain() {
+}
+
+void ChinaTrain::init() {
+}
+
+void ChinaTrain::tick() {
+	g_system->displayMessageOnOSD(Common::U32String("Train minigame not implemented yet!"));
+	DgdsEngine::getInstance()->setMenuToTrigger(kMenuSkipArcade);
+}
+
+void ChinaTrain::end() {
+}
+
+} // end namespace Dgds
diff --git a/engines/dgds/minigames/china_train.h b/engines/dgds/minigames/china_train.h
new file mode 100644
index 00000000000..fa783ee9004
--- /dev/null
+++ b/engines/dgds/minigames/china_train.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DGDS_MINIGAMES_CHINA_TRAIN_H
+#define DGDS_MINIGAMES_CHINA_TRAIN_H
+
+namespace Dgds {
+
+/** Train fight mini-game for Heart of China */
+class ChinaTrain {
+public:
+	ChinaTrain();
+
+	void init();
+	void tick();
+	void end();
+
+private:
+	// TODO add private members
+
+};
+
+} // end namespace Dgds
+
+#endif // DGDS_MINIGAMES_CHINA_TRAIN_H
diff --git a/engines/dgds/module.mk b/engines/dgds/module.mk
index 4fa01afb023..157f6f51287 100644
--- a/engines/dgds/module.mk
+++ b/engines/dgds/module.mk
@@ -26,6 +26,8 @@ MODULE_OBJS := \
 	sound.o \
 	sound_raw.o \
 	ttm.o \
+	minigames/china_tank.o \
+	minigames/china_train.o \
 	minigames/dragon_arcade.o \
 	minigames/dragon_arcade_ttm.o \
 	minigames/shell_game.o \
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index 9706821145d..4b1e0955b4b 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -42,6 +42,8 @@
 #include "dgds/globals.h"
 #include "dgds/image.h"
 #include "dgds/inventory.h"
+#include "dgds/minigames/china_tank.h"
+#include "dgds/minigames/china_train.h"
 #include "dgds/minigames/dragon_arcade.h"
 #include "dgds/dragon_native.h"
 #include "dgds/hoc_intro.h"
@@ -160,15 +162,22 @@ static Common::String _sceneOpCodeName(SceneOpCode code) {
 		}
 	} else if (DgdsEngine::getInstance()->getGameId() == GID_HOC) {
 		switch (code) {
-		case kSceneOpOpenChinaTankMenu:		return "openTankMenu";
+		case kSceneOpChinaTankInit:			return "tankInit";
+		case kSceneOpChinaTankEnd:			return "tankEnd";
+		case kSceneOpChinaTankTick:			return "tankTick";
+		case kSceneOpChinaScrollLeft:		return "scrollLeft";
+		case kSceneOpChinaScrollRight:		return "scrollRight";
+		case kSceneOpShellGameInit:			return "shellGameInit";
 		case kSceneOpShellGameEnd:			return "shellGameEnd";
 		case kSceneOpShellGameTick:			return "shellGameTick";
-		case kSceneOpOpenChinaTrainMenu:	return "trainMenu";
-		case kSceneOpOpenChinaOpenGameOverMenu: return "gameOverMenu";
-		case kSceneOpOpenChinaOpenSkipCreditsMenu: return "skipCreditsMenu";
+		case kSceneOpChinaTrainInit:		return "trainInit";
+		case kSceneOpChinaTrainEnd:			return "trainEnd";
+		case kSceneOpChinaTrainTick:		return "trainTick";
+		case kSceneOpChinaOpenGameOverMenu: return "gameOverMenu";
+		case kSceneOpChinaOpenSkipCreditsMenu: return "skipCreditsMenu";
 		case kSceneOpChinaOnIntroInit:		return "chinaOnIntroInit";
 		case kSceneOpChinaOnIntroTick:		return "chinaOnIntroTick";
-		case kSceneOpChinaOnIntroLeave:  	return "chinaOnIntroLeave";
+		case kSceneOpChinaOnIntroEnd:  		return "chinaOnIntroEnd";
 		default:
 			break;
 		}
@@ -770,15 +779,15 @@ bool Scene::runDragonOp(const SceneOp &op) {
 bool Scene::runChinaOp(const SceneOp &op) {
 	DgdsEngine *engine = DgdsEngine::getInstance();
 	switch (op._opCode) {
-	case kSceneOpOpenChinaOpenGameOverMenu:
-		engine->setMenuToTrigger(kMenuGameOver);
+	case kSceneOpChinaTankInit:
+		engine->getChinaTank()->init();
 		break;
-	case kSceneOpOpenChinaOpenSkipCreditsMenu:
-		engine->setMenuToTrigger(kMenuSkipPlayIntro);
+	case kSceneOpChinaTankEnd:
+		engine->getChinaTank()->end();
 		break;
-	case kSceneOpOpenChinaTankMenu:
-	case kSceneOpOpenChinaTrainMenu:
-		engine->setMenuToTrigger(kMenuSkipArcade);
+	case kSceneOpChinaTankTick:
+		engine->getChinaTank()->tick();
+		//engine->setMenuToTrigger(kMenuSkipArcade);
 		break;
 	case kSceneOpShellGameTick:
 		engine->getShellGame()->shellGameTick();
@@ -786,17 +795,38 @@ bool Scene::runChinaOp(const SceneOp &op) {
 	case kSceneOpShellGameEnd:
 		engine->getShellGame()->shellGameEnd();
 		break;
+	case kSceneOpChinaTrainInit:
+		engine->getChinaTrain()->init();
+		break;
+	case kSceneOpChinaTrainEnd:
+		engine->getChinaTrain()->end();
+		break;
+	case kSceneOpChinaTrainTick:
+		engine->getChinaTrain()->tick();
+		break;
+	case kSceneOpChinaOpenGameOverMenu:
+		engine->setMenuToTrigger(kMenuGameOver);
+		break;
+	case kSceneOpChinaOpenSkipCreditsMenu:
+		engine->setMenuToTrigger(kMenuSkipPlayIntro);
+		break;
 	case kSceneOpChinaOnIntroInit:
 		engine->getHocIntro()->init();
 		break;
 	case kSceneOpChinaOnIntroTick:
 		engine->getHocIntro()->tick();
 		break;
-	case kSceneOpChinaOnIntroLeave:
-		engine->getHocIntro()->leave();
+	case kSceneOpChinaOnIntroEnd:
+		engine->getHocIntro()->end();
+		break;
+	case kSceneOpChinaScrollIntro:
+	case kSceneOpChinaScrollLeft:
+	case kSceneOpChinaScrollRight:
+		// These map to null functions.
 		break;
 	default:
-		warning("TODO: Implement china-specific scene opcode %d", op._opCode);
+		warning("TODO: Implement china-specific scene opcode %d (%s)", op._opCode,
+			_sceneOpCodeName(op._opCode).c_str());
 		break;
 	}
 	return false;
diff --git a/engines/dgds/scene.h b/engines/dgds/scene.h
index 3d160a1f888..902f0f90351 100644
--- a/engines/dgds/scene.h
+++ b/engines/dgds/scene.h
@@ -126,16 +126,23 @@ enum SceneOpCode {
 
 	// China-specific opcodes
 	kSceneOpChinaTankInit = 100,
-	kSceneOpChinaTankExit = 101,
-	kSceneOpOpenChinaTankMenu = 102,
+	kSceneOpChinaTankEnd = 101,
+	kSceneOpChinaTankTick = 102,
+	kSceneOpChinaSetLanding = 103,
+	kSceneOpChinaScrollIntro = 104,
+	kSceneOpChinaScrollLeft = 105,
+	kSceneOpChinaScrollRight = 107,
+	kSceneOpShellGameInit = 108,
 	kSceneOpShellGameEnd = 109,
 	kSceneOpShellGameTick = 110,
-	kSceneOpOpenChinaTrainMenu = 113,
-	kSceneOpOpenChinaOpenGameOverMenu = 114,	// args: none.
-	kSceneOpOpenChinaOpenSkipCreditsMenu = 115,	// args: none.
+	kSceneOpChinaTrainInit = 111,
+	kSceneOpChinaTrainEnd = 112,
+	kSceneOpChinaTrainTick = 113,
+	kSceneOpChinaOpenGameOverMenu = 114,	// args: none.
+	kSceneOpChinaOpenSkipCreditsMenu = 115,	// args: none.
 	kSceneOpChinaOnIntroTick = 116,	// args: none.
 	kSceneOpChinaOnIntroInit = 117,	// args: none.
-	kSceneOpChinaOnIntroLeave = 118,	// args: none.
+	kSceneOpChinaOnIntroEnd = 118,	// args: none.
 
 	// Beamish-specific opcodes
 	kSceneOpOpenBeamishGameOverMenu = 100,




More information about the Scummvm-git-logs mailing list