Exemplo n.º 1
0
        public NES(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings)
        {
            var ser = new BasicServiceProvider(this);

            ServiceProvider = ser;

            byte[] fdsbios = comm.CoreFileProvider.GetFirmware("NES", "Bios_FDS", false);
            if (fdsbios != null && fdsbios.Length == 40976)
            {
                comm.ShowMessage("Your FDS BIOS is a bad dump.  BizHawk will attempt to use it, but no guarantees!  You should find a new one.");
                var tmp = new byte[8192];
                Buffer.BlockCopy(fdsbios, 16 + 8192 * 3, tmp, 0, 8192);
                fdsbios = tmp;
            }

            this.SyncSettings       = (NESSyncSettings)SyncSettings ?? new NESSyncSettings();
            this.ControllerSettings = this.SyncSettings.Controls;
            CoreComm = comm;

            MemoryCallbacks = new MemoryCallbackSystem();
            BootGodDB.Initialize();
            videoProvider = new MyVideoProvider(this);
            Init(game, rom, fdsbios);
            if (Board is FDS)
            {
                DriveLightEnabled = true;
                (Board as FDS).SetDriveLightCallback((val) => DriveLightOn = val);
                // bit of a hack: we don't have a private gamedb for FDS, but the frontend
                // expects this to be set.
                RomStatus = game.Status;
            }
            PutSettings((NESSettings)Settings ?? new NESSettings());


            ser.Register <IDisassemblable>(cpu);

            Tracer = new TraceBuffer {
                Header = cpu.TraceHeader
            };
            ser.Register <ITraceable>(Tracer);
            ser.Register <IVideoProvider>(videoProvider);

            if (Board is BANDAI_FCG_1)
            {
                var reader = (Board as BANDAI_FCG_1).reader;
                // not all BANDAI FCG 1 boards have a barcode reader
                if (reader != null)
                {
                    ser.Register <DatachBarcode>(reader);
                }
            }
        }
Exemplo n.º 2
0
        private void SyncState(Serializer ser)
        {
            byte[] core = null;
            if (ser.IsWriter)
            {
                var ms = new MemoryStream();
                ms.Close();
                core = ms.ToArray();
            }

            if (ser.IsWriter)
            {
                ser.SyncEnum("_machineType", ref _machineType);

                _cpu.SyncState(ser);
                ser.BeginSection("AmstradCPC");
                _machine.SyncState(ser);
                ser.Sync("Frame", ref _machine.FrameCount);
                ser.Sync("LagCount", ref _lagCount);
                ser.Sync("IsLag", ref _isLag);
                ser.EndSection();
            }

            if (ser.IsReader)
            {
                var tmpM = _machineType;
                ser.SyncEnum("_machineType", ref _machineType);
                if (tmpM != _machineType && _machineType.ToString() != "72")
                {
                    string msg = "SAVESTATE FAILED TO LOAD!!\n\n";
                    msg += "Current Configuration: " + tmpM.ToString();
                    msg += "\n";
                    msg += "Saved Configuration:    " + _machineType.ToString();
                    msg += "\n\n";
                    msg += "If you wish to load this SaveState ensure that you have the correct machine configuration selected, reboot the core, then try again.";
                    CoreComm.ShowMessage(msg);
                    _machineType = tmpM;
                }
                else
                {
                    _cpu.SyncState(ser);
                    ser.BeginSection("AmstradCPC");
                    _machine.SyncState(ser);
                    ser.Sync("Frame", ref _machine.FrameCount);
                    ser.Sync("LagCount", ref _lagCount);
                    ser.Sync("IsLag", ref _isLag);
                    ser.EndSection();

                    SyncAllByteArrayDomains();
                }
            }
        }
