diff --git a/.run/backlog.jsonl b/.run/backlog.jsonl index 97f4bdebf..2755a3f62 100644 --- a/.run/backlog.jsonl +++ b/.run/backlog.jsonl @@ -839,3 +839,4 @@ {"ts": "2026-08-05 16:05:31", "addr": "0x8017C6F4", "name": "func_8017C6F4", "reach": 3, "klass": "regalloc: register rotation (mnc/xmx1/cell/prim); ILS took hand-63 -> 42, flat across 5 restarts", "nins": 947, "status": "near", "closeness": 42, "where_stuck": "ov_SC03_126; permuter ILS plateau (masked 44 over 6 warm restarts); residual still the register rotation, fewer instances", "best_draft": ".run/s43/func_8017C6F4.ils44.c", "binary": "ov_SC03_126", "source": "s43-permuter-ils", "residual": null, "passes_tried": null} {"ts": "2026-08-05 16:17:15", "addr": "0x8017C6F4", "name": "func_8017C6F4", "reach": 3, "klass": "regalloc: register rotation; hand 63 -> ILS 42 (pin-free seed) -> ILS 41 (pin-t5 seed); both basins plateau", "nins": 947, "status": "near", "closeness": 41, "where_stuck": "ov_SC03_126; BEST KNOWN. permuter ILS from the pin-t5 seed, masked 43, flat over 5 warm restarts", "best_draft": ".run/s43/func_8017C6F4.ils43-pin.c", "binary": "ov_SC03_126", "source": "s43-permuter-ils", "residual": null, "passes_tried": null} {"ts": "2026-08-05 16:38:43", "addr": "0x8017EF68", "name": "func_8017EF68", "reach": 1, "klass": "SCHEDULE-REORDER/2: sched2 INSN_LUID tie, lw $v0,0($s3) vs srl $a2,$a1,16 transposed; hand levers documented spent in the draft header; permuter ILS plateaus at 2 (6 cycles)", "nins": 969, "status": "near", "closeness": 2, "where_stuck": "ov_SC06_000 (the 970-ins variant; ov_SC03_007's is a DIFFERENT 12-ins body at the same addr)", "best_draft": ".run/drafts-p30beh/func_8017EF68.c", "binary": "ov_SC06_000", "source": "s43-rescan", "residual": null, "passes_tried": null} +{"ts": "2026-08-05 17:07:03", "addr": "0x8017C6F4", "name": "func_8017C6F4", "reach": 4, "klass": "SOLVED: per-pass variables + prim-loop clamp reuse (cookbook \u00a7150); NOT an allocator tie", "nins": 947, "status": "matched", "closeness": 0, "where_stuck": "BANKED x4 (SC03_126/003, SC04_021, SC05_019) pending R22 clean-fleet", "best_draft": ".run/s43/fable/8017C6F4/v2_rtu.c", "binary": "ov_SC03_126", "source": "s43-fable", "residual": null, "passes_tried": null} diff --git a/config/overlays.mk b/config/overlays.mk index f36d05e6f..aa412ac79 100644 --- a/config/overlays.mk +++ b/config/overlays.mk @@ -1293,7 +1293,7 @@ ov_SC03_003_ELF := $(ov_SC03_003_OUT).elf ov_SC03_003_MAPFILE := $(ov_SC03_003_OUT).map ov_SC03_003_LD_SCRIPT := $(ov_SC03_003_OUT).ld ov_SC03_003_SPLAT_YAML := config/splat.ov_SC03_003.yaml -ov_SC03_003_JTBL_INTERLEAVE := --order tail.data.o,ov_SC03_003.o,ov_SC03_003_jr_8012ACE0.o,tail2.data.o,ov_SC03_003_jr_80135888.o,tail3.data.o,ov_SC03_003_jr_80135A4C.o,tail4.data.o,ov_SC03_003_jr_80135D20.o,tail5.data.o,ov_SC03_003_jr_801380E0.o,ov_SC03_003_o0c.o,tail6.data.o,ov_SC03_003_jr_8013F350.o,tail7.data.o,ov_SC03_003_jr_8013FFD8.o,tail8.data.o,ov_SC03_003_jr_80140608.o,tail9.data.o,ov_SC03_003_jr_8015444C.o,ov_SC03_003_jr_80154C24.o,ov_SC03_003_jr_801588CC.o,ov_SC03_003_jr_80159C84.o,tail10.data.o,ov_SC03_003_jr_8015A3C8.o,tail11.data.o,ov_SC03_003_jr_8015AE2C.o,tail12.data.o,ov_SC03_003_jr_8015C32C.o,tail13.data.o,ov_SC03_003_jr_8016AB6C.o,tail14.data.o,ov_SC03_003_jr_80171B4C.o,ov_SC03_003_jr_801734BC.o,tail15.data.o,ov_SC03_003_jr_801789AC.o,ov_SC03_003_jr_80178D40.o,tail16.data.o,ov_SC03_003_jr_8017A4AC.o,tail17.data.o,ov_SC03_003_jr_8017AE2C.o,tail18.data.o,ov_SC03_003_jr_8017D5C0.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC03_003_JTBL_INTERLEAVE := --order tail.data.o,ov_SC03_003.o,ov_SC03_003_jr_8012ACE0.o,tail2.data.o,ov_SC03_003_jr_80135888.o,tail3.data.o,ov_SC03_003_jr_80135A4C.o,tail4.data.o,ov_SC03_003_jr_80135D20.o,tail5.data.o,ov_SC03_003_jr_801380E0.o,ov_SC03_003_o0c.o,tail6.data.o,ov_SC03_003_jr_8013F350.o,tail7.data.o,ov_SC03_003_jr_8013FFD8.o,tail8.data.o,ov_SC03_003_jr_80140608.o,tail9.data.o,ov_SC03_003_jr_8015444C.o,ov_SC03_003_jr_80154C24.o,ov_SC03_003_jr_801588CC.o,ov_SC03_003_jr_80159C84.o,tail10.data.o,ov_SC03_003_jr_8015A3C8.o,tail11.data.o,ov_SC03_003_jr_8015AE2C.o,tail12.data.o,ov_SC03_003_jr_8015C32C.o,tail13.data.o,ov_SC03_003_jr_8016AB6C.o,tail14.data.o,ov_SC03_003_jr_80171B4C.o,ov_SC03_003_jr_801734BC.o,tail15.data.o,ov_SC03_003_jr_801789AC.o,ov_SC03_003_jr_80178D40.o,tail16.data.o,ov_SC03_003_jr_8017A4AC.o,tail17.data.o,ov_SC03_003_jr_8017AE2C.o,ov_SC03_003_jr_8017D5C0.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC03_003/ov_SC03_003.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC03_003/ov_SC03_003_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0 build/src/ov_SC03_003/ov_SC03_003_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -1306,6 +1306,7 @@ build/src/ov_SC03_003/ov_SC03_003_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC03_003/ov_SC03_003_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC03_003/ov_SC03_003_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC03_003/ov_SC03_003_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 +build/src/ov_SC03_003/ov_SC03_003_jr_8017AE2C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC03_003/ov_SC03_003_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC03_003_CHECK_SHA := config/check.ov_SC03_003.sha ov_SC03_003_SYMBOLS := config/symbols.ov_SC03_003.txt @@ -2920,7 +2921,7 @@ ov_SC03_126_ELF := $(ov_SC03_126_OUT).elf ov_SC03_126_MAPFILE := $(ov_SC03_126_OUT).map ov_SC03_126_LD_SCRIPT := $(ov_SC03_126_OUT).ld ov_SC03_126_SPLAT_YAML := config/splat.ov_SC03_126.yaml -ov_SC03_126_JTBL_INTERLEAVE := --order tail.data.o,ov_SC03_126.o,ov_SC03_126_jr_8012ACE0.o,tail2.data.o,ov_SC03_126_jr_80135888.o,tail3.data.o,ov_SC03_126_jr_80135A4C.o,tail4.data.o,ov_SC03_126_jr_80135D20.o,tail5.data.o,ov_SC03_126_jr_801380E0.o,ov_SC03_126_o0c.o,tail6.data.o,ov_SC03_126_jr_8013F350.o,tail7.data.o,ov_SC03_126_jr_8013FFD8.o,tail8.data.o,ov_SC03_126_jr_80140608.o,tail9.data.o,ov_SC03_126_jr_8015444C.o,ov_SC03_126_jr_80154C24.o,ov_SC03_126_jr_801588CC.o,ov_SC03_126_jr_80159C84.o,tail10.data.o,ov_SC03_126_jr_8015A3C8.o,tail11.data.o,ov_SC03_126_jr_8015AE2C.o,tail12.data.o,ov_SC03_126_jr_8015C32C.o,tail13.data.o,ov_SC03_126_jr_8016AB6C.o,tail14.data.o,ov_SC03_126_jr_80171B4C.o,ov_SC03_126_jr_801734BC.o,tail15.data.o,ov_SC03_126_jr_801789AC.o,ov_SC03_126_jr_80178D40.o,tail16.data.o,ov_SC03_126_jr_8017A4AC.o,tail17.data.o,ov_SC03_126_jr_8017AE2C.o,tail18.data.o,ov_SC03_126_jr_8017D5C0.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC03_126_JTBL_INTERLEAVE := --order tail.data.o,ov_SC03_126.o,ov_SC03_126_jr_8012ACE0.o,tail2.data.o,ov_SC03_126_jr_80135888.o,tail3.data.o,ov_SC03_126_jr_80135A4C.o,tail4.data.o,ov_SC03_126_jr_80135D20.o,tail5.data.o,ov_SC03_126_jr_801380E0.o,ov_SC03_126_o0c.o,tail6.data.o,ov_SC03_126_jr_8013F350.o,tail7.data.o,ov_SC03_126_jr_8013FFD8.o,tail8.data.o,ov_SC03_126_jr_80140608.o,tail9.data.o,ov_SC03_126_jr_8015444C.o,ov_SC03_126_jr_80154C24.o,ov_SC03_126_jr_801588CC.o,ov_SC03_126_jr_80159C84.o,tail10.data.o,ov_SC03_126_jr_8015A3C8.o,tail11.data.o,ov_SC03_126_jr_8015AE2C.o,tail12.data.o,ov_SC03_126_jr_8015C32C.o,tail13.data.o,ov_SC03_126_jr_8016AB6C.o,tail14.data.o,ov_SC03_126_jr_80171B4C.o,ov_SC03_126_jr_801734BC.o,tail15.data.o,ov_SC03_126_jr_801789AC.o,ov_SC03_126_jr_80178D40.o,tail16.data.o,ov_SC03_126_jr_8017A4AC.o,tail17.data.o,ov_SC03_126_jr_8017AE2C.o,ov_SC03_126_jr_8017D5C0.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC03_126/ov_SC03_126.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC03_126/ov_SC03_126_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0 build/src/ov_SC03_126/ov_SC03_126_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -2933,6 +2934,7 @@ build/src/ov_SC03_126/ov_SC03_126_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC03_126/ov_SC03_126_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC03_126/ov_SC03_126_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC03_126/ov_SC03_126_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 +build/src/ov_SC03_126/ov_SC03_126_jr_8017AE2C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC03_126/ov_SC03_126_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC03_126_CHECK_SHA := config/check.ov_SC03_126.sha ov_SC03_126_SYMBOLS := config/symbols.ov_SC03_126.txt @@ -3449,7 +3451,7 @@ ov_SC04_021_ELF := $(ov_SC04_021_OUT).elf ov_SC04_021_MAPFILE := $(ov_SC04_021_OUT).map ov_SC04_021_LD_SCRIPT := $(ov_SC04_021_OUT).ld ov_SC04_021_SPLAT_YAML := config/splat.ov_SC04_021.yaml -ov_SC04_021_JTBL_INTERLEAVE := --order tail.data.o,ov_SC04_021.o,ov_SC04_021_jr_8012ACE0.o,tail2.data.o,ov_SC04_021_jr_80135888.o,tail3.data.o,ov_SC04_021_jr_80135A4C.o,tail4.data.o,ov_SC04_021_jr_80135D20.o,tail5.data.o,ov_SC04_021_jr_801380E0.o,ov_SC04_021_o0c.o,tail6.data.o,ov_SC04_021_jr_8013F350.o,tail7.data.o,ov_SC04_021_jr_8013FFD8.o,tail8.data.o,ov_SC04_021_jr_80140608.o,tail9.data.o,ov_SC04_021_jr_8015444C.o,ov_SC04_021_jr_80154C24.o,ov_SC04_021_jr_801588CC.o,ov_SC04_021_jr_80159C84.o,tail10.data.o,ov_SC04_021_jr_8015A3C8.o,tail11.data.o,ov_SC04_021_jr_8015AE2C.o,tail12.data.o,ov_SC04_021_jr_8015C32C.o,tail13.data.o,ov_SC04_021_jr_8016AB6C.o,tail14.data.o,ov_SC04_021_jr_80171B4C.o,ov_SC04_021_jr_801734BC.o,tail15.data.o,ov_SC04_021_jr_801789AC.o,ov_SC04_021_jr_80178D40.o,tail16.data.o,ov_SC04_021_jr_8017A4AC.o,tail17.data.o,ov_SC04_021_jr_8017AE2C.o,tail18.data.o,ov_SC04_021_jr_8017D5C0.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC04_021_JTBL_INTERLEAVE := --order tail.data.o,ov_SC04_021.o,ov_SC04_021_jr_8012ACE0.o,tail2.data.o,ov_SC04_021_jr_80135888.o,tail3.data.o,ov_SC04_021_jr_80135A4C.o,tail4.data.o,ov_SC04_021_jr_80135D20.o,tail5.data.o,ov_SC04_021_jr_801380E0.o,ov_SC04_021_o0c.o,tail6.data.o,ov_SC04_021_jr_8013F350.o,tail7.data.o,ov_SC04_021_jr_8013FFD8.o,tail8.data.o,ov_SC04_021_jr_80140608.o,tail9.data.o,ov_SC04_021_jr_8015444C.o,ov_SC04_021_jr_80154C24.o,ov_SC04_021_jr_801588CC.o,ov_SC04_021_jr_80159C84.o,tail10.data.o,ov_SC04_021_jr_8015A3C8.o,tail11.data.o,ov_SC04_021_jr_8015AE2C.o,tail12.data.o,ov_SC04_021_jr_8015C32C.o,tail13.data.o,ov_SC04_021_jr_8016AB6C.o,tail14.data.o,ov_SC04_021_jr_80171B4C.o,ov_SC04_021_jr_801734BC.o,tail15.data.o,ov_SC04_021_jr_801789AC.o,ov_SC04_021_jr_80178D40.o,tail16.data.o,ov_SC04_021_jr_8017A4AC.o,tail17.data.o,ov_SC04_021_jr_8017AE2C.o,ov_SC04_021_jr_8017D5C0.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC04_021/ov_SC04_021.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC04_021/ov_SC04_021_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0 build/src/ov_SC04_021/ov_SC04_021_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -3462,6 +3464,7 @@ build/src/ov_SC04_021/ov_SC04_021_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC04_021/ov_SC04_021_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC04_021/ov_SC04_021_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC04_021/ov_SC04_021_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 +build/src/ov_SC04_021/ov_SC04_021_jr_8017AE2C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC04_021/ov_SC04_021_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC04_021_CHECK_SHA := config/check.ov_SC04_021.sha ov_SC04_021_SYMBOLS := config/symbols.ov_SC04_021.txt @@ -3942,7 +3945,7 @@ ov_SC05_019_ELF := $(ov_SC05_019_OUT).elf ov_SC05_019_MAPFILE := $(ov_SC05_019_OUT).map ov_SC05_019_LD_SCRIPT := $(ov_SC05_019_OUT).ld ov_SC05_019_SPLAT_YAML := config/splat.ov_SC05_019.yaml -ov_SC05_019_JTBL_INTERLEAVE := --order tail.data.o,ov_SC05_019.o,ov_SC05_019_jr_8012ACE0.o,tail2.data.o,ov_SC05_019_jr_80135888.o,tail3.data.o,ov_SC05_019_jr_80135A4C.o,tail4.data.o,ov_SC05_019_jr_80135D20.o,tail5.data.o,ov_SC05_019_jr_801380E0.o,ov_SC05_019_o0c.o,tail6.data.o,ov_SC05_019_jr_8013F350.o,tail7.data.o,ov_SC05_019_jr_8013FFD8.o,tail8.data.o,ov_SC05_019_jr_80140608.o,tail9.data.o,ov_SC05_019_jr_8015444C.o,ov_SC05_019_jr_80154C24.o,ov_SC05_019_jr_801588CC.o,ov_SC05_019_jr_80159C84.o,tail10.data.o,ov_SC05_019_jr_8015A3C8.o,tail11.data.o,ov_SC05_019_jr_8015AE2C.o,tail12.data.o,ov_SC05_019_jr_8015C32C.o,tail13.data.o,ov_SC05_019_jr_8016AB6C.o,tail14.data.o,ov_SC05_019_jr_80171B4C.o,ov_SC05_019_jr_801734BC.o,tail15.data.o,ov_SC05_019_jr_801789AC.o,ov_SC05_019_jr_80178D40.o,tail16.data.o,ov_SC05_019_jr_8017A4AC.o,tail17.data.o,ov_SC05_019_jr_8017AE2C.o,tail18.data.o,ov_SC05_019_jr_8017D5C0.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve +ov_SC05_019_JTBL_INTERLEAVE := --order tail.data.o,ov_SC05_019.o,ov_SC05_019_jr_8012ACE0.o,tail2.data.o,ov_SC05_019_jr_80135888.o,tail3.data.o,ov_SC05_019_jr_80135A4C.o,tail4.data.o,ov_SC05_019_jr_80135D20.o,tail5.data.o,ov_SC05_019_jr_801380E0.o,ov_SC05_019_o0c.o,tail6.data.o,ov_SC05_019_jr_8013F350.o,tail7.data.o,ov_SC05_019_jr_8013FFD8.o,tail8.data.o,ov_SC05_019_jr_80140608.o,tail9.data.o,ov_SC05_019_jr_8015444C.o,ov_SC05_019_jr_80154C24.o,ov_SC05_019_jr_801588CC.o,ov_SC05_019_jr_80159C84.o,tail10.data.o,ov_SC05_019_jr_8015A3C8.o,tail11.data.o,ov_SC05_019_jr_8015AE2C.o,tail12.data.o,ov_SC05_019_jr_8015C32C.o,tail13.data.o,ov_SC05_019_jr_8016AB6C.o,tail14.data.o,ov_SC05_019_jr_80171B4C.o,ov_SC05_019_jr_801734BC.o,tail15.data.o,ov_SC05_019_jr_801789AC.o,ov_SC05_019_jr_80178D40.o,tail16.data.o,ov_SC05_019_jr_8017A4AC.o,tail17.data.o,ov_SC05_019_jr_8017AE2C.o,ov_SC05_019_jr_8017D5C0.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve build/src/ov_SC05_019/ov_SC05_019.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC05_019/ov_SC05_019_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0 build/src/ov_SC05_019/ov_SC05_019_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18 @@ -3955,6 +3958,7 @@ build/src/ov_SC05_019/ov_SC05_019_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC05_019/ov_SC05_019_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC05_019/ov_SC05_019_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC05_019/ov_SC05_019_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 +build/src/ov_SC05_019/ov_SC05_019_jr_8017AE2C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14 build/src/ov_SC05_019/ov_SC05_019_o0c.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x38,+0xa8,+0x118 ov_SC05_019_CHECK_SHA := config/check.ov_SC05_019.sha ov_SC05_019_SYMBOLS := config/symbols.ov_SC05_019.txt diff --git a/config/splat.ov_SC03_003.yaml b/config/splat.ov_SC03_003.yaml index 6d8ba0ebe..52f9167bf 100644 --- a/config/splat.ov_SC03_003.yaml +++ b/config/splat.ov_SC03_003.yaml @@ -162,9 +162,8 @@ segments: - [0x66488, .rodata, ov_SC03_003_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x66514, data, tail17] - [0x66518, .rodata, ov_SC03_003_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x6652c, data, tail18] - [0x6654c, .rodata, ov_SC03_003_jr_8017D5C0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x6656c, data, tail19] + - [0x6656c, data, tail18] - [0x67A24, bin, trailing] # final 1 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x67A25] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/config/splat.ov_SC03_126.yaml b/config/splat.ov_SC03_126.yaml index c093306e2..4b10624e1 100644 --- a/config/splat.ov_SC03_126.yaml +++ b/config/splat.ov_SC03_126.yaml @@ -162,9 +162,8 @@ segments: - [0x6643c, .rodata, ov_SC03_126_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x664c8, data, tail17] - [0x664cc, .rodata, ov_SC03_126_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x664e0, data, tail18] - [0x66500, .rodata, ov_SC03_126_jr_8017D5C0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x66520, data, tail19] + - [0x66520, data, tail18] - [0x679D4, bin, trailing] # final 1 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x679D5] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/config/splat.ov_SC04_021.yaml b/config/splat.ov_SC04_021.yaml index 6e798c60f..e32b51a3c 100644 --- a/config/splat.ov_SC04_021.yaml +++ b/config/splat.ov_SC04_021.yaml @@ -162,9 +162,8 @@ segments: - [0x6643c, .rodata, ov_SC04_021_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x664c8, data, tail17] - [0x664cc, .rodata, ov_SC04_021_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x664e0, data, tail18] - [0x66500, .rodata, ov_SC04_021_jr_8017D5C0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x66520, data, tail19] + - [0x66520, data, tail18] - [0x679D4, bin, trailing] # final 1 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x679D5] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/config/splat.ov_SC05_019.yaml b/config/splat.ov_SC05_019.yaml index 1cb069878..8315a9f17 100644 --- a/config/splat.ov_SC05_019.yaml +++ b/config/splat.ov_SC05_019.yaml @@ -162,9 +162,8 @@ segments: - [0x6643c, .rodata, ov_SC05_019_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x664c8, data, tail17] - [0x664cc, .rodata, ov_SC05_019_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x664e0, data, tail18] - [0x66500, .rodata, ov_SC05_019_jr_8017D5C0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x66520, data, tail19] + - [0x66520, data, tail18] - [0x679D4, bin, trailing] # final 1 bytes (EOF not 4-aligned; spimdisasm drops a partial word) - [0x679D5] # EOF marker = the 0.4.dec byte length # @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes diff --git a/docs/backlog.md b/docs/backlog.md index 5c5603c83..103273a99 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -2,12 +2,12 @@ > 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:** 837 · by status {'near': 797, 'failed': 40} · by class {'regalloc: qty_compare tie + stratum-3 frame slot (cookbook 147)': 1, 'regalloc: register rotation; hand 63 -> ILS 42 (pin-free seed) -> ILS 41 (pin-t5 seed); both basins plateau': 1, 'plumbing': 3, 'struct': 4, 'regalloc-order': 3, 'schedule': 2, 'loose-typing': 1, 'WAVE': 8, None: 804, 'SCHEDULE-REORDER/2: sched2 INSN_LUID tie, lw $v0,0($s3) vs srl $a2,$a1,16 transposed; hand levers documented spent in the draft header; permuter ILS plateaus at 2 (6 cycles)': 1, 'STRUCT': 9} +**Open near-misses:** 837 · by status {'near': 796, 'matched': 1, 'failed': 40} · by class {'regalloc: qty_compare tie + stratum-3 frame slot (cookbook 147)': 1, 'SOLVED: per-pass variables + prim-loop clamp reuse (cookbook §150); NOT an allocator tie': 1, 'plumbing': 3, 'struct': 4, 'regalloc-order': 3, 'schedule': 2, 'loose-typing': 1, 'WAVE': 8, None: 804, 'SCHEDULE-REORDER/2: sched2 INSN_LUID tie, lw $v0,0($s3) vs srl $a2,$a1,16 transposed; hand levers documented spent in the draft header; permuter ILS plateaus at 2 (6 cycles)': 1, 'STRUCT': 9} | # | addr | reach | class | nins | status | closeness | where it stuck | best draft | |--:|------|------:|-------|-----:|--------|----------:|----------------|------------| | 1 | func_8017C294 | 16 | regalloc: qty_compare tie + stratum-3 frame slot (cookbook 147) | 246 | near | 12 | ov_SC01_077 | `.run/s42/ov_SC01_077/func_8017C294.c` | -| 2 | func_8017C6F4 | 3 | regalloc: register rotation; hand 63 -> ILS 42 (pin-free seed) -> ILS 41 (pin-t5 seed); both basins plateau | 947 | near | 41 | ov_SC03_126; BEST KNOWN. permuter ILS from the pin-t5 seed, masked 43, flat over 5 warm restarts | `.run/s43/func_8017C6F4.ils43-pin.c` | +| 2 | func_8017C6F4 | 4 | SOLVED: per-pass variables + prim-loop clamp reuse (cookbook §150); NOT an allocator tie | 947 | matched | 0 | BANKED x4 (SC03_126/003, SC04_021, SC05_019) pending R22 clean-fleet | `.run/s43/fable/8017C6F4/v2_rtu.c` | | 3 | func_8017F714 | 1 | plumbing | 27 | near | 0 | none — MATCH (27/27 ins, match_one verified) | `.run/backlog_drafts/func_8017F714.c` | | 4 | func_8017E224 | 1 | struct | 29 | near | 0 | none — MATCH (unaligned 8-byte memcpy of global onto stack + cond byte incr) | `.run/backlog_drafts/func_8017E224.c` | | 5 | func_80184A68 | 1 | regalloc-order | 33 | near | 0 | none — MATCH | `.run/backlog_drafts/func_80184A68.c` | diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index ec544e25f..254c7c187 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -10259,3 +10259,58 @@ it is scheduled — the probe here cost minutes and removed a phantom item from **Symptom lines for the index:** **"the permuter found no match in 0 seconds"** · **"a wall that only one tool reports"** · **"a backlog row that outranks a better result"** · **"CC1-FAIL: make: *** Error N"** · **"cheap fuel nobody has probed"**. + +--- + +## §150 — A register ROTATION across symmetric blocks is VARIABLE-IDENTITY evidence, not an allocator tie (P30 S43, `func_8017C6F4`, 947 ins ×4) + +The function that §147-E's signature fit perfectly — "structure exactly right, one register pair +transposed, hand sweep and permuter plateau at the same number" — and the signature was **wrong about +the cause**. Every lever aimed at the allocator was structurally inert because the draft had the wrong +NUMBER OF PSEUDOS. Two coupled source-shape changes matched it pin-free. + +### The fix +1. **The X-pass and Y-pass min/max intermediates are DIFFERENT variables** — `xmn1/xmx1/xmn2/xmx2` + *and* `ymn1/ymx1/ymn2/ymx2` (8, not 4 reused). +2. **The cell-level clamp temps did not exist.** The original reuses the PRIM-LOOP variables: + `mn/mx` for the cell X clamp, `mny/my` for the Y clamp. + +**Neither half works alone** — split-only = 63 mismatched (which is exactly why a previous session's +"separate X vs Y variables" probe was recorded as a failure), reuse-only = 624 + length drift, the +conjunction = MATCH. **Ablate both ways before believing either half is wrong.** + +### The method that found it (this is the transferable part) +The diff's **matching** regions are a pseudo→register ownership map. Read the *mismatching* region's +target registers against that map before touching the allocator: +- **Different target registers for different instances of a symmetric block ⇒ per-instance + variables.** gcc-2.7.2 does no live-range splitting: one pseudo holds one hard reg for life. So if + the X pass uses `(a2,t1,a1,a3)` and the Y pass `(a3,t0,a1,a2)`, the original CANNOT have used one + shared set — and no allocator steering on a shared-variable draft can ever reproduce it. +- **Contested registers that coincide with a KNOWN variable's register ⇒ the region reuses that + variable.** Here the four clamp registers were exactly the prim-loop `mn/mx/mny/my` registers, + already byte-matched elsewhere in the function, with the right semantics per axis. +- **A deleted self-move in ONE instance of a repeated block is a per-instance-variables tell.** + `global_conflicts` processes `REG_DEAD` **before** `mark_reg_store` (`global.c:719` vs `:729`), so a + copy whose source dies at that point records no conflict and the destination may be granted the + source's register by ordinary first-fit — the copy then vanishes. A single shared pseudo can never + be "same register as its source" in one pass and "different" in the other. + +### Two corrections to the record +- **§147-E named the wrong allocator.** The contested values here are multi-block and non-call-crossing + ⇒ **`global.c` allocnos**, not local `qty_compare` quantities. With the right variable identities, + plain `allocno_compare` density order + first-fit reproduces every grant deterministically (full + priority table in `.run/s43/fable/8017C6F4/NOTES.md`). Check WHICH allocator owns the value before + citing a tie in it. +- **§148's "residual is one register rotation, did not move under ~40 probes"** is explained: the + probes were all allocator-shaped, and the defect was arithmetic — the wrong number of pseudos. + Register pins, priority sliders (§148-C), declaration order and the permuter are all *inert* against + a variable-identity error, which is why they agreed on a floor. + +### Diagnostic order (adopt this) +**Decode ownership → check pseudo COUNT and per-instance identity → only then reach for pins, sliders, +statement order, or the permuter.** A rotation that survives every allocator lever is evidence about +the VARIABLES, not about the allocator. + +**Symptom lines for the index:** **"one register pair transposed"** · **"different registers in the X +pass than the Y pass"** · **"a missing move / deleted copy in one of two symmetric blocks"** · **"every +pin and slider is inert"** · **"hand sweep and permuter plateau at the same number"**. diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index 2279c37b2..859469bbc 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -2286,6 +2286,46 @@ read of the scheduler is exactly this class) — that needs Drew's go (R27). near-miss; `func_8017CE58`'s only draft is Ghidra-C and CC1-FAILs. **Re-derive every queue entry's size and home from the bytes before briefing an agent on it** — the list's annotations are unreliable. +### ▶ S43-6 — `func_8017C6F4` CRACKED by Fable5, pin-free, and banked ×4 (~3,788 ins) (2026-08-05) +Drew approved the Fable5 escalation (R27). Two isolated agents, one per function, never batched. + +**RESULT: byte-exact, pin-free, 947 ins — and my diagnosis was wrong.** I had this filed as §147-E, a +`qty_compare` tie unreachable from source. It was **variable-identity evidence** all along: +1. the X-pass and Y-pass min/max intermediates are **different variables** (8, not 4 reused); +2. `mnc`/`mxc` **do not exist** — the cell clamps reuse the PRIM-LOOP `mn/mx` (X) and `mny/my` (Y). +Ablations prove the conjunction is required: split-only **63**, reuse-only **624**, both = MATCH. +That also explains why S42's "separate X vs Y variables" probe was recorded as a failure — it was +half the fix. And why every allocator lever was inert (pins, §148-C sliders, declaration order, 14 +permuter restarts): **the draft had the wrong NUMBER OF PSEUDOS**, which no allocator steering reaches. + +**Verified independently before believing it (R14):** `match_one` MATCH (947 ins) re-run by me, then +the whole-binary gate. + +**BANKED ×4 — every 948-ins sibling of this body:** +| binary | SHA (byte-identical) | +|---|---| +| ov_SC03_126 | `c48a8bb894974dd3746a5833a20ee6da2feb831f` | +| ov_SC03_003 | `898bf52a903dcb74ce11d2a8389c483ecc24e49e` | +| ov_SC04_021 | `336142349b39ea4f5139b035fdb1ca8d8e7961c8` | +| ov_SC05_019 | `3f5b4f132ed3ca63522d75c4021033b9d32b7a39` | +`family_remap` produced all three siblings cleanly (SC03_003 remapped 4 per-overlay symbols; the other +two needed none). **≈3,788 instructions.** ⚠️ These are INCREMENTAL-build gates — R22 clean-fleet is +owed before the commit is trustworthy (§130: an incremental build can pass what a clean build cannot +even link). Deferred only because the second Fable5 agent is reading `asm/` and `make clean` would +destroy its inputs mid-run. + +**The propagation gotcha (§146, seen again):** all three siblings first failed the gate with +`PLUMBING: parse error before 'MTX_C6F4'` — `family_remap`'s `_carry_macros` carries `#define`s but +**not typedefs**. Prepending the 9 typedef lines to each remapped draft fixed all three. +**Worth noting: that label is legible only because of this session's classifier fix — before it, this +would have read `CC1-FAIL: make: *** Error N` and cost three manual splice-and-rebuild diagnoses.** + +**Idiom distilled → cookbook §150** (a register rotation across symmetric blocks is variable-identity +evidence; decode ownership from the MATCHING diff regions first; per-instance register asymmetry ⇒ +per-instance variables; a deleted self-move in one of two symmetric blocks is the tell; and the +`global.c:719`-vs-`:729` death-before-store exemption that produces it). §147-E corrected: it named +the wrong allocator — these are `global.c` allocnos, not local `qty_compare` quantities. + ### ▶ S11 — the propagation lag: EXTEND 0/36 -> 31/36, and every blocker was a DECLARATION (2026-08-03/04) Lane 2 of the S10 checkpoint ("26,006 ins, ~0 agent tokens, PARTLY BLOCKED"), taken first on the standing doctrine that the cheap deterministic lever is probed before the expensive agent one. diff --git a/src/ov_SC03_003/ov_SC03_003_jr_8017AE2C.c b/src/ov_SC03_003/ov_SC03_003_jr_8017AE2C.c index 22be0cbcc..bb503a5f5 100644 --- a/src/ov_SC03_003/ov_SC03_003_jr_8017AE2C.c +++ b/src/ov_SC03_003/ov_SC03_003_jr_8017AE2C.c @@ -3402,4 +3402,469 @@ void func_8017C688(s32 a0, s32 a1) { } -INCLUDE_ASM("asm/ov_SC03_003/nonmatchings/ov_SC03_003_jr_8017AE2C", func_8017C6F4); +typedef struct { u32 w0, w1, w2; } Prim126; +typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126; +typedef struct { s16 vx, vy; } DVEC2_C6F4; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C6F4; +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2, x3, y3; } PF4_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; } PFT3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; s16 x3, y3; u16 uv3, p3; } PFT4_C6F4; + +#define gte_ldv0(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 )" \ + : \ + : "r"( r0 ) ) +#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 0( %1 );" \ + "lwc2 $3, 4( %1 );" \ + "lwc2 $4, 0( %2 );" \ + "lwc2 $5, 4( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) ) +#define gte_ldv3c(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 8( %0 );" \ + "lwc2 $3, 12( %0 );" \ + "lwc2 $4, 16( %0 );" \ + "lwc2 $5, 20( %0 )" \ + : \ + : "r"( r0 ) ) +#define gte_rtps() __asm__ volatile ("nop;nop;rtps") +#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt") +#define gte_nclip() __asm__ volatile ("nop;nop;nclip") +#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3") +#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4") +#define gte_stsxy(r0) __asm__ volatile ( \ + "swc2 $14, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 0( %1 );" \ + "swc2 $14, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) +#define gte_stsxy3c(r0) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 4( %0 );" \ + "swc2 $14, 8( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsxy3_f3(r0) __asm__ volatile ( \ + "swc2 $12, 8( %0 );" \ + "swc2 $13, 12( %0 );" \ + "swc2 $14, 16( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $17, 0( %0 );" \ + "swc2 $18, 0( %1 );" \ + "swc2 $19, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) +#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \ + "swc2 $16, 0( %0 );" \ + "swc2 $17, 0( %1 );" \ + "swc2 $18, 0( %2 );" \ + "swc2 $19, 0( %3 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \ + : "memory" ) +#define gte_stflg(r0) __asm__ volatile ( \ + "cfc2 $12, $31;" \ + "nop;" \ + "sw $12, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "$12", "memory" ) +#define gte_stopz(r0) __asm__ volatile ( \ + "swc2 $24, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +void func_8017C6F4(s32 arg0) +{ + extern s32 func_800491EC(void); + extern void func_800547D8(s32, MTX_C6F4 *); + extern void func_80052E38(MTX_C6F4 *); + extern void func_8017C014(void *, void *, s32); + extern u8 D_8018FA10[]; + extern u8 *D_800A5E60; + extern u8 D_800A6610[]; + extern short D_800B9A02; + + s16 rect[4]; + DVEC2_C6F4 tmpxy[4]; + SVEC2_C6F4 box[8]; + SVEC2_C6F4 sxy[8]; + MTX_C6F4 mtx; + struct { long flag, opz, sz0, sz1, sz2, sz3; } g; + + s32 cx0, cx1, cy0, cy1, y, col; + Cell126 **rowptr; + Cell126 **p; + Cell126 *cell; + Prim126 *prim; + Prim126 *end; + u8 *pkt; + u32 ot; + u8 *vtx; + u8 *va, *vb, *vc, *vd; + u32 w, code; + u32 wx, wy, wz; + u32 xlo, xhi, ylo, yhi, zlo, zhi; + s32 xa32, xb32, t32; + s32 xmn1, xmx1, xmn2, xmx2; + s32 ymn1, ymx1, ymn2, ymx2; + s32 my, mny, mx, mn; + + func_800491EC(); + func_800547D8(arg0 + 0x10, &mtx); + func_80052E38(&mtx); + func_8017C014(D_8018FA10, rect, *(s32 *)(arg0 + 0x60)); + + pkt = D_800A5E60; + ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14]; + + cx0 = (rect[0] + 0x4000) / 512; + cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2; + cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0); + cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1); + cy0 = (rect[1] + 0x4000) / 512 - 1; + cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2; + cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0); + cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1); + + rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0); + + for (y = cy0; y < cy1; y++, rowptr += 0x40) { + for (col = cx0, p = rowptr; col < cx1; col++, p++) { + cell = *p; + if (cell == 0) continue; + + wx = cell->xx; + xlo = wx & 0xFFFF; + xhi = wx >> 16; + wy = cell->yy; + ylo = wy & 0xFFFF; + yhi = wy >> 16; + wz = cell->zz; + zlo = wz & 0xFFFF; + zhi = wz >> 16; + + box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo; + box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo; + box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi; + box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi; + box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo; + box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo; + box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi; + box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi; + + gte_ldv3c(&box[0]); + gte_rtpt(); + gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]); + gte_ldv0(&box[3]); + gte_rtps(); + gte_stsxy(&sxy[3]); + gte_ldv3c(&box[4]); + gte_rtpt(); + gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]); + gte_ldv0(&box[7]); + gte_rtps(); + gte_stsxy(&sxy[7]); + + xa32 = sxy[0].vx; + xb32 = sxy[1].vx; + if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; } + t32 = sxy[2].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + t32 = sxy[3].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + xa32 = sxy[4].vx; + xb32 = sxy[5].vx; + if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; } + t32 = sxy[6].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + t32 = sxy[7].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + mn = xmn1; + if (xmn2 < mn) mn = xmn2; + mx = xmx1; + if (mx < xmx2) mx = xmx2; + if (mx < -0xA0) continue; + if (!(mn < 0xA1)) continue; + + xa32 = sxy[0].vy; + xb32 = sxy[1].vy; + if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; } + t32 = sxy[2].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + t32 = sxy[3].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + xa32 = sxy[4].vy; + xb32 = sxy[5].vy; + if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; } + t32 = sxy[6].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + t32 = sxy[7].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + mny = ymn1; + if (ymn2 < mny) mny = ymn2; + my = ymx1; + if (my < ymx2) my = ymx2; + if (my < -0x78) continue; + if (!(mny < 0x79)) continue; + + prim = cell->prim; + end = cell->end; + vtx = cell->vtx; + while (prim < end) { + w = prim->w1; + va = vtx + (w & 0xFFFF); + vb = vtx + (w >> 16); + w = prim->w2; + vc = vtx + (w & 0xFFFF); + w = w >> 16; + gte_ldv3(va, vb, vc); + gte_rtpt(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_nclip(); + code = w & 0xF; + vd = vtx + ((w & 0xFFF0) >> 1); + gte_stopz(&g.opz); + if (g.opz > 0) { + switch (code) { + case 4: + case 5: + gte_stsxy3_f3(pkt); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) { + mx = ((PFT3_C6F4 *)pkt)->x0; + mn = ((PFT3_C6F4 *)pkt)->x1; + } else { + mn = ((PFT3_C6F4 *)pkt)->x0; + mx = ((PFT3_C6F4 *)pkt)->x1; + } + if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2; + else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) { + my = ((PFT3_C6F4 *)pkt)->y0; + mny = ((PFT3_C6F4 *)pkt)->y1; + } else { + mny = ((PFT3_C6F4 *)pkt)->y0; + my = ((PFT3_C6F4 *)pkt)->y1; + } + if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2; + else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 4) g.opz = za + 0x200; + ((PF3_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x14; + } + } + break; + case 6: + case 7: + gte_stsxy3c(&tmpxy[0]); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + u32 *tp; + gte_avsz3(); + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 6) g.opz = za + 0x200; + *(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + tp = (u32 *)prim->w0; + ((PFT3_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT3_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT3_C6F4 *)pkt)->uvp1 = tp[2]; + ((PFT3_C6F4 *)pkt)->uv2 = tp[3]; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x20; + } + } + break; + case 0: + case 1: + gte_stsxy3_f3(pkt); + gte_ldv0(vd); + gte_rtps(); + if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) { + mx = ((PF4_C6F4 *)pkt)->x0; + mn = ((PF4_C6F4 *)pkt)->x1; + } else { + mn = ((PF4_C6F4 *)pkt)->x0; + mx = ((PF4_C6F4 *)pkt)->x1; + } + if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2; + else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2; + if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) { + my = ((PF4_C6F4 *)pkt)->y0; + mny = ((PF4_C6F4 *)pkt)->y1; + } else { + mny = ((PF4_C6F4 *)pkt)->y0; + my = ((PF4_C6F4 *)pkt)->y1; + } + if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2; + else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2; + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3); + if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3; + else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3; + else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 0) g.opz = za + 0x200; + ((PF4_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x18; + } + } + } + break; + case 2: + case 3: + gte_stsxy3c(&tmpxy[0]); + gte_ldv0(vd); + gte_rtps(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsxy(&tmpxy[3]); + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (tmpxy[3].vx > mx) mx = tmpxy[3].vx; + else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (tmpxy[3].vx > my) my = tmpxy[3].vx; + else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + u32 *tp; + u32 uvw; + gte_avsz4(); + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 2) g.opz = za + 0x200; + *(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3]; + tp = (u32 *)prim->w0; + ((PFT4_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT4_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT4_C6F4 *)pkt)->uvp1 = tp[2]; + uvw = tp[3]; + ((PFT4_C6F4 *)pkt)->uv2 = uvw; + ((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x28; + } + } + } + break; + } + } + } + prim++; + } + } + } + D_800A5E60 = pkt; +} + diff --git a/src/ov_SC03_126/ov_SC03_126_jr_8017AE2C.c b/src/ov_SC03_126/ov_SC03_126_jr_8017AE2C.c index 528fd3221..b0a69e7b8 100644 --- a/src/ov_SC03_126/ov_SC03_126_jr_8017AE2C.c +++ b/src/ov_SC03_126/ov_SC03_126_jr_8017AE2C.c @@ -3401,5 +3401,503 @@ void func_8017C688(s32 a0, s32 a1) { } -INCLUDE_ASM("asm/ov_SC03_126/nonmatchings/ov_SC03_126_jr_8017AE2C", func_8017C6F4); +#include "common.h" + +/* func_8017C6F4 — ov_SC03_126_jr_8017AE2C — MAP-TILE model renderer (947 ins). + * Sibling of the matched func_8017BEBC (952 ins, §47) and func_8017CDF0. + * Outer: screen rect -> 64x64 cell grid window -> per-cell bbox RTPT/RTPS cull. + * Inner: per-prim RTPT -> flag/nclip/opz cull -> switch(w & 0xF): + * 0,1=POLY_F4 / 2,3=POLY_FT4 / 4,5=POLY_F3 / 6,7=POLY_FT3 -> OT insert. + * NOTE: the F3 arm bbox-tests the packet through PFT3_C6F4 offsets (8/0x10/0x18) + * — a source-level copy/paste quirk of this variant, reproduced verbatim. + * + * MATCH (947 ins, pin-free) — s43 Fable crack. Two load-bearing source shapes + * (byte-proven; see .run/s43/fable/8017C6F4/NOTES.md): + * 1. X-pass and Y-pass bbox min/max intermediates are DISTINCT variables + * (xmn1..xmx2 vs ymn1..ymx2) — the target allocates them differently. + * 2. The cell-level clamps REUSE the prim-loop vars (mn/mx for X, mny/my + * for Y); there are no separate mnc/mxc. This puts the clamps in + * $t0/$a2/$a3/$a1 and makes the Y-pass `mny = ymn1` a deleted self-move. + * Neither change matches alone (63 / 624 mismatches); prim lands $t5 and + * cell $t3 naturally once the bbox block allocates right. + */ + +typedef struct { u32 w0, w1, w2; } Prim126; +typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126; + +typedef struct { s16 vx, vy; } DVEC2_C6F4; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C6F4; +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2, x3, y3; } PF4_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; } PFT3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; s16 x3, y3; u16 uv3, p3; } PFT4_C6F4; + +#define gte_ldv0(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 )" \ + : \ + : "r"( r0 ) ) + +#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 0( %1 );" \ + "lwc2 $3, 4( %1 );" \ + "lwc2 $4, 0( %2 );" \ + "lwc2 $5, 4( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) ) + +#define gte_ldv3c(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 8( %0 );" \ + "lwc2 $3, 12( %0 );" \ + "lwc2 $4, 16( %0 );" \ + "lwc2 $5, 20( %0 )" \ + : \ + : "r"( r0 ) ) + +#define gte_rtps() __asm__ volatile ("nop;nop;rtps") +#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt") +#define gte_nclip() __asm__ volatile ("nop;nop;nclip") +#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3") +#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4") + +#define gte_stsxy(r0) __asm__ volatile ( \ + "swc2 $14, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 0( %1 );" \ + "swc2 $14, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) + +#define gte_stsxy3c(r0) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 4( %0 );" \ + "swc2 $14, 8( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsxy3_f3(r0) __asm__ volatile ( \ + "swc2 $12, 8( %0 );" \ + "swc2 $13, 12( %0 );" \ + "swc2 $14, 16( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $17, 0( %0 );" \ + "swc2 $18, 0( %1 );" \ + "swc2 $19, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) + +#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \ + "swc2 $16, 0( %0 );" \ + "swc2 $17, 0( %1 );" \ + "swc2 $18, 0( %2 );" \ + "swc2 $19, 0( %3 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \ + : "memory" ) + +#define gte_stflg(r0) __asm__ volatile ( \ + "cfc2 $12, $31;" \ + "nop;" \ + "sw $12, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "$12", "memory" ) + +#define gte_stopz(r0) __asm__ volatile ( \ + "swc2 $24, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +void func_8017C6F4(s32 arg0) +{ + extern s32 func_800491EC(void); + extern void func_800547D8(s32, MTX_C6F4 *); + extern void func_80052E38(MTX_C6F4 *); + extern void func_8017C014(void *, void *, s32); + extern u8 D_8018F9C0[]; + extern u8 *D_800A5E60; + extern u8 D_800A6610[]; + extern short D_800B9A02; + + s16 rect[4]; + DVEC2_C6F4 tmpxy[4]; + SVEC2_C6F4 box[8]; + SVEC2_C6F4 sxy[8]; + MTX_C6F4 mtx; + struct { long flag, opz, sz0, sz1, sz2, sz3; } g; + + s32 cx0, cx1, cy0, cy1, y, col; + Cell126 **rowptr; + Cell126 **p; + Cell126 *cell; + Prim126 *prim; + Prim126 *end; + u8 *pkt; + u32 ot; + u8 *vtx; + u8 *va, *vb, *vc, *vd; + u32 w, code; + u32 wx, wy, wz; + u32 xlo, xhi, ylo, yhi, zlo, zhi; + s32 xa32, xb32, t32; + s32 xmn1, xmx1, xmn2, xmx2; + s32 ymn1, ymx1, ymn2, ymx2; + s32 my, mny, mx, mn; + + func_800491EC(); + func_800547D8(arg0 + 0x10, &mtx); + func_80052E38(&mtx); + func_8017C014(D_8018F9C0, rect, *(s32 *)(arg0 + 0x60)); + + pkt = D_800A5E60; + ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14]; + + cx0 = (rect[0] + 0x4000) / 512; + cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2; + cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0); + cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1); + cy0 = (rect[1] + 0x4000) / 512 - 1; + cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2; + cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0); + cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1); + + rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0); + + for (y = cy0; y < cy1; y++, rowptr += 0x40) { + for (col = cx0, p = rowptr; col < cx1; col++, p++) { + cell = *p; + if (cell == 0) continue; + + wx = cell->xx; + xlo = wx & 0xFFFF; + xhi = wx >> 16; + wy = cell->yy; + ylo = wy & 0xFFFF; + yhi = wy >> 16; + wz = cell->zz; + zlo = wz & 0xFFFF; + zhi = wz >> 16; + + box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo; + box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo; + box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi; + box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi; + box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo; + box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo; + box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi; + box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi; + + gte_ldv3c(&box[0]); + gte_rtpt(); + gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]); + gte_ldv0(&box[3]); + gte_rtps(); + gte_stsxy(&sxy[3]); + gte_ldv3c(&box[4]); + gte_rtpt(); + gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]); + gte_ldv0(&box[7]); + gte_rtps(); + gte_stsxy(&sxy[7]); + + xa32 = sxy[0].vx; + xb32 = sxy[1].vx; + if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; } + t32 = sxy[2].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + t32 = sxy[3].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + xa32 = sxy[4].vx; + xb32 = sxy[5].vx; + if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; } + t32 = sxy[6].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + t32 = sxy[7].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + mn = xmn1; + if (xmn2 < mn) mn = xmn2; + mx = xmx1; + if (mx < xmx2) mx = xmx2; + if (mx < -0xA0) continue; + if (!(mn < 0xA1)) continue; + + xa32 = sxy[0].vy; + xb32 = sxy[1].vy; + if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; } + t32 = sxy[2].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + t32 = sxy[3].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + xa32 = sxy[4].vy; + xb32 = sxy[5].vy; + if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; } + t32 = sxy[6].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + t32 = sxy[7].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + mny = ymn1; + if (ymn2 < mny) mny = ymn2; + my = ymx1; + if (my < ymx2) my = ymx2; + if (my < -0x78) continue; + if (!(mny < 0x79)) continue; + + prim = cell->prim; + end = cell->end; + vtx = cell->vtx; + while (prim < end) { + w = prim->w1; + va = vtx + (w & 0xFFFF); + vb = vtx + (w >> 16); + w = prim->w2; + vc = vtx + (w & 0xFFFF); + w = w >> 16; + gte_ldv3(va, vb, vc); + gte_rtpt(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_nclip(); + code = w & 0xF; + vd = vtx + ((w & 0xFFF0) >> 1); + gte_stopz(&g.opz); + if (g.opz > 0) { + switch (code) { + case 4: + case 5: + gte_stsxy3_f3(pkt); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) { + mx = ((PFT3_C6F4 *)pkt)->x0; + mn = ((PFT3_C6F4 *)pkt)->x1; + } else { + mn = ((PFT3_C6F4 *)pkt)->x0; + mx = ((PFT3_C6F4 *)pkt)->x1; + } + if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2; + else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) { + my = ((PFT3_C6F4 *)pkt)->y0; + mny = ((PFT3_C6F4 *)pkt)->y1; + } else { + mny = ((PFT3_C6F4 *)pkt)->y0; + my = ((PFT3_C6F4 *)pkt)->y1; + } + if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2; + else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 4) g.opz = za + 0x200; + ((PF3_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x14; + } + } + break; + case 6: + case 7: + gte_stsxy3c(&tmpxy[0]); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + u32 *tp; + gte_avsz3(); + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 6) g.opz = za + 0x200; + *(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + tp = (u32 *)prim->w0; + ((PFT3_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT3_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT3_C6F4 *)pkt)->uvp1 = tp[2]; + ((PFT3_C6F4 *)pkt)->uv2 = tp[3]; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x20; + } + } + break; + case 0: + case 1: + gte_stsxy3_f3(pkt); + gte_ldv0(vd); + gte_rtps(); + if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) { + mx = ((PF4_C6F4 *)pkt)->x0; + mn = ((PF4_C6F4 *)pkt)->x1; + } else { + mn = ((PF4_C6F4 *)pkt)->x0; + mx = ((PF4_C6F4 *)pkt)->x1; + } + if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2; + else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2; + if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) { + my = ((PF4_C6F4 *)pkt)->y0; + mny = ((PF4_C6F4 *)pkt)->y1; + } else { + mny = ((PF4_C6F4 *)pkt)->y0; + my = ((PF4_C6F4 *)pkt)->y1; + } + if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2; + else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2; + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3); + if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3; + else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3; + else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 0) g.opz = za + 0x200; + ((PF4_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x18; + } + } + } + break; + case 2: + case 3: + gte_stsxy3c(&tmpxy[0]); + gte_ldv0(vd); + gte_rtps(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsxy(&tmpxy[3]); + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (tmpxy[3].vx > mx) mx = tmpxy[3].vx; + else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (tmpxy[3].vx > my) my = tmpxy[3].vx; + else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + u32 *tp; + u32 uvw; + gte_avsz4(); + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 2) g.opz = za + 0x200; + *(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3]; + tp = (u32 *)prim->w0; + ((PFT4_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT4_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT4_C6F4 *)pkt)->uvp1 = tp[2]; + uvw = tp[3]; + ((PFT4_C6F4 *)pkt)->uv2 = uvw; + ((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x28; + } + } + } + break; + } + } + } + prim++; + } + } + } + D_800A5E60 = pkt; +} + diff --git a/src/ov_SC04_021/ov_SC04_021_jr_8017AE2C.c b/src/ov_SC04_021/ov_SC04_021_jr_8017AE2C.c index a5157b962..66b1bb92e 100644 --- a/src/ov_SC04_021/ov_SC04_021_jr_8017AE2C.c +++ b/src/ov_SC04_021/ov_SC04_021_jr_8017AE2C.c @@ -3401,5 +3401,470 @@ void func_8017C688(s32 a0, s32 a1) { } -INCLUDE_ASM("asm/ov_SC04_021/nonmatchings/ov_SC04_021_jr_8017AE2C", func_8017C6F4); +typedef struct { u32 w0, w1, w2; } Prim126; +typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126; +typedef struct { s16 vx, vy; } DVEC2_C6F4; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C6F4; +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2, x3, y3; } PF4_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; } PFT3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; s16 x3, y3; u16 uv3, p3; } PFT4_C6F4; + +#define gte_ldv0(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 )" \ + : \ + : "r"( r0 ) ) +#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 0( %1 );" \ + "lwc2 $3, 4( %1 );" \ + "lwc2 $4, 0( %2 );" \ + "lwc2 $5, 4( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) ) +#define gte_ldv3c(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 8( %0 );" \ + "lwc2 $3, 12( %0 );" \ + "lwc2 $4, 16( %0 );" \ + "lwc2 $5, 20( %0 )" \ + : \ + : "r"( r0 ) ) +#define gte_rtps() __asm__ volatile ("nop;nop;rtps") +#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt") +#define gte_nclip() __asm__ volatile ("nop;nop;nclip") +#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3") +#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4") +#define gte_stsxy(r0) __asm__ volatile ( \ + "swc2 $14, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 0( %1 );" \ + "swc2 $14, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) +#define gte_stsxy3c(r0) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 4( %0 );" \ + "swc2 $14, 8( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsxy3_f3(r0) __asm__ volatile ( \ + "swc2 $12, 8( %0 );" \ + "swc2 $13, 12( %0 );" \ + "swc2 $14, 16( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $17, 0( %0 );" \ + "swc2 $18, 0( %1 );" \ + "swc2 $19, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) +#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \ + "swc2 $16, 0( %0 );" \ + "swc2 $17, 0( %1 );" \ + "swc2 $18, 0( %2 );" \ + "swc2 $19, 0( %3 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \ + : "memory" ) +#define gte_stflg(r0) __asm__ volatile ( \ + "cfc2 $12, $31;" \ + "nop;" \ + "sw $12, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "$12", "memory" ) +#define gte_stopz(r0) __asm__ volatile ( \ + "swc2 $24, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +void func_8017C6F4(s32 arg0) +{ + extern s32 func_800491EC(void); + extern void func_800547D8(s32, MTX_C6F4 *); + extern void func_80052E38(MTX_C6F4 *); + extern void func_8017C014(void *, void *, s32); + extern u8 D_8018F9C0[]; + extern u8 *D_800A5E60; + extern u8 D_800A6610[]; + extern short D_800B9A02; + + s16 rect[4]; + DVEC2_C6F4 tmpxy[4]; + SVEC2_C6F4 box[8]; + SVEC2_C6F4 sxy[8]; + MTX_C6F4 mtx; + struct { long flag, opz, sz0, sz1, sz2, sz3; } g; + + s32 cx0, cx1, cy0, cy1, y, col; + Cell126 **rowptr; + Cell126 **p; + Cell126 *cell; + Prim126 *prim; + Prim126 *end; + u8 *pkt; + u32 ot; + u8 *vtx; + u8 *va, *vb, *vc, *vd; + u32 w, code; + u32 wx, wy, wz; + u32 xlo, xhi, ylo, yhi, zlo, zhi; + s32 xa32, xb32, t32; + s32 xmn1, xmx1, xmn2, xmx2; + s32 ymn1, ymx1, ymn2, ymx2; + s32 my, mny, mx, mn; + + func_800491EC(); + func_800547D8(arg0 + 0x10, &mtx); + func_80052E38(&mtx); + func_8017C014(D_8018F9C0, rect, *(s32 *)(arg0 + 0x60)); + + pkt = D_800A5E60; + ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14]; + + cx0 = (rect[0] + 0x4000) / 512; + cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2; + cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0); + cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1); + cy0 = (rect[1] + 0x4000) / 512 - 1; + cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2; + cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0); + cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1); + + rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0); + + for (y = cy0; y < cy1; y++, rowptr += 0x40) { + for (col = cx0, p = rowptr; col < cx1; col++, p++) { + cell = *p; + if (cell == 0) continue; + + wx = cell->xx; + xlo = wx & 0xFFFF; + xhi = wx >> 16; + wy = cell->yy; + ylo = wy & 0xFFFF; + yhi = wy >> 16; + wz = cell->zz; + zlo = wz & 0xFFFF; + zhi = wz >> 16; + + box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo; + box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo; + box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi; + box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi; + box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo; + box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo; + box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi; + box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi; + + gte_ldv3c(&box[0]); + gte_rtpt(); + gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]); + gte_ldv0(&box[3]); + gte_rtps(); + gte_stsxy(&sxy[3]); + gte_ldv3c(&box[4]); + gte_rtpt(); + gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]); + gte_ldv0(&box[7]); + gte_rtps(); + gte_stsxy(&sxy[7]); + + xa32 = sxy[0].vx; + xb32 = sxy[1].vx; + if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; } + t32 = sxy[2].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + t32 = sxy[3].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + xa32 = sxy[4].vx; + xb32 = sxy[5].vx; + if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; } + t32 = sxy[6].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + t32 = sxy[7].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + mn = xmn1; + if (xmn2 < mn) mn = xmn2; + mx = xmx1; + if (mx < xmx2) mx = xmx2; + if (mx < -0xA0) continue; + if (!(mn < 0xA1)) continue; + + xa32 = sxy[0].vy; + xb32 = sxy[1].vy; + if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; } + t32 = sxy[2].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + t32 = sxy[3].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + xa32 = sxy[4].vy; + xb32 = sxy[5].vy; + if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; } + t32 = sxy[6].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + t32 = sxy[7].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + mny = ymn1; + if (ymn2 < mny) mny = ymn2; + my = ymx1; + if (my < ymx2) my = ymx2; + if (my < -0x78) continue; + if (!(mny < 0x79)) continue; + + prim = cell->prim; + end = cell->end; + vtx = cell->vtx; + while (prim < end) { + w = prim->w1; + va = vtx + (w & 0xFFFF); + vb = vtx + (w >> 16); + w = prim->w2; + vc = vtx + (w & 0xFFFF); + w = w >> 16; + gte_ldv3(va, vb, vc); + gte_rtpt(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_nclip(); + code = w & 0xF; + vd = vtx + ((w & 0xFFF0) >> 1); + gte_stopz(&g.opz); + if (g.opz > 0) { + switch (code) { + case 4: + case 5: + gte_stsxy3_f3(pkt); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) { + mx = ((PFT3_C6F4 *)pkt)->x0; + mn = ((PFT3_C6F4 *)pkt)->x1; + } else { + mn = ((PFT3_C6F4 *)pkt)->x0; + mx = ((PFT3_C6F4 *)pkt)->x1; + } + if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2; + else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) { + my = ((PFT3_C6F4 *)pkt)->y0; + mny = ((PFT3_C6F4 *)pkt)->y1; + } else { + mny = ((PFT3_C6F4 *)pkt)->y0; + my = ((PFT3_C6F4 *)pkt)->y1; + } + if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2; + else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 4) g.opz = za + 0x200; + ((PF3_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x14; + } + } + break; + case 6: + case 7: + gte_stsxy3c(&tmpxy[0]); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + u32 *tp; + gte_avsz3(); + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 6) g.opz = za + 0x200; + *(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + tp = (u32 *)prim->w0; + ((PFT3_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT3_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT3_C6F4 *)pkt)->uvp1 = tp[2]; + ((PFT3_C6F4 *)pkt)->uv2 = tp[3]; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x20; + } + } + break; + case 0: + case 1: + gte_stsxy3_f3(pkt); + gte_ldv0(vd); + gte_rtps(); + if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) { + mx = ((PF4_C6F4 *)pkt)->x0; + mn = ((PF4_C6F4 *)pkt)->x1; + } else { + mn = ((PF4_C6F4 *)pkt)->x0; + mx = ((PF4_C6F4 *)pkt)->x1; + } + if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2; + else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2; + if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) { + my = ((PF4_C6F4 *)pkt)->y0; + mny = ((PF4_C6F4 *)pkt)->y1; + } else { + mny = ((PF4_C6F4 *)pkt)->y0; + my = ((PF4_C6F4 *)pkt)->y1; + } + if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2; + else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2; + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3); + if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3; + else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3; + else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 0) g.opz = za + 0x200; + ((PF4_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x18; + } + } + } + break; + case 2: + case 3: + gte_stsxy3c(&tmpxy[0]); + gte_ldv0(vd); + gte_rtps(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsxy(&tmpxy[3]); + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (tmpxy[3].vx > mx) mx = tmpxy[3].vx; + else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (tmpxy[3].vx > my) my = tmpxy[3].vx; + else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + u32 *tp; + u32 uvw; + gte_avsz4(); + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 2) g.opz = za + 0x200; + *(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3]; + tp = (u32 *)prim->w0; + ((PFT4_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT4_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT4_C6F4 *)pkt)->uvp1 = tp[2]; + uvw = tp[3]; + ((PFT4_C6F4 *)pkt)->uv2 = uvw; + ((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x28; + } + } + } + break; + } + } + } + prim++; + } + } + } + D_800A5E60 = pkt; +} + diff --git a/src/ov_SC05_019/ov_SC05_019_jr_8017AE2C.c b/src/ov_SC05_019/ov_SC05_019_jr_8017AE2C.c index f7b974bda..f79ff061f 100644 --- a/src/ov_SC05_019/ov_SC05_019_jr_8017AE2C.c +++ b/src/ov_SC05_019/ov_SC05_019_jr_8017AE2C.c @@ -3401,5 +3401,470 @@ void func_8017C688(s32 a0, s32 a1) { } -INCLUDE_ASM("asm/ov_SC05_019/nonmatchings/ov_SC05_019_jr_8017AE2C", func_8017C6F4); +typedef struct { u32 w0, w1, w2; } Prim126; +typedef struct { u8 *vtx; u32 f4; u32 xx, yy, zz; Prim126 *prim, *end; } Cell126; +typedef struct { s16 vx, vy; } DVEC2_C6F4; +typedef struct { s16 vx, vy, vz, pad; } SVEC2_C6F4; +typedef struct { s16 m[3][3]; s32 t[3]; } MTX_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2; } PF3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0, x1, y1, x2, y2, x3, y3; } PF4_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; } PFT3_C6F4; +typedef struct { u32 tag, rgbc; s16 x0, y0; u32 uvc0; s16 x1, y1; u32 uvp1; s16 x2, y2; u16 uv2, p2; s16 x3, y3; u16 uv3, p3; } PFT4_C6F4; + +#define gte_ldv0(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 )" \ + : \ + : "r"( r0 ) ) +#define gte_ldv3(r0, r1, r2) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 0( %1 );" \ + "lwc2 $3, 4( %1 );" \ + "lwc2 $4, 0( %2 );" \ + "lwc2 $5, 4( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) ) +#define gte_ldv3c(r0) __asm__ volatile ( \ + "lwc2 $0, 0( %0 );" \ + "lwc2 $1, 4( %0 );" \ + "lwc2 $2, 8( %0 );" \ + "lwc2 $3, 12( %0 );" \ + "lwc2 $4, 16( %0 );" \ + "lwc2 $5, 20( %0 )" \ + : \ + : "r"( r0 ) ) +#define gte_rtps() __asm__ volatile ("nop;nop;rtps") +#define gte_rtpt() __asm__ volatile ("nop;nop;rtpt") +#define gte_nclip() __asm__ volatile ("nop;nop;nclip") +#define gte_avsz3() __asm__ volatile ("nop;nop;avsz3") +#define gte_avsz4() __asm__ volatile ("nop;nop;avsz4") +#define gte_stsxy(r0) __asm__ volatile ( \ + "swc2 $14, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsxy3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 0( %1 );" \ + "swc2 $14, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) +#define gte_stsxy3c(r0) __asm__ volatile ( \ + "swc2 $12, 0( %0 );" \ + "swc2 $13, 4( %0 );" \ + "swc2 $14, 8( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsxy3_f3(r0) __asm__ volatile ( \ + "swc2 $12, 8( %0 );" \ + "swc2 $13, 12( %0 );" \ + "swc2 $14, 16( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) +#define gte_stsz3(r0, r1, r2) __asm__ volatile ( \ + "swc2 $17, 0( %0 );" \ + "swc2 $18, 0( %1 );" \ + "swc2 $19, 0( %2 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ) \ + : "memory" ) +#define gte_stsz4(r0, r1, r2, r3) __asm__ volatile ( \ + "swc2 $16, 0( %0 );" \ + "swc2 $17, 0( %1 );" \ + "swc2 $18, 0( %2 );" \ + "swc2 $19, 0( %3 )" \ + : \ + : "r"( r0 ), "r"( r1 ), "r"( r2 ), "r"( r3 ) \ + : "memory" ) +#define gte_stflg(r0) __asm__ volatile ( \ + "cfc2 $12, $31;" \ + "nop;" \ + "sw $12, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "$12", "memory" ) +#define gte_stopz(r0) __asm__ volatile ( \ + "swc2 $24, 0( %0 )" \ + : \ + : "r"( r0 ) \ + : "memory" ) + +void func_8017C6F4(s32 arg0) +{ + extern s32 func_800491EC(void); + extern void func_800547D8(s32, MTX_C6F4 *); + extern void func_80052E38(MTX_C6F4 *); + extern void func_8017C014(void *, void *, s32); + extern u8 D_8018F9C0[]; + extern u8 *D_800A5E60; + extern u8 D_800A6610[]; + extern short D_800B9A02; + + s16 rect[4]; + DVEC2_C6F4 tmpxy[4]; + SVEC2_C6F4 box[8]; + SVEC2_C6F4 sxy[8]; + MTX_C6F4 mtx; + struct { long flag, opz, sz0, sz1, sz2, sz3; } g; + + s32 cx0, cx1, cy0, cy1, y, col; + Cell126 **rowptr; + Cell126 **p; + Cell126 *cell; + Prim126 *prim; + Prim126 *end; + u8 *pkt; + u32 ot; + u8 *vtx; + u8 *va, *vb, *vc, *vd; + u32 w, code; + u32 wx, wy, wz; + u32 xlo, xhi, ylo, yhi, zlo, zhi; + s32 xa32, xb32, t32; + s32 xmn1, xmx1, xmn2, xmx2; + s32 ymn1, ymx1, ymn2, ymx2; + s32 my, mny, mx, mn; + + func_800491EC(); + func_800547D8(arg0 + 0x10, &mtx); + func_80052E38(&mtx); + func_8017C014(D_8018F9C0, rect, *(s32 *)(arg0 + 0x60)); + + pkt = D_800A5E60; + ot = (u32)&D_800A6610[(*(u16 *)&D_800B9A02) << 14]; + + cx0 = (rect[0] + 0x4000) / 512; + cx1 = (rect[0] + rect[2] + 0x4000) / 512 + 2; + cx0 = (cx0 < 0) ? 0 : ((cx0 > 0x3F) ? 0x3F : cx0); + cx1 = (cx1 < 0) ? 0 : ((cx1 > 0x3F) ? 0x3F : cx1); + cy0 = (rect[1] + 0x4000) / 512 - 1; + cy1 = (rect[1] + rect[3] + 0x4000) / 512 + 2; + cy0 = (cy0 < 0) ? 0 : ((cy0 > 0x3F) ? 0x3F : cy0); + cy1 = (cy1 < 0) ? 0 : ((cy1 > 0x3F) ? 0x3F : cy1); + + rowptr = (Cell126 **)(*(s32 *)(arg0 + 0xC)) + (cy0 * 64 + cx0); + + for (y = cy0; y < cy1; y++, rowptr += 0x40) { + for (col = cx0, p = rowptr; col < cx1; col++, p++) { + cell = *p; + if (cell == 0) continue; + + wx = cell->xx; + xlo = wx & 0xFFFF; + xhi = wx >> 16; + wy = cell->yy; + ylo = wy & 0xFFFF; + yhi = wy >> 16; + wz = cell->zz; + zlo = wz & 0xFFFF; + zhi = wz >> 16; + + box[0].vx = xlo; box[0].vy = ylo; box[0].vz = zlo; + box[1].vx = xhi; box[1].vy = ylo; box[1].vz = zlo; + box[2].vx = xlo; box[2].vy = ylo; box[2].vz = zhi; + box[3].vx = xhi; box[3].vy = ylo; box[3].vz = zhi; + box[4].vx = xlo; box[4].vy = yhi; box[4].vz = zlo; + box[5].vx = xhi; box[5].vy = yhi; box[5].vz = zlo; + box[6].vx = xlo; box[6].vy = yhi; box[6].vz = zhi; + box[7].vx = xhi; box[7].vy = yhi; box[7].vz = zhi; + + gte_ldv3c(&box[0]); + gte_rtpt(); + gte_stsxy3(&sxy[0], &sxy[1], &sxy[2]); + gte_ldv0(&box[3]); + gte_rtps(); + gte_stsxy(&sxy[3]); + gte_ldv3c(&box[4]); + gte_rtpt(); + gte_stsxy3(&sxy[4], &sxy[5], &sxy[6]); + gte_ldv0(&box[7]); + gte_rtps(); + gte_stsxy(&sxy[7]); + + xa32 = sxy[0].vx; + xb32 = sxy[1].vx; + if (xb32 < xa32) { xmx1 = xa32; xmn1 = xb32; } else { xmn1 = xa32; xmx1 = xb32; } + t32 = sxy[2].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + t32 = sxy[3].vx; + if (xmx1 < t32) xmx1 = t32; else if (t32 < xmn1) xmn1 = t32; + xa32 = sxy[4].vx; + xb32 = sxy[5].vx; + if (xb32 < xa32) { xmx2 = xa32; xmn2 = xb32; } else { xmn2 = xa32; xmx2 = xb32; } + t32 = sxy[6].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + t32 = sxy[7].vx; + if (xmx2 < t32) xmx2 = t32; else if (t32 < xmn2) xmn2 = t32; + mn = xmn1; + if (xmn2 < mn) mn = xmn2; + mx = xmx1; + if (mx < xmx2) mx = xmx2; + if (mx < -0xA0) continue; + if (!(mn < 0xA1)) continue; + + xa32 = sxy[0].vy; + xb32 = sxy[1].vy; + if (xb32 < xa32) { ymx1 = xa32; ymn1 = xb32; } else { ymn1 = xa32; ymx1 = xb32; } + t32 = sxy[2].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + t32 = sxy[3].vy; + if (ymx1 < t32) ymx1 = t32; else if (t32 < ymn1) ymn1 = t32; + xa32 = sxy[4].vy; + xb32 = sxy[5].vy; + if (xb32 < xa32) { ymx2 = xa32; ymn2 = xb32; } else { ymn2 = xa32; ymx2 = xb32; } + t32 = sxy[6].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + t32 = sxy[7].vy; + if (ymx2 < t32) ymx2 = t32; else if (t32 < ymn2) ymn2 = t32; + mny = ymn1; + if (ymn2 < mny) mny = ymn2; + my = ymx1; + if (my < ymx2) my = ymx2; + if (my < -0x78) continue; + if (!(mny < 0x79)) continue; + + prim = cell->prim; + end = cell->end; + vtx = cell->vtx; + while (prim < end) { + w = prim->w1; + va = vtx + (w & 0xFFFF); + vb = vtx + (w >> 16); + w = prim->w2; + vc = vtx + (w & 0xFFFF); + w = w >> 16; + gte_ldv3(va, vb, vc); + gte_rtpt(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_nclip(); + code = w & 0xF; + vd = vtx + ((w & 0xFFF0) >> 1); + gte_stopz(&g.opz); + if (g.opz > 0) { + switch (code) { + case 4: + case 5: + gte_stsxy3_f3(pkt); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (((PFT3_C6F4 *)pkt)->x0 > ((PFT3_C6F4 *)pkt)->x1) { + mx = ((PFT3_C6F4 *)pkt)->x0; + mn = ((PFT3_C6F4 *)pkt)->x1; + } else { + mn = ((PFT3_C6F4 *)pkt)->x0; + mx = ((PFT3_C6F4 *)pkt)->x1; + } + if (((PFT3_C6F4 *)pkt)->x2 > mx) mx = ((PFT3_C6F4 *)pkt)->x2; + else if (((PFT3_C6F4 *)pkt)->x2 < mn) mn = ((PFT3_C6F4 *)pkt)->x2; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PFT3_C6F4 *)pkt)->y0 > ((PFT3_C6F4 *)pkt)->y1) { + my = ((PFT3_C6F4 *)pkt)->y0; + mny = ((PFT3_C6F4 *)pkt)->y1; + } else { + mny = ((PFT3_C6F4 *)pkt)->y0; + my = ((PFT3_C6F4 *)pkt)->y1; + } + if (((PFT3_C6F4 *)pkt)->y2 > my) my = ((PFT3_C6F4 *)pkt)->y2; + else if (((PFT3_C6F4 *)pkt)->y2 < mny) mny = ((PFT3_C6F4 *)pkt)->y2; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 4) g.opz = za + 0x200; + ((PF3_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x4000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x14; + } + } + break; + case 6: + case 7: + gte_stsxy3c(&tmpxy[0]); + gte_stsz3(&g.sz0, &g.sz1, &g.sz2); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (my >= -0x78 && mny < 0x79) { + s32 za; + u32 *otp; + u32 *tp; + gte_avsz3(); + if (g.sz0 > g.sz1) { + za = g.sz0; + if (za < g.sz2) za = g.sz2; + } else { + za = g.sz1; + if (za < g.sz2) za = g.sz2; + } + g.opz = za; + if (code != 6) g.opz = za + 0x200; + *(u32 *)&((PFT3_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT3_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + tp = (u32 *)prim->w0; + ((PFT3_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT3_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT3_C6F4 *)pkt)->uvp1 = tp[2]; + ((PFT3_C6F4 *)pkt)->uv2 = tp[3]; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x7000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x20; + } + } + break; + case 0: + case 1: + gte_stsxy3_f3(pkt); + gte_ldv0(vd); + gte_rtps(); + if (((PF4_C6F4 *)pkt)->x0 > ((PF4_C6F4 *)pkt)->x1) { + mx = ((PF4_C6F4 *)pkt)->x0; + mn = ((PF4_C6F4 *)pkt)->x1; + } else { + mn = ((PF4_C6F4 *)pkt)->x0; + mx = ((PF4_C6F4 *)pkt)->x1; + } + if (((PF4_C6F4 *)pkt)->x2 > mx) mx = ((PF4_C6F4 *)pkt)->x2; + else if (((PF4_C6F4 *)pkt)->x2 < mn) mn = ((PF4_C6F4 *)pkt)->x2; + if (((PF4_C6F4 *)pkt)->y0 > ((PF4_C6F4 *)pkt)->y1) { + my = ((PF4_C6F4 *)pkt)->y0; + mny = ((PF4_C6F4 *)pkt)->y1; + } else { + mny = ((PF4_C6F4 *)pkt)->y0; + my = ((PF4_C6F4 *)pkt)->y1; + } + if (((PF4_C6F4 *)pkt)->y2 > my) my = ((PF4_C6F4 *)pkt)->y2; + else if (((PF4_C6F4 *)pkt)->y2 < mny) mny = ((PF4_C6F4 *)pkt)->y2; + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + gte_stsxy((long *)&((PF4_C6F4 *)pkt)->x3); + if (((PF4_C6F4 *)pkt)->x3 < mn) mn = ((PF4_C6F4 *)pkt)->x3; + else if (mx < ((PF4_C6F4 *)pkt)->x3) mx = ((PF4_C6F4 *)pkt)->x3; + if (mx >= -0xA0 && mn < 0xA1) { + if (((PF4_C6F4 *)pkt)->y3 < mny) mny = ((PF4_C6F4 *)pkt)->y3; + else if (my < ((PF4_C6F4 *)pkt)->y3) my = ((PF4_C6F4 *)pkt)->y3; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 0) g.opz = za + 0x200; + ((PF4_C6F4 *)pkt)->rgbc = prim->w0; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x5000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x18; + } + } + } + break; + case 2: + case 3: + gte_stsxy3c(&tmpxy[0]); + gte_ldv0(vd); + gte_rtps(); + gte_stflg(&g.flag); + if (!(g.flag & 0x7F85E000)) { + gte_stsxy(&tmpxy[3]); + gte_stsz4(&g.sz0, &g.sz1, &g.sz2, &g.sz3); + if (tmpxy[0].vx > tmpxy[1].vx) { + mx = tmpxy[0].vx; + mn = tmpxy[1].vx; + } else { + mn = tmpxy[0].vx; + mx = tmpxy[1].vx; + } + if (tmpxy[2].vx > mx) mx = tmpxy[2].vx; + else if (tmpxy[2].vx < mn) mn = tmpxy[2].vx; + if (tmpxy[3].vx > mx) mx = tmpxy[3].vx; + else if (tmpxy[3].vx < mn) mn = tmpxy[3].vx; + if (mx >= -0xA0 && mn < 0xA1) { + if (tmpxy[0].vy > tmpxy[1].vy) { + my = tmpxy[0].vy; + mny = tmpxy[1].vy; + } else { + mny = tmpxy[0].vy; + my = tmpxy[1].vy; + } + if (tmpxy[2].vy > my) my = tmpxy[2].vy; + else if (tmpxy[2].vy < mny) mny = tmpxy[2].vy; + if (tmpxy[3].vx > my) my = tmpxy[3].vx; + else if (tmpxy[3].vx < mny) mny = tmpxy[3].vx; + if (my >= -0x78 && mny < 0x79) { + s32 za, zb; + u32 *otp; + u32 *tp; + u32 uvw; + gte_avsz4(); + zb = g.sz2; + if (zb < g.sz3) zb = g.sz3; + za = g.sz0; + if (za < g.sz1) za = g.sz1; + if (za < zb) za = zb; + g.opz = za; + if (code != 2) g.opz = za + 0x200; + *(u32 *)&((PFT4_C6F4 *)pkt)->x0 = *(u32 *)&tmpxy[0]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x1 = *(u32 *)&tmpxy[1]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x2 = *(u32 *)&tmpxy[2]; + *(u32 *)&((PFT4_C6F4 *)pkt)->x3 = *(u32 *)&tmpxy[3]; + tp = (u32 *)prim->w0; + ((PFT4_C6F4 *)pkt)->rgbc = tp[0]; + ((PFT4_C6F4 *)pkt)->uvc0 = tp[1]; + ((PFT4_C6F4 *)pkt)->uvp1 = tp[2]; + uvw = tp[3]; + ((PFT4_C6F4 *)pkt)->uv2 = uvw; + ((PFT4_C6F4 *)pkt)->uv3 = uvw >> 16; + otp = (u32 *)(((g.opz >> 2) << 2) + ot); + *(u32 *)pkt = (*otp & 0xFFFFFF) | 0x9000000; + *otp = (*otp & 0xFF000000) | ((u32)pkt & 0xFFFFFF); + pkt += 0x28; + } + } + } + break; + } + } + } + prim++; + } + } + } + D_800A5E60 = pkt; +} +