From 99b97f78317d907c62b8a0b84b632881085d12af Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Mon, 8 Jan 2024 22:42:17 +0100 Subject: [PATCH] PWM: simplify enable API, add some Sega/DataEast tables, little fix --- release/whatsnew.txt | 11 +++--- src/wpc/core.c | 39 ++++++++++--------- src/wpc/core.h | 5 +-- src/wpc/s11.c | 76 ++++++++++++++++++++++++++++++------- src/wpc/sims/wpc/full/bop.c | 2 + src/wpc/vpintf.c | 22 +++++------ src/wpc/wpc.c | 5 +-- 7 files changed, 103 insertions(+), 57 deletions(-) diff --git a/release/whatsnew.txt b/release/whatsnew.txt index 90c792a7e..e4ea3bf13 100644 --- a/release/whatsnew.txt +++ b/release/whatsnew.txt @@ -32,12 +32,11 @@ Fix some external DMD alphanumeric mappings: GTS80B, GTS3, Hankin, Police Force, Added the emulation of physical bulbs & LEDs connected to binary outputs, for WPC, GTS3, SAM, Whitestar, Capcom and S11 hardware. This allows to dramatically improve e.g. lamp or flasher modulation (for example the pulsing lights below the princess of TOTAN, or the Sauron eye of LOTR, or slowly fading lamps in Breakshot). This needs to be enabled before use, the same way as for the existing - 'modulated' solenoids: by setting SolMask(2) which is now a bitmask: 1 is legacy modulated solenoids, 2 is physical model for solenoid - outputs, 4 is physical model for lamps/GIs/Segment outputs. To be emulated correctly, devices connected to binary output must be defined. - PinMAME already has the definition for lots of them (to be found in MACHINE_INIT of each driver) but if the one you want is missing, - or you want to modify it, use 'SolMask(xx) = type' to change it, where xx is the output to be modified (see vp_setSolMask), and yy is - the type (see core.h). Also see the updated core scripts coming with VPX. - This also opens up the path for emulation of dimmed alphanumerical segments and strength modulated solenoids + 'modulated' solenoids: by setting SolMask(2) to 1 for legacy modulated solenoids or 2 for physical model of all outputs. + To be emulated correctly, devices connected to binary output must be defined. PinMAME already has the definition for lots of them + (to be found in MACHINE_INIT of each driver) but if the one you want is missing, or you want to modify it, use 'SolMask(xx) = type' + to change it, where xx is the output to be modified (see vp_setSolMask), and yy is the type (see core.h). Also see the updated core + scripts coming with VPX. This also opens up the path for emulation of dimmed alphanumerical segments and strength modulated solenoids (for example Capcom Kingpin, or the way most modern hardware handle Power/Hold and EOS switch). *** CORE/CPU *** diff --git a/src/wpc/core.c b/src/wpc/core.c index a6e342528..182fcaad9 100644 --- a/src/wpc/core.c +++ b/src/wpc/core.c @@ -1464,8 +1464,8 @@ void core_updateSw(int flipEn) { (SIM_BALLS(inports[CORE_SIMINPORT]))); /*-- Report changed solenoids --*/ - if (coreGlobals.nSolenoids && ((options.usemodsol & CORE_MODOUT_ENABLE_SOLENOIDS) - || ((core_gameData->gen & GEN_ALLWPC) && (options.usemodsol & CORE_MODOUT_ENABLE_LEGACY)) )) + if (coreGlobals.nSolenoids && + ((options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT) || ((core_gameData->gen & GEN_ALLWPC | core_gameData->gen & GEN_SAM) && (options.usemodsol & CORE_MODOUT_ENABLE_MODSOL)) )) { float state[CORE_MODOUT_SOL_MAX]; core_getAllPhysicSols(state); @@ -1632,7 +1632,7 @@ static VIDEO_UPDATE(core_status) { for (qq = 0; qq < drawData->lamps[num].totnum; qq++) { const int lampx = drawData->lamps[num].lamppos[qq].x; const int lampy = drawData->lamps[num].lamppos[qq].y; - if (options.usemodsol & (CORE_MODOUT_ENABLE_LGIAS | CORE_MODOUT_FORCE_ON)) { + if (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON)) { UINT8 v = saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + ii * 8 + jj].value); line[lampx][starty + lampy] = 64 + (v >> 4); } @@ -1653,12 +1653,12 @@ static VIDEO_UPDATE(core_status) { } /*-- Default square lamp matrix layout --*/ else { - int nCols = coreGlobals.nLamps ? (coreGlobals.nLamps + 7) >> 3 : CORE_CUSTLAMPCOL + core_gameData->hw.lampCol * 8; - for (ii = 0; ii < nCols; ii++) { + assert((coreGlobals.nLamps == 0) || ((coreGlobals.nLamps + 7) >> 3 == CORE_CUSTLAMPCOL + core_gameData->hw.lampCol)); + for (ii = 0; ii < CORE_CUSTLAMPCOL + core_gameData->hw.lampCol; ii++) { BMTYPE** line = &lines[locals.firstSimRow + startRow]; bits = coreGlobals.lampMatrix[ii]; for (jj = 0; jj < 8; jj++) { - if (options.usemodsol & (CORE_MODOUT_ENABLE_LGIAS | CORE_MODOUT_FORCE_ON)) { + if (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON)) { UINT8 v = saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + ii * 8 + jj].value); line[0][thisCol + ii * 2] = 64 + (v >> 4); } else @@ -1693,7 +1693,7 @@ static VIDEO_UPDATE(core_status) { { BMTYPE **line = &lines[locals.firstSimRow + startRow]; - if (options.usemodsol & (CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LEGACY | CORE_MODOUT_FORCE_ON)) + if (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)) { float state[CORE_MODOUT_SOL_MAX]; core_getAllPhysicSols(state); @@ -1752,7 +1752,7 @@ static VIDEO_UPDATE(core_status) { for (ii = 0; ii < CORE_MAXGI; ii++) { - if (options.usemodsol & (CORE_MODOUT_ENABLE_LGIAS | CORE_MODOUT_FORCE_ON)) + if (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON)) { UINT8 v = saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_GI0 + ii].value); lines[locals.firstSimRow + startRow][thisCol + ii * 2] = 64 + (v >> 4); @@ -1853,10 +1853,10 @@ void core_updInvSw(int swNo, int inv) { /--------------------------------------*/ int core_getSol(int solNo) { if (solNo <= 28) - return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LEGACY)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + solNo - 1].value) : coreGlobals.solenoids & CORE_SOLBIT(solNo); + return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_ENABLE_MODSOL)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + solNo - 1].value) : coreGlobals.solenoids & CORE_SOLBIT(solNo); else if (solNo <= 32) { // 29-32 if (core_gameData->gen & GEN_ALLS11) - return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LEGACY)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + solNo - 1].value) : coreGlobals.solenoids & CORE_SOLBIT(solNo); + return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_ENABLE_MODSOL)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + solNo - 1].value) : coreGlobals.solenoids & CORE_SOLBIT(solNo); else if (core_gameData->gen & GEN_ALLWPC) // GI circuits return coreGlobals.solenoids2 & (1<<(solNo-29+8)); // GameOn } @@ -1875,9 +1875,9 @@ int core_getSol(int solNo) { } else if (solNo <= 44) { // 37-44 WPC95 & S11 extra if (core_gameData->gen & (GEN_WPC95|GEN_WPC95DCS)) // Duplicated in 37..40 / 41..44, so always read from 41..44 (hence the |4 in the index/mask) - return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LEGACY)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + ((solNo - 13) | 4)].value) : coreGlobals.solenoids & (1<<((solNo - 13)|4)); + return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_ENABLE_MODSOL)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + ((solNo - 13) | 4)].value) : coreGlobals.solenoids & (1<<((solNo - 13)|4)); if (core_gameData->gen & GEN_ALLS11) - return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LEGACY)) ? saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + 32 + solNo - 37 + 8].value) : coreGlobals.solenoids2 & (1<<(solNo - 37 + 8)); + return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_ENABLE_MODSOL)) ? 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 int mask = 1<<(solNo - 45); @@ -1951,7 +1951,7 @@ UINT64 core_getAllSol(void) { /--------------------------------------------------*/ void core_getAllPhysicSols(float* state) { - assert(coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_LEGACY | CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_FORCE_ON))); + assert(coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON))); memset(state, 0, CORE_MODOUT_SOL_MAX * sizeof(float)); // To avoid reporting garbage states for unused solenoid slots /*-- 1..32, hardware solenoids --*/ if (core_gameData->gen & GEN_ALLWPC) { @@ -2199,10 +2199,9 @@ static MACHINE_INIT(core) { /*-- init PWM integration (needs to be done after coreData->init() which defines the number of outputs and the physical model to be used on each output) --*/ // If physic output enabled and defined by driver, update all outputs every 1ms to allow async reading done by VPinMame (should be optimized to something less heavy...) // Note that some table made during 3.6 beta phase define output type even AFTER init. They will not work with the new implementation and need to be updated - // options.usemodsol = CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LGIAS; // Uncomment for testing - if ( ((options.usemodsol & CORE_MODOUT_ENABLE_SOLENOIDS) && coreGlobals.nSolenoids) - || ((options.usemodsol & CORE_MODOUT_ENABLE_LEGACY ) && coreGlobals.nSolenoids) - || ((options.usemodsol & CORE_MODOUT_ENABLE_LGIAS ) && (coreGlobals.nLamps || coreGlobals.nGI || coreGlobals.nAlphaSegs)) + //options.usemodsol = CORE_MODOUT_ENABLE_PHYSOUT; // Uncomment for testing + if ( ((options.usemodsol & CORE_MODOUT_ENABLE_MODSOL ) && coreGlobals.nSolenoids) + || ((options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT) && (coreGlobals.nSolenoids || coreGlobals.nLamps || coreGlobals.nGI || coreGlobals.nAlphaSegs)) || (options.usemodsol & CORE_MODOUT_FORCE_ON)) timer_pulse(TIME_IN_HZ(999), 0, core_update_pwm_outputs); memset(coreOutputinfos, 0, sizeof(coreOutputinfos)); @@ -2734,7 +2733,7 @@ void core_set_pwm_output_types(int startIndex, int count, int* outputTypes) // Write binary state of outputs, taking care of PWM integration based on physical model of the connected device void core_write_pwm_output(int index, int count, UINT8 bitStates) { - if ((options.usemodsol & (CORE_MODOUT_ENABLE_LEGACY | CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LGIAS | CORE_MODOUT_FORCE_ON)) == 0) + if ((options.usemodsol & (CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON)) == 0) return; const float now = (float)timer_get_time(); for (int i = 0; i < count; i++) { @@ -2751,7 +2750,7 @@ void core_write_pwm_output(int index, int count, UINT8 bitStates) void core_write_pwm_output_8b(int index, UINT8 bitStates) { - if ((options.usemodsol & (CORE_MODOUT_ENABLE_LEGACY | CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LGIAS | CORE_MODOUT_FORCE_ON)) == 0) + if ((options.usemodsol & (CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON)) == 0) return; assert((index & 7) == 0); UINT8 changeMask = coreGlobals.binaryOutputState[index >> 3] ^ bitStates; // Identify differences @@ -2772,7 +2771,7 @@ void core_write_pwm_output_8b(int index, UINT8 bitStates) void core_write_masked_pwm_output_8b(int index, UINT8 bitStates, UINT8 bitMask) { - if ((options.usemodsol & (CORE_MODOUT_ENABLE_LEGACY | CORE_MODOUT_ENABLE_SOLENOIDS | CORE_MODOUT_ENABLE_LGIAS | CORE_MODOUT_FORCE_ON)) == 0) + if ((options.usemodsol & (CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_ENABLE_PHYSOUT | CORE_MODOUT_FORCE_ON)) == 0) return; assert((index & 7) == 0); UINT8 changeMask = bitMask & (coreGlobals.binaryOutputState[index >> 3] ^ bitStates); // Identify differences diff --git a/src/wpc/core.h b/src/wpc/core.h index c7b09a69c..941f224c8 100644 --- a/src/wpc/core.h +++ b/src/wpc/core.h @@ -359,9 +359,8 @@ extern void video_update_core_dmd(struct mame_bitmap *bitmap, const struct recta /*-- Physical devices on binary outputs --*/ -#define CORE_MODOUT_ENABLE_LEGACY 1 /* Bitmask for options.usemodsol to enable legacy behavior (simple solenoid integration for WPC/SAM) */ -#define CORE_MODOUT_ENABLE_SOLENOIDS 2 /* Bitmask for options.usemodsol to enable solenoids */ -#define CORE_MODOUT_ENABLE_LGIAS 4 /* Bitmask for options.usemodsol to enable Lamp/GI/AlphaSegments */ +#define CORE_MODOUT_ENABLE_MODSOL 1 /* Bitmask for options.usemodsol to enable legacy behavior (simple solenoid linear integration for WPC/SAM) */ +#define CORE_MODOUT_ENABLE_PHYSOUT 2 /* Bitmask for options.usemodsol to enable physics output for solenoids/Lamp/GI/AlphaSegments */ #define CORE_MODOUT_FORCE_ON 128 /* Bitmask for options.usemodsol for drivers that needs PWM integration to be performed whatever the user settings are */ #define CORE_MODOUT_LAMP_MAX (CORE_MAXLAMPCOL*8) /* Maximum number of modulated outputs for lamps */ diff --git a/src/wpc/s11.c b/src/wpc/s11.c index bc0ef1403..6fac24519 100644 --- a/src/wpc/s11.c +++ b/src/wpc/s11.c @@ -512,7 +512,7 @@ static void updsol(void) { core_write_pwm_output_8b(CORE_MODOUT_SOL0 , coreGlobals.pulsedSolState & 0x0FF); core_write_pwm_output_8b(CORE_MODOUT_SOL0 + 8, (coreGlobals.pulsedSolState >> 8) & 0x0FF); core_write_pwm_output_8b(CORE_MODOUT_SOL0 + 16, (coreGlobals.pulsedSolState >> 16) & 0x0FF); - core_write_pwm_output_8b(CORE_MODOUT_SOL0 + 24, (coreGlobals.pulsedSolState >> 24) & 0x0FF); + core_write_pwm_output_8b(CORE_MODOUT_SOL0 + 24, (coreGlobals.pulsedSolState >> 24) & 0x0FF); // Muxed solenoids locals.solenoids |= coreGlobals.pulsedSolState; } @@ -553,7 +553,7 @@ static WRITE_HANDLER(latch2200) { } #endif -static WRITE_HANDLER(pia0cb2_w) { locals.ssEn = !data;} +static WRITE_HANDLER(pia0cb2_w) { locals.ssEn = !data; coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + S11_GAMEONSOL - 1].value = data ? 0.f : 1.f; } static WRITE_HANDLER(pia1ca2_w) { setSSSol(data, 0); } static WRITE_HANDLER(pia1cb2_w) { setSSSol(data, 1); } @@ -811,22 +811,70 @@ static MACHINE_INIT(s11) { core_set_pwm_output_type(CORE_MODOUT_LAMP0, coreGlobals.nLamps, CORE_MODOUT_BULB_44_18V_DC_S11); coreGlobals.nSolenoids = CORE_FIRSTCUSTSOL - 1 + core_gameData->hw.custSol; core_set_pwm_output_type(CORE_MODOUT_SOL0, coreGlobals.nSolenoids, CORE_MODOUT_SOL_2_STATE); + core_set_pwm_output_type(CORE_MODOUT_SOL0 + S11_GAMEONSOL - 1, 1, CORE_MODOUT_NONE); // GameOn output for fast flips + if (core_gameData->sxx.muxSol) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + core_gameData->sxx.muxSol - 1, 1, CORE_MODOUT_PULSE); // K1 mux relay const struct GameDriver* rootDrv = Machine->gamedrv; while (rootDrv->clone_of && (rootDrv->clone_of->flags & NOT_A_DRIVER) == 0) rootDrv = rootDrv->clone_of; const char* const gn = rootDrv->name; - if (strncasecmp(gn, "gnr_300", 7) == 0) { // Guns'n Roses - int solenoids[32] = { - /* 1.. 4 */ CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, - /* 5.. 8 */ CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, - /* 9..12 */ CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_PULSE, CORE_MODOUT_BULB_44_6_3V_AC, CORE_MODOUT_SOL_2_STATE, /* #10 is K1 mux relay, #11 is GI relay */ - /* 13..16 */ CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, - /* 17..20 */ CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, - /* 21..24 */ CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_SOL_2_STATE, CORE_MODOUT_PULSE, - /* 25..28 */ CORE_MODOUT_BULB_44_18V_DC_S11, CORE_MODOUT_BULB_44_18V_DC_S11, CORE_MODOUT_BULB_44_18V_DC_S11, CORE_MODOUT_BULB_44_18V_DC_S11, /* 8 muxed outputs (K1 relay is solenoid #10) */ - /* 29..32 */ CORE_MODOUT_BULB_44_18V_DC_S11, CORE_MODOUT_BULB_44_18V_DC_S11, CORE_MODOUT_BULB_44_18V_DC_S11, CORE_MODOUT_BULB_44_18V_DC_S11 /* 8 muxed outputs (K1 relay is solenoid #10) */ - }; - core_set_pwm_output_types(CORE_MODOUT_SOL0, 32, solenoids); + // DataEast/Sega 1 + if (strncasecmp(gn, "lwar_a83", 8) == 0) { // Laser War + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 8, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 1 - 1, 3, CORE_MODOUT_BULB_89_32V_DC_S11); + // Note: The yellow, red & blue mars flashers are connected to ground through 660 ohms resistor, not sure why (5 ohms when switched on, 2 bulbs in parallel). + // One explication would be to keep the filament warm (don't think it would be visible. This would need further investigation) + } + // DataEast/Sega 3 + // Missing: Rocky & Bullwinkle, BTTF, Checkpoint, TMNT, The Simpsons, WWF Royal Rumble + else if ((strncasecmp(gn, "gnr_300", 7) == 0) // Guns'n Roses + || (strncasecmp(gn, "tftc_303", 8) == 0) // Tales from The Crypt + || (strncasecmp(gn, "stwr_104", 8) == 0) // Star Wars + || (strncasecmp(gn, "jupk_513", 8) == 0)) { // Jurassic Park + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 8, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + } + else if ((strncasecmp(gn, "btmn_103", 8) == 0) // Batman + || (strncasecmp(gn, "hook_408", 8) == 0)) { // Hook + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 8, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 9 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 12 - 1, 3, CORE_MODOUT_BULB_89_32V_DC_S11); + } + else if (strncasecmp(gn, "lah_112", 7) == 0) { // Last Action Hero + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 7, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 9 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + } + else if ((strncasecmp(gn, "aar_101", 7) == 0) // Aaron Spelling + || (strncasecmp(gn, "lw3_208", 7) == 0)) { // Lethal Weapon 3 + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 7, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 9 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 16 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + } + else if (strncasecmp(gn, "trek_201", 8) == 0) { // Star Trek 25th + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 7, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 9 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 12 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + } + else if (strncasecmp(gn, "tomy_400", 8) == 0) { // Tommy Pinball Wizard + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 7, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 15 - 1, 1, CORE_MODOUT_BULB_89_32V_DC_S11); + } + // DataEast/Sega 3b + else if ((strncasecmp(gn, "batmanf", 7) == 0) // Batman Forever + || (strncasecmp(gn, "baywatch", 8) == 0) // Baywatch + || (strncasecmp(gn, "mav_402", 7) == 0)) { // Maverick + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 8, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) + } + else if (strncasecmp(gn, "frankst", 7) == 0) { // Mary Shelley's Frankenstein + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 11 - 1, 1, CORE_MODOUT_BULB_44_6_3V_AC); // GI output + core_set_pwm_output_type(CORE_MODOUT_SOL0 + 25 - 1, 7, CORE_MODOUT_BULB_89_32V_DC_S11); // 8 muxed flasher outputs (K1 relay is solenoid #10) } } static MACHINE_RESET(s11) { diff --git a/src/wpc/sims/wpc/full/bop.c b/src/wpc/sims/wpc/full/bop.c index 2c29171fc..4e70df833 100644 --- a/src/wpc/sims/wpc/full/bop.c +++ b/src/wpc/sims/wpc/full/bop.c @@ -712,9 +712,11 @@ static int bop_getMech(int mechNo) { static WRITE_HANDLER(parallel_0_out) { coreGlobals.lampMatrix[8] = coreGlobals.tmpLampMatrix[8] = data ^ 0xff; + core_write_pwm_output_8b(CORE_MODOUT_LAMP0 + 8 * 8, data ^ 0xff); } static WRITE_HANDLER(parallel_1_out) { coreGlobals.lampMatrix[9] = coreGlobals.tmpLampMatrix[9] = data ^ 0xff; + core_write_pwm_output_8b(CORE_MODOUT_LAMP0 + 9 * 8, data ^ 0xff); } static WRITE_HANDLER(qspin_0_out) { HC4094_data_w(1, data); diff --git a/src/wpc/vpintf.c b/src/wpc/vpintf.c index 6a870733b..bd91d5fed 100644 --- a/src/wpc/vpintf.c +++ b/src/wpc/vpintf.c @@ -33,7 +33,7 @@ void vp_init(void) { int vp_getLamp(int lampNo) { if (coreData->lamp2m) lampNo = coreData->lamp2m(lampNo) - 8; /*-- Physical output mode: return a physically meaningful value depending on the output type --*/ - if (coreGlobals.nLamps && (options.usemodsol & CORE_MODOUT_ENABLE_LGIAS)) + if (coreGlobals.nLamps && (options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT)) return (int)saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + lampNo].value); #ifndef LIBPINMAME return (coreGlobals.lampMatrix[lampNo/8]>>(lampNo%8)) & 0x01; @@ -57,7 +57,7 @@ int vp_getSolenoid(int solNo) int vp_getGI(int giNo) { /*-- Physical output mode: return a physically meaningful value depending on the output type --*/ - if (coreGlobals.nGI && (options.usemodsol & CORE_MODOUT_ENABLE_LGIAS)) + if (coreGlobals.nGI && (options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT)) return (int)saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_GI0 + giNo].value); return coreGlobals.gi[giNo]; } @@ -69,7 +69,7 @@ int vp_getGI(int giNo) int vp_getChangedLamps(vp_tChgLamps chgStat) { int ii, idx = 0; /*-- fill in array --*/ - if (coreGlobals.nLamps && (options.usemodsol & CORE_MODOUT_ENABLE_LGIAS)) + if (coreGlobals.nLamps && (options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT)) { for (ii = 0; ii < coreGlobals.nLamps; ii++) { UINT8 val = saturatedByte(coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + ii].value); @@ -132,8 +132,8 @@ int vp_getChangedSolenoids(vp_tChgSols chgStat) { int ii, idx = 0; if (coreGlobals.nSolenoids && ( - (options.usemodsol & CORE_MODOUT_ENABLE_SOLENOIDS) - || ((core_gameData->gen & GEN_ALLWPC) && (options.usemodsol & CORE_MODOUT_ENABLE_LEGACY)) )) + (options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT) + || ((core_gameData->gen & GEN_ALLWPC) && (options.usemodsol & CORE_MODOUT_ENABLE_MODSOL)) )) { float state[CORE_MODOUT_SOL_MAX]; core_getAllPhysicSols(state); @@ -171,7 +171,7 @@ int vp_getChangedSolenoids(vp_tChgSols chgStat) /-------------------------------------*/ int vp_getChangedGI(vp_tChgGIs chgStat) { /*-- Physical output mode: return a physically meaningful value depending on the output type --*/ - if (coreGlobals.nGI && (options.usemodsol & CORE_MODOUT_ENABLE_LGIAS)) + if (coreGlobals.nGI && (options.usemodsol & CORE_MODOUT_ENABLE_PHYSOUT)) { int idx = 0; for (int i = 0; i < coreGlobals.nGI; i++) { @@ -263,7 +263,7 @@ int vp_getSolMask(int no) { else if (2001 <= no) return vp_getModOutputType(VP_OUT_ALPHASEG, no - 2000); else if (no == 2) - return options.usemodsol; + return options.usemodsol & ~CORE_MODOUT_FORCE_ON; else if (no == 0 || no == 1) return locals.solMask[no]; else @@ -282,22 +282,22 @@ void vp_setModOutputType(int output, int no, int type) { if (output == VP_OUT_SOLENOID && 1 <= no && no <= coreGlobals.nSolenoids) { pos = CORE_MODOUT_SOL0 + no - 1; - options.usemodsol |= CORE_MODOUT_ENABLE_SOLENOIDS; + options.usemodsol |= CORE_MODOUT_ENABLE_PHYSOUT; } else if (output == VP_OUT_GI && 1 <= no && no <= coreGlobals.nGI) { pos = CORE_MODOUT_GI0 + no - 1; - options.usemodsol |= CORE_MODOUT_ENABLE_LGIAS; + options.usemodsol |= CORE_MODOUT_ENABLE_PHYSOUT; } else if (output == VP_OUT_LAMP && 1 <= no && no <= coreGlobals.nLamps) { pos = CORE_MODOUT_LAMP0 + no - 1; - options.usemodsol |= CORE_MODOUT_ENABLE_LGIAS; + options.usemodsol |= CORE_MODOUT_ENABLE_PHYSOUT; } else if (output == VP_OUT_ALPHASEG && 1 <= no && no <= coreGlobals.nAlphaSegs) { pos = CORE_MODOUT_SEG0 + no - 1; - options.usemodsol |= CORE_MODOUT_ENABLE_LGIAS; + options.usemodsol |= CORE_MODOUT_ENABLE_PHYSOUT; } if (pos != -1) { diff --git a/src/wpc/wpc.c b/src/wpc/wpc.c index f938a04c9..0cb789b2a 100644 --- a/src/wpc/wpc.c +++ b/src/wpc/wpc.c @@ -1182,8 +1182,7 @@ static MACHINE_INIT(wpc) { int flashers[] = { 17, 18, 19, 20, 23, 24 }; for (int i = 0; i < sizeof(flashers) / sizeof(int); i++) coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + flashers[i] - 1].type = CORE_MODOUT_BULB_89_20V_DC_WPC; - // TODO check Helmet (seems they are 12V) wired at sol #21/#22 (motor ? but operator manual states flashers) - // TODO add Helmet lights + core_set_pwm_output_type(CORE_MODOUT_LAMP0 + 8 * 8, 16, CORE_MODOUT_BULB_44_18V_DC_WPC); // Helmet lights } else if (strncasecmp(gn, "br_l4", 5) == 0) { // Black Rose int flashers[] = { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }; @@ -1403,7 +1402,7 @@ static MACHINE_INIT(wpc) { coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + flashers[i] - 1].type = CORE_MODOUT_BULB_89_20V_DC_WPC; } // Legacy integrator for backward compatibility: not really needed, the new one gives better result but could be uncommented if bugs are found with existing tables - /*if (options.usemodsol & CORE_MODOUT_ENABLE_LEGACY) + /*if (options.usemodsol & CORE_MODOUT_ENABLE_MODSOL) core_set_pwm_output_type(CORE_MODOUT_SOL0, coreGlobals.nSolenoids, CORE_MODOUT_LEGACY_SOL_WPC); //for (int i = 0; i < coreGlobals.nSolenoids; i++) // if (coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].type == CORE_MODOUT_BULB_89_20V_DC_WPC)