Exemplo n.º 3
0
        public NES(CoreComm comm, GameInfo game, byte[] rom, NESSettings settings, NESSyncSettings syncSettings, bool subframe = false)
        {
            var ser = new BasicServiceProvider(this);

            ServiceProvider = ser;

            var fdsBios = comm.CoreFileProvider.GetFirmware(new("NES", "Bios_FDS"));

            if (fdsBios != null && fdsBios.Length == 40976)
            {
                comm.ShowMessage("Your FDS BIOS is a bad dump.  BizHawk will attempt to use it, but no guarantees!  You should find a new one.");
                var tmp = new byte[8192];
                Buffer.BlockCopy(fdsBios, 16 + 8192 * 3, tmp, 0, 8192);
                fdsBios = tmp;
            }

            SyncSettings       = (NESSyncSettings)syncSettings ?? new NESSyncSettings();
            ControllerSettings = SyncSettings.Controls;

            videoProvider = new MyVideoProvider(this);
            Init(game, rom, fdsBios);
            if (Board is FDS fds)
            {
                DriveLightEnabled = true;
                fds.SetDriveLightCallback(val => DriveLightOn = val);
                // bit of a hack: we don't have a private gamedb for FDS, but the frontend
                // expects this to be set.
                RomStatus = game.Status;
            }
            PutSettings((NESSettings)settings ?? new NESSettings());

            // we need to put this here because the line directly above will overwrite palette intialization anywhere else
            // TODO: What if settings are later loaded?
            if (_isVS)
            {
                PickVSPalette(cart);
            }

            ser.Register <IDisassemblable>(cpu);

            Tracer = new TraceBuffer(cpu.TraceHeader);
            ser.Register <ITraceable>(Tracer);
            ser.Register <IVideoProvider>(videoProvider);
            ser.Register <ISoundProvider>(this);
            ser.Register <IStatable>(new StateSerializer(SyncState)
            {
                LoadStateCallback = SetupMemoryDomains
            });

            if (Board is BANDAI_FCG_1 bandai)
            {
                var reader = bandai.reader;
                // not all BANDAI FCG 1 boards have a barcode reader
                if (reader != null)
                {
                    ser.Register(reader);
                }
            }

            ResetControllerDefinition(subframe);
        }
Exemplo n.º 4
0
        private string snes_path_request(int slot, string hint)
        {
            // every rom requests msu1.rom... why? who knows.
            // also handle msu-1 pcm files here
            bool isMsu1Rom = hint == "msu1.rom";
            bool isMsu1Pcm = Path.GetExtension(hint).ToLower() == ".pcm";

            if (isMsu1Rom || isMsu1Pcm)
            {
                // well, check if we have an msu-1 xml
                if (_romxml?["cartridge"]?["msu1"] != null)
                {
                    var msu1 = _romxml["cartridge"]["msu1"];
                    if (isMsu1Rom && msu1["rom"]?.Attributes["name"] != null)
                    {
                        return(CoreComm.CoreFileProvider.PathSubfile(msu1["rom"].Attributes["name"].Value));
                    }

                    if (isMsu1Pcm)
                    {
                        // return @"D:\roms\snes\SuperRoadBlaster\SuperRoadBlaster-1.pcm";
                        // return "";
                        int wantsTrackNumber = int.Parse(hint.Replace("track-", "").Replace(".pcm", ""));
                        wantsTrackNumber++;
                        string wantsTrackString = wantsTrackNumber.ToString();
                        foreach (var child in msu1.ChildNodes.Cast <XmlNode>())
                        {
                            if (child.Name == "track" && child.Attributes["number"].Value == wantsTrackString)
                            {
                                return(CoreComm.CoreFileProvider.PathSubfile(child.Attributes["name"].Value));
                            }
                        }
                    }
                }

                // not found.. what to do? (every rom will get here when msu1.rom is requested)
                return("");
            }

            // not MSU-1.  ok.
            string firmwareId;

            switch (hint)
            {
            case "cx4.rom": firmwareId = "CX4"; break;

            case "dsp1.rom": firmwareId = "DSP1"; break;

            case "dsp1b.rom": firmwareId = "DSP1b"; break;

            case "dsp2.rom": firmwareId = "DSP2"; break;

            case "dsp3.rom": firmwareId = "DSP3"; break;

            case "dsp4.rom": firmwareId = "DSP4"; break;

            case "st010.rom": firmwareId = "ST010"; break;

            case "st011.rom": firmwareId = "ST011"; break;

            case "st018.rom": firmwareId = "ST018"; break;

            default:
                CoreComm.ShowMessage($"Unrecognized SNES firmware request \"{hint}\".");
                return("");
            }

            string ret;
            var    data = CoreComm.CoreFileProvider.GetFirmware("SNES", firmwareId, false, "Game may function incorrectly without the requested firmware.");

            if (data != null)
            {
                ret = hint;
                Api.AddReadonlyFile(data, hint);
            }
            else
            {
                ret = "";
            }

            Console.WriteLine("Served libsnes request for firmware \"{0}\"", hint);

            // return the path we built
            return(ret);
        }
