mirror of
https://wiilab.wiimart.org/wiimart/WiiMart-Patcher
synced 2025-09-04 04:21:19 +02:00
84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"log"
|
|
)
|
|
|
|
var (
|
|
ErrInconsistentPatch = errors.New("before and after data present within file are not the same size")
|
|
ErrPatchOutOfRange = errors.New("patch cannot be applied past binary size")
|
|
ErrInvalidPatch = errors.New("before data present within patch did not exist in file")
|
|
)
|
|
|
|
// Patch represents a patch applied to the main binary.
|
|
type Patch struct {
|
|
// Name is an optional name for this patch.
|
|
// If present, its name will be logged upon application.
|
|
Name string
|
|
|
|
// AtOffset is the offset within the file this patch should be applied at.
|
|
AtOffset int
|
|
|
|
// Before is an array of the bytes to find for, i.e. present within the original file.
|
|
Before []byte
|
|
|
|
// After is an array of the bytes to replace with.
|
|
After []byte
|
|
}
|
|
|
|
// PatchSet represents multiple patches available to be applied.
|
|
type PatchSet []Patch
|
|
|
|
// applyPatch applies the given patch to the main DOL.
|
|
func applyPatch(patch Patch) error {
|
|
// Print name if present
|
|
if patch.Name != "" {
|
|
log.Println("Applying patch " + patch.Name)
|
|
}
|
|
|
|
// Ensure consistency
|
|
if len(patch.Before) != len(patch.After) {
|
|
return ErrInconsistentPatch
|
|
}
|
|
if patch.AtOffset > len(mainDol) {
|
|
return ErrPatchOutOfRange
|
|
}
|
|
|
|
// Either Before or After should return the same length.
|
|
patchLen := len(patch.Before)
|
|
|
|
// Ensure original bytes are present
|
|
originalBytes := mainDol[patch.AtOffset : patch.AtOffset+patchLen]
|
|
if !bytes.Equal(originalBytes, patch.Before) {
|
|
return ErrInvalidPatch
|
|
}
|
|
|
|
// Apply patch
|
|
copy(mainDol[patch.AtOffset:], patch.After)
|
|
|
|
return nil
|
|
}
|
|
|
|
// applyPatchSet iterates through all possible patches, noting their name.
|
|
func applyPatchSet(setName string, set PatchSet) {
|
|
log.Printf("Handling patch set \"%s\":", setName)
|
|
|
|
for _, patch := range set {
|
|
err := applyPatch(patch)
|
|
check(err)
|
|
}
|
|
}
|
|
|
|
// emptyBytes returns an empty byte array of the given length.
|
|
func emptyBytes(length int) []byte {
|
|
return bytes.Repeat([]byte{0x00}, length)
|
|
}
|
|
|
|
// applyDefaultPatches iterates through a list of default patches.
|
|
func applyDefaultPatches() {
|
|
applyPatchSet("Overwrite IOS Syscall for ES", OverwriteIOSPatch)
|
|
applyPatchSet("Load Custom CA within IOS", LoadCustomCA(rootCertificate))
|
|
}
|