Ejemplo n.º 1
0
        public byte ReadByte(int address)
        {
            if (address < 0XFF)
            {
                return(_bios[address]);
            }

            if (address < 0x8000)
            {
                return(_cartridge.ReadByte(address));
            }
            if (address < 0xA000)
            {
                return(_gpu.ReadByte(address));
            }
            if (address < 0xC000)
            {
                return(_cartridge.ReadByte(address));
            }
            if (address < 0xFE00)
            {
                return(_lowRam[address]);
            }
            if (address < 0xFEA0)
            {
                return(_gpu.ReadByte(address));
            }
            if (address < 0xFF40)
            {
                return(_sound[address - 0xFF00]);
            }
            if (address < 0xFF80)
            {
                return(_gpu.ReadByte(address));
            }
            if (address < 0xFFFF) // FF80 -> FFFE
            {
                return(_highRam[address & 0x7F]);
            }



            return(GetBufferArea(address)[0]);

            throw new NotImplementedException("MMU failed at address " + address);
        }
Ejemplo n.º 2
0
        public void WriteByteTest(ushort address, byte value, byte expected)
        {
            var data = new byte[0x8000];

            _cartridge = new Cartridge(data);


            _cartridge.WriteByte(address, value);


            Assert.Equal(expected, _cartridge.ReadByte(address));
        }
Ejemplo n.º 3
0
        public void ReadByteTest(ushort address, byte expected)
        {
            var data = new byte[0x8000];

            if (address < data.Length)
            {
                data[address] = expected;
            }

            _cartridge = new Cartridge(data);

            Assert.Equal(expected, _cartridge.ReadByte(address));
        }
Ejemplo n.º 4
0
 // For debugging display
 public string NextThreeBytes()
 {
     return(cartridge.ReadByte(PC).ToString("X2") + " " + cartridge.ReadByte((ushort)(PC + 1)).ToString("X2") + " " + cartridge.ReadByte((ushort)(PC + 2)).ToString("X2"));
 }
