From f91122aee7ee01589f425d709b9e888b6ad0a578 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Sat, 16 Sep 2023 14:17:27 -0700 Subject: [PATCH] Move floppy disk image reading to be behind an ImgFile class Allows different implementations for native (C++ streams) and JS (workerApi.disks.* functions) versions. Updates mihaip/infinite-mac#219 --- devices/floppy/floppyimg.cpp | 60 +++++++++++------------------ utils/CMakeLists.txt | 5 ++- utils/imgfile.h | 48 +++++++++++++++++++++++ utils/imgfile_js.cpp | 75 ++++++++++++++++++++++++++++++++++++ utils/imgfile_sdl.cpp | 67 ++++++++++++++++++++++++++++++++ 5 files changed, 216 insertions(+), 39 deletions(-) create mode 100644 utils/imgfile.h create mode 100644 utils/imgfile_js.cpp create mode 100644 utils/imgfile_sdl.cpp diff --git a/devices/floppy/floppyimg.cpp b/devices/floppy/floppyimg.cpp index 59ab54181c..4e0d3cf32a 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/utils/CMakeLists.txt b/utils/CMakeLists.txt index 6010b1f860..fa593adf4c 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 0000000000..bb8307d972 --- /dev/null +++ b/utils/imgfile.h @@ -0,0 +1,48 @@ +/* +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 + +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_js.cpp b/utils/imgfile_js.cpp new file mode 100644 index 0000000000..45ff1adbeb --- /dev/null +++ b/utils/imgfile_js.cpp @@ -0,0 +1,75 @@ +/* +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: + int disk_id; +}; + +ImgFile::ImgFile(): impl(std::make_unique()) +{ + +} + +ImgFile::~ImgFile() = default; + +bool ImgFile::open(const std::string &img_path) +{ + int disk_id = EM_ASM_INT({ + return workerApi.disks.open(UTF8ToString($0)); + }, img_path.c_str()); + if (disk_id == -1) { + return false; + } + + impl->disk_id = disk_id; + return true; +} + +void ImgFile::close() +{ + EM_ASM_({ workerApi.disks.close($0); }, impl->disk_id); +} + +size_t ImgFile::size() const +{ + return EM_ASM_INT({ return workerApi.disks.size($0); }, impl->disk_id); +} + +size_t ImgFile::read(void* buf, off_t offset, size_t length) const +{ + int read_size = EM_ASM_INT({ + return workerApi.disks.read($0, $1, $2, $3); + }, impl->disk_id, buf, int(offset), int(length)); + return read_size; +} + +size_t ImgFile::write(const void* buf, off_t offset, size_t length) +{ + int write_size = EM_ASM_INT({ + return workerApi.disks.write($0, $1, $2, $3); + }, impl->disk_id, buf, int(offset), int(length)); + return write_size; +} diff --git a/utils/imgfile_sdl.cpp b/utils/imgfile_sdl.cpp new file mode 100644 index 0000000000..4f7a155166 --- /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(); +}