public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); Settings = (SmsSettings)settings ?? new SmsSettings(); SyncSettings = (SmsSyncSettings)syncSettings ?? new SmsSyncSettings(); CoreComm = comm; MemoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus" }); IsGameGear = game.System == "GG"; IsGameGear_C = game.System == "GG"; IsSG1000 = game.System == "SG"; RomData = rom; if (RomData.Length % BankSize != 0) { Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } RomBanks = (byte)(RomData.Length / BankSize); Region = DetermineDisplayType(SyncSettings.DisplayType, game.Region); if (game["PAL"] && Region != DisplayType.PAL) { Region = DisplayType.PAL; CoreComm.Notify("Display was forced to PAL mode for game compatibility."); } if (IsGameGear) { Region = DisplayType.NTSC; // all game gears run at 60hz/NTSC mode } _region = SyncSettings.ConsoleRegion; if (_region == SmsSyncSettings.Regions.Auto) { _region = DetermineRegion(game.Region); } if (game["Japan"] && _region != SmsSyncSettings.Regions.Japan) { _region = SmsSyncSettings.Regions.Japan; CoreComm.Notify("Region was forced to Japan for game compatibility."); } if (game["Korea"] && _region != SmsSyncSettings.Regions.Korea) { _region = SmsSyncSettings.Regions.Korea; CoreComm.Notify("Region was forced to Korea for game compatibility."); } if ((game.NotInDatabase || game["FM"]) && SyncSettings.EnableFm && !IsGameGear) { HasYM2413 = true; } Cpu = new Z80A() { ReadHardware = ReadPort, WriteHardware = WritePort, FetchMemory = FetchMemory, ReadMemory = ReadMemory, WriteMemory = WriteMemory, MemoryCallbacks = MemoryCallbacks, OnExecFetch = OnExecMemory }; if (game["GG_in_SMS"]) { // skip setting the BIOS because this is a game gear game that puts the system // in SMS compatibility mode (it will fail the check sum if played on an actual SMS though.) IsGameGear = false; IsGameGear_C = true; game.System = "GG"; Console.WriteLine("Using SMS Compatibility mode for Game Gear System"); } Vdp = new VDP(this, Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, Region); (ServiceProvider as BasicServiceProvider).Register <IVideoProvider>(Vdp); PSG = new SN76489sms(); YM2413 = new YM2413(); //SoundMixer = new SoundMixer(YM2413, PSG); if (HasYM2413 && game["WhenFMDisablePSG"]) { disablePSG = true; } blip_L.SetRates(3579545, 44100); blip_R.SetRates(3579545, 44100); (ServiceProvider as BasicServiceProvider).Register <ISoundProvider>(this); SystemRam = new byte[0x2000]; if (game["CMMapper"]) { InitCodeMastersMapper(); } else if (game["CMMapperWithRam"]) { InitCodeMastersMapperRam(); } else if (game["ExtRam"]) { InitExt2kMapper(int.Parse(game.OptionValue("ExtRam"))); } else if (game["KoreaMapper"]) { InitKoreaMapper(); } else if (game["MSXMapper"]) { InitMSXMapper(); } else if (game["NemesisMapper"]) { InitNemesisMapper(); } else if (game["TerebiOekaki"]) { InitTerebiOekaki(); } else if (game["EEPROM"]) { InitEEPROMMapper(); } else { InitSegaMapper(); } if (Settings.ForceStereoSeparation && !IsGameGear) { if (game["StereoByte"]) { ForceStereoByte = byte.Parse(game.OptionValue("StereoByte")); } PSG.Set_Panning(ForceStereoByte); } if (SyncSettings.AllowOverClock && game["OverclockSafe"]) { Vdp.IPeriod = 512; } if (Settings.SpriteLimit) { Vdp.SpriteLimit = true; } if (game["3D"]) { IsGame3D = true; } if (game["BIOS"]) { Port3E = 0xF7; // Disable cartridge, enable BIOS rom InitBiosMapper(); } else if (game.System == "SMS" && !game["GG_in_SMS"]) { BiosRom = comm.CoreFileProvider.GetFirmware("SMS", _region.ToString(), false); if (BiosRom == null) { throw new MissingFirmwareException("No BIOS found"); } if (!game["RequireBios"] && !SyncSettings.UseBios) { // we are skipping the BIOS // but only if it won't break the game } else { Port3E = 0xF7; } } if (game["SRAM"]) { SaveRAM = new byte[int.Parse(game.OptionValue("SRAM"))]; Console.WriteLine(SaveRAM.Length); } else if (game.NotInDatabase) { SaveRAM = new byte[0x8000]; } SetupMemoryDomains(); //this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete ((ICodeDataLogger)this).SetCDL(null); InputCallbacks = new InputCallbackSystem(); Tracer = new TraceBuffer { Header = Cpu.TraceHeader }; var serviceProvider = ServiceProvider as BasicServiceProvider; serviceProvider.Register <ITraceable>(Tracer); serviceProvider.Register <IDisassemblable>(Cpu); Vdp.ProcessOverscan(); Cpu.ReadMemory = ReadMemory; Cpu.WriteMemory = WriteMemory; // Z80 SP initialization // stops a few SMS and GG games from crashing Cpu.Regs[Cpu.SPl] = 0xF0; Cpu.Regs[Cpu.SPh] = 0xDF; }
public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); Settings = (SMSSettings)settings ?? new SMSSettings(); SyncSettings = (SMSSyncSettings)syncSettings ?? new SMSSyncSettings(); CoreComm = comm; MemoryCallbacks = new MemoryCallbackSystem(); IsGameGear = game.System == "GG"; IsSG1000 = game.System == "SG"; RomData = rom; if (RomData.Length % BankSize != 0) { Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } RomBanks = (byte)(RomData.Length / BankSize); Region = DetermineDisplayType(SyncSettings.DisplayType, game.Region); if (game["PAL"] && Region != DisplayType.PAL) { Region = DisplayType.PAL; CoreComm.Notify("Display was forced to PAL mode for game compatibility."); } if (IsGameGear) { Region = DisplayType.NTSC; // all game gears run at 60hz/NTSC mode } CoreComm.VsyncNum = Region == DisplayType.NTSC ? 60 : 50; CoreComm.VsyncDen = 1; RegionStr = SyncSettings.ConsoleRegion; if (RegionStr == "Auto") { RegionStr = DetermineRegion(game.Region); } if (game["Japan"] && RegionStr != "Japan") { RegionStr = "Japan"; CoreComm.Notify("Region was forced to Japan for game compatibility."); } if ((game.NotInDatabase || game["FM"]) && SyncSettings.EnableFM && !IsGameGear) { HasYM2413 = true; } if (Controller == null) { Controller = NullController.Instance; } Cpu = new Z80A(); Cpu.RegisterSP = 0xDFF0; Cpu.ReadHardware = ReadPort; Cpu.WriteHardware = WritePort; Cpu.MemoryCallbacks = MemoryCallbacks; Vdp = new VDP(this, Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, Region); (ServiceProvider as BasicServiceProvider).Register <IVideoProvider>(Vdp); PSG = new SN76489(); YM2413 = new YM2413(); SoundMixer = new SoundMixer(YM2413, PSG); if (HasYM2413 && game["WhenFMDisablePSG"]) { SoundMixer.DisableSource(PSG); } ActiveSoundProvider = HasYM2413 ? (IAsyncSoundProvider)SoundMixer : PSG; _fakeSyncSound = new FakeSyncSound(ActiveSoundProvider, 735); (ServiceProvider as BasicServiceProvider).Register <ISoundProvider>(_fakeSyncSound); SystemRam = new byte[0x2000]; if (game["CMMapper"]) { InitCodeMastersMapper(); } else if (game["CMMapperWithRam"]) { InitCodeMastersMapperRam(); } else if (game["ExtRam"]) { InitExt2kMapper(int.Parse(game.OptionValue("ExtRam"))); } else if (game["KoreaMapper"]) { InitKoreaMapper(); } else if (game["MSXMapper"]) { InitMSXMapper(); } else if (game["NemesisMapper"]) { InitNemesisMapper(); } else if (game["TerebiOekaki"]) { InitTerebiOekaki(); } else { InitSegaMapper(); } if (Settings.ForceStereoSeparation && !IsGameGear) { if (game["StereoByte"]) { ForceStereoByte = byte.Parse(game.OptionValue("StereoByte")); } PSG.StereoPanning = ForceStereoByte; } if (SyncSettings.AllowOverlock && game["OverclockSafe"]) { Vdp.IPeriod = 512; } if (Settings.SpriteLimit) { Vdp.SpriteLimit = true; } if (game["3D"]) { IsGame3D = true; } if (game["BIOS"]) { Port3E = 0xF7; // Disable cartridge, enable BIOS rom InitBiosMapper(); } else if (game.System == "SMS") { BiosRom = comm.CoreFileProvider.GetFirmware("SMS", RegionStr, false); if (BiosRom != null && (game["RequireBios"] || SyncSettings.UseBIOS)) { Port3E = 0xF7; } if (BiosRom == null && game["RequireBios"]) { throw new MissingFirmwareException("BIOS image not available. This game requires BIOS to function."); } if (SyncSettings.UseBIOS && BiosRom == null) { CoreComm.Notify("BIOS was selected, but rom image not available. BIOS not enabled."); } } if (game["SRAM"]) { SaveRAM = new byte[int.Parse(game.OptionValue("SRAM"))]; } else if (game.NotInDatabase) { SaveRAM = new byte[0x8000]; } SetupMemoryDomains(); //this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete ((ICodeDataLogger)this).SetCDL(null); InputCallbacks = new InputCallbackSystem(); Tracer = new TraceBuffer { Header = Cpu.TraceHeader }; var serviceProvider = ServiceProvider as BasicServiceProvider; serviceProvider.Register <ITraceable>(Tracer); serviceProvider.Register <IDisassemblable>(new Disassembler()); Vdp.ProcessOverscan(); }