Exemple #1
0
		unsafe static void DrawNameTable(LibGPGX.VDPNameTable NT, ushort* vram, byte* tiles, int* pal, BmpView bv)
		{
			ushort* nametable = vram + NT.Baseaddr / 2;
			int tilew = NT.Width;
			int tileh = NT.Height;

			Size pixsize = new Size(tilew * 8, tileh * 8);
			bv.Size = pixsize;
			bv.ChangeBitmapSize(pixsize);

			var lockdata = bv.bmp.LockBits(new Rectangle(Point.Empty, pixsize), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
			int pitch = lockdata.Stride / sizeof(int);
			int* dest = (int*)lockdata.Scan0;

			for (int tiley = 0; tiley < tileh; tiley++)
			{
				for (int tilex = 0; tilex < tilew; tilex++)
				{
					ushort bgent = *nametable++;
					int palidx = bgent >> 9 & 0x30;
					int tileent = bgent & 0x1fff; // h and v flip are stored separately in cache
					DrawTile(dest, pitch, tiles + tileent * 64, pal + palidx);
					dest += 8;
				}
				dest -= 8 * tilew;
				dest += 8 * pitch;
			}
			bv.bmp.UnlockBits(lockdata);
			bv.Refresh();
		}
Exemple #2
0
        public void SaveStateBinary(System.IO.BinaryWriter writer)
        {
            if (!LibGPGX.gpgx_state_save(savebuff, savebuff.Length))
            {
                throw new Exception("gpgx_state_save() returned false");
            }

            writer.Write(savebuff.Length);
            writer.Write(savebuff);
            // other variables
            writer.Write(Frame);
            writer.Write(LagCount);
            writer.Write(IsLagFrame);
        }
Exemple #3
0
        unsafe void update_video()
        {
            int    gppitch, gpwidth, gpheight;
            IntPtr src = IntPtr.Zero;

            LibGPGX.gpgx_get_video(out gpwidth, out gpheight, out gppitch, ref src);

            vwidth  = gpwidth;
            vheight = gpheight;

            if (_Settings.PadScreen320 && vwidth == 256)
            {
                vwidth = 320;
            }

            int xpad  = (vwidth - gpwidth) / 2;
            int xpad2 = vwidth - gpwidth - xpad;

            if (vidbuff.Length < vwidth * vheight)
            {
                vidbuff = new int[vwidth * vheight];
            }

            int rinc = (gppitch / 4) - gpwidth;

            fixed(int *pdst_ = &vidbuff[0])
            {
                int *pdst = pdst_;
                int *psrc = (int *)src;

                for (int j = 0; j < gpheight; j++)
                {
                    for (int i = 0; i < xpad; i++)
                    {
                        *pdst++ = unchecked ((int)0xff000000);
                    }
                    for (int i = 0; i < gpwidth; i++)
                    {
                        *pdst++ = *psrc++;                        // | unchecked((int)0xff000000);
                    }
                    for (int i = 0; i < xpad2; i++)
                    {
                        *pdst++ = unchecked ((int)0xff000000);
                    }
                    psrc += rinc;
                }
            }
        }
Exemple #4
0
        unsafe void SetMemoryDomains()
        {
            var mm = new List <MemoryDomain>();

            for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++)
            {
                IntPtr area  = IntPtr.Zero;
                int    size  = 0;
                IntPtr pname = LibGPGX.gpgx_get_memdom(i, ref area, ref size);
                if (area == IntPtr.Zero || pname == IntPtr.Zero || size == 0)
                {
                    continue;
                }
                string name = Marshal.PtrToStringAnsi(pname);
                if (name == "VRAM")
                {
                    // vram pokes need to go through hook which invalidates cached tiles
                    byte *p = (byte *)area;
                    mm.Add(new MemoryDomain(name, size, MemoryDomain.Endian.Unknown,
                                            delegate(long addr)
                    {
                        if (addr < 0 || addr >= 65536)
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        return(p[addr ^ 1]);
                    },
                                            delegate(long addr, byte val)
                    {
                        if (addr < 0 || addr >= 65536)
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        LibGPGX.gpgx_poke_vram(((int)addr) ^ 1, val);
                    },
                                            byteSize: 2));
                }

                else
                {
                    var byteSize = name.Contains("Z80") ? 1 : 2;
                    mm.Add(MemoryDomain.FromIntPtrSwap16(name, size, MemoryDomain.Endian.Big, area, writable: true, byteSize: byteSize));
                }
            }
            MemoryDomains = new MemoryDomainList(mm);
            (ServiceProvider as BasicServiceProvider).Register <IMemoryDomains>(MemoryDomains);
        }
		private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags)
		{
			//TODO - hard reset makes CDL go nuts.

			if (CDL == null) return;
			if (!CDL.Active) return;
			string key;
			switch (addrtype)
			{
				case LibGPGX.CDLog_AddrType.MDCART: key = "MD CART"; break;
				case LibGPGX.CDLog_AddrType.RAM68k: key = "68K RAM"; break;
				case LibGPGX.CDLog_AddrType.RAMZ80: key = "Z80 RAM"; break;
				case LibGPGX.CDLog_AddrType.SRAM: key = "SRAM"; break;
				default: throw new InvalidOperationException("Lagrangian earwax incident");
			}
			CDL[key][addr] |= (byte)flags;
		}
