Example #1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="callback">null to cancel</param>
 /// <param name="scanline">0-227, null = end of frame</param>
 public void SetScanlineCallback(Action callback, int?scanline)
 {
     if (callback == null)
     {
         LibMeteor.libmeteor_setscanlinecallback(null, 400);
         EndOfFrameCallback = null;
         scanlinecb         = null;
     }
     else if (scanline == null)
     {
         LibMeteor.libmeteor_setscanlinecallback(null, 400);
         EndOfFrameCallback = callback;
         scanlinecb         = null;
     }
     else if (scanline >= 0 && scanline <= 227)
     {
         scanlinecb = new LibMeteor.ScanlineCallback(callback);
         LibMeteor.libmeteor_setscanlinecallback(scanlinecb, (int)scanline);
         EndOfFrameCallback = null;
     }
     else
     {
         throw new ArgumentOutOfRangeException("Scanline must be in [0, 227]!");
     }
 }
Example #2
0
        public GBA(CoreComm comm, byte[] file)
        {
            ServiceProvider = new BasicServiceProvider(this);
            Tracer          = new TraceBuffer
            {
                Header = "   -Addr--- -Opcode- -Instruction------------------- -R0----- -R1----- -R2----- -R3----- -R4----- -R5----- -R6----- -R7----- -R8----- -R9----- -R10---- -R11---- -R12---- -R13(SP) -R14(LR) -R15(PC) -CPSR--- -SPSR---"
            };

            (ServiceProvider as BasicServiceProvider).Register <ITraceable>(Tracer);

            CoreComm = comm;

            comm.VsyncNum      = 262144;
            comm.VsyncDen      = 4389;
            comm.NominalWidth  = 240;
            comm.NominalHeight = 160;

            byte[] bios = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory.");

            if (bios.Length != 16384)
            {
                throw new InvalidDataException("GBA bios must be exactly 16384 bytes!");
            }
            if (file.Length > 32 * 1024 * 1024)
            {
                throw new InvalidDataException("Rom file is too big!  No GBA game is larger than 32MB");
            }
            Init();
            LibMeteor.libmeteor_hardreset();
            LibMeteor.libmeteor_loadbios(bios, (uint)bios.Length);
            LibMeteor.libmeteor_loadrom(file, (uint)file.Length);

            SetUpMemoryDomains();
        }
Example #3
0
        void Init()
        {
            if (attachedcore != null)
            {
                attachedcore.Dispose();
            }

            messagecallback = PrintMessage;
            inputcallback   = GetInput;
            tracecallback   = Trace;           // don't set this callback now, only set if enabled
            LibMeteor.libmeteor_setmessagecallback(messagecallback);
            LibMeteor.libmeteor_setkeycallback(inputcallback);

            LibMeteor.libmeteor_init();
            videobuffer = new int[240 * 160];
            videohandle = GCHandle.Alloc(videobuffer, GCHandleType.Pinned);
            soundbuffer = new short[2048];             // nominal length of one frame is something like 1480 shorts?
            soundhandle = GCHandle.Alloc(soundbuffer, GCHandleType.Pinned);

            if (!LibMeteor.libmeteor_setbuffers
                    (videohandle.AddrOfPinnedObject(), (uint)(sizeof(int) * videobuffer.Length),
                    soundhandle.AddrOfPinnedObject(), (uint)(sizeof(short) * soundbuffer.Length)))
            {
                throw new Exception("libmeteor_setbuffers() returned false??");
            }

            attachedcore = this;
        }
 private void LoadCoreBinary(byte[] data)
 {
     if (!LibMeteor.libmeteor_loadstate(data, (uint)data.Length))
     {
         throw new Exception("libmeteor_loadstate() failed!");
     }
 }
Example #5
0
 public void ClearSaveRam()
 {
     if (disposed)
     {
         throw new ObjectDisposedException(this.GetType().ToString());
     }
     LibMeteor.libmeteor_clearsaveram();
 }
Example #6
0
		private void AddMemoryDomain(LibMeteor.MemoryArea which, int size, string name)
		{
			IntPtr data = LibMeteor.libmeteor_getmemoryarea(which);
			if (data == IntPtr.Zero)
				throw new Exception("libmeteor_getmemoryarea() returned NULL??");

			MemoryDomain md = MemoryDomain.FromIntPtr(name, size, MemoryDomain.Endian.Little, data);
			_domainList.Add(md);
		}
