mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-20 15:31:10 +00:00
Merge pull request #36 from TomHarte/Better6522
Added communication of the static level 6522 control line outputs and slightly simplified the Vic's memory bus
This commit is contained in:
commit
df533874f0
@ -108,9 +108,24 @@ template <class T> 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<T *>(this)->set_control_line_output(Port::A, Line::Two, false); break;
|
||||
case 0x0e: static_cast<T *>(this)->set_control_line_output(Port::A, Line::Two, true); break;
|
||||
}
|
||||
switch(value & 0xe0)
|
||||
{
|
||||
default: break;
|
||||
case 0xc0: static_cast<T *>(this)->set_control_line_output(Port::B, Line::Two, false); break;
|
||||
case 0xe0: static_cast<T *>(this)->set_control_line_output(Port::B, Line::Two, true); break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Interrupt control
|
||||
@ -176,7 +191,7 @@ template <class T> 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 T> 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
|
||||
|
@ -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<Storage::Tape> 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
|
||||
|
@ -57,6 +57,12 @@ class UserPortVIA: public MOS::MOS6522<UserPortVIA>, 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<KeyboardVIA>, public MOS::MOS6522IRQDelegate {
|
||||
@ -96,6 +102,12 @@ class KeyboardVIA: public MOS::MOS6522<KeyboardVIA>, 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<MOS::MOS6560> _mos6560;
|
||||
UserPortVIA _userPortVIA;
|
||||
|
Loading…
Reference in New Issue
Block a user