Skip to content

Commit

Permalink
fix harmless warnings and some typos
Browse files Browse the repository at this point in the history
  • Loading branch information
toxieainc committed Jan 7, 2024
1 parent 36a25db commit 419c336
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 91 deletions.
19 changes: 12 additions & 7 deletions release/whatsnew.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,24 @@ Version 3.6 (XX XXth, 2024) - "Sounds good III"

Updated LISY support to 5.28-91 (Linux for Gottlieb System1 & System80, Bally, Atari, Williams and 'Home' Pinballs)

Fix Capcom crashes in 64bit builds, reworked Capcom timings allowing all tables to behave 'normally' (no more delay on Flipper Football, DMD's animation at the right speed,...).
Fix Capcom crashes in 64bit builds

Fix some external DMD alphanumeric mappings: GTS80B, GTS3, Hankin, Police Force, Riverboat Gambler, Algar, Alien Poker and 7 digit variants of Firepower

Added the emulation of physical bulbs & LEDs connected to binary outputs for WPC, GTS3, SAM, Whitestar 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 physic model for solenoid outputs, 4 is physic model for lamps/GIs/Segment outputs. To be emulated correctly,
device connected to binary output must be defined. PinMame already has teh 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).
This also opens the path for emulation of dimmed alphanum segments and strength modulated solenoids (for example Capcom Kingpin, or the way most modern hardware handle Power/Hold and EOS switch).
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
(for example Capcom Kingpin, or the way most modern hardware handle Power/Hold and EOS switch).

*** CORE/CPU ***
Fixed WPC General Illumination (GI) Dimming (most noticably if more than one GI line is involved, also all 8 levels are now handled properly)
Reworked Capcom emulation & timings, allowing all tables to behave 'normally' (no more delay on Flipper Football, DMD's animation at the right speed,...)
Added Cosmic Flash sound emulation (Bell stole it from Bally's Squalk&Talk, but removed speech and DAC chips)
Improved Zaccaria 11178 sound emulation a little (clown, poolcham, bbeltzac, mexico, zankor, spooky)
Fixed Zaccaria strsphnx sound, background music works correctly now
Expand Down
34 changes: 17 additions & 17 deletions src/wpc/capcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
09/21/03-09/24/03 - DMD working 100% incuding 256x64 size, switches, solenoids working on most games except kp, and ff
09/25/03 - First time game booted without any errors.. (Even though in reality, the U16 would still fail if not hacked around)
11/03/03 - First time sound was working almost fully (although still some glitches and much work left to do)
11/09/03 - 50V Line finally reports a voltage & KP,FF fire hi-volt solenoids
11/09/03 - 50V Line finally reports a voltage & KP,FF fire hi-volt solenoids
11/10/03 - Seem to have found decent IRQ4 freq. to allow KP & FF to fire sols 1 & 2 properly
11/15/03 - 68306 optimized & true address mappings implemented, major speed improvements!
11/15/03 - 68306 optimized & true address mappings implemented, major speed improvements!
Hacks & Issues that need to be looked into:
#1) Why do we need to adjust the CPU Speed to get the animations to display at correct speed? U16 related bug?
Expand Down Expand Up @@ -88,13 +88,13 @@
#include "sndbrd.h"

//Turn off when not testing mpg audio
#define TEST_MPGAUDIO 0
#define TEST_MPGAUDIO 0

// Define to get read/write log to U16
#define VERBOSE_U16 0

// Define to 1 to patch ROM to disable error messages
#define SKIP_ERROR_MSG 0
#define SKIP_ERROR_MSG 0

// Define to log lamp strobe timings
#define LOG_LAMP_STROBE 0
Expand Down Expand Up @@ -146,18 +146,18 @@ static INTERRUPT_GEN(cc_vblank) {
memset(coreGlobals.lampMatrix, 0, sizeof(coreGlobals.lampMatrix));
for (int i = 0; i < 8 + core_gameData->hw.lampCol; i++)
for (int j = 0; j < 8; j++)
if (coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + i * 8 + j].value >= 0.1)
if (coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + i * 8 + j].value >= 0.1f)
coreGlobals.lampMatrix[i] |= 1 << j;

/*-- solenoids --*/
coreGlobals.solenoids = 0;
for (int i = 0; i < 32; i++)
if (coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value >= 0.5)
if (coreGlobals.physicOutputState[CORE_MODOUT_SOL0 + i].value >= 0.5f)
coreGlobals.solenoids |= 1 << i;

/*-- update leds (they are PWM faded, so uses physic output) --*/
coreGlobals.diagnosticLed = (coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + 8 * 8 + (core_gameData->hw.lampCol - 1) * 8 ].value >= 0.5 ? 1 : 0)
| (coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + 8 * 8 + (core_gameData->hw.lampCol - 1) * 8 + 1].value >= 0.5 ? 2 : 0);
coreGlobals.diagnosticLed = (coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + 8 * 8 + (core_gameData->hw.lampCol - 1) * 8 ].value >= 0.5f ? 1 : 0)
| (coreGlobals.physicOutputState[CORE_MODOUT_LAMP0 + 8 * 8 + (core_gameData->hw.lampCol - 1) * 8 + 1].value >= 0.5f ? 2 : 0);

