Remove TI83Hawk
This commit is contained in:
parent
89e94be8c1
commit
30cc02c9ff
|
@ -4,7 +4,7 @@ An emulation project.
|
|||
|
||||
EmuHawk is a multi-system emulator written in C#. As well as quality-of-life features for casual players, it also has recording/playback and debugging tools, making it the first choice for TASers (Tool-Assisted Speedrunners). More info [below](#features-and-systems).
|
||||
|
||||
A7800Hawk, Atari2600Hawk, C64Hawk, ChannelFHawk, ColecoHawk, GBHawk, IntelliHawk, NesHawk, O2Hawk, PCEHawk, SMSHawk, TI83Hawk, VectrexHawk, and ZXHawk are bespoke emulation cores written in C#.
|
||||
A7800Hawk, Atari2600Hawk, C64Hawk, ChannelFHawk, ColecoHawk, GBHawk, IntelliHawk, NesHawk, O2Hawk, PCEHawk, SMSHawk, VectrexHawk, and ZXHawk are bespoke emulation cores written in C#.
|
||||
MSXHawk is a bespoke emulation core written in C++.
|
||||
More info [below](#cores).
|
||||
|
||||
|
@ -357,7 +357,7 @@ Sega Master System | **Genplus-gx**, **SMSHawk**
|
|||
Sega Saturn | **Saturnus**
|
||||
SNES | **BSNES**, Faust, Snes9x
|
||||
Super Game Boy | **BSNES**, **Gambatte**
|
||||
TI-83 | **Emu83**, **TI83Hawk**
|
||||
TI-83 | **Emu83**
|
||||
TIC-80 | **TIC-80** reference implementation
|
||||
TurboGrafx | HyperNyma, **PCEHawk**, **TurboNyma**
|
||||
Uzebox | **Uzem**
|
||||
|
|
|
@ -50,8 +50,6 @@ namespace BizHawk.Client.Common
|
|||
[ CoreNames.Gpgx, CoreNames.SMSHawk ]),
|
||||
([ VSystemID.Raw.SNES ],
|
||||
[ CoreNames.Snes9X, CoreNames.Bsnes115, CoreNames.SubBsnes115, CoreNames.Faust, CoreNames.Bsnes ]),
|
||||
([ VSystemID.Raw.TI83 ],
|
||||
[ CoreNames.Emu83, CoreNames.TI83Hawk ]),
|
||||
};
|
||||
|
||||
public static Dictionary<string, string> GenDefaultCorePreferences()
|
||||
|
|
|
@ -233,7 +233,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
this.BarcodeReaderMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.TI83SubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.KeypadMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.LoadTIFileMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.toolStripSeparator13 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx();
|
||||
this.paletteToolStripMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.A7800SubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
|
@ -1557,7 +1556,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
//
|
||||
this.TI83SubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.KeypadMenuItem,
|
||||
this.LoadTIFileMenuItem,
|
||||
this.toolStripSeparator13,
|
||||
this.paletteToolStripMenuItem});
|
||||
this.TI83SubMenu.Text = "TI83";
|
||||
|
@ -1567,11 +1565,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
this.KeypadMenuItem.Text = "Keypad";
|
||||
this.KeypadMenuItem.Click += new System.EventHandler(this.Ti83KeypadMenuItem_Click);
|
||||
//
|
||||
// LoadTIFileMenuItem
|
||||
//
|
||||
this.LoadTIFileMenuItem.Text = "Load TI-83 File...";
|
||||
this.LoadTIFileMenuItem.Click += new System.EventHandler(this.Ti83LoadTIFileMenuItem_Click);
|
||||
//
|
||||
// paletteToolStripMenuItem
|
||||
//
|
||||
this.paletteToolStripMenuItem.Text = "Palette...";
|
||||
|
@ -2643,7 +2636,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx ConfigContextMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx RewindOptionsMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx FirmwareMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx LoadTIFileMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx ClearSRAMContextMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripSeparatorEx ShowMenuContextMenuSeparator;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx StopAVContextMenuItem;
|
||||
|
|
|
@ -13,7 +13,6 @@ using BizHawk.Emulation.Cores.Atari.Atari2600;
|
|||
using BizHawk.Emulation.Cores.Atari.Jaguar;
|
||||
using BizHawk.Emulation.Cores.Atari.Lynx;
|
||||
using BizHawk.Emulation.Cores.Calculators.Emu83;
|
||||
using BizHawk.Emulation.Cores.Calculators.TI83;
|
||||
using BizHawk.Emulation.Cores.ColecoVision;
|
||||
using BizHawk.Emulation.Cores.Computers.Amiga;
|
||||
using BizHawk.Emulation.Cores.Computers.AmstradCPC;
|
||||
|
@ -894,34 +893,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
private void Ti83KeypadMenuItem_Click(object sender, EventArgs e)
|
||||
=> Tools.Load<TI83KeyPad>();
|
||||
|
||||
private void Ti83LoadTIFileMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (Emulator is not TI83 ti83) return;
|
||||
var result = this.ShowFileOpenDialog(
|
||||
discardCWDChange: true,
|
||||
filter: TI83ProgramFilesFSFilterSet,
|
||||
initDir: Config.PathEntries.RomAbsolutePath(Emulator.SystemId));
|
||||
if (result is null) return;
|
||||
try
|
||||
{
|
||||
ti83.LinkPort.SendFileToCalc(File.OpenRead(result), true);
|
||||
return;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
if (this.ShowMessageBox3(
|
||||
owner: null,
|
||||
icon: EMsgBoxIcon.Question,
|
||||
caption: "Upload Failed",
|
||||
text: $"Invalid file format. Reason: {ex.Message} \nForce transfer? This may cause the calculator to crash.")
|
||||
is not true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
ti83.LinkPort.SendFileToCalc(File.OpenRead(result), false);
|
||||
}
|
||||
|
||||
private DialogResult OpenTI83PaletteSettingsDialog(ISettingsAdapter settable)
|
||||
{
|
||||
using TI83PaletteConfig form = new(settable);
|
||||
|
@ -933,7 +904,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
var result = Emulator switch
|
||||
{
|
||||
Emu83 => OpenTI83PaletteSettingsDialog(GetSettingsAdapterForLoadedCore<Emu83>()),
|
||||
TI83 => OpenTI83PaletteSettingsDialog(GetSettingsAdapterForLoadedCore<TI83>()),
|
||||
_ => DialogResult.None
|
||||
};
|
||||
if (result.IsOk()) AddOnScreenMessage("Palette settings saved");
|
||||
|
@ -1386,9 +1356,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
};
|
||||
items.Add(subNESHawkSubmenu);
|
||||
|
||||
// TI83Hawk
|
||||
items.Add(CreateCoreSubmenu(VSystemCategory.Other, CoreNames.TI83Hawk, CreateSettingsItem("Palette...", (_, _) => OpenTI83PaletteSettingsDialog(GetSettingsAdapterFor<TI83>()))));
|
||||
|
||||
// TIC80
|
||||
items.Add(CreateCoreSubmenu(VSystemCategory.PCs, CoreNames.TIC80, CreateGenericCoreConfigItem<TIC80>(CoreNames.TIC80)));
|
||||
|
||||
|
@ -1486,7 +1453,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
break;
|
||||
case VSystemID.Raw.TI83:
|
||||
TI83SubMenu.Visible = true;
|
||||
LoadTIFileMenuItem.Visible = Emulator is TI83;
|
||||
break;
|
||||
case VSystemID.Raw.ZXSpectrum:
|
||||
zXSpectrumToolStripMenuItem.Visible = true;
|
||||
|
|
|
@ -4275,7 +4275,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
var recommendedCore = currentCoreName switch
|
||||
{
|
||||
CoreNames.Snes9X => CoreNames.Bsnes115,
|
||||
CoreNames.TI83Hawk => CoreNames.Emu83,
|
||||
CoreNames.QuickNes => CoreNames.NesHawk,
|
||||
CoreNames.Atari2600Hawk => CoreNames.Stella,
|
||||
CoreNames.HyperNyma => CoreNames.TurboNyma,
|
||||
|
|
|
@ -589,7 +589,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
break;
|
||||
case ConsoleID.TI83:
|
||||
TryAddDomain("RAM"); // Emu83
|
||||
TryAddDomain("Main RAM"); // TI83Hawk
|
||||
break;
|
||||
case ConsoleID.DS:
|
||||
case ConsoleID.DSi:
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
<ItemGroup>
|
||||
<Compile Update="Arcades/MAME/MAME.*.cs" DependentUpon="MAME.cs" />
|
||||
<Compile Update="Calculators/Emu83/Emu83.*.cs" DependentUpon="Emu83.cs" />
|
||||
<Compile Update="Calculators/TI83/TI83.*.cs" DependentUpon="TI83.cs" />
|
||||
<Compile Update="Computers/Amiga/UAE.*.cs" DependentUpon="UAE.cs" />
|
||||
<Compile Update="Computers/AppleII/AppleII.*.cs" DependentUpon="AppleII.cs" />
|
||||
<Compile Update="Computers/Commodore64/C64.*.cs" DependentUpon="C64.cs" />
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
using BizHawk.Emulation.Cores.Components.Z80A;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83
|
||||
{
|
||||
public readonly struct CpuLink(TI83 ti83) : IZ80ALink
|
||||
{
|
||||
public byte FetchMemory(ushort address)
|
||||
=> ti83.ReadMemory(address);
|
||||
|
||||
public byte ReadMemory(ushort address)
|
||||
=> ti83.ReadMemory(address);
|
||||
|
||||
public void WriteMemory(ushort address, byte value)
|
||||
=> ti83.WriteMemory(address, value);
|
||||
|
||||
public byte ReadHardware(ushort address)
|
||||
=> ti83.ReadHardware(address);
|
||||
|
||||
public void WriteHardware(ushort address, byte value)
|
||||
=> ti83.WriteHardware(address, value);
|
||||
|
||||
public byte FetchDB()
|
||||
=> 0xFF;
|
||||
|
||||
public void OnExecFetch(ushort address)
|
||||
{
|
||||
}
|
||||
|
||||
public void IRQCallback()
|
||||
=> ti83.IRQCallback();
|
||||
|
||||
public void NMICallback()
|
||||
=> ti83.NMICallback();
|
||||
|
||||
public void IRQACKCallback()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83 : IDebuggable
|
||||
{
|
||||
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters() => _cpu.GetCpuFlagsAndRegisters();
|
||||
|
||||
public void SetCpuRegister(string register, int value) => _cpu.SetCpuRegister(register, value);
|
||||
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get; } = new MemoryCallbackSystem(new[] { "System Bus" });
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void Step(StepType type) => throw new NotImplementedException();
|
||||
|
||||
public bool CanStep(StepType type) => false;
|
||||
|
||||
public long TotalExecutedCycles => _cpu.TotalExecutedCycles;
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83 : IEmulator
|
||||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
public ControllerDefinition ControllerDefinition => TI83Controller;
|
||||
|
||||
public bool FrameAdvance(IController controller, bool render, bool renderSound)
|
||||
{
|
||||
_controller = controller;
|
||||
_lagged = true;
|
||||
|
||||
if (_tracer.IsEnabled())
|
||||
{
|
||||
_cpu.TraceCallback = s => _tracer.Put(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cpu.TraceCallback = null;
|
||||
}
|
||||
|
||||
_onPressed = controller.IsPressed("ON");
|
||||
|
||||
if (_onPressed && ON_key_int_EN && !ON_key_int)
|
||||
{
|
||||
ON_key_int = true;
|
||||
_cpu.FlagI = true;
|
||||
}
|
||||
|
||||
// see: http://wikiti.brandonw.net/index.php?title=83:Ports:04
|
||||
// for timer interrupt frequency
|
||||
|
||||
// CPU frequency is 6MHz
|
||||
for (int i = 0; i < 100000; i++)
|
||||
{
|
||||
_cpu.ExecuteOne();
|
||||
|
||||
TIM_count++;
|
||||
if (TIM_count >= TIM_hit)
|
||||
{
|
||||
TIM_count = 0;
|
||||
|
||||
if (TIM_1_int_EN)
|
||||
{
|
||||
TIM_1_int = true;
|
||||
_cpu.FlagI = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Frame++;
|
||||
|
||||
if (_lagged)
|
||||
{
|
||||
_lagCount++;
|
||||
}
|
||||
|
||||
_isLag = _lagged;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Frame
|
||||
{
|
||||
get => _frame;
|
||||
private set => _frame = value;
|
||||
}
|
||||
|
||||
public string SystemId => VSystemID.Raw.TI83;
|
||||
|
||||
public bool DeterministicEmulation => true;
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
Frame = 0;
|
||||
_lagCount = 0;
|
||||
_isLag = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83 : IInputPollable
|
||||
{
|
||||
private int _lagCount = 0;
|
||||
private bool _lagged = true;
|
||||
private bool _isLag = false;
|
||||
|
||||
public int LagCount
|
||||
{
|
||||
get => _lagCount;
|
||||
set => _lagCount = value;
|
||||
}
|
||||
|
||||
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
|
||||
|
||||
public bool IsLagFrame
|
||||
{
|
||||
get => _isLag;
|
||||
set => _isLag = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83
|
||||
{
|
||||
private readonly Dictionary<string, MemoryDomainByteArray> _byteArrayDomains = new Dictionary<string, MemoryDomainByteArray>();
|
||||
private IMemoryDomains _memoryDomains;
|
||||
private bool _memoryDomainsInit;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
var domains = new List<MemoryDomain>();
|
||||
|
||||
var systemBusDomain = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little,
|
||||
(addr) =>
|
||||
{
|
||||
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
|
||||
return ReadMemory((ushort)addr);
|
||||
},
|
||||
(addr, value) =>
|
||||
{
|
||||
if (addr is < 0 or > 0xFFFF) throw new ArgumentOutOfRangeException(paramName: nameof(addr), addr, message: "address out of range");
|
||||
WriteMemory((ushort)addr, value);
|
||||
}, 1);
|
||||
|
||||
domains.Add(systemBusDomain);
|
||||
|
||||
SyncAllByteArrayDomains();
|
||||
|
||||
_memoryDomains = new MemoryDomainList(_byteArrayDomains.Values.Concat(domains).ToList());
|
||||
((BasicServiceProvider) ServiceProvider).Register(_memoryDomains);
|
||||
|
||||
_memoryDomainsInit = true;
|
||||
}
|
||||
|
||||
private void SyncAllByteArrayDomains()
|
||||
{
|
||||
SyncByteArrayDomain("Main RAM", _ram);
|
||||
}
|
||||
|
||||
private void SyncByteArrayDomain(string name, byte[] data)
|
||||
{
|
||||
if (_memoryDomainsInit)
|
||||
{
|
||||
var m = _byteArrayDomains[name];
|
||||
m.Data = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1);
|
||||
_byteArrayDomains.Add(name, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
using System.IO;
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83
|
||||
{
|
||||
private void SyncState(Serializer ser)
|
||||
{
|
||||
if (ser.IsWriter)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
ms.Close();
|
||||
ms.ToArray();
|
||||
}
|
||||
|
||||
ser.BeginSection(nameof(TI83));
|
||||
_cpu.SyncState(ser);
|
||||
ser.Sync("RAM", ref _ram, false);
|
||||
ser.Sync("romPageLow3Bits", ref _romPageLow3Bits);
|
||||
ser.Sync("romPageHighBit", ref _romPageHighBit);
|
||||
ser.Sync("disp_mode", ref _displayMode);
|
||||
ser.Sync("disp_move", ref _displayMove);
|
||||
ser.Sync("disp_x", ref _displayX);
|
||||
ser.Sync("disp_y", ref _displayY);
|
||||
ser.Sync("m_CursorMoved", ref _cursorMoved);
|
||||
ser.Sync("maskOn", ref _maskOn);
|
||||
ser.Sync("onPressed", ref _onPressed);
|
||||
ser.Sync("keyboardMask", ref _keyboardMask);
|
||||
ser.Sync("m_LinkOutput", ref _linkOutput);
|
||||
ser.Sync("VRAM", ref _vram, false);
|
||||
ser.Sync("Frame", ref _frame);
|
||||
ser.Sync("LagCount", ref _lagCount);
|
||||
ser.Sync("IsLag", ref _isLag);
|
||||
ser.Sync(nameof(ON_key_int), ref ON_key_int);
|
||||
ser.Sync(nameof(ON_key_int_EN), ref ON_key_int_EN);
|
||||
ser.Sync(nameof(TIM_1_int), ref TIM_1_int);
|
||||
ser.Sync(nameof(TIM_1_int_EN), ref TIM_1_int_EN);
|
||||
ser.Sync(nameof(TIM_frq), ref TIM_frq);
|
||||
ser.Sync(nameof(TIM_mult), ref TIM_mult);
|
||||
ser.Sync(nameof(TIM_count), ref TIM_count);
|
||||
ser.Sync(nameof(TIM_hit), ref TIM_hit);
|
||||
|
||||
ser.EndSection();
|
||||
|
||||
if (ser.IsReader)
|
||||
{
|
||||
SyncAllByteArrayDomains();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public partial class TI83 : IVideoProvider
|
||||
{
|
||||
public int VirtualWidth => 96;
|
||||
public int VirtualHeight => 64;
|
||||
public int BufferWidth => 96;
|
||||
public int BufferHeight => 64;
|
||||
public int BackgroundColor => 0;
|
||||
public int VsyncNumerator => NullVideo.DefaultVsyncNum;
|
||||
public int VsyncDenominator => NullVideo.DefaultVsyncDen;
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
// unflatten bit buffer
|
||||
int[] pixels = new int[96 * 64];
|
||||
int i = 0;
|
||||
for (int y = 0; y < 64; y++)
|
||||
{
|
||||
for (int x = 0; x < 96; x++)
|
||||
{
|
||||
int offset = (y * 96) + x;
|
||||
int buffByte = offset >> 3;
|
||||
int buffBit = offset & 7;
|
||||
int bit = (_vram[buffByte] >> (7 - buffBit)) & 1;
|
||||
if (bit == 0)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
pixels[i++] = (int)_settings.BGColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels[i++] = (int)_settings.ForeColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pixels;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,503 +0,0 @@
|
|||
using System.IO;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components.Z80A;
|
||||
|
||||
// http://www.ticalc.org/pub/text/calcinfo/
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
[Core(CoreNames.TI83Hawk, "zeromus")]
|
||||
[ServiceNotApplicable(typeof(IBoardInfo), typeof(IRegionable), typeof(ISaveRam), typeof(ISoundProvider))]
|
||||
public partial class TI83 : TI83Common, IEmulator, IVideoProvider, IDebuggable, IInputPollable
|
||||
{
|
||||
[CoreConstructor(VSystemID.Raw.TI83)]
|
||||
public TI83(CoreLoadParameters<TI83CommonSettings, object> lp)
|
||||
{
|
||||
var ser = new BasicServiceProvider(this);
|
||||
ServiceProvider = ser;
|
||||
PutSettings(lp.Settings ?? new TI83CommonSettings());
|
||||
|
||||
_cpu = new Z80A<CpuLink>(new CpuLink(this));
|
||||
|
||||
_rom = lp.Comm.CoreFileProvider.GetFirmwareOrThrow(new("TI83", "Rom"));
|
||||
LinkPort = new TI83LinkPort(this);
|
||||
|
||||
HardReset();
|
||||
SetupMemoryDomains();
|
||||
|
||||
_tracer = new TraceBuffer(_cpu.TraceHeader);
|
||||
|
||||
ser.Register<ITraceable>(_tracer);
|
||||
ser.Register<IDisassemblable>(_cpu);
|
||||
ser.Register<IStatable>(new StateSerializer(SyncState));
|
||||
LinkPort.SendFileToCalc(new MemoryStream(lp.Roms[0].RomData, false), false);
|
||||
}
|
||||
|
||||
private readonly TraceBuffer _tracer;
|
||||
|
||||
private readonly Z80A<CpuLink> _cpu;
|
||||
private readonly byte[] _rom;
|
||||
|
||||
// configuration
|
||||
private IController _controller = NullController.Instance;
|
||||
|
||||
private byte[] _ram;
|
||||
private byte[] _vram = new byte[0x300];
|
||||
private int _romPageLow3Bits;
|
||||
private int _romPageHighBit;
|
||||
private byte _maskOn;
|
||||
private bool _onPressed;
|
||||
private int _keyboardMask;
|
||||
|
||||
private int _displayMode;
|
||||
private int _displayMove;
|
||||
private uint _displayX, _displayY;
|
||||
private bool _cursorMoved;
|
||||
private int _frame;
|
||||
|
||||
public bool ON_key_int, ON_key_int_EN;
|
||||
public bool TIM_1_int, TIM_1_int_EN;
|
||||
public int TIM_frq, TIM_mult, TIM_count, TIM_hit;
|
||||
|
||||
// Link Cable
|
||||
public TI83LinkPort LinkPort { get; }
|
||||
|
||||
private int _linkOutput;
|
||||
|
||||
internal int LinkOutput => _linkOutput;
|
||||
internal bool LinkActive { get; set; }
|
||||
internal int LinkInput { get; set; }
|
||||
|
||||
internal int LinkState => (_linkOutput | LinkInput) ^ 3;
|
||||
|
||||
private static readonly ControllerDefinition TI83Controller = new ControllerDefinition("TI83 Controller")
|
||||
{
|
||||
BoolButtons =
|
||||
{
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "DOT",
|
||||
"ON", "ENTER",
|
||||
"DOWN", "LEFT", "UP", "RIGHT",
|
||||
"PLUS", "MINUS", "MULTIPLY", "DIVIDE",
|
||||
"CLEAR", "EXP", "DASH", "PARACLOSE", "TAN", "VARS", "PARAOPEN",
|
||||
"COS", "PRGM", "STAT", "COMMA", "SIN", "MATRIX", "X",
|
||||
"STO", "LN", "LOG", "SQUARED", "NEG1", "MATH", "ALPHA",
|
||||
"GRAPH", "TRACE", "ZOOM", "WINDOW", "Y", "2ND", "MODE", "DEL",
|
||||
},
|
||||
}.MakeImmutable();
|
||||
|
||||
private byte ReadMemory(ushort addr)
|
||||
{
|
||||
byte ret;
|
||||
int romPage = _romPageLow3Bits | (_romPageHighBit << 3);
|
||||
|
||||
if (addr < 0x4000)
|
||||
{
|
||||
ret = _rom[addr]; // ROM zero-page
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
ret = _rom[(romPage * 0x4000) + addr - 0x4000]; // other rom page
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = _ram[addr - 0x8000];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
if (addr < 0x4000)
|
||||
{
|
||||
// ROM zero-page
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
// other rom page
|
||||
}
|
||||
else
|
||||
{
|
||||
_ram[addr - 0x8000] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteHardware(ushort addr, byte value)
|
||||
{
|
||||
addr &= 0xFF;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0: // PORT_LINK
|
||||
_romPageHighBit = (value >> 4) & 1;
|
||||
_linkOutput = value & 3;
|
||||
|
||||
if (LinkActive)
|
||||
{
|
||||
// Prevent rom calls from disturbing link port activity
|
||||
if (LinkActive && _cpu.RegPC < 0x4000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LinkPort.Update();
|
||||
}
|
||||
|
||||
break;
|
||||
case 1: // PORT_KEYBOARD:
|
||||
_lagged = false;
|
||||
_keyboardMask = value;
|
||||
////Console.WriteLine("write PORT_KEYBOARD {0:X2}",value);
|
||||
break;
|
||||
case 2: // PORT_ROMPAGE
|
||||
_romPageLow3Bits = value & 0x7;
|
||||
break;
|
||||
case 3: // PORT_STATUS
|
||||
// controls ON key interrupts
|
||||
if ((value & 0x1) == 0)
|
||||
{
|
||||
ON_key_int = false;
|
||||
ON_key_int_EN = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ON_key_int_EN = true;
|
||||
}
|
||||
|
||||
// controls first timer interrupts
|
||||
if ((value & 0x2) == 0)
|
||||
{
|
||||
TIM_1_int = false;
|
||||
TIM_1_int_EN = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TIM_1_int_EN = true;
|
||||
}
|
||||
|
||||
// controls second timer, not yet implemented and unclear how to differentiate
|
||||
if ((value & 0x4) == 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
// controls low power mode, not yet implemeneted
|
||||
if ((value & 0x8) == 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
case 4: // PORT_INTCTRL
|
||||
// controls ON key interrupts
|
||||
TIM_frq = value & 6;
|
||||
|
||||
TIM_mult = ((value & 0x10) == 0x10) ? 1800 : 1620;
|
||||
|
||||
TIM_hit = (int) Math.Floor(6000000.0 / Math.Floor((double) TIM_mult / (2 * TIM_frq + 3)));
|
||||
|
||||
// Bit 0 is some form of memory mapping
|
||||
|
||||
// Bit 5 controls reset
|
||||
|
||||
// Bit 6-7 controls battery power compare (not implemented, will always return full power)
|
||||
|
||||
break;
|
||||
case 16: // PORT_DISPCTRL
|
||||
////Console.WriteLine("write PORT_DISPCTRL {0}",value);
|
||||
WriteDispCtrl(value);
|
||||
break;
|
||||
case 17: // PORT_DISPDATA
|
||||
////Console.WriteLine("write PORT_DISPDATA {0}",value);
|
||||
WriteDispData(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private byte ReadHardware(ushort addr)
|
||||
{
|
||||
addr &= 0xFF;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0: // PORT_LINK
|
||||
LinkPort.Update();
|
||||
return (byte)((_romPageHighBit << 4) | (LinkState << 2) | LinkOutput);
|
||||
case 1: // PORT_KEYBOARD:
|
||||
////Console.WriteLine("read PORT_KEYBOARD");
|
||||
return ReadKeyboard();
|
||||
case 2: // PORT_ROMPAGE
|
||||
return (byte)_romPageLow3Bits;
|
||||
case 3: // PORT_STATUS
|
||||
{
|
||||
// Console.WriteLine("read PORT_STATUS");
|
||||
// Bits:
|
||||
// 0 - Set if ON key Interrupt generated
|
||||
// 1 - Update things (keyboard etc)
|
||||
// 2 - Unknown, but used
|
||||
// 3 - Set if ON key is up
|
||||
// 4-7 - Unknown
|
||||
|
||||
return (byte)((_controller.IsPressed("ON") ? 0 : 8) |
|
||||
(TIM_1_int ? 2 : 0) |
|
||||
(ON_key_int ? 1 : 0));
|
||||
}
|
||||
|
||||
case 4: // PORT_INTCTRL
|
||||
// returns mirror of link port
|
||||
return (byte)((_romPageHighBit << 4) | (LinkState << 2) | LinkOutput);
|
||||
|
||||
case 16: // PORT_DISPCTRL
|
||||
// Console.WriteLine("read DISPCTRL");
|
||||
break;
|
||||
|
||||
case 17: // PORT_DISPDATA
|
||||
return ReadDispData();
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
private byte ReadKeyboard()
|
||||
{
|
||||
InputCallbacks.Call();
|
||||
|
||||
// ref TI-9X
|
||||
int ret = 0xFF;
|
||||
////Console.WriteLine("keyboardMask: {0:X2}",keyboardMask);
|
||||
if ((_keyboardMask & 1) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("DOWN")) ret ^= 1;
|
||||
if (_controller.IsPressed("LEFT")) ret ^= 2;
|
||||
if (_controller.IsPressed("RIGHT")) ret ^= 4;
|
||||
if (_controller.IsPressed("UP")) ret ^= 8;
|
||||
}
|
||||
|
||||
if ((_keyboardMask & 2) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("ENTER")) ret ^= 1;
|
||||
if (_controller.IsPressed("PLUS")) ret ^= 2;
|
||||
if (_controller.IsPressed("MINUS")) ret ^= 4;
|
||||
if (_controller.IsPressed("MULTIPLY")) ret ^= 8;
|
||||
if (_controller.IsPressed("DIVIDE")) ret ^= 16;
|
||||
if (_controller.IsPressed("EXP")) ret ^= 32;
|
||||
if (_controller.IsPressed("CLEAR")) ret ^= 64;
|
||||
}
|
||||
|
||||
if ((_keyboardMask & 4) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("DASH")) ret ^= 1;
|
||||
if (_controller.IsPressed("3")) ret ^= 2;
|
||||
if (_controller.IsPressed("6")) ret ^= 4;
|
||||
if (_controller.IsPressed("9")) ret ^= 8;
|
||||
if (_controller.IsPressed("PARACLOSE")) ret ^= 16;
|
||||
if (_controller.IsPressed("TAN")) ret ^= 32;
|
||||
if (_controller.IsPressed("VARS")) ret ^= 64;
|
||||
}
|
||||
|
||||
if ((_keyboardMask & 8) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("DOT")) ret ^= 1;
|
||||
if (_controller.IsPressed("2")) ret ^= 2;
|
||||
if (_controller.IsPressed("5")) ret ^= 4;
|
||||
if (_controller.IsPressed("8")) ret ^= 8;
|
||||
if (_controller.IsPressed("PARAOPEN")) ret ^= 16;
|
||||
if (_controller.IsPressed("COS")) ret ^= 32;
|
||||
if (_controller.IsPressed("PRGM")) ret ^= 64;
|
||||
if (_controller.IsPressed("STAT")) ret ^= 128;
|
||||
}
|
||||
|
||||
if ((_keyboardMask & 16) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("0")) ret ^= 1;
|
||||
if (_controller.IsPressed("1")) ret ^= 2;
|
||||
if (_controller.IsPressed("4")) ret ^= 4;
|
||||
if (_controller.IsPressed("7")) ret ^= 8;
|
||||
if (_controller.IsPressed("COMMA")) ret ^= 16;
|
||||
if (_controller.IsPressed("SIN")) ret ^= 32;
|
||||
if (_controller.IsPressed("MATRIX")) ret ^= 64;
|
||||
if (_controller.IsPressed("X")) ret ^= 128;
|
||||
}
|
||||
|
||||
if ((_keyboardMask & 32) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("STO")) ret ^= 2;
|
||||
if (_controller.IsPressed("LN")) ret ^= 4;
|
||||
if (_controller.IsPressed("LOG")) ret ^= 8;
|
||||
if (_controller.IsPressed("SQUARED")) ret ^= 16;
|
||||
if (_controller.IsPressed("NEG1")) ret ^= 32;
|
||||
if (_controller.IsPressed("MATH")) ret ^= 64;
|
||||
if (_controller.IsPressed("ALPHA")) ret ^= 128;
|
||||
}
|
||||
|
||||
if ((_keyboardMask & 64) == 0)
|
||||
{
|
||||
if (_controller.IsPressed("GRAPH")) ret ^= 1;
|
||||
if (_controller.IsPressed("TRACE")) ret ^= 2;
|
||||
if (_controller.IsPressed("ZOOM")) ret ^= 4;
|
||||
if (_controller.IsPressed("WINDOW")) ret ^= 8;
|
||||
if (_controller.IsPressed("Y")) ret ^= 16;
|
||||
if (_controller.IsPressed("2ND")) ret ^= 32;
|
||||
if (_controller.IsPressed("MODE")) ret ^= 64;
|
||||
if (_controller.IsPressed("DEL")) ret ^= 128;
|
||||
}
|
||||
|
||||
return (byte)ret;
|
||||
}
|
||||
|
||||
private byte ReadDispData()
|
||||
{
|
||||
if (_cursorMoved)
|
||||
{
|
||||
_cursorMoved = false;
|
||||
return 0x00; // not accurate this should be stale data or something
|
||||
}
|
||||
|
||||
byte ret;
|
||||
if (_displayMode == 1)
|
||||
{
|
||||
ret = _vram[(_displayY * 12) + _displayX];
|
||||
}
|
||||
else
|
||||
{
|
||||
int column = 6 * (int)_displayX;
|
||||
int offset = (int)(_displayY * 12) + (column >> 3);
|
||||
int shift = 10 - (column & 7);
|
||||
ret = (byte)(((_vram[offset] << 8) | _vram[offset + 1]) >> shift);
|
||||
}
|
||||
|
||||
DoDispMove();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void WriteDispData(byte value)
|
||||
{
|
||||
int offset;
|
||||
if (_displayMode == 1)
|
||||
{
|
||||
offset = (int)(_displayY * 12) + (int)_displayX;
|
||||
_vram[offset] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
int column = 6 * (int)_displayX;
|
||||
offset = (int)(_displayY * 12) + (column >> 3);
|
||||
if (offset < 0x300)
|
||||
{
|
||||
int shift = column & 7;
|
||||
int mask = ~(252 >> shift);
|
||||
int data = value << 2;
|
||||
_vram[offset] = (byte)(_vram[offset] & mask | (data >> shift));
|
||||
if (shift > 2 && offset < 0x2ff)
|
||||
{
|
||||
offset++;
|
||||
|
||||
shift = 8 - shift;
|
||||
|
||||
mask = ~(252 << shift);
|
||||
_vram[offset] = (byte)(_vram[offset] & mask | (data << shift));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoDispMove();
|
||||
}
|
||||
|
||||
private void DoDispMove()
|
||||
{
|
||||
switch (_displayMove)
|
||||
{
|
||||
case 0:
|
||||
_displayY--;
|
||||
break;
|
||||
case 1:
|
||||
_displayY++;
|
||||
break;
|
||||
case 2:
|
||||
_displayX--;
|
||||
break;
|
||||
case 3:
|
||||
_displayX++;
|
||||
break;
|
||||
}
|
||||
|
||||
_displayX &= 0xF; // 0xF or 0x1F? dunno
|
||||
_displayY &= 0x3F;
|
||||
}
|
||||
|
||||
private void WriteDispCtrl(byte value)
|
||||
{
|
||||
if (value <= 1)
|
||||
{
|
||||
_displayMode = value;
|
||||
}
|
||||
else if (value >= 4 && value <= 7)
|
||||
{
|
||||
_displayMove = value - 4;
|
||||
}
|
||||
else if ((value & 0xC0) == 0x40)
|
||||
{
|
||||
// hardware scroll
|
||||
}
|
||||
else if ((value & 0xE0) == 0x20)
|
||||
{
|
||||
_displayX = (uint)(value & 0x1F);
|
||||
_cursorMoved = true;
|
||||
}
|
||||
else if ((value & 0xC0) == 0x80)
|
||||
{
|
||||
_displayY = (uint)(value & 0x3F);
|
||||
_cursorMoved = true;
|
||||
}
|
||||
else if ((value & 0xC0) == 0xC0)
|
||||
{
|
||||
// contrast
|
||||
}
|
||||
else if (value == 2)
|
||||
{
|
||||
}
|
||||
else if (value == 3)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void IRQCallback()
|
||||
{
|
||||
//Console.WriteLine("IRQ with vec {0} and cpu.InterruptMode {1}", _cpu.Regs[_cpu.I], _cpu.InterruptMode);
|
||||
_cpu.FlagI = false;
|
||||
}
|
||||
|
||||
private void NMICallback()
|
||||
{
|
||||
//Console.WriteLine("NMI");
|
||||
_cpu.NonMaskableInterrupt = false;
|
||||
}
|
||||
|
||||
private void HardReset()
|
||||
{
|
||||
_cpu.Reset();
|
||||
_ram = new byte[0x8000];
|
||||
for (int i = 0; i < 0x8000; i++)
|
||||
{
|
||||
_ram[i] = 0xFF;
|
||||
}
|
||||
|
||||
_cpu.RegPC = 0;
|
||||
|
||||
_cpu.IFF1 = false;
|
||||
_cpu.IFF2 = false;
|
||||
_cpu.InterruptMode = 2;
|
||||
|
||||
_maskOn = 1;
|
||||
_romPageHighBit = 0;
|
||||
_romPageLow3Bits = 0;
|
||||
_keyboardMask = 0;
|
||||
|
||||
_displayMode = 0;
|
||||
_displayMove = 0;
|
||||
_displayX = _displayY = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,405 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Calculators.TI83
|
||||
{
|
||||
public class TI83LinkPort
|
||||
{
|
||||
// Emulates TI linking software.
|
||||
// See http://www.ticalc.org/archives/files/fileinfo/294/29418.html for documentation
|
||||
|
||||
// Note: Each hardware read/write to the link port calls tthe update method.
|
||||
private readonly TI83 Parent;
|
||||
private readonly Queue<byte> CurrentData = new Queue<byte>();
|
||||
|
||||
private Stream _currentFile;
|
||||
private byte[] _variableData;
|
||||
|
||||
private Action _nextStep;
|
||||
|
||||
private ushort _bytesToSend;
|
||||
private byte _bitsLeft;
|
||||
private byte _currentByte;
|
||||
private byte _stepsLeft;
|
||||
|
||||
private Status _currentStatus = Status.Inactive;
|
||||
|
||||
private enum Status
|
||||
{
|
||||
Inactive,
|
||||
PrepareReceive,
|
||||
PrepareSend,
|
||||
Receive,
|
||||
Send
|
||||
}
|
||||
|
||||
public TI83LinkPort(TI83 parent)
|
||||
{
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_currentStatus == Status.PrepareReceive)
|
||||
{
|
||||
// Get the first byte, and start sending it.
|
||||
_currentByte = CurrentData.Dequeue();
|
||||
_currentStatus = Status.Receive;
|
||||
_bitsLeft = 8;
|
||||
_stepsLeft = 5;
|
||||
}
|
||||
|
||||
if (_currentStatus == Status.PrepareSend && Parent.LinkState != 3)
|
||||
{
|
||||
_currentStatus = Status.Send;
|
||||
_bitsLeft = 8;
|
||||
_stepsLeft = 5;
|
||||
_currentByte = 0;
|
||||
}
|
||||
|
||||
if (_currentStatus == Status.Receive)
|
||||
{
|
||||
switch (_stepsLeft)
|
||||
{
|
||||
case 5:
|
||||
// Receive step 1: Lower the other device's line.
|
||||
Parent.LinkInput = ((_currentByte & 1) == 1) ? 2 : 1;
|
||||
_currentByte >>= 1;
|
||||
_stepsLeft--;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Receive step 2: Wait for the calc to lower the other line.
|
||||
if ((Parent.LinkState & 3) == 0)
|
||||
{
|
||||
_stepsLeft--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Receive step 3: Raise the other device's line back up.
|
||||
Parent.LinkInput = 0;
|
||||
_stepsLeft--;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Receive step 4: Wait for the calc to raise its line back up.
|
||||
if ((Parent.LinkState & 3) == 3)
|
||||
{
|
||||
_stepsLeft--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Receive step 5: Finish.
|
||||
_bitsLeft--;
|
||||
|
||||
if (_bitsLeft == 0)
|
||||
{
|
||||
if (CurrentData.Count > 0)
|
||||
{
|
||||
_currentStatus = Status.PrepareReceive;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentStatus = Status.Inactive;
|
||||
_nextStep?.Invoke();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Next bit in the current byte.
|
||||
_stepsLeft = 5;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (_currentStatus == Status.Send)
|
||||
{
|
||||
switch (_stepsLeft)
|
||||
{
|
||||
case 5:
|
||||
// Send step 1: Calc lowers a line.
|
||||
if (Parent.LinkState != 3)
|
||||
{
|
||||
int bit = Parent.LinkState & 1;
|
||||
int shift = 8 - _bitsLeft;
|
||||
_currentByte |= (byte)(bit << shift);
|
||||
_stepsLeft--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Send step 2: Lower our line.
|
||||
Parent.LinkInput = Parent.LinkOutput ^ 3;
|
||||
_stepsLeft--;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Send step 3: wait for the calc to raise its line.
|
||||
if ((Parent.LinkOutput & 3) == 0)
|
||||
{
|
||||
_stepsLeft--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Send step 4: raise the other devices lines.
|
||||
Parent.LinkInput = 0;
|
||||
_stepsLeft--;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Send step 5: Finish
|
||||
_bitsLeft--;
|
||||
|
||||
if (_bitsLeft == 0)
|
||||
{
|
||||
_bytesToSend--;
|
||||
CurrentData.Enqueue(_currentByte);
|
||||
|
||||
if (_bytesToSend > 0)
|
||||
{
|
||||
_currentStatus = Status.PrepareSend;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentStatus = Status.Inactive;
|
||||
_nextStep?.Invoke();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Next bit in the current byte.
|
||||
_stepsLeft = 5;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SendFileToCalc(Stream fs, bool verify)
|
||||
{
|
||||
if (verify)
|
||||
{
|
||||
VerifyFile(fs);
|
||||
}
|
||||
|
||||
fs.Seek(55, SeekOrigin.Begin);
|
||||
_currentFile = fs;
|
||||
SendNextFile();
|
||||
}
|
||||
|
||||
private void VerifyFile(Stream fs)
|
||||
{
|
||||
// Verify the file format.
|
||||
byte[] expected = { 0x2a, 0x2a, 0x54, 0x49, 0x38, 0x33, 0x2a, 0x2a, 0x1a, 0x0a, 0x00 };
|
||||
byte[] actual = new byte[11];
|
||||
|
||||
fs.Seek(0, SeekOrigin.Begin);
|
||||
fs.Read(actual, 0, 11);
|
||||
|
||||
// Check the header.
|
||||
for (int n = 0; n < 11; n++)
|
||||
{
|
||||
if (expected[n] != actual[n])
|
||||
{
|
||||
fs.Close();
|
||||
throw new IOException("Invalid Header.");
|
||||
}
|
||||
}
|
||||
|
||||
// Seek to the end of the comment.
|
||||
fs.Seek(53, SeekOrigin.Begin);
|
||||
|
||||
int size = fs.ReadByte() + (fs.ReadByte() * 256);
|
||||
|
||||
if (fs.Length != size + 57)
|
||||
{
|
||||
fs.Close();
|
||||
throw new IOException("Invalid file length.");
|
||||
}
|
||||
|
||||
// Verify the checksum.
|
||||
ushort checksum = 0;
|
||||
for (int n = 0; n < size; n++)
|
||||
{
|
||||
checksum += (ushort)fs.ReadByte();
|
||||
}
|
||||
|
||||
ushort actualChecksum = (ushort)(fs.ReadByte() + (fs.ReadByte() * 256));
|
||||
|
||||
if (checksum != actualChecksum)
|
||||
{
|
||||
fs.Close();
|
||||
throw new IOException("Invalid Checksum.");
|
||||
}
|
||||
}
|
||||
|
||||
private void SendNextFile()
|
||||
{
|
||||
byte[] header = new byte[13];
|
||||
if (!_currentFile.CanRead || _currentFile.Read(header, 0, 13) != 13)
|
||||
{
|
||||
// End of file.
|
||||
_currentFile.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
int size = header[2] + (header[3] * 256);
|
||||
_variableData = new byte[size + 2];
|
||||
_currentFile.Read(_variableData, 0, size + 2);
|
||||
|
||||
// Request to send the file.
|
||||
CurrentData.Clear();
|
||||
|
||||
CurrentData.Enqueue(0x03);
|
||||
CurrentData.Enqueue(0xC9);
|
||||
foreach (byte b in header)
|
||||
{
|
||||
CurrentData.Enqueue(b);
|
||||
}
|
||||
|
||||
// Calculate the checksum for the command.
|
||||
ushort checksum = 0;
|
||||
for (int n = 2; n < header.Length; n++)
|
||||
{
|
||||
checksum += header[n];
|
||||
}
|
||||
|
||||
CurrentData.Enqueue((byte)(checksum % 256));
|
||||
CurrentData.Enqueue((byte)(checksum / 256));
|
||||
|
||||
// Finalize the command.
|
||||
_currentStatus = Status.PrepareReceive;
|
||||
_nextStep = ReceiveReqAck;
|
||||
Parent.LinkActive = true;
|
||||
}
|
||||
|
||||
private void ReceiveReqAck()
|
||||
{
|
||||
Parent.LinkActive = false;
|
||||
CurrentData.Clear();
|
||||
|
||||
// Prepare to receive the Aknowledgement response from the calculator.
|
||||
_bytesToSend = 8;
|
||||
_currentStatus = Status.PrepareSend;
|
||||
_nextStep = SendVariableData;
|
||||
}
|
||||
|
||||
private void SendVariableData()
|
||||
{
|
||||
// Check to see if out of memory first.
|
||||
CurrentData.Dequeue();
|
||||
CurrentData.Dequeue();
|
||||
CurrentData.Dequeue();
|
||||
CurrentData.Dequeue();
|
||||
CurrentData.Dequeue();
|
||||
|
||||
if (CurrentData.Dequeue() == 0x36)
|
||||
{
|
||||
OutOfMemory();
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentData.Clear();
|
||||
|
||||
CurrentData.Enqueue(0x03);
|
||||
CurrentData.Enqueue(0x56);
|
||||
CurrentData.Enqueue(0x00);
|
||||
CurrentData.Enqueue(0x00);
|
||||
|
||||
CurrentData.Enqueue(0x03);
|
||||
CurrentData.Enqueue(0x15);
|
||||
|
||||
// Add variable data.
|
||||
foreach (byte b in _variableData)
|
||||
{
|
||||
CurrentData.Enqueue(b);
|
||||
}
|
||||
|
||||
// Calculate the checksum.
|
||||
ushort checksum = 0;
|
||||
for (int n = 2; n < _variableData.Length; n++)
|
||||
{
|
||||
checksum += _variableData[n];
|
||||
}
|
||||
|
||||
CurrentData.Enqueue((byte)(checksum % 256));
|
||||
CurrentData.Enqueue((byte)(checksum / 256));
|
||||
|
||||
_currentStatus = Status.PrepareReceive;
|
||||
_nextStep = ReceiveDataAck;
|
||||
Parent.LinkActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReceiveDataAck()
|
||||
{
|
||||
Parent.LinkActive = false;
|
||||
CurrentData.Clear();
|
||||
|
||||
// Prepare to receive the Aknowledgement response from the calculator.
|
||||
_bytesToSend = 4;
|
||||
_currentStatus = Status.PrepareSend;
|
||||
_nextStep = EndTransmission;
|
||||
}
|
||||
|
||||
private void EndTransmission()
|
||||
{
|
||||
CurrentData.Clear();
|
||||
|
||||
// Send the end transmission command.
|
||||
CurrentData.Enqueue(0x03);
|
||||
CurrentData.Enqueue(0x92);
|
||||
CurrentData.Enqueue(0x00);
|
||||
CurrentData.Enqueue(0x00);
|
||||
|
||||
_currentStatus = Status.PrepareReceive;
|
||||
_nextStep = FinalizeFile;
|
||||
Parent.LinkActive = true;
|
||||
}
|
||||
|
||||
private void OutOfMemory()
|
||||
{
|
||||
_currentFile.Close();
|
||||
Parent.LinkActive = false;
|
||||
CurrentData.Clear();
|
||||
|
||||
// Prepare to receive the Aknowledgement response from the calculator.
|
||||
_bytesToSend = 3;
|
||||
_currentStatus = Status.PrepareSend;
|
||||
_nextStep = EndOutOfMemory;
|
||||
}
|
||||
|
||||
private void EndOutOfMemory()
|
||||
{
|
||||
CurrentData.Clear();
|
||||
|
||||
// Send the end transmission command.
|
||||
CurrentData.Enqueue(0x03);
|
||||
CurrentData.Enqueue(0x56);
|
||||
CurrentData.Enqueue(0x01);
|
||||
CurrentData.Enqueue(0x00);
|
||||
|
||||
_currentStatus = Status.PrepareReceive;
|
||||
_nextStep = FinalizeFile;
|
||||
Parent.LinkActive = true;
|
||||
}
|
||||
|
||||
private void FinalizeFile()
|
||||
{
|
||||
// Resets the link software, and checks to see if there is an additional file to send.
|
||||
CurrentData.Clear();
|
||||
Parent.LinkActive = false;
|
||||
_nextStep = null;
|
||||
SendNextFile();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,7 +56,6 @@ namespace BizHawk.Emulation.Cores
|
|||
public const string SubBsnes115 = "SubBSNESv115+";
|
||||
public const string SubGbHawk = "SubGBHawk";
|
||||
public const string SubNesHawk = "SubNESHawk";
|
||||
public const string TI83Hawk = "TI83Hawk";
|
||||
public const string TIC80 = "TIC-80";
|
||||
public const string TST = "T. S. T.";
|
||||
public const string TurboNyma = "TurboNyma";
|
||||
|
|
Loading…
Reference in New Issue