Example #1
0
        void InitMemoryDomains()
        {
            CreateMemoryDomain(LibGambatte.MemoryAreas.wram, "WRAM");
            CreateMemoryDomain(LibGambatte.MemoryAreas.rom, "ROM");
            CreateMemoryDomain(LibGambatte.MemoryAreas.vram, "VRAM");
            CreateMemoryDomain(LibGambatte.MemoryAreas.cartram, "Cart RAM");
            CreateMemoryDomain(LibGambatte.MemoryAreas.oam, "OAM");
            CreateMemoryDomain(LibGambatte.MemoryAreas.hram, "HRAM");

            // also add a special memory domain for the system bus, where calls get sent directly to the core each time

            _MemoryDomains.Add(new MemoryDomain("System Bus", 65536, MemoryDomain.Endian.Little,
                                                delegate(int addr)
            {
                if (addr < 0 || addr >= 65536)
                {
                    throw new ArgumentOutOfRangeException();
                }
                return(LibGambatte.gambatte_cpuread(GambatteState, (ushort)addr));
            },
                                                delegate(int addr, byte val)
            {
                if (addr < 0 || addr >= 65536)
                {
                    throw new ArgumentOutOfRangeException();
                }
                LibGambatte.gambatte_cpuwrite(GambatteState, (ushort)addr, val);
            }));

            MemoryDomains = new MemoryDomainList(_MemoryDomains);
        }
Example #2
0
        public bool GetGPUMemoryAreas(out IntPtr vram, out IntPtr bgpal, out IntPtr sppal, out IntPtr oam)
        {
            IntPtr _vram  = IntPtr.Zero;
            IntPtr _bgpal = IntPtr.Zero;
            IntPtr _sppal = IntPtr.Zero;
            IntPtr _oam   = IntPtr.Zero;
            int    unused = 0;

            if (!LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.vram, ref _vram, ref unused) ||
                !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.bgpal, ref _bgpal, ref unused) ||
                !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.sppal, ref _sppal, ref unused) ||
                !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.oam, ref _oam, ref unused))
            {
                vram  = IntPtr.Zero;
                bgpal = IntPtr.Zero;
                sppal = IntPtr.Zero;
                oam   = IntPtr.Zero;
                return(false);
            }
            vram  = _vram;
            bgpal = _bgpal;
            sppal = _sppal;
            oam   = _oam;
            return(true);
        }
Example #3
0
        private void ProcessMbcSound(bool processSound)
        {
            int nsamp = LibGambatte.gambatte_generatembcsamples(GambatteState, _mbcsoundbuff);

            if (nsamp == 0)
            {
                return;
            }

            for (uint i = 0; i < nsamp; i++)
            {
                int ls = _mbcsoundbuff[i * 2] - _mbcLatchL;
                int rs = _mbcsoundbuff[(i * 2) + 1] - _mbcLatchR;
                if (ls != 0 && processSound)
                {
                    _blipL.AddDelta(i, ls);
                }
                if (rs != 0 && processSound)
                {
                    _blipR.AddDelta(i, rs);
                }
                _mbcLatchL = _mbcsoundbuff[i * 2];
                _mbcLatchR = _mbcsoundbuff[(i * 2) + 1];
            }
        }
Example #4
0
 public void Disconnect()
 {
     if (gb.GambatteState != IntPtr.Zero)
     {
         LibGambatte.gambatte_setlinkcallback(gb.GambatteState, null);
     }
 }
Example #5
0
        private void ProcessSgbSound(int nsamp, bool processSound)
        {
            int remainder = LibGambatte.gambatte_generatesgbsamples(GambatteState, _sgbsoundbuff, out uint samples);

            if (remainder < 0)
            {
                throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_generatesgbsamples)}() returned negative (spc error???)");
            }
            uint t = 65 - (uint)remainder;

            for (int i = 0; i < samples; i++, t += 65)
            {
                int ls = _sgbsoundbuff[i * 2] - _sgbLatchL;
                int rs = _sgbsoundbuff[(i * 2) + 1] - _sgbLatchR;
                if (ls != 0 && processSound)
                {
                    _blipL.AddDelta(t, ls);
                }
                if (rs != 0 && processSound)
                {
                    _blipR.AddDelta(t, rs);
                }
                _sgbLatchL = _sgbsoundbuff[i * 2];
                _sgbLatchR = _sgbsoundbuff[(i * 2) + 1];
            }
        }
