Esempio n. 1
0
        private void HardReset()
        {
            _ram = new byte[128];
            _mapper.HardReset();

            Cpu = new MOS6502X
            {
                ReadMemory      = ReadMemory,
                WriteMemory     = WriteMemory,
                PeekMemory      = PeekMemory,
                DummyReadMemory = ReadMemory,
                OnExecFetch     = ExecFetch
            };

            _tia.Reset();

            _m6532 = new M6532(this);
            Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8));             // set the initial PC

            // as it turns out, the stack pointer cannot be set to 0 for some games as they do not initilize it themselves.
            // some documentation seems to indicate it should beset to FD, but currently there is no documentation of the 6532
            // executing a reset sequence at power on, but it's needed so let's hard code it for now
            Cpu.S = 0xFD;

            SetupMemoryDomains();
        }
Esempio n. 2
0
        private void MakeTrace(IntPtr data)
        {
            int[] s = new int[7];
            Marshal.Copy(data, s, 0, 7);

            byte   a  = (byte)s[0];
            byte   x  = (byte)s[1];
            byte   y  = (byte)s[2];
            ushort sp = (ushort)s[3];
            ushort pc = (ushort)s[4];
            byte   p  = (byte)s[5];

            byte opcode = (byte)s[6];

            int    notused   = 0;
            string opcodeStr = MOS6502X.Disassemble(pc, out notused, (address) => _memoryDomains.SystemBus.PeekByte(address));

            Tracer.Put(new TraceInfo
            {
                Disassembly  = string.Format("{0:X4} {1}", pc, opcodeStr).PadRight(26),
                RegisterInfo = string.Format(
                    "SP:{0:X2} A:{1:X2} P:{2:X2} X:{3:X2} Y:{4:X2}",
                    sp,
                    a,
                    p,
                    x,
                    y)
            });
        }
Esempio n. 3
0
        private void MakeTrace(IntPtr data)
        {
            int[] s = new int[7];
            Marshal.Copy(data, s, 0, 7);

            byte   a  = (byte)s[0];
            byte   x  = (byte)s[1];
            byte   y  = (byte)s[2];
            ushort sp = (ushort)s[3];
            ushort pc = (ushort)s[4];
            byte   p  = (byte)s[5];

            byte opcode = (byte)s[6];

            int    notused   = 0;
            string opcodeStr = MOS6502X.Disassemble(pc, out notused, (address) => _memoryDomains.SystemBus.PeekByte(address));

            Tracer.Put(new TraceInfo
            {
                Disassembly  = $"{pc:X4}:  {opcodeStr}".PadRight(26),
                RegisterInfo = string.Join(" ",
                                           $"A:{a:X2}",
                                           $"X:{x:X2}",
                                           $"Y:{y:X2}",
                                           $"P:{p:X2}",
                                           $"SP:{sp:X2}")
            });
        }
Esempio n. 4
0
        public Chip6510()
        {
            // configure cpu r/w
            _cpu = new MOS6502X <CpuLink>(new CpuLink(this));

            // perform hard reset
            HardReset();
        }
Esempio n. 5
0
 public Cpu()
 {
     processor = new MOS6502X();
     processor.DummyReadMemory = CoreReadMemory;
     processor.ReadMemory      = CoreReadMemory;
     processor.WriteMemory     = CoreWriteMemory;
     Reset();
 }
Esempio n. 6
0
        // ------------------------------------

        public MOS6510()
        {
            cpu = new MOS6502X();

            // configure cpu r/w
            cpu.DummyReadMemory = Read;
            cpu.ReadMemory      = Read;
            cpu.WriteMemory     = Write;

            // perform hard reset
            HardReset();
        }
Esempio n. 7
0
        private void HardReset()
        {
            _ram = new byte[128];
            _mapper.HardReset();

            Cpu = new MOS6502X <CpuLink>(new CpuLink(this));

            _tia.Reset();
            _m6532 = new M6532(this);
            SetupMemoryDomains();
            cyc_counter = 0;
        }
Esempio n. 8
0
        // ------------------------------------

        public Chip6510()
        {
            // configure cpu r/w
            _cpu = new MOS6502X
            {
                DummyReadMemory = CpuRead,
                ReadMemory      = CpuRead,
                WriteMemory     = CpuWrite,
                PeekMemory      = CpuPeek
            };

            // perform hard reset
            HardReset();
        }
Esempio n. 9
0
        public Drive1541(int clockNum, int clockDen)
        {
            DriveRom = new Chip23128();
            _cpu     = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                NMI = false
            };

            _ram = new int[0x800];
            Via0 = Chip6522.Create(ViaReadClock, ViaReadData, ViaReadAtn, 8);
            Via1 = Chip6522.Create(ReadVia1PrA, ReadVia1PrB);

            _cpuClockNum      = clockNum;
            _driveCpuClockNum = clockDen * 16000000;             // 16mhz
        }
Esempio n. 10
0
        private void RebootCore()
        {
            // Regenerate mapper here to make sure its state is entirely clean
            _mapper   = CreateMapper(this, _game.GetOptions()["m"], Rom.Length);
            _lagCount = 0;
            Cpu       = new MOS6502X <CpuLink>(new CpuLink(this));

            if (_game["PAL"])
            {
                _pal = true;
            }
            else if (_game["NTSC"])
            {
                _pal = false;
            }
            else
            {
                _pal = DetectPal(_game, Rom);
            }

            // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
            _tia = new TIA(this, _pal, Settings.SECAMColors);

            _dcfilter = new DCFilter(_tia, 256);

            _m6532 = new M6532(this);

            HardReset();

            RomDetails = $"{_game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(Rom)}\r\n{MD5Checksum.ComputePrefixedHex(Rom)}\r\nMapper Impl \"{_mapper.GetType()}\"";

            // Some games (ex. 3D tic tac toe), turn off the screen for extended periods, so we need to allow for this here.
            if (_game.GetOptions().TryGetValue("SP_FRAME", out var spFrameStr) && spFrameStr == "true")
            {
                SP_FRAME = true;
            }
            // Some games wait for reset to be unpressed before turning the screen back on, hack unset it if needed
            if (_game.GetOptions().TryGetValue("SP_RESET", out var spResetStr) && spResetStr == "true")
            {
                SP_RESET = true;
            }
            // Ditto select (ex. Karate)
            if (_game.GetOptions().TryGetValue("SP_SELECT", out var spSelectStr) && spSelectStr == "true")
            {
                SP_SELECT = true;
            }
        }
        private void RebootCore()
        {
            // Regenerate mapper here to make sure its state is entirely clean
            _mapper   = CreateMapper(this, _game.GetOptions()["m"], Rom.Length);
            _lagCount = 0;
            Cpu       = new MOS6502X <CpuLink>(new CpuLink(this));

            if (_game["PAL"])
            {
                _pal = true;
            }
            else if (_game["NTSC"])
            {
                _pal = false;
            }
            else
            {
                _pal = DetectPal(_game, Rom);
            }

            // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
            _tia = new TIA(this, _pal, Settings.SECAMColors);

            _dcfilter = new DCFilter(_tia, 256);

            _m6532 = new M6532(this);

            HardReset();

            RomDetails = $"{_game.Name}\r\nSHA1:{Rom.HashSHA1()}\r\nMD5:{Rom.HashMD5()}\r\nMapper Impl \"{_mapper.GetType()}\"";

            // Some games (ex. 3D tic tac toe), turn off the screen for extended periods, so we need to allow for this here.
            if (_game.GetOptions().ContainsKey("SP_FRAME"))
            {
                if (_game.GetOptions()["SP_FRAME"] == "true")
                {
                    SP_FRAME = true;
                }
            }
            if (_game.GetOptions().ContainsKey("SP_RESET"))
            {
                if (_game.GetOptions()["SP_RESET"] == "true")
                {
                    SP_RESET = true;
                }
            }
        }