Example #7
0
 public void StoreSaveRam(byte[] data)
 {
     if (disposed)
     {
         throw new ObjectDisposedException(this.GetType().ToString());
     }
     if (!LibMeteor.libmeteor_loadsaveram(data, (uint)data.Length))
     {
         throw new Exception("libmeteor_loadsaveram() returned false!");
     }
 }
Example #8
0
        public Dictionary <string, int> GetCpuFlagsAndRegisters()
        {
            var ret = new Dictionary <string, int>();

            int[] data = new int[LibMeteor.regnames.Length];
            LibMeteor.libmeteor_getregs(data);
            for (int i = 0; i < data.Length; i++)
            {
                ret.Add(LibMeteor.regnames[i], data[i]);
            }
            return(ret);
        }
        private void AddMemoryDomain(LibMeteor.MemoryArea which, int size, string name)
        {
            IntPtr data = LibMeteor.libmeteor_getmemoryarea(which);

            if (data == IntPtr.Zero)
            {
                throw new Exception("libmeteor_getmemoryarea() returned NULL??");
            }

            MemoryDomain md = MemoryDomain.FromIntPtr(name, size, MemoryDomain.Endian.Little, data);

            _domainList.Add(md);
        }
Example #10
0
        public void GetSamples(out short[] samples, out int nsamp)
        {
            uint nbytes = LibMeteor.libmeteor_emptysound();

            samples = soundbuffer;
            if (!coredead)
            {
                nsamp = (int)(nbytes / 4);
            }
            else
            {
                nsamp = 738;
            }
        }
Example #11
0
        public void StoreSaveRam(byte[] data)
        {
            throw new Exception("This needs to be fixed to match the VBANext Core!");
#if false
            if (disposed)
            {
                throw new ObjectDisposedException(this.GetType().ToString());
            }
            if (!LibMeteor.libmeteor_loadsaveram(data, (uint)data.Length))
            {
                throw new Exception("libmeteor_loadsaveram() returned false!");
            }
#endif
        }
Example #12
0
        public void GetGPUMemoryAreas(out IntPtr vram, out IntPtr palram, out IntPtr oam, out IntPtr mmio)
        {
            IntPtr _vram   = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.vram);
            IntPtr _palram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.palram);
            IntPtr _oam    = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.oam);
            IntPtr _mmio   = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.io);

            if (_vram == IntPtr.Zero || _palram == IntPtr.Zero || _oam == IntPtr.Zero || _mmio == IntPtr.Zero)
            {
                throw new Exception("libmeteor_getmemoryarea() failed!");
            }

            vram   = _vram;
            palram = _palram;
            oam    = _oam;
            mmio   = _mmio;
        }
Example #13
0
 public void Dispose()
 {
     if (!disposed)
     {
         disposed = true;
         videohandle.Free();
         soundhandle.Free();
         // guarantee crash if it gets accessed
         LibMeteor.libmeteor_setbuffers(IntPtr.Zero, 240 * 160 * 4, IntPtr.Zero, 4);
         messagecallback = null;
         inputcallback   = null;
         tracecallback   = null;
         LibMeteor.libmeteor_setmessagecallback(messagecallback);
         LibMeteor.libmeteor_setkeycallback(inputcallback);
         LibMeteor.libmeteor_settracecallback(tracecallback);
         _MemoryDomains.Clear();
     }
 }
Example #14
0
        public void SetScanlineCallback(Action callback, int scanline)
        {
            if (scanline < 0 || scanline > 227)
            {
                throw new ArgumentOutOfRangeException(nameof(scanline), "Scanline must be in [0, 227]!");
            }

            if (callback == null)
            {
                scanlinecb = null;
                LibMeteor.libmeteor_setscanlinecallback(null, 0);
            }
            else
            {
                scanlinecb = new LibMeteor.ScanlineCallback(callback);
                LibMeteor.libmeteor_setscanlinecallback(scanlinecb, scanline);
            }
        }
        private byte[] SaveCoreBinary()
        {
            IntPtr ndata = IntPtr.Zero;
            uint   nsize = 0;

            if (!LibMeteor.libmeteor_savestate(ref ndata, ref nsize))
            {
                throw new Exception("libmeteor_savestate() failed!");
            }
            if (ndata == IntPtr.Zero || nsize == 0)
            {
                throw new Exception("libmeteor_savestate() returned bad!");
            }

            byte[] ret = new byte[nsize];
            Marshal.Copy(ndata, ret, 0, (int)nsize);
            LibMeteor.libmeteor_savestate_destroy(ndata);
            return(ret);
        }