Example #6
0
        public IDictionary <string, RegisterValue> GetCpuFlagsAndRegisters()
        {
            int[] data = new int[10];
            LibGambatte.gambatte_getregs(GambatteState, data);

            return(new Dictionary <string, RegisterValue>
            {
                ["PC"] = (ushort)(data[(int)LibGambatte.RegIndices.PC] & 0xffff),
                ["SP"] = (ushort)(data[(int)LibGambatte.RegIndices.SP] & 0xffff),
                ["A"] = (byte)(data[(int)LibGambatte.RegIndices.A] & 0xff),
                ["B"] = (byte)(data[(int)LibGambatte.RegIndices.B] & 0xff),
                ["C"] = (byte)(data[(int)LibGambatte.RegIndices.C] & 0xff),
                ["D"] = (byte)(data[(int)LibGambatte.RegIndices.D] & 0xff),
                ["E"] = (byte)(data[(int)LibGambatte.RegIndices.E] & 0xff),
                ["F"] = (byte)(data[(int)LibGambatte.RegIndices.F] & 0xff),
                ["H"] = (byte)(data[(int)LibGambatte.RegIndices.H] & 0xff),
                ["L"] = (byte)(data[(int)LibGambatte.RegIndices.L] & 0xff),
                // banks
                ["ROM0 BANK"] = (ushort)LibGambatte.gambatte_getbank(GambatteState, LibGambatte.BankType.ROM0),
                ["ROMX BANK"] = (ushort)LibGambatte.gambatte_getbank(GambatteState, LibGambatte.BankType.ROMX),
                ["VRAM BANK"] = (byte)LibGambatte.gambatte_getbank(GambatteState, LibGambatte.BankType.VRAM),
                ["SRAM BANK"] = (byte)LibGambatte.gambatte_getbank(GambatteState, LibGambatte.BankType.SRAM),
                ["WRAM BANK"] = (byte)LibGambatte.gambatte_getbank(GambatteState, LibGambatte.BankType.WRAM),
                // todo: maybe do [bc]/[de]/[hl]?
            });
        }
Example #7
0
        /// <summary>
        /// set up callback
        /// </summary>
        /// <param name="line">scanline. -1 = end of frame, -2 = RIGHT NOW</param>
        public void SetScanlineCallback(ScanlineCallback callback, int line)
        {
            if (GambatteState == IntPtr.Zero)
            {
                return;                 // not sure how this is being reached.  tried the debugger...
            }

            endofframecallback = null;
            if (callback == null || line == -1 || line == -2)
            {
                scanlinecb = null;
                LibGambatte.gambatte_setscanlinecallback(GambatteState, null, 0);
                if (line == -1)
                {
                    endofframecallback = callback;
                }
                else if (line == -2)
                {
                    callback(LibGambatte.gambatte_cpuread(GambatteState, 0xff40));
                }
            }
            else if (line >= 0 && line <= 153)
            {
                scanlinecb = delegate
                {
                    callback(LibGambatte.gambatte_cpuread(GambatteState, 0xff40));
                };
                LibGambatte.gambatte_setscanlinecallback(GambatteState, scanlinecb, line);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(line), "line must be in [0, 153]");
            }
        }
Example #8
0
        private void MakeTrace(IntPtr _s)
        {
            int[] s = new int[14];
            System.Runtime.InteropServices.Marshal.Copy(_s, s, 0, 14);
            ushort unused;

            Tracer.Put(new TraceInfo
            {
                Disassembly =
                    LR35902.Disassemble((ushort)s[1], addr => LibGambatte.gambatte_cpuread(GambatteState, addr), out unused)
                    .PadRight(36),
                RegisterInfo =
                    string.Format(
                        "A:{3:x2} B:{4:x2} C:{5:x2} D:{6:x2} E:{7:x2} F:{8:x2} H:{9:x2} L:{10:x2} LY:{13:x2} SP:{2:x2} {11} Cy:{0}",
                        s[0],
                        s[1] & 0xffff,
                        s[2] & 0xffff,
                        s[3] & 0xff,
                        s[4] & 0xff,
                        s[5] & 0xff,
                        s[6] & 0xff,
                        s[7] & 0xff,
                        s[8] & 0xff,
                        s[9] & 0xff,
                        s[10] & 0xff,
                        s[11] != 0 ? "skip" : "",
                        s[12] & 0xff,
                        s[13] & 0xff)
            });
        }