Esempio n. 12
0
        private void HardReset()
        {
            _ram = new byte[128];
            _mapper.HardReset();

            Cpu = new MOS6502X
            {
                ReadMemory      = ReadMemory,
                WriteMemory     = WriteMemory,
                PeekMemory      = PeekMemory,
                DummyReadMemory = ReadMemory,
                OnExecFetch     = ExecFetch
            };

            _tia.Reset();
            _m6532 = new M6532(this);
            SetupMemoryDomains();
            cyc_counter = 0;
        }
Esempio n. 13
0
        public Drive1541(int clockNum, int clockDen)
        {
            DriveRom = new Chip23128();
            _cpu     = new MOS6502X
            {
                ReadMemory      = CpuRead,
                WriteMemory     = CpuWrite,
                DummyReadMemory = CpuRead,
                PeekMemory      = CpuPeek,
                NMI             = false
            };

            _ram = new int[0x800];
            Via0 = Chip6522.Create(ViaReadClock, ViaReadData, ViaReadAtn, 8);
            Via1 = Chip6522.Create(ReadVia1PrA, ReadVia1PrB);

            _cpuClockNum      = clockNum;
            _driveCpuClockNum = clockDen * 16000000;             // 16mhz
        }
Esempio n. 14
0
        public void HardReset()
        {
            Ram = new byte[128];
            _mapper.HardReset();

            Cpu = new MOS6502X
            {
                ReadMemory      = this.ReadMemory,
                WriteMemory     = this.WriteMemory,
                PeekMemory      = this.PeekMemory,
                DummyReadMemory = this.ReadMemory,
                OnExecFetch     = this.ExecFetch
            };

            _tia.Reset();

            M6532  = new M6532(this);
            Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8));             // set the initial PC
        }
Esempio n. 15
0
        public A7800Hawk(CoreComm comm, byte[] rom, A7800Hawk.A7800Settings settings, A7800Hawk.A7800SyncSettings syncSettings)
        {
            var ser = new BasicServiceProvider(this);

            maria = new Maria();
            tia   = new TIA();
            m6532 = new M6532();
            pokey = new Pokey();

            cpu = new MOS6502X <CpuLink>(new CpuLink(this));

            maria = new Maria
            {
                ReadMemory = ReadMemory
            };

            _blip.SetRates(1789773, 44100);

            _settings       = (A7800Settings)settings ?? new A7800Settings();
            _syncSettings   = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings();
            _controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2);

            var highscoreBios = comm.CoreFileProvider.GetFirmware(new("A78", "Bios_HSC"), "Some functions may not work without the high score BIOS.");
            var palBios       = comm.CoreFileProvider.GetFirmware(new("A78", "Bios_PAL"), "The game will not run if the correct region BIOS is not available.");
            var ntscBios      = comm.CoreFileProvider.GetFirmware(new("A78", "Bios_NTSC"), "The game will not run if the correct region BIOS is not available.");

            byte[] header    = new byte[128];
            bool   is_header = false;

            if (rom.Length % 1024 == 128)
            {
                Console.WriteLine("128 byte header detected");
                byte[] newrom = new byte[rom.Length - 128];
                is_header = true;
                Buffer.BlockCopy(rom, 0, header, 0, 128);
                Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length);
                rom = newrom;
            }

            _isPAL = false;

            // look up hash in gamedb to see what mapper to use
            // if none found default is zero
            // also check for PAL region
            s_mapper = null;
            var hash_md5 = MD5Checksum.ComputePrefixedHex(rom);

            var gi = Database.CheckDatabase(hash_md5);

            if (gi != null)
            {
                var dict = gi.GetOptions();
                if (dict.ContainsKey("PAL"))
                {
                    _isPAL = true;
                }

                if (!dict.TryGetValue("board", out s_mapper))
                {
                    throw new Exception("No Board selected for this game");
                }

                // check if the game uses pokey or RAM
                if (dict.TryGetValue("RAM", out var cartRAMStr))
                {
                    int.TryParse(cartRAMStr, out cart_RAM);
                }

                if (dict.TryGetValue("Pokey", out var pokeyStr))
                {
                    bool.TryParse(pokeyStr, out is_pokey);
                }

                if (dict.TryGetValue("Pokey_450", out var pokey450Str))
                {
                    bool.TryParse(pokey450Str, out is_pokey_450);
                }

                // some games will not function with the high score bios
                // if such a game is being played, tell the user and disable it
                if (dict.TryGetValue("No_HS", out var noHSStr))
                {
                    bool.TryParse(noHSStr, out var no_hs);

                    if (no_hs)
                    {
                        Console.WriteLine("This game is incompatible with the High Score BIOS, disabling it");
                        highscoreBios = null;
                    }
                }
            }
            else if (is_header)
            {
                Console.WriteLine("ROM not in DB, inferring mapper info from header");

                byte cart_1 = header[0x35];
                byte cart_2 = header[0x36];

                _isPAL = (header[0x39] > 0);

                if (cart_2.Bit(1))
                {
                    if (cart_2.Bit(3))
                    {
                        s_mapper = "2";
                    }
                    else
                    {
                        s_mapper = "1";
                    }

                    if (cart_2.Bit(2))
                    {
                        cart_RAM = 8;

                        // the homebrew game serpentine requires extra RAM, but in the alternative style
                        if (hash_md5 == RomChecksums.Serpentine)
                        {
                            cart_RAM = 16;
                        }
                    }
                }
                else
                {
                    s_mapper = "0";
                }

                if (cart_2.Bit(0))
                {
                    is_pokey = true;
                }

                // the homebrew game serpentine requires the pokey chip to be available at the alternative location 0x450
                if (cart_2.Bit(6))
                {
                    is_pokey_450 = true;
                }
            }
            else
            {
                throw new Exception("ROM not in gamedb and has no header");
            }

            // some games that use the Super Game mapper only have 4 banks, so let's set a flag to limit bank size
            if (rom.Length < 0x14000)
            {
                small_flag = true;

                // additionally, PAL Karateka  has bank 6 (actually 2) at 0x4000
                if (hash_md5 == RomChecksums.KaratekaPAL)
                {
                    PAL_Kara = true;
                }
            }

            _rom = rom;

            Reset_Mapper(s_mapper);

            _hsbios = highscoreBios;
            _bios   = _isPAL ? palBios : ntscBios;

            if (_bios == null)
            {
                throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games.");
            }

            // set up palette and frame rate
            if (_isPAL)
            {
                _frameHz       = 50;
                _screen_width  = 320;
                _screen_height = 313;
                _vblanklines   = 20;
                maria._palette = PALPalette;
            }
            else
            {
                _frameHz       = 60;
                _screen_width  = 320;
                _screen_height = 263;
                _vblanklines   = 20;
                maria._palette = NTSCPalette;
            }

            maria.Core = this;
            m6532.Core = this;
            tia.Core   = this;
            pokey.Core = this;

            ser.Register <IVideoProvider>(this);
            ser.Register <ISoundProvider>(this);
            ServiceProvider = ser;

            _tracer = new TraceBuffer(cpu.TraceHeader);
            ser.Register <ITraceable>(_tracer);
            ser.Register <IStatable>(new StateSerializer(SyncState));
            SetupMemoryDomains();
            ser.Register <IDisassemblable>(cpu);
            HardReset();
        }