Ejemplo n.º 5
0
        public int ReadByte(int address)
        {
            if (address <= 0x7FFF || (address >= 0xA000 && address <= 0xBFFF))
            {
                return(cartridge.ReadByte(address));
            }
            else if (address >= 0x8000 && address <= 0x9FFF)
            {
                return(vRam[address - 0x8000]);
            }
            else if (address >= 0xC000 && address <= 0xDFFF)
            {
                return(wRam[address - 0xC000]);
            }
            else if (address >= 0xE000 && address <= 0xFDFF)
            {
                return(wRam[address - 0xE000]);
            }
            else if (address >= 0xFE00 && address <= 0xFEFF)
            {
                return(oam[address - 0xFE00]);
            }
            else if (address >= 0xFF80 && address <= 0xFFFE)
            {
                return(highRam[0xFF & address]);
            }
            else
            {
                switch (address)
                {
                case 0xFF00:     // key pad
                    if (keyP14)
                    {
                        int value = 0;
                        if (!downKeyPressed)
                        {
                            value |= 0x08;
                        }
                        if (!upKeyPressed)
                        {
                            value |= 0x04;
                        }
                        if (!leftKeyPressed)
                        {
                            value |= 0x02;
                        }
                        if (!rightKeyPressed)
                        {
                            value |= 0x01;
                        }
                        return(value);
                    }
                    else if (keyP15)
                    {
                        int value = 0;
                        if (!startButtonPressed)
                        {
                            value |= 0x08;
                        }
                        if (!selectButtonPressed)
                        {
                            value |= 0x04;
                        }
                        if (!bButtonPressed)
                        {
                            value |= 0x02;
                        }
                        if (!aButtonPressed)
                        {
                            value |= 0x01;
                        }
                        return(value);
                    }
                    break;

                case 0xFF04:     // Timer divider
                    return(Z80.ticks & 0xFF);

                case 0xFF05:     // Timer counter
                    return(Z80.timerCounter & 0xFF);

                case 0xFF06:     // Timer modulo
                    return(Z80.timerModulo & 0xFF);

                case 0xFF07:
                {         // Time Control
                    int value = 0;
                    if (Z80.timerRunning)
                    {
                        value |= 0x04;
                    }
                    value |= (int)Z80.timerFrequency;
                    return(value);
                }

                case 0xFF0F:
                {         // Interrupt Flag (an interrupt request)
                    int value = 0;
                    if (Z80.keyPressedInterruptRequested)
                    {
                        value |= 0x10;
                    }
                    if (Z80.serialIOTransferCompleteInterruptRequested)
                    {
                        value |= 0x08;
                    }
                    if (Z80.timerOverflowInterruptRequested)
                    {
                        value |= 0x04;
                    }
                    if (Z80.lcdcInterruptRequested)
                    {
                        value |= 0x02;
                    }
                    if (Z80.vBlankInterruptRequested)
                    {
                        value |= 0x01;
                    }
                    return(value);
                }

                case 0xFF40:
                {         // LCDC control
                    int value = 0;
                    if (Z80.lcdControlOperationEnabled)
                    {
                        value |= 0x80;
                    }
                    if (GPU.windowTileMapDisplaySelect)
                    {
                        value |= 0x40;
                    }
                    if (GPU.windowDisplayed)
                    {
                        value |= 0x20;
                    }
                    if (GPU.backgroundAndWindowTileDataSelect)
                    {
                        value |= 0x10;
                    }
                    if (GPU.backgroundTileMapDisplaySelect)
                    {
                        value |= 0x08;
                    }
                    if (GPU.largeSprites)
                    {
                        value |= 0x04;
                    }
                    if (GPU.spritesDisplayed)
                    {
                        value |= 0x02;
                    }
                    if (GPU.backgroundDisplayed)
                    {
                        value |= 0x01;
                    }
                    return(value);
                }

                case 0xFF41:
                {        // LCDC Status
                    int value = 0;
                    if (GPU.lcdcLycLyCoincidenceInterruptEnabled)
                    {
                        value |= 0x40;
                    }
                    if (GPU.lcdcOamInterruptEnabled)
                    {
                        value |= 0x20;
                    }
                    if (GPU.lcdcVBlankInterruptEnabled)
                    {
                        value |= 0x10;
                    }
                    if (GPU.lcdcHBlankInterruptEnabled)
                    {
                        value |= 0x08;
                    }
                    if (GPU.ly == GPU.lyCompare)
                    {
                        value |= 0x04;
                    }
                    value |= (int)GPU.lcdcMode;
                    return(value);
                }

                case 0xFF42:     // Scroll Y
                    return(GPU.scrollY);

                case 0xFF43:     // Scroll X
                    return(GPU.scrollX);

                case 0xFF44:     // LY
                    return(GPU.ly);

                case 0xFF45:     // LY Compare
                    return(GPU.lyCompare);

                case 0xFF47:
                {         // Background palette
                    GPU.invalidateAllBackgroundTilesRequest = true;
                    int value = 0;
                    for (int i = 3; i >= 0; i--)
                    {
                        value <<= 2;
                        switch (GPU.backgroundPalette[i])
                        {
                        case 0xFF000000:
                            value |= 3;
                            break;

                        case 0xFF555555:
                            value |= 2;
                            break;

                        case 0xFFAAAAAA:
                            value |= 1;
                            break;

                        case 0xFFFFFFFF:
                            break;
                        }
                    }
                    return(value);
                }

                case 0xFF48:
                {         // Object palette 0
                    GPU.invalidateAllSpriteTilesRequest = true;
                    int value = 0;
                    for (int i = 3; i >= 0; i--)
                    {
                        value <<= 2;
                        switch (GPU.objectPallete0[i])
                        {
                        case 0xFF000000:
                            value |= 3;
                            break;

                        case 0xFF555555:
                            value |= 2;
                            break;

                        case 0xFFAAAAAA:
                            value |= 1;
                            break;

                        case 0xFFFFFFFF:
                            break;
                        }
                    }
                    return(value);
                }

                case 0xFF49:
                {         // Object palette 1
                    GPU.invalidateAllSpriteTilesRequest = true;
                    int value = 0;
                    for (int i = 3; i >= 0; i--)
                    {
                        value <<= 2;
                        switch (GPU.objectPallete1[i])
                        {
                        case 0xFF000000:
                            value |= 3;
                            break;

                        case 0xFF555555:
                            value |= 2;
                            break;

                        case 0xFFAAAAAA:
                            value |= 1;
                            break;

                        case 0xFFFFFFFF:
                            break;
                        }
                    }
                    return(value);
                }

                case 0xFF4A:     // Window Y
                    return(GPU.windowY);

                case 0xFF4B:     // Window X
                    return(GPU.windowX);

                case 0xFFFF:
                {         // Interrupt Enable
                    int value = 0;
                    if (Z80.keyPressedInterruptEnabled)
                    {
                        value |= 0x10;
                    }
                    if (Z80.serialIOTransferCompleteInterruptEnabled)
                    {
                        value |= 0x08;
                    }
                    if (Z80.timerOverflowInterruptEnabled)
                    {
                        value |= 0x04;
                    }
                    if (Z80.lcdcInterruptEnabled)
                    {
                        value |= 0x02;
                    }
                    if (Z80.vBlankInterruptEnabled)
                    {
                        value |= 0x01;
                    }
                    return(value);
                }
                }
            }
            return(0);
        }
Ejemplo n.º 6
0
        public byte ReadByte(ushort addr)
        {
            if (addr < 0x8000)
            {
                if (RomMapMode == MapMode.Boot && addr < bootRom?.Length)
                {
                    return(bootRom[addr]);
                }
                else
                {
                    return(cartridge.ReadByte(addr));
                }
            }
            else if (addr < 0xA000)
            {
                return(videoRam[addr - 0x8000]);
            }
            else if (addr < 0xC000)
            {
                return(cartridge.ReadByte(addr));
            }
            else if (addr < 0xE000)
            {
                return(workRam[addr - 0xC000]);
            }
            else if (addr < 0xFE00)
            {
                // Echo of internal RAM
                return(workRam[addr - 0xE000]);
            }
            else if (addr < 0xFEA0)
            {
                return(oam[addr - 0xFE00]);
            }
            else if (addr < 0xFF00)
            {
                // Empty but unusable for I/O, return default bus value 0xFF
                return(0xFF);
            }
            else if (addr < 0xFF4C)
            {
                ioMasks.TryGetValue(addr, out byte mask);

                if (addr == 0xFF00)
                {
                    ioRegisters[0] = inputRegister.ReadValue(ioRegisters[0]);
                }

                return((byte)(ioRegisters[addr - 0xFF00] | mask));
            }
            else if (addr < 0xFF80)
            {
                // Empty but unusable for I/O, return default bus value 0xFF
                return(0xFF);
            }
            else if (addr < 0xFFFF)
            {
                return(highRam[addr - 0xFF80]);
            }
            else if (addr == 0xFFFF)
            {
                return(interruptEnableRegister);
            }
            else
            {
                throw new ArgumentException($"Could not read from illegal memory address: {addr:X4}");
            }
        }