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 prviously unshared data without overloading too much the API by adding a single data block for pulsed state, device state, modulated segments, multiple DMDs, raw DMD frames (for correct rendering and allow coloring) and video.

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 3, 2025
1 parent afa11cf commit ee5fc74
Show file tree
Hide file tree
Showing 9 changed files with 865 additions and 5 deletions.
33 changes: 33 additions & 0 deletions src/libpinmame/libpinmame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1410,4 +1410,37 @@ PINMAMEAPI int PinmameGetChangedNVRAM(PinmameNVRAMState* const p_nvramStates)
PINMAMEAPI void PinmameSetUserData(const void* p_userData)
{
_p_userData = (void*)p_userData;
}

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

PINMAMEAPI int PinmameGetStateBlock(PinMame::core_tGlobalOutputState** pp_outputState)
{
if (!_isRunning)
return -1;

PinMame::core_tGlobalOutputState* p_outputState = (PinMame::core_tGlobalOutputState*)core_getOutputState(CORE_STATE_REQMASK_ALL);
if (!p_outputState)
return -1;

*pp_outputState = p_outputState;

return 0;
}

/******************************************************
* PinmameUpdateStateBlock
******************************************************/

PINMAMEAPI int PinmameUpdateStateBlock(const unsigned int updateMask)
{
if (!_isRunning)
return -1;

if (!core_getOutputState(updateMask))
return -1;

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

namespace PinMame
{
#pragma warning(disable : 4200) // 0 length array is a non standard extension used intentionally, so disable corresponding warning
typedef struct
{
double updateTimestamp;
unsigned int nOutputs;
uint32_t outputBitset[]; // Bitset array of nOutputs bits with their current binary state
} core_tBinaryState;
#define CORE_DEVICE_STATE_TYPE_CUSTOM 1 // Custom state defined by each driver (value maybe either binary of 0/1 or 0/255, or modulated between 0..255)
#define CORE_DEVICE_STATE_TYPE_BULB 2 // Bulb state defined by its relative luminance and average filament temperature
#define CORE_DEVICE_STATE_TYPE_LED 3 // LED state defined by its relative luminance
#define CORE_DEVICE_STATE_TYPE_SEGMENTS 4 // LED or VFD state defined by a segment layout and the relative luminance of each segment
typedef struct
{
unsigned int deviceType;
union
{
// CORE_DEVICE_STATE_TYPE_DS
uint8_t customState; // Custom value, depending on each driver definition
// CORE_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 under its rating voltage after heating stabilization)
} bulb;
// CORE_DEVICE_STATE_TYPE_LED
float ledLuminance; // relative luminance to bulb design (equals 1.f when LED is pulsed at its designed PWM)
// CORE_DEVICE_STATE_TYPE_SEGMENTS
struct
{
unsigned int type; // see CORE_SEG16, ...
float luminance[16]; // relative luminance of each segment (from 7 to 16)
} segment;
};
} core_tDeviceSingleState;
#pragma warning(disable : 4200) // 0 length array is a non standard extension used intentionally, so disable corresponding warning
typedef struct
{
double updateTimestamp;
unsigned int nDevices;
unsigned int dataStride;
core_tDeviceSingleState states[]; // array of nDevices * dataStride with the current device state
} core_tDeviceState;
#define CORE_FRAME_LUM 1 // Linear luminance (for monochrome DMD)
#define CORE_FRAME_RGB 2 // sRGB (for video frame)
#define CORE_FRAME_BP2 3 // 2 bitplanes, used to identify frames
#define CORE_FRAME_BP4 4 // 4 bitplanes, used to identify frames
#pragma warning(disable : 4200) // 0 length array is a non standard extension used intentionally, so disable corresponding warning
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;
unsigned int dataFormat;
unsigned int frameId;
uint8_t frameData[]; // The display frame data which size depends on width, height and data format
} core_tFrameState;
typedef struct
{
unsigned int nDisplays;
// core_tFrameState displays[]; // Array of nDisplays * core_tFrameState (can't be directly declared since frame size is undefined)
} core_tDisplayState;
typedef struct
{
unsigned int versionID;
core_tBinaryState* controlledOutputBinaryState;
core_tDeviceState* controlledOutputDeviceState;
core_tDeviceState* lampMatrixState;
core_tDeviceState* alphaDisplayState;
core_tDisplayState* displayState;
core_tDisplayState* rawDMDState;
} core_tGlobalOutputState;

