mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
Add side-effect-free psx_peek_word + test
Debug reads of RAM/scratchpad/BIOS without MMIO, read hooks or unmapped_fatal. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -94,6 +94,10 @@ void psx_host_write_word(uint32_t addr, uint32_t val);
|
||||
void psx_host_write_half(uint32_t addr, uint16_t val);
|
||||
void psx_host_write_byte(uint32_t addr, uint8_t val);
|
||||
|
||||
/* Side-effect-free aligned word peek (RAM / scratchpad / BIOS ROM only), for
|
||||
* the debug path. Returns 0 (and leaves *out alone) for anything else. */
|
||||
int psx_peek_word(uint32_t addr, uint32_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -164,6 +164,28 @@ static inline uint32_t psx_phys_addr_store(uint32_t addr) {
|
||||
/* Expose RAM pointer for oracle comparison (find_first_divergence). */
|
||||
uint8_t *memory_get_ram_ptr(void) { return ram; }
|
||||
uint8_t *memory_get_scratchpad_ptr(void) { return scratchpad; }
|
||||
|
||||
/* Side-effect-FREE aligned word peek for the debug/observability path ONLY:
|
||||
* main RAM (every KUSEG/KSEG0/KSEG1 mirror), scratchpad and BIOS ROM. Never
|
||||
* touches MMIO, the lockstep/DS read hooks, read watches, or unmapped_fatal.
|
||||
* Returns 1 and fills *out when addr is backed by one of those; 0 otherwise. */
|
||||
int psx_peek_word(uint32_t addr, uint32_t *out) {
|
||||
uint32_t phys, off;
|
||||
const uint8_t *p;
|
||||
if (addr >= 0xC0000000u || (addr & 3u)) return 0;
|
||||
phys = addr & 0x1FFFFFFFu;
|
||||
if (psx_ram_resolve(addr, 4u, &off)) {
|
||||
p = &ram[off];
|
||||
} else if (phys >= 0x1F800000u && phys <= 0x1F8003FCu) {
|
||||
p = &scratchpad[phys - 0x1F800000u];
|
||||
} else if (phys >= 0x1FC00000u && phys <= 0x1FC7FFFCu) {
|
||||
p = &bios_rom[phys - 0x1FC00000u];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (out) memcpy(out, p, sizeof(*out));
|
||||
return 1;
|
||||
}
|
||||
void memory_clear_low_boot_scratch(void) {
|
||||
memset(ram, 0, 0x10u);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ uint32_t ls_read_hook(uint32_t a, int s, uint32_t v) { (void)a; (void)s; return
|
||||
void ls_write_hook(uint32_t a, int s, uint32_t v) { (void)a; (void)s; (void)v; }
|
||||
void ls_shadow_record_unreplayable(void) {}
|
||||
int fntrace_is_game_started(void) { return 0; }
|
||||
void fntrace_restore_game_started(int started) { (void)started; }
|
||||
void overlay_loader_note_code_write(void) {}
|
||||
void overlay_loader_resync_validation_after_restore(void) {}
|
||||
void gte_canonicalize_cpu_state(CPUState *cpu) { (void)cpu; }
|
||||
|
||||
@@ -35,6 +35,7 @@ extern void psx_write_word(uint32_t addr, uint32_t val);
|
||||
extern void psx_write_half(uint32_t addr, uint16_t val);
|
||||
extern void psx_write_byte(uint32_t addr, uint8_t val);
|
||||
extern uint8_t *memory_get_ram_ptr(void);
|
||||
extern uint8_t *memory_get_scratchpad_ptr(void);
|
||||
|
||||
/* Stub-side mutation counters (psx_ram_runtime_map_stubs.c). */
|
||||
extern int g_stub_device_restores;
|
||||
@@ -130,6 +131,39 @@ static void check_guest_access(int expanded) {
|
||||
check(psx_read_byte(0x80204005u) == 0x5Au, "byte reads back at its own address");
|
||||
}
|
||||
|
||||
/* ---- psx_peek_word: debug read that must never reach the bus ----------- */
|
||||
static void check_peek(int expanded) {
|
||||
uint32_t v = 0xDEADBEEFu;
|
||||
memset(memory_get_ram_ptr(), 0, PSX_MAIN_RAM_BACKING_BYTES);
|
||||
psx_write_word(0x80001000u, 0x11223344u);
|
||||
check(psx_peek_word(0x80001000u, &v) && v == 0x11223344u, "peek: KSEG0 RAM");
|
||||
check(psx_peek_word(0x00001000u, &v) && v == 0x11223344u, "peek: KUSEG RAM");
|
||||
check(psx_peek_word(0xA0001000u, &v) && v == 0x11223344u, "peek: KSEG1 RAM");
|
||||
v = 0;
|
||||
check(psx_peek_word(0x80201000u, &v) && ((v == 0x11223344u) == !expanded),
|
||||
"peek: 2nd mirror follows the live geometry");
|
||||
check(psx_peek_word(0x807FFFFCu, &v), "peek: top of the RAM window");
|
||||
memory_get_scratchpad_ptr()[0x10] = 0x78; memory_get_scratchpad_ptr()[0x13] = 0x12;
|
||||
check(psx_peek_word(0x1F800010u, &v) && (v & 0xFF) == 0x78 && (v >> 24) == 0x12,
|
||||
"peek: scratchpad");
|
||||
check(psx_peek_word(0x1F8003FCu, &v) && !psx_peek_word(0x1F800400u, &v),
|
||||
"peek: scratchpad end bound");
|
||||
check(psx_peek_word(0xBFC00000u, &v) && psx_peek_word(0x1FC7FFFCu, &v) &&
|
||||
!psx_peek_word(0x1FC80000u, &v), "peek: BIOS ROM bounds");
|
||||
/* Device / unmapped space is refused WITHOUT touching the bus (the stubbed
|
||||
* psx_fatal_halt traps if a real access reached unmapped_fatal). */
|
||||
v = 0xDEADBEEFu;
|
||||
check(!psx_peek_word(0x1F801044u, &v), "peek: JOY_RX refused");
|
||||
check(!psx_peek_word(0x1F801810u, &v), "peek: GPUREAD refused");
|
||||
check(!psx_peek_word(0x1F802000u, &v), "peek: expansion-2 MMIO refused");
|
||||
check(!psx_peek_word(0x1F000000u, &v), "peek: expansion-1 refused");
|
||||
check(!psx_peek_word(0x80800000u, &v), "peek: past the RAM window refused");
|
||||
check(!psx_peek_word(0xFFFE0130u, &v) && !psx_peek_word(0xC0000000u, &v),
|
||||
"peek: KSEG2 refused");
|
||||
check(!psx_peek_word(0x80001002u, &v), "peek: unaligned refused");
|
||||
check(v == 0xDEADBEEFu, "peek: refused reads leave *out untouched");
|
||||
}
|
||||
|
||||
/* ---- 3. a real DMA writing RAM from a guest-chosen MADR --------------- */
|
||||
#define DMA_BASE 0x1F801080u
|
||||
static void run_otc(uint32_t madr, uint32_t entries) {
|
||||
@@ -288,6 +322,7 @@ int main(void) {
|
||||
for (int expanded = 0; expanded < 2; ++expanded) {
|
||||
set_geometry(expanded);
|
||||
check_guest_access(expanded);
|
||||
check_peek(expanded);
|
||||
check_dma(expanded);
|
||||
}
|
||||
check_savestates();
|
||||
|
||||
Reference in New Issue
Block a user