core_updateSw(TRUE);
}
Expand Down Expand Up @@ -196,7 +196,7 @@ static void cc_zeroCross(int data) {
//PA7 - GRESET (output only)
static READ16_HANDLER(cc_porta_r) {
int data = locals.parallelA & 0xCF;

// Hardware measure 5V DV and 50V DC voltage by performing pulses (using PULSE out signal) through a RC low pass filter (time constant is 363us, since it is a 11k resistor with a 33nF capacitor)
// then reading the binary compared value against voltage divided from 5V or 50V line. So we compute the voltage at the capacitor and perform the comparison like the hardware
// Some games seems to also have 5V line voltage with the same RC schematics as for 50V (f.e. in Airborne scematics but missing in Breakshot ones). There is no audit result for it.
Expand Down Expand Up @@ -253,7 +253,7 @@ static WRITE16_HANDLER(cc_porta_w) {
if(data !=0x0048 && data !=0x0040 && data !=0x0008)
DBGLOG(("Port A write %04x\n",data));

// Bulletin service 95-010a states that the diag led should goes bright then dims 4 times per second => PWM integration on the diag LED...
// Bulletin service 95-010a states that the diag led should go bright then dims 4 times per second => PWM integration on the diag LED...
core_write_masked_pwm_output_8b(CORE_MODOUT_LAMP0 + 8 * 8 + (core_gameData->hw.lampCol - 1) * 8, (data & 0x08) >> 3, 0x01);

// Cabinet switch voltage level comparator (either comparator from +5V with 2.2k/1.2k =>1.76V or 2.2k/3.9k => 3.20V), not sure why
Expand Down Expand Up @@ -465,8 +465,8 @@ static WRITE16_HANDLER(u16_w) {

case 0x200: { // IRQ1 Frequency, IRQ4 line 1/2/3 enable
LOG_U16(("PC %08x - U16w IRQ1 f=%x IRQ4=%x [data@%03x=%04x] (%04x)\n", activecpu_get_pc(), (data >> 6) & 3, (data & 0x7) ^ 4, offset, data, mem_mask));
//int irq1NCycles[] = { 22662, 11308, 5631, 2789 }; // Number of CPU cycles taken from startup check disassembly (value without IRQ1 adjusting on ACK)
int irq1NCycles[] = { 22602, 11248, 5571, 2729 }; // Number of CPU cycles taken from startup check disassembly (value with IRQ1 adjusting on ACK)
//static const int irq1NCycles[] = { 22662, 11308, 5631, 2789 }; // Number of CPU cycles taken from startup check disassembly (value without IRQ1 adjusting on ACK)
static const int irq1NCycles[] = { 22602, 11248, 5571, 2729 }; // Number of CPU cycles taken from startup check disassembly (value with IRQ1 adjusting on ACK)
locals.u16IRQ1Period = TIME_IN_SEC(irq1NCycles[(data >> 6) & 3] / (double)CPU_CLOCK);
timer_adjust(locals.u16IRQ1timer, locals.u16IRQ1Adjust ? (locals.u16IRQ1Period * 120.0 / 165.0) : locals.u16IRQ1Period, 0, locals.u16IRQ1Adjust ? (locals.u16IRQ1Period * 120.0 / 165.0) : locals.u16IRQ1Period);
timer_adjust(locals.u16IRQ4Line1timer, locals.u16IRQ4Line1Period, 0, locals.u16IRQ4Line1Period);
Expand Down Expand Up @@ -689,12 +689,12 @@ static MACHINE_INIT(cc) {

// If wanted, we can skip the startup error messages by patching the rom (NOTE: MUST COME BEFORE WE COPY ROMS BELOW)
#if SKIP_ERROR_MSG
//NOTE: Due to the way we load the roms, the fixaddress values must remove the top 8th bit, ie,
// 0x10092192 becomes 0x00092192
//NOTE: Due to the way we load the roms, the fixaddress values must remove the top 8th bit, i.e.
// 0x10092192 becomes 0x00092192
UINT32 fixaddr = 0;
switch (core_gameData->hw.gameSpecific1) {
case 0: break;
case 1: case 2: fixaddr = 0x0009593c; break; //PM
case 1: case 2: fixaddr = 0x0009593c; break; //PM
case 3: fixaddr = 0x0008ce04; break; //AB
case 4: fixaddr = 0x00088204; break; //ABR
case 5: case 6: fixaddr = 0x0008eb60; break; //BS
Expand Down Expand Up @@ -750,7 +750,7 @@ static MACHINE_INIT(cc) {
core_set_pwm_output_type(CORE_MODOUT_SOL0 + 28 - 1, 5, CORE_MODOUT_BULB_89_20V_DC_WPC);
}
else if (strncasecmp(gn, "kpb105", 6) == 0) { // KingPin
// To be checked since this is from VPX table (did not found a manual for this one)
// To be checked since this is from VPX table (did not find a manual for this one)
coreGlobals.flipperCoils = 0xFFFFFFFFFFFF0908;
core_set_pwm_output_type(CORE_MODOUT_SOL0 + 18 - 1, 2, CORE_MODOUT_BULB_89_20V_DC_WPC);
core_set_pwm_output_type(CORE_MODOUT_SOL0 + 21 - 1, 11, CORE_MODOUT_BULB_89_20V_DC_WPC);
Expand Down Expand Up @@ -884,7 +884,7 @@ CS3 = 30000000-3001ffff (RW) - NVRAM
0 0 (40000000) - /AUX I-O => Power Driver Board - Lamp matrices (and strobed switch matrix for Breakshot)
0 1 (40400000) - /EXT I-O => Power Driver Board - Solenoids / Switch Board (not present for Breakshot)
1 0 (40800000) - /SWITCH0 => 16 Cabinet switches
1 1 (40c00000) - /CS => U16 custom chip
1 1 (40c00000) - /CS => U16 custom chip
*/
static MEMORY_READ16_START(cc_readmem)
{ 0x00000000, 0x0007ffff, MRA16_RAM }, /* DRAM */
Expand Down
2 changes: 1 addition & 1 deletion src/wpc/capgames.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "sndbrd.h"

// CPU controlled flipper coils. Fast flips are also provided but are not 100% correct since the hardware is CPU controlled and pulse modulated
#define FLIP FLIP_SWNO(5,6) + FLIP_SOL(FLIP_LL | FLIP_LR | FLIP_UR | FLIP_UL)
#define FLIP (FLIP_SWNO(5,6) + FLIP_SOL(FLIP_LL | FLIP_LR | FLIP_UR | FLIP_UL))

/*-- DMD 128 X 32 --*/
const core_tLCDLayout cc_dispDMD128x32[] = {
Expand Down
50 changes: 23 additions & 27 deletions src/wpc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void vp_setDIP(int bank, int value) { }
extern void libpinmame_update_display(const int index, const struct core_dispLayout* p_layout, const void* p_data);
#endif

INLINE UINT8 saturatedByte(double v) { return (UINT8)(255.0 * (v < 0.0 ? 0.0 : v > 1.0 ? 1.0 : v)); }
INLINE UINT8 saturatedByte(float v) { return (UINT8)(255.0f * (v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v)); }

static void drawChar(struct mame_bitmap *bitmap, int row, int col, UINT32 bits, int type, int dimming);
static UINT32 core_initDisplaySize(const struct core_dispLayout *layout);
Expand Down Expand Up @@ -1230,12 +1230,8 @@ static void updateDisplay(struct mame_bitmap *bitmap, const struct rectangle *cl

//

#ifdef VPINMAME
memset(AlphaNumericFrameBuffer,0x00,2048);
#endif

#ifdef LIBPINMAME
memset(AlphaNumericFrameBuffer,0x00,4096);
#if defined(VPINMAME) || defined(LIBPINMAME)
memset(AlphaNumericFrameBuffer,0,sizeof(AlphaNumericFrameBuffer));
#endif

switch (alpha_layout) {
Expand Down Expand Up @@ -1474,7 +1470,7 @@ void core_updateSw(int flipEn) {
float state[CORE_MODOUT_SOL_MAX];
core_getAllPhysicSols(state);
for (ii = 0; ii < coreGlobals.nSolenoids; ii++) {
UINT8 v = saturatedByte(state[ii]);
UINT8 v = saturatedByte(state[ii]);
if (v != locals.lastPhysicsOutput[CORE_MODOUT_SOL0 + ii]) {
#ifdef LIBPINMAME
OnSolenoid(ii + 1, v);
Expand Down Expand Up @@ -1503,11 +1499,11 @@ void core_updateSw(int flipEn) {
}
else {
UINT64 allSol = core_getAllSol();
UINT64 chgSol = (allSol ^ locals.lastSol) & vp_getSolMask64();
UINT64 chgSol = (allSol ^ locals.lastSol) & vp_getSolMask64();
locals.lastSol = allSol;
for (ii = 0; ii < CORE_FIRSTCUSTSOL + core_gameData->hw.custSol - 1; ii++)
{
if (chgSol & 0x01) {
for (ii = 0; ii < CORE_FIRSTCUSTSOL + core_gameData->hw.custSol - 1; ii++)
{
if (chgSol & 0x01) {
OnSolenoid(ii + 1, allSol & 0x01);
/*-- log solenoid number on the display (except flippers) --*/
if ((!pmoptions.dmd_only && (allSol & 0x01)) && ((ii < CORE_FIRSTLFLIPSOL) || (ii >= CORE_FIRSTSIMSOL))) {
Expand All @@ -1524,9 +1520,9 @@ void core_updateSw(int flipEn) {
proc_mechsounds(ii, allSol & 0x01);
#endif
}
chgSol >>= 1;
allSol >>= 1;
}
chgSol >>= 1;
allSol >>= 1;
}
}

/*-- check if we should use simulator keys --*/
Expand Down Expand Up @@ -2085,7 +2081,7 @@ typedef struct {
{
int type; /* bulb physical characteristics */
int isAC; /* AC or DC ? */
float U; /* voltage (Volts) */
float U; /* voltage (Volts) */
float serial_R; /* serial resistor (Ohms) */
} bulb;
};
Expand Down Expand Up @@ -2216,7 +2212,7 @@ static MACHINE_INIT(core) {
coreOutputinfos[CORE_MODOUT_PULSE].minPWMIntegrationTime = 0.0f;
// binary output: fire as soon as a low to high transition is found, then go low if low and not pulsed
coreOutputinfos[CORE_MODOUT_SOL_2_STATE].minPWMIntegrationTime = 0.001f;
// legacy binary output: like CORE_MODOUT_SOL_2_STATE but with legacy behavior of delaying the state by a few 'VBlank's (also used to have a bug on WPC which would only check if not pulsed but not base state)
// legacy binary output: like CORE_MODOUT_SOL_2_STATE but with legacy behavior of delaying the state by a few 'VBlank's (also used to have a bug on WPC which would only check if not pulsed but not base state)
coreOutputinfos[CORE_MODOUT_LEGACY_SOL_2_STATE].minPWMIntegrationTime = 0.001f;
// legacy binary output: return binary value for driver's getSol function
coreOutputinfos[CORE_MODOUT_LEGACY_SOL_CUSTOM].minPWMIntegrationTime = 0.0f;
Expand Down Expand Up @@ -2513,7 +2509,7 @@ void core_update_pwm_output(float now, int index, int isFlip)
const int state = (coreGlobals.binaryOutputState[index >> 3] >> (index & 7)) & 1;
output->elapsedInStateTime[state] += (now - output->dataTimestamp);
output->dataTimestamp = now;

const float elapsedSinceLastFlip = now - output->lastFlipTimestamp;
const float minPWMIntegrationTime = coreOutputinfos[output->type].minPWMIntegrationTime;
float integrationLength = output->elapsedInStateTime[0] + output->elapsedInStateTime[1];
Expand All @@ -2536,14 +2532,14 @@ void core_update_pwm_output(float now, int index, int isFlip)
else if (integrationLength < minPWMIntegrationTime)
{
// Perform only the basic state accumulation for performance reasons
// This avoid doing full physics model integration for each state change on fast controllers like Capcom or SAM hardware
return;
// This avoid doing full physics model integration for each state change on fast controllers like Capcom or SAM hardware
return;
}
else if (elapsedSinceLastFlip < integrationLength) // integrationLength is >= minPWMIntegrationTime but last flip happened inside the integration period
{
// Last flip happened in this integration period: perform integration up to the last flip event (to align on end of pulse if applicable), keeping the remaining for later integration
now -= elapsedSinceLastFlip;
integrationLength -= elapsedSinceLastFlip;
now -= elapsedSinceLastFlip;
integrationLength -= elapsedSinceLastFlip;
output->elapsedInStateTime[state] -= elapsedSinceLastFlip;
pwmDutyCycle = output->elapsedInStateTime[1] / integrationLength;
output->elapsedInStateTime[1 - state] = 0.0f;
Expand All @@ -2570,14 +2566,14 @@ void core_update_pwm_output(float now, int index, int isFlip)
output->value = (float)state;
break;
case CORE_MODOUT_SOL_2_STATE: {
// Apply the legacy solenoid behavior but directly updating coreGlobals on state change avoiding the latency of legacy implementation
// Apply the legacy solenoid behavior but directly updating coreGlobals on state change avoiding the latency of legacy implementation
// (which used to handle PWM by 'or'ing solenoids states for a few 'VBlank's then deliver them, 'VBlank' being a custom 60Hz interrupt not corresponding to any hardware)
double prevValue = output->value;
double prevValue = output->value;
if (isFlip && state == 0) {
// If binary output is flipping to ON state, immediatly retain the ON state
output->value = 1.0f;
}
else if ((now - coreGlobals.physicOutputState[index].lastFlipTimestamp) > 0.060f) {
else if ((now - coreGlobals.physicOutputState[index].lastFlipTimestamp) > 0.060f) {
// Output is in a stable state (not PWMed since at least 60ms), just report its value
// TODO 60ms is likely too much. For example for Stern SAM, the sequence is 40ms pulse to lift flipper then 1ms pulse every 12ms to hold.
output->value = (float)state;
Expand Down Expand Up @@ -2665,7 +2661,7 @@ void core_update_pwm_output(float now, int index, int isFlip)
const float dt = integrationLength < minPWMIntegrationTime ? integrationLength : minPWMIntegrationTime;
// Keeps T within the range of the LUT (between room temperature and melt down point)
output->state.bulb.filament_temperature = output->state.bulb.filament_temperature < 293.0f ? 293.0f : output->state.bulb.filament_temperature > (float) BULB_T_MAX ? (float) BULB_T_MAX : output->state.bulb.filament_temperature;
const float Ut = isAC ? (1.41421356f * sinf(60.0f * 2.0f * (float) PI * (integrationTime - coreGlobals.lastACZeroCrossTimeStamp)) * U) : U;
const float Ut = isAC ? (1.41421356f * sinf((float)(60.0 * 2.0 * PI) * (integrationTime - coreGlobals.lastACZeroCrossTimeStamp)) * U) : U;
const float dT = dt * (float) bulb_heat_up_factor(bulb, output->state.bulb.filament_temperature, Ut, serial_R);
output->state.bulb.filament_temperature += dT < 1000.0f ? dT : 1000.0f;
core_eye_flicker_fusion(output, dt, (float) bulb_filament_temperature_to_emission(output->state.bulb.filament_temperature));
Expand Down Expand Up @@ -2709,7 +2705,7 @@ void core_update_pwm_output(float now, int index, int isFlip)
}

// Called periodically to perform PWM integration on all outputs.
// This is needed if we need multithreaded access to the output state like for VPinMame since integration is not thread safe.
// This is needed if we need multithreaded access to the output state like for VPinMAME since integration is not thread safe.
void core_update_pwm_outputs(int unused)
{
float now = (float) timer_get_time();
Expand Down
Loading

0 comments on commit 419c336

Please sign in to comment.