Skip to content

Commit

Permalink
DMD: fix WPC incorrectly mixing Snd & DMD FIRQ
Browse files Browse the repository at this point in the history
  • Loading branch information
vbousquet committed Oct 5, 2024
1 parent 7db3cae commit 145a527
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 35 deletions.
8 changes: 6 additions & 2 deletions docs/dmd.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ The table below gives the main information (PWM FPS / Display FPS / PWM pattern)

## WPC

WPC simply renders frame at 122.1Hz, expecting the viewer eye to merge the 3 last rasterized frame.
WPC continuously renders frame at 122.1Hz. The game code uses this to render sequences of
either 1 (0/100), 2 (0/50/100), or 3 (0/33/66/100) frames, expecting the viewer eye to
merge these frames into shades. For example, Terminator 2 uses a 2 frame PWM pattern while
Creature from the Black Lagoon uses a 3 frame PWM pattern.

Phantom Haus uses a double height DMD which is therefore rasterized at half frequency: 61.5Hz. As a consequence, the game only uses a PWM pattern limited to 2 frame patterns, likely to avoid flicker.
Phantom Haus uses a double height DMD which is rasterized by the same hardware at half frequency: 61.5Hz.
As a consequence, the game only uses a 2 frame PWM pattern, likely to avoid flicker.


## Alvin G
Expand Down
51 changes: 18 additions & 33 deletions src/wpc/wpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,13 @@ static struct {
int modsol_sample;
mame_timer* highres_timer;
int wpcFIRQ; // State of the WPC chip high res timer FIRQ output
int sndFIRQ; // State of the FIRQ output of the sound board
} wpclocals;

// Have to put this here, instead of wpclocals, since wpclocals is cleared/initialized AFTER game specific init. Grrr.
static int wpc_modsol_aux_board = 0;
static int wpc_fastflip_addr = 0;

static struct {
int visiblePage; // rasterized memory page
int row; // Rasterizer row position
int firq; // State of FIRQ output line to CPU
core_tDMDPWMState pwm_state;
Expand Down Expand Up @@ -416,7 +414,7 @@ MACHINE_DRIVER_END
// - the sound board FIRQ output
// - the programmable DMD FIRQ output (raise when a given row is reached, clear when the FIRS row is defined)
static void update_firq() {
cpu_set_irq_line(WPC_CPUNO, M6809_FIRQ_LINE, (wpclocals.wpcFIRQ | wpclocals.sndFIRQ | dmdlocals.firq) ? HOLD_LINE : CLEAR_LINE);
cpu_set_irq_line(WPC_CPUNO, M6809_FIRQ_LINE, (wpclocals.wpcFIRQ | dmdlocals.firq) ? HOLD_LINE : CLEAR_LINE);
}

// High resolution timer provided by the WPC chip. Used by alpha gen games to dim segments
Expand Down Expand Up @@ -724,14 +722,6 @@ READ_HANDLER(wpc_r) {
DBGLOG(("wpc_r %4x\n", offset+WPC_BASE));
break;
}
// All reads from sound board seem to perform a ack on the sound board FIRQ
// since SndBoard U16 chips decodes the address in the given range, and
// produce the CpuRd* signal which happens to ack the FIRQ board output
if (wpclocals.sndFIRQ != 0 && (0x3fd8-WPC_BASE <= offset) && (0x3fdf-WPC_BASE <= offset))
{
wpclocals.sndFIRQ = 0;
update_firq();
}
return wpc_data[offset];
}