Example #9
0
 /// <summary>
 /// update gambatte core's internal colors
 /// </summary>
 public void ChangeDMGColors(int[] colors)
 {
     for (int i = 0; i < 12; i++)
     {
         LibGambatte.gambatte_setdmgpalettecolor(GambatteState, (LibGambatte.PalType)(i / 4), (uint)i % 4, (uint)colors[i]);
     }
 }
        public void SaveStateBinary(BinaryWriter writer)
        {
#if USE_UPSTREAM_STATES
            int size = LibGambatte.gambatte_savestate(GambatteState, null, 160, _stateBuf);
            if (size != _stateBuf.Length)
            {
                throw new InvalidOperationException("Savestate buffer size mismatch!");
            }
#else
            if (!LibGambatte.gambatte_newstatesave(GambatteState, _stateBuf, _stateBuf.Length))
            {
                throw new Exception($"{nameof(LibGambatte.gambatte_newstatesave)}() returned false");
            }
#endif

            writer.Write(_stateBuf.Length);
            writer.Write(_stateBuf);

            // other variables
            writer.Write(IsLagFrame);
            writer.Write(LagCount);
            writer.Write(Frame);
            writer.Write(frameOverflow);
            writer.Write(_cycleCount);
            writer.Write(IsCgb);
            writer.Write(IsSgb);
        }
        public void LoadStateBinary(BinaryReader reader)
        {
            int length = reader.ReadInt32();

            if (length != _stateBuf.Length)
            {
                throw new InvalidOperationException("Savestate buffer size mismatch!");
            }

            reader.Read(_stateBuf, 0, _stateBuf.Length);

#if USE_UPSTREAM_STATES
            if (!LibGambatte.gambatte_loadstate(GambatteState, _stateBuf, _stateBuf.Length))
            {
                throw new Exception($"{nameof(LibGambatte.gambatte_loadstate)}() returned false");
            }
#else
            if (!LibGambatte.gambatte_newstateload(GambatteState, _stateBuf, _stateBuf.Length))
            {
                throw new Exception($"{nameof(LibGambatte.gambatte_newstateload)}() returned false");
            }
#endif

            // other variables
            IsLagFrame    = reader.ReadBoolean();
            LagCount      = reader.ReadInt32();
            Frame         = reader.ReadInt32();
            frameOverflow = reader.ReadUInt32();
            _cycleCount   = reader.ReadUInt64();
            IsCgb         = reader.ReadBoolean();
            IsSgb         = reader.ReadBoolean();
        }
Example #12
0
        public GambatteLink(CoreComm comm, GameInfo leftinfo, byte[] leftrom, GameInfo rightinfo, byte[] rightrom, object settings, object syncSettings, bool deterministic)
        {
            ServiceProvider = new BasicServiceProvider(this);
            GambatteLinkSettings     linkSettings     = (GambatteLinkSettings)settings ?? new GambatteLinkSettings();
            GambatteLinkSyncSettings linkSyncSettings = (GambatteLinkSyncSettings)syncSettings ?? new GambatteLinkSyncSettings();

            L = new Gameboy(comm, leftinfo, leftrom, linkSettings.L, linkSyncSettings.L, deterministic);
            R = new Gameboy(comm, rightinfo, rightrom, linkSettings.R, linkSyncSettings.R, deterministic);

            // connect link cable
            LibGambatte.gambatte_linkstatus(L.GambatteState, 259);
            LibGambatte.gambatte_linkstatus(R.GambatteState, 259);

            L.ConnectInputCallbackSystem(_inputCallbacks);
            R.ConnectInputCallbackSystem(_inputCallbacks);
            L.ConnectMemoryCallbackSystem(_memorycallbacks);
            R.ConnectMemoryCallbackSystem(_memorycallbacks);

            RomDetails = "LEFT:\r\n" + L.RomDetails + "RIGHT:\r\n" + R.RomDetails;

            LinkConnected = true;

            Frame      = 0;
            LagCount   = 0;
            IsLagFrame = false;

            _blipLeft  = new BlipBuffer(1024);
            _blipRight = new BlipBuffer(1024);
            _blipLeft.SetRates(2097152 * 2, 44100);
            _blipRight.SetRates(2097152 * 2, 44100);

            SetMemoryDomains();
        }
        private void InitMemoryCallbacks()
        {
            LibGambatte.MemoryCallback CreateCallback(MemoryCallbackFlags flags, Func <bool> getHasCBOfType)
            {
                var rawFlags = (uint)flags;

                return((address, cycleOffset) =>
                {
                    callbackCycleCount = _cycleCount + cycleOffset;
                    if (getHasCBOfType())
                    {
                        MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, systemBusScope);
                    }
                });
            }

            _readcb  = CreateCallback(MemoryCallbackFlags.AccessRead, () => MemoryCallbacks.HasReads);
            _writecb = CreateCallback(MemoryCallbackFlags.AccessWrite, () => MemoryCallbacks.HasWrites);
            _execcb  = CreateCallback(MemoryCallbackFlags.AccessExecute, () => MemoryCallbacks.HasExecutes);

            _memorycallbacks.ActiveChanged += () =>
            {
                LibGambatte.gambatte_setreadcallback(GambatteState, MemoryCallbacks.HasReads ? _readcb : null);
                LibGambatte.gambatte_setwritecallback(GambatteState, MemoryCallbacks.HasWrites ? _writecb : null);
                LibGambatte.gambatte_setexeccallback(GambatteState, MemoryCallbacks.HasExecutes ? _execcb : null);
            };
        }
