From 9838e01cc19d6702e40a33d4f81242b982dad68b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 13 Aug 2015 13:24:02 +0100 Subject: [PATCH] Made a first attempt at paging. --- Machines/Atari2600.cpp | 42 +++++++++++++++++++++++++++++++++++++----- Machines/Atari2600.hpp | 4 ++-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/Machines/Atari2600.cpp b/Machines/Atari2600.cpp index 347bd8685..24fc65e63 100644 --- a/Machines/Atari2600.cpp +++ b/Machines/Atari2600.cpp @@ -23,6 +23,7 @@ Machine::Machine() _crt = new Outputs::CRT(228, 262, 1, 4); _piaTimerStatus = 0xff; memset(_collisions, 0xff, sizeof(_collisions)); + _rom = nullptr; setup6502(); set_reset_line(true); @@ -30,6 +31,7 @@ Machine::Machine() Machine::~Machine() { + delete[] _rom; delete _crt; } @@ -267,9 +269,30 @@ int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t add if(operation != CPU6502::BusOperation::Ready) { - // check for a ROM access + // check for a ROM or paging access if ((address&0x1000) && isReadOperation(operation)) { - returnValue &= _rom[address&_romMask]; + + if(_rom_size > 4096 && ((address & 0x1f00) == 0x1f00)) { + uint8_t *base_ptr = _romPages[0]; + uint8_t first_paging_register = 0xf8 - (_rom_size >> 14)*2; + + const uint8_t paging_register = address&0xff; + if(paging_register >= first_paging_register) { + const uint16_t selected_page = paging_register - first_paging_register; + if(selected_page * 4096 < _rom_size) { + base_ptr = &_rom[selected_page * 4096]; + } + } + + if(base_ptr != _romPages[0]) { + _romPages[0] = base_ptr; + _romPages[1] = base_ptr + 1024; + _romPages[2] = base_ptr + 2048; + _romPages[3] = base_ptr + 3072; + } + } + + returnValue &= _romPages[(address >> 10)&3][address&1023]; } // check for a RAM access @@ -458,7 +481,16 @@ int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t add void Machine::set_rom(size_t length, const uint8_t *data) { - length = std::min((size_t)4096, length); - memcpy(_rom, data, length); - _romMask = length - 1; + _rom_size = 1024; + while(_rom_size < length && _rom_size < 32768) _rom_size <<= 1; + + delete[] _rom; + _rom = new uint8_t[_rom_size]; + memcpy(_rom, data, std::min(_rom_size, length)); + + size_t romMask = _rom_size - 1; + _romPages[0] = _rom; + _romPages[1] = &_rom[1024 & romMask]; + _romPages[2] = &_rom[2048 & romMask]; + _romPages[3] = &_rom[3072 & romMask]; } diff --git a/Machines/Atari2600.hpp b/Machines/Atari2600.hpp index d8131d5f9..9a3d9dabb 100644 --- a/Machines/Atari2600.hpp +++ b/Machines/Atari2600.hpp @@ -30,8 +30,8 @@ class Machine: public CPU6502::Processor { Outputs::CRT *get_crt() { return _crt; } private: - uint8_t _rom[4096], _ram[128]; - uint16_t _romMask; + uint8_t *_rom, *_romPages[4], _ram[128]; + size_t _rom_size; uint64_t _timestamp;