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(); +}