Expand Down Expand Up @@ -994,17 +984,17 @@ WRITE_HANDLER(wpc_w) {
// cpu_set_irq_line(WPC_CPUNO, M6809_IRQ_LINE, CLEAR_LINE);
DBGLOG(("WPC_IRQACK. PC=%04x d=%02x\n",activecpu_get_pc(), data));
break;
case WPC_DMD_PAGE3000: /* set the page that is visible at 0x3000 (WPC-95 only) */
cpu_setbank(4, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3200: /* set the page that is visible at 0x3200 (WPC-95 only) */
cpu_setbank(5, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3400: /* set the page that is visible at 0x3400 (WPC-95 only) */
cpu_setbank(6, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3600: /* set the page that is visible at 0x3600 (WPC-95 only) */
cpu_setbank(7, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3800: /* set the page that is visible at 0x3800 */
case WPC_DMD_PAGE3000: /* set the page that is accessed by CPU at 0x3000 (WPC-95 only) */
if (core_gameData->gen & (GEN_WPC95DCS | GEN_WPC95)) cpu_setbank(4, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3200: /* set the page that is accessed by CPU at 0x3200 (WPC-95 only) */
if (core_gameData->gen & (GEN_WPC95DCS | GEN_WPC95)) cpu_setbank(5, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3400: /* set the page that is accessed by CPU at 0x3400 (WPC-95 only) */
if (core_gameData->gen & (GEN_WPC95DCS | GEN_WPC95)) cpu_setbank(6, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3600: /* set the page that is accessed by CPU at 0x3600 (WPC-95 only) */
if (core_gameData->gen & (GEN_WPC95DCS | GEN_WPC95)) cpu_setbank(7, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3800: /* set the page that is accessed by CPU at 0x3800 */
cpu_setbank(2, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_PAGE3A00: /* set the page that is visible at 0x3A00 */
case WPC_DMD_PAGE3A00: /* set the page that is accessed by CPU at 0x3A00 */
cpu_setbank(3, memory_region(WPC_DMDREGION) + (data & 0x0f) * 0x200); break;
case WPC_DMD_FIRQLINE: /* acknowledge raised DMD FIRQ if any, and set the line to generate the next FIRQ (0xFF to ack and disable) */
//printf("%8.5f FIRQ ROW: %02x PC: %04x\n", timer_get_time(), data, activecpu_get_pc());
Expand All @@ -1014,6 +1004,7 @@ WRITE_HANDLER(wpc_w) {
}
break;
case WPC_DMD_SHOWPAGE: /* set the page that will be rasterized after next DMD vblank */
//{ static double prev = 0.; printf("%8.5f Set page: %02x PC: %04x elapsed:%8.5f\n", timer_get_time(), data, activecpu_get_pc(), timer_get_time()-prev); prev = timer_get_time(); }
break;
case WPC_RTCHOUR:
case WPC_RTCMIN:
Expand Down Expand Up @@ -1143,13 +1134,6 @@ static SWITCH_UPDATE(wpc) {
#endif
}

static WRITE_HANDLER(snd_data_cb) { // WPCS sound generates FIRQ on reply
if (wpclocals.sndFIRQ != 1) {
wpclocals.sndFIRQ = 1;
update_firq();
}
}

static MACHINE_INIT(wpc) {
/*128K 256K 512K 768K 1024K*/
static const int romLengthMask[] = {0x07, 0x0f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f};
Expand All @@ -1172,7 +1156,7 @@ static MACHINE_INIT(wpc) {
case GEN_WPCALPHA_2:
case GEN_WPCDMD:
case GEN_WPCFLIPTRON:
sndbrd_0_init(SNDBRD_WPCS, 1, memory_region(WPCS_ROMREGION),snd_data_cb,NULL);
sndbrd_0_init(SNDBRD_WPCS, 1, memory_region(WPCS_ROMREGION),NULL,NULL);
break;
case GEN_WPCDCS:
case GEN_WPCSECURITY:
Expand Down Expand Up @@ -1601,16 +1585,17 @@ static void wpc_dmd_hsync(int param) {
dmdlocals.row = (dmdlocals.row + 1) % dmdlocals.pwm_state.height; // FIXME Phantom Haus uses the same AV card than other WPC95 but with a 64 row display, therefore the CPU must tell the rasterizer that it is 64 row high somewhere we don't know
if (dmdlocals.row == 0) { // VSYNC
// Rasterize next page (latched while rasterizing the previous page)
dmdlocals.visiblePage = wpc_data[WPC_DMD_SHOWPAGE];
core_dmd_submit_frame(&dmdlocals.pwm_state, memory_region(WPC_DMDREGION) + (dmdlocals.visiblePage & 0x0f) * dmdlocals.pwm_state.rawFrameSize, 1);
const int rasterizedPage = wpc_data[WPC_DMD_SHOWPAGE] & 0x0f;
//printf("%8.5f Rnd page: %02x\n", timer_get_time(), rasterizedPage);
core_dmd_submit_frame(&dmdlocals.pwm_state, memory_region(WPC_DMDREGION) + rasterizedPage * dmdlocals.pwm_state.rawFrameSize, 1);
#ifdef PROC_SUPPORT
if (coreGlobals.p_rocEn) /* looks like P-ROC uses the last 3 subframes sent rather than the first 3 */
procFillDMDSubFrame(dmd_state->frame_index % 3, memory_region(WPC_DMDREGION) + (dmdlocals.visiblePage & 0x0f) * dmdlocals.pwm_state.rawFrameSize, dmdlocals.pwm_state.rawFrameSize);
procFillDMDSubFrame(dmd_state->frame_index % 3, memory_region(WPC_DMDREGION) + rasterizedPage * dmdlocals.pwm_state.rawFrameSize, dmdlocals.pwm_state.rawFrameSize);
/* Don't explicitly update the DMD from here. The P-ROC code will update after the next DMD event. */
#endif
}
if (dmdlocals.row == wpc_data[WPC_DMD_FIRQLINE] && dmdlocals.firq != 1) {
// printf("%8.5f FIRQ RAISED\n", timer_get_time());
//printf("%8.5f FIRQ at row %02x\n", timer_get_time(), dmdlocals.row);
dmdlocals.firq = 1;
update_firq();
}
Expand Down

0 comments on commit 145a527

Please sign in to comment.