feat: partial support for patches

This commit is contained in:
2025-04-11 15:27:13 +00:00
parent b9a40d44a8
commit 1a68eda8c1
21 changed files with 1218 additions and 583 deletions

View File

@ -15,6 +15,7 @@ import { listen } from '@tauri-apps/api/event';
import ModList from './ModList.vue';
import ModStore from './ModStore.vue';
import OptionList from './OptionList.vue';
import PatchList from './PatchList.vue';
import ProfileList from './ProfileList.vue';
import StartButton from './StartButton.vue';
import { invoke } from '../invoke';
@ -55,14 +56,26 @@ onMounted(async () => {
}
fetch_promise.then(async () => {
await invoke('install_package', {
key: 'segatools-mu3hook',
force: false,
});
await invoke('install_package', {
key: 'segatools-chusanhook',
force: false,
});
const promises = [];
promises.push(
invoke('install_package', {
key: 'segatools-mu3hook',
force: false,
})
);
promises.push(
invoke('install_package', {
key: 'segatools-chusanhook',
force: false,
})
);
promises.push(
invoke('install_package', {
key: 'mempatcher-mempatcher',
force: false,
})
);
await Promise.all(promises);
});
});
@ -163,7 +176,10 @@ listen<{ message: string; header: string }>('invoke-error', (event) => {
<div class="grow"></div>
<div class="flex gap-4">
<div class="flex" v-if="currentTab !== 3">
<div
class="flex"
v-if="[0, 1, 2].includes(currentTab as number)"
>
<InputIcon class="self-center mr-2">
<i class="pi pi-search" />
</InputIcon>
@ -240,13 +256,7 @@ listen<{ message: string; header: string }>('invoke-error', (event) => {
</footer>
</TabPanel>
<TabPanel :value="4">
CHUNITHM patches are not implemented yet.<br />Use
<a
href="https://patcher.two-torial.xyz/"
target="_blank"
style="text-decoration: underline"
>patcher.two-torial.xyz</a
>
<PatchList />
</TabPanel>
</TabPanels>
<div v-if="currentTab === 5 || currentTab === 3">

View File

@ -62,7 +62,10 @@ const iconSrc = computed(() => {
>
</span>
<span
v-if="hasFeature(pkg, Feature.Mu3IO)"
v-if="
hasFeature(pkg, Feature.Mu3IO) ||
hasFeature(pkg, Feature.ChuniIO)
"
v-tooltip="'IO'"
class="pi pi-wrench ml-1 text-green-400"
>
@ -73,6 +76,16 @@ const iconSrc = computed(() => {
class="pi pi-credit-card ml-1 text-purple-400"
>
</span>
<span
v-if="
hasFeature(pkg, Feature.Mempatcher) ||
hasFeature(pkg, Feature.GameDLL) ||
hasFeature(pkg, Feature.AmdDLL)
"
v-tooltip="'DLL'"
class="pi pi-cog ml-1 text-red-400"
>
</span>
<span
v-if="showNamespace && pkg?.namespace"
class="text-sm opacity-75"

View File

@ -7,6 +7,7 @@ const general = useGeneralStore();
defineProps({
title: String,
collapsed: Boolean,
alwaysFound: Boolean,
});
</script>
@ -14,7 +15,7 @@ defineProps({
<Fieldset
:legend="title"
:toggleable="true"
v-show="general.cfgCategories.has(title ?? '')"
v-show="general.cfgCategories.has(title ?? '') || alwaysFound"
:collapsed="collapsed"
>
<div class="flex w-full flex-col gap-1">

View File

@ -9,6 +9,7 @@ const props = defineProps({
title: String,
tooltip: String,
dangerousTooltip: String,
greytext: String,
});
const searched = computed(() => {
@ -38,6 +39,12 @@ const searched = computed(() => {
class="pi pi-exclamation-circle ml-2 text-red-500"
v-tooltip="dangerousTooltip"
></span>
<span
v-if="greytext"
style="font-size: 0.65rem"
class="ml-2 text-gray-400"
>{{ greytext }}</span
>
</div>
<slot />

View File

@ -0,0 +1,34 @@
<script setup lang="ts">
import InputNumber from 'primevue/inputnumber';
import ToggleSwitch from 'primevue/toggleswitch';
import OptionRow from './OptionRow.vue';
import { usePrfStore } from '../stores';
const prf = usePrfStore();
const toggleUnary = (key: string, val: boolean) => {
if (val) {
prf.current!.data.patches[key] = 'Enabled';
} else {
delete prf.current!.data.patches[key];
}
};
defineProps({
id: String,
name: String,
tooltip: String,
type: String,
});
</script>
<template>
<OptionRow :title="name" :tooltip="tooltip" :greytext="id">
<ToggleSwitch
v-if="type === undefined"
:model-value="prf.current!.data.patches[id!] !== undefined"
@update:model-value="(v: boolean) => toggleUnary(id!, v)"
/>
<InputNumber v-else class="number-input" />
</OptionRow>
</template>

View File

@ -0,0 +1,54 @@
<script setup lang="ts">
import { Ref, ref } from 'vue';
import * as path from '@tauri-apps/api/path';
import OptionCategory from './OptionCategory.vue';
import OptionRow from './OptionRow.vue';
import PatchEntry from './PatchEntry.vue';
import { invoke } from '../invoke';
import { usePrfStore } from '../stores';
import { Patch } from '../types';
const prf = usePrfStore();
prf.reload();
const gamePatches: Ref<Patch[]> = ref([]);
const amdPatches: Ref<Patch[]> = ref([]);
invoke('list_patches', { target: prf.current!.data.sgt.target }).then(
(patches) => {
gamePatches.value = patches as Patch[];
}
);
(async () => {
const amd = await path.join(
prf.current!.data.sgt.target,
'../amdaemon.exe'
);
amdPatches.value = (await invoke('list_patches', {
target: amd,
})) as Patch[];
})();
</script>
<template>
<OptionCategory title="chusanApp.exe" always-found>
<PatchEntry
v-for="p in gamePatches"
:id="p.id"
:title="p.name"
:tooltip="p.tooltip"
:type="p.type"
/>
</OptionCategory>
<OptionCategory title="amdaemon.exe" always-found>
<PatchEntry
v-for="p in amdPatches"
:id="p.id"
:title="p.name"
:tooltip="p.tooltip"
:type="p.type"
/>
</OptionCategory>
</template>

View File

@ -30,6 +30,10 @@ export enum Feature {
Mu3Hook = 1 << 3,
Mu3IO = 1 << 4,
ChusanHook = 1 << 5,
ChuniIO = 1 << 6,
Mempatcher = 1 << 7,
GameDLL = 1 << 8,
AmdDLL = 1 << 9,
}
export type Status =
@ -54,6 +58,9 @@ export interface ProfileData {
bepinex: BepInExConfig;
mu3_ini: Mu3IniConfig | undefined;
keyboard: KeyboardConfig | undefined;
patches: {
[key: string]: 'Enabled' | { Number: number } | { Hex: Int8Array };
};
}
export interface SegatoolsConfig {
@ -149,3 +156,10 @@ export interface Dirs {
data_dir: string;
cache_dir: string;
}
export interface Patch {
id: string;
name: string;
tooltip: string;
type: undefined | 'number';
}