mirror of
https://github.com/isledecomp/isle.git
synced 2024-11-26 09:38:14 -05:00
100% match of many functions in the LegoGameState::Save codepath (#86)
* Only include decomps * One more function * Add offset to endOfVariables * Remove leftover header * Use undefined where applicable * Fixes, refactorings * Fixes * Fix calling convention * Added offset comment --------- Co-authored-by: Christian Semmler <mail@csemmler.com>
This commit is contained in:
parent
49ec7364c2
commit
91c3ed3e70
16 changed files with 489 additions and 40 deletions
|
@ -74,6 +74,7 @@ add_library(lego1 SHARED
|
||||||
LEGO1/legolocomotionanimpresenter.cpp
|
LEGO1/legolocomotionanimpresenter.cpp
|
||||||
LEGO1/legomodelpresenter.cpp
|
LEGO1/legomodelpresenter.cpp
|
||||||
LEGO1/legonavcontroller.cpp
|
LEGO1/legonavcontroller.cpp
|
||||||
|
LEGO1/legoobjectfactory.cpp
|
||||||
LEGO1/legoomni.cpp
|
LEGO1/legoomni.cpp
|
||||||
LEGO1/legopalettepresenter.cpp
|
LEGO1/legopalettepresenter.cpp
|
||||||
LEGO1/legopartpresenter.cpp
|
LEGO1/legopartpresenter.cpp
|
||||||
|
@ -89,6 +90,7 @@ add_library(lego1 SHARED
|
||||||
LEGO1/legostream.cpp
|
LEGO1/legostream.cpp
|
||||||
LEGO1/legotexturepresenter.cpp
|
LEGO1/legotexturepresenter.cpp
|
||||||
LEGO1/legoutil.cpp
|
LEGO1/legoutil.cpp
|
||||||
|
LEGO1/legounksavedatawriter.cpp
|
||||||
LEGO1/legovideomanager.cpp
|
LEGO1/legovideomanager.cpp
|
||||||
LEGO1/legoworld.cpp
|
LEGO1/legoworld.cpp
|
||||||
LEGO1/legoworldpresenter.cpp
|
LEGO1/legoworldpresenter.cpp
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "infocenterstate.h"
|
#include "infocenterstate.h"
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(InfocenterState, 0x94);
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10071600 STUB
|
// OFFSET: LEGO1 0x10071600 STUB
|
||||||
InfocenterState::InfocenterState()
|
InfocenterState::InfocenterState()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "legostate.h"
|
#include "legostate.h"
|
||||||
|
|
||||||
|
#include "decomp.h"
|
||||||
|
|
||||||
// VTABLE 0x100d93a8
|
// VTABLE 0x100d93a8
|
||||||
// SIZE 0x94
|
// SIZE 0x94
|
||||||
class InfocenterState : public LegoState
|
class InfocenterState : public LegoState
|
||||||
|
@ -23,6 +25,40 @@ class InfocenterState : public LegoState
|
||||||
{
|
{
|
||||||
return !strcmp(name, InfocenterState::ClassName()) || LegoState::IsA(name);
|
return !strcmp(name, InfocenterState::ClassName()) || LegoState::IsA(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline MxU32 GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Members should be renamed with their offsets before use
|
||||||
|
/*
|
||||||
|
struct SomeStruct
|
||||||
|
{
|
||||||
|
undefined4 unk1;
|
||||||
|
undefined2 unk2;
|
||||||
|
undefined2 unk3;
|
||||||
|
undefined2 unk4;
|
||||||
|
};
|
||||||
|
|
||||||
|
undefined2 unk1;
|
||||||
|
undefined2 unk2;
|
||||||
|
undefined4 unk3;
|
||||||
|
undefined4 padding1;
|
||||||
|
void *unk4;
|
||||||
|
undefined2 unk5;
|
||||||
|
undefined2 unk6;
|
||||||
|
undefined2 unk7;
|
||||||
|
undefined2 padding2;
|
||||||
|
void *unk8;
|
||||||
|
undefined2 unk9;
|
||||||
|
undefined2 unk10;
|
||||||
|
undefined2 unk11;
|
||||||
|
undefined2 padding3;
|
||||||
|
SomeStruct unk12[6];
|
||||||
|
undefined4 unk13;
|
||||||
|
*/
|
||||||
|
|
||||||
|
undefined pad[0x70];
|
||||||
|
MxU32 m_buffer[7]; // 0x78
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INFOCENTERSTATE_H
|
#endif // INFOCENTERSTATE_H
|
||||||
|
|
|
@ -1,17 +1,77 @@
|
||||||
#include "legogamestate.h"
|
#include "legogamestate.h"
|
||||||
|
|
||||||
#include "legoomni.h"
|
#include "legoomni.h"
|
||||||
|
#include "legostate.h"
|
||||||
|
#include "infocenterstate.h"
|
||||||
|
#include "legostream.h"
|
||||||
|
#include "mxobjectfactory.h"
|
||||||
#include "mxvariabletable.h"
|
#include "mxvariabletable.h"
|
||||||
#include "decomp.h"
|
#include "mxstring.h"
|
||||||
|
|
||||||
// Based on the highest dword offset (0x42c) referenced in the constructor.
|
// Based on the highest dword offset (0x42c) referenced in the constructor.
|
||||||
// There may be other members that come after.
|
// There may be other members that come after.
|
||||||
DECOMP_SIZE_ASSERT(LegoGameState, 0x430)
|
DECOMP_SIZE_ASSERT(LegoGameState, 0x430)
|
||||||
|
|
||||||
|
// GLOBAL OFFSET: LEGO1 0x100f3e40
|
||||||
|
const char *g_fileExtensionGS = ".GS";
|
||||||
|
|
||||||
|
// GLOBAL OFFSET: LEGO1 0x100f3e58
|
||||||
|
ColorStringStruct g_colorSaveData[43] = {
|
||||||
|
{"c_dbbkfny0", "lego red"},
|
||||||
|
{"c_dbbkxly0", "lego white"},
|
||||||
|
{"c_chbasey0", "lego black"},
|
||||||
|
{"c_chbacky0", "lego black"},
|
||||||
|
{"c_chdishy0", "lego white"},
|
||||||
|
{"c_chhorny0", "lego black"},
|
||||||
|
{"c_chljety1", "lego black"},
|
||||||
|
{"c_chrjety1", "lego black"},
|
||||||
|
{"c_chmidly0", "lego black"},
|
||||||
|
{"c_chmotry0", "lego blue"},
|
||||||
|
{"c_chsidly0", "lego black"},
|
||||||
|
{"c_chsidry0", "lego black"},
|
||||||
|
{"c_chstuty0", "lego black"},
|
||||||
|
{"c_chtaily0", "lego black"},
|
||||||
|
{"c_chwindy1", "lego black"},
|
||||||
|
{"c_dbfbrdy0", "lego red"},
|
||||||
|
{"c_dbflagy0", "lego yellow"},
|
||||||
|
{"c_dbfrfny4", "lego red"},
|
||||||
|
{"c_dbfrxly0", "lego white"},
|
||||||
|
{"c_dbhndly0", "lego white"},
|
||||||
|
{"c_dbltbry0", "lego white"},
|
||||||
|
{"c_jsdashy0", "lego white"},
|
||||||
|
{"c_jsexhy0", "lego black"},
|
||||||
|
{"c_jsfrnty5", "lego black"},
|
||||||
|
{"c_jshndly0", "lego red"},
|
||||||
|
{"c_jslsidy0", "lego black"},
|
||||||
|
{"c_jsrsidy0", "lego black"},
|
||||||
|
{"c_jsskiby0", "lego red"},
|
||||||
|
{"c_jswnshy5", "lego white"},
|
||||||
|
{"c_rcbacky6", "lego green"},
|
||||||
|
{"c_rcedgey0", "lego green"},
|
||||||
|
{"c_rcfrmey0", "lego red"},
|
||||||
|
{"c_rcfrnty6", "lego green"},
|
||||||
|
{"c_rcmotry0", "lego white"},
|
||||||
|
{"c_rcsidey0", "lego green"},
|
||||||
|
{"c_rcstery0", "lego white"},
|
||||||
|
{"c_rcstrpy0", "lego yellow"},
|
||||||
|
{"c_rctailya", "lego white"},
|
||||||
|
{"c_rcwhl1y0", "lego white"},
|
||||||
|
{"c_rcwhl2y0", "lego white"},
|
||||||
|
{"c_jsbasey0", "lego white"},
|
||||||
|
{"c_chblady0", "lego black"},
|
||||||
|
{"c_chseaty0", "lego white"},
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: This offset = the end of the variables table, the last entry
|
||||||
|
// in that table is a special entry, the string "END_OF_VARIABLES"
|
||||||
|
// GLOBAL OFFSET: LEGO1 0x100f3e50
|
||||||
|
extern const char *s_endOfVariables;
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10039550
|
// OFFSET: LEGO1 0x10039550
|
||||||
LegoGameState::LegoGameState()
|
LegoGameState::LegoGameState()
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
m_stateCount = 0;
|
||||||
m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68");
|
m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68");
|
||||||
VariableTable()->SetVariable(m_backgroundColor);
|
VariableTable()->SetVariable(m_backgroundColor);
|
||||||
|
|
||||||
|
@ -25,33 +85,93 @@ LegoGameState::LegoGameState()
|
||||||
SerializeScoreHistory(1);
|
SerializeScoreHistory(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10039720
|
// OFFSET: LEGO1 0x10039720 STUB
|
||||||
LegoGameState::~LegoGameState()
|
LegoGameState::~LegoGameState()
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10039c60
|
// OFFSET: LEGO1 0x10039c60 STUB
|
||||||
MxResult LegoGameState::Load(MxULong)
|
MxResult LegoGameState::Load(MxULong)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10039980
|
// OFFSET: LEGO1 0x1003a170
|
||||||
MxResult LegoGameState::Save(MxULong p)
|
void LegoGameState::GetFileSavePath(MxString *p_outPath, MxULong p_slotn)
|
||||||
{
|
{
|
||||||
// TODO
|
char baseForSlot[2] = "0";
|
||||||
return 0;
|
char path[1024] = "";
|
||||||
|
|
||||||
|
// Save path base
|
||||||
|
if (m_savePath != NULL)
|
||||||
|
strcpy(path, m_savePath);
|
||||||
|
|
||||||
|
// Slot: "G0", "G1", ...
|
||||||
|
strcat(path, "G");
|
||||||
|
baseForSlot[0] += p_slotn;
|
||||||
|
strcat(path, baseForSlot);
|
||||||
|
|
||||||
|
// Extension: ".GS"
|
||||||
|
strcat(path, g_fileExtensionGS);
|
||||||
|
*p_outPath = MxString(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x1003a2e0
|
// OFFSET: LEGO1 0x1003a020
|
||||||
|
MxResult LegoGameState::WriteEndOfVariables(LegoStream *p_stream)
|
||||||
|
{
|
||||||
|
MxU8 len = strlen(s_endOfVariables);
|
||||||
|
if (p_stream->Write(&len, 1) == SUCCESS)
|
||||||
|
return p_stream->Write(s_endOfVariables, len);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x10039980
|
||||||
|
MxResult LegoGameState::Save(MxULong p_slot)
|
||||||
|
{
|
||||||
|
MxResult result;
|
||||||
|
InfocenterState *infocenterState = (InfocenterState *)GameState()->GetState("InfocenterState");
|
||||||
|
if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == 0)
|
||||||
|
result = SUCCESS;
|
||||||
|
else {
|
||||||
|
result = FAILURE;
|
||||||
|
MxVariableTable *variableTable = VariableTable();
|
||||||
|
MxString savePath;
|
||||||
|
GetFileSavePath(&savePath, p_slot);
|
||||||
|
LegoFileStream fileStream;
|
||||||
|
if (fileStream.Open(savePath.GetData(), LegoStream::WriteBit) != FAILURE) {
|
||||||
|
MxU32 maybeVersion = 0x1000C;
|
||||||
|
fileStream.Write(&maybeVersion, 4);
|
||||||
|
fileStream.Write(&m_secondThingWritten, 2);
|
||||||
|
fileStream.Write(&m_someEnumState, 2);
|
||||||
|
fileStream.Write(&m_someModeSwitch, 1);
|
||||||
|
|
||||||
|
for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) {
|
||||||
|
if (LegoStream::WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LegoStream::WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) {
|
||||||
|
if (LegoStream::WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) {
|
||||||
|
WriteEndOfVariables(&fileStream);
|
||||||
|
|
||||||
|
// TODO: Calls down to more aggregate writing functions
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x1003a2e0 STUB
|
||||||
void LegoGameState::SerializePlayersInfo(MxS16 p)
|
void LegoGameState::SerializePlayersInfo(MxS16 p)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x1003cdd0
|
// OFFSET: LEGO1 0x1003cdd0 STUB
|
||||||
void LegoGameState::SerializeScoreHistory(MxS16 p)
|
void LegoGameState::SerializeScoreHistory(MxS16 p)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -61,16 +181,56 @@ void LegoGameState::SerializeScoreHistory(MxS16 p)
|
||||||
void LegoGameState::SetSavePath(char *p_savePath)
|
void LegoGameState::SetSavePath(char *p_savePath)
|
||||||
{
|
{
|
||||||
if (m_savePath != NULL)
|
if (m_savePath != NULL)
|
||||||
{
|
|
||||||
delete[] m_savePath;
|
delete[] m_savePath;
|
||||||
}
|
|
||||||
if (p_savePath)
|
if (p_savePath) {
|
||||||
{
|
|
||||||
m_savePath = new char[strlen(p_savePath) + 1];
|
m_savePath = new char[strlen(p_savePath) + 1];
|
||||||
strcpy(m_savePath, p_savePath);
|
strcpy(m_savePath, p_savePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
m_savePath = NULL;
|
m_savePath = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x1003bbb0
|
||||||
|
LegoState *LegoGameState::GetState(char *p_stateName)
|
||||||
|
{
|
||||||
|
for (MxS32 i = 0; i < m_stateCount; ++i)
|
||||||
|
if (m_stateArray[i]->IsA(p_stateName))
|
||||||
|
return m_stateArray[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x1003bc00
|
||||||
|
LegoState *LegoGameState::CreateState(char *p_stateName)
|
||||||
|
{
|
||||||
|
LegoState* newState = (LegoState*)ObjectFactory()->Create(p_stateName);
|
||||||
|
RegisterState(newState);
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x1003bc30
|
||||||
|
void LegoGameState::RegisterState(LegoState *p_state)
|
||||||
|
{
|
||||||
|
MxS32 targetIndex;
|
||||||
|
for (targetIndex = 0; targetIndex < m_stateCount; ++targetIndex)
|
||||||
|
if (m_stateArray[targetIndex]->IsA(p_state->ClassName()))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (targetIndex == m_stateCount) {
|
||||||
|
LegoState **newBuffer = new LegoState*[m_stateCount + 1];
|
||||||
|
|
||||||
|
if (m_stateCount != 0) {
|
||||||
|
memcpy(newBuffer, m_stateArray, m_stateCount * sizeof(LegoState*));
|
||||||
|
delete[] m_stateArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
newBuffer[m_stateCount++] = p_state;
|
||||||
|
m_stateArray = newBuffer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_stateArray[targetIndex])
|
||||||
|
delete m_stateArray[targetIndex];
|
||||||
|
m_stateArray[targetIndex] = p_state;
|
||||||
}
|
}
|
|
@ -6,6 +6,17 @@
|
||||||
#include "legobackgroundcolor.h"
|
#include "legobackgroundcolor.h"
|
||||||
#include "legofullscreenmovie.h"
|
#include "legofullscreenmovie.h"
|
||||||
|
|
||||||
|
class LegoState;
|
||||||
|
class LegoStream;
|
||||||
|
class MxVariable;
|
||||||
|
class MxString;
|
||||||
|
|
||||||
|
struct ColorStringStruct
|
||||||
|
{
|
||||||
|
const char *m_targetName;
|
||||||
|
const char *m_colorName;
|
||||||
|
};
|
||||||
|
|
||||||
// SIZE 0x430 (at least)
|
// SIZE 0x430 (at least)
|
||||||
class LegoGameState
|
class LegoGameState
|
||||||
{
|
{
|
||||||
|
@ -18,13 +29,27 @@ class LegoGameState
|
||||||
__declspec(dllexport) void SerializeScoreHistory(MxS16 p);
|
__declspec(dllexport) void SerializeScoreHistory(MxS16 p);
|
||||||
__declspec(dllexport) void SetSavePath(char *p);
|
__declspec(dllexport) void SetSavePath(char *p);
|
||||||
|
|
||||||
|
LegoState *GetState(char *p_stateName);
|
||||||
|
LegoState *CreateState(char *p_stateName);
|
||||||
|
|
||||||
|
void GetFileSavePath(MxString *p_outPath, MxULong p_slotn);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RegisterState(LegoState *p_state);
|
||||||
|
MxResult WriteEndOfVariables(LegoStream *p_stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *m_savePath; // 0x0
|
char *m_savePath; // 0x0
|
||||||
undefined m_unk04[20];
|
MxS16 m_stateCount;
|
||||||
|
LegoState **m_stateArray;
|
||||||
|
MxU8 m_someModeSwitch;
|
||||||
|
MxU32 m_someEnumState;
|
||||||
|
undefined4 m_unk0x14;
|
||||||
LegoBackgroundColor *m_backgroundColor; // 0x18
|
LegoBackgroundColor *m_backgroundColor; // 0x18
|
||||||
LegoBackgroundColor *m_tempBackgroundColor; // 0x1c
|
LegoBackgroundColor *m_tempBackgroundColor; // 0x1c
|
||||||
LegoFullScreenMovie *m_fullScreenMovie; // 0x20
|
LegoFullScreenMovie *m_fullScreenMovie; // 0x20
|
||||||
undefined m_unk24[1036];
|
MxU16 m_secondThingWritten;
|
||||||
|
undefined m_unk24[1032];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LEGOGAMESTATE_H
|
#endif // LEGOGAMESTATE_H
|
||||||
|
|
35
LEGO1/legoobjectfactory.cpp
Normal file
35
LEGO1/legoobjectfactory.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include "legoobjectfactory.h"
|
||||||
|
|
||||||
|
#include "infocenterstate.h"
|
||||||
|
#include "decomp.h"
|
||||||
|
|
||||||
|
// TODO: Uncomment once we have all the relevant types ready
|
||||||
|
// DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c8);
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x10006e40
|
||||||
|
LegoObjectFactory::LegoObjectFactory()
|
||||||
|
{
|
||||||
|
#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact);
|
||||||
|
FOR_LEGOOBJECTFACTORY_OBJECTS(X)
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x10009a90
|
||||||
|
MxCore *LegoObjectFactory::Create(const char *p_name)
|
||||||
|
{
|
||||||
|
MxAtomId atom(p_name, LookupMode_Exact);
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
#define X(V) } else if (this->m_id##V == atom) { return new V;
|
||||||
|
FOR_LEGOOBJECTFACTORY_OBJECTS(X)
|
||||||
|
#undef X
|
||||||
|
} else {
|
||||||
|
return MxObjectFactory::Create(p_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x1000fb30 STUB
|
||||||
|
void LegoObjectFactory::Destroy(void *p_object)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
22
LEGO1/legoobjectfactory.h
Normal file
22
LEGO1/legoobjectfactory.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef LEGOOBJECTFACTORY_H
|
||||||
|
#define LEGOOBJECTFACTORY_H
|
||||||
|
|
||||||
|
#include "mxobjectfactory.h"
|
||||||
|
|
||||||
|
#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) \
|
||||||
|
X(InfocenterState)
|
||||||
|
|
||||||
|
// VTABLE 0x100d4768
|
||||||
|
class LegoObjectFactory : public MxObjectFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LegoObjectFactory();
|
||||||
|
virtual MxCore *Create(const char *p_name) override; // vtable 0x14
|
||||||
|
virtual void Destroy(void *p_object) override; // vtable 0x18
|
||||||
|
private:
|
||||||
|
#define X(V) MxAtomId m_id##V;
|
||||||
|
FOR_LEGOOBJECTFACTORY_OBJECTS(X)
|
||||||
|
#undef X
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LEGOOBJECTFACTORY_H
|
|
@ -4,6 +4,7 @@
|
||||||
#include "mxdsfile.h"
|
#include "mxdsfile.h"
|
||||||
#include "legogamestate.h"
|
#include "legogamestate.h"
|
||||||
#include "legoutil.h"
|
#include "legoutil.h"
|
||||||
|
#include "legoobjectfactory.h"
|
||||||
|
|
||||||
// 0x100f4588
|
// 0x100f4588
|
||||||
MxAtomId *g_nocdSourceName = NULL;
|
MxAtomId *g_nocdSourceName = NULL;
|
||||||
|
@ -261,7 +262,7 @@ void LegoOmni::Init()
|
||||||
m_currentWorld = NULL;
|
m_currentWorld = NULL;
|
||||||
m_unk80 = FALSE;
|
m_unk80 = FALSE;
|
||||||
m_isle = NULL;
|
m_isle = NULL;
|
||||||
m_unk8c = 0;
|
m_unkLegoSaveDataWriter = NULL;
|
||||||
m_plantManager = NULL;
|
m_plantManager = NULL;
|
||||||
m_gameState = NULL;
|
m_gameState = NULL;
|
||||||
m_animationManager = NULL;
|
m_animationManager = NULL;
|
||||||
|
@ -271,11 +272,12 @@ void LegoOmni::Init()
|
||||||
m_transitionManager = NULL;
|
m_transitionManager = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10058e70
|
// OFFSET: LEGO1 0x10058e70 STUB
|
||||||
MxResult LegoOmni::Create(COMPAT_CONST MxOmniCreateParam &p)
|
MxResult LegoOmni::Create(COMPAT_CONST MxOmniCreateParam &p)
|
||||||
{
|
{
|
||||||
// FIXME: Stub
|
|
||||||
MxOmni::Create(p);
|
MxOmni::Create(p);
|
||||||
|
|
||||||
|
m_objectFactory = new LegoObjectFactory();
|
||||||
m_gameState = new LegoGameState();
|
m_gameState = new LegoGameState();
|
||||||
m_bkgAudioManager = new MxBackgroundAudioManager();
|
m_bkgAudioManager = new MxBackgroundAudioManager();
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ class LegoPathBoundary;
|
||||||
class LegoPlantManager;
|
class LegoPlantManager;
|
||||||
class LegoROI;
|
class LegoROI;
|
||||||
class LegoSoundManager;
|
class LegoSoundManager;
|
||||||
|
class LegoUnkSaveDataWriter;
|
||||||
class LegoVideoManager;
|
class LegoVideoManager;
|
||||||
class LegoWorld;
|
class LegoWorld;
|
||||||
class MxAtomId;
|
class MxAtomId;
|
||||||
|
@ -77,8 +78,8 @@ class LegoOmni : public MxOmni
|
||||||
LegoWorld *GetCurrentWorld() { return m_currentWorld; }
|
LegoWorld *GetCurrentWorld() { return m_currentWorld; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_unk68;
|
undefined4 m_unk68;
|
||||||
int m_unk6c;
|
undefined4 m_unk6c;
|
||||||
LegoInputManager *m_inputMgr; // 0x70
|
LegoInputManager *m_inputMgr; // 0x70
|
||||||
undefined4 m_unk74;
|
undefined4 m_unk74;
|
||||||
undefined4 m_unk78;
|
undefined4 m_unk78;
|
||||||
|
@ -86,7 +87,7 @@ class LegoOmni : public MxOmni
|
||||||
MxBool m_unk80;
|
MxBool m_unk80;
|
||||||
LegoNavController *m_navController; // 0x84
|
LegoNavController *m_navController; // 0x84
|
||||||
Isle* m_isle; // 0x88
|
Isle* m_isle; // 0x88
|
||||||
undefined4 m_unk8c;
|
LegoUnkSaveDataWriter* m_unkLegoSaveDataWriter;
|
||||||
LegoPlantManager* m_plantManager; // 0x90
|
LegoPlantManager* m_plantManager; // 0x90
|
||||||
LegoAnimationManager* m_animationManager;
|
LegoAnimationManager* m_animationManager;
|
||||||
LegoBuildingManager* m_buildingManager; // 0x98
|
LegoBuildingManager* m_buildingManager; // 0x98
|
||||||
|
|
|
@ -4,6 +4,14 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "mxvariabletable.h"
|
||||||
|
|
||||||
|
// This is a pointer to the end of the global variable name table, which has
|
||||||
|
// the text "END_OF_VARIABLES" in it.
|
||||||
|
// TODO: make s_endOfVariables reference the actual end of the variable array.
|
||||||
|
// GLOBAL OFFSET: LEGO1 0x100f3e50
|
||||||
|
const char *s_endOfVariables = "END_OF_VARIABLES";
|
||||||
|
|
||||||
// Very likely but not certain sizes.
|
// Very likely but not certain sizes.
|
||||||
// The classes are only used on the stack in functions we have not 100% matched
|
// The classes are only used on the stack in functions we have not 100% matched
|
||||||
// yet, we can confirm the size once we have.
|
// yet, we can confirm the size once we have.
|
||||||
|
@ -38,7 +46,7 @@ LegoFileStream::~LegoFileStream()
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x100992c0
|
// OFFSET: LEGO1 0x100992c0
|
||||||
MxResult LegoFileStream::Read(char* p_buffer, MxU32 p_size)
|
MxResult LegoFileStream::Read(void* p_buffer, MxU32 p_size)
|
||||||
{
|
{
|
||||||
if (m_hFile == NULL)
|
if (m_hFile == NULL)
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
|
@ -47,7 +55,7 @@ MxResult LegoFileStream::Read(char* p_buffer, MxU32 p_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10099300
|
// OFFSET: LEGO1 0x10099300
|
||||||
MxResult LegoFileStream::Write(char* p_buffer, MxU32 p_size)
|
MxResult LegoFileStream::Write(const void* p_buffer, MxU32 p_size)
|
||||||
{
|
{
|
||||||
if (m_hFile == NULL)
|
if (m_hFile == NULL)
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
|
@ -117,7 +125,7 @@ LegoMemoryStream::LegoMemoryStream(char* p_buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10099160
|
// OFFSET: LEGO1 0x10099160
|
||||||
MxResult LegoMemoryStream::Read(char* p_buffer, MxU32 p_size)
|
MxResult LegoMemoryStream::Read(void* p_buffer, MxU32 p_size)
|
||||||
{
|
{
|
||||||
memcpy(p_buffer, m_buffer + m_offset, p_size);
|
memcpy(p_buffer, m_buffer + m_offset, p_size);
|
||||||
m_offset += p_size;
|
m_offset += p_size;
|
||||||
|
@ -125,7 +133,7 @@ MxResult LegoMemoryStream::Read(char* p_buffer, MxU32 p_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x10099190
|
// OFFSET: LEGO1 0x10099190
|
||||||
MxResult LegoMemoryStream::Write(char* p_buffer, MxU32 p_size)
|
MxResult LegoMemoryStream::Write(const void* p_buffer, MxU32 p_size)
|
||||||
{
|
{
|
||||||
memcpy(m_buffer + m_offset, p_buffer, p_size);
|
memcpy(m_buffer + m_offset, p_buffer, p_size);
|
||||||
m_offset += p_size;
|
m_offset += p_size;
|
||||||
|
@ -146,4 +154,51 @@ MxResult LegoMemoryStream::Seek(MxU32 p_offset)
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x10039f70
|
||||||
|
MxResult LegoStream::WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName)
|
||||||
|
{
|
||||||
|
MxResult result = FAILURE;
|
||||||
|
const char *variableValue = p_from->GetVariable(p_variableName);
|
||||||
|
|
||||||
|
if (variableValue) {
|
||||||
|
MxU8 length = strlen(p_variableName);
|
||||||
|
if (p_stream->Write((char*)&length, 1) == SUCCESS) {
|
||||||
|
if (p_stream->Write(p_variableName, length) == SUCCESS) {
|
||||||
|
length = strlen(variableValue);
|
||||||
|
if (p_stream->Write((char*)&length, 1) == SUCCESS)
|
||||||
|
result = p_stream->Write((char *)variableValue, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 95% match, just some instruction ordering differences on the call to
|
||||||
|
// MxVariableTable::SetVariable at the end.
|
||||||
|
// OFFSET: LEGO1 0x1003a080
|
||||||
|
MxS32 LegoStream::ReadVariable(LegoStream* p_stream, MxVariableTable* p_to)
|
||||||
|
{
|
||||||
|
MxS32 result = 1;
|
||||||
|
MxU8 length;
|
||||||
|
|
||||||
|
if (p_stream->Read((char*)&length, 1) == SUCCESS) {
|
||||||
|
char nameBuffer[256];
|
||||||
|
if (p_stream->Read(nameBuffer, length) == SUCCESS) {
|
||||||
|
nameBuffer[length] = '\0';
|
||||||
|
if (strcmp(nameBuffer, s_endOfVariables) == 0)
|
||||||
|
// 2 -> "This was the last entry, done reading."
|
||||||
|
result = 2;
|
||||||
|
else {
|
||||||
|
if (p_stream->Read((char*)&length, 1) == SUCCESS) {
|
||||||
|
char valueBuffer[256];
|
||||||
|
if (p_stream->Read(valueBuffer, length) == SUCCESS) {
|
||||||
|
result = 0;
|
||||||
|
valueBuffer[length] = '\0';
|
||||||
|
p_to->SetVariable(nameBuffer, valueBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#define LEGOSTREAM_MODE_READ 1
|
#define LEGOSTREAM_MODE_READ 1
|
||||||
#define LEGOSTREAM_MODE_WRITE 2
|
#define LEGOSTREAM_MODE_WRITE 2
|
||||||
|
|
||||||
|
class MxVariableTable;
|
||||||
|
|
||||||
// VTABLE 0x100d7d80
|
// VTABLE 0x100d7d80
|
||||||
class LegoStream
|
class LegoStream
|
||||||
{
|
{
|
||||||
|
@ -17,8 +19,8 @@ class LegoStream
|
||||||
LegoStream() : m_mode(0) {}
|
LegoStream() : m_mode(0) {}
|
||||||
inline virtual ~LegoStream() {};
|
inline virtual ~LegoStream() {};
|
||||||
|
|
||||||
virtual MxResult Read(char* p_buffer, MxU32 p_size) = 0;
|
virtual MxResult Read(void* p_buffer, MxU32 p_size) = 0;
|
||||||
virtual MxResult Write(char* p_buffer, MxU32 p_size) = 0;
|
virtual MxResult Write(const void* p_buffer, MxU32 p_size) = 0;
|
||||||
virtual MxResult Tell(MxU32* p_offset) = 0;
|
virtual MxResult Tell(MxU32* p_offset) = 0;
|
||||||
virtual MxResult Seek(MxU32 p_offset) = 0;
|
virtual MxResult Seek(MxU32 p_offset) = 0;
|
||||||
|
|
||||||
|
@ -32,6 +34,9 @@ class LegoStream
|
||||||
BinaryBit = 4,
|
BinaryBit = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static MxResult __stdcall WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName);
|
||||||
|
static MxS32 __stdcall ReadVariable(LegoStream* p_stream, MxVariableTable* p_to);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MxU8 m_mode;
|
MxU8 m_mode;
|
||||||
};
|
};
|
||||||
|
@ -43,8 +48,8 @@ class LegoFileStream : public LegoStream
|
||||||
LegoFileStream();
|
LegoFileStream();
|
||||||
virtual ~LegoFileStream();
|
virtual ~LegoFileStream();
|
||||||
|
|
||||||
MxResult Read(char* p_buffer, MxU32 p_size) override;
|
MxResult Read(void* p_buffer, MxU32 p_size) override;
|
||||||
MxResult Write(char* p_buffer, MxU32 p_size) override;
|
MxResult Write(const void* p_buffer, MxU32 p_size) override;
|
||||||
MxResult Tell(MxU32* p_offset) override;
|
MxResult Tell(MxU32* p_offset) override;
|
||||||
MxResult Seek(MxU32 p_offset) override;
|
MxResult Seek(MxU32 p_offset) override;
|
||||||
|
|
||||||
|
@ -61,8 +66,8 @@ class LegoMemoryStream : public LegoStream
|
||||||
LegoMemoryStream(char* p_buffer);
|
LegoMemoryStream(char* p_buffer);
|
||||||
~LegoMemoryStream() {}
|
~LegoMemoryStream() {}
|
||||||
|
|
||||||
MxResult Read(char* p_buffer, MxU32 p_size) override;
|
MxResult Read(void* p_buffer, MxU32 p_size) override;
|
||||||
MxResult Write(char* p_buffer, MxU32 p_size) override;
|
MxResult Write(const void* p_buffer, MxU32 p_size) override;
|
||||||
MxResult Tell(MxU32* p_offset) override;
|
MxResult Tell(MxU32* p_offset) override;
|
||||||
MxResult Seek(MxU32 p_offset) override;
|
MxResult Seek(MxU32 p_offset) override;
|
||||||
|
|
||||||
|
|
48
LEGO1/legounksavedatawriter.cpp
Normal file
48
LEGO1/legounksavedatawriter.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
#include "legounksavedatawriter.h"
|
||||||
|
#include "legogamestate.h"
|
||||||
|
#include "legostream.h"
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108);
|
||||||
|
|
||||||
|
// GLOBAL OFFSET: LEGO1 0x10104f20
|
||||||
|
LegoSaveDataEntry3 g_saveData3[66];
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x10083310
|
||||||
|
MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream *p_stream)
|
||||||
|
{
|
||||||
|
MxResult result = FAILURE;
|
||||||
|
|
||||||
|
// This should probably be a for loop but I can't figure out how to
|
||||||
|
// make it match as a for loop.
|
||||||
|
LegoSaveDataEntry3 *entry = g_saveData3;
|
||||||
|
const LegoSaveDataEntry3 *end = &g_saveData3[66];
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS)
|
||||||
|
break;
|
||||||
|
if (++entry >= end) {
|
||||||
|
result = SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
40
LEGO1/legounksavedatawriter.h
Normal file
40
LEGO1/legounksavedatawriter.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef LEGOUNKSAVEDATAWRITER_H
|
||||||
|
#define LEGOUNKSAVEDATAWRITER_H
|
||||||
|
|
||||||
|
#include "mxtypes.h"
|
||||||
|
#include "decomp.h"
|
||||||
|
|
||||||
|
class LegoStream;
|
||||||
|
|
||||||
|
struct LegoSaveDataEntry3
|
||||||
|
{
|
||||||
|
char *m_name;
|
||||||
|
void *m_unk0x04;
|
||||||
|
void *m_unk0x08;
|
||||||
|
MxS32 m_savePart1;
|
||||||
|
MxS32 m_savePart2;
|
||||||
|
MxU8 m_savePart3;
|
||||||
|
undefined4 m_unk0x18[6];
|
||||||
|
MxU8 m_frameOffsetInDwords; // 0x30
|
||||||
|
MxS32 *m_pFrameData;
|
||||||
|
MxU8 m_currentFrame;
|
||||||
|
undefined4 m_unk0x3c[2];
|
||||||
|
MxU8 m_savePart5; // 0x44
|
||||||
|
undefined4 m_unk0x48[5];
|
||||||
|
MxU8 m_savePart6; // 0x5c
|
||||||
|
undefined4 m_unk0x60[11];
|
||||||
|
MxU8 m_savePart7; // 0x8c
|
||||||
|
undefined4 m_unk0x90[5];
|
||||||
|
MxU8 m_savePart8; // 0xa4
|
||||||
|
undefined4 m_unk0xa8[17];
|
||||||
|
MxU8 m_savePart9; // 0xec
|
||||||
|
undefined4 m_unk0xf0[5];
|
||||||
|
MxU8 m_savePart10; // 0x104
|
||||||
|
};
|
||||||
|
|
||||||
|
class LegoUnkSaveDataWriter
|
||||||
|
{
|
||||||
|
MxResult WriteSaveData3(LegoStream *p_stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LEGOUNKSAVEDATAWRITER_H
|
|
@ -26,9 +26,9 @@ MxObjectFactory::MxObjectFactory()
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x100b12c0
|
// OFFSET: LEGO1 0x100b12c0
|
||||||
MxCore *MxObjectFactory::Create(const char *name)
|
MxCore *MxObjectFactory::Create(const char *p_name)
|
||||||
{
|
{
|
||||||
MxAtomId atom(name, LookupMode_Exact);
|
MxAtomId atom(p_name, LookupMode_Exact);
|
||||||
|
|
||||||
if (0) {
|
if (0) {
|
||||||
#define X(V) } else if (this->m_id##V == atom) { return new V;
|
#define X(V) } else if (this->m_id##V == atom) { return new V;
|
||||||
|
@ -40,6 +40,6 @@ MxCore *MxObjectFactory::Create(const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x100b1a30 STUB
|
// OFFSET: LEGO1 0x100b1a30 STUB
|
||||||
void MxObjectFactory::vtable18(void *) {
|
void MxObjectFactory::Destroy(void *p_object) {
|
||||||
// FIXME
|
// FIXME
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,22 @@ class MxObjectFactory : public MxCore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MxObjectFactory();
|
MxObjectFactory();
|
||||||
virtual MxCore *Create(const char *name); // vtable 0x14
|
|
||||||
virtual void vtable18(void *); // vtable 0x18
|
// OFFSET: LEGO1 0x10008f70
|
||||||
|
inline virtual const char *ClassName() const override // vtable+0xc
|
||||||
|
{
|
||||||
|
// 0x100f0730
|
||||||
|
return "MxObjectFactory";
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x10008f80
|
||||||
|
inline virtual MxBool IsA(const char *name) const override // vtable+0x10
|
||||||
|
{
|
||||||
|
return !strcmp(name, MxObjectFactory::ClassName()) || MxCore::IsA(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual MxCore *Create(const char *p_name); // vtable 0x14
|
||||||
|
virtual void Destroy(void *p_object); // vtable 0x18
|
||||||
private:
|
private:
|
||||||
#define X(V) MxAtomId m_id##V;
|
#define X(V) MxAtomId m_id##V;
|
||||||
FOR_MXOBJECTFACTORY_OBJECTS(X)
|
FOR_MXOBJECTFACTORY_OBJECTS(X)
|
||||||
|
|
|
@ -93,7 +93,9 @@ __declspec(dllexport) MxVariableTable * VariableTable();
|
||||||
__declspec(dllexport) MxMusicManager * MusicManager();
|
__declspec(dllexport) MxMusicManager * MusicManager();
|
||||||
__declspec(dllexport) MxEventManager * EventManager();
|
__declspec(dllexport) MxEventManager * EventManager();
|
||||||
__declspec(dllexport) MxNotificationManager * NotificationManager();
|
__declspec(dllexport) MxNotificationManager * NotificationManager();
|
||||||
|
|
||||||
MxVideoManager *MVideoManager();
|
MxVideoManager *MVideoManager();
|
||||||
MxAtomIdCounterSet *AtomIdCounterSet();
|
MxAtomIdCounterSet *AtomIdCounterSet();
|
||||||
|
MxObjectFactory *ObjectFactory();
|
||||||
|
|
||||||
#endif // MXOMNI_H
|
#endif // MXOMNI_H
|
||||||
|
|
Loading…
Reference in a new issue