diff --git a/devices/common/ata/atahd.cpp b/devices/common/ata/atahd.cpp
index d445cb8..abd1592 100644
--- a/devices/common/ata/atahd.cpp
+++ b/devices/common/ata/atahd.cpp
@@ -24,7 +24,6 @@ along with this program. If not, see .
#include
#include
-#include
#include
#include
#include
@@ -35,16 +34,11 @@ AtaHardDisk::AtaHardDisk() : AtaBaseDevice("ATA-HD", DEVICE_TYPE_ATA) {
}
void AtaHardDisk::insert_image(std::string filename) {
- this->hdd_img.open(filename, std::fstream::out | std::fstream::in | std::fstream::binary);
-
- struct stat stat_buf;
- int rc = stat(filename.c_str(), &stat_buf);
- if (!rc) {
- this->img_size = stat_buf.st_size;
- } else {
- ABORT_F("AtaHardDisk: could not determine file size using stat()");
+ if (!this->hdd_img.open(filename)) {
+ ABORT_F("AtaHardDisk: could not open image file");
}
- this->hdd_img.seekg(0, std::ios_base::beg);
+
+ this->img_size = this->hdd_img.size();
}
int AtaHardDisk::perform_command()
@@ -56,7 +50,6 @@ int AtaHardDisk::perform_command()
case NOP:
break;
case RECALIBRATE:
- hdd_img.seekg(0, std::ios::beg);
this->r_error = 0;
this->r_cylinder_lo = 0;
this->r_cylinder_hi = 0;
@@ -68,8 +61,7 @@ int AtaHardDisk::perform_command()
uint32_t sector = (r_sect_num << 16);
sector |= ((this->r_cylinder_lo) << 8) + (this->r_cylinder_hi);
uint64_t offset = sector * ATA_HD_SEC_SIZE;
- hdd_img.seekg(offset, std::ios::beg);
- hdd_img.read(buffer, sec_count * ATA_HD_SEC_SIZE);
+ hdd_img.read(buffer, offset, sec_count * ATA_HD_SEC_SIZE);
this->r_status &= ~DRQ;
}
break;
@@ -80,8 +72,7 @@ int AtaHardDisk::perform_command()
uint32_t sector = (r_sect_num << 16);
sector |= ((this->r_cylinder_lo) << 8) + (this->r_cylinder_hi);
uint64_t offset = sector * ATA_HD_SEC_SIZE;
- hdd_img.seekg(offset, std::ios::beg);
- hdd_img.write(buffer, sec_count * ATA_HD_SEC_SIZE);
+ hdd_img.write(buffer, offset, sec_count * ATA_HD_SEC_SIZE);
this->r_status &= ~DRQ;
}
break;
diff --git a/devices/common/ata/atahd.h b/devices/common/ata/atahd.h
index fa9ce32..20965a8 100644
--- a/devices/common/ata/atahd.h
+++ b/devices/common/ata/atahd.h
@@ -25,8 +25,9 @@ along with this program. If not, see .
#define ATA_HARD_DISK_H
#include
+#include
+
#include
-#include
#define ATA_HD_SEC_SIZE 512
@@ -40,7 +41,7 @@ public:
int perform_command() override;
private:
- std::fstream hdd_img;
+ ImgFile hdd_img;
uint64_t img_size;
char * buffer = new char[1 <<17];
diff --git a/devices/common/scsi/scsicdrom.cpp b/devices/common/scsi/scsicdrom.cpp
index 5e74c8d..6b29dd2 100644
--- a/devices/common/scsi/scsicdrom.cpp
+++ b/devices/common/scsi/scsicdrom.cpp
@@ -30,7 +30,6 @@ along with this program. If not, see .
#include
#include
-#include
using namespace std;
@@ -50,25 +49,20 @@ ScsiCdrom::ScsiCdrom(int my_id) : ScsiDevice(my_id)
void ScsiCdrom::insert_image(std::string filename)
{
- this->cdr_img.open(filename, ios::out | ios::in | ios::binary);
-
- struct stat stat_buf;
- int rc = stat(filename.c_str(), &stat_buf);
- if (!rc) {
- this->img_size = stat_buf.st_size;
- this->total_frames = (this->img_size + this->sector_size - 1) / this->sector_size;
-
- // create single track descriptor
- this->tracks[0] = {.trk_num = 1, .adr_ctrl = 0x14, .start_lba = 0};
- this->num_tracks = 1;
-
- // create Lead-out descriptor containing all data
- this->tracks[1] = {.trk_num = LEAD_OUT_TRK_NUM, .adr_ctrl = 0x14,
- .start_lba = static_cast(this->total_frames)};
- } else {
- ABORT_F("SCSI-CDROM: could not determine file size using stat()");
+ if (!this->cdr_img.open(filename)) {
+ ABORT_F("SCSI-CDROM: could not open image file");
}
- this->cdr_img.seekg(0, std::ios_base::beg);
+
+ this->img_size = this->cdr_img.size();
+ this->total_frames = (this->img_size + this->sector_size - 1) / this->sector_size;
+
+ // create single track descriptor
+ this->tracks[0] = {.trk_num = 1, .adr_ctrl = 0x14, .start_lba = 0};
+ this->num_tracks = 1;
+
+ // create Lead-out descriptor containing all data
+ this->tracks[1] = {.trk_num = LEAD_OUT_TRK_NUM, .adr_ctrl = 0x14,
+ .start_lba = static_cast(this->total_frames)};
}
void ScsiCdrom::process_command()
@@ -155,8 +149,7 @@ void ScsiCdrom::read(const uint32_t lba, const uint16_t transfer_len, const uint
transfer_size *= this->sector_size;
uint64_t device_offset = lba * this->sector_size;
- this->cdr_img.seekg(device_offset, this->cdr_img.beg);
- this->cdr_img.read(this->data_buf, transfer_size);
+ this->cdr_img.read(this->data_buf, device_offset, transfer_size);
this->bytes_out = transfer_size;
this->msg_buf[0] = ScsiMessage::COMMAND_COMPLETE;
diff --git a/devices/common/scsi/scsicdrom.h b/devices/common/scsi/scsicdrom.h
index bae5834..0859617 100644
--- a/devices/common/scsi/scsicdrom.h
+++ b/devices/common/scsi/scsicdrom.h
@@ -25,9 +25,9 @@ along with this program. If not, see .
#define SCSI_CDROM_H
#include
+#include
#include
-#include
#include
#include
@@ -74,7 +74,7 @@ private:
AddrMsf lba_to_msf(const int lba);
private:
- std::fstream cdr_img;
+ ImgFile cdr_img;
uint64_t img_size;
int total_frames;
int num_tracks;
diff --git a/devices/common/scsi/scsihd.cpp b/devices/common/scsi/scsihd.cpp
index 695636e..d17c559 100644
--- a/devices/common/scsi/scsihd.cpp
+++ b/devices/common/scsi/scsihd.cpp
@@ -30,7 +30,6 @@ along with this program. If not, see .
#include
#include
-#include
#define HDD_SECTOR_SIZE 512
@@ -43,17 +42,12 @@ ScsiHardDisk::ScsiHardDisk(int my_id) : ScsiDevice(my_id) {
void ScsiHardDisk::insert_image(std::string filename) {
//We don't want to store everything in memory, but
//we want to keep the hard disk available.
- this->hdd_img.open(filename, ios::out | ios::in | ios::binary);
-
- struct stat stat_buf;
- int rc = stat(filename.c_str(), &stat_buf);
- if (!rc) {
- this->img_size = stat_buf.st_size;
- this->total_blocks = (this->img_size + HDD_SECTOR_SIZE - 1) / HDD_SECTOR_SIZE;
- } else {
- ABORT_F("ScsiHardDisk: could not determine file size using stat()");
+ if (!this->hdd_img.open(filename)) {
+ ABORT_F("ScsiHardDisk: could not open image file");
}
- this->hdd_img.seekg(0, std::ios_base::beg);
+
+ this->img_size = this->hdd_img.size();
+ this->total_blocks = (this->img_size + HDD_SECTOR_SIZE - 1) / HDD_SECTOR_SIZE;
}
void ScsiHardDisk::process_command() {
@@ -267,8 +261,7 @@ void ScsiHardDisk::read(uint32_t lba, uint16_t transfer_len, uint8_t cmd_len) {
transfer_size *= HDD_SECTOR_SIZE;
uint64_t device_offset = lba * HDD_SECTOR_SIZE;
- this->hdd_img.seekg(device_offset, this->hdd_img.beg);
- this->hdd_img.read(img_buffer, transfer_size);
+ this->hdd_img.read(img_buffer, device_offset, transfer_size);
this->cur_buf_cnt = transfer_size;
this->msg_buf[0] = ScsiMessage::COMMAND_COMPLETE;
@@ -288,20 +281,17 @@ void ScsiHardDisk::write(uint32_t lba, uint16_t transfer_len, uint8_t cmd_len) {
this->incoming_size = transfer_size;
- this->hdd_img.seekg(device_offset, this->hdd_img.beg);
-
- this->post_xfer_action = [this]() {
- this->hdd_img.write(this->img_buffer, this->incoming_size);
+ this->post_xfer_action = [this, device_offset]() {
+ this->hdd_img.write(this->img_buffer, device_offset, this->incoming_size);
};
}
void ScsiHardDisk::seek(uint32_t lba) {
- uint64_t device_offset = lba * HDD_SECTOR_SIZE;
- this->hdd_img.seekg(device_offset, this->hdd_img.beg);
+ // No-op
}
void ScsiHardDisk::rewind() {
- this->hdd_img.seekg(0, this->hdd_img.beg);
+ // No-op
}
static const PropMap SCSI_HD_Properties = {
diff --git a/devices/common/scsi/scsihd.h b/devices/common/scsi/scsihd.h
index 98f7118..fc8f168 100644
--- a/devices/common/scsi/scsihd.h
+++ b/devices/common/scsi/scsihd.h
@@ -25,9 +25,9 @@ along with this program. If not, see .
#define SCSI_HD_H
#include
+#include
#include
-#include
#include
#include
@@ -60,7 +60,7 @@ protected:
void rewind();
private:
- std::fstream hdd_img;
+ ImgFile hdd_img;
uint64_t img_size;
int total_blocks;
uint64_t file_offset = 0;
diff --git a/devices/floppy/floppyimg.cpp b/devices/floppy/floppyimg.cpp
index 59ab541..4e0d3cf 100644
--- a/devices/floppy/floppyimg.cpp
+++ b/devices/floppy/floppyimg.cpp
@@ -25,13 +25,13 @@ along with this program. If not, see .
#include
#include
#include
+#include
#include
#include
-#include
#include
-static FlopImgType identify_image(std::ifstream& img_file)
+static FlopImgType identify_image(ImgFile& img_file)
{
// WOZ images identification strings
static uint8_t WOZ1_SIG[] = {0x57, 0x4F, 0x5A, 0x31, 0xFF, 0x0A, 0x0D, 0x0A};
@@ -39,8 +39,7 @@ static FlopImgType identify_image(std::ifstream& img_file)
uint8_t buf[8] = { 0 };
- img_file.seekg(0, std::ios::beg);
- img_file.read((char *)buf, sizeof(buf));
+ img_file.read((char *)buf, 0, sizeof(buf));
// WOZ files are easily identified
if (!std::memcmp(buf, WOZ1_SIG, sizeof(buf))) {
@@ -50,8 +49,7 @@ static FlopImgType identify_image(std::ifstream& img_file)
} else {
for (int offset = 0; offset <=84; offset += 84) {
// rewind to logical block 2
- img_file.seekg(2*BLOCK_SIZE + offset, std::ios::beg);
- img_file.read((char *)buf, sizeof(buf));
+ img_file.read((char *)buf, 2*BLOCK_SIZE + offset, sizeof(buf));
// check for HFS/MFS signature at the start of the logical block 2
if ((buf[0] == 0x42 && buf[1] == 0x44) ||
@@ -79,26 +77,22 @@ RawFloppyImg::RawFloppyImg(std::string& file_path) : FloppyImgConverter()
*/
int RawFloppyImg::calc_phys_params()
{
- std::ifstream img_file;
+ ImgFile img_file;
- img_file.open(img_path, std::ios::in | std::ios::binary);
- if (img_file.fail()) {
+ if (!img_file.open(img_path)) {
img_file.close();
LOG_F(ERROR, "RawFloppyImg: Could not open specified floppy image!");
return -1;
}
// determine image size
- img_file.seekg(0, img_file.end);
- size_t img_size = img_file.tellg();
+ size_t img_size = img_file.size();
+ img_file.close();
if (img_size > 2*1024*1024) {
LOG_F(ERROR, "RawFloppyImg: image size is too large to determine disk format from image size!");
return -1;
}
this->img_size = (int)img_size;
- img_file.seekg(0, img_file.beg);
-
- img_file.close();
// verify image size
if (this->img_size < 5*BLOCK_SIZE) {
@@ -177,17 +171,15 @@ int RawFloppyImg::calc_phys_params()
/** Retrieve raw disk data. */
int RawFloppyImg::get_raw_disk_data(char* buf)
{
- std::ifstream img_file;
+ ImgFile img_file;
- img_file.open(img_path, std::ios::in | std::ios::binary);
- if (img_file.fail()) {
+ if (!img_file.open(img_path)) {
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.read(buf, 0, this->data_size);
img_file.close();
return 0;
@@ -206,24 +198,20 @@ DiskCopy42Img::DiskCopy42Img(std::string& file_path) : FloppyImgConverter()
}
int DiskCopy42Img::calc_phys_params() {
- std::ifstream img_file;
+ ImgFile img_file;
- img_file.open(img_path, std::ios::in | std::ios::binary);
- if (img_file.fail()) {
+ if (!img_file.open(img_path)) {
img_file.close();
LOG_F(ERROR, "DiskCopy42Img: could not open specified floppy image!");
return -1;
}
// determine image size
- img_file.seekg(0, img_file.end);
- size_t img_size = img_file.tellg();
- img_file.seekg(0, img_file.beg);
+ size_t img_size = img_file.size();
// get data size from image
uint8_t buf[4];
- img_file.seekg(0x40, img_file.beg);
- img_file.read((char *)&buf, 4);
+ img_file.read((char *)&buf, 0x40, 4);
this->data_size = READ_DWORD_BE_U(buf);
if (this->data_size > img_size) {
@@ -235,9 +223,8 @@ int DiskCopy42Img::calc_phys_params() {
uint8_t disk_format = 0xFFU;
- img_file.seekg(0x50, img_file.beg);
- img_file.read((char *)&disk_format, 1);
- img_file.read((char *)&this->format_byte, 1);
+ img_file.read((char *)&disk_format, 0x50, 1);
+ img_file.read((char *)&this->format_byte, 0x51, 1);
img_file.close();
@@ -272,17 +259,15 @@ int DiskCopy42Img::calc_phys_params() {
}
int DiskCopy42Img::get_raw_disk_data(char* buf) {
- std::ifstream img_file;
+ ImgFile img_file;
- img_file.open(img_path, std::ios::in | std::ios::binary);
- if (img_file.fail()) {
+ if (!img_file.open(img_path)) {
img_file.close();
LOG_F(ERROR, "DiskCopy42Img: could not open specified floppy image!");
return -1;
}
- img_file.seekg(0x54, img_file.beg);
- img_file.read(buf, this->data_size);
+ img_file.read(buf, 0x54, this->data_size);
img_file.close();
return 0;
@@ -296,10 +281,9 @@ FloppyImgConverter* open_floppy_image(std::string& img_path)
{
FloppyImgConverter *fconv = nullptr;
- std::ifstream img_file;
+ ImgFile img_file;
- img_file.open(img_path, std::ios::in | std::ios::binary);
- if (img_file.fail()) {
+ if (!img_file.open(img_path)) {
img_file.close();
LOG_F(ERROR, "Could not open specified floppy image (%s)!", img_path.c_str());
return nullptr;
diff --git a/devices/storage/blockstoragedevice.cpp b/devices/storage/blockstoragedevice.cpp
index 52379b3..e797aa1 100644
--- a/devices/storage/blockstoragedevice.cpp
+++ b/devices/storage/blockstoragedevice.cpp
@@ -23,8 +23,6 @@ along with this program. If not, see .
#include
-#include
-
using namespace std;
BlockStorageDevice::BlockStorageDevice(const uint32_t cache_blocks, const uint32_t block_size) {
@@ -36,21 +34,17 @@ BlockStorageDevice::BlockStorageDevice(const uint32_t cache_blocks, const uint32
}
BlockStorageDevice::~BlockStorageDevice() {
- if (this->img_file)
- this->img_file.close();
+ this->img_file.close();
}
int BlockStorageDevice::set_host_file(std::string file_path) {
this->is_ready = false;
- this->img_file.open(file_path, ios::out | ios::in | ios::binary);
-
- struct stat stat_buf;
- int rc = stat(file_path.c_str(), &stat_buf);
- if (rc)
+ if (!this->img_file.open(file_path)) {
return -1;
+ }
- this->size_bytes = stat_buf.st_size;
+ this->size_bytes = this->img_file.size();
this->size_blocks = this->size_bytes / this->block_size;
this->set_fpos(0);
@@ -61,7 +55,6 @@ int BlockStorageDevice::set_host_file(std::string file_path) {
int BlockStorageDevice::set_fpos(const uint32_t lba) {
this->cur_fpos = lba * this->block_size;
- this->img_file.seekg(this->cur_fpos, this->img_file.beg);
return 0;
}
@@ -75,7 +68,7 @@ int BlockStorageDevice::read_begin(int nblocks, uint32_t max_len) {
this->remain_size = 0;
}
- this->img_file.read(this->data_cache.get(), read_size);
+ this->img_file.read(this->data_cache.get(), this->cur_fpos, read_size);
this->cur_fpos += read_size;
return read_size;
@@ -95,7 +88,7 @@ int BlockStorageDevice::read_more() {
this->remain_size = 0;
}
- this->img_file.read(this->data_cache.get(), read_size);
+ this->img_file.read(this->data_cache.get(), this->cur_fpos, read_size);
this->cur_fpos += read_size;
return read_size;
diff --git a/devices/storage/blockstoragedevice.h b/devices/storage/blockstoragedevice.h
index 858f98c..3a93270 100644
--- a/devices/storage/blockstoragedevice.h
+++ b/devices/storage/blockstoragedevice.h
@@ -24,8 +24,9 @@ along with this program. If not, see .
#ifndef BLOCK_STORAGE_DEVICE_H
#define BLOCK_STORAGE_DEVICE_H
+#include
+
#include
-#include
#include
#include
@@ -45,7 +46,7 @@ public:
int write_begin(char *buf, int nblocks);
protected:
- std::fstream img_file = {};
+ ImgFile img_file;
uint64_t size_bytes = 0; // image file size in bytes
uint64_t size_blocks = 0; // image file size in blocks
uint64_t cur_fpos = 0; // current image file pointer position
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 6010b1f..fa593ad 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -1,6 +1,9 @@
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+include(PlatformGlob)
+
include_directories("${PROJECT_SOURCE_DIR}")
-file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
+platform_glob(SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
add_library(utils OBJECT ${SOURCES})
target_link_libraries(utils PRIVATE)
diff --git a/utils/imgfile.h b/utils/imgfile.h
new file mode 100644
index 0000000..cb72e5f
--- /dev/null
+++ b/utils/imgfile.h
@@ -0,0 +1,49 @@
+/*
+DingusPPC - The Experimental PowerPC Macintosh emulator
+Copyright (C) 2018-23 divingkatae and maximum
+ (theweirdo) spatium
+
+(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+/** @file Image file abstraction for floppy, hard drive and CD-ROM images
+ * (implemented on each platform). */
+
+#ifndef IMGFILE_H
+#define IMGFILE_H
+
+#include
+#include
+#include
+
+class ImgFile {
+public:
+ ImgFile();
+ ~ImgFile();
+
+ bool open(const std::string& img_path);
+ void close();
+
+ size_t size() const;
+
+ size_t read(void* buf, off_t offset, size_t length) const;
+ size_t write(const void* buf, off_t offset, size_t length);
+private:
+ class Impl; // Holds private fields
+ std::unique_ptr impl;
+};
+
+#endif // IMGFILE_H
diff --git a/utils/imgfile_sdl.cpp b/utils/imgfile_sdl.cpp
new file mode 100644
index 0000000..4f7a155
--- /dev/null
+++ b/utils/imgfile_sdl.cpp
@@ -0,0 +1,67 @@
+/*
+DingusPPC - The Experimental PowerPC Macintosh emulator
+Copyright (C) 2018-23 divingkatae and maximum
+ (theweirdo) spatium
+
+(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#include
+
+#include
+
+class ImgFile::Impl {
+public:
+ std::fstream stream;
+};
+
+ImgFile::ImgFile(): impl(std::make_unique())
+{
+
+}
+
+ImgFile::~ImgFile() = default;
+
+bool ImgFile::open(const std::string &img_path)
+{
+ impl->stream.open(img_path, std::ios::in | std::ios::out | std::ios::binary);
+ return !impl->stream.fail();
+}
+
+void ImgFile::close()
+{
+ impl->stream.close();
+}
+
+size_t ImgFile::size() const
+{
+ impl->stream.seekg(0, impl->stream.end);
+ return impl->stream.tellg();
+}
+
+size_t ImgFile::read(void* buf, off_t offset, size_t length) const
+{
+ impl->stream.seekg(offset, std::ios::beg);
+ impl->stream.read((char *)buf, length);
+ return impl->stream.gcount();
+}
+
+size_t ImgFile::write(const void* buf, off_t offset, size_t length)
+{
+ impl->stream.seekg(offset, std::ios::beg);
+ impl->stream.write((const char *)buf, length);
+ return impl->stream.gcount();
+}