Example #16
0
        public void Load(byte[] rom)
        {
            byte[] bios = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory.");

            if (bios.Length != 16384)
            {
                throw new InvalidDataException("GBA bios must be exactly 16384 bytes!");
            }
            if (rom.Length > 32 * 1024 * 1024)
            {
                throw new InvalidDataException("Rom file is too big!  No GBA game is larger than 32MB");
            }
            Init();
            LibMeteor.libmeteor_hardreset();
            LibMeteor.libmeteor_loadbios(bios, (uint)bios.Length);
            LibMeteor.libmeteor_loadrom(rom, (uint)rom.Length);

            SetUpMemoryDomains();
        }
Example #17
0
        public void FrameAdvance(bool render, bool rendersound = true)
        {
            Frame++;
            IsLagFrame = true;

            if (Controller.IsPressed("Power"))
            {
                LibMeteor.libmeteor_hardreset();
            }
            // due to the design of the tracing api, we have to poll whether it's active each frame
            LibMeteor.libmeteor_settracecallback(Tracer.Enabled ? tracecallback : null);
            if (!coredead)
            {
                LibMeteor.libmeteor_frameadvance();
            }
            if (IsLagFrame)
            {
                LagCount++;
            }
        }
Example #18
0
        public GBAGPUMemoryAreas GetMemoryAreas()
        {
            IntPtr _vram   = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.vram);
            IntPtr _palram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.palram);
            IntPtr _oam    = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.oam);
            IntPtr _mmio   = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.io);

            if (_vram == IntPtr.Zero || _palram == IntPtr.Zero || _oam == IntPtr.Zero || _mmio == IntPtr.Zero)
            {
                throw new Exception("libmeteor_getmemoryarea() failed!");
            }

            return(new GBAGPUMemoryAreas
            {
                vram = _vram,
                palram = _palram,
                oam = _oam,
                mmio = _mmio
            });
        }
Example #19
0
        public byte[] ReadSaveRam()
        {
            if (disposed)
            {
                throw new ObjectDisposedException(this.GetType().ToString());
            }
            if (!LibMeteor.libmeteor_hassaveram())
            {
                return(null);
            }
            IntPtr data = IntPtr.Zero;
            uint   size = 0;

            if (!LibMeteor.libmeteor_savesaveram(ref data, ref size))
            {
                throw new Exception("libmeteor_savesaveram() returned false!");
            }
            byte[] ret = new byte[size];
            Marshal.Copy(data, ret, 0, (int)size);
            LibMeteor.libmeteor_savesaveram_destroy(data);
            return(ret);
        }
Example #20
0
        void AddMemoryDomain(LibMeteor.MemoryArea which, int size, string name)
        {
            IntPtr data = LibMeteor.libmeteor_getmemoryarea(which);

            if (data == IntPtr.Zero)
            {
                throw new Exception("libmeteor_getmemoryarea() returned NULL??");
            }

            MemoryDomain md = new MemoryDomain(name, size, MemoryDomain.Endian.Little,
                                               delegate(int addr)
            {
                unsafe
                {
                    byte *d = (byte *)data;
                    if (addr < 0 || addr >= size)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    return(d[addr]);
                }
            },
                                               delegate(int addr, byte val)
            {
                unsafe
                {
                    byte *d = (byte *)data;
                    if (addr < 0 || addr >= size)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    d[addr] = val;
                }
            });

            _MemoryDomains.Add(md);
        }