Exemplo n.º 5
0
        public Gameboy(CoreComm comm, GameInfo game, byte[] file, GambatteSettings settings, GambatteSyncSettings syncSettings, bool deterministic)
        {
            var ser = new BasicServiceProvider(this);

            ser.Register <IDisassemblable>(_disassembler);
            ServiceProvider = ser;
            const string TRACE_HEADER = "LR35902: PC, opcode, registers (A, F, B, C, D, E, H, L, LY, SP, CY)";

            Tracer = new TraceBuffer(TRACE_HEADER);
            ser.Register <ITraceable>(Tracer);
            InitMemoryCallbacks();

            ThrowExceptionForBadRom(file);
            BoardName = MapperName(file);

            DeterministicEmulation = deterministic;

            GambatteState = LibGambatte.gambatte_create();

            if (GambatteState == IntPtr.Zero)
            {
                throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_create)}() returned null???");
            }

            Console.WriteLine(game.System);

            try
            {
                _syncSettings = syncSettings ?? new GambatteSyncSettings();

                LibGambatte.LoadFlags flags = LibGambatte.LoadFlags.READONLY_SAV;

                switch (_syncSettings.ConsoleMode)
                {
                case GambatteSyncSettings.ConsoleModeType.GB:
                    break;

                case GambatteSyncSettings.ConsoleModeType.GBC:
                    flags |= LibGambatte.LoadFlags.CGB_MODE;
                    break;

                case GambatteSyncSettings.ConsoleModeType.GBA:
                    flags |= LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG;
                    break;

                default:
                    if (game.System == VSystemID.Raw.GBC)
                    {
                        flags |= LibGambatte.LoadFlags.CGB_MODE;
                    }
                    break;
                }

                if (game.System == VSystemID.Raw.SGB)
                {
                    flags &= ~(LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG);
                    flags |= LibGambatte.LoadFlags.SGB_MODE;
                    IsSgb  = true;
                }

                if (_syncSettings.MulticartCompat)
                {
                    flags |= LibGambatte.LoadFlags.MULTICART_COMPAT;
                }

                IsCgb = (flags & LibGambatte.LoadFlags.CGB_MODE) == LibGambatte.LoadFlags.CGB_MODE;
                if (_syncSettings.EnableBIOS)
                {
                    FirmwareID fwid = new(
                        IsCgb ? "GBC" : "GB",
                        IsSgb
                                                        ? "SGB2"
                                                        : _syncSettings.ConsoleMode is GambatteSyncSettings.ConsoleModeType.GBA
                                                                ? "AGB"
                                                                : "World");
                    var bios = comm.CoreFileProvider.GetFirmwareOrThrow(fwid, "BIOS Not Found, Cannot Load.  Change SyncSettings to run without BIOS.");                     // https://github.com/TASEmulators/BizHawk/issues/2832 tho
                    if (LibGambatte.gambatte_loadbiosbuf(GambatteState, bios, (uint)bios.Length) != 0)
                    {
                        throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbiosbuf)}() returned non-zero (bios error)");
                    }
                }
                else
                {
                    if (DeterministicEmulation)                     // throw a warning if a movie is being recorded with the bios disabled
                    {
                        comm.ShowMessage("Detected disabled BIOS during movie recording. It is recommended to use a BIOS for movie recording. Change Sync Settings to run with a BIOS.");
                    }
                    flags |= LibGambatte.LoadFlags.NO_BIOS;
                }

                if (LibGambatte.gambatte_loadbuf(GambatteState, file, (uint)file.Length, flags) != 0)
                {
                    throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbuf)}() returned non-zero (is this not a gb or gbc rom?)");
                }

                if (IsSgb)
                {
                    ResetStallTicks = 128 * (2 << 14);
                }
                else if (_syncSettings.EnableBIOS && (_syncSettings.ConsoleMode is GambatteSyncSettings.ConsoleModeType.GBA))
                {
                    ResetStallTicks = 485808;                     // GBA takes 971616 cycles to switch to CGB mode; CGB CPU is inactive during this time.
                }
                else
                {
                    ResetStallTicks = 0;
                }

                // set real default colors (before anyone mucks with them at all)
                PutSettings((GambatteSettings)settings ?? new GambatteSettings());

                InitSound();

                Frame      = 0;
                LagCount   = 0;
                IsLagFrame = false;

                InputCallback = new LibGambatte.InputGetter(ControllerCallback);

                LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback);

                InitMemoryDomains();

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

                byte[] buff = new byte[32];
                LibGambatte.gambatte_romtitle(GambatteState, buff);
                string romname = System.Text.Encoding.ASCII.GetString(buff);
                Console.WriteLine("Core reported rom name: {0}", romname);

                if (!_syncSettings.EnableBIOS && IsCgb && IsCGBDMGMode())                 // without a bios, we need to set the palette for cgbdmg ourselves
                {
                    int[] cgbDmgColors = new int[] { 0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000 };
                    if (file[0x14B] == 0x01 || (file[0x14B] == 0x33 && file[0x144] == '0' && file[0x145] == '1'))                     // Nintendo licencees get special palettes
                    {
                        cgbDmgColors = ColorsFromTitleHash(file);
                    }
                    ChangeDMGColors(cgbDmgColors);
                }

                if (!DeterministicEmulation && _syncSettings.RealTimeRTC)
                {
                    LibGambatte.gambatte_settimemode(GambatteState, false);
                }

                if (DeterministicEmulation)
                {
                    int[] rtcRegs = new int[11];
                    rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] = 0;
                    if (_syncSettings.InternalRTCOverflow)
                    {
                        rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] |= 0x80;
                    }
                    if (_syncSettings.InternalRTCHalt)
                    {
                        rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] |= 0x40;
                    }
                    rtcRegs[(int)LibGambatte.RtcRegIndices.Dh]  |= _syncSettings.InternalRTCDays >> 8;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.Dl]   = _syncSettings.InternalRTCDays & 0xFF;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.H]    = (_syncSettings.InternalRTCHours < 0) ? (_syncSettings.InternalRTCHours + 0x20) : _syncSettings.InternalRTCHours;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.M]    = (_syncSettings.InternalRTCMinutes < 0) ? (_syncSettings.InternalRTCMinutes + 0x40) : _syncSettings.InternalRTCMinutes;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.S]    = (_syncSettings.InternalRTCSeconds < 0) ? (_syncSettings.InternalRTCSeconds + 0x40) : _syncSettings.InternalRTCSeconds;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.C]    = _syncSettings.InternalRTCCycles;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] = 0;
                    if (_syncSettings.LatchedRTCOverflow)
                    {
                        rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] |= 0x80;
                    }
                    if (_syncSettings.LatchedRTCHalt)
                    {
                        rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] |= 0x40;
                    }
                    rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] |= _syncSettings.LatchedRTCDays >> 8;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.Dl_L]  = _syncSettings.LatchedRTCDays & 0xFF;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.H_L]   = _syncSettings.LatchedRTCHours;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.M_L]   = _syncSettings.LatchedRTCMinutes;
                    rtcRegs[(int)LibGambatte.RtcRegIndices.S_L]   = _syncSettings.LatchedRTCSeconds;
                    LibGambatte.gambatte_setrtcregs(GambatteState, rtcRegs);
                }

                LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset);

                LibGambatte.gambatte_setcartbuspulluptime(GambatteState, (uint)_syncSettings.CartBusPullUpTime);

                _cdCallback = new LibGambatte.CDCallback(CDCallbackProc);

                ControllerDefinition = CreateControllerDefinition(IsSgb, _syncSettings.FrameLength is GambatteSyncSettings.FrameLengthType.UserDefinedFrames);

                NewSaveCoreSetBuff();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
