From d0463ddb5e9889e1397a3ea96184cb915956abea Mon Sep 17 00:00:00 2001 From: Andy Vandijck Date: Sun, 13 Jul 2025 09:39:38 +0200 Subject: [PATCH] Initial tar support Initial tar support --- src/core/fex/CMakeLists.txt | 2 + src/core/fex/fex/File_Extractor.h | 2 +- src/core/fex/fex/Tar_Extractor.cpp | 94 ++++++++++++++++++++++++++++++ src/core/fex/fex/Tar_Extractor.h | 76 ++++++++++++++++++++++++ src/core/fex/fex/blargg_config.h | 2 +- src/core/fex/fex/fex.cpp | 2 + src/wx/cmdevents.cpp | 6 +- 7 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 src/core/fex/fex/Tar_Extractor.cpp create mode 100644 src/core/fex/fex/Tar_Extractor.h diff --git a/src/core/fex/CMakeLists.txt b/src/core/fex/CMakeLists.txt index f8e5cc3e..e21ec546 100644 --- a/src/core/fex/CMakeLists.txt +++ b/src/core/fex/CMakeLists.txt @@ -71,6 +71,8 @@ target_sources(vbam-fex fex/LZ_Reader.h fex/Rar_Extractor.cpp fex/Rar_Extractor.h + fex/Tar_Extractor.cpp + fex/Tar_Extractor.h fex/Zip7_Extractor.cpp fex/Zip7_Extractor.h fex/Zip_Extractor.cpp diff --git a/src/core/fex/fex/File_Extractor.h b/src/core/fex/fex/File_Extractor.h index 7e133977..7ee2016a 100644 --- a/src/core/fex/fex/File_Extractor.h +++ b/src/core/fex/fex/File_Extractor.h @@ -213,7 +213,7 @@ struct fex_type_t_ { blargg_err_t (*init)(); // Called by fex_init(). Can be NULL. }; -extern const fex_type_t_ fex_7z_type[1], fex_gz_type[1], fex_bz2_type[1], fex_xz_type[1], fex_lz_type[1], fex_rar_type[1], fex_zip_type[1], +extern const fex_type_t_ fex_7z_type[1], fex_gz_type[1], fex_bz2_type[1], fex_xz_type[1], fex_lz_type[1], fex_tar_type[1], fex_rar_type[1], fex_zip_type[1], fex_bin_type[1]; inline blargg_err_t File_Extractor::open_v() diff --git a/src/core/fex/fex/Tar_Extractor.cpp b/src/core/fex/fex/Tar_Extractor.cpp new file mode 100644 index 00000000..8fd0b98f --- /dev/null +++ b/src/core/fex/fex/Tar_Extractor.cpp @@ -0,0 +1,94 @@ +// File_Extractor 1.0.0. http://www.slack.net/~ant/ + +#include +#include +#include + +#include "Tar_Extractor.h" + +/* Copyright (C) 2025 Andy Vandijck. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module 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 Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +// TODO: could close file once data has been read into memory + +static blargg_err_t init_tar_file() +{ + get_crc_table(); // initialize zlib's CRC-32 tables + return blargg_ok; +} + +static File_Extractor* new_tar() +{ + return BLARGG_NEW Tar_Extractor; +} + +fex_type_t_ const fex_tar_type [1] = {{ + ".tar", + &new_tar, + "tar file", + &init_tar_file +}}; + +Tar_Extractor::Tar_Extractor() : + File_Extractor( fex_tar_type ) +{ } + +Tar_Extractor::~Tar_Extractor() +{ + close(); +} + +blargg_err_t Tar_Extractor::open_path_v() +{ + RETURN_ERR( open_arc_file(true) ); + RETURN_ERR( arc().seek( 0 ) ); + return open_v(); +} + +blargg_err_t Tar_Extractor::stat_v() +{ + set_info( arc().remain(), 0, 0 ); + return blargg_ok; +} + +blargg_err_t Tar_Extractor::open_v() +{ + arc().read(&header, BLOCKSIZE); + set_name( header.name ); + sscanf(header.size, "%o", &tarsize); + return blargg_ok; +} + +void Tar_Extractor::close_v() +{ + name.clear(); +} + +blargg_err_t Tar_Extractor::next_v() +{ + arc().read(&header, BLOCKSIZE); + set_name( header.name ); + sscanf(header.size, "%o", &tarsize); + return blargg_ok; +} + +blargg_err_t Tar_Extractor::rewind_v() +{ + arc().seek(0); + return blargg_ok; +} + +blargg_err_t Tar_Extractor::extract_v( void* p, int n ) +{ + return arc().read( p, n ); +} diff --git a/src/core/fex/fex/Tar_Extractor.h b/src/core/fex/fex/Tar_Extractor.h new file mode 100644 index 00000000..b84424bf --- /dev/null +++ b/src/core/fex/fex/Tar_Extractor.h @@ -0,0 +1,76 @@ +// Presents a gzipped file as an "archive" of just that file. +// Also handles non-gzipped files. + +// File_Extractor 1.0.0 +#ifndef TAR_EXTRACTOR_H +#define TAR_EXTRACTOR_H + +#include "File_Extractor.h" + +typedef struct posix_header +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + char padding[12]; /* 500 */ + /* 512 */ +} posix_header; + +#define BLOCKSIZE 512 + +#define TMAGIC "ustar" /* ustar and a null */ +#define TMAGLEN 6 +#define TVERSION "00" /* 00 and no null */ +#define TVERSLEN 2 + +/* Values used in typeflag field. */ +#define REGTYPE '0' /* regular file */ +#define AREGTYPE '\0' /* regular file */ +#define LNKTYPE '1' /* link */ +#define SYMTYPE '2' /* reserved */ +#define CHRTYPE '3' /* character special */ +#define BLKTYPE '4' /* block special */ +#define DIRTYPE '5' /* directory */ +#define FIFOTYPE '6' /* FIFO special */ +#define CONTTYPE '7' /* reserved */ + +class Tar_Extractor : public File_Extractor +{ + public: + Tar_Extractor(); + virtual ~Tar_Extractor(); + + protected: + virtual blargg_err_t open_path_v(); + virtual blargg_err_t open_v(); + virtual void close_v(); + + virtual blargg_err_t next_v(); + virtual blargg_err_t rewind_v(); + + virtual blargg_err_t stat_v(); + virtual blargg_err_t extract_v(void *, int); + + private: + File_Reader *gr; + posix_header header; + unsigned int tarsize; + blargg_vector name; + + void set_info_(); +}; + +#endif diff --git a/src/core/fex/fex/blargg_config.h b/src/core/fex/fex/blargg_config.h index 2c3f15a9..09948954 100644 --- a/src/core/fex/fex/blargg_config.h +++ b/src/core/fex/fex/blargg_config.h @@ -33,7 +33,7 @@ #define FEX_TYPE_LZMA #endif -#define FEX_TYPE_LIST fex_7z_type, fex_gz_type, fex_zip_type, fex_rar_type, FEX_TYPE_BZ2 FEX_TYPE_LZMA +#define FEX_TYPE_LIST fex_7z_type, fex_gz_type, fex_zip_type, fex_tar_type, fex_rar_type, FEX_TYPE_BZ2 FEX_TYPE_LZMA // Use standard config.h if present #ifdef HAVE_CONFIG_H diff --git a/src/core/fex/fex/fex.cpp b/src/core/fex/fex/fex.cpp index 7db63193..abf8c63c 100644 --- a/src/core/fex/fex/fex.cpp +++ b/src/core/fex/fex/fex.cpp @@ -33,6 +33,7 @@ BLARGG_EXPORT const fex_type_t* fex_type_list( void ) // Modify blargg_config.h to change type list, NOT this file fex_7z_type, fex_gz_type, + fex_tar_type, #if FEX_ENABLE_LZMA fex_xz_type, fex_lz_type, @@ -148,6 +149,7 @@ static int is_archive_extension( const char str [] ) ".rar", ".sit", ".sitx", + ".tar", ".tgz", ".tlz", ".z", diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp index 0a3bd85f..8546b805 100644 --- a/src/wx/cmdevents.cpp +++ b/src/wx/cmdevents.cpp @@ -145,7 +145,7 @@ EVT_HANDLER(wxID_OPEN, "Open ROM...") "*.dmg.bz2;*.gb.bz2;*.gbc.bz2;*.cgb.bz2;*.sgb.bz2;" "*.dmg.gz;*.gb.gz;*.gbc.gz;*.cgb.gz;*.sgb.gz;" "*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z;" - "*.zip;*.7z;*.rar|"); + "*.tar;*.zip;*.7z;*.rar|"); pats.append(wxALL_FILES); wxFileDialog dlg(this, _("Open ROM file"), gba_rom_dir, "", @@ -179,7 +179,7 @@ EVT_HANDLER(OpenGB, "Open GB...") "*.dmg.bz2;*.gb.bz2;*.gbc.bz2;*.cgb.bz2;*.sgb.bz2;" "*.dmg.gz;*.gb.gz;*.gbc.gz;*.cgb.gz;*.sgb.gz;" "*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z;" - "*.zip;*.7z;*.rar|"); + "*.tar;*.zip;*.7z;*.rar|"); pats.append(wxALL_FILES); wxFileDialog dlg(this, _("Open GB ROM file"), gb_rom_dir, "", pats, @@ -211,7 +211,7 @@ EVT_HANDLER(OpenGBC, "Open GBC...") "*.dmg.bz2;*.gb.bz2;*.gbc.bz2;*.cgb.bz2;*.sgb.bz2;" "*.dmg.gz;*.gb.gz;*.gbc.gz;*.cgb.gz;*.sgb.gz;" "*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z;" - "*.zip;*.7z;*.rar|"); + "*.tar;*.zip;*.7z;*.rar|"); pats.append(wxALL_FILES); wxFileDialog dlg(this, _("Open GBC ROM file"), gbc_rom_dir, "", pats,