mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 18:25:35 -04:00
fe42da2744
Keeps both lines: master's PGXP session, draw-distance clamps, masked rejects and saturated-winding NCLIP; the release's render-pass kit additions, verified media/disc extents, timeline/present rings, cull-scale sites. Overlay ABI v30. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
74 lines
2.9 KiB
C
74 lines
2.9 KiB
C
/* device_trace.h — general two-process DEVICE-EVENT cycle ring.
|
|
*
|
|
* Purpose: name the device/IRQ event whose guest-cycle timing diverges between
|
|
* psx-runtime (code under test) and psx-beetle (independent oracle). Where
|
|
* parity_trace answers "which control-flow / gate-input diverged", this answers
|
|
* the level below it: "which hardware event (CD sector IRQ / DMA completion /
|
|
* RootCounter / VBlank / SPU) fired at a different guest cycle" — the producer
|
|
* of an over-fast or over-slow wait.
|
|
*
|
|
* Model (CLAUDE.md ring-buffer doctrine): ALWAYS-ON from boot, records one row
|
|
* per hardware IRQ-raise edge (the single choke point each backend funnels its
|
|
* device interrupts through — native psx_irq_raise(); Beetle mednafen
|
|
* IRQ_Assert rising edge), stamped with the deterministic guest-cycle ruler.
|
|
* A probe QUERIES the ring for a cycle window; it never arms-then-times.
|
|
*
|
|
* Generality: nothing here is title-specific. The SAME TU compiles into both
|
|
* binaries and emits IDENTICAL rows, so tools/devtrace_diff.py pulls both
|
|
* timelines and aligns them by guest cycle to find the first divergent event.
|
|
* This is the reusable device-timing audit substrate for the whole ecosystem
|
|
* (see recomp-template); the MMX6 cutscene asset-load over-fast wedge is its
|
|
* first user.
|
|
*/
|
|
#ifndef DEVICE_TRACE_H
|
|
#define DEVICE_TRACE_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* IRQ source = the PSX I_STAT bit index. Identical on both backends (mednafen
|
|
* irq.h uses the same numbering). */
|
|
typedef enum {
|
|
DEV_IRQ_VBLANK = 0,
|
|
DEV_IRQ_GPU = 1,
|
|
DEV_IRQ_CDROM = 2,
|
|
DEV_IRQ_DMA = 3,
|
|
DEV_IRQ_TIMER0 = 4,
|
|
DEV_IRQ_TIMER1 = 5,
|
|
DEV_IRQ_TIMER2 = 6,
|
|
DEV_IRQ_SIO0 = 7,
|
|
DEV_IRQ_SIO1 = 8,
|
|
DEV_IRQ_SPU = 9,
|
|
DEV_IRQ_PIO = 10,
|
|
} dev_irq_source_t;
|
|
|
|
typedef struct {
|
|
uint64_t seq; /* monotonic event index since boot */
|
|
uint64_t cycle; /* absolute guest CPU cycles at the raise (the ruler) */
|
|
uint32_t frame; /* host video frame at the raise */
|
|
uint32_t source; /* dev_irq_source_t — the I_STAT bit raised */
|
|
uint32_t detail; /* source-specific: DMA channel / timer index / 0 */
|
|
} DevEvent;
|
|
|
|
void device_trace_arm(int on); /* on=1 begins recording (idempotent) */
|
|
void device_trace_reset(void); /* clear ring (keeps armed state) */
|
|
int device_trace_is_armed(void); /* hot-path gate: cheap one-branch check */
|
|
|
|
/* Record one device-IRQ raise edge. No-op unless armed. Stamps cycle+frame via
|
|
* the process's guest-cycle/frame accessors (shared with parity_trace). */
|
|
void device_trace_note(uint32_t source, uint32_t detail);
|
|
|
|
/* Readback: copies up to max_rows NEWEST events, oldest-first, into out[]. */
|
|
uint32_t device_trace_get(DevEvent* out, uint32_t max_rows);
|
|
uint64_t device_trace_total(void);
|
|
const char* device_source_str(uint32_t source);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* DEVICE_TRACE_H */
|