diff --git a/.gitmodules b/.gitmodules index 15106228fcf..0d3ffe34879 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 00000000000..ca01b08ceda 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 00000000000..e109193e3ae --- /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 00000000000..7efdc52832b --- /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 1c0c5c04612..0d0423e2440 100644 --- a/src/BizHawk.Client.Common/RomLoader.cs +++ b/src/BizHawk.Client.Common/RomLoader.cs @@ -875,6 +875,8 @@ private static class RomFileExtensions 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 @@ private static class RomFileExtensions public static readonly IReadOnlyCollection AutoloadFromArchive = Array.Empty() .Concat(A26) .Concat(A78) + .Concat(Amiga) .Concat(AppleII) .Concat(C64) .Concat(Coleco) @@ -1004,6 +1007,7 @@ private static class RomFileExtensions 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 524462c4971..e7deff8949d 100644 --- a/src/BizHawk.Client.Common/config/PathEntryCollection.cs +++ b/src/BizHawk.Client.Common/config/PathEntryCollection.cs @@ -22,6 +22,7 @@ public class PathEntryCollection 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 @@ public void ResolveWithDefaults() 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 bef6976ac10..87e39cecfe1 100644 --- a/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs +++ b/src/BizHawk.Client.Common/movie/bk2/Bk2MnemonicLookup.cs @@ -717,6 +717,19 @@ public static string LookupAxis(string button, string systemId) ["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 09dd61baf66..382672c41ff 100644 --- a/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs +++ b/src/BizHawk.Client.EmuHawk/config/FirmwaresConfig.cs @@ -62,6 +62,7 @@ public partial class FirmwaresConfig : Form, IDialogParent // 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 f98ac30fde0..cdaa5e7f5f7 100644 --- a/src/BizHawk.Emulation.Common/Database/Database.cs +++ b/src/BizHawk.Emulation.Common/Database/Database.cs @@ -401,6 +401,15 @@ public static GameInfo GetGameInfo(byte[] romData, string fileName) 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 f82528580d4..28e0ff2c775 100644 --- a/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs +++ b/src/BizHawk.Emulation.Common/Database/FirmwareDatabase.cs @@ -505,6 +505,30 @@ void AddPatchAndMaybeReverse(FirmwarePatchOption fpo) 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 d3e83b7d855..6a7f492bad0 100644 --- a/src/BizHawk.Emulation.Common/Extensions.cs +++ b/src/BizHawk.Emulation.Common/Extensions.cs @@ -17,6 +17,7 @@ public static class EmulatorExtensions /// 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 00000000000..a577c8f0a58 --- /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 00000000000..ab09719ffff --- /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 + { + public const int FASTMEM_AUTO = -1; + + public enum MachineConfig + { + [Display(Name = "A500 OCS KS1.3 512K 512K")] + A500_OCS_130_512K_512K, + [Display(Name = "A600 ECS KS2.05 2M")] + A600_ECS_205_2M, + [Display(Name = "A1200 AGA KS3.1 2M 8M")] + A1200_AGA_310_2M_8M, + [Display(Name = "A4000 AGA KS3.1 2M 8M")] + A4000_AGA_310_2M_8M, + // CD32 + } + + public enum CpuModel + { + [Display(Name = "68000")] + _68000 = 68000, + [Display(Name = "68010")] + _68010 = 68010, + [Display(Name = "68020")] + _68020 = 68020, + [Display(Name = "68030")] + _68030 = 68030, + [Display(Name = "68040")] + _68040 = 68040, + [Display(Name = "68060")] + _68060 = 68060, + Auto + } + + public enum ChipsetCompatible + { + A500, + A600, + A1200, + A4000, + Auto + } + + public enum Chipset + { + OCS, + [Display(Name = "ECS Agnus")] + ECS_Agnus, + [Display(Name = "ECS Denise")] + ECS_Denise, + ECS, + AGA, + Auto + } + + public enum ChipMemory + { + [Display(Name = "512KB")] + KB_512 = 1, + [Display(Name = "1MB")] + MB_1, + [Display(Name = "1.5MB")] + MB_1_5, + [Display(Name = "2MB")] + MB_2, + [Display(Name = "2.5MB")] + MB_2_5, + [Display(Name = "3MB")] + MB_3, + [Display(Name = "3.5MB")] + MB_3_5, + [Display(Name = "4MB")] + MB_4, + [Display(Name = "4.5MB")] + MB_4_5, + [Display(Name = "5MB")] + MB_5, + [Display(Name = "5.5MB")] + MB_5_5, + [Display(Name = "6MB")] + MB_6, + [Display(Name = "6.5MB")] + MB_6_5, + [Display(Name = "7MB")] + MB_7, + [Display(Name = "7.5MB")] + MB_7_5, + [Display(Name = "8MB")] + MB_8, + Auto + } + + public enum SlowMemory + { + [Display(Name = "0")] + KB_0 = 0, + [Display(Name = "512KB")] + KB_512 = 2, + [Display(Name = "1MB")] + MB_1 = 4, + [Display(Name = "1.5MB")] + MB_1_5 = 6, + Auto + } + + public object GetSettings() => null; + public PutSettingsDirtyBits PutSettings(object o) => PutSettingsDirtyBits.None; + + private PUAESyncSettings _syncSettings; + public PUAESyncSettings GetSyncSettings() + => _syncSettings.Clone(); + + public PutSettingsDirtyBits PutSyncSettings(PUAESyncSettings o) + { + var ret = PUAESyncSettings.NeedsReboot(_syncSettings, o); + _syncSettings = o; + return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; + } + + [CoreSettings] + public class PUAESyncSettings + { + [DisplayName("Machine configuration")] + [Description("")] + [DefaultValue(MachineConfig.A500_OCS_130_512K_512K)] + [TypeConverter(typeof(DescribableEnumConverter))] + public MachineConfig MachineConfig { get; set; } + + [DisplayName("CPU model")] + [Description("")] + [DefaultValue(CpuModel.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public CpuModel CpuModel { get; set; } + + [DisplayName("Chipset compatible")] + [Description("")] + [DefaultValue(ChipsetCompatible.Auto)] + public ChipsetCompatible ChipsetCompatible { get; set; } + + [DisplayName("Chipset")] + [Description("")] + [DefaultValue(Chipset.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public Chipset Chipset { get; set; } + + [DisplayName("Chip memory")] + [Description("Size of chip-memory")] + [DefaultValue(ChipMemory.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public ChipMemory ChipMemory { get; set; } + + [DisplayName("Slow memory")] + [Description("Size of bogo-memory at 0xC00000")] + [DefaultValue(SlowMemory.Auto)] + [TypeConverter(typeof(DescribableEnumConverter))] + public SlowMemory SlowMemory { get; set; } + + [DisplayName("Fast memory")] + [Description("Size in megabytes of fast-memory. -1 means Auto.")] + [Range(FASTMEM_AUTO, 512)] + [DefaultValue(FASTMEM_AUTO)] + [TypeConverter(typeof(ConstrainedIntConverter))] + public int FastMemory { get; set; } + + public PUAESyncSettings() + => SettingsUtil.SetDefaultValues(this); + + public PUAESyncSettings Clone() + => (PUAESyncSettings)MemberwiseClone(); + + public static bool NeedsReboot(PUAESyncSettings x, PUAESyncSettings y) + => !DeepEquality.DeepEquals(x, y); + } + } +} diff --git a/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.cs b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.cs new file mode 100644 index 00000000000..51f91b29be6 --- /dev/null +++ b/src/BizHawk.Emulation.Cores/Computers/Amiga/PUAE.cs @@ -0,0 +1,265 @@ +using BizHawk.Common; +using BizHawk.Common.CollectionExtensions; +using BizHawk.Common.StringExtensions; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; + +using System; +using System.Collections.Generic; + +namespace BizHawk.Emulation.Cores.Computers.Amiga +{ + [PortedCore( + name: CoreNames.PUAE, + author: "UAE Team", + portedVersion: "5.0.0", + portedUrl: "https://github.com/libretro/libretro-uae")] + public partial class PUAE : WaterboxCore + { + private LibPUAE _puae; + private static string _chipsetCompatible = ""; + + [CoreConstructor(VSystemID.Raw.Amiga)] + public PUAE(CoreLoadParameters lp) + : base(lp.Comm, new Configuration + { + DefaultWidth = LibPUAE.PAL_WIDTH, + DefaultHeight = LibPUAE.PAL_HEIGHT, + MaxWidth = LibPUAE.PAL_WIDTH, + MaxHeight = LibPUAE.PAL_HEIGHT, + MaxSamples = 2 * 1024, + SystemId = VSystemID.Raw.Amiga, + DefaultFpsNumerator = 50, + DefaultFpsDenominator = 1 + }) + { + _syncSettings = lp.SyncSettings ?? new(); + + _puae = PreInit(new WaterboxOptions + { + Filename = "puae.wbx", + SbrkHeapSizeKB = 5 * 512, + SealedHeapSizeKB = 10 * 1024, + InvisibleHeapSizeKB = 10 * 1024, + PlainHeapSizeKB = 10 * 1024, + MmapHeapSizeKB = 40 * 1024, + SkipCoreConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), + SkipMemoryConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), + }); + + var filesToRemove = new List(); + var args = CreateArguments(_syncSettings); + + _exe.AddReadonlyFile(lp.Roms[0].FileData, "romfile"); + filesToRemove.Add("romfile"); + + var (kickstartData, kickstartInfo) = CoreComm.CoreFileProvider.GetFirmwareWithGameInfoOrThrow( + new(VSystemID.Raw.Amiga, _chipsetCompatible), + "Firmware files are usually required and may stop your game from loading"); + _exe.AddReadonlyFile(kickstartData, kickstartInfo.Name); + filesToRemove.Add(kickstartInfo.Name); + args.AddRange(new List + { + "-r", kickstartInfo.Name + }); + + ControllerDefinition = InitInput(); + + if (!_puae.Init(args.Count, args.ToArray())) + throw new InvalidOperationException("Core rejected the rom!"); + + foreach (var s in filesToRemove) + { + //_exe.RemoveReadonlyFile(s); + } + + PostInit(); + } + + private static List CreateArguments(PUAESyncSettings settings) + { + + var args = new List + { + "puae" + , "-0", "romfile" + , "-s", "cpu_compatible=true" + , "-s", "cpu_cycle_exact=true" + , "-s", "cpu_memory_cycle_exact=true" + , "-s", "blitter_cycle_exact=true" + }; + + switch(settings.MachineConfig) + { + case MachineConfig.A500_OCS_130_512K_512K: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A500); + args.AddRange(new List + { + "-s", "cpu_model=" + (int)CpuModel._68000 + , "-s", "chipset=" + Chipset.OCS + , "-s", "chipset_compatible=" + _chipsetCompatible + , "-s", "chipmem_size=" + (int)ChipMemory.KB_512 + , "-s", "bogomem_size=" + (int)SlowMemory.KB_512 + , "-s", "fastmem_size=0" + }); + break; + case MachineConfig.A600_ECS_205_2M: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A600); + args.AddRange(new List + { + "-s", "cpu_model=" + (int)CpuModel._68000 + , "-s", "chipset=" + Chipset.ECS + , "-s", "chipset_compatible=" + _chipsetCompatible + , "-s", "chipmem_size=" + (int)ChipMemory.MB_2 + , "-s", "bogomem_size=" + (int)SlowMemory.KB_0 + , "-s", "fastmem_size=0" + }); + break; + case MachineConfig.A1200_AGA_310_2M_8M: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A1200); + args.AddRange(new List + { + "-s", "cpu_model=" + (int)CpuModel._68020 + , "-s", "chipset=" + Chipset.AGA + , "-s", "chipset_compatible=" + _chipsetCompatible + , "-s", "chipmem_size=" + (int)ChipMemory.MB_2 + , "-s", "bogomem_size=" + (int)SlowMemory.KB_0 + , "-s", "fastmem_size=8" + }); + break; + case MachineConfig.A4000_AGA_310_2M_8M: + _chipsetCompatible = Enum.GetName(typeof(ChipsetCompatible), ChipsetCompatible.A4000); + args.AddRange(new List + { + "-s", "cpu_model=" + (int)CpuModel._68040 + , "-s", "fpu_model=68040" + , "-s", "mmu_model=68040" + , "-s", "chipset=" + Chipset.AGA + , "-s", "chipset_compatible=" + _chipsetCompatible + , "-s", "chipmem_size=" + (int)ChipMemory.MB_2 + , "-s", "bogomem_size=" + (int)SlowMemory.KB_0 + , "-s", "fastmem_size=8" + }); + break; + } + + if (settings.CpuModel != CpuModel.Auto) + { + args.AddRange(new List { "-s", "cpu_model=" + (int)settings.CpuModel }); + } + + if (settings.Chipset != Chipset.Auto) + { + args.AddRange(new List { "-s", "chipset=" + (int)settings.Chipset }); + } + + if (settings.ChipsetCompatible != ChipsetCompatible.Auto) + { + args.AddRange(new List { "-s", "chipset_compatible=" + + Enum.GetName(typeof(ChipsetCompatible), settings.ChipsetCompatible) }); + } + + if (settings.ChipMemory != ChipMemory.Auto) + { + args.AddRange(new List { "-s", "chipmem_size=" + (int)settings.ChipMemory }); + } + + if (settings.SlowMemory != SlowMemory.Auto) + { + args.AddRange(new List { "-s", "bogomem_size=" + (int)settings.SlowMemory }); + } + + if (settings.FastMemory != FASTMEM_AUTO) + { + args.AddRange(new List { "-s", "fastmem_size=" + settings.FastMemory }); + } + + return args; + } + + private static ControllerDefinition InitInput() + { + var controller = new ControllerDefinition("Amiga Controller"); + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEJoystick))) + { + var name = Enum.GetName(typeof(LibPUAE.PUAEJoystick), b).Replace('_', ' '); + controller.BoolButtons.Add(name); + controller.CategoryLabels[name] = "Joystick"; + } + + controller.BoolButtons.AddRange(new List + { + "Mouse Left Button", "Mouse Middle Button", "Mouse Right Button" + }); + + controller + .AddAxis("Mouse X", (0).RangeTo(LibPUAE.PAL_WIDTH), LibPUAE.PAL_WIDTH / 2) + .AddAxis("Mouse Y", (0).RangeTo(LibPUAE.PAL_HEIGHT), LibPUAE.PAL_HEIGHT / 2); + + foreach (var b in controller.BoolButtons) + { + if (b.StartsWithOrdinal("Mouse")) + { + controller.CategoryLabels[b] = "Mouse"; + } + } + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEKeyboard))) + { + var name = Enum.GetName(typeof(LibPUAE.PUAEKeyboard), b).Replace('_', ' '); + controller.BoolButtons.Add(name); + controller.CategoryLabels[name] = "Keyboard"; + } + + return controller.MakeImmutable(); + } + + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) + { + var fi = new LibPUAE.FrameInfo + { + MouseButtons = 0 + }; + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEJoystick))) + { + if (controller.IsPressed(Enum.GetName(typeof(LibPUAE.PUAEJoystick), b).Replace('_', ' '))) + { + fi.JoystickState |= (LibPUAE.PUAEJoystick)b; + } + } + + if (controller.IsPressed("Mouse Left Button")) + { + fi.MouseButtons |= 1 << 0; + } + if (controller.IsPressed("Mouse Right Button")) + { + fi.MouseButtons |= 1 << 1; + } + if (controller.IsPressed("Mouse Middle Button")) + { + fi.MouseButtons |= 1 << 2; + } + + fi.MouseX = controller.AxisValue("Mouse X"); + fi.MouseY = controller.AxisValue("Mouse Y"); + + foreach (var b in Enum.GetValues(typeof(LibPUAE.PUAEKeyboard))) + { + var name = Enum.GetName(typeof(LibPUAE.PUAEKeyboard), b); + var value = (int)Enum.Parse(typeof(LibPUAE.PUAEKeyboard), name); + if (controller.IsPressed(name.Replace('_', ' '))) + { + unsafe + { + fi.Keys.Buffer[value] = 1; + } + } + } + + return fi; + } + } +} \ No newline at end of file diff --git a/src/BizHawk.Emulation.Cores/CoreNames.cs b/src/BizHawk.Emulation.Cores/CoreNames.cs index 34f729b7232..3dd44477c88 100644 --- a/src/BizHawk.Emulation.Cores/CoreNames.cs +++ b/src/BizHawk.Emulation.Cores/CoreNames.cs @@ -46,6 +46,7 @@ public static class CoreNames public const string Octoshock = "Octoshock"; public const string PceHawk = "PCEHawk"; public const string PicoDrive = "PicoDrive"; + public const string PUAE = "PUAE"; public const string QuickNes = "quickerNES"; public const string Sameboy = "SameBoy"; public const string Saturnus = "Saturnus"; diff --git a/waterbox/uae/Makefile b/waterbox/uae/Makefile new file mode 100644 index 00000000000..1641ba2f628 --- /dev/null +++ b/waterbox/uae/Makefile @@ -0,0 +1,270 @@ +CORE_DIR = libretro-uae +TARGET = puae.wbx +EMU = $(CORE_DIR)/sources/src +LIBRETRO = $(CORE_DIR)/libretro +DEPS_DIR = $(CORE_DIR)/deps +RETRODEP = $(CORE_DIR)/retrodep +LIBRETRO_COMM_DIR = $(CORE_DIR)/libretro-common + +SOURCES_C += bizhawk.c + +INCFLAGS = \ + -I$(EMU) \ + -I$(EMU)/include \ + -I$(CORE_DIR) \ + -I$(RETRODEP) \ + -I$(DEPS_DIR)/7zip \ + -I$(DEPS_DIR)/libmpeg2/include \ + -I$(LIBRETRO) \ + -I$(LIBRETRO_COMM_DIR)/include \ + -I$(LIBRETRO_COMM_DIR)/include/compat/zlib + +LDFLAGS += + +CCFLAGS += \ + -std=gnu99 \ + -w -ferror-limit=0 + +CCFLAGS += $(INCFLAGS) \ + -D__LIBRETRO__ \ + -DINLINE="inline" \ + -MMD \ + -DHAVE_ZLIB \ + -DHAVE_7ZIP \ + -D_7ZIP_ST \ + -DWATERBOX \ + -DWITH_MPEG2 + +#CCFLAGS += \ + -DPICASSO96_SUPPORTED \ + +CXXFLAGS += $(INCFLAGS) -DUAE -MMD + +SOURCES_C += \ + $(LIBRETRO)/libretro-core.c \ + $(LIBRETRO)/libretro-mapper.c \ + $(LIBRETRO)/libretro-dc.c \ + $(LIBRETRO)/libretro-glue.c \ + $(LIBRETRO)/libretro-vkbd.c \ + $(LIBRETRO)/libretro-graph.c \ + $(DEPS_DIR)/libz/unzip.c \ + $(DEPS_DIR)/libz/ioapi.c + +SOURCES_C += \ + $(EMU)/a2065.c \ + $(EMU)/a2091.c \ + $(EMU)/akiko.c \ + $(EMU)/amax.c \ + $(EMU)/ar.c \ + $(EMU)/arcadia.c \ + $(EMU)/aros.rom.c \ + $(EMU)/audio.c \ + $(EMU)/autoconf.c \ + $(EMU)/blitfunc.c \ + $(EMU)/blittable.c \ + $(EMU)/blitter.c \ + $(EMU)/blkdev.c \ + $(EMU)/blkdev_cdimage.c \ + $(EMU)/bsdsocket.c \ + $(EMU)/calc.c \ + $(EMU)/caps/caps.c \ + $(EMU)/caps/uae_dlopen.c \ + $(EMU)/casablanca.c \ + $(EMU)/cd32_fmv.c \ + $(EMU)/cd32_fmv_genlock.c \ + $(EMU)/cda_play.c \ + $(EMU)/cdrom.c \ + $(EMU)/cdtv.c \ + $(EMU)/cdtvcr.c \ + $(EMU)/cfgfile.c \ + $(EMU)/cia.c \ + $(EMU)/cpuboard.c \ + $(EMU)/cpudefs.c \ + $(EMU)/cpuemu_0.c \ + $(EMU)/cpuemu_11.c \ + $(EMU)/cpuemu_13.c \ + $(EMU)/cpuemu_20.c \ + $(EMU)/cpuemu_21.c \ + $(EMU)/cpuemu_22.c \ + $(EMU)/cpuemu_23.c \ + $(EMU)/cpuemu_24.c \ + $(EMU)/cpuemu_31.c \ + $(EMU)/cpuemu_32.c \ + $(EMU)/cpuemu_33.c \ + $(EMU)/cpuemu_34.c \ + $(EMU)/cpuemu_35.c \ + $(EMU)/cpuemu_40.c \ + $(EMU)/cpuemu_50.c \ + $(EMU)/cpummu.c \ + $(EMU)/cpummu30.c \ + $(EMU)/cpustbl.c \ + $(EMU)/crc32.c \ + $(EMU)/custom.c \ + $(EMU)/debug.c \ + $(EMU)/debugmem.c \ + $(EMU)/devices.c \ + $(EMU)/disasm.c \ + $(EMU)/disk.c \ + $(EMU)/diskutil.c \ + $(EMU)/dongle.c \ + $(EMU)/drawing.c \ + $(EMU)/driveclick.c \ + $(EMU)/ethernet.c \ + $(EMU)/events.c \ + $(EMU)/expansion.c \ + $(EMU)/fdi2raw.c\ + $(EMU)/filesys.c \ + $(EMU)/filesys_unix.c \ + $(EMU)/flashrom.c \ + $(EMU)/fpp.c \ + $(EMU)/fpp_native.c \ + $(EMU)/fpp_softfloat.c \ + $(EMU)/fsdb.c \ + $(EMU)/fsdb_unix.c \ + $(EMU)/fsusage.c \ + $(EMU)/gayle.c \ + $(EMU)/gfxboard.c \ + $(EMU)/gfxlib.c \ + $(EMU)/gfxutil.c \ + $(EMU)/hardfile.c \ + $(EMU)/hardfile_unix.c \ + $(EMU)/hrtmon.rom.c \ + $(EMU)/ide.c \ + $(EMU)/idecontrollers.c \ + $(EMU)/identify.c \ + $(EMU)/ini.c \ + $(EMU)/inputdevice.c \ + $(EMU)/isofs.c \ + $(EMU)/keybuf.c \ + $(EMU)/main.c \ + $(EMU)/memory.c \ + $(EMU)/misc.c \ + $(EMU)/missing.c \ + $(EMU)/native2amiga.c \ + $(EMU)/ncr_scsi.c \ + $(EMU)/ncr9x_scsi.c \ + $(EMU)/newcpu.c \ + $(EMU)/newcpu_common.c \ + $(EMU)/pci.c \ + $(EMU)/picasso96.c \ + $(EMU)/readcpu.c \ + $(EMU)/rommgr.c \ + $(EMU)/rtc.c \ + $(EMU)/sampler.c \ + $(EMU)/sana2.c \ + $(EMU)/savestate.c \ + $(EMU)/scsi.c \ + $(EMU)/scsiemul.c \ + $(EMU)/scsitape.c \ + $(EMU)/sndboard.c \ + $(EMU)/specialmonitors.c \ + $(EMU)/statusline.c \ + $(EMU)/test_card.c\ + $(EMU)/traps.c\ + $(EMU)/uaelib.c \ + $(EMU)/uaenet.c \ + $(EMU)/uaeresource.c \ + $(EMU)/uaeserial.c \ + $(EMU)/writelog.c \ + $(EMU)/x86.c \ + $(EMU)/zfile.c \ + $(EMU)/zfile_archive.c \ + $(EMU)/softfloat/softfloat.c \ + $(EMU)/softfloat/softfloat_decimal.c \ + $(EMU)/softfloat/softfloat_fpsp.c + +SOURCES_C += \ + $(RETRODEP)/gui.c \ + $(RETRODEP)/main.c \ + $(RETRODEP)/mman.c \ + $(RETRODEP)/parser.c \ + $(RETRODEP)/serial_host.c \ + $(RETRODEP)/machdep/support.c \ + $(RETRODEP)/sounddep/sound.c \ + $(RETRODEP)/stubs/inputrecord.c \ + $(RETRODEP)/threaddep/thread.c + +SOURCES_C += \ + $(EMU)/archivers/dms/crc_csum.c \ + $(EMU)/archivers/dms/getbits.c \ + $(EMU)/archivers/dms/maketbl.c \ + $(EMU)/archivers/dms/pfile.c \ + $(EMU)/archivers/dms/tables.c \ + $(EMU)/archivers/dms/u_deep.c \ + $(EMU)/archivers/dms/u_heavy.c \ + $(EMU)/archivers/dms/u_init.c \ + $(EMU)/archivers/dms/u_medium.c \ + $(EMU)/archivers/dms/u_quick.c \ + $(EMU)/archivers/dms/u_rle.c \ + $(EMU)/archivers/lha/crcio.c \ + $(EMU)/archivers/lha/dhuf.c \ + $(EMU)/archivers/lha/header.c \ + $(EMU)/archivers/lha/huf.c \ + $(EMU)/archivers/lha/larc.c \ + $(EMU)/archivers/lha/lhamaketbl.c \ + $(EMU)/archivers/lha/lharc.c \ + $(EMU)/archivers/lha/shuf.c \ + $(EMU)/archivers/lha/slide.c \ + $(EMU)/archivers/lha/uae_lha.c \ + $(EMU)/archivers/lha/util.c \ + $(EMU)/archivers/mp2/kjmp2.c + +SOURCES_C += \ + $(DEPS_DIR)/libmpeg2/src/convert/rgb.c \ + $(DEPS_DIR)/libmpeg2/src/cpu_accel.c \ + $(DEPS_DIR)/libmpeg2/src/cpu_state.c \ + $(DEPS_DIR)/libmpeg2/src/alloc.c \ + $(DEPS_DIR)/libmpeg2/src/decode.c \ + $(DEPS_DIR)/libmpeg2/src/header.c \ + $(DEPS_DIR)/libmpeg2/src/idct.c \ + $(DEPS_DIR)/libmpeg2/src/motion_comp.c \ + $(DEPS_DIR)/libmpeg2/src/slice.c + +SOURCES_C += \ + $(DEPS_DIR)/libz/adler32.c \ + $(DEPS_DIR)/libz/crc32.c \ + $(DEPS_DIR)/libz/deflate.c \ + $(DEPS_DIR)/libz/gzclose.c \ + $(DEPS_DIR)/libz/gzlib.c \ + $(DEPS_DIR)/libz/gzread.c \ + $(DEPS_DIR)/libz/gzwrite.c \ + $(DEPS_DIR)/libz/inffast.c \ + $(DEPS_DIR)/libz/inflate.c \ + $(DEPS_DIR)/libz/inftrees.c \ + $(DEPS_DIR)/libz/trees.c \ + $(DEPS_DIR)/libz/zutil.c + +SOURCES_C += \ + $(DEPS_DIR)/7zip/7zArcIn.c \ + $(DEPS_DIR)/7zip/7zBuf.c \ + $(DEPS_DIR)/7zip/7zCrc.c \ + $(DEPS_DIR)/7zip/7zCrcOpt.c \ + $(DEPS_DIR)/7zip/7zDec.c \ + $(DEPS_DIR)/7zip/7zFile.c \ + $(DEPS_DIR)/7zip/7zStream.c \ + $(DEPS_DIR)/7zip/Bcj2.c \ + $(DEPS_DIR)/7zip/Bra.c \ + $(DEPS_DIR)/7zip/Bra86.c \ + $(DEPS_DIR)/7zip/BraIA64.c \ + $(DEPS_DIR)/7zip/CpuArch.c \ + $(DEPS_DIR)/7zip/Delta.c \ + $(DEPS_DIR)/7zip/Lzma2Dec.c \ + $(DEPS_DIR)/7zip/LzmaDec.c + +SOURCES_C += \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ + $(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ + $(LIBRETRO_COMM_DIR)/file/file_path.c \ + $(LIBRETRO_COMM_DIR)/file/file_path_io.c \ + $(LIBRETRO_COMM_DIR)/file/retro_dirent.c \ + $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ + $(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \ + $(LIBRETRO_COMM_DIR)/string/stdstring.c \ + $(LIBRETRO_COMM_DIR)/time/rtime.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c + +SRCS = $(SOURCES_C) + +include ../common.mak \ No newline at end of file diff --git a/waterbox/uae/bizhawk.c b/waterbox/uae/bizhawk.c new file mode 100644 index 00000000000..5045ba99fe8 --- /dev/null +++ b/waterbox/uae/bizhawk.c @@ -0,0 +1,91 @@ +#include "bizhawk.h" + +ECL_EXPORT bool Init(int argc, char **argv) +{ + last_mouse_x = 0; + last_mouse_y = 0; + libretro_runloop_active = 0; + pix_bytes = 4; + defaultw = PUAE_VIDEO_WIDTH; + defaulth = PUAE_VIDEO_HEIGHT_PAL; + retrow = PUAE_VIDEO_WIDTH; + retrow_crop = retrow; + retroh_crop = retroh; + log_cb = biz_log_cb; + + retro_set_audio_sample_batch(biz_audio_cb); + init_output_audio_buffer(2048); + umain(argc, argv); + m68k_go(1, 0); + + libretro_runloop_active = 1; + + return true; +} + +ECL_EXPORT void FrameAdvance(MyFrameInfo* f) +{ + f->base.Width = 720; + f->base.Height = 576; + sound_buffer = f->base.SoundBuffer; + thisframe_y_adjust = minfirstline; + visible_left_border = retro_max_diwlastword - retrow; + + setjoystickstate(PORT_0, AXIS_VERTICAL, + f->JoystickState.up ? JOY_MIN : + f->JoystickState.down ? JOY_MAX : JOY_MID, 1); + setjoystickstate(PORT_0, AXIS_HORIZONTAL, + f->JoystickState.left ? JOY_MIN : + f->JoystickState.right ? JOY_MAX : JOY_MID, 1); + setjoybuttonstate(PORT_0, 0, f->JoystickState.b1); + setjoybuttonstate(PORT_0, 1, f->JoystickState.b2); + setjoybuttonstate(PORT_0, 2, f->JoystickState.b3); + + setmousebuttonstate(PORT_0, MOUSE_LEFT, f->MouseButtons & 1); + setmousebuttonstate(PORT_0, MOUSE_RIGHT, f->MouseButtons & 2); + setmousebuttonstate(PORT_0, MOUSE_MIDDLE, f->MouseButtons & 4); + setmousestate( PORT_0, AXIS_HORIZONTAL, f->MouseX - last_mouse_x, MOUSE_RELATIVE); + setmousestate( PORT_0, AXIS_VERTICAL, f->MouseY - last_mouse_y, MOUSE_RELATIVE); + + for (int i = 0; i < KEY_COUNT; i++) + { + if (f->Keys[i] != last_key_state[i]) + { + inputdevice_do_keyboard(i, f->Keys[i]); + } + } + memcpy(last_key_state, f->Keys, KEY_COUNT); + + m68k_go(1, 1); + upload_output_audio_buffer(); + f->base.Samples = sound_sample_count; + memcpy(f->base.VideoBuffer, retro_bmp, sizeof(retro_bmp) / sizeof(retro_bmp[0])); + last_mouse_x = f->MouseX; + last_mouse_y = f->MouseY; + sound_buffer = NULL; +} + +ECL_EXPORT void GetMemoryAreas(MemoryArea *m) +{ + m[0].Data = chipmem_bank.baseaddr; + m[0].Name = "Chip RAM"; + m[0].Size = chipmem_bank.allocated_size; + m[0].Flags = MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_PRIMARY; + + m[1].Data = bogomem_bank.baseaddr; + m[1].Name = "Slow RAM"; + m[1].Size = bogomem_bank.allocated_size; + m[1].Flags = MEMORYAREA_FLAGS_WORDSIZE1; + + m[2].Data = fastmem_bank[0].baseaddr; + m[2].Name = "Fast RAM"; + m[2].Size = fastmem_bank[0].allocated_size; + m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE1; +} + +void (*InputCallback)(); + +ECL_EXPORT void SetInputCallback(void (*callback)()) +{ + InputCallback = callback; +} diff --git a/waterbox/uae/bizhawk.h b/waterbox/uae/bizhawk.h new file mode 100644 index 00000000000..f4e4391981e --- /dev/null +++ b/waterbox/uae/bizhawk.h @@ -0,0 +1,133 @@ +#pragma once + +// system +#include +#include +#include +#include + +// waterbox +#include "emulibc.h" +#include "waterboxcore.h" + +// core +#include "include/sysdeps.h" +#include "include/options.h" +#include "include/uae.h" +#include "include/memory.h" +#include "include/custom.h" +#include "include/drawing.h" +#include "include/inputdevice.h" + +#include "libretro/libretro-core.h" + +static const int KEY_COUNT = 0x68; + +int16_t* sound_buffer = NULL; +int sound_sample_count = 0; +static char last_key_state[KEY_COUNT]; +static int last_mouse_x; +static int last_mouse_y; + +extern int thisframe_y_adjust; +extern unsigned short int defaultw; +extern unsigned short int defaulth; +extern int retro_max_diwlastword; + +extern int umain(int argc, char **argv); +extern int m68k_go(int may_quit, int resume); +extern void init_output_audio_buffer(int32_t capacity); +extern void upload_output_audio_buffer(); + +enum Axis +{ + AXIS_HORIZONTAL, + AXIS_VERTICAL +}; + +enum JoystickRange +{ + JOY_MIN = -1, + JOY_MID, + JOY_MAX +}; + +enum ControllerPort +{ + PORT_0, + PORT_1 +}; + +enum MouseButtons +{ + MOUSE_LEFT, + MOUSE_RIGHT, + MOUSE_MIDDLE +}; + +enum MousePosition +{ + MOUSE_RELATIVE, + MOUSE_ABSOLUTE +}; + +enum AudioChannels +{ + AUDIO_MONO = 1, + AUDIO_STEREO +}; + +typedef union +{ + struct + { + bool up:1; + bool down:1; + bool left:1; + bool right:1; + bool b1:1; + bool b2:1; + bool b3:1; + }; + uint8_t data; +} PUAEJoystick; + +typedef struct +{ + FrameInfo base; + PUAEJoystick JoystickState; + uint8_t MouseButtons; + int MouseX; + int MouseY; + char Keys[KEY_COUNT]; +} MyFrameInfo; + +size_t biz_audio_cb(const int16_t *data, size_t frames) +{ + sound_sample_count = frames; + memcpy(sound_buffer, data, frames * sizeof(int16_t) * AUDIO_STEREO); +} + +void biz_log_cb(enum retro_log_level level, const char *fmt, ...) +{ + fprintf(stderr, "[PUAE "); + switch (level) + { + case RETRO_LOG_DEBUG: + fprintf(stderr, "DEBUG]: "); + break; + case RETRO_LOG_INFO: + fprintf(stderr, "INFO]: "); + break; + case RETRO_LOG_WARN: + fprintf(stderr, "WARN]: "); + break; + case RETRO_LOG_ERROR: + fprintf(stderr, "ERROR]: "); + break; + } + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); +} \ No newline at end of file diff --git a/waterbox/uae/libretro-uae b/waterbox/uae/libretro-uae new file mode 160000 index 00000000000..5de7a00350b --- /dev/null +++ b/waterbox/uae/libretro-uae @@ -0,0 +1 @@ +Subproject commit 5de7a00350b21f79805881cf36af8234aa7c3fd6