# How Apollo Applies Save Wizard and Bruteforce Save Data Patches to PS4 Game Saves

> Discover how Apollo applies Save Wizard and Bruteforce Save Data patches to PS4 game saves. Learn about its three-stage pipeline for modifying and re-signing save data.

- Repository: [Damián Parrino/apollo-ps4](https://github.com/bucanero/apollo-ps4)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Apollo’s patch system loads `.savepatch` files containing BSD or Save Wizard syntax, converts them into structured cheat entries, and applies binary modifications through a three-stage pipeline before re-signing the save data.**

Apollo is an open-source save game editor for PS4 that supports cheat formats from **Save Wizard** and **Bruteforce Save Data (BSD)**. According to the `bucanero/apollo-ps4` source code, the application implements a modular patch engine that parses plain-text instructions and applies them to encrypted save files while handling file wildcards, type differentiation, and cryptographic resigning.

## Loading and Parsing the Patch File

When you open a save entry in Apollo, the system initiates the patch discovery phase in `ReadCodes()` at `source/saves.c:777-792`. This function constructs the path to the patch file using the save’s `title_id` and the `APOLLO_DATA_PATH` constant:

```c
snprintf(filePath, sizeof(filePath), APOLLO_DATA_PATH "%s.savepatch", save->title_id);
if ((buffer = readTextFile(filePath)) == NULL) goto skip_end;
load_patch_code_list(buffer, save->codes, &get_file_entries, save->path);

```

If the file exists, `load_patch_code_list()` parses the text line-by-line according to BSD/Save-Wizard syntax (e.g., `80 123456 1234`). For each instruction, it creates a `code_entry_t` structure and sets the `type` field to either `PATCH_BSD` or `PATCH_GAMEGENIE` as defined in [`include/types.h`](https://github.com/bucanero/apollo-ps4/blob/main/include/types.h). This type flag determines which interpreter engine processes the patch during the application phase.

## User Selection and Activation

After parsing, the UI layer in [`menu_cheats.c`](https://github.com/bucanero/apollo-ps4/blob/main/menu_cheats.c) and [`menu_main.c`](https://github.com/bucanero/apollo-ps4/blob/main/menu_main.c) renders each `code_entry_t` as a toggleable menu item. When you select a cheat, the system sets the `code_entry_t.activated` flag to `1`. Unselected patches remain in the list but retain an `activated` value of `0`, ensuring only user-approved modifications reach the binary stage.

## Applying Patches to Save Files

When you trigger **Apply changes & resign**, Apollo executes `apply_cheat_patches()` located at `source/exec_cmd.c:1524-1529`. This function filters the code list for activated entries of type `PATCH_GAMEGENIE`, `PATCH_BSD`, or `PATCH_PYTHON`, resolves target file paths (including wildcards), and dispatches the patch:

```c
for (node = list_head(entry->codes); (code = list_get(node)); node = list_next(node)) {
    if (!code->activated ||
       (code->type != PATCH_GAMEGENIE && code->type != PATCH_BSD && code->type != PATCH_PYTHON))
        continue;

    LOG("Active code: [%s]", code->name);
    /* Resolve filename, honouring optional wild‑cards */
    if (strchr(code->file, '*')) {
        option_value_t *opt = list_get_item(code->options[0].opts, code->options[0].sel);
        filename = opt->name;
    }
    snprintf(tmpfile, sizeof(tmpfile), "%s%s", entry->path, filename);
    if (!apply_cheat_patch_code(tmpfile, code, &orbis_host_callback)) {
        LOG("Error: failed to apply (%s)", code->name);
    }
    code->activated = 0;
}

```

The `apply_cheat_patch_code()` function (linked through the `orbis_host_callback` interface) performs the actual binary manipulation. It reads the target save file, interprets the address and value/mask specifications from the BSD or Save Wizard instruction, writes the modified bytes, and returns. After all active patches process, Apollo calls `resignSave()` to regenerate cryptographic signatures, ensuring the PS4 recognizes the edited data as valid.

## SFO Parameter Patching

Before resigning, `apply_sfo_patches()` (referenced around `exec_cmd.c:1434-1450`) updates the `param.sfo` metadata file. This step handles account ID transfers and title ID corrections, ensuring the save ownership matches the target console profile.

## Summary

- **Apollo searches** for `<title-id>.savepatch` files in `APOLLO_DATA_PATH` via `ReadCodes()` in [`source/saves.c`](https://github.com/bucanero/apollo-ps4/blob/main/source/saves.c).
- **The parser** `load_patch_code_list()` tokenizes BSD and Save Wizard syntax into `code_entry_t` structures with types `PATCH_BSD` or `PATCH_GAMEGENIE`.
- **The UI** toggles the `activated` flag to mark selected patches.
- **The executor** `apply_cheat_patches()` in [`source/exec_cmd.c`](https://github.com/bucanero/apollo-ps4/blob/main/source/exec_cmd.c) filters by type, resolves wildcards, and invokes `apply_cheat_patch_code()`.
- **Binary changes** are applied through the cheat engine callback, followed by SFO patching and cryptographic resigning.

## Frequently Asked Questions

### What is the difference between PATCH_BSD and PATCH_GAMEGENIE types?

`PATCH_BSD` indicates a Bruteforce Save Data format instruction (hex address followed by value), while `PATCH_GAMEGENIE` represents Save Wizard’s encrypted code pattern. The `apply_cheat_patch_code()` function uses these type flags from [`include/types.h`](https://github.com/bucanero/apollo-ps4/blob/main/include/types.h) to select the appropriate decoder ring when interpreting the patch bytes.

### How does Apollo handle patch files with wildcards in the filename?

If `code->file` contains an asterisk (`*`), Apollo treats it as a wildcard selector. It extracts the selected option from `code->options[0].sel`, retrieves the concrete filename from the `option_value_t` list, and concatenates it with `entry->path` before calling `apply_cheat_patch_code()`.

### Does Apollo modify the param.sfo file when applying patches?

Yes. Before `apply_cheat_patches()` runs, Apollo invokes `apply_sfo_patches()` to modify `param.sfo` metadata. This updates account IDs and title information to match the destination user profile, which is required for the PS4 to recognize the save as belonging to the signed-in account.

### Where does Apollo look for .savepatch files?

Apollo constructs the path using `snprintf()` with the format `APOLLO_DATA_PATH "%s.savepatch"` where `%s` is the save’s `title_id`. This typically resolves to a directory like `/data/apollo/` or similar configured path, followed by the game ID and `.savepatch` extension.