Exemple #6
0
        // TODO: use render and rendersound
        public void FrameAdvance(bool render, bool rendersound = true)
        {
            if (Controller["Reset"])
            {
                LibGPGX.gpgx_reset(false);
            }
            if (Controller["Power"])
            {
                LibGPGX.gpgx_reset(true);
            }

            // do we really have to get each time?  nothing has changed
            if (!LibGPGX.gpgx_get_control(input, inputsize))
            {
                throw new Exception("gpgx_get_control() failed!");
            }

            ControlConverter.ScreenWidth  = vwidth;
            ControlConverter.ScreenHeight = vheight;
            ControlConverter.Convert(Controller, input);

            if (!LibGPGX.gpgx_put_control(input, inputsize))
            {
                throw new Exception("gpgx_put_control() failed!");
            }

            IsLagFrame = true;
            Frame++;
            drivelight = false;

            RefreshMemCallbacks();

            LibGPGX.gpgx_advance();
            update_video();
            update_audio();

            if (IsLagFrame)
            {
                LagCount++;
            }

            if (CD != null)
            {
                CoreComm.DriveLED = drivelight;
            }
        }
Exemple #7
0
        public Dictionary <string, int> GetCpuFlagsAndRegisters()
        {
            LibGPGX.RegisterInfo[] regs = new LibGPGX.RegisterInfo[LibGPGX.gpgx_getmaxnumregs()];

            int n = LibGPGX.gpgx_getregs(regs);

            if (n > regs.Length)
            {
                throw new InvalidOperationException("A buffer overrun has occured!");
            }
            var ret = new Dictionary <string, int>();

            for (int i = 0; i < n; i++)
            {
                ret[Marshal.PtrToStringAnsi(regs[i].Name)] = regs[i].Value;
            }
            return(ret);
        }
Exemple #8
0
        public void LoadStateBinary(System.IO.BinaryReader reader)
        {
            int newlen = reader.ReadInt32();

            if (newlen != savebuff.Length)
            {
                throw new Exception("Unexpected state size");
            }
            reader.Read(savebuff, 0, savebuff.Length);
            if (!LibGPGX.gpgx_state_load(savebuff, savebuff.Length))
            {
                throw new Exception("gpgx_state_load() returned false");
            }
            // other variables
            Frame      = reader.ReadInt32();
            LagCount   = reader.ReadInt32();
            IsLagFrame = reader.ReadBoolean();
            update_video();
        }
Exemple #9
0
        public byte[] ReadSaveRam()
        {
            if (disposed)
            {
                return(DisposedSaveRam ?? new byte[0]);
            }
            else
            {
                int    size = 0;
                IntPtr area = IntPtr.Zero;
                LibGPGX.gpgx_get_sram(ref area, ref size);
                if (size <= 0 || area == IntPtr.Zero)
                {
                    return(new byte[0]);
                }
                LibGPGX.gpgx_sram_prepread();

                byte[] ret = new byte[size];
                Marshal.Copy(area, ret, 0, size);
                return(ret);
            }
        }
