mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-27 10:38:46 -04:00
1b59103b3c
Two passive, always-on rings for auditing memory-card reads end-to-end without arming/timing probes: card_read_summary (non-evicting, first 32 successful reads): Captured at the MC_READ_END transition in sio_process_byte. Records slot/cmd/sector/checksum/data_idx/first 16 bytes/cycle/caller func. TCP cmds: card_read_summary, card_read_summary_reset. card_data_writes (4096 entries, rolling tail): Arm side: sio_read(SIO_RX_DATA) sets a pending flag while the card protocol is in MC_READ_DATA..MC_READ_END. Check side: psx_write_byte/half/word capture the next RAM write whose new_val matches the armed RX byte, then disarm. Records dest addr / value / store_pc / func / mc_idx / slot / cycle. TCP cmds: card_data_writes, card_data_writes_reset. Helpers: tools/probe_card_reads.py tools/probe_card_writes.py tools/probe_card_writes_raw.py tools/peek_cards.py Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
52 lines
1.6 KiB
C
52 lines
1.6 KiB
C
/* card_read_summary.c — non-evicting first-32 completed card reads. */
|
|
|
|
#include "card_read_summary.h"
|
|
#include "psx_cycles.h"
|
|
#include <string.h>
|
|
|
|
extern uint32_t g_debug_current_func_addr;
|
|
extern uint32_t g_debug_last_store_pc;
|
|
|
|
static CardReadSummary s_ring[CARD_READ_SUMMARY_CAP];
|
|
static uint32_t s_count = 0;
|
|
static uint64_t s_seq = 0;
|
|
|
|
void card_read_summary_record(uint8_t slot, uint8_t cmd, uint16_t sector,
|
|
uint8_t checksum, uint8_t data_idx,
|
|
const uint8_t *data128) {
|
|
if (s_count >= CARD_READ_SUMMARY_CAP) return;
|
|
CardReadSummary *e = &s_ring[s_count];
|
|
memset(e, 0, sizeof(*e));
|
|
e->seq = s_seq++;
|
|
e->psx_cycle_count = psx_get_cycle_count();
|
|
e->current_func = g_debug_current_func_addr;
|
|
e->last_store_pc = g_debug_last_store_pc;
|
|
e->slot = slot;
|
|
e->cmd = cmd;
|
|
e->sector = sector;
|
|
e->checksum_card = checksum;
|
|
e->data_idx_at_end = data_idx;
|
|
e->dest_ram_addr = 0; /* filled by chain trace */
|
|
if (data128) {
|
|
memcpy(e->data_peek, data128, CARD_READ_SUMMARY_PEEK);
|
|
}
|
|
s_count++;
|
|
}
|
|
|
|
uint32_t card_read_summary_get(const CardReadSummary **buf_out) {
|
|
if (buf_out) *buf_out = s_ring;
|
|
return s_count;
|
|
}
|
|
|
|
void card_read_summary_reset(void) {
|
|
memset(s_ring, 0, sizeof(s_ring));
|
|
s_count = 0;
|
|
s_seq = 0;
|
|
}
|
|
|
|
void card_read_summary_set_dest(uint32_t dest_addr) {
|
|
if (s_count == 0) return;
|
|
/* Set on the most recent record (the one that just completed). */
|
|
s_ring[s_count - 1].dest_ram_addr = dest_addr;
|
|
}
|