public static List <Repo> Discovery(string start_url) { IntPtr repo_list = ThcrapUpdateDll.RepoDiscover(start_url); if (repo_list == IntPtr.Zero) { return(new List <Repo>()); } var out_list = new List <Repo>(); int current_repo = 0; IntPtr repo_ptr = Marshal.ReadIntPtr(repo_list, current_repo * IntPtr.Size); while (repo_ptr != IntPtr.Zero) { out_list.Add(new Repo(repo_ptr)); current_repo++; repo_ptr = Marshal.ReadIntPtr(repo_list, current_repo * IntPtr.Size); } ThcrapDll.thcrap_free(repo_list); return(out_list); }
public void AddToStack() { ThcrapDll.patch_desc_t patch_desc; patch_desc.repo_id = this.Repo.Id; patch_desc.patch_id = this.Id; IntPtr patch_desc_ptr = AllocStructure(patch_desc); ThcrapDll.patch_t patch_info = ThcrapUpdateDll.patch_bootstrap(patch_desc_ptr, this.Repo.repo_ptr); this.Archive = Marshal.PtrToStringAnsi(patch_info.archive); ThcrapDll.patch_t patch_full = ThcrapDll.patch_init(this.Archive, IntPtr.Zero, 0); IntPtr patch_full_ptr = AllocStructure(patch_full); ThcrapDll.stack_add_patch(patch_full_ptr); // TODO: use DestroyStructure instead? Marshal.DestroyStructure <ThcrapDll.patch_desc_t>(patch_desc_ptr); Marshal.DestroyStructure <ThcrapDll.patch_t>(patch_full_ptr); Marshal.FreeHGlobal(patch_desc_ptr); Marshal.FreeHGlobal(patch_full_ptr); }
private async Task CreateStandalonePatchForGame(Game game) { ThcrapDll.log_print("Generating standalone for " + game.Name + "...\n"); Directory.CreateDirectory(game.Id); Directory.CreateDirectory(game.Id + "\\thcrap\\"); Environment.CurrentDirectory = game.Id + "\\thcrap\\"; ZipFile.ExtractToDirectory(@"..\..\thcrap.zip", "."); foreach (RepoPatch patch in selectedPatchesList) { await Task.Run(() => patch.AddToStack()); } await Task.Run(() => ThcrapUpdateDll.stack_update( (string fn, IntPtr filter_data) => (fn.Contains('/') == false) || fn.StartsWith(game.Id + "/") ? 1 : 0, IntPtr.Zero, (IntPtr status_, IntPtr param) => { var status = Marshal.PtrToStructure <ThcrapUpdateDll.progress_callback_status_t>(status_); switch (status.status) { case ThcrapUpdateDll.get_status_t.GET_DOWNLOADING: case ThcrapUpdateDll.get_status_t.GET_CANCELLED: break; case ThcrapUpdateDll.get_status_t.GET_OK: var patch = Marshal.PtrToStructure <ThcrapDll.patch_t>(status.patch); string patch_id = Marshal.PtrToStringAnsi(patch.id); ThcrapDll.log_print(string.Format("[{0}/{1}] {2}/{3}: OK ({4}b)\n", status.nb_files_downloaded, status.nb_files_total, patch_id, status.fn, status.file_size)); break; case ThcrapUpdateDll.get_status_t.GET_CLIENT_ERROR: case ThcrapUpdateDll.get_status_t.GET_SERVER_ERROR: case ThcrapUpdateDll.get_status_t.GET_SYSTEM_ERROR: ThcrapDll.log_print(status.url + " : " + status.error + "\n"); break; case ThcrapUpdateDll.get_status_t.GET_CRC32_ERROR: ThcrapDll.log_print(status.url + " : CRC32 error\n"); break; } return(true); }, IntPtr.Zero) ); var runconfig = new Runconfig(); foreach (RepoPatch patch in selectedPatchesList) { runconfig.patches.Add(new RunconfigPatch(patch.Archive)); } runconfig.Save(uiConfigName.Text); var gamesJs = new Dictionary <string, string>() { { game.Id, "../" + game.Id + ".exe" }, { game.Id + "_custom", "../custom.exe" }, }; string jsonGamesJs = JsonSerializer.Serialize(gamesJs, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText("config/games.js", jsonGamesJs); Environment.CurrentDirectory = ".."; CreateExe(game.Id, game.ImagePath); CreateExe(game.Id + "_custom", null); ThcrapDll.stack_free(); Environment.CurrentDirectory = ".."; ThcrapDll.log_print("Standalone for " + game.Name + " generated!\n"); }