void TrySkipPatch() { //Check for arguments and write them in gStartupSettings ParseArgs(splitCmdArgsW(std::wstring(GetCommandLineW()))); // If we have stdin/stdout, attach to the IPC server ipcServer.AttachStdinStdout(); if (gStartupSettings.patch){ PATCH(0x8BECF2).NOP_PAD_TO_SIZE<0x1B5>().Apply(); //nop out the loader code *(WORD*)(0xB25046) = -1; //set run to true PATCH(0x8BED00).CALL(&InitHook).Apply(); } // Init freeimage: gFreeImgInit.init(); // Insert callback for patching which must occur after the runtime has started // (0x8BEC61 is not quite as early as would be ideal for this, but it's convenient) PATCH(0x8BEC61).CALL(&LatePatch).Apply(); //Load graphics from the HardcodedGraphicsManager HardcodedGraphicsManager::loadGraphics(); // Either in root or in config folder. The config folder is recommended however. gGeneralConfig.setFilename(getLatestConfigFile(L"luna.ini")); gGeneralConfig.loadOrDefault(); //game.ini reader GameConfiguration::runPatchByIni(INIReader(WStr2Str(getLatestConfigFile(L"game.ini")))); /************************************************************************/ /* Simple ASM Source Patches */ /************************************************************************/ fixup_TypeMismatch13(); fixup_Credits(); fixup_Mushbug(); fixup_Veggibug(); fixup_NativeFuncs(); fixup_BGODepletion(); /************************************************************************/ /* Replaced Imports */ /************************************************************************/ IMP_vbaStrCmp = &replacement_VbaStrCmp; /************************************************************************/ /* Set Hook */ /************************************************************************/ HookWnd = SetWindowsHookExA(WH_CALLWNDPROC, MsgHOOKProc, (HINSTANCE)NULL, GetCurrentThreadId()); if (!HookWnd){ DWORD errCode = GetLastError(); std::string errCmd = "Failed to Hook"; errCmd += "\nErr-Code: "; errCmd += std::to_string((long long)errCode); MessageBoxA(NULL, errCmd.c_str(), "Failed to Hook", NULL); } KeyHookWnd = SetWindowsHookExA(WH_KEYBOARD, KeyHOOKProc, (HINSTANCE)NULL, GetCurrentThreadId()); if (!KeyHookWnd){ DWORD errCode = GetLastError(); std::string errCmd = "Failed to Hook"; errCmd += "\nErr-Code: "; errCmd += std::to_string((long long)errCode); MessageBoxA(NULL, errCmd.c_str(), "Failed to Hook", NULL); } /************************************************************************/ /* Source Code Function Patch */ /************************************************************************/ PATCH(0x8D9446) .CALL(&OnLvlLoad) .NOP() .NOP() .Apply(); PATCH(0x8CA23B) .CALL(&TestFunc) .NOP() .Apply(); PATCH(0x92EC24) .CALL(&LevelHUDHook) .Apply(); *(void**)0xB2F244 = (void*)&mciSendStringHookA; PATCH(0x8D6BB6).CALL(&forceTermination).Apply(); PATCH(0x8C11D5).CALL(&LoadWorld).Apply(); PATCH(0x8C16F7).CALL(&WorldLoop).Apply(); PATCH(0x8C0E6D).CALL(&LoadIntro).Apply(); PATCH(0x932353).CALL(&printLunaLuaVersion).Apply(); PATCH(0x9090F5).CALL(&WorldRender).Apply(); PATCH(0x9204E5).CALL(&NPCKillHook).Apply(); PATCH(0x9B4E35).CALL(&NPCKillHook).Apply(); PATCH(0xA0664E).CALL(&NPCKillHook).Apply(); PATCH(0xA23278).CALL(&NPCKillHook).Apply(); PATCH(0xAA4352) .CALL(&__vbaStrCmp_TriggerSMBXEventHook) .NOP() .Apply(); PATCH(0x8C23CB) .CALL(&checkLevelShutdown) .NOP() .NOP() .Apply(); PATCH(0xA755D2).CALL(&UpdateInputHook_Wrapper).Apply(); PATCH(0x902D3D).CALL(&WorldOverlayHUDBitBltHook).Apply(); PATCH(0x902DFC).CALL(&WorldOverlayHUDBitBltHook).Apply(); PATCH(0x902EBB).CALL(&WorldOverlayHUDBitBltHook).Apply(); PATCH(0x902F80).CALL(&WorldOverlayHUDBitBltHook).Apply(); PATCH(0x908995).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9087A8).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9085BB).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9083CE).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x908115).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x907F28).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x907D3B).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x907B4E).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9077FD).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x907537).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9072B2).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x90702D).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x906DB2).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9055CE).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x905304).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9051A7).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x905055).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x904F24).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x908995).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x904D4F).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9062E0).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x906183).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x906031).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x905F00).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x905D29).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x905990).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9065DE).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x906973).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x90499A).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9046D0).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x904573).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x904421).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9042F0).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x90411B).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x906B31).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x903D66).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9063FF).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x903A9C).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x90393F).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9037ED).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9036BC).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9034E7).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9032E9).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x90323D).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x90319F).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9030F2).CALL(&WorldIconsHUDBitBltHook).Apply(); PATCH(0x9000B2).CALL(&WorldHUDIsOnCameraHook).Apply(); PATCH(0x900235).CALL(&WorldHUDIsOnCameraHook).Apply(); PATCH(0x9004B7).CALL(&WorldHUDIsOnCameraHook).Apply(); PATCH(0x90068F).CALL(&WorldHUDIsOnCameraHook).Apply(); PATCH(0x901439).CALL(&WorldHUDPrintTextController).Apply(); PATCH(0x90266A).CALL(&WorldHUDPrintTextController).Apply(); PATCH(0x907611).CALL(&WorldHUDPrintTextController).Apply(); PATCH(0x9081E7).CALL(&WorldHUDPrintTextController).Apply(); PATCH(0x908B03).CALL(&WorldHUDPrintTextController).Apply(); PATCH(0x908A67).CALL(&WorldHUDPrintTextController).Apply(); PATCH(0x909217).CALL(&GenerateScreenshotHook).Apply(); PATCH(0x94D5E7).CALL(&GenerateScreenshotHook).Apply(); PATCH(0x8C03DC).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x8C0A1A).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x8C1383).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x8C1953).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x8CE292).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x8E61BD).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x8FE8D4).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x987E94).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0x9B7B2C).CALL(&InitLevelEnvironmentHook).Apply(); PATCH(0xA02AD3).CALL(&InitLevelEnvironmentHook).Apply(); // Graphics Bitblt hooks PATCH(0x8C137E).CALL(&LoadLocalGfxHook).Apply(); PATCH(0x8D8BF1).CALL(&LoadLocalGfxHook).Apply(); PATCH(0x8D9611).CALL(&LoadLocalGfxHook).Apply(); PATCH(0x8DF52B).CALL(&LoadLocalGfxHook).Apply(); PATCH(0x8DFF7C).CALL(&LoadLocalGfxHook).Apply(); PATCH(0x8DEF73).CALL(&LoadLocalOverworldGfxHook).Apply(); PATCH(0x8DF808).CALL(&LoadLocalOverworldGfxHook).Apply(); //PATCH(0x4242D0).JMP(GET_RETADDR_TRACE_HOOK<&BitBltTraceHook>()).Apply(); PATCH(0x4242D0).JMP(&BitBltHook).Apply(); PATCH(0x424314).JMP(&StretchBltHook).Apply(); PATCH(0x8E54EC) .CALL(&MessageBoxOpenHook) .NOP() .Apply(); // Okay redigit, I know your debug values are in general pretty dumb, but right now they are awesome for easy patching! Thx mate! PATCH(0x90C856) .CALL(&CameraUpdateHook_Wrapper) .NOP() .NOP() .Apply(); // Hook to fix 100% CPU when window is inactive PATCH(0x8E6FE1) .NOP() .CALL(&WindowInactiveHook) .Apply(); // PATCH(0x96CC61).TRACE_CALL<&HardcodedGraphicsBitBltHook>().Apply(); // Don't trust QPC as much on WinXP void* frameTimingHookPtr; void* frameTimingMaxFPSHookPtr; if (gIsWindowsVistaOrNewer) { frameTimingHookPtr = (void*)&FrameTimingHookQPC; frameTimingMaxFPSHookPtr = (void*)&FrameTimingMaxFPSHookQPC; } else { frameTimingHookPtr = (void*)&FrameTimingHook; frameTimingMaxFPSHookPtr = (void*)&FrameTimingMaxFPSHook; } // Hooks to fix 100% CPU during operation // These ones are normally not sensitive to the "max FPS" setting PATCH(0x8BFD4A).SAFE_CALL(frameTimingHookPtr).NOP_PAD_TO_SIZE<0x40>().Apply(); PATCH(0x8C0488).SAFE_CALL(frameTimingHookPtr).NOP_PAD_TO_SIZE<0x40>().Apply(); PATCH(0x8C0EE6).SAFE_CALL(frameTimingHookPtr).NOP_PAD_TO_SIZE<0x40>().Apply(); // These ones are normally sensitive to the "max FPS" setting PATCH(0x8C15A7).SAFE_CALL(frameTimingMaxFPSHookPtr).NOP_PAD_TO_SIZE<0x4A>().Apply(); PATCH(0x8C20FC).SAFE_CALL(frameTimingMaxFPSHookPtr).NOP_PAD_TO_SIZE<0x4A>().Apply(); PATCH(0x8E2AED).SAFE_CALL(frameTimingMaxFPSHookPtr).NOP_PAD_TO_SIZE<0x4A>().Apply(); PATCH(0x8E56ED).SAFE_CALL(frameTimingMaxFPSHookPtr).NOP_PAD_TO_SIZE<0x4A>().Apply(); // Logging for NPC collisions //PATCH(0xA281B0).JMP(GET_RETADDR_TRACE_HOOK<&collideNPCLoggingHook>()).NOP().Apply(); // Level and world render hooks PATCH(0x909290).JMP(RenderLevelHook).NOP().Apply(); PATCH(0x8FEB10).JMP(RenderWorldHook).NOP().Apply(); // Level rendering layering hooks //PATCH(0x90C856).NOP().NOP().CALL(GetRenderBelowPriorityHook<-95>()).Apply(); //-100: Level Background PATCH(0x90F4FA).NOP().NOP().CALL(GetRenderBelowPriorityHook<-95>()).Apply(); // -95: Furthest back BGOs PATCH(0x910433).NOP().NOP().CALL(GetRenderBelowPriorityHook<-90>()).Apply(); // -90: Sizable Blocks PATCH(0x910E5D).NOP().NOP().CALL(GetRenderBelowPriorityHook<-85>()).Apply(); // -85: Some more BGOs PATCH(0x911F19).NOP().NOP().CALL(GetRenderBelowPriorityHook<-80>()).Apply(); // -80: Warp - Derived BGOs (locks on doors and stuff) PATCH(0x912748).NOP().NOP().CALL(GetRenderBelowPriorityHook<-75>()).Apply(); // -75: Background NPCs (vines, piranah plants, diggable sand, mother brain, things in MB jars) PATCH(0x915316).NOP().NOP().CALL(GetRenderBelowPriorityHook<-70>()).Apply(); // -70: Held NPCs PATCH(0x91D422).NOP().NOP().CALL(GetRenderBelowPriorityHook<-65>()).Apply(); // -65: Normal Blocks PATCH(0x91DD44).NOP().NOP().CALL(GetRenderBelowPriorityHook<-60>()).Apply(); // -60: Furthest Back Effects (doors, pressed p-switches, some other stuff) PATCH(0x91E1F2).NOP().NOP().CALL(GetRenderBelowPriorityHook<-55>()).Apply(); // -55: Some NPCs (i.e. coins, clown car, chompy, herb, wood rocket, koopaling fire) PATCH(0x91F802).NOP().NOP().CALL(GetRenderBelowPriorityHook<-50>()).Apply(); // -50: Some NPCs (ice blocks) PATCH(0x920040).NOP().NOP().CALL(GetRenderBelowPriorityHook<-45>()).Apply(); // -45: Normal NPCs PATCH(0x922D00).NOP().NOP().CALL(GetRenderBelowPriorityHook<-40>()).Apply(); // -40: Symbol above NPCs that want to chat (hardcoded-43/44) PATCH(0x923786).NOP().NOP().CALL(GetRenderBelowPriorityHook<-35>()).Apply(); // -35: Player Mounts PATCH(0x927F21).NOP().NOP().CALL(GetRenderBelowPriorityHook<-30>()).Apply(); // -30: Something else player mount related? PATCH(0x928EA5).NOP().NOP().CALL(GetRenderBelowPriorityHook<-25>()).Apply(); // -25: Players PATCH(0x928F0A).NOP().NOP().CALL(GetRenderBelowPriorityHook<-20>()).Apply(); // -20: Foreground BGOs PATCH(0x929F81).NOP().NOP().CALL(GetRenderBelowPriorityHook<-15>()).Apply(); // -15: Foreground NPCs PATCH(0x92B428).NOP().NOP().CALL(GetRenderBelowPriorityHook<-10>()).Apply(); // -10: Foreground Blocks PATCH(0x92BAC0).NOP().NOP().CALL(GetRenderBelowPriorityHook<-5>()).Apply(); // -5: Foreground Effects (all not at 0091DD90) // Handle Priority 5 from LevelHUDHook // 5: HUD PATCH(0x939977).NOP().NOP().CALL(GetRenderBelowPriorityHook<100>()).Apply(); // Change Mode Hook // Runs when the game starts or the game mode changes. PATCH(0x8BF4E3).CALL(runtimeHookSmbxChangeModeHookRaw).NOP_PAD_TO_SIZE<10>().Apply(); // Load level hook PATCH(0x8D8F40).JMP(runtimeHookLoadLevel).NOP_PAD_TO_SIZE<6>().Apply(); // Close window hook PATCH(0x8BE3DA).CALL(runtimeHookCloseWindow).Apply(); // Anti-Fullscreen hook PATCH(0x95429A).CALL(runtimeHookChangeResolution).Apply(); PATCH(0xA98142).CALL(runtimeHookChangeResolution).Apply(); PATCH(0xA98166).CALL(runtimeHookChangeResolution).Apply(); PATCH(0x96ADD7).CALL(runtimeHookSmbxCheckWindowedRaw).NOP_PAD_TO_SIZE<8>().Apply(); PATCH(0x9DB1D8).JMP(runtimeHookBlockBumpableRaw).NOP_PAD_TO_SIZE<6>().Apply(); PATCH(0xA28FE3).JMP(runtimeHookNPCVulnerabilityRaw).Apply(); PATCH(0x9A9D33).JMP(runtimeHookNPCSpinjumpSafeRaw).NOP_PAD_TO_SIZE<10>().Apply(); PATCH(0xA75079).JMP(runtimeHookCheckInputRaw).NOP_PAD_TO_SIZE<7>().Apply(); /************************************************************************/ /* Import Table Patch */ /************************************************************************/ __vbaR4Var = (float(*)(VARIANTARG*))0x00401124; *(void**)0x00401124 = (void*)&vbaR4VarHook; rtcMsgBox = (int(__stdcall *)(VARIANTARG*, DWORD, DWORD, DWORD, DWORD))(*(void**)0x004010A8); *(void**)0x004010A8 = (void*)&rtcMsgBoxHook; }
bool FreeImageData::loadFile(const std::wstring &filename) { void* theFile; void* theMap; void* theAddress; theFile = CreateFileW(filename.c_str(), GENERIC_READ, 1, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (theFile == INVALID_HANDLE_VALUE) return false; DWORD size = GetFileSize(theFile, NULL); theMap = CreateFileMappingW(theFile, NULL, PAGE_READONLY, 0, 0, NULL); if( theMap == NULL ) { CloseHandle(theFile); return false; } theAddress = MapViewOfFile(theMap, FILE_MAP_READ, 0, 0, size); if(theAddress == NULL) { CloseHandle(theMap); CloseHandle(theFile); return false; } bool reply = loadMem((unsigned char*)theAddress, size, WStr2Str(filename)); try{ UnmapViewOfFile(theAddress); } catch(void * /*e*/) {} try{ CloseHandle(theMap); } catch(void * /*e*/) {} try{ CloseHandle(theFile);} catch(void* /*e*/) {} return reply; }
bool DirMan::DirMan_private::getListOfFolders(std::vector<std::string> &list, const std::vector<std::string> &suffix_filters) { list.clear(); HANDLE hFind; WIN32_FIND_DATAW data; hFind = FindFirstFileW((m_dirPathW + L"/*").c_str(), &data); if(hFind == INVALID_HANDLE_VALUE) return false; do { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if((wcscmp(data.cFileName, L"..") == 0) || (wcscmp(data.cFileName, L".") == 0)) continue; std::string fileName = WStr2Str(data.cFileName); if(matchSuffixFilters(fileName, suffix_filters)) list.push_back(fileName); } } while(FindNextFileW(hFind, &data)); FindClose(hFind); return true; }
luabind::object luabindResolveFile(std::string file, lua_State* L){ std::vector<std::string> paths = { WStr2Str(getCustomFolderPath()), (std::string)GM_FULLDIR, WStr2Str(getModulePath()) + "\\LuaScriptsLib\\", WStr2Str(getModulePath()) + "\\" }; for (std::string nextSearchPath : paths) { std::string nextEntry = nextSearchPath + file; DWORD objectAttributes = GetFileAttributesA(nextEntry.c_str()); if(objectAttributes == INVALID_FILE_ATTRIBUTES) continue; if(objectAttributes & FILTER) return luabind::object(L, nextEntry); } return luabind::object(); }
void DirMan::DirMan_private::setPath(const std::string &dirPath) { m_dirPathW = Str2WStr(dirPath); wchar_t fullPath[MAX_PATH]; GetFullPathNameW(m_dirPathW.c_str(), MAX_PATH, fullPath, NULL); m_dirPathW = fullPath; //Force UNIX paths std::replace(m_dirPathW.begin(), m_dirPathW.end(), L'\\', L'/'); m_dirPath = WStr2Str(m_dirPathW); delEnd(m_dirPathW, L'/'); delEnd(m_dirPath, '/'); }
bool DirMan::DirMan_private::fetchListFromWalker(std::string &curPath, std::vector<std::string> &list) { if(m_walkerState.digStack.empty()) return false; list.clear(); std::wstring path = m_walkerState.digStack.top(); m_walkerState.digStack.pop(); HANDLE hFind; WIN32_FIND_DATAW data; hFind = FindFirstFileW((path + L"/*").c_str(), &data); if(hFind == INVALID_HANDLE_VALUE) return true; //Can't read this directory. Continue do { if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if((wcscmp(data.cFileName, L"..") == 0) || (wcscmp(data.cFileName, L".") == 0)) continue; m_walkerState.digStack.push(path + L"/" + data.cFileName); } else { std::string fileNameU = WStr2Str(data.cFileName); if(matchSuffixFilters(fileNameU, m_walkerState.suffix_filters)) list.push_back(fileNameU); } } while(FindNextFileW(hFind, &data)); FindClose(hFind); curPath = WStr2Str(path); return true; }
std::string LuaProxy::Data::resolvePathFromSection() { std::string levelName = WStr2Str(::Level::GetName()); std::string episodePath = (std::string)GM_FULLDIR; std::string smbxPath = WStr2Str(getModulePath()); std::string returnPath = ""; switch (m_dataType) { case LuaProxy::Data::DATA_LEVEL: returnPath += episodePath; returnPath += removeExtension(levelName); returnPath += "\\"; returnPath += "LuaData_"; if (m_useSaveSlot) returnPath += "Save" + std::to_string(GM_CUR_SAVE_SLOT) + "_"; returnPath += m_sectionName; returnPath += ".txt"; break; case LuaProxy::Data::DATA_WORLD: returnPath += episodePath; returnPath += "LuaData_"; if (m_useSaveSlot) returnPath += "Save" + std::to_string(GM_CUR_SAVE_SLOT) + "_"; returnPath += m_sectionName; returnPath += ".txt"; break; case LuaProxy::Data::DATA_GLOBAL: default: returnPath += smbxPath; returnPath += "\\worlds\\"; returnPath += "LuaData_"; if (m_useSaveSlot) returnPath += "Save" + std::to_string(GM_CUR_SAVE_SLOT) + "_"; returnPath += m_sectionName; returnPath += ".txt"; break; } return returnPath; }
// TRY LOAD WORLD VARS bool SavedVariableBank::TryLoadWorldVars() { if(Saves::GetCurSaveSlot() > 3) return false; std::wstring full_path = GetSaveFileFullPath(GetSaveFileName()); ClearBank(); // Try to open the file std::wfstream var_file(WStr2Str(full_path).c_str(), std::ios::in | std::ios::out); // If open failed, try to create empty file if(var_file.is_open() == false) { var_file.open(WStr2Str(full_path).c_str(), std::ios::out); var_file.flush(); var_file.close(); var_file.open(WStr2Str(full_path).c_str(), std::ios::in | std::ios::out);; } // If create failed, get out if(var_file.is_open() == false) return false; // If size < 2 bytes, init new save file var_file.seekg(0, std::fstream::end); int cursize = (int)var_file.tellg(); var_file.seekg(0, std::fstream::beg); if(cursize < 2) { InitSaveFile(&var_file); var_file.flush(); var_file.seekg(0, std::fstream::beg); } ReadFile(&var_file); var_file.flush(); var_file.close(); return true; }
// WRITE BANK void SavedVariableBank::WriteBank() { if(Saves::GetCurSaveSlot() > 3) return; std::wstring full_path = GetSaveFileFullPath(GetSaveFileName()); std::wfstream var_file(WStr2Str(full_path).c_str(), std::ios::out | std::ios::trunc); for(std::map<std::wstring, double>::iterator it = m_VarBank.begin(); it != m_VarBank.end(); ++it) { var_file << it->first << std::endl << it->second << std::endl; } var_file.flush(); var_file.close(); }
luabind::object LuaProxy::Misc::listFiles(const std::string& path, lua_State* L) { luabind::object theList = luabind::newtable(L); std::string modulePath = path; if (!isAbsolutePath(path)) { modulePath = WStr2Str(getModulePath()); modulePath += "\\"; modulePath += path; } std::vector<std::string> listedFiles = listFilesOfDir(modulePath); for (unsigned int i = 0; i < listedFiles.size(); ++i){ theList[i + 1] = listedFiles[i]; } return theList; }
// CHECK SAVE DELETION void SavedVariableBank::CheckSaveDeletion() { if(Saves::GetCurSaveSlot() > 3) return; std::wstring star_counter = SPECIAL_SAVE_STR; if(!VarExists(star_counter)) SetVar(star_counter, GM_STAR_COUNT); // Reset save slot detected? Reset the user save file too if(GM_STAR_COUNT < GetVar(SPECIAL_SAVE_STR)) { if(true) //DEBUG gLogger.Log(L"Deleting user save file - Star count: " + std::to_wstring((long long)GM_STAR_COUNT) + L" slot: " + std::to_wstring((long long)Saves::GetCurSaveSlot()), LOG_STD); std::wstring full_path = GetSaveFileFullPath(GetSaveFileName()); ClearBank(); std::wfstream var_file(WStr2Str(full_path).c_str(), std::ios::out); InitSaveFile(&var_file); var_file.flush(); var_file.close(); } }
void ImageLoader::LoadHardcodedGfx(const std::unordered_map<std::wstring, ResourceFileInfo>* fileData, const std::unordered_map<std::wstring, ResourceFileInfo>* oldFileData) { for (int idx1 = 1; idx1 <= HardcodedGraphicsItem::Size(); idx1++) { HardcodedGraphicsItem& hItemInfo = HardcodedGraphicsItem::Get(idx1); // No processing invalid or mask items here if ((hItemInfo.state != HardcodedGraphicsItem::HITEMSTATE_NORMAL) && (hItemInfo.state != HardcodedGraphicsItem::HITEMSTATE_ARRAY)) continue; int minItem = hItemInfo.isArray() ? hItemInfo.minItem : -1; int maxItem = hItemInfo.isArray() ? hItemInfo.maxItem : -1; for (int idx2 = minItem; idx2 <= maxItem; idx2++) { if (hItemInfo.isArray() && !hItemInfo.isValidArrayIndex(idx2)) { // If this index isn't valid, skip it continue; } HDC colorHDC = nullptr; HDC maskHDC = nullptr; hItemInfo.getHDC(idx2, &colorHDC, &maskHDC); if (colorHDC == nullptr) { // No such thing as mask-only graphics continue; } std::wstring hardcodedName = L"hardcoded-" + std::to_wstring(idx1); if (hItemInfo.isArray()) { hardcodedName += L"-" + std::to_wstring(idx2); } // Make note of name to HDC mapping m_NameToHDC[WStr2Str(hardcodedName)] = (uintptr_t)colorHDC; ResourceFileInfo newMain, newMask; ResourceFileInfo oldMain, oldMask; getImageResource(hardcodedName, *fileData, newMain, newMask); if (oldFileData != nullptr) { getImageResource(hardcodedName, *oldFileData, oldMain, oldMask); } // If anything has changed, reload if ((oldFileData == nullptr) || (newMain != oldMain) || (newMask != oldMask)) { std::shared_ptr<LunaImage> img = nullptr; std::shared_ptr<LunaImage> mask = nullptr; if (newMain.done) { // If we found a file, load from it img = LunaImage::fromFile(newMain.path.c_str(), &newMain); mask = LunaImage::fromFile(newMask.path.c_str(), &newMask); } else { // Otherwise, load from HDC img = LunaImage::fromHDC(colorHDC); mask = LunaImage::fromHDC(maskHDC); // TODO: Consider special case for maskless hardcoded graphics from HDC, where black should be made transparent } if (img && mask) { img->setMask(mask); } if (img) { if (colorHDC != nullptr) ImageLoader::m_Gfx[(uintptr_t)colorHDC] = img; if (maskHDC != nullptr) ImageLoader::m_Gfx[(uintptr_t)maskHDC] = img; } } } } }
void ImageLoaderCategory::updateLoadedImages(const std::unordered_map<std::wstring, ResourceFileInfo>* fileData, const std::unordered_map<std::wstring, ResourceFileInfo>* oldFileData) { uint32_t firstIdx = m_Category.getFirstIdx(); uint32_t lastIdx = m_Category.getLastIdx(); std::wstring prefix = m_Category.getPrefix(); for (uint32_t i = firstIdx; i <= lastIdx; i++) { std::wstring imageName = prefix + L"-" + std::to_wstring(i); ResourceFileInfo newMain, newMask; ResourceFileInfo oldMain, oldMask; getImageResource(imageName, *fileData, newMain, newMask); if (oldFileData != nullptr) { getImageResource(imageName, *oldFileData, oldMain, oldMask); } // If anything has changed, reload if ((oldFileData == nullptr) || (newMain != oldMain) || (newMask != oldMask)) { uint32_t width = 0, height = 0; HDC mainImgHdc = nullptr; std::shared_ptr<LunaImage> mainImg = nullptr; if (m_Category.haveImagePtrArray()) { // Make HDC if-needed mainImgHdc = m_Category.getImagePtr(i); if (mainImgHdc == nullptr) { mainImgHdc = CreateCompatibleDC(NULL); m_Category.setImagePtr(i, mainImgHdc); ImageLoader::m_NameToHDC[WStr2Str(imageName)] = (uintptr_t)mainImgHdc; ImageLoader::m_HDCToCategoryAndIndex[(uintptr_t)mainImgHdc] = std::pair<const SMBXImageCategory*, uint32_t>(&m_Category, i); } // Try to load image if (newMain.path.length() > 0) { mainImg = LunaImage::fromFile(newMain.path.c_str(), &newMain); } // Assign image, note size ImageLoader::m_Gfx[(uintptr_t)mainImgHdc] = mainImg; if (mainImg) { if (width < mainImg->getW()) width = mainImg->getW(); if (height < mainImg->getH()) height = mainImg->getH(); } } else { // That's required... throw; } if (m_Category.haveMaskPtrArray() && mainImg) { // Match HDC to non-mask version m_Category.setMaskPtr(i, mainImgHdc); // Try to load image std::shared_ptr<LunaImage> maskImg = nullptr; if (newMask.path.length() > 0) { maskImg = LunaImage::fromFile(newMask.path.c_str(), &newMask); } // Assign image, note size mainImg->setMask(maskImg); if (maskImg) { if (width < maskImg->getW()) width = maskImg->getW(); if (height < maskImg->getH()) height = maskImg->getH(); mainImg->tryMaskToRGBA(); } } m_Category.setWidth(i, (int16_t)min(width, 0x7FFF)); m_Category.setHeight(i, (int16_t)min(height, 0x7FFF)); } } }
VOID SetDefaultPLOTDM( HANDLE hPrinter, PPLOTGPC pPlotGPC, LPWSTR pwDeviceName, PPLOTDEVMODE pPlotDM, PFORMSIZE pCurForm ) /*++ Routine Description: This function set the default devmode based on the current pPlotGPC Arguments: hPrinter - Handle to the printer pPlotGPC - our loaded/verified GPC data. pwDeviceName - the device name passed in pPlotDM - Pointer to our ExtDevMode pCurForm - Pointer to the FORMSIZE data structure which will be updated if the pointer is not NULL, the final result of the form size/imagable area selected by the user will be written to here. the form name will be in pPlotDM->dmFormName. Return Value: VOID Author: 14-Dec-1993 Tue 20:21:48 updated -by- Daniel Chou (danielc) Update the dmScale based on maximum the device can support 06-Dec-1993 Mon 12:49:52 updated -by- Daniel Chou (danielc) make sure we turn off the DM_xxx bits if one of those is not valid or supported in current plotter 16-Nov-1993 Tue 13:49:27 created -by- Daniel Chou (danielc) Revision History: --*/ { WCHAR DeviceName[CCHDEVICENAME]; if (pwDeviceName) { _WCPYSTR(DeviceName, pwDeviceName, CCHDEVICENAME); // // Make sure the PlotGPC's device name is ssync with the pDeviceName // passed // WStr2Str(pPlotGPC->DeviceName, DeviceName); PLOTDBG(DBG_DEFDEVMODE, ("PlotGPC DeviceName=%hs\npwDeviceName=%ls", pPlotGPC->DeviceName, pwDeviceName)); } else { PLOTERR(("No DeviceName passed, using GPC's '%hs'", pPlotGPC->DeviceName)); str2Wstr(DeviceName, pPlotGPC->DeviceName); } // // Make a default copy first then copy device name down // CopyMemory(pPlotDM, &_DefPlotDM, sizeof(PLOTDEVMODE)); WCPYFIELDNAME(pPlotDM->dm.dmDeviceName, DeviceName); // // We must turn off the DM_xxx bits in dmFields if we do not support it, // look at default fields we copy down then update it // if (pPlotGPC->MaxScale) { if ((WORD)pPlotDM->dm.dmScale > pPlotGPC->MaxScale) { pPlotDM->dm.dmScale = (SHORT)pPlotGPC->MaxScale; } } else { pPlotDM->dm.dmFields &= ~DM_SCALE; } if (pPlotGPC->MaxCopies <= 1) { pPlotDM->dm.dmFields &= ~DM_COPIES; } if (!(pPlotGPC->MaxQuality)) { pPlotDM->dm.dmFields &= ~DM_PRINTQUALITY; } // // DEFAULT 50% quality for byte align plotter (DJ 600) to do ROP right // if (pPlotGPC->Flags & PLOTF_RASTERBYTEALIGN) { pPlotDM->dm.dmPrintQuality = DMRES_LOW; PLOTWARN(("SetDefaultPLOTDM: HACK Default Qaulity = DMRES_LOW")); } if (!(pPlotGPC->Flags & PLOTF_COLOR)) { if (pPlotGPC->Flags & PLOTF_RASTER) { pPlotDM->dm.dmFields &= ~DM_COLOR; pPlotDM->dm.dmColor = DMCOLOR_MONOCHROME; } else { PLOTASSERT(0, "SetDefaultPLOTDM: The Pen Ploter CANNOT be MONO.", (pPlotGPC->Flags & PLOTF_COLOR), 0); pPlotGPC->Flags |= PLOTF_COLOR; } } // // Set default form name based on the country // SetDefaultDMForm(pPlotDM, pCurForm); }
VOID SetDefaultPLOTDM( HANDLE hPrinter, _In_ PPLOTGPC pPlotGPC, _In_opt_ LPCWSTR pwDeviceName, _In_ PPLOTDEVMODE pPlotDM, _Out_opt_ PFORMSIZE pCurForm ) /*++ Routine Description: This function set the default devmode based on the current pPlotGPC Arguments: hPrinter - Handle to the printer pPlotGPC - our loaded/verified GPC data. pwDeviceName - the device name passed in pPlotDM - Pointer to our ExtDevMode pCurForm - Pointer to the FORMSIZE data structure which will be updated if the pointer is not NULL, the final result of the form size/imagable area selected by the user will be written to here. the form name will be in pPlotDM->dmFormName. Return Value: VOID Author: 14-Dec-1993 Tue 20:21:48 updated Update the dmScale based on maximum the device can support 06-Dec-1993 Mon 12:49:52 updated make sure we turn off the DM_xxx bits if one of those is not valid or supported in current plotter 16-Nov-1993 Tue 13:49:27 created Revision History: --*/ { WCHAR *pwchDeviceName = NULL; ULONG ulStrLen = 0; UNREFERENCED_PARAMETER(hPrinter); // // Device name including NULL terminator // must be equal or shorter than CCHDEVICENAME. // PREFIX doesn' take this assumption. Buffer size needs to be flexible and // should not be on stack. // if (pwDeviceName) { ulStrLen = (ULONG)wcslen(pwDeviceName); // // Allocate buffer to hold pwDeviceName including null terminator. // Make sure that pwDeviceName has a device name. // if (0 == ulStrLen || !(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR)))) { PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n")); // // Make sure that pPlotGPC->DeviceName has a null terminator. // pPlotGPC->DeviceName[0] = (BYTE)'\0'; } else { _WCPYSTR_FILL_TRAIL_WITH_NULL(pwchDeviceName, ulStrLen + 1, pwDeviceName); // // Make sure the PlotGPC's device name is ssync with the pDeviceName // passed. // String length must be equal or shorter than CCHDEVICENAME. // DEVMODE's device name and pPlotGPC->DeviceName can't hold a sting // longer than CCHDEVICENAME. // if (ulStrLen + 1 > CCHDEVICENAME) { PLOTERR(("SetDefaultPLOTDM: DeviceName is longer than buffer size.\n")); } else { WStr2Str(pPlotGPC->DeviceName, CCHOF(pPlotGPC->DeviceName), pwchDeviceName); } } PLOTDBG(DBG_DEFDEVMODE, ("PlotGPC DeviceName=%hs\npwDeviceName=%ls", pPlotGPC->DeviceName, pwDeviceName)); } else { PLOTERR(("No DeviceName passed, using GPC's '%hs'", pPlotGPC->DeviceName)); ulStrLen = (ULONG)strlen(pPlotGPC->DeviceName); // // Allocate buffer to hold pwDeviceName including null terminator. // Make sure that pwDeviceName has a device name. // if (0 == ulStrLen || !(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR)))) { PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n")); } else { str2Wstr(pwchDeviceName, ulStrLen + 1, pPlotGPC->DeviceName); } } // // Make a default copy first then copy device name down // CopyMemory(pPlotDM, &_DefPlotDM, sizeof(PLOTDEVMODE)); if (pwchDeviceName) { WCPYFIELDNAME(pPlotDM->dm.dmDeviceName, CCHOF(pPlotDM->dm.dmDeviceName), pwchDeviceName); LocalFree(pwchDeviceName); } else { pPlotDM->dm.dmDeviceName[0] = L'\0'; } // // We must turn off the DM_xxx bits in dmFields if we do not support it, // look at default fields we copy down then update it // if (pPlotGPC->MaxScale) { if ((WORD)pPlotDM->dm.dmScale > pPlotGPC->MaxScale) { pPlotDM->dm.dmScale = (SHORT)pPlotGPC->MaxScale; } } else { pPlotDM->dm.dmFields &= ~DM_SCALE; } if (pPlotGPC->MaxCopies <= 1) { pPlotDM->dm.dmFields &= ~DM_COPIES; } if (!(pPlotGPC->MaxQuality)) { pPlotDM->dm.dmFields &= ~DM_PRINTQUALITY; } // // DEFAULT 50% quality for byte align plotter (DJ 600) to do ROP right // if (pPlotGPC->Flags & PLOTF_RASTERBYTEALIGN) { pPlotDM->dm.dmPrintQuality = DMRES_LOW; PLOTWARN(("SetDefaultPLOTDM: Force Default Qaulity = DMRES_LOW")); } if (!(pPlotGPC->Flags & PLOTF_COLOR)) { if (pPlotGPC->Flags & PLOTF_RASTER) { pPlotDM->dm.dmFields &= ~DM_COLOR; pPlotDM->dm.dmColor = DMCOLOR_MONOCHROME; } else { PLOTASSERT(0, "SetDefaultPLOTDM: The Pen Ploter CANNOT be MONO.", (pPlotGPC->Flags & PLOTF_COLOR), 0); pPlotGPC->Flags |= PLOTF_COLOR; } } // // Set default form name based on the country/region // SetDefaultDMForm(pPlotDM, pCurForm); }
luabind::object LuaProxy::Misc::listLocalFiles(std::string path, lua_State* L) { return listFiles(WStr2Str(getCustomFolderPath()) + path, L); }
// *EXPORT* On Level Load -- Run once as a level is loaded (including title screen level) int OnLvlLoad() { // Restore some code the hook overwrote *(DWORD*)0x00B25958 = 0; ResetLunaModule(); // WIP // dumpTypeLibrary((IDispatch*)*(DWORD*)0xB2D7E8, std::wcout); std::string custPath = WStr2Str(getCustomFolderPath()); std::string wldPath = WStr2Str(GM_FULLDIR); std::string SndRoot = MusicManager::SndRoot(); replaceSubStr(wldPath, "\"", ""); replaceSubStr(wldPath, "\\\\", "\\"); replaceSubStr(wldPath, "/", "\\"); replaceSubStr(SndRoot, "\"", ""); replaceSubStr(SndRoot, "\\\\", "\\"); replaceSubStr(SndRoot, "/", "\\"); bool doSoundLoading = false; if ((!custPath.empty()) && (file_existsX(custPath + "\\sounds.ini"))) { //If custom-level specific sounds.ini detected doSoundLoading = true; LevelCustomSounds = true; } else if (LevelCustomSounds) { //If custom-level specific sounds.ini was NOT detected, but was loaded recently - reload episode specific sounds doSoundLoading = true; LevelCustomSounds = false; } if (!episodeStarted) { //Load custom sounds if episode is not finally started if (wldPath != SndRoot) doSoundLoading = true; } if (doSoundLoading) MusicManager::loadCustomSounds(wldPath + "\\", custPath); // BMPBox::initMovieCache(); if(gLunaEnabled) { // Load autocode gAutoMan.Clear(false); gAutoMan.ReadFile((std::wstring)GM_FULLDIR); // Try to load world codes gAutoMan.ReadWorld((std::wstring)GM_FULLDIR); // Init var bank gSavedVarBank.TryLoadWorldVars(); gSavedVarBank.CheckSaveDeletion(); gSavedVarBank.CopyBank(&gAutoMan.m_UserVars); // Don't try to call the CLunaLua constructor... It's already // constructed automatically once, and trying to do this will call // the constructor extra times *without* ever calling the destructor, // which can result in a memory leak of the whole Lua state! // gLunaLua = CLunaLua(); gLunaLua.init(CLunaLua::LUNALUA_LEVEL, (std::wstring)GM_FULLDIR, Level::GetName()); gLunaLua.setReady(true); // Do some stuff gAutoMan.DoEvents(true); // do with init // Init some stuff InitLevel(); gAutoMan.m_Hearts = 2; // Recount deaths gDeathCounter.Recount(); } //PGE DBG STUFF //readAndWriteNPCSettings(); //overwriteFunc(); return 0; }