Compare commits

..
2 Commits
Author SHA1 Message Date
GuyPerfect bcd80d291b Pseudo-halt timing fix 2024-10-23 21:16:35 -05:00
GuyPerfect 0c914fce1a Implement additional pseudo-halt addresses 2024-10-23 20:35:40 -05:00
4 changed files with 153 additions and 43 deletions
+1 -1
View File
@@ -1860,7 +1860,7 @@ static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
/* Pseudo-halting */ /* Pseudo-halting */
if (sim->cpu.operation == CPU_PHALT) { if (sim->cpu.operation == CPU_PHALT) {
if (!sim->ph.operation) if (sim->cpu.clocks == 0)
return clocks; return clocks;
} }
+99 -13
View File
@@ -6,8 +6,13 @@
/********************************* Constants *********************************/ /********************************* Constants *********************************/
/* Pseudo-halt operations */ /* Pseudo-halt operations */
#define PH_NEVER 0 /* Must be zero */ #define PH_NEVER 0
#define PH_XPSTTS 1 #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
@@ -17,32 +22,76 @@
static void phActivate(VB *sim, uint32_t address, int type) { static void phActivate(VB *sim, uint32_t address, int type) {
int range; /* Memory address range by component */ int range; /* Memory address range by component */
(void) type;
/* Working variables */ /* Working variables */
address = 0x07FFFFFF; address &= 0x07FFFFFF;
range = address >> 24; range = address >> 24;
/* Configure CPU */ /* Configure pseudo-halt */
sim->cpu.operation = CPU_PHALT; sim->ph.operation = PH_NEVER;
sim->ph.operation = PH_NEVER;
/* VIP */ /* VIP */
if (range == 0) { if (range == 0) {
address &= 0x0007FFFF; address &= 0x0007FFFF;
/* TODO: Frame buffer */
/* I/O register */ /* I/O register */
switch (address) { 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;
case 0x5F840: /* XPSTTS */ case 0x5F840: /* XPSTTS */
if (sim->vip.dp.disp && sim->vip.xp.xpen) if (sim->vip.xp.enabled || sim->vip.xp.xpen)
sim->ph.operation = PH_XPSTTS; sim->ph.operation = PH_XPSTTS;
break; 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;
}
}
/* Configure CPU */ /* Configure CPU */
sim->cpu.clocks = phUntil(sim); sim->cpu.clocks = phUntil(sim);
sim->cpu.operation = CPU_PHALT;
} }
/* Test whether the current memory access matches the monitored access */ /* Test whether the current memory access matches the monitored access */
@@ -72,11 +121,12 @@ static int phMatches(VB *sim, uint32_t address, int type, int32_t value) {
return return
sim->ph.adtre == sim->cpu.adtre && sim->ph.adtre == sim->cpu.adtre &&
sim->ph.chcw == cpuGetSystemRegister(sim, VB_CHCW) && sim->ph.chcw == cpuGetSystemRegister(sim, VB_CHCW) &&
sim->ph.ecr == cpuGetSystemRegister(sim, VB_ECR) &&
sim->ph.eipc == sim->cpu.eipc && sim->ph.eipc == sim->cpu.eipc &&
sim->ph.eipsw == sim->cpu.eipsw && sim->ph.eipsw == sim->cpu.eipsw &&
sim->ph.fepc == sim->cpu.fepc && sim->ph.fepc == sim->cpu.fepc &&
sim->ph.fepsw == sim->cpu.fepsw && sim->ph.fepsw == sim->cpu.fepsw &&
sim->ph.psw == cpuGetSystemRegister(sim, VB_PSW) sim->ph.psw == cpuGetSystemRegister(sim, VB_PSW )
; ;
} }
@@ -84,6 +134,35 @@ static int phMatches(VB *sim, uint32_t address, int type, int32_t value) {
/****************************** Clock Measurers ******************************/ /****************************** 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 */
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;
}
/* XPSTTS */ /* XPSTTS */
static uint32_t phXPSTTS(VB *sim) { static uint32_t phXPSTTS(VB *sim) {
uint32_t clocks; /* Return value */ uint32_t clocks; /* Return value */
@@ -125,6 +204,7 @@ static int phAssess(VB *sim, uint32_t address, int type, int32_t value) {
int x; /* Iterator */ int x; /* Iterator */
/* Memory access does not match last time */ /* Memory access does not match last time */
address &= TYPE_MASKS[type];
if (!phMatches(sim, address, type, value)) if (!phMatches(sim, address, type, value))
sim->ph.step = 0; sim->ph.step = 0;
@@ -150,6 +230,7 @@ static int phAssess(VB *sim, uint32_t address, int type, int32_t value) {
sim->ph.program[x - 1] = sim->cpu.program[x]; sim->ph.program[x - 1] = sim->cpu.program[x];
sim->ph.adtre = sim->cpu.adtre; sim->ph.adtre = sim->cpu.adtre;
sim->ph.chcw = cpuGetSystemRegister(sim, VB_CHCW); sim->ph.chcw = cpuGetSystemRegister(sim, VB_CHCW);
sim->ph.ecr = cpuGetSystemRegister(sim, VB_ECR);
sim->ph.eipc = sim->cpu.eipc; sim->ph.eipc = sim->cpu.eipc;
sim->ph.eipsw = sim->cpu.eipsw; sim->ph.eipsw = sim->cpu.eipsw;
sim->ph.fepc = sim->cpu.fepc; sim->ph.fepc = sim->cpu.fepc;
@@ -167,7 +248,12 @@ static int phAssess(VB *sim, uint32_t address, int type, int32_t value) {
/* Determine how long the CPU should wait before checking the monitor value */ /* Determine how long the CPU should wait before checking the monitor value */
static uint32_t phUntil(VB *sim) { static uint32_t phUntil(VB *sim) {
switch (sim->ph.operation) { switch (sim->ph.operation) {
case PH_XPSTTS: return phXPSTTS(sim); 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);
} }
return 0; /* PH_NEVER */ return 0; /* PH_NEVER */
} }
+18 -6
View File
@@ -209,6 +209,7 @@ struct VB {
uint32_t clocks; /* Master clocks to wait */ uint32_t clocks; /* Master clocks to wait */
int column; /* Index of column to display */ int column; /* Index of column to display */
uint32_t cta; /* Column table pointer in memory */ uint32_t cta; /* Column table pointer in memory */
uint8_t enabled; /* Was enabled at FCLK */
uint32_t fbDest; /* Output frame pixel address */ uint32_t fbDest; /* Output frame pixel address */
uint32_t fbSrc; /* Source frame buffer address */ uint32_t fbSrc; /* Source frame buffer address */
int32_t repeat; /* Current column table repeat value */ int32_t repeat; /* Current column table repeat value */
@@ -231,6 +232,7 @@ struct VB {
/* Other state */ /* Other state */
uint32_t clocks; /* Master clocks to wait */ uint32_t clocks; /* Master clocks to wait */
int column; /* Current horizontal output position */ int column; /* Current horizontal output position */
uint8_t enabled; /* Was enabled at FCLK */
int frame; /* FRMCYC counter */ int frame; /* FRMCYC counter */
int32_t halfword; /* Current output halfword offset */ int32_t halfword; /* Current output halfword offset */
int step; /* Processing phase */ int step; /* Processing phase */
@@ -320,6 +322,7 @@ struct VB {
/* CPU snapshot */ /* CPU snapshot */
uint32_t adtre; uint32_t adtre;
uint32_t chcw; uint32_t chcw;
uint32_t ecr;
uint32_t eipc; uint32_t eipc;
uint32_t eipsw; uint32_t eipsw;
uint32_t fepc; uint32_t fepc;
@@ -379,12 +382,21 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
/* Process a simulation for a given number of clocks */ /* Process a simulation for a given number of clocks */
static int sysEmulate(VB *sim, uint32_t clocks) { static int sysEmulate(VB *sim, uint32_t clocks) {
int ret; int ret = 0;
ret = cpuEmulate(sim, clocks);
padEmulate(sim, clocks); /* CPU is in a pseudo-halt state that requires an interrupt to exit */
tmrEmulate(sim, clocks); int never =
vsuEmulate(sim, clocks); sim->cpu.operation == CPU_PHALT &&
ret |= vipEmulate(sim, clocks); sim->ph.operation == PH_NEVER
;
/* Process all components */
if (!never) ret = cpuEmulate(sim, clocks);
padEmulate(sim, clocks);
tmrEmulate(sim, clocks);
vsuEmulate(sim, clocks);
ret |= vipEmulate(sim, clocks);
if ( never) ret |= cpuEmulate(sim, clocks);
return ret; return ret;
} }
+35 -23
View File
@@ -420,7 +420,7 @@ static void vipTransferColumn(VB *sim, int32_t eye) {
[sim->vip.dp.buffer][eye][sim->vip.dp.column]; [sim->vip.dp.buffer][eye][sim->vip.dp.column];
/* Output is disabled */ /* Output is disabled */
if ((sim->vip.dp.disp & sim->vip.dp.synce) == 0) { if (!sim->vip.dp.enabled) {
for (y = 0; y < 224; y += 16) for (y = 0; y < 224; y += 16)
for (z = 0; z < 16; z++, dest += 384) for (z = 0; z < 16; z++, dest += 384)
*dest = 0; *dest = 0;
@@ -465,10 +465,11 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
switch (sim->vip.dp.step) { switch (sim->vip.dp.step) {
case 0: /* 0ms - FCLK rising edge */ case 0: /* 0ms - FCLK rising edge */
sim->vip.dp.clocks = vipClocksMs(3); sim->vip.dp.clocks = vipClocksMs(3);
sim->vip.dp.fclk = 1; sim->vip.dp.enabled = sim->vip.dp.disp & sim->vip.dp.synce;
sim->vip.dp.step = 1; sim->vip.dp.fclk = 1;
sim->vip.dp.until = vipClocksMs(8); sim->vip.dp.step = 1;
sim->vip.dp.until = vipClocksMs(8);
vipThrow(sim, 0x0010); /* FRAMESTART */ vipThrow(sim, 0x0010); /* FRAMESTART */
/* Game frame */ /* Game frame */
@@ -479,6 +480,7 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
/* Initiate drawing procedure */ /* Initiate drawing procedure */
if (sim->vip.xp.step == 0) { if (sim->vip.xp.step == 0) {
sim->vip.dp.buffer ^= 1; sim->vip.dp.buffer ^= 1;
sim->vip.xp.enabled = 1;
sim->vip.xp.overtime = 0; sim->vip.xp.overtime = 0;
sim->vip.xp.step = 1; sim->vip.xp.step = 1;
vipThrow(sim, 0x0008); /* GAMESTART */ vipThrow(sim, 0x0008); /* GAMESTART */
@@ -498,9 +500,11 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
/* 0ms-3ms - Idle */ /* 0ms-3ms - Idle */
case 1: /* 3ms - L*BSY rising edge */ case 1: /* 3ms - L*BSY rising edge */
if (sim->vip.dp.buffer == 0) if (sim->vip.dp.enabled) {
sim->vip.dp.l0bsy = 1; if (sim->vip.dp.buffer == 0)
else sim->vip.dp.l1bsy = 1; sim->vip.dp.l0bsy = 1;
else sim->vip.dp.l1bsy = 1;
}
sim->vip.dp.column = 0; sim->vip.dp.column = 0;
sim->vip.dp.cta = 0x3DC00 | (uint32_t)sim->vip.cta.cta_l<<1; sim->vip.dp.cta = 0x3DC00 | (uint32_t)sim->vip.cta.cta_l<<1;
sim->vip.dp.step = 2; sim->vip.dp.step = 2;
@@ -521,13 +525,15 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
break; break;
case 3: /* 8ms - L*BSY falling edge */ case 3: /* 8ms - L*BSY falling edge */
if (sim->vip.dp.buffer == 0) if (sim->vip.dp.enabled) {
sim->vip.dp.l0bsy = 0; if (sim->vip.dp.buffer == 0)
else sim->vip.dp.l1bsy = 0; sim->vip.dp.l0bsy = 0;
else sim->vip.dp.l1bsy = 0;
vipThrow(sim, 0x0002); /* LFBEND */
}
sim->vip.dp.clocks = vipClocksMs(2); sim->vip.dp.clocks = vipClocksMs(2);
sim->vip.dp.step = 4; sim->vip.dp.step = 4;
sim->vip.dp.until = vipClocksMs(10); sim->vip.dp.until = vipClocksMs(10);
vipThrow(sim, 0x0002); /* LFBEND */
break; break;
/* 8ms-10ms - Idle */ /* 8ms-10ms - Idle */
@@ -541,9 +547,11 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
/* 10ms-13ms - Idle */ /* 10ms-13ms - Idle */
case 5: /* 13ms - R*BSY rising edge */ case 5: /* 13ms - R*BSY rising edge */
if (sim->vip.dp.buffer == 0) if (sim->vip.dp.enabled) {
sim->vip.dp.r0bsy = 1; if (sim->vip.dp.buffer == 0)
else sim->vip.dp.r1bsy = 1; sim->vip.dp.r0bsy = 1;
else sim->vip.dp.r1bsy = 1;
}
sim->vip.dp.column = 0; sim->vip.dp.column = 0;
sim->vip.dp.cta = 0x3DE00 | (uint32_t)sim->vip.cta.cta_r<<1; sim->vip.dp.cta = 0x3DE00 | (uint32_t)sim->vip.cta.cta_r<<1;
sim->vip.dp.step = 6; sim->vip.dp.step = 6;
@@ -563,13 +571,16 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
break; break;
case 7: /* 18ms - R*BSY falling edge */ case 7: /* 18ms - R*BSY falling edge */
if (sim->vip.dp.buffer == 0) if (sim->vip.dp.enabled) {
sim->vip.dp.r0bsy = 0; if (sim->vip.dp.buffer == 0)
else sim->vip.dp.r1bsy = 0; sim->vip.dp.r0bsy = 0;
sim->vip.dp.clocks = vipClocksMs(2); else sim->vip.dp.r1bsy = 0;
sim->vip.dp.step = 0; vipThrow(sim, 0x0004); /* RFBEND */
sim->vip.dp.until = vipClocksMs(2); }
vipThrow(sim, 0x0004); /* RFBEND */ sim->vip.dp.clocks = vipClocksMs(2);
sim->vip.dp.enabled = 0;
sim->vip.dp.step = 0;
sim->vip.dp.until = vipClocksMs(2);
if (vipOnFrame(sim)) if (vipOnFrame(sim))
return 1; return 1;
break; break;
@@ -1009,7 +1020,8 @@ static void vipEmulateDrawing(VB *sim, uint32_t clocks) {
break; break;
case 4: /* Drawing complete */ case 4: /* Drawing complete */
sim->vip.xp.step = 0; sim->vip.xp.enabled = 0;
sim->vip.xp.step = 0;
if (sim->vip.dp.buffer == 0) if (sim->vip.dp.buffer == 0)
sim->vip.xp.f1bsy = 0; sim->vip.xp.f1bsy = 0;
else sim->vip.xp.f0bsy = 0; else sim->vip.xp.f0bsy = 0;