Exemple #10
0
        unsafe void SetMemoryDomains()
        {
            var mm = new List <MemoryDomain>();

            for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++)
            {
                IntPtr area  = IntPtr.Zero;
                int    size  = 0;
                IntPtr pname = LibGPGX.gpgx_get_memdom(i, ref area, ref size);
                if (area == IntPtr.Zero || pname == IntPtr.Zero || size == 0)
                {
                    continue;
                }
                string name = Marshal.PtrToStringAnsi(pname);
                byte * p    = (byte *)area;

                mm.Add(new MemoryDomain(name, size, MemoryDomain.Endian.Unknown,
                                        delegate(int addr)
                {
                    if (addr < 0 || addr >= size)
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                    return(p[addr]);
                },
                                        delegate(int addr, byte val)
                {
                    if (addr < 0 || addr >= size)
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                    p[addr] = val;
                }));
            }

            MemoryDomains = new MemoryDomainList(mm, 0);
        }
        public void StoreSaveRam(byte[] data)
        {
            if (disposed)
            {
                throw new ObjectDisposedException(typeof(GPGX).ToString());
            }
            else
            {
                int    size = 0;
                IntPtr area = IntPtr.Zero;
                LibGPGX.gpgx_get_sram(ref area, ref size);
                if (size <= 0 || area == IntPtr.Zero)
                {
                    return;
                }
                if (size != data.Length)
                {
                    throw new Exception("Unexpected saveram size");
                }

                Marshal.Copy(data, 0, area, size);
                LibGPGX.gpgx_sram_commitwrite();
            }
        }
Exemple #12
0
 public bool PutSettings(GPGXSettings o)
 {
     _Settings = o;
     LibGPGX.gpgx_set_draw_mask(_Settings.GetDrawMask());
     return(false);
 }
        private unsafe void UpdateVideo()
        {
            int    gppitch, gpwidth, gpheight;
            IntPtr src = IntPtr.Zero;

            LibGPGX.gpgx_get_video(out gpwidth, out gpheight, out gppitch, ref src);

            //in case we're receiving high vertical resolution video, we shall double the horizontal resolution to keep the same proportions
            //(concept pioneered for snes)

            bool dotDouble  = (gpheight == 448);            //todo: pal?
            bool lineDouble = false;

            vwidth  = gpwidth;
            vheight = gpheight;

            if (_settings.AlwaysDoubleSize)
            {
                dotDouble = true;
                if (gpheight == 224 || gpheight == 240)
                {
                    lineDouble = true;
                    vheight   *= 2;
                }
            }

            if (_settings.PadScreen320 && vwidth == 256)
            {
                vwidth = 320;
            }

            int xpad  = (vwidth - gpwidth) / 2;
            int xpad2 = vwidth - gpwidth - xpad;

            if (dotDouble)
            {
                vwidth *= 2;
            }

            if (vidbuff.Length < vwidth * vheight)
            {
                vidbuff = new int[vwidth * vheight];
            }

            int xskip = 1;

            if (dotDouble)
            {
                xskip = 2;
            }

            int lines = lineDouble ? 2: 1;

            for (int D = 0; D < xskip; D++)
            {
                int rinc = (gppitch / 4) - gpwidth;
                fixed(int *pdst_ = &vidbuff[0])
                {
                    int *pdst = pdst_ + D;
                    int *psrc = (int *)src;

                    for (int j = 0; j < gpheight; j++)
                    {
                        int *ppsrc = psrc;
                        for (int L = 0; L < lines; L++)
                        {
                            int *pppsrc = ppsrc;
                            for (int i = 0; i < xpad; i++)
                            {
                                *pdst = unchecked ((int)0xff000000);
                                pdst += xskip;
                            }
                            for (int i = 0; i < gpwidth; i++)
                            {
                                *pdst = *pppsrc++;                                // | unchecked((int)0xff000000);
                                pdst += xskip;
                            }
                            for (int i = 0; i < xpad2; i++)
                            {
                                *pdst = unchecked ((int)0xff000000);
                                pdst += xskip;
                            }
                            psrc = pppsrc;
                        }
                        psrc += rinc;
                    }
                }
            }
        }
