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

mduggan mgithub at guarana.org
Thu Apr 29 09:29:58 UTC 2021


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

Summary:
e3ee65de99 ULTIMA8: After implies, continue current process until suspend


Commit: e3ee65de991697d79b1f5642343ee65bd4588506
    https://github.com/scummvm/scummvm/commit/e3ee65de991697d79b1f5642343ee65bd4588506
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-04-29T17:51:14+09:00

Commit Message:
ULTIMA8: After implies, continue current process until suspend

Previously we implemented implies as the same as waitFor, but that suspends the
current process straight away.  All uses of implies in the usecode are
also immediately followed by a suspend.  A typical flow is something like:

005A: 0A    push byte   05h
005C: 0C    push dword  00000000h
0061: 57    spawn       02 00 0A0C:0032 (FREE::ordinal32 (waitNTimerTicks))
0068: 6E    add sp      -02h
006A: 5E    push        retval
006B: 54    implies     01 01
006E: 12    pop     temp
006F: 53    suspend

So after implies we should actually continue executing the current UC process
until a suspend or return, otherwise we wake up next frame only to suspend
again.  For longer-running spawns this probably makes no noticable difference,
but in Crusader the elevators spawn a process which only waits 1 tick.  This
should actually run the ELEVAT process again on the very next tick, but instead
it restarts *3* ticks later:

Tick 1:
1a. ELEVAT: spawn 1 tick sleep, execnow
1b. SLEEP: record start tick as tick 1
1c. ELEVAT: implies (waitFor) - process suspends

Tick 2:
2a. SLEEP: current tick is tick 2, (start+1) return, terminateDeferred

Tick 3:
3a. SLEEP: process terminates, notify ELEVAT process
3b. ELEVAT: wake up because of terminated sleep, pop return, suspend again

Tick 4:
4a. ELEVAT: continue again

This fixes it to only sleep for 2 ticks, which is still not totally correct
(terminateDeferred should maybe happen at the end of the frame to match
original?) but it's an improvement and it doesn't seem to break anything in U8.

Changed paths:
    engines/ultima/ultima8/usecode/uc_machine.cpp


diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index fd243b5890..a6f6b042d3 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -162,7 +162,8 @@ void UCMachine::execProcess(UCProcess *p) {
 
 #ifdef DEBUG
 	if (trace_show(p->_pid, p->_itemNum, p->_classId)) {
-		pout << ConsoleStream::hex << "running process " << p->_pid
+		pout << "tick " << Kernel::get_instance()->getTickNum()
+			 << ConsoleStream::hex << " running process " << p->_pid
 		     << ", item " << p->_itemNum << ", type " << p->_type
 		     << ", class " << p->_classId << ", offset " << p->_ip
 		     << ConsoleStream::dec << Std::endl;
@@ -171,6 +172,7 @@ void UCMachine::execProcess(UCProcess *p) {
 
 	bool cede = false;
 	bool error = false;
+	bool go_until_cede = false;
 
 	while (!cede && !error && !p->is_terminated()) {
 		//! guard against reading past end of class
@@ -1308,6 +1310,7 @@ void UCMachine::execProcess(UCProcess *p) {
 			// 53
 			// suspend
 			LOGPF(("suspend\n"));
+			go_until_cede = false;
 			cede = true;
 			break;
 
@@ -1342,6 +1345,9 @@ void UCMachine::execProcess(UCProcess *p) {
 			Process *proc2 = Kernel::get_instance()->getProcess(ui16a);
 			if (proc && proc2) {
 				proc->waitFor(ui16a);
+				// The proc is now marked suspended, but finish this execution
+				// until we hit a suspend or return.
+				go_until_cede = true;
 			} else {
 				perr << "Non-existent process PID (";
 				if (!proc && !proc2) {
@@ -1400,7 +1406,8 @@ void UCMachine::execProcess(UCProcess *p) {
 
 #ifdef DEBUG
 			if (trace_show(p->_pid, p->_itemNum, p->_classId)) {
-				pout << ConsoleStream::hex << "(still) running process " << p->_pid
+				pout << "tick " << Kernel::get_instance()->getTickNum()
+				     << " (still) running process " << ConsoleStream::hex << p->_pid
 				     << ", item " << p->_itemNum << ", type " << p->_type
 				     << ", class " << p->_classId << ", offset " << p->_ip
 				     << ConsoleStream::dec << Std::endl;
@@ -1434,7 +1441,8 @@ void UCMachine::execProcess(UCProcess *p) {
 
 #ifdef DEBUG
 			if (trace_show(p->_pid, p->_itemNum, p->_classId)) {
-				pout << ConsoleStream::hex << "(still) running process " << p->_pid
+				pout << "tick " << Kernel::get_instance()->getTickNum()
+					 << ConsoleStream::hex << " (still) running process " << p->_pid
 				     << ", item " << p->_itemNum << ", class " << p->_classId
 				     << ", offset " << p->_ip << ConsoleStream::dec << Std::endl;
 			}
@@ -2044,7 +2052,7 @@ void UCMachine::execProcess(UCProcess *p) {
 			p->_ip = static_cast<uint16>(cs->pos());   // TRUNCATES!
 
 		// check if we suspended ourselves
-		if ((p->_flags & Process::PROC_SUSPENDED) != 0)
+		if ((p->_flags & Process::PROC_SUSPENDED) != 0 && !go_until_cede)
 			cede = true;
 	} // while(!cede && !error && !p->terminated && !p->terminate_deferred)
 




More information about the Scummvm-git-logs mailing list