fix TIC80 inputs, wire up time/clock callbacks
This commit is contained in:
parent
1d4e7dd3fb
commit
84af66f523
Binary file not shown.
|
@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
public abstract class LibTIC80 : LibWaterboxCore
|
public abstract class LibTIC80 : LibWaterboxCore
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum TI80Gamepad : byte
|
public enum TIC80Gamepad : byte
|
||||||
{
|
{
|
||||||
Up = 0x01,
|
Up = 0x01,
|
||||||
Down = 0x02,
|
Down = 0x02,
|
||||||
|
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
Y = 0x80,
|
Y = 0x80,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TI80Keys : byte
|
public enum TIC80Keys : byte
|
||||||
{
|
{
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
||||||
|
@ -115,20 +115,32 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public new class FrameInfo : LibWaterboxCore.FrameInfo
|
public new class FrameInfo : LibWaterboxCore.FrameInfo
|
||||||
{
|
{
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
public long Time;
|
||||||
public TI80Gamepad[] Gamepads = new TI80Gamepad[4];
|
public bool Crop;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct TIC80Inputs
|
||||||
|
{
|
||||||
|
public TIC80Gamepad P1Gamepad;
|
||||||
|
public TIC80Gamepad P2Gamepad;
|
||||||
|
public TIC80Gamepad P3Gamepad;
|
||||||
|
public TIC80Gamepad P4Gamepad;
|
||||||
|
|
||||||
public sbyte MouseX;
|
public sbyte MouseX;
|
||||||
public sbyte MouseY;
|
public sbyte MouseY;
|
||||||
public ushort MouseButtons;
|
public ushort MouseButtons;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
public TIC80Keys Key1;
|
||||||
public TI80Keys[] Keys = new TI80Keys[4];
|
public TIC80Keys Key2;
|
||||||
|
public TIC80Keys Key3;
|
||||||
public bool Crop;
|
public TIC80Keys Key4;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BizImport(CC)]
|
[BizImport(CC)]
|
||||||
public abstract bool Init(byte[] rom, int sz);
|
public abstract bool Init(byte[] rom, int sz);
|
||||||
|
|
||||||
|
[BizImport(CC)]
|
||||||
|
public abstract void SetInputs(ref TIC80Inputs inputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
@ -5,15 +6,16 @@ using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Computers.TIC80
|
namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
{
|
{
|
||||||
public partial class TIC80 : ISettable<TIC80.TIC80Settings, object>
|
public partial class TIC80 : ISettable<TIC80.TIC80Settings, TIC80.TIC80SyncSettings>
|
||||||
{
|
{
|
||||||
private TIC80Settings _settings;
|
private TIC80Settings _settings;
|
||||||
|
private TIC80SyncSettings _syncSettings;
|
||||||
|
|
||||||
public TIC80Settings GetSettings()
|
public TIC80Settings GetSettings()
|
||||||
=> _settings.Clone();
|
=> _settings.Clone();
|
||||||
|
|
||||||
public object GetSyncSettings()
|
public TIC80SyncSettings GetSyncSettings()
|
||||||
=> null;
|
=> _syncSettings.Clone();
|
||||||
|
|
||||||
public PutSettingsDirtyBits PutSettings(TIC80Settings o)
|
public PutSettingsDirtyBits PutSettings(TIC80Settings o)
|
||||||
{
|
{
|
||||||
|
@ -21,14 +23,18 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
return PutSettingsDirtyBits.None;
|
return PutSettingsDirtyBits.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PutSettingsDirtyBits PutSyncSettings(object o)
|
public PutSettingsDirtyBits PutSyncSettings(TIC80SyncSettings o)
|
||||||
=> PutSettingsDirtyBits.None;
|
{
|
||||||
|
var ret = TIC80SyncSettings.NeedsReboot(_syncSettings, o);
|
||||||
|
_syncSettings = o;
|
||||||
|
return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None;
|
||||||
|
}
|
||||||
|
|
||||||
public class TIC80Settings
|
public class TIC80Settings
|
||||||
{
|
{
|
||||||
[DisplayName("Crop")]
|
[DisplayName("Crop")]
|
||||||
[Description("")]
|
[Description("")]
|
||||||
[DefaultValue(false)]
|
[DefaultValue(true)]
|
||||||
public bool Crop { get; set; }
|
public bool Crop { get; set; }
|
||||||
|
|
||||||
public TIC80Settings()
|
public TIC80Settings()
|
||||||
|
@ -37,5 +43,28 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
public TIC80Settings Clone()
|
public TIC80Settings Clone()
|
||||||
=> (TIC80Settings)MemberwiseClone();
|
=> (TIC80Settings)MemberwiseClone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TIC80SyncSettings
|
||||||
|
{
|
||||||
|
[DisplayName("Initial Time")]
|
||||||
|
[Description("Initial time of emulation.")]
|
||||||
|
[DefaultValue(typeof(DateTime), "2010-01-01")]
|
||||||
|
[TypeConverter(typeof(BizDateTimeConverter))]
|
||||||
|
public DateTime InitialTime { get; set; }
|
||||||
|
|
||||||
|
[DisplayName("Use Real Time")]
|
||||||
|
[Description("If true, RTC clock will be based off of real time instead of emulated time. Ignored (set to false) when recording a movie.")]
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool UseRealTime { get; set; }
|
||||||
|
|
||||||
|
public TIC80SyncSettings()
|
||||||
|
=> SettingsUtil.SetDefaultValues(this);
|
||||||
|
|
||||||
|
public TIC80SyncSettings Clone()
|
||||||
|
=> (TIC80SyncSettings)MemberwiseClone();
|
||||||
|
|
||||||
|
public static bool NeedsReboot(TIC80SyncSettings x, TIC80SyncSettings y)
|
||||||
|
=> !DeepEquality.DeepEquals(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
private readonly LibTIC80 _core;
|
private readonly LibTIC80 _core;
|
||||||
|
|
||||||
[CoreConstructor(VSystemID.Raw.TIC80)]
|
[CoreConstructor(VSystemID.Raw.TIC80)]
|
||||||
public TIC80(CoreLoadParameters<TIC80Settings, object> lp)
|
public TIC80(CoreLoadParameters<TIC80Settings, TIC80SyncSettings> lp)
|
||||||
: base(lp.Comm, new Configuration
|
: base(lp.Comm, new Configuration
|
||||||
{
|
{
|
||||||
DefaultWidth = 240,
|
DefaultWidth = 240,
|
||||||
|
@ -28,6 +28,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
_settings = lp.Settings ?? new();
|
_settings = lp.Settings ?? new();
|
||||||
|
_syncSettings = lp.SyncSettings ?? new();
|
||||||
|
|
||||||
if (!_settings.Crop)
|
if (!_settings.Crop)
|
||||||
{
|
{
|
||||||
|
@ -55,13 +56,16 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
}
|
}
|
||||||
|
|
||||||
PostInit();
|
PostInit();
|
||||||
|
|
||||||
|
DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime);
|
||||||
|
InitializeRtc(_syncSettings.InitialTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly List<KeyValuePair<string, LibTIC80.TI80Keys>> KeyMap = new();
|
private static readonly List<KeyValuePair<string, LibTIC80.TIC80Keys>> KeyMap = new();
|
||||||
|
|
||||||
public override ControllerDefinition ControllerDefinition => TI80Controller;
|
public override ControllerDefinition ControllerDefinition => TIC80Controller;
|
||||||
|
|
||||||
private static readonly ControllerDefinition TI80Controller = CreateControllerDefinition();
|
private static readonly ControllerDefinition TIC80Controller = CreateControllerDefinition();
|
||||||
|
|
||||||
private static ControllerDefinition CreateControllerDefinition()
|
private static ControllerDefinition CreateControllerDefinition()
|
||||||
{
|
{
|
||||||
|
@ -69,9 +73,9 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
foreach (var b in Enum.GetValues(typeof(LibTIC80.TI80Gamepad)))
|
foreach (var b in Enum.GetValues(typeof(LibTIC80.TIC80Gamepad)))
|
||||||
{
|
{
|
||||||
ret.BoolButtons.Add($"P{i + 1} {Enum.GetName(typeof(LibTIC80.TI80Gamepad), b)}");
|
ret.BoolButtons.Add($"P{i + 1} {Enum.GetName(typeof(LibTIC80.TIC80Gamepad), b)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +102,11 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var k in Enum.GetValues(typeof(LibTIC80.TI80Keys)))
|
foreach (var k in Enum.GetValues(typeof(LibTIC80.TIC80Keys)))
|
||||||
{
|
{
|
||||||
var name = Enum.GetName(typeof(LibTIC80.TI80Keys), k).TrimStart('_').Replace('_', ' ');
|
var name = Enum.GetName(typeof(LibTIC80.TIC80Keys), k).TrimStart('_').Replace('_', ' ');
|
||||||
if (name is "Unknown") continue;
|
if (name is "Unknown") continue;
|
||||||
KeyMap.Add(new(name, (LibTIC80.TI80Keys)k));
|
KeyMap.Add(new(name, (LibTIC80.TIC80Keys)k));
|
||||||
ret.BoolButtons.Add(name);
|
ret.BoolButtons.Add(name);
|
||||||
ret.CategoryLabels[name] = "Keyboard";
|
ret.CategoryLabels[name] = "Keyboard";
|
||||||
}
|
}
|
||||||
|
@ -110,19 +114,25 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
return ret.MakeImmutable();
|
return ret.MakeImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetGamepads(IController controller, LibTIC80.TI80Gamepad[] gamepads)
|
private static void GetGamepads(IController controller, ref LibTIC80.TIC80Inputs inputs)
|
||||||
{
|
{
|
||||||
|
var gamepads = new LibTIC80.TIC80Gamepad[4];
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
gamepads[i] = 0;
|
gamepads[i] = 0;
|
||||||
foreach (var b in Enum.GetValues(typeof(LibTIC80.TI80Gamepad)))
|
foreach (var b in Enum.GetValues(typeof(LibTIC80.TIC80Gamepad)))
|
||||||
{
|
{
|
||||||
if (controller.IsPressed($"P{i + 1} {Enum.GetName(typeof(LibTIC80.TI80Gamepad), b)}"))
|
if (controller.IsPressed($"P{i + 1} {Enum.GetName(typeof(LibTIC80.TIC80Gamepad), b)}"))
|
||||||
{
|
{
|
||||||
gamepads[i] |= (LibTIC80.TI80Gamepad)b;
|
gamepads[i] |= (LibTIC80.TIC80Gamepad)b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputs.P1Gamepad = gamepads[0];
|
||||||
|
inputs.P2Gamepad = gamepads[1];
|
||||||
|
inputs.P3Gamepad = gamepads[2];
|
||||||
|
inputs.P4Gamepad = gamepads[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ushort GetMouseButtons(IController controller)
|
private static ushort GetMouseButtons(IController controller)
|
||||||
|
@ -151,8 +161,9 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetKeys(IController controller, LibTIC80.TI80Keys[] keys)
|
private static void GetKeys(IController controller, ref LibTIC80.TIC80Inputs inputs)
|
||||||
{
|
{
|
||||||
|
var keys = new LibTIC80.TIC80Keys[4];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var kvp in KeyMap)
|
foreach (var kvp in KeyMap)
|
||||||
{
|
{
|
||||||
|
@ -165,23 +176,31 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputs.Key1 = keys[0];
|
||||||
|
inputs.Key2 = keys[1];
|
||||||
|
inputs.Key3 = keys[2];
|
||||||
|
inputs.Key4 = keys[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
|
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
|
||||||
{
|
{
|
||||||
var ret = new LibTIC80.FrameInfo
|
var inputs = new LibTIC80.TIC80Inputs
|
||||||
{
|
{
|
||||||
MouseX = (sbyte)controller.AxisValue("Mouse Position X"),
|
MouseX = (sbyte)controller.AxisValue("Mouse Position X"),
|
||||||
MouseY = (sbyte)controller.AxisValue("Mouse Position Y"),
|
MouseY = (sbyte)controller.AxisValue("Mouse Position Y"),
|
||||||
MouseButtons = GetMouseButtons(controller),
|
MouseButtons = GetMouseButtons(controller),
|
||||||
|
|
||||||
Crop = _settings.Crop,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GetGamepads(controller, ret.Gamepads);
|
GetGamepads(controller, ref inputs);
|
||||||
GetKeys(controller, ret.Keys);
|
GetKeys(controller, ref inputs);
|
||||||
|
_core.SetInputs(ref inputs);
|
||||||
|
|
||||||
return ret;
|
return new LibTIC80.FrameInfo
|
||||||
|
{
|
||||||
|
Time = GetRtcTime(!DeterministicEmulation),
|
||||||
|
Crop = _settings.Crop
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,19 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static time_t biz_time = 0;
|
||||||
|
static u32 biz_clock_rm = 0;
|
||||||
|
|
||||||
|
time_t BizTimeCallback()
|
||||||
|
{
|
||||||
|
return biz_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t BizClockCallback()
|
||||||
|
{
|
||||||
|
return biz_time * CLOCKS_PER_SEC + (biz_clock_rm * CLOCKS_PER_SEC / 60);
|
||||||
|
}
|
||||||
|
|
||||||
static tic80* tic;
|
static tic80* tic;
|
||||||
|
|
||||||
ECL_EXPORT bool Init(u8* rom, u32 sz)
|
ECL_EXPORT bool Init(u8* rom, u32 sz)
|
||||||
|
@ -41,10 +54,17 @@ ECL_EXPORT void GetMemoryAreas(MemoryArea* m)
|
||||||
m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
|
m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_WRITABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static tic80_input biz_inputs;
|
||||||
|
|
||||||
|
ECL_EXPORT void SetInputs(tic80_input* inputs)
|
||||||
|
{
|
||||||
|
memcpy(&biz_inputs, inputs, sizeof(tic80_input));
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FrameInfo b;
|
FrameInfo b;
|
||||||
tic80_input inputs;
|
u64 time;
|
||||||
bool crop;
|
bool crop;
|
||||||
} MyFrameInfo;
|
} MyFrameInfo;
|
||||||
|
|
||||||
|
@ -54,8 +74,10 @@ void (*inputcb)() = 0;
|
||||||
ECL_EXPORT void FrameAdvance(MyFrameInfo* f)
|
ECL_EXPORT void FrameAdvance(MyFrameInfo* f)
|
||||||
{
|
{
|
||||||
lagged = true;
|
lagged = true;
|
||||||
|
biz_time = f->time;
|
||||||
|
biz_clock_rm = (biz_clock_rm + 1) % 60;
|
||||||
|
|
||||||
tic80_tick(tic, f->inputs);
|
tic80_tick(tic, biz_inputs);
|
||||||
tic80_sound(tic);
|
tic80_sound(tic);
|
||||||
|
|
||||||
f->b.Samples = tic->samples.count / TIC80_SAMPLE_CHANNELS;
|
f->b.Samples = tic->samples.count / TIC80_SAMPLE_CHANNELS;
|
||||||
|
|
|
@ -46,6 +46,9 @@ static_assert(sizeof(tic_map) < 1024 * 32, "tic_map");
|
||||||
static_assert(sizeof(tic_vram) == TIC_VRAM_SIZE, "tic_vram");
|
static_assert(sizeof(tic_vram) == TIC_VRAM_SIZE, "tic_vram");
|
||||||
static_assert(sizeof(tic_ram) == TIC_RAM_SIZE, "tic_ram");
|
static_assert(sizeof(tic_ram) == TIC_RAM_SIZE, "tic_ram");
|
||||||
|
|
||||||
|
time_t BizTimeCallback();
|
||||||
|
clock_t BizClockCallback();
|
||||||
|
|
||||||
u8 tic_api_peek(tic_mem* memory, s32 address, s32 bits)
|
u8 tic_api_peek(tic_mem* memory, s32 address, s32 bits)
|
||||||
{
|
{
|
||||||
if (address < 0)
|
if (address < 0)
|
||||||
|
@ -204,13 +207,13 @@ void tic_api_sync(tic_mem* tic, u32 mask, s32 bank, bool toCart)
|
||||||
double tic_api_time(tic_mem* memory)
|
double tic_api_time(tic_mem* memory)
|
||||||
{
|
{
|
||||||
tic_core* core = (tic_core*)memory;
|
tic_core* core = (tic_core*)memory;
|
||||||
return (clock() - core->data->start) * 1000.0 / CLOCKS_PER_SEC;
|
return (BizClockCallback() - core->data->start) * 1000.0 / CLOCKS_PER_SEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 tic_api_tstamp(tic_mem* memory)
|
s32 tic_api_tstamp(tic_mem* memory)
|
||||||
{
|
{
|
||||||
tic_core* core = (tic_core*)memory;
|
tic_core* core = (tic_core*)memory;
|
||||||
return (s32)time(NULL);
|
return (s32)BizTimeCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compareMetatag(const char* code, const char* tag, const char* value, const char* comment)
|
static bool compareMetatag(const char* code, const char* tag, const char* value, const char* comment)
|
||||||
|
@ -452,7 +455,7 @@ void tic_core_tick(tic_mem* tic, tic_tick_data* data)
|
||||||
tic->input.keyboard = 1;
|
tic->input.keyboard = 1;
|
||||||
else tic->input.data = -1; // default is all enabled
|
else tic->input.data = -1; // default is all enabled
|
||||||
|
|
||||||
data->start = clock();
|
data->start = BizClockCallback();
|
||||||
|
|
||||||
// TODO: does where to fetch code from need to be a config option so this isn't hard
|
// TODO: does where to fetch code from need to be a config option so this isn't hard
|
||||||
// coded for just a single langage? perhaps change it later when we have a second script
|
// coded for just a single langage? perhaps change it later when we have a second script
|
||||||
|
@ -492,7 +495,7 @@ void tic_core_pause(tic_mem* memory)
|
||||||
if (core->data)
|
if (core->data)
|
||||||
{
|
{
|
||||||
core->pause.time.start = core->data->start;
|
core->pause.time.start = core->data->start;
|
||||||
core->pause.time.paused = clock();
|
core->pause.time.paused = BizClockCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,7 +507,7 @@ void tic_core_resume(tic_mem* memory)
|
||||||
{
|
{
|
||||||
memcpy(&core->state, &core->pause.state, sizeof(tic_core_state_data));
|
memcpy(&core->state, &core->pause.state, sizeof(tic_core_state_data));
|
||||||
memcpy(memory->ram, &core->pause.ram, sizeof(tic_ram));
|
memcpy(memory->ram, &core->pause.ram, sizeof(tic_ram));
|
||||||
core->data->start = core->pause.time.start + clock() - core->pause.time.paused;
|
core->data->start = core->pause.time.start + BizClockCallback() - core->pause.time.paused;
|
||||||
memory->input.data = core->pause.input;
|
memory->input.data = core->pause.input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue