Add LZIP support

Add LZIP support
This commit is contained in:
Andy Vandijck 2025-07-12 10:52:04 +02:00
parent de64dfd9e9
commit 604f5412a6
9 changed files with 325 additions and 3 deletions

View File

@ -65,6 +65,10 @@ target_sources(vbam-fex
fex/XZ_Extractor.h
fex/XZ_Reader.cpp
fex/XZ_Reader.h
fex/LZ_Extractor.cpp
fex/LZ_Extractor.h
fex/LZ_Reader.cpp
fex/LZ_Reader.h
fex/Rar_Extractor.cpp
fex/Rar_Extractor.h
fex/Zip7_Extractor.cpp

View File

@ -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_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_rar_type[1], fex_zip_type[1],
fex_bin_type[1];
inline blargg_err_t File_Extractor::open_v()

View File

@ -194,6 +194,8 @@ blargg_err_t LZMA_Inflater::set_mode( mode_t mode, int data_offset )
if (mode == mode_raw_deflate)
err = lzma_alone_decoder( &zbuf, UINT64_MAX);
else if (mode == mode_unlz)
err = lzma_lzip_decoder( &zbuf, UINT64_MAX, LZMA_CONCATENATED);
else
err = lzma_stream_decoder( &zbuf, UINT64_MAX, LZMA_CONCATENATED);
@ -300,7 +302,7 @@ blargg_err_t LZMA_Inflater::read( void* out, int* count_io )
if ( zbuf.avail_in )
{
fprintf(stderr, "Available in: %d, file corrupt\n");
fprintf(stderr, "Available in: %zu, file corrupt\n", zbuf.avail_in);
// inflate() should never leave input if there's still space for output
check( false );
return blargg_err_file_corrupt;

View File

@ -0,0 +1,103 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#if FEX_ENABLE_LZMA
#include "LZ_Extractor.h"
#include <zlib.h>
/* Copyright (C) 2005-2009 Shay Green. 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_lz_file()
{
get_crc_table(); // initialize zlib's CRC-32 tables
return blargg_ok;
}
static File_Extractor* new_lz()
{
return BLARGG_NEW LZ_Extractor;
}
fex_type_t_ const fex_lz_type [1] = {{
".lz",
&new_lz,
"lzip file",
&init_lz_file
}};
LZ_Extractor::LZ_Extractor() :
File_Extractor( fex_lz_type )
{ }
LZ_Extractor::~LZ_Extractor()
{
close();
}
blargg_err_t LZ_Extractor::open_path_v()
{
// skip opening file
return open_v();
}
blargg_err_t LZ_Extractor::stat_v()
{
RETURN_ERR( open_arc_file( true ) );
if ( !gr.opened() || gr.tell() != 0 )
RETURN_ERR( gr.open( &arc() ) );
set_info( gr.remain(), 0, gr.crc32() );
return blargg_ok;
}
blargg_err_t LZ_Extractor::open_v()
{
// Remove .gz suffix
size_t len = strlen( arc_path() );
if ( fex_has_extension( arc_path(), ".lz" ) )
len -= 3;
RETURN_ERR( name.resize( len + 1 ) );
memcpy( name.begin(), arc_path(), name.size() );
name [name.size() - 1] = '\0';
set_name( name.begin() );
return blargg_ok;
}
void LZ_Extractor::close_v()
{
name.clear();
gr.close();
}
blargg_err_t LZ_Extractor::next_v()
{
return blargg_ok;
}
blargg_err_t LZ_Extractor::rewind_v()
{
set_name( name.begin() );
return blargg_ok;
}
blargg_err_t LZ_Extractor::extract_v( void* p, int n )
{
return gr.read( p, n );
}
#endif

View File

@ -0,0 +1,35 @@
// Presents a gzipped file as an "archive" of just that file.
// Also handles non-gzipped files.
// File_Extractor 1.0.0
#ifndef LZ_EXTRACTOR_H
#define LZ_EXTRACTOR_H
#include "File_Extractor.h"
#include "LZ_Reader.h"
class LZ_Extractor : public File_Extractor
{
public:
LZ_Extractor();
virtual ~LZ_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:
LZ_Reader gr;
blargg_vector<char> name;
void set_info_();
};
#endif

View File

@ -0,0 +1,117 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#if FEX_ENABLE_LZMA
#include <stdio.h>
#include "LZ_Reader.h"
#include "blargg_endian.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"
LZ_Reader::LZ_Reader()
{
close();
}
LZ_Reader::~LZ_Reader()
{ }
static blargg_err_t LZ_reader_read( void* file, void* out, int* count )
{
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
}
enum { header_size = 6, trailer_size = 20 };
size_t LZ_Reader::get_uncompressed_size()
{
uint8_t *header_ptr = NULL;
uint8_t *trailer_ptr = NULL;
const uint8_t *data = (const uint8_t *)malloc(in->size());
if (data == NULL) {
fprintf(stderr, "Error: Couldn't allocate data\n");
return 0;
}
in->seek(0);
in->read((void *)data, in->size());
header_ptr = (uint8_t *)data;
unsigned dict_size = 1 << (header_ptr[5] & 0x1F);
dict_size -= (dict_size / 16) * ((header_ptr[5] >> 5 ) & 7);
if(dict_size < (1 << 12) || dict_size > (1 << 29))
{
fprintf(stderr, "Invalid dictionary size in member header.\n");
return 0;
}
trailer_ptr = (uint8_t *)data + (in->size() - trailer_size);
unsigned long long data_size = 0;
for (int i = 11; i >= 4; --i)
data_size = ( data_size << 8 ) + trailer_ptr[i];
in->seek(0);
return (size_t)data_size;
}
blargg_err_t LZ_Reader::calc_size()
{
size_ = (int)get_uncompressed_size();
fprintf(stderr, "LZ uncompressed size: %d\n", size_);
crc32_ = 0;
return blargg_ok;
}
blargg_err_t LZ_Reader::open( File_Reader* new_in )
{
close();
in = new_in;
RETURN_ERR( in->seek( 0 ) );
RETURN_ERR( inflater.begin( LZ_reader_read, new_in ) );
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
RETURN_ERR( calc_size() );
set_remain( size_ );
return blargg_ok;
}
void LZ_Reader::close()
{
in = NULL;
inflater.end();
}
blargg_err_t LZ_Reader::read_v( void* out, int count )
{
assert( in );
int actual = count;
RETURN_ERR( inflater.read( out, &actual ) );
fprintf(stderr, "LZ: Actual read: %d, count: %d\n", actual, count);
if ( actual != count )
return blargg_err_file_corrupt;
return blargg_ok;
}
#endif

View File

@ -0,0 +1,60 @@
// Transparently decompresses gzip files, as well as uncompressed
// File_Extractor 1.0.0
#ifndef LZ_READER_H
#define LZ_READER_H
#include "Data_Reader.h"
#include "LZMA_Inflater.h"
class LZ_Reader : public Data_Reader
{
public:
// Keeps pointer to reader until close(). If
blargg_err_t open(File_Reader *);
// True if file is open
bool opened() const
{
return in != NULL;
}
// Frees memory
void close();
// True if file is compressed
bool deflated() const
{
return inflater.deflated();
}
// CRC-32 of data, of 0 if unavailable
unsigned int crc32() const
{
return crc32_;
}
// Number of bytes read since opening
int tell() const
{
return size_ - remain();
}
public:
LZ_Reader();
virtual ~LZ_Reader();
size_t get_uncompressed_size();
protected:
virtual blargg_err_t read_v(void *, int);
private:
File_Reader *in;
unsigned crc32_;
int size_;
LZMA_Inflater inflater;
blargg_err_t calc_size();
};
#endif

View File

@ -28,7 +28,7 @@
#endif
#if FEX_ENABLE_LZMA
#define FEX_TYPE_LZMA fex_xz_type,
#define FEX_TYPE_LZMA fex_xz_type, fex_lz_type,
#else
#define FEX_TYPE_LZMA
#endif

View File

@ -35,6 +35,7 @@ BLARGG_EXPORT const fex_type_t* fex_type_list( void )
fex_gz_type,
#if FEX_ENABLE_LZMA
fex_xz_type,
fex_lz_type,
#endif
#if FEX_ENABLE_BZ2
fex_bz2_type,