diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index c9de1eab2..c97adf70a 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -108,9 +108,24 @@ template class MOS6522 { case 0xa: _registers.shift = value; break; // Control - case 0xb: _registers.auxiliary_control = value; break; + case 0xb: + _registers.auxiliary_control = value; + break; case 0xc: + printf("Peripheral control %02x\n", value); _registers.peripheral_control = value; + switch(value & 0x0e) + { + default: break; + case 0x0c: static_cast(this)->set_control_line_output(Port::A, Line::Two, false); break; + case 0x0e: static_cast(this)->set_control_line_output(Port::A, Line::Two, true); break; + } + switch(value & 0xe0) + { + default: break; + case 0xc0: static_cast(this)->set_control_line_output(Port::B, Line::Two, false); break; + case 0xe0: static_cast(this)->set_control_line_output(Port::B, Line::Two, true); break; + } break; // Interrupt control @@ -176,7 +191,7 @@ template class MOS6522 { return 0xff; } - inline void set_control_line(Port port, Line line, bool value) + inline void set_control_line_input(Port port, Line line, bool value) { switch(line) { @@ -270,6 +285,7 @@ template class MOS6522 { uint8_t get_port_input(Port port) { return 0xff; } void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {} bool get_control_line(Port port, Line line) { return true; } + void set_control_line_output(Port port, Line line, bool value) {} // void set_interrupt_status(bool status) {} // Input/output multiplexer diff --git a/Machines/Vic-20/Vic20.cpp b/Machines/Vic-20/Vic20.cpp index 59083df3c..9f9c2a86b 100644 --- a/Machines/Vic-20/Vic20.cpp +++ b/Machines/Vic-20/Vic20.cpp @@ -18,8 +18,40 @@ Machine::Machine() : _userPortVIA.set_delegate(this); _keyboardVIA.set_delegate(this); _tape.set_delegate(this); + + memset(_videoMemoryMap, 0, sizeof(_videoMemoryMap)); + memset(_processorReadMemoryMap, 0, sizeof(_processorReadMemoryMap)); + memset(_processorWriteMemoryMap, 0, sizeof(_processorWriteMemoryMap)); + + write_to_map(_videoMemoryMap, _characterROM, 0x0000, sizeof(_characterROM)); + write_to_map(_videoMemoryMap, _userBASICMemory, 0x2000, sizeof(_userBASICMemory)); + write_to_map(_videoMemoryMap, _screenMemory, 0x3000, sizeof(_screenMemory)); + + write_to_map(_processorReadMemoryMap, _userBASICMemory, 0x0000, sizeof(_userBASICMemory)); + write_to_map(_processorReadMemoryMap, _screenMemory, 0x1000, sizeof(_screenMemory)); + write_to_map(_processorReadMemoryMap, _colorMemory, 0x9400, sizeof(_colorMemory)); + write_to_map(_processorReadMemoryMap, _characterROM, 0x8000, sizeof(_characterROM)); + write_to_map(_processorReadMemoryMap, _basicROM, 0xc000, sizeof(_basicROM)); + write_to_map(_processorReadMemoryMap, _kernelROM, 0xe000, sizeof(_kernelROM)); + + write_to_map(_processorWriteMemoryMap, _userBASICMemory, 0x0000, sizeof(_userBASICMemory)); + write_to_map(_processorWriteMemoryMap, _screenMemory, 0x1000, sizeof(_screenMemory)); + write_to_map(_processorWriteMemoryMap, _colorMemory, 0x9400, sizeof(_colorMemory)); } +void Machine::write_to_map(uint8_t **map, uint8_t *area, uint16_t address, uint16_t length) +{ + address >>= 10; + length >>= 10; + while(length--) + { + map[address] = area; + area += 0x400; + address++; + } +} + + Machine::~Machine() { delete[] _rom; @@ -27,66 +59,44 @@ Machine::~Machine() unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value) { - // test for PC at F92F - if(_use_fast_tape_hack && address == 0xf92f && operation == CPU6502::BusOperation::ReadOpcode) - { - // advance time on the tape and the VIAs until an interrupt is signalled - while(!_userPortVIA.get_interrupt_line() && !_keyboardVIA.get_interrupt_line()) - { - _userPortVIA.run_for_half_cycles(2); - _keyboardVIA.run_for_half_cycles(2); - _tape.run_for_cycles(1); - } - } - // run the phase-1 part of this cycle, in which the VIC accesses memory uint16_t video_address = _mos6560->get_address(); - uint8_t video_value = 0xff; // TODO - if(!(video_address&0x2000)) - { - video_value = _characterROM[video_address & 0x0fff]; - } - else - { - video_address &= 0x1fff; - if(video_address < sizeof(_userBASICMemory)) video_value = _userBASICMemory[video_address]; - else if(video_address >= 0x1000 && video_address < 0x2000) video_value = _screenMemory[video_address&0x0fff]; - } + uint8_t video_value = _videoMemoryMap[video_address >> 10] ? _videoMemoryMap[video_address >> 10][video_address & 0x3ff] : 0xff; // TODO _mos6560->set_graphics_value(video_value, _colorMemory[video_address & 0x03ff]); // run the phase-2 part of the cycle, which is whatever the 6502 said it should be if(isReadOperation(operation)) { - uint8_t result = read_memory(address); - if((address&0xff00) == 0x9000) + uint8_t result = _processorReadMemoryMap[address >> 10] ? _processorReadMemoryMap[address >> 10][address & 0x3ff] : 0xff; + if((address&0xfc00) == 0x9000) { - result &= _mos6560->get_register(address); - } - if((address&0xfc10) == 0x9010) - { - result &= _userPortVIA.get_register(address); - } - if((address&0xfc20) == 0x9020) - { - result &= _keyboardVIA.get_register(address); + if((address&0xff00) == 0x9000) result &= _mos6560->get_register(address); + if((address&0xfc10) == 0x9010) result &= _userPortVIA.get_register(address); + if((address&0xfc20) == 0x9020) result &= _keyboardVIA.get_register(address); } *value = result; + + // test for PC at F92F + if(_use_fast_tape_hack && address == 0xf92f && operation == CPU6502::BusOperation::ReadOpcode) + { + // advance time on the tape and the VIAs until an interrupt is signalled + while(!_userPortVIA.get_interrupt_line() && !_keyboardVIA.get_interrupt_line()) + { + _userPortVIA.run_for_half_cycles(2); + _keyboardVIA.run_for_half_cycles(2); + _tape.run_for_cycles(1); + } + } } else { - uint8_t *ram = ram_pointer(address); - if(ram) *ram = *value; - if((address&0xff00) == 0x9000) + uint8_t *ram = _processorWriteMemoryMap[address >> 10]; + if(ram) ram[address & 0x3ff] = *value; + if((address&0xfc00) == 0x9000) { - _mos6560->set_register(address, *value); - } - if((address&0xfc10) == 0x9010) - { - _userPortVIA.set_register(address, *value); - } - if((address&0xfc20) == 0x9020) - { - _keyboardVIA.set_register(address, *value); + if((address&0xff00) == 0x9000) _mos6560->set_register(address, *value); + if((address&0xfc10) == 0x9010) _userPortVIA.set_register(address, *value); + if((address&0xfc20) == 0x9020) _keyboardVIA.set_register(address, *value); } } @@ -143,6 +153,7 @@ void Machine::add_prg(size_t length, const uint8_t *data) _rom = new uint8_t[length - 2]; memcpy(_rom, &data[2], length - 2); + write_to_map(_processorReadMemoryMap, _rom, _rom_address, _rom_length); } } @@ -156,7 +167,7 @@ void Machine::set_tape(std::shared_ptr tape) void Machine::tape_did_change_input(Tape *tape) { - _keyboardVIA.set_control_line(KeyboardVIA::Port::A, KeyboardVIA::Line::One, tape->get_input()); + _keyboardVIA.set_control_line_input(KeyboardVIA::Port::A, KeyboardVIA::Line::One, tape->get_input()); } #pragma mark - Typer diff --git a/Machines/Vic-20/Vic20.hpp b/Machines/Vic-20/Vic20.hpp index b73ea198b..3f5f247c8 100644 --- a/Machines/Vic-20/Vic20.hpp +++ b/Machines/Vic-20/Vic20.hpp @@ -57,6 +57,12 @@ class UserPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQDeleg } return 0xff; } + + void set_control_line_output(Port port, Line line, bool value) { + if(port == Port::A && line == Line::Two) { + printf("Tape motor %s\n", value ? "on" : "off"); + } + } }; class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { @@ -96,6 +102,12 @@ class KeyboardVIA: public MOS::MOS6522, public MOS::MOS6522IRQDeleg _activation_mask = (value & mask) | (~mask); } + void set_control_line_output(Port port, Line line, bool value) { + if(port == Port::A && line == Line::Two) { + printf("Blah Tape motor %s\n", value ? "on" : "off"); + } + } + private: uint8_t _columns[8]; uint8_t _activation_mask; @@ -180,23 +192,12 @@ class Machine: uint8_t _userBASICMemory[0x0400]; uint8_t _screenMemory[0x1000]; uint8_t _colorMemory[0x0400]; + uint8_t _junkMemory[0x0400]; - inline uint8_t *ram_pointer(uint16_t address) { - if(address < sizeof(_userBASICMemory)) return &_userBASICMemory[address]; - if(address >= 0x1000 && address < 0x2000) return &_screenMemory[address&0x0fff]; - if(address >= 0x9400 && address < 0x9800) return &_colorMemory[address&0x03ff]; // TODO: make this 4-bit - return nullptr; - } - - inline uint8_t read_memory(uint16_t address) { - uint8_t *ram = ram_pointer(address); - if(ram) return *ram; - else if(address >= 0x8000 && address < 0x9000) return _characterROM[address&0x0fff]; - else if(address >= 0xc000 && address < 0xe000) return _basicROM[address&0x1fff]; - else if(address >= 0xe000) return _kernelROM[address&0x1fff]; - else if(address >= _rom_address && address < _rom_address+_rom_length) return _rom[address - _rom_address]; - return 0xff; - } + uint8_t *_videoMemoryMap[16]; + uint8_t *_processorReadMemoryMap[64]; + uint8_t *_processorWriteMemoryMap[64]; + void write_to_map(uint8_t **map, uint8_t *area, uint16_t address, uint16_t length); std::unique_ptr _mos6560; UserPortVIA _userPortVIA;