From fc402cfab1eff3b6859316e8d64bde9d42d75154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Tr=C4=99bacz?= Date: Sun, 28 Dec 2025 12:59:41 +0100 Subject: [PATCH 1/3] Optimized Docker build script for faster rebuilds --- CLAUDE.md | 360 ++++++++++++++++++++++++++++++++++++++++++ tools/docker-build.sh | 19 +++ 2 files changed, 379 insertions(+) create mode 100644 CLAUDE.md create mode 100755 tools/docker-build.sh diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6b1a440 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,360 @@ +## FF7 Decomp: Working Notes for Agents + +Final Fantasy VII (PS1 USA) decompilation project. Goal: byte-accurate recompilation of game executables. + +## Quick Reference + +### Docker Build Commands (Optimized) +```shell +# Build Docker image (only needed once) +docker build --platform=linux/amd64 --tag ff7-build:latest . + +# Run a build (FAST - uses Go caching, ~12s clean, ~2s incremental) +./tools/docker-build.sh "make build" + +# Format code after changes +./tools/docker-build.sh "make format" + +# Enter container interactively +./tools/docker-build.sh bash +``` + +The `docker-build.sh` wrapper adds Go module and build caching which provides a significant speedup. + +**Legacy commands** - only use if you have issues with the optimized script: +```shell +docker run --rm --platform=linux/amd64 -v "$(pwd)":/ff7 -v ff7_venv:/ff7/.venv -v "$(pwd)/build":/ff7/build ff7-build:latest -lc 'cd /ff7 && make build' +``` + +### Key Make Targets +- `make build` - Build all overlays, verify SHA1 checksums +- `make format` - Run clang-format on code +- `make clean` - Remove build artifacts +- `make submit` - Clean + build + format + stage files for commit + +### Mako Commands (via `./mako.sh`) +- `./mako.sh build` - Build project +- `./mako.sh dec ` - Decompile function, replace INCLUDE_ASM +- `./mako.sh dec --fix-structs` - Also replace D_8009XXXX with Savemap fields +- `./mako.sh rank ` - Rank functions by difficulty (easiest first) +- `./mako.sh symbols add [size]` - Add new symbol +- `./mako.sh format` - Format code + +## Project Structure + +``` +src/ # Decompiled C source (organized by overlay) +asm/us/ # MIPS assembly (original/undecompiled) + └── / + ├── nonmatchings/ # Undecompiled function .s files + └── data/ # Data segment .s files +include/ # Headers (common.h, game.h, psxsdk/) +config/ # Build config and symbol files + ├── us.yaml # Main overlay definitions + ├── symbols.*.txt # Symbol address files + └── sym_*.txt # Import/export symbol files +build/us/ # Build output (.o, .exe, .map files) +tools/ # Build tools (Go builder, Python scripts) +disks/us/ # Extracted game files (from disc image) +``` + +## Overlays + +| Overlay | VRAM Start | Source | Description | +|---------|------------|--------|-------------| +| main | 0x80010000 | `src/main/` | Core engine, initialization | +| battle | 0x800A0000 | `src/battle/` | Battle system | +| batini | 0x801B0000 | `src/battle/batini.c` | Battle initialization | +| field | 0x800A0000 | `src/field/` | Field exploration | +| world | 0x800A0000 | `src/world/` | World map | +| menu | varies | `src/menu/` | Menu systems (savemenu, title, etc.) | + +## Decompilation Workflow + +### 1. Find a function to decompile +```shell +# List undecompiled functions, ranked by difficulty (easiest first) +./mako.sh rank src/battle/nonmatchings/battle + +# Or browse asm files directly +ls asm/us/battle/nonmatchings/battle/ +``` + +### 2. Decompile with m2c +```shell +# This replaces INCLUDE_ASM in the .c file with decompiled code and performs struct field replacement +./mako.sh dec func_800A1158 --fix-structs +``` + +### 3. Refine the code +- Fix unknown types (marked with `/*?*/`) +- Match register allocation and instruction order +- Add/reference symbols in `config/symbols.*.txt` +- The goal is to produce a decompiled code that is 1:1 matching the original PSX binaries + +### 4. Build and verify +```shell +make build # Rebuilds and verifies SHA1 match +``` + +### 5. Format and submit +```shell +make format +git add config/ include/ src/ +git commit -m "Decompile func_800A1158" +``` + +## Code Patterns + +### INCLUDE_ASM Macro +Embeds undecompiled assembly: +```c +INCLUDE_ASM("asm/us/battle/nonmatchings/battle", func_800A1158); +``` +Replace with decompiled C code when function matches. + +### Common Types +```c +typedef signed char s8; typedef unsigned char u8; +typedef signed short s16; typedef unsigned short u16; +typedef signed int s32; typedef unsigned int u32; +typedef u8 unk_data; typedef unsigned int* unk_ptr; +``` + +### String Encoding +FF7 uses custom character encoding, not ASCII. Use `_S()` macro: +```c +const char* msg = _S("Save game?"); +``` + +## Naming Conventions + +### Functions +- Undecompiled: `func_800XXXXX` (address-based) +- Decompiled: verb-first descriptive names, prefer PSX SDK names when applicable +- Examples: `InitBattle`, `LoadScene`, `DrawSprite` + +### Data/Globals +- Unknown: `D_800XXXXX` (address-based) +- Known game state: `g_` prefix (e.g., `g_BattleState`) +- Module constants: module prefix (e.g., `BATTLE_MAX_ENEMIES`) +- Struct fields: `unkXX` until purpose known + +## Symbol Files + +Located in `config/`: +- `symbols.main.us.txt` - Main overlay symbols +- `symbols.battle.txt` - Battle overlay symbols +- `sym_export.us.txt` - Cross-overlay exports +- `sym_extern.us.txt` - External references + +Format: +``` +function_name = 0x800A1158; +D_800F5BB8 = 0x800F5BB8; // size:0xCC +``` + +Add symbols with: +```shell +./mako.sh symbols add config/symbols.battle.txt MyFunction 0x800A1234 +``` + +## Key Data Structures + +### Savemap (0x8009C6E4) +Game save data. Use `--fix-structs` to auto-replace `D_8009XXXX` references: +- `Savemap.party[9]` - Party member data +- `Savemap.inventory` - Item inventory +- `Savemap.materia` - Materia slots +- `Savemap.gil` - Money +- See `tools/fix_structs.py` for full field list + +### Battle Structures (`src/battle/battle.h`) +- `BattleSetup` - Battle configuration +- `Unk800F83E0` - Battle state (0x68 bytes) +- `BattleSetupType` - Encounter types (preemptive, back attack, etc.) + +## Tips for Matching + +1. **Compiler quirks**: Two PSX compilers available (`cc1-psx-26`, `cc1-psx-272`). Check which one the overlay uses in `config/us.yaml`. + +2. **Register allocation**: Order of operations matters. Sometimes restructuring expressions helps match. + +3. **Global pointer (GP)**: Main overlay uses `gp=0x80062D44`. Variables near this use gp-relative addressing. + +4. **Rodata association**: Battle overlay has `migrate_rodata_to_functions: true` - rodata is bundled with functions. + +5. **Use mipsel-linux-gnu-objdump** for line-by-line comparison + +## Comparing Original vs Compiled Assembly + +When a decompiled function doesn't match, compare the original assembly with the compiled output: + +### 1. Check Function Size (Quick Check) +```shell +# Get compiled function size from symbol table +./tools/docker-build.sh "mipsel-linux-gnu-objdump -t build/us/src/main/18B8.c.o" | grep func_80026F44 + +# Output: 00015e8c g F .text 00000128 func_80026F44 +# ^^^^^^^^ ^^^^^^^^ <- size in hex (0x128 = 296 bytes) +``` + +Compare with original size: count bytes from function start to end in the `.s` file, or calculate from addresses (end_addr - start_addr + 4). + +### 2. View Compiled Disassembly +```shell +# Disassemble a specific function from the compiled object +./tools/docker-build.sh "mipsel-linux-gnu-objdump -d build/us/src/main/18B8.c.o" | grep -A100 ':' +``` + +### 3. View Original Assembly +```shell +# Original assembly is in asm/us//nonmatchings// +cat asm/us/main/nonmatchings/18B8/func_80026F44.s +``` + +### 4. Common Size Mismatch Causes +- **Code merged after branches**: Compiler optimizes common code after if/else. Fix: put function calls inside each branch. +- **Delay slot optimization**: Original uses delay slots cleverly. The compiled code may not reproduce this. +- **Sign extension duplication**: Original may have `sll/sra` pairs duplicated in branches; compiler merges them. +- **Register allocation**: Different register choices can cause different instruction sequences. +- **Type differences**: `s8` vs `u8` generates `lb` vs `lbu` instructions. + +### 5. Useful Patterns +```shell +# Count instructions in original (each line with glabel excluded, /* */ comments have instructions) +grep -c '/\*' asm/us/main/nonmatchings/18B8/func_80026F44.s + +# Find jr ra (function returns) to identify function boundaries +./tools/docker-build.sh "mipsel-linux-gnu-objdump -d build/us/src/main/18B8.c.o" | grep 'jr.*ra' +``` + +## Decompilation Tips Checklist + +When decompiling a function, follow this checklist: + +- [ ] No prototypes or parameters with '?' as type +- [ ] No 'void*' parameters that should be typed structs +- [ ] No pointer arithmetic with manual offset calculations +- [ ] Use array indices to access arrays, do not use arithmetic calculations +- [ ] All struct field accesses use '->' or '.' operators +- [ ] Struct sizes match the assembly access patterns +- [ ] 'goto loop_*' are converted as 'while' loops +- [ ] 'goto block_*' in 'switch' are inlined, to reverse code optimization + +Alignment is critical. Code and data are aligned by 4-byte. + +## Finding symbol names and applying them to the decompiled code + +Our goal in this project currently is to find out as many symbol names (functions, variables, enums, structs, local variables, function parameters) as possible and apply them to the decompiled code. At the same time we want to ensure the code compiles 1:1 matching the original PSX binaries so we cannot alter the parameter types and change any logic. + +1. First we need to analyse both the decompiled PSX code in the @src/ folder and the PC decompiled code in the @assets/ folder. You usually start with a function in the PSX code that is unique enough and already has some symbols decompiled or its logic is recognizable enough that it can be matched to the PC code. +2. Spawn a sub-agent to look through the PC code in the @assets/ folder (do not read these files directly because they're huge) and find any corresponding code that can help us find new symbol names +3. Map out the connections between the PSX code (skip function names defined with INCLUDE_ASM macro, only functions fully defined in C can be renamed) and the PC code and store your findings in @CLAUDE_DECOMP.md for future reference. Make sure you're absolutely certain when creating this mapping - if there is any doubt about a specific symbol you should skip it. +4. Apply the changes. To do this spawn an Apply sub-agent that will take a map of symbol names to update (eg. "func_800A1158 = MyFunction", "D_800F5BB8 = MyVariable") and then the sub-agent will figure out how to efficiently and comprehensively apply these changes to the PSX code in @src/ (remember to update references to the changed symbol names in other source and header files; when changing a function name you should update all function calls to it in the code). The sub-agent should think hard to make sure it does not break anything as some symbol names are used in multiple places. The sub-agent shall not alter parameter types in function signatures. The sub-agent shall not read or update the assembly files in asm/ (these are generated by the disassembler and should not be manually edited). After finishing applying the changes it should return immediately without trying to run the build. +5. In parallel spawn a second sub-agent that will update the symbol maps in @config/ in symbols.main.us.txt and any other *.txt files that contain symbol names (skip sym_export.us.txt and sym_export_battle.us.txt since these are autogenerated by the build system) +6. After the work is done run the build to verify if the changes are correct. The build should succeed without any errors and all the SHA1 sums should match. Fix any issues that arise and repeat the process until the changes are correct. +7. Take one more look at CLAUDE_DECOMP.md and make sure its updated with all the new knowledge you've gained. +8. Finally think about what the next steps would be and suggest options to the user + +## Files to Commit +When submitting decompiled code: +```shell +git add config/ # Symbol files +git add include/ # Headers (if modified) +git add src/ # Decompiled source +``` + +## Advanced Matching Techniques + +### Understanding Why Decompiled Code Doesn't Match + +When the size is wrong, the compiler is generating different code structure. Common causes: + +#### 1. Merged Function Calls +**Problem**: Modern compilers merge common code after if/else branches. +```c +// BAD - compiler merges the call after the branches +if (condition) { + setup_a(); +} else { + setup_b(); +} +common_call(); // Compiler optimizes: one call site + +// GOOD - forces separate code paths (matches original) +if (condition) { + setup_a(); + common_call(); // Call inside branch +} else { + setup_b(); + common_call(); // Duplicate call +} +``` + +#### 2. Variable Type Affects Load Instructions +- `s8` generates `lb` (load byte signed) +- `u8` generates `lbu` (load byte unsigned) +- Check if global variables need type changes to match original instructions + +#### 3. Struct vs Separate Variables +**Problem**: Compiler optimizes away stores to local variables if it thinks they're unused. +```c +// BAD - compiler may skip storing to sp1C, sp1E +s16 sp18, sp1A, sp1C, sp1E; +sp1C = 0xFF; // May be optimized away! +sp1E = 0xFF; +sp18 = 0; +sp1A = 0; +SetDrawMode(..., (RECT*)&sp18); + +// GOOD - using proper struct ensures all fields are stored +RECT rect; +rect.w = 0xFF; // Compiler knows RECT fields are accessed +rect.h = 0xFF; +rect.x = 0; +rect.y = 0; +SetDrawMode(..., &rect); +``` + +#### 4. Delay Slot Optimization +Original PSX compiler often put useful instructions in branch delay slots. Modern compilers may: +- Put the instruction before the branch instead +- Use NOP in delay slots + +Example: Original saves `y << 16` before loop, uses delay slot for `s2 = 0`: +```asm +beqz v0, check_mode +addu s2, zero, zero # delay slot: s2 = 0 +sll s1, a1, 16 # after branch: save y +``` + +#### 5. Redundant Instructions in Original +The original compiler sometimes generated redundant code: +- `andi t0, v1, 0xFF` after `lbu v1` (already 8-bit) +- Duplicate `sra a1, s1, 16` in both branches + +These are hard to reproduce with modern compilers without tricks. + +### Matching Workflow + +1. **Get size right first** - Restructure code until instruction count matches (note: if the output size is wrong you might see compiler/linker errors in unrelated files - this is a good indicator that the size is wrong) +2. **Fix types second** - Change s8/u8, s16/u16 to match load/store instructions +3. **Reorder operations** - Match the order of stores/loads in original +4. **Check branch structure** - Use goto labels to match original control flow +5. Look at other decompiled functions in the same file to see how they handle similar patterns to the ones you're trying to match + +### Debugging Commands +```shell +# Compare function sizes +./tools/docker-build.sh "mipsel-linux-gnu-objdump -t build/us/src/main/18B8.c.o" | grep func_NAME + +# View compiled assembly +./tools/docker-build.sh "mipsel-linux-gnu-objdump -d build/us/src/main/18B8.c.o" | grep -A100 ':' + +# Original is in asm/us//nonmatchings//func_NAME.s +``` + +## Reference Links +- PSX SDK docs: PSY-Q library documentation +- FF7 Scarlet: https://github.com/petfriendamy/ff7-scarlet (game data structures) diff --git a/tools/docker-build.sh b/tools/docker-build.sh new file mode 100755 index 0000000..900f8df --- /dev/null +++ b/tools/docker-build.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Optimized Docker build wrapper for FF7 decomp +# This script adds Go caching for 3x faster builds + +set -e + +# Create Go cache directories if they don't exist +mkdir -p ~/.cache/ff7-go-mod ~/.cache/ff7-go-build + +# Run Docker with all necessary volume mounts including Go caches +exec docker run --rm --platform=linux/amd64 \ + -v "$(pwd)":/ff7 \ + -v ff7_venv:/ff7/.venv \ + -v "$(pwd)/build":/ff7/build \ + -v "$HOME/.cache/ff7-go-mod":/gocache/mod \ + -v "$HOME/.cache/ff7-go-build":/gocache/build \ + -e "GOMODCACHE=/gocache/mod" \ + -e "GOCACHE=/gocache/build" \ + ff7-build:latest -lc "cd /ff7 && $*" From 1d4b0b76ce75455fbdde8d3fc98b5551fe6aad43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Tr=C4=99bacz?= Date: Sun, 28 Dec 2025 16:51:10 +0100 Subject: [PATCH 2/3] Add symbol names in main & menu overlays --- CLAUDE.md | 32 ++++ config/sym_ovl_export.us.txt | 2 +- config/symbols.cnfgmenu.us.txt | 2 + config/symbols.main.us.txt | 52 ++++++ config/symbols.savemenu.us.txt | 1 + include/game.h | 33 ++-- src/battle/battle3.c | 34 ++-- src/main/18B8.c | 179 ++++++++++----------- src/main/ovl.c | 4 +- src/menu/bginmenu.c | 32 ++-- src/menu/cnfgmenu.c | 74 ++++----- src/menu/savemenu.c | 248 ++++++++++++++--------------- src/menu/savemenu.h | 8 +- src/menu/title.c | 278 ++++++++++++++++----------------- 14 files changed, 537 insertions(+), 442 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6b1a440..6f116ce 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,6 +113,38 @@ INCLUDE_ASM("asm/us/battle/nonmatchings/battle", func_800A1158); ``` Replace with decompiled C code when function matches. +### Renaming INCLUDE_ASM Functions + +INCLUDE_ASM functions can be renamed without decompiling them. The process differs between the **main overlay** and **other overlays**: + +#### Main Overlay (src/main/*.c) +The asm files in `asm/us/main/nonmatchings/` are **static** - they persist on disk and are not regenerated. + +To rename a function (e.g., `func_80026F44` → `MenuDrawText`): +1. **Rename the asm file**: `mv asm/us/main/nonmatchings/18B8/func_80026F44.s asm/us/main/nonmatchings/18B8/MenuDrawText.s` +2. **Update the asm file contents**: + - Change `glabel func_80026F44` → `glabel MenuDrawText` + - Change `.size func_80026F44, . - func_80026F44` → `.size MenuDrawText, . - MenuDrawText` +3. **Update the INCLUDE_ASM macro** in the C file +4. **Update all call sites** in `src/` that reference this function +5. **Update the symbol file** (e.g., `config/symbols.main.us.txt`) + +#### Other Overlays (src/menu/*.c, src/battle/*.c, etc.) +The asm files in overlay directories are **regenerated by splat** on each build. Renaming the files directly won't work - splat will recreate them with the old names. + +To rename a function (e.g., `func_801D080C` → `MenuConfig` in cnfgmenu): +1. **Add the new name to the overlay's symbol file** (e.g., `config/symbols.cnfgmenu.us.txt`): + ``` + MenuConfig = 0x801D080C; + ``` +2. **Update `config/sym_ovl_export.us.txt`** (for cross-overlay references): + - Change `func_801D080C = 0x801d080c;` → `MenuConfig = 0x801d080c;` +3. **Update the INCLUDE_ASM macro** in the C file +4. **Update any references** in other files (e.g., `src/main/ovl.c` for exported functions) +5. **Run the build** - splat will generate the asm file with the new name + +The old asm file may remain in the directory but will be unused. It can be deleted manually. + ### Common Types ```c typedef signed char s8; typedef unsigned char u8; diff --git a/config/sym_ovl_export.us.txt b/config/sym_ovl_export.us.txt index d56fe19..7552969 100644 --- a/config/sym_ovl_export.us.txt +++ b/config/sym_ovl_export.us.txt @@ -1943,8 +1943,8 @@ func_801D0408 = 0x801d0408; func_801D0500 = 0x801d0500; func_801D05C4 = 0x801d05c4; func_801D0704 = 0x801d0704; +MenuConfig = 0x801d080c; func_801D069C = 0x801d069c; -func_801D080C = 0x801d080c; unused = 0x801d2514; func_801D05C0 = 0x801d05c0; func_801D06B0 = 0x801d06b0; diff --git a/config/symbols.cnfgmenu.us.txt b/config/symbols.cnfgmenu.us.txt index ce054a2..d8f1a38 100644 --- a/config/symbols.cnfgmenu.us.txt +++ b/config/symbols.cnfgmenu.us.txt @@ -1,4 +1,6 @@ D_8009D7C0 = 0x8009D7C0; // size:0x10 +PlaySound = 0x801D0040; +MenuConfig = 0x801D080C; D_801D2478 = 0x801D2478; // size:0x14 D_801D24A0 = 0x801D24A0; // size:0x10 D_801D24B8 = 0x801D24B8; // size:0x8 diff --git a/config/symbols.main.us.txt b/config/symbols.main.us.txt index 1fe7c0e..3624890 100644 --- a/config/symbols.main.us.txt +++ b/config/symbols.main.us.txt @@ -1,9 +1,54 @@ __main = 0x800110B8; __SN_ENTRY_POINT = 0x800110C0; main = 0x80011C1C; +MenuUnloadPortraits = 0x80017678; +MenuLoadPartyPortrait = 0x8001786C; SetupGamepad = 0x8001C434; +MenuStoreKeypressBitmask = 0x8001CB48; +MenuDrawPartyPortrait = 0x8001D180; +MenuCreateWindow = 0x8001DE0C; +MenuMoveWindow = 0x8001DE24; +MenuCopyWindow = 0x8001DE40; +MenuStoreWindowColors = 0x8001DE70; +MenuRestoreWindowColors = 0x8001DEB0; +MenuSetWindowColors = 0x8001DEF0; +MenuDrawWindow = 0x8001E040; +MenuDrawCursor = 0x8001EB2C; +MenuGetPopupState = 0x8001F6B4; +MenuShowPopupText = 0x8001F6C0; +MenuUpdatePopup = 0x8001F710; +MenuLoadPartyData = 0x80020058; +MenuInitDisplayEnv = 0x80021044; +MenuSetTransition = 0x8002120C; +MenuIsBusy = 0x80023050; +MenuExitSubmenu = 0x8002305C; +MenuDrawSubmenuTitle = 0x800230C4; +MenuGetPlaytimeHours = 0x80023788; +MenuGetPlaytimeMinutes = 0x8002382C; +PartyAddMateria = 0x8002542C; SYS_gil = 0x80025B7C; +MenuLoadTexture = 0x80025D14; +MenuGetMateriaColor = 0x8002603C; +MenuSetCursorPickerObj = 0x80026448; +MenuCursorPickerHandler = 0x800264A8; +SetPolyBuffer = 0x800269C0; +MenuPushDrawState = 0x800269D0; +MenuPopDrawState = 0x800269E8; +MenuSetOTag = 0x80026A00; func_80026A0C = 0x80026A0C; +MenuSetDrawMode = 0x80026A34; +MenuSetClipRect = 0x80026A94; +MenuSetBrightness = 0x80026B5C; +MenuSetBrightnessUnused = 0x80026B64; +MenuGetTextWidth = 0x80026B70; +MenuDrawText = 0x80026F44; +MenuDrawLetter = 0x8002708C; +MenuDrawSliderBg = 0x80027B84; +MenuDrawSlider = 0x80028030; +MenuDrawProgressBar = 0x800285AC; +MenuDrawBtlImage = 0x80028CA0; +MenuDrawNumber = 0x80028E00; +MenuDrawNumberPadded = 0x80029114; SetReverbMode = 0x80029AF0; DS_read = 0x80033E74; ChangeClearSIO = 0x80034CE8; @@ -444,6 +489,13 @@ _patch_card = 0x80048B34; _patch_card2 = 0x80048BEC; _ExitCard = 0x80048C7C; g_bPadsInitialized = 0x80062D70; +ButtonsDown = 0x80062D78; +ButtonsTapped = 0x80062D7C; +MenuPopupState = 0x80062DDB; +MenuPopupTextColor = 0x80062DDC; +MenuPopupDelayCounter = 0x80062DE0; +MenuBusy = 0x80062DF8; +MenuPopupText = 0x80062EB8; D_800696AC = 0x800696AC; g_ReverbMode = 0x8009A140; g_ReverbAttr = 0x8009C564; // type:SpuReverbAttr size:0x14 diff --git a/config/symbols.savemenu.us.txt b/config/symbols.savemenu.us.txt index 804e9f7..3490a89 100644 --- a/config/symbols.savemenu.us.txt +++ b/config/symbols.savemenu.us.txt @@ -1,5 +1,6 @@ func_801D1774 = 0x801D1774; func_801D1BAC = 0x801D1BAC; +PlaySound = 0x801D2B58; // title.c static g_MenuStartMode = 0x801E2CF8; D_801E2E64 = 0x801E2E64; menus = 0x801E379C; // size:0x90 diff --git a/include/game.h b/include/game.h index 6488821..84fd542 100644 --- a/include/game.h +++ b/include/game.h @@ -61,8 +61,8 @@ typedef struct { s8 unkE; s8 unkF; s8 unk10; - s8 unk11; // scroll type: 0=no wrap, 1/2:wrap, 3>:infinite -} Unk80026448; // size: 0x12 + s8 unk11; // scroll type: 0=no wrap, 1/2:wrap, 3>:infinite +} CursorPicker; // size: 0x12 typedef union { void* poly; @@ -293,13 +293,13 @@ typedef struct { u8 unB0[0x390]; } Unk8009D84C; // size: 0x440 -extern u8 D_80049208[12]; // window colors maybe?? -extern u8 D_800492F0[][12]; // see Labels enum -extern u16 D_80062D78; // pressed button? -extern u16 D_80062D7C; // pressed button? -extern u16 D_80062D7E; // pressed button? -extern u16 D_80062D80; // tapped button -extern u16 D_80062D82; // repeated button +extern u8 D_80049208[12]; // window colors maybe?? +extern u8 D_800492F0[][12]; // see Labels enum +extern u16 ButtonsDown; // pressed button? +extern u16 ButtonsTapped; // pressed button? +extern u16 ButtonsRepeating; // pressed button? +extern u16 D_80062D80; // tapped button +extern u16 D_80062D82; // repeated button extern u8 D_80062D98; extern u8 D_80062D99; extern s32 D_80062DCC; @@ -342,13 +342,14 @@ s32 func_8001521C(s32); const char* func_80015248(s32 arg0, s32 arg1, s32 arg2); void func_800155A4(s32); void func_8001726C(s16, u16); -void func_80021044(DRAWENV* draw_env, DISPENV* disp_env); -void func_80026448(Unk80026448* arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, - s32 arg5, s32 arg6, s32 arg7, s32 arg8, s32 arg9, s32 arg10, - s32 arg11, s32 arg12, u16 arg13); -void func_800269C0(void* poly); -s32 func_80026B70(unsigned char* str); -void func_80026F44(s32 x, s32 y, const char*, s32 color); // print FF7 string +void MenuInitDisplayEnv(DRAWENV* draw_env, DISPENV* disp_env); +void MenuSetCursorPickerObj( + CursorPicker* arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, + s32 arg6, s32 arg7, s32 arg8, s32 arg9, s32 arg10, s32 arg11, s32 arg12, + u16 arg13); +void SetPolyBuffer(void* buffer); +s32 MenuGetTextWidth(unsigned char* str); +void MenuDrawText(s32 x, s32 y, const char*, s32 color); // print FF7 string void func_8002DA7C(); int func_80033DAC(int sector_no, void (*cb)()); diff --git a/src/battle/battle3.c b/src/battle/battle3.c index f3d9dad..5cdbaaf 100644 --- a/src/battle/battle3.c +++ b/src/battle/battle3.c @@ -73,7 +73,7 @@ static void func_800DBEA4(s32 arg0, s16 arg1) { func_800DBC18(arg0, arg1); } INCLUDE_ASM("asm/us/battle/nonmatchings/battle3", func_800DBEC8); -static void func_800DBF54(void) { func_800269C0(D_80077F64); } +static void func_800DBF54(void) { SetPolyBuffer(D_80077F64); } static void func_800DBF7C(void) { D_800F3122 = 0; } @@ -105,7 +105,7 @@ static void func_800DD690(s32 arg0, s16 arg1) { s32 setupType; s32 temp_v1; - func_80026A00(); + MenuSetOTag(); switch (arg1) { case 0: func_800E2098(); @@ -131,10 +131,10 @@ static void func_800DD690(s32 arg0, s16 arg1) { if (temp_v1 < NUM_SETUP) { setupType = -(temp_v1 <= SETUP_BACK_ATTACK) & 7; } - func_80026F44(8, 7, func_80015248(5, 0x12, 8), setupType); + MenuDrawText(8, 7, func_80015248(5, 0x12, 8), setupType); break; case 3: - func_80026F44(9, 7, func_80015248(5, 0x13, 8), 7); + MenuDrawText(9, 7, func_80015248(5, 0x13, 8), 7); break; case 24: func_800E33A0(); @@ -242,7 +242,7 @@ void func_800DF900(void) { u16* tapped; if (D_800F3896 == 3 && D_800F99E4 == 0) { - tapped = &D_80062D7E; + tapped = &ButtonsRepeating; if (*tapped & 0x20) { func_800BB9B8(1); D_800F99E4 = 1; @@ -250,7 +250,7 @@ void func_800DF900(void) { func_800A4350(D_800F38A0, D_800F389C, D_800F389E, D_801516F8); func_800D9F5C(3); func_800D9F5C(1); - } else if (D_80062D7E & 0x8040) { + } else if (ButtonsRepeating & 0x8040) { func_800BB9B8(4); D_800F99E4 = 1; D_800F3896 = 1; @@ -287,7 +287,7 @@ void func_800E0294(void) { temp_s0 = &D_8009D84C[D_800F38A1].unAC[0]; if (D_800F3896 == 0x1B && D_800F99E4 == 0) { - if (D_80062D7E & 0x20) { + if (ButtonsRepeating & 0x20) { if (func_800E54EC() == 2) { D_800F99E4 = 1; func_800BB9B8(1); @@ -300,7 +300,7 @@ void func_800E0294(void) { func_800D9F5C(0x1B); func_800D9F5C(1); } - } else if ((D_80062D7E & 0x40) && (func_800E54EC() == 0)) { + } else if ((ButtonsRepeating & 0x40) && (func_800E54EC() == 0)) { func_800BB9B8(4); D_800F99E4 = 1; D_800F3896 = 1; @@ -318,7 +318,7 @@ void func_800E03F0(void) { temp_s0 = &D_8009D8F8[D_800F38A1 * 0x440]; if ((D_800F3896 == 0x1A) && (D_800F99E4 == 0)) { - if (D_80062D7E & 0x20) { + if (ButtonsRepeating & 0x20) { D_800F99E4 = 1; if (func_800E4BCC() == 2) { func_800BB9B8(1); @@ -331,7 +331,7 @@ void func_800E03F0(void) { func_800D9F5C(0x1A); func_800D9F5C(1); } - } else if ((D_80062D7E & 0x40) && (func_800E4BCC() == 0)) { + } else if ((ButtonsRepeating & 0x40) && (func_800E4BCC() == 0)) { func_800BB9B8(4); D_800F99E4 = 1; D_800F3896 = 1; @@ -352,8 +352,8 @@ INCLUDE_ASM("asm/us/battle/nonmatchings/battle3", func_800E0794); void func_800E084C(void) { if (D_800F3896 == 9) { - func_800264A8(&D_800F9144); - if (D_80062D7C & 0x20) { + MenuCursorPickerHandler(&D_800F9144); + if (ButtonsTapped & 0x20) { if (D_800F914E == 0) { func_800A4844(1); } else { @@ -418,7 +418,7 @@ static void func_800E1938(s16 arg0, s16 arg1, s32 arg2) { } x = ((var_a3 & 1) << 4) | 0x60; y = ((var_a3 >> 1) << 4) + 0x70; - func_80028CA0(arg0, arg1, x, y, 0x10, 0x10, 1, 0); + MenuDrawBtlImage(arg0, arg1, x, y, 0x10, 0x10, 1, 0); } INCLUDE_ASM("asm/us/battle/nonmatchings/battle3", func_800E1A2C); @@ -590,12 +590,12 @@ INCLUDE_ASM("asm/us/battle/nonmatchings/battle3", func_800E6018); INCLUDE_ASM("asm/us/battle/nonmatchings/battle3", func_800E60F8); -s32 func_800E6820(void) { return func_80026B70(D_800F384A); } +s32 func_800E6820(void) { return MenuGetTextWidth(D_800F384A); } static void func_800E6848(void) { - func_80026F44(0x10, 8, &D_800F3828[0], 7); - func_80026F44(0x2C, 0x1C, &D_800F3828[0x22], 7); - func_80026F44(func_800E6820() + 0x4C, 0x1C, &D_800F3828[0x44], 7); + MenuDrawText(0x10, 8, &D_800F3828[0], 7); + MenuDrawText(0x2C, 0x1C, &D_800F3828[0x22], 7); + MenuDrawText(func_800E6820() + 0x4C, 0x1C, &D_800F3828[0x44], 7); } INCLUDE_ASM("asm/us/battle/nonmatchings/battle3", func_800E68B4); diff --git a/src/main/18B8.c b/src/main/18B8.c index 9abb132..3482e8b 100644 --- a/src/main/18B8.c +++ b/src/main/18B8.c @@ -37,11 +37,11 @@ typedef struct { } GzHeader; typedef struct { - u16 unk0; - u16 unk2; - u16 unk4; - u16 unk6; -} Unk8001DE0C; + u16 x; + u16 y; + u16 w; + u16 h; +} Window; typedef struct { u8 padABuffer; @@ -122,10 +122,10 @@ s8 D_80062D71 = 0x00; s16 D_80062D72 = 0x0000; s16 D_80062D74 = 0x0000; s16 D_80062D76 = 0x0000; -u16 D_80062D78 = 0x0000; +u16 ButtonsDown = 0x0000; s16 D_80062D7A = 0x0000; -u16 D_80062D7C = 0x0000; -u16 D_80062D7E = 0x0000; +u16 ButtonsTapped = 0x0000; +u16 ButtonsRepeating = 0x0000; u16 D_80062D80 = 0x0000; u16 D_80062D82 = 0x0000; s32 D_80062D84 = 0x00000000; @@ -157,12 +157,12 @@ s32 D_80062DD0 = 0x00000000; s32 D_80062DD4 = 0x00000000; s16 D_80062DD8 = 0x0000; s8 D_80062DDA = 0x00; -u8 D_80062DDB = 0x00; -u8 D_80062DDC = 0x02; +u8 MenuPopupState = 0x00; +u8 MenuPopupTextColor = 0x02; static s8 _D_80062DDD = 0x00; static s8 _D_80062DDE = 0x00; static s8 _D_80062DDF = 0x00; -s32 D_80062DE0 = 0x00000000; +s32 MenuPopupDelayCounter = 0x00000000; u8 D_80062DE4 = 0x00; u8 D_80062DE5 = 0x00; s16 D_80062DE6 = 0x00B4; @@ -171,7 +171,7 @@ s16 D_80062DEA = 0x0000; s32 D_80062DEC = 0x801D0000; s32 D_80062DF0 = 0x00000084; s32 D_80062DF4 = 0xFFFFFFFF; -s32 D_80062DF8 = 0x00000001; +s32 MenuBusy = 0x00000001; s8 D_80062DFC = 0x40; static s8 _D_80062DFD = 0x00; static s8 _D_80062DFE = 0x00; @@ -259,7 +259,7 @@ s8 D_80062EB4 = 0x00; static s8 _D_80062EB5 = 0x00; static s8 _D_80062EB6 = 0x00; static s8 _D_80062EB7 = 0x00; -s32 D_80062EB8 = 0; +s32 MenuPopupText = 0; s8 D_80062EBC = 0; static s8 _D_80062EBD = 0; static s8 _D_80062EBE = 0; @@ -275,7 +275,7 @@ u16* func_80014D9C(s32, s32, s32); s32 func_800150E4(u16*, u16*); u16* func_800151F4(s32); void func_80015CA0(GzHeader* src, s32* dst); -u8 func_8001F6B4(); +u8 MenuGetPopupState(); void __main(void) {} @@ -725,9 +725,9 @@ void func_80017238(u32 arg0, u32* arg1, u8* arg2) { INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001726C); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80017678); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuUnloadPortraits); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001786C); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuLoadPartyPortrait); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80017E68); @@ -903,7 +903,7 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001C498); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001C4E8); void func_8001C58C(void) { - if (!func_8001F6B4()) { + if (!MenuGetPopupState()) { D_80062D71 = 0; } } @@ -918,7 +918,7 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001C8D4); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001C980); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001CB48); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuStoreKeypressBitmask); void func_8001CDA4(void) { SetPolyFT4(D_80062F24.ft4); @@ -974,8 +974,8 @@ void func_8001CF3C(s16 x, s16 y, s16 w, s16 h, u16 tx, u16 ty, u16 tw, u16 th, D_80062F24.ft4++; } -void func_8001D180(s16 x, s16 y, s16 w, s16 h, u16 tx, u16 ty, u16 tw, u16 th, - s16 clut, s32 tex) { +void MenuDrawPartyPortrait(s16 x, s16 y, s16 w, s16 h, u16 tx, u16 ty, u16 tw, + u16 th, s16 clut, s32 tex) { SetPolyFT4(D_80062F24.ft4); SetShadeTex(D_80062F24.ft4, 1); if (tex << 0x10) { @@ -1049,37 +1049,37 @@ void func_8001D56C(s16 x0, s16 y0, s16 x1, s16 y1, s16 is_yellow) { INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001D6A8); -void func_8001DE0C(Unk8001DE0C* arg0, s16 arg1, s16 arg2, s16 arg3, s32 arg4) { - arg0->unk0 = arg1; - arg0->unk2 = arg2; - arg0->unk4 = arg3; - arg0->unk6 = arg4; +void MenuCreateWindow(Window* window, s16 x, s16 y, s16 w, s32 h) { + window->x = x; + window->y = y; + window->w = w; + window->h = h; } // translate window dialog -void func_8001DE24(Unk8001DE0C* arg0, s32 arg1, s32 arg2) { - arg0->unk0 = arg0->unk0 + arg1; - arg0->unk2 = arg0->unk2 + arg2; +void MenuMoveWindow(Window* window, s32 dx, s32 dy) { + window->x = window->x + dx; + window->y = window->y + dy; } // set window dialog rect -void func_8001DE40(Unk8001DE0C* arg0, Unk8001DE0C* arg1) { - arg0->unk0 = arg1->unk0; - arg0->unk2 = arg1->unk2; - arg0->unk4 = arg1->unk4; - arg0->unk6 = arg1->unk6; +void MenuCopyWindow(Window* dest, Window* src) { + dest->x = src->x; + dest->y = src->y; + dest->w = src->w; + dest->h = src->h; } -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001DE70); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuStoreWindowColors); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001DEB0); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuRestoreWindowColors); #ifndef NON_MATCHINGS -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001DEF0); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuSetWindowColors); #else // only matches with --aspsx-version=2.21 // sets the menu color with a quadruplet of RGB values -void func_8001DEF0(u8* menu_colors) { +void MenuSetWindowColors(u8* menu_colors) { s32 i; for (i = 0; i < 12; i++) { D_80049208[i] = *menu_colors++; @@ -1101,10 +1101,10 @@ void func_8001DF24(RECT* rect, u8 arg1, u8 arg2, u8 arg3) { } // prints menu window -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001E040); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawWindow); // print menu cursor -void func_8001EB2C(s16 x, s16 y) { +void MenuDrawCursor(s16 x, s16 y) { RECT rect; setSprt(D_80062F24.sprt); @@ -1122,7 +1122,7 @@ void func_8001EB2C(s16 x, s16 y) { rect.y = 0; rect.w = 0xFF; rect.h = 0xFF; - func_80026A34(0, 1, (u16)GetTPage(0, 2, 0x3C0, 0x100), &rect); + MenuSetDrawMode(0, 1, (u16)GetTPage(0, 2, 0x3C0, 0x100), &rect); } INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001EC70); @@ -1153,20 +1153,20 @@ void func_8001EF84(s32 x, s32 y, s32 n, s32 len) { rect.y = 0; rect.w = 255; rect.h = 255; - func_80026A34(0, 1, (u16)GetTPage(0, 1, 0x3C0, 0x100), &rect); + MenuSetDrawMode(0, 1, (u16)GetTPage(0, 1, 0x3C0, 0x100), &rect); } INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001F1BC); void func_8001F6AC(void) {} -u8 func_8001F6B4(void) { return D_80062DDB; } +u8 MenuGetPopupState(void) { return MenuPopupState; } -void func_8001F6C0(s32 arg0, s8 arg1) { - D_80062DDB = 1; - D_80062DDC = arg1; - D_80062DE0 = 0x28; - D_80062EB8 = arg0; +void MenuShowPopupText(s32 text, s8 color) { + MenuPopupState = 1; + MenuPopupTextColor = color; + MenuPopupDelayCounter = 0x28; + MenuPopupText = text; D_80062DE5 = 1; } @@ -1176,11 +1176,11 @@ void func_8001F6E4(s16 arg0, s16 arg1, s16 arg2) { D_80062DE6 = arg1; D_80062DE8 = arg2; } else { - D_80062DDB = 0; + MenuPopupState = 0; } } -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001F710); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuUpdatePopup); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001FA28); @@ -1206,13 +1206,13 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8001FFD4); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002001C); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80020058); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuLoadPartyData); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800206E4); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80020B68); -void func_80021044(DRAWENV* draw_env, DISPENV* disp_env) { +void MenuInitDisplayEnv(DRAWENV* draw_env, DISPENV* disp_env) { VSync(0); SetDefDrawEnv(draw_env, 0, 0, 0x180, 0x1D8); draw_env[0].dfe = 1; @@ -1247,7 +1247,7 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800211B8); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800211C4); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002120C); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuSetTransition); void func_80021258(s32 arg0) { func_80015248(13, arg0, 8); } @@ -1271,17 +1271,17 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80022DE4); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80022FE0); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80023050); +s32 MenuIsBusy(void) { return MenuBusy; } -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002305C); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuExitSubmenu); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800230C4); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawSubmenuTitle); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002368C); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80023788); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuGetPlaytimeHours); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002382C); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuGetPlaytimeMinutes); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80023940); @@ -1405,21 +1405,21 @@ void func_80025360() { func_8001FA28(0x19F); } INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80025380); -s32 func_8002542C(s32 arg0) { +s32 PartyAddMateria(s32 materiaId) { s32 i; for (i = 0; i < MAX_MATERIA_COUNT; i++) { if (Savemap.materia[i] == -1) { - Savemap.materia[i] = arg0; - if (func_8002603C(arg0 & 0xFF) == 10) { + Savemap.materia[i] = materiaId; + if (MenuGetMateriaColor(materiaId & 0xFF) == 10) { Savemap.memory_bank_1[75] |= 1; } - if ((arg0 & 0xFF) == 44) { + if ((materiaId & 0xFF) == 44) { Savemap.memory_bank_1[75] |= 2; } return -1; } } - return arg0; + return materiaId; } void func_800254D8() { D_80062EBC = 0; } @@ -1529,7 +1529,7 @@ void func_80025CD4(u_long* image) { StoreImage(&rect, image); } -void func_80025D14(u_long* addr, s32 px, s32 py, s32 cx, s32 cy) { +void MenuLoadTexture(u_long* addr, s32 px, s32 py, s32 cx, s32 cy) { TIM_IMAGE tim; OpenTIM(addr); while (ReadTIM(&tim)) { @@ -1566,7 +1566,7 @@ void func_80025DF8(void) { func_80033F40(sector_off[i * 2], length[i * 2], dst, 0); cx = 0x340 + (i / 5) * 0x18; cy = 0x100 + (i % 5) * 0x30; - func_80025D14(dst, cx, cy, 0x180, i); + MenuLoadTexture(dst, cx, cy, 0x180, i); DrawSync(0); } } @@ -1576,10 +1576,10 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80025ED4); void func_80026034(void) {} #ifndef NON_MATCHINGS -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002603C); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuGetMateriaColor); #else // --aspsx-version=2.21 -u8 func_8002603C(u8 arg0) { +u8 MenuGetMateriaColor(u8 arg0) { return D_80049520[D_80049528[D_800730DC[arg0][1] & 0xF]]; } #endif @@ -1594,9 +1594,10 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800262D8); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026408); -void func_80026448(Unk80026448* arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, - s32 arg5, s32 arg6, s32 arg7, s32 arg8, s32 arg9, s32 arg10, - s32 arg11, s32 arg12, u16 arg13) { +void MenuSetCursorPickerObj( + CursorPicker* arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, + s32 arg6, s32 arg7, s32 arg8, s32 arg9, s32 arg10, s32 arg11, s32 arg12, + u16 arg13) { arg0->unkA = arg1; arg0->unkB = arg2; arg0->unkC = arg3; @@ -1612,38 +1613,38 @@ void func_80026448(Unk80026448* arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, arg0->unk8 = arg13; } -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800264A8); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuCursorPickerHandler); -void func_800269C0(void* arg0) { D_80062F24.poly = arg0; } +void SetPolyBuffer(void* buffer) { D_80062F24.poly = buffer; } -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800269D0); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuPushDrawState); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800269E8); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuPopDrawState); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026A00); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuSetOTag); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026A0C); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026A20); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026A34); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuSetDrawMode); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026A94); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuSetClipRect); -void func_80026B5C(void) {} +void MenuSetBrightness(void) {} -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026B64); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuSetBrightnessUnused); -// strlen but for FF7 strings +// MenuGetTextWidth: returns pixel width of FF7 string // FF7 string is 0x00: ' ', 0x10: '0', 0x21: 'A', 0xFF: terminator -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026B70); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuGetTextWidth); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026C5C); // print FF7 string -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80026F44); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawText); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_8002708C); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawLetter); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80027354); @@ -1651,19 +1652,19 @@ INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80027408); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80027990); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80027B84); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawSliderBg); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80028030); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawSlider); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80028484); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_800285AC); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawProgressBar); INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80028930); -void func_80028CA0(s16, s16, s16, s16, s16, s16, s16, s16); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80028CA0); +void MenuDrawBtlImage(s16, s16, s16, s16, s16, s16, s16, s16); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawBtlImage); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80028E00); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawNumber); -INCLUDE_ASM("asm/us/main/nonmatchings/18B8", func_80029114); +INCLUDE_ASM("asm/us/main/nonmatchings/18B8", MenuDrawNumberPadded); diff --git a/src/main/ovl.c b/src/main/ovl.c index 252abda..b998935 100644 --- a/src/main/ovl.c +++ b/src/main/ovl.c @@ -15,13 +15,13 @@ void* D_800493A8[] = { void func_80023AD4(); void func_801D00C4(); -void func_801D080C(); +void MenuConfig(); void func_801D06B0(); void func_801D00C4(); void* D_800493FC[] = { func_80023AD4, (void*)0x801D0E80, (void*)0x801D0490, (void*)0x801D6C2C, (void*)0x801D0BD0, (void*)0x801D167C, func_801D00C4, (void*)0x801D042C, - func_801D080C, (void*)0x801D0E94, func_801D06B0, (void*)0x801D0250, + MenuConfig, (void*)0x801D0E94, func_801D06B0, (void*)0x801D0250, func_801D00C4, (void*)0x801D0E80, (void*)0x801D0E80, (void*)0x801D0BD0, (void*)0x801D0E80, (void*)0x801D0E80, (void*)0x801D0E80, (void*)0x801D0E80, (void*)0x801D0E80, diff --git a/src/menu/bginmenu.c b/src/menu/bginmenu.c index 5c6d513..9345cb0 100644 --- a/src/menu/bginmenu.c +++ b/src/menu/bginmenu.c @@ -17,13 +17,15 @@ extern u8 D_801D082C[21]; extern u8 D_801D0844[16]; extern u8 D_801D0854[7]; extern u8 D_801D085C[2]; -extern Unk80026448 D_801D0860[]; +extern CursorPicker D_801D0860[]; extern s8 D_801D086B; void func_801D0000(void) { volatile s32 padding; - func_80026448(&D_801D0860[0], 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 0, 1, 0); - func_80026448(&D_801D0860[1], 0, 0, 1, 3, 0, 0, 1, 9, 0, 0, 0, 0, 0); + MenuSetCursorPickerObj( + &D_801D0860[0], 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 0, 1, 0); + MenuSetCursorPickerObj( + &D_801D0860[1], 0, 0, 1, 3, 0, 0, 1, 9, 0, 0, 0, 0, 0); D_801D07F0 = 0; } @@ -31,18 +33,18 @@ void func_801D00C4(void) { volatile s32 padding[4]; s32 i; - func_800230C4(D_80062F58); + MenuDrawSubmenuTitle(D_80062F58); if (D_801D07F0 == 0) { - func_8001EB2C(0, D_801D07FE + (D_801D086B << 6) + 0x20); + MenuDrawCursor(0, D_801D07FE + (D_801D086B << 6) + 0x20); } - func_80026F44(0x10, 0xB, D_801D0804, 7); + MenuDrawText(0x10, 0xB, D_801D0804, 7); for (i = 0; i < 2; i++) { - func_8001E040(&D_801D07F4[i]); + MenuDrawWindow(&D_801D07F4[i]); } - func_800264A8(&D_801D0860[D_801D07F0]); - if (D_80062D7E & 0x40) { - func_8002305C(5, 0); - func_8002120C(0); + MenuCursorPickerHandler(&D_801D0860[D_801D07F0]); + if (ButtonsRepeating & 0x40) { + MenuExitSubmenu(5, 0); + MenuSetTransition(0); } } @@ -144,22 +146,22 @@ void func_801D0704(s32 arg0) { for (i = 0; i < 21; i++) { func_801D0324(D_801D082C[i]); } - func_8002542C(0x49); + PartyAddMateria(0x49); break; case 1: for (i = 0; i < 16; i++) { func_801D0324(D_801D0844[i]); } - func_8002542C(0x5A); + PartyAddMateria(0x5A); break; case 2: for (i = 0; i < 7; i++) { func_801D0324(D_801D0854[i]); } - func_8002542C(0x30); + PartyAddMateria(0x30); break; case 3: - func_8002542C(0x58); + PartyAddMateria(0x58); break; } } diff --git a/src/menu/cnfgmenu.c b/src/menu/cnfgmenu.c index bc89a7d..93962ed 100644 --- a/src/menu/cnfgmenu.c +++ b/src/menu/cnfgmenu.c @@ -104,12 +104,12 @@ static u16 D_801D24BC = 0; static u8 D_801D24C0[] = {4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0}; // from now on this is the BSS section; this can be moved up if necessary -static Unk80026448 D_801D24CC[4]; +static CursorPicker D_801D24CC[4]; static s32 unused[5]; static s32 D_801D2528; static u8 D_801D252C[LEN(D_80049208)]; -static void func_801D0040(u16 arg0) { +static void PlaySound(u16 arg0) { D_8009A000 = 0x30; D_8009A004 = arg0; D_8009A008 = arg0; @@ -150,7 +150,7 @@ static u8 func_801D0118(u16 arg0) { static void func_801D014C(s16 x, s16 y, s32 value) { u8 uv = D_801D1AAC[value * 2 + 0]; u8 page = D_801D1AAC[value * 2 + 1]; - func_80028CA0( + MenuDrawBtlImage( x, y, (uv & 3) * 16 + 96, (uv >> 2) * 16 + 64, 16, 16, page, 0); } @@ -165,67 +165,67 @@ static void func_801D01C8(void) { u8* setting; y = D_801D24A0[1].y + 33; - func_80026F44(40, D_801D24A0[1].y + 14, D_801D1AE8[0], 5); + MenuDrawText(40, D_801D24A0[1].y + 14, D_801D1AE8[0], 5); for (i = 1; i < 9; i++) { - func_80026F44(40, y + (i - 1) * 18, D_801D1AE8[i], 5); + MenuDrawText(40, y + (i - 1) * 18, D_801D1AE8[i], 5); } - func_80026F44(40, y + (i - 1) * 18, D_801D1AE8[33], 5); + MenuDrawText(40, y + (i - 1) * 18, D_801D1AE8[33], 5); for (i = 0; i < 2; i++) { - func_80026F44(165 + i * 65, y, D_801D1AE8[15 + i], - -((Savemap.config & 3) == i) & 7); + MenuDrawText(165 + i * 65, y, D_801D1AE8[15 + i], + -((Savemap.config & 3) == i) & 7); } for (i = 0; i < 2; i++) { - func_80026F44(165 + i * 65, y + 18, D_801D1E48[i], - -(((Savemap.config >> 2) & 3) == i) & 7); + MenuDrawText(165 + i * 65, y + 18, D_801D1E48[i], + -(((Savemap.config >> 2) & 3) == i) & 7); } for (i = 0; i < 2; i++) { - func_80026F44(165 + i * 65, y + 0x24, D_801D1EA8[i], - -(((Savemap.config >> 4) & 3) == i) & 7); + MenuDrawText(165 + i * 65, y + 0x24, D_801D1EA8[i], + -(((Savemap.config >> 4) & 3) == i) & 7); } temp_s4 = y + 54; - func_80026F44( + MenuDrawText( 165, temp_s4, D_801D1F08[0], -(((Savemap.config >> 6) & 3) == 0) & 7); - x = func_80026B70(D_801D1F08[0]); - func_80026F44(x + 175, temp_s4, D_801D1F08[1], - -(((Savemap.config >> 6) & 3) == 1) & 7); - func_80026F44(x + func_80026B70(D_801D1F08[1]) + 185, temp_s4, - D_801D1F08[2], -(((Savemap.config >> 6) & 3) == 2) & 7); + x = MenuGetTextWidth(D_801D1F08[0]); + MenuDrawText(x + 175, temp_s4, D_801D1F08[1], + -(((Savemap.config >> 6) & 3) == 1) & 7); + MenuDrawText(x + MenuGetTextWidth(D_801D1F08[1]) + 185, temp_s4, + D_801D1F08[2], -(((Savemap.config >> 6) & 3) == 2) & 7); for (i = 0; i < 2; i++) { - func_80026F44(165 + i * 65, y + 126, D_801D1F08[3 + i], - -(((Savemap.config >> 8) & 3) == i) & 7); + MenuDrawText(165 + i * 65, y + 126, D_801D1F08[3 + i], + -(((Savemap.config >> 8) & 3) == i) & 7); } for (i = 0; i < 3; i++) { _setting = D_801D248C[((Savemap.config >> 10) & 7) * 3 + i]; setting = &D_801D248C[((Savemap.config >> 10) & 7) * 3]; - func_80026F44(189 + i * 52, y + 0x90, D_801D1F08[12 + setting[i]], 7); + MenuDrawText(189 + i * 52, y + 0x90, D_801D1F08[12 + setting[i]], 7); } - func_80026F44(149, y + 0x90, D_801D1F08[16], 7); + MenuDrawText(149, y + 0x90, D_801D1F08[16], 7); // battle speed value rect.y = y + 72; rect.w = 8; rect.h = 11; rect.x = (Savemap.battle_speed >> 1) + 184; - func_80028030(&rect); + MenuDrawSlider(&rect); // battle message speed value rect.y = y + 0x5A; rect.w = 8; rect.h = 11; rect.x = (Savemap.battle_msg_speed >> 1) + 184; - func_80028030(&rect); + MenuDrawSlider(&rect); // field message speed value rect.y = y + 108; rect.w = 8; rect.h = 11; rect.x = (Savemap.field_msg_speed >> 1) + 184; - func_80028030(&rect); + MenuDrawSlider(&rect); // speed values for (i = 0; i < 3; i++) { - func_80026F44(157, y + 72 + i * 18 + 2, D_801D1F08[7], 7); - func_80026F44(324, y + 72 + i * 18 + 2, D_801D1F08[6], 7); + MenuDrawText(157, y + 72 + i * 18 + 2, D_801D1F08[7], 7); + MenuDrawText(324, y + 72 + i * 18 + 2, D_801D1F08[6], 7); } // speed bars @@ -234,27 +234,31 @@ static void func_801D01C8(void) { rect.y = y + 72 + i * 18; rect.w = 136; rect.h = 11; - func_80027B84(&rect); + MenuDrawSliderBg(&rect); } // magic order ID - func_80029114(173, y + 146, ((Savemap.config >> 0xA) & 7) + 1, 1, 7); + MenuDrawNumberPadded(173, y + 146, ((Savemap.config >> 0xA) & 7) + 1, 1, 7); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x1F, &rect); + MenuSetDrawMode(0, 1, 0x1F, &rect); } // exported, see 800493C8 void func_801D069C(void) { volatile s32 dummy; s32 i; - func_80026448(&D_801D24CC[0], 0, 0, 1, 10, 0, 0, 1, 10, 0, 0, 0, 1, 0); - func_80026448(&D_801D24CC[1], 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0); - func_80026448(&D_801D24CC[2], 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 0, 1, 0); - func_80026448(&D_801D24CC[3], 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0); + MenuSetCursorPickerObj( + &D_801D24CC[0], 0, 0, 1, 10, 0, 0, 1, 10, 0, 0, 0, 1, 0); + MenuSetCursorPickerObj( + &D_801D24CC[1], 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0); + MenuSetCursorPickerObj( + &D_801D24CC[2], 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 0, 1, 0); + MenuSetCursorPickerObj( + &D_801D24CC[3], 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0); D_801D1AA8 = 0; for (i = 0; i < LEN(D_80049208); i++) { D_801D252C[i] = D_80049208[i]; @@ -262,6 +266,6 @@ void func_801D069C(void) { } // exported, see 8004941C -INCLUDE_ASM("asm/us/menu/nonmatchings/cnfgmenu", func_801D080C); +INCLUDE_ASM("asm/us/menu/nonmatchings/cnfgmenu", MenuConfig); static void func_801D1AA0(void) {} diff --git a/src/menu/savemenu.c b/src/menu/savemenu.c index da01564..8910fdf 100644 --- a/src/menu/savemenu.c +++ b/src/menu/savemenu.c @@ -5,7 +5,7 @@ #include "savemenu.h" -static void func_801D0408(u16 arg0) { +static void PlaySound(u16 arg0) { D_8009A000 = 0x30; D_8009A004 = arg0; D_8009A008 = arg0; @@ -29,7 +29,7 @@ static s32 func_801D0448(s32 arg0) { rect.y = 0; rect.w = 255; rect.h = 255; - func_80026A34(0, 1, 0x5F, &rect); + MenuSetDrawMode(0, 1, 0x5F, &rect); D_801D4EC4 += arg0; if (D_801D4EC4 < 0) { D_801D4EC4 = 0; @@ -44,7 +44,8 @@ void func_801D05C0(u8 arg0) { D_801E3860 = 0xF0; D_801E36B8 = arg0; D_801E3850 = 0; - func_80026448(menus.D_801E379C, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 0); + MenuSetCursorPickerObj( + menus.D_801E379C, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 0); func_80025B8C(&D_801E8F44); func_80025C14(&D_801E4538); func_80025DF8(); @@ -71,7 +72,7 @@ int func_801D06B0(s32 arg0) { s8 temp_s0_2; if (D_801E36B8 == 0) { - func_800230C4(D_80062F58); + MenuDrawSubmenuTitle(D_80062F58); } else if (D_801E36B0 == 0) { if (func_801D0448(-15) == 0) { D_801E36B0 = 1; @@ -81,8 +82,8 @@ int func_801D06B0(s32 arg0) { D_801E36B0 = -1; } } - if (!func_80023050() || (D_801E36B8 && D_801E36B0 == 1)) { - if (!(u8)func_8001F6B4()) { + if (!MenuIsBusy() || (D_801E36B8 && D_801E36B0 == 1)) { + if (!(u8)MenuGetPopupState()) { if (D_801E3850 >= 0 && D_801E3850 < 2) { func_801D3668(arg0); } @@ -91,89 +92,89 @@ int func_801D06B0(s32 arg0) { } } } - func_80026B5C(0x80); + MenuSetBrightness(0x80); switch (D_801E3850) { case 0: - func_8001EB2C(D_801D4EC8.x - 18, - D_801D4EC8.y + 6 + (menus.D_801E379C[0].unkB * 12)); - func_80026F44(0xA, 0xB, D_801E2CFC[1], 7); - func_80026F44(D_801D4EC8.x + 12, D_801D4EC8.y + 5, D_801E2CFC[3], - -(D_801E8F38[0][0] != 0) & 7); - func_80026F44(D_801D4EC8.x + 12, D_801D4EC8.y + 17, D_801E2CFC[4], - -(D_801E8F3B != 0) & 7); + MenuDrawCursor(D_801D4EC8.x - 18, + D_801D4EC8.y + 6 + (menus.D_801E379C[0].unkB * 12)); + MenuDrawText(0xA, 0xB, D_801E2CFC[1], 7); + MenuDrawText(D_801D4EC8.x + 12, D_801D4EC8.y + 5, D_801E2CFC[3], + -(D_801E8F38[0][0] != 0) & 7); + MenuDrawText(D_801D4EC8.x + 12, D_801D4EC8.y + 17, D_801E2CFC[4], + -(D_801E8F3B != 0) & 7); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x7F, &rect); - func_8001E040(&D_801D4EC8); + MenuSetDrawMode(0, 1, 0x7F, &rect); + MenuDrawWindow(&D_801D4EC8); break; case 7: - func_8001EB2C(D_801D4ED0.x + 0x16, - 0x15 + D_801D4ED0.y + menus.D_801E3808[1].unkB * 0xC); + MenuDrawCursor(D_801D4ED0.x + 0x16, + 0x15 + D_801D4ED0.y + menus.D_801E3808[1].unkB * 0xC); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x7F, &rect); - func_80026F44(D_801D4ED0.x + 0xA, D_801D4ED0.y + 6, D_801E2CFC[33], 7); - func_80026F44(D_801D4ED0.x + 48, D_801D4ED0.y + 19, D_801E2CFC[34], 7); - func_80026F44(D_801D4ED0.x + 48, D_801D4ED0.y + 31, D_801E2CFC[35], 7); - func_8001E040(&D_801D4ED0); + MenuSetDrawMode(0, 1, 0x7F, &rect); + MenuDrawText(D_801D4ED0.x + 0xA, D_801D4ED0.y + 6, D_801E2CFC[33], 7); + MenuDrawText(D_801D4ED0.x + 48, D_801D4ED0.y + 19, D_801E2CFC[34], 7); + MenuDrawText(D_801D4ED0.x + 48, D_801D4ED0.y + 31, D_801E2CFC[35], 7); + MenuDrawWindow(&D_801D4ED0); /* fallthrough */ case 1: if (!D_801E8F38[menus.D_801E379C[0].unkB][0]) { D_801E3850 = 0; } else { - func_800269D0(); + MenuPushDrawState(); if (D_801E36B8 == 0) { - func_800269C0(D_80062F58 * 0x5000 + D_801D4EDC); + SetPolyBuffer(D_80062F58 * 0x5000 + D_801D4EDC); } else { - func_800269C0(D_801E36B4 * 0x5000 + D_801D4EDC); + SetPolyBuffer(D_801E36B4 * 0x5000 + D_801D4EDC); } if (D_801E3850 != 7 || (arg0 & 2)) { - func_8001EB2C(8, (menus.D_801E379C[1].unkB << 6) | 0x38); + MenuDrawCursor(8, (menus.D_801E379C[1].unkB << 6) | 0x38); } var_s3 = !menus.D_801E379C[1].unk8 ? 3 : 4; for (var_s0 = 0; var_s0 < var_s3; var_s0++) { if ((D_80062F3C >> (var_s0 + menus.D_801E379C[1].unk2)) & 1) { - func_8001DE70(); + MenuStoreWindowColors(); func_801D370C( 0, var_s0 * 64 + 29 + menus.D_801E379C[1].unkF * 8, var_s0 + menus.D_801E379C[1].unk2); - func_8001DEB0(); + MenuRestoreWindowColors(); } else { - func_80026F44( + MenuDrawText( 0x32, var_s0 * 64 + 55 + menus.D_801E379C[1].unkF * 8, D_801E2CFC[8], 6); - func_8001DE40(&sp38, &D_801DEEF4); - func_8001DE24( + MenuCopyWindow(&sp38, &D_801DEEF4); + MenuMoveWindow( &sp38, 0, var_s0 * 64 + 29 + menus.D_801E379C[1].unkF * 8); - func_8001E040(&sp38); + MenuDrawWindow(&sp38); } } - func_80026B5C(0x80); + MenuSetBrightness(0x80); rect.y = 29; rect.w = 364; rect.x = 0; rect.h = 195; if (D_801E36B8 == 0) { - func_80026A94(&D_800706A4[D_80062F58], &rect); + MenuSetClipRect(&D_800706A4[D_80062F58], &rect); } else { - func_80026A94(&D_801E36BC[D_801E36B4], &rect); + MenuSetClipRect(&D_801E36BC[D_801E36B4], &rect); } - func_80026F44(10, 11, D_801E2CFC[2], 7); - func_80026F44(206, 11, D_801E2CFC[9], 6); - func_80026F44( - func_80026B70(D_801E2CFC[9]) + 208, 11, + MenuDrawText(10, 11, D_801E2CFC[2], 7); + MenuDrawText(206, 11, D_801E2CFC[9], 6); + MenuDrawText( + MenuGetTextWidth(D_801E2CFC[9]) + 208, 11, ((13 + menus.D_801E379C[1].unkB + menus.D_801E379C[1].unk2) * 36) + D_801E2CFC[0], 7); - func_8001DE0C(&sp38, 200, 5, 78, 24); - func_8001E040(&sp38); - func_800269E8(); + MenuCreateWindow(&sp38, 200, 5, 78, 24); + MenuDrawWindow(&sp38); + MenuPopDrawState(); } break; case 2: @@ -187,75 +188,75 @@ int func_801D06B0(s32 arg0) { var_s1 = 128; var_s0 = 0; } - func_80026F44(10, 11, D_801E2CFC[12], 7); + MenuDrawText(10, 11, D_801E2CFC[12], 7); if (D_801E36A8 == 0) { - func_800285AC( + MenuDrawProgressBar( 122, 117, (D_801E36AC + 1) * 8, 8, var_s2, var_s1, var_s0); rect.x = 0; rect.y = 0; rect.w = 0xFF; rect.h = 0xFF; - func_80026A34(0, 1, 0x3F, &rect); + MenuSetDrawMode(0, 1, 0x3F, &rect); } - func_8001DE0C(&sp38, 0x70, 0x6D, 0x8C, 0x18); - func_8001E040(&sp38); + MenuCreateWindow(&sp38, 0x70, 0x6D, 0x8C, 0x18); + MenuDrawWindow(&sp38); break; case 4: - temp_s1 = func_80026B70(D_801E2CFC[7]) + 0x10; - func_80026F44(190 - temp_s1 / 2, 115, D_801E2CFC[7], 7); - func_8001DE0C(&sp38, 182 - temp_s1 / 2, 109, temp_s1, 24); - func_8001E040(&sp38); + temp_s1 = MenuGetTextWidth(D_801E2CFC[7]) + 0x10; + MenuDrawText(190 - temp_s1 / 2, 115, D_801E2CFC[7], 7); + MenuCreateWindow(&sp38, 182 - temp_s1 / 2, 109, temp_s1, 24); + MenuDrawWindow(&sp38); break; case 6: if (arg0 & 2) { - func_8001EB2C(D_801D4EC8.x - 18, - D_801D4EC8.y + 6 + menus.D_801E379C[0].unkB * 0xC); + MenuDrawCursor(D_801D4EC8.x - 18, + D_801D4EC8.y + 6 + menus.D_801E379C[0].unkB * 0xC); } - func_80026F44(D_801D4EC8.x + 12, D_801D4EC8.y + 5, D_801E2CFC[3], - -(D_801E8F38[0][0] != 0) & 7); - func_80026F44(D_801D4EC8.x + 12, D_801D4EC8.y + 0x11, D_801E2CFC[4], - -(D_801E8F38[1][0] != 0) & 7); + MenuDrawText(D_801D4EC8.x + 12, D_801D4EC8.y + 5, D_801E2CFC[3], + -(D_801E8F38[0][0] != 0) & 7); + MenuDrawText(D_801D4EC8.x + 12, D_801D4EC8.y + 0x11, D_801E2CFC[4], + -(D_801E8F38[1][0] != 0) & 7); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x7F, &rect); - func_8001E040(&D_801D4EC8); - func_80026F44(10, 11, D_801E3260[4], 7); - temp_s2 = func_80026B70(D_801E3260[5]) + 0x10; - func_80026F44(190 - temp_s2 / 2, D_801D4EC8.h + 99, D_801E3260[5], 7); - func_80026F44(228 - temp_s2 / 2, D_801D4EC8.h + 112, D_801E2CFC[34], 7); - func_80026F44(228 - temp_s2 / 2, D_801D4EC8.h + 124, D_801E2CFC[35], 7); - func_8001EB2C(200 - temp_s2 / 2, - 115 + (menus.D_801E3808[0].unkB * 12) + D_801D4EC8.h); - func_8001DE0C( + MenuSetDrawMode(0, 1, 0x7F, &rect); + MenuDrawWindow(&D_801D4EC8); + MenuDrawText(10, 11, D_801E3260[4], 7); + temp_s2 = MenuGetTextWidth(D_801E3260[5]) + 0x10; + MenuDrawText(190 - temp_s2 / 2, D_801D4EC8.h + 99, D_801E3260[5], 7); + MenuDrawText(228 - temp_s2 / 2, D_801D4EC8.h + 112, D_801E2CFC[34], 7); + MenuDrawText(228 - temp_s2 / 2, D_801D4EC8.h + 124, D_801E2CFC[35], 7); + MenuDrawCursor(200 - temp_s2 / 2, + 115 + (menus.D_801E3808[0].unkB * 12) + D_801D4EC8.h); + MenuCreateWindow( &sp38, 182 - temp_s2 / 2, D_801D4EC8.h + 93, temp_s2, 0x30); - func_8001E040(&sp38); + MenuDrawWindow(&sp38); break; } if (D_801E36B8 != 0) { - func_80026B5C(0x80); - func_80026F44(294, 11, &D_801DEEDC, 7); - func_8001E040(&D_801DEEFC); + MenuSetBrightness(0x80); + MenuDrawText(294, 11, &D_801DEEDC, 7); + MenuDrawWindow(&D_801DEEFC); } - func_8001DE0C(&sp38, 0, 5, 364, 24); - func_8001E040(&sp38); - if (!(D_801E36B8 == 0 && !func_80023050()) && + MenuCreateWindow(&sp38, 0, 5, 364, 24); + MenuDrawWindow(&sp38); + if (!(D_801E36B8 == 0 && !MenuIsBusy()) && (D_801E36B8 == 0 || D_801E36B0 != 1)) { return; } - if (func_8001F6B4() & 0xFF) { + if (MenuGetPopupState() & 0xFF) { return; } switch (D_801E3850) { case 0: - if (D_80062D7C & 0x20) { + if (ButtonsTapped & 0x20) { if (D_801E8F38[menus.D_801E379C[0].unkB][0]) { - func_801D0408(1); + PlaySound(1); if (D_801E8F38[menus.D_801E379C[0].unkB][2]) { D_801E3850 = 6; - func_80026448(&menus.D_801E3808[0], 0, 1, 1, 2, 0, 0, 1, 2, - 0, 0, 0, 1, 0); + MenuSetCursorPickerObj(&menus.D_801E3808[0], 0, 1, 1, 2, 0, + 0, 1, 2, 0, 0, 0, 1, 0); } else { D_801E3850 = 2; D_801E36AC = 0; @@ -263,25 +264,26 @@ int func_801D06B0(s32 arg0) { D_80062F3C = 0; D_801E36A8 = 1; D_801E36A4 = 0x3C; - func_80026448(&menus.D_801E379C[1], 0, 0, 1, 3, 0, 0, 1, 15, - 0, 0, 0, 0, 0); + MenuSetCursorPickerObj(&menus.D_801E379C[1], 0, 0, 1, 3, 0, + 0, 1, 15, 0, 0, 0, 0, 0); } } else { - func_801D0408(3); - func_8001F6C0(!D_801E3860 ? D_801E33B0[0] : D_801E3260[6], 7); + PlaySound(3); + MenuShowPopupText( + !D_801E3860 ? D_801E33B0[0] : D_801E3260[6], 7); } } else { - func_800264A8(&menus.D_801E379C[0]); + MenuCursorPickerHandler(&menus.D_801E379C[0]); if (D_801E36B8 != 0) { - if (D_80062D7C & 0x40) { - func_801D0408(4); + if (ButtonsTapped & 0x40) { + PlaySound(4); D_801E36B0 = 2; } - } else if (D_80062D7C & 0x40) { - func_801D0408(4); + } else if (ButtonsTapped & 0x40) { + PlaySound(4); func_801D0670(); - func_8002305C(5, 0); - func_8002120C(0); + MenuExitSubmenu(5, 0); + MenuSetTransition(0); } } break; @@ -289,13 +291,13 @@ int func_801D06B0(s32 arg0) { var_s0 = menus.D_801E379C[1].unkF; func_801D2DA8(&menus.D_801E379C[1]); if ((menus.D_801E379C[1].unkF == 0) && (var_s0 == 0)) { - if (D_80062D7C & 0x20) { + if (ButtonsTapped & 0x20) { D_801E3850 = 7; - func_80026448(&menus.D_801E3808[1], 0, 0, 1, 2, 0, 0, 1, 2, 0, - 0, 0, 1, 0); - func_801D0408(1); - } else if (D_80062D7C & 0x40) { - func_801D0408(4); + MenuSetCursorPickerObj(&menus.D_801E3808[1], 0, 0, 1, 2, 0, 0, + 1, 2, 0, 0, 0, 1, 0); + PlaySound(1); + } else if (ButtonsTapped & 0x40) { + PlaySound(4); D_801E3850 = 0; } } @@ -315,13 +317,13 @@ int func_801D06B0(s32 arg0) { D_801E36AC++; if (var_s0) { D_801E3850 = 0; - func_8001F6C0(D_801E33B0[8], 2); + MenuShowPopupText(D_801E33B0[8], 2); } if (D_801E36AC == 0xF) { D_801E36AC = 0xE; D_801E3850 = 3; D_801E36A4 = 0xA; - func_801D0408(2); + PlaySound(2); } } } else { @@ -345,21 +347,21 @@ int func_801D06B0(s32 arg0) { var_v0_6 |= 0x10; } if (!func_801D2A34(var_v0_6)) { - func_801D0408(0xD0); - func_8001F6C0(D_801E2CFC[28], 7); + PlaySound(0xD0); + MenuShowPopupText(D_801E2CFC[28], 7); D_80062F3C |= 1 << (menus.D_801E379C[1].unkB + menus.D_801E379C[1].unk2); } else { - func_801D0408(3); - func_8001F6C0(D_801E33B0[3], 7); + PlaySound(3); + MenuShowPopupText(D_801E33B0[3], 7); } break; case 6: - func_800264A8(&menus.D_801E3808[0]); - if (D_80062D7C & 0x20) { + MenuCursorPickerHandler(&menus.D_801E3808[0]); + if (ButtonsTapped & 0x20) { if (menus.D_801E3808[0].unkB) { D_801E3850 = 0; - func_801D0408(4); + PlaySound(4); } else { if (menus.D_801E379C[0].unkB) { temp_v1 = format("bu10:"); @@ -369,37 +371,37 @@ int func_801D06B0(s32 arg0) { D_801E3850 = 0; if (temp_v1 == 1) { D_801E8F38[menus.D_801E379C[0].unkB][2] = 0; - func_8001F6C0(D_801E2CFC[41], 7); - func_801D0408(0xD0); + MenuShowPopupText(D_801E2CFC[41], 7); + PlaySound(0xD0); } else { - func_8001F6C0(D_801E3260[3], 7); - func_801D0408(3); + MenuShowPopupText(D_801E3260[3], 7); + PlaySound(3); } } - } else if (D_80062D7C & 0x40) { + } else if (ButtonsTapped & 0x40) { D_801E3850 = 0; - func_801D0408(4); + PlaySound(4); } break; case 7: - if (D_80062D7C & 0x20) { + if (ButtonsTapped & 0x20) { temp_s0_2 = menus.D_801E3808[1].unkB; switch (menus.D_801E3808[1].unkB) { case 0: - func_801D0408(1); + PlaySound(1); D_801E3850 = 4; D_801E36A4 = 0xA; break; case 1: - func_801D0408(4); + PlaySound(4); D_801E3850 = temp_s0_2; break; } - } else if (D_80062D7C & 0x40) { + } else if (ButtonsTapped & 0x40) { D_801E3850 = 1; - func_801D0408(4); + PlaySound(4); } else { - func_800264A8(&menus.D_801E3808[1]); + MenuCursorPickerHandler(&menus.D_801E3808[1]); } break; } @@ -418,18 +420,18 @@ s32 func_801D1774(void) { s32 ret; s32 i; - func_80021044(D_801E36BC, D_801E3774); + MenuInitDisplayEnv(D_801E36BC, D_801E3774); i = 0; D_801E36B0 = 0; func_801D05C0(1); D_801E36B4 = 0; while (1) { - func_8001CB48(); - func_800269C0(D_80077F64[D_801E36B4]); + MenuStoreKeypressBitmask(); + SetPolyBuffer(D_80077F64[D_801E36B4]); D_801E3854 = (u_long*)D_801E3858[D_801E36B4]; ClearOTag(D_801E3854, 1); - func_80026A00(D_801E3854); - func_8001F710(); + MenuSetOTag(D_801E3854); + MenuUpdatePopup(); ret = func_801D06B0(i); if (D_801E36B0 == -1) { break; diff --git a/src/menu/savemenu.h b/src/menu/savemenu.h index 1de647b..c507809 100644 --- a/src/menu/savemenu.h +++ b/src/menu/savemenu.h @@ -12,11 +12,11 @@ typedef enum { typedef struct { // this whole thing might be a D_801E379C[6] - /* 0x00 */ Unk80026448 D_801E379C[2]; + /* 0x00 */ CursorPicker D_801E379C[2]; /* 0x24 */ u8 unk24[0x40]; /* 0x64 */ s32 D_801E3800; /* 0x68 */ s32 D_801E3804; - /* 0x6C */ Unk80026448 D_801E3808[2]; + /* 0x6C */ CursorPicker D_801E3808[2]; } Menus; // size: 0x90 extern const char D_801D018C[]; @@ -57,7 +57,7 @@ extern s32 D_801E3D54; extern s32 D_801E3D58; // backbuffer id? extern u_long* D_801E3D5C; // otag pointer extern u_long* D_801E3D60[2][4]; -extern Unk80026448 D_801E3DFE[2]; +extern CursorPicker D_801E3DFE[2]; extern DRAWENV D_801E3E34[2]; extern DISPENV D_801E3EEC[2]; extern s32 D_801E3F2C[]; @@ -72,7 +72,7 @@ extern u8 D_801E3158; extern RECT D_801E3668; extern s16 D_801E366A; extern s16 D_801E366E; -extern Unk80026448 D_801E3D80[2]; +extern CursorPicker D_801E3D80[2]; extern s32 D_801E3F14; extern s32 D_801E3F18; extern s32 D_801E3F1C; diff --git a/src/menu/title.c b/src/menu/title.c index 4d29d57..7a4f930 100644 --- a/src/menu/title.c +++ b/src/menu/title.c @@ -3,9 +3,9 @@ #include "savemenu.h" extern s32 D_801E2CF4; -extern Unk80026448 D_801E3DEC[2]; +extern CursorPicker D_801E3DEC[2]; -static void func_801D2B58(u16 arg0) { +static void PlaySound(u16 arg0) { D_8009A000 = 0x30; D_8009A004 = arg0; D_8009A008 = arg0; @@ -29,7 +29,7 @@ static s32 func_801D2B98(s32 arg0) { rect.y = 0; rect.w = 255; rect.h = 255; - func_80026A34(0, 1, 0x5F, &rect); + MenuSetDrawMode(0, 1, 0x5F, &rect); D_801E2CF4 += arg0; if (D_801E2CF4 < 0) { D_801E2CF4 = 0; @@ -149,10 +149,10 @@ void func_801D370C(s32 x, s32 y, s32 slot_no) { save = func_801D1D1C(slot_no); data = (u8*)save; - func_80026F44(192, y + 46, save->place_name, 7); + MenuDrawText(192, y + 46, save->place_name, 7); for (i = 0; i < 3; i++) { if (data[i + 5] != 0xFF) { - func_8001D180( + MenuDrawPartyPortrait( 22 + i * 52, y + 6, 48, 48, (data[i + 5] >= 5) ? 48 : 0, (data[i + 5] % 5) * 48, 48, 48, data[i + 5], 0); } @@ -162,39 +162,39 @@ void func_801D370C(s32 x, s32 y, s32 slot_no) { rect.y = 0; rect.w = 0xFF; rect.h = 0xFF; - func_80026A34(0, 1, 127, &rect); - func_80028E00( - func_80026B70(D_801E3684) + 194, y + 28, save->leader_level, 2, 7); - func_8002708C(338, y + 12, 213, 7); // prints the ':' symbol maybe? - func_80029114(324, y + 11, func_80023788(save->time), 2, 7); - func_80029114(345, y + 11, func_8002382C(save->time), 2, 7); - func_80028E00(309, y + 25, save->gil, 7, 7); + MenuSetDrawMode(0, 1, 127, &rect); + MenuDrawNumber( + MenuGetTextWidth(D_801E3684) + 194, y + 28, save->leader_level, 2, 7); + MenuDrawLetter(338, y + 12, 213, 7); // prints the ':' symbol maybe? + MenuDrawNumberPadded(324, y + 11, MenuGetPlaytimeHours(save->time), 2, 7); + MenuDrawNumberPadded(345, y + 11, MenuGetPlaytimeMinutes(save->time), 2, 7); + MenuDrawNumber(309, y + 25, save->gil, 7, 7); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 127, &rect); - func_80026F44(189, y + 26, D_801E3684, 5); - func_80026F44(184, y + 8, save->leader_name, 7); - func_80026F44(284, y + 9, D_800492F0[LABEL_TIME], 7); - func_80026F44(284, y + 23, D_800492F0[LABEL_GIL], 7); - func_8001DEF0(save->menu_color); + MenuSetDrawMode(0, 1, 127, &rect); + MenuDrawText(189, y + 26, D_801E3684, 5); + MenuDrawText(184, y + 8, save->leader_name, 7); + MenuDrawText(284, y + 9, D_800492F0[LABEL_TIME], 7); + MenuDrawText(284, y + 23, D_800492F0[LABEL_GIL], 7); + MenuSetWindowColors(save->menu_color); for (j = 0; j < 3; j++) { - func_8001DE40(&sp28, &D_801E3650[j]); - func_8001DE24(&sp28, 0, y); - func_8001E040(&sp28); + MenuCopyWindow(&sp28, &D_801E3650[j]); + MenuMoveWindow(&sp28, 0, y); + MenuDrawWindow(&sp28); } } static void func_801D39C4(void) { D_801E3698 = 0; g_MenuStartMode = START_MENU_MODE_TITLE; - func_8001DEF0(D_801E368C); - func_80025D14(D_801D4EDC, 0x380, 0, 0, 0x1E0); + MenuSetWindowColors(D_801E368C); + MenuLoadTexture(D_801D4EDC, 0x380, 0, 0, 0x1E0); DrawSync(0); - func_80026448(D_801E3DFE, 0, 1, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 0); + MenuSetCursorPickerObj(D_801E3DFE, 0, 1, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 0); func_80025CD4(D_801E3F2C); func_80025B8C(D_801E8F44); func_80025C14(D_801E4538); @@ -221,7 +221,7 @@ static s32 func_801D3AB0(s32 arg0) { D_801E3D54 != 2 && D_801E3D54 != 0) { func_801D3668(arg0); } - func_80026B5C(0x80); + MenuSetBrightness(0x80); if (D_801E3D54 == 0) { if (func_801D2B98(-15) == 0) { D_801E3D54 = 1; @@ -231,64 +231,63 @@ static s32 func_801D3AB0(s32 arg0) { D_801E3D54 = -1; } } - func_8001F6B4(); + MenuGetPopupState(); switch (g_MenuStartMode) { case START_MENU_MODE_SELECT_SLOT: - func_8001EB2C( + MenuDrawCursor( D_801E3668.x - 18, D_801E3668.y + 6 + D_801E3D80[0].unkB * 12); - func_80026F44(10, 11, D_801E2CFC[1], 7); - func_80026F44(D_801E3668.x + 12, D_801E3668.y + 5, D_801E2CFC[3], - -(D_801E8F38[0][0] != 0) & 7); - func_80026F44(D_801E3668.x + 12, D_801E3668.y + 0x11, D_801E2CFC[4], - -(D_801E8F3B != 0) & 7); + MenuDrawText(10, 11, D_801E2CFC[1], 7); + MenuDrawText(D_801E3668.x + 12, D_801E3668.y + 5, D_801E2CFC[3], + -(D_801E8F38[0][0] != 0) & 7); + MenuDrawText(D_801E3668.x + 12, D_801E3668.y + 0x11, D_801E2CFC[4], + -(D_801E8F3B != 0) & 7); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x7F, &rect); - func_8001E040(&D_801E3668); + MenuSetDrawMode(0, 1, 0x7F, &rect); + MenuDrawWindow(&D_801E3668); break; case START_MENU_MODE_SELECT_FILE: if (!D_801E8F38[D_801E3D80[0].unkB][0]) { g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; } else { - func_800269D0(); - func_800269C0(D_801E3D58 * 0x5000 + D_801D4EDC); - func_8001EB2C(8, (D_801E3D80[1].unkB * 64) | 0x38); + MenuPushDrawState(); + SetPolyBuffer(D_801E3D58 * 0x5000 + D_801D4EDC); + MenuDrawCursor(8, (D_801E3D80[1].unkB * 64) | 0x38); var_s3 = !D_801E3D80[1].unk8 ? 3 : 4; for (var_s0 = 0; var_s0 < var_s3; var_s0++) { if ((D_80062F3C >> (var_s0 + D_801E3D80[1].unk2)) & 1) { - func_8001DE70(); + MenuStoreWindowColors(); func_801D370C( 0, var_s0 * 64 + 0x1D + D_801E3D80[1].unkF * 8, var_s0 + D_801E3D80[1].unk2); - func_8001DEB0(); + MenuRestoreWindowColors(); } else { - func_80026F44( + MenuDrawText( 0x32, var_s0 * 64 + 55 + D_801E3D80[1].unkF * 8, D_801E2CFC[8], 6); - func_8001DE40(&sp38, &D_801E3660); - func_8001DE24( + MenuCopyWindow(&sp38, &D_801E3660); + MenuMoveWindow( &sp38, 0, var_s0 * 64 + 0x1D + D_801E3D80[1].unkF * 8); - func_8001E040(&sp38); + MenuDrawWindow(&sp38); } } - func_80026B5C(0x80); + MenuSetBrightness(0x80); rect.y = 0x1D; rect.w = 0x16C; rect.h = 0xC3; rect.x = 0; - func_80026A94(&D_801E3E34[D_801E3D58], &rect); - func_80026F44(10, 11, D_801E2CFC[2], 7); - func_80026F44(0xCE, 11, D_801E2CFC[9], 6); - func_80026F44( - func_80026B70(D_801E2CFC[9]) + 0xD0, 11, - ((13 + D_801E3D80[1].unkB + D_801E3D80[1].unk2) * 36) + - (D_801E2CFC[0]), - 7); - func_8001DE0C(&sp38, 200, 5, 0x4E, 0x18); - func_8001E040(&sp38); - func_800269E8(); + MenuSetClipRect(&D_801E3E34[D_801E3D58], &rect); + MenuDrawText(10, 11, D_801E2CFC[2], 7); + MenuDrawText(0xCE, 11, D_801E2CFC[9], 6); + MenuDrawText(MenuGetTextWidth(D_801E2CFC[9]) + 0xD0, 11, + ((13 + D_801E3D80[1].unkB + D_801E3D80[1].unk2) * 36) + + (D_801E2CFC[0]), + 7); + MenuCreateWindow(&sp38, 200, 5, 0x4E, 0x18); + MenuDrawWindow(&sp38); + MenuPopDrawState(); } break; case START_MENU_MODE_CHECKING_FILES: @@ -302,66 +301,65 @@ static s32 func_801D3AB0(s32 arg0) { var_s1 = 0x80; var_s0_2 = 0; } - func_80026F44(10, 11, D_801E2CFC[12], 7); + MenuDrawText(10, 11, D_801E2CFC[12], 7); if (D_801E3F1C == 0) { - func_800285AC( + MenuDrawProgressBar( 122, 117, (D_801E3F20 + 1) * 8, 8, var_s2, var_s1, var_s0_2); rect.x = 0; rect.y = 0; rect.w = 0xFF; rect.h = 0xFF; - func_80026A34(0, 1, 0x3F, &rect); + MenuSetDrawMode(0, 1, 0x3F, &rect); } - func_8001DE0C(&sp38, 112, 0x6D, 0x8C, 0x18); - func_8001E040(&sp38); + MenuCreateWindow(&sp38, 112, 0x6D, 0x8C, 0x18); + MenuDrawWindow(&sp38); break; case START_MENU_MODE_LOADING: if (D_801E3D54 != 2) { - temp_s1 = func_80026B70(D_801E2CFC[6]) + 0x10; - func_80026F44(190 - temp_s1 / 2, 0x73, D_801E2CFC[6], 7); - func_8001DE0C(&sp38, 0xB6 - temp_s1 / 2, 0x6D, temp_s1, 24); - func_8001E040(&sp38); + temp_s1 = MenuGetTextWidth(D_801E2CFC[6]) + 0x10; + MenuDrawText(190 - temp_s1 / 2, 0x73, D_801E2CFC[6], 7); + MenuCreateWindow(&sp38, 0xB6 - temp_s1 / 2, 0x6D, temp_s1, 24); + MenuDrawWindow(&sp38); } break; case START_MENU_MODE_FORMAT_PROMPT: if (arg0 & 2) { - func_8001EB2C(D_801E3668.x - 0x12, - D_801E3668.y + 6 + D_801E3D80[0].unkB * 12); + MenuDrawCursor(D_801E3668.x - 0x12, + D_801E3668.y + 6 + D_801E3D80[0].unkB * 12); } - func_80026F44(D_801E3668.x + 12, D_801E3668.y + 5, D_801E2CFC[3], - -(D_801E8F38[0][0] != 0) & 7); - func_80026F44(D_801E3668.x + 12, D_801E3668.y + 0x11, D_801E2CFC[4], - -(D_801E8F3B != 0) & 7); + MenuDrawText(D_801E3668.x + 12, D_801E3668.y + 5, D_801E2CFC[3], + -(D_801E8F38[0][0] != 0) & 7); + MenuDrawText(D_801E3668.x + 12, D_801E3668.y + 0x11, D_801E2CFC[4], + -(D_801E8F3B != 0) & 7); rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x7F, &rect); - func_8001E040(&D_801E3668.x); - func_80026F44(10, 11, D_801E3260[4], 7); - temp_s2 = func_80026B70(D_801E3260[5]) + 0x10; - func_80026F44(190 - temp_s2 / 2, D_801E3668.h + 99, D_801E3260[5], 7); - func_80026F44(228 - temp_s2 / 2, D_801E3668.h + 112, D_801E2CFC[34], 7); - func_80026F44(228 - temp_s2 / 2, D_801E3668.h + 124, D_801E2CFC[35], 7); - func_8001EB2C( + MenuSetDrawMode(0, 1, 0x7F, &rect); + MenuDrawWindow(&D_801E3668.x); + MenuDrawText(10, 11, D_801E3260[4], 7); + temp_s2 = MenuGetTextWidth(D_801E3260[5]) + 0x10; + MenuDrawText(190 - temp_s2 / 2, D_801E3668.h + 99, D_801E3260[5], 7); + MenuDrawText(228 - temp_s2 / 2, D_801E3668.h + 112, D_801E2CFC[34], 7); + MenuDrawText(228 - temp_s2 / 2, D_801E3668.h + 124, D_801E2CFC[35], 7); + MenuDrawCursor( 200 - temp_s2 / 2, 0x73 + D_801E3DEC[0].unkB * 12 + D_801E3668.h); - func_8001DE0C( + MenuCreateWindow( &sp38, 0xB6 - temp_s2 / 2, D_801E3668.h + 0x5D, temp_s2, 0x30); - func_8001E040(&sp38); + MenuDrawWindow(&sp38); break; case START_MENU_MODE_TITLE: - func_8001EB2C( + MenuDrawCursor( D_801E3668.x - 0x12, D_801E3668.y + 6 + D_801E3DEC[1].unkB * 12); - func_80026F44( + MenuDrawText( D_801E3668.x + 8, D_801E3668.y + 6, D_801E2CFC[32], 7); // new game - func_80026F44( - D_801E3668.x + 8, D_801E3668.y + 18, D_801E2CFC[10], - D_801E8F38[0][0] || D_801E8F38[1][0] ? 7 : 0); // continue? + MenuDrawText(D_801E3668.x + 8, D_801E3668.y + 18, D_801E2CFC[10], + D_801E8F38[0][0] || D_801E8F38[1][0] ? 7 : 0); // continue? rect.x = 0; rect.y = 0; rect.w = 0x100; rect.h = 0x100; - func_80026A34(0, 1, 0x7F, &rect); + MenuSetDrawMode(0, 1, 0x7F, &rect); SetPolyFT4(D_80062F24.ft4); D_80062F24.ft4->r0 = 0x60; D_80062F24.ft4->g0 = 0x60; @@ -389,16 +387,16 @@ static s32 func_801D3AB0(s32 arg0) { break; } if (g_MenuStartMode != START_MENU_MODE_TITLE) { - func_80026F44(0x126, 11, D_801E2CFC[0], 7); - func_8001DE0C(&sp38, 0x116, 5, 0x56, 0x18); - func_8001E040(&sp38); - func_8001DE0C(&sp38, 0, 5, 0x16C, 0x18); - func_8001E040(&sp38); + MenuDrawText(0x126, 11, D_801E2CFC[0], 7); + MenuCreateWindow(&sp38, 0x116, 5, 0x56, 0x18); + MenuDrawWindow(&sp38); + MenuCreateWindow(&sp38, 0, 5, 0x16C, 0x18); + MenuDrawWindow(&sp38); } - if (!(func_8001F6B4() & 0xFF) && D_801E3D54 == 1) { + if (!(MenuGetPopupState() & 0xFF) && D_801E3D54 == 1) { switch (g_MenuStartMode) { case START_MENU_MODE_SELECT_SLOT: - if (D_80062D7C & 0x20) { + if (ButtonsTapped & 0x20) { temp_v1_2 = D_801E3D80[0].unkB; if (temp_v1_2 >= 2) { break; @@ -407,11 +405,11 @@ static s32 func_801D3AB0(s32 arg0) { break; } if (D_801E8F38[temp_v1_2][0]) { - func_801D2B58(1); + PlaySound(1); if (D_801E8F38[D_801E3D80[0].unkB][2]) { g_MenuStartMode = START_MENU_MODE_FORMAT_PROMPT; - func_80026448(&D_801E3D80[6], 0, 1, 1, 2, 0, 0, 1, 2, 0, - 0, 0, 1, 0); + MenuSetCursorPickerObj(&D_801E3D80[6], 0, 1, 1, 2, 0, 0, + 1, 2, 0, 0, 0, 1, 0); } else { D_801E3F18 = 10; g_MenuStartMode = START_MENU_MODE_CHECKING_FILES; @@ -419,36 +417,36 @@ static s32 func_801D3AB0(s32 arg0) { D_801E3F14 = 0; D_80062F3C = 0; D_801E3F1C = 1; - func_80026448(&D_801E3D80[1], 0, 0, 1, 3, 0, 0, 1, 15, - 0, 0, 0, 0, 0); + MenuSetCursorPickerObj(&D_801E3D80[1], 0, 0, 1, 3, 0, 0, + 1, 15, 0, 0, 0, 0, 0); } } else { - func_801D2B58(3); - func_8001F6C0(D_801E33B0, 7); + PlaySound(3); + MenuShowPopupText(D_801E33B0, 7); } - } else if (D_80062D7C & 0x40) { - func_801D2B58(4); + } else if (ButtonsTapped & 0x40) { + PlaySound(4); g_MenuStartMode = START_MENU_MODE_TITLE; } else { - func_800264A8(&D_801E3D80[0]); + MenuCursorPickerHandler(&D_801E3D80[0]); } break; case START_MENU_MODE_SELECT_FILE: var_s1 = D_801E3D80[1].unkF; func_801D2DA8(&D_801E3D80[1]); if (!D_801E3D80[1].unkF && !var_s1) { - if ((u16)D_80062D7C & 0x20) { + if ((u16)ButtonsTapped & 0x20) { if (((s32)D_80062F3C >> (D_801E3D80[1].unkB + D_801E3D80[1].unk2)) & 1) { - func_801D2B58(1); + PlaySound(1); g_MenuStartMode = START_MENU_MODE_LOADING; D_801E3F18 = 10; } else { - func_801D2B58(3); + PlaySound(3); } - } else if ((u16)D_80062D7C & 0x40) { - func_801D2B58(4); + } else if ((u16)ButtonsTapped & 0x40) { + PlaySound(4); g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; } } @@ -467,14 +465,14 @@ static s32 func_801D3AB0(s32 arg0) { D_801E3F20++; if (var_s1) { g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; - func_8001F6C0(D_801E33B0[8], 2); - func_801D2B58(3); + MenuShowPopupText(D_801E33B0[8], 2); + PlaySound(3); } if (D_801E3F20 == 0xF) { D_801E3F20 = 0xE; g_MenuStartMode = START_MENU_MODE_CHECKING_WAIT; D_801E3F18 = 10; - func_801D2B58(2); + PlaySound(2); } } } else { @@ -503,23 +501,23 @@ static s32 func_801D3AB0(s32 arg0) { (u16)func_801D1950( sizeof(SaveWork) - 4, &Savemap.header.leader_level)) { g_MenuStartMode = START_MENU_MODE_SELECT_FILE; - func_801D2B58(3); - func_8001F6C0(D_801E2CFC[31], 0); + PlaySound(3); + MenuShowPopupText(D_801E2CFC[31], 0); } else { - func_801D2B58(0xD0); + PlaySound(0xD0); D_801E3D54 = 2; func_801D2D10(Savemap.config & 3); } } else { g_MenuStartMode = START_MENU_MODE_SELECT_FILE; - func_801D2B58(3); - func_8001F6C0(D_801E2CFC[11], var_s1); + PlaySound(3); + MenuShowPopupText(D_801E2CFC[11], var_s1); } D_80062D99 = 0; break; case START_MENU_MODE_FORMAT_PROMPT: - func_800264A8(&D_801E3DEC[0]); - if (D_80062D7C & 0x20) { + MenuCursorPickerHandler(&D_801E3DEC[0]); + if (ButtonsTapped & 0x20) { if (D_801E3DEC[0].unkB == 0) { if (D_801E3D80[0].unkB) { temp_v1_2 = format("bu10:"); @@ -529,42 +527,42 @@ static s32 func_801D3AB0(s32 arg0) { g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; if (temp_v1_2 == 1) { D_801E8F38[D_801E3D80[0].unkB][2] = 0; - func_8001F6C0(D_801E2CFC[41], 7); - func_801D2B58(0xD0); + MenuShowPopupText(D_801E2CFC[41], 7); + PlaySound(0xD0); } else { - func_8001F6C0(D_801E3260[3], 7); - func_801D2B58(3); + MenuShowPopupText(D_801E3260[3], 7); + PlaySound(3); } } else { g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; - func_801D2B58(4); + PlaySound(4); } - } else if (D_80062D7C & 0x40) { + } else if (ButtonsTapped & 0x40) { g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; - func_801D2B58(4); + PlaySound(4); } break; case START_MENU_MODE_TITLE: - if (D_80062D7C & 0x20) { + if (ButtonsTapped & 0x20) { switch (D_801E3D80[7].unkB) { case 0: - func_801D2B58(0xD0); + PlaySound(0xD0); D_801E3698 = 1; D_801E3D54 = 2; break; case 1: if (D_801E8F38[0][0] || D_801E8F3B) { - func_801D2B58(1); - func_80026448(&D_801E3D80[0], 0, 0, 1, 2, 0, 0, 1, 2, 0, - 0, 0, 1, 0); + PlaySound(1); + MenuSetCursorPickerObj(&D_801E3D80[0], 0, 0, 1, 2, 0, 0, + 1, 2, 0, 0, 0, 1, 0); g_MenuStartMode = START_MENU_MODE_SELECT_SLOT; } else { - func_801D2B58(3); + PlaySound(3); } break; } } else { - func_800264A8(D_801E3DFE); + MenuCursorPickerHandler(D_801E3DFE); } break; } @@ -588,17 +586,17 @@ s32 func_801D4CC0(void) { s32 i; s32 ret; - func_80021044(D_801E3E34, D_801E3EEC); + MenuInitDisplayEnv(D_801E3E34, D_801E3EEC); D_801E3D54 = 0; func_801D39C4(); D_801E3D58 = 0; for (i = 0;; i++) { - func_8001CB48(); - func_800269C0(D_80077F64[D_801E3D58]); + MenuStoreKeypressBitmask(); + SetPolyBuffer(D_80077F64[D_801E3D58]); D_801E3D5C = (u_long*)D_801E3D60[D_801E3D58]; ClearOTag(D_801E3D5C, 1); - func_80026A00(D_801E3D5C); - func_8001F710(); + MenuSetOTag(D_801E3D5C); + MenuUpdatePopup(); ret = func_801D3AB0(i); if (D_801E3D54 == -1) { break; @@ -616,10 +614,10 @@ s32 func_801D4CC0(void) { PutDrawEnv(&D_801E3E34[1]); for (i = 0; i < 3; i++) { if (Savemap.partyID[i] != 0xFF) { - func_80020058(i); - func_8001786C((u8)i); + MenuLoadPartyData(i); + MenuLoadPartyPortrait((u8)i); } } - func_80017678(); + MenuUnloadPortraits(); return ret; } From b432b6f3ef0ac41d76594a172a6a719ec1ecd8f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Tr=C4=99bacz?= Date: Mon, 29 Dec 2025 21:22:55 +0100 Subject: [PATCH 3/3] Remove CLAUDE.md --- CLAUDE.md | 392 ------------------------------------------------------ 1 file changed, 392 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 6f116ce..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,392 +0,0 @@ -## FF7 Decomp: Working Notes for Agents - -Final Fantasy VII (PS1 USA) decompilation project. Goal: byte-accurate recompilation of game executables. - -## Quick Reference - -### Docker Build Commands (Optimized) -```shell -# Build Docker image (only needed once) -docker build --platform=linux/amd64 --tag ff7-build:latest . - -# Run a build (FAST - uses Go caching, ~12s clean, ~2s incremental) -./tools/docker-build.sh "make build" - -# Format code after changes -./tools/docker-build.sh "make format" - -# Enter container interactively -./tools/docker-build.sh bash -``` - -The `docker-build.sh` wrapper adds Go module and build caching which provides a significant speedup. - -**Legacy commands** - only use if you have issues with the optimized script: -```shell -docker run --rm --platform=linux/amd64 -v "$(pwd)":/ff7 -v ff7_venv:/ff7/.venv -v "$(pwd)/build":/ff7/build ff7-build:latest -lc 'cd /ff7 && make build' -``` - -### Key Make Targets -- `make build` - Build all overlays, verify SHA1 checksums -- `make format` - Run clang-format on code -- `make clean` - Remove build artifacts -- `make submit` - Clean + build + format + stage files for commit - -### Mako Commands (via `./mako.sh`) -- `./mako.sh build` - Build project -- `./mako.sh dec ` - Decompile function, replace INCLUDE_ASM -- `./mako.sh dec --fix-structs` - Also replace D_8009XXXX with Savemap fields -- `./mako.sh rank ` - Rank functions by difficulty (easiest first) -- `./mako.sh symbols add [size]` - Add new symbol -- `./mako.sh format` - Format code - -## Project Structure - -``` -src/ # Decompiled C source (organized by overlay) -asm/us/ # MIPS assembly (original/undecompiled) - └── / - ├── nonmatchings/ # Undecompiled function .s files - └── data/ # Data segment .s files -include/ # Headers (common.h, game.h, psxsdk/) -config/ # Build config and symbol files - ├── us.yaml # Main overlay definitions - ├── symbols.*.txt # Symbol address files - └── sym_*.txt # Import/export symbol files -build/us/ # Build output (.o, .exe, .map files) -tools/ # Build tools (Go builder, Python scripts) -disks/us/ # Extracted game files (from disc image) -``` - -## Overlays - -| Overlay | VRAM Start | Source | Description | -|---------|------------|--------|-------------| -| main | 0x80010000 | `src/main/` | Core engine, initialization | -| battle | 0x800A0000 | `src/battle/` | Battle system | -| batini | 0x801B0000 | `src/battle/batini.c` | Battle initialization | -| field | 0x800A0000 | `src/field/` | Field exploration | -| world | 0x800A0000 | `src/world/` | World map | -| menu | varies | `src/menu/` | Menu systems (savemenu, title, etc.) | - -## Decompilation Workflow - -### 1. Find a function to decompile -```shell -# List undecompiled functions, ranked by difficulty (easiest first) -./mako.sh rank src/battle/nonmatchings/battle - -# Or browse asm files directly -ls asm/us/battle/nonmatchings/battle/ -``` - -### 2. Decompile with m2c -```shell -# This replaces INCLUDE_ASM in the .c file with decompiled code and performs struct field replacement -./mako.sh dec func_800A1158 --fix-structs -``` - -### 3. Refine the code -- Fix unknown types (marked with `/*?*/`) -- Match register allocation and instruction order -- Add/reference symbols in `config/symbols.*.txt` -- The goal is to produce a decompiled code that is 1:1 matching the original PSX binaries - -### 4. Build and verify -```shell -make build # Rebuilds and verifies SHA1 match -``` - -### 5. Format and submit -```shell -make format -git add config/ include/ src/ -git commit -m "Decompile func_800A1158" -``` - -## Code Patterns - -### INCLUDE_ASM Macro -Embeds undecompiled assembly: -```c -INCLUDE_ASM("asm/us/battle/nonmatchings/battle", func_800A1158); -``` -Replace with decompiled C code when function matches. - -### Renaming INCLUDE_ASM Functions - -INCLUDE_ASM functions can be renamed without decompiling them. The process differs between the **main overlay** and **other overlays**: - -#### Main Overlay (src/main/*.c) -The asm files in `asm/us/main/nonmatchings/` are **static** - they persist on disk and are not regenerated. - -To rename a function (e.g., `func_80026F44` → `MenuDrawText`): -1. **Rename the asm file**: `mv asm/us/main/nonmatchings/18B8/func_80026F44.s asm/us/main/nonmatchings/18B8/MenuDrawText.s` -2. **Update the asm file contents**: - - Change `glabel func_80026F44` → `glabel MenuDrawText` - - Change `.size func_80026F44, . - func_80026F44` → `.size MenuDrawText, . - MenuDrawText` -3. **Update the INCLUDE_ASM macro** in the C file -4. **Update all call sites** in `src/` that reference this function -5. **Update the symbol file** (e.g., `config/symbols.main.us.txt`) - -#### Other Overlays (src/menu/*.c, src/battle/*.c, etc.) -The asm files in overlay directories are **regenerated by splat** on each build. Renaming the files directly won't work - splat will recreate them with the old names. - -To rename a function (e.g., `func_801D080C` → `MenuConfig` in cnfgmenu): -1. **Add the new name to the overlay's symbol file** (e.g., `config/symbols.cnfgmenu.us.txt`): - ``` - MenuConfig = 0x801D080C; - ``` -2. **Update `config/sym_ovl_export.us.txt`** (for cross-overlay references): - - Change `func_801D080C = 0x801d080c;` → `MenuConfig = 0x801d080c;` -3. **Update the INCLUDE_ASM macro** in the C file -4. **Update any references** in other files (e.g., `src/main/ovl.c` for exported functions) -5. **Run the build** - splat will generate the asm file with the new name - -The old asm file may remain in the directory but will be unused. It can be deleted manually. - -### Common Types -```c -typedef signed char s8; typedef unsigned char u8; -typedef signed short s16; typedef unsigned short u16; -typedef signed int s32; typedef unsigned int u32; -typedef u8 unk_data; typedef unsigned int* unk_ptr; -``` - -### String Encoding -FF7 uses custom character encoding, not ASCII. Use `_S()` macro: -```c -const char* msg = _S("Save game?"); -``` - -## Naming Conventions - -### Functions -- Undecompiled: `func_800XXXXX` (address-based) -- Decompiled: verb-first descriptive names, prefer PSX SDK names when applicable -- Examples: `InitBattle`, `LoadScene`, `DrawSprite` - -### Data/Globals -- Unknown: `D_800XXXXX` (address-based) -- Known game state: `g_` prefix (e.g., `g_BattleState`) -- Module constants: module prefix (e.g., `BATTLE_MAX_ENEMIES`) -- Struct fields: `unkXX` until purpose known - -## Symbol Files - -Located in `config/`: -- `symbols.main.us.txt` - Main overlay symbols -- `symbols.battle.txt` - Battle overlay symbols -- `sym_export.us.txt` - Cross-overlay exports -- `sym_extern.us.txt` - External references - -Format: -``` -function_name = 0x800A1158; -D_800F5BB8 = 0x800F5BB8; // size:0xCC -``` - -Add symbols with: -```shell -./mako.sh symbols add config/symbols.battle.txt MyFunction 0x800A1234 -``` - -## Key Data Structures - -### Savemap (0x8009C6E4) -Game save data. Use `--fix-structs` to auto-replace `D_8009XXXX` references: -- `Savemap.party[9]` - Party member data -- `Savemap.inventory` - Item inventory -- `Savemap.materia` - Materia slots -- `Savemap.gil` - Money -- See `tools/fix_structs.py` for full field list - -### Battle Structures (`src/battle/battle.h`) -- `BattleSetup` - Battle configuration -- `Unk800F83E0` - Battle state (0x68 bytes) -- `BattleSetupType` - Encounter types (preemptive, back attack, etc.) - -## Tips for Matching - -1. **Compiler quirks**: Two PSX compilers available (`cc1-psx-26`, `cc1-psx-272`). Check which one the overlay uses in `config/us.yaml`. - -2. **Register allocation**: Order of operations matters. Sometimes restructuring expressions helps match. - -3. **Global pointer (GP)**: Main overlay uses `gp=0x80062D44`. Variables near this use gp-relative addressing. - -4. **Rodata association**: Battle overlay has `migrate_rodata_to_functions: true` - rodata is bundled with functions. - -5. **Use mipsel-linux-gnu-objdump** for line-by-line comparison - -## Comparing Original vs Compiled Assembly - -When a decompiled function doesn't match, compare the original assembly with the compiled output: - -### 1. Check Function Size (Quick Check) -```shell -# Get compiled function size from symbol table -./tools/docker-build.sh "mipsel-linux-gnu-objdump -t build/us/src/main/18B8.c.o" | grep func_80026F44 - -# Output: 00015e8c g F .text 00000128 func_80026F44 -# ^^^^^^^^ ^^^^^^^^ <- size in hex (0x128 = 296 bytes) -``` - -Compare with original size: count bytes from function start to end in the `.s` file, or calculate from addresses (end_addr - start_addr + 4). - -### 2. View Compiled Disassembly -```shell -# Disassemble a specific function from the compiled object -./tools/docker-build.sh "mipsel-linux-gnu-objdump -d build/us/src/main/18B8.c.o" | grep -A100 ':' -``` - -### 3. View Original Assembly -```shell -# Original assembly is in asm/us//nonmatchings// -cat asm/us/main/nonmatchings/18B8/func_80026F44.s -``` - -### 4. Common Size Mismatch Causes -- **Code merged after branches**: Compiler optimizes common code after if/else. Fix: put function calls inside each branch. -- **Delay slot optimization**: Original uses delay slots cleverly. The compiled code may not reproduce this. -- **Sign extension duplication**: Original may have `sll/sra` pairs duplicated in branches; compiler merges them. -- **Register allocation**: Different register choices can cause different instruction sequences. -- **Type differences**: `s8` vs `u8` generates `lb` vs `lbu` instructions. - -### 5. Useful Patterns -```shell -# Count instructions in original (each line with glabel excluded, /* */ comments have instructions) -grep -c '/\*' asm/us/main/nonmatchings/18B8/func_80026F44.s - -# Find jr ra (function returns) to identify function boundaries -./tools/docker-build.sh "mipsel-linux-gnu-objdump -d build/us/src/main/18B8.c.o" | grep 'jr.*ra' -``` - -## Decompilation Tips Checklist - -When decompiling a function, follow this checklist: - -- [ ] No prototypes or parameters with '?' as type -- [ ] No 'void*' parameters that should be typed structs -- [ ] No pointer arithmetic with manual offset calculations -- [ ] Use array indices to access arrays, do not use arithmetic calculations -- [ ] All struct field accesses use '->' or '.' operators -- [ ] Struct sizes match the assembly access patterns -- [ ] 'goto loop_*' are converted as 'while' loops -- [ ] 'goto block_*' in 'switch' are inlined, to reverse code optimization - -Alignment is critical. Code and data are aligned by 4-byte. - -## Finding symbol names and applying them to the decompiled code - -Our goal in this project currently is to find out as many symbol names (functions, variables, enums, structs, local variables, function parameters) as possible and apply them to the decompiled code. At the same time we want to ensure the code compiles 1:1 matching the original PSX binaries so we cannot alter the parameter types and change any logic. - -1. First we need to analyse both the decompiled PSX code in the @src/ folder and the PC decompiled code in the @assets/ folder. You usually start with a function in the PSX code that is unique enough and already has some symbols decompiled or its logic is recognizable enough that it can be matched to the PC code. -2. Spawn a sub-agent to look through the PC code in the @assets/ folder (do not read these files directly because they're huge) and find any corresponding code that can help us find new symbol names -3. Map out the connections between the PSX code (skip function names defined with INCLUDE_ASM macro, only functions fully defined in C can be renamed) and the PC code and store your findings in @CLAUDE_DECOMP.md for future reference. Make sure you're absolutely certain when creating this mapping - if there is any doubt about a specific symbol you should skip it. -4. Apply the changes. To do this spawn an Apply sub-agent that will take a map of symbol names to update (eg. "func_800A1158 = MyFunction", "D_800F5BB8 = MyVariable") and then the sub-agent will figure out how to efficiently and comprehensively apply these changes to the PSX code in @src/ (remember to update references to the changed symbol names in other source and header files; when changing a function name you should update all function calls to it in the code). The sub-agent should think hard to make sure it does not break anything as some symbol names are used in multiple places. The sub-agent shall not alter parameter types in function signatures. The sub-agent shall not read or update the assembly files in asm/ (these are generated by the disassembler and should not be manually edited). After finishing applying the changes it should return immediately without trying to run the build. -5. In parallel spawn a second sub-agent that will update the symbol maps in @config/ in symbols.main.us.txt and any other *.txt files that contain symbol names (skip sym_export.us.txt and sym_export_battle.us.txt since these are autogenerated by the build system) -6. After the work is done run the build to verify if the changes are correct. The build should succeed without any errors and all the SHA1 sums should match. Fix any issues that arise and repeat the process until the changes are correct. -7. Take one more look at CLAUDE_DECOMP.md and make sure its updated with all the new knowledge you've gained. -8. Finally think about what the next steps would be and suggest options to the user - -## Files to Commit -When submitting decompiled code: -```shell -git add config/ # Symbol files -git add include/ # Headers (if modified) -git add src/ # Decompiled source -``` - -## Advanced Matching Techniques - -### Understanding Why Decompiled Code Doesn't Match - -When the size is wrong, the compiler is generating different code structure. Common causes: - -#### 1. Merged Function Calls -**Problem**: Modern compilers merge common code after if/else branches. -```c -// BAD - compiler merges the call after the branches -if (condition) { - setup_a(); -} else { - setup_b(); -} -common_call(); // Compiler optimizes: one call site - -// GOOD - forces separate code paths (matches original) -if (condition) { - setup_a(); - common_call(); // Call inside branch -} else { - setup_b(); - common_call(); // Duplicate call -} -``` - -#### 2. Variable Type Affects Load Instructions -- `s8` generates `lb` (load byte signed) -- `u8` generates `lbu` (load byte unsigned) -- Check if global variables need type changes to match original instructions - -#### 3. Struct vs Separate Variables -**Problem**: Compiler optimizes away stores to local variables if it thinks they're unused. -```c -// BAD - compiler may skip storing to sp1C, sp1E -s16 sp18, sp1A, sp1C, sp1E; -sp1C = 0xFF; // May be optimized away! -sp1E = 0xFF; -sp18 = 0; -sp1A = 0; -SetDrawMode(..., (RECT*)&sp18); - -// GOOD - using proper struct ensures all fields are stored -RECT rect; -rect.w = 0xFF; // Compiler knows RECT fields are accessed -rect.h = 0xFF; -rect.x = 0; -rect.y = 0; -SetDrawMode(..., &rect); -``` - -#### 4. Delay Slot Optimization -Original PSX compiler often put useful instructions in branch delay slots. Modern compilers may: -- Put the instruction before the branch instead -- Use NOP in delay slots - -Example: Original saves `y << 16` before loop, uses delay slot for `s2 = 0`: -```asm -beqz v0, check_mode -addu s2, zero, zero # delay slot: s2 = 0 -sll s1, a1, 16 # after branch: save y -``` - -#### 5. Redundant Instructions in Original -The original compiler sometimes generated redundant code: -- `andi t0, v1, 0xFF` after `lbu v1` (already 8-bit) -- Duplicate `sra a1, s1, 16` in both branches - -These are hard to reproduce with modern compilers without tricks. - -### Matching Workflow - -1. **Get size right first** - Restructure code until instruction count matches (note: if the output size is wrong you might see compiler/linker errors in unrelated files - this is a good indicator that the size is wrong) -2. **Fix types second** - Change s8/u8, s16/u16 to match load/store instructions -3. **Reorder operations** - Match the order of stores/loads in original -4. **Check branch structure** - Use goto labels to match original control flow -5. Look at other decompiled functions in the same file to see how they handle similar patterns to the ones you're trying to match - -### Debugging Commands -```shell -# Compare function sizes -./tools/docker-build.sh "mipsel-linux-gnu-objdump -t build/us/src/main/18B8.c.o" | grep func_NAME - -# View compiled assembly -./tools/docker-build.sh "mipsel-linux-gnu-objdump -d build/us/src/main/18B8.c.o" | grep -A100 ':' - -# Original is in asm/us//nonmatchings//func_NAME.s -``` - -## Reference Links -- PSX SDK docs: PSY-Q library documentation -- FF7 Scarlet: https://github.com/petfriendamy/ff7-scarlet (game data structures)