1
0
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:
Thomas Harte 2024-12-28 21:49:04 -05:00
parent 6f638805f7
commit 570f1caa8f
3 changed files with 63 additions and 14 deletions

View File

@ -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

View File

@ -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)];
} }

View File

@ -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_);