public override byte Read(int address)
        {
            // Handle the C64 memory map and the bank switching capabilities of the 6510
            // http://sta.c64.org/cbm64mem.html
            // https://www.c64-wiki.com/wiki/Bank_Switching


            // Processor port. Configuration for memory areas. (Bits 0-2)
            // Memory location 0x01 is hard wired for bank switching
            var bankState = (BankMode)
                            ((byte)(_memory[1] & 0b00000111))
                            .SetBit(BitFlag.BIT_3, _game)
                            .SetBit(BitFlag.BIT_4, _exRom);


            // Always RAM (page 0-15)
            if (address >= 0x0000 && address <= 0x0FFF)
            {
                return(base.Read(address));
            }


            // Always RAM (page 16-127)
            // Except when EXROM==1 and GAME==0
            // Some exceptions for cartridge rom, not implemented yet
            if (address >= 0x1000 && address <= 0x7FFF)
            {
                // UNMAPPED
                if (_exRom && !_game)
                {
                    throw new AccessViolationException();
                }

                // RAM
                return(base.Read(address));
            }


            // Page 128-159
            // RAM OR CART ROM LO
            if (address >= 0x8000 && address <= 0x9FFF)
            {
                switch (bankState)
                {
                // CART ROM LO
                case BankMode.BANK_MODE_23:
                case BankMode.BANK_MODE_22:
                case BankMode.BANK_MODE_21:
                case BankMode.BANK_MODE_20:
                case BankMode.BANK_MODE_19:
                case BankMode.BANK_MODE_18:
                case BankMode.BANK_MODE_17:
                case BankMode.BANK_MODE_16:
                case BankMode.BANK_MODE_15:
                case BankMode.BANK_MODE_11:
                case BankMode.BANK_MODE_07:
                case BankMode.BANK_MODE_03:
                    return(_cartridge[address]);

                // RAM
                default:
                    return(base.Read(address));
                }
            }


            // BASIC ROM, RAM or CARTRIDGE ROM (page 160-191)
            if (address >= 0xA000 && address <= 0xBFFF)
            {
                // UNMAPPED
                if (_exRom && !_game)
                {
                    throw new AccessViolationException();
                }


                switch (bankState)
                {
                // BASIC
                case BankMode.BANK_MODE_31:
                case BankMode.BANK_MODE_27:
                case BankMode.BANK_MODE_15:
                case BankMode.BANK_MODE_11:
                    return(_romBasic.Read(address - 0xA000));

                // CART ROM HI
                case BankMode.BANK_MODE_07:
                case BankMode.BANK_MODE_06:
                case BankMode.BANK_MODE_03:
                case BankMode.BANK_MODE_02:
                    return(_cartridge[address]);

                // RAM
                default:
                    return(base.Read(address));
                }
            }


            // Always RAM (page 192-207)
            if (address >= 0xC000 && address <= 0xCFFF)
            {
                // UNMAPPED
                if (_exRom && !_game)
                {
                    throw new AccessViolationException();
                }

                // RAM
                return(base.Read(address));
            }


            // I/O, RAM, CHAR ROM (page 208-223)
            if (address >= 0xD000 && address <= 0xDFFF)
            {
                switch (bankState)
                {
                // IO
                case BankMode.BANK_MODE_31:
                case BankMode.BANK_MODE_30:
                case BankMode.BANK_MODE_14:
                case BankMode.BANK_MODE_29:
                case BankMode.BANK_MODE_13:
                case BankMode.BANK_MODE_23:
                case BankMode.BANK_MODE_22:
                case BankMode.BANK_MODE_21:
                case BankMode.BANK_MODE_20:
                case BankMode.BANK_MODE_19:
                case BankMode.BANK_MODE_18:
                case BankMode.BANK_MODE_17:
                case BankMode.BANK_MODE_16:
                case BankMode.BANK_MODE_15:
                case BankMode.BANK_MODE_07:
                case BankMode.BANK_MODE_06:
                case BankMode.BANK_MODE_05:

                    // VIC-II (0xD000 - 0xD3FF, VIC-II register images repeated every $40, 64 bytes)
                    if (address >= 0xD000 && address <= 0xD3FF)
                    {
                        // The VIC-II class has its own indexer which makes it easy to map
                        // addresses into the VIC-II. The `% 0x40` makes sure that the
                        // registers available in the VIC-II are mirrored all the way up to
                        // 0xD3FF.
                        return(_vic[(Register)((address - 0xD000) % 0x40)]);
                    }

                    // CIA 1
                    if (address >= 0xDC00 && address <= 0xDCFF)
                    {
                        switch (address)
                        {
                        case 0xDC09:
                            return(_cia.TimeOfDaySecondsBcd);

                        case 0xDC0A:
                            return(_cia.TimeOfDayMinutesBcd);

                        case 0xDC0B:
                            return(_cia.TimeOfDayHoursBcd);

                        default:
                            // The CIA class has its own indexer which makes it easy to map
                            // addresses into the CIA. The `% 0x10` makes sure that the
                            // 16 registers available in the CIA are mirrored all the way up to
                            // 0xDCFF.
                            return(_cia[(address - 0xDC00) % 0x10]);
                        }
                    }

                    // CIA 2
                    if (address >= 0xDD00 && address <= 0xDDFF)
                    {
                        return(_cia2[(Cia.Enums.Register)((address - 0xDD00) % 0x10)]);
                        //return base.Read(address);
                    }

                    //throw new AccessViolationException();
                    //Debug.WriteLine($"Trying to access I/O at address: 0x{address:X2}");
                    break;

                // CHAR ROM
                case BankMode.BANK_MODE_27:
                case BankMode.BANK_MODE_26:
                case BankMode.BANK_MODE_10:
                case BankMode.BANK_MODE_25:
                case BankMode.BANK_MODE_09:
                case BankMode.BANK_MODE_11:
                case BankMode.BANK_MODE_03:
                case BankMode.BANK_MODE_02:
                    return(_romCharacter.Read(address - 0xD000));

                // RAM
                default:
                    return(base.Read(address));
                }
            }

            // KERNAL ROM, RAM, CARTRIDGE ROM (page 224-255)
            // Some exceptions for I/O and cartridge rom, not implemented yet
            if (address >= 0xE000 && address <= 0xFFFF)
            {
                switch (bankState)
                {
                // KERNAL ROM
                case BankMode.BANK_MODE_31:
                case BankMode.BANK_MODE_30:
                case BankMode.BANK_MODE_14:
                case BankMode.BANK_MODE_27:
                case BankMode.BANK_MODE_26:
                case BankMode.BANK_MODE_10:
                case BankMode.BANK_MODE_15:
                case BankMode.BANK_MODE_11:
                case BankMode.BANK_MODE_07:
                case BankMode.BANK_MODE_06:
                case BankMode.BANK_MODE_03:
                case BankMode.BANK_MODE_02:
                    return(_romKernal.Read(address - 0xE000));

                // CART ROM HI
                case BankMode.BANK_MODE_23:
                case BankMode.BANK_MODE_22:
                case BankMode.BANK_MODE_21:
                case BankMode.BANK_MODE_20:
                case BankMode.BANK_MODE_19:
                case BankMode.BANK_MODE_18:
                case BankMode.BANK_MODE_17:
                case BankMode.BANK_MODE_16:
                    return(_cartridge[address]);

                // RAM
                default:
                    return(base.Read(address));
                }
            }

            // RAM
            return(base.Read(address));
        }
Exemple #2
0
 /// <summary>
 ///     Converts a pointer to a given type. This function converts the value of the pointer or the pointed value,
 ///     according if the data type is primitive or reference.
 /// </summary>
 /// <param name="memorySharp">The concerned process.</param>
 /// <param name="pointer">The pointer to convert.</param>
 /// <returns>The return value is the pointer converted to the given data type.</returns>
 public static T PtrToObject(MemoryBase memorySharp, IntPtr pointer)
 {
     return(ByteArrayToObject(CanBeStoredInRegisters
         ? BitConverter.GetBytes(pointer.ToInt64())
         : memorySharp.Read <byte>(pointer, Size, false)));
 }