Skip to content

Commit

Permalink
Merge pull request #59 from CookiePLMonster/master
Browse files Browse the repository at this point in the history
Fixes #60 and adds support for Wide WinAPI on path translators
  • Loading branch information
thelink2012 authored Nov 12, 2016
2 parents 38d9c46 + a08331c commit c236933
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 46 deletions.
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

0 comments on commit c236933

Please sign in to comment.