Пример #1
0
 public void CpuWriteBE<T>(int addr, T data) where T : struct {
     switch(Type.GetTypeCode(typeof(T))) {
         case TypeCode.Byte:
         case TypeCode.SByte:
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr), (byte) (object) data);
             break;
         case TypeCode.Int16:
         case TypeCode.UInt16:
             ushort u16 = (ushort) (object) data;
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr), (byte) (u16 >> 8));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 1), (byte) (u16 & 0xff));
             break;
         case TypeCode.Int32:
         case TypeCode.UInt32:
             uint u32 = (uint) (object) data;
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr), (byte) (u32 >> 24));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 1), (byte) (u32 >> 16));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 2), (byte) (u32 >> 8));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 3), (byte) (u32 & 0xff));
             break;
         case TypeCode.Int64:
         case TypeCode.UInt64:
             ulong u64 = (ulong) (object) data;
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr), (byte) (u64 >> 56));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 1), (byte) (u64 >> 48));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 2), (byte) (u64 >> 40));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 3), (byte) (u64 >> 32));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 4), (byte) (u64 >> 24));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 5), (byte) (u64 >> 16));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 6), (byte) (u64 >> 8));
             Libgambatte.gambatte_cpuwrite(Handle, (ushort) (addr + 7), (byte) (u64 & 0xff));
             break;
     }
 }
Пример #2
0
 // Emulates until the next video frame has to be drawn. Returns the hit address.
 public int AdvanceFrame(Joypad joypad = Joypad.None)
 {
     CurrentJoypad = joypad;
     RunFor(SamplesPerFrame - BufferSamples);
     CurrentJoypad = Joypad.None;
     return(Libgambatte.gambatte_gethitinterruptaddress(Handle));
 }
Пример #3
0
    public T CpuReadBE <T>(int addr) where T : struct
    {
        switch (Type.GetTypeCode(typeof(T)))
        {
        case TypeCode.Byte:
        case TypeCode.SByte:
            return((T)(object)Libgambatte.gambatte_cpuread(Handle, (ushort)(addr)));

        case TypeCode.Int16:
        case TypeCode.UInt16:
            return((T)(object)(ushort)((Libgambatte.gambatte_cpuread(Handle, (ushort)(addr)) << 8) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 1)))));

        case TypeCode.Int32:
        case TypeCode.UInt32:
            return((T)(object)(uint)((Libgambatte.gambatte_cpuread(Handle, (ushort)(addr)) << 24) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 1)) << 16) |
                                     (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 2)) << 8) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 3)))));

        case TypeCode.Int64:
        case TypeCode.UInt64:
            return((T)(object)(ulong)((Libgambatte.gambatte_cpuread(Handle, (ushort)(addr)) << 56) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 1)) << 48) |
                                      (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 2)) << 40) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 3)) << 32) |
                                      (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 4)) << 24) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 5)) << 16) |
                                      (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 6)) << 8) | (Libgambatte.gambatte_cpuread(Handle, (ushort)(addr + 7)))));

        default: return(default);
        }
    }
Пример #4
0
 public void Dispose()
 {
     if (Scene != null)
     {
         Scene.Dispose();
     }
     Libgambatte.gambatte_destroy(Handle);
 }
Пример #5
0
    // Emulates while holding the specified input until the program counter hits one of the specified breakpoints.
    public unsafe virtual int Hold(Joypad joypad, params int[] addrs)
    {
        fixed(int *addrPtr = addrs)   // Note: Not fixing the pointer causes an AccessValidationException.
        {
            Libgambatte.gambatte_setinterruptaddresses(Handle, addrPtr, addrs.Length);
            int hitaddress;

            do
            {
                hitaddress = AdvanceFrame(joypad);
            } while(Array.IndexOf(addrs, hitaddress) == -1);
            Libgambatte.gambatte_setinterruptaddresses(Handle, null, 0);
            return(hitaddress);
        }
    }
Пример #6
0
    public GameBoy(string biosFile, string romFile, SpeedupFlags speedupFlags = SpeedupFlags.None)
    {
        ROM = new ROM(romFile);
        Debug.Assert(ROM.HeaderChecksumMatches(), "Cartridge header checksum mismatch!");

        Handle = Libgambatte.gambatte_create();
        Debug.Assert(Libgambatte.gambatte_loadbios(Handle, biosFile, 0x900, 0x31672598) == 0, "Unable to load BIOS!");
        Debug.Assert(Libgambatte.gambatte_load(Handle, romFile, LoadFlags.GbaFlag | LoadFlags.GcbMode | LoadFlags.ReadOnlySav) == 0, "Unable to load ROM!");

        VideoBuffer = new byte[160 * 144 * 4];
        AudioBuffer = new byte[(SamplesPerFrame + 2064) * 2 * 2]; // Stereo 16-bit samples

        InputGetter = () => CurrentJoypad;
        Libgambatte.gambatte_setinputgetter(Handle, InputGetter);

        string symPath = "symfiles/" + Path.GetFileNameWithoutExtension(romFile) + ".sym";

        if (File.Exists(symPath))
        {
            SYM         = new SYM(symPath);
            ROM.Symbols = SYM;
        }

        SetSpeedupFlags(speedupFlags);
        StateSize = Libgambatte.gambatte_savestate(Handle, null, 160, null);

        SaveStateLabels = new Dictionary <string, int>();
        byte[]     state = SaveState();
        ByteStream data  = new ByteStream(state);

        data.Seek(3);
        data.Seek(data.u24be());
        while (data.Position < state.Length)
        {
            string label = "";
            byte   character;
            while ((character = data.u8()) != 0x00)
            {
                label += Convert.ToChar(character);
            }
            int size = data.u24be();
            SaveStateLabels[label] = (int)data.Position;
            data.Seek(size);
        }
    }
