ITexture * VOODOO_METHODTYPE FrostAdapter::CreateTexture(_In_ const String & name, _In_ const TextureDesc pDesc) { GLuint texture; GLint texFmt, texIFmt, texType; switch (pDesc.Format) { case VSFmtRGBA8: texFmt = GL_RGBA; texIFmt = GL_RGBA8; texType = GL_UNSIGNED_BYTE; break; case VSFmtRGB8: texFmt = GL_RGB; texIFmt = GL_RGB8; texType = GL_UNSIGNED_BYTE; break; case VSFmtRGBA16F: texFmt = GL_RGBA; texIFmt = GL_RGBA16F; texType = GL_FLOAT; break; case VSFmtRGBA32F: texFmt = GL_RGBA; texIFmt = GL_RGBA32F; texType = GL_DOUBLE; break; case VSFmtD16: texFmt = GL_DEPTH_COMPONENT; texIFmt = GL_DEPTH_COMPONENT16; texType = GL_FLOAT; break; case VSFmtD32: texFmt = GL_DEPTH_COMPONENT; texIFmt = GL_DEPTH_COMPONENT32; texType = GL_DOUBLE; break; case VSFmtUnknown: default: m_Core->GetLogger()->LogMessage(VSLog_ModWarning, VOODOO_FROST_NAME, VSTR("Unable to resolve texture format.")); return false; } glGenTextures(1, &texture); GLenum error = glGetError(); while (error != GL_NO_ERROR) { m_Core->GetLogger()->LogMessage(VSLog_ModWarning, VOODOO_FROST_NAME, Format("OpenGL returned error %u: %S") << error << glGetString(error)); error = glGetError(); } glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, texIFmt, pDesc.Size.X, pDesc.Size.Y, 0, texFmt, texType, nullptr); glBindTexture(GL_TEXTURE_2D, 0); error = glGetError(); while (error != GL_NO_ERROR) { m_Core->GetLogger()->LogMessage(VSLog_ModWarning, VOODOO_FROST_NAME, Format("OpenGL returned error %u: %S") << error << glGetString(error)); error = glGetError(); } if (glIsTexture(texture)) { m_Core->GetLogger()->LogMessage(VSLog_ModDebug, VOODOO_FROST_NAME, Format("OpenGL texture %u created successfully.") << texture); } else { m_Core->GetLogger()->LogMessage(VSLog_ModDebug, VOODOO_FROST_NAME, Format("OpenGL create failed, returned texture %u.") << texture); } return new FrostTexture(m_Core, name, texture); }
void Jit::Comp_SVQ(u32 op) { CONDITIONAL_DISABLE; int imm = (signed short)(op&0xFFFC); int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5); int rs = _RS; bool doCheck = false; switch (op >> 26) { case 54: //lv.q { // CC might be set by slow path below, so load regs first. u8 vregs[4]; GetVectorRegs(vregs, V_Quad, vt); fpr.MapRegsV(vregs, V_Quad, MAP_DIRTY | MAP_NOINIT); fpr.ReleaseSpillLocks(); if (gpr.IsImm(rs)) { u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF; MOVI2R(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { SetR0ToEffectiveAddress(rs, imm); } else { SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } ADD(R0, R0, R11); } for (int i = 0; i < 4; i++) VLDR(fpr.V(vregs[i]), R0, i * 4); if (doCheck) { SetCC(CC_EQ); MOVI2R(R0, 0); for (int i = 0; i < 4; i++) VMOV(fpr.V(vregs[i]), R0); SetCC(CC_AL); } } break; case 62: //sv.q { // CC might be set by slow path below, so load regs first. u8 vregs[4]; GetVectorRegs(vregs, V_Quad, vt); fpr.MapRegsV(vregs, V_Quad, 0); fpr.ReleaseSpillLocks(); if (gpr.IsImm(rs)) { u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF; MOVI2R(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { SetR0ToEffectiveAddress(rs, imm); } else { SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } ADD(R0, R0, R11); } for (int i = 0; i < 4; i++) VSTR(fpr.V(vregs[i]), R0, i * 4); if (doCheck) { SetCC(CC_AL); } } break; default: DISABLE; break; } }
void Jit::Comp_SV(u32 op) { CONDITIONAL_DISABLE; s32 imm = (signed short)(op&0xFFFC); int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5); int rs = _RS; bool doCheck = false; switch (op >> 26) { case 50: //lv.s // VI(vt) = Memory::Read_U32(addr); { // CC might be set by slow path below, so load regs first. fpr.MapRegV(vt, MAP_DIRTY | MAP_NOINIT); fpr.ReleaseSpillLocks(); if (gpr.IsImm(rs)) { u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF; MOVI2R(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { SetR0ToEffectiveAddress(rs, imm); } else { SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } ADD(R0, R0, R11); } VLDR(fpr.V(vt), R0, 0); if (doCheck) { SetCC(CC_EQ); MOVI2R(R0, 0); VMOV(fpr.V(vt), R0); SetCC(CC_AL); } } break; case 58: //sv.s // Memory::Write_U32(VI(vt), addr); { // CC might be set by slow path below, so load regs first. fpr.MapRegV(vt); fpr.ReleaseSpillLocks(); if (gpr.IsImm(rs)) { u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF; MOVI2R(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { SetR0ToEffectiveAddress(rs, imm); } else { SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } ADD(R0, R0, R11); } VSTR(fpr.V(vt), R0, 0); if (doCheck) { SetCC(CC_AL); } } break; default: DISABLE; } }
void Jit::Comp_FPULS(u32 op) { CONDITIONAL_DISABLE; s32 offset = (s16)(op & 0xFFFF); int ft = _FT; int rs = _RS; // u32 addr = R(rs) + offset; // logBlocks = 1; bool doCheck = false; switch(op >> 26) { case 49: //FI(ft) = Memory::Read_U32(addr); break; //lwc1 fpr.SpillLock(ft); fpr.MapReg(ft, MAP_NOINIT | MAP_DIRTY); if (gpr.IsImm(rs)) { u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF; MOVI2R(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { SetR0ToEffectiveAddress(rs, offset); } else { SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } ADD(R0, R0, R11); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; if (doCheck) { skip = B_CC(CC_EQ); } VLDR(fpr.R(ft), R0, 0); if (doCheck) { SetJumpTarget(skip); SetCC(CC_AL); } #else VLDR(fpr.R(ft), R0, 0); if (doCheck) { SetCC(CC_EQ); MOVI2R(R0, 0); VMOV(fpr.R(ft), R0); SetCC(CC_AL); } #endif fpr.ReleaseSpillLocksAndDiscardTemps(); break; case 57: //Memory::Write_U32(FI(ft), addr); break; //swc1 fpr.MapReg(ft); if (gpr.IsImm(rs)) { u32 addr = (offset + gpr.GetImm(rs)) & 0x3FFFFFFF; MOVI2R(R0, addr + (u32)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { SetR0ToEffectiveAddress(rs, offset); } else { SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } ADD(R0, R0, R11); } #ifdef __ARM_ARCH_7S__ FixupBranch skip2; if (doCheck) { skip2 = B_CC(CC_EQ); } VSTR(fpr.R(ft), R0, 0); if (doCheck) { SetJumpTarget(skip2); SetCC(CC_AL); } #else VSTR(fpr.R(ft), R0, 0); if (doCheck) { SetCC(CC_AL); } #endif break; default: Comp_Generic(op); return; } }
{ public: VSParser(); VOODOO_METHOD_(uint32_t, AddRef)() CONST; VOODOO_METHOD_(uint32_t, Release)() CONST; VOODOO_METHOD(QueryInterface)(_In_ CONST Uuid refid, _Outptr_result_maybenull_ IObject ** ppOut); VOODOO_METHOD_(String, ToString)() CONST; VOODOO_METHOD_(ICore *, GetCore)() CONST; VOODOO_METHOD(Add)(_In_ CONST String & name, _In_ CONST String & value, _In_ CONST VariableType type = VSVar_Normal); VOODOO_METHOD(Remove)(_In_ CONST String & name); VOODOO_METHOD_(String, Parse)(_In_ CONST String & input, _In_ CONST ParseFlags flags = VSParse_None) CONST; static const uint32_t VarMaxDepth = 8; static const wchar_t VarDelimPre = VSTR('$'); static const wchar_t VarDelimStart = VSTR('('); static const wchar_t VarDelimEnd = VSTR(')'); static const wchar_t VarMarkerState = VSTR(':'); static const wchar_t VarMarkerReq = VSTR('!'); static const wchar_t VarMarkerDelay = VSTR('~'); static const wchar_t VarMarkerMode = VSTR('@'); static const wchar_t VarMarkerModeD = VSTR(' '); static const wchar_t VarMarkerModeM = VSTR('+'); static const wchar_t VarMarkerModeR = VSTR('-'); private: // Private these to prevent copying internally (external libs never will). VSParser(CONST VSParser & other); VSParser & operator=(CONST VSParser & other); ~VSParser();
_Check_return_ VOODOO_METHODDEF(VSCore::Init)(_In_z_ CONST wchar_t * config) { if (config) { m_Parser->Add(VSTR("config"), config, VSVar_System); } else { m_Parser->Add(VSTR("config"), VSTR("VoodooShader.xml"), VSVar_System); } // Load variables, built-in first { wchar_t buffer[MAX_PATH]; ZeroMemory(buffer, MAX_PATH); // Global path GetVoodooPath(buffer); m_Parser->Add(VSTR("path"), buffer, VSVar_System); // Bin prefix GetVoodooBinPrefix(buffer); m_Parser->Add(VSTR("prefix"), buffer, VSVar_System); // Framework bin path GetVoodooBinPath(buffer); m_Parser->Add(VSTR("binpath"), buffer, VSVar_System); // Target HMODULE pTarget = GetModuleHandle(NULL); GetModuleFileName(pTarget, buffer, MAX_PATH); m_Parser->Add(VSTR("target"), buffer, VSVar_System); // Local path PathRemoveFileSpec(buffer); PathAddBackslash(buffer); m_Parser->Add(VSTR("local"), buffer, VSVar_System); // Startup path GetCurrentDirectory(MAX_PATH, buffer); PathAddBackslash(buffer); m_Parser->Add(VSTR("startup"), buffer, VSVar_System); GetModuleFileName(gCoreHandle, buffer, MAX_PATH); m_Parser->Add(VSTR("core"), buffer, VSVar_System); } // Command line processing LPWSTR cmdline = GetCommandLine(); m_Parser->Add(VSTR("args"), cmdline, VSVar_System); int cmdargc = 0; LPWSTR * cmdargv = CommandLineToArgvW(cmdline, &cmdargc); m_Parser->Add(VSTR("argc"), StringFormat(VSTR("%d")) << cmdargc, VSVar_System); for (int i = 0; i < cmdargc; ++i) { m_Parser->Add(StringFormat(VSTR("argv_%d")) << i, cmdargv[i], VSVar_System); } // Load the config try { m_ConfigFile = new pugi::xml_document(); // Try loading the config file from each major location String configPath = m_Parser->Parse(VSTR("$(config)"), VSParse_PathCanon); pugi::xml_parse_result result = m_ConfigFile->load_file(configPath.GetData()); if (!result) { configPath = m_Parser->Parse(VSTR("$(startup)\\$(config)"), VSParse_PathCanon); result = m_ConfigFile->load_file(configPath.GetData()); if (!result) { configPath = m_Parser->Parse(VSTR("$(local)\\$(config)"), VSParse_PathCanon); result = m_ConfigFile->load_file(configPath.GetData()); if (!result) { configPath = m_Parser->Parse(VSTR("$(path)\\$(config)"), VSParse_PathCanon); result = m_ConfigFile->load_file(configPath.GetData()); if (!result) { Throw(VOODOO_CORE_NAME, VSTR("Unable to find or parse config file."), nullptr); } } } } // Start setting things up pugi::xml_node configRoot = static_cast<pugi::xml_node>(*m_ConfigFile); pugi::xml_node globalNode = configRoot.select_single_node(L"/VoodooConfig/Global").node(); if (!globalNode) { Throw(VOODOO_CORE_NAME, VSTR("Could not find global config node."), nullptr); } // Create query for node text, used multiple times pugi::xpath_query xpq_getName(L"./@name"); pugi::xpath_query xpq_getText(L"./text()"); // Load variables { pugi::xpath_query xpq_getVariables(L"./Variables/Variable"); pugi::xpath_node_set nodes = xpq_getVariables.evaluate_node_set(globalNode); pugi::xpath_node_set::const_iterator iter = nodes.begin(); while (iter != nodes.end()) { String name = xpq_getName.evaluate_string(*iter).c_str(); String value = xpq_getText.evaluate_string(*iter).c_str(); m_Parser->Add(name, value); ++iter; } } // Open the logger as early as possible pugi::xpath_query logfQuery(L"./Log/File/text()"); pugi::xpath_query logaQuery(L"./Log/Append/text()"); pugi::xpath_query loglQuery(L"./Log/Level/text()"); String logFile = m_Parser->Parse(logfQuery.evaluate_string(globalNode)); String logLevelStr = m_Parser->Parse(loglQuery.evaluate_string(globalNode)); String logAppendStr = m_Parser->Parse(logaQuery.evaluate_string(globalNode)); LogLevel logLevel = VSLog_Default; try { logLevel = (LogLevel)stoi(logLevelStr.ToString()); } catch (const std::exception & exc) { UNREFERENCED_PARAMETER(exc); logLevel = VSLog_Default; } bool logAppend = logAppendStr.Compare(VSTR("true"), false) || logAppendStr.StartsWith("1"); m_Logger->Open(logFile, logAppend); m_Logger->SetFilter(logLevel); // Log extended build information String configMsg = m_Parser->Parse(VSTR("Config loaded from '$(config)'.")); m_Logger->LogMessage(VSLog_CoreNotice, VOODOO_CORE_NAME, configMsg); m_Logger->LogMessage(VSLog_CoreNotice, VOODOO_CORE_NAME, VOODOO_GLOBAL_COPYRIGHT_FULL); // Load plugins, starting with the core m_Server->LoadPlugin(this, VSTR("$(core)")); { pugi::xpath_query xpq_getPluginPaths(L"./Plugins/Path"); pugi::xpath_query xpq_getFilter(L"./@filter"); pugi::xpath_node_set nodes = xpq_getPluginPaths.evaluate_node_set(globalNode); pugi::xpath_node_set::const_iterator iter = nodes.begin(); while (iter != nodes.end()) { String filter = xpq_getFilter.evaluate_string(*iter); String path = xpq_getText.evaluate_string(*iter); m_Server->LoadPath(this, path, filter); ++iter; } } { pugi::xpath_query xpq_getPluginFiles(L"./Plugins/File"); pugi::xpath_node_set nodes = xpq_getPluginFiles.evaluate_node_set(globalNode); pugi::xpath_node_set::const_iterator iter = nodes.begin(); while (iter != nodes.end()) { String file = xpq_getText.evaluate_string(*iter); m_Server->LoadPlugin(this, file); ++iter; } } // Lookup classes pugi::xpath_query fsQuery(L"./Classes/FileSystem/text()"); pugi::xpath_query hookQuery(L"./Classes/HookManager/text()"); String fsClass = m_Parser->Parse(fsQuery.evaluate_string(globalNode).c_str()); String hookClass = m_Parser->Parse(hookQuery.evaluate_string(globalNode).c_str()); // Load less vital classes ObjectRef coreplugin = m_Server->CreateObject(this, hookClass); IHookManager * phm = nullptr; if (coreplugin && SUCCEEDED(coreplugin->QueryInterface(IID_IHookManager, (IObject**)&phm)) && phm) { m_HookManager = phm; phm->Release(); } else { StringFormat fmt(VSTR("Unable to create hook manager (class %1%).")); fmt << hookClass; Throw(VOODOO_CORE_NAME, fmt, this); } coreplugin = m_Server->CreateObject(this, fsClass); IFileSystem * pfs = nullptr; if (coreplugin && SUCCEEDED(coreplugin->QueryInterface(IID_IFileSystem, (IObject**)&pfs)) && pfs) { m_FileSystem = pfs; pfs->Release(); } else { StringFormat fmt(VSTR("Unable to create file system (class %1%).")); fmt << fsClass; Throw(VOODOO_CORE_NAME, fmt, this); } // ICore done loading m_Logger->LogMessage(VSLog_CoreInfo, VOODOO_CORE_NAME, VSTR("Core initialization complete.")); // Call finalization events this->CallEvent(EventIds::Finalize, 0, nullptr); // Return return VSF_OK; } catch (const Exception & exc) { if (m_Logger) { m_Logger->LogMessage(VSLog_CoreError, VOODOO_CORE_NAME, StringFormat(VSTR("Exception during Core creation: %1%")) << exc.strwhat()); } else { GlobalLog(VSTR("Unlogged exception during core creation: %S\n"), exc.what()); } return VSF_FAIL; } catch (const std::exception & exc) { if (m_Logger) { m_Logger->LogMessage(VSLog_CoreError, VOODOO_CORE_NAME, StringFormat(VSTR("Error during Core creation: %1%")) << exc.what()); } else { GlobalLog(VSTR("Unlogged exception during core creation: %S\n"), exc.what()); } return VSF_FAIL; } }