Exemplo n.º 6
0
        public PCEngine(CoreComm comm, GameInfo game, Disc disc, object Settings, object syncSettings)
        {
            CoreComm          = comm;
            MemoryCallbacks   = new MemoryCallbackSystem();
            DriveLightEnabled = true;
            SystemId          = "PCECD";
            Type          = NecSystemType.TurboCD;
            this.disc     = disc;
            this.Settings = (PCESettings)Settings ?? new PCESettings();
            _syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings();

            GameInfo biosInfo;

            byte[] rom = CoreComm.CoreFileProvider.GetFirmwareWithGameInfo("PCECD", "Bios", true, out biosInfo,
                                                                           "PCE-CD System Card not found. Please check the BIOS settings in Config->Firmwares.");

            if (biosInfo.Status == RomStatus.BadDump)
            {
                CoreComm.ShowMessage(
                    "The PCE-CD System Card you have selected is known to be a bad dump. This may cause problems playing PCE-CD games.\n\n"
                    + "It is recommended that you find a good dump of the system card. Sorry to be the bearer of bad news!");
            }
            else if (biosInfo.NotInDatabase)
            {
                CoreComm.ShowMessage(
                    "The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom.");
            }
            else if (biosInfo["BIOS"] == false)
            {
                // zeromus says: someone please write a note about how this could possibly happen.
                // it seems like this is a relic of using gameDB for storing whether something is a bios? firmwareDB should be handling it now.
                CoreComm.ShowMessage(
                    "The PCE-CD System Card you have selected is not a BIOS image. You may have selected the wrong rom. FYI-Please report this to developers, I don't think this error message should happen.");
            }

            if (biosInfo["SuperSysCard"])
            {
                game.AddOption("SuperSysCard");
            }

            if (game["NeedSuperSysCard"] && game["SuperSysCard"] == false)
            {
                CoreComm.ShowMessage(
                    "This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in the firmware configuration.");
                throw new Exception();
            }

            game.FirmwareHash = rom.HashSHA1();

            Init(game, rom);

            // the default RomStatusDetails don't do anything with Disc
            CoreComm.RomStatusDetails = string.Format("{0}\r\nDisk partial hash:{1}", game.Name, new DiscSystem.DiscHasher(disc).OldHash());

            _controllerDeck = new PceControllerDeck(
                _syncSettings.Port1,
                _syncSettings.Port2,
                _syncSettings.Port3,
                _syncSettings.Port4,
                _syncSettings.Port5);
        }