Example #21
0
        public byte[] CloneSaveRam()
        {
            throw new Exception("This needs to be fixed to match the VBANext Core!");
#if false
            if (disposed)
            {
                throw new ObjectDisposedException(this.GetType().ToString());
            }
            if (!LibMeteor.libmeteor_hassaveram())
            {
                return(null);
            }
            IntPtr data = IntPtr.Zero;
            uint   size = 0;
            if (!LibMeteor.libmeteor_savesaveram(ref data, ref size))
            {
                throw new Exception("libmeteor_savesaveram() returned false!");
            }
            byte[] ret = new byte[size];
            Marshal.Copy(data, ret, 0, (int)size);
            LibMeteor.libmeteor_savesaveram_destroy(data);
            return(ret);
#endif
        }
Example #22
0
 public void DiscardSamples()
 {
     LibMeteor.libmeteor_emptysound();
 }
Example #23
0
		void AddMemoryDomain(LibMeteor.MemoryArea which, int size, string name)
		{
			IntPtr data = LibMeteor.libmeteor_getmemoryarea(which);
			if (data == IntPtr.Zero)
				throw new Exception("libmeteor_getmemoryarea() returned NULL??");

			MemoryDomain md = new MemoryDomain(name, size, MemoryDomain.Endian.Little,
				delegate(int addr)
				{
					unsafe
					{
						byte* d = (byte*)data;
						if (addr < 0 || addr >= size)
							throw new IndexOutOfRangeException();
						return d[addr];
					}
				},
				delegate(int addr, byte val)
				{
					unsafe
					{
						byte* d = (byte*)data;
						if (addr < 0 || addr >= size)
							throw new IndexOutOfRangeException();
						d[addr] = val;
					}
				});
			_MemoryDomains.Add(md);
		}
Example #24
0
        void SetUpMemoryDomains()
        {
            _MemoryDomains.Clear();
            // this must be first to coincide with "main memory"
            // note that ewram could also be considered main memory depending on which hairs you split
            AddMemoryDomain(LibMeteor.MemoryArea.iwram, 32 * 1024, "IWRAM");
            AddMemoryDomain(LibMeteor.MemoryArea.ewram, 256 * 1024, "EWRAM");
            AddMemoryDomain(LibMeteor.MemoryArea.bios, 16 * 1024, "BIOS");
            AddMemoryDomain(LibMeteor.MemoryArea.palram, 1024, "PALRAM");
            AddMemoryDomain(LibMeteor.MemoryArea.vram, 96 * 1024, "VRAM");
            AddMemoryDomain(LibMeteor.MemoryArea.oam, 1024, "OAM");
            // even if the rom is less than 32MB, the whole is still valid in meteor
            AddMemoryDomain(LibMeteor.MemoryArea.rom, 32 * 1024 * 1024, "ROM");
            // special domain for system bus
            {
                MemoryDomain sb = new MemoryDomain("BUS", 1 << 28, MemoryDomain.Endian.Little,
                                                   delegate(int addr)
                        {
                        if (addr < 0 || addr >= 0x10000000)
                        {
                            throw new IndexOutOfRangeException();
                        }
                        return(LibMeteor.libmeteor_peekbus((uint)addr));
                    },
                                                   delegate(int addr, byte val)
                        {
                        if (addr < 0 || addr >= 0x10000000)
                        {
                            throw new IndexOutOfRangeException();
                        }
                        LibMeteor.libmeteor_writebus((uint)addr, val);
                    });
                _MemoryDomains.Add(sb);
            }
            // special combined ram memory domain
            {
                var          ew = _MemoryDomains[1];
                var          iw = _MemoryDomains[0];
                MemoryDomain cr = new MemoryDomain("Combined WRAM", (256 + 32) * 1024, MemoryDomain.Endian.Little,
                                                   delegate(int addr)
                {
                    if (addr < 0 || addr >= (256 + 32) * 1024)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    if (addr >= 256 * 1024)
                    {
                        return(iw.PeekByte(addr & 32767));
                    }
                    else
                    {
                        return(ew.PeekByte(addr));
                    }
                },
                                                   delegate(int addr, byte val)
                {
                    if (addr < 0 || addr >= (256 + 32) * 1024)
                    {
                        throw new IndexOutOfRangeException();
                    }
                    if (addr >= 256 * 1024)
                    {
                        iw.PokeByte(addr & 32767, val);
                    }
                    else
                    {
                        ew.PokeByte(addr, val);
                    }
                });
                _MemoryDomains.Add(cr);
            }

            MemoryDomains = new MemoryDomainList(_MemoryDomains);
        }