Esempio n. 16
0
        private void RebootCore()
        {
            // Regenerate mapper here to make sure its state is entirely clean
            switch (_game.GetOptionsDict()["m"])
            {
            case "2IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 2);
                break;

            case "4IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 4);
                break;

            case "8IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 8);
                break;

            case "16IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 16);
                break;

            case "32IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 32);
                break;

            case "AR":
                _mapper = new mAR(this);                         // This mapper has to set up configurations in the contructor.
                break;

            case "4K":
                _mapper = new m4K();
                break;

            case "2K":
                _mapper = new m2K();
                break;

            case "CM":
                _mapper = new mCM();
                break;

            case "CV":
                _mapper = new mCV();
                break;

            case "DPC":
                _mapper = new mDPC();
                break;

            case "DPC+":
                _mapper = new mDPCPlus();
                break;

            case "F8":
                _mapper = new mF8();
                break;

            case "F8SC":
                _mapper = new mF8SC();
                break;

            case "F6":
                _mapper = new mF6();
                break;

            case "F6SC":
                _mapper = new mF6SC();
                break;

            case "F4":
                _mapper = new mF4();
                break;

            case "F4SC":
                _mapper = new mF4SC();
                break;

            case "FE":
                _mapper = new mFE();
                break;

            case "E0":
                _mapper = new mE0();
                break;

            case "3F":
                _mapper = new m3F();
                break;

            case "FA":
                _mapper = new mFA();
                break;

            case "FA2":
                _mapper = new mFA2();
                break;

            case "E7":
                _mapper = new mE7();
                break;

            case "F0":
                _mapper = new mF0();
                break;

            case "UA":
                _mapper = new mUA();
                break;

            // Special Sega Mapper which has swapped banks
            case "F8_sega":
                _mapper = new mF8_sega();
                break;

            // Homebrew mappers
            case "3E":
                _mapper = new m3E();
                break;

            case "0840":
                _mapper = new m0840();
                break;

            case "MC":
                _mapper = new mMC();
                break;

            case "EF":
                _mapper = new mEF();
                break;

            case "EFSC":
                _mapper = new mEFSC();
                break;

            case "X07":
                _mapper = new mX07();
                break;

            case "4A50":
                _mapper = new m4A50();
                break;

            case "SB":
                _mapper = new mSB();
                break;

            default:
                throw new InvalidOperationException("mapper not supported: " + _game.GetOptionsDict()["m"]);
            }

            _mapper.Core = this;

            _lagCount = 0;
            Cpu       = new MOS6502X <CpuLink>(new CpuLink(this));

            if (_game["PAL"])
            {
                _pal = true;
            }
            else if (_game["NTSC"])
            {
                _pal = false;
            }
            else
            {
                _pal = DetectPal(_game, Rom);
            }

            // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
            _tia = new TIA(this, _pal, Settings.SECAMColors);

            _dcfilter = new DCFilter(_tia, 256);

            _m6532 = new M6532(this);

            HardReset();

            // Show mapper class on romstatusdetails
            CoreComm.RomStatusDetails = $"{this._game.Name}\r\nSHA1:{Rom.HashSHA1()}\r\nMD5:{Rom.HashMD5()}\r\nMapper Impl \"{_mapper.GetType()}\"";

            // Some games (ex. 3D tic tac toe), turn off the screen for extended periods, so we need to allow for this here.
            if (_game.GetOptionsDict().ContainsKey("SP_FRAME"))
            {
                if (_game.GetOptionsDict()["SP_FRAME"] == "true")
                {
                    SP_FRAME = true;
                }
            }
            if (_game.GetOptionsDict().ContainsKey("SP_RESET"))
            {
                if (_game.GetOptionsDict()["SP_RESET"] == "true")
                {
                    SP_RESET = true;
                }
            }
        }
