Finish surface loading, but not test ready

This commit is contained in:
momo5502 2016-09-14 23:01:53 +02:00
parent ab3c75cb5b
commit 52487aa224
13 changed files with 328 additions and 53 deletions

View File

@ -522,7 +522,7 @@ namespace Components
if (file.Exists())
{
std::string& buffer = file.GetBuffer();
std::string buffer = file.GetBuffer();
mg_printf(nc,
"HTTP/1.1 200 OK\r\n"

View File

@ -2,24 +2,64 @@
namespace Components
{
void FileSystem::File::Read()
FileSystem::File::File(std::string file) : Name(file), Handle(0)
{
this->Size = Game::FS_FOpenFileRead(this->Name.data(), &this->Handle, 0);
}
FileSystem::File::~File()
{
char* buffer = nullptr;
int size = Game::FS_ReadFile(this->FilePath.data(), &buffer);
this->Buffer.clear();
if (size < 0)
if (this->Exists())
{
if (buffer)
{
Game::FS_FreeFile(buffer);
}
Game::FS_FCloseFile(this->Handle);
}
else
}
bool FileSystem::File::Exists()
{
return (this->Size > 0);
}
std::string FileSystem::File::GetName()
{
return this->Name;
}
std::string FileSystem::File::GetBuffer()
{
Utils::Memory::Allocator allocator;
if (!this->Exists()) return std::string();
int position = Game::FS_FTell(this->Handle);
this->Seek(0, FS_SEEK_SET);
char* buffer = allocator.AllocateArray<char>(this->Size);
if (!FileSystem::File::Read(buffer, this->Size))
{
this->Buffer.append(buffer, size);
Game::FS_FreeFile(buffer);
this->Seek(position, FS_SEEK_SET);
return std::string();
}
this->Seek(position, FS_SEEK_SET);
return std::string(buffer, this->Size);
}
bool FileSystem::File::Read(void* buffer, size_t size)
{
if (!this->Exists() || static_cast<size_t>(this->Size) < size || Game::FS_Read(buffer, size, this->Handle) != static_cast<int>(size))
{
return false;
}
return true;
}
void FileSystem::File::Seek(int offset, int origin)
{
if (this->Exists())
{
Game::FS_Seek(this->Handle, offset, origin);
}
}

View File

@ -7,18 +7,20 @@ namespace Components
class File
{
public:
File() {};
File(std::string file) : FilePath(file) { this->Read(); };
File() : Size(-1), Name(), Handle(0) {};
File(std::string file);
~File();
bool Exists() { return !this->Buffer.empty(); };
std::string GetName() { return this->FilePath; };
std::string& GetBuffer() { return this->Buffer; };
bool Exists();
std::string GetName();
std::string GetBuffer();
bool Read(void* buffer, size_t size);
void Seek(int offset, int origin);
private:
std::string FilePath;
std::string Buffer;
void Read();
int Handle;
int Size;
std::string Name;
};
class FileWriter

View File

@ -25,7 +25,7 @@ namespace Components
return i;
}
Game::script_t* Menus::LoadMenuScript(std::string name, std::string& buffer)
Game::script_t* Menus::LoadMenuScript(std::string name, std::string buffer)
{
Game::script_t* script = Game::Script_Alloc(sizeof(Game::script_t) + 1 + buffer.length());
@ -52,7 +52,7 @@ namespace Components
return script;
}
int Menus::LoadMenuSource(std::string name, std::string& buffer)
int Menus::LoadMenuSource(std::string name, std::string buffer)
{
int handle = Menus::ReserveSourceHandle();
if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot!

View File

@ -30,8 +30,8 @@ namespace Components
static std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef);
static std::vector<Game::menuDef_t*> LoadMenu(std::string file);
static Game::script_t* LoadMenuScript(std::string name, std::string& buffer);
static int LoadMenuSource(std::string name, std::string& buffer);
static Game::script_t* LoadMenuScript(std::string name, std::string buffer);
static int LoadMenuSource(std::string name, std::string buffer);
static int ReserveSourceHandle();
static bool IsValidSourceHandle(int handle);

View File

@ -3,6 +3,7 @@
namespace Components
{
std::map<void*, IUnknown*> ModelSurfs::BufferMap;
std::map<void*, Game::CModelAllocData*> ModelSurfs::AllocMap;
IUnknown* ModelSurfs::GetBuffer(void* buffer)
{
@ -11,22 +12,172 @@ namespace Components
void ModelSurfs::SetBuffer(char /*streamHandle*/, void* buffer, IUnknown** bufferOut, int* offsetOut)
{
*offsetOut;
*offsetOut = 0;
*bufferOut = ModelSurfs::BufferMap[buffer];
}
// TODO: Implement
bool ModelSurfs::LoadXSurfaces(Game::XModel* model)
void ModelSurfs::CreateBuffers(Game::XModelSurfs* surfs)
{
(model);
return false;
for (int i = 0; i < surfs->numSurfaces; ++i)
{
Game::XSurface* surface = &surfs->surfaces[i];
if (surface->streamHandle == 0xFF)
{
IDirect3DVertexBuffer9* vertexBuffer;
IDirect3DIndexBuffer9* indexBuffer;
Game::Load_VertexBuffer(surface->vertexBuffer, &vertexBuffer, surface->numVertices * 32);
Game::Load_IndexBuffer(surface->indexBuffer, &indexBuffer, surface->numPrimitives * 3);
ModelSurfs::BufferMap[surface->vertexBuffer] = vertexBuffer;
ModelSurfs::BufferMap[surface->indexBuffer] = indexBuffer;
}
}
}
Game::XModelSurfs* ModelSurfs::LoadXModelSurfaces(std::string name)
{
Utils::Memory::Allocator allocator;
FileSystem::File model(fmt::sprintf("models/%s", name.data()));
if (!model.Exists())
{
Logger::Error("Loading model %s failed!", name.data());
}
Game::CModelHeader header;
if (!model.Read(&header, sizeof header))
{
Logger::Error("Reading header for model %s failed!", name.data());
}
if (header.version != 1)
{
Logger::Error("Model %s has an invalid version %d (should be 1)!", name.data(), header.version);
}
// Allocate section buffers
header.sectionHeader[Game::SECTION_MAIN].buffer = Utils::Memory::Allocate(header.sectionHeader[Game::SECTION_MAIN].size);
header.sectionHeader[Game::SECTION_INDEX].buffer = Utils::Memory::AllocateAlign(header.sectionHeader[Game::SECTION_INDEX].size, 16);
header.sectionHeader[Game::SECTION_VERTEX].buffer = Utils::Memory::AllocateAlign(header.sectionHeader[Game::SECTION_VERTEX].size, 16);
header.sectionHeader[Game::SECTION_FIXUP].buffer = allocator.AllocateArray<char>(header.sectionHeader[Game::SECTION_FIXUP].size);
// Load section data
for (int i = 0; i < ARRAY_SIZE(header.sectionHeader); ++i)
{
model.Seek(header.sectionHeader[i].offset, FS_SEEK_SET);
if (!model.Read(header.sectionHeader[i].buffer, header.sectionHeader[i].size))
{
Logger::Error("Reading section %d for model %s failed!", i, name.data());
}
}
// Fixup sections
unsigned int* fixups = reinterpret_cast<unsigned int*>(header.sectionHeader[Game::SECTION_FIXUP].buffer);
for (int i = 0; i < 3; ++i)
{
Game::CModelSectionHeader* section = &header.sectionHeader[i];
for (int j = section->fixupStart; j < section->fixupStart + section->fixupCount; ++j)
{
unsigned int fixup = fixups[i];
*reinterpret_cast<DWORD*>(reinterpret_cast<char*>(section->buffer) + (fixup >> 3)) += reinterpret_cast<DWORD>(header.sectionHeader[fixup & 3].buffer);
}
}
// Store allocation data (not sure if this is correct)
Game::CModelAllocData* allocationData = Utils::Memory::AllocateArray<Game::CModelAllocData>();
allocationData->mainArray = header.sectionHeader[Game::SECTION_MAIN].buffer;
allocationData->indexBuffer = header.sectionHeader[Game::SECTION_INDEX].buffer;
allocationData->vertexBuffer = header.sectionHeader[Game::SECTION_VERTEX].buffer;
ModelSurfs::AllocMap[allocationData->vertexBuffer] = allocationData;
*reinterpret_cast<void**>(reinterpret_cast<char*>(allocationData->mainArray) + 44) = allocationData;
Assert_Size(Game::XSurface, 64);
Game::XModelSurfs* modelSurfs = reinterpret_cast<Game::XModelSurfs*>(allocationData->mainArray);
Game::XSurface* tempSurfaces = allocator.AllocateArray<Game::XSurface>(modelSurfs->numSurfaces);
char* surfaceData = reinterpret_cast<char*>(modelSurfs->surfaces);
for (int i = 0; i < modelSurfs->numSurfaces; ++i)
{
memcpy(&tempSurfaces[i], surfaceData + (i * 84), 12);
memcpy(&tempSurfaces[i].indexBuffer, surfaceData + (i * 84) + 16, 20);
memcpy(&tempSurfaces[i].numCT, surfaceData + (i * 84) + 40, 8);
memcpy(&tempSurfaces[i].pad5, surfaceData + (i * 84) + 52, 24);
tempSurfaces[i].streamHandle = 0xFF; // Fake handle for buffer interception
}
memcpy(surfaceData, tempSurfaces, 64 * modelSurfs->numSurfaces);
ModelSurfs::CreateBuffers(modelSurfs);
return modelSurfs;
}
bool ModelSurfs::LoadSurfaces(Game::XModel* model)
{
if (!model) return false;
bool changed = false;
short surfCount = 0;
for (char i = 0; i < model->numLods; ++i)
{
Game::XModelSurfs* surfs = model->lods[i].surfaces;
if (!surfs->surfaces)
{
Game::XModelSurfs* newSurfs = ModelSurfs::LoadXModelSurfaces(surfs->name);
surfs->surfaces = newSurfs->surfaces;
surfs->numSurfaces = newSurfs->numSurfaces;
model->lods[i].surfaces = newSurfs;
memcpy(model->lods[i].pad3, newSurfs->pad, 24);
short numSurfs = static_cast<short>(newSurfs->numSurfaces);
model->lods[i].someCount = numSurfs;
model->lods[i].someTotalCount = surfCount;
surfCount += numSurfs;
}
}
return changed;
}
// TODO: Implement
void ModelSurfs::ReleaseModelSurf(Game::XAssetHeader header)
{
Game::XModelSurfs* surfaces = header.surfaces;
(surfaces);
for (int i = 0; i < header.surfaces->numSurfaces && header.surfaces->surfaces; ++i)
{
Game::XSurface* surface = &header.surfaces->surfaces[i];
if (surface->streamHandle == 0xFF)
{
auto buffer = ModelSurfs::BufferMap.find(surface->indexBuffer);
if (buffer != ModelSurfs::BufferMap.end())
{
buffer->second->Release();
ModelSurfs::BufferMap.erase(buffer);
}
buffer = ModelSurfs::BufferMap.find(surface->vertexBuffer);
if (buffer != ModelSurfs::BufferMap.end())
{
buffer->second->Release();
ModelSurfs::BufferMap.erase(buffer);
}
auto allocData = ModelSurfs::AllocMap.find(surface->vertexBuffer);
if (allocData != ModelSurfs::AllocMap.end())
{
Utils::Memory::Free(allocData->second->indexBuffer);
Utils::Memory::Free(allocData->second->vertexBuffer);
Utils::Memory::Free(allocData->second->mainArray);
Utils::Memory::Free(allocData->second);
ModelSurfs::AllocMap.erase(allocData);
}
}
}
}
void ModelSurfs::BeginRecover()
@ -39,19 +190,17 @@ namespace Components
ModelSurfs::BufferMap.clear();
}
// TODO: Implement
void ModelSurfs::EndRecover()
{
Game::DB_EnumXAssets_Internal(Game::XAssetType::ASSET_TYPE_XMODELSURFS, [] (Game::XAssetHeader header, void* /*userdata*/)
{
Game::XModelSurfs* surfaces = header.surfaces;
(surfaces);
ModelSurfs::CreateBuffers(header.surfaces);
}, nullptr, false);
}
void ModelSurfs::XModelSurfsFixup(Game::XModel* model)
{
if (!ModelSurfs::LoadXSurfaces(model))
if (!ModelSurfs::LoadSurfaces(model))
{
Game::DB_XModelSurfsFixup(model);
}
@ -154,5 +303,6 @@ namespace Components
ModelSurfs::~ModelSurfs()
{
assert(ModelSurfs::BufferMap.empty());
assert(ModelSurfs::AllocMap.empty());
}
}

View File

@ -7,8 +7,8 @@ namespace Components
~ModelSurfs();
private:
static std::map<void*, IUnknown*> BufferMap;
static std::map<void*, Game::CModelAllocData*> AllocMap;
static void ReleaseModelSurf(Game::XAssetHeader header);
@ -18,7 +18,9 @@ namespace Components
static IUnknown* GetBuffer(void* buffer);
static void SetBuffer(char streamHandle, void* buffer, IUnknown** bufferOut, int* offsetOut);
static bool LoadXSurfaces(Game::XModel* model);
static void CreateBuffers(Game::XModelSurfs* surfs);
static Game::XModelSurfs* LoadXModelSurfaces(std::string name);
static bool LoadSurfaces(Game::XModel* model);
static void XModelSurfsFixup(Game::XModel* model);
static void GetIndexBaseStub();

View File

@ -135,6 +135,7 @@ namespace Game
PartyHost_GetMemberName_t PartyHost_GetMemberName = (PartyHost_GetMemberName_t)0x44BE90;
R_AddCmdDrawStretchPic_t R_AddCmdDrawStretchPic = (R_AddCmdDrawStretchPic_t)0x509770;
R_AllocStaticIndexBuffer_t R_AllocStaticIndexBuffer = (R_AllocStaticIndexBuffer_t)0x51E7A0;
R_Cinematic_StartPlayback_Now_t R_Cinematic_StartPlayback_Now = (R_Cinematic_StartPlayback_Now_t)0x51C5B0;
R_RegisterFont_t R_RegisterFont = (R_RegisterFont_t)0x505670;
R_AddCmdDrawText_t R_AddCmdDrawText = (R_AddCmdDrawText_t)0x509D80;
@ -465,4 +466,37 @@ namespace Game
pop esi
}
}
void Load_IndexBuffer(void* data, IDirect3DIndexBuffer9** storeHere, int count)
{
if (Components::Dvar::Var("r_loadForRenderer").Get<bool>())
{
void* buffer = R_AllocStaticIndexBuffer(storeHere, 2 * count);
memcpy(buffer, data, 2 * count);
if (storeHere && *storeHere)
{
(*storeHere)->Unlock();
}
}
}
void Load_VertexBuffer(void* data, IDirect3DVertexBuffer9** where, int len)
{
DWORD func = 0x5112C0;
__asm
{
push edi
mov eax, len
mov edi, where
push data
call func
add esp, 4
pop edi
}
}
}

