Skip to content

Commit

Permalink
Add data exchange through a global shared state block
Browse files Browse the repository at this point in the history
This commits allows to share previously unshared data without overloading too much the API by adding a single data block for pulsed state, device state, modulated segments, video displays, multiple DMDs with raw DMD frames (for correct rendering and colorization).

This commit contains the skeleton and base implementation to set up the ground for more testing on client side  (VPX) when support will be more advanced there.
  • Loading branch information
vbousquet committed Feb 7, 2025
1 parent afa11cf commit d32d2e2
Show file tree
Hide file tree
Showing 22 changed files with 992 additions and 80 deletions.
1 change: 1 addition & 0 deletions cmake/libpinmame/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ set(PINMAME_SOURCES
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/pinmame/CMakeLists_win-x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ add_executable(pinmame WIN32
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/pinmame/CMakeLists_win-x86.txt
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ add_executable(pinmame WIN32
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/pinmame32/CMakeLists_win-x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ add_executable(pinmame32 WIN32
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/pinmame32/CMakeLists_win-x86.txt
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ add_executable(pinmame32 WIN32
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/vpinmame/CMakeLists_win-x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ add_library(vpinmame SHARED
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/vpinmame/CMakeLists_win-x86.txt
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ add_library(vpinmame SHARED
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/xpinmame/CMakeLists_linux-x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ add_executable(xpinmame
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
1 change: 1 addition & 0 deletions cmake/xpinmame/CMakeLists_osx-x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ add_executable(xpinmame
src/wpc/peyper.c
src/wpc/peyper.h
src/wpc/peypergames.c
src/libpinmame/pinmamedef.h
src/wpc/play.c
src/wpc/play.h
src/wpc/playgames.c
Expand Down
28 changes: 24 additions & 4 deletions src/libpinmame/libpinmame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ int StartGame(const int gameNum)
* PinmameGetGame
******************************************************/

PINMAMEAPI PINMAME_STATUS PinmameGetGame(const char* const p_name, PinmameGameCallback callback, const void* p_userData)
PINMAMEAPI PINMAME_STATUS PinmameGetGame(const char* const p_name, PinmameGameCallback callback, void* const p_userData)
{
if (!_p_Config)
return PINMAME_STATUS_CONFIG_NOT_SET;
Expand Down Expand Up @@ -686,7 +686,7 @@ PINMAMEAPI PINMAME_STATUS PinmameGetGame(const char* const p_name, PinmameGameCa
* PinmameGetGames
******************************************************/

PINMAMEAPI PINMAME_STATUS PinmameGetGames(PinmameGameCallback callback, const void* p_userData)
PINMAMEAPI PINMAME_STATUS PinmameGetGames(PinmameGameCallback callback, void* const p_userData)
{
if (!_p_Config)
return PINMAME_STATUS_CONFIG_NOT_SET;
Expand Down Expand Up @@ -886,6 +886,8 @@ PINMAMEAPI PINMAME_STATUS PinmameRun(const char* const p_name)
if (gameNum < 0)
return PINMAME_STATUS_GAME_NOT_FOUND;

OnStateChange(2); // Starting state

vp_init();

_p_gameThread = new std::thread(StartGame, gameNum);
Expand Down Expand Up @@ -1407,7 +1409,25 @@ PINMAMEAPI int PinmameGetChangedNVRAM(PinmameNVRAMState* const p_nvramStates)
* PinmameSetUserData
******************************************************/

PINMAMEAPI void PinmameSetUserData(const void* p_userData)
PINMAMEAPI void PinmameSetUserData(void* const p_userData)
{
_p_userData = (void*)p_userData;
}
}

/******************************************************
* PinmameGetStateBlock
******************************************************/

PINMAMEAPI int PinmameGetStateBlock(const unsigned int updateMask, pinmame_tMachineOutputState** pp_outputState)
{
if (!_isRunning)
return -1;

pinmame_tMachineOutputState* p_outputState = (pinmame_tMachineOutputState*)core_getOutputState(updateMask);
if (!p_outputState)
return -1;

*pp_outputState = p_outputState;

return 0;
}
38 changes: 22 additions & 16 deletions src/libpinmame/libpinmame.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#define PINMAME_MAX_MECHSW 20
#define PINMAME_ACCUMULATOR_SAMPLES 8192 // from mixer.c

#define UINT32 uint32_t
#define UINT8 uint8_t
#include "pinmamedef.h"

typedef enum {
PINMAME_LOG_LEVEL_DEBUG = 0,
PINMAME_LOG_LEVEL_INFO = 1,
Expand Down Expand Up @@ -394,19 +398,19 @@ typedef struct {
unsigned int standardcode;
} PinmameKeyboardInfo;

typedef void (PINMAMECALLBACK *PinmameGameCallback)(PinmameGame* p_game, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnStateUpdatedCallback)(int state, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnDisplayAvailableCallback)(int index, int displayCount, PinmameDisplayLayout* p_displayLayout, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnDisplayUpdatedCallback)(int index, void* p_displayData, PinmameDisplayLayout* p_displayLayout, const void* p_userData);
typedef int (PINMAMECALLBACK *PinmameOnAudioAvailableCallback)(PinmameAudioInfo* p_audioInfo, const void* p_userData);
typedef int (PINMAMECALLBACK *PinmameOnAudioUpdatedCallback)(void* p_buffer, int samples, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnMechAvailableCallback)(int mechNo, PinmameMechInfo* p_mechInfo, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnMechUpdatedCallback)(int mechNo, PinmameMechInfo* p_mechInfo, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnSolenoidUpdatedCallback)(PinmameSolenoidState* p_solenoidState, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnConsoleDataUpdatedCallback)(void* p_data, int size, const void* p_userData);
typedef int (PINMAMECALLBACK *PinmameIsKeyPressedFunction)(PINMAME_KEYCODE keycode, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnLogMessageCallback)(PINMAME_LOG_LEVEL logLevel, const char* format, va_list args, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameOnSoundCommandCallback)(int boardNo, int cmd, const void* p_userData);
typedef void (PINMAMECALLBACK *PinmameGameCallback)(PinmameGame* p_game, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnStateUpdatedCallback)(int state, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnDisplayAvailableCallback)(int index, int displayCount, PinmameDisplayLayout* p_displayLayout, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnDisplayUpdatedCallback)(int index, void* p_displayData, PinmameDisplayLayout* p_displayLayout, void* const p_userData);
typedef int (PINMAMECALLBACK *PinmameOnAudioAvailableCallback)(PinmameAudioInfo* p_audioInfo, void* const p_userData);
typedef int (PINMAMECALLBACK *PinmameOnAudioUpdatedCallback)(void* p_buffer, int samples, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnMechAvailableCallback)(int mechNo, PinmameMechInfo* p_mechInfo, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnMechUpdatedCallback)(int mechNo, PinmameMechInfo* p_mechInfo, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnSolenoidUpdatedCallback)(PinmameSolenoidState* p_solenoidState, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnConsoleDataUpdatedCallback)(void* p_data, int size, void* const p_userData);
typedef int (PINMAMECALLBACK *PinmameIsKeyPressedFunction)(PINMAME_KEYCODE keycode, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnLogMessageCallback)(PINMAME_LOG_LEVEL logLevel, const char* format, va_list args, void* const p_userData);
typedef void (PINMAMECALLBACK *PinmameOnSoundCommandCallback)(int boardNo, int cmd, void* const p_userData);

typedef struct {
const PINMAME_AUDIO_FORMAT audioFormat;
Expand All @@ -426,8 +430,8 @@ typedef struct {
PinmameOnSoundCommandCallback cb_OnSoundCommand;
} PinmameConfig;

PINMAMEAPI PINMAME_STATUS PinmameGetGame(const char* const p_name, PinmameGameCallback callback, const void* p_userData);
PINMAMEAPI PINMAME_STATUS PinmameGetGames(PinmameGameCallback callback, const void* p_userData);
PINMAMEAPI PINMAME_STATUS PinmameGetGame(const char* const p_name, PinmameGameCallback callback, void* const p_userData);
PINMAMEAPI PINMAME_STATUS PinmameGetGames(PinmameGameCallback callback, void* const p_userData);
PINMAMEAPI void PinmameSetConfig(const PinmameConfig* const p_config);
PINMAMEAPI void PinmameSetPath(const PINMAME_FILE_TYPE fileType, const char* const p_path);
PINMAMEAPI int PinmameGetCheat();
Expand Down Expand Up @@ -476,4 +480,6 @@ PINMAMEAPI void PinmameSetDIP(const int dipBank, const int value);
PINMAMEAPI int PinmameGetMaxNVRAM();
PINMAMEAPI int PinmameGetNVRAM(PinmameNVRAMState* const p_nvramStates);
PINMAMEAPI int PinmameGetChangedNVRAM(PinmameNVRAMState* const p_nvramStates);
PINMAMEAPI void PinmameSetUserData(const void* p_userData);
PINMAMEAPI void PinmameSetUserData(void* const p_userData);
PINMAMEAPI int PinmameGetStateBlock(const unsigned int updateMask, pinmame_tMachineOutputState** pp_outputState);

170 changes: 170 additions & 0 deletions src/libpinmame/pinmamedef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#pragma once

// This file contains definitions used inside PinMame and for external integration through libpinmame


///////////////////////////////////////////////////////////////////////////////
//
// Complete machine output state, provided in a global state block
//
// 0 length array is a non standard extension used intentionally here.
// Corresponding warning #4200 is therefore disabled when needed.
//

// Digital output instantaneous states

#pragma warning(disable : 4200)
typedef struct
{
double updateTimestamp;
unsigned int nOutputs;
UINT32 outputBitset[]; // Bitset array of nOutputs bits with their current binary state
} pinmame_tBinaryStates;


// Controlled device states

typedef enum {
PINMAME_DEVICE_STATE_TYPE_CUSTOM, // Custom state defined by each driver (value maybe either binary of 0/1 or 0/255, or modulated between 0..255)
PINMAME_DEVICE_STATE_TYPE_BULB, // Bulb state defined by its relative luminance and average filament temperature
PINMAME_DEVICE_STATE_TYPE_LED, // LED state defined by its relative luminance
PINMAME_DEVICE_STATE_TYPE_SOLENOID, // Solenoid (not yet defined)
PINMAME_DEVICE_STATE_TYPE_STEPPER, // Stepper motor (not yet defined)
} pinmame_tDeviceCategory;

typedef enum {
PINMAME_DEVICE_TYPE_UNDEFINED, // Hardware type identifier
PINMAME_DEVICE_TYPE_VFD_BLUE, // VFD used for segment display
PINMAME_DEVICE_TYPE_VFD_GREEN, // VFD used for segment display
PINMAME_DEVICE_TYPE_NEON_PLASMA, // Neon Plasma display (Panaplex, Burroughs,...) used for segment and dot matrix display
PINMAME_DEVICE_TYPE_LED_RED, //
} pinmame_tDeviceType;

typedef struct
{
pinmame_tDeviceCategory category;
pinmame_tDeviceType type;
unsigned int mapping; // Device mapping to a user understandable id (for example lamp matrix are usually numbered by row/column and not index)
union
{
// PINMAME_DEVICE_STATE_TYPE_CUSTOM
UINT8 customState; // Custom value, depending on each driver definition

// PINMAME_DEVICE_STATE_TYPE_BULB
struct
{
float luminance; // relative luminance to bulb rating (equals 1.f when bulb is under its rating voltage after heating stabilization)
float filamentTemperature; // perceived filament temperature (equals to bulb filament rating when bulb is at its rating voltage after heating stabilization)
} bulb;

// PINMAME_DEVICE_STATE_TYPE_LED
float ledLuminance; // relative luminance to bulb design (equals 1.f when LED is pulsed at its designed PWM)

// PINMAME_DEVICE_STATE_TYPE_SOLENOID
// To be added in a later revision

// PINMAME_DEVICE_STATE_TYPE_STEPPER
// To be added in a later revision
};
} pinmame_tDeviceState;

#pragma warning(disable : 4200)
typedef struct
{
double updateTimestamp;
unsigned int nDevices;
unsigned int stateByteSize; // sizeof(pinmame_tDeviceState), to be used to access states since the size of a single state my avolve in future revisions
pinmame_tDeviceState states[]; // array of nDevices * stateByteSize with the current device states
} pinmame_tDeviceStates;


// Alphanumeric segment displays

// Individual segment layouts inside a display (usually made of multiple elements)
typedef enum {
PINMAME_SEG_LAYOUT_7, // 7 segments
PINMAME_SEG_LAYOUT_7C, // 7 segments with comma
PINMAME_SEG_LAYOUT_7D, // 7 segments with dot
PINMAME_SEG_LAYOUT_9, // 9 segments
PINMAME_SEG_LAYOUT_9C, // 9 segments with comma
PINMAME_SEG_LAYOUT_14, // 14 segments
PINMAME_SEG_LAYOUT_14D, // 14 segments with dot
PINMAME_SEG_LAYOUT_14DC, // 14 segments with dot and comma
PINMAME_SEG_LAYOUT_16, // 16 segments
} pinmame_tSegElementType;

typedef struct
{
pinmame_tSegElementType type; // see PINMAME_SEG_LAYOUT_xxx
float luminance[16]; // relative luminance of each segment (from 7 to 16)
} pinmame_tAlphaSegmentState;

typedef struct
{
unsigned int nElements; // Number of elements (each element is composed of 7 to 16 segments)
pinmame_tDeviceType type; // Hardware reference (Panaplex, VFD, ...)
} pinmame_tAlphaDisplayDef;

#pragma warning(disable : 4200)
typedef struct
{
double updateTimestamp;
unsigned int nDisplays; // Number of displays (each display is composed of multiple elements)
pinmame_tAlphaDisplayDef displayDefs[]; // Definition of each display (number of elements, hardware type,...)
// pinmame_tAlphaSegmentState states[]; // State of each display element as a linear array
} pinmame_tAlphaStates;
#define PINMAME_STATE_BLOCK_FIRST_ALPHA_FRAME(pAlphaState) ((pinmame_tAlphaSegmentState*)((UINT8*)(pAlphaState) + sizeof(pinmame_tAlphaStates) + (pAlphaState->nDisplays) * sizeof(pinmame_tAlphaDisplayDef)))


// DMD and video displays

typedef enum {
PINMAME_FRAME_FORMAT_LUM, // Linear luminance (for monochrome DMD)
PINMAME_FRAME_FORMAT_RGB, // sRGB (for video frame)
PINMAME_FRAME_FORMAT_BP2, // 2 bitplanes, only used to identify frames
PINMAME_FRAME_FORMAT_BP4 // 4 bitplanes, only used to identify frames
} pinmame_tFrameDataFormat;

#pragma warning(disable : 4200)
typedef struct
{
unsigned int structSize; // Struct size including header and frame data in bytes (for safe DMD/Display array iteration)
unsigned int displayId; // Unique Id, shared between render frame and raw frame used for frame identification
double updateTimestamp;
unsigned int width;
unsigned int height;
pinmame_tFrameDataFormat dataFormat;
unsigned int frameId;
UINT8 frameData[]; // The display frame data which size depends on width, height and data format
} pinmame_tFrameState;

typedef struct
{
unsigned int nDisplays;
// pinmame_tFrameState displays[]; // Array of nDisplays * pinmame_tFrameState (can't be directly declared since frame size is undefined)
} pinmame_tDisplayStates;
#define PINMAME_STATE_BLOCK_FIRST_DISPLAY_FRAME(pDisplayState) ((pinmame_tFrameState*)((UINT8*)(pDisplayState) + sizeof(pinmame_tDisplayStates)))
#define PINMAME_STATE_BLOCK_NEXT_DISPLAY_FRAME(pFrameState) ((pinmame_tFrameState*)((UINT8*)(pFrameState) + (pFrameState)->structSize))


// Global output state block

typedef struct
{
unsigned int versionID; // Data block format version (current version
pinmame_tBinaryStates* controlledOutputBinaryStates; // Binary state (instantaneous state of controlled output)
pinmame_tDeviceStates* controlledDeviceStates; // Device state (state of the emulated device)
pinmame_tDeviceStates* lampMatrixStates; // State of emulated lamps powered from a strobed lamp matrix
pinmame_tAlphaStates* alphaDisplayStates; // State of alphanumeric segment displays
pinmame_tDisplayStates* displayStates; // State of displays and DMDs
pinmame_tDisplayStates* rawDMDStates; // Raw logic state of DMDs (stable view of the stae that can be used for frame identification)
} pinmame_tMachineOutputState;

#define PINMAME_STATE_REQMASK_GPOUTPUT_BINARY_STATE 0x01
#define PINMAME_STATE_REQMASK_GPOUTPUT_DEVICE_STATE 0x02
#define PINMAME_STATE_REQMASK_LAMP_DEVICE_STATE 0x04
#define PINMAME_STATE_REQMASK_ALPHA_DEVICE_STATE 0x08
#define PINMAME_STATE_REQMASK_DISPLAY_STATE 0x10
#define PINMAME_STATE_REQMASK_RAW_DMD_STATE 0x20
#define PINMAME_STATE_REQMASK_ALL 0x3F

Loading

0 comments on commit d32d2e2

Please sign in to comment.