Esempio n. 17
0
        public void HardReset()
        {
            cpu = new MOS6502X();
            cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory);

            cpu.BCD_Enabled = false;
            cpu.OnExecFetch = ExecFetch;
            ppu             = new PPU(this);
            ram             = new byte[0x800];
            CIRAM           = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition      = new ControllerDefinition(ControllerDeck.GetDefinition());
                ControllerDefinition.Name = "NES Controller";
                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (Board is FDS)
                {
                    var b = Board as FDS;
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }

                if (_isVS)
                {
                    ControllerDefinition.BoolButtons.Add("Insert Coin P1");
                    ControllerDefinition.BoolButtons.Add("Insert Coin P2");
                    ControllerDefinition.BoolButtons.Add("Service Switch");
                }
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case Common.DisplayType.PAL:
                apu               = new APU(this, apu, true);
                ppu.region        = PPU.Region.PAL;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1662607;
                cpu_sequence      = cpu_sequence_PAL;
                _display_type     = DisplayType.PAL;
                break;

            case Common.DisplayType.NTSC:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.NTSC;
                CoreComm.VsyncNum = 39375000;
                CoreComm.VsyncDen = 655171;
                cpuclockrate      = 1789773;
                cpu_sequence      = cpu_sequence_NTSC;
                break;

            // this is in bootgod, but not used at all
            case Common.DisplayType.DENDY:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.Dendy;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1773448;
                cpu_sequence      = cpu_sequence_NTSC;
                _display_type     = DisplayType.DENDY;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }
            if (magicSoundProvider == null)
            {
                magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate);
            }

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();


            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.

            if (cart.DB_GameInfo != null)
            {
                if (cart.DB_GameInfo.Hash == "60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558" ||              // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "BAD382331C30B22A908DA4BFF2759C25113CC26A" ||                     // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "40409FEC8249EFDB772E6FFB2DCD41860C6CCA23"                        // Camerica Pegasus 4-in-1
                    )
                {
                    ram[0x701] = 0xFF;
                }
            }
        }
Esempio n. 18
0
        public void RebootCore()
        {
            // Regenerate mapper here to make sure its state is entirely clean
            switch (_game.GetOptionsDict()["m"])
            {
            case "2IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 2);
                break;

            case "4IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 4);
                break;

            case "8IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 8);
                break;

            case "16IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 16);
                break;

            case "32IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 32);
                break;

            case "AR":
                _mapper = new mAR(this);                         // This mapper has to set up configurations in the contructor.
                break;

            case "4K":
                _mapper = new m4K();
                break;

            case "2K":
                _mapper = new m2K();
                break;

            case "CM":
                _mapper = new mCM();
                break;

            case "CV":
                _mapper = new mCV();
                break;

            case "DPC":
                _mapper = new mDPC();
                break;

            case "DPC+":
                _mapper = new mDPCPlus();
                break;

            case "F8":
                _mapper = new mF8();
                break;

            case "F8SC":
                _mapper = new mF8SC();
                break;

            case "F6":
                _mapper = new mF6();
                break;

            case "F6SC":
                _mapper = new mF6SC();
                break;

            case "F4":
                _mapper = new mF4();
                break;

            case "F4SC":
                _mapper = new mF4SC();
                break;

            case "FE":
                _mapper = new mFE();
                break;

            case "E0":
                _mapper = new mE0();
                break;

            case "3F":
                _mapper = new m3F();
                break;

            case "FA":
                _mapper = new mFA();
                break;

            case "FA2":
                _mapper = new mFA2();
                break;

            case "E7":
                _mapper = new mE7();
                break;

            case "F0":
                _mapper = new mF0();
                break;

            case "UA":
                _mapper = new mUA();
                break;

            // Homebrew mappers
            case "3E":
                _mapper = new m3E();
                break;

            case "0840":
                _mapper = new m0840();
                break;

            case "MC":
                _mapper = new mMC();
                break;

            case "EF":
                _mapper = new mEF();
                break;

            case "EFSC":
                _mapper = new mEFSC();
                break;

            case "X07":
                _mapper = new mX07();
                break;

            case "4A50":
                _mapper = new m4A50();
                break;

            case "SB":
                _mapper = new mSB();
                break;

            default:
                throw new InvalidOperationException("mapper not supported: " + _game.GetOptionsDict()["m"]);
            }

            _mapper.Core = this;

            _lagcount = 0;
            Cpu       = new MOS6502X
            {
                ReadMemory      = this.ReadMemory,
                WriteMemory     = this.WriteMemory,
                PeekMemory      = this.PeekMemory,
                DummyReadMemory = this.ReadMemory,
                OnExecFetch     = this.ExecFetch
            };

            if (_game["PAL"])
            {
                _pal = true;
            }
            else if (_game["NTSC"])
            {
                _pal = false;
            }
            else
            {
                _pal = DetectPal(_game, Rom);
            }

            _tia = new TIA(this, _pal, Settings.SECAMColors);
            _tia.GetFrameRate(out CoreComm.VsyncNum, out CoreComm.VsyncDen);

            // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
            _dcfilter = DCFilter.AsISoundProvider(_tia, 256);

            M6532 = new M6532(this);

            // Set up the system state here. for instance..
            // Read from the reset vector for where to start
            Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8));             // set the initial PC

            // Show mapper class on romstatusdetails
            CoreComm.RomStatusDetails =
                string.Format(
                    "{0}\r\nSHA1:{1}\r\nMD5:{2}\r\nMapper Impl \"{3}\"",
                    this._game.Name,
                    Rom.HashSHA1(),
                    Rom.HashMD5(),
                    _mapper.GetType());
        }
