Fix up SMX PGEX to remove timing desync bugs and add second pad compatibility.
This commit is contained in:
parent
ecba99cd7e
commit
04636be072
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "olcPixelGameEngine.h"
|
#include "olcPixelGameEngine.h"
|
||||||
#include "SMX.h"
|
#include "SMX.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
using namespace olc;
|
using namespace olc;
|
||||||
|
|
||||||
@ -15,15 +16,17 @@ public:
|
|||||||
//LEFT is 0x08
|
//LEFT is 0x08
|
||||||
//Add these bytes together to get the combination (all 4 held down is 0xAA
|
//Add these bytes together to get the combination (all 4 held down is 0xAA
|
||||||
HWButton GetPanel(Key k,int pad=0)const{
|
HWButton GetPanel(Key k,int pad=0)const{
|
||||||
return panelState[k-UP];
|
return panelState[k-UP][pad];
|
||||||
};
|
};
|
||||||
void EnableLogMessages(bool enabled){
|
void EnableLogMessages(bool enabled){
|
||||||
logMessages=enabled;
|
logMessages=enabled;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
static bool logMessages;
|
static bool logMessages;
|
||||||
HWButton internal_panelState[4];
|
HWButton internal_panelState[4][2];
|
||||||
HWButton panelState[4]; //We store the 4 main panel states, similar to how PGE does.
|
HWButton panelState[4][2]; //We store the 4 main panel states, similar to how PGE does.
|
||||||
|
double totalElapsedTime{0.};
|
||||||
|
double nextLightUpdate{0.};
|
||||||
//SMX "screen" is 12x21
|
//SMX "screen" is 12x21
|
||||||
//Each panel is 4x7
|
//Each panel is 4x7
|
||||||
static void SMXStateChangedCallback(int pad, SMXUpdateCallbackReason reason, void *pUser)
|
static void SMXStateChangedCallback(int pad, SMXUpdateCallbackReason reason, void *pUser)
|
||||||
@ -44,31 +47,57 @@ private:
|
|||||||
{
|
{
|
||||||
if(logMessages){
|
if(logMessages){
|
||||||
printf("Device %i state changed: %04x\n", pad, SMX_GetInputState(pad));
|
printf("Device %i state changed: %04x\n", pad, SMX_GetInputState(pad));
|
||||||
|
printf("Device %i state changed: %04x\n", 1, SMX_GetInputState(1));
|
||||||
}
|
}
|
||||||
int16_t state(SMX_GetInputState(pad));
|
int16_t state(SMX_GetInputState(0));
|
||||||
if(state&0x2&&!internal_panelState[UP-UP].bPressed){
|
if(state&0x2&&!internal_panelState[UP-UP][0].bPressed){
|
||||||
internal_panelState[UP-UP]={true,false,true};
|
internal_panelState[UP-UP][0]={true,false,true};
|
||||||
}else
|
}else
|
||||||
if(!(state&0x2)&&!internal_panelState[UP-UP].bReleased){
|
if(!(state&0x2)&&!internal_panelState[UP-UP][0].bReleased){
|
||||||
internal_panelState[UP-UP]={false,true,false};
|
internal_panelState[UP-UP][0]={false,true,false};
|
||||||
}
|
}
|
||||||
if(state&0x20&&!internal_panelState[RIGHT-UP].bPressed){
|
if(state&0x20&&!internal_panelState[RIGHT-UP][0].bPressed){
|
||||||
internal_panelState[RIGHT-UP]={true,false,true};
|
internal_panelState[RIGHT-UP][0]={true,false,true};
|
||||||
}else
|
}else
|
||||||
if(!(state&0x20)&&!internal_panelState[RIGHT-UP].bReleased){
|
if(!(state&0x20)&&!internal_panelState[RIGHT-UP][0].bReleased){
|
||||||
internal_panelState[RIGHT-UP]={false,true,false};
|
internal_panelState[RIGHT-UP][0]={false,true,false};
|
||||||
}
|
}
|
||||||
if(state&0x80&&!internal_panelState[DOWN-UP].bPressed){
|
if(state&0x80&&!internal_panelState[DOWN-UP][0].bPressed){
|
||||||
internal_panelState[DOWN-UP]={true,false,true};
|
internal_panelState[DOWN-UP][0]={true,false,true};
|
||||||
}else
|
}else
|
||||||
if(!(state&0x80)&&!internal_panelState[DOWN-UP].bReleased){
|
if(!(state&0x80)&&!internal_panelState[DOWN-UP][0].bReleased){
|
||||||
internal_panelState[DOWN-UP]={false,true,false};
|
internal_panelState[DOWN-UP][0]={false,true,false};
|
||||||
}
|
}
|
||||||
if(state&0x8&&!internal_panelState[LEFT-UP].bPressed){
|
if(state&0x8&&!internal_panelState[LEFT-UP][0].bPressed){
|
||||||
internal_panelState[LEFT-UP]={true,false,true};
|
internal_panelState[LEFT-UP][0]={true,false,true};
|
||||||
}else
|
}else
|
||||||
if(!(state&0x8)&&!internal_panelState[LEFT-UP].bReleased){
|
if(!(state&0x8)&&!internal_panelState[LEFT-UP][0].bReleased){
|
||||||
internal_panelState[LEFT-UP]={false,true,false};
|
internal_panelState[LEFT-UP][0]={false,true,false};
|
||||||
|
}
|
||||||
|
state=SMX_GetInputState(1);
|
||||||
|
if(state&0x2&&!internal_panelState[UP-UP][1].bPressed){
|
||||||
|
internal_panelState[UP-UP][1]={true,false,true};
|
||||||
|
}else
|
||||||
|
if(!(state&0x2)&&!internal_panelState[UP-UP][1].bReleased){
|
||||||
|
internal_panelState[UP-UP][1]={false,true,false};
|
||||||
|
}
|
||||||
|
if(state&0x20&&!internal_panelState[RIGHT-UP][1].bPressed){
|
||||||
|
internal_panelState[RIGHT-UP][1]={true,false,true};
|
||||||
|
}else
|
||||||
|
if(!(state&0x20)&&!internal_panelState[RIGHT-UP][1].bReleased){
|
||||||
|
internal_panelState[RIGHT-UP][1]={false,true,false};
|
||||||
|
}
|
||||||
|
if(state&0x80&&!internal_panelState[DOWN-UP][1].bPressed){
|
||||||
|
internal_panelState[DOWN-UP][1]={true,false,true};
|
||||||
|
}else
|
||||||
|
if(!(state&0x80)&&!internal_panelState[DOWN-UP][1].bReleased){
|
||||||
|
internal_panelState[DOWN-UP][1]={false,true,false};
|
||||||
|
}
|
||||||
|
if(state&0x8&&!internal_panelState[LEFT-UP][1].bPressed){
|
||||||
|
internal_panelState[LEFT-UP][1]={true,false,true};
|
||||||
|
}else
|
||||||
|
if(!(state&0x8)&&!internal_panelState[LEFT-UP][1].bReleased){
|
||||||
|
internal_panelState[LEFT-UP][1]={false,true,false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,18 +108,29 @@ private:
|
|||||||
virtual bool OnBeforeUserUpdate(float& fElapsedTime){
|
virtual bool OnBeforeUserUpdate(float& fElapsedTime){
|
||||||
//We don't want the panel states changing in the middle of a frame, since the input polling is on a separate thread.
|
//We don't want the panel states changing in the middle of a frame, since the input polling is on a separate thread.
|
||||||
//Copy over the internal button states to the current panel state.
|
//Copy over the internal button states to the current panel state.
|
||||||
|
for(int pad=0;pad<2;pad++){
|
||||||
for(int i=0;i<4;i++){
|
for(int i=0;i<4;i++){
|
||||||
panelState[i]=internal_panelState[i];
|
panelState[i][pad]=internal_panelState[i][pad];
|
||||||
internal_panelState[i].bPressed=false;
|
internal_panelState[i][pad].bPressed=false;
|
||||||
internal_panelState[i].bReleased=false;
|
internal_panelState[i][pad].bReleased=false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnAfterUserUpdate(float fElapsedTime)override{
|
virtual void OnAfterUserUpdate(float fElapsedTime)override{
|
||||||
|
double previousTotalElapsedTime{totalElapsedTime};
|
||||||
|
totalElapsedTime=fmod(totalElapsedTime+fElapsedTime,10000.);
|
||||||
|
if(previousTotalElapsedTime>totalElapsedTime){
|
||||||
|
//We are in the past, so reset lastLightUpdate to keep lights running.
|
||||||
|
nextLightUpdate=totalElapsedTime;
|
||||||
|
}
|
||||||
|
if(nextLightUpdate>totalElapsedTime)return; //Ignore light updates if not enough time has passed. We can only send light updates at 30 FPS.
|
||||||
|
for(int pad=0;pad<2;pad++){
|
||||||
for(int i=0;i<4;i++){
|
for(int i=0;i<4;i++){
|
||||||
panelState[i].bPressed=false;
|
panelState[i][pad].bPressed=false;
|
||||||
panelState[i].bReleased=false;
|
panelState[i][pad].bReleased=false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::string lightData;
|
std::string lightData;
|
||||||
//The light data for an SMX dance pad is outlined in the docs but the code used to transform the PGE's pixels to SMX pad's lights will be annotated here.
|
//The light data for an SMX dance pad is outlined in the docs but the code used to transform the PGE's pixels to SMX pad's lights will be annotated here.
|
||||||
@ -105,7 +145,7 @@ private:
|
|||||||
col++;
|
col++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Pixel p(pge->GetDrawTarget()->GetPixel(x,y));
|
Pixel p(pge->GetDrawTarget()->GetPixel(x+12*pad,y));
|
||||||
lightData.append(1,p.r);
|
lightData.append(1,p.r);
|
||||||
lightData.append(1,p.g);
|
lightData.append(1,p.g);
|
||||||
lightData.append(1,p.b);
|
lightData.append(1,p.b);
|
||||||
@ -121,7 +161,7 @@ private:
|
|||||||
col++;
|
col++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Pixel p(pge->GetDrawTarget()->GetPixel(x,y));
|
Pixel p(pge->GetDrawTarget()->GetPixel(x+12*pad,y));
|
||||||
lightData.append(1,p.r);
|
lightData.append(1,p.r);
|
||||||
lightData.append(1,p.g);
|
lightData.append(1,p.g);
|
||||||
lightData.append(1,p.b);
|
lightData.append(1,p.b);
|
||||||
@ -131,6 +171,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(lightData.size()!=1350)throw;
|
||||||
|
nextLightUpdate=totalElapsedTime+1/30.f;
|
||||||
SMX_SetLights2( lightData.data(), lightData.size() );
|
SMX_SetLights2( lightData.data(), lightData.size() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<configSections>
|
<configSections>
|
||||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<section name="smx_config.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
<section name="smx_config.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
|
||||||
</sectionGroup>
|
</sectionGroup>
|
||||||
</configSections>
|
</configSections>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||||
</startup>
|
</startup>
|
||||||
<userSettings>
|
<userSettings>
|
||||||
<smx_config.Properties.Settings>
|
<smx_config.Properties.Settings>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
<value>False</value>
|
<value>False</value>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="CustomSensors" serializeAs="String">
|
<setting name="CustomSensors" serializeAs="String">
|
||||||
<value />
|
<value/>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="UseInnerSensorThresholds" serializeAs="String">
|
<setting name="UseInnerSensorThresholds" serializeAs="String">
|
||||||
<value>False</value>
|
<value>False</value>
|
||||||
|
2
smx-config/Properties/Resources.Designer.cs
generated
2
smx-config/Properties/Resources.Designer.cs
generated
@ -19,7 +19,7 @@ namespace smx_config.Properties {
|
|||||||
// class via a tool like ResGen or Visual Studio.
|
// class via a tool like ResGen or Visual Studio.
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// with the /str option, or rebuild your VS project.
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
internal class Resources {
|
internal class Resources {
|
||||||
|
2
smx-config/Properties/Settings.Designer.cs
generated
2
smx-config/Properties/Settings.Designer.cs
generated
@ -12,7 +12,7 @@ namespace smx_config.Properties {
|
|||||||
|
|
||||||
|
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")]
|
||||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>smx_config</RootNamespace>
|
<RootNamespace>smx_config</RootNamespace>
|
||||||
<AssemblyName>SMXConfig</AssemblyName>
|
<AssemblyName>SMXConfig</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
@ -29,6 +29,7 @@
|
|||||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
<UseApplicationTrust>false</UseApplicationTrust>
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user