diff --git a/.gitmodules b/.gitmodules
index 15106228fc..0d3ffe3487 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -74,3 +74,7 @@
path = waterbox/gpgx/Genesis-Plus-GX
url = https://github.com/TASEmulators/Genesis-Plus-GX.git
branch = tasvideos-2.1
+[submodule "waterbox/uae/libretro-uae"]
+ path = waterbox/uae/libretro-uae
+ url = https://github.com/TASEmulators/libretro-uae.git
+ branch = wbx
diff --git a/Assets/dll/puae.wbx.zst b/Assets/dll/puae.wbx.zst
new file mode 100644
index 0000000000..ca01b08ced
Binary files /dev/null and b/Assets/dll/puae.wbx.zst differ
diff --git a/src/BizHawk.Client.Common/Api/BizHawkSystemIdToCoreSystemEnumConverter.cs b/src/BizHawk.Client.Common/Api/BizHawkSystemIdToCoreSystemEnumConverter.cs
new file mode 100644
index 0000000000..e109193e3a
--- /dev/null
+++ b/src/BizHawk.Client.Common/Api/BizHawkSystemIdToCoreSystemEnumConverter.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Globalization;
+
+using BizHawk.Emulation.Common;
+
+namespace BizHawk.Client.Common
+{
+ ///
+ /// This class holds a converter for BizHawk SystemId (which is a simple
+ /// It allows you to convert it to a value and vice versa
+ ///
+ /// I made it this way just in case one day we need it for WPF (DependencyProperty binding). Just uncomment :IValueConverter implementation
+ /// I didn't implemented it because of mono compatibility
+ ///
+ public sealed class BizHawkSystemIdToEnumConverter //:IValueConverter
+ {
+ ///
+ /// Convert BizHawk SystemId to value
+ ///
+ /// you want to convert
+ /// The type of the binding target property
+ /// The converter parameter to use; null in our case
+ /// The culture to use in the converter
+ /// A that is equivalent to BizHawk SystemId
+ /// Thrown when SystemId hasn't been found
+ public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)
+ {
+ return (string) value switch
+ {
+ VSystemID.Raw.Amiga => CoreSystem.Amiga,
+ VSystemID.Raw.AppleII => CoreSystem.AppleII,
+ VSystemID.Raw.A26 => CoreSystem.Atari2600,
+ VSystemID.Raw.A78 => CoreSystem.Atari7800,
+ VSystemID.Raw.Arcade => CoreSystem.Arcade,
+ VSystemID.Raw.Coleco => CoreSystem.ColecoVision,
+ VSystemID.Raw.C64 => CoreSystem.Commodore64,
+ VSystemID.Raw.GBL => CoreSystem.GameBoyLink,
+ VSystemID.Raw.GB => CoreSystem.GameBoy,
+ VSystemID.Raw.GBA => CoreSystem.GameBoyAdvance,
+ VSystemID.Raw.GEN => CoreSystem.Genesis,
+ VSystemID.Raw.INTV => CoreSystem.Intellivision,
+ VSystemID.Raw.Libretro => CoreSystem.Libretro,
+ VSystemID.Raw.Lynx => CoreSystem.Lynx,
+ VSystemID.Raw.SMS => CoreSystem.MasterSystem,
+ VSystemID.Raw.NDS => CoreSystem.NintendoDS,
+ VSystemID.Raw.NES => CoreSystem.NES,
+ VSystemID.Raw.N64 => CoreSystem.Nintendo64,
+ VSystemID.Raw.NULL => CoreSystem.Null,
+ VSystemID.Raw.PCE => CoreSystem.PCEngine,
+ VSystemID.Raw.PCECD => CoreSystem.PCEngine,
+ VSystemID.Raw.SGX => CoreSystem.PCEngine,
+ VSystemID.Raw.PSX => CoreSystem.Playstation,
+ VSystemID.Raw.SAT => CoreSystem.Saturn,
+ VSystemID.Raw.SNES => CoreSystem.SNES,
+ VSystemID.Raw.TI83 => CoreSystem.TI83,
+ VSystemID.Raw.VEC => CoreSystem.Vectrex,
+ VSystemID.Raw.WSWAN => CoreSystem.WonderSwan,
+ VSystemID.Raw.ZXSpectrum => CoreSystem.ZXSpectrum,
+ VSystemID.Raw.AmstradCPC => CoreSystem.AmstradCPC,
+ VSystemID.Raw.GGL => CoreSystem.GGL,
+ VSystemID.Raw.ChannelF => CoreSystem.ChannelF,
+ VSystemID.Raw.O2 => CoreSystem.Odyssey2,
+ VSystemID.Raw.MSX => CoreSystem.MSX,
+ VSystemID.Raw.VB => CoreSystem.VirtualBoy,
+ VSystemID.Raw.NGP => CoreSystem.NeoGeoPocket,
+ VSystemID.Raw.SGB => CoreSystem.SuperGameBoy,
+ VSystemID.Raw.UZE => CoreSystem.UzeBox,
+ VSystemID.Raw.PCFX => CoreSystem.PcFx,
+ _ => throw new InvalidOperationException($"{value} is missing in convert list")
+ };
+ }
+
+
+ ///
+ /// Convert BizHawk SystemId to value
+ ///
+ /// you want to convert
+ /// A that is equivalent to BizHawk SystemId
+ /// Thrown when SystemId hasn't been found
+ public CoreSystem Convert(string value)
+ {
+ return (CoreSystem)Convert(value, null, null, CultureInfo.CurrentCulture);
+ }
+
+
+ ///
+ /// Convert a value to BizHawk SystemId
+ ///
+ /// you want to convert
+ /// The type of the binding target property
+ /// The converter parameter to use; null in our case
+ /// The culture to use in the converter
+ /// A that is used by BizHawk SystemId
+ /// Thrown when hasn't been found
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo)
+ {
+ return (CoreSystem) value switch
+ {
+ CoreSystem.Amiga => VSystemID.Raw.Amiga,
+ CoreSystem.AppleII => VSystemID.Raw.AppleII,
+ CoreSystem.Atari2600 => VSystemID.Raw.A26,
+ CoreSystem.Atari7800 => VSystemID.Raw.A78,
+ CoreSystem.Arcade => VSystemID.Raw.Arcade,
+ CoreSystem.ChannelF => VSystemID.Raw.ChannelF,
+ CoreSystem.ColecoVision => VSystemID.Raw.Coleco,
+ CoreSystem.Commodore64 => VSystemID.Raw.C64,
+ CoreSystem.GameBoyLink => VSystemID.Raw.GBL,
+ CoreSystem.GameBoy => VSystemID.Raw.GB,
+ CoreSystem.GameBoyAdvance => VSystemID.Raw.GBA,
+ CoreSystem.Genesis => VSystemID.Raw.GEN,
+ CoreSystem.GGL => VSystemID.Raw.GGL,
+ CoreSystem.Intellivision => VSystemID.Raw.INTV,
+ CoreSystem.Libretro => VSystemID.Raw.Libretro,
+ CoreSystem.Lynx => VSystemID.Raw.Lynx,
+ CoreSystem.MasterSystem => VSystemID.Raw.SMS,
+ CoreSystem.MSX => VSystemID.Raw.MSX,
+ CoreSystem.NeoGeoPocket => VSystemID.Raw.NGP,
+ CoreSystem.NES => VSystemID.Raw.NES,
+ CoreSystem.Nintendo64 => VSystemID.Raw.N64,
+ CoreSystem.NintendoDS => VSystemID.Raw.NDS,
+ CoreSystem.Null => VSystemID.Raw.NULL,
+ CoreSystem.PCEngine => VSystemID.Raw.PCE,
+ CoreSystem.PcFx => VSystemID.Raw.PCFX,
+ CoreSystem.Playstation => VSystemID.Raw.PSX,
+ CoreSystem.Saturn => VSystemID.Raw.SAT,
+ CoreSystem.SNES => VSystemID.Raw.SNES,
+ CoreSystem.SuperGameBoy => VSystemID.Raw.SGB,
+ CoreSystem.TI83 => VSystemID.Raw.TI83,
+ CoreSystem.UzeBox => VSystemID.Raw.UZE,
+ CoreSystem.Vectrex => VSystemID.Raw.VEC,
+ CoreSystem.VirtualBoy => VSystemID.Raw.VB,
+ CoreSystem.WonderSwan => VSystemID.Raw.WSWAN,
+ CoreSystem.ZXSpectrum => VSystemID.Raw.ZXSpectrum,
+ CoreSystem.AmstradCPC => VSystemID.Raw.AmstradCPC,
+ CoreSystem.Odyssey2 => VSystemID.Raw.O2,
+ _ => throw new InvalidOperationException($"{value} is missing in convert list")
+ };
+ }
+
+
+ ///
+ /// Convert a value to BizHawk SystemId
+ ///
+ /// you want to convert
+ /// A that is used by BizHawk SystemId
+ /// Thrown when hasn't been found
+ public string ConvertBack(CoreSystem value)
+ {
+ return (string)ConvertBack(value, null, null, CultureInfo.CurrentCulture);
+ }
+ }
+}
diff --git a/src/BizHawk.Client.Common/Api/CoreSystem.cs b/src/BizHawk.Client.Common/Api/CoreSystem.cs
new file mode 100644
index 0000000000..7efdc52832
--- /dev/null
+++ b/src/BizHawk.Client.Common/Api/CoreSystem.cs
@@ -0,0 +1,46 @@
+namespace BizHawk.Client.Common
+{
+ ///
+ /// Enumeration of each system emulated by BizHawk
+ ///
+ public enum CoreSystem
+ {
+ Null = 0,
+ TI83,
+ AppleII,
+ Commodore64,
+ Atari2600,
+ Atari7800,
+ Lynx,
+ ColecoVision,
+ Intellivision,
+ GameBoy,
+ GameBoyLink,
+ GameBoyAdvance,
+ NintendoDS,
+ Nintendo64,
+ NES,
+ SNES,
+ PCEngine,
+ Genesis,
+ Saturn,
+ MasterSystem,
+ Playstation,
+ WonderSwan,
+ Libretro,
+ VirtualBoy,
+ Vectrex,
+ NeoGeoPocket,
+ ZXSpectrum,
+ AmstradCPC,
+ GGL,
+ ChannelF,
+ Odyssey2,
+ Arcade,
+ MSX,
+ SuperGameBoy,
+ UzeBox,
+ PcFx,
+ Amiga
+ }
+}
diff --git a/src/BizHawk.Client.Common/RomLoader.cs b/src/BizHawk.Client.Common/RomLoader.cs
index 1c0c5c0461..0d0423e244 100644
--- a/src/BizHawk.Client.Common/RomLoader.cs
+++ b/src/BizHawk.Client.Common/RomLoader.cs
@@ -875,6 +875,8 @@ namespace BizHawk.Client.Common
public static readonly IReadOnlyCollection A78 = new[] { "a78" };
+ public static readonly IReadOnlyCollection Amiga = new[] { "adf", "adz", "dms", "fdi", "ipf", "lha" };
+
public static readonly IReadOnlyCollection AppleII = new[] { "dsk", "do", "po" };
public static readonly IReadOnlyCollection Arcade = new[] { "zip", "7z", "chd" };
@@ -934,6 +936,7 @@ namespace BizHawk.Client.Common
public static readonly IReadOnlyCollection AutoloadFromArchive = Array.Empty()
.Concat(A26)
.Concat(A78)
+ .Concat(Amiga)
.Concat(AppleII)
.Concat(C64)
.Concat(Coleco)
@@ -1004,6 +1007,7 @@ namespace BizHawk.Client.Common
new FilesystemFilter("Vectrex", RomFileExtensions.VEC),
new FilesystemFilter("MSX", RomFileExtensions.MSX),
new FilesystemFilter("Arcade", RomFileExtensions.Arcade),
+ new FilesystemFilter("Amiga", RomFileExtensions.Amiga),
FilesystemFilter.EmuHawkSaveStates)
{
CombinedEntryDesc = "Everything",
diff --git a/src/BizHawk.Client.Common/config/PathEntryCollection.cs b/src/BizHawk.Client.Common/config/PathEntryCollection.cs
index 524462c497..e7deff8949 100644
--- a/src/BizHawk.Client.Common/config/PathEntryCollection.cs
+++ b/src/BizHawk.Client.Common/config/PathEntryCollection.cs
@@ -22,6 +22,7 @@ namespace BizHawk.Client.Common
private static readonly Dictionary _displayNameLookup = new()
{
[GLOBAL] = "Global",
+ [VSystemID.Raw.Amiga] = "Amiga",
[VSystemID.Raw.Arcade] = "Arcade",
[VSystemID.Raw.INTV] = "Intellivision",
[VSystemID.Raw.NES] = "NES",
@@ -193,6 +194,8 @@ namespace BizHawk.Client.Common
CommonEntriesFor(VSystemID.Raw.Sega32X, basePath: Path.Combine(".", "32X")),
+ CommonEntriesFor(VSystemID.Raw.Amiga, basePath: Path.Combine(".", "Amiga")),
+
CommonEntriesFor(VSystemID.Raw.A26, basePath: Path.Combine(".", "Atari 2600"), omitSaveRAM: true),
CommonEntriesFor(VSystemID.Raw.A78, basePath: Path.Combine(".", "Atari 7800")),
diff --git a/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs b/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs
index bef6976ac1..87e39cecfe 100644
--- a/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs
+++ b/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs
@@ -717,6 +717,19 @@ namespace BizHawk.Client.Common
["F11"] = '1',
["F12"] = '2',
},
+ [VSystemID.Raw.Amiga] = new()
+ {
+ ["Joystick Up"] = 'U',
+ ["Joystick Down"] = 'D',
+ ["Joystick Left"] = 'L',
+ ["Joystick Right"] = 'R',
+ ["Joystick Button 1"] = '1',
+ ["Joystick Button 2"] = '2',
+ ["Joystick Button 3"] = '3',
+ ["Mouse Left Button"] = 'l',
+ ["Mouse Middle Button"] = 'm',
+ ["Mouse Right Button"] = 'r',
+ }
};
private static readonly Dictionary BaseAxisLookupTable = new Dictionary
diff --git a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs
index 09dd61baf6..382672c41f 100644
--- a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs
+++ b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs
@@ -62,6 +62,7 @@ namespace BizHawk.Client.EmuHawk
// Redundant with SystemLookup? Not so fast. That data drives things. This is one step abstracted. Don't be such a smart guy. Keep this redundant list up to date.
private static readonly Dictionary SystemGroupNames = new Dictionary
{
+ ["Amiga"] = "Amiga",
["NES"] = "NES",
["SNES"] = "SNES",
["BSX"] = "SNES+Satellaview",
diff --git a/src/BizHawk.Emulation.Common/Database/Database.cs b/src/BizHawk.Emulation.Common/Database/Database.cs
index f98ac30fde..cdaa5e7f5f 100644
--- a/src/BizHawk.Emulation.Common/Database/Database.cs
+++ b/src/BizHawk.Emulation.Common/Database/Database.cs
@@ -401,6 +401,15 @@ namespace BizHawk.Emulation.Common
game.System = VSystemID.Raw.TIC80;
break;
+ case ".ADF":
+ case ".ADZ":
+ case ".DMS":
+ case ".IPF":
+ case ".FDI":
+ case ".LHA":
+ game.System = VSystemID.Raw.Amiga;
+ break;
+
case ".32X":
game.System = VSystemID.Raw.Sega32X;
game.AddOption("32X", "true");
diff --git a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs
index f82528580d..28e0ff2c77 100644
--- a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs
+++ b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs
@@ -505,6 +505,30 @@ namespace BizHawk.Emulation.Common
FirmwareAndOption("10C4173C2A7EB09C6579818F72EF18FA0B6D32DE", 4 * 1024 * 1024, "N64DD", "IPL_DEV", "64DD_IPL_DEV.bin", "N64DD Development IPL");
FirmwareAndOption("3C5B93CA231550C68693A14F03CEA8D5DBD1BE9E", 4 * 1024 * 1024, "N64DD", "IPL_USA", "64DD_IPL_USA.bin", "N64DD Prototype USA IPL");
+ Firmware("Amiga", "A500", "A500 Kickstart");
+ Option("Amiga", "A500", File("891E9A547772FE0C6C19B610BAF8BC4EA7FCB785", 262144, "amiga-os-130.rom", "Kickstart v1.3 r34.005 (1987-12)(Commodore)(A500-A1000-A2000-CDTV)[!]"), FirmwareOptionStatus.Ideal);
+ Option("Amiga", "A500", File("11F9E62CF299F72184835B7B2A70A16333FC0D88", 262144, "amiga-os-120.rom", "Kickstart v1.2 r33.180 (1986-10)(Commodore)(A500-A1000-A2000)[!]"));
+ Option("Amiga", "A500", File("3B7F1493B27E212830F989F26CA76C02049F09CA", 524288, "amiga-os-310-a600.rom", "Kickstart v3.1 r40.063 (1993-07)(Commodore)(A500-A600-A2000)[!]"));
+
+ Firmware("Amiga", "A600", "A500+/A600/A600HD Kickstart");
+ Option("Amiga", "A600", File("02843C4253BBD29ABA535B0AA3BD9A85034ECDE4", 524288, "amiga-os-205-a600.rom", "Kickstart v2.05 r37.350 (1992-04)(Commodore)(A600HD)[!]"), FirmwareOptionStatus.Ideal);
+ Option("Amiga", "A600", File("C5839F5CB98A7A8947065C3ED2F14F5F42E334A1", 524288, "amiga-os-204.rom", "Kickstart v2.04 r37.175 (1991-05)(Commodore)(A500+)[!]"));
+ Option("Amiga", "A600", File("3B7F1493B27E212830F989F26CA76C02049F09CA", 524288, "amiga-os-310-a600.rom", "Kickstart v3.1 r40.063 (1993-07)(Commodore)(A500-A600-A2000)[!]"));
+
+ Firmware("Amiga", "A1200", "A1200 Kickstart");
+ Option("Amiga", "A1200", File("E21545723FE8374E91342617604F1B3D703094F1", 524288, "amiga-os-310-a1200.rom", "Kickstart v3.1 r40.068 (1993-12)(Commodore)(A1200)[!]"), FirmwareOptionStatus.Ideal);
+ Option("Amiga", "A1200", File("70033828182FFFC7ED106E5373A8B89DDA76FAA5", 524288, "amiga-os-300-a1200.rom", "Kickstart v3.0 r39.106 (1992-09)(Commodore)(A1200)[!]"));
+
+ Firmware("Amiga", "A4000", "A4000/A4000T Kickstart");
+ Option("Amiga", "A4000", File("5FE04842D04A489720F0F4BB0E46948199406F49", 524288, "amiga-os-310-a4000.rom", "Kickstart v3.1 r40.068 (1993-12)(Commodore)(A4000)[!]"), FirmwareOptionStatus.Ideal);
+ Option("Amiga", "A4000", File("F0B4E9E29E12218C2D5BD7020E4E785297D91FD7", 524288, "amiga-os-300-a4000.rom", "Kickstart v3.0 r39.106 (1992-09)(Commodore)(A4000)[!]"));
+ Option("Amiga", "A4000", File("B0EC8B84D6768321E01209F11E6248F2F5281A21", 524288, "amiga-os-310-a4000t.rom", "Kickstart v3.1 r40.070 (1994-02)(Commodore)(A4000T)[!]"));
+
+ Firmware("Amiga", "CD32", "CD32 Kickstart");
+ Option("Amiga", "CD32", File("3525BE8887F79B5929E017B42380A79EDFEE542D", 524288, "amiga-os-310-cd32.rom", "Kickstart v3.1 r40.060 (1993-05)(Commodore)(CD32)[!].rom"), FirmwareOptionStatus.Ideal);
+ Firmware("Amiga", "CD32ext", "CD32 Extended ROM");
+ Option("Amiga", "CD32ext", File("5BEF3D628CE59CC02A66E6E4AE0DA48F60E78F7F", 524288, "amiga-os-310-cd32-ext.rom", "CD32 Extended-ROM r40.60 (1993)(Commodore)(CD32).rom"), FirmwareOptionStatus.Ideal);
+
/*Firmware("PS2", "BIOS", "PS2 Bios");
Option("PS2", "BIOS", File("FBD54BFC020AF34008B317DCB80B812DD29B3759", 4 * 1024 * 1024, "ps2-0230j-20080220.bin", "PS2 Bios"));
Option("PS2", "BIOS", File("8361D615CC895962E0F0838489337574DBDC9173", 4 * 1024 * 1024, "ps2-0220a-20060905.bin", "PS2 Bios"));
diff --git a/src/BizHawk.Emulation.Common/Extensions.cs b/src/BizHawk.Emulation.Common/Extensions.cs
index d3e83b7d85..6a7f492bad 100644
--- a/src/BizHawk.Emulation.Common/Extensions.cs
+++ b/src/BizHawk.Emulation.Common/Extensions.cs
@@ -17,6 +17,7 @@ namespace BizHawk.Emulation.Common
/// need to think about e.g. Genesis / Mega Drive using one sysID but having a different display name depending on the BIOS region --yoshi
public static readonly IReadOnlyDictionary SystemIDDisplayNames = new Dictionary
{
+ [VSystemID.Raw.Amiga] = "Amiga",
[VSystemID.Raw.A26] = "Atari 2600",
[VSystemID.Raw.A78] = "Atari 7800",
[VSystemID.Raw.AmstradCPC] = "Amstrad CPC",
diff --git a/src/BizHawk.Emulation.Cores/Computers/Amiga/LibPUAE.cs b/src/BizHawk.Emulation.Cores/Computers/Amiga/LibPUAE.cs
new file mode 100644
index 0000000000..a577c8f0a5
--- /dev/null
+++ b/src/BizHawk.Emulation.Cores/Computers/Amiga/LibPUAE.cs
@@ -0,0 +1,156 @@
+using BizHawk.BizInvoke;
+using BizHawk.Emulation.Cores.Waterbox;
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Emulation.Cores.Computers.Amiga
+{
+ public abstract class LibPUAE : LibWaterboxCore
+ {
+ public const int PAL_WIDTH = 720;
+ public const int PAL_HEIGHT = 576;
+ public const int NTSC_WIDTH = 720;
+ public const int NTSC_HEIGHT = 480;
+ public const int KEY_COUNT = 0x68;
+
+ [BizImport(CC, Compatibility = true)]
+ public abstract bool Init(int argc, string[] argv);
+
+ [StructLayout(LayoutKind.Sequential)]
+ public new class FrameInfo : LibWaterboxCore.FrameInfo
+ {
+ public PUAEJoystick JoystickState;
+ public byte MouseButtons;
+ public int MouseX;
+ public int MouseY;
+ public KeyBuffer Keys;
+
+ public struct KeyBuffer
+ {
+ public unsafe fixed byte Buffer[LibPUAE.KEY_COUNT];
+ }
+ }
+
+ [Flags]
+ public enum PUAEJoystick : byte
+ {
+ Joystick_Up = 1 << 0,
+ Joystick_Down = 1 << 1,
+ Joystick_Left = 1 << 2,
+ Joystick_Right = 1 << 3,
+ Joystick_Button_1 = 1 << 4,
+ Joystick_Button_2 = 1 << 5,
+ Joystick_Button_3 = 1 << 6
+ }
+
+ // https://wiki.amigaos.net/wiki/Keymap_Library
+ public enum PUAEKeyboard : int
+ {
+ Key_Backquote = 0x00,
+ Key_1 = 0x01,
+ Key_2 = 0x02,
+ Key_3 = 0x03,
+ Key_4 = 0x04,
+ Key_5 = 0x05,
+ Key_6 = 0x06,
+ Key_7 = 0x07,
+ Key_8 = 0x08,
+ Key_9 = 0x09,
+ Key_0 = 0x0A,
+ Key_Minus = 0x0B,
+ Key_Equal = 0x0C,
+ Key_Backslash = 0x0D,
+// Undefined = 0x0E,
+ Key_NP_0 = 0x0F,
+ Key_Q = 0x10,
+ Key_W = 0x11,
+ Key_E = 0x12,
+ Key_R = 0x13,
+ Key_T = 0x14,
+ Key_Y = 0x15,
+ Key_U = 0x16,
+ Key_I = 0x17,
+ Key_O = 0x18,
+ Key_P = 0x19,
+ Key_Left_Bracket = 0x1A,
+ Key_Right_Bracket = 0x1B,
+// Undefined = 0x1C,
+ Key_NP_1 = 0x1D,
+ Key_NP_2 = 0x1E,
+ Key_NP_3 = 0x1F,
+ Key_A = 0x20,
+ Key_S = 0x21,
+ Key_D = 0x22,
+ Key_F = 0x23,
+ Key_G = 0x24,
+ Key_H = 0x25,
+ Key_J = 0x26,
+ Key_K = 0x27,
+ Key_L = 0x28,
+ Key_Semicolon = 0x29,
+ Key_Quote = 0x2A,
+ Key_Number_Sign = 0x2B, // not on most USA keyboards
+// Undefined = 0x2C,
+ Key_NP_4 = 0x2D,
+ Key_NP_5 = 0x2E,
+ Key_NP_6 = 0x2F,
+ Key_Less = 0x30, // not on most USA keyboards
+ Key_Z = 0x31,
+ Key_X = 0x32,
+ Key_C = 0x33,
+ Key_V = 0x34,
+ Key_B = 0x35,
+ Key_N = 0x36,
+ Key_M = 0x37,
+ Key_Comma = 0x38,
+ Key_Period = 0x39,
+ Key_Slash = 0x3A,
+// Undefined = 0x3B,
+ Key_NP_Delete = 0x3C,
+ Key_NP_7 = 0x3D,
+ Key_NP_8 = 0x3E,
+ Key_NP_9 = 0x3F,
+ Key_Space = 0x40,
+ Key_Backspace = 0x41,
+ Key_Tab = 0x42,
+ Key_NP_Enter = 0x43,
+ Key_Return = 0x44,
+ Key_Escape = 0x45,
+ Key_Delete = 0x46,
+// Undefined = 0x47,
+// Undefined = 0x48,
+// Undefined = 0x49,
+ Key_NP_Sub = 0x4A,
+// Undefined = 0x4B,
+ Key_Up = 0x4C,
+ Key_Down = 0x4D,
+ Key_Right = 0x4E,
+ Key_Left = 0x4F,
+ Key_F1 = 0x50,
+ Key_F2 = 0x51,
+ Key_F3 = 0x52,
+ Key_F4 = 0x53,
+ Key_F5 = 0x54,
+ Key_F6 = 0x55,
+ Key_F7 = 0x56,
+ Key_F8 = 0x57,
+ Key_F9 = 0x58,
+ Key_F10 = 0x59,
+ Key_NP_Left_Paren = 0x5A,
+ Key_NP_Right_Paren = 0x5B,
+ Key_NP_Div = 0x5C,
+ Key_NP_Mul = 0x5D,
+ Key_NP_Add = 0x5E,
+ Key_Help = 0x5F,
+ Key_Left_Shift = 0x60,
+ Key_Right_Shift = 0x61,
+ Key_Caps_Lock = 0x62,
+ Key_Ctrl = 0x63,
+ Key_Left_Alt = 0x64,
+ Key_Right_Alt = 0x65,
+ Key_Left_Amiga = 0x66,
+ Key_Right_Amiga = 0x67,
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.ISettable.cs b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.ISettable.cs
new file mode 100644
index 0000000000..ab09719fff
--- /dev/null
+++ b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.ISettable.cs
@@ -0,0 +1,184 @@
+using System;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+
+using BizHawk.Common;
+using BizHawk.Emulation.Common;
+
+namespace BizHawk.Emulation.Cores.Computers.Amiga
+{
+ public partial class PUAE : ISettable