Implement additional pseudo-halt addresses
This commit is contained in:
parent
226da7a5b3
commit
0c914fce1a
|
@ -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) /* Requires an interrupt */
|
||||||
return clocks;
|
return clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
@ -84,6 +133,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 +203,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;
|
||||||
|
|
||||||
|
@ -167,7 +246,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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
58
core/vip.c
58
core/vip.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue