ColecoHawk: Fix turbo controller

This commit is contained in:
alyosha-tas 2018-03-08 19:58:38 -05:00
parent 900a9e5322
commit 1cd82aa5d9
5 changed files with 254 additions and 94 deletions

View File

@ -44,27 +44,24 @@ namespace BizHawk.Emulation.Cores.ColecoVision
Definition.FloatRanges.AddRange(Port2.Definition.FloatRanges);
}
private int wheel1;
private int wheel2;
public float wheel1;
public float wheel2;
public float temp_wheel1;
public float temp_wheel2;
public byte ReadPort1(IController c, bool leftMode, bool updateWheel)
{
if (updateWheel)
{
wheel1 = Port1.UpdateWheel(c, wheel1);
}
wheel1 = Port1.UpdateWheel(c);
return Port1.Read(c, leftMode, wheel1);
return Port1.Read(c, leftMode, updateWheel, temp_wheel1);
}
public byte ReadPort2(IController c, bool leftMode, bool updateWheel)
{
if (updateWheel)
{
wheel2 = Port2.UpdateWheel(c, wheel2);
}
wheel2 = Port2.UpdateWheel(c);
return Port2.Read(c, leftMode, wheel2);
return Port2.Read(c, leftMode, updateWheel, temp_wheel2);
}
public ControllerDefinition Definition { get; }
@ -72,12 +69,12 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public void SyncState(Serializer ser)
{
ser.BeginSection("Port1");
ser.Sync("Wheel 1", ref wheel1);
Port1.SyncState(ser);
ser.Sync("temp_wheel1", ref temp_wheel1);
ser.EndSection();
ser.BeginSection("Port2");
ser.Sync("Wheel 2", ref wheel2);
ser.Sync("temp_wheel2", ref temp_wheel2);
Port2.SyncState(ser);
ser.EndSection();
}

View File

@ -13,9 +13,9 @@ namespace BizHawk.Emulation.Cores.ColecoVision
/// </summary>
public interface IPort
{
byte Read(IController c, bool leftMode, int wheel);
byte Read(IController c, bool leftMode, bool updateWheel, float wheelAngle);
int UpdateWheel(IController c, int wheel);
float UpdateWheel(IController c);
ControllerDefinition Definition { get; }
@ -36,7 +36,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
};
}
public byte Read(IController c, bool left_mode, int wheel)
public byte Read(IController c, bool left_mode, bool updateWheel, float wheelAngle)
{
return 0x7F; // needs checking
}
@ -50,7 +50,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public int PortNum { get; }
public int UpdateWheel(IController c, int wheel)
public float UpdateWheel(IController c)
{
return 0;
}
@ -72,7 +72,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public int PortNum { get; }
public byte Read(IController c, bool leftMode, int wheel)
public byte Read(IController c, bool leftMode, bool updateWheel, float wheelAngle)
{
if (leftMode)
{
@ -124,7 +124,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
"Key 6", "Key 7", "Key 8", "Key 9", "Pound", "Star"
};
public int UpdateWheel(IController c, int wheel)
public float UpdateWheel(IController c)
{
return 0;
}
@ -150,7 +150,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public ControllerDefinition Definition { get; }
public byte Read(IController c, bool leftMode, int wheel)
public byte Read(IController c, bool leftMode, bool updateWheel, float wheelAngle)
{
if (leftMode)
{
@ -160,8 +160,45 @@ namespace BizHawk.Emulation.Cores.ColecoVision
int x = (int)c.GetFloat(Definition.FloatControls[0]);
int y = (int)c.GetFloat(Definition.FloatControls[1]);
retval |= CalcDirection(x, y);
float angle;
if (updateWheel)
{
angle = wheelAngle;
}
else
{
angle = CalcDirection(x, y);
}
byte temp2 = 0;
int temp1 = (int)Math.Floor(angle / 1.25);
temp1 = temp1 % 4;
if (temp1 == 0)
{
temp2 = 0x10;
}
if (temp1 == 1)
{
temp2 = 0x30;
}
if (temp1 == 2)
{
temp2 = 0x20;
}
if (temp1 == 3)
{
temp2 = 0x00;
}
retval |= temp2;
return retval;
}
else
@ -171,7 +208,44 @@ namespace BizHawk.Emulation.Cores.ColecoVision
int x = (int)c.GetFloat(Definition.FloatControls[0]);
int y = (int)c.GetFloat(Definition.FloatControls[1]);
retval |= CalcDirection(x, y);
float angle;
if (updateWheel)
{
angle = wheelAngle;
}
else
{
angle = CalcDirection(x, y);
}
byte temp2 = 0;
int temp1 = (int)Math.Floor(angle / 1.25);
temp1 = temp1 % 4;
if (temp1 == 0)
{
temp2 = 0x10;
}
if (temp1 == 1)
{
temp2 = 0x30;
}
if (temp1 == 2)
{
temp2 = 0x20;
}
if (temp1 == 3)
{
temp2 = 0x00;
}
retval |= temp2;
return retval;
}
@ -190,36 +264,30 @@ namespace BizHawk.Emulation.Cores.ColecoVision
// x and y are both assumed to be in [-127, 127]
// x increases from left to right
// y increases from top to bottom
private static byte CalcDirection(int x, int y)
private static float CalcDirection(int x, int y)
{
y = -y; // vflip to match the arrangement of FloatControllerButtons
if (y >= 0 && x > 0)
// the wheel is arranged in a grey coded configuration of sensitivity ~2.5 degrees
// for each signal
// so overall the value returned changes every 1.25 degrees
float angle = (float)(Math.Atan2(y, x) * 180.0/Math.PI);
if (angle < 0)
{
return 0x10;
angle = 360 + angle;
}
if (y >= 0 && x <= 0)
{
return 0x30;
}
if (y < 0 && x <= 0)
{
return 0x20;
}
if (y < 0 && x > 0)
{
return 0x00;
}
Console.WriteLine("Error");
return 0x1F;
return angle;
}
public int UpdateWheel(IController c, int wheel)
public float UpdateWheel(IController c)
{
return 0;
int x = (int)c.GetFloat(Definition.FloatControls[0]);
int y = (int)c.GetFloat(Definition.FloatControls[1]);
return CalcDirection(x, y);
}
}
@ -243,7 +311,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public ControllerDefinition Definition { get; private set; }
public byte Read(IController c, bool left_mode, int wheel)
public byte Read(IController c, bool left_mode, bool updateWheel, float wheelAngle)
{
if (left_mode)
{
@ -254,7 +322,45 @@ namespace BizHawk.Emulation.Cores.ColecoVision
if (c.IsPressed(Definition.BoolButtons[3])) retval &= 0xF7;
if (c.IsPressed(Definition.BoolButtons[4])) retval &= 0x3F;
retval |= CalcDirection(wheel);
int x = (int)c.GetFloat(Definition.FloatControls[0]);
int y = (int)c.GetFloat(Definition.FloatControls[1]);
float angle;
if (updateWheel)
{
angle = wheelAngle;
}
else
{
angle = CalcDirection(x, y);
}
byte temp2 = 0;
int temp1 = (int)Math.Floor(angle / 1.25);
temp1 = temp1 % 4;
if (temp1 == 0)
{
temp2 = 0x10;
}
if (temp1 == 1)
{
temp2 = 0x30;
}
if (temp1 == 2)
{
temp2 = 0x20;
}
if (temp1 == 3)
{
temp2 = 0x00;
}
retval |= temp2;
return retval;
}
@ -300,53 +406,30 @@ namespace BizHawk.Emulation.Cores.ColecoVision
"Purple", "Blue"
};
// positive x represents spinning to the right, negative spinning to the left
private static byte CalcDirection(int wheel)
// x and y are both assumed to be in [-127, 127]
// x increases from left to right
// y increases from top to bottom
private static float CalcDirection(int x, int y)
{
byte retval = 0;
y = -y; // vflip to match the arrangement of FloatControllerButtons
if (wheel >= 0 && wheel < 180)
// the wheel is arranged in a grey coded configuration of sensitivity ~2.5 degrees
// for each signal
// so overall the value returned changes every 1.25 degrees
float angle = (float)(Math.Atan2(y, x) * 180.0 / Math.PI);
if (angle < 0)
{
retval = 0x00;
angle = 360 + angle;
}
if (wheel >= 180 && wheel < 360)
{
retval = 0x10;
}
if (wheel < 0 && wheel > -180)
{
retval = 0x20;
}
if (wheel <= -180 && wheel > -360)
{
retval = 0x30;
}
return retval;
return angle;
}
public int UpdateWheel(IController c, int wheel)
public float UpdateWheel(IController c)
{
int x = (int)c.GetFloat(Definition.FloatControls[0]);
int diff = -x;
wheel += diff;
if (wheel >= 360)
{
wheel = wheel - 360;
}
if (wheel <= -360)
{
wheel = wheel + 360;
}
return wheel;
return 0;
}
}
}

View File

@ -1,5 +1,6 @@
using BizHawk.Emulation.Common;
using BizHawk.Common.NumberExtensions;
using System;
namespace BizHawk.Emulation.Cores.ColecoVision
{
@ -25,8 +26,8 @@ namespace BizHawk.Emulation.Cores.ColecoVision
}
_frame++;
_isLag = true;
_isLag = true;
if (_tracer.Enabled)
{
_cpu.TraceCallback = s => _tracer.Put(s);
@ -35,10 +36,42 @@ namespace BizHawk.Emulation.Cores.ColecoVision
{
_cpu.TraceCallback = null;
}
byte tempRet1 = ControllerDeck.ReadPort1(controller, true, true);
byte tempRet2 = ControllerDeck.ReadPort2(controller, true, true);
byte tempRet1 = ControllerDeck.ReadPort1(controller, true, false);
byte tempRet2 = ControllerDeck.ReadPort2(controller, true, false);
bool intPending = (!tempRet1.Bit(4)) | (!tempRet2.Bit(4));
bool intPending = false;
// the return values represent the controller's current state, but the sampling rate is not high enough
// to catch all changes in wheel orientation
// so we use the wheel variable and interpolate between frames
// first determine how many degrees the wheels changed, and how many regions have been traversed
float change1 = (float)(((ControllerDeck.wheel1 - ControllerDeck.temp_wheel1) % 180) / 1.25);
float change2 = (float)(((ControllerDeck.wheel2 - ControllerDeck.temp_wheel2) % 180) / 1.25);
// special cases
if ((ControllerDeck.temp_wheel1 > 270) && (ControllerDeck.wheel1 < 90))
{
change1 = (float)((ControllerDeck.wheel1 + (360 - ControllerDeck.temp_wheel1)) / 1.25);
}
if ((ControllerDeck.wheel1 > 270) && (ControllerDeck.temp_wheel1 < 90))
{
change1 = -(float)((ControllerDeck.temp_wheel1 + (360 - ControllerDeck.wheel1)) / 1.25);
}
if ((ControllerDeck.temp_wheel2 > 270) && (ControllerDeck.wheel2 < 90))
{
change2 = (float)((ControllerDeck.wheel2 + (360 - ControllerDeck.temp_wheel2)) / 1.25);
}
if ((ControllerDeck.wheel2 > 270) && (ControllerDeck.temp_wheel2 < 90))
{
change2 = -(float)((ControllerDeck.temp_wheel2 + (360 - ControllerDeck.wheel2)) / 1.25);
}
int changes_1 = change1 > 0 ? (int)Math.Floor(change1) : (int)Math.Ceiling(change1);
int changes_2 = change2 > 0 ? (int)Math.Floor(change2) : (int)Math.Ceiling(change2);
for (int scanLine = 0; scanLine < 262; scanLine++)
{
@ -66,8 +99,45 @@ namespace BizHawk.Emulation.Cores.ColecoVision
}
}
// starting from scanline 20, changes to the wheel are added once per scanline (up to 144)
if (scanLine > 20)
{
if (changes_1 != 0)
{
if (changes_1 > 0)
{
ControllerDeck.temp_wheel1 = (float)((ControllerDeck.temp_wheel1 + 1.25) % 360);
changes_1--;
}
else
{
ControllerDeck.temp_wheel1 = (float)((ControllerDeck.temp_wheel1 - 1.25) % 360);
changes_1++;
}
}
if (changes_2 != 0)
{
if (changes_2 > 0)
{
ControllerDeck.temp_wheel2 = (float)((ControllerDeck.temp_wheel2 + 1.25) % 360);
changes_2--;
}
else
{
ControllerDeck.temp_wheel2 = (float)((ControllerDeck.temp_wheel2 - 1.25) % 360);
changes_2++;
}
}
}
tempRet1 = ControllerDeck.ReadPort1(controller, true, true);
tempRet2 = ControllerDeck.ReadPort2(controller, true, true);
intPending = (!tempRet1.Bit(4) && temp_1_prev) | (!tempRet2.Bit(4) && temp_2_prev);
_cpu.FlagI = false;
if (intPending && scanLine == 50)
if (intPending)
{
if (_vdp.EnableInterrupts)
{
@ -75,8 +145,14 @@ namespace BizHawk.Emulation.Cores.ColecoVision
intPending = false;
}
}
temp_1_prev = tempRet1.Bit(4);
temp_2_prev = tempRet2.Bit(4);
}
ControllerDeck.temp_wheel1 = ControllerDeck.wheel1;
ControllerDeck.temp_wheel2 = ControllerDeck.wheel2;
if (_isLag)
{
_lagCount++;

View File

@ -54,6 +54,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
ser.BeginSection("Coleco");
_vdp.SyncState(ser);
ControllerDeck.SyncState(ser);
PSG.SyncState(ser);
SGM_sound.SyncState(ser);
ser.Sync("UseSGM", ref use_SGM);
@ -69,6 +70,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
ser.Sync("Frame", ref _frame);
ser.Sync("LagCount", ref _lagCount);
ser.Sync("IsLag", ref _isLag);
ser.EndSection();
if (ser.IsReader)

View File

@ -71,6 +71,8 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public byte[] SGM_high_RAM = new byte[0x6000];
public byte[] SGM_low_RAM = new byte[0x2000];
public bool temp_1_prev, temp_2_prev;
private int _frame;
private IController _controller;
@ -245,13 +247,13 @@ namespace BizHawk.Emulation.Cores.ColecoVision
byte retval;
if (_inputPortSelection == InputPortMode.Left)
{
retval = ControllerDeck.ReadPort1(_controller, true, false);
retval = ControllerDeck.ReadPort1(_controller, true, true);
return retval;
}
if (_inputPortSelection == InputPortMode.Right)
{
retval = ControllerDeck.ReadPort1(_controller, false, false);
retval = ControllerDeck.ReadPort1(_controller, false, true);
return retval;
}
@ -264,13 +266,13 @@ namespace BizHawk.Emulation.Cores.ColecoVision
byte retval;
if (_inputPortSelection == InputPortMode.Left)
{
retval = ControllerDeck.ReadPort2(_controller, true, false);
retval = ControllerDeck.ReadPort2(_controller, true, true);
return retval;
}
if (_inputPortSelection == InputPortMode.Right)
{
retval = ControllerDeck.ReadPort2(_controller, false, false);
retval = ControllerDeck.ReadPort2(_controller, false, true);
return retval;
}