mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
The Disk II now being its proper speed, withdraws the quickload option.
This commit is contained in:
parent
70c4d6b9b3
commit
c4f86cc324
@ -27,27 +27,17 @@
|
|||||||
|
|
||||||
#include "../../Analyser/Static/AppleII/Target.hpp"
|
#include "../../Analyser/Static/AppleII/Target.hpp"
|
||||||
#include "../../ClockReceiver/ForceInline.hpp"
|
#include "../../ClockReceiver/ForceInline.hpp"
|
||||||
#include "../../Configurable/Configurable.hpp"
|
|
||||||
#include "../../Storage/Disk/Track/TrackSerialiser.hpp"
|
|
||||||
#include "../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> AppleII::get_options() {
|
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> options;
|
|
||||||
options.emplace_back(new Configurable::BooleanOption("Accelerate DOS 3.3", "quickload"));
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <bool is_iie> class ConcreteMachine:
|
template <bool is_iie> class ConcreteMachine:
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public MediaTarget::Machine,
|
public MediaTarget::Machine,
|
||||||
public KeyboardMachine::Machine,
|
public KeyboardMachine::Machine,
|
||||||
public Configurable::Device,
|
|
||||||
public CPU::MOS6502::BusHandler,
|
public CPU::MOS6502::BusHandler,
|
||||||
public Inputs::Keyboard,
|
public Inputs::Keyboard,
|
||||||
public AppleII::Machine,
|
public AppleII::Machine,
|
||||||
@ -256,9 +246,6 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
// MARK - typing
|
// MARK - typing
|
||||||
std::unique_ptr<Utility::StringSerialiser> string_serialiser_;
|
std::unique_ptr<Utility::StringSerialiser> string_serialiser_;
|
||||||
|
|
||||||
// MARK - quick loading
|
|
||||||
bool should_load_quickly_ = false;
|
|
||||||
|
|
||||||
// MARK - joysticks
|
// MARK - joysticks
|
||||||
class Joystick: public Inputs::ConcreteJoystick {
|
class Joystick: public Inputs::ConcreteJoystick {
|
||||||
public:
|
public:
|
||||||
@ -441,85 +428,6 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
set_card_paging();
|
set_card_paging();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(should_load_quickly_) {
|
|
||||||
// Check for a prima facie entry into RWTS.
|
|
||||||
if(operation == CPU::MOS6502::BusOperation::ReadOpcode && address == 0xb7b5) {
|
|
||||||
// Grab the IO control block address for inspection.
|
|
||||||
uint16_t io_control_block_address =
|
|
||||||
static_cast<uint16_t>(
|
|
||||||
(m6502_.get_value_of_register(CPU::MOS6502::Register::A) << 8) |
|
|
||||||
m6502_.get_value_of_register(CPU::MOS6502::Register::Y)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify that this is table type one, for execution on card six,
|
|
||||||
// against drive 1 or 2, and that the command is either a seek or a sector read.
|
|
||||||
if(
|
|
||||||
ram_[io_control_block_address+0x00] == 0x01 &&
|
|
||||||
ram_[io_control_block_address+0x01] == 0x60 &&
|
|
||||||
ram_[io_control_block_address+0x02] > 0 && ram_[io_control_block_address+0x02] < 3 &&
|
|
||||||
ram_[io_control_block_address+0x0c] < 2
|
|
||||||
) {
|
|
||||||
const uint8_t iob_track = ram_[io_control_block_address+4];
|
|
||||||
const uint8_t iob_sector = ram_[io_control_block_address+5];
|
|
||||||
const uint8_t iob_drive = ram_[io_control_block_address+2] - 1;
|
|
||||||
|
|
||||||
// Get the track identified and store the new head position.
|
|
||||||
auto track = diskii_card()->get_drive(iob_drive).step_to(Storage::Disk::HeadPosition(iob_track));
|
|
||||||
|
|
||||||
// DOS 3.3 keeps the current track (unspecified drive) in 0x478; the current track for drive 1 and drive 2
|
|
||||||
// is also kept in that Disk II card's screen hole.
|
|
||||||
ram_[0x478] = iob_track;
|
|
||||||
if(ram_[io_control_block_address+0x02] == 1) {
|
|
||||||
ram_[0x47e] = iob_track;
|
|
||||||
} else {
|
|
||||||
ram_[0x4fe] = iob_track;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether this is a read, not merely a seek.
|
|
||||||
if(ram_[io_control_block_address+0x0c] == 1) {
|
|
||||||
// Apple the DOS 3.3 formula to map the requested logical sector to a physical sector.
|
|
||||||
const int physical_sector = (iob_sector == 15) ? 15 : ((iob_sector * 13) % 15);
|
|
||||||
|
|
||||||
// Parse the entire track. TODO: cache these.
|
|
||||||
auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
|
|
||||||
Storage::Disk::track_serialisation(*track, Storage::Time(1, 50000)));
|
|
||||||
|
|
||||||
bool found_sector = false;
|
|
||||||
for(const auto &pair: sector_map) {
|
|
||||||
if(pair.second.address.sector == physical_sector) {
|
|
||||||
found_sector = true;
|
|
||||||
|
|
||||||
// Copy the sector contents to their destination.
|
|
||||||
uint16_t target = static_cast<uint16_t>(
|
|
||||||
ram_[io_control_block_address+8] |
|
|
||||||
(ram_[io_control_block_address+9] << 8)
|
|
||||||
);
|
|
||||||
|
|
||||||
for(size_t c = 0; c < 256; ++c) {
|
|
||||||
ram_[target] = pair.second.data[c];
|
|
||||||
++target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set no error encountered.
|
|
||||||
ram_[io_control_block_address + 0xd] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(found_sector) {
|
|
||||||
// Set no error in the flags register too, and RTS.
|
|
||||||
m6502_.set_value_of_register(CPU::MOS6502::Register::Flags, m6502_.get_value_of_register(CPU::MOS6502::Register::Flags) & ~1);
|
|
||||||
*value = 0x60;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No error encountered; RTS.
|
|
||||||
m6502_.set_value_of_register(CPU::MOS6502::Register::Flags, m6502_.get_value_of_register(CPU::MOS6502::Register::Flags) & ~1);
|
|
||||||
*value = 0x60;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Assume a vapour read unless it turns out otherwise; this is a little
|
// Assume a vapour read unless it turns out otherwise; this is a little
|
||||||
// wasteful but works for now.
|
// wasteful but works for now.
|
||||||
@ -609,11 +517,18 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
// printf("Unknown (?) write to %04x\n", address);
|
// printf("Unknown (?) write to %04x\n", address);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0xc000:
|
||||||
|
case 0xc001:
|
||||||
|
video_->set_80_store(!!(address&1));
|
||||||
|
set_main_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xc002:
|
case 0xc002:
|
||||||
case 0xc003:
|
case 0xc003:
|
||||||
read_auxiliary_memory_ = !!(address&1);
|
read_auxiliary_memory_ = !!(address&1);
|
||||||
set_main_paging();
|
set_main_paging();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc004:
|
case 0xc004:
|
||||||
case 0xc005:
|
case 0xc005:
|
||||||
write_auxiliary_memory_ = !!(address&1);
|
write_auxiliary_memory_ = !!(address&1);
|
||||||
@ -625,26 +540,6 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
internal_CX_rom_ = !!(address&1);
|
internal_CX_rom_ = !!(address&1);
|
||||||
set_card_paging();
|
set_card_paging();
|
||||||
break;
|
break;
|
||||||
case 0xc00a:
|
|
||||||
case 0xc00b:
|
|
||||||
slot_C3_rom_ = !!(address&1);
|
|
||||||
set_card_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc00e:
|
|
||||||
case 0xc00f: video_->set_alternative_character_set(!!(address&1)); break;
|
|
||||||
|
|
||||||
case 0xc00c:
|
|
||||||
case 0xc00d: video_->set_80_columns(!!(address&1)); break;
|
|
||||||
|
|
||||||
case 0xc000:
|
|
||||||
case 0xc001:
|
|
||||||
video_->set_80_store(!!(address&1));
|
|
||||||
set_main_paging();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xc05e:
|
|
||||||
case 0xc05f: video_->set_double_high_resolution(!(address&1)); break;
|
|
||||||
|
|
||||||
case 0xc008:
|
case 0xc008:
|
||||||
case 0xc009:
|
case 0xc009:
|
||||||
@ -654,6 +549,21 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
set_zero_page_paging();
|
set_zero_page_paging();
|
||||||
set_language_card_paging();
|
set_language_card_paging();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0xc00a:
|
||||||
|
case 0xc00b:
|
||||||
|
slot_C3_rom_ = !!(address&1);
|
||||||
|
set_card_paging();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xc00c:
|
||||||
|
case 0xc00d: video_->set_80_columns(!!(address&1)); break;
|
||||||
|
|
||||||
|
case 0xc00e:
|
||||||
|
case 0xc00f: video_->set_alternative_character_set(!!(address&1)); break;
|
||||||
|
|
||||||
|
case 0xc05e:
|
||||||
|
case 0xc05f: video_->set_double_high_resolution(!(address&1)); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -860,30 +770,6 @@ template <bool is_iie> class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Options
|
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> get_options() override {
|
|
||||||
return AppleII::get_options();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_selections(const Configurable::SelectionSet &selections_by_option) override {
|
|
||||||
bool quickload;
|
|
||||||
if(Configurable::get_quick_load_tape(selections_by_option, quickload)) {
|
|
||||||
should_load_quickly_ = quickload;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Configurable::SelectionSet get_accurate_selections() override {
|
|
||||||
Configurable::SelectionSet selection_set;
|
|
||||||
Configurable::append_quick_load_tape_selection(selection_set, false);
|
|
||||||
return selection_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
Configurable::SelectionSet get_user_friendly_selections() override {
|
|
||||||
Configurable::SelectionSet selection_set;
|
|
||||||
Configurable::append_quick_load_tape_selection(selection_set, true);
|
|
||||||
return selection_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: JoystickMachine
|
// MARK: JoystickMachine
|
||||||
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
|
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
|
||||||
return joysticks_;
|
return joysticks_;
|
||||||
|
@ -18,9 +18,6 @@
|
|||||||
|
|
||||||
namespace AppleII {
|
namespace AppleII {
|
||||||
|
|
||||||
/// @returns The options available for an Apple II.
|
|
||||||
std::vector<std::unique_ptr<Configurable::Option>> get_options();
|
|
||||||
|
|
||||||
class Machine {
|
class Machine {
|
||||||
public:
|
public:
|
||||||
virtual ~Machine();
|
virtual ~Machine();
|
||||||
|
@ -130,7 +130,6 @@ std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> Machin
|
|||||||
std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> options;
|
std::map<std::string, std::vector<std::unique_ptr<Configurable::Option>>> options;
|
||||||
|
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AmstradCPC), AmstradCPC::get_options()));
|
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AmstradCPC), AmstradCPC::get_options()));
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::AppleII), AppleII::get_options()));
|
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Electron), Electron::get_options()));
|
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Electron), Electron::get_options()));
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::MSX), MSX::get_options()));
|
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::MSX), MSX::get_options()));
|
||||||
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Oric), Oric::get_options()));
|
options.emplace(std::make_pair(LongNameForTargetMachine(Analyser::Machine::Oric), Oric::get_options()));
|
||||||
|
Loading…
Reference in New Issue
Block a user