#define CORE_STATE_REQMASK_GPOUTPUT_BINARY_STATE 0x01
#define CORE_STATE_REQMASK_GPOUTPUT_DEVICE_STATE 0x02
#define CORE_STATE_REQMASK_LAMP_DEVICE_STATE 0x04
#define CORE_STATE_REQMASK_ALPHA_DEVICE_STATE 0x08
#define CORE_STATE_REQMASK_DISPLAY_STATE 0x10
#define CORE_STATE_REQMASK_RAW_DMD_STATE 0x20
#define CORE_STATE_REQMASK_ALL 0x3F
};

typedef enum {
PINMAME_LOG_LEVEL_DEBUG = 0,
PINMAME_LOG_LEVEL_INFO = 1,
Expand Down Expand Up @@ -477,3 +562,6 @@ 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 int PinmameGetStateBlock(PinMame::core_tGlobalOutputState** pp_outputState);
PINMAMEAPI int PinmameUpdateStateBlock(const unsigned int updateMask);

30 changes: 30 additions & 0 deletions src/win32com/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,36 @@ STDMETHODIMP CController::put_TimeFence(double timeInS)
return S_OK;
}

/****************************************************************************
* IController.get_StateBlock: returns a shared memory block name which holds
* a global state block prepended by the memory block size as an unsigned int
****************************************************************************/
STDMETHODIMP CController::get_StateBlock(/*[out, retval]*/ BSTR* pVal)
{
if (!pVal)
return E_POINTER;
if (!Machine)
return E_FAIL;
if (core_getOutputState(CORE_STATE_REQMASK_ALL) == NULL)
return E_FAIL;
CComBSTR bsStateSharedMemName(TEXT("Local\\VPinMameStateBlock"));
*pVal = bsStateSharedMemName.Detach();
return S_OK;
}

/****************************************************************************
* IController.UpdateStateBlock: Update requested outputs of the global state
* block
****************************************************************************/
STDMETHODIMP CController::UpdateStateBlock(/*[in, defaultvalue(0x3F)]*/ unsigned int updateMask)
{
if (!Machine)
return E_FAIL;
if (core_getOutputState(updateMask) == NULL)
return E_FAIL;
return S_OK;
}

/****************************************************************************
* IController.Version (read-only): gets the program version of VPM
****************************************************************************/
Expand Down
3 changes: 3 additions & 0 deletions src/win32com/Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ DECLARE_PROTECT_FINAL_CONSTRUCT()
STDMETHOD(put_ModOutputType)(/*[in]*/ int output, /*[in]*/ int no, /*[in]*/ int newVal);

STDMETHOD(put_TimeFence)(/*[in]*/ double fenceIns);

STDMETHOD(get_StateBlock)(/*[out, retval]*/ BSTR* pVal);
STDMETHOD(UpdateStateBlock)(/*[in, defaultvalue(0x1F)]*/ unsigned int updateMask);
};

#endif // !defined(AFX_Controller_H__D2811491_40D6_4656_9AA7_8FF85FD63543__INCLUDED_)
2 changes: 2 additions & 0 deletions src/win32com/VPinMAME.idl
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ import "ocidl.idl";
[propget, id(88), helpstring("property ModOutputType")] HRESULT ModOutputType([in] int output, [in] int no, [out, retval] int *pVal);
[propput, id(88), helpstring("property ModOutputType")] HRESULT ModOutputType([in] int output, [in] int no, [in] int newVal);
[propput, id(89), helpstring("property TimeFence")] HRESULT TimeFence([in] double timeInS);
[propget, id(90), helpstring("property StateBlock")] HRESULT StateBlock([out, retval] BSTR* pVal);
[id(91), helpstring("method UpdateStateBlock")] HRESULT UpdateStateBlock([in, defaultvalue(0x3F)] unsigned int updateMask);
};

// WSHDlg and related interfaces
Expand Down
6 changes: 6 additions & 0 deletions src/wpc/byvidpin.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,12 @@ static VIDEO_STOP(byVP) {

static PINMAME_VIDEO_UPDATE(byVP_update) {
TMS9928A_refresh((core_gameData->hw.display ? 2 : 1), bitmap, 1);
struct rectangle bounds;
bounds.min_x = 0;
bounds.min_y = 0;
bounds.max_x = 192;
bounds.max_y = 256;
core_display_video_update(bitmap, &bounds, layout, 1);
return 0;
}

Expand Down
Loading

0 comments on commit ee5fc74

Please sign in to comment.