WATCHMAKER: Move room loading to RoomManager.

This lets us remove the dependency on malloc.h.

The replacement logic is not 100% perfect, as the original logic will
resize arrays to load additional t3dBODY-structs, and those would then
be free-d alongside their parent. This logic is currently missing, so
we will use some more memory.

However, we won't leak, as all loads are tracked by the RoomManager, and
will be freed when closing/restarting the game.
This commit is contained in:
Einar Johan Trøan Sømåen 2023-04-15 09:12:47 +02:00 committed by Eugene Sandulenko
parent 6ea8aefa7b
commit ca12fc10ab
12 changed files with 256 additions and 241 deletions

View File

@ -356,9 +356,10 @@ void FixupAnim(t3dMESH *mesh, uint8 pos, const char *room) {
db = &mesh->Anim;
if (pos) {
if (room && (room[0] != '\0')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(room))
t3dCurRoom = LoadedFiles[i].b;
t3dBODY *roomPtr = _vm->_roomManager->getRoomIfLoaded(room);
if (room) {
t3dCurRoom = roomPtr;
}
}
if (!GetLightPosition(&lp, pos) || (lp.x == 0.0f) || (lp.z == 0.0f)) pos = 0;
if (!GetLightDirection(&ld, pos) || (ld.x == 0.0f) || (ld.z == 0.0f)) pos = 0;
@ -508,7 +509,7 @@ t3dBODY *LoadShadowMeshes(WGame &game, const char *pname, t3dBODY *Body) {
strcpy(Name, pname);
strncpy(&Name[strlen(pname) - 4], "_Shadow.t3d\0", 12);
uint16 numBodys = 0;
shadow = t3dLoadRoom(game, Name, shadow, &numBodys, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_NOBOUNDS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
shadow = _vm->_roomManager->loadRoom(Name, shadow, &numBodys, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_NOBOUNDS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
if (!shadow) return nullptr;
for (uint16 i = 0; i < shadow->NumMeshes(); i++) {
@ -564,8 +565,11 @@ t3dCHARACTER *t3dLoadCharacter(WGame &game, const char *pname, uint16 num) {
// gVertex *v;
t3dCHARACTER *b = new t3dCHARACTER[1] {};
b->Body = t3dLoadRoom(game, pname, b->Body, &n, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
if (!b->Body) return nullptr;
b->Body = _vm->_roomManager->loadRoom(pname, b->Body, &n, (T3D_NOLIGHTMAPS | T3D_NORECURSION | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_STATIC_SET0 | T3D_STATIC_SET1));
if (!b->Body) {
delete b;
return nullptr;
}
b->Mesh = &b->Body->MeshTable[0];
b->CurRoom = t3dCurRoom;
b->Flags = T3D_CHARACTER_HIDE | T3D_CHARACTER_REALTIMELIGHTING;
@ -700,9 +704,7 @@ uint8 CompareLightPosition(char *roomname, uint8 pos1, t3dV3F *pos2, t3dF32 acce
// cerco la stanza
t = nullptr;
if (roomname && (roomname[0] != '\0')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(roomname))
t = LoadedFiles[i].b;
t = _vm->_roomManager->getRoomIfLoaded(roomname);
} else t = t3dCurRoom;
if (!t) return FALSE;

View File

@ -20,81 +20,30 @@
*/
#include "watchmaker/3d/loader.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/t3d.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/3d/t3d_mesh.h"
#include "watchmaker/types.h"
#include "common/stream.h"
#include "watchmaker/utils.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/work_dirs.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/light.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/3d/math/llmath.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/3d/t3d_mesh.h"
#include "watchmaker/game.h"
#include "watchmaker/ll/ll_mesh.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/renderer.h"
#include "watchmaker/t3d.h"
#include "watchmaker/types.h"
#include "watchmaker/utils.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/work_dirs.h"
namespace Watchmaker {
#define T3DFILEVERSION 11
// TODO: Globals
#define MAX_LOADED_FILES 100
RecStruct LoadedFiles[MAX_LOADED_FILES];
uint16 NumLoadedFiles = 0;
t3dV3F CharCorrection;
t3dF32 CurFloorY;
int32 t3dCurTime = 900, t3dCurOliSet = 0;
// LoadRoom vars
#define MAX_T3D_LOADLIST_ITEMS 50
struct _t3dLOADLIST {
Common::String pname = {};
uint32 LoaderFlags = 0;
t3dMESH *m = nullptr;
} t3dLoadList[MAX_T3D_LOADLIST_ITEMS] = {};
/* -----------------10/06/99 16.03-------------------
* AddToLoadList
* --------------------------------------------------*/
void AddToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags) {
int32 a;
if (!pname.empty()) {
for (a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
if (t3dLoadList[a].pname.empty()) {
t3dLoadList[a].LoaderFlags = LoaderFlags;
t3dLoadList[a].m = m;
t3dLoadList[a].pname = pname;
break;
}
}
if (a >= MAX_T3D_LOADLIST_ITEMS)
warning("Cannot add %s to LoadList", pname.c_str());
} else {
warning("Invalid parameters invoking AddToLoadList()");
warning("Mesh (%s), pname %s", m->name.c_str(), pname.c_str());
}
}
/* -----------------10/06/99 16.04-------------------
* GetFromLoadList
* --------------------------------------------------*/
struct _t3dLOADLIST *GetFromLoadList(void) {
int32 a;
for (a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
if (!t3dLoadList[a].pname.empty())
return &t3dLoadList[a];
}
return nullptr;
}
t3dPathCamera::t3dPathCamera(Common::SeekableReadStream &stream) {
NumCamera = stream.readByte();
PathIndex = stream.readByte();
@ -160,21 +109,6 @@ void decodeLoaderFlags(uint32 flags) {
warning("%d: T3D_HIPOLYCHARACTERS", flags & T3D_HIPOLYCHARACTERS);
}
/* -----------------10/06/99 16.04-------------------
* CheckIfAlreadyLoaded
* --------------------------------------------------*/
t3dBODY *CheckIfAlreadyLoaded(const Common::String &Name) {
if (Name.empty()) return nullptr;
for (uint16 i = 0; i < NumLoadedFiles; i++) {
if ((LoadedFiles[i].b != nullptr) && /*(LoadedFiles[i].Name != nullptr) &&*/ (!LoadedFiles[i].name.empty()))
if (LoadedFiles[i].name.equalsIgnoreCase(Name))
return LoadedFiles[i].b;
}
return nullptr;
}
Common::String constructPath(const Common::String &prefix, const Common::String &filename, const char *suffix) {
Common::String Name = prefix + filename;
uint16 len = Name.size();
@ -186,15 +120,188 @@ Common::String constructPath(const Common::String &prefix, const Common::String
return Common::String(Name);
}
class RoomManagerImplementation : public RoomManager {
WGame *_game;
#define MAX_LOADED_FILES 100
RecStruct LoadedFiles[MAX_LOADED_FILES];
uint16 NumLoadedFiles = 0;
public:
RoomManagerImplementation(WGame *game) : _game(game) {}
#define MAX_T3D_LOADLIST_ITEMS 50
struct _t3dLOADLIST {
Common::String pname = {};
uint32 LoaderFlags = 0;
t3dMESH *m = nullptr;
};
_t3dLOADLIST t3dLoadList[MAX_T3D_LOADLIST_ITEMS] = {};
void addToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags) {
if (!pname.empty()) {
int32 a;
for (a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
if (t3dLoadList[a].pname.empty()) {
t3dLoadList[a].LoaderFlags = LoaderFlags;
t3dLoadList[a].m = m;
t3dLoadList[a].pname = pname;
break;
}
}
if (a >= MAX_T3D_LOADLIST_ITEMS)
warning("Cannot add %s to LoadList", pname.c_str());
} else {
warning("Invalid parameters invoking AddToLoadList()");
warning("Mesh (%s), pname %s", m->name.c_str(), pname.c_str());
}
}
_t3dLOADLIST* getFromLoadList(void) {
for (int a = 0; a < MAX_T3D_LOADLIST_ITEMS; a++) {
if (!t3dLoadList[a].pname.empty())
return &t3dLoadList[a];
}
return nullptr;
}
t3dBODY *getRoomIfLoaded(const Common::String &roomname) override {
t3dBODY *t = nullptr;
for (int i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(roomname))
t = LoadedFiles[i].b;
return t;
}
t3dBODY* loadRoom(const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) override;
t3dBODY* loadSingleRoom(const Common::String &pname, uint16 *NumBody, uint32 LoaderFlags);
void hideRoomMeshesMatching(const Common::String &pname) override {
for (int i = 0; i < NumLoadedFiles; i++)
if (LoadedFiles[i].b)
if (LoadedFiles[i].b->name.equalsIgnoreCase(pname)) {
HideRoomMeshes(_game->init, LoadedFiles[i].b);
}
}
Common::Array<t3dBODY*> getLoadedFiles() override {
// TODO: This won't need to be a copy if we maintain a Common::Array only containing the valid ones.
Common::Array<t3dBODY*> files;
for (int i = 0; i < NumLoadedFiles; i++)
if (LoadedFiles[i].b)
files.push_back(LoadedFiles[i].b);
return files;
}
t3dBODY *checkIfAlreadyLoaded(const Common::String &Name) override {
if (Name.empty()) return nullptr;
for (uint16 i = 0; i < NumLoadedFiles; i++) {
if ((LoadedFiles[i].b != nullptr) && /*(LoadedFiles[i].Name != nullptr) &&*/ (!LoadedFiles[i].name.empty()))
if (LoadedFiles[i].name.equalsIgnoreCase(Name))
return LoadedFiles[i].b;
}
return nullptr;
}
t3dMESH *linkMeshToStr(Init &init, const Common::String &str) {
if (str.empty()) return nullptr;
// Cerca tra le camere
if (str.equalsIgnoreCase("camera"))
return &init._globals._invVars.CameraDummy;
// Cerca tra i personaggi
for (uint16 i = 0; i < T3D_MAX_CHARACTERS; i++)
if ((Character[i]) && (str.equalsIgnoreCase((char *)init.Obj[i].meshlink[0])))
return Character[i]->Mesh;
// Cerca nelle stanze caricate
for (uint16 i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b)
for (uint16 j = 0; j < LoadedFiles[i].b->NumMeshes(); j++) {
if (str.equalsIgnoreCase(LoadedFiles[i].b->MeshTable[j].name))
return &LoadedFiles[i].b->MeshTable[j];
}
}
return nullptr;
}
void releaseBody(const Common::String &name, const Common::String &altName) override {
for (int j = 0; j < NumLoadedFiles; j++) {
if (LoadedFiles[j].name.equalsIgnoreCase(name) || LoadedFiles[j].name.equalsIgnoreCase(altName)) {
t3dReleaseBody(LoadedFiles[j].b);
LoadedFiles[j].b = nullptr;
break;
}
}
}
void releaseLoadedFiles(uint32 exceptFlag) override {
for (int i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b && !(LoadedFiles[i].Flags & exceptFlag)) {
t3dReleaseBody(LoadedFiles[i].b);
LoadedFiles[i] = RecStruct(); // TODO: Deduplicate.
}
}
}
private:
void loadFromList();
};
RoomManager *RoomManager::create(WGame *game) {
return new RoomManagerImplementation(game);
}
/* -----------------10/06/99 16.04-------------------
* t3dLoadSingleRoom
* t3dLoadRoom
* --------------------------------------------------*/
t3dBODY *t3dLoadSingleRoom(WGame &game, const Common::String &_pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) {
t3dBODY* RoomManagerImplementation::loadRoom(const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) {
warning("t3dLoadRoom(%s, b, %d, %d)", pname.c_str(), *NumBody, LoaderFlags);
struct _t3dLOADLIST *l;
t3dBODY *r, *rez;
uint16 num, i;
// reset everything that was previously in the load list
for (int i = 0; i < MAX_T3D_LOADLIST_ITEMS; i++) {
t3dLoadList[i] = _t3dLOADLIST();
}
// Add the base stanza to the upload list
addToLoadList(nullptr, pname, LoaderFlags);
while ((l = getFromLoadList())) {
num = 0;
if (l->m) {
if ((rez = _vm->_roomManager->checkIfAlreadyLoaded(l->pname)))
l->m->PortalList = rez;
else {
// if (l->m->Flags&T3D_MESH_PREPROCESSPORTAL)
// body=l->m->PortalList = t3dLoadSingleRoom( l->pname, l->m->PortalList, &num, (l->LoaderFlags|T3D_HALFTEXTURESIZE) );
// else
// TODO: This should increase some refcount on the PortalList
warning("TODO: Handle refcounts on PortalList");
l->m->PortalList = loadSingleRoom(l->pname, &num, l->LoaderFlags);
}
} else
r = loadSingleRoom(l->pname, NumBody, l->LoaderFlags);
*l = _t3dLOADLIST();
}
if (!(LoaderFlags & T3D_NORECURSION)) {
for (i = 0; i < NumLoadedFiles; i++)
if (LoadedFiles[i].b)
t3dCalcRejectedMeshFromPortal(LoadedFiles[i].b);
}
warning("Room loaded");
return r;
}
t3dBODY* RoomManagerImplementation::loadSingleRoom(const Common::String &_pname, uint16 *NumBody, uint32 LoaderFlags) {
//warning("t3dLoadSingleRoom(workDirs, %s, b, %d, %d)", _pname, *NumBody, LoaderFlags);
//decodeLoaderFlags(LoaderFlags);
Common::String pname(_pname);
WorkDirs &workdirs = game.workDirs;
WorkDirs &workdirs = _game->workDirs;
if (pname.equalsIgnoreCase("r1c.t3d"))
if (((t3dCurTime >= 1300) && (t3dCurTime <= 1310)) || (t3dCurTime >= 1800)) //se viene cambiato l'orario cambiarlo anche in UpdateRoomVis...
@ -212,11 +319,11 @@ t3dBODY *t3dLoadSingleRoom(WGame &game, const Common::String &_pname, t3dBODY *b
return nullptr;
}
if (*NumBody == 0) { // Se e' il primo body, alloca
b = new t3dBODY;
(*NumBody)++;
} else
b = (t3dBODY *)t3dRealloc((uint32 *)b, sizeof(t3dBODY) * (++(*NumBody))); // Altrimenti, ridimensiona
if (*NumBody != 0) {
// TODO: This currently means that we never free the dependant bodies.
warning("Loading a dependant body, should also be deleted alongside the base body");
}
t3dBODY *b = new t3dBODY();
//warning("Loading %s ...", name.c_str());
*b = t3dBODY(); // Azzera Body
@ -229,67 +336,25 @@ t3dBODY *t3dLoadSingleRoom(WGame &game, const Common::String &_pname, t3dBODY *b
{
uint16 j = 1;
while (LoadedFiles[j].b != nullptr) j++;
while (LoadedFiles[j].b != nullptr)
j++;
if (j > MAX_LOADED_FILES) {
warning("Too many t3d files loaded!");
return nullptr;
}
if ((j + 1) > NumLoadedFiles) NumLoadedFiles = j + 1;
if ((j + 1) > NumLoadedFiles)
NumLoadedFiles = j + 1;
LoadedFiles[j].name = _pname; // Aggiunge il file alla lista
LoadedFiles[j].Flags = LoaderFlags; // Aggiunge Flags alla lista
LoadedFiles[j].b = b; // Aggiunge Body alla lista
j = 0;
}
b->loadFromStream(game, pname, *stream, LoaderFlags);
b->loadFromStream(*_game, pname, *stream, LoaderFlags);
return b;
}
/* -----------------10/06/99 16.04-------------------
* t3dLoadRoom
* --------------------------------------------------*/
t3dBODY *t3dLoadRoom(WGame &game, const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) {
warning("t3dLoadRoom(%s, b, %d, %d)", pname.c_str(), *NumBody, LoaderFlags);
struct _t3dLOADLIST *l;
t3dBODY *r, *rez;
uint16 num, i;
// azzera tutto quello che c'era prima nella load list
for (int i = 0; i < MAX_T3D_LOADLIST_ITEMS; i++) {
t3dLoadList[i] = _t3dLOADLIST();
}
// Aggiunge la stanza base alla lista di caricamenti
AddToLoadList(nullptr, pname, LoaderFlags);
while ((l = GetFromLoadList())) {
num = 0;
if (l->m) {
if ((rez = CheckIfAlreadyLoaded(l->pname)))
l->m->PortalList = rez;
else {
// if (l->m->Flags&T3D_MESH_PREPROCESSPORTAL)
// body=l->m->PortalList = t3dLoadSingleRoom( l->pname, l->m->PortalList, &num, (l->LoaderFlags|T3D_HALFTEXTURESIZE) );
// else
l->m->PortalList = t3dLoadSingleRoom(game, l->pname, l->m->PortalList, &num, l->LoaderFlags);
}
} else
r = t3dLoadSingleRoom(game, l->pname, b, NumBody, l->LoaderFlags);
*l = _t3dLOADLIST();
}
if (!(LoaderFlags & T3D_NORECURSION)) {
for (i = 0; i < NumLoadedFiles; i++)
if (LoadedFiles[i].b)
t3dCalcRejectedMeshFromPortal(LoadedFiles[i].b);
}
warning("Room loaded");
return r;
}
t3dParticle::t3dParticle(Common::SeekableReadStream &stream) {
t3dF32 difR1, difG1, difB1;
t3dF32 difR2, difG2, difB2;
@ -408,7 +473,7 @@ void t3dLoadSky(WGame &game, t3dBODY * /*body*/) {
// t3dF32 Tile=1.5f;
t3dF32 div;
if (!(t3dSky = t3dLoadRoom(game, "sky.t3d", t3dSky, &n, T3D_NORECURSION | T3D_NOLIGHTMAPS | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_NOBOUNDS | T3D_STATIC_SET0))) {
if (!(t3dSky = _vm->_roomManager->loadRoom("sky.t3d", t3dSky, &n, T3D_NORECURSION | T3D_NOLIGHTMAPS | T3D_NOVOLUMETRICLIGHTS | T3D_NOCAMERAS | T3D_NOBOUNDS | T3D_STATIC_SET0))) {
warning("Error during t3dLoadRoom: Sky not loaded");
}

View File

@ -69,20 +69,28 @@ struct RecStruct {
uint32 Flags = 0;
};
extern RecStruct LoadedFiles[];
extern uint16 NumLoadedFiles;
t3dBODY *t3dLoadRoom(WGame &game, const Common::String &pname, t3dBODY *b, unsigned short *NumBody, unsigned int LoaderFlags);
t3dBODY *t3dLoadSingleRoom(WGame &game, const char *_pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags);
void t3dOptimizeMaterialList(t3dBODY *b);
void t3dFinalizeMaterialList(t3dBODY *b);
void t3dPrecalcLight(t3dBODY *b, unsigned char *sun);
void t3dLoadSky(WGame &game, t3dBODY *b);
t3dBODY *CheckIfAlreadyLoaded(const Common::String &Name);
void AddToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags);
Common::String constructPath(const Common::String &prefix, const Common::String &filename, const char *suffix = nullptr);
class RoomManager {
public:
virtual ~RoomManager() {}
virtual void addToLoadList(t3dMESH *m, const Common::String &pname, uint32 LoaderFlags) = 0;
virtual t3dBODY* loadRoom(const Common::String &pname, t3dBODY *b, uint16 *NumBody, uint32 LoaderFlags) = 0;
static RoomManager *create(WGame *game);
virtual t3dBODY *getRoomIfLoaded(const Common::String &roomname) = 0;
virtual t3dMESH *linkMeshToStr(Init &init, const Common::String &str) = 0;
virtual void hideRoomMeshesMatching(const Common::String &pname) = 0;
virtual void releaseBody(const Common::String &name, const Common::String &altName) = 0;
virtual void releaseLoadedFiles(uint32 exceptFlag) = 0;
virtual t3dBODY *checkIfAlreadyLoaded(const Common::String &Name) = 0;
virtual Common::Array<t3dBODY*> getLoadedFiles() = 0;
};
} // End of namespace Watchmaker
#endif // WATCHMAKER_LOADER_H

View File

@ -177,15 +177,15 @@ void t3dBODY::populatePortalLists() {
//#endif
// TODO: This should probably be upfactored.
t3dBODY *rez = nullptr;
if (((rez = CheckIfAlreadyLoaded(Name)) == nullptr) && (!(LoaderFlags & T3D_NORECURSION))) { // Controlla se lo ha gia' caricato
if (((rez = _vm->_roomManager->checkIfAlreadyLoaded(Name)) == nullptr) && (!(LoaderFlags & T3D_NORECURSION))) { // Controlla se lo ha gia' caricato
if (Name.equalsIgnoreCase("rxt.t3d"))
AddToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags | T3D_NORECURSION & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
_vm->_roomManager->addToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags | T3D_NORECURSION & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
// Mesh[mesh].Flags|=T3D_MESH_NOPORTALCHECK;
else {
if (LoaderFlags & T3D_RECURSIONLEVEL1)
AddToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags | T3D_NORECURSION & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
_vm->_roomManager->addToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags | T3D_NORECURSION & ~T3D_RECURSIONLEVEL1)); // aggiunge e leva la ricorsione
else
AddToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags)); // altrimenti lo agggiunge alla lista
_vm->_roomManager->addToLoadList(&Mesh[mesh], Name, (uint16)(LoaderFlags)); // altrimenti lo agggiunge alla lista
}
} else
Mesh[mesh].PortalList = rez;

View File

@ -562,10 +562,9 @@ void ProcessTime(WGame &game) {
//DebugLogFile("Updating Listener ");
UpdateListener = 20;
for (i = 0; i < NumLoadedFiles; i++)
if (LoadedFiles[i].b && t3dCurRoom)
if (LoadedFiles[i].b->name.equalsIgnoreCase(t3dCurRoom->name))
HideRoomMeshes(game.init, LoadedFiles[i].b);
if (t3dCurRoom) {
_vm->_roomManager->hideRoomMeshesMatching(t3dCurRoom->name);
}
}
}
//

View File

@ -162,13 +162,7 @@ bool WGame::CheckAndLoadMoglieSupervisoreModel(int32 c) {
t3dReleaseCharacter(Character[c]);
Character[c] = nullptr;
for (j = 0; j < NumLoadedFiles; j++) {
if (LoadedFiles[j].name.equalsIgnoreCase(RemoveName) || LoadedFiles[j].name.equalsIgnoreCase(RemoveNameHI)) {
t3dReleaseBody(LoadedFiles[j].b);
LoadedFiles[j].b = nullptr;
break;
}
}
_vm->_roomManager->releaseBody(RemoveName, RemoveNameHI);
LoaderFlags |= T3D_PRELOADBASE;
LoaderFlags |= T3D_STATIC_SET1;
@ -192,6 +186,7 @@ bool WGame::CheckAndLoadMoglieSupervisoreModel(int32 c) {
WGame::WGame() : workDirs(WATCHMAKER_CFG_NAME) {
_vm = this;
_meshModifiers = new MeshModifiers();
_roomManager = RoomManager::create(this);
configLoaderFlags(); // TODO: This should probably happen before the constructor
// if LoaderFlags & T3D_DEBUGMODE
@ -219,6 +214,7 @@ WGame::~WGame() {
delete _renderer;
delete sdl;
delete _meshModifiers;
delete _roomManager;
_vm = nullptr;
}
@ -313,7 +309,7 @@ bool WGame::LoadAndSetup(const Common::String &name, uint8 lite) {
// PrintLoading();
if (!(LoaderFlags & T3D_NOICONS))
if (!(init._globals._invVars.t3dIcons = t3dLoadRoom(*this, "Icons.t3d", init._globals._invVars.t3dIcons, &i, (LoaderFlags | T3D_NORECURSION | T3D_NOLIGHTMAPS | T3D_NOBOUNDS | T3D_NOCAMERAS | T3D_STATIC_SET1)))) {
if (!(init._globals._invVars.t3dIcons = _roomManager->loadRoom("Icons.t3d", init._globals._invVars.t3dIcons, &i, (LoaderFlags | T3D_NORECURSION | T3D_NOLIGHTMAPS | T3D_NOBOUNDS | T3D_NOCAMERAS | T3D_STATIC_SET1)))) {
warning("Error loading Icons");
return false;
}
@ -361,7 +357,8 @@ bool WGame::LoadAndSetup(const Common::String &name, uint8 lite) {
if (!lite) {
if (LoaderFlags & T3D_PRELOAD_RXT) {
t3dCurOliSet = -1;
if (!(t3dRxt = t3dLoadRoom(*this, "rxt.t3d", t3dCurRoom, &i, LoaderFlags | T3D_NOLIGHTMAPS))) {
// TODO: Figure out how this i works out.
if (!(t3dRxt = _roomManager->loadRoom("rxt.t3d", t3dCurRoom, &i, LoaderFlags | T3D_NOLIGHTMAPS))) {
warning("Error loading room rxt.t3d");
return false;
}
@ -379,7 +376,7 @@ bool WGame::LoadAndSetup(const Common::String &name, uint8 lite) {
}
if (!((LoaderFlags & T3D_PRELOAD_RXT) && name.equalsIgnoreCase("rxt.t3d"))) {
if (!(t3dCurRoom = t3dLoadRoom(*this, name, t3dCurRoom, &i, LoaderFlags))) {
if (!(t3dCurRoom = _roomManager->loadRoom(name, t3dCurRoom, &i, LoaderFlags))) {
warning("Error loading room %s", name.c_str());
return false;
}
@ -506,12 +503,12 @@ bool WGame::LoadAndSetup(const Common::String &name, uint8 lite) {
void WGame::UpdateAll() {
int32 i;
UpdateRoomVisibility(*this);
for (i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b) {
HideRoomMeshes(init, LoadedFiles[i].b);
_meshModifiers->applyAllMeshModifiers(*this, LoadedFiles[i].b);
}
auto bodies = _roomManager->getLoadedFiles();
for (auto loadedBody : bodies) {
HideRoomMeshes(init, loadedBody);
_meshModifiers->applyAllMeshModifiers(*this, loadedBody);
}
UpdateAllClocks(*this);
// Init for Clock33

View File

@ -50,6 +50,7 @@ public:
};
class MeshModifiers;
class RoomManager;
class WGame {
bool g_bReady, g_bActive;
@ -69,6 +70,7 @@ public:
GameRect _gameRect;
Fonts _fonts;
MessageSystem _messageSystem;
RoomManager *_roomManager;
WGame();
~WGame();

View File

@ -1829,12 +1829,7 @@ void StopPlayingGame(WGame &game) {
StopAllAnims(init);
StopMusic();
t3dResetPipeline();
for (i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b && !(LoadedFiles[i].Flags & T3D_STATIC_SET1)) {
t3dReleaseBody(LoadedFiles[i].b);
LoadedFiles[i] = RecStruct(); // TODO: Deduplicate.
}
}
_vm->_roomManager->releaseLoadedFiles(T3D_STATIC_SET1);
t3dRxt = nullptr;
t3dSky = nullptr;

View File

@ -71,27 +71,6 @@ void *t3dCalloc(uint32 n) {
return (res);
}
void *t3dRealloc(void *pp, uint32 additionalBytes) {
uint32 *res = (uint32 *)pp;
uint32 size = 0;
if (pp == nullptr) size = 0;
else
size = (uint32) MALLOC_SIZE(pp);
//Reallocate and show new size:
if ((res = (uint32 *)realloc(pp, (additionalBytes + size))) == nullptr) {
warning("t3dRealloc: Memory allocation error: can't alloc %d bytes", additionalBytes + size);
return res;
}
t3dAllocatedMemory += additionalBytes;
//malloc_size()
pp = res;//realloc(pp, additionalBytes);
//warning("t3dRealloc() size: %d, additionalBytes: %d, newSize = %d", size, additionalBytes, malloc_size(pp));
return (pp);
}
void t3dFree(void *p) {
if (!p) return;

View File

@ -269,25 +269,8 @@ int32 LoadDDBitmap(WGame &game, const char *n, uint8 flags) {
* LinkMeshToStr
* --------------------------------------------------*/
t3dMESH *LinkMeshToStr(Init &init, const Common::String &str) {
if (str.empty()) return nullptr;
// Cerca tra le camere
if (str.equalsIgnoreCase("camera"))
return &init._globals._invVars.CameraDummy;
// Cerca tra i personaggi
for (uint16 i = 0; i < T3D_MAX_CHARACTERS; i++)
if ((Character[i]) && (str.equalsIgnoreCase((char *)init.Obj[i].meshlink[0])))
return Character[i]->Mesh;
// Cerca nelle stanze caricate
for (uint16 i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b)
for (uint16 j = 0; j < LoadedFiles[i].b->NumMeshes(); j++) {
if (str.equalsIgnoreCase(LoadedFiles[i].b->MeshTable[j].name))
return &LoadedFiles[i].b->MeshTable[j];
}
}
return nullptr;
// TODO: Refactor the callsites:
return _vm->_roomManager->linkMeshToStr(init, str);
}
/* -----------------18/12/00 18.02-------------------
@ -444,9 +427,7 @@ bool SetBndLevel(WGame &game, const char *roomname, int32 lev) {
t = nullptr;
if (roomname && (roomname[0] != '\0')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(roomname))
t = LoadedFiles[i].b;
_vm->_roomManager->getRoomIfLoaded(roomname);
} else t = t3dCurRoom;
if (!t) {
@ -522,20 +503,13 @@ void ChangeRoom(WGame &game, Common::String n, uint8 pos, int32 an) {
// se esso aveva delle modifiche da fare al piano corrente le fa subito, e non dopo quando il piano non e' piu' disponibile
StopDiary(game, 0, 0, 0);
t = nullptr;
// Prima lo cerca tra le stanze in memoria
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(n))
t = LoadedFiles[i].b;
t = _vm->_roomManager->getRoomIfLoaded(n);
// Se non lo trova tra le stanze in memoria
if (!t) {
t3dResetPipeline();
for (i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b && !(LoadedFiles[i].Flags & T3D_STATIC_SET0)) {
t3dReleaseBody(LoadedFiles[i].b);
LoadedFiles[i] = RecStruct(); // TODO: Deduplicate this
}
}
_vm->_roomManager->releaseLoadedFiles(T3D_STATIC_SET0);
for (i = 0; i < T3D_MAX_CHARACTERS; i++) {
if (Character[i]) {
@ -597,9 +571,7 @@ int32 GetBndLevel(char *roomname) {
t = nullptr;
if (roomname && (roomname[0] != '\0')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(roomname))
t = LoadedFiles[i].b;
t = _vm->_roomManager->getRoomIfLoaded(roomname);
} else t = t3dCurRoom;
if (!t) return FALSE;

View File

@ -545,12 +545,7 @@ bool DataLoad(WGame &game, const Common::String &FileName, uint8 slot) {
StopSounds();
StopMusic();
t3dResetPipeline();
for (int i = 0; i < NumLoadedFiles; i++) {
if (LoadedFiles[i].b && !(LoadedFiles[i].Flags & T3D_STATIC_SET1)) {
t3dReleaseBody(LoadedFiles[i].b);
LoadedFiles[i] = RecStruct();
}
}
_vm->_roomManager->releaseLoadedFiles(T3D_STATIC_SET1);
t3dRxt = nullptr;
t3dSky = nullptr;
rReleaseAllTextures(T3D_STATIC_SET0);

View File

@ -214,9 +214,10 @@ void CharSetPosition(int32 oc, uint8 pos, const char *room) {
CharStop(oc);
if (pos == 99) return;
if (room && (room[0] != '\0')) {
for (i = 0; i < NumLoadedFiles; i++)
if ((LoadedFiles[i].b != nullptr) && LoadedFiles[i].b->name.equalsIgnoreCase(room))
t3dCurRoom = LoadedFiles[i].b;
t3dBODY *roomPtr = _vm->_roomManager->getRoomIfLoaded(room);
if (roomPtr) {
t3dCurRoom = roomPtr;
}
}
if (pos) {