Esempio n. 19
0
        private void RebootCore()
        {
            // Regenerate mapper here to make sure its state is entirely clean
            switch (_game.GetOptionsDict()["m"])
            {
            case "2IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 2);
                break;

            case "4IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 4);
                break;

            case "8IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 8);
                break;

            case "16IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 16);
                break;

            case "32IN1":
                _mapper = SetMultiCartMapper(Rom.Length, 32);
                break;

            case "AR":
                _mapper = new mAR(this);                         // This mapper has to set up configurations in the contructor.
                break;

            case "4K":
                _mapper = new m4K();
                break;

            case "2K":
                _mapper = new m2K();
                break;

            case "CM":
                _mapper = new mCM();
                break;

            case "CV":
                _mapper = new mCV();
                break;

            case "DPC":
                _mapper = new mDPC();
                break;

            case "DPC+":
                _mapper = new mDPCPlus();
                break;

            case "F8":
                _mapper = new mF8();
                break;

            case "F8SC":
                _mapper = new mF8SC();
                break;

            case "F6":
                _mapper = new mF6();
                break;

            case "F6SC":
                _mapper = new mF6SC();
                break;

            case "F4":
                _mapper = new mF4();
                break;

            case "F4SC":
                _mapper = new mF4SC();
                break;

            case "FE":
                _mapper = new mFE();
                break;

            case "E0":
                _mapper = new mE0();
                break;

            case "3F":
                _mapper = new m3F();
                break;

            case "FA":
                _mapper = new mFA();
                break;

            case "FA2":
                _mapper = new mFA2();
                break;

            case "E7":
                _mapper = new mE7();
                break;

            case "F0":
                _mapper = new mF0();
                break;

            case "UA":
                _mapper = new mUA();
                break;

            // Special Sega Mapper which has swapped banks
            case "F8_sega":
                _mapper = new mF8_sega();
                break;

            // Homebrew mappers
            case "3E":
                _mapper = new m3E();
                break;

            case "0840":
                _mapper = new m0840();
                break;

            case "MC":
                _mapper = new mMC();
                break;

            case "EF":
                _mapper = new mEF();
                break;

            case "EFSC":
                _mapper = new mEFSC();
                break;

            case "X07":
                _mapper = new mX07();
                break;

            case "4A50":
                _mapper = new m4A50();
                break;

            case "SB":
                _mapper = new mSB();
                break;

            default:
                throw new InvalidOperationException("mapper not supported: " + _game.GetOptionsDict()["m"]);
            }

            _mapper.Core = this;

            _lagcount = 0;
            Cpu       = new MOS6502X
            {
                ReadMemory      = this.ReadMemory,
                WriteMemory     = this.WriteMemory,
                PeekMemory      = this.PeekMemory,
                DummyReadMemory = this.ReadMemory,
                OnExecFetch     = this.ExecFetch
            };

            if (_game["PAL"])
            {
                _pal = true;
            }
            else if (_game["NTSC"])
            {
                _pal = false;
            }
            else
            {
                _pal = DetectPal(_game, Rom);
            }

            // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
            _tia = new TIA(this, _pal, Settings.SECAMColors, CoreComm.VsyncRate > 55.0 ? 735 : 882);
            _tia.GetFrameRate(out CoreComm.VsyncNum, out CoreComm.VsyncDen);

            _dcfilter = new DCFilter(_tia, 256);

            M6532 = new M6532(this);

            // Set up the system state here. for instance..
            // Read from the reset vector for where to start
            Cpu.PC = (ushort)(ReadMemory(0x1FFC) + (ReadMemory(0x1FFD) << 8));             // set the initial PC

            // Show mapper class on romstatusdetails
            CoreComm.RomStatusDetails =
                string.Format(
                    "{0}\r\nSHA1:{1}\r\nMD5:{2}\r\nMapper Impl \"{3}\"",
                    this._game.Name,
                    Rom.HashSHA1(),
                    Rom.HashMD5(),
                    _mapper.GetType());


            // as it turns out, the stack pointer cannot be set to 0 for some games as they do not initilize it themselves.
            // some documentation seems to indicate it should beset to FD, but currently there is no documentation of the 6532
            // executing a reset sequence at power on, but it's needed so let's hard code it for now
            Cpu.S = 0xFD;
        }
Esempio n. 20
0
        public void HardReset()
        {
            cpu = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                BCD_Enabled = false
            };

            ppu   = new PPU(this);
            ram   = new byte[0x800];
            CIRAM = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition      = new ControllerDefinition(ControllerDeck.GetDefinition());
                ControllerDefinition.Name = "NES Controller";
                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (Board is FDS)
                {
                    var b = Board as FDS;
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }

                if (_isVS)
                {
                    ControllerDefinition.BoolButtons.Add("Insert Coin P1");
                    ControllerDefinition.BoolButtons.Add("Insert Coin P2");
                    ControllerDefinition.BoolButtons.Add("Service Switch");
                }
            }

            // Add in the reset timing float control for subneshawk
            if (using_reset_timing && (ControllerDefinition.FloatControls.Count() == 0))
            {
                ControllerDefinition.FloatControls.Add("Reset Cycle");
                ControllerDefinition.FloatRanges.Add(new ControllerDefinition.FloatRange(0, 0, 500000));
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case Common.DisplayType.PAL:
                apu           = new APU(this, apu, true);
                ppu.region    = PPU.Region.PAL;
                VsyncNum      = 50;
                VsyncDen      = 1;
                cpuclockrate  = 1662607;
                cpu_sequence  = cpu_sequence_PAL;
                _display_type = DisplayType.PAL;
                ClockRate     = 5320342.5;
                break;

            case Common.DisplayType.NTSC:
                apu          = new APU(this, apu, false);
                ppu.region   = PPU.Region.NTSC;
                VsyncNum     = 39375000;
                VsyncDen     = 655171;
                cpuclockrate = 1789773;
                cpu_sequence = cpu_sequence_NTSC;
                ClockRate    = 5369318.1818181818181818181818182;
                break;

            // this is in bootgod, but not used at all
            case Common.DisplayType.Dendy:
                apu           = new APU(this, apu, false);
                ppu.region    = PPU.Region.Dendy;
                VsyncNum      = 50;
                VsyncDen      = 1;
                cpuclockrate  = 1773448;
                cpu_sequence  = cpu_sequence_NTSC;
                _display_type = DisplayType.Dendy;
                ClockRate     = 5320342.5;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }

            blip.SetRates((uint)cpuclockrate, 44100);

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();

            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.

            if (cart.DB_GameInfo != null)
            {
                if (cart.DB_GameInfo.Hash == "60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558" ||              // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "BAD382331C30B22A908DA4BFF2759C25113CC26A" ||                     // Camerica Golden 5
                    cart.DB_GameInfo.Hash == "40409FEC8249EFDB772E6FFB2DCD41860C6CCA23"                        // Camerica Pegasus 4-in-1
                    )
                {
                    ram[0x701] = 0xFF;
                }

                if (cart.DB_GameInfo.Hash == "68ABE1E49C9E9CCEA978A48232432C252E5912C0")                 // Dancing Blocks
                {
                    ram[0xEC] = 0;
                    ram[0xED] = 0;
                }

                if (cart.DB_GameInfo.Hash == "00C50062A2DECE99580063777590F26A253AAB6B")                 // Silva Saga
                {
                    for (int i = 0; i < Board.WRAM.Length; i++)
                    {
                        Board.WRAM[i] = 0xFF;
                    }
                }
            }
        }
Esempio n. 21
0
        public void HardReset()
        {
            cpu = new MOS6502X();
            cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory);

            cpu.BCD_Enabled = false;
            cpu.OnExecFetch = ExecFetch;
            ppu             = new PPU(this);
            ram             = new byte[0x800];
            CIRAM           = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition      = new ControllerDefinition(ControllerDeck.GetDefinition());
                ControllerDefinition.Name = "NES Controller";
                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (board is FDS)
                {
                    var b = board as FDS;
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case Common.DisplayType.PAL:
                apu               = new APU(this, apu, true);
                ppu.region        = PPU.Region.PAL;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1662607;
                cpu_sequence      = cpu_sequence_PAL;
                _display_type     = DisplayType.PAL;
                break;

            case Common.DisplayType.NTSC:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.NTSC;
                CoreComm.VsyncNum = 39375000;
                CoreComm.VsyncDen = 655171;
                cpuclockrate      = 1789773;
                cpu_sequence      = cpu_sequence_NTSC;
                break;

            // this is in bootgod, but not used at all
            case Common.DisplayType.DENDY:
                apu               = new APU(this, apu, false);
                ppu.region        = PPU.Region.Dendy;
                CoreComm.VsyncNum = 50;
                CoreComm.VsyncDen = 1;
                cpuclockrate      = 1773448;
                cpu_sequence      = cpu_sequence_NTSC;
                _display_type     = DisplayType.DENDY;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }
            if (magicSoundProvider == null)
            {
                magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate);
            }

            BoardSystemHardReset();

            //check fceux's PowerNES and FCEU_MemoryRand function for more information:
            //relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
            for (int i = 0; i < 0x800; i++)
            {
                if ((i & 4) != 0)
                {
                    ram[i] = 0xFF;
                }
                else
                {
                    ram[i] = 0x00;
                }
            }

            SetupMemoryDomains();

            //in this emulator, reset takes place instantaneously
            cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8));
            cpu.P  = 0x34;
            cpu.S  = 0xFD;
        }