Exemple #14
0
		public void UpdateVDPViewContext(LibGPGX.VDPView view)
		{
			LibGPGX.gpgx_get_vdp_view(view);
		}
		public void Convert(IController source, LibGPGX.InputData target)
		{
			this.source = source;
			this.target = target;
			target.ClearAllBools();
			foreach (var f in Converts)
				f();
			this.source = null;
			this.target = null;
		}
			public CName(string Name, LibGPGX.INPUT_KEYS Key)
			{
				this.Name = Name;
				this.Key = Key;
			}
		public GPGXControlConverter(LibGPGX.InputData input)
		{
			Console.WriteLine("Genesis Controller report:");
			foreach (var e in input.system)
				Console.WriteLine("S:{0}", e);
			foreach (var e in input.dev)
				Console.WriteLine("D:{0}", e);

			int player = 1;

			ControllerDef = new ControllerDefinition();

			ControllerDef.BoolButtons.Add("Power");
			ControllerDef.BoolButtons.Add("Reset");

			for (int i = 0; i < LibGPGX.MAX_DEVICES; i++)
			{
				switch (input.dev[i])
				{
					case LibGPGX.INPUT_DEVICE.DEVICE_PAD3B:
						AddToController(i, player, Genesis3);
						player++;
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_PAD6B:
						AddToController(i, player, Genesis6);
						player++;
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_MOUSE:
						AddToController(i, player, Mouse);
						DoMouseAnalog(i, player);
						player++;
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_NONE:
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_LIGHTGUN:
						// supports menacers and justifiers
						AddToController(i, player, Lightgun);
						DoLightgunAnalog(i, player);
						player++;
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_PAD2B:
					case LibGPGX.INPUT_DEVICE.DEVICE_PADDLE:
					case LibGPGX.INPUT_DEVICE.DEVICE_SPORTSPAD:
					case LibGPGX.INPUT_DEVICE.DEVICE_TEREBI:
						throw new Exception("Master System only device?  Something went wrong.");
					case LibGPGX.INPUT_DEVICE.DEVICE_ACTIVATOR:
						AddToController(i, player, Activator);
						player++;
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_XE_A1P:
						AddToController(i, player, XEA1P);
						DoXEA1PAnalog(i, player);
						player++;
						break;
					case LibGPGX.INPUT_DEVICE.DEVICE_PICO:
						// PICO isn't finished on the unmanaged side either
						throw new Exception("Sega PICO not implemented yet!");
					default:
						throw new Exception("Unknown Genesis control device!  Something went wrong.");
				}
			}

			ControllerDef.Name = "GPGX Genesis Controller";
		}
Exemple #18
0
        private unsafe void SetMemoryDomains()
        {
            var mm = new List <MemoryDomain>();

            for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++)
            {
                IntPtr area  = IntPtr.Zero;
                int    size  = 0;
                IntPtr pname = LibGPGX.gpgx_get_memdom(i, ref area, ref size);
                if (area == IntPtr.Zero || pname == IntPtr.Zero || size == 0)
                {
                    continue;
                }
                string name = Marshal.PtrToStringAnsi(pname);
                if (name == "VRAM")
                {
                    // vram pokes need to go through hook which invalidates cached tiles
                    byte *p = (byte *)area;
                    mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Unknown,
                                                    delegate(long addr)
                    {
                        if (addr < 0 || addr >= 65536)
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        return(p[addr ^ 1]);
                    },
                                                    delegate(long addr, byte val)
                    {
                        if (addr < 0 || addr >= 65536)
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        LibGPGX.gpgx_poke_vram(((int)addr) ^ 1, val);
                    },
                                                    wordSize: 2));
                }

                else
                {
                    // TODO: are the Z80 domains really Swap16 in the core?  Check this
                    //var byteSize = name.Contains("Z80") ? 1 : 2;
                    mm.Add(MemoryDomain.FromIntPtrSwap16(name, size,
                                                         MemoryDomain.Endian.Big, area, name != "MD CART" && name != "CD BOOT ROM"));
                }
            }
            var m68Bus = new MemoryDomainDelegate("M68K BUS", 0x1000000, MemoryDomain.Endian.Big,
                                                  delegate(long addr)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                return(LibGPGX.gpgx_peek_m68k_bus(a));
            },
                                                  delegate(long addr, byte val)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                LibGPGX.gpgx_write_m68k_bus(a, val);
            }, 2);

            mm.Add(m68Bus);

            var s68Bus = new MemoryDomainDelegate("S68K BUS", 0x1000000, MemoryDomain.Endian.Big,
                                                  delegate(long addr)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                return(LibGPGX.gpgx_peek_s68k_bus(a));
            },
                                                  delegate(long addr, byte val)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                LibGPGX.gpgx_write_s68k_bus(a, val);
            }, 2);

            if (IsSegaCD)
            {
                mm.Add(s68Bus);
            }

            MemoryDomains           = new MemoryDomainList(mm);
            MemoryDomains.SystemBus = m68Bus;

            (ServiceProvider as BasicServiceProvider).Register <IMemoryDomains>(MemoryDomains);
        }
