shrooms-vb-core/core/pseudo-halt.c

265 lines
7.9 KiB
C
Raw Normal View History

2024-10-23 21:29:11 +00:00
/* This file is included into vb.c and cannot be compiled on its own. */
#ifdef VBAPI
/********************************* Constants *********************************/
/* Pseudo-halt operations */
#define PH_NEVER 0
#define PH_DPSTTS 1
#define PH_GAME_PAD 2
#define PH_INTPND 3
#define PH_TCR 4
#define PH_TLHR 5
#define PH_XPSTTS 6
2024-10-23 21:29:11 +00:00
/***************************** Module Functions ******************************/
/* Activate pseudo-halt */
static void phActivate(VB *sim, uint32_t address, int type) {
int range; /* Memory address range by component */
/* Working variables */
address &= 0x07FFFFFF;
range = address >> 24;
2024-10-23 21:29:11 +00:00
/* Configure pseudo-halt */
sim->ph.operation = PH_NEVER;
2024-10-23 21:29:11 +00:00
/* VIP */
if (range == 0) {
address &= 0x0007FFFF;
/* TODO: Frame buffer */
2024-10-23 21:29:11 +00:00
/* I/O register */
switch (address) {
case 0x5F800: /* INTPND */
if (
sim->vip.dp.step != 0 ||
sim->vip.dp.enabled ||
(sim->vip.dp.disp && sim->vip.dp.synce) ||
sim->vip.xp.enabled ||
sim->vip.xp.xpen
) sim->ph.operation = PH_INTPND;
break;
case 0x5F820: /* DPSTTS */
if (
sim->vip.dp.step != 0 ||
sim->vip.dp.enabled ||
(sim->vip.dp.disp && sim->vip.dp.synce)
) sim->ph.operation = PH_DPSTTS;
break;
2024-10-23 21:29:11 +00:00
case 0x5F840: /* XPSTTS */
if (sim->vip.xp.enabled || sim->vip.xp.xpen)
2024-10-23 21:29:11 +00:00
sim->ph.operation = PH_XPSTTS;
break;
}
}
/* Misc. I/O */
else if (range == 2 && (type == VB_S8 || type == VB_U8)) {
address &= 0x0000003F;
switch (address) {
/* TODO: Communication port */
/* Game pad */
case 0x10: /* SDLR */
case 0x14: /* SDHR */
case 0x28: /* SCR */
if (sim->pad.si_stat != 0)
sim->ph.operation = PH_GAME_PAD;
break;
/* Timer */
case 0x18: /* TLR */
case 0x1C: /* THR */
if (sim->tmr.t_enb)
sim->ph.operation = PH_TLHR;
break;
case 0x20: /* TCR */
if (sim->tmr.t_enb)
sim->ph.operation = PH_TCR;
break;
}
}
2024-10-23 21:29:11 +00:00
/* Configure CPU */
sim->cpu.clocks = phUntil(sim);
sim->cpu.operation = CPU_PHALT;
2024-10-23 21:29:11 +00:00
}
/* Test whether the current memory access matches the monitored access */
static int phMatches(VB *sim, uint32_t address, int type, int32_t value) {
int match; /* Parameter match */
int x; /* Iterator */
/* New memory access */
if (sim->ph.step == 0)
return 0;
/* Check memory access parameters */
match =
address == sim->ph.address &&
sim->cpu.pc == sim->ph.pc &&
type == sim->ph.type &&
value == sim->ph.value
;
if (!match || sim->ph.step != 3)
return match;
/* Check full CPU state */
for (x = 1; x < 32; x++) {
if (sim->ph.program[x - 1] != sim->cpu.program[x])
return 0;
}
return
sim->ph.adtre == sim->cpu.adtre &&
sim->ph.chcw == cpuGetSystemRegister(sim, VB_CHCW) &&
2024-10-24 02:16:35 +00:00
sim->ph.ecr == cpuGetSystemRegister(sim, VB_ECR) &&
2024-10-23 21:29:11 +00:00
sim->ph.eipc == sim->cpu.eipc &&
sim->ph.eipsw == sim->cpu.eipsw &&
sim->ph.fepc == sim->cpu.fepc &&
sim->ph.fepsw == sim->cpu.fepsw &&
2024-10-24 02:16:35 +00:00
sim->ph.psw == cpuGetSystemRegister(sim, VB_PSW )
2024-10-23 21:29:11 +00:00
;
}
/****************************** Clock Measurers ******************************/
/* DPSTTS */
static uint32_t phDPSTTS(VB *sim) {
switch (sim->vip.dp.step) {
case 0: /* 0ms - FCLK rising edge */
case 2: /* 3ms-8ms - Display left frame buffer */
case 3: /* 8ms - L*BSY falling edge */
case 6: /* 13ms-18ms - Display right frame buffer */
case 7: /* 18ms - R*BSY falling edge */
2024-11-01 00:14:18 +00:00
case 8: /* 20ms - Display interval complete */
return sim->vip.dp.until;
}
/* case 1: 3ms - L*BSY rising edge */
/* case 4: 10ms - FCLK falling edge */
/* case 5: 13ms - R*BSY rising edge */
return sim->vip.dp.clocks;
}
/* INTPND */
static uint32_t phINTPND(VB *sim) {
if (!(
sim->vip.dp.step != 0 ||
sim->vip.dp.enabled ||
(sim->vip.dp.disp && sim->vip.dp.synce)
)) return sim->vip.xp.until;
if (!(sim->vip.xp.enabled || sim->vip.xp.xpen))
return sim->vip.dp.until;
return sim->vip.dp.until < sim->vip.xp.until ?
sim->vip.dp.until : sim->vip.xp.until;
}
2024-10-23 21:29:11 +00:00
/* XPSTTS */
static uint32_t phXPSTTS(VB *sim) {
uint32_t clocks; /* Return value */
uint16_t *halfwords; /* Drawing clocks this SBCOUNT */
uint32_t x; /* Iterator */
/* Drawing is underway */
if (sim->vip.xp.f0bsy || sim->vip.xp.f1bsy) {
clocks = 0;
halfwords = &sim->vip.halfwords[
(uint32_t) sim->vip.xp.sbcount * 384 + sim->vip.xp.column];
for (x = sim->vip.xp.column; x < 384; x++, halfwords++)
clocks += *halfwords;
return clocks;
}
/* Drawing is idle */
switch (sim->vip.dp.step) {
case 0: /* 0ms - FCLK rising edge */
return sim->vip.dp.until;
case 1: /* 3ms - L*BSY rising edge */
case 2: /* 3ms-8ms - Display left frame buffer */
case 3: /* 8ms - L*BSY falling edge */
return sim->vip.dp.until + vipClocksMs(12);
}
/* case 4: 10ms - FCLK falling edge */
/* case 5: 13ms - R*BSY rising edge */
/* case 6: 13ms-18ms - Display right frame buffer */
/* case 7: 18ms - R*BSY falling edge */
return sim->vip.dp.until + vipClocksMs(2);
}
/***************************** Library Functions *****************************/
/* Test whether to activate pseudo-halt */
static int phAssess(VB *sim, uint32_t address, int type, int32_t value) {
int x; /* Iterator */
/* Memory access does not match last time */
address &= TYPE_MASKS[type];
2024-10-23 21:29:11 +00:00
if (!phMatches(sim, address, type, value))
sim->ph.step = 0;
/* New memory access */
if (sim->ph.step == 0) {
sim->ph.address = address;
sim->ph.pc = sim->cpu.pc;
sim->ph.step = 1;
sim->ph.type = type;
sim->ph.value = value;
return 0;
}
/* Repeated memory access, not checking full CPU state */
if (sim->ph.step < 2) {
sim->ph.step++;
return 0;
}
/* Take a snapshot of the full CPU state */
if (sim->ph.step == 2) {
for (x = 1; x < 32; x++)
sim->ph.program[x - 1] = sim->cpu.program[x];
sim->ph.adtre = sim->cpu.adtre;
sim->ph.chcw = cpuGetSystemRegister(sim, VB_CHCW);
2024-10-24 02:16:35 +00:00
sim->ph.ecr = cpuGetSystemRegister(sim, VB_ECR);
2024-10-23 21:29:11 +00:00
sim->ph.eipc = sim->cpu.eipc;
sim->ph.eipsw = sim->cpu.eipsw;
sim->ph.fepc = sim->cpu.fepc;
sim->ph.fepsw = sim->cpu.fepsw;
sim->ph.psw = cpuGetSystemRegister(sim, VB_PSW);
sim->ph.step = 3;
return 0;
}
/* Activate pseudo-halt */
phActivate(sim, address, type);
return 1;
}
/* Determine how long the CPU should wait before checking the monitor value */
static uint32_t phUntil(VB *sim) {
switch (sim->ph.operation) {
case PH_DPSTTS : return phDPSTTS(sim);
case PH_GAME_PAD: return sim->pad.si_stat;
case PH_INTPND : return phINTPND(sim);
case PH_TCR : return sim->tmr.until;
case PH_TLHR : return sim->tmr.clocks;
case PH_XPSTTS : return phXPSTTS(sim);
2024-10-23 21:29:11 +00:00
}
return 0; /* PH_NEVER */
}
#endif /* VBAPI */