mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-28 06:29:37 +00:00
Attempt also to integrate a C1541.
This commit is contained in:
parent
6f638805f7
commit
570f1caa8f
@ -19,6 +19,8 @@
|
|||||||
#include "../../../Analyser/Static/Commodore/Target.hpp"
|
#include "../../../Analyser/Static/Commodore/Target.hpp"
|
||||||
|
|
||||||
#include "../../../Storage/Tape/Tape.hpp"
|
#include "../../../Storage/Tape/Tape.hpp"
|
||||||
|
#include "../SerialBus.hpp"
|
||||||
|
#include "../1540/C1540.hpp"
|
||||||
|
|
||||||
using namespace Commodore::Plus4;
|
using namespace Commodore::Plus4;
|
||||||
|
|
||||||
@ -100,6 +102,20 @@ private:
|
|||||||
Interrupts &interrupts_;
|
Interrupts &interrupts_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SerialPort: public Commodore::Serial::Port {
|
||||||
|
public:
|
||||||
|
void set_input(Commodore::Serial::Line line, Commodore::Serial::LineLevel value) override {
|
||||||
|
levels_[size_t(line)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Commodore::Serial::LineLevel level(Commodore::Serial::Line line) const {
|
||||||
|
return levels_[size_t(line)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Commodore::Serial::LineLevel levels_[5];
|
||||||
|
};
|
||||||
|
|
||||||
class ConcreteMachine:
|
class ConcreteMachine:
|
||||||
public BusController,
|
public BusController,
|
||||||
public CPU::MOS6502::BusHandler,
|
public CPU::MOS6502::BusHandler,
|
||||||
@ -118,12 +134,17 @@ public:
|
|||||||
const auto clock = clock_rate(false);
|
const auto clock = clock_rate(false);
|
||||||
media_divider_ = Cycles(clock);
|
media_divider_ = Cycles(clock);
|
||||||
set_clock_rate(clock);
|
set_clock_rate(clock);
|
||||||
tape_player_ = std::make_unique<Storage::Tape::BinaryTapePlayer>(clock);
|
|
||||||
|
// TODO: decide whether to attach a 1541 for real.
|
||||||
|
const bool has_c1541 = true;
|
||||||
|
|
||||||
const auto kernel = ROM::Name::Plus4KernelPALv5;
|
const auto kernel = ROM::Name::Plus4KernelPALv5;
|
||||||
const auto basic = ROM::Name::Plus4BASIC;
|
const auto basic = ROM::Name::Plus4BASIC;
|
||||||
|
ROM::Request request = ROM::Request(basic) && ROM::Request(kernel);
|
||||||
|
if(has_c1541) {
|
||||||
|
request = request && Commodore::C1540::Machine::rom_request(Commodore::C1540::Personality::C1541);
|
||||||
|
}
|
||||||
|
|
||||||
const ROM::Request request = ROM::Request(basic) && ROM::Request(kernel);
|
|
||||||
auto roms = rom_fetcher(request);
|
auto roms = rom_fetcher(request);
|
||||||
if(!request.validate(roms)) {
|
if(!request.validate(roms)) {
|
||||||
throw ROMMachine::Error::MissingROMs;
|
throw ROMMachine::Error::MissingROMs;
|
||||||
@ -138,6 +159,14 @@ public:
|
|||||||
|
|
||||||
video_map_.page<PagerSide::ReadWrite, 0, 65536>(ram_.data());
|
video_map_.page<PagerSide::ReadWrite, 0, 65536>(ram_.data());
|
||||||
|
|
||||||
|
if(has_c1541) {
|
||||||
|
c1541_ = std::make_unique<Commodore::C1540::Machine>(Commodore::C1540::Personality::C1541, roms);
|
||||||
|
c1541_->set_serial_bus(serial_bus_);
|
||||||
|
serial_port_.set_bus(serial_bus_);
|
||||||
|
}
|
||||||
|
|
||||||
|
tape_player_ = std::make_unique<Storage::Tape::BinaryTapePlayer>(clock);
|
||||||
|
|
||||||
insert_media(target.media);
|
insert_media(target.media);
|
||||||
printf("Loading command is: %s\n", target.loading_command.c_str());
|
printf("Loading command is: %s\n", target.loading_command.c_str());
|
||||||
}
|
}
|
||||||
@ -159,6 +188,11 @@ public:
|
|||||||
video_.run_for(length);
|
video_.run_for(length);
|
||||||
tape_player_->run_for(length);
|
tape_player_->run_for(length);
|
||||||
|
|
||||||
|
if(c1541_) {
|
||||||
|
c1541_cycles_ += length;
|
||||||
|
c1541_->run_for(c1541_cycles_.divide(media_divider_));
|
||||||
|
}
|
||||||
|
|
||||||
if(operation == CPU::MOS6502::BusOperation::Ready) {
|
if(operation == CPU::MOS6502::BusOperation::Ready) {
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@ -179,9 +213,11 @@ public:
|
|||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
if(!address) {
|
if(!address) {
|
||||||
*value = io_direction_;
|
*value = io_direction_;
|
||||||
// printf("Read data direction: %02x\n", *value);
|
|
||||||
} else {
|
} else {
|
||||||
const uint8_t all_inputs = (tape_player_->input() ? 0x00 : 0x10) | 0xe0;
|
const uint8_t all_inputs =
|
||||||
|
(tape_player_->input() ? 0x00 : 0x10) |
|
||||||
|
(serial_port_.level(Commodore::Serial::Line::Data) ? 0x80 : 0x00) |
|
||||||
|
(serial_port_.level(Commodore::Serial::Line::Clock) ? 0x40 : 0x00);
|
||||||
*value =
|
*value =
|
||||||
(io_direction_ & io_output_) |
|
(io_direction_ & io_output_) |
|
||||||
((~io_direction_) & all_inputs);
|
((~io_direction_) & all_inputs);
|
||||||
@ -190,13 +226,18 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
if(!address) {
|
if(!address) {
|
||||||
io_direction_ = *value;
|
io_direction_ = *value;
|
||||||
// printf("Set data direction: %02x\n", *value);
|
|
||||||
} else {
|
} else {
|
||||||
io_output_ = *value;
|
io_output_ = *value;
|
||||||
printf("[%04x] Out: %02x\n", m6502_.value_of(CPU::MOS6502::Register::ProgramCounter), *value);
|
|
||||||
// tape_player_->set_motor_control(*value & 0x08);
|
|
||||||
tape_player_->set_motor_control(!(*value & 0x08));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto output = io_output_ & ~io_direction_;
|
||||||
|
tape_player_->set_motor_control(!(output & 0x08));
|
||||||
|
serial_port_.set_output(
|
||||||
|
Commodore::Serial::Line::Data, Commodore::Serial::LineLevel(~output & 0x01));
|
||||||
|
serial_port_.set_output(
|
||||||
|
Commodore::Serial::Line::Clock, Commodore::Serial::LineLevel(~output & 0x02));
|
||||||
|
serial_port_.set_output(
|
||||||
|
Commodore::Serial::Line::Attention, Commodore::Serial::LineLevel(~output & 0x04));
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("%04x: %02x %c\n", address, *value, isReadOperation(operation) ? 'r' : 'w');
|
// printf("%04x: %02x %c\n", address, *value, isReadOperation(operation) ? 'r' : 'w');
|
||||||
@ -372,6 +413,10 @@ private:
|
|||||||
tape_player_->set_tape(media.tapes[0]);
|
tape_player_->set_tape(media.tapes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!media.disks.empty() && c1541_) {
|
||||||
|
c1541_->set_disk(media.disks[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,12 +449,16 @@ private:
|
|||||||
std::array<uint8_t, 8> key_states_{};
|
std::array<uint8_t, 8> key_states_{};
|
||||||
uint8_t keyboard_latch_ = 0xff;
|
uint8_t keyboard_latch_ = 0xff;
|
||||||
|
|
||||||
Cycles media_divider_;
|
Cycles media_divider_, c1541_cycles_;
|
||||||
|
std::unique_ptr<Commodore::C1540::Machine> c1541_;
|
||||||
|
Commodore::Serial::Bus serial_bus_;
|
||||||
|
SerialPort serial_port_;
|
||||||
|
|
||||||
std::unique_ptr<Storage::Tape::BinaryTapePlayer> tape_player_;
|
std::unique_ptr<Storage::Tape::BinaryTapePlayer> tape_player_;
|
||||||
uint8_t io_direction_ = 0x00, io_output_ = 0x00;
|
uint8_t io_direction_ = 0x00, io_output_ = 0x00;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Machine> Machine::Plus4(
|
std::unique_ptr<Machine> Machine::Plus4(
|
||||||
const Analyser::Static::Target *target,
|
const Analyser::Static::Target *target,
|
||||||
const ROMMachine::ROMFetcher &rom_fetcher
|
const ROMMachine::ROMFetcher &rom_fetcher
|
||||||
|
@ -56,13 +56,13 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
Adds the supplied port to the bus.
|
Adds the supplied port to the bus.
|
||||||
*/
|
*/
|
||||||
void add_port(Port &port);
|
void add_port(Port &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Communicates to the bus that one of its attached port has changed its output level for the given line.
|
Communicates to the bus that one of its attached port has changed its output level for the given line.
|
||||||
The bus will therefore recalculate bus state and propagate as necessary.
|
The bus will therefore recalculate bus state and propagate as necessary.
|
||||||
*/
|
*/
|
||||||
void set_line_output_did_change(Line line);
|
void set_line_output_did_change(Line);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LineLevel line_levels_[5];
|
LineLevel line_levels_[5];
|
||||||
@ -97,7 +97,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
Gets the previously set level of an output line.
|
Gets the previously set level of an output line.
|
||||||
*/
|
*/
|
||||||
LineLevel get_output(Line line) {
|
LineLevel get_output(Line line) const {
|
||||||
return line_levels_[size_t(line)];
|
return line_levels_[size_t(line)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +352,7 @@ public:
|
|||||||
|
|
||||||
if(target.has_c1540) {
|
if(target.has_c1540) {
|
||||||
// construct the 1540
|
// construct the 1540
|
||||||
c1540_ = std::make_unique<::Commodore::C1540::Machine>(Commodore::C1540::Personality::C1540, roms);
|
c1540_ = std::make_unique<C1540::Machine>(C1540::Personality::C1540, roms);
|
||||||
|
|
||||||
// attach it to the serial bus
|
// attach it to the serial bus
|
||||||
c1540_->set_serial_bus(serial_bus_);
|
c1540_->set_serial_bus(serial_bus_);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user