Exemple #19
0
        public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object settings, object syncSettings)
        {
            ServiceProvider = new BasicServiceProvider(this);
            // this can influence some things internally
            string romextension = "GEN";

            // three or six button?
            // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds

            //hack, don't use
            if (rom != null && rom.Length > 32 * 1024 * 1024)
            {
                throw new InvalidOperationException("ROM too big!  Did you try to load a CD as a ROM?");
            }

            try
            {
                _syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings();
                _settings     = (GPGXSettings)settings ?? new GPGXSettings();

                CoreComm = comm;
                if (AttachedCore != null)
                {
                    AttachedCore.Dispose();
                    AttachedCore = null;
                }
                AttachedCore = this;

                LoadCallback = new LibGPGX.load_archive_cb(load_archive);

                this.romfile          = rom;
                this.CD               = CD;
                this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD);

                LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
                LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;

                switch (_syncSettings.ControlType)
                {
                case ControlType.None:
                default:
                    break;

                case ControlType.Activator:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    break;

                case ControlType.Normal:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.OnePlayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.Xea1p:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P;
                    break;

                case ControlType.Teamplayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    break;

                case ControlType.Wayplay:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    break;

                case ControlType.Mouse:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    // seems like mouse in port 1 would be supported, but not both at the same time
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE;
                    break;
                }


                if (!LibGPGX.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings()))
                {
                    throw new Exception("gpgx_init() failed");
                }

                {
                    int fpsnum = 60;
                    int fpsden = 1;
                    LibGPGX.gpgx_get_fps(ref fpsnum, ref fpsden);
                    VsyncNumerator   = fpsnum;
                    VsyncDenominator = fpsden;
                    Region           = VsyncNumerator / VsyncDenominator > 55 ? DisplayType.NTSC : DisplayType.PAL;
                }

                // compute state size
                {
                    byte[] tmp  = new byte[LibGPGX.gpgx_state_max_size()];
                    int    size = LibGPGX.gpgx_state_size(tmp, tmp.Length);
                    if (size <= 0)
                    {
                        throw new Exception("Couldn't Determine GPGX internal state size!");
                    }
                    _savebuff  = new byte[size];
                    _savebuff2 = new byte[_savebuff.Length + 13];
                    Console.WriteLine("GPGX Internal State Size: {0}", size);
                }

                SetControllerDefinition();

                // pull the default video size from the core
                UpdateVideoInitial();

                SetMemoryDomains();

                InputCallback = new LibGPGX.input_cb(input_callback);
                LibGPGX.gpgx_set_input_callback(InputCallback);

                if (CD != null)
                {
                    DriveLightEnabled = true;
                }

                // process the non-init settings now
                PutSettings(_settings);

                //TODO - this hits performance, we need to make it controllable
                CDCallback = new LibGPGX.CDCallback(CDCallbackProc);

                InitMemCallbacks();
                KillMemCallbacks();

                ConnectTracer();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
Exemple #20
0
		public void UpdateVDPViewContext(LibGPGX.VDPView view)
		{
			LibGPGX.gpgx_get_vdp_view(view);
			LibGPGX.gpgx_flush_vram(); // fully regenerate internal caches as needed
		}
