diff --git a/quicknes/fex/Binary_Extractor.cpp b/quicknes/fex/Binary_Extractor.cpp deleted file mode 100644 index 7940c0a0b9..0000000000 --- a/quicknes/fex/Binary_Extractor.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Binary_Extractor.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 File_Extractor* new_binary() -{ - return BLARGG_NEW Binary_Extractor; -} - -fex_type_t_ const fex_bin_type [1] = {{ - "", - &new_binary, - "file", - NULL -}}; - -Binary_Extractor::Binary_Extractor() : - File_Extractor( fex_bin_type ) -{ } - -Binary_Extractor::~Binary_Extractor() -{ - close(); -} - -blargg_err_t Binary_Extractor::open_path_v() -{ - set_name( arc_path() ); - return blargg_ok; -} - -blargg_err_t Binary_Extractor::open_v() -{ - set_name( arc_path() ); - set_info( arc().remain(), 0, 0 ); - return blargg_ok; -} - -void Binary_Extractor::close_v() -{ } - -blargg_err_t Binary_Extractor::next_v() -{ - return blargg_ok; -} - -blargg_err_t Binary_Extractor::rewind_v() -{ - return open_path_v(); -} - -blargg_err_t Binary_Extractor::stat_v() -{ - RETURN_ERR( open_arc_file() ); - RETURN_ERR( arc().seek( 0 ) ); - return open_v(); -} - -blargg_err_t Binary_Extractor::extract_v( void* p, int n ) -{ - return arc().read( p, n ); -} diff --git a/quicknes/fex/Binary_Extractor.h b/quicknes/fex/Binary_Extractor.h deleted file mode 100644 index d8cca642f6..0000000000 --- a/quicknes/fex/Binary_Extractor.h +++ /dev/null @@ -1,26 +0,0 @@ -// Presents a single file as an "archive" of just that file. - -// File_Extractor 1.0.0 -#ifndef BINARY_EXTRACTOR_H -#define BINARY_EXTRACTOR_H - -#include "File_Extractor.h" - -class Binary_Extractor : public File_Extractor { -public: - Binary_Extractor(); - virtual ~Binary_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 ); -}; - -#endif diff --git a/quicknes/fex/File_Extractor.cpp b/quicknes/fex/File_Extractor.cpp deleted file mode 100644 index 68b061fa91..0000000000 --- a/quicknes/fex/File_Extractor.cpp +++ /dev/null @@ -1,341 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "File_Extractor.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" - -File_Extractor::fex_t( fex_type_t t ) : - type_( t ) -{ - own_file_ = NULL; - - close_(); -} - -// Open - -blargg_err_t File_Extractor::set_path( const char* path ) -{ - if ( !path ) - path = ""; - - RETURN_ERR( path_.resize( strlen( path ) + 1 ) ); - memcpy( path_.begin(), path, path_.size() ); - return blargg_ok; -} - -blargg_err_t File_Extractor::open( const char path [] ) -{ - close(); - - RETURN_ERR( set_path( path ) ); - - blargg_err_t err = open_path_v(); - if ( err ) - close(); - else - opened_ = true; - - return err; -} - -blargg_err_t File_Extractor::open_path_v() -{ - RETURN_ERR( open_arc_file() ); - - return open_v(); -} - -inline -static void make_unbuffered( Std_File_Reader* r ) -{ - r->make_unbuffered(); -} - -inline -static void make_unbuffered( void* ) -{ } - -blargg_err_t File_Extractor::open_arc_file( bool unbuffered ) -{ - if ( reader_ ) - return blargg_ok; - - FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER; - CHECK_ALLOC( in ); - - blargg_err_t err = in->open( arc_path() ); - if ( err ) - { - delete in; - } - else - { - reader_ = in; - own_file(); - if ( unbuffered ) - make_unbuffered( in ); - } - - return err; -} - -blargg_err_t File_Extractor::open( File_Reader* input, const char* path ) -{ - close(); - - RETURN_ERR( set_path( path ) ); - - RETURN_ERR( input->seek( 0 ) ); - - reader_ = input; - blargg_err_t err = open_v(); - if ( err ) - close(); - else - opened_ = true; - - return err; -} - -// Close - -void File_Extractor::close() -{ - close_v(); - close_(); -} - -void File_Extractor::close_() -{ - delete own_file_; - own_file_ = NULL; - - tell_ = 0; - reader_ = NULL; - opened_ = false; - - path_.clear(); - clear_file(); -} - -File_Extractor::~fex_t() -{ - check( !opened() ); // fails if derived destructor didn't call close() - - delete own_file_; -} - -// Scanning - -void File_Extractor::clear_file() -{ - name_ = NULL; - wname_ = NULL; - done_ = true; - stat_called = false; - data_ptr_ = NULL; - - set_info( 0 ); - own_data_.clear(); - clear_file_v(); -} - -void File_Extractor::set_name( const char new_name [], const blargg_wchar_t* new_wname ) -{ - name_ = new_name; - wname_ = new_wname; - done_ = false; -} - -void File_Extractor::set_info( BOOST::uint64_t new_size, unsigned date, unsigned crc ) -{ - size_ = new_size; - date_ = (date != 0xFFFFFFFF ? date : 0); - crc32_ = crc; - set_remain( new_size ); -} - -blargg_err_t File_Extractor::next_() -{ - tell_++; - clear_file(); - - blargg_err_t err = next_v(); - if ( err ) - clear_file(); - - return err; -} - -blargg_err_t File_Extractor::next() -{ - assert( !done() ); - return next_(); -} - -blargg_err_t File_Extractor::rewind() -{ - assert( opened() ); - - tell_ = 0; - clear_file(); - - blargg_err_t err = rewind_v(); - if ( err ) - clear_file(); - - return err; -} - -blargg_err_t File_Extractor::stat() -{ - assert( !done() ); - - if ( !stat_called ) - { - RETURN_ERR( stat_v() ); - stat_called = true; - } - return blargg_ok; -} - -// Tell/seek - -int const pos_offset = 1; - -fex_pos_t File_Extractor::tell_arc() const -{ - assert( opened() ); - - fex_pos_t pos = tell_arc_v(); - assert( pos >= 0 ); - - return pos + pos_offset; -} - -blargg_err_t File_Extractor::seek_arc( fex_pos_t pos ) -{ - assert( opened() ); - assert( pos != 0 ); - - clear_file(); - - blargg_err_t err = seek_arc_v( pos - pos_offset ); - if ( err ) - clear_file(); - - return err; -} - -fex_pos_t File_Extractor::tell_arc_v() const -{ - return tell_; -} - -blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos ) -{ - // >= because seeking to current file should always reset read pointer etc. - if ( tell_ >= pos ) - RETURN_ERR( rewind() ); - - while ( tell_ < pos ) - { - RETURN_ERR( next_() ); - - if ( done() ) - { - assert( false ); - return blargg_err_caller; - } - } - - assert( tell_ == pos ); - - return blargg_ok; -} - -// Extraction - -blargg_err_t File_Extractor::rewind_file() -{ - RETURN_ERR( stat() ); - - if ( tell() > 0 ) - { - if ( data_ptr_ ) - { - set_remain( size() ); - } - else - { - RETURN_ERR( seek_arc( tell_arc() ) ); - RETURN_ERR( stat() ); - } - } - - return blargg_ok; -} - -blargg_err_t File_Extractor::data( const void** data_out ) -{ - assert( !done() ); - - *data_out = NULL; - if ( !data_ptr_ ) - { - BOOST::uint64_t old_tell = tell(); - - RETURN_ERR( rewind_file() ); - - void const* ptr; - RETURN_ERR( data_v( &ptr ) ); - data_ptr_ = ptr; - - // Now that data is in memory, we can seek by simply setting remain - set_remain( size() - old_tell ); - } - - *data_out = data_ptr_; - return blargg_ok; -} - -blargg_err_t File_Extractor::data_v( void const** out ) -{ - RETURN_ERR( own_data_.resize( size() ) ); - *out = own_data_.begin(); - - blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() ); - if ( err ) - own_data_.clear(); - - return err; -} - -blargg_err_t File_Extractor::extract_v( void* out, int count ) -{ - void const* p; - RETURN_ERR( data( &p ) ); - memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count ); - - return blargg_ok; -} - -blargg_err_t File_Extractor::read_v( void* out, int count ) -{ - if ( data_ptr_ ) - return File_Extractor::extract_v( out, count ); - - return extract_v( out, count ); -} diff --git a/quicknes/fex/File_Extractor.h b/quicknes/fex/File_Extractor.h deleted file mode 100644 index 3855bf69c1..0000000000 --- a/quicknes/fex/File_Extractor.h +++ /dev/null @@ -1,191 +0,0 @@ -// Compressed file archive interface - -// File_Extractor 1.0.0 -#ifndef FILE_EXTRACTOR_H -#define FILE_EXTRACTOR_H - -#include "blargg_common.h" -#include "Data_Reader.h" -#include "fex.h" - -struct fex_t : private Data_Reader { -public: - virtual ~fex_t(); - -// Open/close - - // Opens archive from custom data source. Keeps pointer until close(). - blargg_err_t open( File_Reader* input, const char* path = NULL ); - - // Takes ownership of File_Reader* passed to open(), so that close() - // will delete it. - void own_file() { own_file_ = reader_; } - - // See fex.h - blargg_err_t open( const char path [] ); - fex_type_t type() const { return type_; } - void close(); - -// Scanning - - // See fex.h - bool done() const { return done_; } - blargg_err_t next(); - blargg_err_t rewind(); - fex_pos_t tell_arc() const; - blargg_err_t seek_arc( fex_pos_t ); - -// Info - - // See fex.h - const char* name() const { return name_; } - const blargg_wchar_t* wname() const { return wname_; } - blargg_err_t stat(); - BOOST::uint64_t size() const { assert( stat_called ); return size_; } - unsigned int dos_date() const { return date_; } - unsigned int crc32() const { return crc32_; } - -// Extraction - - // Data_Reader to current file's data, so standard Data_Reader interface can - // be used, rather than having to treat archives specially. stat() must have - // been called. - Data_Reader& reader() { assert( stat_called ); return *this; } - - // See fex.h - blargg_err_t data( const void** data_out ); - BOOST::uint64_t tell() const { return size_ - remain(); } - -// Derived interface -protected: - - // Sets type of object - fex_t( fex_type_t ); - - // Path to archive file, or "" if none supplied - const char* arc_path() const { return path_.begin(); } - - // Opens archive file if it's not already. If unbuffered is true, opens file - // without any buffering. - blargg_err_t open_arc_file( bool unbuffered = false ); - - // Archive file - File_Reader& arc() const { return *reader_; } - - // Sets current file name - void set_name( const char name [], const blargg_wchar_t* wname = NULL ); - - // Sets current file information - void set_info( BOOST::uint64_t size, unsigned date = 0, unsigned crc = 0 ); - -// User overrides - - // Overrides must do indicated task. Non-pure functions have reasonable default - // implementation. Overrides should avoid calling public functions like - // next() and rewind(). - - // Open archive using file_path(). OK to delay actual file opening until later. - // Default just calls open_arc_file(), then open_v(). - virtual blargg_err_t open_path_v(); - - // Open archive using file() for source data. If unsupported, return error. - virtual blargg_err_t open_v() BLARGG_PURE( ; ) - - // Go to next file in archive and call set_name() and optionally set_info() - virtual blargg_err_t next_v() BLARGG_PURE( ; ) - - // Go back to first file in archive - virtual blargg_err_t rewind_v() BLARGG_PURE( ; ) - - // Close archive. Called even if open_path_v() or open_v() return unsuccessfully. - virtual void close_v() BLARGG_PURE( ; ) - - // Clear any fields related to current file - virtual void clear_file_v() { } - - // Call set_info() if not already called by next_v() - virtual blargg_err_t stat_v() { return blargg_ok; } - - // Return value that allows later return to this file. Result must be >= 0. - virtual fex_pos_t tell_arc_v() const; - - // Return to previously saved position - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - // One or both of the following must be overridden - - // Provide pointer to data for current file in archive - virtual blargg_err_t data_v( const void** out ); - - // Extract next n bytes - virtual blargg_err_t extract_v( void* out, int n ); - -// Implementation -public: - BLARGG_DISABLE_NOTHROW - -private: - fex_type_t const type_; - - // Archive file - blargg_vector path_; - File_Reader* reader_; - File_Reader* own_file_; - bool opened_; - - // Position in archive - fex_pos_t tell_; // only used by default implementation of tell/seek - bool done_; - - // Info for current file in archive - const char* name_; - const blargg_wchar_t* wname_; - unsigned date_; - unsigned crc32_; - BOOST::uint64_t size_; - bool stat_called; - - // Current file contents - void const* data_ptr_; // NULL if not read into memory - blargg_vector own_data_; - - bool opened() const { return opened_; } - void clear_file(); - void close_(); - blargg_err_t set_path( const char* path ); - blargg_err_t rewind_file(); - blargg_err_t next_(); - - // Data_Reader overrides - // TODO: override skip_v? - virtual blargg_err_t read_v( void* out, int n ); -}; - -struct fex_type_t_ -{ - const char* extension; - File_Extractor* (*new_fex)(); - const char* name; - 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_rar_type [1], - fex_zip_type [1], - fex_bin_type [1]; - -inline blargg_err_t File_Extractor::open_v() { return blargg_ok; } -inline blargg_err_t File_Extractor::next_v() { return blargg_ok; } -inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; } -inline void File_Extractor::close_v() { } - -// Default to Std_File_Reader for archive access -#ifndef FEX_FILE_READER - #define FEX_FILE_READER Std_File_Reader -#elif defined (FEX_FILE_READER_INCLUDE) - #include FEX_FILE_READER_INCLUDE -#endif - -#endif diff --git a/quicknes/fex/Gzip_Extractor.cpp b/quicknes/fex/Gzip_Extractor.cpp deleted file mode 100644 index 6946de27da..0000000000 --- a/quicknes/fex/Gzip_Extractor.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Gzip_Extractor.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_gzip_file() -{ - get_crc_table(); // initialize zlib's CRC-32 tables - return blargg_ok; -} - -static File_Extractor* new_gzip() -{ - return BLARGG_NEW Gzip_Extractor; -} - -fex_type_t_ const fex_gz_type [1] = {{ - ".gz", - &new_gzip, - "gzipped file", - &init_gzip_file -}}; - -Gzip_Extractor::Gzip_Extractor() : - File_Extractor( fex_gz_type ) -{ } - -Gzip_Extractor::~Gzip_Extractor() -{ - close(); -} - -blargg_err_t Gzip_Extractor::open_path_v() -{ - // skip opening file - return open_v(); -} - -blargg_err_t Gzip_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 Gzip_Extractor::open_v() -{ - // Remove .gz suffix - size_t len = strlen( arc_path() ); - if ( fex_has_extension( arc_path(), ".gz" ) ) - 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 Gzip_Extractor::close_v() -{ - name.clear(); - gr.close(); -} - -blargg_err_t Gzip_Extractor::next_v() -{ - return blargg_ok; -} - -blargg_err_t Gzip_Extractor::rewind_v() -{ - set_name( name.begin() ); - return blargg_ok; -} - -blargg_err_t Gzip_Extractor::extract_v( void* p, int n ) -{ - return gr.read( p, n ); -} diff --git a/quicknes/fex/Gzip_Extractor.h b/quicknes/fex/Gzip_Extractor.h deleted file mode 100644 index 02044d0c78..0000000000 --- a/quicknes/fex/Gzip_Extractor.h +++ /dev/null @@ -1,34 +0,0 @@ -// Presents a gzipped file as an "archive" of just that file. -// Also handles non-gzipped files. - -// File_Extractor 1.0.0 -#ifndef GZIP_EXTRACTOR_H -#define GZIP_EXTRACTOR_H - -#include "File_Extractor.h" -#include "Gzip_Reader.h" - -class Gzip_Extractor : public File_Extractor { -public: - Gzip_Extractor(); - virtual ~Gzip_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: - Gzip_Reader gr; - blargg_vector name; - - void set_info_(); -}; - -#endif diff --git a/quicknes/fex/Gzip_Reader.cpp b/quicknes/fex/Gzip_Reader.cpp deleted file mode 100644 index 464beee7e4..0000000000 --- a/quicknes/fex/Gzip_Reader.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Gzip_Reader.h" - -#include "blargg_endian.h" - -/* Copyright (C) 2006-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" - -Gzip_Reader::Gzip_Reader() -{ - close(); -} - -Gzip_Reader::~Gzip_Reader() -{ } - -static blargg_err_t gzip_reader_read( void* file, void* out, int* count ) -{ - return STATIC_CAST(File_Reader*,file)->read_avail( out, count ); -} - -blargg_err_t Gzip_Reader::calc_size() -{ - size_ = in->size(); - crc32_ = 0; - if ( inflater.deflated() ) - { - byte trailer [8]; - int old_pos = in->tell(); - RETURN_ERR( in->seek( size_ - sizeof trailer ) ); - RETURN_ERR( in->read( trailer, sizeof trailer ) ); - RETURN_ERR( in->seek( old_pos ) ); - crc32_ = get_le32( trailer + 0 ); - - unsigned n = get_le32( trailer + 4 ); - if ( n > INT_MAX ) - return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" ); - - size_ = n; - } - return blargg_ok; -} - -blargg_err_t Gzip_Reader::open( File_Reader* new_in ) -{ - close(); - - in = new_in; - RETURN_ERR( in->seek( 0 ) ); - RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) ); - RETURN_ERR( inflater.set_mode( inflater.mode_auto ) ); - RETURN_ERR( calc_size() ); - set_remain( size_ ); - - return blargg_ok; -} - -void Gzip_Reader::close() -{ - in = NULL; - inflater.end(); -} - -blargg_err_t Gzip_Reader::read_v( void* out, int count ) -{ - assert( in ); - int actual = count; - RETURN_ERR( inflater.read( out, &actual ) ); - - if ( actual != count ) - return blargg_err_file_corrupt; - - return blargg_ok; -} diff --git a/quicknes/fex/Gzip_Reader.h b/quicknes/fex/Gzip_Reader.h deleted file mode 100644 index b514772faa..0000000000 --- a/quicknes/fex/Gzip_Reader.h +++ /dev/null @@ -1,46 +0,0 @@ -// Transparently decompresses gzip files, as well as uncompressed - -// File_Extractor 1.0.0 -#ifndef GZIP_READER_H -#define GZIP_READER_H - -#include "Data_Reader.h" -#include "Zlib_Inflater.h" - -class Gzip_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 - BOOST::uint64_t tell() const { return size_ - remain(); } - -public: - Gzip_Reader(); - virtual ~Gzip_Reader(); - -protected: - virtual blargg_err_t read_v( void*, int ); - -private: - File_Reader* in; - unsigned crc32_; - int size_; - Zlib_Inflater inflater; - - blargg_err_t calc_size(); -}; - -#endif diff --git a/quicknes/fex/Rar_Extractor.cpp b/quicknes/fex/Rar_Extractor.cpp deleted file mode 100644 index 410586464e..0000000000 --- a/quicknes/fex/Rar_Extractor.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "blargg_common.h" - -#if FEX_ENABLE_RAR - -#include "Rar_Extractor.h" - -/* Copyright (C) 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" - -static blargg_err_t init_rar() -{ - unrar_init(); - return blargg_ok; -} - -static File_Extractor* new_rar() -{ - return BLARGG_NEW Rar_Extractor; -} - -fex_type_t_ const fex_rar_type [1] = {{ - ".rar", - &new_rar, - "RAR archive", - &init_rar -}}; - -blargg_err_t Rar_Extractor::convert_err( unrar_err_t err ) -{ - blargg_err_t reader_err = reader.err; - reader.err = blargg_ok; - if ( reader_err ) - check( err == unrar_next_err ); - - switch ( err ) - { - case unrar_ok: return blargg_ok; - case unrar_err_memory: return blargg_err_memory; - case unrar_err_open: return blargg_err_file_read; - case unrar_err_not_arc: return blargg_err_file_type; - case unrar_err_corrupt: return blargg_err_file_corrupt; - case unrar_err_io: return blargg_err_file_io; - case unrar_err_arc_eof: return blargg_err_internal; - case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" ); - case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" ); - case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" ); - case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" ); - case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" ); - case unrar_next_err: break; - default: - check( false ); // unhandled RAR error - } - - if ( reader_err ) - return reader_err; - - check( false ); - return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" ); -} - -static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err ) -{ - if ( !err ) - return unrar_ok; - - h->err = err; - return unrar_next_err; -} - -extern "C" -{ - static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos ) - { - // TODO: 64-bit file support - - Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data); - if ( h->pos != pos ) - { - blargg_err_t err = h->in->seek( pos ); - if ( err ) - return handle_err( h, err ); - - h->pos = pos; - } - - blargg_err_t err = h->in->read_avail( out, count ); - if ( err ) - return handle_err( h, err ); - - h->pos += *count; - - return unrar_ok; - } -} - -Rar_Extractor::Rar_Extractor() : - File_Extractor( fex_rar_type ) -{ - unrar = NULL; -} - -Rar_Extractor::~Rar_Extractor() -{ - close(); -} - -blargg_err_t Rar_Extractor::open_v() -{ - reader.pos = 0; - reader.in = &arc(); - reader.err = blargg_ok; - - RETURN_ERR( arc().seek( 0 ) ); - RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) ); - return skip_unextractables(); -} - -void Rar_Extractor::close_v() -{ - unrar_close( unrar ); - - unrar = NULL; - reader.in = NULL; -} - -blargg_err_t Rar_Extractor::skip_unextractables() -{ - while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) ) - RETURN_ERR( next_raw() ); - - if ( !unrar_done( unrar ) ) - { - unrar_info_t const* info = unrar_info( unrar ); - - set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL ); - set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) ); - } - - return blargg_ok; -} - -blargg_err_t Rar_Extractor::next_raw() -{ - return convert_err( unrar_next( unrar ) ); -} - -blargg_err_t Rar_Extractor::next_v() -{ - RETURN_ERR( next_raw() ); - return skip_unextractables(); -} - -blargg_err_t Rar_Extractor::rewind_v() -{ - RETURN_ERR( convert_err( unrar_rewind( unrar ) ) ); - return skip_unextractables(); -} - -fex_pos_t Rar_Extractor::tell_arc_v() const -{ - return unrar_tell( unrar ); -} - -blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos ) -{ - RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) ); - return skip_unextractables(); -} - -blargg_err_t Rar_Extractor::data_v( void const** out ) -{ - return convert_err( unrar_extract_mem( unrar, out ) ); -} - -blargg_err_t Rar_Extractor::extract_v( void* out, int count ) -{ - // We can read entire file directly into user buffer - if ( count == size() ) - return convert_err( unrar_extract( unrar, out, count ) ); - - // This will call data_v() and copy from that buffer for us - return File_Extractor::extract_v( out, count ); -} - -#endif diff --git a/quicknes/fex/Rar_Extractor.h b/quicknes/fex/Rar_Extractor.h deleted file mode 100644 index a2dbf39e93..0000000000 --- a/quicknes/fex/Rar_Extractor.h +++ /dev/null @@ -1,43 +0,0 @@ -// RAR archive extractor - -// File_Extractor 1.0.0 -#ifndef RAR_EXTRACTOR_H -#define RAR_EXTRACTOR_H - -#include "File_Extractor.h" -#include "unrar/unrar.h" - -class Rar_Extractor : public File_Extractor { -public: - Rar_Extractor(); - virtual ~Rar_Extractor(); - - struct read_callback_t - { - const char* err; - BOOST::uint64_t pos; - File_Reader* in; - }; - -protected: - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - virtual fex_pos_t tell_arc_v() const; - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - virtual blargg_err_t data_v( void const** ); - virtual blargg_err_t extract_v( void*, int ); - -private: - unrar_t* unrar; - read_callback_t reader; - - blargg_err_t convert_err( unrar_err_t ); - blargg_err_t skip_unextractables(); - blargg_err_t next_raw(); -}; - -#endif diff --git a/quicknes/fex/Zip7_Extractor.cpp b/quicknes/fex/Zip7_Extractor.cpp deleted file mode 100644 index 65c935a0fc..0000000000 --- a/quicknes/fex/Zip7_Extractor.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Zip7_Extractor.h" - -extern "C" { -#include "7z_C/7z.h" -#include "7z_C/7zAlloc.h" -#include "7z_C/7zCrc.h" -} - -#include - -/* 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" - -static ISzAlloc zip7_alloc = { SzAlloc, SzFree }; -static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp }; - -struct Zip7_Extractor_Impl : - ISeekInStream -{ - CLookToRead look; - CSzArEx db; - - // SzExtract state - UInt32 block_index; - Byte* buf; - size_t buf_size; - - File_Reader* in; - const char* in_err; -}; - -extern "C" -{ - // 7-zip callbacks pass an ISeekInStream* for data, so we must cast it - // back to ISeekInStream* FIRST, then cast to our Impl structure - - static SRes zip7_read_( void* vstream, void* out, size_t* size ) - { - assert( out && size ); - ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); - Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); - - long lsize = *size; - blargg_err_t err = impl->in->read_avail( out, &lsize ); - if ( err ) - { - *size = 0; - impl->in_err = err; - return SZ_ERROR_READ; - } - - *size = lsize; - return SZ_OK; - } - - static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode ) - { - ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); - Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); - - if ( mode == SZ_SEEK_CUR ) - { - assert( *pos == 0 ); // only used to find the archive start position - *pos = impl->in->tell(); - return SZ_OK; - } - - if ( mode == SZ_SEEK_END ) - { - assert( *pos == 0 ); // only used to find file length - *pos = impl->in->size(); - return SZ_OK; - } - - assert( mode == SZ_SEEK_SET ); - blargg_err_t err = impl->in->seek( *pos ); - if ( err ) - { - // don't set in_err in this case, since it might be benign - if ( err == blargg_err_file_eof ) - return SZ_ERROR_INPUT_EOF; - - impl->in_err = err; - return SZ_ERROR_READ; - } - - return SZ_OK; - } -} - -blargg_err_t Zip7_Extractor::zip7_err( int err ) -{ - // TODO: ignore in_err in some cases? unsure about which error to use - blargg_err_t in_err = impl->in_err; - impl->in_err = NULL; - if ( in_err ) - { - check( err != SZ_OK ); - return in_err; - } - - switch ( err ) - { - case SZ_OK: return blargg_ok; - case SZ_ERROR_MEM: return blargg_err_memory; - case SZ_ERROR_READ: return blargg_err_file_io; - case SZ_ERROR_CRC: - case SZ_ERROR_DATA: - case SZ_ERROR_INPUT_EOF: - case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt; - case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature; - case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type; - } - - return blargg_err_generic; -} - -static blargg_err_t init_7z() -{ - static bool inited; - if ( !inited ) - { - inited = true; - CrcGenerateTable(); - } - return blargg_ok; -} - -static File_Extractor* new_7z() -{ - return BLARGG_NEW Zip7_Extractor; -} - -fex_type_t_ const fex_7z_type [1] = {{ - ".7z", - &new_7z, - "7-zip archive", - &init_7z -}}; - -Zip7_Extractor::Zip7_Extractor() : - File_Extractor( fex_7z_type ) -{ - impl = NULL; -} - -Zip7_Extractor::~Zip7_Extractor() -{ - close(); -} - -blargg_err_t Zip7_Extractor::open_v() -{ - RETURN_ERR( init_7z() ); - - if ( !impl ) - { - impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl ); - CHECK_ALLOC( impl ); - } - - impl->in = &arc(); - impl->block_index = (UInt32) -1; - impl->buf = NULL; - impl->buf_size = 0; - - LookToRead_CreateVTable( &impl->look, false ); - impl->ISeekInStream::Read = zip7_read_; - impl->ISeekInStream::Seek = zip7_seek_; - impl->look.realStream = impl; - LookToRead_Init( &impl->look ); - - SzArEx_Init( &impl->db ); - - impl->in_err = NULL; - RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s, - &zip7_alloc, &zip7_alloc_temp ) ) ); - - return seek_arc_v( 0 ); -} - -void Zip7_Extractor::close_v() -{ - if ( impl ) - { - if ( impl->in ) - { - impl->in = NULL; - SzArEx_Free( &impl->db, &zip7_alloc ); - } - IAlloc_Free( &zip7_alloc, impl->buf ); - free( impl ); - impl = NULL; - } -} - -blargg_err_t Zip7_Extractor::next_v() -{ - while ( ++index < (int) impl->db.db.NumFiles ) - { - CSzFileItem const& item = impl->db.db.Files [index]; - if ( !item.IsDir ) - { - unsigned long date = 0; - if ( item.MTimeDefined ) - { - const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000; - /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */ - struct tm tm; - - UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch; - time /= 1000000; - - time_t _time = time; - -#ifdef _MSC_VER - localtime_s( &tm, &_time ); -#else - localtime_r( &_time, &tm ); -#endif - - date = ( tm.tm_sec >> 1 ) & 0x1F | - (( tm.tm_min & 0x3F ) << 5 ) | - (( tm.tm_hour & 0x1F ) << 11 ) | - (( tm.tm_mday & 0x1F ) << 16 ) | - (( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) | - (( ( tm.tm_year - 80 ) & 0x7F ) << 25 ); - } - - size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 ); - name16.resize( name_length ); - SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() ); - char * temp = blargg_to_utf8( name16.begin() ); - if ( !temp ) temp = ""; - size_t utf8_length = strlen( temp ); - name8.resize( utf8_length + 1 ); - memcpy( name8.begin(), temp, utf8_length + 1 ); - free( temp ); - set_name( name8.begin(), name16.begin() ); - set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) ); - break; - } - } - - return blargg_ok; -} - -blargg_err_t Zip7_Extractor::rewind_v() -{ - return seek_arc_v( 0 ); -} - -fex_pos_t Zip7_Extractor::tell_arc_v() const -{ - return index; -} - -blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos ) -{ - assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles ); - - index = pos - 1; - return next_v(); -} - -blargg_err_t Zip7_Extractor::data_v( void const** out ) -{ - impl->in_err = NULL; - size_t offset = 0; - size_t count = 0; - RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.s, index, - &impl->block_index, &impl->buf, &impl->buf_size, - &offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) ); - assert( count == (size_t) size() ); - - *out = impl->buf + offset; - return blargg_ok; -} diff --git a/quicknes/fex/Zip7_Extractor.h b/quicknes/fex/Zip7_Extractor.h deleted file mode 100644 index b533a12819..0000000000 --- a/quicknes/fex/Zip7_Extractor.h +++ /dev/null @@ -1,36 +0,0 @@ -// 7-zip archive extractor - -// File_Extractor 1.0.0 -#ifndef ZIP7_EXTRACTOR_H -#define ZIP7_EXTRACTOR_H - -#include "File_Extractor.h" - -struct Zip7_Extractor_Impl; - -class Zip7_Extractor : public File_Extractor { -public: - Zip7_Extractor(); - virtual ~Zip7_Extractor(); - -protected: - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - virtual fex_pos_t tell_arc_v() const; - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - virtual blargg_err_t data_v( void const** out ); - -private: - Zip7_Extractor_Impl* impl; - int index; - blargg_vector name8; - blargg_vector name16; - - blargg_err_t zip7_err( int err ); -}; - -#endif diff --git a/quicknes/fex/Zip_Extractor.cpp b/quicknes/fex/Zip_Extractor.cpp deleted file mode 100644 index fd08d102ee..0000000000 --- a/quicknes/fex/Zip_Extractor.cpp +++ /dev/null @@ -1,390 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Zip_Extractor.h" - -#include "blargg_endian.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 */ - -/* To avoid copying filename string from catalog, I terminate it by modifying -catalog data. This potentially requires moving the first byte of the type -of the next entry elsewhere; I move it to the first byte of made_by. Kind -of hacky, but I'd rather not have to allocate memory for a copy of it. */ - -#include "blargg_source.h" - -/* Reads this much from end of file when first opening. Only this much is -searched for the end catalog entry. If whole catalog is within this data, -nothing more needs to be read on open. */ -int const end_read_size = 8 * 1024; - -/* Reads are are made using file offset that's a multiple of this, -increasing performance. */ -int const disk_block_size = 4 * 1024; - -// Read buffer used for extracting file data -int const read_buf_size = 16 * 1024; - -struct header_t -{ - char type [4]; - byte vers [2]; - byte flags [2]; - byte method [2]; - byte date [4]; - byte crc [4]; - byte raw_size [4]; - byte size [4]; - byte filename_len [2]; - byte extra_len [2]; - char filename [2]; // [filename_len] - //char extra [extra_len]; -}; -int const header_size = 30; - -struct entry_t -{ - char type [4]; - byte made_by [2]; - byte vers [2]; - byte flags [2]; - byte method [2]; - byte date [4]; - byte crc [4]; - byte raw_size [4]; - byte size [4]; - byte filename_len [2]; - byte extra_len [2]; - byte comment_len [2]; - byte disk [2]; - byte int_attrib [2]; - byte ext_attrib [4]; - byte file_offset [4]; - char filename [2]; // [filename_len] - //char extra [extra_len]; - //char comment [comment_len]; -}; -int const entry_size = 46; - -struct end_entry_t -{ - char type [4]; - byte disk [2]; - byte first_disk [2]; - byte disk_entry_count [2]; - byte entry_count [2]; - byte dir_size [4]; - byte dir_offset [4]; - byte comment_len [2]; - char comment [2]; // [comment_len] -}; -int const end_entry_size = 22; - -static blargg_err_t init_zip() -{ - get_crc_table(); // initialize zlib's CRC-32 tables - return blargg_ok; -} - -static File_Extractor* new_zip() -{ - return BLARGG_NEW Zip_Extractor; -} - -fex_type_t_ const fex_zip_type [1] = {{ - ".zip", - &new_zip, - "ZIP archive", - &init_zip -}}; - -Zip_Extractor::Zip_Extractor() : - File_Extractor( fex_zip_type ) -{ - Zip_Extractor::clear_file_v(); - - // If these fail, structures had extra padding inserted by compiler - assert( offsetof (header_t,filename) == header_size ); - assert( offsetof (entry_t,filename) == entry_size ); - assert( offsetof (end_entry_t,comment) == end_entry_size ); -} - -Zip_Extractor::~Zip_Extractor() -{ - close(); -} - -blargg_err_t Zip_Extractor::open_path_v() -{ - RETURN_ERR( open_arc_file( true ) ); - return File_Extractor::open_path_v(); -} - -inline -void Zip_Extractor::reorder_entry_header( int offset ) -{ - catalog [offset + 0] = 0; - catalog [offset + 4] = 'P'; -} - -blargg_err_t Zip_Extractor::open_v() -{ - if ( arc().size() < end_entry_size ) - return blargg_err_file_type; - - // Read final end_read_size bytes of file - BOOST::uint64_t file_pos = max( (BOOST::uint64_t) 0, arc().size() - end_read_size ); - file_pos -= file_pos % disk_block_size; - RETURN_ERR( catalog.resize( arc().size() - file_pos ) ); - RETURN_ERR( arc().seek( file_pos ) ); - RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) ); - - // Find end-of-catalog entry - BOOST::uint64_t end_pos = catalog.size() - end_entry_size; - while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) ) - end_pos--; - if ( end_pos < 0 ) - return blargg_err_file_type; - end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos]; - end_pos += file_pos; - - // some idiotic zip compressors add data to end of zip without setting comment len -// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) ); - - // Find file offset of beginning of catalog - catalog_begin = get_le32( end_entry.dir_offset ); - int catalog_size = end_pos - catalog_begin; - if ( catalog_size < 0 ) - return blargg_err_file_corrupt; - catalog_size += end_entry_size; - - // See if catalog is entirely contained in bytes already read - BOOST::uint64_t begin_offset = catalog_begin - file_pos; - if ( begin_offset >= 0 ) - memmove( catalog.begin(), &catalog [begin_offset], catalog_size ); - - RETURN_ERR( catalog.resize( catalog_size ) ); - if ( begin_offset < 0 ) - { - // Catalog begins before bytes read, so it needs to be read - RETURN_ERR( arc().seek( catalog_begin ) ); - RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) ); - } - - // First entry in catalog should be a file or end of archive - if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) ) - return blargg_err_file_type; - - reorder_entry_header( 0 ); - return rewind_v(); -} - -void Zip_Extractor::close_v() -{ - catalog.clear(); -} - -// Scanning - -inline -static bool is_normal_file( entry_t const& e, unsigned len ) -{ - int last_char = (len ? e.filename [len - 1] : '/'); - bool is_dir = (last_char == '/' || last_char == '\\'); - if ( is_dir && get_le32( e.size ) == 0 ) - return false; - check( !is_dir ); - - // Mac OS X puts meta-information in separate files with normal extensions, - // so they must be filtered out or caller will mistake them for normal files. - if ( e.made_by[1] == 3 ) - { - const char* dir = strrchr( e.filename, '/' ); - if ( dir ) - dir++; - else - dir = e.filename; - - if ( *dir == '.' ) - return false; - - if ( !strcmp( dir, "Icon\x0D" ) ) - return false; - } - - return true; -} - -blargg_err_t Zip_Extractor::update_info( bool advance_first ) -{ - while ( 1 ) - { - entry_t& e = (entry_t&) catalog [catalog_pos]; - - if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) ) - { - check( !memcmp( e.type, "\0K\5\6P", 5 ) ); - break; - } - - unsigned len = get_le16( e.filename_len ); - int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) + - get_le16( e.comment_len ); - if ( (unsigned) next_offset > catalog.size() - end_entry_size ) - return blargg_err_file_corrupt; - - if ( catalog [next_offset] == 'P' ) - reorder_entry_header( next_offset ); - - if ( !advance_first ) - { - e.filename [len] = 0; // terminate name - - if ( is_normal_file( e, len ) ) - { - set_name( e.filename ); - set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) ); - break; - } - } - - catalog_pos = next_offset; - advance_first = false; - } - - return blargg_ok; -} - -blargg_err_t Zip_Extractor::next_v() -{ - return update_info( true ); -} - -blargg_err_t Zip_Extractor::rewind_v() -{ - return seek_arc_v( 0 ); -} - -fex_pos_t Zip_Extractor::tell_arc_v() const -{ - return catalog_pos; -} - -blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos ) -{ - assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size ); - - catalog_pos = pos; - return update_info( false ); -} - -// Reading - -void Zip_Extractor::clear_file_v() -{ - buf.end(); -} - -blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count ) -{ - Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data); - - if ( *count > self.raw_remain ) - *count = self.raw_remain; - - self.raw_remain -= *count; - - return self.arc().read( out, *count ); -} - -blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read ) -{ - raw_remain = arc().size() - offset; - RETURN_ERR( arc().seek( offset ) ); - return buf.begin( inflater_read, this, buf_size, initial_read ); -} - -blargg_err_t Zip_Extractor::first_read( int count ) -{ - entry_t const& e = (entry_t&) catalog [catalog_pos]; - - // Determine compression - { - int method = get_le16( e.method ); - if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 ) - return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" ); - file_deflated = (method != 0); - } - - int raw_size = get_le32( e.raw_size ); - - int file_offset = get_le32( e.file_offset ); - int align = file_offset % disk_block_size; - { - // read header - int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data - buf_size -= buf_size % disk_block_size; - int initial_read = buf_size; - if ( !file_deflated || count < size() ) - { - buf_size = read_buf_size; - initial_read = disk_block_size * 2; - } - // TODO: avoid re-reading if buffer already has data we want? - RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) ); - } - header_t const& h = (header_t&) buf.data() [align]; - if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) ) - return blargg_err_file_corrupt; - - // CRCs of header and file data - correct_crc = get_le32( h.crc ); - if ( !correct_crc ) - correct_crc = get_le32( e.crc ); - check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match - crc = ::crc32( 0, NULL, 0 ); - - // Data offset - int data_offset = file_offset + header_size + - get_le16( h.filename_len ) + get_le16( h.extra_len ); - if ( data_offset + raw_size > catalog_begin ) - return blargg_err_file_corrupt; - - // Refill buffer if there's lots of extra data after header - int buf_offset = data_offset - file_offset + align; - if ( buf_offset > buf.filled() ) - { - // TODO: this will almost never occur, making it a good place for bugs - buf_offset = data_offset % disk_block_size; - RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) ); - } - - raw_remain = raw_size - (buf.filled() - buf_offset); - return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset ); -} - -blargg_err_t Zip_Extractor::extract_v( void* out, int count ) -{ - if ( tell() == 0 ) - RETURN_ERR( first_read( count ) ); - - int actual = count; - RETURN_ERR( buf.read( out, &actual ) ); - if ( actual < count ) - return blargg_err_file_corrupt; - - crc = ::crc32( crc, (byte const*) out, count ); - if ( count == reader().remain() && crc != correct_crc ) - return blargg_err_file_corrupt; - - return blargg_ok; -} diff --git a/quicknes/fex/Zip_Extractor.h b/quicknes/fex/Zip_Extractor.h deleted file mode 100644 index 46ced04b7d..0000000000 --- a/quicknes/fex/Zip_Extractor.h +++ /dev/null @@ -1,45 +0,0 @@ -// ZIP archive extractor. Only supports deflation and store (no compression). - -// File_Extractor 1.0.0 -#ifndef ZIP_EXTRACTOR_H -#define ZIP_EXTRACTOR_H - -#include "File_Extractor.h" -#include "Zlib_Inflater.h" - -class Zip_Extractor : public File_Extractor { -public: - Zip_Extractor(); - virtual ~Zip_Extractor(); - -protected: - virtual blargg_err_t open_path_v(); - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual void clear_file_v(); - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - virtual fex_pos_t tell_arc_v() const; - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - virtual blargg_err_t extract_v( void*, int ); - -private: - blargg_vector catalog; - int catalog_begin; // offset of first catalog entry in file (to detect corruption) - int catalog_pos; // position of current entry in catalog - BOOST::uint64_t raw_remain; // bytes remaining to be read from zip file for current file - unsigned crc; // ongoing CRC of extracted bytes - unsigned correct_crc; - bool file_deflated; - Zlib_Inflater buf; - - blargg_err_t fill_buf( int offset, int buf_size, int initial_read ); - blargg_err_t update_info( bool advance_first ); - blargg_err_t first_read( int count ); - void reorder_entry_header( int offset ); - static blargg_err_t inflater_read( void* data, void* out, int* count ); -}; - -#endif diff --git a/quicknes/fex/Zlib_Inflater.cpp b/quicknes/fex/Zlib_Inflater.cpp deleted file mode 100644 index ac77ca5153..0000000000 --- a/quicknes/fex/Zlib_Inflater.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Zlib_Inflater.h" - -/* Copyright (C) 2006-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" - -int const block_size = 4096; - -static const char* get_zlib_err( int code ) -{ - assert( code != Z_OK ); - switch ( code ) - { - case Z_MEM_ERROR: return blargg_err_memory; - case Z_DATA_ERROR: return blargg_err_file_corrupt; - // TODO: handle more error codes - } - - const char* str = zError( code ); - if ( !str ) - str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" ); - - return str; -} - -void Zlib_Inflater::end() -{ - if ( deflated_ ) - { - deflated_ = false; - if ( inflateEnd( &zbuf ) ) - check( false ); - } - buf.clear(); - - static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - memcpy( &zbuf, &empty, sizeof zbuf ); -} - -Zlib_Inflater::Zlib_Inflater() -{ - deflated_ = false; - end(); // initialize things -} - -Zlib_Inflater::~Zlib_Inflater() -{ - end(); -} - -blargg_err_t Zlib_Inflater::fill_buf( int count ) -{ - byte* out = buf.end() - count; - RETURN_ERR( callback( user_data, out, &count ) ); - zbuf.avail_in = count; - zbuf.next_in = out; - return blargg_ok; -} - -blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data, - int new_buf_size, int initial_read ) -{ - callback = new_callback; - user_data = new_user_data; - - end(); - - // TODO: decide whether using different size on alloc failure is a good idea - //RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) ); - if ( new_buf_size && buf.resize( new_buf_size ) ) - { - ACK_FAILURE(); - new_buf_size = 0; - } - - if ( !new_buf_size ) - { - RETURN_ERR( buf.resize( 4 * block_size ) ); - initial_read = 0; - } - - // Fill buffer with some data, less than normal buffer size since caller might - // just be examining beginning of file. - return fill_buf( initial_read ? initial_read : block_size ); -} - -blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset ) -{ - zbuf.next_in += data_offset; - zbuf.avail_in -= data_offset; - - if ( mode == mode_auto ) - { - // examine buffer for gzip header - mode = mode_copy; - unsigned const min_gzip_size = 2 + 8 + 8; - if ( zbuf.avail_in >= min_gzip_size && - zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B ) - mode = mode_ungz; - } - - if ( mode != mode_copy ) - { - int wb = MAX_WBITS + 16; // have zlib handle gzip header - if ( mode == mode_raw_deflate ) - wb = -MAX_WBITS; - - int zerr = inflateInit2( &zbuf, wb ); - if ( zerr ) - { - zbuf.next_in = NULL; - return get_zlib_err( zerr ); - } - - deflated_ = true; - } - return blargg_ok; -} - -/* -// Reads/inflates entire stream. All input must be in buffer, and count must be total -// of all output. -blargg_err_t read_all( void* out, int count ); - - -// zlib automatically applies this optimization (uses inflateFast) -// TODO: remove -blargg_err_t Zlib_Inflater::read_all( void* out, int count ) -{ - if ( deflated_ ) - { - zbuf.next_out = (Bytef*) out; - zbuf.avail_out = count; - - int err = inflate( &zbuf, Z_FINISH ); - - if ( zbuf.avail_out || err != Z_STREAM_END ) - return blargg_err_file_corrupt; - } - else - { - if ( zbuf.avail_in < count ) - return blargg_err_file_corrupt; - - memcpy( out, zbuf.next_in, count ); - - zbuf.next_in += count; - zbuf.avail_in -= count; - } - - return blargg_ok; -} -*/ - -blargg_err_t Zlib_Inflater::read( void* out, int* count_io ) -{ - int remain = *count_io; - if ( remain && zbuf.next_in ) - { - if ( deflated_ ) - { - zbuf.next_out = (Bytef*) out; - zbuf.avail_out = remain; - - while ( 1 ) - { - uInt old_avail_in = zbuf.avail_in; - int err = inflate( &zbuf, Z_NO_FLUSH ); - if ( err == Z_STREAM_END ) - { - remain = zbuf.avail_out; - end(); - break; // no more data to inflate - } - - if ( err && (err != Z_BUF_ERROR || old_avail_in) ) - return get_zlib_err( err ); - - if ( !zbuf.avail_out ) - { - remain = 0; - break; // requested number of bytes inflated - } - - if ( zbuf.avail_in ) - { - // inflate() should never leave input if there's still space for output - check( false ); - return blargg_err_file_corrupt; - } - - RETURN_ERR( fill_buf( buf.size() ) ); - if ( !zbuf.avail_in ) - return blargg_err_file_corrupt; // stream didn't end but there's no more data - } - } - else - { - while ( 1 ) - { - // copy buffered data - if ( zbuf.avail_in ) - { - long count = zbuf.avail_in; - if ( count > remain ) - count = remain; - memcpy( out, zbuf.next_in, count ); - zbuf.total_out += count; - out = (char*) out + count; - remain -= count; - zbuf.next_in += count; - zbuf.avail_in -= count; - } - - if ( !zbuf.avail_in && zbuf.next_in < buf.end() ) - { - end(); - break; - } - - // read large request directly - if ( remain + zbuf.total_out % block_size >= buf.size() ) - { - int count = remain; - RETURN_ERR( callback( user_data, out, &count ) ); - zbuf.total_out += count; - out = (char*) out + count; - remain -= count; - - if ( remain ) - { - end(); - break; - } - } - - if ( !remain ) - break; - - RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) ); - } - } - } - *count_io -= remain; - return blargg_ok; -} diff --git a/quicknes/fex/Zlib_Inflater.h b/quicknes/fex/Zlib_Inflater.h deleted file mode 100644 index 8dedfe8e2a..0000000000 --- a/quicknes/fex/Zlib_Inflater.h +++ /dev/null @@ -1,70 +0,0 @@ -// Simplifies use of zlib for inflating data - -// File_Extractor 1.0.0 -#ifndef ZLIB_INFLATER_H -#define ZLIB_INFLATER_H - -#include "blargg_common.h" -#include "Data_Reader.h" -#include - -class Zlib_Inflater { -public: - - // Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count - // to that number, or returns error if that many can't be read. - typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count ); - - // Begins by setting callback and filling buffer. Default buffer is 16K and - // filled to 4K, or specify buf_size and initial_read for custom buffer size - // and how much to read initially. - blargg_err_t begin( callback_t, void* user_data, - int buf_size = 0, int initial_read = 0 ); - - // Data read into buffer by begin() - const unsigned char* data() const { return zbuf.next_in; } - int filled() const { return zbuf.avail_in; } - - // Begins inflation using specified mode. Using mode_auto selects between - // mode_copy and mode_ungz by examining first two bytes of buffer. Use - // buf_offset to specify where data begins in buffer, in case there is - // header data that should be skipped. - enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto }; - blargg_err_t set_mode( mode_t, int buf_offset = 0 ); - - // True if set_mode() has been called with mode_ungz or mode_raw_deflate - bool deflated() const { return deflated_; } - - // Reads/inflates at most *count_io bytes into *out and sets *count_io to actual - // number of bytes read (less than requested if end of data was reached). - // Buffers source data internally, even in copy mode, so input file can be - // unbuffered without sacrificing performance. - blargg_err_t read( void* out, int* count_io ); - - // Total number of bytes read since begin() - int tell() const { return zbuf.total_out; } - - // Ends inflation and frees memory - void end(); - -private: - // noncopyable - Zlib_Inflater( const Zlib_Inflater& ); - Zlib_Inflater& operator = ( const Zlib_Inflater& ); - -// Implementation -public: - Zlib_Inflater(); - ~Zlib_Inflater(); - -private: - z_stream_s zbuf; - blargg_vector buf; - bool deflated_; - callback_t callback; - void* user_data; - - blargg_err_t fill_buf( int count ); -}; - -#endif diff --git a/quicknes/fex/fex.cpp b/quicknes/fex/fex.cpp deleted file mode 100644 index 8a7dee6a47..0000000000 --- a/quicknes/fex/fex.cpp +++ /dev/null @@ -1,321 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "fex.h" - -#include "File_Extractor.h" -#include "blargg_endian.h" -#include -#include - -/* 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" - - -//// Types - -BLARGG_EXPORT const fex_type_t* fex_type_list( void ) -{ - static fex_type_t const fex_type_list_ [] = - { - #ifdef FEX_TYPE_LIST - FEX_TYPE_LIST - #else - // Modify blargg_config.h to change type list, NOT this file - fex_7z_type, - fex_gz_type, - #if FEX_ENABLE_RAR - fex_rar_type, - #endif - fex_zip_type, - #endif - fex_bin_type, - NULL - }; - - return fex_type_list_; -} - -BLARGG_EXPORT fex_err_t fex_init( void ) -{ - static bool inited; - if ( !inited ) - { - for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t ) - { - if ( (*t)->init ) - RETURN_ERR( (*t)->init() ); - } - inited = true; - } - return blargg_ok; -} - -BLARGG_EXPORT const char* fex_identify_header( void const* header ) -{ - unsigned four = get_be32( header ); - switch ( four ) - { - case 0x52457E5E: - case 0x52617221: return ".rar"; - - case 0x377ABCAF: return ".7z"; - - case 0x504B0304: - case 0x504B0506: return ".zip"; - - case 0x53495421: return ".sit"; - case 0x41724301: return ".arc"; - case 0x4D534346: return ".cab"; - case 0x5A4F4F20: return ".zoo"; - } - - unsigned three = four >> 8; - switch ( three ) - { - case 0x425A68: return ".bz2"; - } - - unsigned two = four >> 16; - switch ( two ) - { - case 0x1F8B: return ".gz"; - case 0x60EA: return ".arj"; - } - - unsigned skip_first_two = four & 0xFFFF; - if ( skip_first_two == 0x2D6C ) - return ".lha"; - - return ""; -} - -static int fex_has_extension_( const char str [], const char suffix [], size_t str_len ) -{ - size_t suffix_len = strlen( suffix ); - if ( str_len >= suffix_len ) - { - str += str_len - suffix_len; - while ( *str && tolower( (unsigned char) *str ) == *suffix ) - { - str++; - suffix++; - } - } - return *suffix == 0; -} - -BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] ) -{ - return fex_has_extension_( str, suffix, strlen( str ) ); -} - -static int is_archive_extension( const char str [] ) -{ - static const char exts [] [6] = { - ".7z", - ".arc", - ".arj", - ".bz2", - ".cab", - ".dmg", - ".gz", - ".lha", - ".lz", - ".lzh", - ".lzma", - ".lzo", - ".lzx", - ".pea", - ".rar", - ".sit", - ".sitx", - ".tgz", - ".tlz", - ".z", - ".zip", - ".zoo", - "" - }; - - size_t str_len = strlen( str ); - const char (*ext) [6] = exts; - for ( ; **ext; ext++ ) - { - if ( fex_has_extension_( str, *ext, str_len ) ) - return 1; - } - return 0; -} - -BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] ) -{ - size_t str_len = strlen( str ); - for ( fex_type_t const* types = fex_type_list(); *types; types++ ) - { - if ( fex_has_extension_( str, (*types)->extension, str_len ) ) - { - // Avoid treating known archive type as binary - if ( *(*types)->extension || !is_archive_extension( str ) ) - return *types; - } - } - return NULL; -} - -BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] ) -{ - *type_out = NULL; - - fex_type_t type = fex_identify_extension( path ); - - // Unsupported extension? - if ( !type ) - return blargg_ok; // reject - - // Unknown/no extension? - if ( !*(type->extension) ) - { - // Examine header - FEX_FILE_READER in; - RETURN_ERR( in.open( path ) ); - if ( in.remain() >= fex_identify_header_size ) - { - char h [fex_identify_header_size]; - RETURN_ERR( in.read( h, sizeof h ) ); - - type = fex_identify_extension( fex_identify_header( h ) ); - } - } - - *type_out = type; - return blargg_ok; -} - -BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type ) -{ - *fe_out = NULL; - - if ( !type ) - return blargg_err_file_type; - - fex_t* fe = type->new_fex(); - CHECK_ALLOC( fe ); - - fex_err_t err = fe->open( path ); - if ( err ) - { - delete fe; - return err; - } - - *fe_out = fe; - return blargg_ok; -} - -BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] ) -{ - *fe_out = NULL; - - fex_type_t type; - RETURN_ERR( fex_identify_file( &type, path ) ); - - return fex_open_type( fe_out, path, type ); -} - - -//// Wide paths - -char* fex_wide_to_path( const blargg_wchar_t* wide ) -{ - return blargg_to_utf8( wide ); -} - -void fex_free_path( char* path ) -{ - free( path ); -} - - -//// Errors - -#define ENTRY( name ) { blargg_err_##name, fex_err_##name } -static blargg_err_to_code_t const fex_codes [] = -{ - ENTRY( generic ), - ENTRY( memory ), - ENTRY( caller ), - ENTRY( internal ), - ENTRY( limitation ), - - ENTRY( file_missing ), - ENTRY( file_read ), - ENTRY( file_io ), - ENTRY( file_eof ), - - ENTRY( file_type ), - ENTRY( file_feature ), - ENTRY( file_corrupt ), - - { 0, -1 } -}; -#undef ENTRY - -static int err_code( fex_err_t err ) -{ - return blargg_err_to_code( err, fex_codes ); -} - -BLARGG_EXPORT int fex_err_code( fex_err_t err ) -{ - int code = err_code( err ); - return (code >= 0 ? code : fex_err_generic); -} - -BLARGG_EXPORT fex_err_t fex_code_to_err( int code ) -{ - return blargg_code_to_err( code, fex_codes ); -} - -BLARGG_EXPORT const char* fex_err_details( fex_err_t err ) -{ - // If we don't have error code assigned, return entire string - return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err )); -} - - -//// Wrappers - -BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count ) -{ - RETURN_ERR( fe->stat() ); - return fe->reader().read( out, count ); -} - -BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; } -BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); } -BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); } -BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); } -BLARGG_EXPORT const blargg_wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); } -BLARGG_EXPORT uint64_t fex_size ( const fex_t* fe ) { return fe->size(); } -BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); } -BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); } -BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); } -BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); } -BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); } -BLARGG_EXPORT uint64_t fex_tell ( const fex_t* fe ) { return fe->tell(); } -BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); } -BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); } -BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; } -BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; } -BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); } -BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); } diff --git a/quicknes/fex/fex.h b/quicknes/fex/fex.h deleted file mode 100644 index 7a85485915..0000000000 --- a/quicknes/fex/fex.h +++ /dev/null @@ -1,206 +0,0 @@ -/** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */ - -/* File_Extractor 1.0.0 */ -#ifndef FEX_H -#define FEX_H - -#include -#include - -#include "blargg_common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** First parameter of most functions is fex_t*, or const fex_t* if nothing is -changed. Once one of these functions returns an error, the archive should not -be used any further, other than to close it. One exception is -fex_error_file_eof; the archive may still be used after this. */ -typedef struct fex_t fex_t; - -/** Pointer to error, or NULL if function was successful. See error functions -below. */ -#ifndef fex_err_t /* (#ifndef allows better testing of library) */ - typedef const char* fex_err_t; -#endif - - -/**** File types ****/ - -/** Archive file type identifier. Can also hold NULL. */ -typedef const struct fex_type_t_* fex_type_t; - -/** Array of supported types, with NULL at end */ -const fex_type_t* fex_type_list( void ); - -/** Name of this archive type, e.g. "ZIP archive", "file" */ -const char* fex_type_name( fex_type_t ); - -/** Usual file extension for type, e.g. ".zip", ".7z". For binary file type, -returns "", since it can open any file. */ -const char* fex_type_extension( fex_type_t ); - - -/**** Wide-character file paths ****/ - -/** Converts wide-character path to form suitable for use with fex functions. */ -char* fex_wide_to_path( const blargg_wchar_t* wide ); - -/** Frees converted path. OK to pass NULL. */ -void fex_free_path( char* ); - - -/**** Identification ****/ - -/** True if str ends in extension. If extension is "", always returns true. -Converts str to lowercase before comparison, so extension should ALREADY be -lowercase (i.e. pass ".zip", NOT ".ZIP"). */ -int fex_has_extension( const char str [], const char extension [] ); - -/** Determines type based on first fex_identify_header_size bytes of file. -Returns usual file extension this should have (e.g. ".zip", ".gz", etc.). -Returns "" if file header is not recognized. */ -const char* fex_identify_header( const void* header ); -enum { fex_identify_header_size = 16 }; - -/** Determines type based on extension of a file path, or just a lone extension -(must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is -for an unsupported type (e.g. ".lzh"). */ -fex_type_t fex_identify_extension( const char path_or_extension [] ); - -/** Determines type based on filename extension and/or file header. Sets *out -to determined type, or NULL if type is not supported. */ -fex_err_t fex_identify_file( fex_type_t* out, const char path [] ); - -/** Type of an already-opened archive */ -fex_type_t fex_type( const fex_t* ); - - -/**** Open/close ****/ - -/** Initializes static tables used by library. Automatically called by -fex_open(). OK to call more than once. */ -fex_err_t fex_init( void ); - -/** Opens archive and points *out at it. If error, sets *out to NULL. */ -fex_err_t fex_open( fex_t** out, const char path [] ); - -/** Opens archive of specified type and sets *out. Returns error if file is not -of that archive type. If error, sets *out to NULL. */ -fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t ); - -/** Closes archive and frees memory. OK to pass NULL. */ -void fex_close( fex_t* ); - - -/**** Scanning ****/ - -/** True if at end of archive. Must be called after fex_open() or fex_rewind(), -as an archive might contain no files. */ -int fex_done( const fex_t* ); - -/** Goes to next file in archive. If there are no more files, fex_done() will -now return true. */ -fex_err_t fex_next( fex_t* ); - -/** Goes back to first file in archive, as if it were just opened with -fex_open() */ -fex_err_t fex_rewind( fex_t* ); - -/** Saved position in archive. Can also store zero. */ -typedef uint64_t fex_pos_t; - -/** Position of current file in archive. Never returns zero. */ -fex_pos_t fex_tell_arc( const fex_t* ); - -/** Returns to file at previously-saved position */ -fex_err_t fex_seek_arc( fex_t*, fex_pos_t ); - - -/**** Info ****/ - -/** Name of current file */ -const char* fex_name( const fex_t* ); - -/** Wide-character name of current file, or NULL if unavailable */ -const blargg_wchar_t* fex_wname( const fex_t* ); - -/** Makes further information available for file */ -fex_err_t fex_stat( fex_t* ); - -/** Size of current file. fex_stat() or fex_data() must have been called. */ -uint64_t fex_size( const fex_t* ); - -/** Modification date of current file (MS-DOS format), or 0 if unavailable. -fex_stat() must have been called. */ -unsigned int fex_dos_date( const fex_t* ); - -/** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't -require calculation; simply gets it from file's header. fex_stat() must have -been called. */ -unsigned int fex_crc32( const fex_t* ); - - -/**** Extraction ****/ - -/** Reads n bytes from current file. Reading past end of file results in -fex_err_file_eof. */ -fex_err_t fex_read( fex_t*, void* out, int n ); - -/** Number of bytes read from current file */ -uint64_t fex_tell( const fex_t* ); - -/** Points *out at current file's data in memory. Pointer is valid until -fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer -must NOT be freed(); library frees it automatically. If error, sets *out to -NULL. */ -fex_err_t fex_data( fex_t*, const void** out ); - - -/**** Errors ****/ - -/** Error string associated with err. Returns "" if err is NULL. Returns err -unchanged if it isn't a fex_err_t returned by library. */ -const char* fex_err_str( fex_err_t err ); - -/** Details of error beyond main cause, or "" if none or err is NULL. Returns -err unchanged if it isn't a fex_err_t returned by library. */ -const char* fex_err_details( fex_err_t err ); - -/** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns -fex_err_generic if err isn't a fex_err_t returned by library. */ -int fex_err_code( fex_err_t err ); - -enum { - fex_ok = 0,/**< Successful call. Guaranteed to be zero. */ - fex_err_generic = 0x01,/**< Error of unspecified type */ - fex_err_memory = 0x02,/**< Out of memory */ - fex_err_caller = 0x03,/**< Caller called function with bad args */ - fex_err_internal = 0x04,/**< Internal problem, bug, etc. */ - fex_err_limitation = 0x05,/**< Exceeded program limit */ - - fex_err_file_missing = 0x20,/**< File not found at specified path */ - fex_err_file_read = 0x21,/**< Couldn't open file for reading */ - fex_err_file_io = 0x23,/**< Read/write error */ - fex_err_file_eof = 0x25,/**< Tried to read past end of file */ - - fex_err_file_type = 0x30,/**< File is of wrong type */ - fex_err_file_feature = 0x32,/**< File requires unsupported feature */ - fex_err_file_corrupt = 0x33 /**< File is corrupt */ -}; - -/** fex_err_t corresponding to numeric code. Note that this might not recover -the original fex_err_t before it was converted to a numeric code; in -particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */ -fex_err_t fex_code_to_err( int code ); - - -/* Deprecated */ -typedef fex_t File_Extractor; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/quicknes/mingw/Makefile b/quicknes/mingw/Makefile index a69360bd08..0868cc53a0 100644 --- a/quicknes/mingw/Makefile +++ b/quicknes/mingw/Makefile @@ -42,10 +42,6 @@ SRCS = \ ../fex/Data_Reader.cpp \ ../fex/blargg_errors.cpp \ ../fex/blargg_common.cpp -# ../nes_emu/Nes_Recorder.cpp -# ../nes_emu/Nes_Film.cpp -# ../nes_emu/Nes_Film_Data.cpp -# ../nes_emu/Nes_Film_Packer.cpp OBJS = $(SRCS:.cpp=.o) diff --git a/quicknes/nes_emu/Mapper_Fme07.cpp b/quicknes/nes_emu/Mapper_Fme07.cpp deleted file mode 100644 index d88f31d378..0000000000 --- a/quicknes/nes_emu/Mapper_Fme07.cpp +++ /dev/null @@ -1,215 +0,0 @@ - -// Sunsoft FME-07 mapper - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/libs/ - -#include "Nes_Mapper.h" - -#include "blargg_endian.h" -#include "Nes_Fme07_Apu.h" - -/* Copyright (C) 2005 Chris Moeller */ -/* Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -struct fme07_state_t -{ - // first 16 bytes in register order - BOOST::uint8_t regs [13]; - BOOST::uint8_t irq_mode; - BOOST::uint16_t irq_count; - - BOOST::uint8_t command; - BOOST::uint8_t irq_pending; - fme07_snapshot_t sound_state; // only used when saving/restoring state - - void swap(); -}; -BOOST_STATIC_ASSERT( sizeof (fme07_state_t) == 18 + sizeof (fme07_snapshot_t) ); - -void fme07_state_t::swap() -{ - set_le16( &irq_count, irq_count ); - for ( int i = 0; i < sizeof sound_state.delays / sizeof sound_state.delays [0]; i++ ) - set_le16( &sound_state.delays [i], sound_state.delays [i] ); -} - -class Mapper_Fme07 : public Nes_Mapper, fme07_state_t { - nes_time_t last_time; - Nes_Fme07_Apu sound; -public: - Mapper_Fme07() - { - fme07_state_t* state = this; - register_state( state, sizeof *state ); - } - - virtual int channel_count() const { return sound.osc_count; } - - virtual void set_channel_buf( int i, Blip_Buffer* b ) { sound.osc_output( i, b ); } - - virtual void set_treble( blip_eq_t const& eq ) { sound.treble_eq( eq ); } - - virtual void reset_state() - { - regs [8] = 0x40; // wram disabled - irq_count = 0xFFFF; - sound.reset(); - } - - virtual void save_state( mapper_state_t& out ) - { - sound.save_snapshot( &sound_state ); - fme07_state_t::swap(); - Nes_Mapper::save_state( out ); - fme07_state_t::swap(); // to do: kind of hacky to swap in place - } - - virtual void read_state( mapper_state_t const& in ) - { - Nes_Mapper::read_state( in ); - fme07_state_t::swap(); - sound.load_snapshot( sound_state ); - } - - void write_register( int index, int data ); - - virtual void apply_mapping() - { - last_time = 0; - for ( int i = 0; i < sizeof regs; i++ ) - write_register( i, regs [i] ); - } - - virtual void run_until( nes_time_t end_time ) - { - int new_count = irq_count - (end_time - last_time); - last_time = end_time; - - if ( new_count <= 0 && (irq_mode & 0x81) == 0x81 ) - irq_pending = true; - - if ( irq_mode & 0x01 ) - irq_count = new_count & 0xFFFF; - } - - virtual nes_time_t next_irq( nes_time_t present ) - { - if ( irq_pending ) - return 0; - - if ( (irq_mode & 0x81) == 0x81 ) - return last_time + irq_count + 1; - - return no_irq; - } - - virtual void end_frame( nes_time_t end_time ) - { - if ( end_time > last_time ) - run_until( end_time ); - - last_time -= end_time; - assert( last_time >= 0 ); - - sound.end_frame( end_time ); - } - - void write_irq( nes_time_t, int index, int data ); - - virtual void write( nes_time_t time, nes_addr_t addr, int data ) - { - switch ( addr & 0xE000 ) - { - case 0x8000: - command = data & 0x0F; - break; - - case 0xA000: - if ( command < 0x0D ) - write_register( command, data ); - else - write_irq( time, command, data ); - break; - - case 0xC000: - sound.write_latch( data ); - break; - - case 0xE000: - sound.write_data( time, data ); - break; - } - } -}; - -void Mapper_Fme07::write_irq( nes_time_t time, int index, int data ) -{ - run_until( time ); - switch ( index ) - { - case 0x0D: - irq_mode = data; - if ( (irq_mode & 0x81) != 0x81 ) - irq_pending = false; - break; - - case 0x0E: - irq_count = (irq_count & 0xFF00) | data; - break; - - case 0x0F: - irq_count = data << 8 | (irq_count & 0xFF); - break; - } - - if ( (irq_mode & 0x81) == 0x81 ) - irq_changed(); -} - -void Mapper_Fme07::write_register( int index, int data ) -{ - regs [index] = data; - int prg_bank = index - 0x09; - if ( (unsigned) prg_bank < 3 ) // most common - { - set_prg_bank( 0x8000 | (prg_bank << bank_8k), bank_8k, data ); - } - else if ( index == 0x08 ) - { - enable_sram( (data & 0xC0) == 0xC0 ); - if ( !(data & 0xC0) ) - set_prg_bank( 0x6000, bank_8k, data & 0x3F ); - } - else if ( index < 0x08 ) - { - set_chr_bank( index * 0x400, bank_1k, data ); - } - else - { - assert( index == 0x0C ); - if ( data & 2 ) - mirror_single( data & 1 ); - else if ( data & 1 ) - mirror_horiz(); - else - mirror_vert(); - } -} - -void register_fme07_mapper(); -void register_fme07_mapper() -{ - register_mapper( 69 ); -} - diff --git a/quicknes/nes_emu/Nes_Apu_State.cpp b/quicknes/nes_emu/Nes_Apu_State.cpp deleted file mode 100644 index 5720090fda..0000000000 --- a/quicknes/nes_emu/Nes_Apu_State.cpp +++ /dev/null @@ -1,125 +0,0 @@ - -// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/ - -#include "Nes_Apu.h" - -#include "Nes_State.h" - -/* Copyright (C) 2003-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -template -struct apu_reflection -{ - #define REFLECT( apu, state ) (mode ? void (apu = state) : void (state = apu)) - - static void reflect_env( apu_state_t::env_t& state, Nes_Envelope& osc ) - { - REFLECT( state [0], osc.env_delay ); - REFLECT( state [1], osc.envelope ); - REFLECT( state [2], osc.reg_written [3] ); - } - - static void reflect_square( apu_state_t::square_t& state, Nes_Square& osc ) - { - reflect_env( state.env, osc ); - REFLECT( state.delay, osc.delay ); - REFLECT( state.length, osc.length_counter ); - REFLECT( state.phase, osc.phase ); - REFLECT( state.swp_delay, osc.sweep_delay ); - REFLECT( state.swp_reset, osc.reg_written [1] ); - } - - static void reflect_triangle( apu_state_t::triangle_t& state, Nes_Triangle& osc ) - { - REFLECT( state.delay, osc.delay ); - REFLECT( state.length, osc.length_counter ); - REFLECT( state.linear_counter, osc.linear_counter ); - REFLECT( state.linear_mode, osc.reg_written [3] ); - } - - static void reflect_noise( apu_state_t::noise_t& state, Nes_Noise& osc ) - { - reflect_env( state.env, osc ); - REFLECT( state.delay, osc.delay ); - REFLECT( state.length, osc.length_counter ); - REFLECT( state.shift_reg, osc.noise ); - } - - static void reflect_dmc( apu_state_t::dmc_t& state, Nes_Dmc& osc ) - { - REFLECT( state.delay, osc.delay ); - REFLECT( state.remain, osc.length_counter ); - REFLECT( state.buf, osc.buf ); - REFLECT( state.bits_remain, osc.bits_remain ); - REFLECT( state.bits, osc.bits ); - REFLECT( state.buf_empty, osc.buf_empty ); - REFLECT( state.silence, osc.silence ); - REFLECT( state.irq_flag, osc.irq_flag ); - if ( mode ) - state.addr = osc.address | 0x8000; - else - osc.address = state.addr & 0x7fff; - } -}; - -void Nes_Apu::get_state( apu_state_t* state ) const -{ - for ( int i = 0; i < osc_count * 4; i++ ) - state->w40xx [i] = oscs [i >> 2]->regs [i & 3]; - state->w40xx [0x11] = dmc.dac; - - state->w4015 = osc_enables; - state->w4017 = frame_mode; - state->delay = frame_delay; - state->step = frame; - state->irq_flag = irq_flag; - - typedef apu_reflection<1> refl; - Nes_Apu& apu = *(Nes_Apu*) this; // const_cast - refl::reflect_square ( state->square1, apu.square1 ); - refl::reflect_square ( state->square2, apu.square2 ); - refl::reflect_triangle( state->triangle, apu.triangle ); - refl::reflect_noise ( state->noise, apu.noise ); - refl::reflect_dmc ( state->dmc, apu.dmc ); -} - -void Nes_Apu::set_state( apu_state_t const& state ) -{ - reset(); - - write_register( 0, 0x4017, state.w4017 ); - write_register( 0, 0x4015, state.w4015 ); - - for ( int i = 0; i < osc_count * 4; i++ ) - { - int n = state.w40xx [i]; - oscs [i >> 2]->regs [i & 3] = n; - write_register( 0, 0x4000 + i, n ); - } - - frame_delay = state.delay; - frame = state.step; - irq_flag = state.irq_flag; - - typedef apu_reflection<0> refl; - apu_state_t& st = (apu_state_t&) state; // const_cast - refl::reflect_square ( st.square1, square1 ); - refl::reflect_square ( st.square2, square2 ); - refl::reflect_triangle( st.triangle, triangle ); - refl::reflect_noise ( st.noise, noise ); - refl::reflect_dmc ( st.dmc, dmc ); - dmc.recalc_irq(); - dmc.last_amp = dmc.dac; -} - diff --git a/quicknes/nes_emu/Nes_Blitter.cpp b/quicknes/nes_emu/Nes_Blitter.cpp deleted file mode 100644 index a5e5b37e0e..0000000000 --- a/quicknes/nes_emu/Nes_Blitter.cpp +++ /dev/null @@ -1,113 +0,0 @@ - -#include "Nes_Blitter.h" - -#include "blargg_endian.h" - -#include "blargg_source.h" - -#ifndef NES_BLITTER_OUT_DEPTH - #define NES_BLITTER_OUT_DEPTH 16 -#endif - -Nes_Blitter::Nes_Blitter() { ntsc = 0; } - -Nes_Blitter::~Nes_Blitter() { free( ntsc ); } - -blargg_err_t Nes_Blitter::init() -{ - assert( !ntsc ); - CHECK_ALLOC( ntsc = (nes_ntsc_emph_t*) malloc( sizeof *ntsc ) ); - static setup_t const s = { }; - setup_ = s; - setup_.ntsc = nes_ntsc_composite; - return setup( setup_ ); -} - -blargg_err_t Nes_Blitter::setup( setup_t const& s ) -{ - setup_ = s; - chunk_count = ((Nes_Emu::image_width - setup_.crop.left - setup_.crop.right) + 5) / 6; - height = Nes_Emu::image_height - setup_.crop.top - setup_.crop.bottom; - nes_ntsc_init_emph( ntsc, &setup_.ntsc ); - return 0; -} - -void Nes_Blitter::blit( Nes_Emu& emu, void* out, long out_pitch ) -{ - short const* palette = emu.frame().palette; - int burst_phase = (setup_.ntsc.merge_fields ? 0 : emu.frame().burst_phase); - long in_pitch = emu.frame().pitch; - unsigned char* in = emu.frame().pixels + setup_.crop.top * in_pitch + setup_.crop.left; - - for ( int n = height; n; --n ) - { - unsigned char* line_in = in; - in += in_pitch; - - BOOST::uint32_t* line_out = (BOOST::uint32_t*) out; - out = (char*) out + out_pitch; - - NES_NTSC_BEGIN_ROW( ntsc, burst_phase, - nes_ntsc_black, nes_ntsc_black, palette [*line_in] ); - - line_in [256] = 252; // loop reads 3 extra pixels, so set them to black - line_in [257] = 252; - line_in [258] = 252; - line_in++; - - burst_phase = (burst_phase + 1) % nes_ntsc_burst_count; - - // assemble two 16-bit pixels into a 32-bit int for better performance - #if BLARGG_BIG_ENDIAN - #define COMBINE_PIXELS right |= left << 16; - #else - #define COMBINE_PIXELS right <<= 16; right |= left; - #endif - - #define OUT_PIXEL( i ) \ - if ( !(i & 1) ) {\ - NES_NTSC_RGB_OUT( (i % 7), left, NES_BLITTER_OUT_DEPTH );\ - if ( i > 1 ) line_out [(i/2)-1] = right;\ - }\ - else {\ - NES_NTSC_RGB_OUT( (i % 7), right, NES_BLITTER_OUT_DEPTH );\ - COMBINE_PIXELS;\ - } - - for ( int n = chunk_count; n; --n ) - { - unsigned long left, right; - - NES_NTSC_COLOR_IN( 0, palette [line_in [0]] ); - OUT_PIXEL( 0 ); - OUT_PIXEL( 1 ); - - NES_NTSC_COLOR_IN( 1, palette [line_in [1]] ); - OUT_PIXEL( 2 ); - OUT_PIXEL( 3 ); - - NES_NTSC_COLOR_IN( 2, palette [line_in [2]] ); - OUT_PIXEL( 4 ); - OUT_PIXEL( 5 ); - OUT_PIXEL( 6 ); - - NES_NTSC_COLOR_IN( 0, palette [line_in [3]] ); - OUT_PIXEL( 7 ); - OUT_PIXEL( 8 ); - - NES_NTSC_COLOR_IN( 1, palette [line_in [4]] ); - OUT_PIXEL( 9 ); - OUT_PIXEL( 10); - - NES_NTSC_COLOR_IN( 2, palette [line_in [5]] ); - line_in += 6; - OUT_PIXEL( 11 ); - OUT_PIXEL( 12 ); - OUT_PIXEL( 13 ); - - line_out [6] = right; - line_out += 7; - } - } -} - diff --git a/quicknes/nes_emu/Nes_Blitter.h b/quicknes/nes_emu/Nes_Blitter.h deleted file mode 100644 index 44e14146aa..0000000000 --- a/quicknes/nes_emu/Nes_Blitter.h +++ /dev/null @@ -1,45 +0,0 @@ - -// NTSC filter for use with Nes_Emu - -#ifndef NES_BLITTER_H -#define NES_BLITTER_H - -#include "nes_emu/Nes_Emu.h" -#include "nes_emu/nes_ntsc.h" - -class Nes_Blitter { -public: - Nes_Blitter(); - ~Nes_Blitter(); - - blargg_err_t init(); - - struct setup_t - { - nes_ntsc_setup_t ntsc; - struct { - // Number of NES source pixels to remove from each border. - // Resulting width will be rounded to multiple of 6 pixels due - // to internal limitations. - int left, top, right, bottom; - } crop; - }; - setup_t const& setup() const { return setup_; } - blargg_err_t setup( setup_t const& ); - - // size of output image generated by blit() - int out_width() const { return chunk_count * 14; } - int out_height() const { return height; } - - // Generate NTSC filtered image to 16-bit 565 RGB output pixels - void blit( Nes_Emu&, void* out, long pitch ); - -private: - setup_t setup_; - nes_ntsc_emph_t* ntsc; - int chunk_count; - int height; -}; - -#endif - diff --git a/quicknes/nes_emu/Nes_Film.cpp b/quicknes/nes_emu/Nes_Film.cpp deleted file mode 100644 index ff258cbf6d..0000000000 --- a/quicknes/nes_emu/Nes_Film.cpp +++ /dev/null @@ -1,531 +0,0 @@ - -// Nes_Emu 0.7.0. http://www.slack.net/~ant/ - -#include "Nes_Film.h" - -#include -#include - -/* Copyright (C) 2004-2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "blargg_source.h" - -nes_tag_t const joypad_data_tag = FOUR_CHAR('JOYP'); - -Nes_Film::Nes_Film() { clear( 60 * 60 ); } - -Nes_Film::~Nes_Film() { } - -void Nes_Film::clear( frame_count_t new_period ) -{ - period_ = new_period; - end_ = begin_ = -invalid_frame_count; - time_offset = 0; - has_joypad_sync_ = true; - has_second_joypad = false; - data.clear( new_period ); -} - -inline int Nes_Film::calc_block_count( frame_count_t new_end ) const -{ - // usually one block extra than absolutely needed - return (new_end - time_offset) / data.period() + 2; -} - -blargg_err_t Nes_Film::resize( frame_count_t new_end ) -{ - blargg_err_t err = data.resize( calc_block_count( new_end ) ); - if ( !err ) - end_ = new_end; - return err; -} - -inline int Nes_Film::calc_block( frame_count_t time, int* index_out ) const -{ - assert( time_offset <= time && time <= end() ); - frame_count_t rel = time - time_offset; - int block = rel / data.period(); - *index_out = rel - block * data.period(); - return block; -} - -Nes_Film::joypad_t Nes_Film::get_joypad( frame_count_t time ) const -{ - int index; - block_t const& b = data.read( calc_block( time, &index ) ); - joypad_t result = b.joypad0 [index]; - if ( b.joypads [1] ) - result |= b.joypads [1] [index] << 8; - - return result; -} - -blargg_err_t Nes_Film::set_joypad( frame_count_t time, joypad_t joypad ) -{ - int index; - int block = calc_block( time, &index ); - block_t* b = data.write( block ); - CHECK_ALLOC( b ); - b->joypad0 [index] = joypad & 0xFF; - - int joypad2 = joypad >> 8 & 0xFF; - if ( joypad2 && !b->joypads [1] ) - CHECK_ALLOC( b = data.alloc_joypad2( block ) ); - if ( b->joypads [1] ) - { - b->joypads [1] [index] = joypad2; - has_second_joypad = true; - } - return 0; -} - -blargg_err_t Nes_Film::record_frame( frame_count_t time, joypad_t joypad, Nes_State_** out ) -{ - if ( out ) - *out = 0; - - if ( !contains( time ) ) - { - require( blank() ); - clear(); - begin_ = end_ = time; - time_offset = time - time % period_; - } - - RETURN_ERR( resize( time + 1 ) ); - - RETURN_ERR( set_joypad( time, joypad ) ); - - // first check detects stale snapshot left after trimming film - if ( read_snapshot( time ).timestamp() > time || time == begin_ || time % period_ == 0 ) - { - Nes_State_* ss = modify_snapshot( time ); - CHECK_ALLOC( ss ); - if ( out ) - *out = ss; - if ( time != begin_ ) - ss->set_timestamp( invalid_frame_count ); // caller might not take snapshot - } - - return 0; -} - -Nes_State_ const* Nes_Film::nearest_snapshot( frame_count_t time ) const -{ - require( contains( time ) ); - - if ( time > end() ) - time = end(); - - for ( int i = snapshot_index( time ); i >= 0; i-- ) - { - Nes_State_ const& ss = snapshots( i ); - if ( ss.timestamp() <= time ) // invalid timestamp will always be greater - return &ss; - } - - return 0; -} - -frame_count_t Nes_Film::constrain( frame_count_t t ) const -{ - if ( t != invalid_frame_count && !blank() ) - { - if ( t < begin_ ) t = begin_; - if ( t > end_ ) t = end_; - } - return t; -} - -inline bool Nes_Film::contains_range( frame_count_t first, frame_count_t last ) const -{ - return begin_ <= first && first <= last && last <= end_; -} - -void Nes_Film::trim( frame_count_t first, frame_count_t last ) -{ - check( begin() <= first && first <= last && last <= end() ); - - // TODO: this routine was broken; check thoroughly - - if ( first > begin_ ) - begin_ = first; - - // preserve first snapshot, which might be before beginning - int first_block = (begin_ - time_offset) / data.period(); - if ( first_block > 0 ) - { - // TODO: pathological thrashing still possible - Nes_State_ const* ss = nearest_snapshot( begin_ ); - if ( ss ) - first_block = (ss->timestamp() - time_offset) / data.period(); - time_offset += first_block * data.period(); - } - - if ( begin_ <= last && last < end_ ) - end_ = last; - data.trim( first_block, calc_block_count( end_ ) ); - // be sure snapshot for beginning was preserved - assert( nearest_snapshot( begin_ ) ); -} - -// Nes_Film_Joypad_Scanner - -// Simplifies scanning joypad data -class Nes_Film_Joypad_Scanner { -public: - // Begin scanning range and set public members for first block - Nes_Film_Joypad_Scanner( frame_count_t first, frame_count_t last, Nes_Film const& ); - - int block; // block index - int offset; // offset in data - int count; // number of bytes - frame_count_t remain; // number of bytes remaining to scan - - // Pointer to temporary buffer of 'block_period' bytes. Cleared - // to zero before first use. - unsigned char* buf(); - - // Go to next block. False if no more blocks. - bool next(); - - ~Nes_Film_Joypad_Scanner(); -private: - Nes_Film& film; - unsigned char* buf_; - void recalc_count(); -}; - -inline unsigned char* Nes_Film_Joypad_Scanner::buf() -{ - if ( !buf_ ) - buf_ = (unsigned char*) calloc( 1, film.data.period() ); - return buf_; -} - -inline void Nes_Film_Joypad_Scanner::recalc_count() -{ - count = film.data.period() - offset; - if ( count > remain ) - count = remain; -} - -Nes_Film_Joypad_Scanner::Nes_Film_Joypad_Scanner( frame_count_t first, frame_count_t last, - Nes_Film const& f ) : film( *(Nes_Film*) &f ) -{ - buf_ = 0; - remain = last - first; - block = film.calc_block( first, &offset ); - recalc_count(); - film.data.joypad_only( true ); -} - -Nes_Film_Joypad_Scanner::~Nes_Film_Joypad_Scanner() -{ - film.data.joypad_only( false ); - free( buf_ ); -} - -bool Nes_Film_Joypad_Scanner::next() -{ - block++; - offset = 0; - remain -= count; - if ( remain <= 0 ) - return false; - recalc_count(); - return true; -} - -// Nes_Film_Writer - -blargg_err_t Nes_Film_Writer::end( Nes_Film const& film, frame_count_t first, - frame_count_t last, frame_count_t period ) -{ - RETURN_ERR( film.write_blocks( *this, first, last, period ) ); - return Nes_File_Writer::end(); -} - -blargg_err_t Nes_Film::write( Auto_File_Writer out, frame_count_t first, - frame_count_t last, frame_count_t period ) const -{ - Nes_Film_Writer writer; - RETURN_ERR( writer.begin( out ) ); - return writer.end( *this, first, last, (period ? period : this->period()) ); -} - -static blargg_err_t write_state( Nes_State_ const& ss, Nes_File_Writer& out ) -{ - RETURN_ERR( out.begin_group( state_file_tag ) ); - RETURN_ERR( ss.write_blocks( out ) ); - return out.end_group(); -} - -blargg_err_t Nes_Film::write_blocks( Nes_File_Writer& out, frame_count_t first, - frame_count_t last, frame_count_t period ) const -{ - require( contains_range( first, last ) ); - require( nearest_snapshot( first ) ); - frame_count_t first_snapshot = nearest_snapshot( first )->timestamp(); - assert( first_snapshot <= first ); - - // write info block - movie_info_t info; - memset( &info, 0, sizeof info ); - info.begin = first; - info.length = last - first; - info.extra = first - first_snapshot; - info.period = period; - info.has_joypad_sync = has_joypad_sync_; - info.joypad_count = 1; - if ( has_second_joypad ) - { - // Scan second joypad data for any blocks containing non-zero data - Nes_Film_Joypad_Scanner joypad( first, last, *this ); - do - { - block_t const& b = data.read( joypad.block ); - if ( b.joypads [1] && - mem_differs( &b.joypads [1] [joypad.offset], 0, joypad.count ) ) - { - info.joypad_count = 2; - break; - } - } - while ( joypad.next() ); - } - RETURN_ERR( write_nes_state( out, info ) ); - - // write joypad data - for ( int i = 0; i < info.joypad_count; i++ ) - { - Nes_Film_Joypad_Scanner joypad( first_snapshot, last, *this ); - RETURN_ERR( out.write_block_header( joypad_data_tag, joypad.remain ) ); - do - { - block_t const& b = data.read( joypad.block ); - byte const* data = b.joypads [i]; - if ( !data ) - CHECK_ALLOC( data = joypad.buf() ); - RETURN_ERR( out.write( &data [joypad.offset], joypad.count ) ); - } - while ( joypad.next() ); - } - - // write first state - int index = snapshot_index( first_snapshot ); - assert( snapshots( index ).timestamp() == first_snapshot ); - RETURN_ERR( write_state( snapshots( index ), out ) ); - - // write snapshots that fall within output periods - // TODO: thorougly verify this tricky algorithm - //dprintf( "last: %6d\n", last ); - int last_index = snapshot_index( last ); - frame_count_t time = first_snapshot + period; - for ( ; ++index <= last_index; ) - { - Nes_State_ const& ss = snapshots( index ); - frame_count_t t = ss.timestamp(); - if ( t != invalid_frame_count ) - { - while ( time + period <= t ) - time += period; - - if ( t >= time - period ) - { - time += period; - //dprintf( "time: %6d\n", t ); - RETURN_ERR( write_state( ss, out ) ); - } - } - } - - return 0; -} - -// Nes_Film_Reader - -blargg_err_t Nes_Film::read( Auto_File_Reader in ) -{ - Nes_Film_Reader reader; - RETURN_ERR( reader.begin( in, this ) ); - while ( !reader.done() ) - RETURN_ERR( reader.next_block() ); - return 0; -} - -Nes_Film_Reader::Nes_Film_Reader() -{ - film = 0; - info_ptr = 0; - joypad_count = 0; - film_initialized = false; - memset( &info_, 0, sizeof info_ ); -} - -Nes_Film_Reader::~Nes_Film_Reader() { } - -blargg_err_t Nes_Film_Reader::begin( Auto_File_Reader dr, Nes_Film* nf ) -{ - film = nf; - RETURN_ERR( Nes_File_Reader::begin( dr ) ); - if ( block_tag() != movie_file_tag ) - return "Not a movie file"; - return 0; -} - -blargg_err_t Nes_Film::begin_read( movie_info_t const& info ) -{ - begin_ = info.begin - info.extra; - end_ = info.begin + info.length; - time_offset = begin_ - begin_ % period_; - has_joypad_sync_ = info.has_joypad_sync; - assert( begin_ <= end_ ); - return resize( end_ ); -} - -blargg_err_t Nes_Film_Reader::customize() -{ - require( info_ptr ); - if ( film_initialized ) - return 0; - film_initialized = true; - film->clear(); - return film->begin_read( info_ ); -} - -blargg_err_t Nes_Film_Reader::next_block() -{ - blargg_err_t err = next_block_(); - if ( err ) - film->clear(); // don't leave film in inconsistent state when reading fails - return err; -} - -blargg_err_t Nes_Film_Reader::next_block_() -{ - for ( ; ; ) - { - RETURN_ERR( Nes_File_Reader::next_block() ); - switch ( depth() == 0 ? block_tag() : 0 ) - { - case movie_info_t::tag: - check( !info_ptr ); - RETURN_ERR( read_nes_state( *this, &info_ ) ); - info_ptr = &info_; - return 0; - - case joypad_data_tag: - RETURN_ERR( customize() ); - RETURN_ERR( film->read_joypad( *this, joypad_count++ ) ); - break; - - case state_file_tag: - RETURN_ERR( customize() ); - RETURN_ERR( film->read_snapshot( *this ) ); - break; - - default: - if ( done() ) - { - // at least first snapshot must have been read - check( film->read_snapshot( film->begin_ ).timestamp() != invalid_frame_count ); - film->begin_ += info_.extra; // bump back to claimed beginning -// todo: remove -#if !defined (NDEBUG) && 0 -FILE* out = fopen( "raw_block", "wb" ); -int block_count = (film->end() - film->time_offset) / film->data.period() + 1; -//for ( int i = 0; i < block_count; i++ ) -int i = (block_count > 1); - fwrite( &film->data.read( i ), offsetof (Nes_Film_Data::block_t,joypad0 [film->data.period()]), 1, out ); -fclose( out ); -#endif - } - return 0; - } - } -} - -blargg_err_t Nes_Film::read_joypad( Nes_File_Reader& in, int index ) -{ - check( index <= 1 ); - if ( index <= 1 ) - { - Nes_Film_Joypad_Scanner joypad( begin_, end_, *this ); - do - { - block_t* b = data.write( joypad.block ); - CHECK_ALLOC( b ); - byte* p = b->joypads [index]; - if ( !p ) - CHECK_ALLOC( p = joypad.buf() ); - p += joypad.offset; - RETURN_ERR( in.read( p, joypad.count ) ); - if ( !b->joypads [index] && mem_differs( p, 0, joypad.count ) ) - { - // non-zero joypad2 data - CHECK_ALLOC( b = data.alloc_joypad2( joypad.block ) ); - memcpy( &b->joypads [index] [joypad.offset], p, joypad.count ); - has_second_joypad = true; - } - } - while ( joypad.next() ); - } - - return 0; -} - -blargg_err_t Nes_Film::read_snapshot( Nes_File_Reader& in ) -{ - RETURN_ERR( in.enter_group() ); - - // read snapshot's timestamp - nes_state_t info; - memset( &info, 0, sizeof info ); - for ( ; ; ) - { - RETURN_ERR( in.next_block() ); - if ( in.block_tag() == info.tag ) - { - RETURN_ERR( read_nes_state( in, &info ) ); - break; - } - check( false ); // shouldn't encounter any unknown blocks - } - frame_count_t time = info.frame_count; - - if ( !contains( time ) ) - { - check( false ); - } - else - { - // read snapshot only if it's earlier than any existing snapshot in same segment - Nes_State_* ss = modify_snapshot( time ); - CHECK_ALLOC( ss ); - - // uninitialized snapshot's time is large positive value so always compares greater - if ( time < ss->timestamp() ) - { - // read new snapshot - ss->clear(); - ss->set_nes_state( info ); - do - { - RETURN_ERR( ss->read_blocks( in ) ); - } - while ( in.block_type() != in.group_end ); - } - } - return in.exit_group(); -} - diff --git a/quicknes/nes_emu/Nes_Film.h b/quicknes/nes_emu/Nes_Film.h deleted file mode 100644 index 9a4128bca0..0000000000 --- a/quicknes/nes_emu/Nes_Film.h +++ /dev/null @@ -1,214 +0,0 @@ - -// Film to record NES movies on using Nes_Recorder - -// Nes_Emu 0.7.0 - -#ifndef NES_FILM_H -#define NES_FILM_H - -#include "blargg_common.h" -#include "Nes_Film_Data.h" - -// See below for custom reader and writer classes that allow user data in movie files -class Nes_Film_Writer; -class Nes_Film_Reader; - -class Nes_Film { -public: - Nes_Film(); - ~Nes_Film(); - - // Clear film to blankness - void clear() { clear( period() ); } - - // Time of first recorded snapshot - frame_count_t begin() const { return begin_; } - - // Time of *end* of last recorded frame - frame_count_t end() const { return end_; } - - // Number of frames in recording - frame_count_t length() const { return end() - begin(); } - - // Trim to subset of recording. OK if new_begin == new_end, which does - // not make film blank, merely of zero length. - void trim( frame_count_t new_begin, frame_count_t new_end ); - - // Write entire recording to file - blargg_err_t write( Auto_File_Writer ) const; - - // Read entire recording from file - blargg_err_t read( Auto_File_Reader ); - -// Additional features - - // Write trimmed recording to file, with snapshots approximately every 'period' frames - blargg_err_t write( Auto_File_Writer, frame_count_t begin, frame_count_t end, - frame_count_t period = 0 ) const; - - // Clear film and set how often snapshots are taken. One snapshot is kept for - // every 'period' frames of recording. A lower period makes seeking faster but - // uses more memory. - void clear( frame_count_t new_period ); - - // Average number of frames between snapshots - frame_count_t period() const { return period_; } - - // True if film has just been cleared - bool blank() const { return end_ < 0; } - - // True if timestamp is within recording. Always false if film is blank. - bool contains( frame_count_t t ) const { return begin() <= t && t <= end(); } - - // True if recording contains frame beginning at timestamp - bool contains_frame( frame_count_t t ) const { return begin() <= t && t < end(); } - - // Constrain timestamp to recorded range, or return unchanged if film is blank - frame_count_t constrain( frame_count_t ) const; - -// Raw access for use by Nes_Recorder - - // True if joypad entries are 0xFF on frames that the joypad isn't read - bool has_joypad_sync() const { return has_joypad_sync_; } - - // Snapshot that might have current timestamp - Nes_State_ const& read_snapshot( frame_count_t ) const; - - // Snapshot that current timestamp maps to. NULL if out of memory. - Nes_State_* modify_snapshot( frame_count_t ); - - // Pointer to nearest snapshot at or before timestamp, or NULL if none - Nes_State_ const* nearest_snapshot( frame_count_t ) const; - - typedef unsigned long joypad_t; - - // Get joypad data for frame beginning at timestamp - joypad_t get_joypad( frame_count_t ) const; - - // Change joypad data for frame beginning at timestamp. Frame must already have - // been recorded normally. - blargg_err_t set_joypad( frame_count_t, joypad_t ); - - // Record new frame beginning at timestamp using joypad data. Returns - // pointer where snapshot should be saved to, or NULL if a snapshot isn't - // needed for this timestamp. Removes anything recorded after frame. - blargg_err_t record_frame( frame_count_t, joypad_t joypad, Nes_State_** out = 0 ); - -private: - // noncopyable - Nes_Film( Nes_Film const& ); - Nes_Film& operator = ( Nes_Film const& ); - - typedef Nes_Film_Data::block_t block_t; - Nes_Film_Data data; - frame_count_t begin_; - frame_count_t end_; - frame_count_t period_; - frame_count_t time_offset; - bool has_joypad_sync_; - bool has_second_joypad; - - int calc_block( frame_count_t time, int* index_out ) const; - int snapshot_index( frame_count_t ) const; - Nes_State_ const& snapshots( int ) const; - int calc_block_count( frame_count_t new_end ) const; - blargg_err_t resize( frame_count_t new_end ); - bool contains_range( frame_count_t first, frame_count_t last ) const; - - blargg_err_t write_blocks( Nes_File_Writer&, frame_count_t first, - frame_count_t last, frame_count_t period ) const; - blargg_err_t begin_read( movie_info_t const& ); - blargg_err_t read_joypad( Nes_File_Reader&, int index ); - blargg_err_t read_snapshot( Nes_File_Reader& ); - - friend class Nes_Film_Reader; - friend class Nes_Film_Writer; - friend class Nes_Film_Joypad_Scanner; -}; - -// Allows user data blocks to be written with film -class Nes_Film_Writer : public Nes_File_Writer { -public: - // Begin writing movie file - blargg_err_t begin( Auto_File_Writer ); - - // End writing movie file. Optionally specify custom period and subset of - // recording to write. - blargg_err_t end( Nes_Film const& ); - blargg_err_t end( Nes_Film const&, frame_count_t first, frame_count_t last, - frame_count_t period ); -}; - -// Allows film information to be checked before loading film, and for handling -// of user data blocks. -class Nes_Film_Reader : public Nes_File_Reader { -public: - Nes_Film_Reader(); - ~Nes_Film_Reader(); - - // Begin reading from movie file. Does not modify film until later (see below). - blargg_err_t begin( Auto_File_Reader, Nes_Film* out ); - - // Go to next custom block in file - blargg_err_t next_block(); - - // Information about film (see nes_state.h for fields). Returns zero - // until information is encountered in file. Once return value becomes - // non-zero, next call to next_block() will read movie into film. - // Until that time, film is not modified or examined at all. - movie_info_t const* info() const { return info_ptr; } - - // to do: allow reading subset of recording from file (for example, last 5 minutes) - -private: - Nes_Film* film; - bool film_initialized; - movie_info_t info_; - movie_info_t* info_ptr; - int joypad_count; - - blargg_err_t customize(); - blargg_err_t next_block_(); -}; - -inline blargg_err_t Nes_Film_Writer::begin( Auto_File_Writer dw ) -{ - return Nes_File_Writer::begin( dw, movie_file_tag ); -} - -inline blargg_err_t Nes_Film::write( Auto_File_Writer out ) const -{ - return write( out, begin(), end(), period() ); -} - -inline blargg_err_t Nes_Film_Writer::end( Nes_Film const& film ) -{ - return end( film, film.begin(), film.end(), film.period() ); -} - -inline int Nes_Film::snapshot_index( frame_count_t time ) const -{ - return (time - time_offset) / period_; -} - -inline Nes_State_ const& Nes_Film::snapshots( int i ) const -{ - return data.read( (unsigned) i / data.block_size ).states [(unsigned) i % data.block_size]; -} - -inline Nes_State_ const& Nes_Film::read_snapshot( frame_count_t time ) const -{ - return snapshots( snapshot_index( time ) ); -} - -inline Nes_State_* Nes_Film::modify_snapshot( frame_count_t time ) -{ - int i = snapshot_index( time ); - block_t* b = data.write( (unsigned) i / data.block_size ); - if ( b ) - return &b->states [(unsigned) i % data.block_size]; - return 0; -} - -#endif - diff --git a/quicknes/nes_emu/Nes_Film_Data.cpp b/quicknes/nes_emu/Nes_Film_Data.cpp deleted file mode 100644 index 253356c9f9..0000000000 --- a/quicknes/nes_emu/Nes_Film_Data.cpp +++ /dev/null @@ -1,273 +0,0 @@ - -// Nes_Emu 0.7.0. http://www.slack.net/~ant/ - -#include "Nes_Film_Data.h" - -#include -#include - -/* Copyright (C) 2004-2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "blargg_source.h" - -Nes_Film_Data::Nes_Film_Data() -{ - blocks = 0; - active = 0; - block_count = 0; - period_ = 0; - packer = 0; - - BOOST_STATIC_ASSERT( sizeof active->cpu [0] % 4 == 0 ); - BOOST_STATIC_ASSERT( sizeof active->joypad [0] % 4 == 0 ); - BOOST_STATIC_ASSERT( sizeof active->apu [0] % 4 == 0 ); - BOOST_STATIC_ASSERT( sizeof active->ppu [0] % 4 == 0 ); - BOOST_STATIC_ASSERT( sizeof active->mapper [0] % 4 == 0 ); - BOOST_STATIC_ASSERT( sizeof active->states [0] % 4 == 0 ); - //BOOST_STATIC_ASSERT( offsetof (block_t,joypad0) % 4 == 0 ); // XXX -} - -#ifndef NDEBUG - -static void write_file( void const* in, long size, const char* path ) -{ - FILE* out = fopen( path, "wb" ); - if ( out ) - { - fwrite( in, size, 1, out ); - fclose( out ); - } -} - -void Nes_Film_Data::debug_packer() const -{ - comp_block_t* b = blocks [active_index]; - static byte* temp = new byte [active_size() * 2]; - for ( int i = 0; i < active_size() * 2; i++ ) - temp [i] = i; - long vs = packer->unpack( b->data, b->size, temp ); - if ( vs != active_size() - b->offset ) - { - dprintf( "Unpacked size differs\n" ); - write_file( (byte*) active + b->offset, vs, "original" ); - write_file( temp, vs, "error" ); - assert( false ); - } - if ( memcmp( (byte*) active + b->offset, temp, vs ) ) - { - dprintf( "Unpacked content differs\n" ); - write_file( (byte*) active + b->offset, vs, "original" ); - write_file( temp, vs, "error" ); - assert( false ); - } - - if ( 0 ) - { - long total = 0; - for ( int i = 0; i < block_count; i++ ) - if ( blocks [i] ) - total += blocks [i]->size; - //dprintf( "Compression: %ld%%\n", total * 100 / (block_count * (active_size() - period_)) ); - dprintf( "Memory: %ld+%ldK\n", total / 1024, active_size() * 2 / 1024 + 16 ); - //dprintf( "Memory: %ldK\n", (total + active_size() * 2) / 1024 + 16 ); - } -} -#endif - -void Nes_Film_Data::flush_active() const -{ - if ( active_dirty ) - { - assert( (unsigned) active_index < (unsigned) block_count ); - - active_dirty = false; - comp_block_t* b = blocks [active_index]; - assert( b && !b->size ); // should have been reallocated in write() - check( b->offset == joypad_only_ ); - b->size = packer->pack( (byte*) active + b->offset, active_size() - b->offset, b->data ); - assert( b->size <= packer->worst_case( active_size() - b->offset ) ); - - // shrink allocation - void* mem = realloc( b, offsetof (comp_block_t, data) + b->size * sizeof(b->data[0]) ); - if ( mem ) - blocks [active_index] = (comp_block_t*) mem; - else - check( false ); // shrink shouldn't fail, but fine if it does - - #ifndef NDEBUG - debug_packer(); - #endif - } - active_index = -1; -} - -void Nes_Film_Data::init_states() const -{ - memset( active->states, 0, sizeof active->states ); - block_t* b = active; - b->garbage0 = 1; - b->garbage1 = 2; - b->garbage2 = 3; - for ( int j = 0; j < block_size; j++ ) - { - Nes_State_& s = b->states [j]; - s.cpu = &b->cpu [j]; - s.joypad = &b->joypad [j]; - s.apu = &b->apu [j]; - s.ppu = &b->ppu [j]; - s.mapper = &b->mapper [j]; - s.ram = b->ram [j]; - s.sram = b->sram [j]; - s.spr_ram = b->spr_ram [j]; - s.nametable = b->nametable [j]; - s.chr = b->chr [j]; - s.set_timestamp( invalid_frame_count ); - } -} - -void Nes_Film_Data::access( index_t i ) const -{ - assert( (unsigned) i < (unsigned) block_count ); - if ( active_dirty ) - flush_active(); - active_index = i; - comp_block_t* b = blocks [i]; - if ( b ) - { - assert( b->size ); - long size = packer->unpack( b->data, b->size, (byte*) active + b->offset ); - assert( b->offset + size == active_size() ); - if ( b->offset ) - init_states(); - } - else - { - active->joypads [0] = &active->joypad0 [0]; - active->joypads [1] = &active->joypad0 [period_]; - init_states(); - memset( active->joypad0, 0, period_ * 2 ); - } -} - -Nes_Film_Data::block_t* Nes_Film_Data::write( int i ) -{ - require( (unsigned) i < (unsigned) block_count ); - if ( i != active_index ) - access( i ); - if ( !active_dirty ) - { - // preallocate now to avoid losing write when flushed later - long size = packer->worst_case( active_size() - joypad_only_ ); - comp_block_t* new_mem = (comp_block_t*) realloc( blocks [i], size ); - if ( !new_mem ) - return 0; - new_mem->size = 0; - new_mem->offset = joypad_only_; - blocks [i] = new_mem; - active_dirty = true; - } - return active; -} - -void Nes_Film_Data::joypad_only( bool b ) -{ - flush_active(); - joypad_only_ = b * offsetof (block_t,joypad0); -} - -blargg_err_t Nes_Film_Data::resize( int new_count ) -{ - if ( new_count < block_count ) - { - assert( active ); - - if ( active_index >= new_count ) - flush_active(); - - for ( int i = new_count; i < block_count; i++ ) - free( blocks [i] ); - - block_count = new_count; - void* new_blocks = realloc( blocks, new_count * sizeof *blocks ); - if ( new_blocks || !new_count ) - blocks = (comp_block_t**) new_blocks; - else - check( false ); // shrink shouldn't fail, but fine if it does - } - else if ( new_count > block_count ) - { - if ( !packer ) - CHECK_ALLOC( packer = BLARGG_NEW Nes_Film_Packer ); - - if ( !active ) - { - assert( period_ ); - active = (block_t*) calloc( active_size(), 1 ); - CHECK_ALLOC( active ); - //init_active(); // TODO: unnecessary since it's called on first access anyway? - packer->prepare( active, active_size() ); - } - - void* new_blocks = realloc( blocks, new_count * sizeof *blocks ); - CHECK_ALLOC( new_blocks ); - blocks = (comp_block_t**) new_blocks; - - for ( int i = block_count; i < new_count; i++ ) - blocks [i] = 0; - - block_count = new_count; - } - return 0; -} - -void Nes_Film_Data::clear( frame_count_t period ) -{ - active_index = -1; - active_dirty = false; - if ( resize( 0 ) ) - check( false ); // shrink should never fail - joypad_only_ = false; - period_ = period * block_size; - free( active ); - active = 0; -} - -void Nes_Film_Data::trim( int begin, int new_count ) -{ - require( 0 <= begin && begin + new_count <= block_count ); - require( (unsigned) new_count <= (unsigned) block_count ); - if ( (unsigned) new_count < (unsigned) block_count ) - { - if ( begin || active_index >= new_count ) - flush_active(); - - if ( begin ) - { - for ( int i = 0; i < begin; i++ ) - free( blocks [i] ); - memmove( &blocks [0], &blocks [begin], (block_count - begin) * sizeof *blocks ); - block_count -= begin; - } - - if ( resize( new_count ) ) - check( false ); // shrink should never fail - } -} - -Nes_Film_Data::~Nes_Film_Data() -{ - if ( resize( 0 ) ) - check( false ); // shrink should never fail - free( active ); - delete packer; -} - diff --git a/quicknes/nes_emu/Nes_Film_Data.h b/quicknes/nes_emu/Nes_Film_Data.h deleted file mode 100644 index 5e0c25fd95..0000000000 --- a/quicknes/nes_emu/Nes_Film_Data.h +++ /dev/null @@ -1,86 +0,0 @@ - -// Film data manager that keeps data compressed in memory - -// Nes_Emu 0.7.0 - -#ifndef NES_FILM_DATA_H -#define NES_FILM_DATA_H - -#include "Nes_State.h" -#include "Nes_Film_Packer.h" - -class Nes_Film_Data { -public: - Nes_Film_Data(); - ~Nes_Film_Data(); - - void clear( frame_count_t period ); - frame_count_t period() const { return period_; } - blargg_err_t resize( int new_count ); - void trim( int begin, int end ); - - enum { block_size = 8 }; // 16 helps compression but doubles temp buffer size - typedef int index_t; - struct block_t - { - BOOST::uint8_t* joypads [2]; - - Nes_State_ states [block_size]; - - Nes_Cpu::registers_t cpu [block_size]; - joypad_state_t joypad [block_size]; - apu_state_t apu [block_size]; - ppu_state_t ppu [block_size]; - mapper_state_t mapper [block_size]; - BOOST::uint8_t spr_ram [block_size] [Nes_State_::spr_ram_size]; - BOOST::uint8_t ram [block_size] [Nes_State_::ram_size]; - BOOST::uint8_t nametable [block_size] [Nes_State_::nametable_max]; - BOOST::uint32_t garbage0; - BOOST::uint8_t chr [block_size] [Nes_State_::chr_max]; - BOOST::uint32_t garbage1; - BOOST::uint8_t sram [block_size] [Nes_State_::sram_max]; - BOOST::uint32_t garbage2; - // garbage values prevent matches in compressor from being longer than 256K - BOOST::uint8_t joypad0 [60 * 60L * 60L]; - }; - block_t const& read( index_t ) const; - block_t* write( index_t ); // NULL if out of memory - block_t* alloc_joypad2( index_t i ) { return write( i ); } - void joypad_only( bool ); - -private: - struct comp_block_t - { - long size; - long offset; - BOOST::uint8_t data [1024 * 1024L]; - }; - comp_block_t** blocks; - int block_count; - frame_count_t period_; - block_t* active; - mutable int active_index; - mutable bool active_dirty; - long joypad_only_; - Nes_Film_Packer* packer; - - void debug_packer() const; - void flush_active() const; - void init_active() const; - void init_states() const; - void invalidate_active(); - void access( index_t ) const; - // must be multiple of 4 for packer - long active_size() const { return (offsetof (block_t,joypad0) + 3) & ~3; } -}; - -inline Nes_Film_Data::block_t const& Nes_Film_Data::read( int i ) const -{ - //assert( blocks [i] ); // catch reads of uninitialized blocks - if ( i != active_index ) - access( i ); - return *active; -} - -#endif - diff --git a/quicknes/nes_emu/Nes_Film_Packer.cpp b/quicknes/nes_emu/Nes_Film_Packer.cpp deleted file mode 100644 index ac7e2c0bb6..0000000000 --- a/quicknes/nes_emu/Nes_Film_Packer.cpp +++ /dev/null @@ -1,220 +0,0 @@ - -// Nes_Emu 0.7.0. http://www.slack.net/~ant/ - -#include "Nes_Film_Packer.h" - -#include - -/* Copyright (C) 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "blargg_source.h" - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -// - On my 400 MHz PowerPC G3, pack() = 230MB/sec, unpack() = 320MB/sec. -// - All 32-bit accessess are on 4-byte boundaries of the input/output buffers. -// - This would not make a good general-purpose compressor because the match -// offset is limited to a multiple of 4. - -#ifdef __MWERKS__ - static unsigned zero = 0; // helps CodeWarrior optimizer when added to constants -#else - const unsigned zero = 0; // compile-time constant on other compilers -#endif - -void Nes_Film_Packer::prepare( void const* begin, long size ) -{ - uint32_t const* end = (uint32_t*) ((byte*) begin + size - 4); - uint32_t const** d = dict; - for ( int n = dict_size; n--; ) - *d++ = end; - - uint32_t temp = 0x80000000; - assert( (BOOST::int32_t) temp < 0 ); // be sure high bit is sign -} - -long Nes_Film_Packer::pack( byte const* in_begin, long in_size, byte* out_begin ) -{ -//memcpy( out_begin, in_begin, in_size ); return in_size; - - assert( (in_size & 3) == 0 ); - uint32_t const* const in_end = (uint32_t*) (in_begin + in_size); - uint32_t const* const end = in_end - 2; - uint32_t const* in = (uint32_t*) in_begin; - uint32_t* out = (uint32_t*) out_begin; - - unsigned long first = *in++; - unsigned long offset; - uint32_t const* match; - - unsigned long const factor = 0x100801 + zero; - - // spaghetti program flow gives better efficiency - - goto begin; - - // match loop - do - { - if ( match [-1] != first ) break; - offset <<= 14; - if ( *match != *in ) break; -match: - // count matching words beyond the first two - unsigned long n = (byte*) end - (byte*) in; - first = *++in; - unsigned long m = *++match; - uint32_t const* start = in; - for ( n >>= 2; n; --n ) - { - if ( m != first ) break; - m = *++match; - first = *++in; - } - - // encode match offset and length - unsigned long length = (byte*) in - (byte*) start; - assert( 0 <= length && length <= 0xFFFF << 2 ); - assert( offset >> 16 <= 0x7FFF ); - offset |= length >> 2; - - // check for next match - unsigned long index = (first * factor) >> dict_shift & (dict_size - 1); - match = dict [index]; - *out++ = offset; // interleved write of previous match - offset = (byte*) in - (byte*) match; assert( !(offset & 3) ); - if ( in >= end ) goto match_end; - ++in; - dict [index] = in; - } - while ( offset < 0x20000 ); - -begin: - // start writing next literal - out [1] = first; - uint32_t* literal; - literal = out; - out++; - - // literal loop -literal: - first = *in; - do - { - // check for match - unsigned long index = (first * factor) >> dict_shift & (dict_size - 1); - *++out = first; // interleved write of current literal - match = dict [index]; - dict [index] = in + 1; - if ( in >= end ) goto literal_end; - offset = (byte*) in - (byte*) match; assert( !(offset & 3) ); - ++in; - if ( match [-1] != first ) goto literal; - first = *in; - } - while ( offset >= 0x20000 || *match != first ); - - // set length of completed literal - offset <<= 14; - *literal = (((byte*) out - (byte*) literal) >> 2) | 0x80000000; - goto match; - -match_end: - // start new literal for remaining data after final match - literal = out++; -literal_end: - --out; - - // write remaining data to literal - assert( in < in_end ); - do - { - *++out = *in++; - } - while ( in < in_end ); - *literal = (((byte*) out - (byte*) literal) >> 2) + 0x80000001; - - // mark end with zero word - *++out = 0x80000000; - ++out; - - long out_size = (byte*) out - out_begin; - assert( (out_size & 3) == 0 ); - return out_size; -} - -long Nes_Film_Packer::unpack( byte const* in_begin, long in_size, byte* out_begin ) -{ -//memcpy( out_begin, in_begin, in_size ); return in_size; - - assert( (in_size & 3) == 0 ); - uint32_t const* in = (uint32_t*) in_begin; - uint32_t* out = (uint32_t*) out_begin; - long const literal_offset = 0x7FFFFFFE + zero; - long count = (BOOST::int32_t) *in++; - uint32_t const* m; - - assert( count < 0 ); // first item should be literal - goto literal; - do - { - // match - do - { - assert( m - 1 >= (void*) out_begin ); - assert( m - 1 < out ); - unsigned long data = m [-1]; - *out++ = data; - data = *m; - if ( (count &= 0xFFFF) != 0 ) - { - do - { - *out++ = data; - data = *++m; - } - while ( --count ); - } - count = (BOOST::int32_t) *in++; - *out++ = data; - m = out - (count >> 16); - } - while ( count >= 0 ); - - literal: - unsigned long data = *in++; - *out++ = data; - data = *in++; - if ( (count += literal_offset) != 0 ) - { - do - { - *out++ = data; - data = *in++; - } - while ( --count ); - } - - count = (BOOST::int32_t) data; - m = out - (data >> 16); - } - while ( count >= 0 ); - - assert( count == (BOOST::int32_t) 0x80000000 ); - assert( (byte*) in == in_begin + in_size ); - long out_size = (byte*) out - out_begin; - assert( (out_size & 3) == 0 ); - return out_size; -} - diff --git a/quicknes/nes_emu/Nes_Film_Packer.h b/quicknes/nes_emu/Nes_Film_Packer.h deleted file mode 100644 index c222b94c78..0000000000 --- a/quicknes/nes_emu/Nes_Film_Packer.h +++ /dev/null @@ -1,32 +0,0 @@ - -// Fast save state compressor/decompressor for reducing Nes_Film memory usage - -// Nes_Emu 0.7.0 - -#ifndef NES_FILM_PACKER_H -#define NES_FILM_PACKER_H - -#include "blargg_common.h" - -class Nes_Film_Packer { -public: - void prepare( void const* begin, long size ); - - // Worst-case output size for given input size - long worst_case( long in_size ) const { return in_size + 8; } - - typedef unsigned char byte; - long pack( byte const* in, long size, byte* packed_out ); - - long unpack( byte const* packed_in, long packed_size, byte* out ); -private: - enum { dict_bits = 12 }; - enum { dict_size = 1 << dict_bits }; - enum { dict_shift = 32 - dict_bits }; - - typedef BOOST::uint32_t uint32_t; - uint32_t const* dict [dict_size]; -}; - -#endif - diff --git a/quicknes/nes_emu/Nes_Fme07_Apu.cpp b/quicknes/nes_emu/Nes_Fme07_Apu.cpp deleted file mode 100644 index 5ee8eee6d9..0000000000 --- a/quicknes/nes_emu/Nes_Fme07_Apu.cpp +++ /dev/null @@ -1,122 +0,0 @@ - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/libs/ - -#include "Nes_Fme07_Apu.h" - -#include - -/* Copyright (C) 2003-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -void Nes_Fme07_Apu::reset() -{ - last_time = 0; - - for ( int i = 0; i < osc_count; i++ ) - oscs [i].last_amp = 0; - - fme07_snapshot_t* state = this; - memset( state, 0, sizeof *state ); -} - -#include BLARGG_ENABLE_OPTIMIZER - -unsigned char Nes_Fme07_Apu::amp_table [16] = -{ - #define ENTRY( n ) (n * amp_range) + 0.5 - ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156), - ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624), - ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498), - ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000) - #undef ENTRY -}; - -void Nes_Fme07_Apu::run_until( blip_time_t end_time ) -{ - require( end_time >= last_time ); - - for ( int index = 0; index < osc_count; index++ ) - { - int mode = regs [7] >> index; - int vol_mode = regs [010 + index]; - int volume = amp_table [vol_mode & 0x0f]; - - if ( !oscs [index].output ) - continue; - - // check for unsupported mode - #ifndef NDEBUG - if ( (mode & 011) <= 001 && vol_mode & 0x1f ) - dprintf( "FME07 used unimplemented sound mode: %02X, vol_mode: %02X\n", - mode, vol_mode & 0x1f ); - #endif - - if ( (mode & 001) | (vol_mode & 0x10) ) - volume = 0; // noise and envelope aren't supported - - // period - int const period_factor = 16; - unsigned period = (regs [index * 2 + 1] & 0x0f) * 0x100 * period_factor + - regs [index * 2] * period_factor; - if ( period < 50 ) // around 22 kHz - { - volume = 0; - if ( !period ) // on my AY-3-8910A, period doesn't have extra one added - period = period_factor; - } - - // current amplitude - int amp = volume; - if ( !phases [index] ) - amp = 0; - int delta = amp - oscs [index].last_amp; - if ( delta ) - { - oscs [index].last_amp = amp; - synth.offset( last_time, delta, oscs [index].output ); - } - - blip_time_t time = last_time + delays [index]; - if ( time < end_time ) - { - Blip_Buffer* const osc_output = oscs [index].output; - int delta = amp * 2 - volume; - - if ( volume ) - { - do - { - delta = -delta; - synth.offset_inline( time, delta, osc_output ); - time += period; - } - while ( time < end_time ); - - oscs [index].last_amp = (delta + volume) >> 1; - phases [index] = (delta > 0); - } - else - { - // maintain phase when silent - int count = (end_time - time + period - 1) / period; - phases [index] ^= count & 1; - time += (long) count * period; - } - } - - delays [index] = time - end_time; - } - - last_time = end_time; -} - diff --git a/quicknes/nes_emu/Nes_Fme07_Apu.h b/quicknes/nes_emu/Nes_Fme07_Apu.h deleted file mode 100644 index 79b0037447..0000000000 --- a/quicknes/nes_emu/Nes_Fme07_Apu.h +++ /dev/null @@ -1,133 +0,0 @@ - -// Sunsoft FME-07 sound emulator - -// Nes_Emu 0.5.6. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. - -#ifndef NES_FME07_APU_H -#define NES_FME07_APU_H - -#include "Blip_Buffer.h" - -struct fme07_snapshot_t -{ - enum { reg_count = 14 }; - BOOST::uint8_t regs [reg_count]; - BOOST::uint8_t phases [3]; // 0 or 1 - BOOST::uint8_t latch; - BOOST::uint16_t delays [3]; // a, b, c -}; -BOOST_STATIC_ASSERT( sizeof (fme07_snapshot_t) == 24 ); - -class Nes_Fme07_Apu : private fme07_snapshot_t { -public: - Nes_Fme07_Apu(); - - // See Nes_Apu.h for reference - void reset(); - void volume( double ); - void treble_eq( blip_eq_t const& ); - void output( Blip_Buffer* ); - enum { osc_count = 3 }; - void osc_output( int index, Blip_Buffer* ); - void end_frame( blip_time_t ); - void save_snapshot( fme07_snapshot_t* ) const; - void load_snapshot( fme07_snapshot_t const& ); - - // Mask and addresses of registers - enum { addr_mask = 0xe000 }; - enum { data_addr = 0xe000 }; - enum { latch_addr = 0xc000 }; - - // (addr & addr_mask) == latch_addr - void write_latch( int ); - - // (addr & addr_mask) == data_addr - void write_data( blip_time_t, int data ); - - // End of public interface -private: - // noncopyable - Nes_Fme07_Apu( const Nes_Fme07_Apu& ); - Nes_Fme07_Apu& operator = ( const Nes_Fme07_Apu& ); - - static unsigned char amp_table [16]; - - struct { - Blip_Buffer* output; - int last_amp; - } oscs [osc_count]; - blip_time_t last_time; - - enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff - Blip_Synth synth; - - void run_until( blip_time_t ); -}; - -inline void Nes_Fme07_Apu::volume( double v ) -{ - synth.volume_unit( 0.38 / amp_range * v ); // to do: fine-tune -} - -inline void Nes_Fme07_Apu::treble_eq( blip_eq_t const& eq ) -{ - synth.treble_eq( eq ); -} - -inline void Nes_Fme07_Apu::output( Blip_Buffer* buf ) -{ - for ( int i = 0; i < osc_count; i++ ) - osc_output( i, buf ); -} - -inline void Nes_Fme07_Apu::osc_output( int i, Blip_Buffer* buf ) -{ - assert( (unsigned) i < osc_count ); - oscs [i].output = buf; -} - -inline Nes_Fme07_Apu::Nes_Fme07_Apu() -{ - output( NULL ); - volume( 1.0 ); - reset(); -} - -inline void Nes_Fme07_Apu::write_latch( int data ) { latch = data; } - -inline void Nes_Fme07_Apu::write_data( blip_time_t time, int data ) -{ - if ( (unsigned) latch >= reg_count ) - { - #ifdef dprintf - dprintf( "FME07 write to %02X (past end of sound registers)\n", (int) latch ); - #endif - return; - } - - run_until( time ); - regs [latch] = data; -} - -inline void Nes_Fme07_Apu::end_frame( blip_time_t time ) -{ - if ( time > last_time ) - run_until( time ); - last_time -= time; - assert( last_time >= 0 ); -} - -inline void Nes_Fme07_Apu::save_snapshot( fme07_snapshot_t* out ) const -{ - *out = *this; -} - -inline void Nes_Fme07_Apu::load_snapshot( fme07_snapshot_t const& in ) -{ - reset(); - fme07_snapshot_t* state = this; - *state = in; -} - -#endif - diff --git a/quicknes/nes_emu/Nes_Nonlinearizer.cpp b/quicknes/nes_emu/Nes_Nonlinearizer.cpp deleted file mode 100644 index d6bff8d632..0000000000 --- a/quicknes/nes_emu/Nes_Nonlinearizer.cpp +++ /dev/null @@ -1,157 +0,0 @@ - -// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/ - -#include "Nes_Nonlinearizer.h" - -/* Library Copyright (C) 2003-2005 Shay Green. This library 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -Nes_Nonlinearizer::Nes_Nonlinearizer() : Multi_Buffer( 1 ) -{ - enable_nonlinearity( true ); -} - -Nes_Nonlinearizer::~Nes_Nonlinearizer() -{ -} - -blargg_err_t Nes_Nonlinearizer::sample_rate( long rate, int msec ) -{ - BLARGG_RETURN_ERR( buf.sample_rate( rate, msec ) ); - BLARGG_RETURN_ERR( tnd.sample_rate( rate, msec ) ); - return Multi_Buffer::sample_rate( buf.sample_rate(), buf.length() ); -} - -void Nes_Nonlinearizer::clock_rate( long rate ) -{ - buf.clock_rate( rate ); - tnd.clock_rate( rate ); -} - -void Nes_Nonlinearizer::bass_freq( int freq ) -{ - buf.bass_freq( freq ); - tnd.bass_freq( freq ); -} - -void Nes_Nonlinearizer::clear() -{ - accum = 0x8000; - buf.clear(); - tnd.clear(); -} - -Nes_Nonlinearizer::channel_t Nes_Nonlinearizer::channel( int i ) -{ - channel_t c; - c.center = (2 <= i && i <= 4) ? &tnd : &buf; - c.left = c.center; - c.right = c.center; - return c; -} - -void Nes_Nonlinearizer::end_frame( blip_time_t length, bool ) -{ - buf.end_frame( length ); - tnd.end_frame( length ); -} - -long Nes_Nonlinearizer::samples_avail() const -{ - return buf.samples_avail(); -} - -#include BLARGG_ENABLE_OPTIMIZER - -void Nes_Nonlinearizer::enable_nonlinearity( bool b ) -{ - require( b ); // to do: implement non-linear output - double gain = 0x7fff * 0.742467605 * 1.2; - for ( int i = 0; i < half * 2; i++ ) - { - int out = i << shift; - if ( i > half ) - { - double n = 202.0 / (half - 1) * (i - half); - double d = 163.67 / (24329.0 / n + 100); - out = int (d * gain) + 0x8000; - } - table [i] = out; - } -} - -void Nes_Nonlinearizer::make_nonlinear( long count ) -{ - const int zero_offset = 0x7f7f; // to do: use private constant from Blip_Buffer.h - - #define ENTRY( s ) (table [((s) >> shift) & entry_mask]) - - BOOST::uint16_t* p = tnd.buffer_; - unsigned prev = ENTRY( accum ); - long accum = this->accum; - - for ( unsigned n = count; n--; ) - { - accum += (long) *p - zero_offset; - if ( (accum >> shift) >= half * 2 ) - { - // to do: extend table to handle overflow better - check( false ); // overflowed - accum = (half * 2 - 1) << shift; - } - unsigned entry = ENTRY( accum ); - *p++ = entry - prev + zero_offset; - prev = entry; - } - - this->accum = accum; -} - -long Nes_Nonlinearizer::read_samples( blip_sample_t* out, long count ) -{ - long avail = buf.samples_avail(); - assert( tnd.samples_avail() == avail ); - if ( count > avail ) - count = avail; - - if ( count ) - { - make_nonlinear( count ); - - Blip_Reader lin; - Blip_Reader nonlin; - - int lin_bass = lin.begin( buf ); - int nonlin_bass = nonlin.begin( tnd ); - - for ( int n = count; n--; ) - { - int s = lin.read() + nonlin.read(); - lin.next( lin_bass ); - nonlin.next( nonlin_bass ); - *out++ = s; - - if ( (BOOST::int16_t) s != s ) - out [-1] = 0x7FFF - (s >> 24); - } - - lin.end( buf ); - nonlin.end( tnd ); - - buf.remove_samples( count ); - tnd.remove_samples( count ); - } - - return count; -} - diff --git a/quicknes/nes_emu/Nes_Nonlinearizer.h b/quicknes/nes_emu/Nes_Nonlinearizer.h deleted file mode 100644 index 1af78e0aaf..0000000000 --- a/quicknes/nes_emu/Nes_Nonlinearizer.h +++ /dev/null @@ -1,44 +0,0 @@ - -// NES non-linear audio output - -// Nes_Emu 0.5.0. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. - -#ifndef NES_NONLINEARIZER_H -#define NES_NONLINEARIZER_H - -#include "Multi_Buffer.h" - -class Nes_Nonlinearizer : public Multi_Buffer { -public: - Nes_Nonlinearizer(); - ~Nes_Nonlinearizer(); - - // Enable non-linear output - void enable_nonlinearity( bool = true ); - - // See Multi_Buffer.h - blargg_err_t sample_rate( long rate, int msec = blip_default_length ); - Multi_Buffer::sample_rate; - void clock_rate( long ); - void bass_freq( int ); - void clear(); - channel_t channel( int ); - void end_frame( blip_time_t, bool unused = true ); - long samples_avail() const; - long read_samples( blip_sample_t*, long ); - - // End of public interface -private: - enum { shift = 5 }; - enum { half = 0x8000 >> shift }; - enum { entry_mask = half * 2 - 1 }; - Blip_Buffer buf; - Blip_Buffer tnd; - long accum; - BOOST::uint16_t table [half * 2]; - - void make_nonlinear( long ); -}; - -#endif - diff --git a/quicknes/nes_emu/Nes_Ppu_Core.cpp b/quicknes/nes_emu/Nes_Ppu_Core.cpp deleted file mode 100644 index 95be6b51e5..0000000000 --- a/quicknes/nes_emu/Nes_Ppu_Core.cpp +++ /dev/null @@ -1,419 +0,0 @@ - -// NES PPU register read/write and frame timing - -// Nes_Emu 0.5.0. http://www.slack.net/~ant/ - -#include "Nes_Ppu.h" - -#include - -/* Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -// to do: implement junk in unused bits when reading registers - -// to do: put in common or something -template -inline const T& min( const T& x, const T& y ) -{ - if ( x < y ) - return x; - return y; -} - -typedef BOOST::uint8_t byte; - -ppu_time_t const ppu_overclock = 3; // PPU clocks for each CPU clock -ppu_time_t const scanline_duration = 341; -ppu_time_t const t_to_v_time = 20 * scanline_duration + 293; -//ppu_time_t const t_to_v_time = 19 * scanline_duration + 330; // 322 - 339 passes test -ppu_time_t const first_scanline_time = 21 * scanline_duration + 128; -ppu_time_t const first_hblank_time = 21 * scanline_duration + 256; - -void Nes_Ppu::start_frame() -{ - scanline_time = first_scanline_time; - hblank_time = first_hblank_time; - next_time = t_to_v_time / ppu_overclock; - next_scanline = 0; - frame_phase = 0; - query_phase = 0; - w2003 = 0; - memset( sprite_scanlines, 64 - max_sprites, sizeof sprite_scanlines ); -} - -void Nes_Ppu::query_until( nes_time_t time ) -{ - // nothing happens until scanline 20 - if ( time > 2271 ) - { - // clear VBL flag and sprite hit after 20 scanlines - if ( query_phase < 1 ) - { - query_phase = 1; - r2002 &= ~0xc0; - } - - // update sprite hit - if ( query_phase < 2 && update_sprite_hit( time ) ) - query_phase = 2; - - // set VBL flag a few clocks before the end of the frame (cheap hack) - if ( query_phase < 3 && time > 29777 ) - { - query_phase = 3; - r2002 |= 0x80; - } - } -} - -void Nes_Ppu::end_frame( nes_time_t end_time ) -{ - render_until( end_time ); - query_until( end_time ); - // to do: remove (shows number of sprites per line graphically) - if ( false ) - if ( base_pixels ) - { - for ( int i = 0; i < image_height; i++ ) - { - int n = sprite_scanlines [i] - (64 - max_sprites); - memset( base_pixels + 16 + i * row_bytes, (n <= 8 ? 3 : 6), n ); - } - } -// dprintf( "End of frame\n" ); - start_frame(); -} - -inline byte const* Nes_Ppu::map_chr( int addr ) const -{ - return &chr_rom [map_chr_addr( addr )]; -} - -// Read/write - -inline byte* Nes_Ppu::map_palette( int addr ) -{ - if ( (addr & 3) == 0 ) - addr &= 0x0f; // 0x10, 0x14, 0x18, 0x1c map to 0x00, 0x04, 0x08, 0x0c - - return &palette [addr & 0x1f]; -} - -int Nes_Ppu::read( nes_time_t time, unsigned addr ) -{ - // Don't catch rendering up to present since status reads don't affect - // rendering and status is often polled in a tight loop. - - switch ( addr & 7 ) - { - // status - case 2: { - second_write = false; - query_until( time ); - int result = r2002; - r2002 &= ~0x80; - return result; - } - - // sprite ram - case 4: { - int result = spr_ram [w2003]; - if ( (w2003 & 3) == 2 ) - result &= 0xe3; - return result; - } - - // video ram - case 7: { - render_until( time ); // changes to vram_addr affect rendering - int result = r2007; - int a = vram_addr & 0x3fff; - vram_addr = a + ((w2000 & 4) ? 32 : 1); - if ( a < 0x2000 ) - { - r2007 = *map_chr( a ); - } - else - { - r2007 = get_nametable( a ) [a & 0x3ff]; - - // palette doesn't use read buffer, but it's still filled with nametable contents - if ( a >= 0x3f00 ) - result = *map_palette( a ); - } - return result; - } - } - - return 0; -} - -void Nes_Ppu::write( nes_time_t time, unsigned addr, int data ) -{ - if ( addr > 0x2007 ) - printf( "Write to mirrored $200x\n" ); - - int reg = (addr & 7); - if ( reg == 0 ) - { - // render only if changes to register could affect it - int new_temp = (vram_temp & ~0x0c00) | ((data & 3) * 0x400); - if ( (new_temp - vram_temp) | ((w2000 ^ data) & 0x38) ) - render_until( time ); - - vram_temp = new_temp; - w2000 = data; - return; - } - - render_until( time ); - switch ( reg ) - { - //case 0: // control (handled above) - - case 1: // sprites, bg enable - w2001 = data; - break; - - case 3: // spr addr - w2003 = data; - break; - - case 4: - spr_ram [w2003] = data; - w2003 = (w2003 + 1) & 0xff; - break; - - case 5: - if ( second_write ) { - vram_temp = (vram_temp & ~0x73e0) | - ((data & 0xf8) << 2) | ((data & 7) << 12); - } - else { - pixel_x = data & 7; - vram_temp = (vram_temp & ~0x001f) | (data >> 3); - } - second_write ^= 1; - break; - - case 6: { - unsigned old_addr = vram_addr; - if ( second_write ) - { - vram_addr = vram_temp = (vram_temp & ~0x00ff) | data; -// if ( time >= 2271 ) -// dprintf( "%d VRAM fine: %d, tile: %d\n", -// (int) time, int (vram_addr >> 12), int ((vram_addr >> 5) & 31) ); - } - else - { - vram_temp = (vram_temp & ~0xff00) | ((data << 8) & 0x3f00); - } - second_write ^= 1; -// if ( (vram_addr & old_addr) & 0x2000 ) -// dprintf( "%d Toggled A13\n", time ); - break; - } - - case 7: - { - int a = vram_addr & 0x3fff; - vram_addr = a + ((w2000 & 4) ? 32 : 1); - if ( a < 0x2000 ) - { - a = map_chr_addr( a ); - BOOST::uint8_t& b = impl->chr_ram [a]; - if ( (b ^ data) & chr_write_mask ) - { - b = data; - assert( a < sizeof impl->chr_ram ); - tiles_modified [(unsigned) a / bytes_per_tile] = true; - any_tiles_modified = true; - } - } - else if ( a < 0x3f00 ) - { - get_nametable( a ) [a & 0x3ff] = data; - } - else - { - *map_palette( a ) = data & 0x3f; - } - break; - } - } -} - -// Frame rendering - -// returns true when sprite hit checking is done for the frame (hit flag won't change any more) -bool Nes_Ppu::update_sprite_hit( nes_time_t cpu_time ) -{ - // earliest time of hit empirically determined by testing on NES - ppu_time_t const delay = 21 * scanline_duration + 333; - if ( cpu_time < delay / ppu_overclock ) - return false; - - long time = cpu_time * ppu_overclock - delay; - long low_bound = spr_ram [0] * scanline_duration + spr_ram [3]; - if ( time < low_bound ) - return false; - - int tile = spr_ram [1] + ((w2000 << 5) & 0x100); - int height = 1; - if ( w2000 & 0x20 ) - { - height = 2; - tile = (tile & 1) * 0x100 + (tile & 0xfe); - } - byte const* data = map_chr( tile * bytes_per_tile ); - for ( int n = height; n--; ) - { - for ( int n = 8; n--; ) - { - if ( time < low_bound ) - return false; - - if ( data [0] | data [8] ) - { - r2002 |= 0x40; - return true; - } - - data++; - low_bound += scanline_duration; - } - - data += 8; - } - - return true; -} - -void Nes_Ppu::run_hblank( int n ) -{ - hblank_time += scanline_duration * n; - if ( w2001 & 0x08 ) - { -// vram_addr = (vram_addr & ~0x41f) | (vram_temp & 0x41f); - long addr = vram_addr + n * 0x1000; - if ( addr >= 0x8000 ) - { - addr &= 0x7fff; - - int const mask = 0x3e0; - int a = (addr + 0x20) & mask; - if ( a == 30 * 0x20 ) - { - a &= 0x1f; - addr ^= 0x800; - } - addr = (addr & ~mask) | (a & mask); - } - assert( addr < 0x8000 ); - vram_addr = addr; - } -} - -void Nes_Ppu::render_until_( nes_time_t cpu_time ) -{ - ppu_time_t time = cpu_time * ppu_overclock; - ppu_time_t const frame_duration = scanline_duration * 261; - if ( time > frame_duration ) - time = frame_duration; - - if ( frame_phase == 0 ) - { - frame_phase = 1; - if ( w2001 & 0x08 ) - vram_addr = vram_temp; -// else -// dprintf( "PPU off\n" ); - } - - if ( hblank_time < scanline_time && hblank_time < time ) - run_hblank( 1 ); - - int count = 0; - while ( scanline_time < time ) - { - scanline_time += scanline_duration; - count++; - } - - if ( count ) - { - int start = next_scanline; - int end = start + count; - assert( end <= image_height ); - next_scanline = end; - - if ( base_pixels ) - { - if ( start == 0 ) - { - memcpy( host_palette, palette, 32 ); - int bg = palette [0]; - for ( int i = 0; i < 32; i += 4 ) - host_palette [i] = bg; - memcpy( host_palette + 32, host_palette, 32 ); - } - - if ( w2001 & 0x18 && any_tiles_modified ) - { - any_tiles_modified = false; - update_tiles( 0 ); - } - - if ( w2001 & 0x08 ) - { - draw_background( start, end ); - } - else - { - run_hblank( end - start - 1 ); - black_background( start, end ); - } - - // when clipping just sprites, save left strip then restore after drawing sprites - int const obj_mask = 0x04; - int const bg_mask = 0x02; - int clip_mode = ~w2001 & (obj_mask | bg_mask); - - if ( clip_mode == obj_mask ) - save_left( start, end ); - else if ( clip_mode == bg_mask ) - clip_left( start, end ); - - if ( w2001 & 0x10 ) - draw_sprites( start, end ); - - if ( clip_mode == obj_mask ) - restore_left( start, end ); - else if ( clip_mode == (obj_mask | bg_mask) ) - clip_left( start, end ); - } - else - { - run_hblank( end - start - 1 ); - } - } - - if ( hblank_time < time ) - run_hblank( 1 ); - assert( time <= hblank_time ); - - next_time = min( scanline_time, hblank_time ) / ppu_overclock; -} - diff --git a/quicknes/nes_emu/Nes_Recorder.cpp b/quicknes/nes_emu/Nes_Recorder.cpp deleted file mode 100644 index 861951184e..0000000000 --- a/quicknes/nes_emu/Nes_Recorder.cpp +++ /dev/null @@ -1,472 +0,0 @@ - -// Nes_Emu 0.7.0. http://www.slack.net/~ant/ - -#include "Nes_Recorder.h" - -#include - -/* Copyright (C) 2004-2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "blargg_source.h" - -int const joypad_sync_value = 0xFF; // joypad data on frames it's never read - -Nes_Recorder::Nes_Recorder() -{ - cache = 0; - film_ = 0; - frames = 0; - resync_enabled = false; - disable_reverse( 1 ); // sets cache_period_ and cache_size - reverse_allowed = true; - buffer_height_ = Nes_Ppu::buffer_height * frames_size + 2; -} - -Nes_Recorder::~Nes_Recorder() -{ - free( frames ); - delete [] cache; -} - -blargg_err_t Nes_Recorder::init_() -{ - RETURN_ERR( base::init_() ); - - cache = new Nes_State [cache_size]; - - int frame_count = reverse_allowed ? frames_size : 1; - CHECK_ALLOC( frames = (saved_frame_t*) calloc( sizeof *frames, frame_count ) ); - for ( int i = 0; i < frame_count; i++ ) - frames [i].top = (long) i * Nes_Ppu::buffer_height + 1; - - return 0; -} - -void Nes_Recorder::clear_cache() -{ - ready_to_resync = false; - reverse_enabled = false; - for ( int i = 0; i < cache_size; i++ ) - cache [i].set_timestamp( invalid_frame_count ); -} - -void Nes_Recorder::set_film( Nes_Film* new_film, frame_count_t time ) -{ - require( new_film ); - film_ = new_film; - clear_cache(); - if ( !film_->blank() ) - { - tell_ = film_->constrain( time ); - check( tell_ == time ); // catch seeks outside film - seek_( tell_ ); - } -} - -void Nes_Recorder::reset( bool full_reset, bool erase_battery_ram ) -{ - base::reset( full_reset, erase_battery_ram ); - tell_ = 0; - film_->clear(); - clear_cache(); -} - -void Nes_Recorder::loading_state( Nes_State const& in ) -{ - reset(); - tell_ = in.timestamp(); -} - -// Frame emulation - -inline int Nes_Recorder::cache_index( frame_count_t t ) const -{ - return (t / cache_period_) % cache_size; -} - -void Nes_Recorder::emulate_frame_( Nes_Film::joypad_t joypad ) -{ - if ( base::timestamp() % cache_period_ == 0 ) - save_state( &cache [cache_index( base::timestamp() )] ); - - if ( base::emulate_frame( joypad & 0xFF, (joypad >> 8) & 0xFF ) ) { } -} - -void Nes_Recorder::replay_frame_( Nes_Film::joypad_t joypad ) -{ - if ( base::timestamp() % film_->period() == 0 ) - { - if ( film_->read_snapshot( base::timestamp() ).timestamp() == invalid_frame_count ) - { - Nes_State_* ss = film_->modify_snapshot( base::timestamp() ); - if ( ss ) - save_state( ss ); - else - check( false ); // out of memory simply causes lack of caching - } - } - - emulate_frame_( joypad ); -} - -int Nes_Recorder::replay_frame() -{ - frame_count_t start_time = base::timestamp(); - int joypad = film_->get_joypad( start_time ); - if ( !film_->has_joypad_sync() ) - { - replay_frame_( joypad ); - } - else if ( (joypad & 0xFF) != joypad_sync_value ) - { - // joypad should be read - replay_frame_( joypad ); - if ( !joypad_read_count() ) - { - // emulator has fallen behind - dprintf( "Fell behind joypad data \n" ); - base::set_timestamp( start_time ); - } - } - else - { - // get joypad for next frame in case emulator gets ahead - if ( film_->contains_frame( start_time + 1 ) ) - { - joypad = film_->get_joypad( start_time + 1 ); - if ( (joypad & 0xFF) == joypad_sync_value ) - joypad = 0; // next frame shouldn't read joypad either, so just give it nothing - } - - // joypad should not be read - replay_frame_( joypad ); - if ( joypad_read_count() ) - { - // emulator is ahead - dprintf( "Ahead of joypad data \n" ); - base::set_timestamp( film_->constrain( base::timestamp() + 1 ) ); - } - } - return base::timestamp() - start_time; -} - -// Film handling - -Nes_State_ const* Nes_Recorder::nearest_snapshot( frame_count_t time ) const -{ - Nes_State_ const* ss = film_->nearest_snapshot( time ); - if ( ss ) - { - // check cache for any snapshots more recent than film_'s - for ( frame_count_t t = time - time % cache_period_; - ss->timestamp() < t; t -= cache_period_ ) - { - Nes_State_ const& cache_ss = cache [cache_index( t )]; - if ( cache_ss.timestamp() == t ) - return &cache_ss; - } - } - return ss; -} - -void Nes_Recorder::seek_( frame_count_t time ) -{ - Nes_State_ const* ss = nearest_snapshot( time ); - if ( !film_->contains( time ) || !ss ) - { - require( false ); // tried to seek outside recording - return; - } - - base::load_state( *ss ); - frame_ = 0; // don't render graphics - frame_count_t max_iter = (time - base::timestamp()) * 2; // don't seek forever - while ( base::timestamp() < time && max_iter-- ) - replay_frame(); -} - -void Nes_Recorder::seek( frame_count_t time ) -{ - check( film_->contains( time ) ); - time = film_->constrain( time ); - if ( time != tell() ) - { - reverse_enabled = false; - seek_( time ); - tell_ = base::timestamp(); - } -} - -inline frame_count_t Nes_Recorder::advancing_frame() -{ - if ( reverse_enabled ) - { - reverse_enabled = false; - if ( !film_->blank() ) - seek_( tell_ ); - } - frame_ = &frames [0]; - tell_ = base::timestamp(); - return tell_++; -} - -blargg_err_t Nes_Recorder::emulate_frame( int joypad, int joypad2 ) -{ - frame_count_t time = advancing_frame(); - require( film_->blank() || film_->contains( time ) ); - - Nes_Film::joypad_t joypads = joypad2 * 0x100 + joypad; - - Nes_State_* ss = 0; - RETURN_ERR( film_->record_frame( time, joypads, &ss ) ); - if ( ss ) - save_state( ss ); - - emulate_frame_( joypads ); - - if ( film_->has_joypad_sync() && !joypad_read_count() ) - RETURN_ERR( film_->set_joypad( time, joypad_sync_value ) ); - - // avoid stale cache snapshot after trimming film - if ( base::timestamp() % cache_period_ == 0 ) - cache [cache_index( base::timestamp() )].set_timestamp( invalid_frame_count ); - - return 0; -} - -void Nes_Recorder::next_frame() -{ - if ( tell() >= film_->end() ) - { - check( false ); // tried to go past end - return; - } - frame_count_t time = advancing_frame(); - assert( base::timestamp() == time || base::timestamp() == time + 1 ); - - // ready_to_resync avoids endless resyncing if joypad isn't getting read when - // it should, thus the timestamp never incrementing. - if ( ready_to_resync ) - { - Nes_State_ const& ss = film_->read_snapshot( time ); - if ( ss.timestamp() == time ) - { - // todo: remove - #if !defined (NDEBUG) && 1 - dprintf( "Resynced \n" ); - - static Nes_State* temp = BLARGG_NEW Nes_State [2]; - static char* temp2 = new char [sizeof *temp]; - if ( temp && temp2 ) - { - save_state( temp ); - memcpy( temp2, temp, sizeof *temp ); - long a = temp->apu.noise.shift_reg; - long b = temp->apu.apu.w40xx [0x11]; - long c = temp->apu.dmc.bits; - base::load_state( ss ); - save_state( temp ); - save_state( &temp [1] ); - - // shift register and dac are not maintained - temp->apu.noise.shift_reg = a; - temp->apu.apu.w40xx [0x11] = b; - temp->apu.dmc.bits = c; - - if ( memcmp( temp2, temp, sizeof *temp ) ) - { - check( !"Film sync corrected error" ); - Std_File_Writer out; - (void) !out.open( "state0" ); - (void) !temp [0].write( out ); - (void) !out.open( "state1" ); - (void) !temp [1].write( out ); - //(void) !out.open( "state2" ); - //(void) !ss.write( out ); - } - } - - if ( 0 ) - #endif - base::load_state( ss ); - } - } - - int count = replay_frame(); - tell_ = base::timestamp(); - - // examination of count prevents endless resync if frame is getting doubled - ready_to_resync = false; - if ( count && resync_enabled && film_->read_snapshot( tell_ ).timestamp() == tell_ ) - { - fade_sound_out = true; - ready_to_resync = true; - } -} - -// Extra features - -void Nes_Recorder::record_keyframe() -{ - if ( !film_->blank() ) - { - Nes_State_* ss = film_->modify_snapshot( base::timestamp() ); - if ( !ss ) - { - check( false ); // out of memory simply causes lack of key frame adjustment - } - // first snapshot can only be replaced if key frame is at beginning of film - else if ( ss->timestamp() > film_->begin() || base::timestamp() == film_->begin() ) - { - if ( ss->timestamp() != base::timestamp() ) - save_state( ss ); - } - } -} - -frame_count_t Nes_Recorder::nearby_keyframe( frame_count_t time ) const -{ - // TODO: reimplement using direct snapshot and cache access - check( film_->contains( time ) ); - - // don't adjust time if seeking to beginning or end - if ( film_->begin() < time && time < film_->end() ) - { - // rounded time must be within about a minute of requested time - int const half_threshold = 45 * frame_rate; - - // find nearest snapshots before and after requested time - frame_count_t after = invalid_frame_count; - frame_count_t before = time + half_threshold; - do - { - after = before; - Nes_State_ const* ss = nearest_snapshot( film_->constrain( before - 1 ) ); - if ( !ss ) - { - require( false ); // tried to seek outside recording - return time; - } - before = ss->timestamp(); - } - while ( time < before ); - - // determine closest and use if within threshold - frame_count_t closest = after; - if ( time - before < after - time ) - closest = before; - int delta = time - closest; - if ( max( delta, -delta ) < half_threshold ) - time = closest; - if ( time < film_->begin() ) - time = film_->begin(); - } - return time; -} - -void Nes_Recorder::skip( int delta ) -{ - if ( delta ) // rounding code can't handle zero - { - // round to nearest cache timestamp (even if not in cache) - frame_count_t current = tell(); - frame_count_t time = current + delta + cache_period_ / 2; - time -= time % cache_period_; - if ( delta < 0 ) - { - if ( time >= current ) - time -= cache_period_; - } - else if ( time <= current ) - { - time += cache_period_; - } - seek( film_->constrain( time ) ); - } -} - -// Reverse handling - -// Get index of frame at given timestamp in reverse frames -inline int Nes_Recorder::reverse_index( frame_count_t time ) const -{ - int index = time % (frames_size * 2); - if ( index >= frames_size ) // opposite direction on odd runs - index = frames_size * 2 - 1 - index; - return index; -} - -// Generate frame at given timestamp into proper position in reverse frames -void Nes_Recorder::reverse_fill( frame_count_t time ) -{ - if ( time >= film_->begin() ) - { - // todo: can cause excessive seeking when joypad data loses sync - if ( base::timestamp() != time ) - seek_( time ); - - saved_frame_t* frame = &frames [reverse_index( time )]; - frame_ = frame; - if ( time % frames_size == frames_size - 1 ) - fade_sound_out = true; - replay_frame(); - frame->sample_count = base::read_samples( frame->samples, frame->max_samples ); - } -} - -void Nes_Recorder::prev_frame() -{ - if ( tell() <= film_->begin() || !reverse_allowed ) - { - check( false ); // tried to go before beginning - return; - } - - int offset = tell_ % frames_size; - frame_count_t aligned = tell_ - offset; - if ( reverse_enabled ) - { - reverse_fill( aligned - 1 - offset ); - } - else - { - reverse_enabled = true; - for ( int i = 0; i < frames_size; i++ ) - { - frame_count_t time = aligned + i; - if ( i >= offset ) - time -= offset + frames_size; // restore some of previous second - reverse_fill( time ); - } - } - - tell_--; - frame_ = &frames [reverse_index( tell_ )]; -} - -long Nes_Recorder::read_samples( short* out, long count ) -{ - require( count >= frame().sample_count ); - if ( !reverse_enabled ) - return base::read_samples( out, count ); - - // copy samples in reverse without reversing left and right channels - // to do: optimize? - count = frame().sample_count; - blip_sample_t const* in = STATIC_CAST(saved_frame_t const&,frame()).samples; - int step = frame().chan_count - 1; - for ( int i = 0; i < count; i++ ) - out [count - 1 - (i ^ step)] = in [i]; - - return count; -} - diff --git a/quicknes/nes_emu/Nes_Recorder.h b/quicknes/nes_emu/Nes_Recorder.h deleted file mode 100644 index eb6254438f..0000000000 --- a/quicknes/nes_emu/Nes_Recorder.h +++ /dev/null @@ -1,142 +0,0 @@ - -// NES emulator with movie recording and playback in both directions - -// Nes_Emu 0.7.0 - -#ifndef NES_RECORDER_H -#define NES_RECORDER_H - -#include "Nes_Emu.h" -#include "Nes_Film.h" - -class Nes_Recorder : public Nes_Emu { -public: - // Set new film to use for recording and playback. If film isn't empty, seeks to - // its beginning (or to optional specified fime). Film *must* be loaded before - // using the recorder for emulation. - void set_film( Nes_Film*, frame_count_t ); - void set_film( Nes_Film* f ) { set_film( f, f->begin() ); } - - // Currently loaded film - Nes_Film& film() const { return *film_; } - - // Time references are in terms of timestamps at a single moment, rather than - // the frames that occur between two timestamps. All timestamps must be within - // the current recording. The emulator is always at a particular timestamp in the - // recording; a frame exists only in the graphics buffer and sample buffer. Shown - // below are timestamps and the frame that occurs between 1 and 2. - // |---|///|---|--- - // 0 1 2 3 timestamps of snapshots between frames - - // Current timestamp - frame_count_t tell() const; - - // Seek to new timestamp. Time is constrained to recording if it falls outside. - void seek( frame_count_t ); - - // Record new frame at current timestamp and remove anything previously - // recorded after it. - blargg_err_t emulate_frame( int joypad, int joypad2 = 0 ); - - // Increment timestamp and generate frame for that duration. Does nothing - // if already at end of recording. - void next_frame(); - - // Decrement timestamp and generate frame for that duration. Does nothing - // if already at beginning of recording. Performance is close to that of - // next_frame(). - void prev_frame(); - -// Additional features - - // Disable reverse support and optionally use less-frequent cache snapshots, in order - // to drastically reduce the required height of the graphics buffer and memory usage. - // If used, must be called one time *before* any use of emulator. - void disable_reverse( int cache_period_secs = 5 ); - - // Call when current film has been significantly changed (loaded from file). - // Doesn't need to be called if film was merely trimmed. - void film_changed(); - - // Attempt to add keyframe to film at current timestamp, which will make future - // seeking to this point faster after film is later loaded. - void record_keyframe(); - - // Get time of nearby key frame within +/- 45 seconds, otherwise return time unchanged. - // Seeking to times of key frames is much faster than an arbitrary time. Time - // is constrained to film if it falls outside. - frame_count_t nearby_keyframe( frame_count_t ) const; - - // Quickly skip forwards or backwards, staying within recording. May skip slightly - // more or less than delta, but will always skip at least some if delta is non-zero - // (i.e. repeated skip( 1 ) calls will eventually reach the end of the recording). - void skip( int delta ); - - // When enabled, emulator is synchronized at each snapshot in film. This - // corrects any emulation differences compared to when the film was made. Might - // be necessary when playing movies made in an older version of this emulator - // or from other emulators. - void enable_resync( bool b = true ) { resync_enabled = b; } - - // Height of graphics buffer needed when running forward (next_frame() or - // emulate_frame(), but not prev_frame()) - enum { forward_buffer_height = Nes_Ppu::buffer_height }; - -public: - Nes_Recorder(); - virtual ~Nes_Recorder(); - virtual blargg_err_t init_(); - virtual void reset( bool = true, bool = false ); - void load_state( Nes_State const& s ) { Nes_Emu::load_state( s ); } - blargg_err_t load_state( Auto_File_Reader r ) { return Nes_Emu::load_state( r ); } - virtual long read_samples( short* out, long count ); -private: - typedef Nes_Emu base; - - // snapshots - Nes_State* cache; - int cache_size; - int cache_period_; - Nes_Film* film_; - void clear_cache(); - int cache_index( frame_count_t ) const; - Nes_State_ const* nearest_snapshot( frame_count_t ) const; - - // film - frame_count_t tell_; - bool resync_enabled; - bool ready_to_resync; - void emulate_frame_( Nes_Film::joypad_t ); - void replay_frame_( Nes_Film::joypad_t ); - int replay_frame(); - void seek_( frame_count_t ); - frame_count_t advancing_frame(); - void loading_state( Nes_State const& ); - - // reverse handling - enum { frames_size = frame_rate }; - struct saved_frame_t : Nes_Emu::frame_t { - enum { max_samples = 2048 }; - blip_sample_t samples [max_samples]; - }; - saved_frame_t* frames; - bool reverse_enabled; - bool reverse_allowed; - void reverse_fill( frame_count_t ); - int reverse_index( frame_count_t ) const; // index for given frame -}; - -inline frame_count_t Nes_Recorder::tell() const { return film_->constrain( tell_ ); } - -inline void Nes_Recorder::film_changed() { set_film( &film(), film().constrain( tell() ) ); } - -inline void Nes_Recorder::disable_reverse( int new_cache_period ) -{ - reverse_allowed = false; - buffer_height_ = Nes_Ppu::buffer_height; - cache_period_ = new_cache_period * frame_rate; - cache_size = 2 * 60 * frame_rate / cache_period_ + 7; // +7 reduces contention -} - -#endif - diff --git a/quicknes/nes_emu/Nes_Rewinder.cpp b/quicknes/nes_emu/Nes_Rewinder.cpp deleted file mode 100644 index 039a270f41..0000000000 --- a/quicknes/nes_emu/Nes_Rewinder.cpp +++ /dev/null @@ -1,324 +0,0 @@ - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/ - -#include "Nes_Rewinder.h" - -#include - -/* Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -// to do: fade out at transitions between forward and reverse - -#include BLARGG_SOURCE_BEGIN - -// If true, always keep recent frame images in graphics buffer. Reduces overall -// performance by about 33% on my machine, due to the frame buffer not staying in the cache. -bool const quick_reverse = false; - -Nes_Rewinder::Nes_Rewinder( frame_count_t snapshot_period ) : recorder( snapshot_period ) -{ - pixels = NULL; - frames = NULL; - reverse_enabled = false; -} - -Nes_Rewinder::~Nes_Rewinder() -{ - delete [] frames; -} - -blargg_err_t Nes_Rewinder::init() -{ - if ( !frames ) - { - BLARGG_RETURN_ERR( recorder::init() ); - - frames = BLARGG_NEW frame_t [frames_size]; - BLARGG_CHECK_ALLOC( frames ); - } - - return blargg_success; -} - -blargg_err_t Nes_Rewinder::load_ines_rom( Data_Reader& in, Data_Reader* ips ) -{ - if ( !frames ) - BLARGG_RETURN_ERR( init() ); - - return recorder::load_ines_rom( in, ips ); -} - -long Nes_Rewinder::samples_avail() const -{ - return frames [current_frame].sample_count; -} - -inline void copy_reverse( const blip_sample_t* in, int count, blip_sample_t* out, int step ) -{ - in += count; - while ( count > 0 ) - { - count -= step; - in -= step; - *out = *in; - out += step; - } -} - -long Nes_Rewinder::read_samples( short* out, long out_size ) -{ - int count = samples_avail(); - if ( count ) - { - if ( count > out_size ) - { - count = out_size; - assert( false ); // has no provision for reading partial buffer - } - - if ( !reverse_enabled ) - { - memcpy( out, frames [current_frame].samples, count * sizeof *out ); - } - else - { - int step = samples_per_frame(); - for ( int i = step; i-- > 0; ) - copy_reverse( frames [current_frame].samples + i, count, out + i, step ); - } - - if ( fade_sound_in ) - { - fade_sound_in = false; - fade_samples_( out, count, 1 ); - } - - if ( frames [current_frame].fade_out ) - { - fade_sound_in = true; - fade_samples_( out, count, -1 ); - } - } - return count; -} - -void Nes_Rewinder::seek( frame_count_t time ) -{ - if ( time != tell() ) - { - clear_reverse(); - recorder::seek_( time ); - } -} - -inline void Nes_Rewinder::set_output( int index ) -{ - recorder::set_pixels( pixels + index * frame_height * row_bytes, row_bytes ); -} - -void Nes_Rewinder::frame_rendered( int index, bool using_buffer ) -{ - frame_t& frame = frames [index]; - if ( recorder::frames_emulated() > 0 ) - { - frame.palette_size = recorder::palette_size(); - for ( int i = frame.palette_size; i--; ) - frame.palette [i] = recorder::palette_entry( i ); - frame.sample_count = recorder::read_samples( frame.samples, frame.max_samples ); - } - else if ( pixels && using_buffer ) - { - int old_index = (index + frames_size - 1) % frames_size; - - memcpy( &frame, &frames [old_index], sizeof frame ); - - // to do: handle case where row_bytes is a lot greater than buffer_width - memcpy( pixels + index * frame_height * row_bytes, - pixels + old_index * frame_height * row_bytes, - row_bytes * frame_height ); - } - frame.fade_out = false; -} - -blargg_err_t Nes_Rewinder::next_frame( int joypad, int joypad2 ) -{ - if ( reverse_enabled ) - { - if ( !get_film().empty() ) // if empty then we can't seek - recorder::seek_( reversed_time ); - clear_reverse(); - } - - current_frame = 0; - if ( quick_reverse ) - { - current_frame = recorder::tell() % frames_size; - if ( buffer_scrambled ) - buffer_scrambled--; - } - set_output( current_frame ); - - BLARGG_RETURN_ERR( recorder::next_frame( joypad, joypad2 ) ); - frame_rendered( current_frame, quick_reverse ); - - return blargg_success; -} - -frame_count_t Nes_Rewinder::tell() const -{ - return reverse_enabled ? reversed_time : recorder::tell(); -} - -void Nes_Rewinder::clear_cache() -{ - recorder::clear_cache(); - clear_reverse(); -} - -void Nes_Rewinder::clear_reverse() -{ - buffer_scrambled = frames_size; - reverse_enabled = false; - reverse_unmirrored = 0; - reverse_pivot = 0; - reversed_time = 0; -} - -void Nes_Rewinder::play_frame_( int index ) -{ - if ( negative_seek > 0 ) - { - negative_seek--; - } - else - { - set_output( index ); - recorder::play_frame_(); - frame_rendered( index, true ); - } -} - -void Nes_Rewinder::seek_clamped( frame_count_t time ) -{ - negative_seek = movie_begin() - time; - if ( negative_seek > 0 ) - time = movie_begin(); - recorder::seek_( time ); -} - -void Nes_Rewinder::enter_reverse() -{ - reversed_time = recorder::tell() - 1; - - reverse_pivot = reversed_time % frames_size; - frame_count_t first_frame = reversed_time - reverse_pivot; - if ( buffer_scrambled ) - { - // buffer hasn't been filled with a clean second of frames since last seek - - dprintf( "Refilling reverse buffer, pivot: %d\n", (int) reverse_pivot ); - - // fill beginning - seek_clamped( first_frame ); - for ( int i = 0; i <= reverse_pivot; i++ ) - play_frame_( i ); - frames [0].fade_out = true; - - // fill end - seek_clamped( first_frame - frames_size + reverse_pivot + 1 ); - for ( int i = reverse_pivot + 1; i < frames_size; i++ ) - play_frame_( i ); - } - - if ( reverse_pivot + 1 < frames_size ) - frames [reverse_pivot + 1].fade_out = true; - - reverse_unmirrored = 2; // unmirrored for first two passes, then alternating - reverse_pivot = -reverse_pivot; // don't pivot yet - - seek_clamped( first_frame - frames_size ); - - // Buffer is now filled. Current second is at beginning and previous at end, - // and in this example reversed_time is 24 and reverse_pivot is 4: - // 20 21 22 23 24 25 16 17 18 19 - - // As fragment of current second is played backwards, it will be replaced with - // beginning of previous second: - - // <--------------- - // 20 21 22 23 24 25 16 17 18 19 frame 25 - // 20 21 22 23 24 10 16 17 18 19 frame 24 - // 20 21 22 23 11 10 16 17 18 19 frame 23 - // 20 21 22 12 11 10 16 17 18 19 frame 22 - // 20 21 13 12 11 10 16 17 18 19 frame 21 - // 20 14 13 12 11 10 16 17 18 19 frame 20 - // 15 14 13 12 11 10 16 17 18 19 frame 19 - // Then filling will keep replacing buffer contents in a converging fashion: - // <--------- - // 15 14 13 12 11 10 16 17 18 0 frame 19 - // 15 14 13 12 11 10 16 17 1 0 frame 18 - // 15 14 13 12 11 10 16 2 1 0 frame 17 - // 15 14 13 12 11 10 3 2 1 0 frame 16 - // --------------> - // 4 14 13 12 11 10 3 2 1 0 frame 15 - // 4 5 13 12 11 10 3 2 1 0 frame 14 - // 4 5 6 12 11 10 3 2 1 0 frame 13 - // 4 5 6 7 11 10 3 2 1 0 frame 12 - // 4 5 6 7 8 10 3 2 1 0 frame 11 - // 4 5 6 7 8 9 3 2 1 0 frame 10 - // <--------------- - // etc. -} - -void Nes_Rewinder::prev_frame() -{ - if ( tell() <= movie_begin() ) - { - require( false ); // tried to go before beginning of movie - return; - } - - if ( !reverse_enabled ) - { - reverse_enabled = true; - enter_reverse(); - } - else - { - play_frame_( current_frame ); - - reversed_time--; - if ( reversed_time % frames_size == frames_size - 1 ) - { - if ( reverse_pivot < 0 ) - reverse_pivot = -reverse_pivot; - - if ( --reverse_unmirrored < 0 ) - reverse_unmirrored = 1; - - seek_clamped( reversed_time - frames_size * 2 + 1 ); - } - } - - // determine index of frame in buffer - int raw_index = reversed_time % frames_size; - int index = raw_index; - if ( !reverse_unmirrored ) - index = frames_size - 1 - index; - if ( index <= reverse_pivot ) - index = reverse_pivot - index; - current_frame = index; - - if ( raw_index == 0 ) // previous frame will be from previous restoration - frames [index].fade_out = true; -} - diff --git a/quicknes/nes_emu/Nes_Rewinder.h b/quicknes/nes_emu/Nes_Rewinder.h deleted file mode 100644 index 5617349875..0000000000 --- a/quicknes/nes_emu/Nes_Rewinder.h +++ /dev/null @@ -1,95 +0,0 @@ - -// NES recorder with smooth rewind (backwards playback) - -// Nes_Emu 0.5.6. Copyright (C) 2004-2005 Shay Green. GNU LGPL license. - -#ifndef NES_REWINDER_H -#define NES_REWINDER_H - -#include "Nes_Recorder.h" - -class Nes_Rewinder : public Nes_Recorder { - typedef Nes_Recorder recorder; - enum { frames_size = frames_per_second }; -public: - explicit Nes_Rewinder( frame_count_t snapshot_period = 0 ); - ~Nes_Rewinder(); - - // Nes_Rewinder adds a single feature to Nes_Recorder: the ability to generate - // consecutive previous frames with similar performance to normal forward - // generation. - - // Emulate frame *ending* at current timestamp. On exit, timestamp = timestamp - 1. - void prev_frame(); - - // Recently-generated frames are stored in a caller-supplied graphics buffer, - // which is many times taller than a single frame image. - enum { frame_height = Nes_Recorder::buffer_height }; - enum { buffer_height = frame_height * frames_size }; - - // Y coordinate of image for current frame in graphics buffer - int get_buffer_y(); - - // Documented in Nes_Emu.h and Nes_Recorder.h - blargg_err_t load_ines_rom( Data_Reader&, Data_Reader* = NULL ); - void set_pixels( void*, long bytes_per_row ); - blargg_err_t next_frame( int joypad, int joypad2 = 0 ); - frame_count_t tell() const; - void seek( frame_count_t ); - long samples_avail() const; - long read_samples( short* out, long max_samples ); - int palette_size() const { return frames [current_frame].palette_size; } - int palette_entry( int i ) const { return frames [current_frame].palette [i]; } - blargg_err_t init(); - - // End of public interface -private: - - BOOST::uint8_t* pixels; - long row_bytes; - - // frame cache - struct frame_t - { - int sample_count; - bool fade_out; - int palette_size; - byte palette [max_palette_size]; - enum { max_samples = 2048 }; - blip_sample_t samples [max_samples]; - }; - frame_t* frames; - int current_frame; - bool fade_sound_in; - void set_output( int index ); - void frame_rendered( int index, bool using_buffer ); - void clear_cache(); // Nes_Recorder override - - // clamped seek - int negative_seek; // if positive, number of frames to ignore before playing - void play_frame_( int index ); - void seek_clamped( frame_count_t ); // allows timestamp to be before beginning - - // reversed frame mapping - frame_count_t reversed_time;// current time is different than emulator time in reverse - int buffer_scrambled; // number of frames remaining before buffer isn't scrambled - bool reverse_enabled; - int reverse_unmirrored; // number of buffers until buffer order is mirrored - int reverse_pivot; // pivot point in buffer - void clear_reverse(); - void enter_reverse(); -}; - -inline int Nes_Rewinder::get_buffer_y() -{ - return current_frame * frame_height + image_top; -} - -inline void Nes_Rewinder::set_pixels( void* p, long rb ) -{ - pixels = (BOOST::uint8_t*) p; - row_bytes = rb; -} - -#endif - diff --git a/quicknes/nes_emu/Nes_Rom.cpp b/quicknes/nes_emu/Nes_Rom.cpp deleted file mode 100644 index d1e74b04e5..0000000000 --- a/quicknes/nes_emu/Nes_Rom.cpp +++ /dev/null @@ -1,216 +0,0 @@ - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/ - -#include "Nes_Rom.h" - -#include -#include - -/* Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -Nes_Rom::Nes_Rom() -{ - prg_ = NULL; - chr_ = NULL; - reset(); -} - -Nes_Rom::~Nes_Rom() -{ - reset(); -} - -void Nes_Rom::reset() -{ - free( prg_ ); - prg_ = NULL; - - free( chr_ ); - chr_ = NULL; - - prg_size_ = 0; - chr_size_ = 0; - mapper = 0; -} - -long Nes_Rom::round_to_bank_size( long n ) -{ - n += bank_size - 1; - return n - n % bank_size; -} - -blargg_err_t Nes_Rom::resize_prg( long size ) -{ - if ( size != prg_size_ ) - { - // extra byte allows CPU to always read operand of instruction, which - // might go past end of ROM - void* p = realloc( prg_, round_to_bank_size( size ) + 1 ); - BLARGG_CHECK_ALLOC( p || !size ); - prg_ = (byte*) p; - prg_size_ = size; - } - return blargg_success; -} - -blargg_err_t Nes_Rom::resize_chr( long size ) -{ - if ( size != chr_size_ ) - { - void* p = realloc( chr_, round_to_bank_size( size ) ); - BLARGG_CHECK_ALLOC( p || !size ); - chr_ = (byte*) p; - chr_size_ = size; - } - return blargg_success; -} - -// iNES reading - -struct ines_header_t { - BOOST::uint8_t signature [4]; - BOOST::uint8_t prg_count; // number of 16K PRG banks - BOOST::uint8_t chr_count; // number of 8K CHR banks - BOOST::uint8_t flags; // MMMM FTBV Mapper low, Four-screen, Trainer, Battery, V mirror - BOOST::uint8_t flags2; // MMMM --XX Mapper high 4 bits - BOOST::uint8_t zero [8]; // if zero [7] is non-zero, treat flags2 as zero -}; -BOOST_STATIC_ASSERT( sizeof (ines_header_t) == 16 ); - -blargg_err_t Nes_Rom::load_ines_rom( Data_Reader& in ) -{ - ines_header_t h; - BLARGG_RETURN_ERR( in.read( &h, sizeof h ) ); - - if ( 0 != memcmp( h.signature, "NES\x1A", 4 ) ) - return "Not a iNES ROM file"; - - if ( h.zero [7] ) // handle header defaced by a fucking idiot's handle - h.flags2 = 0; - - set_mapper( h.flags, h.flags2 ); - - if ( h.flags & 0x04 ) // skip trainer - BLARGG_RETURN_ERR( in.skip( 512 ) ); - - BLARGG_RETURN_ERR( resize_prg( h.prg_count * 16 * 1024L ) ); - BLARGG_RETURN_ERR( resize_chr( h.chr_count * 8 * 1024L ) ); - - BLARGG_RETURN_ERR( in.read( prg(), prg_size() ) ); - BLARGG_RETURN_ERR( in.read( chr(), chr_size() ) ); - - return blargg_success; -} - -// IPS patching - -// IPS patch file format (integers are big-endian): -// 5 "PATCH" -// n blocks -// -// normal block: -// 3 offset -// 2 size -// n data -// -// repeated byte block: -// 3 offset -// 2 0 -// 2 size -// 1 fill value -// -// end block (optional): -// 3 "EOF" -// -// A block can append data to the file by specifying an offset at the end of -// the current file data. - -typedef BOOST::uint8_t byte; -static blargg_err_t apply_ips_patch( Data_Reader& patch, byte** file, long* file_size ) -{ - byte signature [5]; - BLARGG_RETURN_ERR( patch.read( signature, sizeof signature ) ); - if ( memcmp( signature, "PATCH", sizeof signature ) ) - return "Not an IPS patch file"; - - while ( patch.remain() ) - { - // read offset - byte buf [6]; - BLARGG_RETURN_ERR( patch.read( buf, 3 ) ); - long offset = buf [0] * 0x10000 + buf [1] * 0x100 + buf [2]; - if ( offset == 'EOF' ) - break; - - // read size - BLARGG_RETURN_ERR( patch.read( buf, 2 ) ); - long size = buf [0] * 0x100 + buf [1]; - - // size = 0 signals a run of identical bytes - int fill = -1; - if ( size == 0 ) - { - BLARGG_RETURN_ERR( patch.read( buf, 3 ) ); - size = buf [0] * 0x100 + buf [1]; - fill = buf [2]; - } - - // expand file if new data is at exact end of file - if ( offset == *file_size ) - { - *file_size = offset + size; - void* p = realloc( *file, *file_size ); - BLARGG_CHECK_ALLOC( p ); - *file = (byte*) p; - } - - //dprintf( "Patch offset: 0x%04X, size: 0x%04X\n", (int) offset, (int) size ); - - if ( offset < 0 || *file_size < offset + size ) - return "IPS tried to patch past end of file"; - - // read/fill data - if ( fill < 0 ) - BLARGG_RETURN_ERR( patch.read( *file + offset, size ) ); - else - memset( *file + offset, fill, size ); - } - - return blargg_success; -} - -blargg_err_t Nes_Rom::load_patched_ines_rom( Data_Reader& in, Data_Reader& patch ) -{ - // read file into memory - long size = in.remain(); - byte* ines = (byte*) malloc( size ); - BLARGG_CHECK_ALLOC( ines ); - const char* err = in.read( ines, size ); - - // apply patch - if ( !err ) - err = apply_ips_patch( patch, &ines, &size ); - - // load patched file - if ( !err ) - { - Mem_File_Reader patched( ines, size ); - err = load_ines_rom( patched ); - } - - free( ines ); - - return err; -} - diff --git a/quicknes/nes_emu/Nes_Rom.h b/quicknes/nes_emu/Nes_Rom.h deleted file mode 100644 index 814bbfeccf..0000000000 --- a/quicknes/nes_emu/Nes_Rom.h +++ /dev/null @@ -1,86 +0,0 @@ - -// NES ROM data loaded into memory - -// Nes_Emu 0.5.6. Copyright (C) 2004-2005 Shay Green. GNU LGPL license. - -#ifndef NES_ROM_H -#define NES_ROM_H - -#include "blargg_common.h" -#include "abstract_file.h" - -class Nes_Rom { - typedef BOOST::uint8_t byte; -public: - Nes_Rom(); - ~Nes_Rom(); - - // Load iNES ROM file - blargg_err_t load_ines_rom( Data_Reader& ); - - // Load iNES ROM file and apply IPS patch - blargg_err_t load_patched_ines_rom( Data_Reader&, Data_Reader& ips_patch ); - - // to do: support UNIF? - - // True if a ROM is currently loaded - bool loaded() const { return prg_ != NULL; } - - // Free any loaded ROM data - void reset(); - - // True if ROM claims to have battery-backed memory - bool has_battery_ram() const; - - // Size of PRG data - long prg_size() const { return prg_size_; } - - // Size of CHR data - long chr_size() const { return chr_size_; } - - // Change size of PRG (code) data - blargg_err_t resize_prg( long ); - - // Change size of CHR (graphics) data - blargg_err_t resize_chr( long ); - - // Set mapper and information bytes. LSB and MSB are the standard iNES header - // bytes at offsets 6 and 7. - void set_mapper( int mapper_lsb, int mapper_msb ); - - // Initial mirroring setup - int mirroring() const { return mapper & 0x09; } - - // iNES mapper code - int mapper_code() const; - - // Pointer to beginning of PRG data - byte * prg() { return prg_; } - byte const* prg() const { return prg_; } - - // Pointer to beginning of CHR data - byte * chr() { return chr_; } - byte const* chr() const { return chr_; } - - // End of public interface -private: - enum { bank_size = 8 * 1024L }; // bank sizes must be a multiple of this - byte* prg_; - byte* chr_; - long prg_size_; - long chr_size_; - unsigned mapper; - long round_to_bank_size( long n ); -}; - -inline bool Nes_Rom::has_battery_ram() const { return mapper & 0x02; } - -inline void Nes_Rom::set_mapper( int mapper_lsb, int mapper_msb ) -{ - mapper = mapper_msb * 0x100 + mapper_lsb; -} - -inline int Nes_Rom::mapper_code() const { return ((mapper >> 8) & 0xf0) | ((mapper >> 4) & 0x0f); } - -#endif - diff --git a/quicknes/nes_emu/Nes_Snapshot.cpp b/quicknes/nes_emu/Nes_Snapshot.cpp deleted file mode 100644 index d27c821b8d..0000000000 --- a/quicknes/nes_emu/Nes_Snapshot.cpp +++ /dev/null @@ -1,329 +0,0 @@ - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/ - -#include "Nes_Snapshot.h" - -#include -#include - -#include "blargg_endian.h" -#include "Nes_Emu.h" -#include "Nes_Mapper.h" - -/* Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -typedef BOOST::uint8_t byte; - -Nes_Snapshot_Array::Nes_Snapshot_Array() -{ - data = NULL; - size_ = 0; -} - -Nes_Snapshot_Array::~Nes_Snapshot_Array() -{ - free( data ); -} - -blargg_err_t Nes_Snapshot_Array::resize( int new_size ) -{ - void* new_mem = realloc( data, new_size * sizeof (Nes_Snapshot) ); - BLARGG_CHECK_ALLOC( !new_size || new_mem ); - data = (Nes_Snapshot*) new_mem; - - int old_size = size_; - size_ = new_size; - for ( int i = old_size; i < new_size; i++ ) - (*this) [i].clear(); - - return blargg_success; -} - -void Nes_Snapshot::clear() -{ - memset( &nes, 0, sizeof nes ); - nes.frame_count = invalid_frame_count; - - nes_valid = false; - cpu_valid = false; - joypad_valid = false; - apu_valid = false; - ppu_valid = false; - mapper_valid = false; - ram_valid = false; - sram_size = 0; - spr_ram_valid = false; - nametable_size = 0; - chr_size = 0; -} - -// write - -blargg_err_t Nes_Snapshot_Writer::end( Nes_Emu const& emu ) -{ - Nes_Snapshot_Array snapshots; - BLARGG_RETURN_ERR( snapshots.resize( 1 ) ); - emu.save_snapshot( &snapshots [0] ); - return end( snapshots [0] ); -} - -blargg_err_t Nes_Snapshot_Writer::end( Nes_Snapshot const& ss ) -{ - BLARGG_RETURN_ERR( ss.write_blocks( *this ) ); - return Nes_File_Writer::end(); -} - -blargg_err_t Nes_Snapshot::write( Data_Writer& out ) const -{ - Nes_Snapshot_Writer writer; - BLARGG_RETURN_ERR( writer.begin( &out ) ); - return writer.end( *this ); -} - -blargg_err_t Nes_Snapshot::write_blocks( Nes_File_Writer& out ) const -{ - if ( nes_valid ) - { - nes_state_t s = nes; - s.pal = false; - s.timestamp = nes.timestamp * 15; - BLARGG_RETURN_ERR( write_nes_state( out, s ) ); - } - - if ( cpu_valid ) - { - cpu_state_t s; - memset( &s, 0, sizeof s ); - s.pc = cpu.pc; - s.s = cpu.sp; - s.a = cpu.a; - s.x = cpu.x; - s.y = cpu.y; - s.p = cpu.status; - BLARGG_RETURN_ERR( write_nes_state( out, s ) ); - } - - if ( ppu_valid ) - { - ppu_state_t s = ppu; - BLARGG_RETURN_ERR( write_nes_state( out, s ) ); - } - - if ( apu_valid ) - { - apu_snapshot_t s = apu; - BLARGG_RETURN_ERR( write_nes_state( out, s ) ); - } - - if ( joypad_valid ) - { - joypad_state_t s = joypad; - BLARGG_RETURN_ERR( write_nes_state( out, s ) ); - } - - if ( mapper_valid ) - BLARGG_RETURN_ERR( out.write_block( 'MAPR', mapper.data, mapper.size ) ); - - if ( ram_valid ) - BLARGG_RETURN_ERR( out.write_block( 'LRAM', ram, sizeof ram ) ); - - if ( spr_ram_valid ) - BLARGG_RETURN_ERR( out.write_block( 'SPRT', spr_ram, sizeof spr_ram ) ); - - if ( nametable_size ) - BLARGG_RETURN_ERR( out.write_block( 'NTAB', nametable, nametable_size ) ); - - if ( chr_size ) - BLARGG_RETURN_ERR( out.write_block( 'CHRR', chr, chr_size ) ); - - if ( sram_size ) - BLARGG_RETURN_ERR( out.write_block( 'SRAM', sram, sram_size ) ); - - return blargg_success; -} - -// read - -Nes_Snapshot_Reader::Nes_Snapshot_Reader() -{ - snapshot_ = NULL; -} - -Nes_Snapshot_Reader::~Nes_Snapshot_Reader() -{ -} - -blargg_err_t Nes_Snapshot_Reader::begin( Data_Reader* dr, Nes_Snapshot* out ) -{ - snapshot_ = out; - if ( !out ) - { - BLARGG_RETURN_ERR( snapshots.resize( 1 ) ); - snapshot_ = &snapshots [0]; - } - - BLARGG_RETURN_ERR( Nes_File_Reader::begin( dr ) ); - if ( block_tag() != snapshot_file_tag ) - return "Not a snapshot file"; - return blargg_success; -} - -blargg_err_t Nes_Snapshot::read( Data_Reader& in ) -{ - Nes_Snapshot_Reader reader; - BLARGG_RETURN_ERR( reader.begin( &in, this ) ); - while ( !reader.done() ) - BLARGG_RETURN_ERR( reader.next_block() ); - - return blargg_success; -} - -blargg_err_t Nes_Snapshot_Reader::next_block() -{ - if ( depth() != 0 ) - return Nes_File_Reader::next_block(); - return snapshot_->read_blocks( *this ); -} - -void Nes_Snapshot::set_nes_state( nes_state_t const& s ) -{ - nes = s; - nes.timestamp /= 15; - nes_valid = true; -} - -blargg_err_t Nes_Snapshot::read_blocks( Nes_File_Reader& in ) -{ - while ( true ) - { - BLARGG_RETURN_ERR( in.next_block() ); - switch ( in.block_tag() ) - { - case nes.tag: - memset( &nes, 0, sizeof nes ); - BLARGG_RETURN_ERR( read_nes_state( in, &nes ) ); - set_nes_state( nes ); - break; - - case cpu_state_t::tag: { - cpu_state_t s; - memset( &s, 0, sizeof s ); - BLARGG_RETURN_ERR( read_nes_state( in, &s ) ); - cpu.pc = s.pc; - cpu.sp = s.s; - cpu.a = s.a; - cpu.x = s.x; - cpu.y = s.y; - cpu.status = s.p; - cpu_valid = true; - break; - } - - case ppu.tag: - memset( &ppu, 0, sizeof ppu ); - BLARGG_RETURN_ERR( read_nes_state( in, &ppu ) ); - ppu_valid = true; - break; - - case apu.tag: - memset( &apu, 0, sizeof apu ); - BLARGG_RETURN_ERR( read_nes_state( in, &apu ) ); - apu_valid = true; - break; - - case joypad.tag: - memset( &joypad, 0, sizeof joypad ); - BLARGG_RETURN_ERR( read_nes_state( in, &joypad ) ); - joypad_valid = true; - break; - - case 'MAPR': - mapper.size = in.remain(); - BLARGG_RETURN_ERR( in.read_block_data( mapper.data, sizeof mapper.data ) ); - mapper_valid = true; - break; - - case 'SPRT': - spr_ram_valid = true; - BLARGG_RETURN_ERR( in.read_block_data( spr_ram, sizeof spr_ram ) ); - break; - - case 'NTAB': - nametable_size = in.remain(); - BLARGG_RETURN_ERR( in.read_block_data( nametable, sizeof nametable ) ); - break; - - case 'LRAM': - ram_valid = true; - BLARGG_RETURN_ERR( in.read_block_data( ram, sizeof ram ) ); - break; - - case 'CHRR': - chr_size = in.remain(); - BLARGG_RETURN_ERR( in.read_block_data( chr, sizeof chr ) ); - break; - - case 'SRAM': - sram_size = in.remain(); - BLARGG_RETURN_ERR( in.read_block_data( sram, sizeof sram ) ); - break; - - default: - return blargg_success; - } - } -} - -// read_sta_file - -struct sta_regs_t { - byte pc [2]; - byte a; - byte p; - byte x; - byte y; - byte s; -}; -BOOST_STATIC_ASSERT( sizeof (sta_regs_t) == 7 ); - -blargg_err_t Nes_Snapshot::read_sta_file( Data_Reader& in ) -{ - sram_size = 0x2000; - BLARGG_RETURN_ERR( in.read( sram, sram_size ) ); - - ram_valid = true; - BLARGG_RETURN_ERR( in.read( ram, 0x800 ) ); - - sta_regs_t r; - BLARGG_RETURN_ERR( in.read( &r, sizeof r ) ); - this->cpu.pc = r.pc [1] * 0x100 + r.pc [0]; - this->cpu.a = r.a; - this->cpu.status = r.p; - this->cpu.x = r.x; - this->cpu.y = r.y; - this->cpu.sp = r.s; - cpu_valid = true; - - BLARGG_RETURN_ERR( in.read( spr_ram, 0x100 ) ); - spr_ram_valid = true; - - chr_size = 0x2000; - BLARGG_RETURN_ERR( in.read( chr, chr_size ) ); - - nametable_size = 0x1000; - BLARGG_RETURN_ERR( in.read( nametable, nametable_size ) ); - - return blargg_success; -} - diff --git a/quicknes/nes_emu/Nes_Snapshot.h b/quicknes/nes_emu/Nes_Snapshot.h deleted file mode 100644 index 7abb1411f5..0000000000 --- a/quicknes/nes_emu/Nes_Snapshot.h +++ /dev/null @@ -1,165 +0,0 @@ - -// NES snapshot for saving and restoring emulator state - -// Nes_Emu 0.5.6. Copyright (C) 2004-2005 Shay Green. GNU LGPL license. - -#ifndef NES_SNAPSHOT_H -#define NES_SNAPSHOT_H - -#include "Nes_File.h" -#include "Nes_Cpu.h" -class Nes_Emu; - -typedef long frame_count_t; -frame_count_t const invalid_frame_count = LONG_MAX / 2; // a large positive value - -class Nes_Snapshot; - -class Nes_Snapshot_Array { -public: - Nes_Snapshot_Array(); - ~Nes_Snapshot_Array(); - - // Change size of array - blargg_err_t resize( int new_size ); - - // Current size of array - int size() const; - - Nes_Snapshot& operator [] ( int ); - Nes_Snapshot const& operator [] ( int ) const; - -private: - Nes_Snapshot* data; - int size_; -}; - -class Nes_Snapshot_Writer : public Nes_File_Writer { -public: - // See Nes_File.h - blargg_err_t begin( Data_Writer* ); - - // Write snapshot of current emulator state and finish writing file - blargg_err_t end( Nes_Emu const& ); - - // Write snapshot and finish writing file - blargg_err_t end( Nes_Snapshot const& ); -}; - -class Nes_Snapshot_Reader : public Nes_File_Reader { -public: - Nes_Snapshot_Reader(); - ~Nes_Snapshot_Reader(); - - // Optionally read snapshot into designated location instead of - // internal snapshot. - blargg_err_t begin( Data_Reader*, Nes_Snapshot* out = NULL ); - - // See Nes_File.h - blargg_err_t next_block(); - - // Snapshot valid after all blocks have been read - Nes_Snapshot const& snapshot() const; -private: - Nes_Snapshot_Array snapshots; - Nes_Snapshot* snapshot_; -}; - -class Nes_Snapshot { - Nes_Snapshot(); // use Nes_Snapshot_Array - Nes_Snapshot( Nes_Snapshot const& ); -public: - - // Invalidate all state - void clear(); - - // Change timestamp - void set_timestamp( frame_count_t ); - - // Timestamp snapshot was taken at - frame_count_t timestamp() const; - - // Read Nesticle .sta file. Currently only reads basic fields. - blargg_err_t read_sta_file( Data_Reader& ); - - // Write snapshot to file - blargg_err_t write( Data_Writer& ) const; - - // Read snapshot from file - blargg_err_t read( Data_Reader& ); - - // End of general interface -public: - blargg_err_t write_blocks( Nes_File_Writer& ) const; - void set_nes_state( nes_state_t const& ); - blargg_err_t read_blocks( Nes_File_Reader& ); -private: - - nes_state_t nes; - bool nes_valid; - - Nes_Cpu::registers_t cpu; - bool cpu_valid; - - joypad_state_t joypad; - bool joypad_valid; - - apu_snapshot_t apu; - bool apu_valid; - - ppu_state_t ppu; - bool ppu_valid; - - mapper_state_t mapper; - bool mapper_valid; - - BOOST::uint8_t ram [0x800]; - bool ram_valid; - - BOOST::uint8_t sram [0x2000]; - int sram_size; - - BOOST::uint8_t spr_ram [0x100]; - bool spr_ram_valid; - - BOOST::uint8_t nametable [0x1000]; - int nametable_size; - - BOOST::uint8_t chr [0x2000]; - int chr_size; - - friend class Nes_Emu; - friend class Nes_Ppu_Impl; -}; - -inline Nes_Snapshot const& Nes_Snapshot_Reader::snapshot() const -{ - assert( depth() == 0 && block_type() == group_end ); - return *snapshot_; -} - -inline blargg_err_t Nes_Snapshot_Writer::begin( Data_Writer* dw ) -{ - return Nes_File_Writer::begin( dw, snapshot_file_tag ); -} - -inline void Nes_Snapshot::set_timestamp( frame_count_t t ) { nes.frame_count = t; } - -inline frame_count_t Nes_Snapshot::timestamp() const { return nes.frame_count; } - -inline int Nes_Snapshot_Array::size() const { return size_; } - -inline Nes_Snapshot& Nes_Snapshot_Array::operator [] ( int i ) -{ - assert( (unsigned) i < size_ ); - return data [i]; -} - -inline Nes_Snapshot const& Nes_Snapshot_Array::operator [] ( int i ) const -{ - assert( (unsigned) i < size_ ); - return data [i]; -} - -#endif - diff --git a/quicknes/nes_emu/Nes_Vrc6.cpp b/quicknes/nes_emu/Nes_Vrc6.cpp deleted file mode 100644 index b2e35cd4a2..0000000000 --- a/quicknes/nes_emu/Nes_Vrc6.cpp +++ /dev/null @@ -1,231 +0,0 @@ - -// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/ - -#include "Nes_Vrc6.h" - -/* Copyright (C) 2003-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -Nes_Vrc6::Nes_Vrc6() -{ - output( NULL ); - volume( 1.0 ); - reset(); -} - -Nes_Vrc6::~Nes_Vrc6() -{ -} - -void Nes_Vrc6::reset() -{ - last_time = 0; - for ( int i = 0; i < osc_count; i++ ) - { - Vrc6_Osc& osc = oscs [i]; - for ( int j = 0; j < reg_count; j++ ) - osc.regs [j] = 0; - osc.delay = 0; - osc.last_amp = 0; - osc.phase = 1; - osc.amp = 0; - } -} - -void Nes_Vrc6::volume( double v ) -{ - double const factor = 0.0967 * 2; - saw_synth.volume_unit( factor / 31 * v ); - square_synth.volume_unit( factor * 0.5 / 15 * v ); -} - -void Nes_Vrc6::treble_eq( blip_eq_t const& eq ) -{ - saw_synth.treble_eq( eq ); - square_synth.treble_eq( eq ); -} - -void Nes_Vrc6::output( Blip_Buffer* buf ) -{ - for ( int i = 0; i < osc_count; i++ ) - osc_output( i, buf ); -} - -void Nes_Vrc6::run_until( nes_time_t time ) -{ - require( time >= last_time ); - run_square( oscs [0], time ); - run_square( oscs [1], time ); - run_saw( time ); - last_time = time; -} - -void Nes_Vrc6::write_osc( nes_time_t time, int osc_index, int reg, int data ) -{ - require( (unsigned) osc_index < osc_count ); - require( (unsigned) reg < reg_count ); - - run_until( time ); - oscs [osc_index].regs [reg] = data; -} - -void Nes_Vrc6::end_frame( nes_time_t time ) -{ - if ( time > last_time ) - run_until( time ); - last_time -= time; - assert( last_time >= 0 ); -} - -void Nes_Vrc6::save_snapshot( vrc6_snapshot_t* out ) const -{ - out->saw_amp = oscs [2].amp; - for ( int i = 0; i < osc_count; i++ ) - { - Vrc6_Osc const& osc = oscs [i]; - for ( int r = 0; r < reg_count; r++ ) - out->regs [i] [r] = osc.regs [r]; - - out->delays [i] = osc.delay; - out->phases [i] = osc.phase; - } -} - -void Nes_Vrc6::load_snapshot( vrc6_snapshot_t const& in ) -{ - reset(); - oscs [2].amp = in.saw_amp; - for ( int i = 0; i < osc_count; i++ ) - { - Vrc6_Osc& osc = oscs [i]; - for ( int r = 0; r < reg_count; r++ ) - osc.regs [r] = in.regs [i] [r]; - - osc.delay = in.delays [i]; - osc.phase = in.phases [i]; - } - if ( !oscs [2].phase ) - oscs [2].phase = 1; -} - -#include BLARGG_ENABLE_OPTIMIZER - -void Nes_Vrc6::run_square( Vrc6_Osc& osc, nes_time_t end_time ) -{ - Blip_Buffer* output = osc.output; - if ( !output ) - return; - - int volume = osc.regs [0] & 15; - if ( !(osc.regs [2] & 0x80) ) - volume = 0; - - int gate = osc.regs [0] & 0x80; - int duty = ((osc.regs [0] >> 4) & 7) + 1; - int delta = ((gate || osc.phase < duty) ? volume : 0) - osc.last_amp; - nes_time_t time = last_time; - if ( delta ) - { - osc.last_amp += delta; - square_synth.offset( time, delta, output ); - } - - time += osc.delay; - osc.delay = 0; - int period = osc.period(); - if ( volume && !gate && period > 4 ) - { - if ( time < end_time ) - { - int phase = osc.phase; - - do - { - phase++; - if ( phase == 16 ) - { - phase = 0; - osc.last_amp = volume; - square_synth.offset( time, volume, output ); - } - if ( phase == duty ) - { - osc.last_amp = 0; - square_synth.offset( time, -volume, output ); - } - time += period; - } - while ( time < end_time ); - - osc.phase = phase; - } - osc.delay = time - end_time; - } -} - -void Nes_Vrc6::run_saw( nes_time_t end_time ) -{ - Vrc6_Osc& osc = oscs [2]; - Blip_Buffer* output = osc.output; - if ( !output ) - return; - - int amp = osc.amp; - int amp_step = osc.regs [0] & 0x3F; - nes_time_t time = last_time; - int last_amp = osc.last_amp; - if ( !(osc.regs [2] & 0x80) || !(amp_step | amp) ) - { - osc.delay = 0; - int delta = (amp >> 3) - last_amp; - last_amp = amp >> 3; - saw_synth.offset( time, delta, output ); - } - else - { - time += osc.delay; - if ( time < end_time ) - { - int period = osc.period() * 2; - int phase = osc.phase; - - do - { - if ( --phase == 0 ) - { - phase = 7; - amp = 0; - } - - int delta = (amp >> 3) - last_amp; - if ( delta ) - { - last_amp = amp >> 3; - saw_synth.offset( time, delta, output ); - } - - time += period; - amp = (amp + amp_step) & 0xFF; - } - while ( time < end_time ); - - osc.phase = phase; - osc.amp = amp; - } - - osc.delay = time - end_time; - } - - osc.last_amp = last_amp; -} - diff --git a/quicknes/nes_emu/Nes_Vrc6.h b/quicknes/nes_emu/Nes_Vrc6.h deleted file mode 100644 index 908b952210..0000000000 --- a/quicknes/nes_emu/Nes_Vrc6.h +++ /dev/null @@ -1,86 +0,0 @@ - -// Konami VRC6 sound chip emulator - -// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. - -#ifndef NES_VRC6_H -#define NES_VRC6_H - -#include "Nes_Apu.h" -#include "Blip_Buffer.h" - -struct vrc6_snapshot_t; - -class Nes_Vrc6 { -public: - Nes_Vrc6(); - ~Nes_Vrc6(); - - // See Nes_Apu.h for reference - void reset(); - void volume( double ); - void treble_eq( blip_eq_t const& ); - void output( Blip_Buffer* ); - enum { osc_count = 3 }; - void osc_output( int index, Blip_Buffer* ); - void end_frame( nes_time_t ); - void save_snapshot( vrc6_snapshot_t* ) const; - void load_snapshot( vrc6_snapshot_t const& ); - - // Oscillator 0 write-only registers are at $9000-$9002 - // Oscillator 1 write-only registers are at $A000-$A002 - // Oscillator 2 write-only registers are at $B000-$B002 - enum { reg_count = 3 }; - enum { base_addr = 0x9000 }; - enum { addr_step = 0x1000 }; - void write_osc( nes_time_t, int osc, int reg, int data ); - -private: - // noncopyable - Nes_Vrc6( const Nes_Vrc6& ); - Nes_Vrc6& operator = ( const Nes_Vrc6& ); - - struct Vrc6_Osc - { - BOOST::uint8_t regs [3]; - Blip_Buffer* output; - int delay; - int last_amp; - int phase; - int amp; // only used by saw - - int period() const - { - return (regs [2] & 0x0f) * 0x100L + regs [1] + 1; - } - }; - - Vrc6_Osc oscs [osc_count]; - nes_time_t last_time; - - Blip_Synth saw_synth; - Blip_Synth square_synth; - - void run_until( nes_time_t ); - void run_square( Vrc6_Osc& osc, nes_time_t ); - void run_saw( nes_time_t ); -}; - -struct vrc6_snapshot_t -{ - BOOST::uint8_t regs [3] [3]; - BOOST::uint8_t saw_amp; - BOOST::uint16_t delays [3]; - BOOST::uint8_t phases [3]; - BOOST::uint8_t unused; -}; -BOOST_STATIC_ASSERT( sizeof (vrc6_snapshot_t) == 20 ); - -inline void Nes_Vrc6::osc_output( int i, Blip_Buffer* buf ) -{ - assert( (unsigned) i < osc_count ); - oscs [i].output = buf; -} - -#endif - diff --git a/quicknes/nes_emu/Nonlinear_Buffer.cpp b/quicknes/nes_emu/Nonlinear_Buffer.cpp deleted file mode 100644 index d1290f1949..0000000000 --- a/quicknes/nes_emu/Nonlinear_Buffer.cpp +++ /dev/null @@ -1,189 +0,0 @@ - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/libs/ - -#include "Nonlinear_Buffer.h" - -#include "Nes_Apu.h" - -/* Library Copyright (C) 2003-2005 Shay Green. This library 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -// Nonlinear_Buffer - -Nonlinear_Buffer::Nonlinear_Buffer() : - Multi_Buffer( 1 ) -{ -} - -Nonlinear_Buffer::~Nonlinear_Buffer() -{ -} - -void Nonlinear_Buffer::enable_nonlinearity( Nes_Apu& apu, bool b ) -{ - if ( b ) - clear(); - nonlinearizer.enable( apu, b ); - for ( int i = 0; i < apu.osc_count; i++ ) - apu.osc_output( i, (i >= 2 ? &tnd : &buf) ); -} - -blargg_err_t Nonlinear_Buffer::sample_rate( long rate, int msec ) -{ - BLARGG_RETURN_ERR( buf.sample_rate( rate, msec ) ); - BLARGG_RETURN_ERR( tnd.sample_rate( rate, msec ) ); - return Multi_Buffer::sample_rate( buf.sample_rate(), buf.length() ); -} - -void Nonlinear_Buffer::clock_rate( long rate ) -{ - buf.clock_rate( rate ); - tnd.clock_rate( rate ); -} - -void Nonlinear_Buffer::bass_freq( int freq ) -{ - buf.bass_freq( freq ); - tnd.bass_freq( freq ); -} - -void Nonlinear_Buffer::clear() -{ - nonlinearizer.clear(); - buf.clear(); - tnd.clear(); -} - -Nonlinear_Buffer::channel_t Nonlinear_Buffer::channel( int i ) -{ - channel_t c; - c.center = &buf; - if ( 2 <= i && i <= 4 ) - c.center = &tnd; // only use for triangle, noise, and dmc - c.left = c.center; - c.right = c.center; - return c; -} - -void Nonlinear_Buffer::end_frame( blip_time_t length, bool ) -{ - buf.end_frame( length ); - tnd.end_frame( length ); -} - -long Nonlinear_Buffer::samples_avail() const -{ - return buf.samples_avail(); -} - -#include BLARGG_ENABLE_OPTIMIZER - -long Nonlinear_Buffer::read_samples( blip_sample_t* out, long count ) -{ - count = nonlinearizer.make_nonlinear( tnd, count ); - if ( count ) - { - Blip_Reader lin; - Blip_Reader nonlin; - - int lin_bass = lin.begin( buf ); - int nonlin_bass = nonlin.begin( tnd ); - - for ( int n = count; n--; ) - { - int s = lin.read() + nonlin.read(); - lin.next( lin_bass ); - nonlin.next( nonlin_bass ); - *out++ = s; - - if ( (BOOST::int16_t) s != s ) - out [-1] = 0x7FFF - (s >> 24); - } - - lin.end( buf ); - nonlin.end( tnd ); - - buf.remove_samples( count ); - tnd.remove_samples( count ); - } - - return count; -} - -// Nes_Nonlinearizer - -Nes_Nonlinearizer::Nes_Nonlinearizer() -{ - nonlinear = false; - - double gain = 0x7fff * 1.3; - // don't use entire range, so any overflow will stay within table - int const range = half * Nes_Apu::nonlinear_tnd_gain(); - for ( int i = 0; i < half * 2; i++ ) - { - int out = i << shift; - if ( i > half ) - { - int j = i - half; - if ( j >= range ) - j = range - 1; - double n = 202.0 / (range - 1) * j; - double d = 163.67 / (24329.0 / n + 100); - out = int (d * gain) + 0x8000; - assert( out < 0x10000 ); - } - table [i] = out; - } - clear(); -} - -void Nes_Nonlinearizer::enable( Nes_Apu& apu, bool b ) -{ - nonlinear = b; - if ( b ) - apu.enable_nonlinear( 1.0 ); - else - apu.volume( 1.0 ); -} - -long Nes_Nonlinearizer::make_nonlinear( Blip_Buffer& buf, long count ) -{ - long avail = buf.samples_avail(); - if ( count > avail ) - count = avail; - - if ( count && nonlinear ) - { - const int zero_offset = Blip_Buffer::sample_offset_; - - #define ENTRY( s ) (table [((s) >> shift) & entry_mask]) - - BOOST::uint16_t* p = buf.buffer_; - unsigned prev = ENTRY( accum ); - long accum = this->accum; - - for ( unsigned n = count; n--; ) - { - accum += (long) *p - zero_offset; - check( (accum >> shift) < half * 2 ); - unsigned entry = ENTRY( accum ); - *p++ = entry - prev + zero_offset; - prev = entry; - } - - this->accum = accum; - } - - return count; -} - diff --git a/quicknes/nes_emu/Nonlinear_Buffer.h b/quicknes/nes_emu/Nonlinear_Buffer.h deleted file mode 100644 index a3cb7ee8ac..0000000000 --- a/quicknes/nes_emu/Nonlinear_Buffer.h +++ /dev/null @@ -1,65 +0,0 @@ - -// NES non-linear audio output handling. - -// Nes_Emu 0.5.6. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. - -#ifndef NONLINEAR_BUFFER_H -#define NONLINEAR_BUFFER_H - -#include "Multi_Buffer.h" -class Nes_Apu; - -// Use to make samples non-linear in Blip_Buffer used for triangle, noise, and DMC only -class Nes_Nonlinearizer { -public: - Nes_Nonlinearizer(); - - // Must be called when buffer is cleared - void clear() { accum = 0x8000; } - - // Enable/disable non-linear output - void enable( Nes_Apu&, bool = true ); - - // Make at most 'count' samples in buffer non-linear and return number - // of samples modified. This many samples must then be read out of the buffer. - long make_nonlinear( Blip_Buffer&, long count ); - -private: - enum { shift = 5 }; - enum { half = 0x8000 >> shift }; - enum { entry_mask = half * 2 - 1 }; - BOOST::uint16_t table [half * 2]; - long accum; - bool nonlinear; -}; - -class Nonlinear_Buffer : public Multi_Buffer { -public: - Nonlinear_Buffer(); - ~Nonlinear_Buffer(); - - // Enable/disable non-linear output - void enable_nonlinearity( Nes_Apu&, bool = true ); - - // Blip_Buffer to output other sound chips to - Blip_Buffer* buffer() { return &buf; } - - // See Multi_Buffer.h - blargg_err_t sample_rate( long rate, int msec = blip_default_length ); - Multi_Buffer::sample_rate; - void clock_rate( long ); - void bass_freq( int ); - void clear(); - channel_t channel( int ); - void end_frame( blip_time_t, bool unused = true ); - long samples_avail() const; - long read_samples( blip_sample_t*, long ); - -private: - Blip_Buffer buf; - Blip_Buffer tnd; - Nes_Nonlinearizer nonlinearizer; -}; - -#endif - diff --git a/quicknes/nes_emu/Nonlinear_Effects_Buffer.cpp b/quicknes/nes_emu/Nonlinear_Effects_Buffer.cpp deleted file mode 100644 index ab1ec3faa1..0000000000 --- a/quicknes/nes_emu/Nonlinear_Effects_Buffer.cpp +++ /dev/null @@ -1,69 +0,0 @@ - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/libs/ - -#include "Nonlinear_Effects_Buffer.h" - -/* Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -Nonlinear_Effects_Buffer::Nonlinear_Effects_Buffer() : Effects_Buffer( true ) -{ - config_t c; - c.effects_enabled = false; - config( c ); -} - -Nonlinear_Effects_Buffer::~Nonlinear_Effects_Buffer() -{ -} - -void Nonlinear_Effects_Buffer::enable_nonlinearity( Nes_Apu& apu, bool b ) -{ - if ( b ) - clear(); - nonlinearizer.enable( apu, b ); -} - -void Nonlinear_Effects_Buffer::config( const config_t& in ) -{ - config_t c = in; - if ( !c.effects_enabled ) - { - // effects must always be enabled to keep separate buffers, so - // set parameters to be equivalent to disabled - c.pan_1 = 0; - c.pan_2 = 0; - c.echo_level = 0; - c.reverb_level = 0; - c.effects_enabled = true; - } - Effects_Buffer::config( c ); -} - -void Nonlinear_Effects_Buffer::clear() -{ - nonlinearizer.clear(); - Effects_Buffer::clear(); -} - -Nonlinear_Effects_Buffer::channel_t Nonlinear_Effects_Buffer::channel( int i ) -{ - return Effects_Buffer::channel( (2 <= i && i <= 4) ? 2 : i & 1 ); -} - -long Nonlinear_Effects_Buffer::read_samples( blip_sample_t* out, long count ) -{ - count = 2 * nonlinearizer.make_nonlinear( *channel( 2 ).center, count / 2 ); - return Effects_Buffer::read_samples( out, count ); -} - diff --git a/quicknes/nes_emu/Nonlinear_Effects_Buffer.h b/quicknes/nes_emu/Nonlinear_Effects_Buffer.h deleted file mode 100644 index 4c79b92cbd..0000000000 --- a/quicknes/nes_emu/Nonlinear_Effects_Buffer.h +++ /dev/null @@ -1,33 +0,0 @@ - -// Effects_Buffer with non-linear sound - -// Nes_Emu 0.5.6. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. - -#ifndef NONLINEAR_EFFECTS_BUFFER_H -#define NONLINEAR_EFFECTS_BUFFER_H - -#include "Nonlinear_Buffer.h" -#include "Effects_Buffer.h" - -// Effects_Buffer uses several buffers and outputs stereo sample pairs. -class Nonlinear_Effects_Buffer : public Effects_Buffer { -public: - Nonlinear_Effects_Buffer(); - ~Nonlinear_Effects_Buffer(); - - // Enable/disable non-linear output - void enable_nonlinearity( Nes_Apu&, bool = true ); - - // See Effects_Buffer.h for reference - void config( const config_t& ); - void clear(); - channel_t channel( int ); - long read_samples( blip_sample_t*, long ); - -// End of public interface -private: - Nes_Nonlinearizer nonlinearizer; -}; - -#endif - diff --git a/quicknes/nes_emu/apu_snapshot.cpp b/quicknes/nes_emu/apu_snapshot.cpp deleted file mode 100644 index 85ad55cfb5..0000000000 --- a/quicknes/nes_emu/apu_snapshot.cpp +++ /dev/null @@ -1,126 +0,0 @@ - -// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/ - -#include "apu_snapshot.h" -#include "Nes_Apu.h" - -/* Copyright (C) 2003-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#ifdef BLARGG_SOURCE_BEGIN -#include BLARGG_SOURCE_BEGIN -#endif - -template -struct apu_reflection -{ - #define REFLECT( apu, state ) (mode ? void (apu = state) : void (state = apu)) - - static void reflect_env( apu_snapshot_t::env_t& state, Nes_Envelope& osc ) - { - REFLECT( state [0], osc.env_delay ); - REFLECT( state [1], osc.envelope ); - REFLECT( state [2], osc.reg_written [3] ); - } - - static void reflect_square( apu_snapshot_t::square_t& state, Nes_Square& osc ) - { - reflect_env( state.env, osc ); - REFLECT( state.delay, osc.delay ); - REFLECT( state.length, osc.length_counter ); - REFLECT( state.phase, osc.phase ); - REFLECT( state.swp_delay, osc.sweep_delay ); - REFLECT( state.swp_reset, osc.reg_written [1] ); - } - - static void reflect_triangle( apu_snapshot_t::triangle_t& state, Nes_Triangle& osc ) - { - REFLECT( state.delay, osc.delay ); - REFLECT( state.length, osc.length_counter ); - REFLECT( state.linear_counter, osc.linear_counter ); - REFLECT( state.linear_mode, osc.reg_written [3] ); - } - - static void reflect_noise( apu_snapshot_t::noise_t& state, Nes_Noise& osc ) - { - reflect_env( state.env, osc ); - REFLECT( state.delay, osc.delay ); - REFLECT( state.length, osc.length_counter ); - REFLECT( state.shift_reg, osc.noise ); - } - - static void reflect_dmc( apu_snapshot_t::dmc_t& state, Nes_Dmc& osc ) - { - REFLECT( state.delay, osc.delay ); - REFLECT( state.remain, osc.length_counter ); - REFLECT( state.buf, osc.buf ); - REFLECT( state.bits_remain, osc.bits_remain ); - REFLECT( state.bits, osc.bits ); - REFLECT( state.buf_empty, osc.buf_empty ); - REFLECT( state.silence, osc.silence ); - REFLECT( state.irq_flag, osc.irq_flag ); - if ( mode ) - state.addr = osc.address | 0x8000; - else - osc.address = state.addr & 0x7fff; - } -}; - -void Nes_Apu::save_snapshot( apu_snapshot_t* state ) const -{ - for ( int i = 0; i < osc_count * 4; i++ ) - state->w40xx [i] = oscs [i >> 2]->regs [i & 3]; - state->w40xx [0x11] = dmc.dac; - - state->w4015 = osc_enables; - state->w4017 = frame_mode; - state->delay = frame_delay; - state->step = frame; - state->irq_flag = irq_flag; - - typedef apu_reflection<1> refl; - Nes_Apu& apu = *(Nes_Apu*) this; // const_cast - refl::reflect_square ( state->square1, apu.square1 ); - refl::reflect_square ( state->square2, apu.square2 ); - refl::reflect_triangle( state->triangle, apu.triangle ); - refl::reflect_noise ( state->noise, apu.noise ); - refl::reflect_dmc ( state->dmc, apu.dmc ); -} - -void Nes_Apu::load_snapshot( apu_snapshot_t const& state ) -{ - reset(); - - write_register( 0, 0x4017, state.w4017 ); - write_register( 0, 0x4015, state.w4015 ); - - for ( int i = 0; i < osc_count * 4; i++ ) - { - int n = state.w40xx [i]; - oscs [i >> 2]->regs [i & 3] = n; - write_register( 0, 0x4000 + i, n ); - } - - frame_delay = state.delay; - frame = state.step; - irq_flag = state.irq_flag; - - typedef apu_reflection<0> refl; - apu_snapshot_t& st = (apu_snapshot_t&) state; // const_cast - refl::reflect_square ( st.square1, square1 ); - refl::reflect_square ( st.square2, square2 ); - refl::reflect_triangle( st.triangle, triangle ); - refl::reflect_noise ( st.noise, noise ); - refl::reflect_dmc ( st.dmc, dmc ); - dmc.recalc_irq(); - dmc.last_amp = dmc.dac; -} - diff --git a/quicknes/nes_emu/apu_snapshot.h b/quicknes/nes_emu/apu_snapshot.h deleted file mode 100644 index df8beac325..0000000000 --- a/quicknes/nes_emu/apu_snapshot.h +++ /dev/null @@ -1,75 +0,0 @@ - -// NES APU snapshot support - -// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. - -#ifndef APU_SNAPSHOT_H -#define APU_SNAPSHOT_H - -#include "blargg_common.h" - -struct apu_snapshot_t -{ - typedef BOOST::uint8_t byte; - - typedef byte env_t [3]; - /*struct env_t { - byte delay; - byte env;3 - byte written; - };*/ - - byte w40xx [0x14]; // $4000-$4013 - byte w4015; // enables - byte w4017; // mode - BOOST::uint16_t delay; - byte step; - byte irq_flag; - - struct square_t { - BOOST::uint16_t delay; - env_t env; - byte length; - byte phase; - byte swp_delay; - byte swp_reset; - byte unused [1]; - }; - - square_t square1; - square_t square2; - - struct triangle_t { - BOOST::uint16_t delay; - byte length; - byte phase; - byte linear_counter; - byte linear_mode; - } triangle; - - struct noise_t { - BOOST::uint16_t delay; - env_t env; - byte length; - BOOST::uint16_t shift_reg; - } noise; - - struct dmc_t { - BOOST::uint16_t delay; - BOOST::uint16_t remain; - BOOST::uint16_t addr; - byte buf; - byte bits_remain; - byte bits; - byte buf_empty; - byte silence; - byte irq_flag; - } dmc; - - enum { tag = 'APUR' }; - void swap(); -}; -BOOST_STATIC_ASSERT( sizeof (apu_snapshot_t) == 72 ); - -#endif - diff --git a/quicknes/nes_emu/optional_mappers.cpp b/quicknes/nes_emu/optional_mappers.cpp deleted file mode 100644 index 1171937d2b..0000000000 --- a/quicknes/nes_emu/optional_mappers.cpp +++ /dev/null @@ -1,194 +0,0 @@ - -// Optional less-common simple mappers - -// Nes_Emu 0.5.6. http://www.slack.net/~ant/ - -#include "Nes_Mapper.h" - -/* Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include BLARGG_SOURCE_BEGIN - -// Nina-1 (Deadly Towers only) - -class Mapper_Nina1 : public Nes_Mapper { - byte bank; -public: - Mapper_Nina1() - { - register_state( &bank, 1 ); - } - - virtual void apply_mapping() - { - write( 0, 0, bank ); - } - - virtual void write( nes_time_t, nes_addr_t addr, int data ) - { - bank = data; - set_prg_bank( 0x8000, bank_32k, bank ); - } -}; - -// GNROM - -class Mapper_Gnrom : public Nes_Mapper { - byte bank; -public: - Mapper_Gnrom() - { - register_state( &bank, 1 ); - } - - virtual void apply_mapping() - { - int b = bank; - bank = ~b; - write( 0, 0, b ); - } - - virtual void write( nes_time_t, nes_addr_t addr, int data ) - { - int changed = bank ^ data; - bank = data; - - if ( changed & 0x30 ) - set_prg_bank( 0x8000, bank_32k, bank >> 4 & 3 ); - - if ( changed & 0x03 ) - set_chr_bank( 0, bank_8k, bank & 3 ); - } -}; - -// Color Dreams - -class Mapper_Color_Dreams : public Nes_Mapper { - byte bank; -public: - Mapper_Color_Dreams() - { - register_state( &bank, 1 ); - } - - virtual void apply_mapping() - { - int b = bank; - bank = ~b; - write( 0, 0, b ); - } - - virtual void write( nes_time_t, nes_addr_t addr, int data ) - { - int changed = bank ^ data; - bank = data; - - if ( changed & 0x0f ) - set_prg_bank( 0x8000, bank_32k, bank & 0x0f ); - - if ( changed & 0xf0 ) - set_chr_bank( 0, bank_8k, bank >> 4 ); - } -}; - -// Camerica - -class Mapper_Camerica : public Nes_Mapper { - byte regs [3]; -public: - Mapper_Camerica() - { - register_state( regs, sizeof regs ); - } - - virtual void apply_mapping() - { - write( 0, 0xc000, regs [0] ); - if ( regs [1] & 0x80 ) - write( 0, 0x9000, regs [1] ); - } - - virtual void write( nes_time_t, nes_addr_t addr, int data ) - { - if ( addr >= 0xc000 ) - { - regs [0] = data; - set_prg_bank( 0x8000, bank_16k, data ); - } - else if ( (addr & 0xf000) == 0x9000 ) - { - regs [1] = 0x80 | data; - mirror_single( (data >> 4) & 1 ); - } - } -}; - -// Quattro - -class Mapper_Quattro : public Nes_Mapper { - byte regs [2]; -public: - Mapper_Quattro() - { - register_state( regs, sizeof regs ); - } - - virtual void reset_state() - { - regs [0] = 0; - regs [1] = 3; - } - - virtual void apply_mapping() - { - int bank = regs [0] >> 1 & 0x0c; - set_prg_bank( 0x8000, bank_16k, bank + (regs [1] & 3) ); - set_prg_bank( 0xC000, bank_16k, bank + 3 ); - } - - virtual void write( nes_time_t, nes_addr_t addr, int data ) - { - if ( addr < 0xc000 ) - regs [0] = data; - else - regs [1] = data; - Mapper_Quattro::apply_mapping(); - } -}; - -void register_misc_mappers(); -void register_misc_mappers() -{ - register_mapper( 11 ); - register_mapper( 34 ); - register_mapper( 66 ); - register_mapper( 71 ); - register_mapper( 232 ); -} - -void Nes_Mapper::register_optional_mappers() -{ - register_misc_mappers(); - - extern void register_vrc6_mapper(); - register_vrc6_mapper(); - - extern void register_mmc5_mapper(); - register_mmc5_mapper(); - - extern void register_fme07_mapper(); - register_fme07_mapper(); - - extern void register_namco106_mapper(); - register_namco106_mapper(); -} -