diff --git a/devices/floppy/floppyimg.cpp b/devices/floppy/floppyimg.cpp index 19669a7..e0b50ed 100644 --- a/devices/floppy/floppyimg.cpp +++ b/devices/floppy/floppyimg.cpp @@ -169,6 +169,15 @@ int RawFloppyImg::calc_phys_params() this->num_sectors = size_to_params[i].num_sectors; this->num_sides = size_to_params[i].num_sides; this->density = size_to_params[i].density; + + // fake format byte for GCR disks + if (!this->rec_method) { + this->format_byte = (this->num_sides == 2) ? 0x22 : 0x2; + } else { + // For MFM disks this byte indicates sector size in blocks + this->format_byte = 2; + } + break; } } diff --git a/devices/floppy/floppyimg.h b/devices/floppy/floppyimg.h index 86b99dd..b090dc9 100644 --- a/devices/floppy/floppyimg.h +++ b/devices/floppy/floppyimg.h @@ -56,6 +56,7 @@ public: int get_number_of_sides() { return this->num_sides; }; int get_sectors_per_side() { return this->num_sectors; }; int get_rec_density() { return this->density; }; + uint8_t get_format_byte() { return this->format_byte; }; protected: std::string img_path; @@ -67,6 +68,7 @@ protected: int num_sides; int num_sectors; int density; + uint8_t format_byte; // GCR format byte from sector header }; /** Converter for raw floppy images. */ diff --git a/devices/floppy/superdrive.cpp b/devices/floppy/superdrive.cpp index 3208e77..e926d56 100644 --- a/devices/floppy/superdrive.cpp +++ b/devices/floppy/superdrive.cpp @@ -40,7 +40,7 @@ MacSuperDrive::MacSuperDrive() this->eject_latch = 0; // eject latch is off this->drive_mode = RecMethod::MFM; // assume MFM mode by default this->motor_stat = 0; // spindle motor is off - this->head_pos = 0; // current head position + this->cur_track = 0; // current head position this->is_ready = 0; // drive not ready } @@ -56,10 +56,10 @@ void MacSuperDrive::command(uint8_t addr, uint8_t value) break; case CommandAddr::Do_Step: if (!value) { - this->head_pos += this->step_dir; - if (this->head_pos < 0) - this->head_pos = 0; - this->track_zero = this->head_pos == 0; + this->cur_track += this->step_dir; + if (this->cur_track < 0) + this->cur_track = 0; + this->track_zero = this->cur_track == 0; } break; case CommandAddr::Motor_On_Off: @@ -101,6 +101,9 @@ uint8_t MacSuperDrive::status(uint8_t addr) return this->motor_stat ^ 1; // reverse logic case StatusAddr::Eject_Latch: return this->eject_latch; + case StatusAddr::Select_Head_0: + this->cur_head = 0; + return 1; // not sure what should be returned here case StatusAddr::MFM_Support: return 1; // Superdrive does support MFM encoding scheme case StatusAddr::Double_Sided: @@ -113,6 +116,9 @@ uint8_t MacSuperDrive::status(uint8_t addr) return this->wr_protect ^ 1; // reverse logic case StatusAddr::Track_Zero: return this->track_zero ^ 1; // reverse logic + case StatusAddr::Select_Head_1: + this->cur_head = 1; + return 1; // not sure what should be returned here case StatusAddr::Drive_Mode: return this->drive_mode; case StatusAddr::Drive_Ready: @@ -157,10 +163,11 @@ int MacSuperDrive::insert_disk(std::string& img_path) void MacSuperDrive::set_disk_phys_params() { - this->rec_method = this->img_conv->get_disk_rec_method(); - this->num_tracks = this->img_conv->get_number_of_tracks(); - this->num_sides = this->img_conv->get_number_of_sides(); - this->media_kind = this->img_conv->get_rec_density(); + this->rec_method = this->img_conv->get_disk_rec_method(); + this->num_tracks = this->img_conv->get_number_of_tracks(); + this->num_sides = this->img_conv->get_number_of_sides(); + this->media_kind = this->img_conv->get_rec_density(); + this->format_byte = this->img_conv->get_format_byte(); switch_drive_mode(this->rec_method); } @@ -200,3 +207,33 @@ void MacSuperDrive::switch_drive_mode(int mode) this->drive_mode = RecMethod::MFM; } } + +double MacSuperDrive::get_current_track_delay() +{ + return (1.0f / (this->rpm_per_track[this->cur_track] / 60)); +} + +double MacSuperDrive::get_sector_delay() +{ + return this->get_current_track_delay() / this->sectors_per_track[this->cur_track]; +} + +void MacSuperDrive::init_track_search(int pos) +{ + if (pos == -1) { + // pick random sector number + this->cur_sector = this->sectors_per_track[this->cur_track] / 2; + } else { + this->cur_sector = pos; + } +} + +SectorHdr MacSuperDrive::next_sector_header() +{ + return SectorHdr { + this->cur_track, + this->cur_head, + this->cur_sector++, + this->format_byte + }; +} diff --git a/devices/floppy/superdrive.h b/devices/floppy/superdrive.h index b5a3851..1015eb7 100644 --- a/devices/floppy/superdrive.h +++ b/devices/floppy/superdrive.h @@ -38,12 +38,14 @@ enum StatusAddr : uint8_t { Step_Status = 1, Motor_Status = 2, Eject_Latch = 3, + Select_Head_0 = 4, MFM_Support = 5, Double_Sided = 6, Drive_Exists = 7, Disk_In_Drive = 8, Write_Protect = 9, Track_Zero = 0xA, + Select_Head_1 = 0xC, Drive_Mode = 0xD, Drive_Ready = 0xE, Media_Kind = 0xF @@ -70,6 +72,13 @@ enum RecMethod : int { MFM = 1 }; +typedef struct SectorHdr { + int track; + int side; + int sector; + int format; +} SectorHdr; + class MacSuperDrive : public HWComponent { public: MacSuperDrive(); @@ -78,6 +87,10 @@ public: void command(uint8_t addr, uint8_t value); uint8_t status(uint8_t addr); int insert_disk(std::string& img_path); + double get_current_track_delay(); + double get_sector_delay(); + void init_track_search(int pos); + SectorHdr next_sector_header(); protected: void set_disk_phys_params(); @@ -91,11 +104,14 @@ private: uint8_t is_ready; uint8_t track_zero; // 1 - if head is at track zero int step_dir; // step direction -1/+1 - int head_pos; // track number the head is currently at + int cur_track; // track number the head is currently at + int cur_head; // current head number: 1 - upper, 0 - lower + int cur_sector; // current sector number // physical parameters of the currently inserted disk uint8_t media_kind; uint8_t wr_protect; + uint8_t format_byte; int rec_method; int num_tracks; int num_sides;