Skip to content

Commit

Permalink
Archive reader updates
Browse files Browse the repository at this point in the history
* Imagine: Combine ArchiveIO and ArchiveEntry classes to simplify the API
* Imagine: Directly move an IO object containing ArchiveIO in IO constructor
* Imagine: Don't return error in tell() for non-seekable ArchiveIO
* EmuFramework: Return empty string from EmuSystem::willLoadContentFromPath() when path is unchanged
* MD.emu & PCE.emu: Add support for loading CD images inside archives
* C64.emu: Further optimize sysfile_open() to avoid reopening the archive on the next call
  • Loading branch information
Robert Broglia committed Dec 1, 2023
1 parent eaeac4d commit cbe3339
Show file tree
Hide file tree
Showing 26 changed files with 304 additions and 200 deletions.
2 changes: 1 addition & 1 deletion C64.emu/src/main/Main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ static void loadSnapshotTrap(uint16_t, void *data)
static void saveSnapshotTrap(uint16_t, void *data)
{
auto &snapData = *((SnapshotTrapData*)data);
log.info("saving state at:{} size:{}", (void*)snapData.buffData, snapData.buffSize);
//log.info("saving state at:{} size:{}", (void*)snapData.buffData, snapData.buffSize);
if(snapData.plugin.machine_write_snapshot(snapshotVPath(snapData).data(), 1, 1, 0) < 0)
snapData.hasError = true;
else
Expand Down
1 change: 0 additions & 1 deletion C64.emu/src/main/MainSystem.hh
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ public:
void setRuntimeReuSize(int size);
void resetCanvasSourcePixmap(struct video_canvas_s *c);
FS::ArchiveIterator &systemFilesArchiveIterator(ApplicationContext, std::string_view path) const;
void returnSystemFilesArchiveIO(ArchiveIO);
bool setSystemFilesPath(ApplicationContext, CStringView path, FS::file_type);
void execC64Frame();

Expand Down
27 changes: 10 additions & 17 deletions C64.emu/src/main/sysfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static int loadSysFile(Readable auto &file, const char *name, uint8_t *dest, int
return (int)rsize;
}

static ArchiveIO archiveIOForSysFile(C64System &system, IG::CStringView archivePath, std::string_view sysFileName, std::string_view subPath, char **complete_path_return)
static ArchiveIO *archiveIOForSysFile(C64System &system, IG::CStringView archivePath, std::string_view sysFileName, std::string_view subPath, char **complete_path_return)
{
auto sysFilePath = FS::pathString(subPath, sysFileName);
try
Expand All @@ -98,7 +98,7 @@ static ArchiveIO archiveIOForSysFile(C64System &system, IG::CStringView archiveP
*complete_path_return = strdup(name.data());
assert(*complete_path_return);
}
return entry.releaseIO();
return &entry;
}
logErr("not found in archive:%s", archivePath.data());
}
Expand Down Expand Up @@ -137,11 +137,6 @@ FS::ArchiveIterator &C64System::systemFilesArchiveIterator(ApplicationContext ct
return viceSysFilesArchiveIt;
}

void C64System::returnSystemFilesArchiveIO(ArchiveIO entry)
{
viceSysFilesArchiveIt = {entry.releaseArchive()};
}

