diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp index 9af95d3a091..82fac9e9e9c 100644 --- a/engines/tinsel/scene.cpp +++ b/engines/tinsel/scene.cpp @@ -84,7 +84,11 @@ struct SCENE_STRUC { int32 numProcess; // number of processes in this scene SCNHANDLE hProcess; // handle to table of processes SCNHANDLE hMusicScript; // handle to music script data - Tinsel 2 only - SCNHANDLE hMusicSegment;// handle to music segments - Tinsel 2 only + SCNHANDLE hMusicSegment; // handle to music segments - Tinsel 2 only + int32 numCameras; + SCNHANDLE hCamera; + int32 numLights; + SCNHANDLE hLight; } PACKED_STRUCT; /** entrance structure - one per entrance */ @@ -96,6 +100,25 @@ struct ENTRANCE_STRUC { uint32 flags; } PACKED_STRUCT; +/** camera strucutre, Noir only */ +struct CAMERA_STRUC { + int32 sceneId; + int32 rotX; + int32 rotY; + int32 rotZ; + int32 posX; + int32 posY; + int32 posZ; + int32 aperture; +} PACKED_STRUCT; + +struct LIGHT_STRUC { + int32 sceneId; + int32 posX; + int32 posY; + int32 posZ; +} PACKED_STRUCT; + #include "common/pack-end.h" // END STRUCT PACKING @@ -114,6 +137,8 @@ static SCNHANDLE g_SceneHandle = 0; // Current scene handle - stored in case of SCENE_STRUC g_tempStruc; +static bool g_isViewSet = false; + struct TP_INIT { SCNHANDLE hTinselCode; // Code TINSEL_EVENT event; // Triggering event @@ -124,45 +149,12 @@ void ResetVarsScene() { g_initialMyEscape = 0; g_SceneHandle = 0; + g_isViewSet = false; memset(&g_tempStruc, 0, sizeof(SCENE_STRUC)); } -SCENE_STRUC* parseV3Scene(const byte *pStruc) { - memset(&g_tempStruc, 0, sizeof(SCENE_STRUC)); - Common::MemoryReadStream stream(pStruc, 84); - g_tempStruc.defRefer = stream.readUint32LE(); - g_tempStruc.hSceneScript = stream.readUint32LE(); - g_tempStruc.hSceneDesc = stream.readUint32LE(); - g_tempStruc.numEntrance = stream.readUint32LE(); - g_tempStruc.hEntrance = stream.readUint32LE(); - stream.readUint32LE(); - stream.readUint32LE(); - stream.readUint32LE(); - stream.readUint32LE(); - g_tempStruc.numPoly = stream.readUint32LE(); - g_tempStruc.hPoly = stream.readUint32LE(); - g_tempStruc.numTaggedActor = stream.readUint32LE(); - g_tempStruc.hTaggedActor = stream.readUint32LE(); - g_tempStruc.numProcess = stream.readUint32LE(); - g_tempStruc.hProcess = stream.readUint32LE(); - g_tempStruc.hMusicScript = stream.readUint32LE(); - g_tempStruc.hMusicSegment = stream.readUint32LE(); - warning("TODO: Complete scene loading logic for Noir"); - - return &g_tempStruc; -} - -const SCENE_STRUC *GetSceneStruc(const byte *pStruc) { - if (TinselVersion == 2) - return (const SCENE_STRUC *)pStruc; - else if (TinselVersion == 3) - return parseV3Scene(pStruc); - - // Copy appropriate fields into tempStruc, and return a pointer to it - const byte *p = pStruc; - memset(&g_tempStruc, 0, sizeof(SCENE_STRUC)); - +SCENE_STRUC* parseSceneV1(const byte *p) { g_tempStruc.numEntrance = READ_UINT32(p); p += sizeof(uint32); g_tempStruc.numPoly = READ_UINT32(p); p += sizeof(uint32); g_tempStruc.numTaggedActor = READ_UINT32(p); p += sizeof(uint32); @@ -175,6 +167,59 @@ const SCENE_STRUC *GetSceneStruc(const byte *pStruc) { return &g_tempStruc; } +SCENE_STRUC* parseSceneV2(const byte *p) { + g_tempStruc.defRefer = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hSceneScript = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hSceneDesc = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numEntrance = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hEntrance = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numPoly = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hPoly = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numTaggedActor = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hTaggedActor = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numProcess = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hProcess = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hMusicScript = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hMusicSegment = READ_UINT32(p); p += sizeof(uint32); + + return &g_tempStruc; +} + +SCENE_STRUC* parseSceneV3(const byte *p) { + g_tempStruc.defRefer = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hSceneScript = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hSceneDesc = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numEntrance = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hEntrance = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numCameras = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hCamera = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numLights = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hLight = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numPoly = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hPoly = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numTaggedActor = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hTaggedActor = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.numProcess = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hProcess = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hMusicScript = READ_UINT32(p); p += sizeof(uint32); + g_tempStruc.hMusicSegment = READ_UINT32(p); p += sizeof(uint32); + // scollfields scaling/speed - 4 ints + warning("TODO: Complete scene loading logic for Noir"); + + return &g_tempStruc; +} + +const SCENE_STRUC *GetSceneStruc(const byte *pStruc) { + memset(&g_tempStruc, 0, sizeof(SCENE_STRUC)); + + if (TinselVersion == 3) { + return parseSceneV3(pStruc); + } else if (TinselVersion == 2) { + return parseSceneV2(pStruc); + } else { + return parseSceneV1(pStruc); + } +} /** * Started up for scene script and entrance script. @@ -423,6 +468,8 @@ void StartNewScene(SCNHANDLE scene, int entry) { PrimeScene(); // Start up the standard stuff for the next scene. LoadScene(scene, entry); + + g_isViewSet = false; } #ifdef DEBUG @@ -469,4 +516,57 @@ void WrapScene() { SendSceneTinselProcess(CLOSEDOWN); } + + +/** + * Set parameters for 3D rendering for Noir. + */ +void SetView(int sceneId, int scale) { + if (sceneId == SysVar(SV_SPRITER_SCENE_ID)) { + if (scale == SysVar(SV_SPRITER_SCALE)) { + debug("Ignoring SetView()"); + return; + } + } + debug("SetView(%d, %d)", sceneId, scale); + + SetSysVar(SV_SPRITER_SCALE, scale); + SetSysVar(SV_USER3 ,0x28); + + if (g_isViewSet) { + //EndActors(); + } else { + g_isViewSet = true; + } + + int i = 0; + CAMERA_STRUC *pCamera = (CAMERA_STRUC *)_vm->_handle->LockMem(g_tempStruc.hCamera); + for (i = 0; i < g_tempStruc.numCameras; ++i, ++pCamera) { + if (sceneId == FROM_32(pCamera->sceneId)) { + // set camera + SetSysVar(SV_SPRITER_SCENE_ID, sceneId); + break; + } + } + + if (i == g_tempStruc.numCameras) { + // no suitable camera found + return; + } + + LIGHT_STRUC *pLight = (LIGHT_STRUC *)_vm->_handle->LockMem(g_tempStruc.hLight); + for (i = 0; i < g_tempStruc.numLights; ++i, ++pLight) { + if (sceneId == FROM_32(pLight->sceneId)) { + // set light + break; + } + } + + if (i == g_tempStruc.numLights) { + // use default light + } + + //update ground plane +} + } // End of namespace Tinsel diff --git a/engines/tinsel/scene.h b/engines/tinsel/scene.h index 827f76f0a4a..617dc2f94cc 100644 --- a/engines/tinsel/scene.h +++ b/engines/tinsel/scene.h @@ -88,6 +88,8 @@ void EndScene(); void SendSceneTinselProcess(TINSEL_EVENT event); +void SetView(int id, int scale); + } // End of namespace Tinsel #endif // TINSEL_SCENE_H diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index a7732cf4d8c..c6d14206864 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -6418,7 +6418,7 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi case SETVIEW: // Noir only pp -= 1; - warning("TODO: Implement SETVIEW(0x%08X, %i)", pp[0], pp[1]); + SetView(pp[0], pp[1]); return -2; case SHELL: