diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d8077d73..2bcdf4cba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -771,7 +771,9 @@ target_sources(${PROJECT_NAME} PRIVATE
core/imgread/cue.cpp
core/imgread/gdi.cpp
core/imgread/ImgReader.cpp
- core/imgread/ioctl.cpp)
+ core/imgread/ioctl.cpp
+ core/imgread/isofs.cpp
+ core/imgread/isofs.h)
if(NOT LIBRETRO)
target_sources(${PROJECT_NAME} PRIVATE
diff --git a/core/imgread/isofs.cpp b/core/imgread/isofs.cpp
new file mode 100644
index 000000000..341e92b51
--- /dev/null
+++ b/core/imgread/isofs.cpp
@@ -0,0 +1,112 @@
+/*
+ Copyright 2022 flyinghead
+
+ This file is part of Flycast.
+
+ Flycast 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 2 of the License, or
+ (at your option) any later version.
+
+ Flycast 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 Flycast. If not, see .
+ */
+#include "isofs.h"
+#include "reios/iso9660.h"
+
+static u32 decode_iso733(iso733_t v)
+{
+ return ((v >> 56) & 0x000000FF)
+ | ((v >> 40) & 0x0000FF00)
+ | ((v >> 24) & 0x00FF0000)
+ | ((v >> 8) & 0xFF000000);
+}
+
+IsoFs::IsoFs(Disc *disc) : disc(disc)
+{
+ baseFad = disc->GetBaseFAD();
+}
+
+IsoFs::Directory *IsoFs::getRoot()
+{
+ u8 temp[2048];
+ disc->ReadSectors(baseFad + 16, 1, temp, 2048);
+ // Primary Volume Descriptor
+ const iso9660_pvd_t *pvd = (const iso9660_pvd_t *)temp;
+
+ Directory *root = new Directory(this);
+ if (pvd->type == 1 && !memcmp(pvd->id, ISO_STANDARD_ID, strlen(ISO_STANDARD_ID)) && pvd->version == 1)
+ {
+ u32 lba = decode_iso733(pvd->root_directory_record.extent);
+ u32 len = decode_iso733(pvd->root_directory_record.size);
+
+ len = ((len + 2047) / 2048) * 2048;
+ root->data.resize(len);
+
+ DEBUG_LOG(GDROM, "iso9660 root directory FAD: %d, len: %d", 150 + lba, len);
+ disc->ReadSectors(150 + lba, len / 2048, root->data.data(), 2048);
+ }
+ else {
+ WARN_LOG(GDROM, "iso9660 PVD NOT found");
+ root->data.resize(1);
+ root->data[0] = 0;
+ }
+ return root;
+}
+
+IsoFs::Entry *IsoFs::Directory::getEntry(const std::string& name)
+{
+ std::string isoname = name + ';';
+ for (u32 i = 0; i < data.size(); )
+ {
+ const iso9660_dir_t *dir = (const iso9660_dir_t *)&data[i];
+ if (dir->length == 0)
+ break;
+
+ if ((u8)dir->filename.str[0] > isoname.size()
+ && memcmp(dir->filename.str + 1, isoname.c_str(), isoname.size()) == 0)
+ {
+ DEBUG_LOG(GDROM, "Found %s at offset %X", name.c_str(), i);
+ u32 startFad = decode_iso733(dir->extent) + 150;
+ u32 len = decode_iso733(dir->size);
+ if ((dir->file_flags & ISO_DIRECTORY) == 0)
+ {
+ File *file = new File(fs);
+ file->startFad = startFad;
+ file->len = len;
+
+ return file;
+ }
+ else
+ {
+ Directory *directory = new Directory(fs);
+ directory->data.resize(len);
+ fs->disc->ReadSectors(startFad, len / 2048, directory->data.data(), 2048);
+
+ return directory;
+ }
+ }
+ i += dir->length;
+ }
+ return nullptr;
+}
+
+u32 IsoFs::File::read(u8 *buf, u32 size, u32 offset) const
+{
+ size = std::min(size, len - offset);
+ u32 sectors = size / 2048;
+ fs->disc->ReadSectors(startFad + offset / 2048, sectors, buf, 2048);
+ size -= sectors * 2048;
+ if (size > 0)
+ {
+ u8 temp[2048];
+ fs->disc->ReadSectors(startFad + offset / 2048 + sectors, 1, temp, 2048);
+ memcpy(buf + sectors * 2048, temp, size);
+ }
+ return sectors * 2048 + size;
+}
diff --git a/core/imgread/isofs.h b/core/imgread/isofs.h
new file mode 100644
index 000000000..4d2944900
--- /dev/null
+++ b/core/imgread/isofs.h
@@ -0,0 +1,76 @@
+/*
+ Copyright 2022 flyinghead
+
+ This file is part of Flycast.
+
+ Flycast 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 2 of the License, or
+ (at your option) any later version.
+
+ Flycast 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 Flycast. If not, see .
+ */
+#pragma once
+#include "common.h"
+
+class IsoFs
+{
+public:
+ class Entry
+ {
+ public:
+ virtual bool isDirectory() const = 0;
+ virtual ~Entry() = default;
+
+ protected:
+ Entry(IsoFs *fs) : fs(fs) {}
+
+ IsoFs *fs;
+ };
+
+ class Directory final : public Entry
+ {
+ public:
+ bool isDirectory() const override { return true; }
+
+ Entry *getEntry(const std::string& name);
+
+ private:
+ Directory(IsoFs *fs) : Entry(fs) {}
+
+ std::vector data;
+
+ friend class IsoFs;
+ };
+
+ class File final : public Entry
+ {
+ public:
+ bool isDirectory() const override { return false; }
+
+ u32 getSize() const { return len; }
+
+ u32 read(u8 *buf, u32 size, u32 offset = 0) const;
+
+ private:
+ File(IsoFs *fs) : Entry(fs) {}
+
+ u32 startFad = 0;
+ u32 len = 0;
+
+ friend class IsoFs;
+ };
+
+ IsoFs(Disc *disc);
+ Directory *getRoot();
+
+private:
+ Disc *disc;
+ u32 baseFad;
+};
diff --git a/core/reios/descrambl.cpp b/core/reios/descrambl.cpp
index aa92ddd13..445cd35b2 100644
--- a/core/reios/descrambl.cpp
+++ b/core/reios/descrambl.cpp
@@ -7,25 +7,24 @@
*/
#include "descrambl.h"
-#include "imgread/common.h"
#include
#define MAXCHUNK (2048*1024)
-static unsigned int seed;
+static u32 seed;
-static void my_srand(unsigned int n)
+static void my_srand(u32 n)
{
seed = n & 0xffff;
}
-static unsigned int my_rand()
+static u32 my_rand()
{
seed = (seed * 2109 + 9273) & 0x7fff;
return (seed + 0xc000) & 0xffff;
}
-static void load_chunk(u8* &src, unsigned char *ptr, unsigned long sz)
+static void load_chunk(const u8* &src, u8 *ptr, u32 sz)
{
verify(sz <= MAXCHUNK);
@@ -53,32 +52,23 @@ static void load_chunk(u8* &src, unsigned char *ptr, unsigned long sz)
}
}
-static void descrambl_buffer(u8* src, unsigned char *dst, unsigned long filesz)
+void descrambl_buffer(const u8 *src, u8 *dst, u32 size)
{
- unsigned long chunksz;
+ u32 chunksz;
- my_srand(filesz);
+ my_srand(size);
/* Descramble 2 meg blocks for as long as possible, then
gradually reduce the window down to 32 bytes (1 slice) */
for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1)
- while (filesz >= chunksz)
+ while (size >= chunksz)
{
load_chunk(src, dst, chunksz);
- filesz -= chunksz;
+ size -= chunksz;
dst += chunksz;
}
/* Load final incomplete slice */
- if (filesz)
- memcpy(dst, src, filesz);
-}
-
-void descrambl_file(u32 FAD, u32 file_size, u8* dst) {
- u8* temp_file = new u8[file_size + 2048];
- libGDR_ReadSector(temp_file, FAD, (file_size+2047) / 2048, 2048);
-
- descrambl_buffer(temp_file, dst, file_size);
-
- delete[] temp_file;
+ if (size)
+ memcpy(dst, src, size);
}
diff --git a/core/reios/descrambl.h b/core/reios/descrambl.h
index 77b02c013..333eea14c 100644
--- a/core/reios/descrambl.h
+++ b/core/reios/descrambl.h
@@ -1,4 +1,4 @@
#pragma once
#include "types.h"
-void descrambl_file(u32 FAD, u32 file_size, u8* dst);
+void descrambl_buffer(const u8 *src, u8 *dst, u32 size);
diff --git a/core/reios/reios.cpp b/core/reios/reios.cpp
index 54ddf733b..6aee35e97 100644
--- a/core/reios/reios.cpp
+++ b/core/reios/reios.cpp
@@ -21,12 +21,12 @@
#include "hw/holly/sb_mem.h"
#include "hw/holly/sb.h"
#include "hw/naomi/naomi_cart.h"
-#include "iso9660.h"
#include "font.h"
#include "hw/aica/aica.h"
#include "hw/aica/aica_mem.h"
#include "hw/pvr/pvr_regs.h"
#include "imgread/common.h"
+#include "imgread/isofs.h"
#include "oslib/oslib.h"
#include