[GambatteLink] changes in link API, misc cleanup
This commit is contained in:
parent
de8748d6d1
commit
f7936a34f8
Binary file not shown.
Binary file not shown.
|
@ -4,6 +4,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
{
|
{
|
||||||
public partial class Gameboy : ILinkable
|
public partial class Gameboy : ILinkable
|
||||||
{
|
{
|
||||||
public bool LinkConnected { get; set; }
|
private bool _linkConnected;
|
||||||
|
|
||||||
|
public bool LinkConnected
|
||||||
|
{
|
||||||
|
get => _linkConnected;
|
||||||
|
set { return; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
{
|
{
|
||||||
public partial class Gameboy : ITextStatable
|
public partial class Gameboy : IStatable, ITextStatable
|
||||||
{
|
{
|
||||||
public void SaveStateText(TextWriter writer)
|
public void SaveStateText(TextWriter writer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
{
|
{
|
||||||
public partial class Gameboy
|
public partial class Gameboy : IVideoProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// buffer of last frame produced
|
/// buffer of last frame produced
|
||||||
|
|
|
@ -13,14 +13,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PortedCore(CoreNames.Gambatte, "", "Gambatte-Speedrun r717+", "https://github.com/pokemon-speedrunning/gambatte-speedrun")]
|
[PortedCore(CoreNames.Gambatte, "", "Gambatte-Speedrun r717+", "https://github.com/pokemon-speedrunning/gambatte-speedrun")]
|
||||||
[ServiceNotApplicable(new[] { typeof(IDriveLight) })]
|
[ServiceNotApplicable(new[] { typeof(IDriveLight) })]
|
||||||
public partial class Gameboy : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable, ICodeDataLogger,
|
public partial class Gameboy : IInputPollable, IRomInfo, IGameboyCommon, ICycleTiming, ILinkable
|
||||||
IBoardInfo, IRomInfo, IDebuggable, ISettable<Gameboy.GambatteSettings, Gameboy.GambatteSyncSettings>,
|
|
||||||
IGameboyCommon, ICycleTiming, ILinkable
|
|
||||||
{
|
{
|
||||||
[CoreConstructor(VSystemID.Raw.GB)]
|
[CoreConstructor(VSystemID.Raw.GB)]
|
||||||
[CoreConstructor(VSystemID.Raw.GBC)]
|
[CoreConstructor(VSystemID.Raw.GBC)]
|
||||||
[CoreConstructor(VSystemID.Raw.SGB)]
|
[CoreConstructor(VSystemID.Raw.SGB)]
|
||||||
public Gameboy(CoreComm comm, GameInfo game, byte[] file, Gameboy.GambatteSettings settings, Gameboy.GambatteSyncSettings syncSettings, bool deterministic)
|
public Gameboy(CoreComm comm, GameInfo game, byte[] file, GambatteSettings settings, GambatteSyncSettings syncSettings, bool deterministic)
|
||||||
{
|
{
|
||||||
var ser = new BasicServiceProvider(this);
|
var ser = new BasicServiceProvider(this);
|
||||||
ser.Register<IDisassemblable>(_disassembler);
|
ser.Register<IDisassemblable>(_disassembler);
|
||||||
|
@ -707,11 +705,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
{
|
{
|
||||||
printer = new GambattePrinter(this, callback);
|
printer = new GambattePrinter(this, callback);
|
||||||
LinkConnected = true;
|
_linkConnected = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LinkConnected = false;
|
_linkConnected = false;
|
||||||
if (printer != null) // have no idea how this is ever null???
|
if (printer != null) // have no idea how this is ever null???
|
||||||
{
|
{
|
||||||
printer.Disconnect();
|
printer.Disconnect();
|
||||||
|
|
|
@ -34,8 +34,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
bool linkDiscoSignalNew = controller.IsPressed("Toggle Link Connection");
|
bool linkDiscoSignalNew = controller.IsPressed("Toggle Link Connection");
|
||||||
if (linkDiscoSignalNew && !_linkDiscoSignal)
|
if (linkDiscoSignalNew && !_linkDiscoSignal)
|
||||||
{
|
{
|
||||||
_linkConnected ^= true;
|
LinkConnected ^= true;
|
||||||
Console.WriteLine("Link connect status to {0}", _linkConnected);
|
Console.WriteLine("Link connect status to {0}", LinkConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
_linkDiscoSignal = linkDiscoSignalNew;
|
_linkDiscoSignal = linkDiscoSignalNew;
|
||||||
|
@ -229,29 +229,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
|
|
||||||
if (CanIR(one, two))
|
if (CanIR(one, two))
|
||||||
{
|
{
|
||||||
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 260) != 0) // InfraredTrigger
|
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 259) != 0) // InfraredTrigger
|
||||||
{
|
{
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 261); // ack
|
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 260); // ack
|
||||||
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 262) != 0) // GetOut
|
if (LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 261) != 0) // GetOut
|
||||||
{
|
{
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 263); // ShiftInOn
|
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 262); // ShiftInOn
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 264); // ShiftInOff
|
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 263); // ShiftInOff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 260) != 0) // InfraredTrigger
|
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 259) != 0) // InfraredTrigger
|
||||||
{
|
{
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 261); // ack
|
LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 260); // ack
|
||||||
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 262) != 0) // GetOut
|
if (LibGambatte.gambatte_linkstatus(_linkedCores[two].GambatteState, 261) != 0) // GetOut
|
||||||
{
|
{
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 263); // ShiftInOn
|
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 262); // ShiftInOn
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 264); // ShiftInOff
|
LibGambatte.gambatte_linkstatus(_linkedCores[one].GambatteState, 263); // ShiftInOff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
for (int i = 0; i < _numCores; i++)
|
for (int i = 0; i < _numCores; i++)
|
||||||
{
|
{
|
||||||
_linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested);
|
_linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested);
|
||||||
LibGambatte.gambatte_linkstatus(_linkedCores[i].GambatteState, 259); // connect link cable
|
|
||||||
_linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks);
|
_linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks);
|
||||||
_linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks);
|
_linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks);
|
||||||
_linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(false, false));
|
_linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(false, false));
|
||||||
|
@ -76,7 +75,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
public bool LinkConnected
|
public bool LinkConnected
|
||||||
{
|
{
|
||||||
get => _linkConnected;
|
get => _linkConnected;
|
||||||
set => _linkConnected = value;
|
set
|
||||||
|
{
|
||||||
|
_linkConnected = value;
|
||||||
|
for (int i = 0; i < _numCores; i++)
|
||||||
|
{
|
||||||
|
LibGambatte.gambatte_linkstatus(_linkedCores[i].GambatteState, _linkConnected ? 264 : 265);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _numCores = 0;
|
private int _numCores = 0;
|
||||||
|
|
|
@ -1,311 +1,314 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy;
|
using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Emulate the gameboy printer in managed code
|
/// Emulate the gameboy printer in managed code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GambattePrinter
|
public class GambattePrinter
|
||||||
{
|
{
|
||||||
// A loose c->c# port of SameBoy's printer code
|
// A loose c->c# port of SameBoy's printer code
|
||||||
|
|
||||||
private enum CommandState : byte
|
private enum CommandState : byte
|
||||||
{
|
{
|
||||||
GB_PRINTER_COMMAND_MAGIC1,
|
GB_PRINTER_COMMAND_MAGIC1,
|
||||||
GB_PRINTER_COMMAND_MAGIC2,
|
GB_PRINTER_COMMAND_MAGIC2,
|
||||||
GB_PRINTER_COMMAND_ID,
|
GB_PRINTER_COMMAND_ID,
|
||||||
GB_PRINTER_COMMAND_COMPRESSION,
|
GB_PRINTER_COMMAND_COMPRESSION,
|
||||||
GB_PRINTER_COMMAND_LENGTH_LOW,
|
GB_PRINTER_COMMAND_LENGTH_LOW,
|
||||||
GB_PRINTER_COMMAND_LENGTH_HIGH,
|
GB_PRINTER_COMMAND_LENGTH_HIGH,
|
||||||
GB_PRINTER_COMMAND_DATA,
|
GB_PRINTER_COMMAND_DATA,
|
||||||
GB_PRINTER_COMMAND_CHECKSUM_LOW,
|
GB_PRINTER_COMMAND_CHECKSUM_LOW,
|
||||||
GB_PRINTER_COMMAND_CHECKSUM_HIGH,
|
GB_PRINTER_COMMAND_CHECKSUM_HIGH,
|
||||||
GB_PRINTER_COMMAND_ACTIVE,
|
GB_PRINTER_COMMAND_ACTIVE,
|
||||||
GB_PRINTER_COMMAND_STATUS,
|
GB_PRINTER_COMMAND_STATUS,
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CommandID : byte
|
private enum CommandID : byte
|
||||||
{
|
{
|
||||||
GB_PRINTER_INIT_COMMAND = 1,
|
GB_PRINTER_INIT_COMMAND = 1,
|
||||||
GB_PRINTER_START_COMMAND = 2,
|
GB_PRINTER_START_COMMAND = 2,
|
||||||
GB_PRINTER_DATA_COMMAND = 4,
|
GB_PRINTER_DATA_COMMAND = 4,
|
||||||
GB_PRINTER_NOP_COMMAND = 0xF,
|
GB_PRINTER_NOP_COMMAND = 0xF,
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int GB_PRINTER_MAX_COMMAND_LENGTH = 0x280;
|
private const int GB_PRINTER_MAX_COMMAND_LENGTH = 0x280;
|
||||||
private const int GB_PRINTER_DATA_SIZE = 0x280;
|
private const int GB_PRINTER_DATA_SIZE = 0x280;
|
||||||
|
|
||||||
private const ushort SerialIRQAddress = 0x58;
|
private const ushort SerialIRQAddress = 0x58;
|
||||||
|
|
||||||
private readonly Gameboy gb;
|
private readonly Gameboy gb;
|
||||||
private readonly PrinterCallback callback;
|
private readonly PrinterCallback callback;
|
||||||
private LibGambatte.LinkCallback linkCallback;
|
private readonly LibGambatte.LinkCallback linkCallback;
|
||||||
|
|
||||||
private CommandState command_state;
|
private CommandState command_state;
|
||||||
private CommandID command_id;
|
private CommandID command_id;
|
||||||
|
|
||||||
private bool compression;
|
private bool compression;
|
||||||
private ushort length_left;
|
private ushort length_left;
|
||||||
private readonly byte[] command_data = new byte[GB_PRINTER_MAX_COMMAND_LENGTH];
|
private readonly byte[] command_data = new byte[GB_PRINTER_MAX_COMMAND_LENGTH];
|
||||||
private ushort command_length;
|
private ushort command_length;
|
||||||
private ushort checksum;
|
private ushort checksum;
|
||||||
private byte status;
|
private byte status;
|
||||||
|
|
||||||
private readonly byte[] image = new byte[160 * 200];
|
private readonly byte[] image = new byte[160 * 200];
|
||||||
private ushort image_offset;
|
private ushort image_offset;
|
||||||
|
|
||||||
private byte compression_run_length;
|
private byte compression_run_length;
|
||||||
private bool compression_run_is_compressed;
|
private bool compression_run_is_compressed;
|
||||||
|
|
||||||
public GambattePrinter(Gameboy gb, PrinterCallback callback)
|
public GambattePrinter(Gameboy gb, PrinterCallback callback)
|
||||||
{
|
{
|
||||||
this.gb = gb;
|
this.gb = gb;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
|
||||||
linkCallback = OnSerial;
|
linkCallback = OnSerial;
|
||||||
LibGambatte.gambatte_setlinkcallback(gb.GambatteState, linkCallback);
|
LibGambatte.gambatte_setlinkcallback(gb.GambatteState, linkCallback);
|
||||||
|
|
||||||
// connect the cable
|
// connect the cable
|
||||||
LibGambatte.gambatte_linkstatus(gb.GambatteState, 259);
|
LibGambatte.gambatte_linkstatus(gb.GambatteState, 264);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
if (gb.GambatteState != IntPtr.Zero)
|
if (gb.GambatteState != IntPtr.Zero)
|
||||||
LibGambatte.gambatte_setlinkcallback(gb.GambatteState, null);
|
{
|
||||||
}
|
LibGambatte.gambatte_setlinkcallback(gb.GambatteState, null);
|
||||||
|
LibGambatte.gambatte_linkstatus(gb.GambatteState, 265);
|
||||||
private void OnSerial()
|
}
|
||||||
{
|
}
|
||||||
if (LibGambatte.gambatte_linkstatus(gb.GambatteState, 256) != 0) // ClockTrigger
|
|
||||||
{
|
private void OnSerial()
|
||||||
LibGambatte.gambatte_linkstatus(gb.GambatteState, 257); // ack
|
{
|
||||||
|
if (LibGambatte.gambatte_linkstatus(gb.GambatteState, 256) != 0) // ClockTrigger
|
||||||
byte output = HandleSerial((byte)LibGambatte.gambatte_linkstatus(gb.GambatteState, 258)); // GetOut
|
{
|
||||||
LibGambatte.gambatte_linkstatus(gb.GambatteState, output); // ShiftIn
|
LibGambatte.gambatte_linkstatus(gb.GambatteState, 257); // ack
|
||||||
}
|
|
||||||
}
|
byte output = HandleSerial((byte)LibGambatte.gambatte_linkstatus(gb.GambatteState, 258)); // GetOut
|
||||||
|
LibGambatte.gambatte_linkstatus(gb.GambatteState, output); // ShiftIn
|
||||||
private byte HandleSerial(byte byte_received)
|
}
|
||||||
{
|
}
|
||||||
byte byte_to_send = 0;
|
|
||||||
|
private byte HandleSerial(byte byte_received)
|
||||||
switch (command_state)
|
{
|
||||||
{
|
byte byte_to_send = 0;
|
||||||
case CommandState.GB_PRINTER_COMMAND_MAGIC1:
|
|
||||||
if (byte_received != 0x88)
|
switch (command_state)
|
||||||
{
|
{
|
||||||
return byte_to_send;
|
case CommandState.GB_PRINTER_COMMAND_MAGIC1:
|
||||||
}
|
if (byte_received != 0x88)
|
||||||
status &= 254;
|
{
|
||||||
command_length = 0;
|
return byte_to_send;
|
||||||
checksum = 0;
|
}
|
||||||
break;
|
status &= 254;
|
||||||
|
command_length = 0;
|
||||||
case CommandState.GB_PRINTER_COMMAND_MAGIC2:
|
checksum = 0;
|
||||||
if (byte_received != 0x33)
|
break;
|
||||||
{
|
|
||||||
if (byte_received != 0x88)
|
case CommandState.GB_PRINTER_COMMAND_MAGIC2:
|
||||||
{
|
if (byte_received != 0x33)
|
||||||
command_state = CommandState.GB_PRINTER_COMMAND_MAGIC1;
|
{
|
||||||
}
|
if (byte_received != 0x88)
|
||||||
return byte_to_send;
|
{
|
||||||
}
|
command_state = CommandState.GB_PRINTER_COMMAND_MAGIC1;
|
||||||
break;
|
}
|
||||||
|
return byte_to_send;
|
||||||
case CommandState.GB_PRINTER_COMMAND_ID:
|
}
|
||||||
command_id = (CommandID)(byte_received & 0xF);
|
break;
|
||||||
break;
|
|
||||||
|
case CommandState.GB_PRINTER_COMMAND_ID:
|
||||||
case CommandState.GB_PRINTER_COMMAND_COMPRESSION:
|
command_id = (CommandID)(byte_received & 0xF);
|
||||||
compression = (byte_received & 1) != 0;
|
break;
|
||||||
break;
|
|
||||||
|
case CommandState.GB_PRINTER_COMMAND_COMPRESSION:
|
||||||
case CommandState.GB_PRINTER_COMMAND_LENGTH_LOW:
|
compression = (byte_received & 1) != 0;
|
||||||
length_left = byte_received;
|
break;
|
||||||
break;
|
|
||||||
|
case CommandState.GB_PRINTER_COMMAND_LENGTH_LOW:
|
||||||
case CommandState.GB_PRINTER_COMMAND_LENGTH_HIGH:
|
length_left = byte_received;
|
||||||
length_left |= (ushort)((byte_received & 3) << 8);
|
break;
|
||||||
break;
|
|
||||||
|
case CommandState.GB_PRINTER_COMMAND_LENGTH_HIGH:
|
||||||
case CommandState.GB_PRINTER_COMMAND_DATA:
|
length_left |= (ushort)((byte_received & 3) << 8);
|
||||||
if (command_length != GB_PRINTER_MAX_COMMAND_LENGTH)
|
break;
|
||||||
{
|
|
||||||
if (compression)
|
case CommandState.GB_PRINTER_COMMAND_DATA:
|
||||||
{
|
if (command_length != GB_PRINTER_MAX_COMMAND_LENGTH)
|
||||||
if (compression_run_length == 0)
|
{
|
||||||
{
|
if (compression)
|
||||||
compression_run_is_compressed = (byte_received & 0x80) != 0;
|
{
|
||||||
compression_run_length = (byte)((byte_received & 0x7F) + 1 + (compression_run_is_compressed ? 1 : 0));
|
if (compression_run_length == 0)
|
||||||
}
|
{
|
||||||
else if (compression_run_is_compressed)
|
compression_run_is_compressed = (byte_received & 0x80) != 0;
|
||||||
{
|
compression_run_length = (byte)((byte_received & 0x7F) + 1 + (compression_run_is_compressed ? 1 : 0));
|
||||||
while (compression_run_length > 0)
|
}
|
||||||
{
|
else if (compression_run_is_compressed)
|
||||||
command_data[command_length++] = byte_received;
|
{
|
||||||
compression_run_length--;
|
while (compression_run_length > 0)
|
||||||
if (command_length == GB_PRINTER_MAX_COMMAND_LENGTH)
|
{
|
||||||
{
|
command_data[command_length++] = byte_received;
|
||||||
compression_run_length = 0;
|
compression_run_length--;
|
||||||
}
|
if (command_length == GB_PRINTER_MAX_COMMAND_LENGTH)
|
||||||
}
|
{
|
||||||
}
|
compression_run_length = 0;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
command_data[command_length++] = byte_received;
|
}
|
||||||
compression_run_length--;
|
else
|
||||||
}
|
{
|
||||||
}
|
command_data[command_length++] = byte_received;
|
||||||
else
|
compression_run_length--;
|
||||||
{
|
}
|
||||||
command_data[command_length++] = byte_received;
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
length_left--;
|
command_data[command_length++] = byte_received;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
case CommandState.GB_PRINTER_COMMAND_CHECKSUM_LOW:
|
length_left--;
|
||||||
checksum ^= byte_received;
|
break;
|
||||||
break;
|
|
||||||
|
case CommandState.GB_PRINTER_COMMAND_CHECKSUM_LOW:
|
||||||
case CommandState.GB_PRINTER_COMMAND_CHECKSUM_HIGH:
|
checksum ^= byte_received;
|
||||||
checksum ^= (ushort)(byte_received << 8);
|
break;
|
||||||
if (checksum != 0)
|
|
||||||
{
|
case CommandState.GB_PRINTER_COMMAND_CHECKSUM_HIGH:
|
||||||
status |= 1; /* Checksum error*/
|
checksum ^= (ushort)(byte_received << 8);
|
||||||
command_state = CommandState.GB_PRINTER_COMMAND_MAGIC1;
|
if (checksum != 0)
|
||||||
return byte_to_send;
|
{
|
||||||
}
|
status |= 1; /* Checksum error*/
|
||||||
break;
|
command_state = CommandState.GB_PRINTER_COMMAND_MAGIC1;
|
||||||
|
return byte_to_send;
|
||||||
case CommandState.GB_PRINTER_COMMAND_ACTIVE:
|
}
|
||||||
byte_to_send = 0x81;
|
break;
|
||||||
break;
|
|
||||||
|
case CommandState.GB_PRINTER_COMMAND_ACTIVE:
|
||||||
case CommandState.GB_PRINTER_COMMAND_STATUS:
|
byte_to_send = 0x81;
|
||||||
|
break;
|
||||||
if (((int)command_id & 0xF) == (byte)CommandID.GB_PRINTER_INIT_COMMAND)
|
|
||||||
{
|
case CommandState.GB_PRINTER_COMMAND_STATUS:
|
||||||
/* Games expect INIT commands to return 0? */
|
|
||||||
byte_to_send = 0;
|
if (((int)command_id & 0xF) == (byte)CommandID.GB_PRINTER_INIT_COMMAND)
|
||||||
}
|
{
|
||||||
else
|
/* Games expect INIT commands to return 0? */
|
||||||
{
|
byte_to_send = 0;
|
||||||
byte_to_send = status;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
/* Printing is done instantly, but let the game recieve a 6 (Printing) status at least once, for compatibility */
|
byte_to_send = status;
|
||||||
if (status == 6)
|
}
|
||||||
{
|
|
||||||
status = 4; /* Done */
|
/* Printing is done instantly, but let the game recieve a 6 (Printing) status at least once, for compatibility */
|
||||||
}
|
if (status == 6)
|
||||||
|
{
|
||||||
command_state = CommandState.GB_PRINTER_COMMAND_MAGIC1;
|
status = 4; /* Done */
|
||||||
HandleCommand();
|
}
|
||||||
return byte_to_send;
|
|
||||||
}
|
command_state = CommandState.GB_PRINTER_COMMAND_MAGIC1;
|
||||||
|
HandleCommand();
|
||||||
if (command_state >= CommandState.GB_PRINTER_COMMAND_ID && command_state < CommandState.GB_PRINTER_COMMAND_CHECKSUM_LOW)
|
return byte_to_send;
|
||||||
{
|
}
|
||||||
checksum += byte_received;
|
|
||||||
}
|
if (command_state >= CommandState.GB_PRINTER_COMMAND_ID && command_state < CommandState.GB_PRINTER_COMMAND_CHECKSUM_LOW)
|
||||||
|
{
|
||||||
if (command_state != CommandState.GB_PRINTER_COMMAND_DATA)
|
checksum += byte_received;
|
||||||
{
|
}
|
||||||
command_state++;
|
|
||||||
}
|
if (command_state != CommandState.GB_PRINTER_COMMAND_DATA)
|
||||||
|
{
|
||||||
if (command_state == CommandState.GB_PRINTER_COMMAND_DATA)
|
command_state++;
|
||||||
{
|
}
|
||||||
if (length_left == 0)
|
|
||||||
{
|
if (command_state == CommandState.GB_PRINTER_COMMAND_DATA)
|
||||||
command_state++;
|
{
|
||||||
}
|
if (length_left == 0)
|
||||||
}
|
{
|
||||||
|
command_state++;
|
||||||
return byte_to_send;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleCommand()
|
return byte_to_send;
|
||||||
{
|
}
|
||||||
switch (command_id)
|
|
||||||
{
|
private void HandleCommand()
|
||||||
case CommandID.GB_PRINTER_INIT_COMMAND:
|
{
|
||||||
status = 0;
|
switch (command_id)
|
||||||
image_offset = 0;
|
{
|
||||||
break;
|
case CommandID.GB_PRINTER_INIT_COMMAND:
|
||||||
|
status = 0;
|
||||||
case CommandID.GB_PRINTER_START_COMMAND:
|
image_offset = 0;
|
||||||
if (command_length == 4)
|
break;
|
||||||
{
|
|
||||||
status = 6; /* Printing */
|
case CommandID.GB_PRINTER_START_COMMAND:
|
||||||
uint[] outputImage = new uint[image_offset];
|
if (command_length == 4)
|
||||||
|
{
|
||||||
int palette = command_data[2];
|
status = 6; /* Printing */
|
||||||
uint[] colors = {
|
uint[] outputImage = new uint[image_offset];
|
||||||
0xFFFFFFFFU,
|
|
||||||
0xFFAAAAAAU,
|
int palette = command_data[2];
|
||||||
0xFF555555U,
|
uint[] colors = {
|
||||||
0xFF000000U
|
0xFFFFFFFFU,
|
||||||
};
|
0xFFAAAAAAU,
|
||||||
for (int i = 0; i < image_offset; i++)
|
0xFF555555U,
|
||||||
{
|
0xFF000000U
|
||||||
outputImage[i] = colors[(palette >> (image[i] * 2)) & 3];
|
};
|
||||||
}
|
for (int i = 0; i < image_offset; i++)
|
||||||
|
{
|
||||||
if (callback != null)
|
outputImage[i] = colors[(palette >> (image[i] * 2)) & 3];
|
||||||
{
|
}
|
||||||
// The native-friendly callback almost seems silly now :P
|
|
||||||
unsafe
|
if (callback != null)
|
||||||
{
|
{
|
||||||
fixed (uint* imagePtr = outputImage)
|
// The native-friendly callback almost seems silly now :P
|
||||||
{
|
unsafe
|
||||||
callback((IntPtr)imagePtr, (byte)(image_offset / 160),
|
{
|
||||||
(byte)(command_data[1] >> 4), (byte)(command_data[1] & 7),
|
fixed (uint* imagePtr = outputImage)
|
||||||
(byte)(command_data[3] & 0x7F));
|
{
|
||||||
}
|
callback((IntPtr)imagePtr, (byte)(image_offset / 160),
|
||||||
}
|
(byte)(command_data[1] >> 4), (byte)(command_data[1] & 7),
|
||||||
}
|
(byte)(command_data[3] & 0x7F));
|
||||||
|
}
|
||||||
image_offset = 0;
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
image_offset = 0;
|
||||||
case CommandID.GB_PRINTER_DATA_COMMAND:
|
}
|
||||||
if (command_length == GB_PRINTER_DATA_SIZE)
|
break;
|
||||||
{
|
|
||||||
image_offset %= (ushort)image.Length;
|
case CommandID.GB_PRINTER_DATA_COMMAND:
|
||||||
status = 8; /* Received 0x280 bytes */
|
if (command_length == GB_PRINTER_DATA_SIZE)
|
||||||
|
{
|
||||||
int data_index = 0;
|
image_offset %= (ushort)image.Length;
|
||||||
|
status = 8; /* Received 0x280 bytes */
|
||||||
for (int row = 2; row > 0; row--)
|
|
||||||
{
|
int data_index = 0;
|
||||||
for (int tile_x = 0; tile_x < 160 / 8; tile_x++)
|
|
||||||
{
|
for (int row = 2; row > 0; row--)
|
||||||
for (int y = 0; y < 8; y++, data_index += 2)
|
{
|
||||||
{
|
for (int tile_x = 0; tile_x < 160 / 8; tile_x++)
|
||||||
for (int x_pixel = 0; x_pixel < 8; x_pixel++)
|
{
|
||||||
{
|
for (int y = 0; y < 8; y++, data_index += 2)
|
||||||
image[image_offset + tile_x * 8 + x_pixel + y * 160] =
|
{
|
||||||
(byte)((command_data[data_index] >> 7) | ((command_data[data_index + 1] >> 7) << 1));
|
for (int x_pixel = 0; x_pixel < 8; x_pixel++)
|
||||||
command_data[data_index] <<= 1;
|
{
|
||||||
command_data[data_index + 1] <<= 1;
|
image[image_offset + tile_x * 8 + x_pixel + y * 160] =
|
||||||
}
|
(byte)((command_data[data_index] >> 7) | ((command_data[data_index + 1] >> 7) << 1));
|
||||||
}
|
command_data[data_index] <<= 1;
|
||||||
}
|
command_data[data_index + 1] <<= 1;
|
||||||
|
}
|
||||||
image_offset += 8 * 160;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
image_offset += 8 * 160;
|
||||||
|
}
|
||||||
default:
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
default:
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 72630bfce765fc8e9fd60e78de3c3fe4aae571a1
|
Subproject commit dc50297053a3e8fff285629d735a9618b9406245
|
Loading…
Reference in New Issue