Exemplo n.º 7
0
        private string snes_path_request(int slot, string hint, bool required)
        {
            // TODO: this msu1 handling code is outdated and needs to be remade from someone with knowledge.
            // every rom requests msu1.rom... why? who knows.
            // also handle msu-1 pcm files here
            bool isMsu1Rom = hint == "msu1/data.rom";
            bool isMsu1Pcm = Path.GetExtension(hint).ToLower() == ".pcm";

            if (isMsu1Rom || isMsu1Pcm)
            {
                // well, check if we have an msu-1 xml
                if (_romxml?["cartridge"]?["msu1"] != null)
                {
                    var msu1 = _romxml["cartridge"]["msu1"];
                    if (isMsu1Rom && msu1["rom"]?.Attributes["name"] != null)
                    {
                        return(PathSubfile(msu1["rom"].Attributes["name"].Value));
                    }

                    if (isMsu1Pcm)
                    {
                        // return @"D:\roms\snes\SuperRoadBlaster\SuperRoadBlaster-1.pcm";
                        // return "";
                        int wantsTrackNumber = int.Parse(hint.Replace("track-", "").Replace(".pcm", ""));
                        wantsTrackNumber++;
                        string wantsTrackString = wantsTrackNumber.ToString();
                        foreach (var child in msu1.ChildNodes.Cast <XmlNode>())
                        {
                            if (child.Name == "track" && child.Attributes["number"].Value == wantsTrackString)
                            {
                                return(PathSubfile(child.Attributes["name"].Value));
                            }
                        }
                    }
                }

                // not found.. what to do? (every rom will get here when msu1.rom is requested)
                return("");
            }

            // not MSU-1.  ok.
            if (hint == "save.ram")
            {
                // core asked for saveram, but the interface isn't designed to be able to handle this.
                // so, we'll just return nothing and the frontend will set the saveram itself later
                return(null);
            }

            string firmwareId;

            switch (hint)
            {
            case "cx4": firmwareId = "CX4"; break;

            case "dsp1": firmwareId = "DSP1"; break;

            case "dsp1b": firmwareId = "DSP1b"; break;

            case "dsp2": firmwareId = "DSP2"; break;

            case "dsp3": firmwareId = "DSP3"; break;

            case "dsp4": firmwareId = "DSP4"; break;

            case "st010": firmwareId = "ST010"; break;

            case "st011": firmwareId = "ST011"; break;

            case "st018": firmwareId = "ST018"; break;

            default:
                CoreComm.ShowMessage($"Unrecognized SNES firmware request \"{hint}\".");
                return("");
            }

            string ret  = "";
            var    data = CoreComm.CoreFileProvider.GetFirmware("SNES", firmwareId, required, "Game may function incorrectly without the requested firmware.");

            if (data != null)
            {
                ret = hint;
                Api.AddReadonlyFile(data, hint);
            }

            Console.WriteLine("Served bsnescore request for firmware \"{0}\"", hint);

            // return the path we built
            return(ret);
        }
