diff --git a/Components/1770/1770.cpp b/Components/1770/1770.cpp index 62aa5f5e3..e1a800c5f 100644 --- a/Components/1770/1770.cpp +++ b/Components/1770/1770.cpp @@ -10,6 +10,8 @@ using namespace WD; +WD1770::WD1770() : state_(State::Waiting), status_(0), has_command_(false) {} + void WD1770::set_drive(std::shared_ptr drive) { } @@ -20,13 +22,54 @@ void WD1770::set_is_double_density(bool is_double_density) void WD1770::set_register(int address, uint8_t value) { + switch(address&3) + { + case 0: + command_ = value; + has_command_ = true; + // TODO: is this force interrupt? + break; + case 1: track_ = value; break; + case 2: sector_ = value; break; + case 3: data_ = value; break; + } } uint8_t WD1770::get_register(int address) { - return 0; + switch(address&3) + { + default: return status_; + case 1: return track_; + case 2: return sector_; + case 3: return data_; + } } void WD1770::run_for_cycles(unsigned int number_of_cycles) { + // perform one step every eight cycles, arbitrariy as I can find no timing documentation + cycles += number_of_cycles; + while(cycles > 8) + { + cycles -= 8; + + switch(state_) + { + case State::Waiting: + if(has_command_) + { + has_command_ = false; + if(command_ & 0x80) + state_ = (command_ & 0x40) ? State::BeginType3 : State::BeginType2; + else + state_ = State::BeginType1; + } + continue; + + default: + printf("Unhandled state %d!", state_); + return; + } + } } diff --git a/Components/1770/1770.hpp b/Components/1770/1770.hpp index 48187087e..735199f3d 100644 --- a/Components/1770/1770.hpp +++ b/Components/1770/1770.hpp @@ -15,12 +15,43 @@ namespace WD { class WD1770 { public: + WD1770(); + void set_drive(std::shared_ptr drive); void set_is_double_density(bool is_double_density); void set_register(int address, uint8_t value); uint8_t get_register(int address); void run_for_cycles(unsigned int number_of_cycles); + + enum Flag: uint8_t { + MotorOn = 0x80, + WriteProtect = 0x40, + RecordType = 0x20, + SpinUp = 0x20, + RecordNotFound = 0x10, + CRCError = 0x08, + LostData = 0x04, + TrackZero = 0x04, + DataRequest = 0x02, + Index = 0x02, + Busy = 0x01 + }; + + private: + unsigned int cycles; + + enum class State { + Waiting, + BeginType1, BeginType2, BeginType3 + } state_; + + uint8_t status_; + uint8_t track_; + uint8_t sector_; + uint8_t data_; + uint8_t command_; + bool has_command_; }; } diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 8c25148d1..95fd858ca 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -120,6 +120,10 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin } else { +// if((address >> 8) == 0xfc) +// { +// printf("d"); +// } switch(address & 0xff0f) { case 0xfe00: @@ -297,7 +301,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin } break; - case 0xfcc4: case 0xfcc5: case 0xfcc6: case 0xfcc7: + case 0xfc04: case 0xfc05: case 0xfc06: case 0xfc07: if(_wd1770 && (address&0x00f0) == 0x00c0) { if(isReadOperation(operation)) @@ -306,7 +310,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin _wd1770->set_register(address, *value); } break; - case 0xfcc0: + case 0xfc00: if(_wd1770 && (address&0x00f0) == 0x00c0) { if(isReadOperation(operation))