Skip to content

Commit

Permalink
Move floppy disk image reading to be behind an ImgFile class
Browse files Browse the repository at this point in the history
Allows different implementations for native (C++ streams) and JS
(workerApi.disks.* functions) versions.

Updates mihaip/infinite-mac#219
  • Loading branch information
mihaip committed Sep 16, 2023
1 parent a434dcb commit f91122a
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 39 deletions.
60 changes: 22 additions & 38 deletions devices/floppy/floppyimg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <machines/machineproperties.h>
#include <loguru.hpp>
#include <memaccess.h>
#include <utils/imgfile.h>

#include <cinttypes>
#include <cstring>
#include <fstream>
#include <string>

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};
static uint8_t WOZ2_SIG[] = {0x57, 0x4F, 0x5A, 0x32, 0xFF, 0x0A, 0x0D, 0x0A};

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))) {
Expand All @@ -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) ||
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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();

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion utils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
48 changes: 48 additions & 0 deletions utils/imgfile.h
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

/** @file Image file abstraction for floppy, hard drive and CD-ROM images
* (implemented on each platform). */

#ifndef IMGFILE_H
#define IMGFILE_H

#include <cstddef>
#include <string>

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

#endif // IMGFILE_H
75 changes: 75 additions & 0 deletions utils/imgfile_js.cpp
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

#include <utils/imgfile.h>

#include <emscripten.h>

class ImgFile::Impl {
public:
int disk_id;
};

ImgFile::ImgFile(): impl(std::make_unique<Impl>())
{

}

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;
}
67 changes: 67 additions & 0 deletions utils/imgfile_sdl.cpp
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

#include <utils/imgfile.h>

#include <fstream>

class ImgFile::Impl {
public:
std::fstream stream;
};

ImgFile::ImgFile(): impl(std::make_unique<Impl>())
{

}

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

0 comments on commit f91122a

Please sign in to comment.