Exemplo n.º 8
0
        private string snes_path_request(int slot, string hint, bool required)
        {
            switch (hint)
            {
            case "manifest.bml":
                Api.AddReadonlyFile($"{_romPath}.bml", hint);
                return(hint);

            case "msu1/data.rom":
                Api.AddReadonlyFile($"{_romPath}.msu", hint);
                return(hint);

            case "save.ram":
                // core asked for saveram, but the interface isn't designed to be able to handle this.
                // so, we'll just return nothing and the frontend will set the saveram itself later
                return(null);
            }

            string firmwareId;
            string firmwareSystem = "SNES";

            switch (hint)
            {
            case "cx4": firmwareId = "CX4"; break;

            case "dsp1": firmwareId = "DSP1"; break;

            case "dsp1b": firmwareId = "DSP1b"; break;

            case "dsp2": firmwareId = "DSP2"; break;

            case "dsp3": firmwareId = "DSP3"; break;

            case "dsp4": firmwareId = "DSP4"; break;

            case "st010": firmwareId = "ST010"; break;

            case "st011": firmwareId = "ST011"; break;

            case "st018": firmwareId = "ST018"; break;

            case "sgb": firmwareId = "SGB"; firmwareSystem = "GB"; break;

            case "sgb2": firmwareId = "SGB2"; firmwareSystem = "GB"; break;

            default:
                CoreComm.ShowMessage($"Unrecognized SNES firmware request \"{hint}\".");
                return("");
            }

            string       ret  = "";
            FirmwareID   fwid = new(firmwareSystem, firmwareId);
            const string MISSING_FIRMWARE_MSG = "Game may function incorrectly without the requested firmware.";

            byte[] data = required
                                ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(fwid, MISSING_FIRMWARE_MSG)
                                : CoreComm.CoreFileProvider.GetFirmware(fwid, MISSING_FIRMWARE_MSG);
            if (data != null)
            {
                ret = hint;
                Api.AddReadonlyFile(data, hint);
            }

            Console.WriteLine("Served bsnescore request for firmware \"{0}\"", hint);

            // return the path we built
            return(ret);
        }
