Skip to content

Commit

Permalink
WPC: add PWM support ot flipper solenoid
Browse files Browse the repository at this point in the history
Also some docs for Scared Stiff which needed this change for the flashers wired on the upper flipper solenoids
  • Loading branch information
vbousquet committed Oct 10, 2024
1 parent ffb4b66 commit d1d9125
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 68 deletions.
2 changes: 1 addition & 1 deletion docs/dmd.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The table below gives the main information (PWM FPS / Display FPS / PWM pattern)
|[WPC Phantom Haus](#wpc) | 61.05 / 30.1 | 2 frames | |
|[Data East 128x16](#data-east-128x16) | 177.5 / **59.2** | 2u row | |
|[Data East 128x32](#data-east-128x32-segastern-whitestar) | 234.2 / **78.1** | 2u row | |
|Sega 192x64 | 224.2 / 74.73 | 2u row |Batman Forever seems to have CPU-DMD communication issues |
|Sega 192x64 | 224.2 / 74.73 | 2u row |Timing issues leading to seldom display of bootup screen |
|Gottlieb GTS3 | **375.9** / 125.3-37.6 | 3/6/8/10 | |
|[Alvin G. 1](#alvin-g) | 332.4 / 83.1 | 4 row |Still a little flicker on the title screen |
|[Alvin G. 2](#alvin-g) | 298.6 / **74.6** | 4 row | |
Expand Down
57 changes: 35 additions & 22 deletions src/wpc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1601,11 +1601,13 @@ int core_getSol(int solNo) {
else if (solNo <= 32) { // 29-32
if (core_gameData->gen & GEN_ALLS11)
return coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | CORE_MODOUT_FORCE_ON)) ? 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
else if (core_gameData->gen & GEN_ALLWPC) // WPC GameOn
return coreGlobals.solenoids2 & (1<<(solNo-29+8));
}
else if (solNo <= 36) { // 33-36 Upper flipper (WPC only)
if (core_gameData->gen & GEN_ALLWPC) {
if (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 --*/
if ((solNo == sURFlip) && (core_gameData->hw.flippers & FLIP_SOL(FLIP_UR)))
Expand All @@ -1624,6 +1626,8 @@ 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))))
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 --*/
if ((solNo == sLRFlip) /*&& (core_gameData->hw.flippers & FLIP_SOL(FLIP_LR))*/)
Expand Down Expand Up @@ -1658,7 +1662,7 @@ UINT64 core_getAllSol(void) {
UINT64 sol = coreGlobals.solenoids;
if (core_gameData->gen & GEN_ALLWPC) // 29-32 GameOn
sol = (sol & 0x0fffffff) | ((coreGlobals.solenoids2 & 0x0f00)<<20);
if (core_gameData->gen & (GEN_WPC95|GEN_WPC95DCS)) { // 37-44 WPC95 extra
if (core_gameData->gen & (GEN_WPC95|GEN_WPC95DCS)) { // 37-44 WPC95 extra, duplicated at 0x......XX........
UINT64 tmp = coreGlobals.solenoids & 0xf0000000;
sol |= (tmp<<12)|(tmp<<8);
}
Expand Down Expand Up @@ -1696,42 +1700,50 @@ void core_getAllPhysicSols(float* const state)
{
assert(coreGlobals.nSolenoids && (options.usemodsol & (CORE_MODOUT_ENABLE_PHYSOUT_SOLENOIDS | CORE_MODOUT_ENABLE_MODSOL | 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) {
for (int i = 0; i < 28; i++)
/*-- 1..28, hardware solenoids --*/
for (int i = 0; i < 28; i++)
state[i] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value;
// 29..32 GameOn (not modulated, stored in 0x0F00 of solenoids2)
// 29..32 GameOn (not modulated, stored in 0x0700 of solenoids2)
for (int i = 28; i < 32; i++)
state[i] = coreGlobals.solenoids2 & (1 << (i - 28 + 8)) ? 1.0f : 0.0f;
}
else
for (int i = 0; i < 32; i++)
/*-- 29..32, hardware solenoids --*/
for (int i = 0; i < 32; i++)
state[i] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value;
/*-- 33..36 upper flipper solenoids (not modulated for the time being) --*/
{
UINT8 uFlip = (coreGlobals.solenoids2 & (CORE_URFLIPSOLBITS | CORE_ULFLIPSOLBITS));
if (core_gameData->hw.flippers & FLIP_SOL(FLIP_UR))
uFlip = uFlip | ((uFlip & 0x10)<<1);
if (core_gameData->hw.flippers & FLIP_SOL(FLIP_UL))
uFlip = uFlip | ((uFlip & 0x40)<<1);
state[32] = uFlip & 0x10 ? 1.0f : 0.0f;
state[33] = uFlip & 0x20 ? 1.0f : 0.0f;
state[34] = uFlip & 0x40 ? 1.0f : 0.0f;
state[35] = uFlip & 0x80 ? 1.0f : 0.0f;
/*-- 33..36 upper flipper solenoids (WPC only) --*/
if (core_gameData->gen & GEN_ALLWPC) {
if (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 {
UINT8 uFlip = (coreGlobals.solenoids2 & (CORE_URFLIPSOLBITS | CORE_ULFLIPSOLBITS));
if (core_gameData->hw.flippers & FLIP_SOL(FLIP_UR))
uFlip = uFlip | ((uFlip & 0x10)<<1);
if (core_gameData->hw.flippers & FLIP_SOL(FLIP_UL))
uFlip = uFlip | ((uFlip & 0x40)<<1);
state[32] = uFlip & 0x10 ? 1.0f : 0.0f;
state[33] = uFlip & 0x20 ? 1.0f : 0.0f;
state[34] = uFlip & 0x40 ? 1.0f : 0.0f;
state[35] = uFlip & 0x80 ? 1.0f : 0.0f;
}
}
/*-- 37..44, extra solenoids --*/
if (core_gameData->gen & (GEN_WPC95 | GEN_WPC95DCS)) { // 37-44 WPC95 extra (duplicated 37..40 / 41..44)
for (int i = 28; i < 32; i++)
{
for (int i = 28; i < 32; i++) {
state[i + 8] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value;
state[i + 12] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value;
}
}
else if (core_gameData->gen & (GEN_ALLS11 | GEN_SAM | GEN_SPA)) // 37-44 S11, SAM extra
for (int i = 40; i < 48; i++)
state[i - 4] = coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value;
/*-- 45..48 lower flipper solenoids (not modulated for the time being) --*/
{
/*-- 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;
Expand Down Expand Up @@ -1942,6 +1954,7 @@ static MACHINE_INIT(core) {
if(((core_gameData->gen & GEN_GTS3) && GTS3locals.alphagen) || (core_gameData->gen & (GEN_WPCALPHA_1 | GEN_WPCALPHA_2)))
options.usemodsol |= CORE_MODOUT_ENABLE_PHYSOUT_ALPHASEGS; // use CORE_MODOUT_ENABLE_PHYSOUT_ALL to enable/test all physical/PWM outputs
#endif
options.usemodsol |= CORE_MODOUT_ENABLE_PHYSOUT_ALL; // For debugging

/*-- init bulb model LUTs --*/
bulb_init();
Expand Down
70 changes: 37 additions & 33 deletions src/wpc/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,41 +231,45 @@ typedef struct core_dispLayout core_tLCDLayout, *core_ptLCDLayout;
#define PINMAME_VIDEO_UPDATE(name) int (name)(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout)
typedef int (*ptPinMAMEvidUpdate)(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout);

/*----------------------
/*---------------------------------------
/ WPC driver constants
/--------------------------------*/
/* Solenoid numbering */
/* */
/* WPC */
/* 1-28 Standard */
/* 33-36 Upper flipper solenoids */
/* 37-40 Standard (WPC95 only) */
/* 41-44 - "" - Copy of above */
/* 45-48 Lower flipper solenoids */
/* 49-50 Simulated */
/* 51-64 */
/* */
/* S9/S11 */
/* 1- 8 Standard 'A'-side */
/* 9-16 Standard */
/* 17-22 Special */
/* 23 Flipper & SS Enabled Sol (fake) */
/* 25-32 Standard 'C'-side */
/* 37-41 Sound overlay board */
/* */
/* S7 */
/* 1-16 Standard */
/* 17-24 Special */
/----------------------------------------*/
/* Solenoid numbering */
/* */
/* WPC */
/* 1-28 Standard */
/* 29-31 GameOn (3 highest bit of GI reg)*/
/* 32 Unused (always 0) */
/* 33-36 Upper flipper solenoids */
/* 37-40 LPDC WPC95 controlled outputs */
/* 41-44 Copy of 37-40 for backward comp.*/
/* 45-48 Lower flipper solenoids */
/* 49 Fake solenoid for ball shooter */
/* 50 Reserved */
/* 51-58 8 drivers Aux Board or custom */
/* 59-64 custom */
/* */
/* S9/S11 */
/* 1- 8 Standard 'A'-side */
/* 9-16 Standard */
/* 17-22 Special */
/* 23 Flipper & Switched Sol. Enable */
/* 25-32 Standard 'C'-side */
/* 37-41 Sound overlay board */
/* */
/* S7 */
/* 1-16 Standard */
/* 17-24 Special */
/* 25 Flipper & SS Enabled Sol (fake) */
/* */
/* BY17/BY35 */
/* 1-15 Standard Pulse */
/* 17-20 Standard Hold */
/* */
/* GTS80 */
/* 1- 9 Standard */
/* 10 GameOn (fake) */
/* 11 Tilt (for GI) (fake) */
/* */
/* BY17/BY35 */
/* 1-15 Standard Pulse */
/* 17-20 Standard Hold */
/* */
/* GTS80 */
/* 1- 9 Standard */
/* 10 GameOn (fake) */
/* 11 Tilt (for GI) (fake) */
#define CORE_FIRSTEXTSOL 37
#define CORE_FIRSTUFLIPSOL 33
#define CORE_FIRSTCUSTSOL 51
Expand Down
9 changes: 7 additions & 2 deletions src/wpc/sims/wpc/full/ss.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,9 @@ static sim_tSimData ssSimData = {
NULL /* no key conditions */
};

// Prototype 0.1 had a 16 LED Skull driver board assembly A-20781 which was not kept in production build
// This board is a simple 16 bit shift register made from 2x4094 and drivers.

static WRITE_HANDLER(parallel_0_out) {
coreGlobals.tmpLampMatrix[9] = core_revbyte(data);
core_write_pwm_output_8b(9 * 8, core_revbyte(data));
Expand All @@ -461,7 +464,9 @@ static core_tGameData ssGameData = {
GEN_WPC95, wpc_dispDMD,
{
FLIP_SW(FLIP_L | FLIP_U) | FLIP_SOL(FLIP_L),
0,2,0,0,0,1,0, // 2 extra lamp columns for the LEDs of rev. 0.1
// 2 extra lamp columns for the LEDs of rev. 0.1
// Why do we set gameSpecific1 as this is unused on WPC ?
/*swCol*/0,/*lampCol*/2,/*custSol*/0,/*soundBoard*/0,/*display*/0,/*gameSpecific1*/1,/*gameSpecific2*/0,
NULL, ss_handleMech, ss_getMech, ss_drawMech,
NULL
#ifdef ENABLE_MECHANICAL_SAMPLES
Expand All @@ -486,7 +491,7 @@ static mech_tInitData ss_wheelMech = {

static WRITE_HANDLER(ss_wpc_w) {
wpc_w(offset, data);
if (offset == WPC_SOLENOID1) {
if (offset == WPC_SOLENOID1) { // J110-3 AUX.LAMP DATA and J110-1 AUX.LAMP CLOCK
HC4094_data_w (0, GET_BIT5);
HC4094_clock_w(0, GET_BIT4);
HC4094_clock_w(1, GET_BIT4);
Expand Down
Loading

0 comments on commit d1d9125

Please sign in to comment.