summaryrefslogtreecommitdiffstats
path: root/src/core/TxdStore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/TxdStore.cpp')
-rw-r--r--src/core/TxdStore.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/core/TxdStore.cpp b/src/core/TxdStore.cpp
new file mode 100644
index 00000000..5085c7e4
--- /dev/null
+++ b/src/core/TxdStore.cpp
@@ -0,0 +1,208 @@
+#include "common.h"
+#include "patcher.h"
+#include "templates.h"
+#include "Streaming.h"
+#include "RwHelper.h"
+#include "TxdStore.h"
+
+CPool<TxdDef,TxdDef> *&CTxdStore::ms_pTxdPool = *(CPool<TxdDef,TxdDef>**)0x8F5FB8;
+RwTexDictionary *&CTxdStore::ms_pStoredTxd = *(RwTexDictionary**)0x9405BC;
+
+void
+CTxdStore::Initialize(void)
+{
+ if(ms_pTxdPool == nil)
+ ms_pTxdPool = new CPool<TxdDef,TxdDef>(TXDSTORESIZE);
+}
+
+void
+CTxdStore::Shutdown(void)
+{
+ if(ms_pTxdPool)
+ delete ms_pTxdPool;
+}
+
+void
+CTxdStore::GameShutdown(void)
+{
+ int i;
+
+ for(i = 0; i < TXDSTORESIZE; i++){
+ TxdDef *def = GetSlot(i);
+ if(def && GetNumRefs(i) == 0)
+ RemoveTxdSlot(i);
+ }
+}
+
+int
+CTxdStore::AddTxdSlot(const char *name)
+{
+ TxdDef *def = ms_pTxdPool->New();
+ assert(def);
+ def->texDict = nil;
+ def->refCount = 0;
+ strcpy(def->name, name);
+ return ms_pTxdPool->GetJustIndex(def);
+}
+
+void
+CTxdStore::RemoveTxdSlot(int slot)
+{
+ TxdDef *def = GetSlot(slot);
+ if(def->texDict)
+ RwTexDictionaryDestroy(def->texDict);
+ ms_pTxdPool->Delete(def);
+}
+
+int
+CTxdStore::FindTxdSlot(const char *name)
+{
+ char *defname;
+ int size = ms_pTxdPool->GetSize();
+ for(int i = 0; i < size; i++){
+ defname = GetTxdName(i);
+ if(defname && _strcmpi(defname, name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+char*
+CTxdStore::GetTxdName(int slot)
+{
+ TxdDef *def = GetSlot(slot);
+ return def ? def->name : nil;
+}
+
+void
+CTxdStore::PushCurrentTxd(void)
+{
+ ms_pStoredTxd = RwTexDictionaryGetCurrent();
+}
+
+void
+CTxdStore::PopCurrentTxd(void)
+{
+ RwTexDictionarySetCurrent(ms_pStoredTxd);
+ ms_pStoredTxd = nil;
+}
+
+void
+CTxdStore::SetCurrentTxd(int slot)
+{
+ TxdDef *def = GetSlot(slot);
+ if(def)
+ RwTexDictionarySetCurrent(def->texDict);
+}
+
+void
+CTxdStore::Create(int slot)
+{
+ GetSlot(slot)->texDict = RwTexDictionaryCreate();
+}
+
+int
+CTxdStore::GetNumRefs(int slot)
+{
+ return GetSlot(slot)->refCount;
+}
+
+void
+CTxdStore::AddRef(int slot)
+{
+ GetSlot(slot)->refCount++;
+}
+
+void
+CTxdStore::RemoveRef(int slot)
+{
+ if(--GetSlot(slot)->refCount <= 0)
+ CStreaming::RemoveModel(slot + STREAM_OFFSET_TXD);
+}
+
+void
+CTxdStore::RemoveRefWithoutDelete(int slot)
+{
+ GetSlot(slot)->refCount--;
+}
+
+bool
+CTxdStore::LoadTxd(int slot, RwStream *stream)
+{
+ TxdDef *def = GetSlot(slot);
+
+ if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){
+ def->texDict = RwTexDictionaryGtaStreamRead(stream);
+ return def->texDict != nil;
+ }
+ printf("Failed to load TXD\n");
+ return false;
+}
+
+bool
+CTxdStore::LoadTxd(int slot, const char *filename)
+{
+ RwStream *stream;
+ bool ret;
+
+ ret = false;
+ _rwD3D8TexDictionaryEnableRasterFormatConversion(true);
+ do
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
+ while(stream == nil);
+ ret = LoadTxd(slot, stream);
+ RwStreamClose(stream, nil);
+ return ret;
+}
+
+bool
+CTxdStore::StartLoadTxd(int slot, RwStream *stream)
+{
+ TxdDef *def = GetSlot(slot);
+ if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){
+ def->texDict = RwTexDictionaryGtaStreamRead1(stream);
+ return def->texDict != nil;
+ }else{
+ printf("Failed to load TXD\n");
+ return false;
+ }
+}
+
+bool
+CTxdStore::FinishLoadTxd(int slot, RwStream *stream)
+{
+ TxdDef *def = GetSlot(slot);
+ def->texDict = RwTexDictionaryGtaStreamRead2(stream, def->texDict);
+ return def->texDict != nil;
+}
+
+void
+CTxdStore::RemoveTxd(int slot)
+{
+ TxdDef *def = GetSlot(slot);
+ if(def->texDict)
+ RwTexDictionaryDestroy(def->texDict);
+ def->texDict = nil;
+}
+
+STARTPATCHES
+ InjectHook(0x527440, CTxdStore::Initialize, PATCH_JUMP);
+ InjectHook(0x527470, CTxdStore::Shutdown, PATCH_JUMP);
+ InjectHook(0x527490, CTxdStore::GameShutdown, PATCH_JUMP);
+ InjectHook(0x5274E0, CTxdStore::AddTxdSlot, PATCH_JUMP);
+ InjectHook(0x5275D0, CTxdStore::FindTxdSlot, PATCH_JUMP);
+ InjectHook(0x527590, CTxdStore::GetTxdName, PATCH_JUMP);
+ InjectHook(0x527900, CTxdStore::PushCurrentTxd, PATCH_JUMP);
+ InjectHook(0x527910, CTxdStore::PopCurrentTxd, PATCH_JUMP);
+ InjectHook(0x5278C0, CTxdStore::SetCurrentTxd, PATCH_JUMP);
+ InjectHook(0x527830, CTxdStore::Create, PATCH_JUMP);
+ InjectHook(0x527A00, CTxdStore::GetNumRefs, PATCH_JUMP);
+ InjectHook(0x527930, CTxdStore::AddRef, PATCH_JUMP);
+ InjectHook(0x527970, CTxdStore::RemoveRef, PATCH_JUMP);
+ InjectHook(0x5279C0, CTxdStore::RemoveRefWithoutDelete, PATCH_JUMP);
+ InjectHook(0x527700, (bool (*)(int, RwStream*))CTxdStore::LoadTxd, PATCH_JUMP);
+ InjectHook(0x5276B0, (bool (*)(int, const char*))CTxdStore::LoadTxd, PATCH_JUMP);
+ InjectHook(0x527770, CTxdStore::StartLoadTxd, PATCH_JUMP);
+ InjectHook(0x5277E0, CTxdStore::FinishLoadTxd, PATCH_JUMP);
+ InjectHook(0x527870, CTxdStore::RemoveTxd, PATCH_JUMP);
+ENDPATCHES