From 8f8fc5c8f0bde2da2f8f91a426884e7de13d2a9c Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Sat, 31 Aug 2024 15:48:08 +0200 Subject: [PATCH] DMD: generic PWM support, Data East 128x32 support, GTS3 cleanups, Alvin.G preliminary cleanups --- src/vidhrdw/crtc6845.c | 10 ++++ src/vidhrdw/crtc6845.h | 4 ++ src/wpc/alvgdmd.c | 81 +++++++++++++++-------------- src/wpc/core.c | 114 ++++++++++++++++++++++++++++++++++++++--- src/wpc/core.h | 21 ++++++++ src/wpc/dedmd.c | 81 +++++++++++++---------------- src/wpc/dedmd.h | 1 - src/wpc/degames.c | 50 +++++++++--------- src/wpc/gts3.c | 32 +++++++----- src/wpc/gts3.h | 2 +- src/wpc/gts3dmd.c | 75 ++++----------------------- src/wpc/gts3dmd.h | 2 - src/wpc/s11.c | 11 ---- src/wpc/s11.h | 1 - src/wpc/wpc.c | 11 ++-- 15 files changed, 280 insertions(+), 216 deletions(-) diff --git a/src/vidhrdw/crtc6845.c b/src/vidhrdw/crtc6845.c index 843de7262..4b00c2601 100644 --- a/src/vidhrdw/crtc6845.c +++ b/src/vidhrdw/crtc6845.c @@ -260,7 +260,17 @@ int crtc6845_start_address_r(int offset) { return crtc6845[offset].start_addr; } +//Return rasterization size +int crtc6845_get_rasterized_height(int offset) +{ + // height in scanlines is the number of displayed character line * number of scanlines per character + return crtc6845[offset].vert_disp * (crtc6845[offset].max_ras_addr + 1); +} +int crtc6845_get_rasterized_width(int offset) +{ + return crtc6845[offset].horiz_disp; +} diff --git a/src/vidhrdw/crtc6845.h b/src/vidhrdw/crtc6845.h index 49d188751..91e00d629 100644 --- a/src/vidhrdw/crtc6845.h +++ b/src/vidhrdw/crtc6845.h @@ -23,6 +23,10 @@ WRITE_HANDLER( crtc6845_register_w ); //Return current video start address int crtc6845_start_address_r(int offset); +//Return rasterization size +int crtc6845_get_rasterized_height(int offset); +int crtc6845_get_rasterized_width(int offset); + /*Convenience handlers*/ READ_HANDLER( crtc6845_register_0_r ); WRITE_HANDLER( crtc6845_address_0_w ); diff --git a/src/wpc/alvgdmd.c b/src/wpc/alvgdmd.c index 8515b0aa8..88aac4143 100644 --- a/src/wpc/alvgdmd.c +++ b/src/wpc/alvgdmd.c @@ -28,7 +28,8 @@ extern UINT32 g_raw_gtswpc_dmdframes; static struct { struct sndbrdData brdData; - int cmd, planenable, disenable, setsync; + int cmd, planenable, disenable; + int selsync; // SELSYNC signal on PCA020A board (Mystery Castle, Pistol Poker). Enable/Disable rasterization VCLOCK. Not present on PCA020 board (Al's Garage Band). int vid_page; int last; @@ -52,12 +53,6 @@ const struct sndbrdIntf alvgdmdIntf = { dmd32_data_w, NULL, dmd32_ctrl_w, NULL, SNDBRD_NOTSOUND }; - -/*Main CPU sends command to DMD*/ -static WRITE_HANDLER(dmd32_data_w) { - dmdlocals.cmd = data; -} - static WRITE_HANDLER(control_w) { UINT16 tmpoffset = offset; @@ -65,50 +60,57 @@ static WRITE_HANDLER(control_w) tmpoffset &= 0xf000; //Remove bits 0-11 (in other words, treat 0x8fff the same as 0x8000!) switch (tmpoffset) { - //Read Main CPU DMD Command + //Read Main CPU DMD Command [PORTIN signal] case 0x8000: LOG(("WARNING! Writing to address 0x8000 - DMD Latch, data=%x!\n",data)); + dmdlocals.selsync = 1; break; - //Send Data to the Main CPU + //Send Data to the Main CPU [PORTOUT signal] case 0x9000: sndbrd_ctrl_cb(dmdlocals.brdData.boardNo, data); + dmdlocals.selsync = 1; break; - //ROM Bankswitching + //ROM Bankswitching [CODEPAGE signal] case 0xa000: dmd32_bank_w(0,data); + dmdlocals.selsync = 1; break; - //ROWSTART Line + //ROWSTART Line [ROWSTART signal] case 0xb000: LOG(("rowstart = %x\n",data)); + dmdlocals.selsync = 1; break; - //COLSTART Line + //COLSTART Line [COLSTART signal] case 0xc000: LOG(("colstart = %x\n",data)); + dmdlocals.selsync = 1; break; //NC case 0xd000: case 0xe000: LOG(("writing to not connected address: %x data=%x\n",offset,data)); + dmdlocals.selsync = 1; break; - //SETSYNC Line + //SELSYNC Line [SELSYNC signal on PCA020A, not wired on PCA020] + //SelSync suspend rasterization (stops rasterization clock) if written to, only the address bus is used, so writing to any other address in 0x8000 - 0xE000 will reset it + //it doesn't seem to be used (didn't find a write to it on Pistol Poker & Mystery Castle) + // FIXME remove for hardware without it case 0xf000: - dmdlocals.setsync=data; - LOG(("setsync=%x\n",data)); + LOG(("setsync=%x\n", data)); + dmdlocals.selsync = 0; + printf("%8.5f selsync off\n", timer_get_time()); break; + default: LOG(("WARNING! Reading invalid control address %x\n", offset)); break; } - //Setsync line goes hi for all address except it's own(0xf000) - if(offset != 0xf000) { - dmdlocals.setsync=1; - } } static READ_HANDLER(control_r) @@ -121,18 +123,25 @@ static READ_HANDLER(control_r) //Read Main CPU DMD Command case 0x8000: { int data = dmd32_latch_r(0); + dmdlocals.selsync = 1; return data; } - //While unlikely, a READ to these addresses, can actually trigger control lines, so we call control_w() + case 0x9000: case 0xa000: case 0xb000: case 0xc000: case 0xd000: case 0xe000: + // undefined behavior as data is not set + dmdlocals.selsync = 1; + break; + + // see control_w (data is unused so it has the same effect) case 0xf000: - control_w(offset,0); + dmdlocals.selsync = 0; break; + default: LOG(("WARNING! Reading invalid control address %x\n", offset)); } @@ -259,7 +268,12 @@ static void dmd32_init(struct sndbrdData *brdData) { memset(&dmdlocals, 0, sizeof(dmdlocals)); dmdlocals.brdData = *brdData; dmd32_bank_w(0,0); //Set DMD Bank to 0 - dmdlocals.setsync = 1; //Start Sync @ 1 + dmdlocals.selsync = 1; //Start Sync @ 1 +} + +// Main CPU sends command to DMD +static WRITE_HANDLER(dmd32_data_w) { + dmdlocals.cmd = data; } //Send data from Main CPU to latch - Set's the INT0 Line @@ -277,7 +291,7 @@ static READ_HANDLER(dmd32_latch_r) { //Pulse the INT1 Line static INTERRUPT_GEN(dmd32_firq) { - if(dmdlocals.setsync) { + if(dmdlocals.selsync) { LOG(("INT1 Pulse\n")); cpu_set_irq_line(dmdlocals.brdData.cpuNo, I8051_INT1_LINE, PULSE_LINE); } @@ -286,17 +300,6 @@ static INTERRUPT_GEN(dmd32_firq) { } } -#if defined(VPINMAME) || defined(LIBPINMAME) -static const unsigned char lookup[16] = { -0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, -0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, }; - -INLINE UINT8 reverse(UINT8 n) { - // Reverse the top and bottom nibble then swap them. - return (lookup[n & 0x0f] << 4) | lookup[n >> 4]; -} -#endif - PINMAME_VIDEO_UPDATE(alvgdmd_update) { #ifdef MAME_DEBUG static int offset = 0; @@ -377,10 +380,10 @@ static void pistol_poker__mystery_castle_dmd(void) { *line++ = level[((RAM[0] >> 1 & 0x01) + (RAM[0x200] >> 1 & 0x01) + (RAM[0x400] >> 1 & 0x01) + (RAM[0x600] >> 1 & 0x01))]; *line++ = level[((RAM[0]/*>>0*/&0x01) + (RAM[0x200]/*>>0*/&0x01) + (RAM[0x400]/*>>0*/&0x01) + (RAM[0x600]/*>>0*/&0x01))]; #if defined(VPINMAME) || defined(LIBPINMAME) - g_raw_gtswpc_dmd[ i] = reverse(RAM[0]); - g_raw_gtswpc_dmd[0x200 + i] = reverse(RAM[0x200]); - g_raw_gtswpc_dmd[0x400 + i] = reverse(RAM[0x400]); - g_raw_gtswpc_dmd[0x600 + i] = reverse(RAM[0x600]); + g_raw_gtswpc_dmd[ i] = core_revbyte(RAM[0]); + g_raw_gtswpc_dmd[0x200 + i] = core_revbyte(RAM[0x200]); + g_raw_gtswpc_dmd[0x400 + i] = core_revbyte(RAM[0x400]); + g_raw_gtswpc_dmd[0x600 + i] = core_revbyte(RAM[0x600]); i++; #endif RAM += 1; @@ -403,7 +406,7 @@ static void pistol_poker__mystery_castle_dmd(void) { g_raw_gtswpc_dmd[ i] = g_raw_gtswpc_dmd[0x200 + i] = g_raw_gtswpc_dmd[0x400 + i] = - g_raw_gtswpc_dmd[0x600 + i] = reverse(RAM[0]); + g_raw_gtswpc_dmd[0x600 + i] = core_revbyte(RAM[0]); i++; #endif RAM += 1; diff --git a/src/wpc/core.c b/src/wpc/core.c index 6decb61a2..31178b934 100644 --- a/src/wpc/core.c +++ b/src/wpc/core.c @@ -55,7 +55,7 @@ static UINT8 has_DMD_Video = 0; #include "gts3dmd.h" - UINT8 g_raw_gtswpc_dmd[GTS3DMD_FRAMES*0x200]; + UINT8 g_raw_gtswpc_dmd[16*0x200]; // TODO cleanup raw frame sharing UINT32 g_raw_gtswpc_dmdframes = 0; UINT8 g_needs_DMD_update = 1; @@ -940,7 +940,8 @@ void video_update_core_dmd(struct mame_bitmap *bitmap, const struct rectangle *c } } #endif - + // The PWM DMD implementation is always returning a full byte, so we shift it down here to return the expected value to existing code + const int shift = ((core_gameData->gen & (GEN_GTS3)) != 0) ? 4 /* 256 to 16 shades */ : ((core_gameData->gen & (GEN_ALLWPC | GEN_DEDMD32)) != 0) ? 6 /* 256 to 4 shades */ : 0; memset(&coreGlobals.dotCol[layout->start+1][0], 0, sizeof(coreGlobals.dotCol[0][0])*layout->length+1); memset(&coreGlobals.dotCol[0][0], 0, sizeof(coreGlobals.dotCol[0][0])*layout->length+1); // clear above for (ii = 0; ii < layout->start+1; ii++) { @@ -948,7 +949,7 @@ void video_update_core_dmd(struct mame_bitmap *bitmap, const struct rectangle *c coreGlobals.dotCol[ii][layout->length] = 0; if (ii > 0) { for (jj = 0; jj < layout->length; jj++) { - const UINT8 col = coreGlobals.dotCol[ii][jj]; + const UINT8 col = coreGlobals.dotCol[ii][jj] >> shift; #if defined(VPINMAME) || defined(LIBPINMAME) const int offs = (ii-1)*layout->length + jj; currbuffer[offs] = col; @@ -963,14 +964,14 @@ void video_update_core_dmd(struct mame_bitmap *bitmap, const struct rectangle *c #endif *line++ = shade_16_enabled ? dmdColor[col+63] : dmdColor[col]; if (locals.displaySize > 1 && jj < layout->length-1) - *line++ = noaa ? 0 : aaColor[col + coreGlobals.dotCol[ii][jj+1]]; + *line++ = noaa ? 0 : aaColor[col + (coreGlobals.dotCol[ii][jj+1] >> shift)]; } } if (locals.displaySize > 1) { - int col1 = coreGlobals.dotCol[ii][0] + coreGlobals.dotCol[ii+1][0]; + int col1 = (coreGlobals.dotCol[ii][0] >> shift) + (coreGlobals.dotCol[ii+1][0] >> shift); line = (*lines++) + (layout->left*locals.displaySize); for (jj = 0; jj < layout->length; jj++) { - int col2 = coreGlobals.dotCol[ii][jj+1] + coreGlobals.dotCol[ii+1][jj+1]; + int col2 = (coreGlobals.dotCol[ii][jj+1] >> shift) + (coreGlobals.dotCol[ii+1][jj+1] >> shift); *line++ = noaa ? 0 : aaColor[col1]; if (jj < layout->length-1) *line++ = noaa ? 0 : aaColor[2*(col1 + col2)/5]; @@ -2942,6 +2943,107 @@ void core_write_pwm_output_lamp_matrix(int startIndex, UINT8 columns, UINT8 rows } } + +// +// +// + +/* The following script allows to compute and display the filter applied to some PWM pattern in GNU Octave: +pkg load signal +fc = 15; % Cut-off frequency (Hz) +fs = 376; % Sampling rate (Hz) +n = number fo stored frame +data=[repmat([0;0;1],100,1),repmat([0;0;0;1;1;1],50,1),repmat([0;0;0;0;1;1;1;1;1;1],30,1),repmat([0;0;0;0;0;0;0;0;0;1],30,1)]; +b = fir1(n - 1, fc/(fs/2)); +filtered = filter(b,1,data); +clf +subplot ( columns ( filtered ), 1, 1) +plot(filtered(:,1),";1/3 - 3;") +subplot ( columns ( filtered ), 1, 2 ) +plot(filtered(:,2),";1/2 - 6;") +subplot ( columns ( filtered ), 1, 3 ) +plot(filtered(:,3),";6/10 - 10;") +subplot ( columns ( filtered ), 1, 4 ) +plot(filtered(:,4),";1/10 - 10;") +bp = 10000 * b; % scaled filter used for PinMame integer math +*/ +void core_dmd_pwm_init(core_tDMDPWMState* dmd_state, const int width, const int height, const int filter) { + dmd_state->width = width; + dmd_state->height = height; + dmd_state->rawFrameSize = width * height / 8; + assert(dmd_state->rawFrameSize * 8 == width * height); + switch (filter) + { + case CORE_DMD_PWM_FILTER_DE: + { + static const UINT16 fir_473_15_4[] = { 47, 453, 453, 47 }; + dmd_state->nFrames = 4; + dmd_state->fir_weights = fir_473_15_4; + dmd_state->fir_sum = 1000; + dmd_state->fir_size = 4; + } + break; + case CORE_DMD_PWM_FILTER_GTS3: + { + static const UINT16 fir_376_15_24[] = { 8, 19, 44, 91, 168, 274, 405, 552, + 699, 830, 928, 981, 981, 928, 830, 699, + 552, 405, 274, 168, 91, 44, 19, 8 }; + dmd_state->nFrames = 24; + dmd_state->fir_weights = fir_376_15_24; + dmd_state->fir_sum = 9998; + dmd_state->fir_size = 24; + } + break; + default: + assert(0); // Unsupported filter + } + dmd_state->rawFrames = malloc(dmd_state->nFrames * dmd_state->rawFrameSize); + memset(dmd_state->rawFrames, 0, dmd_state->nFrames * dmd_state->rawFrameSize); + dmd_state->shadedFrame = malloc(dmd_state->width * dmd_state->height * sizeof(UINT16)); + memset(dmd_state->shadedFrame, 0, dmd_state->width * dmd_state->height * sizeof(UINT16)); + dmd_state->nextFrame = 0; +} + +void core_dmd_pwm_exit(core_tDMDPWMState* dmd_state) { + free(dmd_state->rawFrames); + dmd_state->rawFrames = NULL; + free(dmd_state->shadedFrame); + dmd_state->shadedFrame = NULL; +} + +void core_dmd_submit_frame(core_tDMDPWMState* dmd_state, const UINT8* frame) { + memcpy(dmd_state->rawFrames + dmd_state->nextFrame * dmd_state->rawFrameSize, frame, dmd_state->rawFrameSize); + dmd_state->nextFrame = (dmd_state->nextFrame + 1) % dmd_state->nFrames; +} + +void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { + int ii, jj, kk; + + // Apply low pass filter over stored frames + memset(dmd_state->shadedFrame, 0, dmd_state->width * dmd_state->height * sizeof(UINT16)); + for (ii = 0; ii < dmd_state->fir_size; ii++) { + const UINT16 frame_weight = dmd_state->fir_weights[ii]; + UINT16* line = dmd_state->shadedFrame; + UINT8* frameData = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 1) + (dmd_state->nFrames - ii)) % dmd_state->nFrames) * dmd_state->rawFrameSize; + for (jj = 0; jj < dmd_state->rawFrameSize; jj++) { + UINT8 data = *frameData++; + for (kk = 0; kk < 8; kk++) { + (*line++) += frame_weight * (UINT16)(data>>7); + data <<= 1; + } + } + } + + // Scale down to final shades (note that precision matters and is needed to avoid flickering) + UINT16* line = dmd_state->shadedFrame; + for (ii = 1; ii <= dmd_state->height; ii++) + for (jj = 0; jj < dmd_state->width; jj++) { + UINT16 data = (*line++); + coreGlobals.dotCol[ii][jj] = (UINT8)((255 * (unsigned int)data) / dmd_state->fir_sum); + } +} + + // // // diff --git a/src/wpc/core.h b/src/wpc/core.h index b19ad8a27..917f66cfc 100644 --- a/src/wpc/core.h +++ b/src/wpc/core.h @@ -598,6 +598,27 @@ extern void core_write_masked_pwm_output_8b(int startIndex, UINT8 bitStates, UIN extern void core_write_pwm_output_lamp_matrix(int startIndex, UINT8 columns, UINT8 rows, int nCols); INLINE void core_zero_cross(void) { coreGlobals.lastACZeroCrossTimeStamp = timer_get_time(); } +/*-- DMD PWM integration --*/ +typedef struct { + int width; // DMD width + int height; // DMD height + int rawFrameSize; // Size of a raw DMD frame in bytes (width * height / 8) + UINT8* rawFrames; // Buffer for raw frames + UINT16* shadedFrame; // Shaded frame computed from raw frames + int nextFrame; // Position in circular buffer to store next raw frame + int nFrames; // Number of frames to store and consider to create shades (depends on hardware refresh frequency and used PWM patterns) + int fir_size; // Selected filter (depends on hardware refresh frequency and number of stored frames) + UINT16* fir_weights; // Selected filter (depends on hardware refresh frequency and number of stored frames) + UINT16 fir_sum; // Selected filter (depends on hardware refresh frequency and number of stored frames) +} core_tDMDPWMState; +#define CORE_DMD_PWM_FILTER_DE 0 // Data East: 473Hz refresh rate / 15Hz low pass filter / 2 frames PWM pattern +#define CORE_DMD_PWM_FILTER_GTS3 1 // GTS3: 376Hz refresh rate / 15Hz low pass filter / 1,3,6,8,10 frames PWM pattern +#define CORE_DMD_PWM_FILTER_WPC 2 // WPC: 122Hz refresh rate / 15Hz low pass filter / 3 frames PWM pattern +extern void core_dmd_pwm_init(core_tDMDPWMState* dmd_state, const int width, const int height, const int filter); +extern void core_dmd_pwm_exit(core_tDMDPWMState* dmd_state); +extern void core_dmd_submit_frame(core_tDMDPWMState* dmd_state, const UINT8* frame); +extern void core_dmd_update_pwm(core_tDMDPWMState* dmd_state); + extern void core_sound_throttle_adj(int sIn, int *sOut, int buffersize, double samplerate); /*-- nvram handling --*/ diff --git a/src/wpc/dedmd.c b/src/wpc/dedmd.c index fa75dfec9..54821fb1b 100644 --- a/src/wpc/dedmd.c +++ b/src/wpc/dedmd.c @@ -13,12 +13,14 @@ static struct { struct sndbrdData brdData; int cmd, ncmd, busy, status, ctrl, bank; - UINT32 *framedata; // dmd16 stuff + UINT32* framedata; UINT32 hv5408, hv5408s, hv5308, hv5308s, hv5222, lasthv5222; int blnk, rowdata, rowclk, frame; - int laststat; + // dmd32 frame shading + int frame_counter; + core_tDMDPWMState pwm_state; } dmdlocals; static UINT16 *dmd64RAM; @@ -32,15 +34,13 @@ static READ_HANDLER(dmd_busy_r) { return dmdlocals.busy; } /*Data East, Sega, Stern 128x32 DMD Handling*/ /*------------------------------------------*/ #define DMD32_BANK0 2 -#define DMD32_FIRQFREQ_HACK 86.20689655172414 // real DE HW 78.07 (measured on LW3), Whitestar 77.77, but this leads to (at least?) LW3 and R&B and SW glitching, thus use the old/working 80Hz * the changes to IRQ freq in Sys11 for these (and Aaron Spelling & Michael Jordan, //!! although (at least) these 2 show the display version screen from time to time) -#define DMD32_FIRQFREQ_DE 78.07 // real DE HW (measured on LW3) -#define DMD32_FIRQFREQ_SE 77.77 // real Whitestar HW static WRITE_HANDLER(dmd32_ctrl_w); static void dmd32_init(struct sndbrdData *brdData); +static void dmd32_exit(int boardNo); const struct sndbrdIntf dedmd32Intf = { - NULL, dmd32_init, NULL, NULL,NULL, + NULL, dmd32_init, dmd32_exit, NULL,NULL, dmd_data_w, dmd_busy_r, dmd32_ctrl_w, dmd_status_r, SNDBRD_NOTSOUND }; @@ -71,27 +71,32 @@ static MEMORY_WRITE_START(dmd32_writemem) { 0x4001, 0xffff, MWA_NOP }, MEMORY_END -MACHINE_DRIVER_START(de_dmd32_hack) - MDRV_CPU_ADD(M6809, 2000000) // 8000000/4 - MDRV_CPU_MEMORY(dmd32_readmem, dmd32_writemem) - MDRV_CPU_PERIODIC_INT(dmd32_firq, DMD32_FIRQFREQ_HACK) - MDRV_INTERLEAVE(50) -MACHINE_DRIVER_END - MACHINE_DRIVER_START(de_dmd32) MDRV_CPU_ADD(M6809, 2000000) // 8000000/4 MDRV_CPU_MEMORY(dmd32_readmem, dmd32_writemem) - MDRV_CPU_PERIODIC_INT(dmd32_firq, DMD32_FIRQFREQ_DE) MDRV_INTERLEAVE(50) MACHINE_DRIVER_END MACHINE_DRIVER_START(se_dmd32) MDRV_CPU_ADD(M6809, 2000000) // 8000000/4 MDRV_CPU_MEMORY(dmd32_readmem, dmd32_writemem) - MDRV_CPU_PERIODIC_INT(dmd32_firq, DMD32_FIRQFREQ_SE) MDRV_INTERLEAVE(50) MACHINE_DRIVER_END +static void dmd32_vblank(int which) { + //static double prev; printf("DMD VBlank %8.5fms => %8.5fHz for 2 frames so %8.5fHz\n", timer_get_time() - prev, 1. / (timer_get_time() - prev), 2. / (timer_get_time() - prev)); prev = timer_get_time(); + // Store 2 next rasterized frame, as the CRTC is setup to render 2 contiguous full frames for each VBLANK + core_dmd_submit_frame(&dmdlocals.pwm_state, ((UINT8*)dmd32RAM) + ((crtc6845_start_address_r(0) & 0x0100) << 2)); + if (crtc6845_get_rasterized_height(0) > 32) + core_dmd_submit_frame(&dmdlocals.pwm_state, ((UINT8*)dmd32RAM) + ((crtc6845_start_address_r(0) & 0x0100) << 2) + 0x200); + // FIRQ is generated by the custom PAL16R4 chip. It is guessed to be a simple divider to perform PWM shading as it nearly matches real hardware measures (so every 6 rasterized frames) + // This leads to 78.89Hz (473,37Hz core rasterization FPS, /2 to give CRTC6845 VSYNC, /3 by PAL to generate FIRQ) + // Previous implementation used real hardware measures of 78.07 measured on LW3, and 77.77 measured on Whitestar, and a hacked 86.20689655172414 Hz to account for glitches for LW3/AS/R&B/SW. + dmdlocals.frame_counter = (dmdlocals.frame_counter + 1) % 3; + if (dmdlocals.frame_counter == 0) + cpu_set_irq_line(dmdlocals.brdData.cpuNo, M6809_FIRQ_LINE, HOLD_LINE); +} + static void dmd32_init(struct sndbrdData *brdData) { memset(&dmdlocals, 0, sizeof(dmdlocals)); dmdlocals.brdData = *brdData; @@ -99,8 +104,15 @@ static void dmd32_init(struct sndbrdData *brdData) { /* copy last 16K of ROM into last 16K of CPU region*/ memcpy(memory_region(DE_DMD32CPUREGION) + 0x8000, memory_region(DE_DMD32ROMREGION) + memory_region_length(DE_DMD32ROMREGION)-0x8000,0x8000); - //Init 6845 + // Init 6845 crtc6845_init(0); + crtc6845_set_vsync(0, 2000000 /* 8000000/4 from 6809 E clock output */, dmd32_vblank); + // Init PWM shading + core_dmd_pwm_init(&dmdlocals.pwm_state, 128, 32, CORE_DMD_PWM_FILTER_DE); +} + +static void dmd32_exit(int boardNo) { + core_dmd_pwm_exit(&dmdlocals.pwm_state); } static WRITE_HANDLER(dmd32_ctrl_w) { @@ -137,13 +149,9 @@ static INTERRUPT_GEN(dmd32_firq) { } PINMAME_VIDEO_UPDATE(dedmd32_update) { - const UINT8 *RAM = ((UINT8 *)dmd32RAM) + ((crtc6845_start_address_r(0) & 0x0100)<<2); - const UINT8 *RAM2 = RAM + 0x200; - int ii; - #ifdef PROC_SUPPORT if (coreGlobals.p_rocEn) { - /* Whitestar games drive 4 colors using 2 subframes, which the P-ROC + /* Whitestar games drive 4 colors using 2 subframes, which the P-ROC has 4 subframes for up to 16 colors. Experimentation has showed using P-ROC subframe 2 and 3 provides a pretty good color match. */ const int procSubFrame0 = 2; @@ -153,8 +161,9 @@ PINMAME_VIDEO_UPDATE(dedmd32_update) { procClearDMD(); /* Fill the P-ROC subframes from the video RAM */ - procFillDMDSubFrame(procSubFrame0, RAM, 0x200); - procFillDMDSubFrame(procSubFrame1, RAM2, 0x200); + const UINT8* RAM = ((UINT8*)dmd32RAM) + ((crtc6845_start_address_r(0) & 0x0100) << 2); + procFillDMDSubFrame(procSubFrame0, RAM , 0x200); + procFillDMDSubFrame(procSubFrame1, RAM + 0x200, 0x200); /* Each byte is reversed in the video RAM relative to the bit order the P-ROC expects. So reverse each byte. */ @@ -166,25 +175,7 @@ PINMAME_VIDEO_UPDATE(dedmd32_update) { } #endif - for (ii = 1; ii <= 32; ii++) { - UINT8 *line = &coreGlobals.dotCol[ii][0]; - int jj; - for (jj = 0; jj < (128/8); jj++) { - const UINT8 intens1 = 2*(*RAM & 0x55) + (*RAM2 & 0x55); - const UINT8 intens2 = (*RAM & 0xaa) + (*RAM2 & 0xaa)/2; - *line++ = (intens2>>6) & 0x03; - *line++ = (intens1>>6) & 0x03; - *line++ = (intens2>>4) & 0x03; - *line++ = (intens1>>4) & 0x03; - *line++ = (intens2>>2) & 0x03; - *line++ = (intens1>>2) & 0x03; - *line++ = (intens2) & 0x03; - *line++ = (intens1) & 0x03; - RAM++; RAM2++; - } - *line = 0; - } - + core_dmd_update_pwm(&dmdlocals.pwm_state); video_update_core_dmd(bitmap, cliprect, layout); return 0; } @@ -305,10 +296,8 @@ PINMAME_VIDEO_UPDATE(dedmd64_update) { /*Data East 128x16 DMD Handling*/ /*------------------------------*/ #define DMD16_BANK0 2 -// Steve said he measured this to 2000 on his game -// but that sometimes causes a new NMI to be triggered before the -// previous one is finished and it leads to stack overflow -#define DMD16_NMIFREQ 2000 +// Steve said he measured this to 2000 on his game but that sometimes causes a new NMI to be triggered before the previous one is finished and it leads to stack overflow +#define DMD16_NMIFREQ (4000000./2048.) // Main CPU clock divided by a 14 bit binary counter, NMI being driven by a 14bit binary counter value masked by 0x0F00 (U9 - 4020) /* HC74 bits */ #define BUSY_CLR 0x01 #define BUSY_SET 0x02 diff --git a/src/wpc/dedmd.h b/src/wpc/dedmd.h index 5afe02243..819c38fc1 100644 --- a/src/wpc/dedmd.h +++ b/src/wpc/dedmd.h @@ -8,7 +8,6 @@ #define DE_DMD32CPUNO 2 #define DE_DMD32CPUREGION (REGION_CPU1 + DE_DMD32CPUNO) #define DE_DMD32ROMREGION (REGION_GFX1 + DE_DMD32CPUNO) -extern MACHINE_DRIVER_EXTERN(de_dmd32_hack); extern MACHINE_DRIVER_EXTERN(de_dmd32); extern MACHINE_DRIVER_EXTERN(se_dmd32); extern PINMAME_VIDEO_UPDATE(dedmd32_update); diff --git a/src/wpc/degames.c b/src/wpc/degames.c index f7e460745..3a709c674 100644 --- a/src/wpc/degames.c +++ b/src/wpc/degames.c @@ -706,7 +706,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND #define input_ports_lw3 input_ports_des11 -CORE_GAMEDEF(lw3,208,"Lethal Weapon 3 (2.08)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_GAMEDEF(lw3,208,"Lethal Weapon 3 (2.08)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_208p,"lw3cpuu.208",CRC(a3041f8a) SHA1(3c5b8525b8e9b924590648429c56aaf97adee460)) DE_DMD32ROM44( "lw3drom1.a26",CRC(44a4cf81) SHA1(c7f3e3d5fbe930650e48423c8ba0ac484ce0640c), @@ -715,7 +715,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae "lw3u17_vm.dat",CRC(5168dbbd) SHA1(e5f91650e613350c542ac93d0d4be64b25333186), "lw3u21_vm.dat",CRC(7ec96750) SHA1(13e41833d43396e370b817928618f72f928d9ba0)) DE_ROMEND -CORE_CLONEDEF(lw3,208p,208,"Lethal Weapon 3 (2.08p, Voices Mod)",2013,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,208p,208,"Lethal Weapon 3 (2.08p, Voices Mod)",2013,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_207,"lw3gc5.207",CRC(27aeaea9) SHA1(f8c40cbc37edac20187ac880be281dd45d8ad614)) DE_DMD32ROM44( "lw3drom1.a26",CRC(44a4cf81) SHA1(c7f3e3d5fbe930650e48423c8ba0ac484ce0640c), @@ -724,7 +724,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae4 "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,207,208,"Lethal Weapon 3 (2.07 Canadian)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,207,208,"Lethal Weapon 3 (2.07 Canadian)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_205,"lw3gc5.205",CRC(5ad8ff4a) SHA1(6a01a2195543c0c57ce4ce78703c91500835a2da)) DE_DMD32ROM44( "lw3dsp1.205",CRC(9dfeffb4) SHA1(f62f2a884da68b4dbfe7da071058dc8cd1766c36), @@ -733,7 +733,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae4 "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,205,208,"Lethal Weapon 3 (2.05)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,205,208,"Lethal Weapon 3 (2.05)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_e204,"lw3cpue.204",CRC(33cb9197) SHA1(c6b25dfd93bb5c425a606ae21f757a87a07dc320)) DE_DMD32ROM44( "lw3dsp1a.202",CRC(4920f84f) SHA1(928e4aefdcf9462201001f4ac03d56a0cda25ec1), @@ -742,7 +742,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,e204,208,"Lethal Weapon 3 (2.04 English)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,e204,208,"Lethal Weapon 3 (2.04 English)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_203,"lw3cpuu.203",CRC(0cfa38d4) SHA1(11d2e101a574c2dfec49ec701f480173b84c842e)) DE_DMD32ROM44( "lw3dsp1.204",CRC(1ba79363) SHA1(46d489a1190533c73370acd8a48cef60d12f87ce), @@ -751,7 +751,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae4 "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,203,208,"Lethal Weapon 3 (2.03)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,203,208,"Lethal Weapon 3 (2.03)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_200,"lw3cpu.200",CRC(ddb6e7a7) SHA1(d48309e1984ef9a7682dfde190cf457632044657)) DE_DMD32ROM44( "lw3dsp1.204",CRC(1ba79363) SHA1(46d489a1190533c73370acd8a48cef60d12f87ce), @@ -760,7 +760,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae4 "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,200,208,"Lethal Weapon 3 (2.00)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,200,208,"Lethal Weapon 3 (2.00)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_300,"LW3CPUU.300",CRC(1ebcf869) SHA1(f708635bd3dedca0979a31de4151a2569e040639)) DE_DMD32ROM44( "lw3drom1.300",CRC(38f0ab03) SHA1(6ab549c6388aacedadd5a16e937ec0612475a0ac), @@ -769,7 +769,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae4 "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,300,208,"Lethal Weapon 3 (3.00 unofficial MOD)",2020,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,300,208,"Lethal Weapon 3 (3.00 unofficial MOD)",2020,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(lw3_301,"LW3CPUU.301",CRC(e6a44d10) SHA1(0da68cfaa2667bc34493ae7ba703c06b60171989)) DE_DMD32ROM44( "lw3drom1.300",CRC(38f0ab03) SHA1(6ab549c6388aacedadd5a16e937ec0612475a0ac), @@ -778,7 +778,7 @@ DE2S_SOUNDROM022( "lw3u7.dat" ,CRC(ba845ac3) SHA1(bb50413ace1885870cb3817edae4 "lw3u17.dat" ,CRC(e34cf2fc) SHA1(417c83ded6637f891c8bb42b32d6898c90a0e5cf), "lw3u21.dat" ,CRC(82bed051) SHA1(49ddc4190762d9b473fda270e0d6d88a4422d5d7)) DE_ROMEND -CORE_CLONEDEF(lw3,301,208,"Lethal Weapon 3 (3.01 unofficial MOD)",2020,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(lw3,301,208,"Lethal Weapon 3 (3.01 unofficial MOD)",2020,"Data East",de_mDEDMD32S2A,0) /*------------------------------------------------------------- / Aaron Spelling - CPU Rev 3 /DMD Type 2 512K Rom - 64K CPU Rom @@ -792,7 +792,7 @@ DE2S_SOUNDROM144( "assndu7.bin" ,CRC(f0414a0d) SHA1(b1f940be05426a39f4e5ea08 "assndu21.bin",CRC(7d69e917) SHA1(73e21e65bc194c063933288cb617127b41593466)) DE_ROMEND #define input_ports_aar input_ports_des11 -CORE_GAMEDEF(aar,101,"Aaron Spelling (1.01)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_GAMEDEF(aar,101,"Aaron Spelling (1.01)",1992,"Data East",de_mDEDMD32S2A,0) /*------------------------------------------------------------- / Michael Jordan - CPU Rev 3 /DMD Type 2 512K Rom - 64K CPU Rom @@ -805,7 +805,7 @@ DE2S_SOUNDROM144( "MJsndu7.bin" ,CRC(a32237f5) SHA1(0fc106429af320c4a30a99c67 "MJsndu21.bin",CRC(addfe20e) SHA1(3a6862640f81493da1beddca11011090d8b7cab0)) DE_ROMEND #define input_ports_mj input_ports_des11 -CORE_GAMEDEF(mj,130,"Michael Jordan (1.30)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_GAMEDEF(mj,130,"Michael Jordan (1.30)",1992,"Data East",de_mDEDMD32S2A,0) /*------------------------------------------------------------- / Star Wars - CPU Rev 3 /DMD Type 2 512K Rom - 64K CPU Rom @@ -818,7 +818,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND #define input_ports_stwr input_ports_des11 -CORE_GAMEDEF(stwr,104,"Star Wars (1.04 20th Anniversary)",2012,"Data East",de_mDEDMD32S2A_hack,0) +CORE_GAMEDEF(stwr,104,"Star Wars (1.04 20th Anniversary)",2012,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_106,"starcpua.106",CRC(35d3cfd9) SHA1(14d8960f3657d7cd977b0a749e995aadb3fd4c7c)) DE_DMD32ROM8x( "sw4mrom.a15",CRC(00c87952) SHA1(cd2f491f03fcb3e3ceff7ee7f678aa1957a5d14b)) @@ -826,7 +826,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,106,104,"Star Wars (1.06 20th Anniversary)",2016,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,106,104,"Star Wars (1.06 20th Anniversary)",2016,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_107s,"starcpua.107",CRC(1a801b7e) SHA1(fef567126dff87a2cb31401b029c3050438072b7)) DE_DMD32ROM8x( "sw4mrom.s15",CRC(158867b9) SHA1(45a0f4d26c21e2259aeb2a726a1eac23744213a2)) @@ -834,7 +834,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,107s,104,"Star Wars (1.07 20th Anniversary, Spanish)",2016,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,107s,104,"Star Wars (1.07 20th Anniversary, Spanish)",2016,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_107,"starcpua.107",CRC(1a801b7e) SHA1(fef567126dff87a2cb31401b029c3050438072b7)) DE_DMD32ROM8x( "sw4mrom.a15",CRC(00c87952) SHA1(cd2f491f03fcb3e3ceff7ee7f678aa1957a5d14b)) @@ -842,7 +842,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,107,104,"Star Wars (1.07 20th Anniversary)",2016,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,107,104,"Star Wars (1.07 20th Anniversary)",2016,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_103,"starcpua.103",CRC(318085ca) SHA1(7c35bdee52e8093fe05f0624615baabe559a1917)) DE_DMD32ROM8x( "sw4mrom.a15",CRC(00c87952) SHA1(cd2f491f03fcb3e3ceff7ee7f678aa1957a5d14b)) @@ -850,7 +850,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,103,104,"Star Wars (1.03, Display 1.05)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,103,104,"Star Wars (1.03, Display 1.05)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_a14,"starcpua.103",CRC(318085ca) SHA1(7c35bdee52e8093fe05f0624615baabe559a1917)) DE_DMD32ROM44( "swrom1.a14", CRC(4d577828) SHA1(8b1f302621fe2ee13a067b9c97e3dc33f4519cea), @@ -859,7 +859,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,a14,104,"Star Wars (1.03, Display 1.04)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,a14,104,"Star Wars (1.03, Display 1.04)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_a046,"starcpua.103",CRC(318085ca) SHA1(7c35bdee52e8093fe05f0624615baabe559a1917)) DE_DMD32ROM44( "swrom1.a046",CRC(5ceac219) SHA1(76b7acf378f83bacf6c4adb020d6e544eacbac7a), @@ -868,7 +868,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,a046,104,"Star Wars (1.03, Display A0.46)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,a046,104,"Star Wars (1.03, Display A0.46)",1992,"Data East",de_mDEDMD32S2A,0) /* USA CPU 1.02 (11/20/92) */ DE_ROMSTARTx0(stwr_102,"starcpua.102",CRC(8b9d90d6) SHA1(2fb7594e6f4aae1dc3a07192546fabd2901acbed)) @@ -877,7 +877,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,102,104,"Star Wars (1.02)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,102,104,"Star Wars (1.02)",1992,"Data East",de_mDEDMD32S2A,0) /* England CPU 1.02 (11/20/92) */ DE_ROMSTARTx0(stwr_e12,"starcpue.102",CRC(b441abd3) SHA1(42cab6e16be8e25a68b2db30f53ba516bbb8741d)) @@ -886,7 +886,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,e12,104,"Star Wars (1.02 English)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,e12,104,"Star Wars (1.02 English)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_101,"starcpu.101",CRC(6efc7b14) SHA1(f669669fbd8733d06b386ea352fdb2041bf98362)) DE_DMD32ROM44( "stardisp_u14.102", CRC(f8087364) SHA1(4cd66b72cf430018cfb7ac8306b96a8499d41896), @@ -895,7 +895,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,101,104,"Star Wars (1.01)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,101,104,"Star Wars (1.01)",1992,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(stwr_g11,"starcpug.101",CRC(c74b4576) SHA1(67db9294cd802be8d62102fe756648f750821960)) DE_DMD32ROM8x( "swdsp_g.102",CRC(afdfbfc4) SHA1(1c3cd90b9cd4f88ee2b556abef863a0ae9a10056)) @@ -903,7 +903,7 @@ DE2S_SOUNDROM042( "s-wars.u7" ,CRC(cefa19d5) SHA1(7ddf9cc85ab601514305bc460 "s-wars.u17" ,CRC(7950a147) SHA1(f5bcd5cf6b35f9e4f14d62b084495c3a743d92a1), "s-wars.u21" ,CRC(7b08fdf1) SHA1(489d21a10e97e886f948d81dedd7f8de3acecd2b)) DE_ROMEND -CORE_CLONEDEF(stwr,g11,104,"Star Wars (1.01 German)",1992,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(stwr,g11,104,"Star Wars (1.01 German)",1992,"Data East",de_mDEDMD32S2A,0) /*------------------------------------------------------------- / The Adventures of Rocky and Bullwinkle and Friends - CPU Rev 3b /DMD Type 2 512K Rom - 64K CPU Rom @@ -916,7 +916,7 @@ DE2S_SOUNDROM142( "rab.u7" ,CRC(b232e630) SHA1(880fffc395d7c24bdea4e7e8000afba "rab.u21" ,CRC(3de1b375) SHA1(a48bb80483ca03cd7c3bf0b5f2930a6ee9cc448d)) DE_ROMEND #define input_ports_rab input_ports_des11 -CORE_GAMEDEF(rab,320,"Adventures of Rocky and Bullwinkle and Friends, The (3.20)",1993,"Data East",de_mDEDMD32S2A_hack,0) +CORE_GAMEDEF(rab,320,"Adventures of Rocky and Bullwinkle and Friends, The (3.20)",1993,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(rab_130,"rabcpua.130",CRC(f59b1a53) SHA1(046cd0eaee6e646286f3dfa73eeacfd93c2be273)) DE_DMD32ROM8x( "rbdspa.130",CRC(b6e2176e) SHA1(9ccbb30dc0f386fcf5e5255c9f80c720e601565f)) @@ -924,7 +924,7 @@ DE2S_SOUNDROM142( "rab.u7" ,CRC(b232e630) SHA1(880fffc395d7c24bdea4e7e8000afba "rab.u17" ,CRC(7f2b53b8) SHA1(fd4f4ed1ed343069ffc534fe4b20026fe7403220), "rab.u21" ,CRC(3de1b375) SHA1(a48bb80483ca03cd7c3bf0b5f2930a6ee9cc448d)) DE_ROMEND -CORE_CLONEDEF(rab,130,320,"Adventures of Rocky and Bullwinkle and Friends, The (1.30)",1993,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(rab,130,320,"Adventures of Rocky and Bullwinkle and Friends, The (1.30)",1993,"Data East",de_mDEDMD32S2A,0) DE_ROMSTARTx0(rab_103,"rabcpu.103",CRC(d5fe3184) SHA1(dc1ca938f15240d1c15ee5724d29a3538418f8de)) DE_DMD32ROM8x( "rabdspsp.103",CRC(02624948) SHA1(069ef69d6ce193d73954935b378230c05b83b8fc)) @@ -932,7 +932,7 @@ DE2S_SOUNDROM142( "rab.u7" ,CRC(b232e630) SHA1(880fffc395d7c24bdea4e7e8000afba "rab.u17" ,CRC(7f2b53b8) SHA1(fd4f4ed1ed343069ffc534fe4b20026fe7403220), "rab.u21" ,CRC(3de1b375) SHA1(a48bb80483ca03cd7c3bf0b5f2930a6ee9cc448d)) DE_ROMEND -CORE_CLONEDEF(rab,103,320,"Adventures of Rocky and Bullwinkle and Friends, The (1.03 Spanish)",1993,"Data East",de_mDEDMD32S2A_hack,0) +CORE_CLONEDEF(rab,103,320,"Adventures of Rocky and Bullwinkle and Friends, The (1.03 Spanish)",1993,"Data East",de_mDEDMD32S2A,0) /*------------------------------------------------------------- / Jurassic Park - CPU Rev 3b /DMD Type 2 512K Rom - 64K CPU Rom diff --git a/src/wpc/gts3.c b/src/wpc/gts3.c index caa29459f..dd1bbd0f9 100644 --- a/src/wpc/gts3.c +++ b/src/wpc/gts3.c @@ -25,9 +25,6 @@ #include "gts3dmd.h" #include "gts80s.h" -UINT8 DMDFrames [GTS3DMD_FRAMES][0x200]; -UINT8 DMDFrames2[GTS3DMD_FRAMES][0x200]; //2nd DMD Display for Strikes N Spares - #define GTS3_INTERFACE_UPD_PER_FRAME 1 /* interface update frequency per 60Hz frame */ #define GTS3_IRQFREQ 1500 /* IRQ Frequency (Guessed) */ #define GTS3_ALPHANMIFREQ 1000 /* Alpha NMI Frequency (Guessed)*/ @@ -584,7 +581,6 @@ static MACHINE_INIT(gts3b) { static void gts3dmd_init(void) { memset(>S3locals, 0, sizeof(GTS3locals)); memset(>S3_dmdlocals[0], 0, sizeof(GTS3_DMDlocals)); - memset(&DMDFrames, 0, sizeof(DMDFrames)); via_config(0, &via_0_interface); via_config(1, &via_1_interface); @@ -594,6 +590,9 @@ static void gts3dmd_init(void) { crtc6845_init(0); crtc6845_set_vsync(0, 3579545. / 2., dmd_vblank); + // Setup PWM shading + core_dmd_pwm_init(>S3_dmdlocals[0].pwm_state, 128, 32, CORE_DMD_PWM_FILTER_GTS3); + /*DMD*/ /*copy last 32K of ROM into last 32K of CPU region*/ /*Setup ROM Swap so opcode will work*/ @@ -726,13 +725,15 @@ static MACHINE_INIT(gts3dmd) { static MACHINE_INIT(gts3dmd2) { gts3dmd_init(); memset(>S3_dmdlocals[1], 0, sizeof(GTS3_DMDlocals)); - memset(&DMDFrames2, 0, sizeof(DMDFrames2)); GTS3_dmdlocals[0].has2DMD = 1; //Init 2nd 6845 crtc6845_init(1); crtc6845_set_vsync(1, 3579545. / 2., dmd_vblank); + // Setup PWM shading + core_dmd_pwm_init(>S3_dmdlocals[1].pwm_state, 128, 32, CORE_DMD_PWM_FILTER_GTS3); + /*copy last 32K of DMD ROM into last 32K of CPU region*/ if (memory_region(GTS3_MEMREG_DCPU2)) { memcpy(memory_region(GTS3_MEMREG_DCPU2) + 0x8000, @@ -744,6 +745,17 @@ static MACHINE_STOP(gts3) { sndbrd_0_exit(); } +static MACHINE_STOP(gts3dmd) { + sndbrd_0_exit(); + core_dmd_pwm_exit(>S3_dmdlocals[0].pwm_state); +} + +static MACHINE_STOP(gts3dmd2) { + sndbrd_0_exit(); + core_dmd_pwm_exit(>S3_dmdlocals[0].pwm_state); + core_dmd_pwm_exit(>S3_dmdlocals[1].pwm_state); +} + /*Solenoids - Need to verify correct solenoid # here!*/ static WRITE_HANDLER(solenoid_w) { @@ -947,12 +959,8 @@ static WRITE_HANDLER(dmd_aux) { //Update the DMD Frames during the DMD VBLANK generated by the CRTC6845 - Supports 2 DMD Displays static void dmd_vblank(int which) { int offset = crtc6845_start_address_r(which) >> 2; - if (which) - memcpy(DMDFrames2[GTS3_dmdlocals[1].nextDMDFrame],memory_region(GTS3_MEMREG_DCPU2)+0x1000+offset,0x200); - else - memcpy(DMDFrames[GTS3_dmdlocals[0].nextDMDFrame],memory_region(GTS3_MEMREG_DCPU1)+0x1000+offset,0x200); + core_dmd_submit_frame(>S3_dmdlocals[which].pwm_state, memory_region(which ? GTS3_MEMREG_DCPU2 : GTS3_MEMREG_DCPU1) + 0x1000 + offset); cpu_set_nmi_line(which ? GTS3_DCPUNO2 : GTS3_DCPUNO, PULSE_LINE); - GTS3_dmdlocals[which].nextDMDFrame = (GTS3_dmdlocals[which].nextDMDFrame + 1) % GTS3DMD_FRAMES; } /* Printer connector */ @@ -1134,7 +1142,7 @@ MACHINE_DRIVER_START(gts3_21) MDRV_IMPORT_FROM(gts3) MDRV_CPU_ADD(M65C02, 3579545./2.) MDRV_CPU_MEMORY(GTS3_dmdreadmem, GTS3_dmdwritemem) - MDRV_CORE_INIT_RESET_STOP(gts3dmd,NULL,gts3) + MDRV_CORE_INIT_RESET_STOP(gts3dmd,NULL,gts3dmd) MDRV_IMPORT_FROM(gts80s_s3) MACHINE_DRIVER_END @@ -1154,7 +1162,7 @@ MACHINE_DRIVER_START(gts3_22) MDRV_CORE_INIT_RESET_STOP(gts3dmd,NULL,gts3) MDRV_CPU_ADD(M65C02, 3579545./2.) MDRV_CPU_MEMORY(GTS3_dmdreadmem2, GTS3_dmdwritemem2) - MDRV_CORE_INIT_RESET_STOP(gts3dmd2,NULL,gts3) + MDRV_CORE_INIT_RESET_STOP(gts3dmd2,NULL,gts3dmd2) MDRV_SOUND_ADD(OKIM6295, sns_okim6295_interface) MDRV_DIAGNOSTIC_LEDH(3) MACHINE_DRIVER_END diff --git a/src/wpc/gts3.h b/src/wpc/gts3.h index b10134427..1ac96eb2c 100644 --- a/src/wpc/gts3.h +++ b/src/wpc/gts3.h @@ -227,7 +227,7 @@ typedef struct { UINT8 status2; // bool UINT8 dstrb; // bool UINT8 dmd_visible_addr; - UINT8 nextDMDFrame; + core_tDMDPWMState pwm_state; } GTS3_DMDlocals; typedef struct { diff --git a/src/wpc/gts3dmd.c b/src/wpc/gts3dmd.c index ccaed7fe7..dbdaab65a 100644 --- a/src/wpc/gts3dmd.c +++ b/src/wpc/gts3dmd.c @@ -3,22 +3,17 @@ #include "gts3.h" #include "gts3dmd.h" -extern UINT8 DMDFrames [GTS3DMD_FRAMES][0x200]; -extern UINT8 DMDFrames2[GTS3DMD_FRAMES][0x200]; extern GTS3_DMDlocals GTS3_dmdlocals[2]; -// Shaded frame computed from stored PWMed DMD frames -UINT16 GTS3_accumulatedFrame[32][128]; - #if defined(VPINMAME) || defined(LIBPINMAME) -extern UINT8 g_raw_gtswpc_dmd[GTS3DMD_FRAMES*0x200]; +extern UINT8 g_raw_gtswpc_dmd[]; extern UINT32 g_raw_gtswpc_dmdframes; #endif // GTS3 hardware creates shades by quickly switching frames (PWM). // It uses pattern of 3, 6, 8 or 10 frames at 376Hz to create the // PWM pattern. We store the last 24 frames and apply a FIR low pass -// filter computed with GNU Octave (script is given below). +// filter computed with GNU Octave (script is given in core.c). // // Previous version had an optimized implementation, storing as little frames as // possible for each GTS3 game (see commit 9b9ac9a5c2bfedac13ca382ff6669837882c129d). @@ -26,74 +21,22 @@ extern UINT32 g_raw_gtswpc_dmdframes; // This lead to better performance since less frames were accumulated but had 2 side effects: // - there were some occasional residual flickers, // - DMD luminance were not fully coherent between GTS3 games (some 4 shades, some other 5 shades). - -/* The following script allows to compute and display the filter applied to some PWM pattern in GNU Octave: -pkg load signal -fc = 15; % Cut-off frequency (Hz) -fs = 376; % Sampling rate (Hz) -data=[repmat([0;0;1],100,1),repmat([0;0;0;1;1;1],50,1),repmat([0;0;0;0;1;1;1;1;1;1],30,1),repmat([0;0;0;0;0;0;0;0;0;1],30,1)]; -b = fir1(23, fc/(fs/2)); -filtered = filter(b,1,data); -clf -subplot ( columns ( filtered ), 1, 1) -plot(filtered(:,1),";1/3 - 3;") -subplot ( columns ( filtered ), 1, 2 ) -plot(filtered(:,2),";1/2 - 6;") -subplot ( columns ( filtered ), 1, 3 ) -plot(filtered(:,3),";6/10 - 10;") -subplot ( columns ( filtered ), 1, 4 ) -plot(filtered(:,4),";1/10 - 10;") -bp = 10000 * b; % scaled filter used for PinMame integer math -*/ - int gts3_dmd128x32(int which, struct mame_bitmap* bitmap, const struct rectangle* cliprect, const struct core_dispLayout* layout) { - static const UINT16 fir_weights[] = { 8, 19, 44, 91, 168, 274, 405, 552, // Octave: b = fir1(23, fc/(fs/2)); with fc = 15; and fs = 376; - 699, 830, 928, 981, 981, 928, 830, 699, - 552, 405, 274, 168, 91, 44, 19, 8 }; - const UINT16 fir_sum = 9998; - - int ii,jj,kk,ll; - UINT8* dmdFrames = which == 0 ? &DMDFrames[0][0] : &DMDFrames2[0][0]; - #if defined(VPINMAME) || defined(LIBPINMAME) - int i = 0; - g_raw_gtswpc_dmdframes = 5; // Only send the last 5 raw frames + core_tDMDPWMState* state = >S3_dmdlocals[which].pwm_state; + g_raw_gtswpc_dmdframes = state->nFrames > 5 ? 5 : state->nFrames; // Only send at most the last 5 raw frames UINT8* rawData = &g_raw_gtswpc_dmd[0]; - for (ii = 0; ii < (int)g_raw_gtswpc_dmdframes; ii++) { - UINT8* frameData = dmdFrames + ((GTS3_dmdlocals[0].nextDMDFrame + (GTS3DMD_FRAMES - 1) + (GTS3DMD_FRAMES - ii)) % GTS3DMD_FRAMES) * 0x200; - for (jj = 0; jj < 32 * 16; jj++) { // 32 lines of 16 columns of 8 pixels - UINT8 data = *frameData++; - *rawData = core_revbyte(data); + for (int frame = 0; frame < (int)g_raw_gtswpc_dmdframes; frame++) { + UINT8* frameData = state->rawFrames + ((state->nextFrame + (state->nFrames - 1) + (state->nFrames - frame)) % state->nFrames) * state->rawFrameSize; + for (int jj = 0; jj < state->rawFrameSize; jj++) { + *rawData = core_revbyte(*frameData++); rawData++; } } #endif - // Apply low pass filter over 24 frames - memset(GTS3_accumulatedFrame, 0, sizeof(GTS3_accumulatedFrame)); - for (ii = 0; ii < sizeof(fir_weights)/sizeof(fir_weights[0]); ii++) { - const UINT16 frame_weight = fir_weights[ii]; - UINT8* frameData = dmdFrames + ((GTS3_dmdlocals[0].nextDMDFrame + (GTS3DMD_FRAMES - 1) + (GTS3DMD_FRAMES - ii)) % GTS3DMD_FRAMES) * 0x200; - for (jj = 1; jj <= 32; jj++) { // 32 lines - UINT16* line = >S3_accumulatedFrame[jj - 1][0]; - for (kk = 0; kk < 16; kk++) { // 16 columns/line - UINT8 data = *frameData++; - for (ll = 0; ll < 8; ll++) { // 8 pixels/column - (*line++) += frame_weight * (UINT16)(data>>7); - data <<= 1; - } - } - } - } - - // Scale down to 16 shades (note that precision matters and is needed to avoid flickering) - for (ii = 1; ii <= 32; ii++) // 32 lines - for (jj = 0; jj < 128; jj++) { // 128 pixels/line - UINT16 data = GTS3_accumulatedFrame[ii-1][jj]; - coreGlobals.dotCol[ii][jj] = ((UINT8)((255 * (unsigned int) data) / fir_sum)) >> 4; - } - + core_dmd_update_pwm(>S3_dmdlocals[which].pwm_state); video_update_core_dmd(bitmap, cliprect, layout); return 0; } diff --git a/src/wpc/gts3dmd.h b/src/wpc/gts3dmd.h index cbde793b8..39fcc67ee 100644 --- a/src/wpc/gts3dmd.h +++ b/src/wpc/gts3dmd.h @@ -4,8 +4,6 @@ #pragma once #endif -#define GTS3DMD_FRAMES 24 //# of Frames to capture - VIDEO_UPDATE(gts3_dmd128x32a); VIDEO_UPDATE(gts3_dmd128x32b); diff --git a/src/wpc/s11.c b/src/wpc/s11.c index 212036eeb..44e0b0d6e 100644 --- a/src/wpc/s11.c +++ b/src/wpc/s11.c @@ -1388,17 +1388,6 @@ MACHINE_DRIVER_START(de_dmd162aS) MDRV_SOUND_CMDHEADING("DE") MACHINE_DRIVER_END -/* DE 128x32 Sound 2a with hacky/tweaked DMD IRQ (LW3/AS/R&B/SW) */ -MACHINE_DRIVER_START(de_dmd322aS_hack) - MDRV_IMPORT_FROM(s11) - MDRV_IMPORT_FROM(de2aas) - MDRV_IMPORT_FROM(de_dmd32_hack) - MDRV_NVRAM_HANDLER(de) - MDRV_DIAGNOSTIC_LEDH(1) - MDRV_SOUND_CMD(de_sndCmd_w) - MDRV_SOUND_CMDHEADING("DE") -MACHINE_DRIVER_END - /* DE 128x32 Sound 2a */ MACHINE_DRIVER_START(de_dmd322aS) MDRV_IMPORT_FROM(s11) diff --git a/src/wpc/s11.h b/src/wpc/s11.h index 49ec170a1..4ce7b7e59 100644 --- a/src/wpc/s11.h +++ b/src/wpc/s11.h @@ -222,7 +222,6 @@ extern MACHINE_DRIVER_EXTERN(de_dmd642aS); #define de_mDEAS1 de_a1S #define de_mDEDMD16S1 de_dmd161S #define de_mDEDMD16S2A de_dmd162aS -#define de_mDEDMD32S2A_hack de_dmd322aS_hack #define de_mDEDMD32S2A de_dmd322aS #define de_mDEDMD64S2A de_dmd642aS diff --git a/src/wpc/wpc.c b/src/wpc/wpc.c index faa54cf28..70b322d0b 100644 --- a/src/wpc/wpc.c +++ b/src/wpc/wpc.c @@ -29,9 +29,8 @@ #else #define WPC_INTERFACE_UPD_PER_FRAME 1 // For regular lib/V/PinMame, one interface update at 60Hz should be enough (it's what most other drivers do) #endif -/*-- no of DMD frames to add together to create shades --*/ -/*-- (hardcoded, do not change) --*/ -#define DMD_FRAMES 8 /* Some early machines like T2 could in some few animations (like T2 attract mode) profit from more shades, but very tricky to get right without flicker ! */ +/*-- no of DMD frames to store and consider to create shades --*/ +#define DMD_FRAMES 8 /*-- Smoothing values --*/ #if defined(PROC_SUPPORT) || defined(PPUC_SUPPORT) @@ -1639,7 +1638,7 @@ int wpcdmd_update(int height, struct mame_bitmap* bitmap, const struct rectangle } #endif - // Apply low pass filter over 24 frames + // Apply low pass filter over stored frames memset(dmdlocals.accumulatedFrame, 0, sizeof(dmdlocals.accumulatedFrame)); for (ii = 0; ii < sizeof(fir_weights)/sizeof(fir_weights[0]); ii++) { const UINT16 frame_weight = fir_weights[ii]; @@ -1656,11 +1655,11 @@ int wpcdmd_update(int height, struct mame_bitmap* bitmap, const struct rectangle } } - // Scale down to 4 shades (note that precision matters and is needed to avoid flickering) + // Scale down to 256 shades (note that precision matters and is needed to avoid flickering) for (ii = 1; ii <= height; ii++) // 32 or 64 lines for (jj = 0; jj < 128; jj++) { // 128 pixels/line UINT16 data = dmdlocals.accumulatedFrame[ii-1][jj]; - coreGlobals.dotCol[ii][jj] = ((UINT8)((255 * (unsigned int) data) / fir_sum)) >> 6; + coreGlobals.dotCol[ii][jj] = (UINT8)((255 * (unsigned int) data) / fir_sum); } video_update_core_dmd(bitmap, cliprect, layout);