public Instruction[] Disassemble(int address, int count) { List <Instruction> opcodes = new List <Instruction>(); int ptr = address; for (int i = 0; i < count; i++) { int pc = ptr; byte opcode = this._memory.ReadByte(ptr); string prototype; if (opcode == 0xCB) { ptr++; opcode = this._memory.ReadByte(ptr); prototype = _prototypes_cb[opcode]; } else { prototype = _prototypes[opcode]; } ptr++; if (prototype.Contains("d8")) { prototype = prototype.Replace("d8", string.Format("0x{0:X2}", _memory.ReadByte(ptr))); ptr++; } if (prototype.Contains("d16")) { prototype = prototype.Replace("d16", string.Format("0x{0:X4}", (_memory.ReadByte(ptr + 1) << 8) + _memory.ReadByte(ptr))); ptr += 2; } if (prototype.Contains("a8")) { prototype = prototype.Replace("a8", string.Format("0x{0:X4}", 0xff00 + _memory.ReadByte(ptr))); ptr++; } if (prototype.Contains("a16")) { prototype = prototype.Replace("a16", string.Format("0x{0:X4}", (_memory.ReadByte(ptr + 1) << 8) + _memory.ReadByte(ptr))); ptr += 2; } if (prototype.Contains("r8")) { int value = _memory.ReadByte(ptr); if (value > 0x7F) { value -= 256; } prototype = prototype.Replace("r8", string.Format("0x{0:X4}", ptr + value + 1)); ptr++; } opcodes.Add(new Instruction(prototype, pc, ptr - pc)); } return(opcodes.ToArray()); }
public byte ReadByte(int address) { if (address <= 0x7FFF) { return(mbc.ReadByte(address)); } else if (address <= 0x9FFF) { return(Video.ReadVRAM(address - 0x8000)); } else if (address <= 0xBFFF) { return(mbc.ReadByte(address)); } else if (address <= 0xCFFF) { return(wram[0, address - 0xC000]); } else if (address <= 0xDFFF) { return(wram[wrambank, address - 0xD000]); } else if (address <= 0xEFFF) { return(wram[0, address - 0xE000]); } else if (address <= 0xFDFF) { return(wram[wrambank, address - 0xF000]); } else if (address <= 0xFE9F) { return(Video.ReadOAM(address - 0xFE00)); } else if (address <= 0xFEFF) { // Not usable return(0); } else if (address <= 0xFF7F) { int value = 0; switch (address - 0xFF00) { case 0x00: // Joypad value = Joypad.SelectButtonKeys ? 0x00 : 0x20; value += Joypad.SelectDirectionKeys ? 0x00 : 0x10; if (Joypad.SelectButtonKeys) { value += Joypad.KeyB ? 0x02 : 0x00; value += Joypad.KeyA ? 0x01 : 0x00; } else { value += Joypad.KeyLeft ? 0x02 : 0x00; value += Joypad.KeyRight ? 0x01 : 0x00; } if (Joypad.SelectDirectionKeys) { value += Joypad.KeyDown ? 0x08 : 0x00; value += Joypad.KeyUp ? 0x04 : 0x00; } else { value += Joypad.KeyStart ? 0x08 : 0x00; value += Joypad.KeySelect ? 0x04 : 0x00; } return((byte)value); case 0x01: // SB Serial transfer data return(serial.Read()); case 0x04: // Divider Register return((byte)Timer.DIV); case 0x05: // Timer Counter return((byte)Timer.TIMA); case 0x06: // Timer Modulo return((byte)Timer.TMA); case 0x07: // Timer Control return((byte)Timer.TAC); case 0x0F: // Interrupt Flag return((byte)Interrupt.IF); case 0x10: // NR10 Channel 1 Sweep register value = Audio.Channel1.SweepShift | ((int)Audio.Channel1.SweepDirection << 3) | (Audio.Channel1.SweepTime << 4); return((byte)value); case 0x11: // NR11 Channel 1 Sound length/Wave pattern duty value = Audio.Channel1.SoundLengthRaw | (Audio.Channel1.WavePatternDuty << 6); return((byte)value); case 0x12: // NR12 Channel 1 Volume Envelope value = Audio.Channel1.EnvelopeSweep | ((int)Audio.Channel1.EnvelopeDirection << 3) | (Audio.Channel1.Volume << 4); return((byte)value); case 0x14: // NR14 Channel 1 Frequency hi return((byte)(Audio.Channel1.StopOnLengthExpired ? 0x40 : 0x00)); case 0x16: // NR21 Channel 2 Sound length/Wave pattern duty value = Audio.Channel2.SoundLengthRaw | (Audio.Channel2.WavePatternDuty << 6); return((byte)value); case 0x17: // NR22 Channel 2 Volume Envelope value = Audio.Channel2.EnvelopeSweep | ((int)Audio.Channel2.EnvelopeDirection << 3) | (Audio.Channel2.Volume << 4); return((byte)value); case 0x19: // NR24 Channel 2 Frequency hi return((byte)(Audio.Channel2.StopOnLengthExpired ? 0x40 : 0x00)); case 0x1A: // NR30 Channel 3 Sound on/off return((byte)(Audio.Channel3.On ? 0x80 : 0x00)); case 0x1B: // NR31 Channel 3 Sound Length return((byte)Audio.Channel3.SoundLengthRaw); case 0x1C: // NR32 Channel 3 Select output level return((byte)(Audio.Channel3.OutputLevel << 5)); case 0x1E: // NR33 Channel 3 Frequency hi return((byte)(Audio.Channel3.StopOnLengthExpired ? 0x40 : 0x00)); case 0x20: case 0x21: case 0x22: case 0x23: throw new NotImplementedException(); // FF30-FF3F Wave Pattern RAM case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: value = Audio.Channel3.WaveRAM[(address & 0xF) * 2 + 1] | (Audio.Channel3.WaveRAM[(address & 0xF) * 2] << 4); return((byte)value); case 0x40: // LCDC value = Video.LCDEnable ? 0x80 : 0x0; value += Video.WindowTileMapSelect ? 0x40 : 0x0; value += Video.WindowEnable ? 0x20 : 0x0; value += Video.TileDataSelect ? 0x10 : 0x0; value += Video.BackgroundTileMapSelect ? 0x08 : 0x0; value += Video.ObjectSize ? 0x04 : 0x0; value += Video.ObjectEnable ? 0x02 : 0x0; value += Video.BackgroundEnable ? 0x01 : 0x0; return((byte)value); case 0x41: // LCDC STAT value = Video.CoincidenceInterrupt ? 0x40 : 0x0; value += Video.OAMInterrupt ? 0x20 : 0x0; value += Video.VBlankInterrupt ? 0x10 : 0x0; value += Video.HBlankInterrupt ? 0x08 : 0x0; value += Video.CoincidenceFlag ? 0x04 : 0x0; value += Video.ModeFlag & 0x03; return((byte)value); case 0x42: // SCY return((byte)Video.SCY); case 0x43: // SCX return((byte)Video.SCX); case 0x44: // LY return((byte)Video.LY); case 0x45: // LYC return((byte)Video.LYC); case 0x47: // BGP return((byte)Video.BGP); case 0x48: // OBP0 return((byte)Video.OBP0); case 0x49: // OBP1 return((byte)Video.OBP1); case 0x4A: // WY return((byte)Video.WY); case 0x4B: // WX return((byte)Video.WX); case 0x4D: // Prepare Speed Switch value = cpu.IsDoubleSpeed ? 0x80 : 0x00; value |= cpu.PrepareSpeedSwitch ? 1 : 0; return((byte)value); case 0x4F: // VRAM bank return((byte)Video.VRAMBank); case 0x51: // HDMA Source, High return((byte)(hdma.SourceAddress >> 8)); case 0x52: // HDMA Source, Low return((byte)hdma.SourceAddress); case 0x53: // HDMA Destination, High return((byte)(hdma.DestinationAddress >> 8)); case 0x54: // HDMA Destination, Low return((byte)hdma.DestinationAddress); case 0x55: // HDMA Length/Mode/Start value = (hdma.Length / 0x10 - 1) | (hdma.IsHBlank ? 0x80 : 0x00); return((byte)value); case 0x68: // Background Palette Index value = Video.BackgroundPaletteIndex; value |= Video.BackgroundPaletteAI ? 0x80 : 0x00; return((byte)value); case 0x69: // Background Palette Data return(Video.ReadPRAM(0)); case 0x6A: // Object Palette Index value = Video.ObjectPaletteIndex; value |= Video.ObjectPaletteAI ? 0x80 : 0x00; return((byte)value); case 0x6B: // Object Palette Data return(Video.ReadPRAM(1)); case 0x70: // WRAM bank return((byte)wrambank); default: //throw new Exception(string.Format("Unknown IO port at 0x{0:X} (READ)", address)); return(0); } } else if (address <= 0xFFFE) { return(hram[address - 0xFF80]); } else { return((byte)Interrupt.IE); } }