Пример #7
0
    // Emulates 'runsamples' number of samples, or until a video frame has to be drawn. (1 sample = 2 cpu cycles)
    public int RunFor(int runsamples)
    {
        int videoFrameDoneSampleCount = Libgambatte.gambatte_runfor(Handle, VideoBuffer, 160, AudioBuffer, ref runsamples);
        int outsamples = videoFrameDoneSampleCount >= 0 ? BufferSamples + videoFrameDoneSampleCount : BufferSamples + runsamples;

        BufferSamples   += runsamples;
        BufferSamples   -= outsamples;
        EmulatedSamples += (ulong)outsamples;

        if (Scene != null)
        {
            Scene.OnAudioReady(outsamples);
            // returns a positive value if the video frame hass been completed.
            if (videoFrameDoneSampleCount >= 0)
            {
                Scene.Begin();
                Scene.Render();
                Scene.End();
            }
        }

        return(runsamples);
    }
Пример #8
0
    // Emulates 'runsamples' number of samples, or until a video frame has to be drawn. (1 sample = 2 cpu cycles)
    public int RunFor(int runsamples)
    {
        int videoFrameDoneSampleCount = Libgambatte.gambatte_runfor(Handle, VideoBuffer, 160, AudioBuffer, ref runsamples);
        int outsamples = videoFrameDoneSampleCount >= 0 ? BufferSamples + videoFrameDoneSampleCount : BufferSamples + runsamples;

        BufferSamples   += runsamples;
        BufferSamples   -= outsamples;
        EmulatedSamples += (ulong)outsamples;

        if (Scene != null)
        {
            Scene.OnAudioReady(outsamples);
            // returns a positive value if a video frame needs to be drawn.
            if (videoFrameDoneSampleCount >= 0)
            {
                Scene.Begin();
                Scene.Render();
                Scene.End();
            }
        }

        return(Libgambatte.gambatte_gethitinterruptaddress(Handle));
    }
Пример #9
0
    public GameBoy(string biosFile, string romFile, string savFile = null, SpeedupFlags speedupFlags = SpeedupFlags.None)
    {
        ROM = new ROM(romFile);
        Debug.Assert(ROM.HeaderChecksumMatches(), "Cartridge header checksum mismatch!");

        string romName = Path.GetFileNameWithoutExtension(romFile);

        if (savFile == null || savFile == "")
        {
            File.Delete("roms/" + romName + ".sav");
        }
        else
        {
            File.WriteAllBytes("roms/" + romName + ".sav", File.ReadAllBytes(savFile));
        }

        Handle = Libgambatte.gambatte_create();
        Debug.Assert(Libgambatte.gambatte_loadbios(Handle, biosFile, 0x900, 0x31672598) == 0, "Unable to load BIOS!");
        Debug.Assert(Libgambatte.gambatte_load(Handle, romFile, LoadFlags.GbaFlag | LoadFlags.GcbMode | LoadFlags.ReadOnlySav) == 0, "Unable to load ROM!");

        VideoBuffer = new byte[160 * 144 * 4];
        AudioBuffer = new byte[(SamplesPerFrame + 2064) * 2 * 2]; // Stereo 16-bit samples

        InputGetter = () => CurrentJoypad;
        Libgambatte.gambatte_setinputgetter(Handle, InputGetter);

        string symPath = "symfiles/" + romName + ".sym";

        if (File.Exists(symPath))
        {
            SYM         = new SYM(symPath);
            ROM.Symbols = SYM;
        }

        SetSpeedupFlags(speedupFlags);
        StateSize = Libgambatte.gambatte_savestate(Handle, null, 160, null);
    }
Пример #10
0
 public void SetRTCDivisorOffset(int rtcDivisorOffset)
 {
     Libgambatte.gambatte_setrtcdivisoroffset(Handle, rtcDivisorOffset);
 }
Пример #11
0
 // Sets flags to control non-critical processes for CPU-concerned emulation.
 public void SetSpeedupFlags(SpeedupFlags flags)
 {
     Libgambatte.gambatte_setspeedupflags(Handle, flags);
 }
Пример #12
0
 // Loads the emulator state given by a buffer.
 public void LoadState(byte[] buffer)
 {
     Libgambatte.gambatte_loadstate(Handle, buffer, buffer.Length);
 }
Пример #13
0
 // Returns the emulator state as a buffer.
 public byte[] SaveState()
 {
     byte[] state = new byte[StateSize];
     Libgambatte.gambatte_savestate(Handle, null, 160, state);
     return(state);
 }
Пример #14
0
 // Reads one byte of data from the CPU bus.
 public byte CpuRead(int addr)
 {
     return(Libgambatte.gambatte_cpuread(Handle, (ushort)addr));
 }
Пример #15
0
 // Writes one byte of data to the CPU bus.
 public void CpuWrite(int addr, byte data)
 {
     Libgambatte.gambatte_cpuwrite(Handle, (ushort)addr, data);
 }
Пример #16
0
 public void HardReset(bool fade = false)
 {
     Libgambatte.gambatte_reset(Handle, fade ? 101 * (2 << 14) : 0);
     BufferSamples = 0;
 }