From 39e6022be56f6db217f16c4e3c8707b12e751dd6 Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Fri, 20 Dec 2024 17:06:56 +0100 Subject: [PATCH 1/5] WPC: Fix flipper solenoid of pre-fliptronic games Fix https://github.com/vpinball/pinmame/issues/359 --- src/wpc/wpc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/wpc/wpc.c b/src/wpc/wpc.c index d04a49f6e..b318258a9 100644 --- a/src/wpc/wpc.c +++ b/src/wpc/wpc.c @@ -491,7 +491,7 @@ static INTERRUPT_GEN(wpc_interface_update) { wpc_data[WPC_SOLENOID1] = wpc_data[WPC_SOLENOID2] = 0; wpc_data[WPC_SOLENOID3] = wpc_data[WPC_SOLENOID4] = 0; - // Move top 3 GI to solenoids -> gameOn = sol31 + // Move top 3 GI to solenoids -> gameOn coreGlobals.solenoids2 = (wpc_data[WPC_GILAMPS] & 0xe0)<<3; if (core_gameData->gen & GENWPC_HASFLIPTRON) { coreGlobals.solenoids2 |= wpclocals.solFlip; @@ -772,7 +772,7 @@ WRITE_HANDLER(wpc_w) { coreGlobals.solenoids2 |= wpclocals.solFlip; #endif core_write_pwm_output(CORE_MODOUT_SOL0 + 45 - 1, 4, ~data); - core_write_pwm_output(CORE_MODOUT_SOL0 + 33 - 1, 4, ~data >> 4); + core_write_pwm_output(CORE_MODOUT_SOL0 + 33 - 1, 4, (~data) >> 4); } break; case WPC_FLIPPERCOIL95: /* WPC_EXTBOARD4 */ @@ -1221,11 +1221,14 @@ static MACHINE_INIT(wpc) { coreGlobals.nLamps = 64 + core_gameData->hw.lampCol * 8; core_set_pwm_output_type(CORE_MODOUT_LAMP0, coreGlobals.nLamps, CORE_MODOUT_BULB_44_18V_DC_WPC); coreGlobals.nSolenoids = CORE_FIRSTCUSTSOL - 1 + core_gameData->hw.custSol; // Auxiliary solenoid board adding 8 outputs are already included in the base solenoid span (see core_gelAllModSol) (WPC Fliptronics: TZ / WPC DCS: DM, IJ, STTNG / WPC Security : RS / WPC 95: NGG) - coreGlobals.flipperCoils = 0x21232D2F20222C2Eull; // Hold: 33/35/45/47 Pow: 32/34/44/46 sol number is 0 based (offset from SOL0), order is UR/UL/LR/LL - if ((core_gameData->hw.flippers & FLIP_SOL(FLIP_UR)) == 0) /* No upper right flipper */ - coreGlobals.flipperCoils |= 0xFF000000FF000000ull; - if ((core_gameData->hw.flippers & FLIP_SOL(FLIP_UL)) == 0) /* No upper left flipper */ - coreGlobals.flipperCoils |= 0x00FF000000FF0000ull; + if (core_gameData->gen & (GENWPC_HASFLIPTRON | GENWPC_HASWPC95)) + { + coreGlobals.flipperCoils = 0x21232D2F20222C2Eull; // Hold: 33/35/45/47 Pow: 32/34/44/46 sol number is 0 based (offset from SOL0), order is UR/UL/LR/LL + if ((core_gameData->hw.flippers & FLIP_SOL(FLIP_UR)) == 0) /* No upper right flipper */ + coreGlobals.flipperCoils |= 0xFF000000FF000000ull; + if ((core_gameData->hw.flippers & FLIP_SOL(FLIP_UL)) == 0) /* No upper left flipper */ + coreGlobals.flipperCoils |= 0x00FF000000FF0000ull; + } core_set_pwm_output_type(CORE_MODOUT_SOL0, coreGlobals.nSolenoids, CORE_MODOUT_SOL_2_STATE); coreGlobals.nGI = 5; core_set_pwm_output_type(CORE_MODOUT_GI0, coreGlobals.nGI, CORE_MODOUT_BULB_44_6_3V_AC); From 618648a88ab1b6f2f6d6598672752f8125822227 Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Fri, 20 Dec 2024 17:20:15 +0100 Subject: [PATCH 2/5] WPC: fix non fliptronic/95 solenoids for VPM --- src/wpc/core.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/wpc/core.c b/src/wpc/core.c index e6ade75e6..a182f582e 100644 --- a/src/wpc/core.c +++ b/src/wpc/core.c @@ -1782,7 +1782,7 @@ int core_getSol(int solNo) { } else if (solNo <= 36) { // 33-36 driver specific sols if (core_gameData->gen & GEN_ALLWPC) { // WPC only: Upper flipper - if (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON))) + if ((core_gameData->gen & (GEN_WPCFLIPTRON | GEN_WPCDCS | GEN_WPCSECURITY | GEN_WPC95 | GEN_WPC95DCS)) && (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)))) return saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + solNo - 1].value); int mask; /*-- flipper coils --*/ @@ -1804,7 +1804,7 @@ int core_getSol(int solNo) { return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + 32 + solNo - 37 + 8].value) : coreGlobals.solenoids2 & (1<<(solNo - 37 + 8)); } else if (solNo <= 48) { // 45-48 Lower flippers - if ((core_gameData->gen & GEN_ALLWPC) && (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)))) + if ((core_gameData->gen & (GEN_WPCFLIPTRON | GEN_WPCDCS | GEN_WPCSECURITY | GEN_WPC95 | GEN_WPC95DCS)) && (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)))) return saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + solNo - 1].value); int mask = 1<<(solNo - 45); /*-- Game must have lower flippers but for symmetry we check anyway --*/ @@ -1897,7 +1897,7 @@ void core_getAllPhysicSols(float* const state) state[i] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value; /*-- 33..36 [WPC only] upper flipper solenoids --*/ if (core_gameData->gen & GEN_ALLWPC) { - if (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON))) + if ((core_gameData->gen & (GEN_WPCFLIPTRON | GEN_WPCDCS | GEN_WPCSECURITY | GEN_WPC95 | GEN_WPC95DCS)) && (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)))) for (int i = 32; i < 36; i++) state[i] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value; else { @@ -1926,16 +1926,19 @@ void core_getAllPhysicSols(float* const state) for (int i = 40; i < 48; i++) state[i - 4] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value; /*-- 45..48 lower flipper solenoids (only modulated for WPC) --*/ - if ((core_gameData->gen & GEN_ALLWPC) && (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)))) - for (int i = 44; i < 48; i++) - state[i] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value; - else { - UINT8 lFlip = (coreGlobals.solenoids2 & (CORE_LRFLIPSOLBITS|CORE_LLFLIPSOLBITS)); - lFlip |= (lFlip & 0x05)<<1; // hold coil is set if either coil is set - state[44] = lFlip & 0x01 ? 1.0f : 0.0f; - state[45] = lFlip & 0x02 ? 1.0f : 0.0f; - state[46] = lFlip & 0x04 ? 1.0f : 0.0f; - state[47] = lFlip & 0x08 ? 1.0f : 0.0f; + if (core_gameData->gen & GEN_ALLWPC) + { + if ((core_gameData->gen & (GEN_WPCFLIPTRON | GEN_WPCDCS | GEN_WPCSECURITY | GEN_WPC95 | GEN_WPC95DCS)) && (coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)))) + for (int i = 44; i < 48; i++) + state[i] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value; + else { + UINT8 lFlip = (coreGlobals.solenoids2 & (CORE_LRFLIPSOLBITS|CORE_LLFLIPSOLBITS)); + lFlip |= (lFlip & 0x05)<<1; // hold coil is set if either coil is set + state[44] = lFlip & 0x01 ? 1.0f : 0.0f; + state[45] = lFlip & 0x02 ? 1.0f : 0.0f; + state[46] = lFlip & 0x04 ? 1.0f : 0.0f; + state[47] = lFlip & 0x08 ? 1.0f : 0.0f; + } } /*-- 49..50 simulated --*/ state[48] = sim_getSol(49) ? 1.0f : 0.0f; From 00574b4f79144865dd34dca74924436de01fd645 Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Sat, 21 Dec 2024 09:17:21 +0100 Subject: [PATCH 3/5] MiniDMD: fix invalid WPT access, fix invalid shades, fix invalid PinMame rendering --- src/wpc/core.c | 18 ++++++++---------- src/wpc/sam.c | 6 ++++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/wpc/core.c b/src/wpc/core.c index a182f582e..6c3770d3e 100644 --- a/src/wpc/core.c +++ b/src/wpc/core.c @@ -3223,18 +3223,14 @@ void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { // Render to internal display, using provided luminance, if there is a visible display (PinMAME always, and VPinMAME when its window is shown) // FIXME apply colors LUT ? #if defined(PINMAME) || defined(VPINMAME) -void core_dmd_render_internal(struct mame_bitmap *bitmap, const int x, const int y, const int width, const int height, const UINT8* const dmdDotLum, const int apply_aa, const int keepColor) { +void core_dmd_render_internal(struct mame_bitmap *bitmap, const int x, const int y, const int width, const int height, const UINT8* const dmdDotLum, const int apply_aa) { #define DMD_OFS(row, col) ((row)*width + col) #define DMD_PAL(x) ((unsigned int)sizeof(core_palette)/3u - 48u + ((unsigned int)(x) * 47u) / 255u) // The trail of PinMAME palette has 48 DMD dot shades BMTYPE **lines = ((BMTYPE **)bitmap->line) + (y * locals.displaySize); for (int ii = 0; ii < height; ii++) { BMTYPE *line = (*lines) + (x * locals.displaySize); for (int jj = 0; jj < width; jj++) { - if (keepColor) { // mini DMDs, don't change their colors - *line = coreGlobals.dmdDotRaw[ii * width + jj] + 1; // +1 needed because the entire palette was shifted!? - } else { - *line = DMD_PAL(dmdDotLum[DMD_OFS(ii, jj)]); - } + *line = DMD_PAL(dmdDotLum[DMD_OFS(ii, jj)]); line += locals.displaySize; } lines += locals.displaySize; @@ -3412,9 +3408,11 @@ void core_dmd_video_update(struct mame_bitmap *bitmap, const struct rectangle *c dmdDotRaw = &coreGlobals.dmdDotRaw[0]; dmdDotLum = &coreGlobals.dmdDotLum[0]; if ((core_gameData->gen & GEN_SAM) == 0) { - const int shift = (core_gameData->gen & GEN_SPA) != 0 ? 4 : 6; + const UINT8 lum4[] = { 0, 85, 170, 255}; + const UINT8 lum16[] = { 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 }; + const UINT8* lum = (core_gameData->gen & GEN_SPA) != 0 ? lum16 : lum4; for (int ii = 0; ii < layout->length * layout->start; ii++) - dmdDotLum[ii] = dmdDotRaw[ii] << shift; + dmdDotLum[ii] = lum[dmdDotRaw[ii]]; } } @@ -3428,7 +3426,7 @@ void core_dmd_video_update(struct mame_bitmap *bitmap, const struct rectangle *c #elif defined(VPINMAME) const int isMainDMD = layout->length >= 128; // Up to 2 main DMDs (1 for all games, except Strike'n Spares which has 2) // FIXME check for VPinMame window hidden/shown state, and do not render if hidden - core_dmd_render_internal(bitmap, layout->left, layout->top, layout->length, layout->start, dmdDotLum, pmoptions.dmd_antialias && !(layout->type & CORE_DMDNOAA), layout->type & CORE_NODISP); + core_dmd_render_internal(bitmap, layout->left, layout->top, layout->length, layout->start, dmdDotLum, pmoptions.dmd_antialias && !(layout->type & CORE_DMDNOAA)); if (isMainDMD) { has_DMD_Video = 1; core_dmd_render_vpm(layout->length, layout->start, dmdDotLum); @@ -3437,7 +3435,7 @@ void core_dmd_video_update(struct mame_bitmap *bitmap, const struct rectangle *c } #elif defined(PINMAME) - core_dmd_render_internal(bitmap, layout->left, layout->top, layout->length, layout->start, dmdDotLum, pmoptions.dmd_antialias && !(layout->type & CORE_DMDNOAA), layout->type & CORE_NODISP); + core_dmd_render_internal(bitmap, layout->left, layout->top, layout->length, layout->start, dmdDotLum, pmoptions.dmd_antialias && !(layout->type & CORE_DMDNOAA)); #endif } diff --git a/src/wpc/sam.c b/src/wpc/sam.c index c5acde86a..47c698bb1 100644 --- a/src/wpc/sam.c +++ b/src/wpc/sam.c @@ -2247,11 +2247,12 @@ static PINMAME_VIDEO_UPDATE(samdmd_update) { #define SAT_NYB(v) (UINT8)(15.0f * (v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v)) #define SAT_BYTE(v) (UINT8)(255.0f * (v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v)) +// Little 5x7 led matrix used in World Poker Tour (2 rows of 7 each) static PINMAME_VIDEO_UPDATE(samminidmd_update) { int ii,kk; const int dmd_x = (layout->left-10)/7; const int dmd_y = (layout->top-34)/9; - for (int y = 0; y < 8; y++) + for (int y = 0; y < 7; y++) for (int x = 0; x < 5; x++) { const int target = 10 * 8 + (dmd_y * 5 + x) * 49 + (dmd_x * 7 + y); const float v = coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + target].value; @@ -2261,7 +2262,7 @@ static PINMAME_VIDEO_UPDATE(samminidmd_update) { // Use the video update to output mini DMD as LED segments (somewhat hacky) for (ii = 0; ii < 5; ii++) { int bits = 0; - for (kk = 0; kk < 7; kk++) // FIXME this does not match y in the for loop just above + for (kk = 0; kk < 7; kk++) bits = (bits<<1) | (coreGlobals.dmdDotRaw[kk * layout->length + ii] ? 1 : 0); coreGlobals.drawSeg[5*dmd_x + 35*dmd_y + ii] = bits; } @@ -2270,6 +2271,7 @@ static PINMAME_VIDEO_UPDATE(samminidmd_update) { return 0; } +// Wheel of Fortune Led matrix display static PINMAME_VIDEO_UPDATE(samminidmd2_update) { int ii,jj,kk; for (jj = 0; jj < 35; jj++) From e1901ca50d2ece53886c43ebfe8ac855a92dc138 Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Sat, 21 Dec 2024 09:46:40 +0100 Subject: [PATCH 4/5] Render dimmed DMD using shaded palette --- src/wpc/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wpc/core.c b/src/wpc/core.c index 6c3770d3e..d22721959 100644 --- a/src/wpc/core.c +++ b/src/wpc/core.c @@ -2013,6 +2013,8 @@ static void drawChar(struct mame_bitmap *bitmap, int row, int col, UINT16 seg_bi } } + #define DMD_PAL(x) ((unsigned int)sizeof(core_palette)/3u - 48u + ((unsigned int)(x) * 47u) / 255u) // The trail of PinMAME palette has 48 DMD dot shades + const UINT8 lum4[] = { 0, 85, 170, 255 }; for (kk = 0; kk < s->rows; kk++) { BMTYPE * __restrict line = &((BMTYPE **)(bitmap->line))[row+kk][col + s->cols]; // size is limited to 15 cols @@ -2021,11 +2023,13 @@ static void drawChar(struct mame_bitmap *bitmap, int row, int col, UINT16 seg_bi for (ll = 0; ll < s->cols; ll++, p >>= 2, np >>= 2) { if (p & 0x03) // segment set? - *(--line) = dimming ? dim_LUT[(p & 0x03)-1][dim[kk][ll]] : Machine->pens[palSize - 33 + (3 - (p & 0x03))*16]; + //*(--line) = dimming ? dim_LUT[(p & 0x03)-1][dim[kk][ll]] : Machine->pens[palSize - 33 + (3 - (p & 0x03))*16]; + *(--line) = dimming ? DMD_PAL((dim[kk][ll] * (4u - (p & 3))) / 3u) : DMD_PAL(((4u - (p & 3)) * 255u) / 3u); else *(--line) = Machine->pens[offPens[np & 0x03]]; } } + #undef DMD_PAL } From 6983c4c3257c12ad1759283252c417d1d2fd4f43 Mon Sep 17 00:00:00 2001 From: toxieainc Date: Sun, 22 Dec 2024 15:57:07 +0100 Subject: [PATCH 5/5] fix warnings --- src/win32com/ControllerDmdDevice.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/win32com/ControllerDmdDevice.cpp b/src/win32com/ControllerDmdDevice.cpp index 31cf6c308..3c8c97a38 100644 --- a/src/win32com/ControllerDmdDevice.cpp +++ b/src/win32com/ControllerDmdDevice.cpp @@ -79,7 +79,7 @@ typedef struct { static bool dmd_hasDMD = false; // Used to send a black frame for clean close static UINT16 dmd_width = 0; // Only valid if dmd_hasDMD is set static UINT16 dmd_height = 0; // Only valid if dmd_hasDMD is set -static dmddevice_t dmdDevices[2] = { 0 }; +static dmddevice_t dmdDevices[2] = { {0} }; extern "C" { @@ -218,8 +218,8 @@ extern "C" void dmddeviceRenderDMDFrame(const int width, const int height, UINT8 if (core_gameData->gen & GEN_GTS3) { const int shift = is16Shades ? 4 : 6; frame = (UINT8*)malloc(width * height); - for (int i = 0; i < width * height; i++) - frame[i] = dmdDotLum[i] >> shift; + for (int i2 = 0; i2 < width * height; i2++) + frame[i2] = dmdDotLum[i2] >> shift; } if (is16Shades) { if ((noOfRawFrames != 0) && dmdDevices[i].Render_16_Shades_with_Raw)