Example #14
0
        internal void FrameAdvancePrep()
        {
            Frame++;

            // update our local copy of the controller data
            CurrentButtons = 0;

            if (Controller["Up"])
            {
                CurrentButtons |= LibGambatte.Buttons.UP;
            }
            if (Controller["Down"])
            {
                CurrentButtons |= LibGambatte.Buttons.DOWN;
            }
            if (Controller["Left"])
            {
                CurrentButtons |= LibGambatte.Buttons.LEFT;
            }
            if (Controller["Right"])
            {
                CurrentButtons |= LibGambatte.Buttons.RIGHT;
            }
            if (Controller["A"])
            {
                CurrentButtons |= LibGambatte.Buttons.A;
            }
            if (Controller["B"])
            {
                CurrentButtons |= LibGambatte.Buttons.B;
            }
            if (Controller["Select"])
            {
                CurrentButtons |= LibGambatte.Buttons.SELECT;
            }
            if (Controller["Start"])
            {
                CurrentButtons |= LibGambatte.Buttons.START;
            }

            // the controller callback will set this to false if it actually gets called during the frame
            IsLagFrame = true;

            if (Controller["Power"])
            {
                LibGambatte.gambatte_reset(GambatteState, GetCurrentTime());
            }

            if (Tracer.Enabled)
            {
                tracecb = MakeTrace;
            }
            else
            {
                tracecb = null;
            }
            LibGambatte.gambatte_settracecallback(GambatteState, tracecb);

            LibGambatte.gambatte_setlayers(GambatteState, (_settings.DisplayBG ? 1 : 0) | (_settings.DisplayOBJ ? 2 : 0) | (_settings.DisplayWindow ? 4 : 0));
        }
Example #15
0
 void NewLoadCoreBinary(byte[] data)
 {
     if (!LibGambatte.gambatte_newstateload(GambatteState, data, data.Length))
     {
         throw new Exception("gambatte_newstateload() returned false");
     }
 }
Example #16
0
        public bool FrameAdvance(IController controller, bool render, bool rendersound)
        {
            FrameAdvancePrep(controller);
            if (_syncSettings.EqualLengthFrames)
            {
                while (true)
                {
                    // target number of samples to emit: length of 1 frame minus whatever overflow
                    uint samplesEmitted = TICKSINFRAME - frameOverflow;
                    Debug.Assert(samplesEmitted * 2 <= _soundbuff.Length);
                    if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                    {
                        LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                    }

                    // account for actual number of samples emitted
                    _cycleCount   += samplesEmitted;
                    frameOverflow += samplesEmitted;

                    if (rendersound && !Muted)
                    {
                        ProcessSound((int)samplesEmitted);
                    }

                    if (frameOverflow >= TICKSINFRAME)
                    {
                        frameOverflow -= TICKSINFRAME;
                        break;
                    }
                }
            }
            else
            {
                // target number of samples to emit: always 59.7fps
                // runfor() always ends after creating a video frame, so sync-up is guaranteed
                // when the display has been off, some frames can be markedly shorter than expected
                uint samplesEmitted = TICKSINFRAME;
                if (LibGambatte.gambatte_runfor(GambatteState, _soundbuff, ref samplesEmitted) > 0)
                {
                    LibGambatte.gambatte_blitto(GambatteState, VideoBuffer, 160);
                }

                _cycleCount  += samplesEmitted;
                frameOverflow = 0;
                if (rendersound && !Muted)
                {
                    ProcessSound((int)samplesEmitted);
                }
            }

            if (rendersound && !Muted)
            {
                ProcessSoundEnd();
            }

            FrameAdvancePost();

            return(true);
        }
