mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-06-04 04:29:28 +00:00
Superdrive: support for inserting of virtual disks.
This commit is contained in:
parent
5e2f2b12e4
commit
b9fbd9b7c9
|
@ -86,8 +86,9 @@ RawFloppyImg::RawFloppyImg(std::string& file_path) : FloppyImgConverter()
|
|||
/** For raw images, we're going to ensure that the data fits into
|
||||
one of the supported floppy disk sizes as well as image size
|
||||
matches the size of the embedded HFS/MFS volume.
|
||||
Then we'll attempt to guess disk format based on image size.
|
||||
*/
|
||||
int RawFloppyImg::validate()
|
||||
int RawFloppyImg::calc_phys_params()
|
||||
{
|
||||
std::ifstream img_file;
|
||||
|
||||
|
@ -141,22 +142,60 @@ int RawFloppyImg::validate()
|
|||
return -1;
|
||||
}
|
||||
|
||||
// raw images don't include anything than raw disk data
|
||||
this->data_size = this->img_size;
|
||||
|
||||
// guess disk format from image file size
|
||||
static struct {
|
||||
int capacity;
|
||||
int rec_method;
|
||||
int num_tracks;
|
||||
int num_sectors;
|
||||
int num_sides;
|
||||
int density;
|
||||
} size_to_params[] = {
|
||||
{ 409600, 0, 80, 800, 1, 0}, // 400K GCR
|
||||
{ 819200, 0, 80, 800, 2, 0}, // 800K GCR
|
||||
{ 737280, 1, 80, 1440, 2, 0}, // 720K MFM
|
||||
{1474560, 1, 80, 2880, 2, 1}, // 1440K MFM
|
||||
};
|
||||
|
||||
this->rec_method = -1;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (this->img_size == size_to_params[i].capacity) {
|
||||
this->rec_method = size_to_params[i].rec_method;
|
||||
this->num_tracks = size_to_params[i].num_tracks;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->rec_method == -1) {
|
||||
LOG_F(ERROR, "RawFloppyImg: could't determine disk format from image size!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Guess physical parameters of the target virtual disk based on image size. */
|
||||
int RawFloppyImg::get_phys_params()
|
||||
/** Retrieve raw disk data. */
|
||||
int RawFloppyImg::get_raw_disk_data(char* buf)
|
||||
{
|
||||
// disk format: GCR vs MFM
|
||||
// single-sided vs double-sided
|
||||
// number of tracks
|
||||
// number of sectors
|
||||
return 0;
|
||||
}
|
||||
std::ifstream img_file;
|
||||
|
||||
img_file.open(img_path, std::ios::in | std::ios::binary);
|
||||
if (img_file.fail()) {
|
||||
img_file.close();
|
||||
LOG_F(ERROR, "RawFloppyImg: Could not open specified floppy image!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
img_file.seekg(0, img_file.beg);
|
||||
img_file.read(buf, this->data_size);
|
||||
img_file.close();
|
||||
|
||||
/** Convert high-level image data to low-level disk data. */
|
||||
int RawFloppyImg::import_data()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -166,7 +205,7 @@ int RawFloppyImg::export_data()
|
|||
return 0;
|
||||
}
|
||||
|
||||
int open_floppy_image(std::string& img_path)
|
||||
FloppyImgConverter* open_floppy_image(std::string& img_path)
|
||||
{
|
||||
FloppyImgConverter *fconv;
|
||||
|
||||
|
@ -176,7 +215,7 @@ int open_floppy_image(std::string& img_path)
|
|||
if (img_file.fail()) {
|
||||
img_file.close();
|
||||
LOG_F(ERROR, "Could not open specified floppy image!");
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FlopImgType itype = identify_image(img_file);
|
||||
|
@ -197,13 +236,13 @@ int open_floppy_image(std::string& img_path)
|
|||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "Unknown/unsupported image format!");
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (fconv->validate()) {
|
||||
LOG_F(ERROR, "Image validation failed!");
|
||||
return -1;
|
||||
if (fconv->calc_phys_params()) {
|
||||
delete fconv;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return fconv;
|
||||
}
|
||||
|
|
|
@ -44,12 +44,29 @@ enum class FlopImgType {
|
|||
class FloppyImgConverter {
|
||||
public:
|
||||
FloppyImgConverter() = default;
|
||||
~FloppyImgConverter() = default;
|
||||
virtual ~FloppyImgConverter() = default;
|
||||
|
||||
virtual int validate(void) = 0;
|
||||
virtual int get_phys_params(void) = 0;
|
||||
virtual int import_data(void) = 0;
|
||||
virtual int calc_phys_params(void) = 0;
|
||||
virtual int get_raw_disk_data(char* buf) = 0;
|
||||
virtual int export_data(void) = 0;
|
||||
|
||||
int get_data_size() { return this->data_size; };
|
||||
int get_disk_rec_method() { return this->rec_method; };
|
||||
int get_number_of_tracks() { return this->num_tracks; };
|
||||
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; };
|
||||
|
||||
protected:
|
||||
std::string img_path;
|
||||
int img_size;
|
||||
int data_size; // disk data size without image format specific stuff
|
||||
|
||||
int rec_method;
|
||||
int num_tracks;
|
||||
int num_sides;
|
||||
int num_sectors;
|
||||
int density;
|
||||
};
|
||||
|
||||
/** Converter for raw floppy images. */
|
||||
|
@ -58,16 +75,11 @@ public:
|
|||
RawFloppyImg(std::string& file_path);
|
||||
~RawFloppyImg() = default;
|
||||
|
||||
int validate(void);
|
||||
int get_phys_params(void);
|
||||
int import_data(void);
|
||||
int calc_phys_params(void);
|
||||
int get_raw_disk_data(char* buf);
|
||||
int export_data(void);
|
||||
|
||||
private:
|
||||
std::string img_path;
|
||||
int img_size;
|
||||
};
|
||||
|
||||
extern int open_floppy_image(std::string& img_path);
|
||||
extern FloppyImgConverter* open_floppy_image(std::string& img_path);
|
||||
|
||||
#endif // FLOPPY_IMG_H
|
||||
|
|
|
@ -26,6 +26,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#include <loguru.hpp>
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
|
||||
using namespace MacSuperdrive;
|
||||
|
||||
|
@ -69,7 +70,7 @@ uint8_t MacSuperDrive::status(uint8_t addr)
|
|||
case StatusAddr::Disk_In_Drive:
|
||||
return this->has_disk ^ 1; // reverse logic (active low)!
|
||||
case StatusAddr::Media_Kind:
|
||||
return this->media_kind;
|
||||
return this->media_kind ^ 1; // reverse logic!
|
||||
default:
|
||||
LOG_F(WARNING, "Superdrive: unimplemented status request, addr=0x%X", addr);
|
||||
return 0;
|
||||
|
@ -78,8 +79,64 @@ uint8_t MacSuperDrive::status(uint8_t addr)
|
|||
|
||||
int MacSuperDrive::insert_disk(std::string& img_path)
|
||||
{
|
||||
//open_floppy_image(img_path.c_str());
|
||||
open_floppy_image(img_path);
|
||||
if (this->has_disk) {
|
||||
LOG_F(ERROR, "Superdrive: drive is not empty!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FloppyImgConverter* img_conv = open_floppy_image(img_path);
|
||||
if (img_conv != nullptr) {
|
||||
this->img_conv = std::unique_ptr<FloppyImgConverter>(img_conv);
|
||||
set_disk_phys_params();
|
||||
|
||||
// allocate memory for raw disk data
|
||||
this->disk_data = std::unique_ptr<char[]>(new char[this->img_conv->get_data_size()]);
|
||||
|
||||
// swallow all raw disk data at once!
|
||||
this->img_conv->get_raw_disk_data(this->disk_data.get());
|
||||
|
||||
// everything is set up, let's say we got a disk
|
||||
this->has_disk = 1;
|
||||
} else {
|
||||
this->has_disk = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (rec_method == RecMethod::GCR) {
|
||||
// Apple GCR speeds per group of 16 tracks
|
||||
static int gcr_rpm_per_group[5] = {394, 429, 472, 525, 590};
|
||||
|
||||
// initialize three lookup tables:
|
||||
// sectors per track
|
||||
// rpm per track
|
||||
// logical block number of the first sector in each track
|
||||
// for easier navigation
|
||||
for (int grp = 0, blk_num = 0; grp < 5; grp++) {
|
||||
for (int trk = 0; trk < 16; trk++) {
|
||||
this->sectors_per_track[grp * 16 + trk] = 12 - grp;
|
||||
this->rpm_per_track[grp * 16 + trk] = gcr_rpm_per_group[grp];
|
||||
this->track_start_block[grp * 16 + trk] = blk_num;
|
||||
blk_num += 12 - grp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int sectors_per_track = this->media_kind ? 18 : 9;
|
||||
|
||||
// MFM disks use constant number of sectors per track
|
||||
// and the fixed rotational speed of 300 RPM
|
||||
for (int trk = 0; trk < 80; trk++) {
|
||||
this->sectors_per_track[trk] = sectors_per_track;
|
||||
this->rpm_per_track[trk] = 300;
|
||||
this->track_start_block[trk] = trk * sectors_per_track;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#define MAC_SUPERDRIVE_H
|
||||
|
||||
#include <devices/common/hwcomponent.h>
|
||||
#include <devices/floppy/floppyimg.h>
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace MacSuperdrive {
|
||||
|
@ -47,8 +49,14 @@ enum CommandAddr : uint8_t {
|
|||
|
||||
/** Type of media currently in the drive. */
|
||||
enum MediaKind : uint8_t {
|
||||
high_density = 0, // 1 or 2 MB disk
|
||||
low_density = 1
|
||||
low_density = 0,
|
||||
high_density = 1, // 1 or 2 MB disk
|
||||
};
|
||||
|
||||
/** Disk recording method. */
|
||||
enum RecMethod : int {
|
||||
GCR = 0,
|
||||
MFM = 1
|
||||
};
|
||||
|
||||
class MacSuperDrive : public HWComponent {
|
||||
|
@ -60,9 +68,24 @@ public:
|
|||
uint8_t status(uint8_t addr);
|
||||
int insert_disk(std::string& img_path);
|
||||
|
||||
protected:
|
||||
void set_disk_phys_params();
|
||||
|
||||
private:
|
||||
uint8_t media_kind;
|
||||
uint8_t has_disk;
|
||||
|
||||
// physical parameters of the currently inserted disk
|
||||
uint8_t media_kind;
|
||||
int rec_method;
|
||||
int num_tracks;
|
||||
int num_sides;
|
||||
int sectors_per_track[80];
|
||||
int rpm_per_track[80];
|
||||
int track_start_block[80]; // logical block number of the first sector in a track
|
||||
|
||||
std::unique_ptr<FloppyImgConverter> img_conv;
|
||||
|
||||
std::unique_ptr<char[]> disk_data;
|
||||
};
|
||||
|
||||
}; // namespace MacSuperdrive
|
||||
|
|
Loading…
Reference in New Issue
Block a user