Replace Windows API to SimpleIni class

Plus also replace spaces to tabs in edited functions.
This commit is contained in:
RadWolfie 2018-09-03 21:46:57 -05:00
parent eff6da7551
commit de347a1719
1 changed files with 164 additions and 176 deletions

View File

@ -29,6 +29,7 @@
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
// * (c) 2017-2018 RadWolfie
// *
// * All rights reserved
// *
@ -55,9 +56,30 @@
#include <unordered_map>
#include <map>
#include <sstream>
#include <clocale>
static const char* section_info = "Info";
static struct {
const char* SymbolDatabaseVersionHash = "SymbolDatabaseVersionHash";
} sect_info_keys;
static const char* section_certificate = "Certificate";
static struct {
const char* Name = "Name";
const char* TitleID = "TitleID";
const char* TitleIDHex = "TitleIDHex";
const char* Region = "Region";
} sect_certificate_keys;
static const char* section_libs = "Libs";
static struct {
const char* BuildVersion = "BuildVersion";
} sect_libs_keys;
static const char* section_symbols = "Symbols";
std::map<std::string, xbaddr> g_SymbolAddresses;
bool g_HLECacheUsed = false;
bool g_SymbolCacheUsed = false;
// D3D build version
uint32 g_BuildVersion = 0;
@ -74,7 +96,7 @@ void* GetXboxFunctionPointer(std::string functionName)
return ptr;
}
// If we got here, the function wasn't patched, so we can just look it up the HLE cache
// If we got here, the function wasn't patched, so we can just look it up the symbol cache
// and return the correct offset
auto symbol = g_SymbolAddresses.find(functionName);
if (symbol != g_SymbolAddresses.end()) {
@ -140,7 +162,7 @@ bool VerifySymbolAddressAgainstXRef(char *SymbolName, xbaddr Address, int XRef)
return false;
}*/
// x1nixmzeng: Hack to notify CxbxDebugger of the HLECache file, which is currently a hashed XBE header AND stripped title (see EmuHLEIntercept)
// x1nixmzeng: Hack to notify CxbxDebugger of the SymbolCache file, which is currently a hashed XBE header AND stripped title (see EmuHLEIntercept)
class CxbxDebuggerScopedMessage
{
std::string& message;
@ -202,7 +224,7 @@ void CDECL EmuRegisterSymbol(const char* library_str,
// Output some details
std::stringstream output;
output << "HLE: 0x" << std::setfill('0') << std::setw(8) << std::hex << func_addr
output << "Symbol: 0x" << std::setfill('0') << std::setw(8) << std::hex << func_addr
<< " -> " << symbol_str << " " << std::dec << revision;
#if 0 // TODO: XbSymbolDatabase - Need to create a structure for patch and stuff.
@ -274,7 +296,7 @@ void CDECL EmuRegisterSymbol(const char* library_str,
printf(output.str().c_str());
}
// TODO: Move this into a function rather than duplicating from HLE scanning code
// TODO: Move this into a function rather than duplicating from Symbol scanning code
void EmuD3D_Init_DeferredStates()
{
if (g_SymbolAddresses.find("D3DDeferredRenderState") != g_SymbolAddresses.end()) {
@ -298,7 +320,7 @@ void EmuD3D_Init_DeferredStates()
}
// Update shared structure with GUI process
uint EmuUpdateLLEStatus(uint32_t XbLibScan)
void EmuUpdateLLEStatus(uint32_t XbLibScan)
{
uint FlagsLLE;
g_EmuShared->GetFlagsLLE(&FlagsLLE);
@ -326,168 +348,152 @@ uint EmuUpdateLLEStatus(uint32_t XbLibScan)
}
#endif
ipc_send_gui_update(IPC_UPDATE_GUI::LLE_FLAGS, FlagsLLE);
return FlagsLLE;
//return FlagsLLE;
}
// NOTE: EmuHLEIntercept do not get to be in XbSymbolDatabase, do the intecept in Cxbx project only.
void EmuHLEIntercept(Xbe::Header *pXbeHeader)
{
// NOTE: Increase this revision number any time we changed something inside Cxbx-Reloaded.
int revisionCache = 5;
Xbe::LibraryVersion *pLibraryVersion = (Xbe::LibraryVersion*)pXbeHeader->dwLibraryVersionsAddr;
Xbe::LibraryVersion *pLibraryVersion = (Xbe::LibraryVersion*)pXbeHeader->dwLibraryVersionsAddr;
uint16 xdkVersion = 0;
uint32_t XbLibScan = 0;
uint16 xdkVersion = 0;
uint32_t XbLibScan = 0;
// NOTE: We need to check if title has library header to optimize verification process.
if (pLibraryVersion != nullptr) {
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
const char* SectionName = nullptr;
Xbe::SectionHeader* pSectionHeaders = (Xbe::SectionHeader*)pXbeHeader->dwSectionHeadersAddr;
// NOTE: We need to check if title has library header to optimize verification process.
if (pLibraryVersion != nullptr) {
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
const char* SectionName = nullptr;
Xbe::SectionHeader* pSectionHeaders = (Xbe::SectionHeader*)pXbeHeader->dwSectionHeadersAddr;
// Get the highest revision build and prefix library to scan.
for (uint32 v = 0; v < dwLibraryVersions; v++) {
uint16 BuildVersion = pLibraryVersion[v].wBuildVersion;
uint16 QFEVersion = pLibraryVersion[v].wFlags.QFEVersion;
// Get the highest revision build and prefix library to scan.
for (uint32 v = 0; v < dwLibraryVersions; v++) {
uint16 BuildVersion = pLibraryVersion[v].wBuildVersion;
uint16 QFEVersion = pLibraryVersion[v].wFlags.QFEVersion;
if (xdkVersion < BuildVersion) {
xdkVersion = BuildVersion;
}
XbLibScan |= XbSymbolLibrayToFlag(std::string(pLibraryVersion[v].szName, pLibraryVersion[v].szName + 8).c_str());
}
if (xdkVersion < BuildVersion) {
xdkVersion = BuildVersion;
}
XbLibScan |= XbSymbolLibrayToFlag(std::string(pLibraryVersion[v].szName, pLibraryVersion[v].szName + 8).c_str());
}
// Since XDK 4039 title does not have library version for DSOUND, let's check section header if it exists or not.
for (unsigned int v = 0; v < pXbeHeader->dwSections; v++) {
SectionName = (const char*)pSectionHeaders[v].dwSectionNameAddr;
if (strncmp(SectionName, Lib_DSOUND, 8) == 0) {
XbLibScan |= XbSymbolLib_DSOUND;
break;
}
}
}
// Since XDK 4039 title does not have library version for DSOUND, let's check section header if it exists or not.
for (unsigned int v = 0; v < pXbeHeader->dwSections; v++) {
SectionName = (const char*)pSectionHeaders[v].dwSectionNameAddr;
if (strncmp(SectionName, Lib_DSOUND, 8) == 0) {
XbLibScan |= XbSymbolLib_DSOUND;
break;
}
}
}
EmuUpdateLLEStatus(XbLibScan);
uint gFlagsLLE = EmuUpdateLLEStatus(XbLibScan);
std::cout << "\n"
"*******************************************************************************\n"
"* Cxbx-Reloaded High Level Emulation database\n"
"*******************************************************************************\n"
<< std::endl;
printf("\n");
printf("*******************************************************************************\n");
printf("* Cxbx-Reloaded High Level Emulation database\n");
printf("*******************************************************************************\n");
printf("\n");
// Make sure the Symbol Cache directory exists
std::string cachePath = std::string(szFolder_CxbxReloadedData) + "\\SymbolCache\\";
if (!std::experimental::filesystem::exists(cachePath) && !std::experimental::filesystem::create_directory(cachePath)) {
CxbxKrnlCleanup(LOG_PREFIX, "Couldn't create Cxbx-Reloaded SymbolCache folder!");
}
// Make sure the HLE Cache directory exists
std::string cachePath = std::string(szFolder_CxbxReloadedData) + "\\HLECache\\";
int result = SHCreateDirectoryEx(nullptr, cachePath.c_str(), nullptr);
if ((result != ERROR_SUCCESS) && (result != ERROR_ALREADY_EXISTS)) {
CxbxKrnlCleanup(LOG_PREFIX, "Couldn't create Cxbx-Reloaded HLECache folder!");
}
// Hash the loaded XBE's header, use it as a filename
uint32_t uiHash = XXHash32::hash((void*)&CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header), 0);
std::stringstream sstream;
char tAsciiTitle[40] = "Unknown";
std::setlocale(LC_ALL, "English");
std::wcstombs(tAsciiTitle, g_pCertificate->wszTitleName, sizeof(tAsciiTitle));
std::string szTitleName(tAsciiTitle);
CxbxKrnl_Xbe->PurgeBadChar(szTitleName);
sstream << cachePath << szTitleName << "-" << std::hex << uiHash << ".ini";
std::string filename = sstream.str();
// Hash the loaded XBE's header, use it as a filename
uint32_t uiHash = XXHash32::hash((void*)&CxbxKrnl_Xbe->m_Header, sizeof(Xbe::Header), 0);
std::stringstream sstream;
char tAsciiTitle[40] = "Unknown";
setlocale(LC_ALL, "English");
wcstombs(tAsciiTitle, g_pCertificate->wszTitleName, sizeof(tAsciiTitle));
std::string szTitleName(tAsciiTitle);
CxbxKrnl_Xbe->PurgeBadChar(szTitleName);
sstream << cachePath << szTitleName << "-" << std::hex << uiHash << ".ini";
std::string filename = sstream.str();
// This will fire when we exit this function scope; either after detecting a previous cache file, or when one is created
CxbxDebuggerScopedMessage symbolCacheFilename(filename);
// This will fire when we exit this function scope; either after detecting a previous cache file, or when one is created
CxbxDebuggerScopedMessage hleCacheFilename(filename);
CSimpleIniA symbolCacheData;
if (PathFileExists(filename.c_str())) {
printf("Found HLE Cache File: %08X.ini\n", uiHash);
if (std::experimental::filesystem::exists(filename.c_str())) {
std::printf("Found Symbol Cache File: %08X.ini\n", uiHash);
g_BuildVersion = GetPrivateProfileInt("Libs", "D3D8_BuildVersion", 0, filename.c_str());
symbolCacheData.LoadFile(filename.c_str());
// Verify the version of the cache file against the HLE Database
const uint32 HLECacheHash = GetPrivateProfileInt("Info", "HLECacheHash", 0, filename.c_str());
g_BuildVersion = symbolCacheData.GetLongValue(section_libs, sect_libs_keys.BuildVersion, /*Default=*/0);
if (HLECacheHash == XbSymbolLibraryVersion()) {
char buffer[SHRT_MAX] = { 0 };
char* bufferPtr = buffer;
g_HLECacheUsed = true;
// Verify the version of the cache file against the Symbol Database version hash
const uint32 SymbolDatabaseVersionHash = symbolCacheData.GetLongValue(section_info, sect_info_keys.SymbolDatabaseVersionHash, /*Default=*/0);
const uint32 cacheRevision = GetPrivateProfileInt("Info", "revision", 0, filename.c_str());
if (SymbolDatabaseVersionHash == XbSymbolLibraryVersion()) {
g_SymbolCacheUsed = true;
CSimpleIniA::TNamesDepend symbol_names;
if (cacheRevision != revisionCache) {
g_HLECacheUsed = false;
}
if (g_SymbolCacheUsed) {
std::printf("Using Symbol Cache\n");
if (g_HLECacheUsed) {
printf("Using HLE Cache\n");
// Parse the .INI file into the map of symbol addresses
symbolCacheData.GetAllKeys(section_symbols, symbol_names);
for (auto it = symbol_names.begin(); it != symbol_names.end(); ++it) {
g_SymbolAddresses[it->pItem] = symbolCacheData.GetLongValue(section_symbols, it->pItem, /*Default=*/0);
}
GetPrivateProfileSection("Symbols", buffer, sizeof(buffer), filename.c_str());
// Iterate through the map of symbol addresses, calling GetEmuPatchAddr on all functions.
for (auto it = g_SymbolAddresses.begin(); it != g_SymbolAddresses.end(); ++it) {
std::string functionName = (*it).first;
xbaddr location = (*it).second;
// Parse the .INI file into the map of symbol addresses
while (strlen(bufferPtr) > 0) {
std::string ini_entry(bufferPtr);
std::stringstream output;
output << "SymbolCache: 0x" << std::setfill('0') << std::setw(8) << std::hex << location
<< " -> " << functionName << "\n";
std::printf(output.str().c_str());
}
auto separator = ini_entry.find('=');
std::string key = ini_entry.substr(0, separator);
std::string value = ini_entry.substr(separator + 1, std::string::npos);
uint32_t addr = strtol(value.c_str(), 0, 16);
// Fix up Render state and Texture States
if (g_SymbolAddresses.find("D3DDeferredRenderState") == g_SymbolAddresses.end()
|| g_SymbolAddresses["D3DDeferredRenderState"] == 0) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuD3DDeferredRenderState was not found!");
}
g_SymbolAddresses[key] = addr;
bufferPtr += strlen(bufferPtr) + 1;
}
if (g_SymbolAddresses.find("D3DDeferredTextureState") == g_SymbolAddresses.end()
|| g_SymbolAddresses["D3DDeferredTextureState"] == 0) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuD3DDeferredTextureState was not found!");
}
// Iterate through the map of symbol addresses, calling GetEmuPatchAddr on all functions.
for (auto it = g_SymbolAddresses.begin(); it != g_SymbolAddresses.end(); ++it) {
std::string functionName = (*it).first;
xbaddr location = (*it).second;
if (g_SymbolAddresses.find("D3DDEVICE") == g_SymbolAddresses.end()
|| g_SymbolAddresses["D3DDEVICE"] == 0) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "D3DDEVICE was not found!");
}
std::stringstream output;
output << "HLECache: 0x" << std::setfill('0') << std::setw(8) << std::hex << location
<< " -> " << functionName << "\n";
printf(output.str().c_str());
}
EmuD3D_Init_DeferredStates();
}
}
// Fix up Render state and Texture States
if (g_SymbolAddresses.find("D3DDeferredRenderState") == g_SymbolAddresses.end()
|| g_SymbolAddresses["D3DDeferredRenderState"] == 0) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuD3DDeferredRenderState was not found!");
}
// If g_SymbolAddresses didn't get filled, then symbol cache is invalid
if (g_SymbolAddresses.empty()) {
std::printf("Symbol Cache file is outdated and will be regenerated\n");
g_SymbolCacheUsed = false;
}
}
if (g_SymbolAddresses.find("D3DDeferredTextureState") == g_SymbolAddresses.end()
|| g_SymbolAddresses["D3DDeferredTextureState"] == 0) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "EmuD3DDeferredTextureState was not found!");
}
if (g_SymbolAddresses.find("D3DDEVICE") == g_SymbolAddresses.end()
|| g_SymbolAddresses["D3DDEVICE"] == 0) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "D3DDEVICE was not found!");
}
EmuD3D_Init_DeferredStates();
}
}
// If g_SymbolAddresses didn't get filled, the HLE cache is invalid
if (g_SymbolAddresses.empty()) {
printf("HLE Cache file is outdated and will be regenerated\n");
g_HLECacheUsed = false;
}
}
// If the HLE Cache was used, go straight to patching, no need to re-scan
if (g_HLECacheUsed) {
// If the Symbol Cache was used, go straight to patching, no need to re-scan
if (g_SymbolCacheUsed) {
EmuInstallPatches();
return;
}
}
//
// initialize Microsoft XDK emulation
//
if(pLibraryVersion != nullptr) {
//
// initialize Microsoft XDK emulation
//
if(pLibraryVersion != nullptr) {
printf("HLE: Detected Microsoft XDK application...\n");
std::printf("Symbol: Detected Microsoft XDK application...\n");
// TODO: Is this enough for alias? We need to verify it.
if ((XbLibScan & XbSymbolLib_D3D8) > 0 || (XbLibScan & XbSymbolLib_D3D8LTCG) > 0) {
g_BuildVersion = xdkVersion;
}
// TODO: Is this enough for alias? We need to verify it.
if ((XbLibScan & XbSymbolLib_D3D8) > 0 || (XbLibScan & XbSymbolLib_D3D8LTCG) > 0) {
g_BuildVersion = xdkVersion;
}
#if 0 // NOTE: This is a note for what we should do for above.
if (BuildVersion >= 5558 && BuildVersion <= 5659 && QFEVersion > 1) {
EmuLog(LOG_PREFIX, LOG_LEVEL::WARNING, "D3D8 version 1.0.%d.%d Title Detected: This game uses an alias version 1.0.5788", BuildVersion, QFEVersion);
@ -520,61 +526,43 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
}
#endif
XbSymbolSetOutputMessage(EmuOutputMessage);
XbSymbolSetOutputMessage(EmuOutputMessage);
XbSymbolScan(pXbeHeader, EmuRegisterSymbol);
XbSymbolScan(pXbeHeader, EmuRegisterSymbol);
EmuD3D_Init_DeferredStates();
}
EmuD3D_Init_DeferredStates();
}
printf("\n");
std::printf("\n");
// Write the HLE Database version string
{
std::string HLECacheHashString = std::to_string(XbSymbolLibraryVersion());
WritePrivateProfileString("Info", "HLECacheHash", HLECacheHashString.c_str(), filename.c_str());
}
// Perform a reset just in case a cached file data still exist.
symbolCacheData.Reset();
// Store Symbol Database version
symbolCacheData.SetLongValue(section_info, sect_info_keys.SymbolDatabaseVersionHash, XbSymbolLibraryVersion(), nullptr, /*UseHex =*/false);
std::stringstream revision;
revision << std::dec << revisionCache;
WritePrivateProfileString("Info", "revision", revision.str().c_str(), filename.c_str());
// Store Certificate Details
symbolCacheData.SetValue(section_certificate, sect_certificate_keys.Name, tAsciiTitle);
symbolCacheData.SetValue(section_certificate, sect_certificate_keys.TitleID, FormatTitleId(g_pCertificate->dwTitleId).c_str());
symbolCacheData.SetLongValue(section_certificate, sect_certificate_keys.TitleIDHex, g_pCertificate->dwTitleId, nullptr, /*UseHex =*/true);
symbolCacheData.SetLongValue(section_certificate, sect_certificate_keys.Region, g_pCertificate->dwGameRegion, nullptr, /*UseHex =*/true);
std::stringstream flagsLLE;
flagsLLE << std::dec << gFlagsLLE;
WritePrivateProfileString("Info", "FlagsLLE", flagsLLE.str().c_str(), filename.c_str());
// Store Library Details
for (uint i = 0; i < pXbeHeader->dwLibraryVersions; i++) {
std::string LibraryName(pLibraryVersion[i].szName, pLibraryVersion[i].szName + 8);
symbolCacheData.SetLongValue(section_libs, LibraryName.c_str(), pLibraryVersion[i].wBuildVersion, nullptr, /*UseHex =*/false);
}
// Write the Certificate Details to the cache file
WritePrivateProfileString("Certificate", "Name", tAsciiTitle, filename.c_str());
WritePrivateProfileString("Certificate", "TitleID", FormatTitleId(g_pCertificate->dwTitleId).c_str(), filename.c_str());
symbolCacheData.SetLongValue(section_libs, sect_libs_keys.BuildVersion, g_BuildVersion, nullptr, /*UseHex =*/false);
std::stringstream titleIdHex;
titleIdHex << std::hex << g_pCertificate->dwTitleId;
WritePrivateProfileString("Certificate", "TitleIDHex", titleIdHex.str().c_str(), filename.c_str());
// Store detected symbol addresses
for(auto it = g_SymbolAddresses.begin(); it != g_SymbolAddresses.end(); ++it) {
symbolCacheData.SetLongValue(section_symbols, it->first.c_str(), it->second, nullptr, /*UseHex =*/true);
}
std::stringstream region;
region << std::hex << g_pCertificate->dwGameRegion;
WritePrivateProfileString("Certificate", "Region", region.str().c_str(), filename.c_str());
// Save data to unique symbol cache file
symbolCacheData.SaveFile(filename.c_str());
// Write Library Details
for (uint i = 0; i < pXbeHeader->dwLibraryVersions; i++) {
std::string LibraryName(pLibraryVersion[i].szName, pLibraryVersion[i].szName + 8);
std::stringstream buildVersion;
buildVersion << pLibraryVersion[i].wBuildVersion;
WritePrivateProfileString("Libs", LibraryName.c_str(), buildVersion.str().c_str(), filename.c_str());
}
std::stringstream buildVersion;
buildVersion << g_BuildVersion;
WritePrivateProfileString("Libs", "D3D8_BuildVersion", buildVersion.str().c_str(), filename.c_str());
// Write the found symbol addresses into the cache file
for(auto it = g_SymbolAddresses.begin(); it != g_SymbolAddresses.end(); ++it) {
std::stringstream cacheAddress;
cacheAddress << std::hex << (*it).second;
WritePrivateProfileString("Symbols", (*it).first.c_str(), cacheAddress.str().c_str(), filename.c_str());
}
EmuInstallPatches();
}