TINSEL: Refactor and simplify actor data loading

- Actor data is now obtained as a copy via GetActorData(), which handles
  endianess internally
- There is now a single ACTORDATA class for all Tinsel versions
- Struct packing has been removed from the actor data class, as we no
  longer cast raw data to image pointers
This commit is contained in:
Filippos Karapetis 2022-01-09 22:34:32 +02:00
parent beed7ba48d
commit e95a3b6efb
4 changed files with 79 additions and 49 deletions

View File

@ -45,25 +45,6 @@
namespace Tinsel {
#include "common/pack-start.h" // START STRUCT PACKING
/** actor struct - one per actor */
struct T1_ACTOR_STRUC {
int32 masking; ///< type of actor masking
SCNHANDLE hActorId; ///< handle actor ID string index
SCNHANDLE hActorCode; ///< handle to actor script
} PACKED_STRUCT;
struct T2_ACTOR_STRUC {
SCNHANDLE hActorId; // handle actor ID string index
SCNHANDLE hTagText; // tag
int32 tagPortionV; // defines tag area
int32 tagPortionH; // defines tag area
SCNHANDLE hActorCode; // handle to actor script
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
#define RANGE_CHECK(num) assert(num > 0 && num <= _numActors);
struct ACTORINFO {
@ -213,8 +194,8 @@ int Actor::TaggedActorIndex(int actor) {
* @param as Actor structure
* @param bRunScript Flag for whether to run actor's script for the scene
*/
void Actor::StartActor(const T1_ACTOR_STRUC *as, bool bRunScript) {
SCNHANDLE hActorId = FROM_32(as->hActorId);
void Actor::StartActor(const ACTORDATA *ad, bool bRunScript) {
SCNHANDLE hActorId = ad->hActorId;
// Zero-out many things
_actorInfo[hActorId - 1].bHidden = false;
@ -226,15 +207,15 @@ void Actor::StartActor(const T1_ACTOR_STRUC *as, bool bRunScript) {
_actorInfo[hActorId - 1].presObj = nullptr;
// Store current scene's parameters for this actor
_actorInfo[hActorId - 1].mtype = FROM_32(as->masking);
_actorInfo[hActorId - 1].actorCode = FROM_32(as->hActorCode);
_actorInfo[hActorId - 1].mtype = ad->masking;
_actorInfo[hActorId - 1].actorCode = ad->hActorCode;
// Run actor's script for this scene
if (bRunScript) {
if (_actorsOn)
_actorInfo[hActorId - 1].bAlive = true;
if (_actorInfo[hActorId - 1].bAlive && FROM_32(as->hActorCode))
if (_actorInfo[hActorId - 1].bAlive && ad->hActorCode)
ActorEvent(hActorId, STARTUP, PLR_NOEVENT);
}
}
@ -246,38 +227,41 @@ void Actor::StartActor(const T1_ACTOR_STRUC *as, bool bRunScript) {
* @param bRunScript Flag for whether to run actor scene scripts
*/
void Actor::StartTaggedActors(SCNHANDLE ah, int numActors, bool bRunScript) {
int i;
if (!TinselV2) {
// Tinsel 1 load variation
if (TinselV2) {
// Clear it all out for a fresh start
memset(_taggedActors, 0, sizeof(_taggedActors));
_numTaggedActors = numActors;
} else {
// Only actors with code blocks got (x, y) re-initialized, so...
for (i = 0; i < _numActors; i++) {
for (int i = 0; i < _numActors; i++) {
_actorInfo[i].x = _actorInfo[i].y = 0;
_actorInfo[i].mtype = 0;
}
}
if (!TinselV2) {
// Tinsel 1 load variation
const T1_ACTOR_STRUC *as = (const T1_ACTOR_STRUC *)_vm->_handle->LockMem(ah);
for (i = 0; i < numActors; i++, as++) {
StartActor(as, bRunScript);
const ACTORDATA *ad = _vm->_handle->GetActorData(ah, numActors);
for (int i = 0; i < numActors; i++) {
StartActor(&ad[i], bRunScript);
}
} else if (numActors > 0) {
delete[] ad;
} else {
// Tinsel 2 load variation
const T2_ACTOR_STRUC *as = (T2_ACTOR_STRUC *)_vm->_handle->LockMem(ah);
for (i = 0; i < numActors; i++, as++) {
assert(as->hActorCode);
// Clear it all out for a fresh start
memset(_taggedActors, 0, sizeof(_taggedActors));
_numTaggedActors = numActors;
if (numActors == 0)
return;
const ACTORDATA *ad = _vm->_handle->GetActorData(ah, numActors);
for (int i = 0; i < numActors; i++) {
assert(ad[i].hActorCode);
// Store current scene's parameters for this tagged actor
_taggedActors[i].id = FROM_32(as->hActorId);
_taggedActors[i].hTagText = FROM_32(as->hTagText);
_taggedActors[i].tagPortionV = FROM_32(as->tagPortionV);
_taggedActors[i].tagPortionH = FROM_32(as->tagPortionH);
_taggedActors[i].hActorCode = FROM_32(as->hActorCode);
_taggedActors[i].id = ad[i].hActorId;
_taggedActors[i].hTagText = ad[i].hTagText;
_taggedActors[i].tagPortionV = ad[i].tagPortionV;
_taggedActors[i].tagPortionH = ad[i].tagPortionH;
_taggedActors[i].hActorCode = ad[i].hActorCode;
// Run actor's script for this scene
if (bRunScript) {
@ -286,6 +270,8 @@ void Actor::StartTaggedActors(SCNHANDLE ah, int numActors, bool bRunScript) {
ActorEvent(_taggedActors[i].id, STARTUP, false, 0);
}
}
delete[] ad;
}
}

View File

@ -39,8 +39,6 @@ struct FREEL;
struct INT_CONTEXT;
struct MOVER;
struct OBJECT;
struct T1_ACTOR_STRUC;
struct T2_ACTOR_STRUC;
struct ACTORINFO;
struct Z_POSITIONS;
@ -82,6 +80,15 @@ struct Z_POSITIONS {
typedef SAVED_ACTOR *PSAVED_ACTOR;
struct ACTORDATA {
int32 masking; ///< type of actor masking (Tinsel V1)
SCNHANDLE hActorId; ///< handle actor ID string index
SCNHANDLE hActorCode; ///< handle to actor script
SCNHANDLE hTagText; // tag (Tinsel V2)
int32 tagPortionV; // defines tag area (Tinsel V2)
int32 tagPortionH; // defines tag area (Tinsel V2)
};
/*----------------------------------------------------------------------*/
class Actor {
@ -194,7 +201,7 @@ public:
void syncAllActorsAlive(Common::Serializer &s);
private:
void StartActor(const T1_ACTOR_STRUC *as, bool bRunScript);
void StartActor(const ACTORDATA *ad, bool bRunScript);
void GetActorTagPortion(int ano, unsigned *top, unsigned *bottom, unsigned *left, unsigned *right);
ACTORINFO *_actorInfo;

View File

@ -26,6 +26,7 @@
#include "common/memstream.h"
#include "common/textconsole.h"
#include "tinsel/actors.h"
#include "tinsel/background.h"
#include "tinsel/drives.h"
#include "tinsel/dw.h"
@ -407,6 +408,40 @@ SCNHANDLE Handle::GetFontImageHandle(SCNHANDLE offset) {
return handle;
}
/**
* Return an actor's data specified by a SCNHANDLE
* Handles endianess internally
* @param offset Handle and offset to data
* @return IMAGE structure
*/
const ACTORDATA *Handle::GetActorData(SCNHANDLE offset, int numActors) {
byte *data = LockMem(offset);
const bool isBE = TinselV1Mac || TinselV1Saturn;
const uint32 size = TinselV2 ? 20 : 12; // ACTORDATA struct size
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size * numActors, isBE);
ACTORDATA *actorData = new ACTORDATA[numActors];
for (int i = 0; i < numActors; i++) {
if (!TinselV2) {
actorData[i].masking = stream->readSint32();
actorData[i].hActorId = stream->readUint32();
actorData[i].hActorCode = stream->readUint32();
} else {
actorData[i].hActorId = stream->readUint32();
actorData[i].hTagText = stream->readUint32();
actorData[i].tagPortionV = stream->readSint32();
actorData[i].tagPortionH = stream->readSint32();
actorData[i].hActorCode = stream->readUint32();
}
}
delete stream;
return actorData;
}
/**
* Compute and return the address specified by a SCNHANDLE.
* @param offset Handle and offset to data

View File

@ -36,6 +36,7 @@ struct FONT;
struct MEMHANDLE;
struct PALETTE;
struct IMAGE;
struct ACTORDATA;
class Handle {
public:
@ -52,6 +53,7 @@ public:
const IMAGE *GetImage(SCNHANDLE offset);
void SetImagePalette(SCNHANDLE offset, SCNHANDLE palHandle);
SCNHANDLE GetFontImageHandle(SCNHANDLE offset);
const ACTORDATA *GetActorData(SCNHANDLE offset, int numActors);
byte *LockMem(SCNHANDLE offset);
void LockScene(SCNHANDLE offset);