Superdrive: implement track seeking.

This commit is contained in:
Maxim Poliakovski 2022-02-13 03:05:55 +01:00
parent 0d3fd01fef
commit 8d8cecbaba
4 changed files with 74 additions and 10 deletions

View File

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

View File

@ -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. */

View File

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

View File

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