Exemple #21
0
        public GPGX(CoreComm NextComm, byte[] romfile, DiscSystem.Disc CD, string romextension, object Settings, object SyncSettings)
        {
            // three or six button?
            // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds

            //hack, don't use
            //romfile = File.ReadAllBytes(@"D:\encodes\bizhawksrc\output\SANIC CD\PierSolar (E).bin");
            if (romfile != null && romfile.Length > 16 * 1024 * 1024)
            {
                throw new InvalidOperationException("ROM too big!  Did you try to load a CD as a ROM?");
            }

            try
            {
                _SyncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings();

                CoreComm = NextComm;
                if (AttachedCore != null)
                {
                    AttachedCore.Dispose();
                    AttachedCore = null;
                }
                AttachedCore = this;

                LoadCallback = new LibGPGX.load_archive_cb(load_archive);

                this.romfile = romfile;
                this.CD      = CD;

                LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
                LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;

                switch (this._SyncSettings.ControlType)
                {
                case ControlType.None:
                default:
                    break;

                case ControlType.Activator:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    break;

                case ControlType.Normal:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.OnePlayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.Xea1p:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P;
                    break;

                case ControlType.Teamplayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    break;

                case ControlType.Wayplay:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    break;

                case ControlType.Mouse:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    // seems like mouse in port 1 would be supported, but not both at the same time
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE;
                    break;
                }


                if (!LibGPGX.gpgx_init(romextension, LoadCallback, this._SyncSettings.UseSixButton, system_a, system_b, this._SyncSettings.Region))
                {
                    throw new Exception("gpgx_init() failed");
                }

                {
                    int fpsnum = 60;
                    int fpsden = 1;
                    LibGPGX.gpgx_get_fps(ref fpsnum, ref fpsden);
                    CoreComm.VsyncNum = fpsnum;
                    CoreComm.VsyncDen = fpsden;
                    DisplayType       = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL;
                }

                // compute state size
                {
                    byte[] tmp  = new byte[LibGPGX.gpgx_state_max_size()];
                    int    size = LibGPGX.gpgx_state_size(tmp, tmp.Length);
                    if (size <= 0)
                    {
                        throw new Exception("Couldn't Determine GPGX internal state size!");
                    }
                    savebuff  = new byte[size];
                    savebuff2 = new byte[savebuff.Length + 13];
                    Console.WriteLine("GPGX Internal State Size: {0}", size);
                }

                SetControllerDefinition();

                // pull the default video size from the core
                update_video();

                SetMemoryDomains();

                InputCallback = new LibGPGX.input_cb(input_callback);
                LibGPGX.gpgx_set_input_callback(InputCallback);

                if (CD != null)
                {
                    CoreComm.UsesDriveLed = true;
                }

                PutSettings(Settings ?? new GPGXSettings());

                InitMemCallbacks();
                KillMemCallbacks();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
Exemple #22
0
        public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings)
        {
            ServiceProvider = new BasicServiceProvider(this);
            // this can influence some things internally (autodetect romtype, etc)
            string romextension = "GEN";

            // three or six button?
            // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds

            //hack, don't use
            if (rom != null && rom.Length > 32 * 1024 * 1024)
            {
                throw new InvalidOperationException("ROM too big!  Did you try to load a CD as a ROM?");
            }

            try
            {
                Elf = new ElfRunner(Path.Combine(comm.CoreFileProvider.DllPath(), "gpgx.elf"), 8 * 1024 * 1024, 36 * 1024 * 1024, 4 * 1024 * 1024);
                if (Elf.ShouldMonitor)
                {
                    Core = BizInvoker.GetInvoker <LibGPGX>(Elf, Elf);
                }
                else
                {
                    Core = BizInvoker.GetInvoker <LibGPGX>(Elf);
                }

                _syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings();
                _settings     = (GPGXSettings)Settings ?? new GPGXSettings();

                CoreComm = comm;

                LoadCallback = new LibGPGX.load_archive_cb(load_archive);

                this.romfile = rom;
                this.CD      = CD;
                if (CD != null)
                {
                    this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD);
                    cd_callback_handle    = new LibGPGX.cd_read_cb(CDRead);
                    Core.gpgx_set_cdd_callback(cd_callback_handle);
                }

                LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
                LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;

                switch (_syncSettings.ControlType)
                {
                case ControlType.None:
                default:
                    break;

                case ControlType.Activator:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                    break;

                case ControlType.Normal:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.OnePlayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    break;

                case ControlType.Xea1p:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P;
                    break;

                case ControlType.Teamplayer:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                    break;

                case ControlType.Wayplay:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                    break;

                case ControlType.Mouse:
                    system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                    // seems like mouse in port 1 would be supported, but not both at the same time
                    system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE;
                    break;
                }


                if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings()))
                {
                    throw new Exception("gpgx_init() failed");
                }

                {
                    int fpsnum = 60;
                    int fpsden = 1;
                    Core.gpgx_get_fps(ref fpsnum, ref fpsden);
                    CoreComm.VsyncNum = fpsnum;
                    CoreComm.VsyncDen = fpsden;
                    Region            = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL;
                }

                // compute state size
                InitStateBuffers();

                SetControllerDefinition();

                // pull the default video size from the core
                UpdateVideoInitial();

                SetMemoryDomains();

                InputCallback = new LibGPGX.input_cb(input_callback);
                Core.gpgx_set_input_callback(InputCallback);

                if (CD != null)
                {
                    DriveLightEnabled = true;
                }

                // process the non-init settings now
                PutSettings(_settings);

                //TODO - this hits performance, we need to make it controllable
                CDCallback = new LibGPGX.CDCallback(CDCallbackProc);

                InitMemCallbacks();
                KillMemCallbacks();

                Tracer = new GPGXTraceBuffer(this, MemoryDomains, this);
                (ServiceProvider as BasicServiceProvider).Register <ITraceable>(Tracer);

                Elf.Seal();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