static bool archiveHasDirectory(CStringView path, std::string_view dirName)
{
for(auto &entry : FS::ArchiveIterator{path})
Expand Down Expand Up @@ -248,11 +243,11 @@ CLINK FILE *sysfile_open(const char *name, const char *subPath, char **complete_
continue;
if(EmuApp::hasArchiveExtension(displayName))
{
auto io = archiveIOForSysFile(system, basePath, name, subPath, complete_path_return);
if(!io)
auto ioPtr = archiveIOForSysFile(system, basePath, name, subPath, complete_path_return);
if(!ioPtr)
continue;
// Uncompress file into memory and wrap in FILE
return MapIO{std::move(io)}.toFileStream(open_mode);
return MapIO{*ioPtr}.toFileStream(open_mode);
}
else
{
Expand Down Expand Up @@ -295,10 +290,9 @@ CLINK int sysfile_locate(const char *name, const char *subPath, char **complete_
continue;
if(EmuApp::hasArchiveExtension(displayName))
{
auto io = archiveIOForSysFile(system, basePath, name, subPath, complete_path_return);
if(!io)
auto ioPtr = archiveIOForSysFile(system, basePath, name, subPath, complete_path_return);
if(!ioPtr)
continue;
system.returnSystemFilesArchiveIO(std::move(io));
return 0;
}
else
Expand Down Expand Up @@ -344,11 +338,10 @@ CLINK int sysfile_load(const char *name, const char *subPath, uint8_t *dest, int
continue;
if(EmuApp::hasArchiveExtension(displayName))
{
auto io = archiveIOForSysFile(system, basePath, name, subPath, nullptr);
if(!io)
auto ioPtr = archiveIOForSysFile(system, basePath, name, subPath, nullptr);
if(!ioPtr)
continue;
auto size = loadSysFile(io, name, dest, minsize, maxsize);
system.returnSystemFilesArchiveIO(std::move(io));
auto size = loadSysFile(*ioPtr, name, dest, minsize, maxsize);
if(size == -1)
{
logErr("failed loading system file:%s from:%s", name, basePath.data());
Expand Down
2 changes: 1 addition & 1 deletion C64.emu/src/main/zfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ CLINK FILE *zfile_fopen(const char *path_, const char *mode_)
if(EmuSystem::defaultFsFilter(entry.name()))
{
EmuEx::log.info("archive file entry:{}", entry.name());
return MapIO{entry.releaseIO()}.toFileStream(mode_);
return MapIO{std::move(entry)}.toFileStream(mode_);
}
}
EmuEx::log.error("no recognized file extensions in archive:{}", path);
Expand Down
2 changes: 2 additions & 0 deletions EmuFramework/include/shared/mednafen/trio/trio.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#define trio_sscanf sscanf
#define trio_fscanf fscanf
#define trio_vasprintf vasprintf
#define trio_vprintf vprintf
#define trio_sprintf sprintf

inline char *trio_vaprintf(const char *format, va_list args)
{
Expand Down
1 change: 1 addition & 0 deletions EmuFramework/make/mednafenCommon.mk
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ MDFN_CDROM_CPPFLAGS = -I$(EMUFRAMEWORK_PATH)/include/shared/lzma \
-I$(EMUFRAMEWORK_PATH)/include/shared \

MDFN_CDROM_SRC := mednafen-emuex/CDImpl.cc \
mednafen-emuex/ArchiveVFS.cc \
mednafen/cdrom/CDAFReader.cpp \
mednafen/cdrom/CDAFReader_FLAC.cpp \
mednafen/cdrom/CDAFReader_MPC.cpp \
Expand Down
50 changes: 33 additions & 17 deletions EmuFramework/src/EmuSystem.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
You should have received a copy of the GNU General Public License
along with EmuFramework. If not, see <http://www.gnu.org/licenses/> */

#define LOGTAG "EmuSystem"
#include <emuframework/EmuSystem.hh>
#include "EmuOptions.hh"
#include <emuframework/EmuApp.hh>
Expand All @@ -30,13 +29,17 @@
#include <imagine/util/ScopeGuard.hh>
#include <imagine/util/string.h>
#include <imagine/util/zlib.hh>
#include <imagine/util/format.hh>
#include <imagine/logger/logger.h>
#include <algorithm>
#include <cstring>
#include "pathUtils.hh"

namespace EmuEx
{

constexpr SystemLogger log{"EmuSystem"};

[[gnu::weak]] bool EmuSystem::inputHasKeyboard = false;
[[gnu::weak]] bool EmuSystem::hasBundledGames = false;
[[gnu::weak]] bool EmuSystem::hasPALVideoSystem = false;
Expand Down Expand Up @@ -129,15 +132,15 @@ void EmuSystem::setupContentFilePaths(CStringView filePath, std::string_view dis
else if(FS::PathStringArray realPath;
!realpath(fileDir.data(), realPath.data()))
{
logErr("error in realpath() while setting content directory");
log.error("error in realpath() while setting content directory");
contentDirectory_ = fileDir;
contentLocation_ = filePath;
}
else
{
contentDirectory_ = realPath.data();
contentLocation_ = FS::pathString(contentDirectory_, contentFileName_);
logMsg("set content directory:%s", contentDirectory_.data());
log.info("set content directory:{}", contentDirectory_);
}
updateContentSaveDirectory();
}
Expand All @@ -160,7 +163,7 @@ void EmuSystem::updateContentSaveDirectory()
else
contentSaveDirectory_ = fallbackSaveDirectory(true);
}
logMsg("updated content save path:%s", contentSaveDirectory_.data());
log.info("updated content save path:%s", contentSaveDirectory_);
}

FS::PathString EmuSystem::fallbackSaveDirectory(bool create)
Expand All @@ -174,7 +177,7 @@ FS::PathString EmuSystem::fallbackSaveDirectory(bool create)
}
catch(...)
{
logErr("error making fallback save dir");
log.error("error making fallback save dir");
return {};
}
}
Expand Down Expand Up @@ -203,7 +206,7 @@ FS::PathString EmuSystem::contentSaveFilePath(std::string_view ext) const

void EmuSystem::setUserSaveDirectory(CStringView path)
{
logMsg("set user save path:%s", path.data());
log.info("set user save path:{}", path);
userSaveDirectory_ = path;
updateContentSaveDirectory();
savePathChanged();
Expand Down Expand Up @@ -270,7 +273,7 @@ void EmuSystem::closeRuntimeSystem(EmuApp &app)
app.audio().flush();
app.autosaveManager().save();
app.saveSessionOptions();
logMsg("closing game:%s", contentName_.data());
log.info("closing game:{}", contentName_);
flushBackupMemory(app);
closeSystem();
app.autosaveManager().cancelTimer();
Expand Down Expand Up @@ -342,7 +345,7 @@ void EmuSystem::configFrameTime(int outputRate, FrameTime outputFrameTime)

void EmuSystem::onFrameTimeChanged()
{
logMsg("frame rate changed:%.2f", frameRate());
log.info("frame rate changed:{}", frameRate());
EmuApp::get(appContext()).configFrameTime();
}

Expand All @@ -364,7 +367,7 @@ int EmuSystem::updateAudioFramesPerVideoFrame()

[[gnu::weak]] FS::PathString EmuSystem::willLoadContentFromPath(std::string_view path, std::string_view displayName)
{
return FS::PathString{path};
return {};
}

void EmuSystem::closeAndSetupNew(CStringView path, std::string_view displayName)
Expand All @@ -375,7 +378,7 @@ void EmuSystem::closeAndSetupNew(CStringView path, std::string_view displayName)
setupContentFilePaths(path, displayName);
else
setupContentUriPaths(path, displayName);
logMsg("set content name:%s location:%s", contentName_.data(), contentLocation_.data());
log.info("set content name:{} location:{}", contentName_, contentLocation_);
app.loadSessionOptions();
}

Expand All @@ -388,17 +391,30 @@ void EmuSystem::createWithMedia(IO io, CStringView path, std::string_view displa
loadContentFromPath(path, displayName, params, onLoadProgress);
}

void EmuSystem::loadContentFromPath(CStringView pathStr, std::string_view displayName, EmuSystemCreateParams params, OnLoadProgressDelegate onLoadProgress)
void EmuSystem::loadContentFromPath(CStringView pathStr, std::string_view displayNameStr, EmuSystemCreateParams params, OnLoadProgressDelegate onLoadProgress)
{
auto path = willLoadContentFromPath(pathStr, displayName);
FS::PathString path;
FS::FileString displayName;
if(auto altPath = willLoadContentFromPath(pathStr, displayName);
altPath.size() && appContext().fileUriExists(altPath))
{
log.info("loading {} instead of {}", altPath, pathStr);
path = altPath;
displayName = appContext().fileUriDisplayName(altPath);
}
else
{
path = pathStr;
displayName = displayNameStr;
}
if(!handlesGenericIO)
{
closeAndSetupNew(path, displayName);
IO nullIO{};
loadContent(nullIO, params, onLoadProgress);
return;
}
logMsg("load from %s:%s", IG::isUri(path) ? "uri" : "path", path.data());
log.info("load from {}:{}", IG::isUri(path) ? "uri" : "path", path);
loadContentFromFile(appContext().openFileUri(path, IOAccessHint::Sequential), path, displayName, params, onLoadProgress);
}

Expand All @@ -415,11 +431,11 @@ void EmuSystem::loadContentFromFile(IO file, CStringView path, std::string_view
continue;
}
auto name = entry.name();
logMsg("archive file entry:%s", name.data());
log.info("archive file entry:{}", name);
if(EmuSystem::defaultFsFilter(name))
{
originalName = name;
io = entry.releaseIO();
io = std::move(entry);
break;
}
}
Expand Down Expand Up @@ -479,7 +495,7 @@ FS::FileString EmuSystem::contentFileName() const

void EmuSystem::setContentDisplayName(std::string_view name)
{
logMsg("set content display name:%s", name.data());
log.info("set content display name:{}", name);
contentDisplayName_ = name;
}

Expand Down Expand Up @@ -572,7 +588,7 @@ FileIO EmuSystem::staticBackupMemoryFile(CStringView uri, size_t size, uint8_t i
size_t fillSize = size - fileSize;
uint8_t fillBuff[fillSize];
memset(fillBuff, initValue, fillSize);
logMsg("padding %zu bytes at offset %zu with value:0x%X", fillSize, fileSize, initValue);
log.info("padding {} bytes at offset {} with value:{:X}", fillSize, fileSize, initValue);
file.write(fillBuff, fillSize, fileSize);
}
}
Expand Down
76 changes: 76 additions & 0 deletions EmuFramework/src/shared/mednafen-emuex/ArchiveVFS.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* This file is part of EmuFramework.
EmuFramework 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.
EmuFramework 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 EmuFramework. If not, see <http://www.gnu.org/licenses/> */

#include "ArchiveVFS.hh"
#include <mednafen/MemoryStream.h>
#include <imagine/fs/FS.hh>
#include <imagine/util/format.hh>
#include <imagine/logger/logger.h>

namespace Mednafen
{

constexpr IG::SystemLogger log{"ArchiveVFS"};

ArchiveVFS::ArchiveVFS(IG::FS::ArchiveIterator it):
VirtualFS('/', "/"),
archIt{std::move(it)} {}

Stream* ArchiveVFS::open(const std::string &path, const uint32 mode, const int do_lock, const bool throw_on_noent, const CanaryType canary)
{
assert(mode == MODE_READ);
assert(do_lock == 0);
archIt.rewind();
auto filename = IG::FS::basename(path);
log.info("looking for file:{}", filename);
for(auto &entry : archIt)
{
if(entry.type() == IG::FS::file_type::directory)
{
continue;
}
auto name = IG::FS::basename(entry.name());
if(name == filename)
{
auto stream = std::make_unique<MemoryStream>(entry.size(), true);
if(entry.read(stream->map(), entry.size()) != entry.size())
{
throw MDFN_Error(0, "Error reading archive file:\n%s", filename.c_str());
}
return stream.release();
}
}
throw MDFN_Error(ENOENT, "Not found");
}

bool ArchiveVFS::mkdir(const std::string &path, const bool throw_on_exist) { return false; }
bool ArchiveVFS::unlink(const std::string &path, const bool throw_on_noent, const CanaryType canary) { return false; }
void ArchiveVFS::rename(const std::string &oldpath, const std::string &newpath, const CanaryType canary) {}

bool ArchiveVFS::is_absolute_path(const std::string &path)
{
if(!path.size())
return false;
if(is_path_separator(path[0]))
return true;
return false;
}

void ArchiveVFS::check_firop_safe(const std::string &path) {}
bool ArchiveVFS::finfo(const std::string& path, FileInfo*, const bool throw_on_noent) { return false; }
void ArchiveVFS::readdirentries(const std::string& path, std::function<bool(const std::string&)> callb) {}
std::string ArchiveVFS::get_human_path(const std::string& path) { return path; }

}

0 comments on commit cbe3339

Please sign in to comment.