Linux WonderSwan - now working

This commit is contained in:
Asnivor 2019-01-26 20:27:07 +00:00
parent b6173db95c
commit cd6d70bce5
4 changed files with 599 additions and 739 deletions

BIN
Assets/libbizswan.dll.so Executable file

Binary file not shown.

View File

@ -1,498 +1,354 @@
// Band-limited sound synthesis buffer
// Various changes and hacks for use in Mednafen.
#ifdef __GNUC__
#define blip_inline inline __attribute__((always_inline))
#else
#define blip_inline inline
#endif
#include <limits.h>
#include <inttypes.h>
// Blip_Buffer 0.4.1
#ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H
// Internal
typedef int32_t blip_long;
typedef uint32_t blip_ulong;
typedef int64_t blip_s64;
typedef uint64_t blip_u64;
// Time unit at source clock rate
typedef blip_long blip_time_t;
// Output samples are 16-bit signed, with a range of -32768 to 32767
typedef short blip_sample_t;
enum { blip_sample_max = 32767 };
class Blip_Buffer {
public:
typedef const char* blargg_err_t;
// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
// isn't enough memory, returns error without affecting current buffer setup.
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
// Set number of source time units per second
void clock_rate( long );
// End current time frame of specified duration and make its samples available
// (along with any still-unread samples) for reading with read_samples(). Begins
// a new time frame at the end of the current frame.
void end_frame( blip_time_t time );
// Read at most 'max_samples' out of buffer into 'dest', removing them from from
// the buffer. Returns number of samples actually read and removed. If stereo is
// true, increments 'dest' one extra time after writing each sample, to allow
// easy interleving of two channels into a stereo output buffer.
long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
// Additional optional features
// Current output sample rate
long sample_rate() const;
// Length of buffer, in milliseconds
int length() const;
// Number of source time units per second
long clock_rate() const;
// Set frequency high-pass filter frequency, where higher values reduce bass more
void bass_freq( int frequency );
// Number of samples delay from synthesis to samples read out
int output_latency() const;
// Remove all available samples and clear buffer to silence. If 'entire_buffer' is
// false, just clears out any samples waiting rather than the entire buffer.
void clear( int entire_buffer = 1 );
// Number of samples available for reading with read_samples()
long samples_avail() const;
// Remove 'count' samples from those waiting to be read
void remove_samples( long count );
// Experimental features
// Count number of clocks needed until 'count' samples will be available.
// If buffer can't even hold 'count' samples, returns number of clocks until
// buffer becomes full.
blip_time_t count_clocks( long count ) const;
// Number of raw samples that can be mixed within frame of specified duration.
long count_samples( blip_time_t duration ) const;
// Mix 'count' samples from 'buf' into buffer.
void mix_samples( blip_sample_t const* buf, long count );
// not documented yet
void set_modified() { modified_ = 1; }
int clear_modified() { int b = modified_; modified_ = 0; return b; }
typedef blip_u64 blip_resampled_time_t;
void remove_silence( long count );
blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
public:
Blip_Buffer();
~Blip_Buffer();
// Deprecated
typedef blip_resampled_time_t resampled_time_t;
blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
private:
// noncopyable
Blip_Buffer( const Blip_Buffer& );
Blip_Buffer& operator = ( const Blip_Buffer& );
public:
typedef blip_time_t buf_t_;
blip_u64 factor_;
blip_resampled_time_t offset_;
buf_t_* buffer_;
blip_long buffer_size_;
blip_long reader_accum_;
int bass_shift_;
private:
long sample_rate_;
long clock_rate_;
int bass_freq_;
int length_;
int modified_;
friend class Blip_Reader;
};
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define BLIP_BUFFER_ACCURACY 32
#define BLIP_PHASE_BITS 8
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
// but reduce maximum buffer size.
//#ifndef BLIP_BUFFER_ACCURACY
// #define BLIP_BUFFER_ACCURACY 16
//#endif
// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
// noticeable broadband noise when synthesizing high frequency square waves.
// Affects size of Blip_Synth objects since they store the waveform directly.
//#ifndef BLIP_PHASE_BITS
// #if BLIP_BUFFER_FAST
// #define BLIP_PHASE_BITS 8
// #else
// #define BLIP_PHASE_BITS 6
// #endif
//#endif
// Internal
typedef blip_u64 blip_resampled_time_t;
int const blip_widest_impulse_ = 16;
int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
int const blip_res = 1 << BLIP_PHASE_BITS;
class blip_eq_t;
class Blip_Synth_Fast_ {
public:
Blip_Buffer* buf;
int last_amp;
int delta_factor;
void volume_unit( double );
Blip_Synth_Fast_();
void treble_eq( blip_eq_t const& ) { }
};
class Blip_Synth_ {
public:
Blip_Buffer* buf;
int last_amp;
int delta_factor;
void volume_unit( double );
Blip_Synth_( short* impulses, int width );
void treble_eq( blip_eq_t const& );
private:
double volume_unit_;
short* const impulses;
int const width;
blip_long kernel_unit;
int impulses_size() const { return blip_res / 2 * width + 1; }
void adjust_impulse();
};
// Quality level. Start with blip_good_quality.
const int blip_med_quality = 8;
const int blip_good_quality = 12;
const int blip_high_quality = 16;
// Range specifies the greatest expected change in amplitude. Calculate it
// by finding the difference between the maximum and minimum expected
// amplitudes (max - min).
template<int quality,int range>
class Blip_Synth {
public:
// Set overall volume of waveform
void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
// Configure low-pass filter (see blip_buffer.txt)
void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
// Get/set Blip_Buffer used for output
Blip_Buffer* output() const { return impl.buf; }
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
// Update amplitude of waveform at given time. Using this requires a separate
// Blip_Synth for each waveform.
void update( blip_time_t time, int amplitude );
// Low-level interface
// Add an amplitude transition of specified delta, optionally into specified buffer
// rather than the one set with output(). Delta can be positive or negative.
// The actual change in amplitude is delta * (volume / range)
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
// Works directly in terms of fractional output samples. Contact author for more info.
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
// Same as offset(), except code is inlined for higher performance
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
}
void offset_inline( blip_time_t t, int delta ) const {
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
}
private:
#if BLIP_BUFFER_FAST
Blip_Synth_Fast_ impl;
#else
Blip_Synth_ impl;
typedef short imp_t;
imp_t impulses [blip_res * (quality / 2) + 1];
public:
Blip_Synth() : impl( impulses, quality ) { }
#endif
};
// Low-pass equalization parameters
class blip_eq_t {
public:
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
// treble, small positive values (0 to 5.0) increase treble.
blip_eq_t( double treble_db = 0 );
// See blip_buffer.txt
blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
private:
double treble;
long rolloff_freq;
long sample_rate;
long cutoff_freq;
void generate( float* out, int count ) const;
friend class Blip_Synth_;
};
int const blip_sample_bits = 30;
// Dummy Blip_Buffer to direct sound output to, for easy muting without
// having to stop sound code.
class Silent_Blip_Buffer : public Blip_Buffer {
buf_t_ buf [blip_buffer_extra_ + 1];
public:
// The following cannot be used (an assertion will fail if attempted):
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
blip_time_t count_clocks( long count ) const;
void mix_samples( blip_sample_t const* buf, long count );
Silent_Blip_Buffer();
};
#if defined (__GNUC__) || _MSC_VER >= 1100
#define BLIP_RESTRICT __restrict
#else
#define BLIP_RESTRICT
#endif
// Optimized reading from Blip_Buffer, for use in custom sample output
// Begin reading from buffer. Name should be unique to the current block.
#define BLIP_READER_BEGIN( name, blip_buffer ) \
const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
blip_long name##_reader_accum = (blip_buffer).reader_accum_
// Get value to pass to BLIP_READER_NEXT()
#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
// code at the cost of having no bass control
int const blip_reader_default_bass = 9;
// Current sample
#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
// Current raw sample in full internal resolution
#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
// Advance to next sample
#define BLIP_READER_NEXT( name, bass ) \
(void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
// End reading samples from buffer. The number of samples read must now be removed
// using Blip_Buffer::remove_samples().
#define BLIP_READER_END( name, blip_buffer ) \
(void) ((blip_buffer).reader_accum_ = name##_reader_accum)
// Compatibility with older version
const long blip_unscaled = 65535;
const int blip_low_quality = blip_med_quality;
const int blip_best_quality = blip_high_quality;
// Deprecated; use BLIP_READER macros as follows:
// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
// r.read() -> BLIP_READER_READ( r )
// r.read_raw() -> BLIP_READER_READ_RAW( r )
// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
// r.end( buf ) -> BLIP_READER_END( r, buf )
class Blip_Reader {
public:
int begin( Blip_Buffer& );
blip_long read() const { return accum >> (blip_sample_bits - 16); }
blip_long read_raw() const { return accum; }
void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
private:
const Blip_Buffer::buf_t_* buf;
blip_long accum;
};
// End of public interface
#include <assert.h>
template<int quality,int range>
blip_inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
int delta, Blip_Buffer* blip_buf ) const
{
// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
// need for a longer buffer as set by set_sample_rate().
assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
delta *= impl.delta_factor;
blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
#if BLIP_BUFFER_FAST
blip_long left = buf [0] + delta;
// Kind of crappy, but doing shift after multiply results in overflow.
// Alternate way of delaying multiply by delta_factor results in worse
// sub-sample resolution.
blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
left -= right;
right += buf [1];
buf [0] = left;
buf [1] = right;
#else
int const fwd = (blip_widest_impulse_ - quality) / 2;
int const rev = fwd + quality - 2;
int const mid = quality / 2 - 1;
imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
// straight forward implementation resulted in better code on GCC for x86
#define ADD_IMP( out, in ) \
buf [out] += (blip_long) imp [blip_res * (in)] * delta
#define BLIP_FWD( i ) {\
ADD_IMP( fwd + i, i );\
ADD_IMP( fwd + 1 + i, i + 1 );\
}
#define BLIP_REV( r ) {\
ADD_IMP( rev - r, r + 1 );\
ADD_IMP( rev + 1 - r, r );\
}
BLIP_FWD( 0 )
if ( quality > 8 ) BLIP_FWD( 2 )
if ( quality > 12 ) BLIP_FWD( 4 )
{
ADD_IMP( fwd + mid - 1, mid - 1 );
ADD_IMP( fwd + mid , mid );
imp = impulses + phase;
}
if ( quality > 12 ) BLIP_REV( 6 )
if ( quality > 8 ) BLIP_REV( 4 )
BLIP_REV( 2 )
ADD_IMP( rev , 1 );
ADD_IMP( rev + 1, 0 );
#else
// for RISC processors, help compiler by reading ahead of writes
#define BLIP_FWD( i ) {\
blip_long t0 = i0 * delta + buf [fwd + i];\
blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
i0 = imp [blip_res * (i + 2)];\
buf [fwd + i] = t0;\
buf [fwd + 1 + i] = t1;\
}
#define BLIP_REV( r ) {\
blip_long t0 = i0 * delta + buf [rev - r];\
blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
i0 = imp [blip_res * (r - 1)];\
buf [rev - r] = t0;\
buf [rev + 1 - r] = t1;\
}
blip_long i0 = *imp;
BLIP_FWD( 0 )
if ( quality > 8 ) BLIP_FWD( 2 )
if ( quality > 12 ) BLIP_FWD( 4 )
{
blip_long t0 = i0 * delta + buf [fwd + mid - 1];
blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
imp = impulses + phase;
i0 = imp [blip_res * mid];
buf [fwd + mid - 1] = t0;
buf [fwd + mid ] = t1;
}
if ( quality > 12 ) BLIP_REV( 6 )
if ( quality > 8 ) BLIP_REV( 4 )
BLIP_REV( 2 )
blip_long t0 = i0 * delta + buf [rev ];
blip_long t1 = *imp * delta + buf [rev + 1];
buf [rev ] = t0;
buf [rev + 1] = t1;
#endif
#endif
}
#undef BLIP_FWD
#undef BLIP_REV
template<int quality,int range>
#if BLIP_BUFFER_FAST
blip_inline
#endif
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
{
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
}
template<int quality,int range>
#if BLIP_BUFFER_FAST
blip_inline
#endif
void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
{
int delta = amp - impl.last_amp;
impl.last_amp = amp;
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
}
blip_inline blip_eq_t::blip_eq_t( double t ) :
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
blip_inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
blip_inline int Blip_Buffer::length() const { return length_; }
blip_inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
blip_inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
blip_inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
blip_inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
blip_inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
blip_inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
{
buf = blip_buf.buffer_;
accum = blip_buf.reader_accum_;
return blip_buf.bass_shift_;
}
int const blip_max_length = 0;
int const blip_default_length = 250;
#endif
// Band-limited sound synthesis and buffering
// Blip_Buffer 0.4.0
#ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H
// Time unit at source clock rate
typedef long blip_time_t;
// Output samples are 16-bit signed, with a range of -32768 to 32767
typedef short blip_sample_t;
enum { blip_sample_max = 32767 };
class Blip_Buffer {
public:
typedef const char* blargg_err_t;
// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
// isn't enough memory, returns error without affecting current buffer setup.
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
// Set number of source time units per second
void clock_rate( long );
// End current time frame of specified duration and make its samples available
// (along with any still-unread samples) for reading with read_samples(). Begins
// a new time frame at the end of the current frame.
void end_frame( blip_time_t time );
// Read at most 'max_samples' out of buffer into 'dest', removing them from from
// the buffer. Returns number of samples actually read and removed. If stereo is
// true, increments 'dest' one extra time after writing each sample, to allow
// easy interleving of two channels into a stereo output buffer.
long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
// Additional optional features
// Current output sample rate
long sample_rate() const;
// Length of buffer, in milliseconds
int length() const;
// Number of source time units per second
long clock_rate() const;
// Set frequency high-pass filter frequency, where higher values reduce bass more
void bass_freq( int frequency );
// Number of samples delay from synthesis to samples read out
int output_latency() const;
// Remove all available samples and clear buffer to silence. If 'entire_buffer' is
// false, just clears out any samples waiting rather than the entire buffer.
void clear( int entire_buffer = 1 );
// Number of samples available for reading with read_samples()
long samples_avail() const;
// Remove 'count' samples from those waiting to be read
void remove_samples( long count );
// Experimental features
// Number of raw samples that can be mixed within frame of specified duration.
long count_samples( blip_time_t duration ) const;
// Mix 'count' samples from 'buf' into buffer.
void mix_samples( blip_sample_t const* buf, long count );
// Count number of clocks needed until 'count' samples will be available.
// If buffer can't even hold 'count' samples, returns number of clocks until
// buffer becomes full.
blip_time_t count_clocks( long count ) const;
// not documented yet
typedef unsigned long blip_resampled_time_t;
void remove_silence( long count );
blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
public:
Blip_Buffer();
~Blip_Buffer();
// Deprecated
typedef blip_resampled_time_t resampled_time_t;
blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
private:
// noncopyable
Blip_Buffer( const Blip_Buffer& );
Blip_Buffer& operator = ( const Blip_Buffer& );
public:
typedef long buf_t_;
unsigned long factor_;
blip_resampled_time_t offset_;
buf_t_* buffer_;
long buffer_size_;
private:
long reader_accum;
int bass_shift;
long sample_rate_;
long clock_rate_;
int bass_freq_;
int length_;
friend class Blip_Reader;
};
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
// but reduce maximum buffer size.
#ifndef BLIP_BUFFER_ACCURACY
#define BLIP_BUFFER_ACCURACY 16
#endif
// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
// noticeable broadband noise when synthesizing high frequency square waves.
// Affects size of Blip_Synth objects since they store the waveform directly.
#ifndef BLIP_PHASE_BITS
#define BLIP_PHASE_BITS 6
#endif
// Internal
typedef unsigned long blip_resampled_time_t;
int const blip_widest_impulse_ = 16;
int const blip_res = 1 << BLIP_PHASE_BITS;
class blip_eq_t;
class Blip_Synth_ {
double volume_unit_;
short* const impulses;
int const width;
long kernel_unit;
int impulses_size() const { return blip_res / 2 * width + 1; }
void adjust_impulse();
public:
Blip_Buffer* buf;
int last_amp;
int delta_factor;
Blip_Synth_( short* impulses, int width );
void treble_eq( blip_eq_t const& );
void volume_unit( double );
};
// Quality level. Start with blip_good_quality.
const int blip_med_quality = 8;
const int blip_good_quality = 12;
const int blip_high_quality = 16;
// Range specifies the greatest expected change in amplitude. Calculate it
// by finding the difference between the maximum and minimum expected
// amplitudes (max - min).
template<int quality,int range>
class Blip_Synth {
public:
// Set overall volume of waveform
void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
// Configure low-pass filter (see notes.txt)
void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
// Get/set Blip_Buffer used for output
Blip_Buffer* output() const { return impl.buf; }
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
// Update amplitude of waveform at given time. Using this requires a separate
// Blip_Synth for each waveform.
void update( blip_time_t time, int amplitude );
// Low-level interface
// Add an amplitude transition of specified delta, optionally into specified buffer
// rather than the one set with output(). Delta can be positive or negative.
// The actual change in amplitude is delta * (volume / range)
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
// Works directly in terms of fractional output samples. Contact author for more.
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
// Same as offset(), except code is inlined for higher performance
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
}
void offset_inline( blip_time_t t, int delta ) const {
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
}
public:
Blip_Synth() : impl( impulses, quality ) { }
private:
typedef short imp_t;
imp_t impulses [blip_res * (quality / 2) + 1];
Blip_Synth_ impl;
};
// Low-pass equalization parameters
class blip_eq_t {
public:
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
// treble, small positive values (0 to 5.0) increase treble.
blip_eq_t( double treble_db = 0 );
// See notes.txt
blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
private:
double treble;
long rolloff_freq;
long sample_rate;
long cutoff_freq;
void generate( float* out, int count ) const;
friend class Blip_Synth_;
};
int const blip_sample_bits = 30;
// Optimized inline sample reader for custom sample formats and mixing of Blip_Buffer samples
class Blip_Reader {
public:
// Begin reading samples from buffer. Returns value to pass to next() (can
// be ignored if default bass_freq is acceptable).
int begin( Blip_Buffer& );
// Current sample
long read() const { return accum >> (blip_sample_bits - 16); }
// Current raw sample in full internal resolution
long read_raw() const { return accum; }
// Advance to next sample
void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
// End reading samples from buffer. The number of samples read must now be removed
// using Blip_Buffer::remove_samples().
void end( Blip_Buffer& b ) { b.reader_accum = accum; }
private:
const Blip_Buffer::buf_t_* buf;
long accum;
};
// End of public interface
#include <assert.h>
// Compatibility with older version
const long blip_unscaled = 65535;
const int blip_low_quality = blip_med_quality;
const int blip_best_quality = blip_high_quality;
#define BLIP_FWD( i ) { \
long t0 = i0 * delta + buf [fwd + i]; \
long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i]; \
i0 = imp [blip_res * (i + 2)]; \
buf [fwd + i] = t0; \
buf [fwd + 1 + i] = t1; }
#define BLIP_REV( r ) { \
long t0 = i0 * delta + buf [rev - r]; \
long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r]; \
i0 = imp [blip_res * (r - 1)]; \
buf [rev - r] = t0; \
buf [rev + 1 - r] = t1; }
template<int quality,int range>
inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
int delta, Blip_Buffer* blip_buf ) const
{
// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
// need for a longer buffer as set by set_sample_rate().
assert( (long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
delta *= impl.delta_factor;
int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
imp_t const* imp = impulses + blip_res - phase;
long* buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
long i0 = *imp;
int const fwd = (blip_widest_impulse_ - quality) / 2;
int const rev = fwd + quality - 2;
BLIP_FWD( 0 )
if ( quality > 8 ) BLIP_FWD( 2 )
if ( quality > 12 ) BLIP_FWD( 4 )
{
int const mid = quality / 2 - 1;
long t0 = i0 * delta + buf [fwd + mid - 1];
long t1 = imp [blip_res * mid] * delta + buf [fwd + mid];
imp = impulses + phase;
i0 = imp [blip_res * mid];
buf [fwd + mid - 1] = t0;
buf [fwd + mid] = t1;
}
if ( quality > 12 ) BLIP_REV( 6 )
if ( quality > 8 ) BLIP_REV( 4 )
BLIP_REV( 2 )
long t0 = i0 * delta + buf [rev];
long t1 = *imp * delta + buf [rev + 1];
buf [rev] = t0;
buf [rev + 1] = t1;
}
#undef BLIP_FWD
#undef BLIP_REV
template<int quality,int range>
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
{
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
}
template<int quality,int range>
void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
{
int delta = amp - impl.last_amp;
impl.last_amp = amp;
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
}
inline blip_eq_t::blip_eq_t( double t ) :
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
inline int Blip_Buffer::length() const { return length_; }
inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
{
buf = blip_buf.buffer_;
accum = blip_buf.reader_accum;
return blip_buf.bass_shift;
}
int const blip_max_length = 0;
int const blip_default_length = 250;
#endif

View File

@ -11,7 +11,7 @@ else
$(error Unknown arch)
endif
CXXFLAGS = -Wall -DLSB_FIRST -I.. -Wno-multichar -O3 -Wzero-as-null-pointer-constant -std=gnu++11 -fomit-frame-pointer -fno-exceptions -flto
CXXFLAGS = -Wall -DLSB_FIRST -I.. -Wno-multichar -O3 -Wzero-as-null-pointer-constant -std=gnu++11 -fomit-frame-pointer -fno-exceptions -flto -fPIC
TARGET = bizswan.dll
LDFLAGS_32 = -static -static-libgcc -static-libstdc++
@ -32,7 +32,7 @@ SRCS = \
../system.cpp \
../tcache.cpp \
../v30mz.cpp \
../Blip/Blip_Buffer.cpp
../blip/Blip_Buffer.cpp
OBJS = $(SRCS:.cpp=.o)

View File

@ -17,35 +17,39 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "system.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cstdarg>
#define EXPORT extern "C" __declspec(dllexport)
#include "system.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cstdarg>
#ifdef _WIN32
#define EXPORT extern "C" __declspec(dllexport)
#elif __linux__
#define EXPORT extern "C"
#endif
namespace MDFN_IEN_WSWAN
{
// maybe change?
int Debug::puts ( const char * str )
{
return std::puts(str);
}
int Debug::printf ( const char * format, ... )
{
va_list args;
va_start(args, format);
int ret = vprintf(format, args);
va_end(args);
return ret;
}
#include "start.inc"
void System::Reset()
// maybe change?
int Debug::puts ( const char * str )
{
return std::puts(str);
}
int Debug::printf ( const char * format, ... )
{
va_list args;
va_start(args, format);
int ret = vprintf(format, args);
va_end(args);
return ret;
}
#include "start.inc"
void System::Reset()
{
cpu.reset();
memory.Reset();
@ -62,8 +66,8 @@ namespace MDFN_IEN_WSWAN
}
cpu.set_reg(NEC_SS,0);
cpu.set_reg(NEC_SP,0x2000);
}
cpu.set_reg(NEC_SP,0x2000);
}
bool System::Advance(uint32 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int &soundbuffsize)
{
@ -86,7 +90,7 @@ namespace MDFN_IEN_WSWAN
cpu.timestamp = 0;
return memory.Lagged;
}
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
// Rounds up to the nearest power of 2.
static inline uint32 round_up_pow2(uint32 v)
@ -103,7 +107,7 @@ namespace MDFN_IEN_WSWAN
return(v);
}
bool System::Load(const uint8 *data, int length, const SyncSettings &settings)
{
uint32 real_rom_size;
@ -202,211 +206,211 @@ namespace MDFN_IEN_WSWAN
Reset();
return true;
}
// this is more than just being defensive; these classes do
// in some cases rely on zero filled constuct state
void *System::operator new(std::size_t size)
{
void *p = ::operator new(size);
std::memset(p, 0, size);
return p;
}
System::System()
{
gfx.sys = this;
memory.sys = this;
eeprom.sys = this;
rtc.sys = this;
sound.sys = this;
cpu.sys = this;
interrupt.sys = this;
}
System::~System()
{
}
int System::SaveRamSize() const
{
return eeprom.ieeprom_size + eeprom.eeprom_size + memory.sram_size;
}
bool System::SaveRamLoad(const uint8 *data, int size)
{
if (size != SaveRamSize())
return false;
#define LOAD(sz,ptr) { if (sz) { std::memcpy((ptr), data, (sz)); data += (sz); } }
LOAD(eeprom.ieeprom_size, eeprom.iEEPROM);
LOAD(eeprom.eeprom_size, eeprom.wsEEPROM);
LOAD(memory.sram_size, memory.wsSRAM);
#undef LOAD
return true;
}
bool System::SaveRamSave(uint8 *dest, int maxsize) const
{
if (maxsize != SaveRamSize())
return false;
#define SAVE(sz,ptr) { if (sz) { std::memcpy(dest, (ptr), (sz)); dest += (sz); } }
SAVE(eeprom.ieeprom_size, eeprom.iEEPROM);
SAVE(eeprom.eeprom_size, eeprom.wsEEPROM);
SAVE(memory.sram_size, memory.wsSRAM);
#undef SAVE
return true;
}
void System::PutSettings(const Settings &s)
{
gfx.SetLayerEnableMask(s.LayerMask);
gfx.SetBWPalette(s.BWPalette);
gfx.SetColorPalette(s.ColorPalette);
}
uint32 System::GetNECReg(int which) const
{
return cpu.get_reg(which);
}
bool System::GetMemoryArea(int index, const char *&name, int &size, uint8 *&data)
{
bool ret = true;
switch (index)
{
case 0: name = "RAM"; size = 65536; data = memory.wsRAM; break;
case 1: name = "ROM"; size = memory.rom_size; data = memory.wsCartROM; break;
case 2: name = "SRAM"; size = memory.sram_size; data = memory.wsSRAM; break;
case 3: name = "iEEPROM"; size = eeprom.ieeprom_size; data = eeprom.iEEPROM; break;
case 4: name = "EEPROM"; size = eeprom.eeprom_size; data = eeprom.wsEEPROM; break;
default: ret = false; break;
}
return ret;
}
SYNCFUNC(System)
{
SSS(gfx);
SSS(memory);
SSS(eeprom);
SSS(rtc);
SSS(sound);
SSS(cpu);
SSS(interrupt);
NSS(rotate);
NSS(oldbuttons);
}
EXPORT System *bizswan_new()
{
return new System();
}
EXPORT void bizswan_delete(System *s)
{
delete s;
}
EXPORT void bizswan_reset(System *s)
{
s->Reset();
}
EXPORT int bizswan_advance(System *s, uint32 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int *soundbuffsize, int *IsRotated)
{
int ret = s->Advance(buttons, novideo, surface, soundbuff, *soundbuffsize);
*IsRotated = s->rotate;
return ret;
}
EXPORT int bizswan_load(System *s, const uint8 *data, int length, const SyncSettings *settings, int *IsRotated)
{
bool ret = s->Load(data, length, *settings);
*IsRotated = s->rotate;
return ret;
}
EXPORT int bizswan_saveramsize(System *s)
{
return s->SaveRamSize();
}
EXPORT int bizswan_saveramload(System *s, const uint8 *data, int size)
{
return s->SaveRamLoad(data, size);
}
EXPORT int bizswan_saveramsave(System *s, uint8 *dest, int maxsize)
{
return s->SaveRamSave(dest, maxsize);
}
EXPORT void bizswan_putsettings(System *s, const Settings *settings)
{
s->PutSettings(*settings);
}
EXPORT uint32 bizswan_getnecreg(System *s, int which)
{
return s->GetNECReg(which);
}
EXPORT int bizswan_getmemoryarea(System *s, int index, const char **name, int *size, uint8 **data)
{
return s->GetMemoryArea(index, *name, *size, *data);
}
EXPORT int bizswan_binstatesize(System *s)
{
NewStateDummy dummy;
s->SyncState<false>(&dummy);
return dummy.GetLength();
}
EXPORT int bizswan_binstatesave(System *s, char *data, int length)
{
NewStateExternalBuffer saver(data, length);
s->SyncState<false>(&saver);
return !saver.Overflow() && saver.GetLength() == length;
}
EXPORT int bizswan_binstateload(System *s, const char *data, int length)
{
NewStateExternalBuffer loader(const_cast<char *>(data), length);
s->SyncState<true>(&loader);
return !loader.Overflow() && loader.GetLength() == length;
}
EXPORT void bizswan_txtstatesave(System *s, FPtrs *ff)
{
NewStateExternalFunctions saver(ff);
s->SyncState<false>(&saver);
}
EXPORT void bizswan_txtstateload(System *s, FPtrs *ff)
{
NewStateExternalFunctions loader(ff);
s->SyncState<true>(&loader);
}
EXPORT void bizswan_setmemorycallbacks(System *s, void (*rcb)(uint32), void (*ecb)(uint32), void (*wcb)(uint32))
{
s->cpu.ReadHook = rcb;
s->cpu.WriteHook = wcb;
s->cpu.ExecHook = ecb;
}
EXPORT void bizswan_setbuttoncallback(System *s, void (*bcb)())
{
s->memory.ButtonHook = bcb;
}
}
}
// this is more than just being defensive; these classes do
// in some cases rely on zero filled constuct state
void *System::operator new(std::size_t size)
{
void *p = ::operator new(size);
std::memset(p, 0, size);
return p;
}
System::System()
{
gfx.sys = this;
memory.sys = this;
eeprom.sys = this;
rtc.sys = this;
sound.sys = this;
cpu.sys = this;
interrupt.sys = this;
}
System::~System()
{
}
int System::SaveRamSize() const
{
return eeprom.ieeprom_size + eeprom.eeprom_size + memory.sram_size;
}
bool System::SaveRamLoad(const uint8 *data, int size)
{
if (size != SaveRamSize())
return false;
#define LOAD(sz,ptr) { if (sz) { std::memcpy((ptr), data, (sz)); data += (sz); } }
LOAD(eeprom.ieeprom_size, eeprom.iEEPROM);
LOAD(eeprom.eeprom_size, eeprom.wsEEPROM);
LOAD(memory.sram_size, memory.wsSRAM);
#undef LOAD
return true;
}
bool System::SaveRamSave(uint8 *dest, int maxsize) const
{
if (maxsize != SaveRamSize())
return false;
#define SAVE(sz,ptr) { if (sz) { std::memcpy(dest, (ptr), (sz)); dest += (sz); } }
SAVE(eeprom.ieeprom_size, eeprom.iEEPROM);
SAVE(eeprom.eeprom_size, eeprom.wsEEPROM);
SAVE(memory.sram_size, memory.wsSRAM);
#undef SAVE
return true;
}
void System::PutSettings(const Settings &s)
{
gfx.SetLayerEnableMask(s.LayerMask);
gfx.SetBWPalette(s.BWPalette);
gfx.SetColorPalette(s.ColorPalette);
}
uint32 System::GetNECReg(int which) const
{
return cpu.get_reg(which);
}
bool System::GetMemoryArea(int index, const char *&name, int &size, uint8 *&data)
{
bool ret = true;
switch (index)
{
case 0: name = "RAM"; size = 65536; data = memory.wsRAM; break;
case 1: name = "ROM"; size = memory.rom_size; data = memory.wsCartROM; break;
case 2: name = "SRAM"; size = memory.sram_size; data = memory.wsSRAM; break;
case 3: name = "iEEPROM"; size = eeprom.ieeprom_size; data = eeprom.iEEPROM; break;
case 4: name = "EEPROM"; size = eeprom.eeprom_size; data = eeprom.wsEEPROM; break;
default: ret = false; break;
}
return ret;
}
SYNCFUNC(System)
{
SSS(gfx);
SSS(memory);
SSS(eeprom);
SSS(rtc);
SSS(sound);
SSS(cpu);
SSS(interrupt);
NSS(rotate);
NSS(oldbuttons);
}
EXPORT System *bizswan_new()
{
return new System();
}
EXPORT void bizswan_delete(System *s)
{
delete s;
}
EXPORT void bizswan_reset(System *s)
{
s->Reset();
}
EXPORT int bizswan_advance(System *s, uint32 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int *soundbuffsize, int *IsRotated)
{
int ret = s->Advance(buttons, novideo, surface, soundbuff, *soundbuffsize);
*IsRotated = s->rotate;
return ret;
}
EXPORT int bizswan_load(System *s, const uint8 *data, int length, const SyncSettings *settings, int *IsRotated)
{
bool ret = s->Load(data, length, *settings);
*IsRotated = s->rotate;
return ret;
}
EXPORT int bizswan_saveramsize(System *s)
{
return s->SaveRamSize();
}
EXPORT int bizswan_saveramload(System *s, const uint8 *data, int size)
{
return s->SaveRamLoad(data, size);
}
EXPORT int bizswan_saveramsave(System *s, uint8 *dest, int maxsize)
{
return s->SaveRamSave(dest, maxsize);
}
EXPORT void bizswan_putsettings(System *s, const Settings *settings)
{
s->PutSettings(*settings);
}
EXPORT uint32 bizswan_getnecreg(System *s, int which)
{
return s->GetNECReg(which);
}
EXPORT int bizswan_getmemoryarea(System *s, int index, const char **name, int *size, uint8 **data)
{
return s->GetMemoryArea(index, *name, *size, *data);
}
EXPORT int bizswan_binstatesize(System *s)
{
NewStateDummy dummy;
s->SyncState<false>(&dummy);
return dummy.GetLength();
}
EXPORT int bizswan_binstatesave(System *s, char *data, int length)
{
NewStateExternalBuffer saver(data, length);
s->SyncState<false>(&saver);
return !saver.Overflow() && saver.GetLength() == length;
}
EXPORT int bizswan_binstateload(System *s, const char *data, int length)
{
NewStateExternalBuffer loader(const_cast<char *>(data), length);
s->SyncState<true>(&loader);
return !loader.Overflow() && loader.GetLength() == length;
}
EXPORT void bizswan_txtstatesave(System *s, FPtrs *ff)
{
NewStateExternalFunctions saver(ff);
s->SyncState<false>(&saver);
}
EXPORT void bizswan_txtstateload(System *s, FPtrs *ff)
{
NewStateExternalFunctions loader(ff);
s->SyncState<true>(&loader);
}
EXPORT void bizswan_setmemorycallbacks(System *s, void (*rcb)(uint32), void (*ecb)(uint32), void (*wcb)(uint32))
{
s->cpu.ReadHook = rcb;
s->cpu.WriteHook = wcb;
s->cpu.ExecHook = ecb;
}
EXPORT void bizswan_setbuttoncallback(System *s, void (*bcb)())
{
s->memory.ButtonHook = bcb;
}
}