Exemple #23
0
 public void UpdateVDPViewContext(LibGPGX.VDPView view)
 {
     LibGPGX.gpgx_get_vdp_view(view);
 }
 private void KillMemCallbacks()
 {
     LibGPGX.gpgx_set_mem_callback(null, null, null);
 }
Exemple #25
0
        public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings)
        {
            ServiceProvider = new BasicServiceProvider(this);
            // this can influence some things internally (autodetect romtype, etc)
            string romextension = "GEN";

            // three or six button?
            // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds

            //hack, don't use
            if (rom != null && rom.Length > 32 * 1024 * 1024)
            {
                throw new InvalidOperationException("ROM too big!  Did you try to load a CD as a ROM?");
            }

            try
            {
                Elf = new ElfRunner(Path.Combine(comm.CoreFileProvider.DllPath(), "gpgx.elf"), 8 * 1024 * 1024, 36 * 1024 * 1024, 4 * 1024 * 1024);
                if (Elf.ShouldMonitor)
                    Core = BizInvoker.GetInvoker<LibGPGX>(Elf, Elf);
                else
                    Core = BizInvoker.GetInvoker<LibGPGX>(Elf);

                _syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings();
                _settings = (GPGXSettings)Settings ?? new GPGXSettings();

                CoreComm = comm;

                LoadCallback = new LibGPGX.load_archive_cb(load_archive);

                this.romfile = rom;
                this.CD = CD;
                if (CD != null)
                {
                    this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD);
                    cd_callback_handle = new LibGPGX.cd_read_cb(CDRead);
                    Core.gpgx_set_cdd_callback(cd_callback_handle);
                }

                LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
                LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;

                switch (_syncSettings.ControlType)
                {
                    case ControlType.None:
                    default:
                        break;
                    case ControlType.Activator:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                        system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
                        break;
                    case ControlType.Normal:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                        system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                        break;
                    case ControlType.OnePlayer:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                        break;
                    case ControlType.Xea1p:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P;
                        break;
                    case ControlType.Teamplayer:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                        system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
                        break;
                    case ControlType.Wayplay:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                        system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
                        break;
                    case ControlType.Mouse:
                        system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
                        // seems like mouse in port 1 would be supported, but not both at the same time
                        system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE;
                        break;
                }

                if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings()))
                    throw new Exception("gpgx_init() failed");

                {
                    int fpsnum = 60;
                    int fpsden = 1;
                    Core.gpgx_get_fps(ref fpsnum, ref fpsden);
                    CoreComm.VsyncNum = fpsnum;
                    CoreComm.VsyncDen = fpsden;
                    Region = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL;
                }

                // compute state size
                InitStateBuffers();

                SetControllerDefinition();

                // pull the default video size from the core
                UpdateVideoInitial();

                SetMemoryDomains();

                InputCallback = new LibGPGX.input_cb(input_callback);
                Core.gpgx_set_input_callback(InputCallback);

                if (CD != null)
                    DriveLightEnabled = true;

                // process the non-init settings now
                PutSettings(_settings);

                //TODO - this hits performance, we need to make it controllable
                CDCallback = new LibGPGX.CDCallback(CDCallbackProc);

                InitMemCallbacks();
                KillMemCallbacks();

                Tracer = new GPGXTraceBuffer(this, MemoryDomains, this);
                (ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);

                Elf.Seal();
            }
            catch
            {
                Dispose();
                throw;
            }
        }
