From 0c914fce1afa846171f32a8f949e174313ee6fe3 Mon Sep 17 00:00:00 2001 From: Guy Perfect Date: Wed, 23 Oct 2024 20:35:40 -0500 Subject: [PATCH] Implement additional pseudo-halt addresses --- core/cpu.c | 2 +- core/pseudo-halt.c | 108 ++++++++++++++++++++++++++++++++++++++++----- core/vb.c | 2 + core/vip.c | 58 ++++++++++++++---------- 4 files changed, 134 insertions(+), 36 deletions(-) diff --git a/core/cpu.c b/core/cpu.c index 90e7530..2eda606 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -1860,7 +1860,7 @@ static uint32_t cpuUntil(VB *sim, uint32_t clocks) { /* Pseudo-halting */ if (sim->cpu.operation == CPU_PHALT) { - if (!sim->ph.operation) + if (sim->cpu.clocks == 0) /* Requires an interrupt */ return clocks; } diff --git a/core/pseudo-halt.c b/core/pseudo-halt.c index fba370c..c65d26c 100644 --- a/core/pseudo-halt.c +++ b/core/pseudo-halt.c @@ -6,8 +6,13 @@ /********************************* Constants *********************************/ /* Pseudo-halt operations */ -#define PH_NEVER 0 /* Must be zero */ -#define PH_XPSTTS 1 +#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 @@ -17,32 +22,76 @@ static void phActivate(VB *sim, uint32_t address, int type) { int range; /* Memory address range by component */ - (void) type; - /* Working variables */ - address = 0x07FFFFFF; - range = address >> 24; + address &= 0x07FFFFFF; + range = address >> 24; - /* Configure CPU */ - sim->cpu.operation = CPU_PHALT; - sim->ph.operation = PH_NEVER; + /* Configure pseudo-halt */ + sim->ph.operation = PH_NEVER; /* VIP */ if (range == 0) { address &= 0x0007FFFF; + /* TODO: Frame buffer */ + /* 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; 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; 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 */ - 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 */ @@ -84,6 +133,35 @@ static int phMatches(VB *sim, uint32_t address, int type, int32_t value) { /****************************** 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 */ static uint32_t phXPSTTS(VB *sim) { 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 */ /* Memory access does not match last time */ + address &= TYPE_MASKS[type]; if (!phMatches(sim, address, type, value)) 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 */ static uint32_t phUntil(VB *sim) { 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 */ } diff --git a/core/vb.c b/core/vb.c index ea96d49..61f7e89 100644 --- a/core/vb.c +++ b/core/vb.c @@ -209,6 +209,7 @@ struct VB { uint32_t clocks; /* Master clocks to wait */ int column; /* Index of column to display */ uint32_t cta; /* Column table pointer in memory */ + uint8_t enabled; /* Was enabled at FCLK */ uint32_t fbDest; /* Output frame pixel address */ uint32_t fbSrc; /* Source frame buffer address */ int32_t repeat; /* Current column table repeat value */ @@ -231,6 +232,7 @@ struct VB { /* Other state */ uint32_t clocks; /* Master clocks to wait */ int column; /* Current horizontal output position */ + uint8_t enabled; /* Was enabled at FCLK */ int frame; /* FRMCYC counter */ int32_t halfword; /* Current output halfword offset */ int step; /* Processing phase */ diff --git a/core/vip.c b/core/vip.c index c026cf3..c4cd2ec 100644 --- a/core/vip.c +++ b/core/vip.c @@ -420,7 +420,7 @@ static void vipTransferColumn(VB *sim, int32_t eye) { [sim->vip.dp.buffer][eye][sim->vip.dp.column]; /* 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 (z = 0; z < 16; z++, dest += 384) *dest = 0; @@ -465,10 +465,11 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) { switch (sim->vip.dp.step) { case 0: /* 0ms - FCLK rising edge */ - sim->vip.dp.clocks = vipClocksMs(3); - sim->vip.dp.fclk = 1; - sim->vip.dp.step = 1; - sim->vip.dp.until = vipClocksMs(8); + sim->vip.dp.clocks = vipClocksMs(3); + sim->vip.dp.enabled = sim->vip.dp.disp & sim->vip.dp.synce; + sim->vip.dp.fclk = 1; + sim->vip.dp.step = 1; + sim->vip.dp.until = vipClocksMs(8); vipThrow(sim, 0x0010); /* FRAMESTART */ /* Game frame */ @@ -479,6 +480,7 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) { /* Initiate drawing procedure */ if (sim->vip.xp.step == 0) { sim->vip.dp.buffer ^= 1; + sim->vip.xp.enabled = 1; sim->vip.xp.overtime = 0; sim->vip.xp.step = 1; vipThrow(sim, 0x0008); /* GAMESTART */ @@ -498,9 +500,11 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) { /* 0ms-3ms - Idle */ case 1: /* 3ms - L*BSY rising edge */ - if (sim->vip.dp.buffer == 0) - sim->vip.dp.l0bsy = 1; - else sim->vip.dp.l1bsy = 1; + if (sim->vip.dp.enabled) { + if (sim->vip.dp.buffer == 0) + sim->vip.dp.l0bsy = 1; + else sim->vip.dp.l1bsy = 1; + } sim->vip.dp.column = 0; sim->vip.dp.cta = 0x3DC00 | (uint32_t)sim->vip.cta.cta_l<<1; sim->vip.dp.step = 2; @@ -521,13 +525,15 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) { break; case 3: /* 8ms - L*BSY falling edge */ - if (sim->vip.dp.buffer == 0) - sim->vip.dp.l0bsy = 0; - else sim->vip.dp.l1bsy = 0; + if (sim->vip.dp.enabled) { + if (sim->vip.dp.buffer == 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.step = 4; sim->vip.dp.until = vipClocksMs(10); - vipThrow(sim, 0x0002); /* LFBEND */ break; /* 8ms-10ms - Idle */ @@ -541,9 +547,11 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) { /* 10ms-13ms - Idle */ case 5: /* 13ms - R*BSY rising edge */ - if (sim->vip.dp.buffer == 0) - sim->vip.dp.r0bsy = 1; - else sim->vip.dp.r1bsy = 1; + if (sim->vip.dp.enabled) { + if (sim->vip.dp.buffer == 0) + sim->vip.dp.r0bsy = 1; + else sim->vip.dp.r1bsy = 1; + } sim->vip.dp.column = 0; sim->vip.dp.cta = 0x3DE00 | (uint32_t)sim->vip.cta.cta_r<<1; sim->vip.dp.step = 6; @@ -563,13 +571,16 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) { break; case 7: /* 18ms - R*BSY falling edge */ - if (sim->vip.dp.buffer == 0) - sim->vip.dp.r0bsy = 0; - else sim->vip.dp.r1bsy = 0; - sim->vip.dp.clocks = vipClocksMs(2); - sim->vip.dp.step = 0; - sim->vip.dp.until = vipClocksMs(2); - vipThrow(sim, 0x0004); /* RFBEND */ + if (sim->vip.dp.enabled) { + if (sim->vip.dp.buffer == 0) + sim->vip.dp.r0bsy = 0; + else sim->vip.dp.r1bsy = 0; + 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)) return 1; break; @@ -1009,7 +1020,8 @@ static void vipEmulateDrawing(VB *sim, uint32_t clocks) { break; 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) sim->vip.xp.f1bsy = 0; else sim->vip.xp.f0bsy = 0;