Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for VS2015 generated ASIs using W WinAPI functions implicitly #59

Merged
merged 6 commits into from
Nov 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 116 additions & 17 deletions src/plugins/gta3/std.asi/ModuleInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,56 +518,107 @@ extern const char aWritePrivateProfileStructA[] = "WritePrivateProfileStructA";
extern const char aGetFileAttributesA[] = "GetFileAttributesA";
extern const char aGetFileAttributesExA[] = "GetFileAttributesExA";

extern const char aCreateFileW[] = "CreateFileW";
extern const char aLoadLibraryW[] = "LoadLibraryW";
extern const char aLoadLibraryExW[] = "LoadLibraryExW";
extern const char aGetModuleFileNameW[] = "GetModuleFileNameW";
extern const char aFindFirstFileW[] = "FindFirstFileW";
extern const char aFindNextFileW[] = "FindNextFileW";
extern const char aSetCurrentDirectoryW[] = "SetCurrentDirectoryW";
extern const char aGetPrivateProfileIntW[] = "GetPrivateProfileIntW";
extern const char aGetPrivateProfileSectionW[] = "GetPrivateProfileSectionW";
extern const char aGetPrivateProfileSectionNamesW[] = "GetPrivateProfileSectionNamesW";
extern const char aGetPrivateProfileStringW[] = "GetPrivateProfileStringW";
extern const char aGetPrivateProfileStructW[] = "GetPrivateProfileStructW";
extern const char aWritePrivateProfileSectionW[] = "WritePrivateProfileSectionW";
extern const char aWritePrivateProfileStringW[] = "WritePrivateProfileStringW";
extern const char aWritePrivateProfileStructW[] = "WritePrivateProfileStructW";
extern const char aGetFileAttributesW[] = "GetFileAttributesW";
extern const char aGetFileAttributesExW[] = "GetFileAttributesExW";


// Operations
static path_translator_stdcall<aCreateFileA, aKernel32, HANDLE(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE)>
static path_translator_stdcall<aCreateFileA, aKernel32, HANDLE(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE)>
psCreateFileA(0, AR_PATH_INE, 0, 0, 0, 0, 0, 0);
static path_translator_stdcall<aSetCurrentDirectoryA, aKernel32, BOOL(LPCTSTR)>
static path_translator_stdcall<aSetCurrentDirectoryA, aKernel32, BOOL(LPCSTR)>
psSetCurrentDirectoryA(0, AR_PATH_INE); // Do not work properly!! Don't use!!!

static path_translator_stdcall<aCreateFileW, aKernel32, HANDLE(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE)>
psCreateFileW(0, AR_PATH_INE, 0, 0, 0, 0, 0, 0);
static path_translator_stdcall<aSetCurrentDirectoryW, aKernel32, BOOL(LPCWSTR)>
psSetCurrentDirectoryW(0, AR_PATH_INE); // Do not work properly!! Don't use!!!

// File finding (used mostly to hack CLEO.asi)
static path_translator_stdcall<aFindFirstFileA, aKernel32, HANDLE(LPCTSTR, LPWIN32_FIND_DATAA)>
static path_translator_stdcall<aFindFirstFileA, aKernel32, HANDLE(LPCSTR, LPWIN32_FIND_DATAA)>
psFindFirstFileA(0, AR_PATH_INEB, 0);
static path_translator_stdcall<aFindNextFileA, aKernel32, BOOL(HANDLE, LPWIN32_FIND_DATAA)> // Hack CLEO.asi
psFindNextFileA(0, 0, 0);
static path_translator_stdcall<aFindFirstFileW, aKernel32, HANDLE(LPCWSTR, LPWIN32_FIND_DATAW)>
psFindFirstFileW(0, AR_PATH_INEB, 0);
static path_translator_stdcall<aFindNextFileW, aKernel32, BOOL(HANDLE, LPWIN32_FIND_DATAW)> // Hack CLEO.asi
psFindNextFileW(0, 0, 0);
static path_translator_stdcall<aFindClose, aKernel32, BOOL(HANDLE)> // Hack CLEO.asi
psFindClose(0, 0);


// Library routines
static path_translator_stdcall<aGetModuleFileNameA, aKernel32, DWORD(HMODULE, LPTSTR, DWORD)>
static path_translator_stdcall<aGetModuleFileNameA, aKernel32, DWORD(HMODULE, LPSTR, DWORD)>
psGetModuleFileNameA(0, 0, 0, 0); // I'll need to intercept this routine for some Ryosuke's plugins compatibility
static path_translator_stdcall<aLoadLibraryA, aKernel32, HMODULE(LPCTSTR)>
static path_translator_stdcall<aLoadLibraryA, aKernel32, HMODULE(LPCSTR)>
psLoadLibraryA(0, AR_PATH_INE);
static path_translator_stdcall<aLoadLibraryExA, aKernel32, HMODULE(LPCTSTR, HANDLE, DWORD)>
static path_translator_stdcall<aLoadLibraryExA, aKernel32, HMODULE(LPCSTR, HANDLE, DWORD)>
psLoadLibraryExA(0, AR_PATH_INE, 0, 0);
static path_translator_stdcall<aGetModuleFileNameW, aKernel32, DWORD(HMODULE, LPWSTR, DWORD)>
psGetModuleFileNameW(0, 0, 0, 0); // I'll need to intercept this routine for some Ryosuke's plugins compatibility
static path_translator_stdcall<aLoadLibraryW, aKernel32, HMODULE(LPCWSTR)>
psLoadLibraryW(0, AR_PATH_INE);
static path_translator_stdcall<aLoadLibraryExW, aKernel32, HMODULE(LPCWSTR, HANDLE, DWORD)>
psLoadLibraryExW(0, AR_PATH_INE, 0, 0);

