mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 18:25:35 -04:00
8b0fc34714
Real card protocol restarts on every fresh 0x81 — SELECT deassert is
a bus-wide reset signal. Earlier model preserved mc_state across
deassert via mc_save_slot, which caused every subsequent 0x81 to land
on a stale non-IDLE saved state and trigger abort_reselect bookkeeping.
Audit confirmed the BIOS-visible RX was still correct (the abort path
itself reset mc_state), but the retained sector/cmd/counter context
across logically-independent transactions was wrong per no$psx.
Clear volatile protocol state on SELECT deassert (state, cmd, sector,
sector_msb, sector_lsb, data_idx, checksum on both slots). Preserve
mc_slots[].flag (persistent "new card" metadata) and mc_slots[].data
(sector buffer, harmless to retain).
Result on a 4-press boot run: 6 transactions reach READ_DATA (ts=10)
and successfully read the "MC" header magic (RX bytes 0x4D 0x43);
remaining txns continue as 4-byte presence pings. Pre-fix: 0 reads
of card data ever; post-fix: card protocol can complete the setup
phase and enter data phase.
The byte-15 abort that follows is a separate blocker — kernel chain
dispatcher interleaves pad polling into the card data read. Tracked
for next session via the chain dispatcher disassembly.
Also includes:
- Slot-state capture in SioTraceEntry + sio_trace JSON emission
- dirty_ram_interp: replace mid-block fprintf+fflush with a counter
(CLAUDE.md §3 — synchronous Windows console I/O at high rate
starves the dispatch loop)
- Passive Python TCP probes (raw_tcp, trace_audit, trace_range,
txn_summary, txn_dist, txn_bytes, drs_filter, readram_test,
step_audit{,2}, verify_card_buffer, wtrace_filter)
- docs/MEMCARD_AUDIT_2026_04_28.md (prior session's 7-layer audit)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
22 lines
846 B
Python
22 lines
846 B
Python
"""Dump a single card txn's full TX/RX bytes given txn_seq + nearby SIO trace."""
|
|
import sys, json, re
|
|
|
|
txt = sys.stdin.read()
|
|
m = re.search(r'\{.*\}', txt, re.S)
|
|
if not m:
|
|
print('parse fail'); sys.exit(1)
|
|
j = json.loads(m.group(0))
|
|
ents = j.get('entries', [])
|
|
|
|
# Print first txn that has bytes >= 15
|
|
for e in ents:
|
|
if e.get('bytes', 0) >= 10:
|
|
print(f"=== txn {e['txn_seq']}: slot={e['slot']} cmd={e['cmd']} "
|
|
f"sect={e['sector']} bytes={e['bytes']} ts={e['terminal_state']} "
|
|
f"reason={e['end_reason']} start_byte_seq={e['start_byte_seq']} "
|
|
f"end_byte_seq={e['end_byte_seq']} ===")
|
|
print(f" start_func={e['start_func']} end_func={e['end_func']}")
|
|
for i, (tx, rx) in enumerate(zip(e['tx'], e['rx'])):
|
|
print(f" byte[{i:>2}] tx={tx} rx={rx}")
|
|
print()
|