TINSEL: Simplify reading of process information

This commit is contained in:
Filippos Karapetis 2022-05-08 13:29:39 +03:00
parent 1a75e459c5
commit 8be80717bb
4 changed files with 71 additions and 48 deletions

View File

@ -34,7 +34,7 @@
#include "tinsel/handle.h"
#include "tinsel/heapmem.h" // heap memory manager
#include "tinsel/palette.h"
#include "tinsel/scn.h" // for the DW1 Mac resource handler
#include "tinsel/sched.h"
#include "tinsel/timers.h" // for DwGetCurrentTime()
#include "tinsel/tinsel.h"
#include "tinsel/scene.h"
@ -414,18 +414,19 @@ SCNHANDLE Handle::GetFontImageHandle(SCNHANDLE offset) {
* Return an actor's data specified by a SCNHANDLE
* Handles endianess internally
* @param offset Handle and offset to data
* @param count Data count
* @return IMAGE structure
*/
const ACTORDATA *Handle::GetActorData(SCNHANDLE offset, int numActors) {
const ACTORDATA *Handle::GetActorData(SCNHANDLE offset, uint32 count) {
byte *data = LockMem(offset);
const bool isBE = TinselV1Mac || TinselV1Saturn;
const uint32 size = (TinselVersion >= 2) ? 20 : 12; // ACTORDATA struct size
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size * numActors, isBE);
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size * count, isBE);
ACTORDATA *actorData = new ACTORDATA[numActors];
ACTORDATA *actorData = new ACTORDATA[count];
for (int i = 0; i < numActors; i++) {
for (int i = 0; i < count; i++) {
if (TinselVersion <= 1) {
actorData[i].masking = stream->readSint32();
actorData[i].hActorId = stream->readUint32();
@ -444,6 +445,32 @@ const ACTORDATA *Handle::GetActorData(SCNHANDLE offset, int numActors) {
return actorData;
}
/**
* Return a process specified by a SCNHANDLE
* Handles endianess internally
* @param offset Handle and offset to data
* @param count Data count
* @return PROCESS_STRUC structure
*/
const PROCESS_STRUC *Handle::GetProcessData(SCNHANDLE offset, uint32 count) {
byte *data = LockMem(offset);
const bool isBE = TinselV1Mac || TinselV1Saturn;
const uint32 size = 8; // PROCESS_STRUC struct size
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size * count, isBE);
PROCESS_STRUC *processData = new PROCESS_STRUC[count];
for (int i = 0; i < count; i++) {
processData[i].processId = stream->readUint32();
processData[i].hProcessCode = stream->readUint32();
}
delete stream;
return processData;
}
/**
* Compute and return the address specified by a SCNHANDLE.
* @param offset Handle and offset to data

View File

@ -37,6 +37,7 @@ struct MEMHANDLE;
struct PALETTE;
struct IMAGE;
struct ACTORDATA;
struct PROCESS_STRUC;
class Handle {
public:
@ -53,7 +54,8 @@ public:
const IMAGE *GetImage(SCNHANDLE offset);
void SetImagePalette(SCNHANDLE offset, SCNHANDLE palHandle);
SCNHANDLE GetFontImageHandle(SCNHANDLE offset);
const ACTORDATA *GetActorData(SCNHANDLE offset, int numActors);
const ACTORDATA *GetActorData(SCNHANDLE offset, uint32 count);
const PROCESS_STRUC *GetProcessData(SCNHANDLE offset, uint32 count);
byte *LockMem(SCNHANDLE offset);
void LockScene(SCNHANDLE offset);

View File

@ -31,15 +31,6 @@
namespace Tinsel {
#include "common/pack-start.h" // START STRUCT PACKING
struct PROCESS_STRUC {
uint32 processId; // ID of process
SCNHANDLE hProcessCode; // handle to actor script
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
//----------------- LOCAL GLOBAL DATA --------------------
// These vars are reset upon engine destruction
@ -129,19 +120,17 @@ static void ProcessTinselProcess(CORO_PARAM, const void *param) {
* Called to restore a scene process.
*/
void RestoreSceneProcess(INT_CONTEXT *pic) {
uint32 i;
PROCESS_STRUC *pStruc;
const PROCESS_STRUC *processes = _vm->_handle->GetProcessData(g_hSceneProcess, g_numSceneProcess);
pStruc = (PROCESS_STRUC *)_vm->_handle->LockMem(g_hSceneProcess);
for (i = 0; i < g_numSceneProcess; i++) {
if (FROM_32(pStruc[i].hProcessCode) == pic->hCode) {
for (uint32 i = 0; i < g_numSceneProcess; i++) {
if (processes[i].hProcessCode == pic->hCode) {
CoroScheduler.createProcess(PID_PROCESS + i, RestoredProcessProcess,
&pic, sizeof(pic));
break;
}
}
assert(i < g_numSceneProcess);
delete[] processes;
}
/**
@ -149,46 +138,47 @@ void RestoreSceneProcess(INT_CONTEXT *pic) {
*/
void SceneProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait, int myEscape,
bool *result) {
uint32 i; // Loop counter
if (result) *result = false;
CORO_BEGIN_CONTEXT;
PROCESS_STRUC *pStruc;
const PROCESS_STRUC *processes;
Common::PPROCESS pProc;
INT_CONTEXT * pic;
INT_CONTEXT *pic;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->pStruc = (PROCESS_STRUC *)_vm->_handle->LockMem(g_hSceneProcess);
for (i = 0; i < g_numSceneProcess; i++) {
if (FROM_32(_ctx->pStruc[i].processId) == procID) {
assert(_ctx->pStruc[i].hProcessCode); // Must have some code to run
_ctx->processes = _vm->_handle->GetProcessData(g_hSceneProcess, g_numSceneProcess);
for (uint32 i = 0; i < g_numSceneProcess; i++) {
if (_ctx->processes[i].processId == procID) {
assert(_ctx->processes[i].hProcessCode); // Must have some code to run
_ctx->pic = InitInterpretContext(GS_PROCESS,
FROM_32(_ctx->pStruc[i].hProcessCode),
_ctx->processes[i].hProcessCode,
event,
NOPOLY, // No polygon
NOPOLY, // No polygon
0, // No actor
NULL, // No object
myEscape);
if (_ctx->pic == NULL)
return;
nullptr, // No object
myEscape
);
if (_ctx->pic) {
_ctx->pProc = CoroScheduler.createProcess(
PID_PROCESS + i,
ProcessTinselProcess,
&_ctx->pic,
sizeof(_ctx->pic));
AttachInterpret(_ctx->pic, _ctx->pProc);
}
_ctx->pProc = CoroScheduler.createProcess(PID_PROCESS + i, ProcessTinselProcess,
&_ctx->pic, sizeof(_ctx->pic));
AttachInterpret(_ctx->pic, _ctx->pProc);
break;
}
}
if (i == g_numSceneProcess)
return;
if (bWait) {
if (bWait && _ctx->pProc)
CORO_INVOKE_2(WaitInterpret, _ctx->pProc, result);
}
delete[] _ctx->processes;
CORO_END_CODE;
}
@ -196,16 +186,16 @@ void SceneProcessEvent(CORO_PARAM, uint32 procID, TINSEL_EVENT event, bool bWait
* Kill all instances of a scene process.
*/
void KillSceneProcess(uint32 procID) {
uint32 i; // Loop counter
PROCESS_STRUC *pStruc;
const PROCESS_STRUC *processes = _vm->_handle->GetProcessData(g_hSceneProcess, g_numSceneProcess);
pStruc = (PROCESS_STRUC *)_vm->_handle->LockMem(g_hSceneProcess);
for (i = 0; i < g_numSceneProcess; i++) {
if (FROM_32(pStruc[i].processId) == procID) {
for (uint32 i = 0; i < g_numSceneProcess; i++) {
if (processes[i].processId == procID) {
CoroScheduler.killMatchingProcess(PID_PROCESS + i, -1);
break;
}
}
delete[] processes;
}
/**

View File

@ -26,13 +26,17 @@
#include "common/coroutines.h"
#include "tinsel/dw.h" // new data types
#include "tinsel/events.h"
#include "tinsel/pcode.h"
#include "tinsel/tinsel.h"
namespace Tinsel {
struct INT_CONTEXT;
struct PROCESS_STRUC {
uint32 processId; // ID of process
SCNHANDLE hProcessCode; // handle to actor script
};
//----------------- FUNCTION PROTOTYPES --------------------
void SceneProcesses(uint32 numProcess, SCNHANDLE hProcess);