diff --git a/.run/backlog.jsonl b/.run/backlog.jsonl index 35e745989..0b580379d 100644 --- a/.run/backlog.jsonl +++ b/.run/backlog.jsonl @@ -497,7 +497,6 @@ {"ts": "2026-07-14 22:58:06", "addr": null, "name": "func_8017DA9C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 83, "where_stuck": "residual: 83 mismatch", "best_draft": ".run/backlog_drafts/func_8017DA9C.c", "binary": "ov_SC01_008", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 22:58:06", "addr": null, "name": "func_8017DD18", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 21, "where_stuck": "residual: 21 mismatch", "best_draft": ".run/backlog_drafts/func_8017DD18.c", "binary": "ov_SC01_008", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 22:58:32", "addr": null, "name": "func_8017D610", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 64, "where_stuck": "residual: 64 mismatch", "best_draft": ".run/backlog_drafts/func_8017D610.c", "binary": "ov_SC02_035", "source": "worker", "residual": null, "passes_tried": null} -{"ts": "2026-07-14 22:58:32", "addr": null, "name": "func_8017F96C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 106, "where_stuck": "residual: 106 mismatch", "best_draft": ".run/backlog_drafts/func_8017F96C.c", "binary": "ov_SC02_035", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 22:59:00", "addr": null, "name": "func_80181A94", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 15, "where_stuck": "residual: 15 mismatch", "best_draft": ".run/backlog_drafts/func_80181A94.c", "binary": "ov_SC02_000", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 22:59:00", "addr": null, "name": "func_80182E08", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 30, "where_stuck": "residual: 30 mismatch", "best_draft": ".run/backlog_drafts/func_80182E08.c", "binary": "ov_SC02_000", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 22:59:00", "addr": null, "name": "func_80183018", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 32, "where_stuck": "residual: 32 mismatch", "best_draft": ".run/backlog_drafts/func_80183018.c", "binary": "ov_SC02_000", "source": "worker", "residual": null, "passes_tried": null} @@ -763,7 +762,6 @@ {"ts": "2026-07-14 23:40:24", "addr": null, "name": "func_80183598", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 42, "where_stuck": "residual: 42 mismatch", "best_draft": ".run/backlog_drafts/func_80183598.c", "binary": "ov_SC06_024", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 23:40:24", "addr": null, "name": "func_80183C58", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 17, "where_stuck": "residual: 17 mismatch", "best_draft": ".run/backlog_drafts/func_80183C58.c", "binary": "ov_SC06_024", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 23:40:24", "addr": null, "name": "func_8018474C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 76, "where_stuck": "residual: 76 mismatch", "best_draft": ".run/backlog_drafts/func_8018474C.c", "binary": "ov_SC06_024", "source": "worker", "residual": null, "passes_tried": null} -{"ts": "2026-07-14 23:40:24", "addr": null, "name": "func_8018788C", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 113, "where_stuck": "residual: 113 mismatch", "best_draft": ".run/backlog_drafts/func_8018788C.c", "binary": "ov_SC06_024", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 23:40:48", "addr": null, "name": "func_80182BC8", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 107, "where_stuck": "residual: 107 mismatch", "best_draft": ".run/backlog_drafts/func_80182BC8.c", "binary": "ov_SC06_029", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 23:40:49", "addr": null, "name": "func_80183D84", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 192, "where_stuck": "residual: 192 mismatch", "best_draft": ".run/backlog_drafts/func_80183D84.c", "binary": "ov_SC06_029", "source": "worker", "residual": null, "passes_tried": null} {"ts": "2026-07-14 23:40:49", "addr": null, "name": "func_80186044", "reach": null, "klass": null, "nins": null, "status": "near", "closeness": 41, "where_stuck": "residual: 41 mismatch", "best_draft": ".run/backlog_drafts/func_80186044.c", "binary": "ov_SC06_029", "source": "worker", "residual": null, "passes_tried": null} diff --git a/docs/backlog.md b/docs/backlog.md index 26960ac2d..f306e53fa 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -2,7 +2,7 @@ > Generated by `tools/backlog.py render` from `.run/backlog.jsonl`. These are functions the Phase-21 automation got **close** on but did NOT byte-match. The whole-binary byte-gate is the sole arbiter (G3/P9): **byte-matches bank and are NOT listed here** — only genuine near-misses/blockers are. Ranked by hand-session priority: **reach** (×N propagation leverage) → **closeness** (match_one mismatch count, lower = closer) → **size**. Each row's `best_draft` is the closest C the machine reached — resume from there. -**Open near-misses:** 847 · by status {'near': 804, 'failed': 43} · by class {'regalloc-order': 8, 'struct': 6, 'plumbing': 3, 'schedule': 2, 'WAVE': 9, None: 808, 'other': 1, 'STRUCT': 10} +**Open near-misses:** 845 · by status {'near': 802, 'failed': 43} · by class {'regalloc-order': 8, 'struct': 6, 'plumbing': 3, 'schedule': 2, 'WAVE': 9, None: 806, 'other': 1, 'STRUCT': 10} | # | addr | reach | class | nins | status | closeness | where it stuck | best draft | |--:|------|------:|-------|-----:|--------|----------:|----------------|------------| @@ -762,94 +762,92 @@ | 754 | func_8017D808 | None | | None | near | 102 | residual: 102 mismatch | `.run/backlog_drafts/func_8017D808.c` | | 755 | func_80182D10 | None | | None | near | 102 | residual: 102 mismatch | `.run/backlog_drafts/func_80182D10.c` | | 756 | func_8017DC40 | None | | None | near | 104 | residual: 104 mismatch | `.run/backlog_drafts/func_8017DC40.c` | -| 757 | func_8017F96C | None | | None | near | 106 | residual: 106 mismatch | `.run/backlog_drafts/func_8017F96C.c` | -| 758 | func_8017EFEC | None | | None | near | 107 | residual: 107 mismatch | `.run/backlog_drafts/func_8017EFEC.c` | -| 759 | func_80182BC8 | None | | None | near | 107 | residual: 107 mismatch | `.run/backlog_drafts/func_80182BC8.c` | -| 760 | func_8017F69C | None | | None | near | 107 | residual: 107 mismatch | `.run/backlog_drafts/func_8017F69C.c` | -| 761 | func_80184828 | None | | None | near | 109 | residual: 109 mismatch | `.run/backlog_drafts/func_80184828.c` | -| 762 | func_8017F3E4 | None | | None | near | 110 | residual: 110 mismatch | `.run/backlog_drafts/func_8017F3E4.c` | -| 763 | func_80181948 | 1 | STRUCT | 132 | near | 111 | STRUCT: 111 mismatch | `.run/backlog_drafts/func_80181948.c` | -| 764 | func_8017DAF4 | None | | None | near | 111 | residual: 111 mismatch | `.run/backlog_drafts/func_8017DAF4.c` | -| 765 | func_8017FE9C | None | | None | near | 111 | residual: 111 mismatch | `.run/backlog_drafts/func_8017FE9C.c` | -| 766 | func_8017F768 | None | | None | near | 112 | residual: 112 mismatch | `.run/backlog_drafts/func_8017F768.c` | -| 767 | func_8017F3B8 | None | | None | near | 112 | residual: 112 mismatch | `.run/backlog_drafts/func_8017F3B8.c` | -| 768 | func_8017D508 | None | | None | near | 113 | residual: 113 mismatch | `.run/backlog_drafts/func_8017D508.c` | -| 769 | func_8018788C | None | | None | near | 113 | residual: 113 mismatch | `.run/backlog_drafts/func_8018788C.c` | -| 770 | func_80180C90 | 1 | STRUCT | 160 | near | 116 | STRUCT: 116 mismatch | `.run/backlog_drafts/func_80180C90.c` | -| 771 | func_80181858 | None | | None | near | 117 | residual: 117 mismatch | `.run/backlog_drafts/func_80181858.c` | -| 772 | func_8017E8F8 | None | | None | near | 120 | residual: 120 mismatch | `.run/backlog_drafts/func_8017E8F8.c` | -| 773 | func_80184358 | None | | None | near | 121 | residual: 121 mismatch | `.run/backlog_drafts/func_80184358.c` | -| 774 | func_8017F074 | None | | None | near | 121 | residual: 121 mismatch | `.run/backlog_drafts/func_8017F074.c` | -| 775 | func_8017D890 | None | | None | near | 124 | residual: 124 mismatch | `.run/backlog_drafts/func_8017D890.c` | -| 776 | func_8017DECC | None | | None | near | 125 | residual: 125 mismatch | `.run/backlog_drafts/func_8017DECC.c` | -| 777 | func_80185020 | None | | None | near | 125 | residual: 125 mismatch | `.run/backlog_drafts/func_80185020.c` | -| 778 | func_801892CC | None | | None | near | 127 | residual: 127 mismatch | `.run/backlog_drafts/func_801892CC.c` | -| 779 | func_8017EB00 | None | | None | near | 127 | residual: 127 mismatch | `.run/backlog_drafts/func_8017EB00.c` | -| 780 | func_80185E68 | 1 | STRUCT | 132 | near | 131 | STRUCT: 131 mismatch | `.run/backlog_drafts/func_80185E68.c` | -| 781 | func_8017E378 | None | | None | near | 134 | residual: 134 mismatch | `.run/backlog_drafts/func_8017E378.c` | -| 782 | func_80186530 | None | | None | near | 139 | residual: 139 mismatch | `.run/backlog_drafts/func_80186530.c` | -| 783 | func_80186078 | 1 | WAVE | 174 | near | 141 | WAVE: 141 mismatch | `.run/backlog_drafts/func_80186078.c` | -| 784 | func_80184F08 | None | regalloc-order | None | near | 141 | none — MATCH (145/145 ins, match_one confirmed) | `.run/backlog_drafts/func_80184F08.c` | -| 785 | func_80185668 | None | | None | near | 142 | residual: 142 mismatch | `.run/backlog_drafts/func_80185668.c` | -| 786 | func_8017DB0C | None | | None | near | 142 | residual: 142 mismatch | `.run/backlog_drafts/func_8017DB0C.c` | -| 787 | func_80181984 | None | | None | near | 153 | residual: 153 mismatch | `.run/backlog_drafts/func_80181984.c` | -| 788 | func_8017E6EC | None | | None | near | 172 | residual: 172 mismatch | `.run/backlog_drafts/func_8017E6EC.c` | -| 789 | func_80181BE4 | 1 | STRUCT | 201 | near | 173 | STRUCT: 173 mismatch | `.run/backlog_drafts/func_80181BE4.c` | -| 790 | func_80184210 | None | | None | near | 176 | residual: 176 mismatch | `.run/backlog_drafts/func_80184210.c` | -| 791 | func_80180568 | None | | None | near | 185 | residual: 185 mismatch | `.run/backlog_drafts/func_80180568.c` | -| 792 | func_801809C4 | None | | None | near | 190 | residual: 190 mismatch | `.run/backlog_drafts/func_801809C4.c` | -| 793 | func_80183D84 | None | | None | near | 192 | residual: 192 mismatch | `.run/backlog_drafts/func_80183D84.c` | -| 794 | func_80183FEC | None | | None | near | 198 | residual: 198 mismatch | `.run/backlog_drafts/func_80183FEC.c` | -| 795 | func_801823B8 | None | | None | near | 204 | residual: 204 mismatch | `.run/backlog_drafts/func_801823B8.c` | -| 796 | func_801826C4 | None | | None | near | 207 | residual: 207 mismatch | `.run/backlog_drafts/func_801826C4.c` | -| 797 | func_8018C3F8 | None | | None | near | 236 | residual: 236 mismatch | `.run/backlog_drafts/func_8018C3F8.c` | -| 798 | func_8017FD14 | 1 | STRUCT | 249 | near | 240 | STRUCT: 240 mismatch | `.run/backlog_drafts/func_8017FD14.c` | -| 799 | func_8017E7D4 | None | | None | near | 241 | residual: 241 mismatch | `.run/backlog_drafts/func_8017E7D4.c` | -| 800 | func_80183BF8 | None | | None | near | 258 | residual: 258 mismatch | `.run/backlog_drafts/func_80183BF8.c` | -| 801 | func_8017EB30 | None | | None | near | 278 | residual: 278 mismatch | `.run/backlog_drafts/func_8017EB30.c` | -| 802 | func_801804A0 | None | | None | near | 280 | residual: 280 mismatch | `.run/backlog_drafts/func_801804A0.c` | -| 803 | func_80181670 | None | | None | near | 311 | residual: 311 mismatch | `.run/backlog_drafts/func_80181670.c` | -| 804 | func_8018057C | None | | None | near | 897 | residual: 897 mismatch | `.run/backlog_drafts/func_8018057C.c` | -| 805 | func_80128CFC | 1 | WAVE | 25 | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80128CFC.c` | -| 806 | func_80184A68 | 1 | regalloc-order | 33 | failed | | none — MATCH | `.run/backlog_drafts/func_80184A68.c` | -| 807 | func_80180B64 | 1 | struct | 75 | failed | | none — MATCH (75 ins, relocation-masked) | `.run/backlog_drafts/func_80180B64.c` | -| 808 | func_80183DE0 | 1 | regalloc-order | 91 | failed | | testing if(!=1) layout + counter-before-pointer init order | `.run/backlog_drafts/func_80183DE0.c` | -| 809 | func_80185BA4 | 1 | WAVE | 177 | failed | | won't compile standalone (loose-typing / missing decl) | | -| 810 | func_80183324 | 1 | STRUCT | 324 | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80183324.c` | -| 811 | func_8017D8DC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017D8DC.c` | -| 812 | func_8017FFEC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017FFEC.c` | -| 813 | func_8017DC18 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017DC18.c` | -| 814 | func_801853CC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801853CC.c` | -| 815 | func_80181894 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181894.c` | -| 816 | func_8018BFBC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8018BFBC.c` | -| 817 | func_801807F4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801807F4.c` | -| 818 | func_8017FFC8 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017FFC8.c` | -| 819 | func_8017E99C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E99C.c` | -| 820 | func_80180294 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80180294.c` | -| 821 | func_8017E76C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E76C.c` | -| 822 | func_8017F29C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017F29C.c` | -| 823 | func_8017F00C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017F00C.c` | -| 824 | func_801802B0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801802B0.c` | -| 825 | func_8017DA1C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017DA1C.c` | -| 826 | func_8017FFC4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017FFC4.c` | -| 827 | func_8017E2F0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E2F0.c` | -| 828 | func_801841E4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801841E4.c` | -| 829 | func_80181738 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181738.c` | -| 830 | func_801873D8 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801873D8.c` | -| 831 | func_80185628 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80185628.c` | -| 832 | func_80181A78 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181A78.c` | -| 833 | func_801805D4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801805D4.c` | -| 834 | func_8017EA1C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017EA1C.c` | -| 835 | func_8017F098 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017F098.c` | -| 836 | func_801822CC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801822CC.c` | -| 837 | func_8017E3F4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E3F4.c` | -| 838 | func_800D1658 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_800D1658.c` | -| 839 | func_800D1984 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_800D1984.c` | -| 840 | func_800D24A0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_800D24A0.c` | -| 841 | func_8013DD68 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8013DD68.c` | -| 842 | func_80132018 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80132018.c` | -| 843 | func_80181164 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181164.c` | -| 844 | func_8012D664 | None | schedule | None | failed | | none — MATCH | `.run/backlog_drafts/func_8012D664.c` | -| 845 | func_80136C90 | None | struct | None | failed | | none — MATCH (28 ins). 10-byte 1-aligned struct copy (S10{char s[10]}) from global D_801A5A7C into a stack buffer, then ((void(*)(int, void *, int, int, int, int))func_8001534C)(0,&buf,0x78,0x10,0,0). gcc emits the block move as 2 unaligned words (lwl/lwr+swl/swr) + 2 bytes (lb/sb). | `.run/backlog_drafts/func_80136C90.c` | -| 846 | func_80145CEC | None | struct | None | failed | | 2 residuals — (1) target RELOADS global ptr ((s32 *)&D_80126B78) before each of its 5 field accesses (f28/f18/f1a/f1c/f2c); gcc-2.7.2 CSEs the single pointer load in every clean-C form I tried (int-cast, (s8*)/(s32) M2C_FIELD, struct*), keeping ONE load. volatile forces reloads but hoists them + leaves delay-slot nops the target fills (target is NOT volatile). (2) frame 0x20 not 0x18: target reserves an unused 8-byte stack local @0x10 (address-taken local — reproduced, but every code-free escape optimizes away and a visible escape corrupts the ((int (*)(void))func_80145EE8)(0) arg). Structure/order/values/callees all match; only the alias-driven reload chain + the phantom frame local remain. Family exemplar (~130 overlays). | `.run/backlog_drafts/func_80145CEC.c` | -| 847 | func_8016BCC0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8016BCC0.c` | +| 757 | func_8017EFEC | None | | None | near | 107 | residual: 107 mismatch | `.run/backlog_drafts/func_8017EFEC.c` | +| 758 | func_80182BC8 | None | | None | near | 107 | residual: 107 mismatch | `.run/backlog_drafts/func_80182BC8.c` | +| 759 | func_8017F69C | None | | None | near | 107 | residual: 107 mismatch | `.run/backlog_drafts/func_8017F69C.c` | +| 760 | func_80184828 | None | | None | near | 109 | residual: 109 mismatch | `.run/backlog_drafts/func_80184828.c` | +| 761 | func_8017F3E4 | None | | None | near | 110 | residual: 110 mismatch | `.run/backlog_drafts/func_8017F3E4.c` | +| 762 | func_80181948 | 1 | STRUCT | 132 | near | 111 | STRUCT: 111 mismatch | `.run/backlog_drafts/func_80181948.c` | +| 763 | func_8017DAF4 | None | | None | near | 111 | residual: 111 mismatch | `.run/backlog_drafts/func_8017DAF4.c` | +| 764 | func_8017FE9C | None | | None | near | 111 | residual: 111 mismatch | `.run/backlog_drafts/func_8017FE9C.c` | +| 765 | func_8017F768 | None | | None | near | 112 | residual: 112 mismatch | `.run/backlog_drafts/func_8017F768.c` | +| 766 | func_8017F3B8 | None | | None | near | 112 | residual: 112 mismatch | `.run/backlog_drafts/func_8017F3B8.c` | +| 767 | func_8017D508 | None | | None | near | 113 | residual: 113 mismatch | `.run/backlog_drafts/func_8017D508.c` | +| 768 | func_80180C90 | 1 | STRUCT | 160 | near | 116 | STRUCT: 116 mismatch | `.run/backlog_drafts/func_80180C90.c` | +| 769 | func_80181858 | None | | None | near | 117 | residual: 117 mismatch | `.run/backlog_drafts/func_80181858.c` | +| 770 | func_8017E8F8 | None | | None | near | 120 | residual: 120 mismatch | `.run/backlog_drafts/func_8017E8F8.c` | +| 771 | func_80184358 | None | | None | near | 121 | residual: 121 mismatch | `.run/backlog_drafts/func_80184358.c` | +| 772 | func_8017F074 | None | | None | near | 121 | residual: 121 mismatch | `.run/backlog_drafts/func_8017F074.c` | +| 773 | func_8017D890 | None | | None | near | 124 | residual: 124 mismatch | `.run/backlog_drafts/func_8017D890.c` | +| 774 | func_8017DECC | None | | None | near | 125 | residual: 125 mismatch | `.run/backlog_drafts/func_8017DECC.c` | +| 775 | func_80185020 | None | | None | near | 125 | residual: 125 mismatch | `.run/backlog_drafts/func_80185020.c` | +| 776 | func_801892CC | None | | None | near | 127 | residual: 127 mismatch | `.run/backlog_drafts/func_801892CC.c` | +| 777 | func_8017EB00 | None | | None | near | 127 | residual: 127 mismatch | `.run/backlog_drafts/func_8017EB00.c` | +| 778 | func_80185E68 | 1 | STRUCT | 132 | near | 131 | STRUCT: 131 mismatch | `.run/backlog_drafts/func_80185E68.c` | +| 779 | func_8017E378 | None | | None | near | 134 | residual: 134 mismatch | `.run/backlog_drafts/func_8017E378.c` | +| 780 | func_80186530 | None | | None | near | 139 | residual: 139 mismatch | `.run/backlog_drafts/func_80186530.c` | +| 781 | func_80186078 | 1 | WAVE | 174 | near | 141 | WAVE: 141 mismatch | `.run/backlog_drafts/func_80186078.c` | +| 782 | func_80184F08 | None | regalloc-order | None | near | 141 | none — MATCH (145/145 ins, match_one confirmed) | `.run/backlog_drafts/func_80184F08.c` | +| 783 | func_80185668 | None | | None | near | 142 | residual: 142 mismatch | `.run/backlog_drafts/func_80185668.c` | +| 784 | func_8017DB0C | None | | None | near | 142 | residual: 142 mismatch | `.run/backlog_drafts/func_8017DB0C.c` | +| 785 | func_80181984 | None | | None | near | 153 | residual: 153 mismatch | `.run/backlog_drafts/func_80181984.c` | +| 786 | func_8017E6EC | None | | None | near | 172 | residual: 172 mismatch | `.run/backlog_drafts/func_8017E6EC.c` | +| 787 | func_80181BE4 | 1 | STRUCT | 201 | near | 173 | STRUCT: 173 mismatch | `.run/backlog_drafts/func_80181BE4.c` | +| 788 | func_80184210 | None | | None | near | 176 | residual: 176 mismatch | `.run/backlog_drafts/func_80184210.c` | +| 789 | func_80180568 | None | | None | near | 185 | residual: 185 mismatch | `.run/backlog_drafts/func_80180568.c` | +| 790 | func_801809C4 | None | | None | near | 190 | residual: 190 mismatch | `.run/backlog_drafts/func_801809C4.c` | +| 791 | func_80183D84 | None | | None | near | 192 | residual: 192 mismatch | `.run/backlog_drafts/func_80183D84.c` | +| 792 | func_80183FEC | None | | None | near | 198 | residual: 198 mismatch | `.run/backlog_drafts/func_80183FEC.c` | +| 793 | func_801823B8 | None | | None | near | 204 | residual: 204 mismatch | `.run/backlog_drafts/func_801823B8.c` | +| 794 | func_801826C4 | None | | None | near | 207 | residual: 207 mismatch | `.run/backlog_drafts/func_801826C4.c` | +| 795 | func_8018C3F8 | None | | None | near | 236 | residual: 236 mismatch | `.run/backlog_drafts/func_8018C3F8.c` | +| 796 | func_8017FD14 | 1 | STRUCT | 249 | near | 240 | STRUCT: 240 mismatch | `.run/backlog_drafts/func_8017FD14.c` | +| 797 | func_8017E7D4 | None | | None | near | 241 | residual: 241 mismatch | `.run/backlog_drafts/func_8017E7D4.c` | +| 798 | func_80183BF8 | None | | None | near | 258 | residual: 258 mismatch | `.run/backlog_drafts/func_80183BF8.c` | +| 799 | func_8017EB30 | None | | None | near | 278 | residual: 278 mismatch | `.run/backlog_drafts/func_8017EB30.c` | +| 800 | func_801804A0 | None | | None | near | 280 | residual: 280 mismatch | `.run/backlog_drafts/func_801804A0.c` | +| 801 | func_80181670 | None | | None | near | 311 | residual: 311 mismatch | `.run/backlog_drafts/func_80181670.c` | +| 802 | func_8018057C | None | | None | near | 897 | residual: 897 mismatch | `.run/backlog_drafts/func_8018057C.c` | +| 803 | func_80128CFC | 1 | WAVE | 25 | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80128CFC.c` | +| 804 | func_80184A68 | 1 | regalloc-order | 33 | failed | | none — MATCH | `.run/backlog_drafts/func_80184A68.c` | +| 805 | func_80180B64 | 1 | struct | 75 | failed | | none — MATCH (75 ins, relocation-masked) | `.run/backlog_drafts/func_80180B64.c` | +| 806 | func_80183DE0 | 1 | regalloc-order | 91 | failed | | testing if(!=1) layout + counter-before-pointer init order | `.run/backlog_drafts/func_80183DE0.c` | +| 807 | func_80185BA4 | 1 | WAVE | 177 | failed | | won't compile standalone (loose-typing / missing decl) | | +| 808 | func_80183324 | 1 | STRUCT | 324 | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80183324.c` | +| 809 | func_8017D8DC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017D8DC.c` | +| 810 | func_8017FFEC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017FFEC.c` | +| 811 | func_8017DC18 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017DC18.c` | +| 812 | func_801853CC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801853CC.c` | +| 813 | func_80181894 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181894.c` | +| 814 | func_8018BFBC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8018BFBC.c` | +| 815 | func_801807F4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801807F4.c` | +| 816 | func_8017FFC8 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017FFC8.c` | +| 817 | func_8017E99C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E99C.c` | +| 818 | func_80180294 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80180294.c` | +| 819 | func_8017E76C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E76C.c` | +| 820 | func_8017F29C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017F29C.c` | +| 821 | func_8017F00C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017F00C.c` | +| 822 | func_801802B0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801802B0.c` | +| 823 | func_8017DA1C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017DA1C.c` | +| 824 | func_8017FFC4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017FFC4.c` | +| 825 | func_8017E2F0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E2F0.c` | +| 826 | func_801841E4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801841E4.c` | +| 827 | func_80181738 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181738.c` | +| 828 | func_801873D8 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801873D8.c` | +| 829 | func_80185628 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80185628.c` | +| 830 | func_80181A78 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181A78.c` | +| 831 | func_801805D4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801805D4.c` | +| 832 | func_8017EA1C | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017EA1C.c` | +| 833 | func_8017F098 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017F098.c` | +| 834 | func_801822CC | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_801822CC.c` | +| 835 | func_8017E3F4 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8017E3F4.c` | +| 836 | func_800D1658 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_800D1658.c` | +| 837 | func_800D1984 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_800D1984.c` | +| 838 | func_800D24A0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_800D24A0.c` | +| 839 | func_8013DD68 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8013DD68.c` | +| 840 | func_80132018 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80132018.c` | +| 841 | func_80181164 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_80181164.c` | +| 842 | func_8012D664 | None | schedule | None | failed | | none — MATCH | `.run/backlog_drafts/func_8012D664.c` | +| 843 | func_80136C90 | None | struct | None | failed | | none — MATCH (28 ins). 10-byte 1-aligned struct copy (S10{char s[10]}) from global D_801A5A7C into a stack buffer, then ((void(*)(int, void *, int, int, int, int))func_8001534C)(0,&buf,0x78,0x10,0,0). gcc emits the block move as 2 unaligned words (lwl/lwr+swl/swr) + 2 bytes (lb/sb). | `.run/backlog_drafts/func_80136C90.c` | +| 844 | func_80145CEC | None | struct | None | failed | | 2 residuals — (1) target RELOADS global ptr ((s32 *)&D_80126B78) before each of its 5 field accesses (f28/f18/f1a/f1c/f2c); gcc-2.7.2 CSEs the single pointer load in every clean-C form I tried (int-cast, (s8*)/(s32) M2C_FIELD, struct*), keeping ONE load. volatile forces reloads but hoists them + leaves delay-slot nops the target fills (target is NOT volatile). (2) frame 0x20 not 0x18: target reserves an unused 8-byte stack local @0x10 (address-taken local — reproduced, but every code-free escape optimizes away and a visible escape corrupts the ((int (*)(void))func_80145EE8)(0) arg). Structure/order/values/callees all match; only the alias-driven reload chain + the phantom frame local remain. Family exemplar (~130 overlays). | `.run/backlog_drafts/func_80145CEC.c` | +| 845 | func_8016BCC0 | None | | None | failed | | won't compile standalone (loose-typing / missing decl) | `.run/backlog_drafts/func_8016BCC0.c` | diff --git a/docs/family-hseq.md b/docs/family-hseq.md index d9ba7b03a..2d7aad42e 100644 --- a/docs/family-hseq.md +++ b/docs/family-hseq.md @@ -2,13 +2,13 @@ > Generated by `tools/family_hseq.py` from the 138 overlay sigs + per-overlay src stubs. Ranked by TEMPLATABLE byte-weight (PURE+IMM members × nins × 4). The byte-gate is the arbiter. > -> **Scope: the 138 OVERLAYS only** (no main, no resident) · generated at HEAD `commit:1461` · stub set derived from `corpus.stubs` — the same oracle `progress.py` counts, so same-tree overlay totals agree by construction; compare digests only at the same HEAD. +> **Scope: the 138 OVERLAYS only** (no main, no resident) · generated at HEAD `commit:1464` · stub set derived from `corpus.stubs` — the same oracle `progress.py` counts, so same-tree overlay totals agree by construction; compare digests only at the same HEAD. -**Fleet (overlays):** 96.8% fn / 95.0% instr / 90.2% distinct-code matched. Unmatched: 11,274 instances / 659,985 ins (9,467 distinct classes). +**Fleet (overlays):** 96.8% fn / 95.0% instr / 90.3% distinct-code matched. Unmatched: 11,231 instances / 654,506 ins (9,424 distinct classes). -**Tail cross-check (Phase-25 close):** 7,355 tail fns / 370,451 ins → 417 h_seq families ≥2, **99 substantial (nins≥80) / 66,568 ins**. +**Tail cross-check (Phase-25 close):** 7,341 tail fns / 370,259 ins → 417 h_seq families ≥2, **99 substantial (nins≥80) / 66,568 ins**. -**Full frontier (all unmatched by h_seq):** 1979 target families (≥2 members or a matched sibling) + 3766 singletons (Step-D residue). Substantial: **345 families / 219,759 templatable ins**, 28 with a matched sibling (zero-crack). Substantial member classes: 1,385 PURE · 23 IMM · 6 STRUCT-excluded. +**Full frontier (all unmatched by h_seq):** 1974 target families (≥2 members or a matched sibling) + 3766 singletons (Step-D residue). Substantial: **340 families / 214,280 templatable ins**, 42 with a matched sibling (zero-crack). Substantial member classes: 1,342 PURE · 23 IMM · 6 STRUCT-excluded. ## Top substantial families (by templatable byte-weight) @@ -46,22 +46,22 @@ | 29 | 255 | 3 (3/0/0) | 3/3 | cross-address | PURE | 0 | · | 0x8018e9bc modal | 765 | | 30 | 254 | 3 (3/0/0) | 3/3 | cross-address | PURE | 0 | · | 0x80192768 modal | 762 | | 31 | 188 | 4 (4/0/0) | 1/4 | per-location | PURE | 134 | Y | 0x8016ab6c matched-ov077 | 752 | -| 32 | 107 | 7 (7/0/0) | 7/7 | cross-address | PURE | 0 | · | 0x8017ef54 modal | 749 | -| 33 | 187 | 4 (4/0/0) | 1/4 | per-location | PURE | 134 | · | 0x8013dd68 matched-ov077 | 748 | -| 34 | 248 | 3 (3/0/0) | 3/3 | cross-address | PURE | 0 | · | 0x8018e5dc modal | 744 | -| 35 | 186 | 4 (4/0/0) | 4/1 | cross-address | PURE | 0 | · | 0x801802ec modal | 744 | -| 36 | 147 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | Y | 0x8017ed5c modal | 735 | -| 37 | 181 | 4 (4/0/0) | 4/4 | cross-address | PURE | 0 | · | 0x8017d7c0 modal | 724 | -| 38 | 144 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | · | 0x80188778 modal | 720 | -| 39 | 710 | 1 (1/0/0) | 1/1 | per-location | PURE | 2 | Y | 0x80191c50 matched | 710 | -| 40 | 171 | 4 (4/0/0) | 4/4 | cross-address | PURE | 0 | · | 0x80183fe0 modal | 684 | -| 41 | 341 | 2 (2/0/0) | 1/2 | per-location | PURE | 0 | · | 0x80184bd8 modal | 682 | -| 42 | 85 | 8 (8/0/0) | 8/8 | cross-address | PURE | 1 | · | 0x801822e0 matched | 680 | -| 43 | 85 | 8 (8/0/0) | 8/8 | cross-address | PURE | 0 | · | 0x80182b90 modal | 680 | -| 44 | 113 | 6 (6/0/0) | 6/6 | cross-address | PURE | 0 | · | 0x80187320 modal | 678 | -| 45 | 226 | 3 (3/0/0) | 3/3 | cross-address | PURE | 0 | · | 0x80192f64 modal | 678 | -| 46 | 134 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | Y | 0x8017eb44 modal | 670 | -| 47 | 133 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | · | 0x80189ea0 modal | 665 | -| 48 | 110 | 6 (6/0/0) | 6/6 | cross-address | PURE | 0 | · | 0x80188b9c modal | 660 | -| 49 | 93 | 7 (7/0/0) | 2/7 | cross-address | PURE | 0 | · | 0x8017c6a0 modal | 651 | -| 50 | 93 | 7 (7/0/0) | 7/7 | cross-address | PURE | 0 | · | 0x8017fb10 modal | 651 | +| 32 | 187 | 4 (4/0/0) | 1/4 | per-location | PURE | 134 | · | 0x8013dd68 matched-ov077 | 748 | +| 33 | 147 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | Y | 0x8017ed5c modal | 735 | +| 34 | 181 | 4 (4/0/0) | 4/4 | cross-address | PURE | 0 | · | 0x8017d7c0 modal | 724 | +| 35 | 710 | 1 (1/0/0) | 1/1 | per-location | PURE | 2 | Y | 0x80191c50 matched | 710 | +| 36 | 341 | 2 (2/0/0) | 1/2 | per-location | PURE | 0 | · | 0x80184bd8 modal | 682 | +| 37 | 134 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | Y | 0x8017eb44 modal | 670 | +| 38 | 93 | 7 (7/0/0) | 2/7 | cross-address | PURE | 0 | · | 0x8017c6a0 modal | 651 | +| 39 | 108 | 6 (6/0/0) | 6/6 | cross-address | PURE | 0 | Y | 0x8017eeec modal | 648 | +| 40 | 107 | 6 (6/0/0) | 6/6 | cross-address | PURE | 1 | · | 0x8017ef54 matched | 642 | +| 41 | 320 | 2 (2/0/0) | 1/2 | per-location | PURE | 0 | · | 0x80181b00 modal | 640 | +| 42 | 317 | 2 (2/0/0) | 2/1 | cross-address | PURE | 0 | · | 0x8017fdf8 modal | 634 | +| 43 | 211 | 3 (3/0/0) | 3/3 | cross-address | PURE | 0 | · | 0x8018e8a0 modal | 633 | +| 44 | 207 | 3 (3/0/0) | 3/3 | cross-address | PURE | 2 | · | 0x801880ec matched | 621 | +| 45 | 124 | 5 (5/0/0) | 4/5 | cross-address | PURE | 0 | · | 0x8017defc modal | 620 | +| 46 | 154 | 4 (4/0/0) | 4/4 | cross-address | PURE | 0 | Y | 0x801844c8 modal | 616 | +| 47 | 203 | 3 (0/3/0) | 2/3 | cross-address | IMM | 7 | · | 0x8017e804 matched | 609 | +| 48 | 304 | 2 (2/0/0) | 1/2 | per-location | PURE | 0 | · | 0x80185ef8 modal | 608 | +| 49 | 101 | 6 (3/3/0) | 6/3 | cross-address | IMM | 0 | · | 0x8018de60 modal | 606 | +| 50 | 201 | 3 (3/0/0) | 2/3 | cross-address | PURE | 0 | Y | 0x80181be4 draft-ov077 | 603 | diff --git a/docs/progress.fleet.md b/docs/progress.fleet.md index 0a6a9017f..4274990f8 100644 --- a/docs/progress.fleet.md +++ b/docs/progress.fleet.md @@ -4,16 +4,16 @@ # cross-binary collapsible-byte leverage: docs/duplicates.cross.md. # THREE progress metrics (all matter — see the labels): -FLEET fn-count byte-ident: 341431 / 353717 = 96.53% (REAL+LINKED+empties; FUNCTION-count, ×134-inflated — one crack counts per overlay) -FLEET instr-weighted : 12425854 / 13160961 = 94.4% (shipped .text across main + resident + 138 overlays; the decomp.dev-DISPLAY number) -FLEET distinct-code(uniq): 5035626 / 5654184 = 89.1% (78021/87459 unique fns; the DISTINCT-RE number) +FLEET fn-count byte-ident: 341492 / 353717 = 96.54% (REAL+LINKED+empties; FUNCTION-count, ×134-inflated — one crack counts per overlay) +FLEET instr-weighted : 12432941 / 13160961 = 94.5% (shipped .text across main + resident + 138 overlays; the decomp.dev-DISPLAY number) +FLEET distinct-code(uniq): 5041771 / 5654184 = 89.2% (78072/87459 unique fns; the DISTINCT-RE number) MAIN game-code weighted : 436 / 79510 = 0.5% (INCLUDED in the fleet numbers above since 2026-07-22 — roadmap §1 metrics contract; LINKED-excluding Ghidra sig dated 2026-08-05; caveat is R34: no independent second oracle for a PS-X EXE, NOT drift) - (fleet EXCLUDING main, for continuity with pre-2026-07-22 readings: 12425418 / 13081451 = 95.0%) + (fleet EXCLUDING main, for continuity with pre-2026-07-22 readings: 12432505 / 13081451 = 95.0%) -FLEET REAL substantive : 339576 (of which dedup-shared 241439 via 1919 groups / 241513 instances) +FLEET REAL substantive : 339637 (of which dedup-shared 241439 via 1919 groups / 241513 instances) FLEET LINKED PsyQ objs : 959 FLEET NON_MATCHING : 7 (0 in any default build — G4) -FLEET INCLUDE_ASM stubs : 12279 +FLEET INCLUDE_ASM stubs : 12218 FLEET matchable : 353717 | binary | REAL | shared | LINKED | byte-ident | matchable | byte-ident % | @@ -37,14 +37,14 @@ FLEET matchable : 353717 | ov_SC02_005 | 2536 | 1747 | 0 | 2546 | 2927 | 87.0% | | ov_SC02_011 | 2624 | 1754 | 0 | 2635 | 2893 | 91.1% | | ov_SC02_015 | 2397 | 1753 | 0 | 2397 | 2414 | 99.3% | -| ov_SC02_016 | 2479 | 1754 | 0 | 2482 | 2545 | 97.5% | +| ov_SC02_016 | 2480 | 1754 | 0 | 2483 | 2545 | 97.6% | | ov_SC02_017 | 2548 | 1754 | 0 | 2556 | 2732 | 93.6% | | ov_SC02_021 | 2402 | 1753 | 0 | 2402 | 2437 | 98.6% | | ov_SC02_026 | 2500 | 1751 | 0 | 2506 | 2572 | 97.4% | | ov_SC02_027 | 2556 | 1751 | 0 | 2565 | 2692 | 95.3% | | ov_SC02_028 | 2561 | 1751 | 0 | 2571 | 2701 | 95.2% | | ov_SC02_031 | 2491 | 1752 | 0 | 2496 | 2562 | 97.4% | -| ov_SC02_035 | 2483 | 1751 | 0 | 2486 | 2520 | 98.7% | +| ov_SC02_035 | 2485 | 1751 | 0 | 2488 | 2520 | 98.7% | | ov_SC02_039 | 2392 | 1751 | 0 | 2392 | 2416 | 99.0% | | ov_SC02_041 | 2473 | 1751 | 0 | 2476 | 2561 | 96.7% | | ov_SC03_001 | 2667 | 1752 | 0 | 2684 | 2869 | 93.6% | @@ -65,24 +65,24 @@ FLEET matchable : 353717 | ov_SC03_030 | 2415 | 1756 | 0 | 2417 | 2495 | 96.9% | | ov_SC03_031 | 2444 | 1751 | 0 | 2447 | 2514 | 97.3% | | ov_SC03_089 | 2510 | 1756 | 0 | 2517 | 2581 | 97.5% | -| ov_SC03_090 | 2523 | 1756 | 0 | 2531 | 2625 | 96.4% | -| ov_SC03_091 | 2537 | 1751 | 0 | 2545 | 2640 | 96.4% | -| ov_SC03_092 | 2502 | 1756 | 0 | 2514 | 2587 | 97.2% | +| ov_SC03_090 | 2525 | 1756 | 0 | 2533 | 2625 | 96.5% | +| ov_SC03_091 | 2539 | 1751 | 0 | 2547 | 2640 | 96.5% | +| ov_SC03_092 | 2503 | 1756 | 0 | 2515 | 2587 | 97.2% | | ov_SC03_093 | 2513 | 1751 | 0 | 2517 | 2563 | 98.2% | -| ov_SC03_094 | 2500 | 1751 | 0 | 2506 | 2577 | 97.2% | +| ov_SC03_094 | 2502 | 1751 | 0 | 2508 | 2577 | 97.3% | | ov_SC03_095 | 2429 | 1751 | 0 | 2432 | 2474 | 98.3% | | ov_SC03_096 | 2426 | 1751 | 0 | 2429 | 2465 | 98.5% | | ov_SC03_097 | 2523 | 1751 | 0 | 2530 | 2603 | 97.2% | -| ov_SC03_098 | 2505 | 1751 | 0 | 2508 | 2541 | 98.7% | +| ov_SC03_098 | 2507 | 1751 | 0 | 2510 | 2541 | 98.8% | | ov_SC03_099 | 2483 | 1751 | 0 | 2486 | 2504 | 99.3% | | ov_SC03_100 | 2518 | 1751 | 0 | 2522 | 2539 | 99.3% | | ov_SC03_101 | 2480 | 1756 | 0 | 2484 | 2528 | 98.3% | | ov_SC03_102 | 2467 | 1751 | 0 | 2470 | 2492 | 99.1% | | ov_SC03_103 | 2491 | 1753 | 0 | 2494 | 2510 | 99.4% | | ov_SC03_104 | 2538 | 1756 | 0 | 2545 | 2616 | 97.3% | -| ov_SC03_105 | 2445 | 1752 | 0 | 2452 | 2597 | 94.4% | +| ov_SC03_105 | 2446 | 1752 | 0 | 2453 | 2597 | 94.5% | | ov_SC03_108 | 2397 | 1751 | 0 | 2397 | 2443 | 98.1% | -| ov_SC03_109 | 2404 | 1751 | 0 | 2406 | 2424 | 99.3% | +| ov_SC03_109 | 2405 | 1751 | 0 | 2407 | 2424 | 99.3% | | ov_SC03_110 | 2438 | 1751 | 0 | 2438 | 2468 | 98.8% | | ov_SC03_111 | 2469 | 1751 | 0 | 2472 | 2510 | 98.5% | | ov_SC03_112 | 2434 | 1753 | 0 | 2436 | 2526 | 96.4% | @@ -94,65 +94,65 @@ FLEET matchable : 353717 | ov_SC03_118 | 2540 | 1776 | 0 | 2541 | 2685 | 94.6% | | ov_SC03_119 | 2537 | 1776 | 0 | 2538 | 2685 | 94.5% | | ov_SC03_121 | 2400 | 1751 | 0 | 2403 | 2459 | 97.7% | -| ov_SC03_124 | 2572 | 1747 | 0 | 2592 | 2741 | 94.6% | +| ov_SC03_124 | 2574 | 1747 | 0 | 2594 | 2741 | 94.6% | | ov_SC03_125 | 2525 | 1751 | 0 | 2537 | 2588 | 98.0% | | ov_SC03_126 | 2396 | 1753 | 0 | 2396 | 2423 | 98.9% | -| ov_SC04_000 | 2470 | 1755 | 0 | 2479 | 2546 | 97.4% | -| ov_SC04_002 | 2499 | 1751 | 0 | 2503 | 2636 | 95.0% | +| ov_SC04_000 | 2471 | 1755 | 0 | 2480 | 2546 | 97.4% | +| ov_SC04_002 | 2501 | 1751 | 0 | 2505 | 2636 | 95.0% | | ov_SC04_003 | 2435 | 1751 | 0 | 2439 | 2502 | 97.5% | | ov_SC04_004 | 2467 | 1751 | 0 | 2469 | 2558 | 96.5% | -| ov_SC04_005 | 2494 | 1751 | 0 | 2500 | 2612 | 95.7% | +| ov_SC04_005 | 2496 | 1751 | 0 | 2502 | 2612 | 95.8% | | ov_SC04_006 | 2427 | 1751 | 0 | 2429 | 2454 | 99.0% | -| ov_SC04_007 | 2488 | 1751 | 0 | 2492 | 2569 | 97.0% | +| ov_SC04_007 | 2490 | 1751 | 0 | 2494 | 2569 | 97.1% | | ov_SC04_008 | 2397 | 1751 | 0 | 2397 | 2415 | 99.3% | -| ov_SC04_009 | 2423 | 1751 | 0 | 2426 | 2441 | 99.4% | +| ov_SC04_009 | 2424 | 1751 | 0 | 2427 | 2441 | 99.4% | | ov_SC04_010 | 2399 | 1751 | 0 | 2400 | 2419 | 99.2% | -| ov_SC04_011 | 2512 | 1756 | 0 | 2518 | 2803 | 89.8% | +| ov_SC04_011 | 2513 | 1756 | 0 | 2519 | 2803 | 89.9% | | ov_SC04_012 | 2394 | 1751 | 0 | 2395 | 2420 | 99.0% | -| ov_SC04_015 | 2529 | 1752 | 0 | 2540 | 2611 | 97.3% | +| ov_SC04_015 | 2530 | 1752 | 0 | 2541 | 2611 | 97.3% | | ov_SC04_016 | 2398 | 1751 | 0 | 2400 | 2440 | 98.4% | -| ov_SC04_018 | 2668 | 1788 | 0 | 2668 | 2857 | 93.4% | -| ov_SC04_019 | 2668 | 1788 | 0 | 2668 | 2857 | 93.4% | +| ov_SC04_018 | 2670 | 1788 | 0 | 2670 | 2857 | 93.5% | +| ov_SC04_019 | 2670 | 1788 | 0 | 2670 | 2857 | 93.5% | | ov_SC04_020 | 2511 | 1751 | 0 | 2523 | 2567 | 98.3% | | ov_SC04_021 | 2396 | 1753 | 0 | 2396 | 2423 | 98.9% | | ov_SC05_000 | 2403 | 1755 | 0 | 2406 | 2422 | 99.3% | | ov_SC05_001 | 2475 | 1751 | 0 | 2480 | 2574 | 96.3% | | ov_SC05_002 | 2427 | 1751 | 0 | 2430 | 2442 | 99.5% | -| ov_SC05_003 | 2409 | 1751 | 0 | 2410 | 2481 | 97.1% | +| ov_SC05_003 | 2410 | 1751 | 0 | 2411 | 2481 | 97.2% | | ov_SC05_004 | 2420 | 1751 | 0 | 2422 | 2464 | 98.3% | -| ov_SC05_005 | 2434 | 1756 | 0 | 2435 | 2491 | 97.8% | +| ov_SC05_005 | 2435 | 1756 | 0 | 2436 | 2491 | 97.8% | | ov_SC05_006 | 2419 | 1751 | 0 | 2419 | 2430 | 99.5% | | ov_SC05_007 | 2428 | 1751 | 0 | 2433 | 2482 | 98.0% | | ov_SC05_008 | 2439 | 1751 | 0 | 2441 | 2543 | 96.0% | -| ov_SC05_009 | 2405 | 1751 | 0 | 2409 | 2438 | 98.8% | -| ov_SC05_010 | 2445 | 1752 | 0 | 2449 | 2588 | 94.6% | +| ov_SC05_009 | 2406 | 1751 | 0 | 2410 | 2438 | 98.9% | +| ov_SC05_010 | 2446 | 1752 | 0 | 2450 | 2588 | 94.7% | | ov_SC05_011 | 2393 | 1751 | 0 | 2394 | 2409 | 99.4% | -| ov_SC05_017 | 2644 | 1748 | 0 | 2655 | 2842 | 93.4% | +| ov_SC05_017 | 2646 | 1748 | 0 | 2657 | 2842 | 93.5% | | ov_SC05_018 | 2543 | 1751 | 0 | 2556 | 2673 | 95.6% | | ov_SC05_019 | 2396 | 1753 | 0 | 2396 | 2423 | 98.9% | | ov_SC06_000 | 2525 | 1760 | 0 | 2528 | 2691 | 93.9% | | ov_SC06_006 | 2420 | 1751 | 0 | 2421 | 2511 | 96.4% | -| ov_SC06_008 | 2484 | 1753 | 0 | 2490 | 2542 | 98.0% | -| ov_SC06_010 | 2454 | 1751 | 0 | 2459 | 2517 | 97.7% | +| ov_SC06_008 | 2485 | 1753 | 0 | 2491 | 2542 | 98.0% | +| ov_SC06_010 | 2457 | 1751 | 0 | 2462 | 2517 | 97.8% | | ov_SC06_011 | 2412 | 1751 | 0 | 2416 | 2468 | 97.9% | | ov_SC06_013 | 2402 | 1751 | 0 | 2403 | 2425 | 99.1% | | ov_SC06_014 | 2413 | 1751 | 0 | 2415 | 2453 | 98.5% | | ov_SC06_015 | 2407 | 1751 | 0 | 2407 | 2421 | 99.4% | | ov_SC06_016 | 2449 | 1752 | 0 | 2451 | 2549 | 96.2% | -| ov_SC06_018 | 2495 | 1753 | 0 | 2502 | 2665 | 93.9% | -| ov_SC06_020 | 2442 | 1753 | 0 | 2443 | 2518 | 97.0% | -| ov_SC06_022 | 2474 | 1751 | 0 | 2482 | 2642 | 93.9% | -| ov_SC06_024 | 2494 | 1751 | 0 | 2500 | 2667 | 93.7% | +| ov_SC06_018 | 2497 | 1753 | 0 | 2504 | 2665 | 94.0% | +| ov_SC06_020 | 2443 | 1753 | 0 | 2444 | 2518 | 97.1% | +| ov_SC06_022 | 2478 | 1751 | 0 | 2486 | 2642 | 94.1% | +| ov_SC06_024 | 2498 | 1751 | 0 | 2504 | 2667 | 93.9% | | ov_SC06_025 | 2449 | 1751 | 0 | 2454 | 2572 | 95.4% | | ov_SC06_027 | 2388 | 1751 | 0 | 2389 | 2408 | 99.2% | -| ov_SC06_029 | 2473 | 1752 | 0 | 2485 | 2662 | 93.4% | +| ov_SC06_029 | 2474 | 1752 | 0 | 2486 | 2662 | 93.4% | | ov_SC06_030 | 2410 | 1752 | 0 | 2410 | 2456 | 98.1% | | ov_SC06_032 | 2484 | 1752 | 0 | 2491 | 2658 | 93.7% | -| ov_SC06_033 | 2479 | 1752 | 0 | 2486 | 2631 | 94.5% | +| ov_SC06_033 | 2484 | 1752 | 0 | 2491 | 2631 | 94.7% | | ov_SC07_000 | 2429 | 1755 | 0 | 2431 | 2521 | 96.4% | | ov_SC07_001 | 2401 | 1751 | 0 | 2403 | 2454 | 97.9% | -| ov_SC07_002 | 2456 | 1752 | 0 | 2460 | 2579 | 95.4% | -| ov_SC07_006 | 2318 | 1575 | 0 | 2398 | 2455 | 97.7% | +| ov_SC07_002 | 2457 | 1752 | 0 | 2461 | 2579 | 95.4% | +| ov_SC07_006 | 2321 | 1575 | 0 | 2401 | 2455 | 97.8% | | ov_SC07_007 | 2334 | 1607 | 0 | 2418 | 2612 | 92.6% | | ov_SC07_008 | 2382 | 1751 | 0 | 2382 | 2386 | 99.8% | | ov_SC07_009 | 2394 | 1751 | 0 | 2396 | 2430 | 98.6% | diff --git a/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c b/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c index 2fddb3641..a99cc8989 100644 --- a/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c +++ b/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c @@ -4265,7 +4265,51 @@ void func_80182E34(void *a0) { INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_8017DC70", func_80182E70); -INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_8017DC70", func_80182FE8); + +extern s32 func_80012C6C(s32 a0, s32 a1, s32 a2); +extern s32 func_80012ABC(s32 a0, s32 a1, s32 a2); +extern void func_80049CAC(s32 a0, s32 a1); +extern void func_8012F14C(s32); + + +void func_80182FE8(s32 param_1) { + + extern s16 D_80126940; + extern s16 D_80126942; + extern s16 D_80126944; + MATRIX m1; + SVECTOR svec_in; + SVECTOR svec_out; + s16 *p; + + *(s32 *)(param_1 + 0x8) = (s16)func_80012C6C((s32)*(s16 *)(param_1 + 0x8), (s32)*(s16 *)(param_1 + 0xC), 4); + *(s32 *)(param_1 + 0x10) = (s16)func_80012C6C((s32)*(s16 *)(param_1 + 0x10), (s32)*(s16 *)(param_1 + 0x14), 4); + *(s16 *)(param_1 + 0x18) = func_80012ABC((s32)*(s16 *)(param_1 + 0x18), (s32)*(s16 *)(param_1 + 0x20), 4); + *(s16 *)(param_1 + 0x1A) = func_80012ABC((s32)*(s16 *)(param_1 + 0x1A), (s32)*(s16 *)(param_1 + 0x22), 4); + *(s16 *)(param_1 + 0x1C) = func_80012ABC((s32)*(s16 *)(param_1 + 0x1C), (s32)*(s16 *)(param_1 + 0x24), 4); + *(s16 *)(param_1 + 0x28) = func_80012C6C((s32)*(s16 *)(param_1 + 0x28), (s32)*(s16 *)(param_1 + 0x2E), 0x10); + *(s16 *)(param_1 + 0x2A) = func_80012C6C((s32)*(s16 *)(param_1 + 0x2A), (s32)*(s16 *)(param_1 + 0x30), 0x10); + *(s16 *)(param_1 + 0x2C) = func_80012C6C((s32)*(s16 *)(param_1 + 0x2C), (s32)*(s16 *)(param_1 + 0x32), 0x10); + + p = &D_80126940; + *(s32 *)(param_1 + 0x48) = (s32)*(s16 *)(param_1 + 0x28) + (s32)*p; + *(s32 *)(param_1 + 0x4C) = (s32)*(s16 *)(param_1 + 0x2A) + (s32)D_80126942; + *(s32 *)(param_1 + 0x50) = (s32)*(s16 *)(param_1 + 0x2C) + (s32)D_80126944; + func_80049CAC(param_1 + 0x18, (s32)&m1); + + m1.t[0] = *(s16 *)(param_1 + 0x28) + *p; + m1.t[1] = *(s16 *)(param_1 + 0x2A) + D_80126942; + m1.t[2] = *(s16 *)(param_1 + 0x2C) + D_80126944; + svec_in.vx = 0; + svec_in.vy = 0; + svec_in.vz = *(s32 *)(param_1 + 0x10); + ((void (*)(s32, s32, s32))func_8012F14C)((s32)&m1, (s32)&svec_in, (s32)&svec_out); + + *(s32 *)(param_1 + 0x3C) = (s32)svec_out.vx; + *(s32 *)(param_1 + 0x40) = (s32)svec_out.vy; + *(s32 *)(param_1 + 0x44) = (s32)svec_out.vz; +} + extern void (*D_801A41D8[])(void); diff --git a/src/ov_SC02_035/ov_SC02_035_jr_8017BEBC.c b/src/ov_SC02_035/ov_SC02_035_jr_8017BEBC.c index fb53e0bfc..627932782 100644 --- a/src/ov_SC02_035/ov_SC02_035_jr_8017BEBC.c +++ b/src/ov_SC02_035/ov_SC02_035_jr_8017BEBC.c @@ -4683,7 +4683,84 @@ INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_8017F8A INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_8017F918); -INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_8017F96C); + +extern void func_8012BE54(s32 a0); +extern void func_8012CBCC(s32 a0); +extern void func_8012E88C(s32); +extern void func_8012B21C(void *a0); +extern s32 func_8004787C(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); + +void func_8017F96C(s32 a0) { + register s32 state __asm__("$16"); /* $s0 */ + register s32 ent __asm__("$17"); /* $s1 */ + s32 sub; + s32 t; + s32 v; + s32 cnt; + + ent = a0; + __asm__ volatile("" ::: "$4"); + state = *(u16 *)(ent + 0x34); + + switch (state) { + case 0: + if (0x10000 < ((s32 (*)(s32))func_8012BE54)(ent)) { + return; + } + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + ((void (*)(u8 *))func_8012E88C)((u8 *)ent); + func_8012B21C((void *)ent); + return; + case 1: + if ((((s32 (*)(s32))func_8012CBCC)(ent) & 0x2000) == 0) { + return; + } + *(s32 *)(ent + 0x1C) = state; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8002D4C8(0x703, 0); + /* fallthrough */ + case 2: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + v = (t * 0x1c00 >> 12) + 0x400; + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = 0x3000 - (t * 0x2800 >> 12); + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (cnt < 9) { + return; + } + *(s32 *)(ent + 0x1C) = 1; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + return; + case 3: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + { + register s32 lo __asm__("$3"); + lo = (t << 12) >> 12; + v = 0x2000 - lo; + } + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = ((t * 0x800) >> 12) + 0x800; + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (8 < cnt) { + *(u16 *)(ent + 2) = 1; + } + return; + } +} + INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_8017FB1C); @@ -4963,7 +5040,50 @@ INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_801808F INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_80180948); -INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_801809E4); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_801809E4(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC02_035/nonmatchings/ov_SC02_035_jr_8017BEBC", func_80180B38); diff --git a/src/ov_SC03_090/ov_SC03_090_jr_8017CA80.c b/src/ov_SC03_090/ov_SC03_090_jr_8017CA80.c index ab085a981..11300f2a2 100644 --- a/src/ov_SC03_090/ov_SC03_090_jr_8017CA80.c +++ b/src/ov_SC03_090/ov_SC03_090_jr_8017CA80.c @@ -6158,7 +6158,84 @@ INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80185FA INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80186020); -INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80186074); + +extern void func_8012BE54(s32 a0); +extern void func_8012CBCC(s32 a0); +extern void func_8012E88C(u8 *a0); +extern void func_8012B21C(void *a0); +extern s32 func_8004787C(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); + +void func_80186074(s32 a0) { + register s32 state __asm__("$16"); /* $s0 */ + register s32 ent __asm__("$17"); /* $s1 */ + s32 sub; + s32 t; + s32 v; + s32 cnt; + + ent = a0; + __asm__ volatile("" ::: "$4"); + state = *(u16 *)(ent + 0x34); + + switch (state) { + case 0: + if (0x10000 < ((s32 (*)(s32))func_8012BE54)(ent)) { + return; + } + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8012E88C((u8 *)ent); + func_8012B21C((void *)ent); + return; + case 1: + if ((((s32 (*)(s32))func_8012CBCC)(ent) & 0x2000) == 0) { + return; + } + *(s32 *)(ent + 0x1C) = state; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8002D4C8(0x703, 0); + /* fallthrough */ + case 2: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + v = (t * 0x1c00 >> 12) + 0x400; + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = 0x3000 - (t * 0x2800 >> 12); + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (cnt < 9) { + return; + } + *(s32 *)(ent + 0x1C) = 1; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + return; + case 3: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + { + register s32 lo __asm__("$3"); + lo = (t << 12) >> 12; + v = 0x2000 - lo; + } + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = ((t * 0x800) >> 12) + 0x800; + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (8 < cnt) { + *(u16 *)(ent + 2) = 1; + } + return; + } +} + INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80186224); @@ -6436,7 +6513,50 @@ INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80186FF INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80187050); -INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_801870EC); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_801870EC(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC03_090/nonmatchings/ov_SC03_090_jr_8017CA80", func_80187240); diff --git a/src/ov_SC03_091/ov_SC03_091_jr_80182268.c b/src/ov_SC03_091/ov_SC03_091_jr_80182268.c index f8177c842..5210303f5 100644 --- a/src/ov_SC03_091/ov_SC03_091_jr_80182268.c +++ b/src/ov_SC03_091/ov_SC03_091_jr_80182268.c @@ -4669,7 +4669,84 @@ INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_80186E5 INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_80186EC8); -INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_80186F1C); + +extern void func_8012BE54(s32 a0); +extern void func_8012CBCC(s32 a0); +extern void func_8012E88C(u8 *a0); +extern void func_8012B21C(void *a0); +extern s32 func_8004787C(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); + +void func_80186F1C(s32 a0) { + register s32 state __asm__("$16"); /* $s0 */ + register s32 ent __asm__("$17"); /* $s1 */ + s32 sub; + s32 t; + s32 v; + s32 cnt; + + ent = a0; + __asm__ volatile("" ::: "$4"); + state = *(u16 *)(ent + 0x34); + + switch (state) { + case 0: + if (0x10000 < ((s32 (*)(s32))func_8012BE54)(ent)) { + return; + } + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8012E88C((u8 *)ent); + func_8012B21C((void *)ent); + return; + case 1: + if ((((s32 (*)(s32))func_8012CBCC)(ent) & 0x2000) == 0) { + return; + } + *(s32 *)(ent + 0x1C) = state; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8002D4C8(0x703, 0); + /* fallthrough */ + case 2: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + v = (t * 0x1c00 >> 12) + 0x400; + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = 0x3000 - (t * 0x2800 >> 12); + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (cnt < 9) { + return; + } + *(s32 *)(ent + 0x1C) = 1; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + return; + case 3: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + { + register s32 lo __asm__("$3"); + lo = (t << 12) >> 12; + v = 0x2000 - lo; + } + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = ((t * 0x800) >> 12) + 0x800; + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (8 < cnt) { + *(u16 *)(ent + 2) = 1; + } + return; + } +} + INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_801870CC); @@ -4947,7 +5024,50 @@ INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_80187EA INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_80187EF8); -INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_80187F94); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_80187F94(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC03_091/nonmatchings/ov_SC03_091_jr_80182268", func_801880E8); diff --git a/src/ov_SC03_092/ov_SC03_092_jr_80181694.c b/src/ov_SC03_092/ov_SC03_092_jr_80181694.c index 3cdcb1071..9287be416 100644 --- a/src/ov_SC03_092/ov_SC03_092_jr_80181694.c +++ b/src/ov_SC03_092/ov_SC03_092_jr_80181694.c @@ -4030,7 +4030,6 @@ void func_80183764(void *a0) { } -extern s32 *D_80126B78; extern u8 D_801B0200[]; extern s32 func_8012BDBC(s32 a0, s32 a1); extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); @@ -4066,6 +4065,10 @@ s32 aF8018A224() __asm__("func_801837D4"); s32 aF8018A224(param_1) void *param_1; { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 *D_80126B78; s32 *m; s32 obj; s32 sv0[2]; @@ -4211,7 +4214,101 @@ extern void func_800296F8(void *a0); } -INCLUDE_ASM("asm/ov_SC03_092/nonmatchings/ov_SC03_092_jr_80181694", func_80183C04); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_80172710(void); +extern s32 func_80178BF8(); +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §71 sibling: identical shape to func_8018F390 (same TU, this file, D_80126B78/RotTransSV/ + * func_80135888/func_8012BDBC/func_80178BF8/func_80172710 idiom) already MATCHED -- only the + * per-overlay data symbol (D_801B0358 vs D_801E33F0) differs. §37 asm-label alias avoids the + * `conflicting types` clash with the fleet's `extern void func_80183C04(void);` used elsewhere + * in this TU as a state-handler function pointer. */ + +s32 aF801904E0() __asm__("func_80183C04"); + +s32 aF801904E0(param_1) + void *param_1; +{ + + extern s32 *D_80126B78; + extern u8 D_801B0358[]; + MATRIX m; + s32 obj; + s32 sv0[2]; + s32 sv1[2]; + s32 flag; + + obj = *(s32 *)((s32)param_1 + 0x64); + m = *(MATRIX *)((u8 *)D_80126B78 + 0x34); + + gte_SetRotMatrix(&m); + gte_SetTransMatrix(&m); + + RotTransSV(D_801B0358, sv0, &flag); + RotTransSV(D_801B0358 + 8, sv1, &flag); + + if (func_80135888(*(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x20), + *(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x58), + (s32)sv0, (s32)sv1) == 0) { + return 0; + } + if (func_8012BDBC(obj, 0x300) == 0) { + return 0; + } + *(s16 *)(obj + 0x2) = 3; + func_80178BF8(); + return (s32)func_80172710; +} + extern s32 func_8012C194(void); diff --git a/src/ov_SC03_094/ov_SC03_094_jr_8017BEBC.c b/src/ov_SC03_094/ov_SC03_094_jr_8017BEBC.c index ae2f1384d..cbee4680f 100644 --- a/src/ov_SC03_094/ov_SC03_094_jr_8017BEBC.c +++ b/src/ov_SC03_094/ov_SC03_094_jr_8017BEBC.c @@ -4837,7 +4837,84 @@ INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80180C2 INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80180CA0); -INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80180CF4); + +extern void func_8012BE54(s32 a0); +extern void func_8012CBCC(s32 a0); +extern void func_8012E88C(s32); +extern void func_8012B21C(void *a0); +extern s32 func_8004787C(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); + +void func_80180CF4(s32 a0) { + register s32 state __asm__("$16"); /* $s0 */ + register s32 ent __asm__("$17"); /* $s1 */ + s32 sub; + s32 t; + s32 v; + s32 cnt; + + ent = a0; + __asm__ volatile("" ::: "$4"); + state = *(u16 *)(ent + 0x34); + + switch (state) { + case 0: + if (0x10000 < ((s32 (*)(s32))func_8012BE54)(ent)) { + return; + } + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + ((void (*)(u8 *))func_8012E88C)((u8 *)ent); + func_8012B21C((void *)ent); + return; + case 1: + if ((((s32 (*)(s32))func_8012CBCC)(ent) & 0x2000) == 0) { + return; + } + *(s32 *)(ent + 0x1C) = state; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8002D4C8(0x703, 0); + /* fallthrough */ + case 2: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + v = (t * 0x1c00 >> 12) + 0x400; + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = 0x3000 - (t * 0x2800 >> 12); + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (cnt < 9) { + return; + } + *(s32 *)(ent + 0x1C) = 1; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + return; + case 3: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + { + register s32 lo __asm__("$3"); + lo = (t << 12) >> 12; + v = 0x2000 - lo; + } + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = ((t * 0x800) >> 12) + 0x800; + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (8 < cnt) { + *(u16 *)(ent + 2) = 1; + } + return; + } +} + INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80180EA4); @@ -5116,7 +5193,50 @@ INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80181C7 INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80181CD0); -INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80181D6C); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_80181D6C(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC03_094/nonmatchings/ov_SC03_094_jr_8017BEBC", func_80181EC0); diff --git a/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c b/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c index 2df7dbae3..054cc759d 100644 --- a/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c +++ b/src/ov_SC03_098/ov_SC03_098_jr_8017D898.c @@ -4773,7 +4773,84 @@ INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_8018143 INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_801814A8); -INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_801814FC); + +extern void func_8012BE54(s32 a0); +extern void func_8012CBCC(s32 a0); +extern void func_8012E88C(u8 *a0); +extern void func_8012B21C(void *a0); +extern s32 func_8004787C(s32 a0); +extern void func_8002D4C8(s32 a0, s32 a1); + +void func_801814FC(s32 a0) { + register s32 state __asm__("$16"); /* $s0 */ + register s32 ent __asm__("$17"); /* $s1 */ + s32 sub; + s32 t; + s32 v; + s32 cnt; + + ent = a0; + __asm__ volatile("" ::: "$4"); + state = *(u16 *)(ent + 0x34); + + switch (state) { + case 0: + if (0x10000 < ((s32 (*)(s32))func_8012BE54)(ent)) { + return; + } + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8012E88C((u8 *)ent); + func_8012B21C((void *)ent); + return; + case 1: + if ((((s32 (*)(s32))func_8012CBCC)(ent) & 0x2000) == 0) { + return; + } + *(s32 *)(ent + 0x1C) = state; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + func_8002D4C8(0x703, 0); + /* fallthrough */ + case 2: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + v = (t * 0x1c00 >> 12) + 0x400; + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = 0x3000 - (t * 0x2800 >> 12); + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (cnt < 9) { + return; + } + *(s32 *)(ent + 0x1C) = 1; + *(u16 *)(ent + 0x34) = *(u16 *)(ent + 0x34) + 1; + return; + case 3: + sub = *(s32 *)(ent + 0x20); + t = func_8004787C(*(s32 *)(ent + 0x1C) << 7); + { + register s32 lo __asm__("$3"); + lo = (t << 12) >> 12; + v = 0x2000 - lo; + } + *(s16 *)(sub + 0x1C) = v; + *(s16 *)(sub + 0x18) = v; + { + s32 w = ((t * 0x800) >> 12) + 0x800; + *(s16 *)(sub + 0x1A) = w; + } + cnt = *(s32 *)(ent + 0x1C) + 1; + *(s32 *)(ent + 0x1C) = cnt; + if (8 < cnt) { + *(u16 *)(ent + 2) = 1; + } + return; + } +} + INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_801816AC); @@ -5051,7 +5128,50 @@ INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_8018248 INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_801824D8); -INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_80182574); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_80182574(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC03_098/nonmatchings/ov_SC03_098_jr_8017D898", func_801826C8); diff --git a/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c b/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c index 2b299be90..13b5266fd 100644 --- a/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c +++ b/src/ov_SC03_105/ov_SC03_105_jr_8017C8D0.c @@ -3182,7 +3182,67 @@ void func_8017D7B0(void *a0) { } -INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_8017D7EC); + + +extern s32 rand(void); + +typedef struct { + u16 f0; + u16 f2; + u16 f4; + u16 f6; + u16 f8; + u16 fA; + s32 fC; + s32 f10; + s32 f14; + s32 f18; +} SubRec_801EB5C8_8017D7EC; /* 0x1C */ + +typedef struct { + u16 g0; + u16 g2; + s32 g4; + s32 g8; + s32 gC; + SubRec_801EB5C8_8017D7EC subs[16]; +} GroupRec_801EB5C8_8017D7EC; /* 0x1D0 */ + + +void func_8017D7EC(s32 param_1) +{ + + extern GroupRec_801EB5C8_8017D7EC D_801B9708[8]; + s32 i, j; + GroupRec_801EB5C8_8017D7EC *grp; + SubRec_801EB5C8_8017D7EC *sub; + + for (i = 0; i < 8; i++) { + grp = &D_801B9708[i]; + grp->g0 = 0; + grp->g2 = i << 9; + grp->gC = (rand() & 0xF) << 16; + grp->g4 = ((rand() & 0xF) << 15) + 0x10000; + grp->g8 = ((rand() & 0xF) << 12) + 0x8000; + + for (j = 0; j < 16; j++) { + sub = &grp->subs[j]; + sub->f0 = 0; + sub->f2 = (rand() & 3) + 4; + sub->f8 = (j << 8) + (rand() & 0xF) * 56; + sub->fA = (rand() & 0xF) << 8; + sub->f14 = (rand() & 0xF) << 13; + sub->fC = ((rand() & 0xF) << 14) + 0x10000; + sub->f10 = ((rand() & 0xF) << 12) + 0x8000; + sub->f4 = 0x200; + sub->f6 = (rand() & 0xF) << 4; + sub->f18 = ((rand() & 3) << 5) + 0x40; + } + } + + *(u16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC03_105/nonmatchings/ov_SC03_105_jr_8017C8D0", func_8017D994); diff --git a/src/ov_SC03_109/ov_SC03_109_jr_8017C180.c b/src/ov_SC03_109/ov_SC03_109_jr_8017C180.c index a5e5daef3..befa222e5 100644 --- a/src/ov_SC03_109/ov_SC03_109_jr_8017C180.c +++ b/src/ov_SC03_109/ov_SC03_109_jr_8017C180.c @@ -76,7 +76,6 @@ extern s32 func_80146128(void); extern void func_80146360(void); extern void func_801463A0(); extern void func_8014607C(void); -extern s32 *D_80126B78; extern u8 D_80078EC1; extern s32 D_80078EC8; extern s32 D_80126B9C; @@ -3638,7 +3637,101 @@ extern void func_800296F8(void); } -INCLUDE_ASM("asm/ov_SC03_109/nonmatchings/ov_SC03_109_jr_8017C180", func_8017E1AC); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_80172710(void); +extern s32 func_80178BF8(); +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §71 sibling: identical shape to func_8018F390 (same TU, this file, D_80126B78/RotTransSV/ + * func_80135888/func_8012BDBC/func_80178BF8/func_80172710 idiom) already MATCHED -- only the + * per-overlay data symbol (D_80197290 vs D_801E33F0) differs. §37 asm-label alias avoids the + * `conflicting types` clash with the fleet's `extern void func_8017E1AC(void);` used elsewhere + * in this TU as a state-handler function pointer. */ + +s32 aF801904E0() __asm__("func_8017E1AC"); + +s32 aF801904E0(param_1) + void *param_1; +{ + + extern s32 *D_80126B78; + extern u8 D_80197290[]; + MATRIX m; + s32 obj; + s32 sv0[2]; + s32 sv1[2]; + s32 flag; + + obj = *(s32 *)((s32)param_1 + 0x64); + m = *(MATRIX *)((u8 *)D_80126B78 + 0x34); + + gte_SetRotMatrix(&m); + gte_SetTransMatrix(&m); + + RotTransSV(D_80197290, sv0, &flag); + RotTransSV(D_80197290 + 8, sv1, &flag); + + if (func_80135888(*(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x20), + *(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x58), + (s32)sv0, (s32)sv1) == 0) { + return 0; + } + if (func_8012BDBC(obj, 0x300) == 0) { + return 0; + } + *(s16 *)(obj + 0x2) = 3; + func_80178BF8(); + return (s32)func_80172710; +} + diff --git a/src/ov_SC03_124/ov_SC03_124_jr_8017AE2C.c b/src/ov_SC03_124/ov_SC03_124_jr_8017AE2C.c index 883feac87..4f0b3a6e0 100644 --- a/src/ov_SC03_124/ov_SC03_124_jr_8017AE2C.c +++ b/src/ov_SC03_124/ov_SC03_124_jr_8017AE2C.c @@ -5594,7 +5594,99 @@ void func_80182C04(void *a0) { void func_80182C40(void) { } -INCLUDE_ASM("asm/ov_SC03_124/nonmatchings/ov_SC03_124_jr_8017AE2C", func_80182C48); + +extern s32 func_8012BEE8(s32 a0); +extern s32 rand(void); + +void func_80182C48(s32 param_1) { + s32 uVar1; + s32 iVar2; + register s32 iVar3 __asm__("$3"); + register s32 iVar4 __asm__("$16"); + u32 uVar3; + + uVar1 = *(u16 *)(param_1 + 0x34); + if (uVar1 == 1) { + goto case1; + } + if (uVar1 < 2) { + if (uVar1 == 0) { + goto case0; + } + return; + } + if (uVar1 == 2) { + goto case2; + } + if (uVar1 != 3) { + return; + } + goto case3; + +case0: + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + iVar4 = uVar3 & 0x3fff; + iVar4 = iVar4 + 0x7800; + uVar3 = rand(); + if ((uVar3 & 1) == 0) { + iVar4 = -iVar4; + } + *(s32 *)(param_1 + 0xe0) = iVar4; + *(s32 *)(param_1 + 0xe4) = 0; + return; + +case1: + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + uVar3 = uVar3 & 0x3f; + goto tail; + +case2: + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + *(s32 *)(param_1 + 0xe4); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0xe0) = -*(s32 *)(param_1 + 0xe0); + return; + +case3: + __asm__ __volatile__("" ::: "memory"); + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = 0; + uVar3 = rand(); + uVar3 = uVar3 & 0xff; + +tail: + *(u32 *)(param_1 + 0x1c) = uVar3 + 0x40; +} + extern void (*D_801906E0[])(void); diff --git a/src/ov_SC03_124/ov_SC03_124_jr_80187010.c b/src/ov_SC03_124/ov_SC03_124_jr_80187010.c index 8ca38e514..4ac935f5d 100644 --- a/src/ov_SC03_124/ov_SC03_124_jr_80187010.c +++ b/src/ov_SC03_124/ov_SC03_124_jr_80187010.c @@ -2984,22 +2984,16 @@ extern void func_80185BD4(void); extern s16 D_800B9A02; extern u8 D_801151C8[]; -extern s32 D_801151D0; -extern s16 D_80115126; extern u16 D_80115112; -extern u16 D_8011511A; extern u8 D_80115138[]; extern u8 D_80115148[]; extern s32 D_80115130; extern u8 D_800B9A15; extern s16 D_801E2360; -extern u16 D_801E2364; -extern s16 D_801E2368; extern s32 D_801E2358; extern s32 D_801E235C; extern s16 D_801E23E8; -extern s16 D_801E23EC; extern s16 D_801E23F0; extern s16 D_801E23F4; extern s16 D_801E23F8; @@ -3034,6 +3028,18 @@ extern s32 func_80188C68(s32 a0, s16 a1); extern s16 func_8018957C(s32 a0); void func_80187010(void) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern u16 D_801E2364; + extern s16 D_801E2368; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 D_801151D0; + extern s16 D_801E23EC; + extern s16 D_80115126; + extern u16 D_8011511A; s32 s0; s32 pad[2]; (void)&pad; @@ -3644,7 +3650,125 @@ INCLUDE_ASM("asm/ov_SC03_124/nonmatchings/ov_SC03_124_jr_80187010", func_8018953 INCLUDE_ASM("asm/ov_SC03_124/nonmatchings/ov_SC03_124_jr_80187010", func_8018957C); -INCLUDE_ASM("asm/ov_SC03_124/nonmatchings/ov_SC03_124_jr_80187010", func_801895C8); + +/* func_801895C8 — ov_SC03_001 (133 ins), exemplar of a 5-member open-only + * h_norm cluster. Builds the full-screen fade overlay: a DR_MODE-style 8-byte + * GP0 packet (0xE1000015), a 320x240 semi-transparent gouraud quad (POLY_G4, + * code 0x3A), and a second 8-byte GP0 packet (0xE1000240), each linked into the + * current OT with the psyq `addPrim` idiom. The type shapes and the + * `((PTag *)x)->addr = ((PTag *)ot)->addr; ((PTag *)ot)->addr = (u32)x;` pair + * are copied VERBATIM from the already-matched neighbour func_8018BCD4 in this + * same TU (§71) — Env_* / PTag_* there are the fleet-canonical shapes. + * + * Levers that were load-bearing (all byte-tested; the draft is PIN-FREE): + * §20 &D_801151D0 / &D_800B9A02 taken into pointer LOCALS -> each address is + * force_reg'd once (lui+addiu -> $t2 / $a3) instead of a %lo per use. + * §36 the 24-bit BITFIELD store, not a hand-written mask, is what emits + * 0x00FFFFFF (lui+ori) ahead of 0xFF000000 (lui) while the body ANDs the + * destination first — expmed's store_fixed_bit_field signature. + * §37 asm-label aliases for D_801E2364/D_801E2368: the TU canon is u16/s16 + * but the target does a bare `lbu %lo(sym)`, and a plain block-scope + * `extern u8` would be a conflicting redeclaration. + * --- `volatile` on the OT index read keeps all SIX *pbh loads alive; a plain + * read cse-folds them and the function loses ~25 instructions. + * S1 the whole body is ONE branch-free basic block and every store ties at + * the same priority, so forward asm order == source statement order — + * the POLY_G4 block below is a literal transcription of the target. + * S2 `p` is destructively updated (multi-set -> no birthing boost) so its + * `addiu +8` floats up into the preceding load-delay gap, while `r` is a + * FRESH single-set local (boosted) so its `addiu +0x24` sinks to sit + * immediately before `sb 3($a0)`. Both placements are the target's. + * --- the bare `p = r;` before r's uses is a COMBINE BARRIER: without a SET + * of `p` between `r = p + 9` and r's first use, `can_combine_p` lets + * combine substitute `r` -> `p + 0x24` into every MEM offset and the + * `addiu` disappears entirely (and, at the tail, `p += 2` folds to + * `addiu $t3,$t3,0x2C` off the stale base instead of `addiu $t3,$a0,8`). + * It also fixes the register rotation for free — verified that adding or + * removing `register __asm__` pins on p/r/pbh is a byte no-op. + */ + +/* ---- TU-visible spellings (file scope of ov_SC03_001_jr_8018A3A8.c) ---- */ + +void func_801895C8(void) { + + extern s32 D_801151D0; + extern u16 D_801E2364; + extern s16 D_801E2368; + /* §100/§120: draft-local, uniquely-named types — they live in the BODY so + * they cannot collide with the TU's own Env_8018BCD4 / PTag_8018BCD4. */ + typedef struct { u32 addr : 24; u32 len : 8; } PTag_8018C960_801895C8; + typedef struct { u32 *ot; u32 pad[4]; } Env_8018C960_801895C8; /* 0x14 stride */ + typedef struct { + u32 tag; /* 0x00 */ + u8 r0, g0, b0, code; /* 0x04..0x07 */ + s16 x0, y0; /* 0x08, 0x0A */ + u8 r1, g1, b1, p1; /* 0x0C..0x0F */ + s16 x1, y1; /* 0x10, 0x12 */ + u8 r2, g2, b2, p2; /* 0x14..0x17 */ + s16 x2, y2; /* 0x18, 0x1A */ + u8 r3, g3, b3, p3; /* 0x1C..0x1F */ + s16 x3, y3; /* 0x20, 0x22 */ + } PG4_8018C960_801895C8; /* -> 0x24 */ + + extern Env_8018C960_801895C8 D_800AE7BC[]; + extern u8 aD801EF1EC __asm__("D_801E2364"); + extern u8 aD801EF1F0 __asm__("D_801E2368"); + + u32 **pp; + volatile u16 *pbh; + u32 *p; + u32 *r; + u8 c1, c2; + + pp = (u32 **)&D_801151D0; + pbh = (volatile u16 *)&D_800B9A02; + + p = *pp; + ((PTag_8018C960_801895C8 *)p)->len = 1; + p[1] = 0xE1000015; + ((PTag_8018C960_801895C8 *)p)->addr = ((PTag_8018C960_801895C8 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_801895C8 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + p += 2; + ((PG4_8018C960_801895C8 *)p)->tag = 0x08000000; + ((PG4_8018C960_801895C8 *)p)->code = 0x3A; + ((PG4_8018C960_801895C8 *)p)->x2 = -160; + ((PG4_8018C960_801895C8 *)p)->x0 = -160; + ((PG4_8018C960_801895C8 *)p)->x3 = 160; + ((PG4_8018C960_801895C8 *)p)->x1 = 160; + c1 = aD801EF1EC; + ((PG4_8018C960_801895C8 *)p)->b1 = c1; + ((PG4_8018C960_801895C8 *)p)->b0 = c1; + ((PG4_8018C960_801895C8 *)p)->g1 = c1; + ((PG4_8018C960_801895C8 *)p)->g0 = c1; + ((PG4_8018C960_801895C8 *)p)->r1 = c1; + ((PG4_8018C960_801895C8 *)p)->r0 = c1; + c2 = aD801EF1F0; + ((PG4_8018C960_801895C8 *)p)->y1 = -120; + ((PG4_8018C960_801895C8 *)p)->b3 = c2; + ((PG4_8018C960_801895C8 *)p)->b2 = c2; + ((PG4_8018C960_801895C8 *)p)->g3 = c2; + ((PG4_8018C960_801895C8 *)p)->g2 = c2; + ((PG4_8018C960_801895C8 *)p)->r3 = c2; + ((PG4_8018C960_801895C8 *)p)->r2 = c2; + ((PG4_8018C960_801895C8 *)p)->y0 = -120; + ((PG4_8018C960_801895C8 *)p)->y3 = 120; + ((PG4_8018C960_801895C8 *)p)->y2 = 120; + + ((PTag_8018C960_801895C8 *)p)->addr = ((PTag_8018C960_801895C8 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_801895C8 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + r = p + 9; /* 0x24 */ + p = r; /* COMBINE BARRIER — see header */ + ((PTag_8018C960_801895C8 *)r)->len = 1; + r[1] = 0xE1000240; + ((PTag_8018C960_801895C8 *)r)->addr = ((PTag_8018C960_801895C8 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_801895C8 *)D_800AE7BC[*pbh].ot)->addr = (u32)r; + + p += 2; + *pp = p; +} + extern void (*D_801D52BC[])(void); diff --git a/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c b/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c index 096ef5af0..0f08bff5b 100644 --- a/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c +++ b/src/ov_SC04_000/ov_SC04_000_jr_8017BEBC.c @@ -5342,7 +5342,6 @@ void func_80180E54(void *a0) { } -extern s32 *D_80126B78; extern u8 D_8019D340[]; extern s32 func_8012BDBC(s32 a0, s32 a1); extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); @@ -5378,6 +5377,10 @@ s32 aF8018A224() __asm__("func_80180EC4"); s32 aF8018A224(param_1) void *param_1; { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 *D_80126B78; s32 *m; s32 obj; s32 sv0[2]; @@ -5894,7 +5897,101 @@ extern void func_800296F8(void *a0); } -INCLUDE_ASM("asm/ov_SC04_000/nonmatchings/ov_SC04_000_jr_8017BEBC", func_801830E4); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_80172710(void); +extern s32 func_80178BF8(); +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §71 sibling: identical shape to func_8018F390 (same TU, this file, D_80126B78/RotTransSV/ + * func_80135888/func_8012BDBC/func_80178BF8/func_80172710 idiom) already MATCHED -- only the + * per-overlay data symbol (D_801A7028 vs D_801E33F0) differs. §37 asm-label alias avoids the + * `conflicting types` clash with the fleet's `extern void func_801830E4(void);` used elsewhere + * in this TU as a state-handler function pointer. */ + +s32 aF801904E0() __asm__("func_801830E4"); + +s32 aF801904E0(param_1) + void *param_1; +{ + + extern s32 *D_80126B78; + extern u8 D_801A7028[]; + MATRIX m; + s32 obj; + s32 sv0[2]; + s32 sv1[2]; + s32 flag; + + obj = *(s32 *)((s32)param_1 + 0x64); + m = *(MATRIX *)((u8 *)D_80126B78 + 0x34); + + gte_SetRotMatrix(&m); + gte_SetTransMatrix(&m); + + RotTransSV(D_801A7028, sv0, &flag); + RotTransSV(D_801A7028 + 8, sv1, &flag); + + if (func_80135888(*(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x20), + *(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x58), + (s32)sv0, (s32)sv1) == 0) { + return 0; + } + if (func_8012BDBC(obj, 0x300) == 0) { + return 0; + } + *(s16 *)(obj + 0x2) = 3; + func_80178BF8(); + return (s32)func_80172710; +} + diff --git a/src/ov_SC04_002/ov_SC04_002_jr_8017BEBC.c b/src/ov_SC04_002/ov_SC04_002_jr_8017BEBC.c index a5db2fcfa..670ebafb7 100644 --- a/src/ov_SC04_002/ov_SC04_002_jr_8017BEBC.c +++ b/src/ov_SC04_002/ov_SC04_002_jr_8017BEBC.c @@ -6688,9 +6688,195 @@ INCLUDE_ASM("asm/ov_SC04_002/nonmatchings/ov_SC04_002_jr_8017BEBC", func_8018717 INCLUDE_ASM("asm/ov_SC04_002/nonmatchings/ov_SC04_002_jr_8017BEBC", func_801871EC); -INCLUDE_ASM("asm/ov_SC04_002/nonmatchings/ov_SC04_002_jr_8017BEBC", func_8018739C); -INCLUDE_ASM("asm/ov_SC04_002/nonmatchings/ov_SC04_002_jr_8017BEBC", func_80187604); +/* --- types: ALREADY PRESENT in src/shared/engine_types.h (pulled into the real TU + * via engine_core.h). Delete these four typedefs when banking into + * src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c — they exist verbatim at + * engine_types.h:1168 (MATRIX), :1726 (CV_801837B0), :3787..:3793 (SV/PKT). + * The immediate neighbour func_801837B0 (line 5484, MATCHed) uses PKT_801837B0 + * with the identical v[4]/rgb[4]/code layout and the same `pkt.code = 0x50000000`. */ + + + + + + +void func_8018739C(s32 a0, void *a1, s32 a2) +{ + extern u16 D_800B99DA; + extern u8 D_801B4F84[]; + extern u8 D_801B4F98[]; + extern s32 func_80017758(void *a0, void *a1); /* canon, TU line 1761 */ + extern void func_801878B0(s32 a0, void *a1, s32 a2, MATRIX *a3); + MATRIX m; /* sp+0x10 */ + PKT_801837B0 pkt; /* sp+0x30 */ + u8 *p; + s32 i; + + func_801878B0(a0, a1, a2, &m); + + if (D_800B99DA & 1) { + pkt.rgb[1].b = 0x58; + } else { + pkt.rgb[1].b = 0x48; + } + + p = D_801B4F84; + pkt.rgb[0].r = pkt.rgb[0].g = pkt.rgb[0].b = 0; + pkt.rgb[2].r = pkt.rgb[2].g = pkt.rgb[2].b = 0; + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[3].b = 0; + pkt.code = 0x50000000; + pkt.v[0].vz = pkt.v[2].vz = pkt.v[3].vz = 0; + pkt.v[1].vx = pkt.v[1].vy = pkt.v[1].vz = 0; + pkt.rgb[1].r = pkt.rgb[1].g = pkt.rgb[1].b >> 2; + + for (i = 0; i < 4; i++) { + pkt.v[0].vx = (s8)*p++; + pkt.v[0].vy = (s8)*p++; + pkt.v[2].vx = (s8)*p++; + pkt.v[2].vy = (s8)*p++; + pkt.v[3].vx = (s8)*p++; + pkt.v[3].vy = (s8)*p--; + func_80017758(&pkt.v[0], &m); + } + + p = D_801B4F98; + pkt.v[1].vz = -0x12; + pkt.v[0].vy = pkt.v[2].vy = pkt.v[3].vy = 0; + pkt.v[1].vx = pkt.v[1].vy = 0; + pkt.rgb[1].b <<= 1; + pkt.rgb[1].r = pkt.rgb[1].g <<= 1; + + for (i = 0; i < 4; i++) { + pkt.v[0].vx = (s8)*p++; + pkt.v[0].vz = (s8)*p++; + pkt.v[2].vx = (s8)*p++; + pkt.v[2].vz = (s8)*p++; + pkt.v[3].vx = (s8)*p++; + pkt.v[3].vz = (s8)*p--; + if (i == 2) { + pkt.rgb[3].b = pkt.rgb[1].b; + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[1].r; + } else if (i == 3) { + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[3].b = 0; + pkt.rgb[0].b = pkt.rgb[1].b; + pkt.rgb[0].r = pkt.rgb[0].g = pkt.rgb[1].r; + } + func_80017758(&pkt.v[0], &m); + } +} + + + +/* func_80187604 (ov_SC02_041_jr_8017BEBC, 171 ins) — byte-matched. + * + * Builds a GTE 4-vertex/4-colour packet on the stack and pushes it three times + * through func_80017758 (the shared "transform + link prim" helper, see the + * sibling func_80182BDC in ov_SC03_099_jr_8017BEBC.c, which uses the identical + * 0x00 verts / 0x20 colours / 0x30 code layout). + * + * Layout notes that had to be right for the frame to come out as 0x78: + * - mtx[0x20] is declared FIRST so it takes the low local slot (sp+0x10) and + * the packet takes sp+0x30 (MIPS frame grows UP; slots go in decl order). + * - locals total 0x54 -> MIPS_STACK_ALIGN 0x58, +0x10 outgoing args +12 saved + * regs = 0x74 -> 0x78. + * + * Two idioms this needed (both byte-verified here): + * 1. The colour/vertex zero-fills are CHAINED assignments; `a = b = c = 0` + * emits the stores RIGHT-TO-LEFT, which is what produces the descending + * 0x52/0x51/0x50 and 0x4C/0x44/0x34 store orders. + * 2. The brightness must be stored into the packet IN EACH ARM (cross-jump + * then merges the three `sb`s into one at the join). Hoisting it into an + * `s32 br` local instead lets cse/combine forward the stored value into + * the `>> 2`, which DELETES the `lbu 0x54(sp)` reload (-1 instruction). + * 3. The inner test is written `!(flags & 2) -> 0x80` so gcc's + * jump-if-false lands `bnez` (with 0xC0 stolen into the delay slot from + * the branch target), not `beqz` with 0x80. + */ + +void func_80187604(s32 a0, s32 a1, s32 a2) +{ + typedef struct { + s16 vx, vy, vz, pad; + } SV_80183FE0_80187604; + + typedef struct { + SV_80183FE0_80187604 v[4]; /* 0x00 */ + u8 c[4][4]; /* 0x20 */ + u32 code; /* 0x30 */ + } Prim_80183FE0_80187604; /* 0x34 */ + + extern void func_801878B0(s32 a0, s32 a1, s32 a2, void *a3); + extern s32 func_80017758(void *a0, void *a1); + extern u16 D_800B99DA; + extern u8 D_8018B4D8[]; + extern u8 D_8018B4EC[]; + + u8 mtx[0x20]; + Prim_80183FE0_80187604 p; + u8 *q; + s32 i; + + func_801878B0(a0, a1, a2, mtx); + + p.v[0].vz = p.v[2].vz = p.v[3].vz = 0; + p.v[1].vx = p.v[1].vy = p.v[1].vz = 0; + if (D_800B99DA & 1) { + p.c[1][0] = 0xA0; + } else if (!(D_800B99DA & 2)) { + p.c[1][0] = 0x80; + } else { + p.c[1][0] = 0xC0; + } + p.c[0][0] = p.c[0][1] = p.c[0][2] = 0; + p.c[2][0] = p.c[2][1] = p.c[2][2] = 0; + p.c[3][0] = p.c[3][1] = p.c[3][2] = 0; + p.code = 0x50000000; + p.c[1][1] = p.c[1][2] = p.c[1][0] >> 2; + + q = D_8018B4D8; + for (i = 0; i < 4; i++) { + p.v[0].vx = (s8)*q++; + p.v[0].vy = (s8)*q++; + p.v[2].vx = (s8)*q++; + p.v[2].vy = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vy = (s8)*q--; + func_80017758(&p, mtx); + } + + p.v[0].vy = p.v[2].vy = p.v[3].vy = 0; + p.v[1].vx = p.v[1].vy = 0; + p.v[1].vz = -0x20; + q = D_8018B4EC; + for (i = 0; i < 4; i++) { + p.v[0].vx = (s8)*q++; + p.v[0].vz = (s8)*q++; + p.v[2].vx = (s8)*q++; + p.v[2].vz = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vz = (s8)*q--; + func_80017758(&p, mtx); + if (i == 1) { + p.v[1].vz = 0x20; + q += 2; + } + } + q += 2; + + p.v[0].vx = 0; + p.v[0].vz = -0x20; + p.c[0][0] = p.c[1][0]; + p.c[0][1] = p.c[0][2] = p.c[1][1]; + for (i = 0; i < 2; i++) { + p.v[2].vx = (s8)*q++; + p.v[2].vz = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vz = (s8)*q++; + func_80017758(&p, mtx); + } +} + INCLUDE_ASM("asm/ov_SC04_002/nonmatchings/ov_SC04_002_jr_8017BEBC", func_801878B0); diff --git a/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c b/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c index d6211a1d1..82c633fdc 100644 --- a/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c +++ b/src/ov_SC04_005/ov_SC04_005_jr_8017BEBC.c @@ -6844,9 +6844,195 @@ INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8018654 INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_801865BC); -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_8018676C); -INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_801869D4); +/* --- types: ALREADY PRESENT in src/shared/engine_types.h (pulled into the real TU + * via engine_core.h). Delete these four typedefs when banking into + * src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c — they exist verbatim at + * engine_types.h:1168 (MATRIX), :1726 (CV_801837B0), :3787..:3793 (SV/PKT). + * The immediate neighbour func_801837B0 (line 5484, MATCHed) uses PKT_801837B0 + * with the identical v[4]/rgb[4]/code layout and the same `pkt.code = 0x50000000`. */ + + + + + + +void func_8018676C(s32 a0, void *a1, s32 a2) +{ + extern u16 D_800B99DA; + extern u8 D_801B5A10[]; + extern u8 D_801B5A24[]; + extern s32 func_80017758(void *a0, void *a1); /* canon, TU line 1761 */ + extern void func_80186C80(s32 a0, void *a1, s32 a2, MATRIX *a3); + MATRIX m; /* sp+0x10 */ + PKT_801837B0 pkt; /* sp+0x30 */ + u8 *p; + s32 i; + + func_80186C80(a0, a1, a2, &m); + + if (D_800B99DA & 1) { + pkt.rgb[1].b = 0x58; + } else { + pkt.rgb[1].b = 0x48; + } + + p = D_801B5A10; + pkt.rgb[0].r = pkt.rgb[0].g = pkt.rgb[0].b = 0; + pkt.rgb[2].r = pkt.rgb[2].g = pkt.rgb[2].b = 0; + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[3].b = 0; + pkt.code = 0x50000000; + pkt.v[0].vz = pkt.v[2].vz = pkt.v[3].vz = 0; + pkt.v[1].vx = pkt.v[1].vy = pkt.v[1].vz = 0; + pkt.rgb[1].r = pkt.rgb[1].g = pkt.rgb[1].b >> 2; + + for (i = 0; i < 4; i++) { + pkt.v[0].vx = (s8)*p++; + pkt.v[0].vy = (s8)*p++; + pkt.v[2].vx = (s8)*p++; + pkt.v[2].vy = (s8)*p++; + pkt.v[3].vx = (s8)*p++; + pkt.v[3].vy = (s8)*p--; + func_80017758(&pkt.v[0], &m); + } + + p = D_801B5A24; + pkt.v[1].vz = -0x12; + pkt.v[0].vy = pkt.v[2].vy = pkt.v[3].vy = 0; + pkt.v[1].vx = pkt.v[1].vy = 0; + pkt.rgb[1].b <<= 1; + pkt.rgb[1].r = pkt.rgb[1].g <<= 1; + + for (i = 0; i < 4; i++) { + pkt.v[0].vx = (s8)*p++; + pkt.v[0].vz = (s8)*p++; + pkt.v[2].vx = (s8)*p++; + pkt.v[2].vz = (s8)*p++; + pkt.v[3].vx = (s8)*p++; + pkt.v[3].vz = (s8)*p--; + if (i == 2) { + pkt.rgb[3].b = pkt.rgb[1].b; + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[1].r; + } else if (i == 3) { + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[3].b = 0; + pkt.rgb[0].b = pkt.rgb[1].b; + pkt.rgb[0].r = pkt.rgb[0].g = pkt.rgb[1].r; + } + func_80017758(&pkt.v[0], &m); + } +} + + + +/* func_801869D4 (ov_SC02_041_jr_8017BEBC, 171 ins) — byte-matched. + * + * Builds a GTE 4-vertex/4-colour packet on the stack and pushes it three times + * through func_80017758 (the shared "transform + link prim" helper, see the + * sibling func_80182BDC in ov_SC03_099_jr_8017BEBC.c, which uses the identical + * 0x00 verts / 0x20 colours / 0x30 code layout). + * + * Layout notes that had to be right for the frame to come out as 0x78: + * - mtx[0x20] is declared FIRST so it takes the low local slot (sp+0x10) and + * the packet takes sp+0x30 (MIPS frame grows UP; slots go in decl order). + * - locals total 0x54 -> MIPS_STACK_ALIGN 0x58, +0x10 outgoing args +12 saved + * regs = 0x74 -> 0x78. + * + * Two idioms this needed (both byte-verified here): + * 1. The colour/vertex zero-fills are CHAINED assignments; `a = b = c = 0` + * emits the stores RIGHT-TO-LEFT, which is what produces the descending + * 0x52/0x51/0x50 and 0x4C/0x44/0x34 store orders. + * 2. The brightness must be stored into the packet IN EACH ARM (cross-jump + * then merges the three `sb`s into one at the join). Hoisting it into an + * `s32 br` local instead lets cse/combine forward the stored value into + * the `>> 2`, which DELETES the `lbu 0x54(sp)` reload (-1 instruction). + * 3. The inner test is written `!(flags & 2) -> 0x80` so gcc's + * jump-if-false lands `bnez` (with 0xC0 stolen into the delay slot from + * the branch target), not `beqz` with 0x80. + */ + +void func_801869D4(s32 a0, s32 a1, s32 a2) +{ + typedef struct { + s16 vx, vy, vz, pad; + } SV_80183FE0_801869D4; + + typedef struct { + SV_80183FE0_801869D4 v[4]; /* 0x00 */ + u8 c[4][4]; /* 0x20 */ + u32 code; /* 0x30 */ + } Prim_80183FE0_801869D4; /* 0x34 */ + + extern void func_80186C80(s32 a0, s32 a1, s32 a2, void *a3); + extern s32 func_80017758(void *a0, void *a1); + extern u16 D_800B99DA; + extern u8 D_8018ABDC[]; + extern u8 D_8018ABF0[]; + + u8 mtx[0x20]; + Prim_80183FE0_801869D4 p; + u8 *q; + s32 i; + + func_80186C80(a0, a1, a2, mtx); + + p.v[0].vz = p.v[2].vz = p.v[3].vz = 0; + p.v[1].vx = p.v[1].vy = p.v[1].vz = 0; + if (D_800B99DA & 1) { + p.c[1][0] = 0xA0; + } else if (!(D_800B99DA & 2)) { + p.c[1][0] = 0x80; + } else { + p.c[1][0] = 0xC0; + } + p.c[0][0] = p.c[0][1] = p.c[0][2] = 0; + p.c[2][0] = p.c[2][1] = p.c[2][2] = 0; + p.c[3][0] = p.c[3][1] = p.c[3][2] = 0; + p.code = 0x50000000; + p.c[1][1] = p.c[1][2] = p.c[1][0] >> 2; + + q = D_8018ABDC; + for (i = 0; i < 4; i++) { + p.v[0].vx = (s8)*q++; + p.v[0].vy = (s8)*q++; + p.v[2].vx = (s8)*q++; + p.v[2].vy = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vy = (s8)*q--; + func_80017758(&p, mtx); + } + + p.v[0].vy = p.v[2].vy = p.v[3].vy = 0; + p.v[1].vx = p.v[1].vy = 0; + p.v[1].vz = -0x20; + q = D_8018ABF0; + for (i = 0; i < 4; i++) { + p.v[0].vx = (s8)*q++; + p.v[0].vz = (s8)*q++; + p.v[2].vx = (s8)*q++; + p.v[2].vz = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vz = (s8)*q--; + func_80017758(&p, mtx); + if (i == 1) { + p.v[1].vz = 0x20; + q += 2; + } + } + q += 2; + + p.v[0].vx = 0; + p.v[0].vz = -0x20; + p.c[0][0] = p.c[1][0]; + p.c[0][1] = p.c[0][2] = p.c[1][1]; + for (i = 0; i < 2; i++) { + p.v[2].vx = (s8)*q++; + p.v[2].vz = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vz = (s8)*q++; + func_80017758(&p, mtx); + } +} + INCLUDE_ASM("asm/ov_SC04_005/nonmatchings/ov_SC04_005_jr_8017BEBC", func_80186C80); diff --git a/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c b/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c index 8445cab35..927896240 100644 --- a/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c +++ b/src/ov_SC04_007/ov_SC04_007_jr_8017BEBC.c @@ -5676,9 +5676,195 @@ INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80182BB INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80182C28); -INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80182DD8); -INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_80183040); +/* --- types: ALREADY PRESENT in src/shared/engine_types.h (pulled into the real TU + * via engine_core.h). Delete these four typedefs when banking into + * src/ov_SC02_041/ov_SC02_041_jr_8017BEBC.c — they exist verbatim at + * engine_types.h:1168 (MATRIX), :1726 (CV_801837B0), :3787..:3793 (SV/PKT). + * The immediate neighbour func_801837B0 (line 5484, MATCHed) uses PKT_801837B0 + * with the identical v[4]/rgb[4]/code layout and the same `pkt.code = 0x50000000`. */ + + + + + + +void func_80182DD8(s32 a0, void *a1, s32 a2) +{ + extern u16 D_800B99DA; + extern u8 D_801980B8[]; + extern u8 D_801980CC[]; + extern s32 func_80017758(void *a0, void *a1); /* canon, TU line 1761 */ + extern void func_801832EC(s32 a0, void *a1, s32 a2, MATRIX *a3); + MATRIX m; /* sp+0x10 */ + PKT_801837B0 pkt; /* sp+0x30 */ + u8 *p; + s32 i; + + func_801832EC(a0, a1, a2, &m); + + if (D_800B99DA & 1) { + pkt.rgb[1].b = 0x58; + } else { + pkt.rgb[1].b = 0x48; + } + + p = D_801980B8; + pkt.rgb[0].r = pkt.rgb[0].g = pkt.rgb[0].b = 0; + pkt.rgb[2].r = pkt.rgb[2].g = pkt.rgb[2].b = 0; + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[3].b = 0; + pkt.code = 0x50000000; + pkt.v[0].vz = pkt.v[2].vz = pkt.v[3].vz = 0; + pkt.v[1].vx = pkt.v[1].vy = pkt.v[1].vz = 0; + pkt.rgb[1].r = pkt.rgb[1].g = pkt.rgb[1].b >> 2; + + for (i = 0; i < 4; i++) { + pkt.v[0].vx = (s8)*p++; + pkt.v[0].vy = (s8)*p++; + pkt.v[2].vx = (s8)*p++; + pkt.v[2].vy = (s8)*p++; + pkt.v[3].vx = (s8)*p++; + pkt.v[3].vy = (s8)*p--; + func_80017758(&pkt.v[0], &m); + } + + p = D_801980CC; + pkt.v[1].vz = -0x12; + pkt.v[0].vy = pkt.v[2].vy = pkt.v[3].vy = 0; + pkt.v[1].vx = pkt.v[1].vy = 0; + pkt.rgb[1].b <<= 1; + pkt.rgb[1].r = pkt.rgb[1].g <<= 1; + + for (i = 0; i < 4; i++) { + pkt.v[0].vx = (s8)*p++; + pkt.v[0].vz = (s8)*p++; + pkt.v[2].vx = (s8)*p++; + pkt.v[2].vz = (s8)*p++; + pkt.v[3].vx = (s8)*p++; + pkt.v[3].vz = (s8)*p--; + if (i == 2) { + pkt.rgb[3].b = pkt.rgb[1].b; + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[1].r; + } else if (i == 3) { + pkt.rgb[3].r = pkt.rgb[3].g = pkt.rgb[3].b = 0; + pkt.rgb[0].b = pkt.rgb[1].b; + pkt.rgb[0].r = pkt.rgb[0].g = pkt.rgb[1].r; + } + func_80017758(&pkt.v[0], &m); + } +} + + + +/* func_80183040 (ov_SC02_041_jr_8017BEBC, 171 ins) — byte-matched. + * + * Builds a GTE 4-vertex/4-colour packet on the stack and pushes it three times + * through func_80017758 (the shared "transform + link prim" helper, see the + * sibling func_80182BDC in ov_SC03_099_jr_8017BEBC.c, which uses the identical + * 0x00 verts / 0x20 colours / 0x30 code layout). + * + * Layout notes that had to be right for the frame to come out as 0x78: + * - mtx[0x20] is declared FIRST so it takes the low local slot (sp+0x10) and + * the packet takes sp+0x30 (MIPS frame grows UP; slots go in decl order). + * - locals total 0x54 -> MIPS_STACK_ALIGN 0x58, +0x10 outgoing args +12 saved + * regs = 0x74 -> 0x78. + * + * Two idioms this needed (both byte-verified here): + * 1. The colour/vertex zero-fills are CHAINED assignments; `a = b = c = 0` + * emits the stores RIGHT-TO-LEFT, which is what produces the descending + * 0x52/0x51/0x50 and 0x4C/0x44/0x34 store orders. + * 2. The brightness must be stored into the packet IN EACH ARM (cross-jump + * then merges the three `sb`s into one at the join). Hoisting it into an + * `s32 br` local instead lets cse/combine forward the stored value into + * the `>> 2`, which DELETES the `lbu 0x54(sp)` reload (-1 instruction). + * 3. The inner test is written `!(flags & 2) -> 0x80` so gcc's + * jump-if-false lands `bnez` (with 0xC0 stolen into the delay slot from + * the branch target), not `beqz` with 0x80. + */ + +void func_80183040(s32 a0, s32 a1, s32 a2) +{ + typedef struct { + s16 vx, vy, vz, pad; + } SV_80183FE0_80183040; + + typedef struct { + SV_80183FE0_80183040 v[4]; /* 0x00 */ + u8 c[4][4]; /* 0x20 */ + u32 code; /* 0x30 */ + } Prim_80183FE0_80183040; /* 0x34 */ + + extern void func_801832EC(s32 a0, s32 a1, s32 a2, void *a3); + extern s32 func_80017758(void *a0, void *a1); + extern u16 D_800B99DA; + extern u8 D_80188C74[]; + extern u8 D_80188C88[]; + + u8 mtx[0x20]; + Prim_80183FE0_80183040 p; + u8 *q; + s32 i; + + func_801832EC(a0, a1, a2, mtx); + + p.v[0].vz = p.v[2].vz = p.v[3].vz = 0; + p.v[1].vx = p.v[1].vy = p.v[1].vz = 0; + if (D_800B99DA & 1) { + p.c[1][0] = 0xA0; + } else if (!(D_800B99DA & 2)) { + p.c[1][0] = 0x80; + } else { + p.c[1][0] = 0xC0; + } + p.c[0][0] = p.c[0][1] = p.c[0][2] = 0; + p.c[2][0] = p.c[2][1] = p.c[2][2] = 0; + p.c[3][0] = p.c[3][1] = p.c[3][2] = 0; + p.code = 0x50000000; + p.c[1][1] = p.c[1][2] = p.c[1][0] >> 2; + + q = D_80188C74; + for (i = 0; i < 4; i++) { + p.v[0].vx = (s8)*q++; + p.v[0].vy = (s8)*q++; + p.v[2].vx = (s8)*q++; + p.v[2].vy = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vy = (s8)*q--; + func_80017758(&p, mtx); + } + + p.v[0].vy = p.v[2].vy = p.v[3].vy = 0; + p.v[1].vx = p.v[1].vy = 0; + p.v[1].vz = -0x20; + q = D_80188C88; + for (i = 0; i < 4; i++) { + p.v[0].vx = (s8)*q++; + p.v[0].vz = (s8)*q++; + p.v[2].vx = (s8)*q++; + p.v[2].vz = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vz = (s8)*q--; + func_80017758(&p, mtx); + if (i == 1) { + p.v[1].vz = 0x20; + q += 2; + } + } + q += 2; + + p.v[0].vx = 0; + p.v[0].vz = -0x20; + p.c[0][0] = p.c[1][0]; + p.c[0][1] = p.c[0][2] = p.c[1][1]; + for (i = 0; i < 2; i++) { + p.v[2].vx = (s8)*q++; + p.v[2].vz = (s8)*q++; + p.v[3].vx = (s8)*q++; + p.v[3].vz = (s8)*q++; + func_80017758(&p, mtx); + } +} + INCLUDE_ASM("asm/ov_SC04_007/nonmatchings/ov_SC04_007_jr_8017BEBC", func_801832EC); diff --git a/src/ov_SC04_009/ov_SC04_009_jr_8017BEBC.c b/src/ov_SC04_009/ov_SC04_009_jr_8017BEBC.c index 859de2ade..35d976a1d 100644 --- a/src/ov_SC04_009/ov_SC04_009_jr_8017BEBC.c +++ b/src/ov_SC04_009/ov_SC04_009_jr_8017BEBC.c @@ -4076,7 +4076,6 @@ void func_8017E4B0(void *a0) { } -extern s32 *D_80126B78; extern u8 D_80194EE8[]; extern s32 func_8012BDBC(s32 a0, s32 a1); extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); @@ -4112,6 +4111,10 @@ s32 aF8018A224() __asm__("func_8017E520"); s32 aF8018A224(param_1) void *param_1; { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 *D_80126B78; s32 *m; s32 obj; s32 sv0[2]; @@ -4257,7 +4260,101 @@ extern void func_800296F8(void); } -INCLUDE_ASM("asm/ov_SC04_009/nonmatchings/ov_SC04_009_jr_8017BEBC", func_8017E950); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_80172710(void); +extern s32 func_80178BF8(); +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §71 sibling: identical shape to func_8018F390 (same TU, this file, D_80126B78/RotTransSV/ + * func_80135888/func_8012BDBC/func_80178BF8/func_80172710 idiom) already MATCHED -- only the + * per-overlay data symbol (D_80195040 vs D_801E33F0) differs. §37 asm-label alias avoids the + * `conflicting types` clash with the fleet's `extern void func_8017E950(void);` used elsewhere + * in this TU as a state-handler function pointer. */ + +s32 aF801904E0() __asm__("func_8017E950"); + +s32 aF801904E0(param_1) + void *param_1; +{ + + extern s32 *D_80126B78; + extern u8 D_80195040[]; + MATRIX m; + s32 obj; + s32 sv0[2]; + s32 sv1[2]; + s32 flag; + + obj = *(s32 *)((s32)param_1 + 0x64); + m = *(MATRIX *)((u8 *)D_80126B78 + 0x34); + + gte_SetRotMatrix(&m); + gte_SetTransMatrix(&m); + + RotTransSV(D_80195040, sv0, &flag); + RotTransSV(D_80195040 + 8, sv1, &flag); + + if (func_80135888(*(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x20), + *(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x58), + (s32)sv0, (s32)sv1) == 0) { + return 0; + } + if (func_8012BDBC(obj, 0x300) == 0) { + return 0; + } + *(s16 *)(obj + 0x2) = 3; + func_80178BF8(); + return (s32)func_80172710; +} + diff --git a/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c b/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c index 920f26bb1..e429f5723 100644 --- a/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c +++ b/src/ov_SC04_011/ov_SC04_011_jr_8017D494.c @@ -3177,7 +3177,67 @@ void func_8017E374(void *a0) { } -INCLUDE_ASM("asm/ov_SC04_011/nonmatchings/ov_SC04_011_jr_8017D494", func_8017E3B0); + + +extern s32 rand(void); + +typedef struct { + u16 f0; + u16 f2; + u16 f4; + u16 f6; + u16 f8; + u16 fA; + s32 fC; + s32 f10; + s32 f14; + s32 f18; +} SubRec_801EB5C8_8017E3B0; /* 0x1C */ + +typedef struct { + u16 g0; + u16 g2; + s32 g4; + s32 g8; + s32 gC; + SubRec_801EB5C8_8017E3B0 subs[16]; +} GroupRec_801EB5C8_8017E3B0; /* 0x1D0 */ + + +void func_8017E3B0(s32 param_1) +{ + + extern GroupRec_801EB5C8_8017E3B0 D_801EEDC8[8]; + s32 i, j; + GroupRec_801EB5C8_8017E3B0 *grp; + SubRec_801EB5C8_8017E3B0 *sub; + + for (i = 0; i < 8; i++) { + grp = &D_801EEDC8[i]; + grp->g0 = 0; + grp->g2 = i << 9; + grp->gC = (rand() & 0xF) << 16; + grp->g4 = ((rand() & 0xF) << 15) + 0x10000; + grp->g8 = ((rand() & 0xF) << 12) + 0x8000; + + for (j = 0; j < 16; j++) { + sub = &grp->subs[j]; + sub->f0 = 0; + sub->f2 = (rand() & 3) + 4; + sub->f8 = (j << 8) + (rand() & 0xF) * 56; + sub->fA = (rand() & 0xF) << 8; + sub->f14 = (rand() & 0xF) << 13; + sub->fC = ((rand() & 0xF) << 14) + 0x10000; + sub->f10 = ((rand() & 0xF) << 12) + 0x8000; + sub->f4 = 0x200; + sub->f6 = (rand() & 0xF) << 4; + sub->f18 = ((rand() & 3) << 5) + 0x40; + } + } + + *(u16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC04_011/nonmatchings/ov_SC04_011_jr_8017D494", func_8017E558); diff --git a/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c b/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c index 7da686703..656e26f1f 100644 --- a/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c +++ b/src/ov_SC04_015/ov_SC04_015_jr_8017AE2C.c @@ -7096,7 +7096,99 @@ void func_80183598(void *a0) { void func_801835D4(void) { } -INCLUDE_ASM("asm/ov_SC04_015/nonmatchings/ov_SC04_015_jr_8017AE2C", func_801835DC); + +extern s32 func_8012BEE8(s32 a0); +extern s32 rand(void); + +void func_801835DC(s32 param_1) { + s32 uVar1; + s32 iVar2; + register s32 iVar3 __asm__("$3"); + register s32 iVar4 __asm__("$16"); + u32 uVar3; + + uVar1 = *(u16 *)(param_1 + 0x34); + if (uVar1 == 1) { + goto case1; + } + if (uVar1 < 2) { + if (uVar1 == 0) { + goto case0; + } + return; + } + if (uVar1 == 2) { + goto case2; + } + if (uVar1 != 3) { + return; + } + goto case3; + +case0: + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + iVar4 = uVar3 & 0x3fff; + iVar4 = iVar4 + 0x7800; + uVar3 = rand(); + if ((uVar3 & 1) == 0) { + iVar4 = -iVar4; + } + *(s32 *)(param_1 + 0xe0) = iVar4; + *(s32 *)(param_1 + 0xe4) = 0; + return; + +case1: + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + uVar3 = uVar3 & 0x3f; + goto tail; + +case2: + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + *(s32 *)(param_1 + 0xe4); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0xe0) = -*(s32 *)(param_1 + 0xe0); + return; + +case3: + __asm__ __volatile__("" ::: "memory"); + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = 0; + uVar3 = rand(); + uVar3 = uVar3 & 0xff; + +tail: + *(u32 *)(param_1 + 0x1c) = uVar3 + 0x40; +} + extern void (*D_801C44E4[])(void); diff --git a/src/ov_SC04_018/ov_SC04_018_jr_801878E8.c b/src/ov_SC04_018/ov_SC04_018_jr_801878E8.c index cceccf410..1d9c96af8 100644 --- a/src/ov_SC04_018/ov_SC04_018_jr_801878E8.c +++ b/src/ov_SC04_018/ov_SC04_018_jr_801878E8.c @@ -3064,22 +3064,16 @@ extern void func_801864AC(void); extern s16 D_800B9A02; extern u8 D_801151C8[]; -extern s32 D_801151D0; -extern s16 D_80115126; extern u16 D_80115112; -extern u16 D_8011511A; extern u8 D_80115138[]; extern u8 D_80115148[]; extern s32 D_80115130; extern u8 D_800B9A15; extern s16 D_801E7708; -extern u16 D_801E770C; -extern s16 D_801E7710; extern s32 D_801E7700; extern s32 D_801E7704; extern s16 D_801E7790; -extern s16 D_801E7794; extern s16 D_801E7798; extern s16 D_801E779C; extern s16 D_801E77A0; @@ -3114,6 +3108,18 @@ extern s32 func_80189540(s32 a0, s16 a1); extern s16 func_80189E54(s32 a0); void func_801878E8(void) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern u16 D_801E770C; + extern s16 D_801E7710; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 D_801151D0; + extern s16 D_801E7794; + extern s16 D_80115126; + extern u16 D_8011511A; s32 s0; s32 pad[2]; (void)&pad; @@ -3322,9 +3328,7 @@ void func_801878E8(void) { extern s32 D_80126B58; extern s16 D_800B9A02; extern u8 D_801151C8[]; -extern s32 D_801151D0; extern s16 D_801E7708; -extern u16 D_8011511A; extern s16 func_8014168C(s16 a0); extern s16 D_801B9414[]; extern void func_8014BB24(s32 a0, s32 a1, s32 a2); @@ -3333,8 +3337,6 @@ extern void func_8014B2A8(void); extern void func_801EA0E4(s32 a0); extern void func_8014BD24(s32 a0, s32 a1); extern void func_80189EA0(void); -extern u16 D_801E770C; -extern s16 D_801E7710; extern s32 func_801621CC(s32 arg0); extern void func_801622C4(void); extern void func_80139954(void); @@ -3355,6 +3357,16 @@ extern void func_8002D4C8(s32 a0, s32 a1); void func_801880EC(void) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern u16 D_801E770C; + extern s16 D_801E7710; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 D_801151D0; + extern u16 D_8011511A; register s16 s0 __asm__("$16"); register s32 s1 __asm__("$17"); register s32 s2 __asm__("$18"); @@ -3707,7 +3719,125 @@ INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_801878E8", func_80189E1 INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_801878E8", func_80189E54); -INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_801878E8", func_80189EA0); + +/* func_80189EA0 — ov_SC03_001 (133 ins), exemplar of a 5-member open-only + * h_norm cluster. Builds the full-screen fade overlay: a DR_MODE-style 8-byte + * GP0 packet (0xE1000015), a 320x240 semi-transparent gouraud quad (POLY_G4, + * code 0x3A), and a second 8-byte GP0 packet (0xE1000240), each linked into the + * current OT with the psyq `addPrim` idiom. The type shapes and the + * `((PTag *)x)->addr = ((PTag *)ot)->addr; ((PTag *)ot)->addr = (u32)x;` pair + * are copied VERBATIM from the already-matched neighbour func_8018BCD4 in this + * same TU (§71) — Env_* / PTag_* there are the fleet-canonical shapes. + * + * Levers that were load-bearing (all byte-tested; the draft is PIN-FREE): + * §20 &D_801151D0 / &D_800B9A02 taken into pointer LOCALS -> each address is + * force_reg'd once (lui+addiu -> $t2 / $a3) instead of a %lo per use. + * §36 the 24-bit BITFIELD store, not a hand-written mask, is what emits + * 0x00FFFFFF (lui+ori) ahead of 0xFF000000 (lui) while the body ANDs the + * destination first — expmed's store_fixed_bit_field signature. + * §37 asm-label aliases for D_801E770C/D_801E7710: the TU canon is u16/s16 + * but the target does a bare `lbu %lo(sym)`, and a plain block-scope + * `extern u8` would be a conflicting redeclaration. + * --- `volatile` on the OT index read keeps all SIX *pbh loads alive; a plain + * read cse-folds them and the function loses ~25 instructions. + * S1 the whole body is ONE branch-free basic block and every store ties at + * the same priority, so forward asm order == source statement order — + * the POLY_G4 block below is a literal transcription of the target. + * S2 `p` is destructively updated (multi-set -> no birthing boost) so its + * `addiu +8` floats up into the preceding load-delay gap, while `r` is a + * FRESH single-set local (boosted) so its `addiu +0x24` sinks to sit + * immediately before `sb 3($a0)`. Both placements are the target's. + * --- the bare `p = r;` before r's uses is a COMBINE BARRIER: without a SET + * of `p` between `r = p + 9` and r's first use, `can_combine_p` lets + * combine substitute `r` -> `p + 0x24` into every MEM offset and the + * `addiu` disappears entirely (and, at the tail, `p += 2` folds to + * `addiu $t3,$t3,0x2C` off the stale base instead of `addiu $t3,$a0,8`). + * It also fixes the register rotation for free — verified that adding or + * removing `register __asm__` pins on p/r/pbh is a byte no-op. + */ + +/* ---- TU-visible spellings (file scope of ov_SC03_001_jr_8018A3A8.c) ---- */ + +void func_80189EA0(void) { + + extern s32 D_801151D0; + extern u16 D_801E770C; + extern s16 D_801E7710; + /* §100/§120: draft-local, uniquely-named types — they live in the BODY so + * they cannot collide with the TU's own Env_8018BCD4 / PTag_8018BCD4. */ + typedef struct { u32 addr : 24; u32 len : 8; } PTag_8018C960_80189EA0; + typedef struct { u32 *ot; u32 pad[4]; } Env_8018C960_80189EA0; /* 0x14 stride */ + typedef struct { + u32 tag; /* 0x00 */ + u8 r0, g0, b0, code; /* 0x04..0x07 */ + s16 x0, y0; /* 0x08, 0x0A */ + u8 r1, g1, b1, p1; /* 0x0C..0x0F */ + s16 x1, y1; /* 0x10, 0x12 */ + u8 r2, g2, b2, p2; /* 0x14..0x17 */ + s16 x2, y2; /* 0x18, 0x1A */ + u8 r3, g3, b3, p3; /* 0x1C..0x1F */ + s16 x3, y3; /* 0x20, 0x22 */ + } PG4_8018C960_80189EA0; /* -> 0x24 */ + + extern Env_8018C960_80189EA0 D_800AE7BC[]; + extern u8 aD801EF1EC __asm__("D_801E770C"); + extern u8 aD801EF1F0 __asm__("D_801E7710"); + + u32 **pp; + volatile u16 *pbh; + u32 *p; + u32 *r; + u8 c1, c2; + + pp = (u32 **)&D_801151D0; + pbh = (volatile u16 *)&D_800B9A02; + + p = *pp; + ((PTag_8018C960_80189EA0 *)p)->len = 1; + p[1] = 0xE1000015; + ((PTag_8018C960_80189EA0 *)p)->addr = ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + p += 2; + ((PG4_8018C960_80189EA0 *)p)->tag = 0x08000000; + ((PG4_8018C960_80189EA0 *)p)->code = 0x3A; + ((PG4_8018C960_80189EA0 *)p)->x2 = -160; + ((PG4_8018C960_80189EA0 *)p)->x0 = -160; + ((PG4_8018C960_80189EA0 *)p)->x3 = 160; + ((PG4_8018C960_80189EA0 *)p)->x1 = 160; + c1 = aD801EF1EC; + ((PG4_8018C960_80189EA0 *)p)->b1 = c1; + ((PG4_8018C960_80189EA0 *)p)->b0 = c1; + ((PG4_8018C960_80189EA0 *)p)->g1 = c1; + ((PG4_8018C960_80189EA0 *)p)->g0 = c1; + ((PG4_8018C960_80189EA0 *)p)->r1 = c1; + ((PG4_8018C960_80189EA0 *)p)->r0 = c1; + c2 = aD801EF1F0; + ((PG4_8018C960_80189EA0 *)p)->y1 = -120; + ((PG4_8018C960_80189EA0 *)p)->b3 = c2; + ((PG4_8018C960_80189EA0 *)p)->b2 = c2; + ((PG4_8018C960_80189EA0 *)p)->g3 = c2; + ((PG4_8018C960_80189EA0 *)p)->g2 = c2; + ((PG4_8018C960_80189EA0 *)p)->r3 = c2; + ((PG4_8018C960_80189EA0 *)p)->r2 = c2; + ((PG4_8018C960_80189EA0 *)p)->y0 = -120; + ((PG4_8018C960_80189EA0 *)p)->y3 = 120; + ((PG4_8018C960_80189EA0 *)p)->y2 = 120; + + ((PTag_8018C960_80189EA0 *)p)->addr = ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + r = p + 9; /* 0x24 */ + p = r; /* COMBINE BARRIER — see header */ + ((PTag_8018C960_80189EA0 *)r)->len = 1; + r[1] = 0xE1000240; + ((PTag_8018C960_80189EA0 *)r)->addr = ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)r; + + p += 2; + *pp = p; +} + INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_801878E8", func_8018A0B4); @@ -3918,7 +4048,99 @@ void func_8018A94C(void *a0) { DEFINE_func_8018A988() /* dedup: shared engine-core @0x8018A988 (src/shared) */ -INCLUDE_ASM("asm/ov_SC04_018/nonmatchings/ov_SC04_018_jr_801878E8", func_8018A990); + +extern s32 func_8012BEE8(s32 a0); +extern s32 rand(void); + +void func_8018A990(s32 param_1) { + s32 uVar1; + s32 iVar2; + register s32 iVar3 __asm__("$3"); + register s32 iVar4 __asm__("$16"); + u32 uVar3; + + uVar1 = *(u16 *)(param_1 + 0x34); + if (uVar1 == 1) { + goto case1; + } + if (uVar1 < 2) { + if (uVar1 == 0) { + goto case0; + } + return; + } + if (uVar1 == 2) { + goto case2; + } + if (uVar1 != 3) { + return; + } + goto case3; + +case0: + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + iVar4 = uVar3 & 0x3fff; + iVar4 = iVar4 + 0x7800; + uVar3 = rand(); + if ((uVar3 & 1) == 0) { + iVar4 = -iVar4; + } + *(s32 *)(param_1 + 0xe0) = iVar4; + *(s32 *)(param_1 + 0xe4) = 0; + return; + +case1: + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + uVar3 = uVar3 & 0x3f; + goto tail; + +case2: + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + *(s32 *)(param_1 + 0xe4); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0xe0) = -*(s32 *)(param_1 + 0xe0); + return; + +case3: + __asm__ __volatile__("" ::: "memory"); + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = 0; + uVar3 = rand(); + uVar3 = uVar3 & 0xff; + +tail: + *(u32 *)(param_1 + 0x1c) = uVar3 + 0x40; +} + DEFINE_func_8018AB3C() /* dedup: shared engine-core @0x8018AB3C (src/shared) */ diff --git a/src/ov_SC04_019/ov_SC04_019_jr_801878E8.c b/src/ov_SC04_019/ov_SC04_019_jr_801878E8.c index cb837d837..2db505226 100644 --- a/src/ov_SC04_019/ov_SC04_019_jr_801878E8.c +++ b/src/ov_SC04_019/ov_SC04_019_jr_801878E8.c @@ -3009,22 +3009,16 @@ extern void func_801864AC(void); extern s16 D_800B9A02; extern u8 D_801151C8[]; -extern s32 D_801151D0; -extern s16 D_80115126; extern u16 D_80115112; -extern u16 D_8011511A; extern u8 D_80115138[]; extern u8 D_80115148[]; extern s32 D_80115130; extern u8 D_800B9A15; extern s16 D_801E7708; -extern u16 D_801E770C; -extern s16 D_801E7710; extern s32 D_801E7700; extern s32 D_801E7704; extern s16 D_801E7790; -extern s16 D_801E7794; extern s16 D_801E7798; extern s16 D_801E779C; extern s16 D_801E77A0; @@ -3059,6 +3053,18 @@ extern s32 func_80189540(s32 a0, s16 a1); extern s16 func_80189E54(s32 a0); void func_801878E8(void) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern u16 D_801E770C; + extern s16 D_801E7710; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 D_801151D0; + extern s16 D_801E7794; + extern s16 D_80115126; + extern u16 D_8011511A; s32 s0; s32 pad[2]; (void)&pad; @@ -3654,7 +3660,125 @@ INCLUDE_ASM("asm/ov_SC04_019/nonmatchings/ov_SC04_019_jr_801878E8", func_80189E1 INCLUDE_ASM("asm/ov_SC04_019/nonmatchings/ov_SC04_019_jr_801878E8", func_80189E54); -INCLUDE_ASM("asm/ov_SC04_019/nonmatchings/ov_SC04_019_jr_801878E8", func_80189EA0); + +/* func_80189EA0 — ov_SC03_001 (133 ins), exemplar of a 5-member open-only + * h_norm cluster. Builds the full-screen fade overlay: a DR_MODE-style 8-byte + * GP0 packet (0xE1000015), a 320x240 semi-transparent gouraud quad (POLY_G4, + * code 0x3A), and a second 8-byte GP0 packet (0xE1000240), each linked into the + * current OT with the psyq `addPrim` idiom. The type shapes and the + * `((PTag *)x)->addr = ((PTag *)ot)->addr; ((PTag *)ot)->addr = (u32)x;` pair + * are copied VERBATIM from the already-matched neighbour func_8018BCD4 in this + * same TU (§71) — Env_* / PTag_* there are the fleet-canonical shapes. + * + * Levers that were load-bearing (all byte-tested; the draft is PIN-FREE): + * §20 &D_801151D0 / &D_800B9A02 taken into pointer LOCALS -> each address is + * force_reg'd once (lui+addiu -> $t2 / $a3) instead of a %lo per use. + * §36 the 24-bit BITFIELD store, not a hand-written mask, is what emits + * 0x00FFFFFF (lui+ori) ahead of 0xFF000000 (lui) while the body ANDs the + * destination first — expmed's store_fixed_bit_field signature. + * §37 asm-label aliases for D_801E770C/D_801E7710: the TU canon is u16/s16 + * but the target does a bare `lbu %lo(sym)`, and a plain block-scope + * `extern u8` would be a conflicting redeclaration. + * --- `volatile` on the OT index read keeps all SIX *pbh loads alive; a plain + * read cse-folds them and the function loses ~25 instructions. + * S1 the whole body is ONE branch-free basic block and every store ties at + * the same priority, so forward asm order == source statement order — + * the POLY_G4 block below is a literal transcription of the target. + * S2 `p` is destructively updated (multi-set -> no birthing boost) so its + * `addiu +8` floats up into the preceding load-delay gap, while `r` is a + * FRESH single-set local (boosted) so its `addiu +0x24` sinks to sit + * immediately before `sb 3($a0)`. Both placements are the target's. + * --- the bare `p = r;` before r's uses is a COMBINE BARRIER: without a SET + * of `p` between `r = p + 9` and r's first use, `can_combine_p` lets + * combine substitute `r` -> `p + 0x24` into every MEM offset and the + * `addiu` disappears entirely (and, at the tail, `p += 2` folds to + * `addiu $t3,$t3,0x2C` off the stale base instead of `addiu $t3,$a0,8`). + * It also fixes the register rotation for free — verified that adding or + * removing `register __asm__` pins on p/r/pbh is a byte no-op. + */ + +/* ---- TU-visible spellings (file scope of ov_SC03_001_jr_8018A3A8.c) ---- */ + +void func_80189EA0(void) { + + extern s32 D_801151D0; + extern u16 D_801E770C; + extern s16 D_801E7710; + /* §100/§120: draft-local, uniquely-named types — they live in the BODY so + * they cannot collide with the TU's own Env_8018BCD4 / PTag_8018BCD4. */ + typedef struct { u32 addr : 24; u32 len : 8; } PTag_8018C960_80189EA0; + typedef struct { u32 *ot; u32 pad[4]; } Env_8018C960_80189EA0; /* 0x14 stride */ + typedef struct { + u32 tag; /* 0x00 */ + u8 r0, g0, b0, code; /* 0x04..0x07 */ + s16 x0, y0; /* 0x08, 0x0A */ + u8 r1, g1, b1, p1; /* 0x0C..0x0F */ + s16 x1, y1; /* 0x10, 0x12 */ + u8 r2, g2, b2, p2; /* 0x14..0x17 */ + s16 x2, y2; /* 0x18, 0x1A */ + u8 r3, g3, b3, p3; /* 0x1C..0x1F */ + s16 x3, y3; /* 0x20, 0x22 */ + } PG4_8018C960_80189EA0; /* -> 0x24 */ + + extern Env_8018C960_80189EA0 D_800AE7BC[]; + extern u8 aD801EF1EC __asm__("D_801E770C"); + extern u8 aD801EF1F0 __asm__("D_801E7710"); + + u32 **pp; + volatile u16 *pbh; + u32 *p; + u32 *r; + u8 c1, c2; + + pp = (u32 **)&D_801151D0; + pbh = (volatile u16 *)&D_800B9A02; + + p = *pp; + ((PTag_8018C960_80189EA0 *)p)->len = 1; + p[1] = 0xE1000015; + ((PTag_8018C960_80189EA0 *)p)->addr = ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + p += 2; + ((PG4_8018C960_80189EA0 *)p)->tag = 0x08000000; + ((PG4_8018C960_80189EA0 *)p)->code = 0x3A; + ((PG4_8018C960_80189EA0 *)p)->x2 = -160; + ((PG4_8018C960_80189EA0 *)p)->x0 = -160; + ((PG4_8018C960_80189EA0 *)p)->x3 = 160; + ((PG4_8018C960_80189EA0 *)p)->x1 = 160; + c1 = aD801EF1EC; + ((PG4_8018C960_80189EA0 *)p)->b1 = c1; + ((PG4_8018C960_80189EA0 *)p)->b0 = c1; + ((PG4_8018C960_80189EA0 *)p)->g1 = c1; + ((PG4_8018C960_80189EA0 *)p)->g0 = c1; + ((PG4_8018C960_80189EA0 *)p)->r1 = c1; + ((PG4_8018C960_80189EA0 *)p)->r0 = c1; + c2 = aD801EF1F0; + ((PG4_8018C960_80189EA0 *)p)->y1 = -120; + ((PG4_8018C960_80189EA0 *)p)->b3 = c2; + ((PG4_8018C960_80189EA0 *)p)->b2 = c2; + ((PG4_8018C960_80189EA0 *)p)->g3 = c2; + ((PG4_8018C960_80189EA0 *)p)->g2 = c2; + ((PG4_8018C960_80189EA0 *)p)->r3 = c2; + ((PG4_8018C960_80189EA0 *)p)->r2 = c2; + ((PG4_8018C960_80189EA0 *)p)->y0 = -120; + ((PG4_8018C960_80189EA0 *)p)->y3 = 120; + ((PG4_8018C960_80189EA0 *)p)->y2 = 120; + + ((PTag_8018C960_80189EA0 *)p)->addr = ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + r = p + 9; /* 0x24 */ + p = r; /* COMBINE BARRIER — see header */ + ((PTag_8018C960_80189EA0 *)r)->len = 1; + r[1] = 0xE1000240; + ((PTag_8018C960_80189EA0 *)r)->addr = ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189EA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)r; + + p += 2; + *pp = p; +} + INCLUDE_ASM("asm/ov_SC04_019/nonmatchings/ov_SC04_019_jr_801878E8", func_8018A0B4); @@ -3864,7 +3988,99 @@ void func_8018A94C(void *a0) { DEFINE_func_8018A988() /* dedup: shared engine-core @0x8018A988 (src/shared) */ -INCLUDE_ASM("asm/ov_SC04_019/nonmatchings/ov_SC04_019_jr_801878E8", func_8018A990); + +extern s32 func_8012BEE8(s32 a0); +extern s32 rand(void); + +void func_8018A990(s32 param_1) { + s32 uVar1; + s32 iVar2; + register s32 iVar3 __asm__("$3"); + register s32 iVar4 __asm__("$16"); + u32 uVar3; + + uVar1 = *(u16 *)(param_1 + 0x34); + if (uVar1 == 1) { + goto case1; + } + if (uVar1 < 2) { + if (uVar1 == 0) { + goto case0; + } + return; + } + if (uVar1 == 2) { + goto case2; + } + if (uVar1 != 3) { + return; + } + goto case3; + +case0: + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + iVar4 = uVar3 & 0x3fff; + iVar4 = iVar4 + 0x7800; + uVar3 = rand(); + if ((uVar3 & 1) == 0) { + iVar4 = -iVar4; + } + *(s32 *)(param_1 + 0xe0) = iVar4; + *(s32 *)(param_1 + 0xe4) = 0; + return; + +case1: + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + uVar3 = uVar3 & 0x3f; + goto tail; + +case2: + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + *(s32 *)(param_1 + 0xe4); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0xe0) = -*(s32 *)(param_1 + 0xe0); + return; + +case3: + __asm__ __volatile__("" ::: "memory"); + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = 0; + uVar3 = rand(); + uVar3 = uVar3 & 0xff; + +tail: + *(u32 *)(param_1 + 0x1c) = uVar3 + 0x40; +} + DEFINE_func_8018AB3C() /* dedup: shared engine-core @0x8018AB3C (src/shared) */ diff --git a/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c b/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c index d6ae93801..12e836c33 100644 --- a/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c +++ b/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c @@ -4226,7 +4226,50 @@ INCLUDE_ASM("asm/ov_SC05_003/nonmatchings/ov_SC05_003_jr_8017BEBC", func_801818B INCLUDE_ASM("asm/ov_SC05_003/nonmatchings/ov_SC05_003_jr_8017BEBC", func_80181A08); -INCLUDE_ASM("asm/ov_SC05_003/nonmatchings/ov_SC05_003_jr_8017BEBC", func_80181AAC); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_80181AAC(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC05_003/nonmatchings/ov_SC05_003_jr_8017BEBC", func_80181C00); diff --git a/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c b/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c index 023fd4416..f1a743461 100644 --- a/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c +++ b/src/ov_SC05_005/ov_SC05_005_jr_8017D898.c @@ -3866,7 +3866,50 @@ INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_801819C INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80181B10); -INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80181BB4); + +extern void func_8012931C(struct vec *a0); +extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); + +/* a0 = actor/entity base (struct vec-compatible; s16 fields at +6/+A/+E, s32 flag/vel at +0x14), + * a1 = s16[3] offset vector, a2 = mode passed through to func_8012CEB0. + * Same family as func_8012CC88 (src/ov_SC02_027/ov_SC02_027_jr_8012ACE0.c etc) but the + * position-integration step is a real call to func_8012931C instead of being inlined. */ +s32 func_80181BB4(s32 a0, s32 a1, s32 a2) { + SV3_8012CC88 sp10; + SV3_8012CC88 sp18; + s32 v0; + + sp10.vx = *(u16*)(a0 + 0x06); + sp10.vy = *(u16*)(a0 + 0x0A); + sp10.vz = *(u16*)(a0 + 0x0E); + sp10.vx += *(u16*)(a1 + 0); + sp10.vy += *(u16*)(a1 + 2); + sp10.vz += *(u16*)(a1 + 4); + + func_8012931C((struct vec *)a0); + + sp18.vx = *(u16*)(a0 + 0x06); + sp18.vy = *(u16*)(a0 + 0x0A); + sp18.vz = *(u16*)(a0 + 0x0E); + sp18.vx += *(u16*)(a1 + 0); + sp18.vy += *(u16*)(a1 + 2); + sp18.vz += *(u16*)(a1 + 4); + + v0 = func_8012CEB0((s32)&sp10, (s32)&sp18, a2); + + sp18.vx -= *(u16*)(a1 + 0); + sp18.vy -= *(u16*)(a1 + 2); + sp18.vz -= *(u16*)(a1 + 4); + *(s16*)(a0 + 0x06) = sp18.vx; + *(s16*)(a0 + 0x0A) = sp18.vy; + *(s16*)(a0 + 0x0E) = sp18.vz; + + if (v0 & 0x6000) { + *(s32*)(a0 + 0x14) = 0; + } + return v0; +} + INCLUDE_ASM("asm/ov_SC05_005/nonmatchings/ov_SC05_005_jr_8017D898", func_80181D08); diff --git a/src/ov_SC05_009/ov_SC05_009_jr_8017BEBC.c b/src/ov_SC05_009/ov_SC05_009_jr_8017BEBC.c index a781b4da2..c4b9c7da9 100644 --- a/src/ov_SC05_009/ov_SC05_009_jr_8017BEBC.c +++ b/src/ov_SC05_009/ov_SC05_009_jr_8017BEBC.c @@ -76,7 +76,6 @@ extern s32 func_80146128(void); extern void func_80146360(void); extern void func_801463A0(); extern void func_8014607C(void); -extern s32 *D_80126B78; extern u8 D_80078EC1; extern s32 D_80078EC8; extern s32 D_80126B9C; @@ -3681,7 +3680,101 @@ extern void func_800296F8(void); } -INCLUDE_ASM("asm/ov_SC05_009/nonmatchings/ov_SC05_009_jr_8017BEBC", func_8017E894); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_80172710(void); +extern s32 func_80178BF8(); +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §71 sibling: identical shape to func_8018F390 (same TU, this file, D_80126B78/RotTransSV/ + * func_80135888/func_8012BDBC/func_80178BF8/func_80172710 idiom) already MATCHED -- only the + * per-overlay data symbol (D_801939E0 vs D_801E33F0) differs. §37 asm-label alias avoids the + * `conflicting types` clash with the fleet's `extern void func_8017E894(void);` used elsewhere + * in this TU as a state-handler function pointer. */ + +s32 aF801904E0() __asm__("func_8017E894"); + +s32 aF801904E0(param_1) + void *param_1; +{ + + extern s32 *D_80126B78; + extern u8 D_801939E0[]; + MATRIX m; + s32 obj; + s32 sv0[2]; + s32 sv1[2]; + s32 flag; + + obj = *(s32 *)((s32)param_1 + 0x64); + m = *(MATRIX *)((u8 *)D_80126B78 + 0x34); + + gte_SetRotMatrix(&m); + gte_SetTransMatrix(&m); + + RotTransSV(D_801939E0, sv0, &flag); + RotTransSV(D_801939E0 + 8, sv1, &flag); + + if (func_80135888(*(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x20), + *(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x58), + (s32)sv0, (s32)sv1) == 0) { + return 0; + } + if (func_8012BDBC(obj, 0x300) == 0) { + return 0; + } + *(s16 *)(obj + 0x2) = 3; + func_80178BF8(); + return (s32)func_80172710; +} + INCLUDE_ASM("asm/ov_SC05_009/nonmatchings/ov_SC05_009_jr_8017BEBC", func_8017E9E8); diff --git a/src/ov_SC05_010/ov_SC05_010_jr_8017C8D0.c b/src/ov_SC05_010/ov_SC05_010_jr_8017C8D0.c index 7bea433a7..83186480f 100644 --- a/src/ov_SC05_010/ov_SC05_010_jr_8017C8D0.c +++ b/src/ov_SC05_010/ov_SC05_010_jr_8017C8D0.c @@ -3413,7 +3413,67 @@ void func_8017DFF0(void *a0) { } -INCLUDE_ASM("asm/ov_SC05_010/nonmatchings/ov_SC05_010_jr_8017C8D0", func_8017E02C); + + +extern s32 rand(void); + +typedef struct { + u16 f0; + u16 f2; + u16 f4; + u16 f6; + u16 f8; + u16 fA; + s32 fC; + s32 f10; + s32 f14; + s32 f18; +} SubRec_801EB5C8_8017E02C; /* 0x1C */ + +typedef struct { + u16 g0; + u16 g2; + s32 g4; + s32 g8; + s32 gC; + SubRec_801EB5C8_8017E02C subs[16]; +} GroupRec_801EB5C8_8017E02C; /* 0x1D0 */ + + +void func_8017E02C(s32 param_1) +{ + + extern GroupRec_801EB5C8_8017E02C D_801C6FA8[8]; + s32 i, j; + GroupRec_801EB5C8_8017E02C *grp; + SubRec_801EB5C8_8017E02C *sub; + + for (i = 0; i < 8; i++) { + grp = &D_801C6FA8[i]; + grp->g0 = 0; + grp->g2 = i << 9; + grp->gC = (rand() & 0xF) << 16; + grp->g4 = ((rand() & 0xF) << 15) + 0x10000; + grp->g8 = ((rand() & 0xF) << 12) + 0x8000; + + for (j = 0; j < 16; j++) { + sub = &grp->subs[j]; + sub->f0 = 0; + sub->f2 = (rand() & 3) + 4; + sub->f8 = (j << 8) + (rand() & 0xF) * 56; + sub->fA = (rand() & 0xF) << 8; + sub->f14 = (rand() & 0xF) << 13; + sub->fC = ((rand() & 0xF) << 14) + 0x10000; + sub->f10 = ((rand() & 0xF) << 12) + 0x8000; + sub->f4 = 0x200; + sub->f6 = (rand() & 0xF) << 4; + sub->f18 = ((rand() & 3) << 5) + 0x40; + } + } + + *(u16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC05_010/nonmatchings/ov_SC05_010_jr_8017C8D0", func_8017E1D4); diff --git a/src/ov_SC05_017/ov_SC05_017_jr_801875E8.c b/src/ov_SC05_017/ov_SC05_017_jr_801875E8.c index a2bf95848..d06c204d7 100644 --- a/src/ov_SC05_017/ov_SC05_017_jr_801875E8.c +++ b/src/ov_SC05_017/ov_SC05_017_jr_801875E8.c @@ -2982,22 +2982,16 @@ extern void func_801861AC(void); extern s16 D_800B9A02; extern u8 D_801151C8[]; -extern s32 D_801151D0; -extern s16 D_80115126; extern u16 D_80115112; -extern u16 D_8011511A; extern u8 D_80115138[]; extern u8 D_80115148[]; extern s32 D_80115130; extern u8 D_800B9A15; extern s16 D_801ED568; -extern u16 D_801ED56C; -extern s16 D_801ED570; extern s32 D_801ED560; extern s32 D_801ED564; extern s16 D_801ED5F0; -extern s16 D_801ED5F4; extern s16 D_801ED5F8; extern s16 D_801ED5FC; extern s16 D_801ED600; @@ -3032,6 +3026,18 @@ extern s32 func_80189240(s32 a0, s16 a1); extern s16 func_80189B54(s32 a0); void func_801875E8(void) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern u16 D_801ED56C; + extern s16 D_801ED570; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern s32 D_801151D0; + extern s16 D_801ED5F4; + extern s16 D_80115126; + extern u16 D_8011511A; s32 s0; s32 pad[2]; (void)&pad; @@ -3499,7 +3505,125 @@ INCLUDE_ASM("asm/ov_SC05_017/nonmatchings/ov_SC05_017_jr_801875E8", func_80189B1 INCLUDE_ASM("asm/ov_SC05_017/nonmatchings/ov_SC05_017_jr_801875E8", func_80189B54); -INCLUDE_ASM("asm/ov_SC05_017/nonmatchings/ov_SC05_017_jr_801875E8", func_80189BA0); + +/* func_80189BA0 — ov_SC03_001 (133 ins), exemplar of a 5-member open-only + * h_norm cluster. Builds the full-screen fade overlay: a DR_MODE-style 8-byte + * GP0 packet (0xE1000015), a 320x240 semi-transparent gouraud quad (POLY_G4, + * code 0x3A), and a second 8-byte GP0 packet (0xE1000240), each linked into the + * current OT with the psyq `addPrim` idiom. The type shapes and the + * `((PTag *)x)->addr = ((PTag *)ot)->addr; ((PTag *)ot)->addr = (u32)x;` pair + * are copied VERBATIM from the already-matched neighbour func_8018BCD4 in this + * same TU (§71) — Env_* / PTag_* there are the fleet-canonical shapes. + * + * Levers that were load-bearing (all byte-tested; the draft is PIN-FREE): + * §20 &D_801151D0 / &D_800B9A02 taken into pointer LOCALS -> each address is + * force_reg'd once (lui+addiu -> $t2 / $a3) instead of a %lo per use. + * §36 the 24-bit BITFIELD store, not a hand-written mask, is what emits + * 0x00FFFFFF (lui+ori) ahead of 0xFF000000 (lui) while the body ANDs the + * destination first — expmed's store_fixed_bit_field signature. + * §37 asm-label aliases for D_801ED56C/D_801ED570: the TU canon is u16/s16 + * but the target does a bare `lbu %lo(sym)`, and a plain block-scope + * `extern u8` would be a conflicting redeclaration. + * --- `volatile` on the OT index read keeps all SIX *pbh loads alive; a plain + * read cse-folds them and the function loses ~25 instructions. + * S1 the whole body is ONE branch-free basic block and every store ties at + * the same priority, so forward asm order == source statement order — + * the POLY_G4 block below is a literal transcription of the target. + * S2 `p` is destructively updated (multi-set -> no birthing boost) so its + * `addiu +8` floats up into the preceding load-delay gap, while `r` is a + * FRESH single-set local (boosted) so its `addiu +0x24` sinks to sit + * immediately before `sb 3($a0)`. Both placements are the target's. + * --- the bare `p = r;` before r's uses is a COMBINE BARRIER: without a SET + * of `p` between `r = p + 9` and r's first use, `can_combine_p` lets + * combine substitute `r` -> `p + 0x24` into every MEM offset and the + * `addiu` disappears entirely (and, at the tail, `p += 2` folds to + * `addiu $t3,$t3,0x2C` off the stale base instead of `addiu $t3,$a0,8`). + * It also fixes the register rotation for free — verified that adding or + * removing `register __asm__` pins on p/r/pbh is a byte no-op. + */ + +/* ---- TU-visible spellings (file scope of ov_SC03_001_jr_8018A3A8.c) ---- */ + +void func_80189BA0(void) { + + extern s32 D_801151D0; + extern u16 D_801ED56C; + extern s16 D_801ED570; + /* §100/§120: draft-local, uniquely-named types — they live in the BODY so + * they cannot collide with the TU's own Env_8018BCD4 / PTag_8018BCD4. */ + typedef struct { u32 addr : 24; u32 len : 8; } PTag_8018C960_80189BA0; + typedef struct { u32 *ot; u32 pad[4]; } Env_8018C960_80189BA0; /* 0x14 stride */ + typedef struct { + u32 tag; /* 0x00 */ + u8 r0, g0, b0, code; /* 0x04..0x07 */ + s16 x0, y0; /* 0x08, 0x0A */ + u8 r1, g1, b1, p1; /* 0x0C..0x0F */ + s16 x1, y1; /* 0x10, 0x12 */ + u8 r2, g2, b2, p2; /* 0x14..0x17 */ + s16 x2, y2; /* 0x18, 0x1A */ + u8 r3, g3, b3, p3; /* 0x1C..0x1F */ + s16 x3, y3; /* 0x20, 0x22 */ + } PG4_8018C960_80189BA0; /* -> 0x24 */ + + extern Env_8018C960_80189BA0 D_800AE7BC[]; + extern u8 aD801EF1EC __asm__("D_801ED56C"); + extern u8 aD801EF1F0 __asm__("D_801ED570"); + + u32 **pp; + volatile u16 *pbh; + u32 *p; + u32 *r; + u8 c1, c2; + + pp = (u32 **)&D_801151D0; + pbh = (volatile u16 *)&D_800B9A02; + + p = *pp; + ((PTag_8018C960_80189BA0 *)p)->len = 1; + p[1] = 0xE1000015; + ((PTag_8018C960_80189BA0 *)p)->addr = ((PTag_8018C960_80189BA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189BA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + p += 2; + ((PG4_8018C960_80189BA0 *)p)->tag = 0x08000000; + ((PG4_8018C960_80189BA0 *)p)->code = 0x3A; + ((PG4_8018C960_80189BA0 *)p)->x2 = -160; + ((PG4_8018C960_80189BA0 *)p)->x0 = -160; + ((PG4_8018C960_80189BA0 *)p)->x3 = 160; + ((PG4_8018C960_80189BA0 *)p)->x1 = 160; + c1 = aD801EF1EC; + ((PG4_8018C960_80189BA0 *)p)->b1 = c1; + ((PG4_8018C960_80189BA0 *)p)->b0 = c1; + ((PG4_8018C960_80189BA0 *)p)->g1 = c1; + ((PG4_8018C960_80189BA0 *)p)->g0 = c1; + ((PG4_8018C960_80189BA0 *)p)->r1 = c1; + ((PG4_8018C960_80189BA0 *)p)->r0 = c1; + c2 = aD801EF1F0; + ((PG4_8018C960_80189BA0 *)p)->y1 = -120; + ((PG4_8018C960_80189BA0 *)p)->b3 = c2; + ((PG4_8018C960_80189BA0 *)p)->b2 = c2; + ((PG4_8018C960_80189BA0 *)p)->g3 = c2; + ((PG4_8018C960_80189BA0 *)p)->g2 = c2; + ((PG4_8018C960_80189BA0 *)p)->r3 = c2; + ((PG4_8018C960_80189BA0 *)p)->r2 = c2; + ((PG4_8018C960_80189BA0 *)p)->y0 = -120; + ((PG4_8018C960_80189BA0 *)p)->y3 = 120; + ((PG4_8018C960_80189BA0 *)p)->y2 = 120; + + ((PTag_8018C960_80189BA0 *)p)->addr = ((PTag_8018C960_80189BA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189BA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)p; + + r = p + 9; /* 0x24 */ + p = r; /* COMBINE BARRIER — see header */ + ((PTag_8018C960_80189BA0 *)r)->len = 1; + r[1] = 0xE1000240; + ((PTag_8018C960_80189BA0 *)r)->addr = ((PTag_8018C960_80189BA0 *)D_800AE7BC[*pbh].ot)->addr; + ((PTag_8018C960_80189BA0 *)D_800AE7BC[*pbh].ot)->addr = (u32)r; + + p += 2; + *pp = p; +} + INCLUDE_ASM("asm/ov_SC05_017/nonmatchings/ov_SC05_017_jr_801875E8", func_80189DB4); @@ -3722,7 +3846,99 @@ void func_8018A64C(void *a0) { void func_8018A688(void) { } -INCLUDE_ASM("asm/ov_SC05_017/nonmatchings/ov_SC05_017_jr_801875E8", func_8018A690); + +extern s32 func_8012BEE8(s32 a0); +extern s32 rand(void); + +void func_8018A690(s32 param_1) { + s32 uVar1; + s32 iVar2; + register s32 iVar3 __asm__("$3"); + register s32 iVar4 __asm__("$16"); + u32 uVar3; + + uVar1 = *(u16 *)(param_1 + 0x34); + if (uVar1 == 1) { + goto case1; + } + if (uVar1 < 2) { + if (uVar1 == 0) { + goto case0; + } + return; + } + if (uVar1 == 2) { + goto case2; + } + if (uVar1 != 3) { + return; + } + goto case3; + +case0: + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + iVar4 = uVar3 & 0x3fff; + iVar4 = iVar4 + 0x7800; + uVar3 = rand(); + if ((uVar3 & 1) == 0) { + iVar4 = -iVar4; + } + *(s32 *)(param_1 + 0xe0) = iVar4; + *(s32 *)(param_1 + 0xe4) = 0; + return; + +case1: + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + uVar3 = rand(); + uVar3 = uVar3 & 0x3f; + goto tail; + +case2: + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + *(s32 *)(param_1 + 0xe4); + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(s32 *)(param_1 + 0x1c) = 0x40; + *(u16 *)(param_1 + 0x34) = *(u16 *)(param_1 + 0x34) + 1; + *(s32 *)(param_1 + 0xe0) = -*(s32 *)(param_1 + 0xe0); + return; + +case3: + __asm__ __volatile__("" ::: "memory"); + iVar3 = *(s32 *)(param_1 + 0xe4); + iVar3 = iVar3 + *(s32 *)(param_1 + 0xe0); + *(s32 *)(param_1 + 0xdc) = *(s32 *)(param_1 + 0xdc) + iVar3; + *(s32 *)(param_1 + 0xe4) = iVar3; + *(u16 *)(*(s32 *)(param_1 + 0x20) + 0x12) = *(u16 *)(param_1 + 0xde); + iVar2 = func_8012BEE8(param_1); + if (iVar2 == 0) { + return; + } + *(u16 *)(param_1 + 0x34) = 0; + uVar3 = rand(); + uVar3 = uVar3 & 0xff; + +tail: + *(u32 *)(param_1 + 0x1c) = uVar3 + 0x40; +} + extern void (*D_801E6814[])(void); diff --git a/src/ov_SC06_008/ov_SC06_008_jr_8017C294.c b/src/ov_SC06_008/ov_SC06_008_jr_8017C294.c index c6e955ff2..69e17fae2 100644 --- a/src/ov_SC06_008/ov_SC06_008_jr_8017C294.c +++ b/src/ov_SC06_008/ov_SC06_008_jr_8017C294.c @@ -7113,7 +7113,101 @@ extern void func_800296F8(void); } -INCLUDE_ASM("asm/ov_SC06_008/nonmatchings/ov_SC06_008_jr_8017C294", func_80184E94); +extern s32 func_8012BDBC(s32 a0, s32 a1); +extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); +extern void func_80172710(void); +extern s32 func_80178BF8(); +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetRotMatrix(r0) __asm__ volatile ( \ + "lw $12, 0( %0 );" \ + "lw $13, 4( %0 );" \ + "ctc2 $12, $0;" \ + "ctc2 $13, $1;" \ + "lw $12, 8( %0 );" \ + "lw $13, 12( %0 );" \ + "lw $14, 16( %0 );" \ + "ctc2 $12, $2;" \ + "ctc2 $13, $3;" \ + "ctc2 $14, $4" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) +#define gte_SetTransMatrix(r0) __asm__ volatile ( \ + "lw $12, 20( %0 );" \ + "lw $13, 24( %0 );" \ + "ctc2 $12, $5;" \ + "lw $14, 28( %0 );" \ + "ctc2 $13, $6;" \ + "ctc2 $14, $7" \ + : \ + : "r"( r0 ) \ + : "$12", "$13", "$14" ) + +/* §71 sibling: identical shape to func_8018F390 (same TU, this file, D_80126B78/RotTransSV/ + * func_80135888/func_8012BDBC/func_80178BF8/func_80172710 idiom) already MATCHED -- only the + * per-overlay data symbol (D_801A6BCC vs D_801E33F0) differs. §37 asm-label alias avoids the + * `conflicting types` clash with the fleet's `extern void func_80184E94(void);` used elsewhere + * in this TU as a state-handler function pointer. */ + +s32 aF801904E0() __asm__("func_80184E94"); + +s32 aF801904E0(param_1) + void *param_1; +{ + + extern s32 *D_80126B78; + extern u8 D_801A6BCC[]; + MATRIX m; + s32 obj; + s32 sv0[2]; + s32 sv1[2]; + s32 flag; + + obj = *(s32 *)((s32)param_1 + 0x64); + m = *(MATRIX *)((u8 *)D_80126B78 + 0x34); + + gte_SetRotMatrix(&m); + gte_SetTransMatrix(&m); + + RotTransSV(D_801A6BCC, sv0, &flag); + RotTransSV(D_801A6BCC + 8, sv1, &flag); + + if (func_80135888(*(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x20), + *(s32 *)(*(s32 *)((s32)param_1 + 0x64) + 0x58), + (s32)sv0, (s32)sv1) == 0) { + return 0; + } + if (func_8012BDBC(obj, 0x300) == 0) { + return 0; + } + *(s16 *)(obj + 0x2) = 3; + func_80178BF8(); + return (s32)func_80172710; +} + extern void (*D_801A75D0[])(void); diff --git a/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c b/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c index 677af8505..76b0f15d7 100644 --- a/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c +++ b/src/ov_SC06_010/ov_SC06_010_jr_8017A4AC.c @@ -4784,7 +4784,152 @@ void aF8017ED80(void *param_1) { } -INCLUDE_ASM("asm/ov_SC06_010/nonmatchings/ov_SC06_010_jr_8017A4AC", func_80181408); + +/* func_80181408 -- ov_SC06_008, TU ov_SC06_008_jr_8017C294.c (open-only h_norm + * cluster exemplar, 7 members). + * + * a0+0x0 : u16 active flag; 0 => early return. + * a0+0x84 : s16 sound cooldown timer. + * cooldown != 0 -> just decrement it. + * cooldown == 0 -> try to play a positional sound (RotTransPers screen + * projection of the parent's position, range-gated on + * screen X/Y, volume from the classic div-by-0xF0 / + * div-by-0x1E magic-constant idiom -- byte-proven sibling + * form is func_80181CF0 in this same TU, sndid 0x849 here + * vs 0x961 there), then unconditionally reset the timer + * to 0xA regardless of whether the sound actually played. + * a0+0xFC / 0xFE : running hit-combo accumulators, bumped by +/-0x280 every + * call (unconditional tail). + * Tail always calls ((void (*)(void *))func_80181234)(a0) (the TU's canonical decl for this + * symbol is void(void) -- S35 self-axis -- so this draft binds its own + * private extern with the asm's real void(void*) shape). + * + * Control flow is EXPLICIT goto/label, mirroring source-order block + * placement (gcc-2.7.2 lays out basic blocks in literal source order, not by + * fallthrough preference -- see the func_80181CF0 comment, same TU): the + * cooldown!=0 decrement is the SHORT block and sits out-of-line (jumped to), + * the cooldown==0 RTP+sound block is the LONG block and sits inline + * (fallthrough), matching the target's physical layout exactly. + * + * MATCH levers (byte-proven, 2026-08-05): + * 1. Naive `if(old!=0){cool=old-1;}else{...}` folds trivially: reorg.c's + * delay-slot filler steals the single-insn decrement into the `bnez`'s + * own delay slot and retargets the branch straight to the join label + * (2 ins short of target). The target instead keeps a genuine copy + * (`addu $v1,$v0,zero`) in the delay slot and a SEPARATE `addiu $v0,$v1,-1` + * at the decrement site. Reproduced by pinning a second variable + * `register s32 v1 __asm__("$3")`, assigned UNCONDITIONALLY right after + * the load (`v1 = old;`) -- the scheduler places that copy in the + * branch's delay slot on its own, and the decrement (`cool = v1 - 1`) + * can no longer be folded away. `cool` is separately pinned to + * `__asm__("$2")` so its other def sites (the three `cool = 0xA` early + * exits) don't drift onto $3 by coalescing with v1. + * 2. The tail's `sh $v0,0x84($s0)` / `addu $a0,$s0,zero` order (store off + * the callee-saved pointer BEFORE reloading it into the call-argument + * register) needed a `__asm__ __volatile__("":::"memory")` fence right + * after the store -- without it, sched1 hoists the independent a0-reload + * ahead of the store even when the reload is written later in source. + * 3. Frame is -0x38, 8 bytes (2 words) larger than the natural -0x30 the + * locals alone produce; `pad2[2]` (dead, address never read) inside `L` + * reserves them, mirroring func_80181CF0's own "dead aggregate sizes the + * frame" idiom. + */ + + +/* §37/§124 def-side asm-label alias (P30 S1d class lever): the TU declares + * `extern void func_80181408(void);` (L4082, L4091) for callers that invoke it with NO args, + * while the byte-true definition takes an s32 in $a0 -> `conflicting types`. Neither side can + * move (a no-prototype escape is illegal once a param promotes), so the DEFINITION gets a + * private C identifier and binds the emitted symbol with a GNU asm label. Zero blast radius: + * the TU's declaration never meets the definition, and the emitted symbol is unchanged. */ +void aF8017EF54(s32 a0) __asm__("func_80181408"); + +void aF8017EF54(s32 a0) +{ + extern void func_8004914C(void *a0); + extern void func_800491AC(void *a0); + extern void func_8002D4C8(s32 a0, s32 a1); + extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + extern u8 D_800AF648; + extern void func_80181234(void); + struct { + s16 v[3]; /* sp+0x10 */ + s16 pad1; /* sp+0x16 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + s32 pad2[2]; /* sp+0x24 -- dead, sizes the frame */ + } L; + + register s32 v1 __asm__("$3"); + register s32 cool __asm__("$2"); + s32 old; + + if (*(u16 *)(a0 + 0x0) == 0) { + return; + } + + old = *(s16 *)(a0 + 0x84); + v1 = old; + if (old != 0) { + goto L_dec; + } + + L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48); + L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C); + L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50); + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } + RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag); + + if (L.flag < 0) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[0] + 0xEF) & 0xFFFF) >= 0x1DF) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[1] + 0xB3) & 0xFFFF) >= 0x167) { + goto L_snd_skip; + } + + { + s32 sx = (s16)L.sxy[0]; + s32 av; + + av = sx; + if (sx < 0) { + av = -sx; + } + av = ((0xF0 - av) * 0x7F) / 0xF0; + sx = (sx + 0xF0) / 0x1E; + if (sx == 0x10) { + sx = 0xF; + } + sx = sx << 8; + func_8002D4C8(0x849, (av | (0x3000 | sx)) & 0xFFFF); + } + +L_snd_skip: + cool = 0xA; + goto L_join; + +L_dec: + cool = v1 - 1; + +L_join: + *(s16 *)(a0 + 0x84) = cool; + __asm__ __volatile__("" ::: "memory"); + + { + s32 p = a0; + *(u16 *)(p + 0xFC) = *(u16 *)(p + 0xFC) + 0x280; + *(u16 *)(p + 0xFE) = *(u16 *)(p + 0xFE) - 0x280; + ((void (*)(void *))func_80181234)((void *)p); + } +} + extern s32 rand(void); @@ -5124,7 +5269,97 @@ void func_80181F88(void *a0) { } -INCLUDE_ASM("asm/ov_SC06_010/nonmatchings/ov_SC06_010_jr_8017A4AC", func_80181FC4); + +/* SV4 is the TU-canonical name (src/shared/engine_types.h) for func_8012F214's + * in/out struct (see ov_SC06_008_jr_8017AE2C.c:3135, "SV4 svec" comment: func_8012F214 out). + * Isolated match_one has no include path to that header, so it is typedef'd + * locally here for the standalone compile only. */ + + +/* func_80181FC4 - ov_SC06_008 / ov_SC06_008_jr_8017C294 (93 ins) + * + * One-time init (guarded by state flag at +0x34): mirror the +0x64 sub-object's + * +0x20/+0x12 field into our own +0x20 sub-object, kick off two "core" calls, + * pick an entry from the 2-element 12-byte table D_801A4C64 (indexed by the + * s16 at +0x70), then call func_8012F214 with a zeroed input SV4 and read the + * first 3 fields of the output SV4 back into +6/+0xA/+0xE. Sets the countdown + * at +0x1c to 0x5a and marks the state flag +0x34 = 1. + * + * Always-executed tail: bump the +0x20 sub-object's +0x10/+0x12/+0x14 fields + * (reloading the +0x20 pointer fresh for each field -- no CSE across the + * intervening stores, straight literal translation), mirror +0x14 into +0xDC, + * call func_8012CBCC(a0) and test its return (canonical fleet decl is + * void func_8012CBCC(s32 a0); the return value is read via a function- + * pointer cast at the use site, per the established TU idiom -- see + * ov_SC03_099_jr_8017BEBC.c:5630 comment block). If (ret & 0x6000), decrement + * the +0xac counter (signed s16 compare-to-zero on the POST-decrement value -- + * gcc-2.7.2's sll-by-16/bnez idiom for a s16 local) and negate +0xDC into + * +0x14; on the counter hitting zero, call func_8012C218. Finally decrement + * the +0x1c countdown and call func_8012C218 again when IT hits zero. + */ + +extern void func_8012B2CC(s32 a0); +extern void func_8012B23C(s32 a0); +extern void func_8012B14C(s32 a0, s32 a1); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); +extern void func_8012CBCC(s32 a0); +extern void func_8012C218(void *a0); + + +void func_80181FC4(s32 a0) +{ + + extern s32 D_801A4C64; + SV4 in; + SV4 out; + s16 v1; + u16 uStack_c; + + if (*(u16 *)(a0 + 0x34) == 0) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(*(s32 *)(a0 + 0x64) + 0x20) + 0x12); + func_8012B2CC(a0); + func_8012B23C(a0); + func_8012B14C(a0, *(s16 *)(a0 + 0x70) * 12 + (s32)&D_801A4C64); + + in.a = 0; + in.b = 0; + in.c = 0x10; + func_8012F214(a0, (s32)&in, (s32)&out); + *(u16 *)(a0 + 6) = out.a; + *(u16 *)(a0 + 0xa) = out.b; + uStack_c = out.c; + *(s32 *)(a0 + 0x1c) = 0x5a; + *(u16 *)(a0 + 0x34) = 1; + *(u16 *)(a0 + 0xe) = uStack_c; + } + + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x10) += -0x80; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += 4; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x14) += *(u16 *)(a0 + 0xfc); + + *(s32 *)(a0 + 0xdc) = *(s32 *)(a0 + 0x14); + if ((((s32 (*)(s32))func_8012CBCC)(a0)) & 0x6000) { + register s32 negdc __asm__("$2"); + negdc = -*(s32 *)(a0 + 0xdc); + v1 = *(u16 *)(a0 + 0xac); + v1 -= 1; + *(s16 *)(a0 + 0xac) = v1; + *(s32 *)(a0 + 0x14) = negdc; + if (v1 == 0) { + func_8012C218((void *)a0); + } + } + + { + s32 iVar3 = *(s32 *)(a0 + 0x1c) - 1; + *(s32 *)(a0 + 0x1c) = iVar3; + if (iVar3 == 0) { + func_8012C218((void *)a0); + } + } +} + extern void (*D_801A4C7C[])(void); @@ -5633,7 +5868,86 @@ void func_8018315C(s32 a0) } -INCLUDE_ASM("asm/ov_SC06_010/nonmatchings/ov_SC06_010_jr_8017A4AC", func_80183560); + + +// TARGET: func_80183560 (ov_SC06_008, TU ov_SC06_008_jr_8017C294.c, 93 ins) +// +// Template: func_801821F8 in this SAME TU (src/ov_SC06_008/ov_SC06_008_jr_8017C294.c, +// around line 5283) is an already-MATCHED sibling (126 ins) with a documented byte-exact +// idiom set (its comment, verbatim): +// @class: plumbing +// @stuck: none — MATCH (126 ins). Keys: (1) cVar1 as `int` (not unsigned char) so the +// lbu-loaded byte stays full-width and gcc omits the per-compare `andi 0xff`; (2) uninitialized +// `int unaff_s1` -> $s1 (live-from-entry across func_8002D4C8); (3) func_8016AA50 takes TWO args +// (param_1, unaff_s1) — a1=unaff_s1 arg-setup is reused by the preceding subtraction and a0=s0 +// hoists into the branch delay slot; (4) 0x76 read UNSIGNED (lhu) in the subtract, SIGNED (lh) in +// the `< 1` test. +// +// func_80183560 is the SAME body with the leading "if (*(short*)(param_1+0xfc)==0) {...}" block +// (the 0x64-indirected 3x int-copy + 3x u16-copy prologue) removed, and the "already fired" gate +// field is 0xe2 instead of 0x102. Confirmed against the target .s: no reference anywhere to 0xfc, +// 0x64, or 0x102/0x20 offsets; the gate compare is `lh $v1, 0xE2($s0)` / `sh $v1(=0xA), 0xE2($s0)`. + +extern void func_8002D4C8(int, int); +extern void func_8016AA50(int, int); +extern s32 func_8016B428(s32); +extern void func_80019064(void *); +extern void func_8002A520(int); +extern void func_8002A790(int); +extern void func_80131E00(int, int); + +void func_80183560(int param_1) +{ + extern unsigned char D_801A7124[]; + int cVar1; + int unaff_s1; + + cVar1 = *(unsigned char *)(param_1 + 0x5e); + *(char *)(param_1 + 0xc1) = 0; + *(short *)(param_1 + 0x5e) = 0; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) & 0xfffe; + if (*(short *)(param_1 + 0xe2) == 0) { + *(short *)(param_1 + 0xe2) = 10; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) | 0x4000; + func_8002D4C8(0x9b7, 0); + if (*(short *)(param_1 + 0x60) != 0) { + if (cVar1 == 0x1d) { + *(short *)(param_1 + 0x82) = 0; + *(short *)(param_1 + 0x7c) = *(unsigned short *)(param_1 + 6); + *(short *)(param_1 + 0x7e) = *(unsigned short *)(param_1 + 0xa); + *(short *)(param_1 + 0x80) = *(unsigned short *)(param_1 + 0xe); + } + if (*(int *)(param_1 + 0x78) != 0) { + unaff_s1 = (int)*(short *)(param_1 + 0x60) * + (int)*(short *)(*(int *)(param_1 + 0x78) + 0x30) >> 0xc; + if (unaff_s1 < 1) { + unaff_s1 = 1; + } + } + *(unsigned short *)(param_1 + 0x76) = + *(unsigned short *)(param_1 + 0x76) - unaff_s1; + func_8016AA50(param_1, unaff_s1); + if ((*(unsigned short *)(param_1 + 0x82) & 1) != 0) { + ((void (*)(int))func_8016B428)(param_1); + func_80019064(D_801A7124); + } + } + if (cVar1 != 0x1d) { + if (*(unsigned char *)(param_1 + 0xc8) != 0) { + func_8002A520(param_1); + } + if (*(unsigned char *)(param_1 + 0xc9) != 0) { + func_8002A790(param_1); + } + } + if (*(short *)(param_1 + 0x76) < 1) { + *(short *)(param_1 + 0x5c) = 0; + func_80131E00(param_1, 6); + } + } + return; +} + // @class: schedule diff --git a/src/ov_SC06_018/ov_SC06_018_jr_8017C24C.c b/src/ov_SC06_018/ov_SC06_018_jr_8017C24C.c index a814989ad..6149932ba 100644 --- a/src/ov_SC06_018/ov_SC06_018_jr_8017C24C.c +++ b/src/ov_SC06_018/ov_SC06_018_jr_8017C24C.c @@ -3996,7 +3996,152 @@ void aF8017ED80(void *param_1) { } -INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_8017ED60); + +/* func_8017ED60 -- ov_SC06_008, TU ov_SC06_008_jr_8017C294.c (open-only h_norm + * cluster exemplar, 7 members). + * + * a0+0x0 : u16 active flag; 0 => early return. + * a0+0x84 : s16 sound cooldown timer. + * cooldown != 0 -> just decrement it. + * cooldown == 0 -> try to play a positional sound (RotTransPers screen + * projection of the parent's position, range-gated on + * screen X/Y, volume from the classic div-by-0xF0 / + * div-by-0x1E magic-constant idiom -- byte-proven sibling + * form is func_80181CF0 in this same TU, sndid 0x849 here + * vs 0x961 there), then unconditionally reset the timer + * to 0xA regardless of whether the sound actually played. + * a0+0xFC / 0xFE : running hit-combo accumulators, bumped by +/-0x280 every + * call (unconditional tail). + * Tail always calls ((void (*)(void *))func_8017EB8C)(a0) (the TU's canonical decl for this + * symbol is void(void) -- S35 self-axis -- so this draft binds its own + * private extern with the asm's real void(void*) shape). + * + * Control flow is EXPLICIT goto/label, mirroring source-order block + * placement (gcc-2.7.2 lays out basic blocks in literal source order, not by + * fallthrough preference -- see the func_80181CF0 comment, same TU): the + * cooldown!=0 decrement is the SHORT block and sits out-of-line (jumped to), + * the cooldown==0 RTP+sound block is the LONG block and sits inline + * (fallthrough), matching the target's physical layout exactly. + * + * MATCH levers (byte-proven, 2026-08-05): + * 1. Naive `if(old!=0){cool=old-1;}else{...}` folds trivially: reorg.c's + * delay-slot filler steals the single-insn decrement into the `bnez`'s + * own delay slot and retargets the branch straight to the join label + * (2 ins short of target). The target instead keeps a genuine copy + * (`addu $v1,$v0,zero`) in the delay slot and a SEPARATE `addiu $v0,$v1,-1` + * at the decrement site. Reproduced by pinning a second variable + * `register s32 v1 __asm__("$3")`, assigned UNCONDITIONALLY right after + * the load (`v1 = old;`) -- the scheduler places that copy in the + * branch's delay slot on its own, and the decrement (`cool = v1 - 1`) + * can no longer be folded away. `cool` is separately pinned to + * `__asm__("$2")` so its other def sites (the three `cool = 0xA` early + * exits) don't drift onto $3 by coalescing with v1. + * 2. The tail's `sh $v0,0x84($s0)` / `addu $a0,$s0,zero` order (store off + * the callee-saved pointer BEFORE reloading it into the call-argument + * register) needed a `__asm__ __volatile__("":::"memory")` fence right + * after the store -- without it, sched1 hoists the independent a0-reload + * ahead of the store even when the reload is written later in source. + * 3. Frame is -0x38, 8 bytes (2 words) larger than the natural -0x30 the + * locals alone produce; `pad2[2]` (dead, address never read) inside `L` + * reserves them, mirroring func_80181CF0's own "dead aggregate sizes the + * frame" idiom. + */ + + +/* §37/§124 def-side asm-label alias (P30 S1d class lever): the TU declares + * `extern void func_8017ED60(void);` (L4082, L4091) for callers that invoke it with NO args, + * while the byte-true definition takes an s32 in $a0 -> `conflicting types`. Neither side can + * move (a no-prototype escape is illegal once a param promotes), so the DEFINITION gets a + * private C identifier and binds the emitted symbol with a GNU asm label. Zero blast radius: + * the TU's declaration never meets the definition, and the emitted symbol is unchanged. */ +void aF8017EF54(s32 a0) __asm__("func_8017ED60"); + +void aF8017EF54(s32 a0) +{ + extern void func_8004914C(void *a0); + extern void func_800491AC(void *a0); + extern void func_8002D4C8(s32 a0, s32 a1); + extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + extern u8 D_800AF648; + extern void func_8017EB8C(s32); + struct { + s16 v[3]; /* sp+0x10 */ + s16 pad1; /* sp+0x16 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + s32 pad2[2]; /* sp+0x24 -- dead, sizes the frame */ + } L; + + register s32 v1 __asm__("$3"); + register s32 cool __asm__("$2"); + s32 old; + + if (*(u16 *)(a0 + 0x0) == 0) { + return; + } + + old = *(s16 *)(a0 + 0x84); + v1 = old; + if (old != 0) { + goto L_dec; + } + + L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48); + L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C); + L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50); + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } + RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag); + + if (L.flag < 0) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[0] + 0xEF) & 0xFFFF) >= 0x1DF) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[1] + 0xB3) & 0xFFFF) >= 0x167) { + goto L_snd_skip; + } + + { + s32 sx = (s16)L.sxy[0]; + s32 av; + + av = sx; + if (sx < 0) { + av = -sx; + } + av = ((0xF0 - av) * 0x7F) / 0xF0; + sx = (sx + 0xF0) / 0x1E; + if (sx == 0x10) { + sx = 0xF; + } + sx = sx << 8; + func_8002D4C8(0x849, (av | (0x3000 | sx)) & 0xFFFF); + } + +L_snd_skip: + cool = 0xA; + goto L_join; + +L_dec: + cool = v1 - 1; + +L_join: + *(s16 *)(a0 + 0x84) = cool; + __asm__ __volatile__("" ::: "memory"); + + { + s32 p = a0; + *(u16 *)(p + 0xFC) = *(u16 *)(p + 0xFC) + 0x280; + *(u16 *)(p + 0xFE) = *(u16 *)(p + 0xFE) - 0x280; + ((void (*)(void *))func_8017EB8C)((void *)p); + } +} + extern s32 rand(void); @@ -4845,7 +4990,86 @@ void func_80180AB4(s32 a0) } -INCLUDE_ASM("asm/ov_SC06_018/nonmatchings/ov_SC06_018_jr_8017C24C", func_80180EB8); + + +// TARGET: func_80180EB8 (ov_SC06_008, TU ov_SC06_008_jr_8017C294.c, 93 ins) +// +// Template: func_801821F8 in this SAME TU (src/ov_SC06_008/ov_SC06_008_jr_8017C294.c, +// around line 5283) is an already-MATCHED sibling (126 ins) with a documented byte-exact +// idiom set (its comment, verbatim): +// @class: plumbing +// @stuck: none — MATCH (126 ins). Keys: (1) cVar1 as `int` (not unsigned char) so the +// lbu-loaded byte stays full-width and gcc omits the per-compare `andi 0xff`; (2) uninitialized +// `int unaff_s1` -> $s1 (live-from-entry across func_8002D4C8); (3) func_8016AA50 takes TWO args +// (param_1, unaff_s1) — a1=unaff_s1 arg-setup is reused by the preceding subtraction and a0=s0 +// hoists into the branch delay slot; (4) 0x76 read UNSIGNED (lhu) in the subtract, SIGNED (lh) in +// the `< 1` test. +// +// func_80180EB8 is the SAME body with the leading "if (*(short*)(param_1+0xfc)==0) {...}" block +// (the 0x64-indirected 3x int-copy + 3x u16-copy prologue) removed, and the "already fired" gate +// field is 0xe2 instead of 0x102. Confirmed against the target .s: no reference anywhere to 0xfc, +// 0x64, or 0x102/0x20 offsets; the gate compare is `lh $v1, 0xE2($s0)` / `sh $v1(=0xA), 0xE2($s0)`. + +extern void func_8002D4C8(int, int); +extern void func_8016AA50(int, int); +extern s32 func_8016B428(s32); +extern void func_80019064(void *); +extern void func_8002A520(int); +extern void func_8002A790(int); +extern void func_80131E00(int, int); + +void func_80180EB8(int param_1) +{ + extern unsigned char D_801AD450[]; + int cVar1; + int unaff_s1; + + cVar1 = *(unsigned char *)(param_1 + 0x5e); + *(char *)(param_1 + 0xc1) = 0; + *(short *)(param_1 + 0x5e) = 0; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) & 0xfffe; + if (*(short *)(param_1 + 0xe2) == 0) { + *(short *)(param_1 + 0xe2) = 10; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) | 0x4000; + func_8002D4C8(0x9b7, 0); + if (*(short *)(param_1 + 0x60) != 0) { + if (cVar1 == 0x1d) { + *(short *)(param_1 + 0x82) = 0; + *(short *)(param_1 + 0x7c) = *(unsigned short *)(param_1 + 6); + *(short *)(param_1 + 0x7e) = *(unsigned short *)(param_1 + 0xa); + *(short *)(param_1 + 0x80) = *(unsigned short *)(param_1 + 0xe); + } + if (*(int *)(param_1 + 0x78) != 0) { + unaff_s1 = (int)*(short *)(param_1 + 0x60) * + (int)*(short *)(*(int *)(param_1 + 0x78) + 0x30) >> 0xc; + if (unaff_s1 < 1) { + unaff_s1 = 1; + } + } + *(unsigned short *)(param_1 + 0x76) = + *(unsigned short *)(param_1 + 0x76) - unaff_s1; + func_8016AA50(param_1, unaff_s1); + if ((*(unsigned short *)(param_1 + 0x82) & 1) != 0) { + ((void (*)(int))func_8016B428)(param_1); + func_80019064(D_801AD450); + } + } + if (cVar1 != 0x1d) { + if (*(unsigned char *)(param_1 + 0xc8) != 0) { + func_8002A520(param_1); + } + if (*(unsigned char *)(param_1 + 0xc9) != 0) { + func_8002A790(param_1); + } + } + if (*(short *)(param_1 + 0x76) < 1) { + *(short *)(param_1 + 0x5c) = 0; + func_80131E00(param_1, 6); + } + } + return; +} + // @class: schedule // @stuck: none — MATCH; success-block placed last via `goto big` (bnez forward into epilogue), single cae4 merge kept diff --git a/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c b/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c index 73b999998..b364a34a6 100644 --- a/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c +++ b/src/ov_SC06_020/ov_SC06_020_jr_80180B04.c @@ -2995,7 +2995,134 @@ store: } -INCLUDE_ASM("asm/ov_SC06_020/nonmatchings/ov_SC06_020_jr_80180B04", func_80181490); + +/* func_80181490 — walk the 0x60-entry / 0x10C-stride entity table D_801202A0 and + * react to the first neighbour of class 0x27A (get pushed away from it) or 0x2F4 + * (get clamped down onto it). + * + * §71 sibling-first: the callee signatures below are copied VERBATIM from this TU's + * own already-matched neighbours — func_8012B0B4 (TU L6971/7855/8177), func_8012B6D4 + * (TU L6419), func_8012CEB0 (TU L7226, the func_80187844 block), func_8012C098 + * (TU L5379) — and D_801202A0 is the TU's file-scope `extern u8 D_801202A0[];` (L384). + * func_8012BC60 / func_8012ADE4 are not declared in this TU; the forms below are the + * fleet-majority shapes (func_8012ADE4 verbatim; func_8012BC60 with `void *` instead of + * `struct Vec *` so the draft does not depend on engine_types.h being in scope). + * + * FIVE load-bearing constructs (do NOT "clean up"): + * + * 1. NO SECOND WALKED POINTER. All of +0x6/+0xA/+0xE are written as `*(T *)(p + k)` + * off the single biv `p`. combine_givs then merges the three DEST_ADDR givs onto + * ONE anchor = the LAST-emitted one (+0xE, from the case-0x2F4 `lh`), giving the + * target's `$s3 = $s2 + 0xE` with -0x8/-0x4/0x0 displacements. + * An explicit `q = p + 0xE` with `*(u16 *)q` looks equivalent and is NOT: + * gcc-2.7.2 excludes a bare `*q` (mult 1, add 0) from givs (find_mem_givs:4198), + * so q stays a live biv AND the remaining two accesses combine onto their own + * anchor +0xA => THREE IVs, the wrong anchor, and the $s6 hoist lost to pressure + * (measured: 111 ins, 87 mismatched). gcc-2.7.2-map/loop.md §L1 rules 4 & 6. + * + * 2. `switch`, not `if/else if`. The two-case switch is what emits the target's + * compare CHAIN with BOTH arms out of line (`beq`/`beq`/`j default`, 6 slots). + * An `if (id == 0x27A) ... else if (id == 0x2F4)` inverts the first test and lets + * the 0x27A arm fall through — 2 instructions short. + * + * 3. do-while with `i++` BEFORE `p += 0x10C`. strength_reduce inserts the reduced + * giv's `addiu` immediately before ITS biv's increment, so the source order + * i-then-p is what produces `addiu $s4,$s4,1` / `addiu $s3,$s3,0x10C` / + * (delay) `addiu $s2,$s2,0x10C`. A `for (i = 0; i < 0x60; i++)` with `p += 0x10C` + * last puts the giv add first and swaps the pair. + * + * 4. `self4` and `sc` are REAL pre-loop locals, in that order. Both are loop + * invariants; written inline as `(s16 *)(a0 + 4)` / `(unsigned int *)sp20` at the + * call, combine folds the address straight into the argument move + * (`addiu $a0,$sp,0x20`) and the target's `$s6 = $sp + 0x20` hoist never happens. + * Assigning them in a *different basic block* from their uses is what keeps the + * pseudos alive; the declaration ORDER (p, i, self4, sc) is what gives + * $s2/$s4/$s5/$s6 in the target's prologue emission order. + * + * 5. `s16 y` (a SHORT local), and `s32 sp20[2]` (an EIGHT-byte scratch). + * - The short local is why `y` gets a second pseudo: gcc-2.7.2 emits + * `(set (reg:HI B) (subreg:HI (reg:SI A)))` for the HImode assignment, i.e. the + * target's `addu $a1,$a0,$zero` in the branch delay slot, with the two `- 0x60` + * recomputed from A ($a0, the compare) and B ($a1, the stored value). + * An `s32 y` coalesces the pair away and loses that instruction. + * - The short local also costs a DEAD 4-byte reload home at the top of the frame + * (`(use (mem:SI (plus $sp 48)))` in the greg dump, no insn references it). + * That is exactly why the func_8012B0B4 buffer is 8 bytes, not 16: 0x10 + 8 + * (v10) + 8 (v18) + 8 (sp20) + 4 (dead) rounds to 0x30 = the target's first + * saved-register slot. 8 bytes also matches the fleet's canonical shape for a + * func_8012B0B4 output buffer (`unsigned int buf[2]`). + */ + + +extern s32 func_8012BC60(void *a0, void *a1); +extern s32 func_8012B6D4(s16 *a0, s16 *a1); +extern void func_8012B0B4(unsigned int *p, int a1, int a2); +extern s32 func_8012CEB0(void *a0, void *a1, s32 a2); +extern void func_8012ADE4(u8 *a0); +extern void func_8012C098(void *param_1); + +void func_80181490(s32 a0) { + + extern u8 D_801202A0[]; + u8 *p; + s16 *self4; + unsigned int *sc; + s32 i; + s16 y; + s32 z; + s32 ang; + s16 v10[4]; /* sp+0x10 */ + s16 v18[4]; /* sp+0x18 */ + s32 sp20[2]; /* sp+0x20 — func_8012B0B4 output */ + + p = D_801202A0; + i = 0; + self4 = (s16 *)(a0 + 4); + sc = (unsigned int *)sp20; + do { + if ((u8 *)a0 != p) { + switch (*(u16 *)p) { + case 0x27A: + if (func_8012BC60((void *)self4, (void *)(p + 4)) < 0x6400) { + ang = func_8012B6D4(self4, (s16 *)(p + 4)); + func_8012B0B4(sc, ang, 0xA1); + v18[0] = *(u16 *)(p + 6); + v18[1] = *(u16 *)(p + 0xA); + v18[2] = *(u16 *)(p + 0xE); + v18[0] += sp20[0]; + v18[2] += sp20[0] >> 16; + v18[1] = *(u16 *)(a0 + 0xA); + v10[0] = *(u16 *)(a0 + 0x3A); + v10[1] = *(u16 *)(a0 + 0x3E); + v10[2] = *(u16 *)(a0 + 0x42); + if ((func_8012CEB0(v10, v18, 0) & 0x2000) == 0) { + func_8012ADE4((u8 *)a0); + return; + } + *(u16 *)(a0 + 6) = v18[0]; + *(u16 *)(a0 + 0xA) = v18[1]; + *(u16 *)(a0 + 0xE) = v18[2]; + return; + } + break; + case 0x2F4: + y = *(s16 *)(p + 0xE); + z = *(s16 *)(a0 + 0xE); + if (y + 0x10 < z) { + func_8012C098((void *)a0); + return; + } + if (y - 0x60 < z) { + *(s16 *)(a0 + 0xE) = y - 0x60; + } + break; + } + } + i++; + p += 0x10C; + } while (i < 0x60); +} + INCLUDE_ASM("asm/ov_SC06_020/nonmatchings/ov_SC06_020_jr_80180B04", func_80181654); diff --git a/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c b/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c index fd9752e02..c6edea9ff 100644 --- a/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c +++ b/src/ov_SC06_022/ov_SC06_022_jr_8017BEBC.c @@ -4408,7 +4408,134 @@ store: } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_801853B4); + +/* func_801853B4 — walk the 0x60-entry / 0x10C-stride entity table D_801202A0 and + * react to the first neighbour of class 0x27A (get pushed away from it) or 0x2F4 + * (get clamped down onto it). + * + * §71 sibling-first: the callee signatures below are copied VERBATIM from this TU's + * own already-matched neighbours — func_8012B0B4 (TU L6971/7855/8177), func_8012B6D4 + * (TU L6419), func_8012CEB0 (TU L7226, the func_80187844 block), func_8012C098 + * (TU L5379) — and D_801202A0 is the TU's file-scope `extern u8 D_801202A0[];` (L384). + * func_8012BC60 / func_8012ADE4 are not declared in this TU; the forms below are the + * fleet-majority shapes (func_8012ADE4 verbatim; func_8012BC60 with `void *` instead of + * `struct Vec *` so the draft does not depend on engine_types.h being in scope). + * + * FIVE load-bearing constructs (do NOT "clean up"): + * + * 1. NO SECOND WALKED POINTER. All of +0x6/+0xA/+0xE are written as `*(T *)(p + k)` + * off the single biv `p`. combine_givs then merges the three DEST_ADDR givs onto + * ONE anchor = the LAST-emitted one (+0xE, from the case-0x2F4 `lh`), giving the + * target's `$s3 = $s2 + 0xE` with -0x8/-0x4/0x0 displacements. + * An explicit `q = p + 0xE` with `*(u16 *)q` looks equivalent and is NOT: + * gcc-2.7.2 excludes a bare `*q` (mult 1, add 0) from givs (find_mem_givs:4198), + * so q stays a live biv AND the remaining two accesses combine onto their own + * anchor +0xA => THREE IVs, the wrong anchor, and the $s6 hoist lost to pressure + * (measured: 111 ins, 87 mismatched). gcc-2.7.2-map/loop.md §L1 rules 4 & 6. + * + * 2. `switch`, not `if/else if`. The two-case switch is what emits the target's + * compare CHAIN with BOTH arms out of line (`beq`/`beq`/`j default`, 6 slots). + * An `if (id == 0x27A) ... else if (id == 0x2F4)` inverts the first test and lets + * the 0x27A arm fall through — 2 instructions short. + * + * 3. do-while with `i++` BEFORE `p += 0x10C`. strength_reduce inserts the reduced + * giv's `addiu` immediately before ITS biv's increment, so the source order + * i-then-p is what produces `addiu $s4,$s4,1` / `addiu $s3,$s3,0x10C` / + * (delay) `addiu $s2,$s2,0x10C`. A `for (i = 0; i < 0x60; i++)` with `p += 0x10C` + * last puts the giv add first and swaps the pair. + * + * 4. `self4` and `sc` are REAL pre-loop locals, in that order. Both are loop + * invariants; written inline as `(s16 *)(a0 + 4)` / `(unsigned int *)sp20` at the + * call, combine folds the address straight into the argument move + * (`addiu $a0,$sp,0x20`) and the target's `$s6 = $sp + 0x20` hoist never happens. + * Assigning them in a *different basic block* from their uses is what keeps the + * pseudos alive; the declaration ORDER (p, i, self4, sc) is what gives + * $s2/$s4/$s5/$s6 in the target's prologue emission order. + * + * 5. `s16 y` (a SHORT local), and `s32 sp20[2]` (an EIGHT-byte scratch). + * - The short local is why `y` gets a second pseudo: gcc-2.7.2 emits + * `(set (reg:HI B) (subreg:HI (reg:SI A)))` for the HImode assignment, i.e. the + * target's `addu $a1,$a0,$zero` in the branch delay slot, with the two `- 0x60` + * recomputed from A ($a0, the compare) and B ($a1, the stored value). + * An `s32 y` coalesces the pair away and loses that instruction. + * - The short local also costs a DEAD 4-byte reload home at the top of the frame + * (`(use (mem:SI (plus $sp 48)))` in the greg dump, no insn references it). + * That is exactly why the func_8012B0B4 buffer is 8 bytes, not 16: 0x10 + 8 + * (v10) + 8 (v18) + 8 (sp20) + 4 (dead) rounds to 0x30 = the target's first + * saved-register slot. 8 bytes also matches the fleet's canonical shape for a + * func_8012B0B4 output buffer (`unsigned int buf[2]`). + */ + + +extern s32 func_8012BC60(void *a0, void *a1); +extern s32 func_8012B6D4(s16 *a0, s16 *a1); +extern void func_8012B0B4(unsigned int *p, int a1, int a2); +extern s32 func_8012CEB0(void *a0, void *a1, s32 a2); +extern void func_8012ADE4(u8 *a0); +extern void func_8012C098(void *param_1); + +void func_801853B4(s32 a0) { + + extern u8 D_801202A0[]; + u8 *p; + s16 *self4; + unsigned int *sc; + s32 i; + s16 y; + s32 z; + s32 ang; + s16 v10[4]; /* sp+0x10 */ + s16 v18[4]; /* sp+0x18 */ + s32 sp20[2]; /* sp+0x20 — func_8012B0B4 output */ + + p = D_801202A0; + i = 0; + self4 = (s16 *)(a0 + 4); + sc = (unsigned int *)sp20; + do { + if ((u8 *)a0 != p) { + switch (*(u16 *)p) { + case 0x27A: + if (func_8012BC60((void *)self4, (void *)(p + 4)) < 0x6400) { + ang = func_8012B6D4(self4, (s16 *)(p + 4)); + func_8012B0B4(sc, ang, 0xA1); + v18[0] = *(u16 *)(p + 6); + v18[1] = *(u16 *)(p + 0xA); + v18[2] = *(u16 *)(p + 0xE); + v18[0] += sp20[0]; + v18[2] += sp20[0] >> 16; + v18[1] = *(u16 *)(a0 + 0xA); + v10[0] = *(u16 *)(a0 + 0x3A); + v10[1] = *(u16 *)(a0 + 0x3E); + v10[2] = *(u16 *)(a0 + 0x42); + if ((func_8012CEB0(v10, v18, 0) & 0x2000) == 0) { + func_8012ADE4((u8 *)a0); + return; + } + *(u16 *)(a0 + 6) = v18[0]; + *(u16 *)(a0 + 0xA) = v18[1]; + *(u16 *)(a0 + 0xE) = v18[2]; + return; + } + break; + case 0x2F4: + y = *(s16 *)(p + 0xE); + z = *(s16 *)(a0 + 0xE); + if (y + 0x10 < z) { + func_8012C098((void *)a0); + return; + } + if (y - 0x60 < z) { + *(s16 *)(a0 + 0xE) = y - 0x60; + } + break; + } + } + i++; + p += 0x10C; + } while (i < 0x60); +} + INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_80185578); @@ -5927,7 +6054,86 @@ void func_80188964(s32 a0) } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_80188D68); + + +// TARGET: func_80188D68 (ov_SC06_008, TU ov_SC06_008_jr_8017C294.c, 93 ins) +// +// Template: func_801821F8 in this SAME TU (src/ov_SC06_008/ov_SC06_008_jr_8017C294.c, +// around line 5283) is an already-MATCHED sibling (126 ins) with a documented byte-exact +// idiom set (its comment, verbatim): +// @class: plumbing +// @stuck: none — MATCH (126 ins). Keys: (1) cVar1 as `int` (not unsigned char) so the +// lbu-loaded byte stays full-width and gcc omits the per-compare `andi 0xff`; (2) uninitialized +// `int unaff_s1` -> $s1 (live-from-entry across func_8002D4C8); (3) func_8016AA50 takes TWO args +// (param_1, unaff_s1) — a1=unaff_s1 arg-setup is reused by the preceding subtraction and a0=s0 +// hoists into the branch delay slot; (4) 0x76 read UNSIGNED (lhu) in the subtract, SIGNED (lh) in +// the `< 1` test. +// +// func_80188D68 is the SAME body with the leading "if (*(short*)(param_1+0xfc)==0) {...}" block +// (the 0x64-indirected 3x int-copy + 3x u16-copy prologue) removed, and the "already fired" gate +// field is 0xe2 instead of 0x102. Confirmed against the target .s: no reference anywhere to 0xfc, +// 0x64, or 0x102/0x20 offsets; the gate compare is `lh $v1, 0xE2($s0)` / `sh $v1(=0xA), 0xE2($s0)`. + +extern void func_8002D4C8(int, int); +extern void func_8016AA50(int, int); +extern s32 func_8016B428(s32); +extern void func_80019064(void *); +extern void func_8002A520(int); +extern void func_8002A790(int); +extern void func_80131E00(int, int); + +void func_80188D68(int param_1) +{ + extern unsigned char D_801D5A38[]; + int cVar1; + int unaff_s1; + + cVar1 = *(unsigned char *)(param_1 + 0x5e); + *(char *)(param_1 + 0xc1) = 0; + *(short *)(param_1 + 0x5e) = 0; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) & 0xfffe; + if (*(short *)(param_1 + 0xe2) == 0) { + *(short *)(param_1 + 0xe2) = 10; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) | 0x4000; + func_8002D4C8(0x9b7, 0); + if (*(short *)(param_1 + 0x60) != 0) { + if (cVar1 == 0x1d) { + *(short *)(param_1 + 0x82) = 0; + *(short *)(param_1 + 0x7c) = *(unsigned short *)(param_1 + 6); + *(short *)(param_1 + 0x7e) = *(unsigned short *)(param_1 + 0xa); + *(short *)(param_1 + 0x80) = *(unsigned short *)(param_1 + 0xe); + } + if (*(int *)(param_1 + 0x78) != 0) { + unaff_s1 = (int)*(short *)(param_1 + 0x60) * + (int)*(short *)(*(int *)(param_1 + 0x78) + 0x30) >> 0xc; + if (unaff_s1 < 1) { + unaff_s1 = 1; + } + } + *(unsigned short *)(param_1 + 0x76) = + *(unsigned short *)(param_1 + 0x76) - unaff_s1; + func_8016AA50(param_1, unaff_s1); + if ((*(unsigned short *)(param_1 + 0x82) & 1) != 0) { + ((void (*)(int))func_8016B428)(param_1); + func_80019064(D_801D5A38); + } + } + if (cVar1 != 0x1d) { + if (*(unsigned char *)(param_1 + 0xc8) != 0) { + func_8002A520(param_1); + } + if (*(unsigned char *)(param_1 + 0xc9) != 0) { + func_8002A790(param_1); + } + } + if (*(short *)(param_1 + 0x76) < 1) { + *(short *)(param_1 + 0x5c) = 0; + func_80131E00(param_1, 6); + } + } + return; +} + // @class: schedule @@ -7396,7 +7602,152 @@ void aF8017ED80(void *param_1) { } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_8018BBBC); + +/* func_8018BBBC -- ov_SC06_008, TU ov_SC06_008_jr_8017C294.c (open-only h_norm + * cluster exemplar, 7 members). + * + * a0+0x0 : u16 active flag; 0 => early return. + * a0+0x84 : s16 sound cooldown timer. + * cooldown != 0 -> just decrement it. + * cooldown == 0 -> try to play a positional sound (RotTransPers screen + * projection of the parent's position, range-gated on + * screen X/Y, volume from the classic div-by-0xF0 / + * div-by-0x1E magic-constant idiom -- byte-proven sibling + * form is func_80181CF0 in this same TU, sndid 0x849 here + * vs 0x961 there), then unconditionally reset the timer + * to 0xA regardless of whether the sound actually played. + * a0+0xFC / 0xFE : running hit-combo accumulators, bumped by +/-0x280 every + * call (unconditional tail). + * Tail always calls ((void (*)(void *))func_8018B9E8)(a0) (the TU's canonical decl for this + * symbol is void(void) -- S35 self-axis -- so this draft binds its own + * private extern with the asm's real void(void*) shape). + * + * Control flow is EXPLICIT goto/label, mirroring source-order block + * placement (gcc-2.7.2 lays out basic blocks in literal source order, not by + * fallthrough preference -- see the func_80181CF0 comment, same TU): the + * cooldown!=0 decrement is the SHORT block and sits out-of-line (jumped to), + * the cooldown==0 RTP+sound block is the LONG block and sits inline + * (fallthrough), matching the target's physical layout exactly. + * + * MATCH levers (byte-proven, 2026-08-05): + * 1. Naive `if(old!=0){cool=old-1;}else{...}` folds trivially: reorg.c's + * delay-slot filler steals the single-insn decrement into the `bnez`'s + * own delay slot and retargets the branch straight to the join label + * (2 ins short of target). The target instead keeps a genuine copy + * (`addu $v1,$v0,zero`) in the delay slot and a SEPARATE `addiu $v0,$v1,-1` + * at the decrement site. Reproduced by pinning a second variable + * `register s32 v1 __asm__("$3")`, assigned UNCONDITIONALLY right after + * the load (`v1 = old;`) -- the scheduler places that copy in the + * branch's delay slot on its own, and the decrement (`cool = v1 - 1`) + * can no longer be folded away. `cool` is separately pinned to + * `__asm__("$2")` so its other def sites (the three `cool = 0xA` early + * exits) don't drift onto $3 by coalescing with v1. + * 2. The tail's `sh $v0,0x84($s0)` / `addu $a0,$s0,zero` order (store off + * the callee-saved pointer BEFORE reloading it into the call-argument + * register) needed a `__asm__ __volatile__("":::"memory")` fence right + * after the store -- without it, sched1 hoists the independent a0-reload + * ahead of the store even when the reload is written later in source. + * 3. Frame is -0x38, 8 bytes (2 words) larger than the natural -0x30 the + * locals alone produce; `pad2[2]` (dead, address never read) inside `L` + * reserves them, mirroring func_80181CF0's own "dead aggregate sizes the + * frame" idiom. + */ + + +/* §37/§124 def-side asm-label alias (P30 S1d class lever): the TU declares + * `extern void func_8018BBBC(void);` (L4082, L4091) for callers that invoke it with NO args, + * while the byte-true definition takes an s32 in $a0 -> `conflicting types`. Neither side can + * move (a no-prototype escape is illegal once a param promotes), so the DEFINITION gets a + * private C identifier and binds the emitted symbol with a GNU asm label. Zero blast radius: + * the TU's declaration never meets the definition, and the emitted symbol is unchanged. */ +void aF8017EF54(s32 a0) __asm__("func_8018BBBC"); + +void aF8017EF54(s32 a0) +{ + extern void func_8004914C(void *a0); + extern void func_800491AC(void *a0); + extern void func_8002D4C8(s32 a0, s32 a1); + extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + extern u8 D_800AF648; + extern void func_8018B9E8(void); + struct { + s16 v[3]; /* sp+0x10 */ + s16 pad1; /* sp+0x16 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + s32 pad2[2]; /* sp+0x24 -- dead, sizes the frame */ + } L; + + register s32 v1 __asm__("$3"); + register s32 cool __asm__("$2"); + s32 old; + + if (*(u16 *)(a0 + 0x0) == 0) { + return; + } + + old = *(s16 *)(a0 + 0x84); + v1 = old; + if (old != 0) { + goto L_dec; + } + + L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48); + L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C); + L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50); + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } + RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag); + + if (L.flag < 0) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[0] + 0xEF) & 0xFFFF) >= 0x1DF) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[1] + 0xB3) & 0xFFFF) >= 0x167) { + goto L_snd_skip; + } + + { + s32 sx = (s16)L.sxy[0]; + s32 av; + + av = sx; + if (sx < 0) { + av = -sx; + } + av = ((0xF0 - av) * 0x7F) / 0xF0; + sx = (sx + 0xF0) / 0x1E; + if (sx == 0x10) { + sx = 0xF; + } + sx = sx << 8; + func_8002D4C8(0x849, (av | (0x3000 | sx)) & 0xFFFF); + } + +L_snd_skip: + cool = 0xA; + goto L_join; + +L_dec: + cool = v1 - 1; + +L_join: + *(s16 *)(a0 + 0x84) = cool; + __asm__ __volatile__("" ::: "memory"); + + { + s32 p = a0; + *(u16 *)(p + 0xFC) = *(u16 *)(p + 0xFC) + 0x280; + *(u16 *)(p + 0xFE) = *(u16 *)(p + 0xFE) - 0x280; + ((void (*)(void *))func_8018B9E8)((void *)p); + } +} + extern s32 rand(void); @@ -7736,7 +8087,97 @@ void func_8018C73C(void *a0) { } -INCLUDE_ASM("asm/ov_SC06_022/nonmatchings/ov_SC06_022_jr_8017BEBC", func_8018C778); + +/* SV4 is the TU-canonical name (src/shared/engine_types.h) for func_8012F214's + * in/out struct (see ov_SC06_008_jr_8017AE2C.c:3135, "SV4 svec" comment: func_8012F214 out). + * Isolated match_one has no include path to that header, so it is typedef'd + * locally here for the standalone compile only. */ + + +/* func_8018C778 - ov_SC06_008 / ov_SC06_008_jr_8017C294 (93 ins) + * + * One-time init (guarded by state flag at +0x34): mirror the +0x64 sub-object's + * +0x20/+0x12 field into our own +0x20 sub-object, kick off two "core" calls, + * pick an entry from the 2-element 12-byte table D_801DD6BC (indexed by the + * s16 at +0x70), then call func_8012F214 with a zeroed input SV4 and read the + * first 3 fields of the output SV4 back into +6/+0xA/+0xE. Sets the countdown + * at +0x1c to 0x5a and marks the state flag +0x34 = 1. + * + * Always-executed tail: bump the +0x20 sub-object's +0x10/+0x12/+0x14 fields + * (reloading the +0x20 pointer fresh for each field -- no CSE across the + * intervening stores, straight literal translation), mirror +0x14 into +0xDC, + * call func_8012CBCC(a0) and test its return (canonical fleet decl is + * void func_8012CBCC(s32 a0); the return value is read via a function- + * pointer cast at the use site, per the established TU idiom -- see + * ov_SC03_099_jr_8017BEBC.c:5630 comment block). If (ret & 0x6000), decrement + * the +0xac counter (signed s16 compare-to-zero on the POST-decrement value -- + * gcc-2.7.2's sll-by-16/bnez idiom for a s16 local) and negate +0xDC into + * +0x14; on the counter hitting zero, call func_8012C218. Finally decrement + * the +0x1c countdown and call func_8012C218 again when IT hits zero. + */ + +extern void func_8012B2CC(s32 a0); +extern void func_8012B23C(s32 a0); +extern void func_8012B14C(s32 a0, s32 a1); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); +extern void func_8012CBCC(s32 a0); +extern void func_8012C218(void *a0); + + +void func_8018C778(s32 a0) +{ + + extern s32 D_801DD6BC; + SV4 in; + SV4 out; + s16 v1; + u16 uStack_c; + + if (*(u16 *)(a0 + 0x34) == 0) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(*(s32 *)(a0 + 0x64) + 0x20) + 0x12); + func_8012B2CC(a0); + func_8012B23C(a0); + func_8012B14C(a0, *(s16 *)(a0 + 0x70) * 12 + (s32)&D_801DD6BC); + + in.a = 0; + in.b = 0; + in.c = 0x10; + func_8012F214(a0, (s32)&in, (s32)&out); + *(u16 *)(a0 + 6) = out.a; + *(u16 *)(a0 + 0xa) = out.b; + uStack_c = out.c; + *(s32 *)(a0 + 0x1c) = 0x5a; + *(u16 *)(a0 + 0x34) = 1; + *(u16 *)(a0 + 0xe) = uStack_c; + } + + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x10) += -0x80; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += 4; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x14) += *(u16 *)(a0 + 0xfc); + + *(s32 *)(a0 + 0xdc) = *(s32 *)(a0 + 0x14); + if ((((s32 (*)(s32))func_8012CBCC)(a0)) & 0x6000) { + register s32 negdc __asm__("$2"); + negdc = -*(s32 *)(a0 + 0xdc); + v1 = *(u16 *)(a0 + 0xac); + v1 -= 1; + *(s16 *)(a0 + 0xac) = v1; + *(s32 *)(a0 + 0x14) = negdc; + if (v1 == 0) { + func_8012C218((void *)a0); + } + } + + { + s32 iVar3 = *(s32 *)(a0 + 0x1c) - 1; + *(s32 *)(a0 + 0x1c) = iVar3; + if (iVar3 == 0) { + func_8012C218((void *)a0); + } + } +} + extern void (*D_801DD6D4[])(void); diff --git a/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c b/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c index e07c3b6e3..2f74a569d 100644 --- a/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c +++ b/src/ov_SC06_024/ov_SC06_024_jr_8017BEBC.c @@ -5055,7 +5055,134 @@ store: } -INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_8017BEBC", func_8018788C); + +/* func_8018788C — walk the 0x60-entry / 0x10C-stride entity table D_801202A0 and + * react to the first neighbour of class 0x27A (get pushed away from it) or 0x2F4 + * (get clamped down onto it). + * + * §71 sibling-first: the callee signatures below are copied VERBATIM from this TU's + * own already-matched neighbours — func_8012B0B4 (TU L6971/7855/8177), func_8012B6D4 + * (TU L6419), func_8012CEB0 (TU L7226, the func_80187844 block), func_8012C098 + * (TU L5379) — and D_801202A0 is the TU's file-scope `extern u8 D_801202A0[];` (L384). + * func_8012BC60 / func_8012ADE4 are not declared in this TU; the forms below are the + * fleet-majority shapes (func_8012ADE4 verbatim; func_8012BC60 with `void *` instead of + * `struct Vec *` so the draft does not depend on engine_types.h being in scope). + * + * FIVE load-bearing constructs (do NOT "clean up"): + * + * 1. NO SECOND WALKED POINTER. All of +0x6/+0xA/+0xE are written as `*(T *)(p + k)` + * off the single biv `p`. combine_givs then merges the three DEST_ADDR givs onto + * ONE anchor = the LAST-emitted one (+0xE, from the case-0x2F4 `lh`), giving the + * target's `$s3 = $s2 + 0xE` with -0x8/-0x4/0x0 displacements. + * An explicit `q = p + 0xE` with `*(u16 *)q` looks equivalent and is NOT: + * gcc-2.7.2 excludes a bare `*q` (mult 1, add 0) from givs (find_mem_givs:4198), + * so q stays a live biv AND the remaining two accesses combine onto their own + * anchor +0xA => THREE IVs, the wrong anchor, and the $s6 hoist lost to pressure + * (measured: 111 ins, 87 mismatched). gcc-2.7.2-map/loop.md §L1 rules 4 & 6. + * + * 2. `switch`, not `if/else if`. The two-case switch is what emits the target's + * compare CHAIN with BOTH arms out of line (`beq`/`beq`/`j default`, 6 slots). + * An `if (id == 0x27A) ... else if (id == 0x2F4)` inverts the first test and lets + * the 0x27A arm fall through — 2 instructions short. + * + * 3. do-while with `i++` BEFORE `p += 0x10C`. strength_reduce inserts the reduced + * giv's `addiu` immediately before ITS biv's increment, so the source order + * i-then-p is what produces `addiu $s4,$s4,1` / `addiu $s3,$s3,0x10C` / + * (delay) `addiu $s2,$s2,0x10C`. A `for (i = 0; i < 0x60; i++)` with `p += 0x10C` + * last puts the giv add first and swaps the pair. + * + * 4. `self4` and `sc` are REAL pre-loop locals, in that order. Both are loop + * invariants; written inline as `(s16 *)(a0 + 4)` / `(unsigned int *)sp20` at the + * call, combine folds the address straight into the argument move + * (`addiu $a0,$sp,0x20`) and the target's `$s6 = $sp + 0x20` hoist never happens. + * Assigning them in a *different basic block* from their uses is what keeps the + * pseudos alive; the declaration ORDER (p, i, self4, sc) is what gives + * $s2/$s4/$s5/$s6 in the target's prologue emission order. + * + * 5. `s16 y` (a SHORT local), and `s32 sp20[2]` (an EIGHT-byte scratch). + * - The short local is why `y` gets a second pseudo: gcc-2.7.2 emits + * `(set (reg:HI B) (subreg:HI (reg:SI A)))` for the HImode assignment, i.e. the + * target's `addu $a1,$a0,$zero` in the branch delay slot, with the two `- 0x60` + * recomputed from A ($a0, the compare) and B ($a1, the stored value). + * An `s32 y` coalesces the pair away and loses that instruction. + * - The short local also costs a DEAD 4-byte reload home at the top of the frame + * (`(use (mem:SI (plus $sp 48)))` in the greg dump, no insn references it). + * That is exactly why the func_8012B0B4 buffer is 8 bytes, not 16: 0x10 + 8 + * (v10) + 8 (v18) + 8 (sp20) + 4 (dead) rounds to 0x30 = the target's first + * saved-register slot. 8 bytes also matches the fleet's canonical shape for a + * func_8012B0B4 output buffer (`unsigned int buf[2]`). + */ + + +extern s32 func_8012BC60(void *a0, void *a1); +extern s32 func_8012B6D4(s16 *a0, s16 *a1); +extern void func_8012B0B4(unsigned int *p, int a1, int a2); +extern s32 func_8012CEB0(void *a0, void *a1, s32 a2); +extern void func_8012ADE4(u8 *a0); +extern void func_8012C098(void *param_1); + +void func_8018788C(s32 a0) { + + extern u8 D_801202A0[]; + u8 *p; + s16 *self4; + unsigned int *sc; + s32 i; + s16 y; + s32 z; + s32 ang; + s16 v10[4]; /* sp+0x10 */ + s16 v18[4]; /* sp+0x18 */ + s32 sp20[2]; /* sp+0x20 — func_8012B0B4 output */ + + p = D_801202A0; + i = 0; + self4 = (s16 *)(a0 + 4); + sc = (unsigned int *)sp20; + do { + if ((u8 *)a0 != p) { + switch (*(u16 *)p) { + case 0x27A: + if (func_8012BC60((void *)self4, (void *)(p + 4)) < 0x6400) { + ang = func_8012B6D4(self4, (s16 *)(p + 4)); + func_8012B0B4(sc, ang, 0xA1); + v18[0] = *(u16 *)(p + 6); + v18[1] = *(u16 *)(p + 0xA); + v18[2] = *(u16 *)(p + 0xE); + v18[0] += sp20[0]; + v18[2] += sp20[0] >> 16; + v18[1] = *(u16 *)(a0 + 0xA); + v10[0] = *(u16 *)(a0 + 0x3A); + v10[1] = *(u16 *)(a0 + 0x3E); + v10[2] = *(u16 *)(a0 + 0x42); + if ((func_8012CEB0(v10, v18, 0) & 0x2000) == 0) { + func_8012ADE4((u8 *)a0); + return; + } + *(u16 *)(a0 + 6) = v18[0]; + *(u16 *)(a0 + 0xA) = v18[1]; + *(u16 *)(a0 + 0xE) = v18[2]; + return; + } + break; + case 0x2F4: + y = *(s16 *)(p + 0xE); + z = *(s16 *)(a0 + 0xE); + if (y + 0x10 < z) { + func_8012C098((void *)a0); + return; + } + if (y - 0x60 < z) { + *(s16 *)(a0 + 0xE) = y - 0x60; + } + break; + } + } + i++; + p += 0x10C; + } while (i < 0x60); +} + INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_8017BEBC", func_80187A50); @@ -6572,7 +6699,86 @@ void func_8018AE3C(s32 a0) } -INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_8017BEBC", func_8018B240); + + +// TARGET: func_8018B240 (ov_SC06_008, TU ov_SC06_008_jr_8017C294.c, 93 ins) +// +// Template: func_801821F8 in this SAME TU (src/ov_SC06_008/ov_SC06_008_jr_8017C294.c, +// around line 5283) is an already-MATCHED sibling (126 ins) with a documented byte-exact +// idiom set (its comment, verbatim): +// @class: plumbing +// @stuck: none — MATCH (126 ins). Keys: (1) cVar1 as `int` (not unsigned char) so the +// lbu-loaded byte stays full-width and gcc omits the per-compare `andi 0xff`; (2) uninitialized +// `int unaff_s1` -> $s1 (live-from-entry across func_8002D4C8); (3) func_8016AA50 takes TWO args +// (param_1, unaff_s1) — a1=unaff_s1 arg-setup is reused by the preceding subtraction and a0=s0 +// hoists into the branch delay slot; (4) 0x76 read UNSIGNED (lhu) in the subtract, SIGNED (lh) in +// the `< 1` test. +// +// func_8018B240 is the SAME body with the leading "if (*(short*)(param_1+0xfc)==0) {...}" block +// (the 0x64-indirected 3x int-copy + 3x u16-copy prologue) removed, and the "already fired" gate +// field is 0xe2 instead of 0x102. Confirmed against the target .s: no reference anywhere to 0xfc, +// 0x64, or 0x102/0x20 offsets; the gate compare is `lh $v1, 0xE2($s0)` / `sh $v1(=0xA), 0xE2($s0)`. + +extern void func_8002D4C8(int, int); +extern void func_8016AA50(int, int); +extern s32 func_8016B428(s32); +extern void func_80019064(void *); +extern void func_8002A520(int); +extern void func_8002A790(int); +extern void func_80131E00(int, int); + +void func_8018B240(int param_1) +{ + extern unsigned char D_801D4B7C[]; + int cVar1; + int unaff_s1; + + cVar1 = *(unsigned char *)(param_1 + 0x5e); + *(char *)(param_1 + 0xc1) = 0; + *(short *)(param_1 + 0x5e) = 0; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) & 0xfffe; + if (*(short *)(param_1 + 0xe2) == 0) { + *(short *)(param_1 + 0xe2) = 10; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) | 0x4000; + func_8002D4C8(0x9b7, 0); + if (*(short *)(param_1 + 0x60) != 0) { + if (cVar1 == 0x1d) { + *(short *)(param_1 + 0x82) = 0; + *(short *)(param_1 + 0x7c) = *(unsigned short *)(param_1 + 6); + *(short *)(param_1 + 0x7e) = *(unsigned short *)(param_1 + 0xa); + *(short *)(param_1 + 0x80) = *(unsigned short *)(param_1 + 0xe); + } + if (*(int *)(param_1 + 0x78) != 0) { + unaff_s1 = (int)*(short *)(param_1 + 0x60) * + (int)*(short *)(*(int *)(param_1 + 0x78) + 0x30) >> 0xc; + if (unaff_s1 < 1) { + unaff_s1 = 1; + } + } + *(unsigned short *)(param_1 + 0x76) = + *(unsigned short *)(param_1 + 0x76) - unaff_s1; + func_8016AA50(param_1, unaff_s1); + if ((*(unsigned short *)(param_1 + 0x82) & 1) != 0) { + ((void (*)(int))func_8016B428)(param_1); + func_80019064(D_801D4B7C); + } + } + if (cVar1 != 0x1d) { + if (*(unsigned char *)(param_1 + 0xc8) != 0) { + func_8002A520(param_1); + } + if (*(unsigned char *)(param_1 + 0xc9) != 0) { + func_8002A790(param_1); + } + } + if (*(short *)(param_1 + 0x76) < 1) { + *(short *)(param_1 + 0x5c) = 0; + func_80131E00(param_1, 6); + } + } + return; +} + // @class: schedule @@ -8038,7 +8244,152 @@ void aF8017ED80(void *param_1) { } -INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_8017BEBC", func_8018E094); + +/* func_8018E094 -- ov_SC06_008, TU ov_SC06_008_jr_8017C294.c (open-only h_norm + * cluster exemplar, 7 members). + * + * a0+0x0 : u16 active flag; 0 => early return. + * a0+0x84 : s16 sound cooldown timer. + * cooldown != 0 -> just decrement it. + * cooldown == 0 -> try to play a positional sound (RotTransPers screen + * projection of the parent's position, range-gated on + * screen X/Y, volume from the classic div-by-0xF0 / + * div-by-0x1E magic-constant idiom -- byte-proven sibling + * form is func_80181CF0 in this same TU, sndid 0x849 here + * vs 0x961 there), then unconditionally reset the timer + * to 0xA regardless of whether the sound actually played. + * a0+0xFC / 0xFE : running hit-combo accumulators, bumped by +/-0x280 every + * call (unconditional tail). + * Tail always calls ((void (*)(void *))func_8018DEC0)(a0) (the TU's canonical decl for this + * symbol is void(void) -- S35 self-axis -- so this draft binds its own + * private extern with the asm's real void(void*) shape). + * + * Control flow is EXPLICIT goto/label, mirroring source-order block + * placement (gcc-2.7.2 lays out basic blocks in literal source order, not by + * fallthrough preference -- see the func_80181CF0 comment, same TU): the + * cooldown!=0 decrement is the SHORT block and sits out-of-line (jumped to), + * the cooldown==0 RTP+sound block is the LONG block and sits inline + * (fallthrough), matching the target's physical layout exactly. + * + * MATCH levers (byte-proven, 2026-08-05): + * 1. Naive `if(old!=0){cool=old-1;}else{...}` folds trivially: reorg.c's + * delay-slot filler steals the single-insn decrement into the `bnez`'s + * own delay slot and retargets the branch straight to the join label + * (2 ins short of target). The target instead keeps a genuine copy + * (`addu $v1,$v0,zero`) in the delay slot and a SEPARATE `addiu $v0,$v1,-1` + * at the decrement site. Reproduced by pinning a second variable + * `register s32 v1 __asm__("$3")`, assigned UNCONDITIONALLY right after + * the load (`v1 = old;`) -- the scheduler places that copy in the + * branch's delay slot on its own, and the decrement (`cool = v1 - 1`) + * can no longer be folded away. `cool` is separately pinned to + * `__asm__("$2")` so its other def sites (the three `cool = 0xA` early + * exits) don't drift onto $3 by coalescing with v1. + * 2. The tail's `sh $v0,0x84($s0)` / `addu $a0,$s0,zero` order (store off + * the callee-saved pointer BEFORE reloading it into the call-argument + * register) needed a `__asm__ __volatile__("":::"memory")` fence right + * after the store -- without it, sched1 hoists the independent a0-reload + * ahead of the store even when the reload is written later in source. + * 3. Frame is -0x38, 8 bytes (2 words) larger than the natural -0x30 the + * locals alone produce; `pad2[2]` (dead, address never read) inside `L` + * reserves them, mirroring func_80181CF0's own "dead aggregate sizes the + * frame" idiom. + */ + + +/* §37/§124 def-side asm-label alias (P30 S1d class lever): the TU declares + * `extern void func_8018E094(void);` (L4082, L4091) for callers that invoke it with NO args, + * while the byte-true definition takes an s32 in $a0 -> `conflicting types`. Neither side can + * move (a no-prototype escape is illegal once a param promotes), so the DEFINITION gets a + * private C identifier and binds the emitted symbol with a GNU asm label. Zero blast radius: + * the TU's declaration never meets the definition, and the emitted symbol is unchanged. */ +void aF8017EF54(s32 a0) __asm__("func_8018E094"); + +void aF8017EF54(s32 a0) +{ + extern void func_8004914C(void *a0); + extern void func_800491AC(void *a0); + extern void func_8002D4C8(s32 a0, s32 a1); + extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + extern u8 D_800AF648; + extern void func_8018DEC0(void); + struct { + s16 v[3]; /* sp+0x10 */ + s16 pad1; /* sp+0x16 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + s32 pad2[2]; /* sp+0x24 -- dead, sizes the frame */ + } L; + + register s32 v1 __asm__("$3"); + register s32 cool __asm__("$2"); + s32 old; + + if (*(u16 *)(a0 + 0x0) == 0) { + return; + } + + old = *(s16 *)(a0 + 0x84); + v1 = old; + if (old != 0) { + goto L_dec; + } + + L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48); + L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C); + L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50); + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } + RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag); + + if (L.flag < 0) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[0] + 0xEF) & 0xFFFF) >= 0x1DF) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[1] + 0xB3) & 0xFFFF) >= 0x167) { + goto L_snd_skip; + } + + { + s32 sx = (s16)L.sxy[0]; + s32 av; + + av = sx; + if (sx < 0) { + av = -sx; + } + av = ((0xF0 - av) * 0x7F) / 0xF0; + sx = (sx + 0xF0) / 0x1E; + if (sx == 0x10) { + sx = 0xF; + } + sx = sx << 8; + func_8002D4C8(0x849, (av | (0x3000 | sx)) & 0xFFFF); + } + +L_snd_skip: + cool = 0xA; + goto L_join; + +L_dec: + cool = v1 - 1; + +L_join: + *(s16 *)(a0 + 0x84) = cool; + __asm__ __volatile__("" ::: "memory"); + + { + s32 p = a0; + *(u16 *)(p + 0xFC) = *(u16 *)(p + 0xFC) + 0x280; + *(u16 *)(p + 0xFE) = *(u16 *)(p + 0xFE) - 0x280; + ((void (*)(void *))func_8018DEC0)((void *)p); + } +} + extern s32 rand(void); @@ -8378,7 +8729,97 @@ void func_8018EC14(void *a0) { } -INCLUDE_ASM("asm/ov_SC06_024/nonmatchings/ov_SC06_024_jr_8017BEBC", func_8018EC50); + +/* SV4 is the TU-canonical name (src/shared/engine_types.h) for func_8012F214's + * in/out struct (see ov_SC06_008_jr_8017AE2C.c:3135, "SV4 svec" comment: func_8012F214 out). + * Isolated match_one has no include path to that header, so it is typedef'd + * locally here for the standalone compile only. */ + + +/* func_8018EC50 - ov_SC06_008 / ov_SC06_008_jr_8017C294 (93 ins) + * + * One-time init (guarded by state flag at +0x34): mirror the +0x64 sub-object's + * +0x20/+0x12 field into our own +0x20 sub-object, kick off two "core" calls, + * pick an entry from the 2-element 12-byte table D_801DC800 (indexed by the + * s16 at +0x70), then call func_8012F214 with a zeroed input SV4 and read the + * first 3 fields of the output SV4 back into +6/+0xA/+0xE. Sets the countdown + * at +0x1c to 0x5a and marks the state flag +0x34 = 1. + * + * Always-executed tail: bump the +0x20 sub-object's +0x10/+0x12/+0x14 fields + * (reloading the +0x20 pointer fresh for each field -- no CSE across the + * intervening stores, straight literal translation), mirror +0x14 into +0xDC, + * call func_8012CBCC(a0) and test its return (canonical fleet decl is + * void func_8012CBCC(s32 a0); the return value is read via a function- + * pointer cast at the use site, per the established TU idiom -- see + * ov_SC03_099_jr_8017BEBC.c:5630 comment block). If (ret & 0x6000), decrement + * the +0xac counter (signed s16 compare-to-zero on the POST-decrement value -- + * gcc-2.7.2's sll-by-16/bnez idiom for a s16 local) and negate +0xDC into + * +0x14; on the counter hitting zero, call func_8012C218. Finally decrement + * the +0x1c countdown and call func_8012C218 again when IT hits zero. + */ + +extern void func_8012B2CC(s32 a0); +extern void func_8012B23C(s32 a0); +extern void func_8012B14C(s32 a0, s32 a1); +extern void func_8012F214(s32 a0, s32 a1, s32 a2); +extern void func_8012CBCC(s32 a0); +extern void func_8012C218(s32); + + +void func_8018EC50(s32 a0) +{ + + extern s32 D_801DC800; + SV4 in; + SV4 out; + s16 v1; + u16 uStack_c; + + if (*(u16 *)(a0 + 0x34) == 0) { + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) = + *(u16 *)(*(s32 *)(*(s32 *)(a0 + 0x64) + 0x20) + 0x12); + func_8012B2CC(a0); + func_8012B23C(a0); + func_8012B14C(a0, *(s16 *)(a0 + 0x70) * 12 + (s32)&D_801DC800); + + in.a = 0; + in.b = 0; + in.c = 0x10; + func_8012F214(a0, (s32)&in, (s32)&out); + *(u16 *)(a0 + 6) = out.a; + *(u16 *)(a0 + 0xa) = out.b; + uStack_c = out.c; + *(s32 *)(a0 + 0x1c) = 0x5a; + *(u16 *)(a0 + 0x34) = 1; + *(u16 *)(a0 + 0xe) = uStack_c; + } + + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x10) += -0x80; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x12) += 4; + *(u16 *)(*(s32 *)(a0 + 0x20) + 0x14) += *(u16 *)(a0 + 0xfc); + + *(s32 *)(a0 + 0xdc) = *(s32 *)(a0 + 0x14); + if ((((s32 (*)(s32))func_8012CBCC)(a0)) & 0x6000) { + register s32 negdc __asm__("$2"); + negdc = -*(s32 *)(a0 + 0xdc); + v1 = *(u16 *)(a0 + 0xac); + v1 -= 1; + *(s16 *)(a0 + 0xac) = v1; + *(s32 *)(a0 + 0x14) = negdc; + if (v1 == 0) { + ((void (*)(void *))func_8012C218)((void *)a0); + } + } + + { + s32 iVar3 = *(s32 *)(a0 + 0x1c) - 1; + *(s32 *)(a0 + 0x1c) = iVar3; + if (iVar3 == 0) { + ((void (*)(void *))func_8012C218)((void *)a0); + } + } +} + extern void (*D_801DC818[])(void); diff --git a/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c b/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c index 98c824592..b0412023a 100644 --- a/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c +++ b/src/ov_SC06_029/ov_SC06_029_jr_8017C954.c @@ -3419,7 +3419,67 @@ void func_8017DBFC(void *a0) { } -INCLUDE_ASM("asm/ov_SC06_029/nonmatchings/ov_SC06_029_jr_8017C954", func_8017DC38); + + +extern s32 rand(void); + +typedef struct { + u16 f0; + u16 f2; + u16 f4; + u16 f6; + u16 f8; + u16 fA; + s32 fC; + s32 f10; + s32 f14; + s32 f18; +} SubRec_801EB5C8_8017DC38; /* 0x1C */ + +typedef struct { + u16 g0; + u16 g2; + s32 g4; + s32 g8; + s32 gC; + SubRec_801EB5C8_8017DC38 subs[16]; +} GroupRec_801EB5C8_8017DC38; /* 0x1D0 */ + + +void func_8017DC38(s32 param_1) +{ + + extern GroupRec_801EB5C8_8017DC38 D_801DCCA8[8]; + s32 i, j; + GroupRec_801EB5C8_8017DC38 *grp; + SubRec_801EB5C8_8017DC38 *sub; + + for (i = 0; i < 8; i++) { + grp = &D_801DCCA8[i]; + grp->g0 = 0; + grp->g2 = i << 9; + grp->gC = (rand() & 0xF) << 16; + grp->g4 = ((rand() & 0xF) << 15) + 0x10000; + grp->g8 = ((rand() & 0xF) << 12) + 0x8000; + + for (j = 0; j < 16; j++) { + sub = &grp->subs[j]; + sub->f0 = 0; + sub->f2 = (rand() & 3) + 4; + sub->f8 = (j << 8) + (rand() & 0xF) * 56; + sub->fA = (rand() & 0xF) << 8; + sub->f14 = (rand() & 0xF) << 13; + sub->fC = ((rand() & 0xF) << 14) + 0x10000; + sub->f10 = ((rand() & 0xF) << 12) + 0x8000; + sub->f4 = 0x200; + sub->f6 = (rand() & 0xF) << 4; + sub->f18 = ((rand() & 3) << 5) + 0x40; + } + } + + *(u16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC06_029/nonmatchings/ov_SC06_029_jr_8017C954", func_8017DDE0); diff --git a/src/ov_SC06_033/ov_SC06_033_jr_8017C24C.c b/src/ov_SC06_033/ov_SC06_033_jr_8017C24C.c index e7fa16029..93ca2d9cc 100644 --- a/src/ov_SC06_033/ov_SC06_033_jr_8017C24C.c +++ b/src/ov_SC06_033/ov_SC06_033_jr_8017C24C.c @@ -4287,7 +4287,86 @@ void func_8017F53C(s32 a0) } -INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8017F940); + + +// TARGET: func_8017F940 (ov_SC06_008, TU ov_SC06_008_jr_8017C294.c, 93 ins) +// +// Template: func_801821F8 in this SAME TU (src/ov_SC06_008/ov_SC06_008_jr_8017C294.c, +// around line 5283) is an already-MATCHED sibling (126 ins) with a documented byte-exact +// idiom set (its comment, verbatim): +// @class: plumbing +// @stuck: none — MATCH (126 ins). Keys: (1) cVar1 as `int` (not unsigned char) so the +// lbu-loaded byte stays full-width and gcc omits the per-compare `andi 0xff`; (2) uninitialized +// `int unaff_s1` -> $s1 (live-from-entry across func_8002D4C8); (3) func_8016AA50 takes TWO args +// (param_1, unaff_s1) — a1=unaff_s1 arg-setup is reused by the preceding subtraction and a0=s0 +// hoists into the branch delay slot; (4) 0x76 read UNSIGNED (lhu) in the subtract, SIGNED (lh) in +// the `< 1` test. +// +// func_8017F940 is the SAME body with the leading "if (*(short*)(param_1+0xfc)==0) {...}" block +// (the 0x64-indirected 3x int-copy + 3x u16-copy prologue) removed, and the "already fired" gate +// field is 0xe2 instead of 0x102. Confirmed against the target .s: no reference anywhere to 0xfc, +// 0x64, or 0x102/0x20 offsets; the gate compare is `lh $v1, 0xE2($s0)` / `sh $v1(=0xA), 0xE2($s0)`. + +extern void func_8002D4C8(int, int); +extern void func_8016AA50(int, int); +extern s32 func_8016B428(s32); +extern void func_80019064(void *); +extern void func_8002A520(int); +extern void func_8002A790(int); +extern void func_80131E00(int, int); + +void func_8017F940(int param_1) +{ + extern unsigned char D_801A7C74[]; + int cVar1; + int unaff_s1; + + cVar1 = *(unsigned char *)(param_1 + 0x5e); + *(char *)(param_1 + 0xc1) = 0; + *(short *)(param_1 + 0x5e) = 0; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) & 0xfffe; + if (*(short *)(param_1 + 0xe2) == 0) { + *(short *)(param_1 + 0xe2) = 10; + *(unsigned short *)(param_1 + 0x5c) = *(unsigned short *)(param_1 + 0x5c) | 0x4000; + func_8002D4C8(0x9b7, 0); + if (*(short *)(param_1 + 0x60) != 0) { + if (cVar1 == 0x1d) { + *(short *)(param_1 + 0x82) = 0; + *(short *)(param_1 + 0x7c) = *(unsigned short *)(param_1 + 6); + *(short *)(param_1 + 0x7e) = *(unsigned short *)(param_1 + 0xa); + *(short *)(param_1 + 0x80) = *(unsigned short *)(param_1 + 0xe); + } + if (*(int *)(param_1 + 0x78) != 0) { + unaff_s1 = (int)*(short *)(param_1 + 0x60) * + (int)*(short *)(*(int *)(param_1 + 0x78) + 0x30) >> 0xc; + if (unaff_s1 < 1) { + unaff_s1 = 1; + } + } + *(unsigned short *)(param_1 + 0x76) = + *(unsigned short *)(param_1 + 0x76) - unaff_s1; + func_8016AA50(param_1, unaff_s1); + if ((*(unsigned short *)(param_1 + 0x82) & 1) != 0) { + ((void (*)(int))func_8016B428)(param_1); + func_80019064(D_801A7C74); + } + } + if (cVar1 != 0x1d) { + if (*(unsigned char *)(param_1 + 0xc8) != 0) { + func_8002A520(param_1); + } + if (*(unsigned char *)(param_1 + 0xc9) != 0) { + func_8002A790(param_1); + } + } + if (*(short *)(param_1 + 0x76) < 1) { + *(short *)(param_1 + 0x5c) = 0; + func_80131E00(param_1, 6); + } + } + return; +} + // @class: schedule @@ -6346,7 +6425,134 @@ store: } -INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_80185DA8); + +/* func_80185DA8 — walk the 0x60-entry / 0x10C-stride entity table D_801202A0 and + * react to the first neighbour of class 0x27A (get pushed away from it) or 0x2F4 + * (get clamped down onto it). + * + * §71 sibling-first: the callee signatures below are copied VERBATIM from this TU's + * own already-matched neighbours — func_8012B0B4 (TU L6971/7855/8177), func_8012B6D4 + * (TU L6419), func_8012CEB0 (TU L7226, the func_80187844 block), func_8012C098 + * (TU L5379) — and D_801202A0 is the TU's file-scope `extern u8 D_801202A0[];` (L384). + * func_8012BC60 / func_8012ADE4 are not declared in this TU; the forms below are the + * fleet-majority shapes (func_8012ADE4 verbatim; func_8012BC60 with `void *` instead of + * `struct Vec *` so the draft does not depend on engine_types.h being in scope). + * + * FIVE load-bearing constructs (do NOT "clean up"): + * + * 1. NO SECOND WALKED POINTER. All of +0x6/+0xA/+0xE are written as `*(T *)(p + k)` + * off the single biv `p`. combine_givs then merges the three DEST_ADDR givs onto + * ONE anchor = the LAST-emitted one (+0xE, from the case-0x2F4 `lh`), giving the + * target's `$s3 = $s2 + 0xE` with -0x8/-0x4/0x0 displacements. + * An explicit `q = p + 0xE` with `*(u16 *)q` looks equivalent and is NOT: + * gcc-2.7.2 excludes a bare `*q` (mult 1, add 0) from givs (find_mem_givs:4198), + * so q stays a live biv AND the remaining two accesses combine onto their own + * anchor +0xA => THREE IVs, the wrong anchor, and the $s6 hoist lost to pressure + * (measured: 111 ins, 87 mismatched). gcc-2.7.2-map/loop.md §L1 rules 4 & 6. + * + * 2. `switch`, not `if/else if`. The two-case switch is what emits the target's + * compare CHAIN with BOTH arms out of line (`beq`/`beq`/`j default`, 6 slots). + * An `if (id == 0x27A) ... else if (id == 0x2F4)` inverts the first test and lets + * the 0x27A arm fall through — 2 instructions short. + * + * 3. do-while with `i++` BEFORE `p += 0x10C`. strength_reduce inserts the reduced + * giv's `addiu` immediately before ITS biv's increment, so the source order + * i-then-p is what produces `addiu $s4,$s4,1` / `addiu $s3,$s3,0x10C` / + * (delay) `addiu $s2,$s2,0x10C`. A `for (i = 0; i < 0x60; i++)` with `p += 0x10C` + * last puts the giv add first and swaps the pair. + * + * 4. `self4` and `sc` are REAL pre-loop locals, in that order. Both are loop + * invariants; written inline as `(s16 *)(a0 + 4)` / `(unsigned int *)sp20` at the + * call, combine folds the address straight into the argument move + * (`addiu $a0,$sp,0x20`) and the target's `$s6 = $sp + 0x20` hoist never happens. + * Assigning them in a *different basic block* from their uses is what keeps the + * pseudos alive; the declaration ORDER (p, i, self4, sc) is what gives + * $s2/$s4/$s5/$s6 in the target's prologue emission order. + * + * 5. `s16 y` (a SHORT local), and `s32 sp20[2]` (an EIGHT-byte scratch). + * - The short local is why `y` gets a second pseudo: gcc-2.7.2 emits + * `(set (reg:HI B) (subreg:HI (reg:SI A)))` for the HImode assignment, i.e. the + * target's `addu $a1,$a0,$zero` in the branch delay slot, with the two `- 0x60` + * recomputed from A ($a0, the compare) and B ($a1, the stored value). + * An `s32 y` coalesces the pair away and loses that instruction. + * - The short local also costs a DEAD 4-byte reload home at the top of the frame + * (`(use (mem:SI (plus $sp 48)))` in the greg dump, no insn references it). + * That is exactly why the func_8012B0B4 buffer is 8 bytes, not 16: 0x10 + 8 + * (v10) + 8 (v18) + 8 (sp20) + 4 (dead) rounds to 0x30 = the target's first + * saved-register slot. 8 bytes also matches the fleet's canonical shape for a + * func_8012B0B4 output buffer (`unsigned int buf[2]`). + */ + + +extern s32 func_8012BC60(void *a0, void *a1); +extern s32 func_8012B6D4(s16 *a0, s16 *a1); +extern void func_8012B0B4(unsigned int *p, int a1, int a2); +extern s32 func_8012CEB0(void *a0, void *a1, s32 a2); +extern void func_8012ADE4(u8 *a0); +extern void func_8012C098(void *param_1); + +void func_80185DA8(s32 a0) { + + extern u8 D_801202A0[]; + u8 *p; + s16 *self4; + unsigned int *sc; + s32 i; + s16 y; + s32 z; + s32 ang; + s16 v10[4]; /* sp+0x10 */ + s16 v18[4]; /* sp+0x18 */ + s32 sp20[2]; /* sp+0x20 — func_8012B0B4 output */ + + p = D_801202A0; + i = 0; + self4 = (s16 *)(a0 + 4); + sc = (unsigned int *)sp20; + do { + if ((u8 *)a0 != p) { + switch (*(u16 *)p) { + case 0x27A: + if (func_8012BC60((void *)self4, (void *)(p + 4)) < 0x6400) { + ang = func_8012B6D4(self4, (s16 *)(p + 4)); + func_8012B0B4(sc, ang, 0xA1); + v18[0] = *(u16 *)(p + 6); + v18[1] = *(u16 *)(p + 0xA); + v18[2] = *(u16 *)(p + 0xE); + v18[0] += sp20[0]; + v18[2] += sp20[0] >> 16; + v18[1] = *(u16 *)(a0 + 0xA); + v10[0] = *(u16 *)(a0 + 0x3A); + v10[1] = *(u16 *)(a0 + 0x3E); + v10[2] = *(u16 *)(a0 + 0x42); + if ((func_8012CEB0(v10, v18, 0) & 0x2000) == 0) { + func_8012ADE4((u8 *)a0); + return; + } + *(u16 *)(a0 + 6) = v18[0]; + *(u16 *)(a0 + 0xA) = v18[1]; + *(u16 *)(a0 + 0xE) = v18[2]; + return; + } + break; + case 0x2F4: + y = *(s16 *)(p + 0xE); + z = *(s16 *)(a0 + 0xE); + if (y + 0x10 < z) { + func_8012C098((void *)a0); + return; + } + if (y - 0x60 < z) { + *(s16 *)(a0 + 0xE) = y - 0x60; + } + break; + } + } + i++; + p += 0x10C; + } while (i < 0x60); +} + INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_80185F6C); @@ -8033,7 +8239,189 @@ void func_80189EC4(void *arg) { } -INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018A318); + +/* func_8018A318 — ov_SC06_018 / ov_SC06_018_jr_8017C24C + * + * Direct structural sibling of func_8018E188 (SAME TU, banked MATCH, + * src/ov_SC06_018/ov_SC06_018_jr_8017C24C.c:9077) and of func_8018D5C0 + * (src/ov_SC06_032/ov_SC06_032_jr_8017C24C.c:8530). Shares VERBATIM: + * - the 0x60 gate + 0x1D snapshot block, + * - the 0x78/0x60 decrement block (AND form — see E188's @stuck note), + * - the 0x82&1 finisher, the C8/C9 pokes, + * - the two 8-iteration spawn loops (0x281 / 0x23), + * - the 0x76<0 else arm (0x8800 / 0x60 / 0xC1 / 0xC2). + * It ADDS three leading func_8012C658 triple-spawns and replaces E188's + * CC/D0/D4 particle-reseed with the byte-proven RTP_SND block already + * matched in this TU at :4292 (func_8017F5xx) — same &D_800AF648 $a0-pin + * idiom, different constants (0x9F/0x13F, 0x77/0xEF, /0xA0, no panning). + * + * Regalloc target (identical to E188): p pinned $s1, e/spawn-ptr coalesce + * on $s0, loop counter $s2, the hoisted constant 2 on $s3. + * + * @class: regalloc-order + * @stuck: none — MATCH (248 ins), iteration 2. + * ONLY residual on iteration 1 was REGALLOC-PERM/$v1>$a0: the 2nd and 3rd + * func_8012C658 results landed in $v1 where the target has $a0 (block 1 was + * already right). LEVER: the three spawn pointers are ONE function-scope + * variable `t`, not three block-scope `s32 t`. Block 1 CSEs the shared -4 + * constant into $v1, which forces its pointer to $a0; making `t` a single + * multi-block (global) allocno propagates that $a0 to blocks 2 and 3. With + * three separate block-local pseudos each block re-runs local-alloc + * independently and takes $v1 (lower in REG_ALLOC_ORDER). This is the §76 + * "variable reuse selects the allocno CLASS" law applied to a pointer whose + * live ranges are disjoint — reuse is what makes it global, and global is + * what makes the first block's forced choice bind the later ones. + */ + +extern s32 rand(void); +extern void func_8016AA50(s32, s32); +extern s32 func_8016B428(s32); +extern void func_80019064(void *); +extern void func_8002A520(int); +extern void func_8002A790(int); +extern void func_8002D4C8(s32, s32); +extern s32 func_8012C658(s32, s32, s32); +extern s32 func_8012C588(s32, s32); +extern u8 *func_8012913C(s32); +extern void func_8012C218(void *); +extern void func_8004914C(void *a0); +extern void func_800491AC(void *a0); +extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + +void func_8018A318(void *arg) { + + extern u8 D_801C835C; + + extern u8 D_800AF648; + + /* L5: slot offsets are exact only through ONE struct (see the TU's other + RTP_SND site) — rv at sp+0x10, sxy at sp+0x18, z sp+0x1C, flag sp+0x20. */ + struct { + s16 rv[4]; /* sp+0x10 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + } L; + + register u8 *p __asm__("$17"); /* $s1 */ + s32 e; + s32 i; + s32 iv; + s32 t; + + p = (u8 *)arg; + e = *(u8 *)(p + 0x5E); + + if (*(s16 *)(p + 0x60) != 0) { + if (e == 0x1D) { + *(u16 *)(p + 0x82) = 0; + *(u16 *)(p + 0x7C) = *(u16 *)(p + 0x06); + *(u16 *)(p + 0x7E) = *(u16 *)(p + 0x0A); + *(u16 *)(p + 0x80) = *(u16 *)(p + 0x0E); + } + { + s32 dec; + s32 q = *(s32 *)(p + 0x78); + if (q != 0 && *(s16 *)(p + 0x60) != 0) { + dec = ((s32)*(s16 *)(p + 0x60) * (s32)*(s16 *)(q + 0x30)) >> 12; + if (dec < 1) dec = 1; + } else { + dec = *(s16 *)(p + 0x60); + } + *(u16 *)(p + 0x76) = *(u16 *)(p + 0x76) - dec; + ((void (*)(void *, s32))func_8016AA50)(p, dec); + } + if (*(u16 *)(p + 0x82) & 1) { + ((void (*)(void *))func_8016B428)(p); + func_80019064(&D_801C835C); + } + } + + if (e != 0x1D) { + if (*(u8 *)(p + 0xC8)) func_8002A520(p); + if (*(u8 *)(p + 0xC9)) func_8002A790(p); + } + + if (*(s16 *)(p + 0x76) < 0) { + t = func_8012C658(0x33, 3, (s32)p); + if (t != 0) { + *(s16 *)(t + 0x12) = -4; + *(s16 *)(t + 0x16) = -0x10; + *(s16 *)(t + 0x1A) = -4; + } + t = func_8012C658(0x33, 2, (s32)p); + if (t != 0) { + *(s16 *)(t + 0x12) = -4; + *(s16 *)(t + 0x16) = -0x10; + *(u16 *)(t + 0x1A) = 0; + } + t = func_8012C658(0x32, 2, (s32)p); + if (t != 0) { + *(s16 *)(t + 0x12) = -4; + *(s16 *)(t + 0x16) = -0x10; + *(u16 *)(t + 0x1A) = 4; + } + + i = 0; + do { + iv = ((s32 (*)(s32, void *))func_8012C588)(0x281, p); + if (iv != 0) { + *(s32 *)(iv + 0x1C) = 2; + *(u16 *)(iv + 0x12) = (rand() & 0x1F) - 0x10; + *(u16 *)(iv + 0x16) = -((rand() & 0x0F) + 0x10); + *(u16 *)(iv + 0x1A) = (rand() & 0x1F) - 0x10; + } + i++; + } while (i < 8); + i = 0; + do { + iv = (s32)func_8012913C(0x23); + if (iv != 0) { + s32 r; + s32 sv; + r = rand(); + *(u16 *)(iv + 0x06) = *(u16 *)(p + 0x06) + (r & 0x3F) - 0x20; + r = rand(); + *(u16 *)(iv + 0x0A) = *(u16 *)(p + 0x0A) - (r & 0x3F) - 0x20; + r = rand(); + sv = *(u16 *)(p + 0x0E); + *(s32 *)(iv + 0x18) = 0; + *(s32 *)(iv + 0x14) = 0; + *(s32 *)(iv + 0x10) = 0; + *(u16 *)(iv + 0x0E) = sv + (r & 0x3F) - 0x20; + r = rand(); + *(u16 *)(iv + 0x34) = (r & 0x17FF) + 0x1800; + } + i++; + } while (i < 8); + + L.rv[0] = *(s32 *)(*(s32 *)(p + 0x20) + 0x48); + L.rv[1] = *(s32 *)(*(s32 *)(p + 0x20) + 0x4C); + L.rv[2] = *(s32 *)(*(s32 *)(p + 0x20) + 0x50); + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } + RotTransPers((s32)L.rv, (s32)L.sxy, &L.z, &L.flag); + if (L.flag >= 0 && (u32)((L.sxy[0] + 0x9F) & 0xFFFF) < 0x13F + && (u32)((L.sxy[1] + 0x77) & 0xFFFF) < 0xEF) { + s32 x = (s16)L.sxy[0]; + s32 ax; + + ax = x; + if (x < 0) { + ax = -x; + } + ax = ((0xA0 - ax) * 0x7F) / 0xA0; + func_8002D4C8(0xB32, (ax | 0x1000) & 0xFFFF); + } + func_8012C218((void *)p); + } else { + *(u16 *)(p + 0x5C) = 0x8800; + *(u16 *)(p + 0x60) = 0; + *(u8 *)(p + 0xC1) = 0; + *(u8 *)(p + 0xC2) = 0x10; + } +} + INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018A6F8); @@ -8244,7 +8632,166 @@ INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018E4A INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018E89C); -INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018ECA0); + +/* func_8018ECA0 — ov_SC06_018 / ov_SC06_018_jr_80191C50 (226 ins) + * + * A "sweeping beam" tick for the 0x318 boss-effect entity family — the same + * entity class its already-MATCHED TU neighbour func_80191C50 drives + * (src/ov_SC06_018/ov_SC06_018_jr_80191C50.c:2860). + * + * - 3-way state machine on +0x34: + * 0 = spawn the child (func_8012C658(0x318, 8, arg0)) -> +0xCC, + * 1 = sweep -Z until 0x8C-z >= 0xFC, then state 2, + * 2 = sweep +Z until z-0x8C >= 0xFC, then state 1. + * - then, if the child (+0xCC) exists: two func_8018AD9C draws (colours + * 0x81818 / 0x204040), and TWO substep-interpolated hit sweeps that walk + * the beam origin backwards by `d` once per substep: + * (a) over the 0x60-entry entity table D_801202A0 (stride 0x10C), + * hit-testing each live entity with func_80135260 and, on a hit, + * stamping state 0x1D / timer 0xA / flag 1 / +0x62 = yaw-0x800; + * (b) against the player with func_8012DF34, stamping D_80126B98. + * + * @class: none — MATCH (226 ins), iteration 3. + * + * @lever (NEW, generalizable — loop.c `combine_givs` ANCHOR RULE): + * Iterations 1-2 were LENGTH-DRIFT +5 / +2 with an EXTRA induction register. + * All of the entity-record accesses (+0x20 +0x58 +0x5C +0x5E +0x60 +0x62 + * +0xAE) are DEST_ADDR givs on the table pointer, and gcc-2.7.2 allocates + * ONE new pseudo for the combined group. Which offset the group is + * ANCHORED at is not free: `record_giv` PREPENDS to `bl->giv`, and + * `combine_givs` walks that list from the head taking the first absorber — + * so the anchor is the **LAST address giv discovered in source order**. + * The target anchors at +0x5E (base $s3, giv $s0, offsets -0x3E..+0x50); + * my draft anchored at +0x62 because `*(u16*)(e+0x62) = ...` was the last + * store in the hit block, which forced a THIRD induction register (+$s7, + * +2 prologue/epilogue insns, +1 giv-init, +1 latch increment, +1 nop). + * FIX: reorder the hit block so the **+0x5E store is last** — pure source + * ordering, zero semantic change, and the scheduler still emits +0x62 last + * in the asm because it depends on a lw->lhu chain. + * + * @lever (§76 allocno CLASS): the spawn result, the +0xCC child pointer and + * the D_801202A0 table walker are ONE variable `e`. Split into separate + * variables the first two are local, call-crossing-free allocnos and land + * in $a0 (first free in REG_ALLOC_ORDER); merged, the live range spans the + * func_80135260 loop, so calls_crossed > 0 forces a callee-saved reg and + * the whole chain coalesces onto $s3 — which is also what frees the + * `bnez $s3` delay slot for `addu $a0, $s2, $zero`. + * + * @lever (store order): `sp10.vy = sp18.vy = v` (not `sp18.vy = sp10.vy = v`) + * — `a = b = v` stores b first, and the target emits sh 0x1A before 0x12. + */ + +extern s32 func_8012C658(s32 a0, s32 a1, s32 a2); +extern void func_8012B2CC(s32 a0); +extern void func_8018AD9C(s32 param_1, u32 param_2, u16 *param_3, u32 param_4); +extern s32 func_8004787C(s32 a0); +extern s32 func_80135260(s32 arg0, s32 arg1, s16 *arg2, s16 *arg3); +extern s32 func_8012DF34(s32 a0, s32 a1, s32 a2); + +typedef struct { + s16 vx, vy, vz, pad; +} SV_80192F64_8018ECA0; + +void func_8018ECA0(s32 arg0) { + + extern u8 D_801202A0[]; + extern u16 D_80126B98[]; + s32 e; + s16 t; + s32 i; + s32 n; + s32 d; + SV_80192F64_8018ECA0 sp10; + SV_80192F64_8018ECA0 sp18; + SV_80192F64_8018ECA0 sp20; + u16 sp28[2]; + + switch (*(u16 *)(arg0 + 0x34)) { + case 0: + e = func_8012C658(0x318, 8, arg0); + if (e != 0) { + *(u16 *)(arg0 + 0x34) = (*(u16 *)(arg0 + 0xFC) & 1) + 1; + *(u16 *)(*(s32 *)(e + 0x20) + 0x12) = *(u16 *)(*(s32 *)(arg0 + 0x20) + 0x12) + 0x800; + *(s32 *)(e + 4) = *(s32 *)(e + 4) - *(s32 *)(arg0 + 0xDC); + *(s32 *)(arg0 + 0xCC) = e; + *(u16 *)(e + 0xFC) = *(u16 *)(arg0 + 0x36); + } + break; + case 1: + t = *(u16 *)(arg0 + 0xE) - 4; + *(u16 *)(arg0 + 0xE) = t; + if (*(s16 *)(arg0 + 0x8C) - t >= *(s16 *)(arg0 + 0xFC)) { + *(u16 *)(arg0 + 0x34) = 2; + } + break; + case 2: + t = *(u16 *)(arg0 + 0xE) + 4; + *(u16 *)(arg0 + 0xE) = t; + if (t - *(s16 *)(arg0 + 0x8C) >= *(s16 *)(arg0 + 0xFC)) { + *(u16 *)(arg0 + 0x34) = 1; + } + break; + } + + e = *(s32 *)(arg0 + 0xCC); + if (e == 0) { + *(u16 *)(arg0 + 2) = *(u16 *)(arg0 + 2) + 1; + return; + } + *(s32 *)(e + 0xC) = *(s32 *)(arg0 + 0xC); + sp28[0] = 0; + sp28[1] = *(u16 *)(arg0 + 0xDE); + func_8012B2CC(arg0); + func_8018AD9C(arg0, 0, sp28, 0x81818); + func_8018AD9C(arg0, 1, sp28, 0x204040); + + sp10.vx = *(u16 *)(arg0 + 6); + sp10.vy = sp18.vy = *(u16 *)(arg0 + 0xA); + sp10.vz = sp18.vz = *(u16 *)(arg0 + 0xE); + e = (s32)D_801202A0; + i = 0; + d = func_8004787C(*(s16 *)(*(s32 *)(arg0 + 0x20) + 0x12)) >> 4; + do { + if (*(u16 *)e != 0 && *(u16 *)e != 0x25D && *(u16 *)e != 0x318 && + (*(u16 *)(e + 0x5C) & 0x8000) != 0 && *(u16 *)(e + 0x5E) != 0x1D && + (*(u16 *)(e + 0xAE) & 1) == 0) { + n = ((s16) * (u16 *)(arg0 + 0xDE) >> 8) + 1; + sp18.vx = sp10.vx; + sp20.vy = sp18.vy; + sp20.vz = sp18.vz; + do { + sp20.vx = sp18.vx - d; + if (func_80135260(*(s32 *)(e + 0x20), *(s32 *)(e + 0x58), &sp18.vx, &sp20.vx) == 1) { + *(u16 *)(e + 0x60) = 0xA; + *(u16 *)(e + 0x5C) = *(u16 *)(e + 0x5C) | 1; + *(u16 *)(e + 0x62) = *(u16 *)(*(s32 *)(e + 0x20) + 0x12) - 0x800; + *(u16 *)(e + 0x5E) = 0x1D; + n = 1; + } + n--; + sp18.vx = sp18.vx - d; + } while (n != 0); + } + e += 0x10C; + i++; + } while (i < 0x60); + + n = ((s16) * (u16 *)(arg0 + 0xDE) >> 8) + 1; + sp18.vx = sp10.vx; + sp20.vy = sp18.vy; + sp20.vz = sp18.vz; + do { + sp20.vx = sp18.vx - d; + if (func_8012DF34(arg0, (s32)&sp18.vx, (s32)&sp20.vx) == 1) { + D_80126B98[0] = 0x96; + D_80126B98[-1] = 0x4018; + n = 1; + } + n--; + sp18.vx = sp18.vx - d; + } while (n != 0); +} + INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018F028); @@ -8320,7 +8867,152 @@ void aF8017ED80(void *param_1) { } -INCLUDE_ASM("asm/ov_SC06_033/nonmatchings/ov_SC06_033_jr_8017C24C", func_8018F6EC); + +/* func_8018F6EC -- ov_SC06_008, TU ov_SC06_008_jr_8017C294.c (open-only h_norm + * cluster exemplar, 7 members). + * + * a0+0x0 : u16 active flag; 0 => early return. + * a0+0x84 : s16 sound cooldown timer. + * cooldown != 0 -> just decrement it. + * cooldown == 0 -> try to play a positional sound (RotTransPers screen + * projection of the parent's position, range-gated on + * screen X/Y, volume from the classic div-by-0xF0 / + * div-by-0x1E magic-constant idiom -- byte-proven sibling + * form is func_80181CF0 in this same TU, sndid 0x849 here + * vs 0x961 there), then unconditionally reset the timer + * to 0xA regardless of whether the sound actually played. + * a0+0xFC / 0xFE : running hit-combo accumulators, bumped by +/-0x280 every + * call (unconditional tail). + * Tail always calls ((void (*)(void *))func_8018F518)(a0) (the TU's canonical decl for this + * symbol is void(void) -- S35 self-axis -- so this draft binds its own + * private extern with the asm's real void(void*) shape). + * + * Control flow is EXPLICIT goto/label, mirroring source-order block + * placement (gcc-2.7.2 lays out basic blocks in literal source order, not by + * fallthrough preference -- see the func_80181CF0 comment, same TU): the + * cooldown!=0 decrement is the SHORT block and sits out-of-line (jumped to), + * the cooldown==0 RTP+sound block is the LONG block and sits inline + * (fallthrough), matching the target's physical layout exactly. + * + * MATCH levers (byte-proven, 2026-08-05): + * 1. Naive `if(old!=0){cool=old-1;}else{...}` folds trivially: reorg.c's + * delay-slot filler steals the single-insn decrement into the `bnez`'s + * own delay slot and retargets the branch straight to the join label + * (2 ins short of target). The target instead keeps a genuine copy + * (`addu $v1,$v0,zero`) in the delay slot and a SEPARATE `addiu $v0,$v1,-1` + * at the decrement site. Reproduced by pinning a second variable + * `register s32 v1 __asm__("$3")`, assigned UNCONDITIONALLY right after + * the load (`v1 = old;`) -- the scheduler places that copy in the + * branch's delay slot on its own, and the decrement (`cool = v1 - 1`) + * can no longer be folded away. `cool` is separately pinned to + * `__asm__("$2")` so its other def sites (the three `cool = 0xA` early + * exits) don't drift onto $3 by coalescing with v1. + * 2. The tail's `sh $v0,0x84($s0)` / `addu $a0,$s0,zero` order (store off + * the callee-saved pointer BEFORE reloading it into the call-argument + * register) needed a `__asm__ __volatile__("":::"memory")` fence right + * after the store -- without it, sched1 hoists the independent a0-reload + * ahead of the store even when the reload is written later in source. + * 3. Frame is -0x38, 8 bytes (2 words) larger than the natural -0x30 the + * locals alone produce; `pad2[2]` (dead, address never read) inside `L` + * reserves them, mirroring func_80181CF0's own "dead aggregate sizes the + * frame" idiom. + */ + + +/* §37/§124 def-side asm-label alias (P30 S1d class lever): the TU declares + * `extern void func_8018F6EC(void);` (L4082, L4091) for callers that invoke it with NO args, + * while the byte-true definition takes an s32 in $a0 -> `conflicting types`. Neither side can + * move (a no-prototype escape is illegal once a param promotes), so the DEFINITION gets a + * private C identifier and binds the emitted symbol with a GNU asm label. Zero blast radius: + * the TU's declaration never meets the definition, and the emitted symbol is unchanged. */ +void aF8017EF54(s32 a0) __asm__("func_8018F6EC"); + +void aF8017EF54(s32 a0) +{ + extern void func_8004914C(void *a0); + extern void func_800491AC(void *a0); + extern void func_8002D4C8(s32 a0, s32 a1); + extern s32 RotTransPers(s32 a0, s32 a1, s32 *a2, s32 *a3); + extern u8 D_800AF648; + extern void func_8018F518(void); + struct { + s16 v[3]; /* sp+0x10 */ + s16 pad1; /* sp+0x16 */ + u16 sxy[2]; /* sp+0x18 */ + s32 z; /* sp+0x1C */ + s32 flag; /* sp+0x20 */ + s32 pad2[2]; /* sp+0x24 -- dead, sizes the frame */ + } L; + + register s32 v1 __asm__("$3"); + register s32 cool __asm__("$2"); + s32 old; + + if (*(u16 *)(a0 + 0x0) == 0) { + return; + } + + old = *(s16 *)(a0 + 0x84); + v1 = old; + if (old != 0) { + goto L_dec; + } + + L.v[0] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x48); + L.v[1] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x4C); + L.v[2] = *(s32 *)(*(s32 *)(a0 + 0x20) + 0x50); + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_8004914C(r4); } + { register void *r4 __asm__("$4"); r4 = &D_800AF648; func_800491AC(r4); } + RotTransPers((s32)L.v, (s32)L.sxy, &L.z, &L.flag); + + if (L.flag < 0) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[0] + 0xEF) & 0xFFFF) >= 0x1DF) { + cool = 0xA; + goto L_join; + } + if ((u32)((L.sxy[1] + 0xB3) & 0xFFFF) >= 0x167) { + goto L_snd_skip; + } + + { + s32 sx = (s16)L.sxy[0]; + s32 av; + + av = sx; + if (sx < 0) { + av = -sx; + } + av = ((0xF0 - av) * 0x7F) / 0xF0; + sx = (sx + 0xF0) / 0x1E; + if (sx == 0x10) { + sx = 0xF; + } + sx = sx << 8; + func_8002D4C8(0x849, (av | (0x3000 | sx)) & 0xFFFF); + } + +L_snd_skip: + cool = 0xA; + goto L_join; + +L_dec: + cool = v1 - 1; + +L_join: + *(s16 *)(a0 + 0x84) = cool; + __asm__ __volatile__("" ::: "memory"); + + { + s32 p = a0; + *(u16 *)(p + 0xFC) = *(u16 *)(p + 0xFC) + 0x280; + *(u16 *)(p + 0xFE) = *(u16 *)(p + 0xFE) - 0x280; + ((void (*)(void *))func_8018F518)((void *)p); + } +} + extern s32 rand(void); diff --git a/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c b/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c index 3265e5671..96d92b2e7 100644 --- a/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c +++ b/src/ov_SC07_002/ov_SC07_002_jr_8017C8D0.c @@ -3203,7 +3203,67 @@ void func_8017E604(void *a0) { } -INCLUDE_ASM("asm/ov_SC07_002/nonmatchings/ov_SC07_002_jr_8017C8D0", func_8017E640); + + +extern s32 rand(void); + +typedef struct { + u16 f0; + u16 f2; + u16 f4; + u16 f6; + u16 f8; + u16 fA; + s32 fC; + s32 f10; + s32 f14; + s32 f18; +} SubRec_801EB5C8_8017E640; /* 0x1C */ + +typedef struct { + u16 g0; + u16 g2; + s32 g4; + s32 g8; + s32 gC; + SubRec_801EB5C8_8017E640 subs[16]; +} GroupRec_801EB5C8_8017E640; /* 0x1D0 */ + + +void func_8017E640(s32 param_1) +{ + + extern GroupRec_801EB5C8_8017E640 D_8019E1B8[8]; + s32 i, j; + GroupRec_801EB5C8_8017E640 *grp; + SubRec_801EB5C8_8017E640 *sub; + + for (i = 0; i < 8; i++) { + grp = &D_8019E1B8[i]; + grp->g0 = 0; + grp->g2 = i << 9; + grp->gC = (rand() & 0xF) << 16; + grp->g4 = ((rand() & 0xF) << 15) + 0x10000; + grp->g8 = ((rand() & 0xF) << 12) + 0x8000; + + for (j = 0; j < 16; j++) { + sub = &grp->subs[j]; + sub->f0 = 0; + sub->f2 = (rand() & 3) + 4; + sub->f8 = (j << 8) + (rand() & 0xF) * 56; + sub->fA = (rand() & 0xF) << 8; + sub->f14 = (rand() & 0xF) << 13; + sub->fC = ((rand() & 0xF) << 14) + 0x10000; + sub->f10 = ((rand() & 0xF) << 12) + 0x8000; + sub->f4 = 0x200; + sub->f6 = (rand() & 0xF) << 4; + sub->f18 = ((rand() & 3) << 5) + 0x40; + } + } + + *(u16 *)(param_1 + 2) = *(u16 *)(param_1 + 2) + 1; +} + INCLUDE_ASM("asm/ov_SC07_002/nonmatchings/ov_SC07_002_jr_8017C8D0", func_8017E7E8); diff --git a/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c b/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c index 539afa709..adc749e46 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c @@ -3966,12 +3966,6 @@ extern Morph_8017DC1C *D_801BF530; extern Morph_8017DC1C *D_801BF534; extern Morph_8017DC1C *D_801BF538; extern Morph_8017DC1C *D_801BF650; -extern Morph_8017DC1C *D_801BF65C; -extern Morph_8017DC1C *D_801BF660; -extern Morph_8017DC1C *D_801BF684; -extern Morph_8017DC1C *D_801BF6A4; -extern Morph_8017DC1C *D_801BF6A8; -extern Morph_8017DC1C *D_801BF6AC; extern SVECTOR2 *D_801C1E14; extern SVECTOR2 *D_801C1E18; @@ -3979,11 +3973,6 @@ extern SVECTOR2 *D_801C1E1C; extern SVECTOR2 *D_801C1E20; extern SVECTOR2 *D_801C1E24; extern SVECTOR2 *D_801C1E28; -extern SVECTOR2 *D_801C1E2C; -extern SVECTOR2 *D_801C1E30; -extern SVECTOR2 *D_801C1E34; -extern SVECTOR2 *D_801C1E38; -extern SVECTOR2 *D_801C1E3C; extern SVECTOR2 *D_801C1E40; extern SVECTOR2 *D_801C1E44; extern SVECTOR2 *D_801C1E48; @@ -3994,24 +3983,11 @@ extern SVECTOR2 *D_801C1E58; extern SVECTOR2 *D_801C1E60; extern SVECTOR2 *D_801C1E64; extern SVECTOR2 *D_801C1E68; -extern SVECTOR2 *D_801C1E6C; -extern SVECTOR2 *D_801C1E70; -extern SVECTOR2 *D_801C1E74; -extern SVECTOR2 *D_801C1E78; -extern SVECTOR2 *D_801C1E7C; -extern SVECTOR2 *D_801C1E80; -extern SVECTOR2 *D_801C1E84; -extern SVECTOR2 *D_801C1E88; extern SVECTOR2 *D_801C1E8C; -extern SVECTOR2 *D_801C1E90; -extern SVECTOR2 *D_801C1E94; -extern SVECTOR2 *D_801C1E98; extern SVECTOR2 *D_801C1E9C; extern SVECTOR2 *D_801C1EA0; extern SVECTOR2 *D_801C1EA4; extern SVECTOR2 *D_801C1EA8; -extern SVECTOR2 *D_801C1EAC; -extern SVECTOR2 *D_801C1EB0; /* MUST be `inline` — see L1. 25 expansions == 1518 ins, 0 jal, frame 25*24=0x258. */ @@ -4042,6 +4018,39 @@ static inline void morph_lerp(Morph_8017DC1C *o, SVECTOR2 *b, SVECTOR2 *a, s32 t void func_8017DC1C(s32 t) { + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern SVECTOR2 *D_801C1E6C; + extern SVECTOR2 *D_801C1E70; + extern SVECTOR2 *D_801C1E74; + extern SVECTOR2 *D_801C1E78; + extern SVECTOR2 *D_801C1E7C; + extern SVECTOR2 *D_801C1EB0; + extern Morph_8017DC1C *D_801BF6A4; + extern Morph_8017DC1C *D_801BF6A8; + extern Morph_8017DC1C *D_801BF6AC; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern SVECTOR2 *D_801C1E2C; + extern SVECTOR2 *D_801C1E30; + extern SVECTOR2 *D_801C1EAC; + extern SVECTOR2 *D_801C1E38; + extern SVECTOR2 *D_801C1E3C; + extern SVECTOR2 *D_801C1E34; + extern Morph_8017DC1C *D_801BF65C; + extern Morph_8017DC1C *D_801BF660; + extern Morph_8017DC1C *D_801BF684; + /* [T51] scoped in from file scope: a file-scope decl of these symbols constrains every + LATER function in this TU, which blocks a byte-true decl of a different type. + Declaration-only move (cookbook §103); the whole-binary byte-gate is the arbiter. */ + extern SVECTOR2 *D_801C1E80; + extern SVECTOR2 *D_801C1E84; + extern SVECTOR2 *D_801C1E88; + extern SVECTOR2 *D_801C1E90; + extern SVECTOR2 *D_801C1E94; + extern SVECTOR2 *D_801C1E98; morph_lerp(D_801BF4F4, D_801C1E14, D_801C1E18, t); morph_lerp(D_801BF4F8, D_801C1E1C, D_801C1E1C, t); morph_lerp(D_801BF4FC, D_801C1E20, D_801C1E20, t); @@ -4106,7 +4115,32 @@ INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_80180CF INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_80181148); -INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_8018163C); + +/* func_8018163C — banked from the S40 wave-1 draft. + * The draft carried the TYPES, the six SVECTOR2 externs and `static inline morph_lerp` so that + * match_one could compile it standalone (-Iinclude only, the §77 probe rule). The REAL TU + * (ov_SC07_006_jr_8017BEBC.c) already defines all of them — morph_lerp at :4018 — so keeping + * them produced `redefinition of morph_lerp`. Per the draft's own banking note, only the three + * NEW externs and the body belong here. §77: a probe layer is scaffolding, not part of the bank. */ + + +void func_8018163C(s32 t) +{ + + extern SVECTOR2 *D_801C1E80; + extern SVECTOR2 *D_801C1E84; + extern SVECTOR2 *D_801C1E88; + extern SVECTOR2 *D_801C1E90; + extern SVECTOR2 *D_801C1E94; + extern SVECTOR2 *D_801C1E98; + extern Morph_8017DC1C *D_801BF5B4; + extern Morph_8017DC1C *D_801BF5B8; + extern Morph_8017DC1C *D_801BF5BC; + morph_lerp(D_801BF5B4, D_801C1E80, D_801C1E90, t); + morph_lerp(D_801BF5B8, D_801C1E84, D_801C1E94, t); + morph_lerp(D_801BF5BC, D_801C1E88, D_801C1E98, t); +} + INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_80181924); @@ -4120,11 +4154,61 @@ INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_8018215 INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_80182268); -INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_801823F8); + +/* func_801823F8 — banked from the S40 wave-1 draft. + * The draft carried the TYPES, the six SVECTOR2 externs and `static inline morph_lerp` so that + * match_one could compile it standalone (-Iinclude only, the §77 probe rule). The REAL TU + * (ov_SC07_006_jr_8017BEBC.c) already defines all of them — morph_lerp at :4018 — so keeping + * them produced `redefinition of morph_lerp`. Per the draft's own banking note, only the three + * NEW externs and the body belong here. §77: a probe layer is scaffolding, not part of the bank. */ + + +void func_801823F8(s32 t) +{ + + extern SVECTOR2 *D_801C1E2C; + extern SVECTOR2 *D_801C1E30; + extern SVECTOR2 *D_801C1EAC; + extern SVECTOR2 *D_801C1E38; + extern SVECTOR2 *D_801C1E3C; + extern SVECTOR2 *D_801C1E34; + extern Morph_8017DC1C *D_801BF65C; + extern Morph_8017DC1C *D_801BF660; + extern Morph_8017DC1C *D_801BF684; + morph_lerp(D_801BF65C, D_801C1E2C, D_801C1E38, t); + morph_lerp(D_801BF660, D_801C1E30, D_801C1E3C, t); + morph_lerp(D_801BF684, D_801C1EAC, D_801C1E34, t); +} + INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_801826E0); -INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_801828A4); + +/* func_801828A4 — banked from the S40 wave-1 draft. + * The draft carried the TYPES, the six SVECTOR2 externs and `static inline morph_lerp` so that + * match_one could compile it standalone (-Iinclude only, the §77 probe rule). The REAL TU + * (ov_SC07_006_jr_8017BEBC.c) already defines all of them — morph_lerp at :4018 — so keeping + * them produced `redefinition of morph_lerp`. Per the draft's own banking note, only the three + * NEW externs and the body belong here. §77: a probe layer is scaffolding, not part of the bank. */ + + +void func_801828A4(s32 t) +{ + + extern SVECTOR2 *D_801C1E6C; + extern SVECTOR2 *D_801C1E70; + extern SVECTOR2 *D_801C1E74; + extern SVECTOR2 *D_801C1E78; + extern SVECTOR2 *D_801C1E7C; + extern SVECTOR2 *D_801C1EB0; + extern Morph_8017DC1C *D_801BF6A4; + extern Morph_8017DC1C *D_801BF6A8; + extern Morph_8017DC1C *D_801BF6AC; + morph_lerp(D_801BF6A4, D_801C1E6C, D_801C1E78, t); + morph_lerp(D_801BF6A8, D_801C1E70, D_801C1E7C, t); + morph_lerp(D_801BF6AC, D_801C1E74, D_801C1EB0, t); +} + INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_8017BEBC", func_80182B8C);