Пример #1
0
        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());
        }
Пример #2
0
        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);
            }
        }