Ejemplo n.º 1
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();
        }
Ejemplo n.º 2
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();
        }