mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 15:31:09 +00:00
Added shift-break as a better way to boot suitable disks. Continued attempting to clean the 1770.
This commit is contained in:
parent
a538b45213
commit
6084020ab3
@ -16,7 +16,8 @@ WD1770::WD1770() :
|
||||
status_(0),
|
||||
interesting_event_mask_(Event::Command),
|
||||
resume_point_(0),
|
||||
delay_time_(0)
|
||||
delay_time_(0),
|
||||
index_hole_count_target_(-1)
|
||||
{
|
||||
set_is_double_density(false);
|
||||
posit_event(Event::Command);
|
||||
@ -136,9 +137,14 @@ void WD1770::process_index_hole()
|
||||
{
|
||||
index_hole_count_++;
|
||||
posit_event(Event::IndexHole);
|
||||
if(index_hole_count_target_ == index_hole_count_)
|
||||
{
|
||||
posit_event(Event::IndexHoleTarget);
|
||||
index_hole_count_target_ = -1;
|
||||
}
|
||||
|
||||
// motor power-down
|
||||
// if(index_hole_count_ == 9 && !(status_&Flag::Busy)) status_ &= ~Flag::MotorOn;
|
||||
if(index_hole_count_ == 9 && !(status_&Flag::Busy)) status_ &= ~Flag::MotorOn;
|
||||
}
|
||||
|
||||
// +------+----------+-------------------------+
|
||||
@ -174,6 +180,16 @@ void WD1770::process_index_hole()
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONCATENATE(x, y) x ## y
|
||||
#define INDIRECT_CONCATENATE(x, y) TOKENPASTE(x, y)
|
||||
#define LINE_LABEL INDIRECT_CONCATENATE(label, __LINE__)
|
||||
|
||||
#define SPIN_UP() \
|
||||
status_ |= Flag::MotorOn; \
|
||||
index_hole_count_ = 0; \
|
||||
index_hole_count_target_ = 6; \
|
||||
WAIT_FOR_EVENT(Event::IndexHoleTarget);
|
||||
|
||||
void WD1770::posit_event(Event new_event_type)
|
||||
{
|
||||
if(!(interesting_event_mask_ & (int)new_event_type)) return;
|
||||
@ -204,13 +220,7 @@ void WD1770::posit_event(Event new_event_type)
|
||||
if((command_&0x08) || (status_ & Flag::MotorOn)) goto test_type1_type;
|
||||
|
||||
// Perform spin up.
|
||||
status_ |= Flag::MotorOn;
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
SPIN_UP();
|
||||
status_ |= Flag::SpinUp;
|
||||
|
||||
test_type1_type:
|
||||
@ -301,13 +311,7 @@ void WD1770::posit_event(Event new_event_type)
|
||||
if((command_&0x08) || (status_ & Flag::MotorOn)) goto test_type2_delay;
|
||||
|
||||
// Perform spin up.
|
||||
status_ |= Flag::MotorOn;
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
WAIT_FOR_EVENT(Event::IndexHole);
|
||||
SPIN_UP();
|
||||
|
||||
test_type2_delay:
|
||||
index_hole_count_ = 0;
|
||||
|
@ -46,6 +46,7 @@ class WD1770: public Storage::Disk::Drive {
|
||||
uint8_t command_;
|
||||
|
||||
int index_hole_count_;
|
||||
int index_hole_count_target_;
|
||||
int bits_since_token_;
|
||||
int distance_into_section_;
|
||||
|
||||
@ -64,10 +65,12 @@ class WD1770: public Storage::Disk::Drive {
|
||||
|
||||
// Events
|
||||
enum Event: int {
|
||||
Command = (1 << 0),
|
||||
Token = (1 << 1),
|
||||
IndexHole = (1 << 2),
|
||||
Timer = (1 << 3)
|
||||
Command = (1 << 0), // Indicates receipt of a new command.
|
||||
Token = (1 << 1), // Indicates recognition of a new token in the flux stream. Interrogate latest_token_ for details.
|
||||
IndexHole = (1 << 2), // Indicates the passing of a physical index hole.
|
||||
|
||||
Timer = (1 << 3), // Indicates that the delay_time_-powered timer has timed out.
|
||||
IndexHoleTarget = (1 << 4) // Indicates that index_hole_count_ has reached index_hole_count_target_.
|
||||
};
|
||||
void posit_event(Event type);
|
||||
int interesting_event_mask_;
|
||||
|
@ -304,6 +304,11 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
|
||||
case 0xfc04: case 0xfc05: case 0xfc06: case 0xfc07:
|
||||
if(_wd1770 && (address&0x00f0) == 0x00c0)
|
||||
{
|
||||
if(is_holding_shift_)
|
||||
{
|
||||
is_holding_shift_ = false;
|
||||
set_key_state(KeyShift, false);
|
||||
}
|
||||
if(isReadOperation(operation))
|
||||
*value = _wd1770->get_register(address);
|
||||
else
|
||||
@ -516,6 +521,11 @@ void Machine::configure_as_target(const StaticAnalyser::Target &target)
|
||||
{
|
||||
set_typer_for_string(target.loadingCommand.c_str());
|
||||
}
|
||||
if(target.acorn.should_hold_shift)
|
||||
{
|
||||
set_key_state(KeyShift, true);
|
||||
is_holding_shift_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Machine::set_rom(ROMSlot slot, std::vector<uint8_t> data, bool is_writeable)
|
||||
|
@ -233,6 +233,7 @@ class Machine:
|
||||
|
||||
// Disk
|
||||
std::unique_ptr<WD::WD1770> _wd1770;
|
||||
bool is_holding_shift_;
|
||||
|
||||
// Outputs
|
||||
std::shared_ptr<Outputs::CRT::CRT> _crt;
|
||||
|
@ -16,7 +16,7 @@ using namespace StaticAnalyser::Acorn;
|
||||
|
||||
class FMParser: public Storage::Disk::Drive {
|
||||
public:
|
||||
FMParser() :
|
||||
FMParser(bool is_mfm) :
|
||||
Storage::Disk::Drive(4000000, 1, 300),
|
||||
crc_generator_(0x1021, 0xffff),
|
||||
shift_register_(0), track_(0)
|
||||
@ -26,7 +26,7 @@ class FMParser: public Storage::Disk::Drive {
|
||||
|
||||
Storage::Time bit_length;
|
||||
bit_length.length = 1;
|
||||
bit_length.clock_rate = 250000; // i.e. 250 kbps (including clocks)
|
||||
bit_length.clock_rate = is_mfm ? 500000 : 250000; // i.e. 250 kbps (including clocks)
|
||||
set_expected_bit_length(bit_length);
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ std::unique_ptr<Catalogue> StaticAnalyser::Acorn::GetDFSCatalogue(const std::sha
|
||||
{
|
||||
// c.f. http://beebwiki.mdfs.net/Acorn_DFS_disc_format
|
||||
std::unique_ptr<Catalogue> catalogue(new Catalogue);
|
||||
FMParser parser;
|
||||
FMParser parser(false);
|
||||
parser.set_disk(disk);
|
||||
|
||||
std::shared_ptr<Storage::Encodings::MFM::Sector> names = parser.get_sector(0, 0);
|
||||
@ -218,3 +218,13 @@ std::unique_ptr<Catalogue> StaticAnalyser::Acorn::GetDFSCatalogue(const std::sha
|
||||
|
||||
return catalogue;
|
||||
}
|
||||
std::unique_ptr<Catalogue> StaticAnalyser::Acorn::GetADFSCatalogue(const std::shared_ptr<Storage::Disk::Disk> &disk)
|
||||
{
|
||||
std::unique_ptr<Catalogue> catalogue(new Catalogue);
|
||||
FMParser parser(true);
|
||||
parser.set_disk(disk);
|
||||
|
||||
std::shared_ptr<Storage::Encodings::MFM::Sector> directory = parser.get_sector(0, 2);
|
||||
|
||||
return catalogue;
|
||||
}
|
||||
|
@ -116,22 +116,17 @@ void StaticAnalyser::Acorn::AddTargets(
|
||||
if(disks.size() > 0)
|
||||
{
|
||||
std::shared_ptr<Storage::Disk::Disk> disk = disks.front();
|
||||
std::unique_ptr<Catalogue> dfs_catalogue = GetDFSCatalogue(disk);
|
||||
if(dfs_catalogue)
|
||||
std::unique_ptr<Catalogue> catalogue = GetDFSCatalogue(disk);
|
||||
if(catalogue == nullptr) catalogue = GetADFSCatalogue(disk);
|
||||
if(catalogue)
|
||||
{
|
||||
target.disks = disks;
|
||||
target.acorn.has_dfs = true;
|
||||
|
||||
// TODO: can't I just press shift?
|
||||
switch(dfs_catalogue->bootOption)
|
||||
switch(catalogue->bootOption)
|
||||
{
|
||||
default: target.loadingCommand = "*CAT\n"; break;
|
||||
case Catalogue::BootOption::LoadBOOT:
|
||||
target.loadingCommand = "*LOAD !BOOT\n"; break;
|
||||
case Catalogue::BootOption::RunBOOT:
|
||||
target.loadingCommand = "*RUN !BOOT\n"; break;
|
||||
case Catalogue::BootOption::ExecBOOT:
|
||||
target.loadingCommand = "*EXEC !BOOT\n"; break;
|
||||
case Catalogue::BootOption::None: target.loadingCommand = "*CAT\n"; break;
|
||||
default: target.acorn.should_hold_shift = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ struct Target {
|
||||
struct {
|
||||
bool has_adfs;
|
||||
bool has_dfs;
|
||||
bool should_hold_shift;
|
||||
} acorn;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user