Exemple #26
0
 public void UpdateVDPViewContext(LibGPGX.VDPView view)
 {
     LibGPGX.gpgx_get_vdp_view(view);
     LibGPGX.gpgx_flush_vram();             // fully regenerate internal caches as needed
 }
        private unsafe void SetMemoryDomains()
        {
            var mm = new List <MemoryDomain>();

            for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++)
            {
                IntPtr area  = IntPtr.Zero;
                int    size  = 0;
                IntPtr pname = LibGPGX.gpgx_get_memdom(i, ref area, ref size);
                if (area == IntPtr.Zero || pname == IntPtr.Zero || size == 0)
                {
                    continue;
                }
                string name = Marshal.PtrToStringAnsi(pname);
                if (name == "VRAM")
                {
                    // vram pokes need to go through hook which invalidates cached tiles
                    byte *p = (byte *)area;
                    mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Unknown,
                                                    delegate(long addr)
                    {
                        if (addr < 0 || addr >= 65536)
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        return(p[addr ^ 1]);
                    },
                                                    delegate(long addr, byte val)
                    {
                        if (addr < 0 || addr >= 65536)
                        {
                            throw new ArgumentOutOfRangeException();
                        }
                        LibGPGX.gpgx_poke_vram(((int)addr) ^ 1, val);
                    },
                                                    wordSize: 2));
                }

                else
                {
                    // TODO: are the Z80 domains really Swap16 in the core?  Check this
                    //var byteSize = name.Contains("Z80") ? 1 : 2;
                    mm.Add(new MemoryDomainIntPtrSwap16(name, MemoryDomain.Endian.Big, area, size, name != "MD CART" && name != "CD BOOT ROM"));
                }
            }

            //it's gross for this not to be the full 32bits.
            //Uhh I mean, I guess the bus is physically smaller.. but the cpu's view of it is larger...
            //So... I guess no matter what we do, some badness will propagate. This is probably least bad.
            //Anyway, the disassembler, for instance, must have been masked down to size, since code can run from FFxxxxxxxx...
            var m68Bus = new MemoryDomainDelegate("M68K BUS", 0x1000000, MemoryDomain.Endian.Big,
                                                  delegate(long addr)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                return(LibGPGX.gpgx_peek_m68k_bus(a));
            },
                                                  delegate(long addr, byte val)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                LibGPGX.gpgx_write_m68k_bus(a, val);
            }, 2);

            mm.Add(m68Bus);

            var s68Bus = new MemoryDomainDelegate("S68K BUS", 0x1000000, MemoryDomain.Endian.Big,
                                                  delegate(long addr)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                return(LibGPGX.gpgx_peek_s68k_bus(a));
            },
                                                  delegate(long addr, byte val)
            {
                var a = (uint)addr;
                if (a >= 0x1000000)
                {
                    throw new ArgumentOutOfRangeException();
                }
                LibGPGX.gpgx_write_s68k_bus(a, val);
            }, 2);

            if (IsSegaCD)
            {
                mm.Add(s68Bus);
            }

            MemoryDomains           = new MemoryDomainList(mm);
            MemoryDomains.SystemBus = m68Bus;

            (ServiceProvider as BasicServiceProvider).Register <IMemoryDomains>(MemoryDomains);
        }