// Get from INI
static path_translator_stdcall<aGetPrivateProfileIntA, aKernel32, UINT(LPCTSTR, LPCTSTR, INT, LPCTSTR)>
static path_translator_stdcall<aGetPrivateProfileIntA, aKernel32, UINT(LPCSTR, LPCSTR, INT, LPCSTR)>
psGetPrivateProfileIntA(0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileSectionA, aKernel32, DWORD(LPCTSTR, LPCTSTR, DWORD, LPCTSTR)>
static path_translator_stdcall<aGetPrivateProfileSectionA, aKernel32, DWORD(LPCSTR, LPCSTR, DWORD, LPCSTR)>
psGetPrivateProfileSectionA(0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileSectionNamesA, aKernel32, DWORD(LPCTSTR, DWORD, LPCTSTR)>
static path_translator_stdcall<aGetPrivateProfileSectionNamesA, aKernel32, DWORD(LPCSTR, DWORD, LPCSTR)>
psGetPrivateProfileSectionNamesA(0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileStringA, aKernel32, DWORD(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, DWORD, LPCTSTR)>
static path_translator_stdcall<aGetPrivateProfileStringA, aKernel32, DWORD(LPCSTR, LPCSTR, LPCSTR, LPSTR, DWORD, LPCSTR)>
psGetPrivateProfileStringA(0, 0, 0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileStructA, aKernel32, DWORD(LPCTSTR, LPCTSTR, LPVOID, UINT, LPTSTR)>
static path_translator_stdcall<aGetPrivateProfileStructA, aKernel32, DWORD(LPCSTR, LPCSTR, LPVOID, UINT, LPSTR)>
psGetPrivateProfileStructA(0, 0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileIntW, aKernel32, UINT(LPCWSTR, LPCWSTR, INT, LPCWSTR)>
psGetPrivateProfileIntW(0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileSectionW, aKernel32, DWORD(LPCWSTR, LPCWSTR, DWORD, LPCWSTR)>
psGetPrivateProfileSectionW(0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileSectionNamesW, aKernel32, DWORD(LPCWSTR, DWORD, LPCWSTR)>
psGetPrivateProfileSectionNamesW(0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileStringW, aKernel32, DWORD(LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR)>
psGetPrivateProfileStringW(0, 0, 0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aGetPrivateProfileStructW, aKernel32, DWORD(LPCWSTR, LPCWSTR, LPVOID, UINT, LPWSTR)>
psGetPrivateProfileStructW(0, 0, 0, 0, 0, AR_PATH_INE);

// Write to INI
static path_translator_stdcall<aWritePrivateProfileSectionA, aKernel32, BOOL(LPCTSTR, LPCTSTR, LPCTSTR)>
static path_translator_stdcall<aWritePrivateProfileSectionA, aKernel32, BOOL(LPCSTR, LPCSTR, LPCSTR)>
psWritePrivateProfileSectionA(0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aWritePrivateProfileStringA, aKernel32, BOOL(LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR)>
static path_translator_stdcall<aWritePrivateProfileStringA, aKernel32, BOOL(LPCSTR, LPCSTR, LPCSTR, LPCSTR)>
psWritePrivateProfileStringA(0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aWritePrivateProfileStructA, aKernel32, BOOL(LPCTSTR, LPCTSTR, LPVOID, UINT, LPCTSTR)>
static path_translator_stdcall<aWritePrivateProfileStructA, aKernel32, BOOL(LPCSTR, LPCSTR, LPVOID, UINT, LPCSTR)>
psWritePrivateProfileStructA(0, 0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aWritePrivateProfileSectionW, aKernel32, BOOL(LPCWSTR, LPCWSTR, LPCWSTR)>
psWritePrivateProfileSectionW(0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aWritePrivateProfileStringW, aKernel32, BOOL(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR)>
psWritePrivateProfileStringW(0, 0, 0, 0, AR_PATH_INE);
static path_translator_stdcall<aWritePrivateProfileStructW, aKernel32, BOOL(LPCWSTR, LPCWSTR, LPVOID, UINT, LPCWSTR)>
psWritePrivateProfileStructW(0, 0, 0, 0, 0, AR_PATH_INE);

// Something
static path_translator_stdcall<aGetFileAttributesA, aKernel32, DWORD(LPCTSTR)>
static path_translator_stdcall<aGetFileAttributesA, aKernel32, DWORD(LPCSTR)>
psGetFileAttributesA(0, AR_PATH_INE);
static path_translator_stdcall<aGetFileAttributesExA, aKernel32, DWORD(LPCTSTR, GET_FILEEX_INFO_LEVELS, LPVOID)>
static path_translator_stdcall<aGetFileAttributesExA, aKernel32, DWORD(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID)>
psGetFileAttributesExA(0, AR_PATH_INE, 0, 0);
static path_translator_stdcall<aGetFileAttributesW, aKernel32, DWORD(LPCWSTR)>
psGetFileAttributesW(0, AR_PATH_INE);
static path_translator_stdcall<aGetFileAttributesExW, aKernel32, DWORD(LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID)>
psGetFileAttributesExW(0, AR_PATH_INE, 0, 0);



Expand All @@ -583,19 +634,45 @@ static path_translator_stdcall<aGetFileAttributesExA, aKernel32, DWORD(LPCTSTR,
extern const char aSTDC[] = ""; // Well, the standard library could be any dll...
extern const char afopen[] = "fopen";
extern const char afreopen[] = "freopen";
extern const char afopens[] = "fopen_s";
extern const char afreopens[] = "freopen_s";
extern const char arename[] = "rename";
extern const char aremove[] = "remove";

extern const char awfopen[] = "_wfopen";
extern const char awfreopen[] = "_wfreopen";
extern const char awfopens[] = "_wfopen_s";
extern const char awfreopens[] = "_wfreopen_s";
extern const char awrename[] = "_wrename";
extern const char awremove[] = "_wremove";

// Translators for STDC
static path_translator_cdecl<afopen, aSTDC, void*(const char*, const char*)>
psfopen(0, AR_PATH_INE, 0);
static path_translator_cdecl<afreopen, aSTDC, void*(const char*, const char*, void*)>
psfreopen(0, AR_PATH_INE, 0, 0);
static path_translator_cdecl<afopens, aSTDC, int(void**, const char*, const char*)>
psfopens(0, 0, AR_PATH_INE, 0);
static path_translator_cdecl<afreopens, aSTDC, int(void**, const char*, const char*, void*)>
psfreopens(0, 0, AR_PATH_INE, 0, 0);
static path_translator_cdecl<arename, aSTDC, int(const char*, const char*)>
psrename(0, AR_PATH_INE, AR_PATH_IN);
static path_translator_cdecl<aremove, aSTDC, void*(const char*)>
psremove(0, AR_PATH_INE);

static path_translator_cdecl<awfopen, aSTDC, void*(const wchar_t*, const wchar_t*)>
pswfopen(0, AR_PATH_INE, 0);
static path_translator_cdecl<awfreopen, aSTDC, void*(const wchar_t*, const wchar_t*, void*)>
pswfreopen(0, AR_PATH_INE, 0, 0);
static path_translator_cdecl<awfopens, aSTDC, int(void**, const wchar_t*, const wchar_t*)>
pswfopens(0, 0, AR_PATH_INE, 0);
static path_translator_cdecl<awfreopens, aSTDC, int(void**, const wchar_t*, const wchar_t*, void*)>
pswfreopens(0, 0, AR_PATH_INE, 0, 0);
static path_translator_cdecl<awrename, aSTDC, int(const wchar_t*, const wchar_t*)>
pswrename(0, AR_PATH_INE, AR_PATH_IN);
static path_translator_cdecl<awremove, aSTDC, void*(const wchar_t*)>
pswremove(0, AR_PATH_INE);



/*
Expand All @@ -612,7 +689,14 @@ extern const char aD3DXLoadMeshFromXA[] = "D3DXLoadMeshFromXA";
extern const char aD3DXCreateEffectFromFileA[] = "D3DXCreateEffectFromFileA";
extern const char aD3DXSaveSurfaceToFileA[] = "D3DXSaveSurfaceToFileA";

extern const char aD3DXCreateTextureFromFileW[] = "D3DXCreateTextureFromFileW";
extern const char aD3DXCompileShaderFromFileW[] = "D3DXCompileShaderFromFileW";
extern const char aD3DXAssembleShaderFromFileW[] = "D3DXAssembleShaderFromFileW";
extern const char aD3DXCreateVolumeTextureFromFileW[] = "D3DXCreateVolumeTextureFromFileW";
extern const char aD3DXCreateCubeTextureFromFileW[] = "D3DXCreateCubeTextureFromFileW";
extern const char aD3DXLoadMeshFromXW[] = "D3DXLoadMeshFromXW";
extern const char aD3DXCreateEffectFromFileW[] = "D3DXCreateEffectFromFileW";
extern const char aD3DXSaveSurfaceToFileW[] = "D3DXSaveSurfaceToFileW";



Expand All @@ -635,8 +719,23 @@ static path_translator_stdcall<aD3DXCreateEffectFromFileA, aD3DX, HRESULT(void*,
static path_translator_stdcall<aD3DXSaveSurfaceToFileA, aD3DX, HRESULT(const char*, DWORD, void*, void*, void*)>
psD3DXSaveSurfaceToFileA(0, AR_PATH_IN, 0, 0, 0, 0);

static path_translator_stdcall<aD3DXCreateTextureFromFileW, aD3DX, HRESULT(void*, const wchar_t*, void*)>
psD3DXCreateTextureFromFileW(0, 0, AR_PATH_INE, 0);
static path_translator_stdcall<aD3DXCompileShaderFromFileW, aD3DX, HRESULT(const wchar_t*, const void*, void*, void*, void*, DWORD, void*, void*, void*)>
psD3DXCompileShaderFromFileW(0, AR_PATH_INE, 0, 0, 0, 0, 0, 0, 0, 0);
static path_translator_stdcall<aD3DXAssembleShaderFromFileW, aD3DX, HRESULT(const wchar_t*, void*, void*, DWORD, void*, void*)>
psD3DXAssembleShaderFromFileW(0, AR_PATH_INE, 0, 0, 0, 0, 0);

static path_translator_stdcall<aD3DXCreateVolumeTextureFromFileW, aD3DX, HRESULT(void*, const wchar_t*, void*)>
psD3DXCreateVolumeTextureFromFileW(0, 0, AR_PATH_INE, 0);
static path_translator_stdcall<aD3DXCreateCubeTextureFromFileW, aD3DX, HRESULT(void*, const wchar_t*, void*)>
psD3DXCreateCubeTextureFromFileW(0, 0, AR_PATH_INE, 0);
static path_translator_stdcall<aD3DXLoadMeshFromXW, aD3DX, HRESULT(const wchar_t*, DWORD, void*, void*, void*, void*, void*, void*)>
psD3DXLoadMeshFromXW(0, AR_PATH_INE, 0, 0, 0, 0, 0, 0, 0);
static path_translator_stdcall<aD3DXCreateEffectFromFileW, aD3DX, HRESULT(void*, const wchar_t*, void*, void*, DWORD, void*, void*, void*)>
psD3DXCreateEffectFromFileW(0, 0, AR_PATH_INE, 0, 0, 0, 0, 0, 0);
static path_translator_stdcall<aD3DXSaveSurfaceToFileW, aD3DX, HRESULT(const wchar_t*, DWORD, void*, void*, void*)>
psD3DXSaveSurfaceToFileW(0, AR_PATH_IN, 0, 0, 0, 0);



Expand Down
38 changes: 23 additions & 15 deletions src/plugins/gta3/std.asi/args_translator/translator_basic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,29 +288,37 @@ struct path_translator_base
static const bool bIsWideChar = std::is_same<decayed_type, wchar_t>::value;

// Character independent strings
static const T a1[] = { '%', 's', '\0' }; // "%s"
static const T a2[] = { '%', 's', '\\', '%', 's', '\0' }; // "%s\\%s"
static const T a3[] = { '%', 's', '\\', '%', 's', '\\', // "%s\\%s\\%s" or "%s\\%s\\%ls"
'%', bIsWideChar? 'l' : 's', bIsWideChar? 's' : '\0',
// This got broken badly for wchar_t overload with Visual Studio 2015!
// swprintf %s will expect wchar_t* once again so we need to force char* by passing %hs
// See here:
// https://blogs.msdn.microsoft.com/vcblog/2014/06/18/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/
static const T a1[] = { '%', 'h', 's', '\0' }; // "%hs"
static const T a2[] = { '%', 'h', 's', '\\', '%', 'h', 's', '\0' }; // "%hs\\%hs"
static const T a3[] = { '%', 'h', 's', '\\', '%', 'h', 's', '\\', // "%hs\\%hs\\%hs" or "%hs\\%hs\\%ls"
'%', bIsWideChar? 'l' : 'h', 's',
'\0' };
static const T a0[] = { '%', 's', '\\', // "%s\\%s" or "%s\\%ls"
'%', bIsWideChar? 'l' : 's', bIsWideChar? 's' : '\0',
static const T a0[] = { '%', 'h', 's', '\\', // "%hs\\%hs" or "%hs\\%ls"
'%', bIsWideChar? 'l' : 'h', 's',
'\0' };

#ifndef _MSC_VER
#error Please check if printf formats in TranslatePathChar are compatible on this compiler!
#endif

// Build output string based on received prefixes / suffixes / whatever
if(currdir)
{
if(suffix)
sprintf(out, a3, prefix, currdir, suffix); // "%s\\%s\\%s" or "%s\\%s\\%ls"
sprintf(out, a3, prefix, currdir, suffix); // "%hs\\%hs\\%hs" or "%hs\\%hs\\%ls"
else
sprintf(out, a2, prefix, currdir); // "%s\\%s"
sprintf(out, a2, prefix, currdir); // "%hs\\%hs"
}
else
{
if(suffix)
sprintf(out, a0, prefix, suffix); // "%s\\%s" or "%s\\%ls"
sprintf(out, a0, prefix, suffix); // "%hs\\%hs" or "%hs\\%ls"
else
sprintf(out, a1, prefix); // "%s"
sprintf(out, a1, prefix); // "%hs"
}

// Done
Expand Down Expand Up @@ -449,11 +457,11 @@ struct path_translator_basic : public path_translator_base

if(LibName == aKernel32)
{
bGetModuleFileName = (Symbol == aGetModuleFileNameA);
bSetCurrentDirectory=(Symbol == aSetCurrentDirectoryA);
bCreateFile = (Symbol == aCreateFileA);
bFindFirstFile = (Symbol == aFindFirstFileA);
bFindNextFile = (Symbol == aFindNextFileA);
bGetModuleFileName = (Symbol == aGetModuleFileNameA) || (Symbol == aGetModuleFileNameW);
bSetCurrentDirectory=(Symbol == aSetCurrentDirectoryA) || (Symbol == aSetCurrentDirectoryW);
bCreateFile = (Symbol == aCreateFileA) || (Symbol == aCreateFileW);
bFindFirstFile = (Symbol == aFindFirstFileA) || (Symbol == aFindFirstFileW);
bFindNextFile = (Symbol == aFindNextFileA) || (Symbol == aFindNextFileW);
bFindClose = (Symbol == aFindClose);
bIniOperations = false;
}
Expand Down
6 changes: 6 additions & 0 deletions src/plugins/gta3/std.asi/args_translator/xtranslator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ extern const char aFindFirstFileA[];
extern const char aFindNextFileA[];
extern const char aFindClose[];

extern const char aCreateFileW[];
extern const char aSetCurrentDirectoryW[];
extern const char aGetModuleFileNameW[];
extern const char aFindFirstFileW[];
extern const char aFindNextFileW[];

// Argument type
enum eArgsType
{
Expand Down
13 changes: 12 additions & 1 deletion src/plugins/gta3/std.stream/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,10 @@ void CAbstractStreaming::Patch()
{
plugin_ptr->Log("Initializing the streaming...");

// III/VC reinitialize streaming on reloading
if(!gvm.IsSA())
this->bHasInitializedStreaming = false;

// Pointers
ms_aInfoForModel = ReadMemory<CStreamingInfo*>(0x40D014, true);
LoadCdDirectory2 = ReadRelativeOffset(0x5B8310 + 1).get<void(const char*, int)>();
Expand All @@ -416,13 +420,20 @@ void CAbstractStreaming::Patch()
this->BuildPrevOnCdMap();
tmp_cd_dir.clear();

// Clear imports in case this is not the first launch
this->imports.clear();

// Do custom setup
this->BuildClothesMap(); // Find out clothing hashes and remove clothes from raw_models
this->LoadAbstractCdDirectory(refs_mapped(raw_models)); // Load abstract directory, our custom files

// Mark streaming as initialized
this->bIsFirstLaunched = true;
this->bHasInitializedStreaming = true;
this->raw_models.clear();

// We can discard it in SA but we still need it in III and VC
if(gvm.IsSA())
this->raw_models.clear();
});

// Standard models
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/gta3/std.stream/directory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ void CAbstractStreaming::LoadAbstractCdDirectory(ref_list<const modloader::file*
StreamingBufferUpdater bufup;

// Streaming bus must be empty before this operation
if(this->bHasInitializedStreaming)
if(this->bIsFirstLaunched)
this->FlushChannels();

// Fill entry buffer and advance iterator
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/gta3/std.stream/streaming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ CAbstractStreaming::~CAbstractStreaming()

void CAbstractStreaming::InitialiseStructAbstraction()
{
if(this->bIsFirstLaunched)
return; // We already init this once, no need to do again

this->sizeof_CStreamingInfo = CStreamingInfo::GetSizeof();
this->f92la = Fastman92LimitAdjusterCreate();

Expand Down
Loading