Esempio n. 22
0
        public VIC1541Motherboard(Region initRegion, byte[] initRom)
        {
            cpu     = new MOS6502X();
            pla     = new VIC1541PLA();
            ram     = new byte[0x800];
            rom     = initRom;
            serPort = new SerialPort();
            via0    = new MOS6522();
            via1    = new MOS6522();

            cpu.DummyReadMemory = pla.Read;
            cpu.ReadMemory      = pla.Read;
            cpu.WriteMemory     = pla.Write;

            pla.PeekRam   = ((int addr) => { return(ram[addr & 0x07FF]); });
            pla.PeekRom   = ((int addr) => { return(rom[addr & 0x3FFF]); });
            pla.PeekVia0  = via0.Peek;
            pla.PeekVia1  = via1.Peek;
            pla.PokeRam   = ((int addr, byte val) => { ram[addr & 0x07FF] = val; });
            pla.PokeRom   = ((int addr, byte val) => { });
            pla.PokeVia0  = via0.Poke;
            pla.PokeVia1  = via1.Poke;
            pla.ReadRam   = ((ushort addr) => { return(ram[addr & 0x07FF]); });
            pla.ReadRom   = ((ushort addr) => { return(rom[addr & 0x3FFF]); });
            pla.ReadVia0  = via0.Read;
            pla.ReadVia1  = via1.Read;
            pla.WriteRam  = ((ushort addr, byte val) => { ram[addr & 0x07FF] = val; });
            pla.WriteRom  = ((ushort addr, byte val) => { });
            pla.WriteVia0 = via0.Write;
            pla.WriteVia1 = via1.Write;

            via0CA0   = false;
            via0CA1   = false;
            via0CB0   = false;
            via0CB1   = false;
            via0DirA  = 0x00;
            via0DirB  = 0x00;
            via0DataA = 0xFF;
            via0DataB = 0xFF;
            via1CA0   = false;
            via1CA1   = false;
            via1CB0   = false;
            via1CB1   = false;
            via1DirA  = 0x00;
            via1DirB  = 0x00;
            via1DataA = 0xFF;
            via1DataB = 0xFF;

            via0.ReadCA0    = (() => { return(via0CA0); });
            via0.ReadCA1    = (() => { return(via0CA1); });
            via0.ReadCB0    = (() => { return(via0CB0); });
            via0.ReadCB1    = (() => { return(via0CB1); });
            via0.ReadDirA   = (() => { return(via0DirA); });
            via0.ReadDirB   = (() => { return(via0DirB); });
            via0.ReadPortA  = (() => { return(via0DataA); });
            via0.ReadPortB  = (() => { return(via0DataB); });
            via0.WriteCA0   = ((bool val) => { via0CA0 = val; });
            via0.WriteCA1   = ((bool val) => { via0CA1 = val; });
            via0.WriteCB0   = ((bool val) => { via0CB0 = val; });
            via0.WriteCB1   = ((bool val) => { via0CB1 = val; });
            via0.WriteDirA  = ((byte val) => { via0DirA = val; });
            via0.WriteDirB  = ((byte val) => { via0DirB = val; });
            via0.WritePortA = ((byte val) => {
                via0DataA = Port.CPUWrite(via0DataA, val, via0DirA);
            });
            via0.WritePortB = ((byte val) => {
                via0DataB = Port.CPUWrite(via0DataB, val, via0DirB);
                serPort.DeviceWriteAtn((via0DataB & 0x80) != 0);
                serPort.DeviceWriteClock((via0DataB & 0x08) != 0);
                serPort.DeviceWriteData((via0DataB & 0x02) != 0);
            });

            via1.ReadCA0    = (() => { return(via1CA0); });
            via1.ReadCA1    = (() => { return(via1CA1); });
            via1.ReadCB0    = (() => { return(via1CB0); });
            via1.ReadCB1    = (() => { return(via1CB1); });
            via1.ReadDirA   = (() => { return(via1DirA); });
            via1.ReadDirB   = (() => { return(via1DirB); });
            via1.ReadPortA  = (() => { return(via1DataA); });
            via1.ReadPortB  = (() => { return(via1DataB); });
            via1.WriteCA0   = ((bool val) => { via1CA0 = val; });
            via1.WriteCA1   = ((bool val) => { via1CA1 = val; });
            via1.WriteCB0   = ((bool val) => { via1CB0 = val; });
            via1.WriteCB1   = ((bool val) => { via1CB1 = val; });
            via1.WriteDirA  = ((byte val) => { via1DirA = val; });
            via1.WriteDirB  = ((byte val) => { via1DirB = val; });
            via1.WritePortA = ((byte val) => {
                via1DataA = Port.CPUWrite(via1DataA, val, via1DirA);
            });
            via1.WritePortB = ((byte val) => {
                via1DataB = Port.CPUWrite(via1DataB, val, via1DirB);
            });
        }
