mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-30 08:47:58 +03:00
New streams class; Refactored chunk IO; Added chunk writer; Started new savegame system;
This commit is contained in:
parent
c7995dae7f
commit
5c376c0f95
22 changed files with 1312 additions and 118 deletions
Binary file not shown.
|
@ -224,14 +224,6 @@ GAME_STATUS __cdecl ControlPhase(__int32 numFrames, __int32 demoMode)
|
||||||
return GAME_STATUS::GAME_STATUS_NONE;
|
return GAME_STATUS::GAME_STATUS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cdecl j_AnimateItem(ITEM_INFO* item)
|
|
||||||
{
|
|
||||||
if (item != LaraItem)
|
|
||||||
printf("AnimateItem\n");
|
|
||||||
AnimateItem(item);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned __stdcall GameMain(void*)
|
unsigned __stdcall GameMain(void*)
|
||||||
{
|
{
|
||||||
DB_Log(2, "GameMain - DLL");
|
DB_Log(2, "GameMain - DLL");
|
||||||
|
@ -875,5 +867,5 @@ void __cdecl TestTriggers(__int16* data, __int32 heavy, __int32 HeavyFlags)
|
||||||
|
|
||||||
void Inject_Control()
|
void Inject_Control()
|
||||||
{
|
{
|
||||||
INJECT(0x0040261C, j_AnimateItem);
|
|
||||||
}
|
}
|
|
@ -2,24 +2,12 @@
|
||||||
|
|
||||||
#include "..\Global\global.h"
|
#include "..\Global\global.h"
|
||||||
|
|
||||||
typedef enum GAME_STATUS {
|
|
||||||
GAME_STATUS_NONE,
|
|
||||||
GAME_STATUS_NEW_GAME,
|
|
||||||
GAME_STATUS_LOAD_GAME,
|
|
||||||
GAME_STATUS_SAVE_GAME,
|
|
||||||
GAME_STATUS_EXIT_TO_TITLE,
|
|
||||||
GAME_STATUS_EXIT_GAME,
|
|
||||||
GAME_STATUS_LARA_DEAD,
|
|
||||||
GAME_STATUS_LEVEL_COMPLETED
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GetFloor ((FLOOR_INFO* (__cdecl*)(int, int, int, short*)) 0x00415B20)
|
#define GetFloor ((FLOOR_INFO* (__cdecl*)(int, int, int, short*)) 0x00415B20)
|
||||||
#define GetCeiling ((int (__cdecl*)(FLOOR_INFO*, int, int, int)) 0x00417640)
|
#define GetCeiling ((int (__cdecl*)(FLOOR_INFO*, int, int, int)) 0x00417640)
|
||||||
#define GetFloorHeight ((int (__cdecl*)(FLOOR_INFO*, int, int, int)) 0x00415FB0)
|
#define GetFloorHeight ((int (__cdecl*)(FLOOR_INFO*, int, int, int)) 0x00415FB0)
|
||||||
#define GetRandomControl ((int (__cdecl*)()) 0x004A7C10)
|
#define GetRandomControl ((int (__cdecl*)()) 0x004A7C10)
|
||||||
#define AnimateItem ((void (__cdecl*)(ITEM_INFO*)) 0x00415300)
|
#define AnimateItem ((void (__cdecl*)(ITEM_INFO*)) 0x00415300)
|
||||||
#define GetWaterHeight ((__int32 (__cdecl*)(__int32, __int32, __int32, __int16)) 0x00415DA0)
|
#define GetWaterHeight ((__int32 (__cdecl*)(__int32, __int32, __int32, __int16)) 0x00415DA0)
|
||||||
//#define TestTriggers ((void (__cdecl*)(__int16*, __int32, __int32)) 0x00416760)
|
|
||||||
#define TriggerActive ((__int32 (__cdecl*)(ITEM_INFO*)) 0x004175B0)
|
#define TriggerActive ((__int32 (__cdecl*)(ITEM_INFO*)) 0x004175B0)
|
||||||
#define GetChange ((__int32 (__cdecl*)(ITEM_INFO*, ANIM_STRUCT*)) 0x00415890)
|
#define GetChange ((__int32 (__cdecl*)(ITEM_INFO*, ANIM_STRUCT*)) 0x00415890)
|
||||||
#define KillMoveItems ((void (__cdecl*)()) 0x00414620)
|
#define KillMoveItems ((void (__cdecl*)()) 0x00414620)
|
||||||
|
@ -55,7 +43,6 @@ GAME_STATUS __cdecl DoLevel(__int32 index, __int32 ambient, bool loadFromSavegam
|
||||||
GAME_STATUS __cdecl ControlPhase(__int32 numFrames, __int32 demoMode);
|
GAME_STATUS __cdecl ControlPhase(__int32 numFrames, __int32 demoMode);
|
||||||
|
|
||||||
unsigned __stdcall GameMain(void*);
|
unsigned __stdcall GameMain(void*);
|
||||||
void __cdecl j_AnimateItem(ITEM_INFO* item);
|
|
||||||
void __cdecl TestTriggers(__int16* data, __int32 heavy, __int32 HeavyFlags);
|
void __cdecl TestTriggers(__int16* data, __int32 heavy, __int32 HeavyFlags);
|
||||||
|
|
||||||
void Inject_Control();
|
void Inject_Control();
|
|
@ -0,0 +1,117 @@
|
||||||
|
#include "savegame.h"
|
||||||
|
#include "..\Global\global.h"
|
||||||
|
|
||||||
|
FileStream* SaveGame::m_stream;
|
||||||
|
ChunkReader* SaveGame::m_reader;
|
||||||
|
ChunkWriter* SaveGame::m_writer;
|
||||||
|
|
||||||
|
ChunkId* SaveGame::m_chunkHeader;
|
||||||
|
ChunkId* SaveGame::m_chunkGameStatus;
|
||||||
|
ChunkId* SaveGame::m_chunkItems;
|
||||||
|
ChunkId* SaveGame::m_chunkItem;
|
||||||
|
ChunkId* SaveGame::m_chunkLara;
|
||||||
|
ChunkId* SaveGame::m_chunkLuaVariables;
|
||||||
|
ChunkId* SaveGame::m_chunkLuaLocal;
|
||||||
|
ChunkId* SaveGame::m_chunkLuaGlobal;
|
||||||
|
|
||||||
|
void SaveGame::SaveHeader(__int32 param)
|
||||||
|
{
|
||||||
|
m_stream->WriteString(g_GameFlow->GetString(g_GameFlow->GetLevel(CurrentLevel)->Name));
|
||||||
|
LEB128::Write(m_stream, (Savegame.Game.Timer / 30) / 86400);
|
||||||
|
LEB128::Write(m_stream, ((Savegame.Game.Timer / 30) % 86400) / 3600);
|
||||||
|
LEB128::Write(m_stream, ((Savegame.Game.Timer / 30) / 60) % 60);
|
||||||
|
LEB128::Write(m_stream, (Savegame.Game.Timer / 30) % 60);
|
||||||
|
LEB128::Write(m_stream, CurrentLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveGame::SaveGameStatus(__int32 param)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveGame::SaveItems(__int32 param)
|
||||||
|
{
|
||||||
|
for (__int32 i = 0; i < NumItems; i++)
|
||||||
|
{
|
||||||
|
m_writer->WriteChunk(m_chunkItem, &SaveItem, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveGame::SaveItem(__int32 itemNumber)
|
||||||
|
{
|
||||||
|
ITEM_INFO* item = &Items[itemNumber];
|
||||||
|
OBJECT_INFO* obj = &Objects[item->objectNumber];
|
||||||
|
|
||||||
|
LEB128::Write(m_stream, item->flags);
|
||||||
|
LEB128::Write(m_stream, item->pos.xPos);
|
||||||
|
LEB128::Write(m_stream, item->pos.yPos);
|
||||||
|
LEB128::Write(m_stream, item->pos.zPos);
|
||||||
|
LEB128::Write(m_stream, item->pos.xRot);
|
||||||
|
LEB128::Write(m_stream, item->pos.yRot);
|
||||||
|
LEB128::Write(m_stream, item->pos.zRot);
|
||||||
|
LEB128::Write(m_stream, item->roomNumber);
|
||||||
|
LEB128::Write(m_stream, item->itemFlags[0]);
|
||||||
|
LEB128::Write(m_stream, item->itemFlags[1]);
|
||||||
|
LEB128::Write(m_stream, item->itemFlags[2]);
|
||||||
|
LEB128::Write(m_stream, item->itemFlags[3]);
|
||||||
|
LEB128::Write(m_stream, item->triggerFlags);
|
||||||
|
LEB128::Write(m_stream, item->timer);
|
||||||
|
LEB128::Write(m_stream, item->speed);
|
||||||
|
LEB128::Write(m_stream, item->fallspeed);
|
||||||
|
LEB128::Write(m_stream, item->currentAnimState);
|
||||||
|
LEB128::Write(m_stream, item->goalAnimState);
|
||||||
|
LEB128::Write(m_stream, item->requiredAnimState);
|
||||||
|
LEB128::Write(m_stream, item->animNumber);
|
||||||
|
LEB128::Write(m_stream, item->frameNumber);
|
||||||
|
LEB128::Write(m_stream, item->objectNumber);
|
||||||
|
LEB128::Write(m_stream, item->hitPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveGame::SaveLara(__int32 param)
|
||||||
|
{
|
||||||
|
LARA_INFO lara;
|
||||||
|
memcpy(&lara, &Lara, sizeof(Lara));
|
||||||
|
|
||||||
|
for (__int32 i = 0; i < 15; i++)
|
||||||
|
lara.meshPtrs[i] = (__int16*)(lara.meshPtrs[i] - MeshBase);
|
||||||
|
|
||||||
|
lara.leftArm.frameBase = (__int16*)(lara.leftArm.frameBase - Objects[ID_PISTOLS_ANIM].frameBase);
|
||||||
|
lara.rightArm.frameBase = (__int16*)(lara.rightArm.frameBase - Objects[ID_PISTOLS_ANIM].frameBase);
|
||||||
|
|
||||||
|
m_stream->Write(reinterpret_cast<char*>(&lara), sizeof(Lara));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SaveGame::Save(char* fileName)
|
||||||
|
{
|
||||||
|
m_chunkHeader = ChunkId::FromString("TR5MSgHeader");
|
||||||
|
m_chunkGameStatus = ChunkId::FromString("TR5MSgGameStatus");
|
||||||
|
m_chunkItems = ChunkId::FromString("TR5MSgItems");
|
||||||
|
m_chunkItem = ChunkId::FromString("TR5MSgItem");
|
||||||
|
m_chunkLara = ChunkId::FromString("TR5MSgLara");
|
||||||
|
m_chunkLuaVariables = ChunkId::FromString("TR5MSgLuaVars");
|
||||||
|
m_chunkLuaLocal = ChunkId::FromString("TR5MSgLuaL");
|
||||||
|
m_chunkLuaGlobal = ChunkId::FromString("TR5MSgLuaG");
|
||||||
|
|
||||||
|
m_stream = new FileStream(fileName);
|
||||||
|
m_writer = new ChunkWriter(0x4D355254, m_stream);
|
||||||
|
|
||||||
|
m_writer->WriteChunk(m_chunkHeader, &SaveHeader, 0);
|
||||||
|
m_writer->WriteChunk(m_chunkLara, &SaveLara, 0);
|
||||||
|
m_writer->WriteChunkWithChildren(m_chunkItems, &SaveItems, 0);
|
||||||
|
|
||||||
|
m_stream->Close();
|
||||||
|
|
||||||
|
delete m_writer;
|
||||||
|
delete m_stream;
|
||||||
|
|
||||||
|
delete m_chunkHeader;
|
||||||
|
delete m_chunkGameStatus;
|
||||||
|
delete m_chunkItems;
|
||||||
|
delete m_chunkItem;
|
||||||
|
delete m_chunkLara;
|
||||||
|
delete m_chunkLuaVariables;
|
||||||
|
delete m_chunkLuaLocal;
|
||||||
|
delete m_chunkLuaGlobal;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -1,8 +1,45 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "..\Global\global.h"
|
||||||
|
#include "..\Specific\IO\ChunkId.h"
|
||||||
|
#include "..\Specific\IO\ChunkReader.h"
|
||||||
|
#include "..\Specific\IO\ChunkWriter.h"
|
||||||
|
#include "..\Specific\IO\LEB128.h"
|
||||||
|
#include "..\Specific\IO\Streams.h"
|
||||||
|
#include "..\Scripting\GameFlowScript.h"
|
||||||
|
#include "..\Scripting\GameLogicScript.h"
|
||||||
|
|
||||||
#define RestoreGame ((__int32 (__cdecl*)()) 0x00472060)
|
#define RestoreGame ((__int32 (__cdecl*)()) 0x00472060)
|
||||||
#define ReadSavegame ((__int32 (__cdecl*)(__int32)) 0x004A8E10)
|
#define ReadSavegame ((__int32 (__cdecl*)(__int32)) 0x004A8E10)
|
||||||
#define CreateSavegame ((void (__cdecl*)()) 0x00470FA0)
|
#define CreateSavegame ((void (__cdecl*)()) 0x00470FA0)
|
||||||
#define WriteSavegame ((__int32 (__cdecl*)(__int32)) 0x004A8BC0)
|
#define WriteSavegame ((__int32 (__cdecl*)(__int32)) 0x004A8BC0)
|
||||||
|
|
||||||
|
#define SAVEGAME_BUFFER_SIZE 1048576
|
||||||
|
|
||||||
|
extern GameFlow* g_GameFlow;
|
||||||
|
extern GameScript* g_GameScript;
|
||||||
|
|
||||||
|
class SaveGame {
|
||||||
|
private:
|
||||||
|
static FileStream* m_stream;
|
||||||
|
static ChunkReader* m_reader;
|
||||||
|
static ChunkWriter* m_writer;
|
||||||
|
|
||||||
|
static ChunkId* m_chunkHeader;
|
||||||
|
static ChunkId* m_chunkGameStatus;
|
||||||
|
static ChunkId* m_chunkItems;
|
||||||
|
static ChunkId* m_chunkItem;
|
||||||
|
static ChunkId* m_chunkLara;
|
||||||
|
static ChunkId* m_chunkLuaVariables;
|
||||||
|
static ChunkId* m_chunkLuaLocal;
|
||||||
|
static ChunkId* m_chunkLuaGlobal;
|
||||||
|
|
||||||
|
static void SaveHeader(__int32 param);
|
||||||
|
static void SaveGameStatus(__int32 param);
|
||||||
|
static void SaveLara(__int32 param);
|
||||||
|
static void SaveItem(__int32 param);
|
||||||
|
static void SaveItems(__int32 param);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool Save(char* fileName);
|
||||||
|
};
|
|
@ -17,7 +17,7 @@
|
||||||
#define BOX_BLOCKED (1 << 14) // unpassable for other enemies, always set for movable blocks & closed doors
|
#define BOX_BLOCKED (1 << 14) // unpassable for other enemies, always set for movable blocks & closed doors
|
||||||
#define BOX_LAST (1 << 15) // unpassable by large enemies (T-Rex, Centaur, etc), always set behind doors
|
#define BOX_LAST (1 << 15) // unpassable by large enemies (T-Rex, Centaur, etc), always set behind doors
|
||||||
|
|
||||||
#define NUM_OBJECTS 488
|
#define NUM_OBJECTS 518
|
||||||
|
|
||||||
#define UNIT_SHADOW 256
|
#define UNIT_SHADOW 256
|
||||||
#define DEFAULT_RADIUS 10
|
#define DEFAULT_RADIUS 10
|
||||||
|
|
|
@ -897,3 +897,14 @@ enum WEATHER_TYPES
|
||||||
WEATHER_RAIN = 1,
|
WEATHER_RAIN = 1,
|
||||||
WEATHER_SNOW = 2
|
WEATHER_SNOW = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum GAME_STATUS {
|
||||||
|
GAME_STATUS_NONE,
|
||||||
|
GAME_STATUS_NEW_GAME,
|
||||||
|
GAME_STATUS_LOAD_GAME,
|
||||||
|
GAME_STATUS_SAVE_GAME,
|
||||||
|
GAME_STATUS_EXIT_TO_TITLE,
|
||||||
|
GAME_STATUS_EXIT_GAME,
|
||||||
|
GAME_STATUS_LARA_DEAD,
|
||||||
|
GAME_STATUS_LEVEL_COMPLETED
|
||||||
|
};
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#define ONE_DEGREE 182
|
#define ONE_DEGREE 182
|
||||||
#define ANGLE(x) ((x) * 65536.0 / 360.0)
|
#define ANGLE(x) ((x) * 65536.0 / 360.0)
|
||||||
|
#define TR_ANGLE_TO_DEGREES(x) ((x) / 65536.0 * 360.0)
|
||||||
#define TR_ANGLE_TO_RAD(x) ((x) / 65536.0 * 360.0 * RADIAN)
|
#define TR_ANGLE_TO_RAD(x) ((x) / 65536.0 * 360.0 * RADIAN)
|
||||||
|
|
||||||
#define SQRT_ASM ((int (__cdecl*)(int)) 0x0048F980)
|
#define SQRT_ASM ((int (__cdecl*)(int)) 0x0048F980)
|
||||||
|
|
|
@ -489,5 +489,35 @@ typedef enum object_types {
|
||||||
ID_NEW_SLOT_485,
|
ID_NEW_SLOT_485,
|
||||||
ID_NEW_SLOT_486,
|
ID_NEW_SLOT_486,
|
||||||
ID_NEW_SLOT_487,
|
ID_NEW_SLOT_487,
|
||||||
ID_NEW_SLOT_488
|
ID_NEW_SLOT_488,
|
||||||
|
ID_NEW_SLOT_489,
|
||||||
|
ID_NEW_SLOT_490,
|
||||||
|
ID_NEW_SLOT_491,
|
||||||
|
ID_NEW_SLOT_492,
|
||||||
|
ID_NEW_SLOT_493,
|
||||||
|
ID_NEW_SLOT_494,
|
||||||
|
ID_NEW_SLOT_495,
|
||||||
|
ID_NEW_SLOT_496,
|
||||||
|
ID_NEW_SLOT_497,
|
||||||
|
ID_NEW_SLOT_498,
|
||||||
|
ID_NEW_SLOT_499,
|
||||||
|
ID_NEW_SLOT_500,
|
||||||
|
ID_NEW_SLOT_501,
|
||||||
|
ID_NEW_SLOT_502,
|
||||||
|
ID_NEW_SLOT_503,
|
||||||
|
ID_NEW_SLOT_504,
|
||||||
|
ID_NEW_SLOT_505,
|
||||||
|
ID_NEW_SLOT_506,
|
||||||
|
ID_NEW_SLOT_507,
|
||||||
|
ID_NEW_SLOT_508,
|
||||||
|
ID_NEW_SLOT_509,
|
||||||
|
ID_NEW_SLOT_510,
|
||||||
|
ID_NEW_SLOT_511,
|
||||||
|
ID_NEW_SLOT_512,
|
||||||
|
ID_NEW_SLOT_513,
|
||||||
|
ID_NEW_SLOT_514,
|
||||||
|
ID_NEW_SLOT_515,
|
||||||
|
ID_NEW_SLOT_516,
|
||||||
|
ID_NEW_SLOT_517,
|
||||||
|
ID_NEW_SLOT_518
|
||||||
} GAME_OBJECT_ID;
|
} GAME_OBJECT_ID;
|
||||||
|
|
|
@ -52,11 +52,14 @@
|
||||||
#define FloorData VAR_U_(0x00875168, __int16*)
|
#define FloorData VAR_U_(0x00875168, __int16*)
|
||||||
#define ObjectTextures VAR_U_(0x008751B0, OBJECT_TEXTURE*)
|
#define ObjectTextures VAR_U_(0x008751B0, OBJECT_TEXTURE*)
|
||||||
#define RoomLightsCount VAR_U_(0x0087B0EC, __int32)
|
#define RoomLightsCount VAR_U_(0x0087B0EC, __int32)
|
||||||
#define LevelDataPtr VAR_U_(0x00874964, char*)
|
//#define LevelDataPtr VAR_U_(0x00874964, char*)
|
||||||
#define NumberRooms VAR_U_(0x0087514C, __int16)
|
#define NumberRooms VAR_U_(0x0087514C, __int16)
|
||||||
#define nAnimUVRanges VAR_U_(0x0087495C, __int32)
|
#define nAnimUVRanges VAR_U_(0x0087495C, __int32)
|
||||||
#define LevelFilePtr VAR_U_(0x00875164, FILE*)
|
#define LevelFilePtr VAR_U_(0x00875164, FILE*)
|
||||||
//#define StaticObjects ARRAY_(0x00874988, STATIC_INFO, [70])
|
//#define StaticObjects ARRAY_(0x00874988, STATIC_INFO, [70])
|
||||||
|
#define NumberCameras VAR_U_(0x00EEFAC0, __int32)
|
||||||
|
#define Cameras VAR_U_(0x00EEF9A2, OBJECT_VECTOR*)
|
||||||
|
#define NumberSpotcams VAR_U_(0x00E4F428, __int32)
|
||||||
|
|
||||||
// Lara
|
// Lara
|
||||||
#define LaraItem VAR_U_(0x00E5BF08, ITEM_INFO*)
|
#define LaraItem VAR_U_(0x00E5BF08, ITEM_INFO*)
|
||||||
|
@ -122,8 +125,8 @@
|
||||||
#define AllStringsOffsets VAR_U_(0x00E5C2B8, __int16*)
|
#define AllStringsOffsets VAR_U_(0x00E5C2B8, __int16*)
|
||||||
|
|
||||||
#define RenderLoadBar VAR_U_(0x008FBDC0, __int32)
|
#define RenderLoadBar VAR_U_(0x008FBDC0, __int32)
|
||||||
#define IsLevelLoading VAR_U_(0x00874968, __int32)
|
//#define IsLevelLoading VAR_U_(0x00874968, __int32)
|
||||||
#define ThreadId VAR_U_(0x00874978, unsigned int)
|
//#define ThreadId VAR_U_(0x00874978, unsigned int)
|
||||||
#define WeatherType VAR_U_(0x00EEF4A0, byte)
|
#define WeatherType VAR_U_(0x00EEF4A0, byte)
|
||||||
#define CreditsDone VAR_U_(0x00E6D838, byte)
|
#define CreditsDone VAR_U_(0x00E6D838, byte)
|
||||||
#define CanLoad VAR_U_(0x0051CE54, byte)
|
#define CanLoad VAR_U_(0x0051CE54, byte)
|
||||||
|
|
|
@ -10,14 +10,37 @@ GameScript::GameScript(sol::state* lua)
|
||||||
{
|
{
|
||||||
m_lua = lua;
|
m_lua = lua;
|
||||||
|
|
||||||
|
// Add constants
|
||||||
(*m_lua)["HIT_POINTS"] = ITEM_PARAM_HIT_POINTS;
|
(*m_lua)["HIT_POINTS"] = ITEM_PARAM_HIT_POINTS;
|
||||||
(*m_lua)["CURRENT_ANIM_STATE"] = ITEM_PARAM_CURRENT_ANIM_STATE;
|
(*m_lua)["CURRENT_ANIM_STATE"] = ITEM_PARAM_CURRENT_ANIM_STATE;
|
||||||
(*m_lua)["ANIM_NUMBER"] = ITEM_PARAM_ANIM_NUMBER;
|
(*m_lua)["ANIM_NUMBER"] = ITEM_PARAM_ANIM_NUMBER;
|
||||||
|
(*m_lua)["GOAL_ANIM_STATE"] = ITEM_PARAM_GOAL_ANIM_STATE;
|
||||||
|
(*m_lua)["REQUIRED_ANIM_STATE"] = ITEM_PARAM_REQUIRED_ANIM_STATE;
|
||||||
|
(*m_lua)["FRAME_NUMBER"] = ITEM_PARAM_FRAME_NUMBER;
|
||||||
|
(*m_lua)["HIT_POINTS"] = ITEM_PARAM_HIT_POINTS;
|
||||||
|
(*m_lua)["HIT_STATUS"] = ITEM_PARAM_HIT_STATUS;
|
||||||
|
(*m_lua)["GRAVITY_STATUS"] = ITEM_PARAM_GRAVITY_STATUS;
|
||||||
|
(*m_lua)["COLLIDABLE"] = ITEM_PARAM_COLLIDABLE;
|
||||||
|
(*m_lua)["POISONED"] = ITEM_PARAM_POISONED;
|
||||||
|
(*m_lua)["ROOM_NUMBER"] = ITEM_PARAM_ROOM_NUMBER;
|
||||||
|
|
||||||
|
// Add the item type
|
||||||
|
m_lua->new_usertype<GameScriptItemPosition>("ItemPosition",
|
||||||
|
"x", &GameScriptItemPosition::x,
|
||||||
|
"y", &GameScriptItemPosition::y,
|
||||||
|
"z", &GameScriptItemPosition::z,
|
||||||
|
"xRot", &GameScriptItemPosition::xRot,
|
||||||
|
"yRot", &GameScriptItemPosition::yRot,
|
||||||
|
"zRot", &GameScriptItemPosition::zRot,
|
||||||
|
"room", &GameScriptItemPosition::room
|
||||||
|
);
|
||||||
|
|
||||||
m_lua->new_usertype<GameScriptItem>("Item",
|
m_lua->new_usertype<GameScriptItem>("Item",
|
||||||
sol::constructors<GameScriptItem(ITEM_INFO*)>(),
|
|
||||||
"Get", &GameScriptItem::Get,
|
"Get", &GameScriptItem::Get,
|
||||||
"Set", &GameScriptItem::Set
|
"Set", &GameScriptItem::Set,
|
||||||
|
"GetPosition", &GameScriptItem::GetItemPosition,
|
||||||
|
"SetPosition", &GameScriptItem::SetItemPosition,
|
||||||
|
"SetRotation", &GameScriptItem::SetItemRotation
|
||||||
);
|
);
|
||||||
|
|
||||||
// GameScript type
|
// GameScript type
|
||||||
|
@ -31,22 +54,16 @@ GameScript::GameScript(sol::state* lua)
|
||||||
"SetSecretsCount", &GameScript::SetSecretsCount,
|
"SetSecretsCount", &GameScript::SetSecretsCount,
|
||||||
"AddOneSecret", &GameScript::AddOneSecret,
|
"AddOneSecret", &GameScript::AddOneSecret,
|
||||||
"JumpToLevel", &GameScript::JumpToLevel,
|
"JumpToLevel", &GameScript::JumpToLevel,
|
||||||
"GetItem", &GameScript::GetItem
|
"GetItem", &GameScript::GetItem,
|
||||||
|
"PlaySoundEffect", &GameScript::PlaySoundEffect,
|
||||||
|
"PlaySoundEffectAtPosition", &GameScript::PlaySoundEffectAtPosition
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add global variables and namespaces
|
||||||
(*m_lua)["TR"] = this;
|
(*m_lua)["TR"] = this;
|
||||||
|
|
||||||
// DEBUG: just for testing
|
m_locals = (*m_lua).create_table("Locals");
|
||||||
LuaFunction* function = new LuaFunction();
|
m_globals = (*m_lua).create_table("Globals");
|
||||||
function->Name = "Trigger_0";
|
|
||||||
function->Code = "function Trigger_0() \n TR:EnableItem(2); \n TR:PlayAudioTrack(15); \n item = TR:GetItem(2); \n item:Set(HIT_POINTS, -16384); \n return true; \n end";
|
|
||||||
m_lua->script(function->Code);
|
|
||||||
Triggers.push_back(function);
|
|
||||||
|
|
||||||
m_itemsMap.insert(pair<__int16, __int16>(0, 0));
|
|
||||||
m_itemsMap.insert(pair<__int16, __int16>(9, 9));
|
|
||||||
m_itemsMap.insert(pair<__int16, __int16>(10, 10));
|
|
||||||
m_itemsMap.insert(pair<__int16, __int16>(2, 8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameScript::~GameScript()
|
GameScript::~GameScript()
|
||||||
|
@ -56,22 +73,32 @@ GameScript::~GameScript()
|
||||||
|
|
||||||
void GameScript::AddTrigger(LuaFunction* function)
|
void GameScript::AddTrigger(LuaFunction* function)
|
||||||
{
|
{
|
||||||
Triggers.push_back(function);
|
m_triggers.push_back(function);
|
||||||
(*m_lua).script(function->Code);
|
(*m_lua).script(function->Code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameScript::AddLuaId(int luaId, int itemId)
|
||||||
|
{
|
||||||
|
m_itemsMap.insert(pair<__int32, __int32>(luaId, itemId));
|
||||||
|
}
|
||||||
|
|
||||||
void GameScript::FreeLevelScripts()
|
void GameScript::FreeLevelScripts()
|
||||||
{
|
{
|
||||||
// Delete all triggers
|
// Delete all triggers
|
||||||
for (__int32 i = 0; i < Triggers.size(); i++)
|
for (__int32 i = 0; i < m_triggers.size(); i++)
|
||||||
{
|
{
|
||||||
LuaFunction* trigger = Triggers[i];
|
LuaFunction* trigger = m_triggers[i];
|
||||||
char* name = (char*)trigger->Name.c_str();
|
char* name = (char*)trigger->Name.c_str();
|
||||||
(*m_lua)[name] = NULL;
|
(*m_lua)[name] = NULL;
|
||||||
delete Triggers[i];
|
delete m_triggers[i];
|
||||||
}
|
}
|
||||||
|
m_triggers.clear();
|
||||||
|
|
||||||
Triggers.clear();
|
// Clear the items mapping
|
||||||
|
m_itemsMap.clear();
|
||||||
|
|
||||||
|
(*m_lua)["Lara"] = NULL;
|
||||||
|
//delete m_Lara;
|
||||||
}
|
}
|
||||||
|
|
||||||
string GameScript::loadScriptFromFile(char* luaFilename)
|
string GameScript::loadScriptFromFile(char* luaFilename)
|
||||||
|
@ -98,10 +125,10 @@ bool GameScript::ExecuteScript(char* luaFilename)
|
||||||
bool GameScript::ExecuteTrigger(__int16 index)
|
bool GameScript::ExecuteTrigger(__int16 index)
|
||||||
{
|
{
|
||||||
// Is this a valid trigger?
|
// Is this a valid trigger?
|
||||||
if (index >= Triggers.size())
|
if (index >= m_triggers.size())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
LuaFunction* trigger = Triggers[index];
|
LuaFunction* trigger = m_triggers[index];
|
||||||
|
|
||||||
// We want to execute a trigger just one time
|
// We want to execute a trigger just one time
|
||||||
// TODO: implement in the future continoous trigger?
|
// TODO: implement in the future continoous trigger?
|
||||||
|
@ -115,7 +142,16 @@ bool GameScript::ExecuteTrigger(__int16 index)
|
||||||
bool result = (*m_lua)[name]();
|
bool result = (*m_lua)[name]();
|
||||||
|
|
||||||
// Trigger was executed, don't execute it anymore
|
// Trigger was executed, don't execute it anymore
|
||||||
Triggers[index]->Executed = result;
|
trigger->Executed = result;
|
||||||
|
|
||||||
|
m_locals.for_each([&](sol::object const& key, sol::object const& value) {
|
||||||
|
if (value.is<bool>())
|
||||||
|
std::cout << key.as<string>() << " " << value.as<bool>() << std::endl;
|
||||||
|
else if (value.is<string>())
|
||||||
|
std::cout << key.as<string>() << " " << value.as<string>() << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << key.as<string>() << " " << value.as<int>() << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -259,13 +295,52 @@ void GameScript::MakeItemInvisible(__int16 id)
|
||||||
GameScriptItem GameScript::GetItem(__int16 id)
|
GameScriptItem GameScript::GetItem(__int16 id)
|
||||||
{
|
{
|
||||||
if (m_itemsMap.find(id) == m_itemsMap.end())
|
if (m_itemsMap.find(id) == m_itemsMap.end())
|
||||||
return NULL;
|
throw "Item not found";
|
||||||
|
|
||||||
__int16 itemNum = m_itemsMap[id];
|
__int16 itemNum = m_itemsMap[id];
|
||||||
ITEM_INFO* item = &Items[itemNum];
|
return m_items[itemNum];
|
||||||
GameScriptItem scriptItem = GameScriptItem(item);
|
}
|
||||||
|
|
||||||
return scriptItem;
|
void GameScript::PlaySoundEffectAtPosition(__int16 id, __int32 x, __int32 y, __int32 z, __int32 flags)
|
||||||
|
{
|
||||||
|
PHD_3DPOS pos;
|
||||||
|
|
||||||
|
pos.xPos = x;
|
||||||
|
pos.yPos = y;
|
||||||
|
pos.zPos = z;
|
||||||
|
pos.xRot = 0;
|
||||||
|
pos.yRot = 0;
|
||||||
|
pos.zRot = 0;
|
||||||
|
|
||||||
|
SoundEffect(id, &pos, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameScript::PlaySoundEffect(__int16 id, __int32 flags)
|
||||||
|
{
|
||||||
|
SoundEffect(id, NULL, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameScript::AssignVariables()
|
||||||
|
{
|
||||||
|
for (__int32 i = 0; i < NUM_ITEMS; i++)
|
||||||
|
m_items[i].NativeItem = NULL;
|
||||||
|
|
||||||
|
for (__int32 i = 0; i < NumItems; i++)
|
||||||
|
m_items[i].NativeItem = &Items[i];
|
||||||
|
|
||||||
|
(*m_lua)["Lara"] = m_items[Lara.itemNumber];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameScript::ResetVariables()
|
||||||
|
{
|
||||||
|
(*m_lua)["Lara"] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameScript::SetItem(__int32 index, ITEM_INFO* item)
|
||||||
|
{
|
||||||
|
if (index >= NUM_ITEMS)
|
||||||
|
return;
|
||||||
|
m_items[index].NativeItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameScript* g_GameScript;
|
GameScript* g_GameScript;
|
|
@ -20,6 +20,7 @@ using namespace std;
|
||||||
#define ITEM_PARAM_GRAVITY_STATUS 7
|
#define ITEM_PARAM_GRAVITY_STATUS 7
|
||||||
#define ITEM_PARAM_COLLIDABLE 8
|
#define ITEM_PARAM_COLLIDABLE 8
|
||||||
#define ITEM_PARAM_POISONED 9
|
#define ITEM_PARAM_POISONED 9
|
||||||
|
#define ITEM_PARAM_ROOM_NUMBER 10
|
||||||
|
|
||||||
typedef struct LuaFunction {
|
typedef struct LuaFunction {
|
||||||
string Name;
|
string Name;
|
||||||
|
@ -27,40 +28,48 @@ typedef struct LuaFunction {
|
||||||
bool Executed;
|
bool Executed;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct GameScriptItem {
|
typedef struct GameScriptItemPosition {
|
||||||
private:
|
__int32 x;
|
||||||
ITEM_INFO* m_item;
|
__int32 y;
|
||||||
|
__int32 z;
|
||||||
|
__int16 xRot;
|
||||||
|
__int16 yRot;
|
||||||
|
__int16 zRot;
|
||||||
|
__int16 room;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
typedef struct GameScriptItem {
|
||||||
GameScriptItem(ITEM_INFO* item)
|
ITEM_INFO* NativeItem;
|
||||||
{
|
|
||||||
m_item = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
__int16 Get(__int32 param)
|
__int16 Get(__int32 param)
|
||||||
{
|
{
|
||||||
|
if (NativeItem == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (param)
|
switch (param)
|
||||||
{
|
{
|
||||||
case ITEM_PARAM_CURRENT_ANIM_STATE:
|
case ITEM_PARAM_CURRENT_ANIM_STATE:
|
||||||
return m_item->currentAnimState;
|
return NativeItem->currentAnimState;
|
||||||
case ITEM_PARAM_REQUIRED_ANIM_STATE:
|
case ITEM_PARAM_REQUIRED_ANIM_STATE:
|
||||||
return m_item->requiredAnimState;
|
return NativeItem->requiredAnimState;
|
||||||
case ITEM_PARAM_GOAL_ANIM_STATE:
|
case ITEM_PARAM_GOAL_ANIM_STATE:
|
||||||
return m_item->goalAnimState;
|
return NativeItem->goalAnimState;
|
||||||
case ITEM_PARAM_ANIM_NUMBER:
|
case ITEM_PARAM_ANIM_NUMBER:
|
||||||
return m_item->animNumber;
|
return NativeItem->animNumber;
|
||||||
case ITEM_PARAM_FRAME_NUMBER:
|
case ITEM_PARAM_FRAME_NUMBER:
|
||||||
return m_item->frameNumber;
|
return NativeItem->frameNumber;
|
||||||
case ITEM_PARAM_HIT_POINTS:
|
case ITEM_PARAM_HIT_POINTS:
|
||||||
return m_item->hitPoints;
|
return NativeItem->hitPoints;
|
||||||
case ITEM_PARAM_HIT_STATUS:
|
case ITEM_PARAM_HIT_STATUS:
|
||||||
return m_item->hitStatus;
|
return NativeItem->hitStatus;
|
||||||
case ITEM_PARAM_GRAVITY_STATUS:
|
case ITEM_PARAM_GRAVITY_STATUS:
|
||||||
return m_item->gravityStatus;
|
return NativeItem->gravityStatus;
|
||||||
case ITEM_PARAM_COLLIDABLE:
|
case ITEM_PARAM_COLLIDABLE:
|
||||||
return m_item->collidable;
|
return NativeItem->collidable;
|
||||||
case ITEM_PARAM_POISONED:
|
case ITEM_PARAM_POISONED:
|
||||||
return m_item->poisoned;
|
return NativeItem->poisoned;
|
||||||
|
case ITEM_PARAM_ROOM_NUMBER:
|
||||||
|
return NativeItem->roomNumber;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -68,53 +77,102 @@ public:
|
||||||
|
|
||||||
void Set(__int32 param, __int16 value)
|
void Set(__int32 param, __int16 value)
|
||||||
{
|
{
|
||||||
|
if (NativeItem == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (param)
|
switch (param)
|
||||||
{
|
{
|
||||||
case ITEM_PARAM_CURRENT_ANIM_STATE:
|
case ITEM_PARAM_CURRENT_ANIM_STATE:
|
||||||
m_item->currentAnimState = value; break;
|
NativeItem->currentAnimState = value; break;
|
||||||
case ITEM_PARAM_REQUIRED_ANIM_STATE:
|
case ITEM_PARAM_REQUIRED_ANIM_STATE:
|
||||||
m_item->requiredAnimState = value; break;
|
NativeItem->requiredAnimState = value; break;
|
||||||
case ITEM_PARAM_GOAL_ANIM_STATE:
|
case ITEM_PARAM_GOAL_ANIM_STATE:
|
||||||
m_item->goalAnimState = value; break;
|
NativeItem->goalAnimState = value; break;
|
||||||
case ITEM_PARAM_ANIM_NUMBER:
|
case ITEM_PARAM_ANIM_NUMBER:
|
||||||
m_item->animNumber = value;
|
NativeItem->animNumber = value;
|
||||||
m_item->frameNumber = Anims[m_item->animNumber].frameBase;
|
NativeItem->frameNumber = Anims[NativeItem->animNumber].frameBase;
|
||||||
break;
|
break;
|
||||||
case ITEM_PARAM_FRAME_NUMBER:
|
case ITEM_PARAM_FRAME_NUMBER:
|
||||||
m_item->frameNumber = value; break;
|
NativeItem->frameNumber = value; break;
|
||||||
case ITEM_PARAM_HIT_POINTS:
|
case ITEM_PARAM_HIT_POINTS:
|
||||||
m_item->hitPoints = value; break;
|
NativeItem->hitPoints = value; break;
|
||||||
case ITEM_PARAM_HIT_STATUS:
|
case ITEM_PARAM_HIT_STATUS:
|
||||||
m_item->hitStatus = value; break;
|
NativeItem->hitStatus = value; break;
|
||||||
case ITEM_PARAM_GRAVITY_STATUS:
|
case ITEM_PARAM_GRAVITY_STATUS:
|
||||||
m_item->gravityStatus = value; break;
|
NativeItem->gravityStatus = value; break;
|
||||||
case ITEM_PARAM_COLLIDABLE:
|
case ITEM_PARAM_COLLIDABLE:
|
||||||
m_item->collidable = value; break;
|
NativeItem->collidable = value; break;
|
||||||
case ITEM_PARAM_POISONED:
|
case ITEM_PARAM_POISONED:
|
||||||
m_item->poisoned = value; break;
|
NativeItem->poisoned = value; break;
|
||||||
|
case ITEM_PARAM_ROOM_NUMBER:
|
||||||
|
NativeItem->roomNumber = value; break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameScriptItemPosition GetItemPosition()
|
||||||
|
{
|
||||||
|
GameScriptItemPosition pos;
|
||||||
|
|
||||||
|
//if (m_item == NULL)
|
||||||
|
// return pos;
|
||||||
|
|
||||||
|
pos.x = NativeItem->pos.xPos;
|
||||||
|
pos.y = NativeItem->pos.yPos;
|
||||||
|
pos.z = NativeItem->pos.zPos;
|
||||||
|
pos.xRot = TR_ANGLE_TO_DEGREES(NativeItem->pos.xRot);
|
||||||
|
pos.yRot = TR_ANGLE_TO_DEGREES(NativeItem->pos.yRot);
|
||||||
|
pos.zRot = TR_ANGLE_TO_DEGREES(NativeItem->pos.zRot);
|
||||||
|
pos.room = NativeItem->roomNumber;
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetItemPosition(__int32 x, __int32 y, __int32 z)
|
||||||
|
{
|
||||||
|
if (NativeItem == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
NativeItem->pos.xPos = x;
|
||||||
|
NativeItem->pos.yPos = y;
|
||||||
|
NativeItem->pos.zPos = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetItemRotation(__int32 x, __int32 y, __int32 z)
|
||||||
|
{
|
||||||
|
if (NativeItem == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
NativeItem->pos.xRot = ANGLE(x);
|
||||||
|
NativeItem->pos.yRot = ANGLE(y);
|
||||||
|
NativeItem->pos.zRot = ANGLE(z);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameScript
|
class GameScript
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
sol::state* m_lua;
|
sol::state* m_lua;
|
||||||
|
sol::table m_globals;
|
||||||
|
sol::table m_locals;
|
||||||
|
map<__int32, __int32> m_itemsMap;
|
||||||
|
vector<LuaFunction*> m_triggers;
|
||||||
|
GameScriptItem m_items[NUM_ITEMS];
|
||||||
|
|
||||||
string loadScriptFromFile(char* luaFilename);
|
string loadScriptFromFile(char* luaFilename);
|
||||||
map<__int16, __int16> m_itemsMap;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vector<LuaFunction*> Triggers;
|
|
||||||
|
|
||||||
GameScript(sol::state* lua);
|
GameScript(sol::state* lua);
|
||||||
~GameScript();
|
~GameScript();
|
||||||
|
|
||||||
bool ExecuteScript(char* luaFilename);
|
bool ExecuteScript(char* luaFilename);
|
||||||
void FreeLevelScripts();
|
void FreeLevelScripts();
|
||||||
void AddTrigger(LuaFunction* function);
|
void AddTrigger(LuaFunction* function);
|
||||||
|
void AddLuaId(int luaId, int itemId);
|
||||||
|
void SetItem(__int32 index, ITEM_INFO* item);
|
||||||
|
void AssignVariables();
|
||||||
|
void ResetVariables();
|
||||||
|
|
||||||
void EnableItem(__int16 id);
|
void EnableItem(__int16 id);
|
||||||
void DisableItem(__int16 id);
|
void DisableItem(__int16 id);
|
||||||
|
@ -127,4 +185,6 @@ public:
|
||||||
void AddOneSecret();
|
void AddOneSecret();
|
||||||
void MakeItemInvisible(__int16 id);
|
void MakeItemInvisible(__int16 id);
|
||||||
GameScriptItem GetItem(__int16 id);
|
GameScriptItem GetItem(__int16 id);
|
||||||
|
void PlaySoundEffectAtPosition(__int16 id, __int32 x, __int32 y, __int32 z, __int32 flags);
|
||||||
|
void PlaySoundEffect(__int16 id, __int32 flags);
|
||||||
};
|
};
|
84
TR5Main/Specific/IO/ChunkId.h
Normal file
84
TR5Main/Specific/IO/ChunkId.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "LEB128.h"
|
||||||
|
#include "Streams.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef struct ChunkId
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
byte* m_chunkBytes;
|
||||||
|
__int32 m_length;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChunkId(char* bytes, __int32 length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
m_chunkBytes = NULL;
|
||||||
|
m_length = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_chunkBytes = (byte*)malloc(length);
|
||||||
|
memcpy(m_chunkBytes, bytes, length);
|
||||||
|
m_length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ChunkId()
|
||||||
|
{
|
||||||
|
if (m_chunkBytes != NULL)
|
||||||
|
delete m_chunkBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChunkId* FromString(char* str)
|
||||||
|
{
|
||||||
|
return new ChunkId(str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChunkId* FromString(string* str)
|
||||||
|
{
|
||||||
|
return new ChunkId((char*)str->c_str(), str->length());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ChunkId* FromStream(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int32 idLength = LEB128::ReadInt32(stream);
|
||||||
|
char* buffer = (char*)malloc(idLength);
|
||||||
|
stream->Read(buffer, idLength);
|
||||||
|
ChunkId* chunk = new ChunkId(buffer, idLength);
|
||||||
|
free(buffer);
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToStream(BaseStream* stream)
|
||||||
|
{
|
||||||
|
LEB128::Write(stream, m_length);
|
||||||
|
stream->WriteBytes(m_chunkBytes, m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte* GetBytes()
|
||||||
|
{
|
||||||
|
return m_chunkBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int32 GetLength()
|
||||||
|
{
|
||||||
|
return m_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EqualsTo(ChunkId* other)
|
||||||
|
{
|
||||||
|
if (m_length != other->GetLength())
|
||||||
|
return false;
|
||||||
|
return (strncmp((const char*)m_chunkBytes, (const char*)other->GetBytes(), m_length) == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
144
TR5Main/Specific/IO/ChunkReader.h
Normal file
144
TR5Main/Specific/IO/ChunkReader.h
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "ChunkId.h"
|
||||||
|
#include "LEB128.h"
|
||||||
|
#include "Streams.h"
|
||||||
|
|
||||||
|
class ChunkReader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool m_isValid;
|
||||||
|
ChunkId* m_emptyChunk;
|
||||||
|
BaseStream* m_stream;
|
||||||
|
|
||||||
|
__int32 readInt32()
|
||||||
|
{
|
||||||
|
__int32 value = 0;
|
||||||
|
m_stream->Read(reinterpret_cast<char *>(&value), 4);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int16 readInt16()
|
||||||
|
{
|
||||||
|
__int16 value = 0;
|
||||||
|
m_stream->Read(reinterpret_cast<char *>(&value), 2);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChunkReader(__int32 expectedMagicNumber, BaseStream* stream)
|
||||||
|
{
|
||||||
|
m_isValid = false;
|
||||||
|
|
||||||
|
if (stream == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_stream = stream;
|
||||||
|
|
||||||
|
// Check the magic number
|
||||||
|
__int32 magicNumber = readInt32();
|
||||||
|
if (magicNumber != expectedMagicNumber)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: future use for compression
|
||||||
|
m_stream->Seek(4, SEEK_ORIGIN::CURRENT);
|
||||||
|
|
||||||
|
m_emptyChunk = new ChunkId(NULL, 0);
|
||||||
|
|
||||||
|
m_isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ChunkReader()
|
||||||
|
{
|
||||||
|
delete m_emptyChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChunkReader::IsValid()
|
||||||
|
{
|
||||||
|
return m_isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChunkReader::ReadChunks(bool(*func)(ChunkId* parentChunkId, __int32 maxSize))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ChunkId* chunkId = ChunkId::FromStream(m_stream);
|
||||||
|
if (chunkId->EqualsTo(m_emptyChunk)) // End reached
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Read up to a 64 bit number for the chunk size
|
||||||
|
__int64 chunkSize = LEB128::ReadLong(m_stream);
|
||||||
|
|
||||||
|
// Try loading chunk content
|
||||||
|
bool chunkRecognized = false;
|
||||||
|
__int32 startPos = m_stream->GetCurrentPosition();
|
||||||
|
|
||||||
|
chunkRecognized = func(chunkId, chunkSize);
|
||||||
|
__int32 readDataCount = m_stream->GetCurrentPosition() - startPos;
|
||||||
|
|
||||||
|
// Adjust _stream position if necessary
|
||||||
|
if (readDataCount != chunkSize)
|
||||||
|
m_stream->Seek(chunkSize, SEEK_ORIGIN::CURRENT);
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ReadChunkArrayOfBytes(__int64 length)
|
||||||
|
{
|
||||||
|
char* value = (char*)malloc(length);
|
||||||
|
m_stream->Read(value, length);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadChunkBool(__int64 length)
|
||||||
|
{
|
||||||
|
return (LEB128::ReadByte(m_stream) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int64 ReadChunkLong(__int64 length)
|
||||||
|
{
|
||||||
|
return LEB128::ReadLong(m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int32 ReadChunkInt32(__int64 length)
|
||||||
|
{
|
||||||
|
return LEB128::ReadInt32(m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned __int32 ReadChunkUInt32(__int64 length)
|
||||||
|
{
|
||||||
|
return LEB128::ReadUInt32(m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
__int16 ReadChunkInt16(__int64 length)
|
||||||
|
{
|
||||||
|
return LEB128::ReadInt16(m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned __int16 ReadChunkUInt16(__int64 length)
|
||||||
|
{
|
||||||
|
return LEB128::ReadUInt16(m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte ReadChunkByte(__int64 length)
|
||||||
|
{
|
||||||
|
return LEB128::ReadByte(m_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ReadChunkString(long length)
|
||||||
|
{
|
||||||
|
char* value = (char*)malloc(length);
|
||||||
|
memcpy(value, LevelDataPtr, length);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStream* GetRawStream()
|
||||||
|
{
|
||||||
|
return m_stream;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
109
TR5Main/Specific/IO/ChunkWriter.h
Normal file
109
TR5Main/Specific/IO/ChunkWriter.h
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Streams.h"
|
||||||
|
#include "LEB128.h"
|
||||||
|
#include "ChunkId.h"
|
||||||
|
|
||||||
|
typedef struct ChunkWritingState
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
BaseStream* m_stream;
|
||||||
|
__int64 m_chunkSizePosition;
|
||||||
|
__int64 m_previousPosition;
|
||||||
|
__int64 m_maximumSize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChunkWritingState(BaseStream* stream, ChunkId* chunkID, __int64 maximumSize)
|
||||||
|
{
|
||||||
|
m_stream = stream;
|
||||||
|
|
||||||
|
// Write chunk ID
|
||||||
|
chunkID->ToStream(m_stream);
|
||||||
|
|
||||||
|
// Write chunk size
|
||||||
|
m_chunkSizePosition = m_stream->GetCurrentPosition();
|
||||||
|
LEB128::Write(m_stream, 0, maximumSize);
|
||||||
|
|
||||||
|
// Prepare for writeing chunk content
|
||||||
|
m_previousPosition = m_stream->GetCurrentPosition();
|
||||||
|
m_maximumSize = maximumSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndWrite()
|
||||||
|
{
|
||||||
|
// Update chunk size
|
||||||
|
long newPosition = m_stream->GetCurrentPosition();
|
||||||
|
long chunkSize = newPosition - m_previousPosition;
|
||||||
|
m_stream->Seek(m_chunkSizePosition, SEEK_ORIGIN::BEGIN);
|
||||||
|
LEB128::Write(m_stream, chunkSize, m_maximumSize);
|
||||||
|
m_stream->Seek(newPosition, SEEK_ORIGIN::BEGIN);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ChunkWriter {
|
||||||
|
private:
|
||||||
|
BaseStream* m_stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChunkWriter(__int32 magicNumber, BaseStream* stream)
|
||||||
|
{
|
||||||
|
m_stream = stream;
|
||||||
|
|
||||||
|
__int32 value = 0;
|
||||||
|
|
||||||
|
m_stream->WriteInt32(&magicNumber);
|
||||||
|
m_stream->WriteInt32(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseStream* GetRawStream()
|
||||||
|
{
|
||||||
|
return m_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteChunkEnd()
|
||||||
|
{
|
||||||
|
byte value = 0;
|
||||||
|
m_stream->WriteByte(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteChunkEmpty(ChunkId* chunkID)
|
||||||
|
{
|
||||||
|
chunkID->ToStream(m_stream);
|
||||||
|
LEB128::Write(m_stream, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteChunkArrayOfBytes(ChunkId* chunkID, byte* value, __int32 length)
|
||||||
|
{
|
||||||
|
chunkID->ToStream(m_stream);
|
||||||
|
LEB128::Write(m_stream, length);
|
||||||
|
m_stream->WriteBytes(value, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteChunkInt(ChunkId* chunkID, __int64 value)
|
||||||
|
{
|
||||||
|
chunkID->ToStream(m_stream);
|
||||||
|
LEB128::Write(m_stream, LEB128::GetLength(m_stream, value));
|
||||||
|
LEB128::Write(m_stream, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkWritingState* WriteChunk(ChunkId* chunkID, __int64 maximumSize = LEB128::MaximumSize4Byte)
|
||||||
|
{
|
||||||
|
return new ChunkWritingState(m_stream, chunkID, maximumSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteChunk(ChunkId* chunkID, void(*writeChunk)(__int32), __int32 arg, __int64 maximumSize = LEB128::MaximumSize4Byte)
|
||||||
|
{
|
||||||
|
ChunkWritingState* state = WriteChunk(chunkID, maximumSize);
|
||||||
|
writeChunk(arg);
|
||||||
|
state->EndWrite();
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteChunkWithChildren(ChunkId* chunkID, void(*writeChunk)(__int32), __int32 arg, __int64 maximumSize = LEB128::MaximumSize4Byte)
|
||||||
|
{
|
||||||
|
ChunkWritingState* state = WriteChunk(chunkID, maximumSize);
|
||||||
|
writeChunk(arg);
|
||||||
|
WriteChunkEnd();
|
||||||
|
state->EndWrite();
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
};
|
116
TR5Main/Specific/IO/LEB128.h
Normal file
116
TR5Main/Specific/IO/LEB128.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "Streams.h"
|
||||||
|
|
||||||
|
extern char* LevelDataPtr;
|
||||||
|
|
||||||
|
typedef struct LEB128 {
|
||||||
|
static const __int64 MaximumSize1Byte = 64L - 1;
|
||||||
|
static const __int64 MaximumSize2Byte = 64L * 128 - 1;
|
||||||
|
static const __int64 MaximumSize3Byte = 64L * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize4Byte = 64L * 128 * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize5Byte = 64L * 128 * 128 * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize6Byte = 64L * 128 * 128 * 128 * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize7Byte = 64L * 128 * 128 * 128 * 128 * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize8Byte = 64L * 128 * 128 * 128 * 128 * 128 * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize9Byte = 64L * 128 * 128 * 128 * 128 * 128 * 128 * 128 * 128 - 1;
|
||||||
|
static const __int64 MaximumSize10Byte = UINT64_MAX;
|
||||||
|
|
||||||
|
static __int64 ReadLong(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int64 result = 0;
|
||||||
|
__int32 currentShift = 0;
|
||||||
|
|
||||||
|
byte currentByte;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
stream->Read(reinterpret_cast<char *>(¤tByte), 1);
|
||||||
|
|
||||||
|
result |= (__int64)(currentByte & 0x7F) << currentShift;
|
||||||
|
currentShift += 7;
|
||||||
|
} while ((currentByte & 0x80) != 0);
|
||||||
|
|
||||||
|
// Sign extend
|
||||||
|
__int32 shift = 64 - currentShift;
|
||||||
|
if (shift > 0)
|
||||||
|
result = (result << shift) >> shift;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __int32 ReadInt32(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int64 value = ReadLong(stream);
|
||||||
|
return (__int32)min(max(value, INT32_MIN), INT32_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __int16 ReadInt16(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int64 value = ReadLong(stream);
|
||||||
|
return (__int16)min(max(value, INT16_MIN), INT16_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte ReadByte(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int64 value = ReadLong(stream);
|
||||||
|
return (byte)min(max(value, 0), UINT8_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned __int32 ReadUInt32(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int64 value = ReadLong(stream);
|
||||||
|
return (unsigned __int32)min(max(value, 0), UINT32_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned __int16 ReadUInt16(BaseStream* stream)
|
||||||
|
{
|
||||||
|
__int64 value = ReadLong(stream);
|
||||||
|
return (unsigned __int16)min(max(value, 0), UINT16_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Write(BaseStream* stream, __int64 value, __int64 maximumSize)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Write byte
|
||||||
|
byte currentByte = ((byte)(value & 0x7F));
|
||||||
|
if (maximumSize >> 6 == 0 || maximumSize >> 6 == -1)
|
||||||
|
{
|
||||||
|
stream->WriteByte(¤tByte);
|
||||||
|
|
||||||
|
if (value >> 6 != 0 && value >> 6 != -1)
|
||||||
|
throw "Unable to write integer because the available space overflowed.";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte b = currentByte | 0x80;
|
||||||
|
stream->WriteByte(&b);
|
||||||
|
|
||||||
|
// Move data to next byte
|
||||||
|
value >>= 7;
|
||||||
|
maximumSize >>= 7;
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Write(BaseStream* stream, __int64 value)
|
||||||
|
{
|
||||||
|
Write(stream, value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __int32 GetLength(BaseStream* stream, __int64 value)
|
||||||
|
{
|
||||||
|
__int32 length = 1;
|
||||||
|
value >>= 6;
|
||||||
|
while (value > 0)
|
||||||
|
{
|
||||||
|
value >>= 7;
|
||||||
|
length += 1;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
200
TR5Main/Specific/IO/Streams.h
Normal file
200
TR5Main/Specific/IO/Streams.h
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
enum SEEK_ORIGIN {
|
||||||
|
BEGIN,
|
||||||
|
CURRENT
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseStream {
|
||||||
|
public:
|
||||||
|
virtual bool Read(char* buffer, __int32 length) = 0;
|
||||||
|
virtual bool Write(char* buffer, __int32 length) = 0;
|
||||||
|
virtual __int32 GetCurrentPosition() = 0;
|
||||||
|
virtual bool Seek(__int32 seek, SEEK_ORIGIN origin) = 0;
|
||||||
|
virtual bool IsEOF() = 0;
|
||||||
|
virtual bool Close() = 0;
|
||||||
|
|
||||||
|
bool ReadBytes(byte* value, __int32 length)
|
||||||
|
{
|
||||||
|
return Read(reinterpret_cast<char*>(value), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadByte(byte* value)
|
||||||
|
{
|
||||||
|
return Read(reinterpret_cast<char*>(value), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadInt16(__int16* value)
|
||||||
|
{
|
||||||
|
return Read(reinterpret_cast<char*>(value), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadInt32(__int32* value)
|
||||||
|
{
|
||||||
|
return Read(reinterpret_cast<char*>(value), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadString(char** value)
|
||||||
|
{
|
||||||
|
__int32 length;
|
||||||
|
ReadInt32(&length);
|
||||||
|
*value = (char*)malloc(length + 1);
|
||||||
|
Read(*value, length);
|
||||||
|
(*value)[length] = NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteBytes(byte* value, __int32 length)
|
||||||
|
{
|
||||||
|
return Write(reinterpret_cast<char*>(value), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteByte(byte* value)
|
||||||
|
{
|
||||||
|
return Write(reinterpret_cast<char*>(value), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteInt16(__int16* value)
|
||||||
|
{
|
||||||
|
return Write(reinterpret_cast<char*>(value), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteInt32(__int32* value)
|
||||||
|
{
|
||||||
|
return Write(reinterpret_cast<char*>(value), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteString(char* str)
|
||||||
|
{
|
||||||
|
__int32 length = (__int32)strlen(str);
|
||||||
|
WriteInt32(&length);
|
||||||
|
Write(str, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemoryStream : public BaseStream {
|
||||||
|
private:
|
||||||
|
char* m_startBuffer;
|
||||||
|
char* m_buffer;
|
||||||
|
__int32 m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryStream(char* buffer, __int32 size)
|
||||||
|
{
|
||||||
|
m_buffer = (char*)malloc(size);
|
||||||
|
m_startBuffer = m_buffer;
|
||||||
|
memcpy(m_buffer, buffer, size);
|
||||||
|
m_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryStream(__int32 size)
|
||||||
|
{
|
||||||
|
m_buffer = (char*)malloc(size);
|
||||||
|
m_startBuffer = m_buffer;
|
||||||
|
m_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
~MemoryStream()
|
||||||
|
{
|
||||||
|
free(m_startBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Read(char* buffer, __int32 length)
|
||||||
|
{
|
||||||
|
memcpy(buffer, m_buffer, length);
|
||||||
|
m_buffer += length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Write(char* buffer, __int32 length)
|
||||||
|
{
|
||||||
|
memcpy(m_buffer, buffer, length);
|
||||||
|
m_buffer += length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int32 GetCurrentPosition()
|
||||||
|
{
|
||||||
|
return (m_buffer - m_startBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Seek(__int32 seek, SEEK_ORIGIN origin)
|
||||||
|
{
|
||||||
|
if (origin == SEEK_ORIGIN::BEGIN)
|
||||||
|
m_buffer = m_startBuffer + seek;
|
||||||
|
else
|
||||||
|
m_buffer += seek;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEOF()
|
||||||
|
{
|
||||||
|
return (GetCurrentPosition() > m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Close()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileStream : public BaseStream {
|
||||||
|
private:
|
||||||
|
fstream m_stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileStream(char* fileName)
|
||||||
|
{
|
||||||
|
m_stream.open(fileName, fstream::in | fstream::out | fstream::trunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
~FileStream()
|
||||||
|
{
|
||||||
|
m_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Read(char* buffer, __int32 length)
|
||||||
|
{
|
||||||
|
m_stream.read(buffer, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Write(char* buffer, __int32 length)
|
||||||
|
{
|
||||||
|
m_stream.write(buffer, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
__int32 GetCurrentPosition()
|
||||||
|
{
|
||||||
|
return (__int32)(m_stream.tellg());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Seek(__int32 seek, SEEK_ORIGIN origin)
|
||||||
|
{
|
||||||
|
m_stream.seekg(seek, (origin == SEEK_ORIGIN::BEGIN ? m_stream.beg : m_stream.cur));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEOF()
|
||||||
|
{
|
||||||
|
return (m_stream.eof());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Close()
|
||||||
|
{
|
||||||
|
m_stream.flush();
|
||||||
|
m_stream.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
#include "patch.h"
|
#include "patch.h"
|
||||||
#include "..\Global\global.h"1
|
#include "..\Global\global.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "roomload.h"
|
||||||
|
|
||||||
// Remapped variables. Some variables must be moved from EXE space to DLL space for having free space for bigger arrays
|
// Remapped variables. Some variables must be moved from EXE space to DLL space for having free space for bigger arrays
|
||||||
__int32 NumItems;
|
__int32 NumItems;
|
||||||
|
@ -97,6 +98,106 @@ void PatchGameCode()
|
||||||
newValue = (__int32)&StaticObjects[0] + 16;
|
newValue = (__int32)&StaticObjects[0] + 16;
|
||||||
WriteProcessMemory(gameHandle, (LPVOID)0x4192B0, &newValue, 4, NULL); // ObjectOnLOS2
|
WriteProcessMemory(gameHandle, (LPVOID)0x4192B0, &newValue, 4, NULL); // ObjectOnLOS2
|
||||||
|
|
||||||
//newValue = 0xFF;
|
// Move LevelDataPtr for having more space for Objects[]
|
||||||
//WriteProcessMemory(gameHandle, (LPVOID)0x004A7385, &newValue, 4, NULL); // ObjectOnLOS2
|
newValue = (__int32)&LevelDataPtr;
|
||||||
|
|
||||||
|
// LoadRooms
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004916C4, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004916CE, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004916DA, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x00491706, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x00491710, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x0049171B, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x00491726, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x00491745, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x0049175B, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadRooms
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A4DCF, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A4DDA, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A4DEA, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A4E0C, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A4E1C, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadSprites
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A59E2, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A59EC, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A59F6, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5A20, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5A4B, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5B61, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5B6E, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5B8C, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5B9D, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5BBF, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5BE4, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5BF7, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadSoundEffects
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5D9D, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5DB5, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5DE2, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5E08, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5E13, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadBoxes
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5E62, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5E6E, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5E8D, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5EB2, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5EBA, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5EC4, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5ED3, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5EF7, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5F04, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5F26, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5F4D, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5F5C, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5F79, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5F9F, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A5FAE, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
//LoadAnimatedTextures
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6061, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6070, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A607F, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A609E, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A60A7, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A60B3, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadTextureInfos
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A60F1, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A60F9, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A610B, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A613D, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6159, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// Sub_4A6760
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6761, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6771, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A677C, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A679B, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A67A4, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadDemoData
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A67D1, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A67D9, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadAIObjects
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A67F2, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A67FF, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A681E, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A683D, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6846, &newValue, 4, NULL);
|
||||||
|
|
||||||
|
// LoadSamples
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A689F, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A68B2, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A68BC, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A68D4, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6913, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6939, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A6941, &newValue, 4, NULL);
|
||||||
|
WriteProcessMemory(gameHandle, (LPVOID)0x004A694D, &newValue, 4, NULL);
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,11 +4,23 @@
|
||||||
#include "..\Specific\setup.h"
|
#include "..\Specific\setup.h"
|
||||||
#include "..\Game\draw.h"
|
#include "..\Game\draw.h"
|
||||||
#include "..\Game\lot.h"
|
#include "..\Game\lot.h"
|
||||||
|
#include "..\Game\savegame.h"
|
||||||
|
|
||||||
|
#include "IO/ChunkId.h"
|
||||||
|
#include "IO/ChunkReader.h"
|
||||||
|
#include "IO/ChunkWriter.h"
|
||||||
|
#include "IO/LEB128.h"
|
||||||
|
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "IO/Streams.h"
|
||||||
|
|
||||||
|
ChunkId* ChunkTriggersList = ChunkId::FromString("Tr5Triggers");
|
||||||
|
ChunkId* ChunkTrigger = ChunkId::FromString("Tr5Trigger");
|
||||||
|
ChunkId* ChunkLuaIds = ChunkId::FromString("Tr5LuaIds");
|
||||||
|
ChunkId* ChunkLuaId = ChunkId::FromString("Tr5LuaId");
|
||||||
|
|
||||||
extern GameScript* g_GameScript;
|
extern GameScript* g_GameScript;
|
||||||
|
|
||||||
|
@ -25,6 +37,8 @@ __int32 NumMeshPointers;
|
||||||
__int32 NumObjectTextures;
|
__int32 NumObjectTextures;
|
||||||
|
|
||||||
uintptr_t hLoadLevel;
|
uintptr_t hLoadLevel;
|
||||||
|
unsigned __int32 ThreadId;
|
||||||
|
__int32 IsLevelLoading;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -33,6 +47,9 @@ vector<__int32> StaticObjectsIds;
|
||||||
|
|
||||||
extern GameFlow* g_GameFlow;
|
extern GameFlow* g_GameFlow;
|
||||||
extern __int16 LaraVehicle;
|
extern __int16 LaraVehicle;
|
||||||
|
char* LevelDataPtr;
|
||||||
|
|
||||||
|
ChunkReader* chunkIO;
|
||||||
|
|
||||||
__int16 ReadInt16()
|
__int16 ReadInt16()
|
||||||
{
|
{
|
||||||
|
@ -287,6 +304,23 @@ void __cdecl LoadObjects()
|
||||||
MoveablesIds.push_back(ID_DEFAULT_SPRITES);
|
MoveablesIds.push_back(ID_DEFAULT_SPRITES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __cdecl LoadCameras()
|
||||||
|
{
|
||||||
|
NumberCameras = ReadInt32();
|
||||||
|
if (NumberCameras != 0)
|
||||||
|
{
|
||||||
|
Cameras = (OBJECT_VECTOR*)GameMalloc(NumberCameras * sizeof(OBJECT_VECTOR));
|
||||||
|
ReadBytes(Cameras, NumberCameras * sizeof(OBJECT_VECTOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberSpotcams = ReadInt32();
|
||||||
|
|
||||||
|
if (NumberSpotcams != 0)
|
||||||
|
{
|
||||||
|
ReadBytes(SpotCam, NumberSpotcams * sizeof(SPOTCAM));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __cdecl LoadTextures()
|
void __cdecl LoadTextures()
|
||||||
{
|
{
|
||||||
DB_Log(2, "LoadTextures - DLL");
|
DB_Log(2, "LoadTextures - DLL");
|
||||||
|
@ -422,6 +456,7 @@ void __cdecl FreeLevel()
|
||||||
MallocPtr = MallocBuffer;
|
MallocPtr = MallocBuffer;
|
||||||
MallocFree = MallocSize;
|
MallocFree = MallocSize;
|
||||||
g_Renderer->FreeRendererData();
|
g_Renderer->FreeRendererData();
|
||||||
|
g_GameScript->FreeLevelScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned __stdcall LoadLevel(void* data)
|
unsigned __stdcall LoadLevel(void* data)
|
||||||
|
@ -480,8 +515,19 @@ unsigned __stdcall LoadLevel(void* data)
|
||||||
LoadDemoData();
|
LoadDemoData();
|
||||||
LoadSamples();
|
LoadSamples();
|
||||||
|
|
||||||
LoadNewData();
|
__int32 extraSize = 0;
|
||||||
|
ReadFileEx(&extraSize, 1, 4, LevelFilePtr);
|
||||||
|
if (extraSize > 0)
|
||||||
|
{
|
||||||
|
ReadFileEx(&extraSize, 1, 4, LevelFilePtr);
|
||||||
|
//free(LevelDataPtr);
|
||||||
|
LevelDataPtr = (char*)malloc(extraSize);
|
||||||
|
ReadFileEx(LevelDataPtr, extraSize, 1, LevelFilePtr);
|
||||||
|
|
||||||
|
LoadNewData(extraSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//free(LevelDataPtr);
|
||||||
LevelDataPtr = NULL;
|
LevelDataPtr = NULL;
|
||||||
FileClose(LevelFilePtr);
|
FileClose(LevelFilePtr);
|
||||||
}
|
}
|
||||||
|
@ -506,6 +552,7 @@ unsigned __stdcall LoadLevel(void* data)
|
||||||
SeedRandomDraw(0xD371F947);
|
SeedRandomDraw(0xD371F947);
|
||||||
SeedRandomControl(0xD371F947);
|
SeedRandomControl(0xD371F947);
|
||||||
LaraVehicle = -1;
|
LaraVehicle = -1;
|
||||||
|
g_GameScript->AssignVariables();
|
||||||
|
|
||||||
// Level loaded
|
// Level loaded
|
||||||
IsLevelLoading = false;
|
IsLevelLoading = false;
|
||||||
|
@ -545,32 +592,33 @@ void __cdecl AdjustUV(__int32 num)
|
||||||
NumObjectTextures = num;
|
NumObjectTextures = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cdecl LoadNewData()
|
bool __cdecl ReadLuaIds(ChunkId* chunkId, __int32 maxSize)
|
||||||
{
|
{
|
||||||
// Free old level scripts
|
if (chunkId->EqualsTo(ChunkLuaId))
|
||||||
g_GameScript->FreeLevelScripts();
|
|
||||||
|
|
||||||
// Check for magic word
|
|
||||||
__int32 magicWord;
|
|
||||||
ReadFileEx(&magicWord, 1, 4, LevelFilePtr);
|
|
||||||
if (magicWord != 0x5455354D)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Load LUA triggers
|
|
||||||
__int32 numTriggers;
|
|
||||||
ReadFileEx(&numTriggers, 1, 4, LevelFilePtr);
|
|
||||||
for (__int32 i = 0; i < numTriggers; i++)
|
|
||||||
{
|
{
|
||||||
__int32 strSize;
|
__int32 luaId = 0;
|
||||||
ReadFileEx(&strSize, 1, 4, LevelFilePtr);
|
chunkIO->GetRawStream()->ReadInt32(&luaId);
|
||||||
char* functionName = (char*)malloc(strSize + 1);
|
|
||||||
ZeroMemory(functionName, strSize + 1);
|
|
||||||
ReadFileEx(functionName, strSize, 1, LevelFilePtr);
|
|
||||||
|
|
||||||
ReadFileEx(&strSize, 1, 4, LevelFilePtr);
|
__int32 itemId = 0;
|
||||||
char* functionCode = (char*)malloc(strSize + 1);
|
chunkIO->GetRawStream()->ReadInt32(&itemId);
|
||||||
ZeroMemory(functionCode, strSize + 1);
|
|
||||||
ReadFileEx(functionCode, strSize, 1, LevelFilePtr);
|
g_GameScript->AddLuaId(luaId, itemId);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __cdecl ReadLuaTriggers(ChunkId* chunkId, __int32 maxSize)
|
||||||
|
{
|
||||||
|
if (chunkId->EqualsTo(ChunkTrigger))
|
||||||
|
{
|
||||||
|
char* functionName = NULL;
|
||||||
|
chunkIO->GetRawStream()->ReadString(&functionName);
|
||||||
|
|
||||||
|
char* functionCode = NULL;
|
||||||
|
chunkIO->GetRawStream()->ReadString(&functionCode);
|
||||||
|
|
||||||
LuaFunction* function = new LuaFunction();
|
LuaFunction* function = new LuaFunction();
|
||||||
function->Name = string(functionName);
|
function->Name = string(functionName);
|
||||||
|
@ -581,7 +629,51 @@ void __cdecl LoadNewData()
|
||||||
|
|
||||||
delete functionName;
|
delete functionName;
|
||||||
delete functionCode;
|
delete functionCode;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __cdecl ReadNewDataChunks(ChunkId* chunkId, __int32 maxSize)
|
||||||
|
{
|
||||||
|
if (chunkId->EqualsTo(ChunkTriggersList))
|
||||||
|
return chunkIO->ReadChunks(ReadLuaTriggers);
|
||||||
|
else if (chunkId->EqualsTo(ChunkLuaIds))
|
||||||
|
return chunkIO->ReadChunks(ReadLuaIds);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ChunkWriter* writer;
|
||||||
|
|
||||||
|
void __cdecl SaveTest()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl LoadNewData(__int32 size)
|
||||||
|
{
|
||||||
|
// Free old level scripts
|
||||||
|
//g_GameScript->FreeLevelScripts();
|
||||||
|
MemoryStream stream(LevelDataPtr, size);
|
||||||
|
chunkIO = new ChunkReader(0x4D355254, &stream);
|
||||||
|
if (!chunkIO->IsValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
chunkIO->ReadChunks(ReadNewDataChunks);
|
||||||
|
|
||||||
|
/*ChunkId* testChunkId = ChunkId::FromString("TR5MSavItems");
|
||||||
|
FileStream fs("H:\\test.sav");
|
||||||
|
writer = new ChunkWriter(0x4D355254, &fs);
|
||||||
|
writer->WriteChunkInt(testChunkId, 1234);
|
||||||
|
fs.Close();*/
|
||||||
|
|
||||||
|
SaveGame::Save((char*)"H:\\test.sav");
|
||||||
|
|
||||||
|
/*SaveGame* sg = new SaveGame();
|
||||||
|
sg->Save("H:\\test.sav");
|
||||||
|
delete sg;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inject_RoomLoad()
|
void Inject_RoomLoad()
|
||||||
|
@ -593,4 +685,5 @@ void Inject_RoomLoad()
|
||||||
INJECT(0x0040130C, S_LoadLevelFile);
|
INJECT(0x0040130C, S_LoadLevelFile);
|
||||||
INJECT(0x004A7130, FreeLevel);
|
INJECT(0x004A7130, FreeLevel);
|
||||||
INJECT(0x004A5430, AdjustUV);
|
INJECT(0x004A5430, AdjustUV);
|
||||||
|
INJECT(0x004A5CA0, LoadCameras);
|
||||||
}
|
}
|
|
@ -5,6 +5,13 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "IO/ChunkId.h"
|
||||||
|
#include "IO/ChunkReader.h"
|
||||||
|
#include "IO/LEB128.h"
|
||||||
|
|
||||||
|
struct ChunkId;
|
||||||
|
struct LEB128;
|
||||||
|
|
||||||
#define DoSomethingWithRooms ((void (__cdecl*)()) 0x004774D0)
|
#define DoSomethingWithRooms ((void (__cdecl*)()) 0x004774D0)
|
||||||
#define FreeItemsStuff ((void (__cdecl*)(__int32)) 0x00440590)
|
#define FreeItemsStuff ((void (__cdecl*)(__int32)) 0x00440590)
|
||||||
#define InitialiseClosedDoors ((void (__cdecl*)()) 0x00473600)
|
#define InitialiseClosedDoors ((void (__cdecl*)()) 0x00473600)
|
||||||
|
@ -17,7 +24,7 @@
|
||||||
#define FileOpen ((FILE* (__cdecl*)(char*)) 0x004A3CD0)
|
#define FileOpen ((FILE* (__cdecl*)(char*)) 0x004A3CD0)
|
||||||
#define FileClose ((void (__cdecl*)(FILE*)) 0x004A3DA0)
|
#define FileClose ((void (__cdecl*)(FILE*)) 0x004A3DA0)
|
||||||
#define LoadSprites ((void (__cdecl*)()) 0x004A59D0)
|
#define LoadSprites ((void (__cdecl*)()) 0x004A59D0)
|
||||||
#define LoadCameras ((void (__cdecl*)()) 0x004A5CA0)
|
//#define LoadCameras ((void (__cdecl*)()) 0x004A5CA0)
|
||||||
#define LoadSoundEffects ((void (__cdecl*)()) 0x004A5D90)
|
#define LoadSoundEffects ((void (__cdecl*)()) 0x004A5D90)
|
||||||
#define LoadBoxes ((void (__cdecl*)()) 0x004A5E50)
|
#define LoadBoxes ((void (__cdecl*)()) 0x004A5E50)
|
||||||
#define LoadAnimatedTextures ((void (__cdecl*)()) 0x004A6060)
|
#define LoadAnimatedTextures ((void (__cdecl*)()) 0x004A6060)
|
||||||
|
@ -53,6 +60,7 @@ extern vector<__int32> StaticObjectsIds;
|
||||||
extern __int32* RawMeshPointers;
|
extern __int32* RawMeshPointers;
|
||||||
extern __int16* RawMeshData;
|
extern __int16* RawMeshData;
|
||||||
extern __int32 NumObjectTextures;
|
extern __int32 NumObjectTextures;
|
||||||
|
extern char* LevelDataPtr;
|
||||||
|
|
||||||
void __cdecl LoadTextures();
|
void __cdecl LoadTextures();
|
||||||
__int32 __cdecl LoadRoomsNew();
|
__int32 __cdecl LoadRoomsNew();
|
||||||
|
@ -61,8 +69,14 @@ void __cdecl LoadObjects();
|
||||||
__int32 __cdecl S_LoadLevelFile(__int32 levelIndex);
|
__int32 __cdecl S_LoadLevelFile(__int32 levelIndex);
|
||||||
void __cdecl FreeLevel();
|
void __cdecl FreeLevel();
|
||||||
void __cdecl AdjustUV(__int32 num);
|
void __cdecl AdjustUV(__int32 num);
|
||||||
void __cdecl LoadNewData();
|
void __cdecl LoadCameras();
|
||||||
|
|
||||||
unsigned __stdcall LoadLevel(void* data);
|
unsigned __stdcall LoadLevel(void* data);
|
||||||
|
|
||||||
|
// New functions for loading data from TR5M footer
|
||||||
|
bool __cdecl ReadLuaIds(ChunkId* chunkId, __int32 maxSize);
|
||||||
|
bool __cdecl ReadLuaTriggers(ChunkId* chunkId, __int32 maxSize);
|
||||||
|
bool __cdecl ReadNewDataChunks(ChunkId* chunkId, __int32 maxSize);
|
||||||
|
void __cdecl LoadNewData(__int32 size);
|
||||||
|
|
||||||
void Inject_RoomLoad();
|
void Inject_RoomLoad();
|
|
@ -169,6 +169,10 @@ xcopy /Y "$(ProjectDir)Scripting\Scripts\*.lua" "$(TargetDir)\Scripts"</Command>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Specific\IO\ChunkId.h" />
|
||||||
|
<ClInclude Include="Specific\IO\ChunkWriter.h" />
|
||||||
|
<ClInclude Include="Specific\IO\LEB128.h" />
|
||||||
|
<ClInclude Include="Specific\IO\ChunkReader.h" />
|
||||||
<ClInclude Include="CustomObjects\bear.h" />
|
<ClInclude Include="CustomObjects\bear.h" />
|
||||||
<ClInclude Include="CustomObjects\customtraps.h" />
|
<ClInclude Include="CustomObjects\customtraps.h" />
|
||||||
<ClInclude Include="CustomObjects\dino.h" />
|
<ClInclude Include="CustomObjects\dino.h" />
|
||||||
|
@ -259,6 +263,7 @@ xcopy /Y "$(ProjectDir)Scripting\Scripts\*.lua" "$(TargetDir)\Scripts"</Command>
|
||||||
<ClInclude Include="Specific\directx.h" />
|
<ClInclude Include="Specific\directx.h" />
|
||||||
<ClInclude Include="Specific\init.h" />
|
<ClInclude Include="Specific\init.h" />
|
||||||
<ClInclude Include="Specific\input.h" />
|
<ClInclude Include="Specific\input.h" />
|
||||||
|
<ClInclude Include="Specific\IO\Streams.h" />
|
||||||
<ClInclude Include="Specific\patch.h" />
|
<ClInclude Include="Specific\patch.h" />
|
||||||
<ClInclude Include="Specific\roomload.h" />
|
<ClInclude Include="Specific\roomload.h" />
|
||||||
<ClInclude Include="Specific\setup.h" />
|
<ClInclude Include="Specific\setup.h" />
|
||||||
|
|
|
@ -300,6 +300,21 @@
|
||||||
<ClInclude Include="Scripting\GameLogicScript.h">
|
<ClInclude Include="Scripting\GameLogicScript.h">
|
||||||
<Filter>File di intestazione</Filter>
|
<Filter>File di intestazione</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Specific\IO\ChunkReader.h">
|
||||||
|
<Filter>File di intestazione</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Specific\IO\LEB128.h">
|
||||||
|
<Filter>File di intestazione</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Specific\IO\ChunkId.h">
|
||||||
|
<Filter>File di intestazione</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Specific\IO\Streams.h">
|
||||||
|
<Filter>File di intestazione</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Specific\IO\ChunkWriter.h">
|
||||||
|
<Filter>File di intestazione</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="TR5Main.cpp">
|
<ClCompile Include="TR5Main.cpp">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue