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
|
||||
{
|
||||
[Flags]
|
||||
public enum TI80Gamepad : byte
|
||||
public enum TIC80Gamepad : byte
|
||||
{
|
||||
Up = 0x01,
|
||||
Down = 0x02,
|
||||
|
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
Y = 0x80,
|
||||
}
|
||||
|
||||
public enum TI80Keys : byte
|
||||
public enum TIC80Keys : byte
|
||||
{
|
||||
Unknown,
|
||||
|
||||
|
@ -115,20 +115,32 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public new class FrameInfo : LibWaterboxCore.FrameInfo
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public TI80Gamepad[] Gamepads = new TI80Gamepad[4];
|
||||
public long Time;
|
||||
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 MouseY;
|
||||
public ushort MouseButtons;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public TI80Keys[] Keys = new TI80Keys[4];
|
||||
|
||||
public bool Crop;
|
||||
public TIC80Keys Key1;
|
||||
public TIC80Keys Key2;
|
||||
public TIC80Keys Key3;
|
||||
public TIC80Keys Key4;
|
||||
}
|
||||
|
||||
[BizImport(CC)]
|
||||
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 BizHawk.Common;
|
||||
|
@ -5,15 +6,16 @@ using BizHawk.Emulation.Common;
|
|||
|
||||
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 TIC80SyncSettings _syncSettings;
|
||||
|
||||
public TIC80Settings GetSettings()
|
||||
=> _settings.Clone();
|
||||
|
||||
public object GetSyncSettings()
|
||||
=> null;
|
||||
public TIC80SyncSettings GetSyncSettings()
|
||||
=> _syncSettings.Clone();
|
||||
|
||||
public PutSettingsDirtyBits PutSettings(TIC80Settings o)
|
||||
{
|
||||
|
@ -21,14 +23,18 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
return PutSettingsDirtyBits.None;
|
||||
}
|
||||
|
||||
public PutSettingsDirtyBits PutSyncSettings(object o)
|
||||
=> PutSettingsDirtyBits.None;
|
||||
public PutSettingsDirtyBits PutSyncSettings(TIC80SyncSettings o)
|
||||
{
|
||||
var ret = TIC80SyncSettings.NeedsReboot(_syncSettings, o);
|
||||
_syncSettings = o;
|
||||
return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None;
|
||||
}
|
||||
|
||||
public class TIC80Settings
|
||||
{
|
||||
[DisplayName("Crop")]
|
||||
[Description("")]
|
||||
[DefaultValue(false)]
|
||||
[DefaultValue(true)]
|
||||
public bool Crop { get; set; }
|
||||
|
||||
public TIC80Settings()
|
||||
|
@ -37,5 +43,28 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
public TIC80Settings Clone()
|
||||
=> (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;
|
||||
|
||||
[CoreConstructor(VSystemID.Raw.TIC80)]
|
||||
public TIC80(CoreLoadParameters<TIC80Settings, object> lp)
|
||||
public TIC80(CoreLoadParameters<TIC80Settings, TIC80SyncSettings> lp)
|
||||
: base(lp.Comm, new Configuration
|
||||
{
|
||||
DefaultWidth = 240,
|
||||
|
@ -28,6 +28,7 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
})
|
||||
{
|
||||
_settings = lp.Settings ?? new();
|
||||
_syncSettings = lp.SyncSettings ?? new();
|
||||
|
||||
if (!_settings.Crop)
|
||||
{
|
||||
|
@ -55,13 +56,16 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -69,9 +73,9 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
|
||||
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;
|
||||
KeyMap.Add(new(name, (LibTIC80.TI80Keys)k));
|
||||
KeyMap.Add(new(name, (LibTIC80.TIC80Keys)k));
|
||||
ret.BoolButtons.Add(name);
|
||||
ret.CategoryLabels[name] = "Keyboard";
|
||||
}
|
||||
|
@ -110,19 +114,25 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
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++)
|
||||
{
|
||||
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)
|
||||
|
@ -151,8 +161,9 @@ namespace BizHawk.Emulation.Cores.Computers.TIC80
|
|||
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;
|
||||
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)
|
||||
{
|
||||
var ret = new LibTIC80.FrameInfo
|
||||
var inputs = new LibTIC80.TIC80Inputs
|
||||
{
|
||||
MouseX = (sbyte)controller.AxisValue("Mouse Position X"),
|
||||
MouseY = (sbyte)controller.AxisValue("Mouse Position Y"),
|
||||
MouseButtons = GetMouseButtons(controller),
|
||||
|
||||
Crop = _settings.Crop,
|
||||
};
|
||||
|
||||
GetGamepads(controller, ret.Gamepads);
|
||||
GetKeys(controller, ret.Keys);
|
||||
GetGamepads(controller, ref inputs);
|
||||
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>
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static tic80_input biz_inputs;
|
||||
|
||||
ECL_EXPORT void SetInputs(tic80_input* inputs)
|
||||
{
|
||||
memcpy(&biz_inputs, inputs, sizeof(tic80_input));
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FrameInfo b;
|
||||
tic80_input inputs;
|
||||
u64 time;
|
||||
bool crop;
|
||||
} MyFrameInfo;
|
||||
|
||||
|
@ -54,8 +74,10 @@ void (*inputcb)() = 0;
|
|||
ECL_EXPORT void FrameAdvance(MyFrameInfo* f)
|
||||
{
|
||||
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);
|
||||
|
||||
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_ram) == TIC_RAM_SIZE, "tic_ram");
|
||||
|
||||
time_t BizTimeCallback();
|
||||
clock_t BizClockCallback();
|
||||
|
||||
u8 tic_api_peek(tic_mem* memory, s32 address, s32 bits)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -452,7 +455,7 @@ void tic_core_tick(tic_mem* tic, tic_tick_data* data)
|
|||
tic->input.keyboard = 1;
|
||||
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
|
||||
// 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)
|
||||
{
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue