示例#1
0
        private void MakeTrace(ushort pc)
        {
            int[] s = new int[10];
            LibSameboy.sameboy_getregs(SameboyState, s);

            Tracer.Put(new(
                           disassembly: LR35902.Disassemble(
                               pc,
                               addr => LibSameboy.sameboy_cpuread(SameboyState, addr),
                               _settings.UseRGBDSSyntax,
                               out _).PadRight(36),
                           registerInfo: string.Format(
                               "A:{0:x2} F:{1:x2} B:{2:x2} C:{3:x2} D:{4:x2} E:{5:x2} H:{6:x2} L:{7:x2} SP:{8:x4} LY:{9:x2} Cy:{10}",
                               s[1] & 0xFF,
                               s[2] & 0xFF,
                               s[3] & 0xFF,
                               s[4] & 0xFF,
                               s[5] & 0xFF,
                               s[6] & 0xFF,
                               s[7] & 0xFF,
                               s[8] & 0xFF,
                               s[9] & 0xFFFF,
                               LibSameboy.sameboy_cpuread(SameboyState, 0xFF44),
                               CycleCount
                               )));
        }
示例#2
0
        public void LoadStateBinary(BinaryReader reader)
        {
            int length = reader.ReadInt32();

            if (length != _stateBuf.Length)
            {
                throw new InvalidOperationException("Savestate buffer size mismatch!");
            }

            reader.Read(_stateBuf, 0, _stateBuf.Length);

            if (LibSameboy.sameboy_loadstate(SameboyState, _stateBuf, _stateBuf.Length))
            {
                throw new Exception($"{nameof(LibSameboy.sameboy_loadstate)}() returned true");
            }

            // other variables
            IsLagFrame = reader.ReadBoolean();
            LagCount   = reader.ReadInt32();
            Frame      = reader.ReadInt32();
            IsCgb      = reader.ReadBoolean();
            CycleCount = reader.ReadInt64();
            theta      = reader.ReadDouble();
            phi        = reader.ReadDouble();
            theta_prev = reader.ReadDouble();
            phi_prev   = reader.ReadDouble();
            phi_prev_2 = reader.ReadDouble();
        }
示例#3
0
        static Sameboy()
        {
            var resolver = new DynamicLibraryImportResolver(
                OSTailoredCode.IsUnixHost ? "libsameboy.so" : "libsameboy.dll", hasLimitedLifetime: false);

            LibSameboy = BizInvoker.GetInvoker <LibSameboy>(resolver, CallingConventionAdapters.Native);
        }
示例#4
0
 public void Dispose()
 {
     if (SameboyState != IntPtr.Zero)
     {
         LibSameboy.sameboy_destroy(SameboyState);
         SameboyState = IntPtr.Zero;
     }
 }
示例#5
0
        public void StoreSaveRam(byte[] data)
        {
            int expected = LibSameboy.sameboy_sramlen(SameboyState);

            if (data.Length - expected != 0)
            {
                throw new ArgumentException("Size of saveram data does not match expected!");
            }

            LibSameboy.sameboy_loadsram(SameboyState, data, data.Length);
        }
示例#6
0
        public byte[] CloneSaveRam()
        {
            int length = LibSameboy.sameboy_sramlen(SameboyState);

            if (length > 0)
            {
                byte[] ret = new byte[length];
                LibSameboy.sameboy_savesram(SameboyState, ret);
                return(ret);
            }

            return(null);
        }
 public PutSettingsDirtyBits PutSettings(SameboySettings o)
 {
     LibSameboy.sameboy_setpalette(SameboyState, o.GBPalette, o.GetCustomPalette());
     LibSameboy.sameboy_setcolorcorrection(SameboyState, o.ColorCorrection);
     LibSameboy.sameboy_setlighttemperature(SameboyState, o.LightTemperature);
     LibSameboy.sameboy_sethighpassfilter(SameboyState, o.HighPassFilter);
     LibSameboy.sameboy_setinterferencevolume(SameboyState, o.InterferenceVolume);
     LibSameboy.sameboy_setbgwinenabled(SameboyState, o.EnableBGWIN);
     LibSameboy.sameboy_setobjenabled(SameboyState, o.EnableOBJ);
     _disassembler.UseRGBDSSyntax = o.UseRGBDSSyntax;
     _settings = o;
     return(PutSettingsDirtyBits.None);
 }
示例#8
0
        private void FrameAdvancePost()
        {
            if (IsLagFrame)
            {
                LagCount++;
            }

            Frame++;

            if (_scanlinecbline == -1)
            {
                _scanlinecb?.Invoke(LibSameboy.sameboy_cpuread(SameboyState, 0xFF40));
            }
        }
示例#9
0
        public bool FrameAdvance(IController controller, bool render, bool rendersound)
        {
            var buttons = FrameAdvancePrep(controller);

            LibSameboy.sameboy_frameadvance(SameboyState, buttons, GetAccX(controller), GetAccY(), VideoBuffer, render, _settings.ShowBorder);

            if (!rendersound)
            {
                DiscardSamples();
            }

            FrameAdvancePost();

            return(true);
        }
示例#10
0
        private void CreateMemoryDomain(LibSameboy.MemoryAreas which, string name)
        {
            IntPtr data   = IntPtr.Zero;
            int    length = 0;

            if (!LibSameboy.sameboy_getmemoryarea(SameboyState, which, ref data, ref length))
            {
                throw new Exception($"{nameof(LibSameboy.sameboy_getmemoryarea)}() failed!");
            }

            // if length == 0, it's an empty block; (usually rambank on some carts); that's ok
            if (data != IntPtr.Zero && length > 0)
            {
                _memoryDomains.Add(new MemoryDomainIntPtr(name, MemoryDomain.Endian.Little, data, length, true, 1));
            }
        }
示例#11
0
 public void SetCpuRegister(string register, int value)
 {
     LibSameboy.sameboy_setreg(SameboyState, register.ToUpper() switch
     {
         "PC" => 0,
         "A" => 1,
         "F" => 2,
         "B" => 3,
         "C" => 4,
         "D" => 5,
         "E" => 6,
         "H" => 7,
         "L" => 8,
         "SP" => 9,
         _ => throw new InvalidOperationException("Invalid Register?"),
     },
示例#12
0
        public IDictionary <string, RegisterValue> GetCpuFlagsAndRegisters()
        {
            int[] data = new int[10];
            LibSameboy.sameboy_getregs(SameboyState, data);

            return(new Dictionary <string, RegisterValue>
            {
                ["PC"] = (ushort)(data[0] & 0xFFFF),
                ["A"] = (byte)(data[1] & 0xFF),
                ["F"] = (byte)(data[2] & 0xFF),
                ["B"] = (byte)(data[3] & 0xFF),
                ["C"] = (byte)(data[4] & 0xFF),
                ["D"] = (byte)(data[5] & 0xFF),
                ["E"] = (byte)(data[6] & 0xFF),
                ["H"] = (byte)(data[7] & 0xFF),
                ["L"] = (byte)(data[8] & 0xFF),
                ["SP"] = (ushort)(data[9] & 0xFFFF),
            });
        }
示例#13
0
        public void SaveStateBinary(BinaryWriter writer)
        {
            LibSameboy.sameboy_savestate(SameboyState, _stateBuf);

            writer.Write(_stateBuf.Length);
            writer.Write(_stateBuf);

            // other variables
            writer.Write(IsLagFrame);
            writer.Write(LagCount);
            writer.Write(Frame);
            writer.Write(IsCgb);
            writer.Write(CycleCount);
            writer.Write(theta);
            writer.Write(phi);
            writer.Write(theta_prev);
            writer.Write(phi_prev);
            writer.Write(phi_prev_2);
        }
示例#14
0
        private void InitMemoryDomains()
        {
            CreateMemoryDomain(LibSameboy.MemoryAreas.ROM, "ROM");
            CreateMemoryDomain(LibSameboy.MemoryAreas.RAM, "WRAM");
            CreateMemoryDomain(LibSameboy.MemoryAreas.CART_RAM, "CartRAM");
            CreateMemoryDomain(LibSameboy.MemoryAreas.VRAM, "VRAM");
            CreateMemoryDomain(LibSameboy.MemoryAreas.HRAM, "HRAM");
            CreateMemoryDomain(LibSameboy.MemoryAreas.IO, "MMIO");
            CreateMemoryDomain(LibSameboy.MemoryAreas.BOOTROM, "BIOS");
            CreateMemoryDomain(LibSameboy.MemoryAreas.OAM, "OAM");
            CreateMemoryDomain(LibSameboy.MemoryAreas.BGP, "BGP");
            CreateMemoryDomain(LibSameboy.MemoryAreas.OBP, "OBP");
            CreateMemoryDomain(LibSameboy.MemoryAreas.IE, "IE");

            // also add a special memory domain for the system bus, where calls get sent directly to the core each time
            _memoryDomains.Add(new MemoryDomainDelegate("System Bus", 65536, MemoryDomain.Endian.Little,
                                                        delegate(long addr)
            {
                if (addr < 0 || addr >= 65536)
                {
                    throw new ArgumentOutOfRangeException();
                }

                return(LibSameboy.sameboy_cpuread(SameboyState, (ushort)addr));
            },
                                                        delegate(long addr, byte val)
            {
                if (addr < 0 || addr >= 65536)
                {
                    throw new ArgumentOutOfRangeException();
                }

                LibSameboy.sameboy_cpuwrite(SameboyState, (ushort)addr, val);
            }, 1));

            MemoryDomains = new MemoryDomainList(_memoryDomains);
            _serviceProvider.Register(MemoryDomains);
        }
示例#15
0
        private LibSameboy.Buttons FrameAdvancePrep(IController controller)
        {
            uint b = 0;

            for (var i = 0; i < 8; i++)
            {
                b <<= 1;
                if (controller.IsPressed(GB_BUTTON_ORDER_IN_BITMASK[i]))
                {
                    b |= 1;
                }
            }

            if (controller.IsPressed("Power"))
            {
                LibSameboy.sameboy_reset(SameboyState);
            }

            IsLagFrame = true;

            LibSameboy.sameboy_settracecallback(SameboyState, Tracer.IsEnabled() ? _tracecb : null);

            return((LibSameboy.Buttons)b);
        }
示例#16
0
 public void DebugSameBoyState()
 {
     LibSameboy.sameboy_savestate(SameboyState, _stateBuf);
     Directory.CreateDirectory("sameboy_debug");
     File.WriteAllBytes($"sameboy_debug/debug_state{Frame}.bin", _stateBuf);
 }
示例#17
0
 public bool IsCGBDMGMode() => LibSameboy.sameboy_iscgbdmg(SameboyState);
示例#18
0
        public Sameboy(CoreComm comm, GameInfo game, byte[] file, SameboySettings settings, SameboySyncSettings syncSettings, bool deterministic)
        {
            _serviceProvider = new BasicServiceProvider(this);

            _settings     = settings ?? new SameboySettings();
            _syncSettings = syncSettings ?? new SameboySyncSettings();

            var model = _syncSettings.ConsoleMode;

            if (model is SameboySyncSettings.GBModel.Auto)
            {
                model = game.System == VSystemID.Raw.GBC
                                        ? SameboySyncSettings.GBModel.GB_MODEL_CGB_E
                                        : SameboySyncSettings.GBModel.GB_MODEL_DMG_B;
            }

            IsCgb = model >= SameboySyncSettings.GBModel.GB_MODEL_CGB_0;

            byte[] bios;
            if (_syncSettings.EnableBIOS)
            {
                FirmwareID fwid = new(
                    IsCgb ? "GBC" : "GB",
                    _syncSettings.ConsoleMode is SameboySyncSettings.GBModel.GB_MODEL_AGB
                                        ? "AGB"
                                        : "World");
                bios = comm.CoreFileProvider.GetFirmwareOrThrow(fwid, "BIOS Not Found, Cannot Load.  Change SyncSettings to run without BIOS.");
            }
            else
            {
                bios = Util.DecompressGzipFile(new MemoryStream(IsCgb
                                        ? _syncSettings.ConsoleMode is SameboySyncSettings.GBModel.GB_MODEL_AGB ? Resources.SameboyAgbBoot.Value : Resources.SameboyCgbBoot.Value
                                        : Resources.SameboyDmgBoot.Value));
            }

            DeterministicEmulation = false;

            bool realtime = true;

            if (!_syncSettings.UseRealTime || deterministic)
            {
                realtime = false;
                DeterministicEmulation = true;
            }

            SameboyState = LibSameboy.sameboy_create(file, file.Length, bios, bios.Length, model, realtime);

            InitMemoryDomains();
            InitMemoryCallbacks();

            _samplecb = QueueSample;
            LibSameboy.sameboy_setsamplecallback(SameboyState, _samplecb);
            _inputcb = InputCallback;
            LibSameboy.sameboy_setinputcallback(SameboyState, _inputcb);
            _tracecb = MakeTrace;
            LibSameboy.sameboy_settracecallback(SameboyState, null);

            LibSameboy.sameboy_setscanlinecallback(SameboyState, null, 0);
            LibSameboy.sameboy_setprintercallback(SameboyState, null);

            const string TRACE_HEADER = "SM83: PC, opcode, registers (A, F, B, C, D, E, H, L, SP, LY, CY)";

            Tracer = new TraceBuffer(TRACE_HEADER);
            _serviceProvider.Register(Tracer);

            _disassembler = new Gameboy.GBDisassembler();
            _serviceProvider.Register <IDisassemblable>(_disassembler);

            PutSettings(_settings);

            _stateBuf = new byte[LibSameboy.sameboy_statelen(SameboyState)];

            RomDetails = $"{game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(file)}\r\n{MD5Checksum.ComputePrefixedHex(file)}\r\n";
            BoardName  = MapperName(file);

            _hasAcc = BoardName is "MBC7 ROM+ACCEL+EEPROM";
            ControllerDefinition = Gameboy.Gameboy.CreateControllerDefinition(sgb: false, sub: false, tilt: _hasAcc);

            LibSameboy.sameboy_setrtcdivisoroffset(SameboyState, _syncSettings.RTCDivisorOffset);
            CycleCount = 0;
        }