Esempio n. 23
0
        public void HardReset()
        {
            cpu = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                BCD_Enabled = false
            };

            ppu   = new PPU(this);
            ram   = new byte[0x800];
            CIRAM = new byte[0x800];

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case DisplayType.PAL:
                apu           = new APU(this, apu, true);
                ppu.region    = PPU.Region.PAL;
                cpuclockrate  = 1662607;
                VsyncNum      = cpuclockrate * 2;
                VsyncDen      = 66495;
                cpu_sequence  = cpu_sequence_PAL;
                _display_type = DisplayType.PAL;
                ClockRate     = 5320342.5;
                break;

            case DisplayType.NTSC:
                apu          = new APU(this, apu, false);
                ppu.region   = PPU.Region.NTSC;
                cpuclockrate = 1789773;
                VsyncNum     = cpuclockrate * 2;
                VsyncDen     = 59561;
                cpu_sequence = cpu_sequence_NTSC;
                ClockRate    = 5369318.1818181818181818181818182;
                break;

            // this is in bootgod, but not used at all
            case DisplayType.Dendy:
                apu           = new APU(this, apu, false);
                ppu.region    = PPU.Region.Dendy;
                cpuclockrate  = 1773448;
                VsyncNum      = cpuclockrate;
                VsyncDen      = 35464;
                cpu_sequence  = cpu_sequence_NTSC;
                _display_type = DisplayType.Dendy;
                ClockRate     = 5320342.5;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }

            blip.SetRates((uint)cpuclockrate, 44100);

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();

            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.
            var hash = cart.GameInfo?.Hash;             // SHA1 or MD5 (see NES.IdentifyFromGameDB)

            if (hash is null)
            {
                // short-circuit
            }
            else if (hash is RomChecksums.CamericaGolden5 or RomChecksums.CamericaGolden5Overdump or RomChecksums.CamericaPegasus4in1)
            {
                ram[0x701] = 0xFF;
            }
 public string Disassemble(MemoryDomain m, uint addr, out int length)
 {
     return(MOS6502X.Disassemble((ushort)addr, out length, a => unchecked ((byte)Peek(a))));
 }
        public void HardReset()
        {
            cpu = new MOS6502X <CpuLink>(new CpuLink(this))
            {
                BCD_Enabled = false
            };

            ppu   = new PPU(this);
            ram   = new byte[0x800];
            CIRAM = new byte[0x800];

            // wire controllers
            // todo: allow changing this
            ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback);
            // set controller definition first time only
            if (ControllerDefinition == null)
            {
                ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition())
                {
                    Name = "NES Controller"
                };

                // controls other than the deck
                ControllerDefinition.BoolButtons.Add("Power");
                ControllerDefinition.BoolButtons.Add("Reset");
                if (Board is FDS b)
                {
                    ControllerDefinition.BoolButtons.Add("FDS Eject");
                    for (int i = 0; i < b.NumSides; i++)
                    {
                        ControllerDefinition.BoolButtons.Add("FDS Insert " + i);
                    }
                }

                if (_isVS)
                {
                    ControllerDefinition.BoolButtons.Add("Insert Coin P1");
                    ControllerDefinition.BoolButtons.Add("Insert Coin P2");
                    ControllerDefinition.BoolButtons.Add("Service Switch");
                }
            }

            // Add in the reset timing axis for subneshawk
            if (using_reset_timing && ControllerDefinition.Axes.Count == 0)
            {
                ControllerDefinition.AddAxis("Reset Cycle", 0.RangeTo(500000), 0);
            }

            // don't replace the magicSoundProvider on reset, as it's not needed
            // if (magicSoundProvider != null) magicSoundProvider.Dispose();

            // set up region
            switch (_display_type)
            {
            case DisplayType.PAL:
                apu           = new APU(this, apu, true);
                ppu.region    = PPU.Region.PAL;
                cpuclockrate  = 1662607;
                VsyncNum      = cpuclockrate * 2;
                VsyncDen      = 66495;
                cpu_sequence  = cpu_sequence_PAL;
                _display_type = DisplayType.PAL;
                ClockRate     = 5320342.5;
                break;

            case DisplayType.NTSC:
                apu          = new APU(this, apu, false);
                ppu.region   = PPU.Region.NTSC;
                cpuclockrate = 1789773;
                VsyncNum     = cpuclockrate * 2;
                VsyncDen     = 59561;
                cpu_sequence = cpu_sequence_NTSC;
                ClockRate    = 5369318.1818181818181818181818182;
                break;

            // this is in bootgod, but not used at all
            case DisplayType.Dendy:
                apu           = new APU(this, apu, false);
                ppu.region    = PPU.Region.Dendy;
                cpuclockrate  = 1773448;
                VsyncNum      = cpuclockrate;
                VsyncDen      = 35464;
                cpu_sequence  = cpu_sequence_NTSC;
                _display_type = DisplayType.Dendy;
                ClockRate     = 5320342.5;
                break;

            default:
                throw new Exception("Unknown displaytype!");
            }

            blip.SetRates((uint)cpuclockrate, 44100);

            BoardSystemHardReset();

            // apu has some specific power up bahaviour that we will emulate here
            apu.NESHardReset();

            if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any())
            {
                for (int i = 0; i < 0x800; i++)
                {
                    ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count];
                }
            }
            else
            {
                // check fceux's PowerNES and FCEU_MemoryRand function for more information:
                // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
                for (int i = 0; i < 0x800; i++)
                {
                    if ((i & 4) != 0)
                    {
                        ram[i] = 0xFF;
                    }
                    else
                    {
                        ram[i] = 0x00;
                    }
                }
            }

            SetupMemoryDomains();

            // some boards cannot have specific values in RAM upon initialization
            // Let's hard code those cases here
            // these will be defined through the gameDB exclusively for now.

            if (cart.GameInfo != null)
            {
                if (cart.GameInfo.Hash is RomChecksums.CamericaGolden5 or RomChecksums.CamericaGolden5Overdump or RomChecksums.CamericaPegasus4in1)
                {
                    ram[0x701] = 0xFF;
                }
                else if (cart.GameInfo.Hash == RomChecksums.DancingBlocks)
                {
                    ram[0xEC] = 0;
                    ram[0xED] = 0;
                }
                else if (cart.GameInfo.Hash == RomChecksums.SilvaSaga)
                {
                    for (int i = 0; i < Board.Wram.Length; i++)
                    {
                        Board.Wram[i] = 0xFF;
                    }
                }
            }
 public string Disassemble(MemoryDomain m, uint addr, out int length)
 {
     return(MOS6502X.Disassemble((ushort)addr, out length, CpuPeek));
 }
