fix TIC80 inputs, wire up time/clock callbacks

This commit is contained in:
CasualPokePlayer 2022-06-16 13:01:50 -07:00
parent 1d4e7dd3fb
commit 84af66f523
6 changed files with 126 additions and 41 deletions

Binary file not shown.

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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
};
}
}
}

View File

@ -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;

View File

@ -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;
}
}