Example #17
0
        private void RefreshMemoryCallbacks()
        {
            var mcs = MemoryCallbacks;

            LibGambatte.gambatte_setreadcallback(GambatteState, mcs.HasReads ? _readcb : null);
            LibGambatte.gambatte_setwritecallback(GambatteState, mcs.HasWrites ? _writecb : null);
            LibGambatte.gambatte_setexeccallback(GambatteState, mcs.HasExecutes ? _execcb : null);
        }
        private void NewSaveCoreSetBuff()
        {
#if USE_UPSTREAM_STATES
            _stateBuf = new byte[LibGambatte.gambatte_savestate(GambatteState, null, 160, null)];
#else
            _stateBuf = new byte[LibGambatte.gambatte_newstatelen(GambatteState)];
#endif
        }
Example #19
0
 byte[] NewSaveCoreBinary()
 {
     if (!LibGambatte.gambatte_newstatesave(GambatteState, newsavebuff, newsavebuff.Length))
     {
         throw new Exception("gambatte_newstatesave() returned false");
     }
     return(newsavebuff);
 }
Example #20
0
 public void StoreSaveRam(byte[] data)
 {
     if (data.Length != LibGambatte.gambatte_savesavedatalength(GambatteState))
     {
         throw new ArgumentException("Size of saveram data does not match expected!");
     }
     LibGambatte.gambatte_loadsavedata(GambatteState, data);
 }
 public void SetCpuRegister(string register, int value)
 {
     int[] data = new int[10];
     LibGambatte.gambatte_getregs(GambatteState, data);
     LibGambatte.RegIndices index = (LibGambatte.RegIndices)Enum.Parse(typeof(LibGambatte.RegIndices), register);
     data[(int)index] = value & (index <= LibGambatte.RegIndices.SP ? 0xffff : 0xff);
     LibGambatte.gambatte_setregs(GambatteState, data);
 }
Example #22
0
        internal void FrameAdvancePost()
        {
            if (IsLagFrame)
            {
                LagCount++;
            }

            endofframecallback?.Invoke(LibGambatte.gambatte_cpuread(GambatteState, 0xff40));
        }
Example #23
0
 public void Dispose()
 {
     if (GambatteState != IntPtr.Zero)
     {
         LibGambatte.gambatte_destroy(GambatteState);
         GambatteState = IntPtr.Zero;
     }
     DisposeSound();
 }
Example #24
0
        void OnSerial()
        {
            if (LibGambatte.gambatte_linkstatus(gb.GambatteState, 256) != 0)                              // ClockTrigger
            {
                LibGambatte.gambatte_linkstatus(gb.GambatteState, 257);                                   // ack

                byte output = HandleSerial((byte)LibGambatte.gambatte_linkstatus(gb.GambatteState, 258)); // GetOut
                LibGambatte.gambatte_linkstatus(gb.GambatteState, output);                                // ShiftIn
            }
        }
Example #25
0
        public GambattePrinter(Gameboy gb, PrinterCallback callback)
        {
            this.gb       = gb;
            this.callback = callback;

            linkCallback = OnSerial;
            LibGambatte.gambatte_setlinkcallback(gb.GambatteState, linkCallback);

            // connect the cable
            LibGambatte.gambatte_linkstatus(gb.GambatteState, 259);
        }
Example #26
0
 void ICodeDataLogger.SetCDL(CodeDataLog cdl)
 {
     CDL = cdl;
     if (cdl == null)
     {
         LibGambatte.gambatte_setcdcallback(GambatteState, null);
     }
     else
     {
         LibGambatte.gambatte_setcdcallback(GambatteState, CDCallback);
     }
 }
Example #27
0
        internal void FrameAdvancePost()
        {
            if (IsLagFrame)
            {
                LagCount++;
            }

            if (endofframecallback != null)
            {
                endofframecallback(LibGambatte.gambatte_cpuread(GambatteState, 0xff40));
            }
        }
Example #28
0
        internal void LoadState(TextState <TextStateData> s)
        {
            s.Prepare();
            var ff = s.GetFunctionPointersLoad();

            LibGambatte.gambatte_newstateload_ex(GambatteState, ref ff);
            IsLagFrame    = s.ExtraData.IsLagFrame;
            LagCount      = s.ExtraData.LagCount;
            Frame         = s.ExtraData.Frame;
            frameOverflow = s.ExtraData.frameOverflow;
            _cycleCount   = s.ExtraData._cycleCount;
        }
		void CreateMemoryDomain(LibGambatte.MemoryAreas which, string name)
		{
			IntPtr data = IntPtr.Zero;
			int length = 0;

			if (!LibGambatte.gambatte_getmemoryarea(GambatteState, which, ref data, ref length))
				throw new Exception("gambatte_getmemoryarea() failed!");

			// if length == 0, it's an empty block; (usually rambank on some carts); that's ok
			if (data != IntPtr.Zero && length > 0)
				_memoryDomains.Add(MemoryDomain.FromIntPtr(name, length, MemoryDomain.Endian.Little, data));
		}
Example #30
0
        public byte[] CloneSaveRam()
        {
            int length = LibGambatte.gambatte_savesavedatalength(GambatteState, DeterministicEmulation);

            if (length > 0)
            {
                byte[] ret = new byte[length];
                LibGambatte.gambatte_savesavedata(GambatteState, ret, DeterministicEmulation);
                return(ret);
            }

            return(new byte[0]);
        }
Example #31
0
        public GPUMemoryAreas GetGPU()
        {
            int unused = 0;

            if (!LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.vram, ref _vram, ref unused) ||
                !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.bgpal, ref _bgpal, ref unused) ||
                !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.sppal, ref _sppal, ref unused) ||
                !LibGambatte.gambatte_getmemoryarea(GambatteState, LibGambatte.MemoryAreas.oam, ref _oam, ref unused))
            {
                throw new InvalidOperationException("Unexpected error in gambatte_getmemoryarea");
            }
            return(new GPUMemoryAreas(_vram, _oam, _sppal, _bgpal));
        }
Example #32
0
		void CDCallbackProc(int addr, LibGambatte.CDLog_AddrType addrtype, LibGambatte.CDLog_Flags flags)
		{
			if (CDL == null) return;
			if (!CDL.Active) return;
			string key;
			switch (addrtype)
			{
				case LibGambatte.CDLog_AddrType.ROM: key = "ROM"; break;
				case LibGambatte.CDLog_AddrType.HRAM: key = "HRAM"; break;
				case LibGambatte.CDLog_AddrType.WRAM: key = "WRAM"; break;
				case LibGambatte.CDLog_AddrType.CartRAM: key = "CartRAM"; break;
				default: throw new InvalidOperationException("Juniper lightbulb proxy");
			}
			CDL[key][addr] |= (byte)flags;
		}
Example #33
0
		unsafe void CreateMemoryDomain(LibGambatte.MemoryAreas which, string name)
		{
			IntPtr data = IntPtr.Zero;
			int length = 0;

			if (!LibGambatte.gambatte_getmemoryarea(GambatteState, which, ref data, ref length))
				throw new Exception("gambatte_getmemoryarea() failed!");

			// if length == 0, it's an empty block; (usually rambank on some carts); that's ok
			// TODO: when length == 0, should we simply not add the memory domain at all?
			if (data == IntPtr.Zero && length > 0)
				throw new Exception("bad return from gambatte_getmemoryarea()");

			byte* ptr = (byte*)data;

			_MemoryDomains.Add(new MemoryDomain(name, length, MemoryDomain.Endian.Little,
				delegate(int addr)
				{
					if (addr < 0 || addr >= length)
						throw new ArgumentOutOfRangeException();
					return ptr[addr];
				},
				delegate(int addr, byte val)
				{
					if (addr < 0 || addr >= length)
						throw new ArgumentOutOfRangeException();
					ptr[addr] = val;
				}));
		}