Esempio n. 27
0
        public A7800Hawk(CoreComm comm, GameInfo game, byte[] rom, string gameDbFn)
        {
            var ser = new BasicServiceProvider(this);

            maria = new Maria();
            tia   = new TIA();
            m6532 = new M6532();

            cpu = new MOS6502X
            {
                ReadMemory      = ReadMemory,
                WriteMemory     = WriteMemory,
                PeekMemory      = ReadMemory,
                DummyReadMemory = ReadMemory,
                OnExecFetch     = ExecFetch
            };

            maria = new Maria
            {
                ReadMemory = ReadMemory
            };

            CoreComm = comm;

            _controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2);

            byte[] highscoreBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS.");
            byte[] palBios       = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available.");
            byte[] ntscBios      = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available.");

            if (rom.Length % 1024 == 128)
            {
                Console.WriteLine("Trimming 128 byte .a78 header...");
                byte[] newrom = new byte[rom.Length - 128];
                Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length);
                rom = newrom;
            }

            _isPAL = false;

            // look up hash in gamedb to see what mapper to use
            // if none found default is zero
            // also check for PAL region
            string hash_md5 = null;

            s_mapper = null;
            hash_md5 = "md5:" + rom.HashMD5(0, rom.Length);

            var gi = Database.CheckDatabase(hash_md5);

            if (gi != null)
            {
                var dict = gi.GetOptionsDict();
                if (dict.ContainsKey("PAL"))
                {
                    _isPAL = true;
                }
                if (dict.ContainsKey("board"))
                {
                    s_mapper = dict["board"];
                }
                else
                {
                    throw new Exception("No Board selected for this game");
                }
            }
            else
            {
                throw new Exception("ROM not in gamedb");
            }

            Reset_Mapper(s_mapper);

            _rom    = rom;
            _hsbios = highscoreBios;
            _bios   = _isPAL ? palBios : ntscBios;

            if (_bios == null)
            {
                throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games.");
            }

            // set up palette and frame rate
            if (_isPAL)
            {
                maria._frameHz       = 50;
                maria._screen_width  = 320;
                maria._screen_height = 313;
                maria._palette       = PALPalette;
            }
            else
            {
                maria._frameHz       = 60;
                maria._screen_width  = 320;
                maria._screen_height = 263;
                maria._palette       = NTSCPalette;
            }

            maria.Core = this;
            m6532.Core = this;
            tia.Core   = this;

            ser.Register <IVideoProvider>(maria);
            ser.Register <ISoundProvider>(tia);
            ServiceProvider = ser;

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

            SetupMemoryDomains();
            HardReset();
        }
Esempio n. 28
0
        public A7800Hawk(CoreComm comm, GameInfo game, byte[] rom, string gameDbFn, object settings, object syncSettings)
        {
            var ser = new BasicServiceProvider(this);

            maria = new Maria();
            tia   = new TIA();
            m6532 = new M6532();
            pokey = new Pokey();

            cpu = new MOS6502X <CpuLink>(new CpuLink(this));

            maria = new Maria
            {
                ReadMemory = ReadMemory
            };

            CoreComm = comm;

            _blip.SetRates(1789773, 44100);

            _settings       = (A7800Settings)settings ?? new A7800Settings();
            _syncSettings   = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings();
            _controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2);

            byte[] highscoreBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS.");
            byte[] palBios       = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available.");
            byte[] ntscBios      = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available.");

            byte[] header    = new byte[128];
            bool   is_header = false;

            if (rom.Length % 1024 == 128)
            {
                Console.WriteLine("128 byte header detected");
                byte[] newrom = new byte[rom.Length - 128];
                is_header = true;
                Buffer.BlockCopy(rom, 0, header, 0, 128);
                Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length);
                rom = newrom;
            }

            _isPAL = false;

            // look up hash in gamedb to see what mapper to use
            // if none found default is zero
            // also check for PAL region
            string hash_md5 = null;

            s_mapper = null;
            hash_md5 = "md5:" + rom.HashMD5(0, rom.Length);

            var gi = Database.CheckDatabase(hash_md5);

            if (gi != null)
            {
                var dict = gi.GetOptionsDict();
                if (dict.ContainsKey("PAL"))
                {
                    _isPAL = true;
                }
                if (dict.ContainsKey("board"))
                {
                    s_mapper = dict["board"];
                }
                else
                {
                    throw new Exception("No Board selected for this game");
                }

                // check if the game uses pokey or RAM
                if (dict.ContainsKey("RAM"))
                {
                    int.TryParse(dict["RAM"], out cart_RAM);
                    Console.WriteLine(cart_RAM);
                }

                if (dict.ContainsKey("Pokey"))
                {
                    bool.TryParse(dict["Pokey"], out is_pokey);
                }

                // some games will not function with the high score bios
                // if such a game is being played, tell the user and disable it
                if (dict.ContainsKey("No_HS"))
                {
                    bool no_hs;
                    bool.TryParse(dict["No_HS"], out no_hs);

                    if (no_hs)
                    {
                        Console.WriteLine("This game is incompatible with the High Score BIOS, disabling it");
                        highscoreBios = null;
                    }
                }
            }
            else if (is_header)
            {
                Console.WriteLine("ROM not in DB, inferring mapper info from header");

                byte cart_1 = header[0x35];
                byte cart_2 = header[0x36];

                _isPAL = (header[0x39] > 0);

                if (cart_2.Bit(1))
                {
                    if (cart_2.Bit(3))
                    {
                        s_mapper = "2";
                    }
                    else
                    {
                        s_mapper = "1";
                    }

                    if (cart_2.Bit(2))
                    {
                        cart_RAM = 8;
                    }
                }
                else
                {
                    s_mapper = "0";
                }

                if (cart_2.Bit(0))
                {
                    is_pokey = true;
                }
            }
            else
            {
                throw new Exception("ROM not in gamedb and has no header");
            }

            // some games that use the Super Game mapper only have 4 banks, so let's set a flag to limit bank size
            if (rom.Length < 0x14000)
            {
                small_flag = true;

                // additionally, PAL Karateka  has bank 6 (actually 2) at 0x4000
                if (rom.HashMD5() == "5E0A1E832BBCEA6FACB832FDE23A440A")
                {
                    PAL_Kara = true;
                }
            }

            _rom = rom;

            Reset_Mapper(s_mapper);

            _hsbios = highscoreBios;
            _bios   = _isPAL ? palBios : ntscBios;

            if (_bios == null)
            {
                throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games.");
            }

            // set up palette and frame rate
            if (_isPAL)
            {
                _frameHz       = 50;
                _screen_width  = 320;
                _screen_height = 313;
                _vblanklines   = 20;
                maria._palette = PALPalette;
            }
            else
            {
                _frameHz       = 60;
                _screen_width  = 320;
                _screen_height = 263;
                _vblanklines   = 20;
                maria._palette = NTSCPalette;
            }

            maria.Core = this;
            m6532.Core = this;
            tia.Core   = this;
            pokey.Core = this;

            ser.Register <IVideoProvider>(this);
            ser.Register <ISoundProvider>(this);
            ServiceProvider = ser;

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

            SetupMemoryDomains();
            ser.Register <IDisassemblable>(cpu);
            HardReset();
        }
 public string Disassemble(MemoryDomain m, uint addr, out int length)
 {
     return(MOS6502X.Disassemble((ushort)addr, out length, (a) => m.PeekByte(a)));
 }