View File

@ -329,6 +329,9 @@ namespace Game
typedef void(_cdecl * R_AddCmdDrawStretchPic_t)(float x, float y, float w, float h, float xScale, float yScale, float xay, float yay, const float *color, Game::Material* material);
extern R_AddCmdDrawStretchPic_t R_AddCmdDrawStretchPic;
typedef void* (__cdecl * R_AllocStaticIndexBuffer_t)(IDirect3DIndexBuffer9** store, int length);
extern R_AllocStaticIndexBuffer_t R_AllocStaticIndexBuffer;
typedef bool(__cdecl * R_Cinematic_StartPlayback_Now_t)();
extern R_Cinematic_StartPlayback_Now_t R_Cinematic_StartPlayback_Now;
@ -530,4 +533,7 @@ namespace Game
void IN_KeyUp(kbutton_t* button);
void IN_KeyDown(kbutton_t* button);
void Load_IndexBuffer(void* data, IDirect3DIndexBuffer9** storeHere, int count);
void Load_VertexBuffer(void* data, IDirect3DVertexBuffer9** where, int len);
}

View File

@ -818,6 +818,10 @@ namespace Game
menuDef_t **menus;
};
#define FS_SEEK_CUR 0
#define FS_SEEK_END 1
#define FS_SEEK_SET 2
enum FsListBehavior_e
{
FS_LIST_PURE_ONLY = 0x0,
@ -1394,7 +1398,10 @@ namespace Game
struct XModelLodInfo
{
char pad[4]; // +0
// I'm not sure if this is correct
short someCount;
short someTotalCount;
short numSurfs; // +4
short pad2;// +6
XModelSurfs* surfaces; // +8
@ -1525,6 +1532,39 @@ namespace Game
PhysCollmap* physCollmap;
}; // total size 304
//static_assert(offsetof(XModel, lods) <= 70, "");
struct CModelAllocData
{
void* mainArray;
void* vertexBuffer;
void* indexBuffer;
};
struct CModelSectionHeader
{
int size;
int offset;
int fixupStart;
int fixupCount;
void* buffer;
};
enum CModelSection
{
SECTION_MAIN = 0,
SECTION_INDEX = 1,
SECTION_VERTEX = 2,
SECTION_FIXUP = 3,
};
struct CModelHeader
{
int version;
unsigned int signature;
CModelSectionHeader sectionHeader[4];
};
struct DSkelPartBits
{
int anim[4];

View File

@ -2,17 +2,17 @@
namespace Utils
{
void* Memory::AllocateAlign(size_t length, size_t alignment)
{
void* data = _aligned_malloc(length, alignment);
assert(data != nullptr);
return data;
}
void* Memory::Allocate(size_t length)
{
void* data = new char[length];
void* data = calloc(length, 1);
assert(data != nullptr);
if (data)
{
ZeroMemory(data, length);
}
return data;
}
@ -27,7 +27,7 @@ namespace Utils
{
if (data)
{
delete[] data;
free(data);
}
}

View File

@ -92,6 +92,7 @@ namespace Utils
std::map<void*, FreeCallback> RefMemory;
};
static void* AllocateAlign(size_t length, size_t alignment);
static void* Allocate(size_t length);
template <typename T> static T* Allocate()
{

View File

@ -12,7 +12,7 @@ namespace Utils
class Reader
{
public:
Reader(Utils::Memory::Allocator* allocator, std::string& buffer) : Buffer(buffer), Allocator(allocator), Position(0) {}
Reader(Utils::Memory::Allocator* allocator, std::string buffer) : Buffer(buffer), Allocator(allocator), Position(0) {}
std::string ReadString();
const char* ReadCString();