Exemplo n.º 9
0
        public Gameboy(CoreComm comm, GameInfo game, byte[] file, GambatteSettings settings, GambatteSyncSettings syncSettings, bool deterministic)
        {
            var ser = new BasicServiceProvider(this);

            ser.Register <IDisassemblable>(_disassembler);
            ServiceProvider = ser;
            const string TRACE_HEADER = "LR35902: PC, opcode, registers (A, F, B, C, D, E, H, L, LY, SP, CY)";

            Tracer = new TraceBuffer(TRACE_HEADER);
            ser.Register <ITraceable>(Tracer);
            InitMemoryCallbacks();

            DeterministicEmulation = deterministic;

            GambatteState = LibGambatte.gambatte_create();

            if (GambatteState == IntPtr.Zero)
            {
                throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_create)}() returned null???");
            }

            Console.WriteLine(game.System);

            try
            {
                _syncSettings = syncSettings ?? new GambatteSyncSettings();

                LibGambatte.LoadFlags flags = LibGambatte.LoadFlags.READONLY_SAV;

                switch (_syncSettings.ConsoleMode)
                {
                case GambatteSyncSettings.ConsoleModeType.GB:
                    break;

                case GambatteSyncSettings.ConsoleModeType.GBC:
                    flags |= LibGambatte.LoadFlags.CGB_MODE;
                    break;

                case GambatteSyncSettings.ConsoleModeType.GBA:
                    flags |= LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG;
                    break;

                default:
                    if (game.System == VSystemID.Raw.GBC)
                    {
                        flags |= LibGambatte.LoadFlags.CGB_MODE;
                    }
                    break;
                }

                if (game.System == VSystemID.Raw.SGB)
                {
                    flags &= ~(LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG);
                    flags |= LibGambatte.LoadFlags.SGB_MODE;
                    IsSgb  = true;
                }

                IsCgb = (flags & LibGambatte.LoadFlags.CGB_MODE) == LibGambatte.LoadFlags.CGB_MODE;
                if (_syncSettings.EnableBIOS)
                {
                    FirmwareID fwid = new(
                        IsCgb ? "GBC" : "GB",
                        IsSgb
                                                        ? "SGB2"
                                                        : _syncSettings.ConsoleMode is GambatteSyncSettings.ConsoleModeType.GBA
                                                                ? "AGB"
                                                                : "World");
                    var bios = comm.CoreFileProvider.GetFirmwareOrThrow(fwid, "BIOS Not Found, Cannot Load.  Change SyncSettings to run without BIOS.");                     // https://github.com/TASEmulators/BizHawk/issues/2832 tho
                    if (LibGambatte.gambatte_loadbiosbuf(GambatteState, bios, (uint)bios.Length) != 0)
                    {
                        throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbiosbuf)}() returned non-zero (bios error)");
                    }
                }
                else
                {
                    if (DeterministicEmulation)                     // throw a warning if a movie is being recorded with the bios disabled
                    {
                        comm.ShowMessage("Detected disabled BIOS during movie recording. It is recommended to use a BIOS for movie recording. Change Sync Settings to run with a BIOS.");
                    }
                    flags |= LibGambatte.LoadFlags.NO_BIOS;
                }

                if (LibGambatte.gambatte_loadbuf(GambatteState, file, (uint)file.Length, flags) != 0)
                {
                    throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbuf)}() returned non-zero (is this not a gb or gbc rom?)");
                }

                if (IsSgb)
                {
                    ResetStallTicks = 128 * (2 << 14);
                }
                else if (_syncSettings.EnableBIOS && (_syncSettings.ConsoleMode is GambatteSyncSettings.ConsoleModeType.GBA))
                {
                    ResetStallTicks = 485808;                     // GBA takes 971616 cycles to switch to CGB mode; CGB CPU is inactive during this time.
                }
                else
                {
                    ResetStallTicks = 0;
                }

                // set real default colors (before anyone mucks with them at all)
                PutSettings(settings ?? new GambatteSettings());

                InitSound();

                Frame      = 0;
                LagCount   = 0;
                IsLagFrame = false;

                InputCallback = new LibGambatte.InputGetter(ControllerCallback);

                LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback, IntPtr.Zero);

                InitMemoryDomains();

                byte[] mbcBuf           = new byte[32];
                uint   rambanks         = 0;
                uint   rombanks         = 0;
                uint   crc              = 0;
                uint   headerchecksumok = 0;
                LibGambatte.gambatte_pakinfo(GambatteState, mbcBuf, ref rambanks, ref rombanks, ref crc, ref headerchecksumok);

                byte[] romNameBuf = new byte[32];
                LibGambatte.gambatte_romtitle(GambatteState, romNameBuf);
                string romname = Encoding.ASCII.GetString(romNameBuf);

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

                RomDetails += $"Core reported Header Name: {romname}\r\n";
                RomDetails += $"Core reported RAM Banks: {rambanks}\r\n";
                RomDetails += $"Core reported ROM Banks: {rombanks}\r\n";
                RomDetails += $"Core reported CRC32: {crc:X8}\r\n";
                RomDetails += $"Core reported Header Checksum Status: {(headerchecksumok != 0 ? "OK" : "BAD")}\r\n";

                if (_syncSettings.EnableBIOS && headerchecksumok == 0)
                {
                    comm.ShowMessage("Core reports the header checksum is bad. This ROM will not boot with the official BIOS.\n" +
                                     "Disable BIOS in sync settings to boot this game");
                }

                if (!_syncSettings.EnableBIOS && IsCgb && IsCGBDMGMode())                 // without a bios, we need to set the palette for cgbdmg ourselves
                {
                    int[] cgbDmgColors = new int[] { 0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000 };
                    if (file[0x14B] == 0x01 || (file[0x14B] == 0x33 && file[0x144] == '0' && file[0x145] == '1'))                     // Nintendo licencees get special palettes
                    {
                        cgbDmgColors = ColorsFromTitleHash(file);
                    }
                    ChangeDMGColors(cgbDmgColors);
                }

                if (!DeterministicEmulation && _syncSettings.RealTimeRTC)
                {
                    LibGambatte.gambatte_settimemode(GambatteState, false);
                }

                if (DeterministicEmulation)
                {
                    ulong dividers = _syncSettings.InitialTime * (0x400000UL + (ulong)_syncSettings.RTCDivisorOffset) / 2UL;
                    LibGambatte.gambatte_settime(GambatteState, dividers);
                }

                LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset);

                LibGambatte.gambatte_setcartbuspulluptime(GambatteState, (uint)_syncSettings.CartBusPullUpTime);

                _cdCallback = new LibGambatte.CDCallback(CDCallbackProc);

                ControllerDefinition = CreateControllerDefinition(sgb: IsSgb, sub: _syncSettings.FrameLength is GambatteSyncSettings.FrameLengthType.UserDefinedFrames, tilt: false);

                NewSaveCoreSetBuff();
            }
            catch
            {
                Dispose();
                throw;
            }
        }