aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTa180m2020-05-17 20:53:50 -0500
committerTa180m2020-05-17 20:53:50 -0500
commit22fa8ebd178edb2067bb80c17b841a9885cd0864 (patch)
tree0011edd9dec286f39ed439d856fe65d66d470d35
parent7f2509e1e272eb94c8fab0c829754671daba0450 (diff)
Removed sound
-rw-r--r--lib/Blip_Buffer.cpp398
-rw-r--r--lib/Multi_Buffer.cpp201
-rw-r--r--lib/Nes_Apu.cpp341
-rw-r--r--lib/Nes_Namco.cpp160
-rw-r--r--lib/Nes_Oscs.cpp498
-rw-r--r--lib/Nes_Vrc6.cpp231
-rw-r--r--lib/Nonlinear_Buffer.cpp189
-rw-r--r--lib/Sound_Queue.cpp138
-rw-r--r--lib/apu_snapshot.cpp124
-rw-r--r--lib/include/Blip_Buffer.h253
-rw-r--r--lib/include/Blip_Synth.h203
-rw-r--r--lib/include/Multi_Buffer.h157
-rw-r--r--lib/include/Nes_Apu.h162
-rw-r--r--lib/include/Nes_Namco.h86
-rw-r--r--lib/include/Nes_Oscs.h142
-rw-r--r--lib/include/Nes_Vrc6.h85
-rw-r--r--lib/include/Nonlinear_Buffer.h65
-rw-r--r--lib/include/Sound_Queue.h44
-rw-r--r--lib/include/apu_snapshot.h75
-rw-r--r--lib/include/blargg_common.h180
-rw-r--r--lib/include/blargg_source.h43
-rw-r--r--lib/include/boost/config.hpp13
-rw-r--r--lib/include/boost/cstdint.hpp42
-rw-r--r--lib/include/boost/static_assert.hpp22
-rw-r--r--main.cpp (renamed from src/main.cpp)189
-rw-r--r--old/apu.cpp50
-rw-r--r--old/cartridge.cpp73
-rw-r--r--old/config.cpp155
-rw-r--r--old/cpu.cpp282
-rw-r--r--old/gui.cpp308
-rw-r--r--old/include/apu.hpp13
-rw-r--r--old/include/cartridge.hpp14
-rw-r--r--old/include/common.hpp10
-rw-r--r--old/include/config.hpp39
-rw-r--r--old/include/cpu.hpp32
-rw-r--r--old/include/gui.hpp30
-rw-r--r--old/include/joypad.hpp11
-rw-r--r--old/include/mapper.hpp32
-rw-r--r--old/include/mappers/mapper0.hpp13
-rw-r--r--old/include/mappers/mapper1.hpp23
-rw-r--r--old/include/mappers/mapper2.hpp22
-rw-r--r--old/include/mappers/mapper3.hpp24
-rw-r--r--old/include/mappers/mapper4.hpp35
-rw-r--r--old/include/menu.hpp73
-rw-r--r--old/include/ppu.hpp93
-rw-r--r--old/joypad.cpp33
-rw-r--r--old/main.cpp11
-rw-r--r--old/mapper.cpp72
-rw-r--r--old/mappers/mapper1.cpp82
-rw-r--r--old/mappers/mapper2.cpp40
-rw-r--r--old/mappers/mapper3.cpp50
-rw-r--r--old/mappers/mapper4.cpp78
-rw-r--r--old/menu.cpp151
-rw-r--r--old/palette.inc9
-rw-r--r--old/ppu.cpp353
-rw-r--r--res/font.ttfbin10656 -> 0 bytes
-rw-r--r--res/init.pngbin418232 -> 0 bytes
-rw-r--r--src/palette.inc9
58 files changed, 57 insertions, 6204 deletions
diff --git a/lib/Blip_Buffer.cpp b/lib/Blip_Buffer.cpp
deleted file mode 100644
index db72188..0000000
--- a/lib/Blip_Buffer.cpp
+++ /dev/null
@@ -1,398 +0,0 @@
-
-// Blip_Buffer 0.3.3. http://www.slack.net/~ant/libs/
-
-#include "Blip_Buffer.h"
-
-#include <string.h>
-#include <math.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
-
-Blip_Buffer::Blip_Buffer()
-{
- samples_per_sec = 44100;
- buffer_ = NULL;
-
- // try to cause assertion failure if buffer is used before these are set
- clocks_per_sec = 0;
- factor_ = ~0ul;
- offset_ = 0;
- buffer_size_ = 0;
- length_ = 0;
-
- bass_freq_ = 16;
-}
-
-void Blip_Buffer::clear( bool entire_buffer )
-{
- long count = (entire_buffer ? buffer_size_ : samples_avail());
- offset_ = 0;
- reader_accum = 0;
- memset( buffer_, sample_offset & 0xFF, (count + widest_impulse_) * sizeof (buf_t_) );
-}
-
-blargg_err_t Blip_Buffer::sample_rate( long new_rate, int msec )
-{
- unsigned new_size = (UINT_MAX >> BLIP_BUFFER_ACCURACY) + 1 - widest_impulse_ - 64;
- if ( msec != blip_default_length )
- {
- size_t s = (new_rate * (msec + 1) + 999) / 1000;
- if ( s < new_size )
- new_size = s;
- else
- require( false ); // requested buffer length exceeds limit
- }
-
- if ( buffer_size_ != new_size )
- {
- delete [] buffer_;
- buffer_ = NULL; // allow for exception in allocation below
- buffer_size_ = 0;
- offset_ = 0;
-
- buffer_ = BLARGG_NEW buf_t_ [new_size + widest_impulse_];
- BLARGG_CHECK_ALLOC( buffer_ );
- }
-
- buffer_size_ = new_size;
- length_ = new_size * 1000 / new_rate - 1;
- if ( msec )
- assert( length_ == msec ); // ensure length is same as that passed in
-
- samples_per_sec = new_rate;
- if ( clocks_per_sec )
- clock_rate( clocks_per_sec ); // recalculate factor
-
- bass_freq( bass_freq_ ); // recalculate shift
-
- clear();
-
- return blargg_success;
-}
-
-void Blip_Buffer::clock_rate( long cps )
-{
- clocks_per_sec = cps;
- factor_ = (unsigned long) floor( (double) samples_per_sec / cps *
- (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
- require( factor_ > 0 ); // clock_rate/sample_rate ratio is too large
-}
-
-Blip_Buffer::~Blip_Buffer()
-{
- delete [] buffer_;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- if ( freq == 0 ) {
- bass_shift = 31; // 32 or greater invokes undefined behavior elsewhere
- return;
- }
- bass_shift = 1 + (int) floor( 1.442695041 * log( 0.124 * samples_per_sec / freq ) );
- if ( bass_shift < 0 )
- bass_shift = 0;
- if ( bass_shift > 24 )
- bass_shift = 24;
-}
-
-long Blip_Buffer::count_samples( blip_time_t t ) const {
- return (resampled_time( t ) >> BLIP_BUFFER_ACCURACY) - (offset_ >> BLIP_BUFFER_ACCURACY);
-}
-
-void Blip_Impulse_::init( blip_pair_t_* imps, int w, int r, int fb )
-{
- fine_bits = fb;
- width = w;
- impulses = (imp_t*) imps;
- generate = true;
- volume_unit_ = -1.0;
- res = r;
- buf = NULL;
-
- impulse = &impulses [width * res * 2 * (fine_bits ? 2 : 1)];
- offset = 0;
-}
-
-const int impulse_bits = 15;
-const long impulse_amp = 1L << impulse_bits;
-const long impulse_offset = impulse_amp / 2;
-
-void Blip_Impulse_::scale_impulse( int unit, imp_t* imp_in ) const
-{
- long offset = ((long) unit << impulse_bits) - impulse_offset * unit +
- (1 << (impulse_bits - 1));
- imp_t* imp = imp_in;
- imp_t* fimp = impulse;
- for ( int n = res / 2 + 1; n--; )
- {
- int error = unit;
- for ( int nn = width; nn--; )
- {
- long a = ((long) *fimp++ * unit + offset) >> impulse_bits;
- error -= a - unit;
- *imp++ = (imp_t) a;
- }
-
- // add error to middle
- imp [-width / 2 - 1] += (imp_t) error;
- }
-
- if ( res > 2 ) {
- // second half is mirror-image
- const imp_t* rev = imp - width - 1;
- for ( int nn = (res / 2 - 1) * width - 1; nn--; )
- *imp++ = *--rev;
- *imp++ = (imp_t) unit;
- }
-
- // copy to odd offset
- *imp++ = (imp_t) unit;
- memcpy( imp, imp_in, (res * width - 1) * sizeof *imp );
-}
-
-const int max_res = 1 << blip_res_bits_;
-
-void Blip_Impulse_::fine_volume_unit()
-{
- // to do: find way of merging in-place without temporary buffer
-
- imp_t temp [max_res * 2 * Blip_Buffer::widest_impulse_];
- scale_impulse( (offset & 0xffff) << fine_bits, temp );
- imp_t* imp2 = impulses + res * 2 * width;
- scale_impulse( offset & 0xffff, imp2 );
-
- // merge impulses
- imp_t* imp = impulses;
- imp_t* src2 = temp;
- for ( int n = res / 2 * 2 * width; n--; ) {
- *imp++ = *imp2++;
- *imp++ = *imp2++;
- *imp++ = *src2++;
- *imp++ = *src2++;
- }
-}
-
-void Blip_Impulse_::volume_unit( double new_unit )
-{
- if ( new_unit == volume_unit_ )
- return;
-
- if ( generate )
- treble_eq( blip_eq_t( -8.87, 8800, 44100 ) );
-
- volume_unit_ = new_unit;
-
- offset = 0x10001 * (unsigned long) floor( volume_unit_ * 0x10000 + 0.5 );
-
- if ( fine_bits )
- fine_volume_unit();
- else
- scale_impulse( offset & 0xffff, impulses );
-}
-
-static const double pi = 3.1415926535897932384626433832795029L;
-
-void Blip_Impulse_::treble_eq( const blip_eq_t& new_eq )
-{
- if ( !generate && new_eq.treble == eq.treble && new_eq.cutoff == eq.cutoff &&
- new_eq.sample_rate == eq.sample_rate )
- return; // already calculated with same parameters
-
- generate = false;
- eq = new_eq;
-
- double treble = pow( 10.0, 1.0 / 20 * eq.treble ); // dB (-6dB = 0.50)
- if ( treble < 0.000005 )
- treble = 0.000005;
-
- const double treble_freq = 22050.0; // treble level at 22 kHz harmonic
- const double sample_rate = eq.sample_rate;
- const double pt = treble_freq * 2 / sample_rate;
- double cutoff = eq.cutoff * 2 / sample_rate;
- if ( cutoff >= pt * 0.95 || cutoff >= 0.95 ) {
- cutoff = 0.5;
- treble = 1.0;
- }
-
- // DSF Synthesis (See T. Stilson & J. Smith (1996),
- // Alias-free digital synthesis of classic analog waveforms)
-
- // reduce adjacent impulse interference by using small part of wide impulse
- const double n_harm = 4096;
- const double rolloff = pow( treble, 1.0 / (n_harm * pt - n_harm * cutoff) );
- const double rescale = 1.0 / pow( rolloff, n_harm * cutoff );
-
- const double pow_a_n = rescale * pow( rolloff, n_harm );
- const double pow_a_nc = rescale * pow( rolloff, n_harm * cutoff );
-
- double total = 0.0;
- const double to_angle = pi / 2 / n_harm / max_res;
-
- float buf [max_res * (Blip_Buffer::widest_impulse_ - 2) / 2];
- const int size = max_res * (width - 2) / 2;
- for ( int i = size; i--; )
- {
- double angle = (i * 2 + 1) * to_angle;
-
- // equivalent
- //double y = dsf( angle, n_harm * cutoff, 1.0 );
- //y -= rescale * dsf( angle, n_harm * cutoff, rolloff );
- //y += rescale * dsf( angle, n_harm, rolloff );
-
- const double cos_angle = cos( angle );
- const double cos_nc_angle = cos( n_harm * cutoff * angle );
- const double cos_nc1_angle = cos( (n_harm * cutoff - 1.0) * angle );
-
- double b = 2.0 - 2.0 * cos_angle;
- double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
-
- double d = 1.0 + rolloff * (rolloff - 2.0 * cos_angle);
- double c = pow_a_n * rolloff * cos( (n_harm - 1.0) * angle ) -
- pow_a_n * cos( n_harm * angle ) -
- pow_a_nc * rolloff * cos_nc1_angle +
- pow_a_nc * cos_nc_angle;
-
- // optimization of a / b + c / d
- double y = (a * d + c * b) / (b * d);
-
- // fixed window which affects wider impulses more
- if ( width > 12 ) {
- double window = cos( n_harm / 1.25 / Blip_Buffer::widest_impulse_ * angle );
- y *= window * window;
- }
-
- total += (float) y;
- buf [i] = (float) y;
- }
-
- // integrate runs of length 'max_res'
- double factor = impulse_amp * 0.5 / total; // 0.5 accounts for other mirrored half
- imp_t* imp = impulse;
- const int step = max_res / res;
- int offset = res > 1 ? max_res : max_res / 2;
- for ( int n = res / 2 + 1; n--; offset -= step )
- {
- for ( int w = -width / 2; w < width / 2; w++ )
- {
- double sum = 0;
- for ( int i = max_res; i--; )
- {
- int index = w * max_res + offset + i;
- if ( index < 0 )
- index = -index - 1;
- if ( index < size )
- sum += buf [index];
- }
- *imp++ = (imp_t) floor( sum * factor + (impulse_offset + 0.5) );
- }
- }
-
- // rescale
- double unit = volume_unit_;
- if ( unit >= 0 ) {
- volume_unit_ = -1;
- volume_unit( unit );
- }
-}
-
-void Blip_Buffer::remove_samples( long count )
-{
- require( buffer_ ); // sample rate must have been set
-
- if ( !count ) // optimization
- return;
-
- remove_silence( count );
-
- // Allows synthesis slightly past time passed to end_frame(), as long as it's
- // not more than an output sample.
- // to do: kind of hacky, could add run_until() which keeps track of extra synthesis
- int const copy_extra = 1;
-
- // copy remaining samples to beginning and clear old samples
- long remain = samples_avail() + widest_impulse_ + copy_extra;
- if ( count >= remain )
- memmove( buffer_, buffer_ + count, remain * sizeof (buf_t_) );
- else
- memcpy( buffer_, buffer_ + count, remain * sizeof (buf_t_) );
- memset( buffer_ + remain, sample_offset & 0xFF, count * sizeof (buf_t_) );
-}
-
-#include BLARGG_ENABLE_OPTIMIZER
-
-long Blip_Buffer::read_samples( blip_sample_t* out, long max_samples, bool stereo )
-{
- require( buffer_ ); // sample rate must have been set
-
- long count = samples_avail();
- if ( count > max_samples )
- count = max_samples;
-
- if ( !count )
- return 0; // optimization
-
- int sample_offset = this->sample_offset;
- int bass_shift = this->bass_shift;
- buf_t_* buf = buffer_;
- long accum = reader_accum;
-
- if ( !stereo ) {
- for ( long n = count; n--; ) {
- long s = accum >> accum_fract;
- accum -= accum >> bass_shift;
- accum += (long (*buf++) - sample_offset) << accum_fract;
- *out++ = (blip_sample_t) s;
-
- // clamp sample
- if ( (BOOST::int16_t) s != s )
- out [-1] = blip_sample_t (0x7FFF - (s >> 24));
- }
- }
- else {
- for ( long n = count; n--; ) {
- long s = accum >> accum_fract;
- accum -= accum >> bass_shift;
- accum += (long (*buf++) - sample_offset) << accum_fract;
- *out = (blip_sample_t) s;
- out += 2;
-
- // clamp sample
- if ( (BOOST::int16_t) s != s )
- out [-2] = blip_sample_t (0x7FFF - (s >> 24));
- }
- }
-
- reader_accum = accum;
-
- remove_samples( count );
-
- return count;
-}
-
-void Blip_Buffer::mix_samples( const blip_sample_t* in, long count )
-{
- buf_t_* buf = &buffer_ [(offset_ >> BLIP_BUFFER_ACCURACY) + (widest_impulse_ / 2 - 1)];
-
- int prev = 0;
- while ( count-- ) {
- int s = *in++;
- *buf += s - prev;
- prev = s;
- ++buf;
- }
- *buf -= *--in;
-}
-
diff --git a/lib/Multi_Buffer.cpp b/lib/Multi_Buffer.cpp
deleted file mode 100644
index dd459eb..0000000
--- a/lib/Multi_Buffer.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-
-// Blip_Buffer 0.3.3. http://www.slack.net/~ant/libs/
-
-#include "Multi_Buffer.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
-
-Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
-{
- length_ = 0;
- sample_rate_ = 0;
-}
-
-blargg_err_t Multi_Buffer::set_channel_count( int )
-{
- return blargg_success;
-}
-
-Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
-{
-}
-
-Mono_Buffer::~Mono_Buffer()
-{
-}
-
-blargg_err_t Mono_Buffer::sample_rate( long rate, int msec )
-{
- BLARGG_RETURN_ERR( buf.sample_rate( rate, msec ) );
- return Multi_Buffer::sample_rate( buf.sample_rate(), buf.length() );
-}
-
-Mono_Buffer::channel_t Mono_Buffer::channel( int index )
-{
- channel_t ch;
- ch.center = &buf;
- ch.left = &buf;
- ch.right = &buf;
- return ch;
-}
-
-void Mono_Buffer::end_frame( blip_time_t t, bool )
-{
- buf.end_frame( t );
-}
-
-Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
-{
- chan.center = &bufs [0];
- chan.left = &bufs [1];
- chan.right = &bufs [2];
-}
-
-Stereo_Buffer::~Stereo_Buffer()
-{
-}
-
-blargg_err_t Stereo_Buffer::sample_rate( long rate, int msec )
-{
- for ( int i = 0; i < buf_count; i++ )
- BLARGG_RETURN_ERR( bufs [i].sample_rate( rate, msec ) );
- return Multi_Buffer::sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Stereo_Buffer::clock_rate( long rate )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clock_rate( rate );
-}
-
-void Stereo_Buffer::bass_freq( int bass )
-{
- for ( unsigned i = 0; i < buf_count; i++ )
- bufs [i].bass_freq( bass );
-}
-
-void Stereo_Buffer::clear()
-{
- stereo_added = false;
- was_stereo = false;
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clear();
-}
-
-void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo )
-{
- for ( unsigned i = 0; i < buf_count; i++ )
- bufs [i].end_frame( clock_count );
-
- stereo_added |= stereo;
-}
-
-long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
-{
- require( !(count & 1) ); // count must be even
- count = (unsigned) count / 2;
-
- long avail = bufs [0].samples_avail();
- if ( count > avail )
- count = avail;
- if ( count )
- {
- if ( stereo_added || was_stereo )
- {
- mix_stereo( out, count );
-
- bufs [0].remove_samples( count );
- bufs [1].remove_samples( count );
- bufs [2].remove_samples( count );
- }
- else
- {
- mix_mono( out, count );
-
- bufs [0].remove_samples( count );
-
- bufs [1].remove_silence( count );
- bufs [2].remove_silence( count );
- }
-
- // to do: this might miss opportunities for optimization
- if ( !bufs [0].samples_avail() ) {
- was_stereo = stereo_added;
- stereo_added = false;
- }
- }
-
- return count * 2;
-}
-
-#include BLARGG_ENABLE_OPTIMIZER
-
-void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count )
-{
- Blip_Reader left;
- Blip_Reader right;
- Blip_Reader center;
-
- left.begin( bufs [1] );
- right.begin( bufs [2] );
- int bass = center.begin( bufs [0] );
-
- while ( count-- )
- {
- int c = center.read();
- long l = c + left.read();
- long r = c + right.read();
- center.next( bass );
- out [0] = l;
- out [1] = r;
- out += 2;
-
- if ( (BOOST::int16_t) l != l )
- out [-2] = 0x7FFF - (l >> 24);
-
- left.next( bass );
- right.next( bass );
-
- if ( (BOOST::int16_t) r != r )
- out [-1] = 0x7FFF - (r >> 24);
- }
-
- center.end( bufs [0] );
- right.end( bufs [2] );
- left.end( bufs [1] );
-}
-
-void Stereo_Buffer::mix_mono( blip_sample_t* out, long count )
-{
- Blip_Reader in;
- int bass = in.begin( bufs [0] );
-
- while ( count-- )
- {
- long s = in.read();
- in.next( bass );
- out [0] = s;
- out [1] = s;
- out += 2;
-
- if ( (BOOST::int16_t) s != s ) {
- s = 0x7FFF - (s >> 24);
- out [-2] = s;
- out [-1] = s;
- }
- }
-
- in.end( bufs [0] );
-}
-
diff --git a/lib/Nes_Apu.cpp b/lib/Nes_Apu.cpp
deleted file mode 100644
index 5b1fdc5..0000000
--- a/lib/Nes_Apu.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-
-// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/
-
-#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 */
-
-#include BLARGG_SOURCE_BEGIN
-
-Nes_Apu::Nes_Apu()
-{
- dmc.apu = this;
- dmc.rom_reader = NULL;
- square1.synth = &square_synth;
- square2.synth = &square_synth;
- irq_notifier_ = NULL;
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &triangle;
- oscs [3] = &noise;
- oscs [4] = &dmc;
-
- output( NULL );
- volume( 1.0 );
- reset( false );
-}
-
-Nes_Apu::~Nes_Apu()
-{
-}
-
-void Nes_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- triangle.synth.treble_eq( eq );
- noise.synth.treble_eq( eq );
- dmc.synth.treble_eq( eq );
-}
-
-void Nes_Apu::buffer_cleared()
-{
- square1.last_amp = 0;
- square2.last_amp = 0;
- triangle.last_amp = 0;
- noise.last_amp = 0;
- dmc.last_amp = 0;
-}
-
-void Nes_Apu::enable_nonlinear( double v )
-{
- dmc.nonlinear = true;
- square_synth.volume( 1.3 * 0.25751258 / 0.742467605 * 0.25 * v );
-
- const double tnd = 0.75 / 202 * 0.48;
- triangle.synth.volume_unit( 3 * tnd );
- noise.synth.volume_unit( 2 * tnd );
- dmc.synth.volume_unit( tnd );
-
- buffer_cleared();
-}
-
-void Nes_Apu::volume( double v )
-{
- dmc.nonlinear = false;
- square_synth.volume( 0.1128 * v );
- triangle.synth.volume( 0.12765 * v );
- noise.synth.volume( 0.0741 * v );
- dmc.synth.volume( 0.42545 * v );
-}
-
-void Nes_Apu::output( Blip_Buffer* buffer )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buffer );
-}
-
-void Nes_Apu::reset( bool pal_mode, int initial_dmc_dac )
-{
- // to do: time pal frame periods exactly
- frame_period = pal_mode ? 8314 : 7458;
- dmc.pal_mode = pal_mode;
-
- square1.reset();
- square2.reset();
- triangle.reset();
- noise.reset();
- dmc.reset();
-
- last_time = 0;
- osc_enables = 0;
- irq_flag = false;
- earliest_irq_ = no_irq;
- frame_delay = 1;
- write_register( 0, 0x4017, 0x00 );
- write_register( 0, 0x4015, 0x00 );
-
- for ( cpu_addr_t addr = start_addr; addr <= 0x4013; addr++ )
- write_register( 0, addr, (addr & 3) ? 0x00 : 0x10 );
-
- dmc.dac = initial_dmc_dac;
- if ( !dmc.nonlinear )
- dmc.last_amp = initial_dmc_dac; // prevent output transition
-}
-
-void Nes_Apu::irq_changed()
-{
- cpu_time_t new_irq = dmc.next_irq;
- if ( dmc.irq_flag | irq_flag ) {
- new_irq = 0;
- }
- else if ( new_irq > next_irq ) {
- new_irq = next_irq;
- }
-
- if ( new_irq != earliest_irq_ ) {
- earliest_irq_ = new_irq;
- if ( irq_notifier_ )
- irq_notifier_( irq_data );
- }
-}
-
-// frames
-
-void Nes_Apu::run_until( cpu_time_t end_time )
-{
- require( end_time >= last_time );
-
- if ( end_time == last_time )
- return;
-
- while ( true )
- {
- // earlier of next frame time or end time
- cpu_time_t time = last_time + frame_delay;
- if ( time > end_time )
- time = end_time;
- frame_delay -= time - last_time;
-
- // run oscs to present
- square1.run( last_time, time );
- square2.run( last_time, time );
- triangle.run( last_time, time );
- noise.run( last_time, time );
- dmc.run( last_time, time );
- last_time = time;
-
- if ( time == end_time )
- break; // no more frames to run
-
- // take frame-specific actions
- frame_delay = frame_period;
- switch ( frame++ )
- {
- case 0:
- if ( !(frame_mode & 0xc0) ) {
- next_irq = time + frame_period * 4 + 1;
- irq_flag = true;
- }
- // fall through
- case 2:
- // clock length and sweep on frames 0 and 2
- square1.clock_length( 0x20 );
- square2.clock_length( 0x20 );
- noise.clock_length( 0x20 );
- triangle.clock_length( 0x80 ); // different bit for halt flag on triangle
-
- square1.clock_sweep( -1 );
- square2.clock_sweep( 0 );
- break;
-
- case 1:
- // frame 1 is slightly shorter
- frame_delay -= 2;
- break;
-
- case 3:
- frame = 0;
-
- // frame 3 is almost twice as long in mode 1
- if ( frame_mode & 0x80 )
- frame_delay += frame_period - 6;
- break;
- }
-
- // clock envelopes and linear counter every frame
- triangle.clock_linear_counter();
- square1.clock_envelope();
- square2.clock_envelope();
- noise.clock_envelope();
- }
-}
-
-void Nes_Apu::end_frame( cpu_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- // make times relative to new frame
- last_time -= end_time;
- require( last_time >= 0 );
-
- if ( next_irq != no_irq ) {
- next_irq -= end_time;
- assert( next_irq >= 0 );
- }
- if ( dmc.next_irq != no_irq ) {
- dmc.next_irq -= end_time;
- assert( dmc.next_irq >= 0 );
- }
- if ( earliest_irq_ != no_irq ) {
- earliest_irq_ -= end_time;
- if ( earliest_irq_ < 0 )
- earliest_irq_ = 0;
- }
-}
-
-// registers
-
-static const unsigned char length_table [0x20] = {
- 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
- 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
- 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
- 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
-};
-
-void Nes_Apu::write_register( cpu_time_t time, cpu_addr_t addr, int data )
-{
- require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
- require( (unsigned) data <= 0xff );
-
- // Ignore addresses outside range
- if ( addr < start_addr || end_addr < addr )
- return;
-
- run_until( time );
-
- if ( addr < 0x4014 )
- {
- // Write to channel
- int osc_index = (addr - start_addr) >> 2;
- Nes_Osc* osc = oscs [osc_index];
-
- int reg = addr & 3;
- osc->regs [reg] = data;
- osc->reg_written [reg] = true;
-
- if ( osc_index == 4 )
- {
- // handle DMC specially
- dmc.write_register( reg, data );
- }
- else if ( reg == 3 )
- {
- // load length counter
- if ( (osc_enables >> osc_index) & 1 )
- osc->length_counter = length_table [(data >> 3) & 0x1f];
-
- // reset square phase
- if ( osc_index < 2 )
- ((Nes_Square*) osc)->phase = Nes_Square::phase_range - 1;
- }
- }
- else if ( addr == 0x4015 )
- {
- // Channel enables
- for ( int i = osc_count; i--; )
- if ( !((data >> i) & 1) )
- oscs [i]->length_counter = 0;
-
- bool recalc_irq = dmc.irq_flag;
- dmc.irq_flag = false;
-
- int old_enables = osc_enables;
- osc_enables = data;
- if ( !(data & 0x10) ) {
- dmc.next_irq = no_irq;
- recalc_irq = true;
- }
- else if ( !(old_enables & 0x10) ) {
- dmc.start(); // dmc just enabled
- }
-
- if ( recalc_irq )
- irq_changed();
- }
- else if ( addr == 0x4017 )
- {
- // Frame mode
- frame_mode = data;
-
- bool irq_enabled = !(data & 0x40);
- irq_flag &= irq_enabled;
- next_irq = no_irq;
-
- // mode 1
- frame_delay = (frame_delay & 1);
- frame = 0;
-
- if ( !(data & 0x80) )
- {
- // mode 0
- frame = 1;
- frame_delay += frame_period;
- if ( irq_enabled )
- next_irq = time + frame_delay + frame_period * 3;
- }
-
- irq_changed();
- }
-}
-
-int Nes_Apu::read_status( cpu_time_t time )
-{
- run_until( time - 1 );
-
- int result = (dmc.irq_flag << 7) | (irq_flag << 6);
-
- for ( int i = 0; i < osc_count; i++ )
- if ( oscs [i]->length_counter )
- result |= 1 << i;
-
- run_until( time );
-
- if ( irq_flag ) {
- irq_flag = false;
- irq_changed();
- }
-
- return result;
-}
-
diff --git a/lib/Nes_Namco.cpp b/lib/Nes_Namco.cpp
deleted file mode 100644
index 89fdf86..0000000
--- a/lib/Nes_Namco.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-
-// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/
-
-#include "Nes_Namco.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_Namco::Nes_Namco()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-Nes_Namco::~Nes_Namco()
-{
-}
-
-void Nes_Namco::reset()
-{
- addr_reg = 0;
-
- int i;
- for ( i = 0; i < reg_count; i++ )
- reg [i] = 0;
-
- for ( i = 0; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- osc.delay = 0;
- osc.last_amp = 0;
- osc.wave_pos = 0;
- }
-}
-
-void Nes_Namco::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-BOOST::uint8_t& Nes_Namco::access()
-{
- int addr = addr_reg & 0x7f;
- if ( addr_reg & 0x80 )
- addr_reg = (addr + 1) | 0x80;
- return reg [addr];
-}
-
-/*
-void Nes_Namco::reflect_state( Tagged_Data& data )
-{
- reflect_int16( data, 'ADDR', &addr_reg );
-
- static const char hex [17] = "0123456789ABCDEF";
- int i;
- for ( i = 0; i < reg_count; i++ )
- reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], &reg [i] );
-
- for ( i = 0; i < osc_count; i++ )
- {
- reflect_int32( data, 'DLY0' + i, &oscs [i].delay );
- reflect_int16( data, 'POS0' + i, &oscs [i].wave_pos );
- }
-}
-*/
-
-void Nes_Namco::end_frame( cpu_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- last_time -= time;
- assert( last_time >= 0 );
-}
-
-#include BLARGG_ENABLE_OPTIMIZER
-
-void Nes_Namco::run_until( cpu_time_t nes_end_time )
-{
- int active_oscs = ((reg [0x7f] >> 4) & 7) + 1;
- for ( int i = osc_count - active_oscs; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- Blip_Buffer* output = osc.output;
- if ( !output )
- continue;
-
- Blip_Buffer::resampled_time_t time =
- output->resampled_time( last_time ) + osc.delay;
- Blip_Buffer::resampled_time_t end_time = output->resampled_time( nes_end_time );
- osc.delay = 0;
- if ( time < end_time )
- {
- const BOOST::uint8_t* osc_reg = &reg [i * 8 + 0x40];
- if ( !(osc_reg [4] & 0xe0) )
- continue;
-
- int volume = osc_reg [7] & 15;
- if ( !volume )
- continue;
-
- long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
- if ( !freq )
- continue;
- Blip_Buffer::resampled_time_t period =
- output->resampled_duration( 983040 ) / freq * active_oscs;
-
- int wave_size = (8 - ((osc_reg [4] >> 2) & 7)) * 4;
- if ( !wave_size )
- continue;
-
- int last_amp = osc.last_amp;
- int wave_pos = osc.wave_pos;
-
- do
- {
- // read wave sample
- int addr = wave_pos + osc_reg [6];
- int sample = reg [addr >> 1];
- wave_pos++;
- if ( addr & 1 )
- sample >>= 4;
- sample = (sample & 15) * volume;
-
- // output impulse if amplitude changed
- int delta = sample - last_amp;
- if ( delta )
- {
- last_amp = sample;
- synth.offset_resampled( time, delta, output );
- }
-
- // next sample
- time += period;
- if ( wave_pos >= wave_size )
- wave_pos = 0;
- }
- while ( time < end_time );
-
- osc.wave_pos = wave_pos;
- osc.last_amp = last_amp;
- }
- osc.delay = time - end_time;
- }
-
- last_time = nes_end_time;
-}
-
diff --git a/lib/Nes_Oscs.cpp b/lib/Nes_Oscs.cpp
deleted file mode 100644
index 272f62f..0000000
--- a/lib/Nes_Oscs.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-
-// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/
-
-#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 */
-
-#include BLARGG_SOURCE_BEGIN
-
-// Nes_Osc
-
-void Nes_Osc::clock_length( int halt_mask )
-{
- if ( length_counter && !(regs [0] & halt_mask) )
- length_counter--;
-}
-
-void Nes_Envelope::clock_envelope()
-{
- int period = regs [0] & 15;
- if ( reg_written [3] ) {
- reg_written [3] = false;
- env_delay = period;
- envelope = 15;
- }
- else if ( --env_delay < 0 ) {
- env_delay = period;
- if ( envelope | (regs [0] & 0x20) )
- envelope = (envelope - 1) & 15;
- }
-}
-
-int Nes_Envelope::volume() const
-{
- return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
-}
-
-// Nes_Square
-
-void Nes_Square::clock_sweep( int negative_adjust )
-{
- int sweep = regs [1];
-
- if ( --sweep_delay < 0 )
- {
- reg_written [1] = true;
-
- int period = this->period();
- int shift = sweep & shift_mask;
- if ( shift && (sweep & 0x80) && period >= 8 )
- {
- int offset = period >> shift;
-
- if ( sweep & negate_flag )
- offset = negative_adjust - offset;
-
- if ( period + offset < 0x800 )
- {
- period += offset;
- // rewrite period
- regs [2] = period & 0xff;
- regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
- }
- }
- }
-
- if ( reg_written [1] ) {
- reg_written [1] = false;
- sweep_delay = (sweep >> 4) & 7;
- }
-}
-
-void Nes_Square::run( cpu_time_t time, cpu_time_t end_time )
-{
- if ( !output )
- return;
-
- const int volume = this->volume();
- const int period = this->period();
- int offset = period >> (regs [1] & shift_mask);
- if ( regs [1] & negate_flag )
- offset = 0;
-
- const int timer_period = (period + 1) * 2;
- if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
- {
- if ( last_amp ) {
- synth->offset( time, -last_amp, output );
- last_amp = 0;
- }
-
- time += delay;
- if ( time < end_time )
- {
- // maintain proper phase
- int count = (end_time - time + timer_period - 1) / timer_period;
- phase = (phase + count) & (phase_range - 1);
- time += (long) count * timer_period;
- }
- }
- else
- {
- // handle duty select
- int duty_select = (regs [0] >> 6) & 3;
- int duty = 1 << duty_select; // 1, 2, 4, 2
- int amp = 0;
- if ( duty_select == 3 ) {
- duty = 2; // negated 25%
- amp = volume;
- }
- if ( phase < duty )
- amp ^= volume;
-
- int delta = update_amp( amp );
- if ( delta )
- synth->offset( time, delta, output );
-
- time += delay;
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- const Synth* synth = this->synth;
- int delta = amp * 2 - volume;
- int phase = this->phase;
-
- do {
- phase = (phase + 1) & (phase_range - 1);
- if ( phase == 0 || phase == duty ) {
- delta = -delta;
- synth->offset_inline( time, delta, output );
- }
- time += timer_period;
- }
- while ( time < end_time );
-
- last_amp = (delta + volume) >> 1;
- this->phase = phase;
- }
- }
-
- delay = time - end_time;
-}
-
-// Nes_Triangle
-
-void Nes_Triangle::clock_linear_counter()
-{
- if ( reg_written [3] )
- linear_counter = regs [0] & 0x7f;
- else if ( linear_counter )
- linear_counter--;
-
- if ( !(regs [0] & 0x80) )
- reg_written [3] = false;
-}
-
-inline int Nes_Triangle::calc_amp() const
-{
- int amp = phase_range - phase;
- if ( amp < 0 )
- amp = phase - (phase_range + 1);
- return amp;
-}
-
-void Nes_Triangle::run( cpu_time_t time, cpu_time_t end_time )
-{
- if ( !output )
- return;
-
- // to do: track phase when period < 3
- // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
-
- int delta = update_amp( calc_amp() );
- if ( delta )
- synth.offset( time, delta, output );
-
- time += delay;
- const int timer_period = period() + 1;
- if ( length_counter == 0 || linear_counter == 0 || timer_period < 3 )
- {
- time = end_time;
- }
- else if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
-
- int phase = this->phase;
- int volume = 1;
- if ( phase > phase_range ) {
- phase -= phase_range;
- volume = -volume;
- }
-
- do {
- if ( --phase == 0 ) {
- phase = phase_range;
- volume = -volume;
- }
- else {
- synth.offset_inline( time, volume, output );
- }
-
- time += timer_period;
- }
- while ( time < end_time );
-
- if ( volume < 0 )
- phase += phase_range;
- this->phase = phase;
- last_amp = calc_amp();
- }
- delay = time - end_time;
-}
-
-// Nes_Dmc
-
-void Nes_Dmc::reset()
-{
- address = 0;
- dac = 0;
- buf = 0;
- bits_remain = 1;
- bits = 0;
- buf_empty = true;
- silence = true;
- next_irq = Nes_Apu::no_irq;
- irq_flag = false;
- irq_enabled = false;
-
- Nes_Osc::reset();
- period = 0x036;
-}
-
-void Nes_Dmc::recalc_irq()
-{
- cpu_time_t irq = Nes_Apu::no_irq;
- if ( irq_enabled && length_counter )
- irq = apu->last_time + delay +
- ((length_counter - 1) * 8 + bits_remain - 1) * cpu_time_t (period) + 1;
- if ( irq != next_irq ) {
- next_irq = irq;
- apu->irq_changed();
- }
-}
-
-int Nes_Dmc::count_reads( cpu_time_t time, cpu_time_t* last_read ) const
-{
- if ( last_read )
- *last_read = time;
-
- if ( length_counter == 0 )
- return 0; // not reading
-
- long first_read = apu->last_time + delay + long (bits_remain - 1) * period;
- long avail = time - first_read;
- if ( avail <= 0 )
- return 0;
-
- int count = (avail - 1) / (period * 8) + 1;
- if ( !(regs [0] & loop_flag) && count > length_counter )
- count = length_counter;
-
- if ( last_read ) {
- *last_read = first_read + (count - 1) * (period * 8) + 1;
- assert( *last_read <= time );
- assert( count == count_reads( *last_read, NULL ) );
- assert( count - 1 == count_reads( *last_read - 1, NULL ) );
- }
-
- return count;
-}
-
-static const short dmc_period_table [2] [16] = {
- 0x1ac, 0x17c, 0x154, 0x140, 0x11e, 0x0fe, 0x0e2, 0x0d6, // NTSC
- 0x0be, 0x0a0, 0x08e, 0x080, 0x06a, 0x054, 0x048, 0x036,
-
- 0x18e, 0x161, 0x13c, 0x129, 0x10a, 0x0ec, 0x0d2, 0x0c7, // PAL (totally untested)
- 0x0b1, 0x095, 0x084, 0x077, 0x062, 0x04e, 0x043, 0x032 // to do: verify PAL periods
-};
-
-inline void Nes_Dmc::reload_sample()
-{
- address = 0x4000 + regs [2] * 0x40;
- length_counter = regs [3] * 0x10 + 1;
-}
-
-static const unsigned char dac_table [128] = {
- 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9,
- 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16, 17, 17, 18, 18,
- 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26,
- 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 32, 33, 33, 34,
- 34, 35, 35, 35, 36, 36, 37, 37, 38, 38, 38, 39, 39, 40, 40, 40,
- 41, 41, 42, 42, 42, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 47,
- 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52,
- 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57
-};
-
-void Nes_Dmc::write_register( int addr, int data )
-{
- if ( addr == 0 ) {
- period = dmc_period_table [pal_mode] [data & 15];
- irq_enabled = (data & 0xc0) == 0x80; // enabled only if loop disabled
- irq_flag &= irq_enabled;
- recalc_irq();
- }
- else if ( addr == 1 )
- {
- if ( !nonlinear )
- {
- // adjust last_amp so that "pop" amplitude will be properly non-linear
- // with respect to change in dac
- int old_amp = dac_table [dac];
- dac = data & 0x7F;
- int diff = dac_table [dac] - old_amp;
- last_amp = dac - diff;
- }
-
- dac = data & 0x7F;
- }
-}
-
-void Nes_Dmc::start()
-{
- reload_sample();
- fill_buffer();
- recalc_irq();
-}
-
-void Nes_Dmc::fill_buffer()
-{
- if ( buf_empty && length_counter )
- {
- require( rom_reader ); // rom_reader must be set
- buf = rom_reader( rom_reader_data, 0x8000u + address );
- address = (address + 1) & 0x7FFF;
- buf_empty = false;
- if ( --length_counter == 0 )
- {
- if ( regs [0] & loop_flag ) {
- reload_sample();
- }
- else {
- apu->osc_enables &= ~0x10;
- irq_flag = irq_enabled;
- next_irq = Nes_Apu::no_irq;
- apu->irq_changed();
- }
- }
- }
-}
-
-void Nes_Dmc::run( cpu_time_t time, cpu_time_t end_time )
-{
- if ( !output )
- return;
-
- int delta = update_amp( dac );
- if ( delta )
- synth.offset( time, delta, output );
-
- time += delay;
- if ( time < end_time )
- {
- int bits_remain = this->bits_remain;
- if ( silence && buf_empty )
- {
- int count = (end_time - time + period - 1) / period;
- bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
- time += count * period;
- }
- else
- {
- Blip_Buffer* const output = this->output;
- const int period = this->period;
- int bits = this->bits;
- int dac = this->dac;
-
- do
- {
- if ( !silence )
- {
- const int step = (bits & 1) * 4 - 2;
- bits >>= 1;
- if ( unsigned (dac + step) <= 0x7F ) {
- dac += step;
- synth.offset_inline( time, step, output );
- }
- }
-
- time += period;
-
- if ( --bits_remain == 0 )
- {
- bits_remain = 8;
- if ( buf_empty ) {
- silence = true;
- }
- else {
- silence = false;
- bits = buf;
- buf_empty = true;
- fill_buffer();
- }
- }
- }
- while ( time < end_time );
-
- this->dac = dac;
- this->last_amp = dac;
- this->bits = bits;
- }
- this->bits_remain = bits_remain;
- }
- delay = time - end_time;
-}
-
-// Nes_Noise
-
-#include BLARGG_ENABLE_OPTIMIZER
-
-static const short noise_period_table [16] = {
- 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
- 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
-};
-
-void Nes_Noise::run( cpu_time_t time, cpu_time_t end_time )
-{
- if ( !output )
- return;
-
- const int volume = this->volume();
- int amp = (noise & 1) ? volume : 0;
- int delta = update_amp( amp );
- if ( delta )
- synth.offset( time, delta, output );
-
- time += delay;
- if ( time < end_time )
- {
- const int mode_flag = 0x80;
-
- int period = noise_period_table [regs [2] & 15];
- if ( !volume )
- {
- // round to next multiple of period
- time += (end_time - time + period - 1) / period * period;
-
- // approximate noise cycling while muted, by shuffling up noise register
- // to do: precise muted noise cycling?
- if ( !(regs [2] & mode_flag) ) {
- int feedback = (noise << 13) ^ (noise << 14);
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- }
- else
- {
- Blip_Buffer* const output = this->output;
-
- // using resampled time avoids conversion in synth.offset()
- Blip_Buffer::resampled_time_t rperiod = output->resampled_duration( period );
- Blip_Buffer::resampled_time_t rtime = output->resampled_time( time );
-
- int noise = this->noise;
- int delta = amp * 2 - volume;
- const int tap = (regs [2] & mode_flag ? 8 : 13);
-
- do {
- int feedback = (noise << tap) ^ (noise << 14);
- time += period;
-
- if ( (noise + 1) & 2 ) {
- // bits 0 and 1 of noise differ
- delta = -delta;
- synth.offset_resampled( rtime, delta, output );
- }
-
- rtime += rperiod;
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- while ( time < end_time );
-
- last_amp = (delta + volume) >> 1;
- this->noise = noise;
- }
- }
-
- delay = time - end_time;
-}
-
diff --git a/lib/Nes_Vrc6.cpp b/lib/Nes_Vrc6.cpp
deleted file mode 100644
index e57e8a5..0000000
--- a/lib/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 )
-{
- v *= 0.0967 * 2;
- saw_synth.volume( v );
- square_synth.volume( v * 0.5 );
-}
-
-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( cpu_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( cpu_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( cpu_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, cpu_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;
- cpu_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( cpu_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;
- cpu_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/lib/Nonlinear_Buffer.cpp b/lib/Nonlinear_Buffer.cpp
deleted file mode 100644
index 447318e..0000000
--- a/lib/Nonlinear_Buffer.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-
-// Nes_Snd_Emu 0.1.7. 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 * 0.75; // to do: must match that in Nes_Apu.cpp
- 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 = 0x7f7f; // to do: use private constant from Blip_Buffer.h
-
- #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/lib/Sound_Queue.cpp b/lib/Sound_Queue.cpp
deleted file mode 100644
index 4577681..0000000
--- a/lib/Sound_Queue.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-
-// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/
-
-#include "Sound_Queue.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Copyright (C) 2005 by Shay Green. Permission is hereby granted, free of
-charge, to any person obtaining a copy of this software module and associated
-documentation files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and
-to permit persons to whom the Software is furnished to do so, subject to the
-following conditions: The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software. THE
-SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-// Return current SDL_GetError() string, or str if SDL didn't have a string
-static const char* sdl_error( const char* str )
-{
- const char* sdl_str = SDL_GetError();
- if ( sdl_str && *sdl_str )
- str = sdl_str;
- return str;
-}
-
-Sound_Queue::Sound_Queue()
-{
- bufs = NULL;
- free_sem = NULL;
- write_buf = 0;
- write_pos = 0;
- read_buf = 0;
- sound_open = false;
-}
-
-Sound_Queue::~Sound_Queue()
-{
- if ( sound_open )
- {
- SDL_PauseAudio( true );
- SDL_CloseAudio();
- }
-
- if ( free_sem )
- SDL_DestroySemaphore( free_sem );
-
- delete [] bufs;
-}
-
-int Sound_Queue::sample_count() const
-{
- int buf_free = SDL_SemValue( free_sem ) * buf_size + (buf_size - write_pos);
- return buf_size * buf_count - buf_free;
-}
-
-const char* Sound_Queue::init( long sample_rate, int chan_count )
-{
- assert( !bufs ); // can only be initialized once
-
- bufs = new sample_t [(long) buf_size * buf_count];
- if ( !bufs )
- return "Out of memory";
-
- free_sem = SDL_CreateSemaphore( buf_count - 1 );
- if ( !free_sem )
- return sdl_error( "Couldn't create semaphore" );
-
- SDL_AudioSpec as;
- as.freq = sample_rate;
- as.format = AUDIO_S16SYS;
- as.channels = chan_count;
- as.silence = 0;
- as.samples = buf_size;
- as.size = 0;
- as.callback = fill_buffer_;
- as.userdata = this;
- if ( SDL_OpenAudio( &as, NULL ) < 0 )
- return sdl_error( "Couldn't open SDL audio" );
- SDL_PauseAudio( false );
- sound_open = true;
-
- return NULL;
-}
-
-inline Sound_Queue::sample_t* Sound_Queue::buf( int index )
-{
- assert( (unsigned) index < buf_count );
- return bufs + (long) index * buf_size;
-}
-
-void Sound_Queue::write( const sample_t* in, int count )
-{
- while ( count )
- {
- int n = buf_size - write_pos;
- if ( n > count )
- n = count;
-
- memcpy( buf( write_buf ) + write_pos, in, n * sizeof (sample_t) );
- in += n;
- write_pos += n;
- count -= n;
-
- if ( write_pos >= buf_size )
- {
- write_pos = 0;
- write_buf = (write_buf + 1) % buf_count;
- SDL_SemWait( free_sem );
- }
- }
-}
-
-void Sound_Queue::fill_buffer( Uint8* out, int count )
-{
- if ( SDL_SemValue( free_sem ) < buf_count - 1 )
- {
- memcpy( out, buf( read_buf ), count );
- read_buf = (read_buf + 1) % buf_count;
- SDL_SemPost( free_sem );
- }
- else
- {
- memset( out, 0, count );
- }
-}
-
-void Sound_Queue::fill_buffer_( void* user_data, Uint8* out, int count )
-{
- ((Sound_Queue*) user_data)->fill_buffer( out, count );
-}
-
diff --git a/lib/apu_snapshot.cpp b/lib/apu_snapshot.cpp
deleted file mode 100644
index bfb277c..0000000
--- a/lib/apu_snapshot.cpp
+++ /dev/null
@@ -1,124 +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 */
-
-#include BLARGG_SOURCE_BEGIN
-
-template<int mode>
-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/lib/include/Blip_Buffer.h b/lib/include/Blip_Buffer.h
deleted file mode 100644
index 1982268..0000000
--- a/lib/include/Blip_Buffer.h
+++ /dev/null
@@ -1,253 +0,0 @@
-
-// Buffer of sound samples into which band-limited waveforms can be synthesized
-// using Blip_Wave or Blip_Synth.
-
-// Blip_Buffer 0.3.3. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
-
-#ifndef BLIP_BUFFER_H
-#define BLIP_BUFFER_H
-
-#include "blargg_common.h"
-
-class Blip_Reader;
-
-// Source time unit.
-typedef long blip_time_t;
-
-// Type of sample produced. Signed 16-bit format.
-typedef BOOST::int16_t blip_sample_t;
-
-// Make buffer as large as possible (currently about 65000 samples)
-const int blip_default_length = 0;
-
-class Blip_Buffer {
-public:
- // Construct an empty buffer.
- Blip_Buffer();
- ~Blip_Buffer();
-
- // Set output sample rate and buffer length in milliseconds (1/1000 sec),
- // then clear buffer. If length is not specified, make as large as possible.
- // If there is insufficient memory for the buffer, sets the buffer length
- // to 0 and returns error string (or propagates exception if compiler supports it).
- blargg_err_t sample_rate( long samples_per_sec, int msec_length = blip_default_length );
- // to do: rename to set_sample_rate
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // Current output sample rate
- long sample_rate() const;
-
- // Number of source time units per second
- void clock_rate( long );
- long clock_rate() const;
-
- // Set frequency at which high-pass filter attenuation passes -3dB
- void bass_freq( int frequency );
-
- // Remove all available samples and clear buffer to silence. If 'entire_buffer' is
- // false, just clear out any samples waiting rather than the entire buffer.
- void clear( bool entire_buffer = true );
-
- // to do:
- // Notify Blip_Buffer that synthesis has been performed until specified time
- //void run_until( blip_time_t );
-
- // End current time frame of specified duration and make its samples available
- // (along with any still-unread samples) for reading with read_samples(). Begin
- // a new time frame at the end of the current frame. All transitions must have
- // been added before 'time'.
- void end_frame( blip_time_t time );
-
- // Number of samples available for reading with read_samples()
- long samples_avail() const;
-
- // Read at most 'max_samples' out of buffer into 'dest', removing them from from
- // the buffer. Return number of samples actually read and removed. If stereo is
- // true, increment '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, bool stereo = false );
-
- // Remove 'count' samples from those waiting to be read
- void remove_samples( long count );
-
- // Number of samples delay from synthesis to samples read out
- int output_latency() const;
-
-
- // Experimental external buffer mixing support
-
- // 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( const blip_sample_t* buf, long count );
-
-
- // not documented yet
-
- void remove_silence( long count );
-
- typedef unsigned long resampled_time_t;
-
- resampled_time_t resampled_time( blip_time_t t ) const {
- return t * resampled_time_t (factor_) + offset_;
- }
-
- resampled_time_t resampled_duration( int t ) const {
- return t * resampled_time_t (factor_);
- }
-
-private:
- // noncopyable
- Blip_Buffer( const Blip_Buffer& );
- Blip_Buffer& operator = ( const Blip_Buffer& );
-
- // Don't use the following members. They are public only for technical reasons.
- public:
- enum { widest_impulse_ = 24 };
- typedef BOOST::uint16_t buf_t_;
-
- unsigned long factor_;
- resampled_time_t offset_;
- buf_t_* buffer_;
- unsigned buffer_size_;
- private:
- long reader_accum;
- int bass_shift;
- long samples_per_sec;
- long clocks_per_sec;
- int bass_freq_;
- int length_;
-
- enum { accum_fract = 15 }; // less than 16 to give extra sample range
- enum { sample_offset = 0x7F7F }; // repeated byte allows memset to clear buffer
-
- friend class Blip_Reader;
-};
-
-// Low-pass equalization parameters (see notes.txt)
-class blip_eq_t {
-public:
- blip_eq_t( double treble = 0 );
- blip_eq_t( double treble, long cutoff, long sample_rate );
-private:
- double treble;
- long cutoff;
- long sample_rate;
- friend class Blip_Impulse_;
-};
-
-// not documented yet (see Multi_Buffer.cpp for an example of use)
-class Blip_Reader {
- const Blip_Buffer::buf_t_* buf;
- long accum;
- #ifdef __MWERKS__
- void operator = ( struct foobar ); // helps optimizer
- #endif
-public:
- // avoid anything which might cause optimizer to put object in memory
-
- int begin( Blip_Buffer& blip_buf ) {
- buf = blip_buf.buffer_;
- accum = blip_buf.reader_accum;
- return blip_buf.bass_shift;
- }
-
- int read() const {
- return accum >> Blip_Buffer::accum_fract;
- }
-
- void next( int bass_shift = 9 ) {
- accum -= accum >> bass_shift;
- accum += ((long) *buf++ - Blip_Buffer::sample_offset) << Blip_Buffer::accum_fract;
- }
-
- void end( Blip_Buffer& blip_buf ) {
- blip_buf.reader_accum = accum;
- }
-};
-
-
-
-// End of public interface
-
-#ifndef BLIP_BUFFER_ACCURACY
- #define BLIP_BUFFER_ACCURACY 16
-#endif
-
-const int blip_res_bits_ = 5;
-
-typedef BOOST::uint32_t blip_pair_t_;
-
-class Blip_Impulse_ {
- typedef BOOST::uint16_t imp_t;
-
- blip_eq_t eq;
- double volume_unit_;
- imp_t* impulses;
- imp_t* impulse;
- int width;
- int fine_bits;
- int res;
- bool generate;
-
- void fine_volume_unit();
- void scale_impulse( int unit, imp_t* ) const;
-public:
- Blip_Buffer* buf;
- BOOST::uint32_t offset;
-
- void init( blip_pair_t_* impulses, int width, int res, int fine_bits = 0 );
- void volume_unit( double );
- void treble_eq( const blip_eq_t& );
-};
-
-inline blip_eq_t::blip_eq_t( double t ) :
- treble( t ), cutoff( 0 ), sample_rate( 44100 ) {
-}
-
-inline blip_eq_t::blip_eq_t( double t, long c, long sr ) :
- treble( t ), cutoff( c ), sample_rate( sr ) {
-}
-
-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 samples_per_sec;
-}
-
-inline void Blip_Buffer::end_frame( blip_time_t t ) {
- offset_ += t * factor_;
- assert(( "Blip_Buffer::end_frame(): Frame went past end of buffer",
- samples_avail() <= (long) buffer_size_ ));
-}
-
-inline void Blip_Buffer::remove_silence( long count ) {
- assert(( "Blip_Buffer::remove_silence(): Tried to remove more samples than available",
- count <= samples_avail() ));
- offset_ -= resampled_time_t (count) << BLIP_BUFFER_ACCURACY;
-}
-
-inline int Blip_Buffer::output_latency() const {
- return widest_impulse_ / 2;
-}
-
-inline long Blip_Buffer::clock_rate() const {
- return clocks_per_sec;
-}
-
-// MSVC6 fix
-typedef Blip_Buffer::resampled_time_t blip_resampled_time_t;
-
-#include "Blip_Synth.h"
-
-#endif
-
diff --git a/lib/include/Blip_Synth.h b/lib/include/Blip_Synth.h
deleted file mode 100644
index b166574..0000000
--- a/lib/include/Blip_Synth.h
+++ /dev/null
@@ -1,203 +0,0 @@
-
-// Blip_Synth and Blip_Wave are waveform transition synthesizers for adding
-// waveforms to a Blip_Buffer.
-
-// Blip_Buffer 0.3.3. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
-
-#ifndef BLIP_SYNTH_H
-#define BLIP_SYNTH_H
-
-#ifndef BLIP_BUFFER_H
- #include "Blip_Buffer.h"
-#endif
-
-// Quality level. Higher levels are slower, and worse in a few cases.
-// Use blip_good_quality as a starting point.
-const int blip_low_quality = 1;
-const int blip_med_quality = 2;
-const int blip_good_quality = 3;
-const int blip_high_quality = 4;
-
-// Blip_Synth is a transition waveform synthesizer which adds band-limited
-// offsets (transitions) into a Blip_Buffer. For a simpler interface, use
-// Blip_Wave (below).
-//
-// Range specifies the greatest expected offset that will occur. For a
-// waveform that goes between +amp and -amp, range should be amp * 2 (half
-// that if it only goes between +amp and 0). When range is large, a higher
-// accuracy scheme is used; to force this even when range is small, pass
-// the negative of range (i.e. -range).
-template<int quality,int range>
-class Blip_Synth {
- BOOST_STATIC_ASSERT( 1 <= quality && quality <= 5 );
- BOOST_STATIC_ASSERT( -32768 <= range && range <= 32767 );
- enum {
- abs_range = (range < 0) ? -range : range,
- fine_mode = (range > 512 || range < 0),
- width = (quality < 5 ? quality * 4 : Blip_Buffer::widest_impulse_),
- res = 1 << blip_res_bits_,
- impulse_size = width / 2 * (fine_mode + 1),
- base_impulses_size = width / 2 * (res / 2 + 1),
- fine_bits = (fine_mode ? (abs_range <= 64 ? 2 : abs_range <= 128 ? 3 :
- abs_range <= 256 ? 4 : abs_range <= 512 ? 5 : abs_range <= 1024 ? 6 :
- abs_range <= 2048 ? 7 : 8) : 0)
- };
- blip_pair_t_ impulses [impulse_size * res * 2 + base_impulses_size];
- Blip_Impulse_ impulse;
-public:
- Blip_Synth() { impulse.init( impulses, width, res, fine_bits ); }
-
- // Configure low-pass filter (see notes.txt). Not optimized for real-time control
- void treble_eq( const blip_eq_t& eq ) { impulse.treble_eq( eq ); }
-
- // Set volume of a transition at amplitude 'range' by setting volume_unit
- // to v / range
- void volume( double v ) { impulse.volume_unit( v * (1.0 / abs_range) ); }
-
- // Set base volume unit of transitions, where 1.0 is a full swing between the
- // positive and negative extremes. Not optimized for real-time control.
- void volume_unit( double unit ) { impulse.volume_unit( unit ); }
-
- // Default Blip_Buffer used for output when none is specified for a given call
- Blip_Buffer* output() const { return impulse.buf; }
- void output( Blip_Buffer* b ) { impulse.buf = b; }
-
- // Add an amplitude offset (transition) with a magnitude of delta * volume_unit
- // into the specified buffer (default buffer if none specified) at the
- // specified source time. Delta can be positive or negative. To increase
- // performance by inlining code at the call site, use offset_inline().
- void offset( blip_time_t, int delta, Blip_Buffer* ) const;
-
- void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
- void offset_resampled( blip_resampled_time_t t, int o ) const {
- offset_resampled( t, o, impulse.buf );
- }
- void offset( blip_time_t t, int delta ) const {
- offset( t, delta, impulse.buf );
- }
- void offset_inline( blip_time_t time, int delta, Blip_Buffer* buf ) const {
- offset_resampled( time * buf->factor_ + buf->offset_, delta, buf );
- }
- void offset_inline( blip_time_t time, int delta ) const {
- offset_inline( time, delta, impulse.buf );
- }
-};
-
-// Blip_Wave is a synthesizer for adding a *single* waveform to a Blip_Buffer.
-// A wave is built from a series of delays and new amplitudes. This provides a
-// simpler interface than Blip_Synth, nothing more.
-template<int quality,int range>
-class Blip_Wave {
- Blip_Synth<quality,range> synth;
- blip_time_t time_;
- int last_amp;
-public:
- // Start wave at time 0 and amplitude 0
- Blip_Wave() : time_( 0 ), last_amp( 0 ) { }
-
- // See Blip_Synth for description
- void volume( double v ) { synth.volume( v ); }
- void volume_unit( double v ) { synth.volume_unit( v ); }
- void treble_eq( const blip_eq_t& eq){ synth.treble_eq( eq ); }
- Blip_Buffer* output() const { return synth.output(); }
- void output( Blip_Buffer* b ) { synth.output( b ); if ( !b ) time_ = last_amp = 0; }
-
- // Current time in frame
- blip_time_t time() const { return time_; }
- void time( blip_time_t t ) { time_ = t; }
-
- // Current amplitude of wave
- int amplitude() const { return last_amp; }
- void amplitude( int );
-
- // Move forward by 't' time units
- void delay( blip_time_t t ) { time_ += t; }
-
- // End time frame of specified duration. Localize time to new frame.
- void end_frame( blip_time_t duration ) {
- assert(( "Blip_Wave::end_frame(): Wave hadn't yet been run for entire frame",
- duration <= time_ ));
- time_ -= duration;
- }
-};
-
-
-// End of public interface
-
-template<int quality,int range>
-void Blip_Wave<quality,range>::amplitude( int amp ) {
- int delta = amp - last_amp;
- last_amp = amp;
- synth.offset_inline( time_, delta );
-}
-
-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
-{
- typedef blip_pair_t_ pair_t;
-
- unsigned sample_index = (time >> BLIP_BUFFER_ACCURACY) & ~1;
- assert(( "Blip_Synth/Blip_wave: Went past end of buffer",
- sample_index < blip_buf->buffer_size_ ));
- enum { const_offset = Blip_Buffer::widest_impulse_ / 2 - width / 2 };
- pair_t* buf = (pair_t*) &blip_buf->buffer_ [const_offset + sample_index];
-
- enum { shift = BLIP_BUFFER_ACCURACY - blip_res_bits_ };
- enum { mask = res * 2 - 1 };
- const pair_t* imp = &impulses [((time >> shift) & mask) * impulse_size];
-
- pair_t offset = impulse.offset * delta;
-
- if ( !fine_bits )
- {
- // normal mode
- for ( int n = width / 4; n; --n )
- {
- pair_t t0 = buf [0] - offset;
- pair_t t1 = buf [1] - offset;
-
- t0 += imp [0] * delta;
- t1 += imp [1] * delta;
- imp += 2;
-
- buf [0] = t0;
- buf [1] = t1;
- buf += 2;
- }
- }
- else
- {
- // fine mode
- enum { sub_range = 1 << fine_bits };
- delta += sub_range / 2;
- int delta2 = (delta & (sub_range - 1)) - sub_range / 2;
- delta >>= fine_bits;
-
- for ( int n = width / 4; n; --n )
- {
- pair_t t0 = buf [0] - offset;
- pair_t t1 = buf [1] - offset;
-
- t0 += imp [0] * delta2;
- t0 += imp [1] * delta;
-
- t1 += imp [2] * delta2;
- t1 += imp [3] * delta;
-
- imp += 4;
-
- buf [0] = t0;
- buf [1] = t1;
- buf += 2;
- }
- }
-}
-
-template<int quality,int range>
-void Blip_Synth<quality,range>::offset( blip_time_t time, int delta, Blip_Buffer* buf ) const {
- offset_resampled( time * buf->factor_ + buf->offset_, delta, buf );
-}
-
-#endif
-
diff --git a/lib/include/Multi_Buffer.h b/lib/include/Multi_Buffer.h
deleted file mode 100644
index 633c7d2..0000000
--- a/lib/include/Multi_Buffer.h
+++ /dev/null
@@ -1,157 +0,0 @@
-
-// Multi-channel sound buffer interface, and basic mono and stereo buffers
-
-// Blip_Buffer 0.3.3. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
-
-#ifndef MULTI_BUFFER_H
-#define MULTI_BUFFER_H
-
-#include "Blip_Buffer.h"
-
-// Multi_Buffer is an interface to one or more Blip_Buffers mapped to one or
-// more channels consisting of left, center, and right buffers.
-class Multi_Buffer {
-public:
- Multi_Buffer( int samples_per_frame );
- virtual ~Multi_Buffer() { }
-
- // Set the number of channels available
- virtual blargg_err_t set_channel_count( int );
-
- // Get indexed channel, from 0 to channel count - 1
- struct channel_t {
- Blip_Buffer* center;
- Blip_Buffer* left;
- Blip_Buffer* right;
- };
- virtual channel_t channel( int index ) = 0;
-
- // See Blip_Buffer.h
- // to do: rename to set_sample_rate
- virtual blargg_err_t sample_rate( long rate, int msec = blip_default_length ) = 0;
- virtual void clock_rate( long ) = 0;
- virtual void bass_freq( int ) = 0;
- virtual void clear() = 0;
- long sample_rate() const;
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // See Blip_Buffer.h. For optimal operation, pass false for 'added_stereo'
- // if nothing was added to the left and right buffers of any channel for
- // this time frame.
- virtual void end_frame( blip_time_t, bool added_stereo = true ) = 0;
-
- // Number of samples per output frame (1 = mono, 2 = stereo)
- int samples_per_frame() const;
-
- // See Blip_Buffer.h
- virtual long read_samples( blip_sample_t*, long ) = 0;
- virtual long samples_avail() const = 0;
-
-private:
- // noncopyable
- Multi_Buffer( const Multi_Buffer& );
- Multi_Buffer& operator = ( const Multi_Buffer& );
-
- long sample_rate_;
- int length_;
- int const samples_per_frame_;
-};
-
-// Mono_Buffer uses a single buffer and outputs mono samples.
-class Mono_Buffer : public Multi_Buffer {
- Blip_Buffer buf;
-public:
- Mono_Buffer();
- ~Mono_Buffer();
-
- // Buffer used for all channels
- Blip_Buffer* center();
-
- // See Multi_Buffer
- blargg_err_t sample_rate( long rate, int msec = blip_default_length );
- using 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 );
-};
-
-// Stereo_Buffer uses three buffers (one for center) and outputs stereo sample pairs.
-class Stereo_Buffer : public Multi_Buffer {
-public:
- Stereo_Buffer();
- ~Stereo_Buffer();
-
- // Buffers used for all channels
- Blip_Buffer* center();
- Blip_Buffer* left();
- Blip_Buffer* right();
-
- // See Multi_Buffer
- blargg_err_t sample_rate( long, int msec = blip_default_length );
- using Multi_Buffer::sample_rate;
- void clock_rate( long );
- void bass_freq( int );
- void clear();
- channel_t channel( int index );
- void end_frame( blip_time_t, bool added_stereo = true );
-
- long samples_avail() const;
- long read_samples( blip_sample_t*, long );
-
-private:
- enum { buf_count = 3 };
- Blip_Buffer bufs [buf_count];
- channel_t chan;
- bool stereo_added;
- bool was_stereo;
-
- void mix_stereo( blip_sample_t*, long );
- void mix_mono( blip_sample_t*, long );
-};
-
-
-// End of public interface
-
-inline blargg_err_t Multi_Buffer::sample_rate( long rate, int msec )
-{
- sample_rate_ = rate;
- length_ = msec;
- return blargg_success;
-}
-
-inline int Multi_Buffer::samples_per_frame() const { return samples_per_frame_; }
-
-inline Blip_Buffer* Stereo_Buffer::left() { return &bufs [1]; }
-
-inline Blip_Buffer* Stereo_Buffer::center() { return &bufs [0]; }
-
-inline Blip_Buffer* Stereo_Buffer::right() { return &bufs [2]; }
-
-inline long Stereo_Buffer::samples_avail() const { return bufs [0].samples_avail() * 2; }
-
-inline Stereo_Buffer::channel_t Stereo_Buffer::channel( int index ) { return chan; }
-
-inline long Multi_Buffer::sample_rate() const { return sample_rate_; }
-
-inline int Multi_Buffer::length() const { return length_; }
-
-inline Blip_Buffer* Mono_Buffer::center() { return &buf; }
-
-inline void Mono_Buffer::clock_rate( long rate ) { buf.clock_rate( rate ); }
-
-inline void Mono_Buffer::clear() { buf.clear(); }
-
-inline void Mono_Buffer::bass_freq( int freq ) { buf.bass_freq( freq ); }
-
-inline long Mono_Buffer::read_samples( blip_sample_t* p, long s ) { return buf.read_samples( p, s ); }
-
-inline long Mono_Buffer::samples_avail() const { return buf.samples_avail(); }
-
-#endif
-
diff --git a/lib/include/Nes_Apu.h b/lib/include/Nes_Apu.h
deleted file mode 100644
index 6ce4c98..0000000
--- a/lib/include/Nes_Apu.h
+++ /dev/null
@@ -1,162 +0,0 @@
-
-// NES 2A03 APU sound chip emulator
-
-// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
-
-#ifndef NES_APU_H
-#define NES_APU_H
-
-typedef long cpu_time_t; // CPU clock cycle count
-typedef unsigned cpu_addr_t; // 16-bit memory address
-
-#include "Nes_Oscs.h"
-
-struct apu_snapshot_t;
-class Nonlinear_Buffer;
-
-class Nes_Apu {
-public:
- Nes_Apu();
- ~Nes_Apu();
-
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Set memory reader callback used by DMC oscillator to fetch samples.
- // When callback is invoked, 'user_data' is passed unchanged as the
- // first parameter.
- void dmc_reader( int (*callback)( void* user_data, cpu_addr_t ), void* user_data = NULL );
-
- // All time values are the number of CPU clock cycles relative to the
- // beginning of the current time frame. Before resetting the CPU clock
- // count, call end_frame( last_cpu_time ).
-
- // Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
- enum { start_addr = 0x4000 };
- enum { end_addr = 0x4017 };
- void write_register( cpu_time_t, cpu_addr_t, int data );
-
- // Read from status register at 0x4015
- enum { status_addr = 0x4015 };
- int read_status( cpu_time_t );
-
- // Run all oscillators up to specified time, end current time frame, then
- // start a new time frame at time 0. Time frames have no effect on emulation
- // and each can be whatever length is convenient.
- void end_frame( cpu_time_t );
-
-// Additional optional features (can be ignored without any problem)
-
- // Reset internal frame counter, registers, and all oscillators.
- // Use PAL timing if pal_timing is true, otherwise use NTSC timing.
- // Set the DMC oscillator's initial DAC value to initial_dmc_dac without
- // any audible click.
- void reset( bool pal_timing = false, int initial_dmc_dac = 0 );
-
- // Save/load snapshot of exact emulation state
- void save_snapshot( apu_snapshot_t* out ) const;
- void load_snapshot( apu_snapshot_t const& );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Reset oscillator amplitudes. Must be called when clearing buffer while
- // using non-linear sound.
- void buffer_cleared();
-
- // Set treble equalization (see notes.txt).
- void treble_eq( const blip_eq_t& );
-
- // Set sound output of specific oscillator to buffer. If buffer is NULL,
- // the specified oscillator is muted and emulation accuracy is reduced.
- // The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
- // 2) Triangle, 3) Noise, 4) DMC.
- enum { osc_count = 5 };
- void osc_output( int index, Blip_Buffer* buffer );
-
- // Set IRQ time callback that is invoked when the time of earliest IRQ
- // may have changed, or NULL to disable. When callback is invoked,
- // 'user_data' is passed unchanged as the first parameter.
- void irq_notifier( void (*callback)( void* user_data ), void* user_data = NULL );
-
- // Get time that APU-generated IRQ will occur if no further register reads
- // or writes occur. If IRQ is already pending, returns irq_waiting. If no
- // IRQ will occur, returns no_irq.
- enum { no_irq = LONG_MAX / 2 + 1 };
- enum { irq_waiting = 0 };
- cpu_time_t earliest_irq() const;
-
- // Count number of DMC reads that would occur if 'run_until( t )' were executed.
- // If last_read is not NULL, set *last_read to the earliest time that
- // 'count_dmc_reads( time )' would result in the same result.
- int count_dmc_reads( cpu_time_t t, cpu_time_t* last_read = NULL ) const;
-
- // Run APU until specified time, so that any DMC memory reads can be
- // accounted for (i.e. inserting CPU wait states).
- void run_until( cpu_time_t );
-
-// End of public interface.
-private:
- friend class Nes_Nonlinearizer;
- void enable_nonlinear( double volume );
-private:
- // noncopyable
- Nes_Apu( const Nes_Apu& );
- Nes_Apu& operator = ( const Nes_Apu& );
-
- Nes_Osc* oscs [osc_count];
- Nes_Square square1;
- Nes_Square square2;
- Nes_Noise noise;
- Nes_Triangle triangle;
- Nes_Dmc dmc;
-
- cpu_time_t last_time; // has been run until this time in current frame
- cpu_time_t earliest_irq_;
- cpu_time_t next_irq;
- int frame_period;
- int frame_delay; // cycles until frame counter runs next
- int frame; // current frame (0-3)
- int osc_enables;
- int frame_mode;
- bool irq_flag;
- void (*irq_notifier_)( void* user_data );
- void* irq_data;
- Nes_Square::Synth square_synth; // shared by squares
-
- void irq_changed();
- void state_restored();
-
- friend struct Nes_Dmc;
-};
-
-inline void Nes_Apu::osc_output( int osc, Blip_Buffer* buf )
-{
- assert(( "Nes_Apu::osc_output(): Index out of range", 0 <= osc && osc < osc_count ));
- oscs [osc]->output = buf;
-}
-
-inline cpu_time_t Nes_Apu::earliest_irq() const
-{
- return earliest_irq_;
-}
-
-inline void Nes_Apu::dmc_reader( int (*func)( void*, cpu_addr_t ), void* user_data )
-{
- dmc.rom_reader_data = user_data;
- dmc.rom_reader = func;
-}
-
-inline void Nes_Apu::irq_notifier( void (*func)( void* user_data ), void* user_data )
-{
- irq_notifier_ = func;
- irq_data = user_data;
-}
-
-inline int Nes_Apu::count_dmc_reads( cpu_time_t time, cpu_time_t* last_read ) const
-{
- return dmc.count_reads( time, last_read );
-}
-
-#endif
-
diff --git a/lib/include/Nes_Namco.h b/lib/include/Nes_Namco.h
deleted file mode 100644
index 87d6585..0000000
--- a/lib/include/Nes_Namco.h
+++ /dev/null
@@ -1,86 +0,0 @@
-
-// Namco 106 sound chip emulator
-
-// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
-
-#ifndef NES_NAMCO_H
-#define NES_NAMCO_H
-
-#include "Nes_Apu.h"
-
-struct namco_snapshot_t;
-
-class Nes_Namco {
-public:
- Nes_Namco();
- ~Nes_Namco();
-
- // See Nes_Apu.h for reference.
- void volume( double );
- void treble_eq( const blip_eq_t& );
- void output( Blip_Buffer* );
- enum { osc_count = 8 };
- void osc_output( int index, Blip_Buffer* );
- void reset();
- void end_frame( cpu_time_t );
-
- // Read/write data register is at 0x4800
- enum { data_reg_addr = 0x4800 };
- void write_data( cpu_time_t, int );
- int read_data();
-
- // Write-only address register is at 0xF800
- enum { addr_reg_addr = 0xF800 };
- void write_addr( int );
-
- // to do: implement save/restore
- void save_snapshot( namco_snapshot_t* out );
- void load_snapshot( namco_snapshot_t const& );
-
-private:
- // noncopyable
- Nes_Namco( const Nes_Namco& );
- Nes_Namco& operator = ( const Nes_Namco& );
-
- struct Namco_Osc {
- long delay;
- Blip_Buffer* output;
- short last_amp;
- short wave_pos;
- };
-
- Namco_Osc oscs [osc_count];
-
- cpu_time_t last_time;
- int addr_reg;
-
- enum { reg_count = 0x80 };
- BOOST::uint8_t reg [reg_count];
- Blip_Synth<blip_good_quality,15> synth;
-
- BOOST::uint8_t& access();
- void run_until( cpu_time_t );
-};
-
-inline void Nes_Namco::volume( double v ) { synth.volume( 0.10 / osc_count * v ); }
-
-inline void Nes_Namco::treble_eq( const blip_eq_t& eq ) { synth.treble_eq( eq ); }
-
-inline void Nes_Namco::write_addr( int v ) { addr_reg = v; }
-
-inline int Nes_Namco::read_data() { return access(); }
-
-inline void Nes_Namco::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Namco::write_data( cpu_time_t time, int data )
-{
- run_until( time );
- access() = data;
-}
-
-#endif
-
diff --git a/lib/include/Nes_Oscs.h b/lib/include/Nes_Oscs.h
deleted file mode 100644
index c189304..0000000
--- a/lib/include/Nes_Oscs.h
+++ /dev/null
@@ -1,142 +0,0 @@
-
-// Private oscillators used by Nes_Apu
-
-// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
-
-#ifndef NES_OSCS_H
-#define NES_OSCS_H
-
-#include "Blip_Buffer.h"
-
-class Nes_Apu;
-
-struct Nes_Osc
-{
- unsigned char regs [4];
- bool reg_written [4];
- Blip_Buffer* output;
- int length_counter;// length counter (0 if unused by oscillator)
- int delay; // delay until next (potential) transition
- int last_amp; // last amplitude oscillator was outputting
-
- void clock_length( int halt_mask );
- int period() const {
- return (regs [3] & 7) * 0x100 + (regs [2] & 0xff);
- }
- void reset() {
- delay = 0;
- last_amp = 0;
- }
- int update_amp( int amp ) {
- int delta = amp - last_amp;
- last_amp = amp;
- return delta;
- }
-};
-
-struct Nes_Envelope : Nes_Osc
-{
- int envelope;
- int env_delay;
-
- void clock_envelope();
- int volume() const;
- void reset() {
- envelope = 0;
- env_delay = 0;
- Nes_Osc::reset();
- }
-};
-
-// Nes_Square
-struct Nes_Square : Nes_Envelope
-{
- enum { negate_flag = 0x08 };
- enum { shift_mask = 0x07 };
- enum { phase_range = 8 };
- int phase;
- int sweep_delay;
-
- typedef Blip_Synth<blip_good_quality,15> Synth;
- const Synth* synth; // shared between squares
-
- void clock_sweep( int adjust );
- void run( cpu_time_t, cpu_time_t );
- void reset() {
- sweep_delay = 0;
- Nes_Envelope::reset();
- }
-};
-
-// Nes_Triangle
-struct Nes_Triangle : Nes_Osc
-{
- enum { phase_range = 16 };
- int phase;
- int linear_counter;
- Blip_Synth<blip_good_quality,15> synth;
-
- int calc_amp() const;
- void run( cpu_time_t, cpu_time_t );
- void clock_linear_counter();
- void reset() {
- linear_counter = 0;
- phase = phase_range;
- Nes_Osc::reset();
- }
-};
-
-// Nes_Noise
-struct Nes_Noise : Nes_Envelope
-{
- int noise;
- Blip_Synth<blip_med_quality,15> synth;
-
- void run( cpu_time_t, cpu_time_t );
- void reset() {
- noise = 1 << 14;
- Nes_Envelope::reset();
- }
-};
-
-// Nes_Dmc
-struct Nes_Dmc : Nes_Osc
-{
- int address; // address of next byte to read
- int period;
- //int length_counter; // bytes remaining to play (already defined in Nes_Osc)
- int buf;
- int bits_remain;
- int bits;
- bool buf_empty;
- bool silence;
-
- enum { loop_flag = 0x40 };
-
- int dac;
-
- cpu_time_t next_irq;
- bool irq_enabled;
- bool irq_flag;
- bool pal_mode;
- bool nonlinear;
-
- int (*rom_reader)( void*, cpu_addr_t ); // needs to be initialized to rom read function
- void* rom_reader_data;
-
- Nes_Apu* apu;
-
- Blip_Synth<blip_med_quality,127> synth;
-
- void start();
- void write_register( int, int );
- void run( cpu_time_t, cpu_time_t );
- void recalc_irq();
- void fill_buffer();
- void reload_sample();
- void reset();
- int count_reads( cpu_time_t, cpu_time_t* ) const;
-};
-
-#endif
-
diff --git a/lib/include/Nes_Vrc6.h b/lib/include/Nes_Vrc6.h
deleted file mode 100644
index 038cd58..0000000
--- a/lib/include/Nes_Vrc6.h
+++ /dev/null
@@ -1,85 +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"
-
-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( cpu_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( cpu_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];
- cpu_time_t last_time;
-
- Blip_Synth<blip_med_quality,31> saw_synth;
- Blip_Synth<blip_good_quality,15> square_synth;
-
- void run_until( cpu_time_t );
- void run_square( Vrc6_Osc& osc, cpu_time_t );
- void run_saw( cpu_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/lib/include/Nonlinear_Buffer.h b/lib/include/Nonlinear_Buffer.h
deleted file mode 100644
index 9497d2a..0000000
--- a/lib/include/Nonlinear_Buffer.h
+++ /dev/null
@@ -1,65 +0,0 @@
-
-// NES non-linear audio output handling.
-
-// Nes_Snd_Emu 0.1.7. 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 );
- using 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/lib/include/Sound_Queue.h b/lib/include/Sound_Queue.h
deleted file mode 100644
index c720648..0000000
--- a/lib/include/Sound_Queue.h
+++ /dev/null
@@ -1,44 +0,0 @@
-
-// Simple sound queue for synchronous sound handling in SDL
-
-// Copyright (C) 2005 Shay Green. MIT license.
-
-#ifndef SOUND_QUEUE_H
-#define SOUND_QUEUE_H
-
-#include <SDL2/SDL.h>
-
-// Simple SDL sound wrapper that has a synchronous interface
-class Sound_Queue {
-public:
- Sound_Queue();
- ~Sound_Queue();
-
- // Initialize with specified sample rate and channel count.
- // Returns NULL on success, otherwise error string.
- const char* init( long sample_rate, int chan_count = 1 );
-
- // Number of samples in buffer waiting to be played
- int sample_count() const;
-
- // Write samples to buffer and block until enough space is available
- typedef short sample_t;
- void write( const sample_t*, int count );
-
-private:
- enum { buf_size = 2048 };
- enum { buf_count = 3 };
- sample_t* volatile bufs;
- SDL_sem* volatile free_sem;
- int volatile read_buf;
- int write_buf;
- int write_pos;
- bool sound_open;
-
- sample_t* buf( int index );
- void fill_buffer( Uint8*, int );
- static void fill_buffer_( void*, Uint8*, int );
-};
-
-#endif
-
diff --git a/lib/include/apu_snapshot.h b/lib/include/apu_snapshot.h
deleted file mode 100644
index 5b894cc..0000000
--- a/lib/include/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/lib/include/blargg_common.h b/lib/include/blargg_common.h
deleted file mode 100644
index db3c6e6..0000000
--- a/lib/include/blargg_common.h
+++ /dev/null
@@ -1,180 +0,0 @@
-
-// Sets up common environment for Shay Green's libraries.
-//
-// Don't modify this file directly; #define HAVE_CONFIG_H and put your
-// configuration into "config.h".
-
-// Copyright (C) 2004-2005 Shay Green.
-
-#ifndef BLARGG_COMMON_H
-#define BLARGG_COMMON_H
-
-// Allow prefix configuration file *which can re-include blargg_common.h*
-// (probably indirectly).
-#ifdef HAVE_CONFIG_H
- #undef BLARGG_COMMON_H
- #include "config.h"
- #define BLARGG_COMMON_H
-#endif
-
-// Source files use #include BLARGG_ENABLE_OPTIMIZER before performance-critical code
-#ifndef BLARGG_ENABLE_OPTIMIZER
- #define BLARGG_ENABLE_OPTIMIZER "blargg_common.h"
-#endif
-
-// Source files have #include BLARGG_SOURCE_BEGIN at the beginning
-#ifndef BLARGG_SOURCE_BEGIN
- #define BLARGG_SOURCE_BEGIN "blargg_source.h"
-#endif
-
-// Determine compiler's language support
-
-#if defined (__MWERKS__)
- // Metrowerks CodeWarrior
- #define BLARGG_COMPILER_HAS_NAMESPACE 1
- #if !__option(bool)
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
-
-#elif defined (_MSC_VER)
- // Microsoft Visual C++
- #if _MSC_VER < 1100
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
-
-#elif defined (__GNUC__)
- // GNU C++
- #define BLARGG_COMPILER_HAS_NAMESPACE 1
- #define BLARGG_COMPILER_HAS_BOOL 1
-
-#elif defined (__MINGW32__)
- // Mingw?
- #define BLARGG_COMPILER_HAS_BOOL 1
-
-#elif __cplusplus < 199711
- // Pre-ISO C++ compiler
- #define BLARGG_COMPILER_HAS_BOOL 0
- #define BLARGG_NEW new
- #define STATIC_CAST( type ) (type)
-
-#endif
-
-// STATIC_CAST(T) (expr) -> static_cast< T > (expr)
-#ifndef STATIC_CAST
- #define STATIC_CAST( type ) static_cast< type >
-#endif
-
-// Set up boost
-#include "boost/config.hpp"
-#ifndef BOOST_MINIMAL
- #define BOOST boost
- #ifndef BLARGG_COMPILER_HAS_NAMESPACE
- #define BLARGG_COMPILER_HAS_NAMESPACE 1
- #endif
- #ifndef BLARGG_COMPILER_HAS_BOOL
- #define BLARGG_COMPILER_HAS_BOOL 1
- #endif
-#endif
-
-// Bool support
-#ifndef BLARGG_COMPILER_HAS_BOOL
- #define BLARGG_COMPILER_HAS_BOOL 1
-#elif !BLARGG_COMPILER_HAS_BOOL
- typedef int bool;
- const bool true = 1;
- const bool false = 0;
-#endif
-
-// Set up namespace support
-
-#ifndef BLARGG_COMPILER_HAS_NAMESPACE
- #define BLARGG_COMPILER_HAS_NAMESPACE 0
-#endif
-
-#ifndef BLARGG_USE_NAMESPACE
- #define BLARGG_USE_NAMESPACE BLARGG_COMPILER_HAS_NAMESPACE
-#endif
-
-#ifndef BOOST
- #if BLARGG_USE_NAMESPACE
- #define BOOST boost
- #else
- #define BOOST
- #endif
-#endif
-
-#undef BLARGG_BEGIN_NAMESPACE
-#undef BLARGG_END_NAMESPACE
-#if BLARGG_USE_NAMESPACE
- #define BLARGG_BEGIN_NAMESPACE( name ) namespace name {
- #define BLARGG_END_NAMESPACE }
-#else
- #define BLARGG_BEGIN_NAMESPACE( name )
- #define BLARGG_END_NAMESPACE
-#endif
-
-#if BLARGG_USE_NAMESPACE
- #define STD std
-#else
- #define STD
-#endif
-
-// BOOST::uint8_t, BOOST::int16_t, etc.
-#include "boost/cstdint.hpp"
-
-// BOOST_STATIC_ASSERT( expr )
-#include "boost/static_assert.hpp"
-
-// Common standard headers
-#if BLARGG_COMPILER_HAS_NAMESPACE
- #include <cstddef>
- #include <cassert>
- #include <new>
-#else
- #include <stddef.h>
- #include <assert.h>
-#endif
-
-// blargg_err_t (NULL on success, otherwise error string)
-typedef const char* blargg_err_t;
-const blargg_err_t blargg_success = 0;
-
-// BLARGG_NEW is used in place of 'new' to create objects. By default,
-// nothrow new is used.
-#ifndef BLARGG_NEW
- #define BLARGG_NEW new (STD::nothrow)
-#endif
-
-// BLARGG_BIG_ENDIAN and BLARGG_LITTLE_ENDIAN
-// Only needed if modules are used which must know byte order.
-#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
- #if defined (__powerc) || defined (macintosh)
- #define BLARGG_BIG_ENDIAN 1
-
- #elif defined (_MSC_VER) && defined (_M_IX86)
- #define BLARGG_LITTLE_ENDIAN 1
-
- #endif
-#endif
-
-// BLARGG_NONPORTABLE (allow use of nonportable optimizations/features)
-#ifndef BLARGG_NONPORTABLE
- #define BLARGG_NONPORTABLE 0
-#endif
-#ifdef BLARGG_MOST_PORTABLE
- #error "BLARGG_MOST_PORTABLE has been removed; use BLARGG_NONPORTABLE."
-#endif
-
-// BLARGG_CPU_*
-#if !defined (BLARGG_CPU_POWERPC) && !defined (BLARGG_CPU_X86)
- #if defined (__powerc)
- #define BLARGG_CPU_POWERPC 1
-
- #elif defined (_MSC_VER) && defined (_M_IX86)
- #define BLARGG_CPU_X86 1
-
- #endif
-#endif
-
-#endif
-
diff --git a/lib/include/blargg_source.h b/lib/include/blargg_source.h
deleted file mode 100644
index f74f311..0000000
--- a/lib/include/blargg_source.h
+++ /dev/null
@@ -1,43 +0,0 @@
-
-// By default, #included at beginning of library source files
-
-// Copyright (C) 2005 Shay Green.
-
-#ifndef BLARGG_SOURCE_H
-#define BLARGG_SOURCE_H
-
-// If debugging is enabled, abort program if expr is false. Meant for checking
-// internal state and consistency. A failed assertion indicates a bug in the module.
-// void assert( bool expr );
-#include <assert.h>
-
-// If debugging is enabled and expr is false, abort program. Meant for checking
-// caller-supplied parameters and operations that are outside the control of the
-// module. A failed requirement indicates a bug outside the module.
-// void require( bool expr );
-#undef require
-#define require( expr ) assert(( "unmet requirement", expr ))
-
-// Like printf() except output goes to debug log file. Might be defined to do
-// nothing (not even evaluate its arguments).
-// void dprintf( const char* format, ... );
-#undef dprintf
-#define dprintf (1) ? ((void) 0) : (void)
-
-// If enabled, evaluate expr and if false, make debug log entry with source file
-// and line. Meant for finding situations that should be examined further, but that
-// don't indicate a problem. In all cases, execution continues normally.
-#undef check
-#define check( expr ) ((void) 0)
-
-// If expr returns non-NULL error string, return it from current function, otherwise continue.
-#define BLARGG_RETURN_ERR( expr ) do { \
- blargg_err_t blargg_return_err_ = (expr); \
- if ( blargg_return_err_ ) return blargg_return_err_; \
- } while ( 0 )
-
-// If ptr is NULL, return out of memory error string.
-#define BLARGG_CHECK_ALLOC( ptr ) do { if ( !(ptr) ) return "Out of memory"; } while ( 0 )
-
-#endif
-
diff --git a/lib/include/boost/config.hpp b/lib/include/boost/config.hpp
deleted file mode 100644
index f271715..0000000
--- a/lib/include/boost/config.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Boost substitute. For full boost library see http://boost.org
-
-#ifndef BOOST_CONFIG_HPP
-#define BOOST_CONFIG_HPP
-
-#define BOOST_MINIMAL 1
-
-#define BLARGG_BEGIN_NAMESPACE( name )
-#define BLARGG_END_NAMESPACE
-
-#endif
-
diff --git a/lib/include/boost/cstdint.hpp b/lib/include/boost/cstdint.hpp
deleted file mode 100644
index e446dfd..0000000
--- a/lib/include/boost/cstdint.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-
-// Boost substitute. For full boost library see http://boost.org
-
-#ifndef BOOST_CSTDINT_HPP
-#define BOOST_CSTDINT_HPP
-
-#if BLARGG_USE_NAMESPACE
- #include <climits>
-#else
- #include <limits.h>
-#endif
-
-BLARGG_BEGIN_NAMESPACE( boost )
-
-#if UCHAR_MAX != 0xFF || SCHAR_MAX != 0x7F
-# error "No suitable 8-bit type available"
-#endif
-
-typedef unsigned char uint8_t;
-typedef signed char int8_t;
-
-#if USHRT_MAX != 0xFFFF
-# error "No suitable 16-bit type available"
-#endif
-
-typedef short int16_t;
-typedef unsigned short uint16_t;
-
-#if ULONG_MAX == 0xFFFFFFFF
- typedef long int32_t;
- typedef unsigned long uint32_t;
-#elif UINT_MAX == 0xFFFFFFFF
- typedef int int32_t;
- typedef unsigned int uint32_t;
-#else
-# error "No suitable 32-bit type available"
-#endif
-
-BLARGG_END_NAMESPACE
-
-#endif
-
diff --git a/lib/include/boost/static_assert.hpp b/lib/include/boost/static_assert.hpp
deleted file mode 100644
index 66927cc..0000000
--- a/lib/include/boost/static_assert.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-
-// Boost substitute. For full boost library see http://boost.org
-
-#ifndef BOOST_STATIC_ASSERT_HPP
-#define BOOST_STATIC_ASSERT_HPP
-
-#if defined (_MSC_VER) && _MSC_VER <= 1200
- // MSVC6 can't handle the ##line concatenation
- #define BOOST_STATIC_ASSERT( expr ) struct { int n [1 / ((expr) ? 1 : 0)]; }
-
-#else
- #define BOOST_STATIC_ASSERT3( expr, line ) \
- typedef int boost_static_assert_##line [1 / ((expr) ? 1 : 0)]
-
- #define BOOST_STATIC_ASSERT2( expr, line ) BOOST_STATIC_ASSERT3( expr, line )
-
- #define BOOST_STATIC_ASSERT( expr ) BOOST_STATIC_ASSERT2( expr, __LINE__ )
-
-#endif
-
-#endif
-
diff --git a/src/main.cpp b/main.cpp
index 640d9db..ce5a696 100644
--- a/src/main.cpp
+++ b/main.cpp
@@ -9,22 +9,18 @@
*/
#include <bits/stdc++.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <unistd.h>
#include <SDL2/SDL.h>
-#include "NES_Apu.h"
-#include "Sound_Queue.h"
#define NTH_BIT(x, n) (((x) >> (n)) & 1)
typedef uint8_t u8; typedef int8_t s8;
typedef uint16_t u16; typedef int16_t s16;
typedef uint32_t u32; typedef int32_t s32;
typedef uint64_t u64; typedef int64_t s64;
+typedef long cpu_time_t; // CPU clock cycle count
+typedef unsigned cpu_addr_t; // 16-bit memory address
// Initial declarations
namespace APU {
template <bool write> u8 access(int elapsed, u16 addr, u8 v = 0);
- void run_frame(int elapsed), reset(), init();
}
namespace CPU {
enum IntType { NMI, RESET, IRQ, BRK }; // Interrupt type.
@@ -98,15 +94,13 @@ namespace Cartridge {
void signal_scanline(), load(const char *fileName);
}
namespace Joypad {
- u8 read_state(int n);
- void write_strobe(bool v);
+ u8 read_state(int n); void write_strobe(bool v);
}
namespace GUI {
const unsigned WIDTH = 256, HEIGHT = 240; // Screen size
- const int TEXT_CENTER = -1, TEXT_RIGHT = -2;
int query_button();
void init(), run();
- void render_texture(SDL_Texture* texture, int x, int y), new_frame(u32* pixels), new_samples(const blip_sample_t* samples, size_t count);
+ void new_frame(u32* pixels);
u8 get_joypad_state(int n);
SDL_Scancode query_key();
}
@@ -290,24 +284,9 @@ public:
// Actual code
namespace APU {
- Nes_Apu apu; Blip_Buffer buf;
const int OUT_SIZE = 4096;
- blip_sample_t outBuf[OUT_SIZE];
- void init() {
- buf.sample_rate(96000); buf.clock_rate(1789773);
- apu.output(&buf); apu.dmc_reader(CPU::dmc_read);
- }
- void reset() { apu.reset(); buf.clear(); }
- template <bool write> u8 access(int elapsed, u16 addr, u8 v) {
- if (write) apu.write_register(elapsed, addr, v);
- else if (addr == apu.status_addr) v = apu.read_status(elapsed);
- return v;
- }
+ template <bool write> u8 access(int elapsed, u16 addr, u8 v) { return v; }
template u8 access<0>(int, u16, u8); template u8 access<1>(int, u16, u8);
- void run_frame(int elapsed) {
- apu.end_frame(elapsed); buf.end_frame(elapsed);
- if (buf.samples_avail() >= OUT_SIZE) GUI::new_samples(outBuf, buf.read_samples(outBuf, OUT_SIZE));
- }
}
namespace CPU {
u8 A, X, Y, S, ram[0x800]; u16 PC; Flags P; bool nmi, irq; // CPU state
@@ -429,85 +408,46 @@ namespace CPU {
// Execute a CPU instruction
void exec() {
switch (rd(PC++)) { // Fetch the opcode and select the right function to emulate the instruction:
- case 0x00: return INT<BRK>() ; case 0x01: return ORA<izx>() ;
- case 0x05: return ORA<zp>() ; case 0x06: return ASL<zp>() ;
- case 0x08: return PHP() ; case 0x09: return ORA<imm>() ;
- case 0x0A: return ASL_A() ; case 0x0D: return ORA<abs>() ;
- case 0x0E: return ASL<abs>() ; case 0x10: return br<N,0>() ;
- case 0x11: return ORA<izy>() ; case 0x15: return ORA<zpx>() ;
- case 0x16: return ASL<zpx>() ; case 0x18: return flag<C,0>() ;
- case 0x19: return ORA<aby>() ; case 0x1D: return ORA<abx>() ;
- case 0x1E: return ASL<_abx>() ; case 0x20: return JSR() ;
- case 0x21: return AND<izx>() ; case 0x24: return BIT<zp>() ;
- case 0x25: return AND<zp>() ; case 0x26: return ROL<zp>() ;
- case 0x28: return PLP() ; case 0x29: return AND<imm>() ;
- case 0x2A: return ROL_A() ; case 0x2C: return BIT<abs>() ;
- case 0x2D: return AND<abs>() ; case 0x2E: return ROL<abs>() ;
- case 0x30: return br<N,1>() ; case 0x31: return AND<izy>() ;
- case 0x35: return AND<zpx>() ; case 0x36: return ROL<zpx>() ;
- case 0x38: return flag<C,1>() ; case 0x39: return AND<aby>() ;
- case 0x3D: return AND<abx>() ; case 0x3E: return ROL<_abx>() ;
- case 0x40: return RTI() ; case 0x41: return EOR<izx>() ;
- case 0x45: return EOR<zp>() ; case 0x46: return LSR<zp>() ;
- case 0x48: return PHA() ; case 0x49: return EOR<imm>() ;
- case 0x4A: return LSR_A() ; case 0x4C: return JMP() ;
- case 0x4D: return EOR<abs>() ; case 0x4E: return LSR<abs>() ;
- case 0x50: return br<V,0>() ; case 0x51: return EOR<izy>() ;
- case 0x55: return EOR<zpx>() ; case 0x56: return LSR<zpx>() ;
- case 0x58: return flag<I,0>() ; case 0x59: return EOR<aby>() ;
- case 0x5D: return EOR<abx>() ; case 0x5E: return LSR<_abx>() ;
- case 0x60: return RTS() ; case 0x61: return ADC<izx>() ;
- case 0x65: return ADC<zp>() ; case 0x66: return ROR<zp>() ;
- case 0x68: return PLA() ; case 0x69: return ADC<imm>() ;
- case 0x6A: return ROR_A() ; case 0x6C: return JMP_IND() ;
- case 0x6D: return ADC<abs>() ; case 0x6E: return ROR<abs>() ;
- case 0x70: return br<V,1>() ; case 0x71: return ADC<izy>() ;
- case 0x75: return ADC<zpx>() ; case 0x76: return ROR<zpx>() ;
- case 0x78: return flag<I,1>() ; case 0x79: return ADC<aby>() ;
- case 0x7D: return ADC<abx>() ; case 0x7E: return ROR<_abx>() ;
- case 0x81: return st<A,izx>() ; case 0x84: return st<Y,zp>() ;
- case 0x85: return st<A,zp>() ; case 0x86: return st<X,zp>() ;
- case 0x88: return dec<Y>() ; case 0x8A: return tr<X,A>() ;
- case 0x8C: return st<Y,abs>() ; case 0x8D: return st<A,abs>() ;
- case 0x8E: return st<X,abs>() ; case 0x90: return br<C,0>() ;
- case 0x91: return st<A,izy>() ; case 0x94: return st<Y,zpx>() ;
- case 0x95: return st<A,zpx>() ; case 0x96: return st<X,zpy>() ;
- case 0x98: return tr<Y,A>() ; case 0x99: return st<A,aby>() ;
- case 0x9A: return tr<X,S>() ; case 0x9D: return st<A,abx>() ;
- case 0xA0: return ld<Y,imm>() ; case 0xA1: return ld<A,izx>() ;
- case 0xA2: return ld<X,imm>() ; case 0xA4: return ld<Y,zp>() ;
- case 0xA5: return ld<A,zp>() ; case 0xA6: return ld<X,zp>() ;
- case 0xA8: return tr<A,Y>() ; case 0xA9: return ld<A,imm>() ;
- case 0xAA: return tr<A,X>() ; case 0xAC: return ld<Y,abs>() ;
- case 0xAD: return ld<A,abs>() ; case 0xAE: return ld<X,abs>() ;
- case 0xB0: return br<C,1>() ; case 0xB1: return ld<A,izy>() ;
- case 0xB4: return ld<Y,zpx>() ; case 0xB5: return ld<A,zpx>() ;
- case 0xB6: return ld<X,zpy>() ; case 0xB8: return flag<V,0>() ;
- case 0xB9: return ld<A,aby>() ; case 0xBA: return tr<S,X>() ;
- case 0xBC: return ld<Y,abx>() ; case 0xBD: return ld<A,abx>() ;
- case 0xBE: return ld<X,aby>() ; case 0xC0: return cmp<Y,imm>();
- case 0xC1: return cmp<A,izx>(); case 0xC4: return cmp<Y,zp>() ;
- case 0xC5: return cmp<A,zp>() ; case 0xC6: return DEC<zp>() ;
- case 0xC8: return inc<Y>() ; case 0xC9: return cmp<A,imm>();
- case 0xCA: return dec<X>() ; case 0xCC: return cmp<Y,abs>();
- case 0xCD: return cmp<A,abs>(); case 0xCE: return DEC<abs>() ;
- case 0xD0: return br<Z,0>() ; case 0xD1: return cmp<A,izy>();
- case 0xD5: return cmp<A,zpx>(); case 0xD6: return DEC<zpx>() ;
- case 0xD8: return flag<D,0>() ; case 0xD9: return cmp<A,aby>();
- case 0xDD: return cmp<A,abx>(); case 0xDE: return DEC<_abx>() ;
- case 0xE0: return cmp<X,imm>(); case 0xE1: return SBC<izx>() ;
- case 0xE4: return cmp<X,zp>() ; case 0xE5: return SBC<zp>() ;
- case 0xE6: return INC<zp>() ; case 0xE8: return inc<X>() ;
- case 0xE9: return SBC<imm>() ; case 0xEA: return NOP() ;
- case 0xEC: return cmp<X,abs>(); case 0xED: return SBC<abs>() ;
- case 0xEE: return INC<abs>() ; case 0xF0: return br<Z,1>() ;
- case 0xF1: return SBC<izy>() ; case 0xF5: return SBC<zpx>() ;
- case 0xF6: return INC<zpx>() ; case 0xF8: return flag<D,1>() ;
- case 0xF9: return SBC<aby>() ; case 0xFD: return SBC<abx>() ;
- case 0xFE: return INC<_abx>() ;
- default:
- std::cout << "Invalid Opcode! PC: " << PC << " Opcode: 0x" << std::hex << (int)(rd(PC - 1)) << "\n";
- return NOP();
+ case 0x00: return INT<BRK>() ; case 0x01: return ORA<izx>() ; case 0x05: return ORA<zp>() ; case 0x06: return ASL<zp>() ;
+ case 0x08: return PHP() ; case 0x09: return ORA<imm>() ; case 0x0A: return ASL_A() ; case 0x0D: return ORA<abs>() ;
+ case 0x0E: return ASL<abs>() ; case 0x10: return br<N,0>() ; case 0x11: return ORA<izy>() ; case 0x15: return ORA<zpx>() ;
+ case 0x16: return ASL<zpx>() ; case 0x18: return flag<C,0>() ; case 0x19: return ORA<aby>() ; case 0x1D: return ORA<abx>() ;
+ case 0x1E: return ASL<_abx>() ; case 0x20: return JSR() ; case 0x21: return AND<izx>() ; case 0x24: return BIT<zp>() ;
+ case 0x25: return AND<zp>() ; case 0x26: return ROL<zp>() ; case 0x28: return PLP() ; case 0x29: return AND<imm>() ;
+ case 0x2A: return ROL_A() ; case 0x2C: return BIT<abs>() ; case 0x2D: return AND<abs>() ; case 0x2E: return ROL<abs>() ;
+ case 0x30: return br<N,1>() ; case 0x31: return AND<izy>() ; case 0x35: return AND<zpx>() ; case 0x36: return ROL<zpx>() ;
+ case 0x38: return flag<C,1>() ; case 0x39: return AND<aby>() ; case 0x3D: return AND<abx>() ; case 0x3E: return ROL<_abx>() ;
+ case 0x40: return RTI() ; case 0x41: return EOR<izx>() ; case 0x45: return EOR<zp>() ; case 0x46: return LSR<zp>() ;
+ case 0x48: return PHA() ; case 0x49: return EOR<imm>() ; case 0x4A: return LSR_A() ; case 0x4C: return JMP() ;
+ case 0x4D: return EOR<abs>() ; case 0x4E: return LSR<abs>() ; case 0x50: return br<V,0>() ; case 0x51: return EOR<izy>() ;
+ case 0x55: return EOR<zpx>() ; case 0x56: return LSR<zpx>() ; case 0x58: return flag<I,0>() ; case 0x59: return EOR<aby>() ;
+ case 0x5D: return EOR<abx>() ; case 0x5E: return LSR<_abx>() ; case 0x60: return RTS() ; case 0x61: return ADC<izx>() ;
+ case 0x65: return ADC<zp>() ; case 0x66: return ROR<zp>() ; case 0x68: return PLA() ; case 0x69: return ADC<imm>() ;
+ case 0x6A: return ROR_A() ; case 0x6C: return JMP_IND() ; case 0x6D: return ADC<abs>() ; case 0x6E: return ROR<abs>() ;
+ case 0x70: return br<V,1>() ; case 0x71: return ADC<izy>() ; case 0x75: return ADC<zpx>() ; case 0x76: return ROR<zpx>() ;
+ case 0x78: return flag<I,1>() ; case 0x79: return ADC<aby>() ; case 0x7D: return ADC<abx>() ; case 0x7E: return ROR<_abx>() ;
+ case 0x81: return st<A,izx>() ; case 0x84: return st<Y,zp>() ; case 0x85: return st<A,zp>() ; case 0x86: return st<X,zp>() ;
+ case 0x88: return dec<Y>() ; case 0x8A: return tr<X,A>() ; case 0x8C: return st<Y,abs>() ; case 0x8D: return st<A,abs>() ;
+ case 0x8E: return st<X,abs>() ; case 0x90: return br<C,0>() ; case 0x91: return st<A,izy>() ; case 0x94: return st<Y,zpx>() ;
+ case 0x95: return st<A,zpx>() ; case 0x96: return st<X,zpy>() ; case 0x98: return tr<Y,A>() ; case 0x99: return st<A,aby>() ;
+ case 0x9A: return tr<X,S>() ; case 0x9D: return st<A,abx>() ; case 0xA0: return ld<Y,imm>() ; case 0xA1: return ld<A,izx>() ;
+ case 0xA2: return ld<X,imm>() ; case 0xA4: return ld<Y,zp>() ; case 0xA5: return ld<A,zp>() ; case 0xA6: return ld<X,zp>() ;
+ case 0xA8: return tr<A,Y>() ; case 0xA9: return ld<A,imm>() ; case 0xAA: return tr<A,X>() ; case 0xAC: return ld<Y,abs>() ;
+ case 0xAD: return ld<A,abs>() ; case 0xAE: return ld<X,abs>() ; case 0xB0: return br<C,1>() ; case 0xB1: return ld<A,izy>() ;
+ case 0xB4: return ld<Y,zpx>() ; case 0xB5: return ld<A,zpx>() ; case 0xB6: return ld<X,zpy>() ; case 0xB8: return flag<V,0>() ;
+ case 0xB9: return ld<A,aby>() ; case 0xBA: return tr<S,X>() ; case 0xBC: return ld<Y,abx>() ; case 0xBD: return ld<A,abx>() ;
+ case 0xBE: return ld<X,aby>() ; case 0xC0: return cmp<Y,imm>(); case 0xC1: return cmp<A,izx>(); case 0xC4: return cmp<Y,zp>() ;
+ case 0xC5: return cmp<A,zp>() ; case 0xC6: return DEC<zp>() ; case 0xC8: return inc<Y>() ; case 0xC9: return cmp<A,imm>();
+ case 0xCA: return dec<X>() ; case 0xCC: return cmp<Y,abs>(); case 0xCD: return cmp<A,abs>(); case 0xCE: return DEC<abs>() ;
+ case 0xD0: return br<Z,0>() ; case 0xD1: return cmp<A,izy>(); case 0xD5: return cmp<A,zpx>(); case 0xD6: return DEC<zpx>() ;
+ case 0xD8: return flag<D,0>() ; case 0xD9: return cmp<A,aby>(); case 0xDD: return cmp<A,abx>(); case 0xDE: return DEC<_abx>() ;
+ case 0xE0: return cmp<X,imm>(); case 0xE1: return SBC<izx>() ; case 0xE4: return cmp<X,zp>() ; case 0xE5: return SBC<zp>() ;
+ case 0xE6: return INC<zp>() ; case 0xE8: return inc<X>() ; case 0xE9: return SBC<imm>() ; case 0xEA: return NOP() ;
+ case 0xEC: return cmp<X,abs>(); case 0xED: return SBC<abs>() ; case 0xEE: return INC<abs>() ; case 0xF0: return br<Z,1>() ;
+ case 0xF1: return SBC<izy>() ; case 0xF5: return SBC<zpx>() ; case 0xF6: return INC<zpx>() ; case 0xF8: return flag<D,1>() ;
+ case 0xF9: return SBC<aby>() ; case 0xFD: return SBC<abx>() ; case 0xFE: return INC<_abx>() ; default:
+ std::cout << "Invalid Opcode! PC: " << PC << " Opcode: 0x" << std::hex << (int)(rd(PC - 1)) << "\n";
+ return NOP();
}
}
void set_nmi(bool v) { nmi = v; }
@@ -530,11 +470,17 @@ namespace CPU {
else if (irq and !P[I]) INT<IRQ>();
exec();
}
- APU::run_frame(elapsed());
}
}
namespace PPU {
- #include "palette.inc"
+ u32 nesRgb[] = { 0x7C7C7C, 0x0000FC, 0x0000BC, 0x4428BC, 0x940084, 0xA80020, 0xA81000, 0x881400,
+ 0x503000, 0x007800, 0x006800, 0x005800, 0x004058, 0x000000, 0x000000, 0x000000,
+ 0xBCBCBC, 0x0078F8, 0x0058F8, 0x6844FC, 0xD800CC, 0xE40058, 0xF83800, 0xE45C10,
+ 0xAC7C00, 0x00B800, 0x00A800, 0x00A844, 0x008888, 0x000000, 0x000000, 0x000000,
+ 0xF8F8F8, 0x3CBCFC, 0x6888FC, 0x9878F8, 0xF878F8, 0xF85898, 0xF87858, 0xFCA044,
+ 0xF8B800, 0xB8F818, 0x58D854, 0x58F898, 0x00E8D8, 0x787878, 0x000000, 0x000000,
+ 0xFCFCFC, 0xA4E4FC, 0xB8B8F8, 0xD8B8F8, 0xF8B8F8, 0xF8A4C0, 0xF0D0B0, 0xFCE0A8,
+ 0xF8D878, 0xD8F878, 0xB8F8B8, 0xB8F8D8, 0x00FCFC, 0xF8D8F8, 0x000000, 0x000000 };
Mirroring mirroring; // Mirroring mode
u8 ciRam[0x800], cgRam[0x20], oamMem[0x100]; // VRAM for nametables, palettes, sprite properties
Sprite oam[8], secOam[8]; // Sprite buffers
@@ -796,7 +742,7 @@ namespace Cartridge {
case 3: mapper = new Mapper3(rom); break;
case 4: mapper = new Mapper4(rom); break;
}
- CPU::power(), PPU::reset(), APU::reset();
+ CPU::power(), PPU::reset();
}
}
namespace Joypad {
@@ -821,7 +767,6 @@ namespace GUI {
SDL_Renderer* renderer;
SDL_Texture* gameTexture;
u8 const* keys;
- Sound_Queue* soundQueue;
SDL_Scancode KEY_A = SDL_SCANCODE_A, KEY_B = SDL_SCANCODE_S, KEY_SELECT = SDL_SCANCODE_SPACE, KEY_START = SDL_SCANCODE_RETURN;
SDL_Scancode KEY_UP = SDL_SCANCODE_UP, KEY_DOWN = SDL_SCANCODE_DOWN, KEY_LEFT = SDL_SCANCODE_LEFT, KEY_RIGHT = SDL_SCANCODE_RIGHT;
// Initialize GUI
@@ -829,43 +774,23 @@ namespace GUI {
// Initialize graphics system
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
- APU::init();
- soundQueue = new Sound_Queue;
- soundQueue->init(96000);
// Initialize graphics structures
- window = SDL_CreateWindow ("BadNES", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);
+ window = SDL_CreateWindow("BadNES", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_RenderSetLogicalSize(renderer, WIDTH, HEIGHT);
gameTexture = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT);
keys = SDL_GetKeyboardState(0);
}
- // Render a texture on screen
- void render_texture(SDL_Texture* texture, int x, int y) {
- int w, h; SDL_Rect dest;
- SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);
- if (x == TEXT_CENTER) dest.x = WIDTH/2 - dest.w/2;
- else if (x == TEXT_RIGHT) dest.x = WIDTH - dest.w - 10;
- else dest.x = x + 10;
- dest.y = y + 5;
- SDL_RenderCopy(renderer, texture, NULL, &dest);
- }
// Get the joypad state from SDL
u8 get_joypad_state(int n) {
const int DEAD_ZONE = 8000;
u8 j = 0;
- j |= keys[KEY_A] << 0;
- j |= keys[KEY_B] << 1;
- j |= keys[KEY_SELECT] << 2;
- j |= keys[KEY_START] << 3;
- j |= keys[KEY_UP] << 4;
- j |= keys[KEY_DOWN] << 5;
- j |= keys[KEY_LEFT] << 6;
- j |= keys[KEY_RIGHT] << 7;
+ j |= keys[KEY_A] << 0; j |= keys[KEY_B] << 1; j |= keys[KEY_SELECT] << 2; j |= keys[KEY_START] << 3;
+ j |= keys[KEY_UP] << 4; j |= keys[KEY_DOWN] << 5; j |= keys[KEY_LEFT] << 6; j |= keys[KEY_RIGHT] << 7;
return j;
}
// Send the rendered frame to the GUI
void new_frame(u32* pixels) { SDL_UpdateTexture(gameTexture, NULL, pixels, WIDTH * sizeof(u32)); }
- void new_samples(const blip_sample_t* samples, size_t count) { soundQueue->write(samples, count); }
// Render the screen
void render() {
SDL_RenderClear(renderer);
diff --git a/old/apu.cpp b/old/apu.cpp
deleted file mode 100644
index 1a22e10..0000000
--- a/old/apu.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "gui.hpp"
-#include "cpu.hpp"
-#include "apu.hpp"
-
-namespace APU {
-
-
-Nes_Apu apu;
-Blip_Buffer buf;
-
-const int OUT_SIZE = 4096;
-blip_sample_t outBuf[OUT_SIZE];
-
-void init()
-{
- buf.sample_rate(96000);
- buf.clock_rate(1789773);
-
- apu.output(&buf);
- apu.dmc_reader(CPU::dmc_read);
-}
-
-void reset()
-{
- apu.reset();
- buf.clear();
-}
-
-template <bool write> u8 access(int elapsed, u16 addr, u8 v)
-{
- if (write)
- apu.write_register(elapsed, addr, v);
- else if (addr == apu.status_addr)
- v = apu.read_status(elapsed);
-
- return v;
-}
-template u8 access<0>(int, u16, u8); template u8 access<1>(int, u16, u8);
-
-void run_frame(int elapsed)
-{
- apu.end_frame(elapsed);
- buf.end_frame(elapsed);
-
- if (buf.samples_avail() >= OUT_SIZE)
- GUI::new_samples(outBuf, buf.read_samples(outBuf, OUT_SIZE));
-}
-
-
-}
diff --git a/old/cartridge.cpp b/old/cartridge.cpp
deleted file mode 100644
index 29673ca..0000000
--- a/old/cartridge.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <cstdio>
-#include "apu.hpp"
-#include "cpu.hpp"
-#include "mappers/mapper0.hpp"
-#include "mappers/mapper1.hpp"
-#include "mappers/mapper2.hpp"
-#include "mappers/mapper3.hpp"
-#include "mappers/mapper4.hpp"
-#include "ppu.hpp"
-#include "cartridge.hpp"
-
-namespace Cartridge {
-
-
-Mapper* mapper = nullptr; // Mapper chip.
-
-/* PRG-ROM access */
-template <bool wr> u8 access(u16 addr, u8 v)
-{
- if (!wr) return mapper->read(addr);
- else return mapper->write(addr, v);
-}
-template u8 access<0>(u16, u8); template u8 access<1>(u16, u8);
-
-/* CHR-ROM/RAM access */
-template <bool wr> u8 chr_access(u16 addr, u8 v)
-{
- if (!wr) return mapper->chr_read(addr);
- else return mapper->chr_write(addr, v);
-}
-template u8 chr_access<0>(u16, u8); template u8 chr_access<1>(u16, u8);
-
-void signal_scanline()
-{
- mapper->signal_scanline();
-}
-
-/* Load the ROM from a file. */
-void load(const char* fileName)
-{
- FILE* f = fopen(fileName, "rb");
-
- fseek(f, 0, SEEK_END);
- int size = ftell(f);
- fseek(f, 0, SEEK_SET);
-
- u8* rom = new u8[size];
- fread(rom, size, 1, f);
- fclose(f);
-
- int mapperNum = (rom[7] & 0xF0) | (rom[6] >> 4);
- if (loaded()) delete mapper;
- switch (mapperNum)
- {
- case 0: mapper = new Mapper0(rom); break;
- case 1: mapper = new Mapper1(rom); break;
- case 2: mapper = new Mapper2(rom); break;
- case 3: mapper = new Mapper3(rom); break;
- case 4: mapper = new Mapper4(rom); break;
- }
-
- CPU::power();
- PPU::reset();
- APU::reset();
-}
-
-bool loaded()
-{
- return mapper != nullptr;
-}
-
-
-}
diff --git a/old/config.cpp b/old/config.cpp
deleted file mode 100644
index 3172e0e..0000000
--- a/old/config.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-#include <cstdlib>
-#include <SimpleIni.h>
-#include "config.hpp"
-#include "gui.hpp"
-
-namespace GUI {
-
-/* Settings */
-CSimpleIniA ini(true, false, false);
-
-/* Window settings */
-int last_window_size = 1;
-
-/* Controls settings */
-SDL_Scancode KEY_A [] = { SDL_SCANCODE_A, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_B [] = { SDL_SCANCODE_S, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_SELECT[] = { SDL_SCANCODE_SPACE, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_START [] = { SDL_SCANCODE_RETURN, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_UP [] = { SDL_SCANCODE_UP, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_DOWN [] = { SDL_SCANCODE_DOWN, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_LEFT [] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_ESCAPE };
-SDL_Scancode KEY_RIGHT [] = { SDL_SCANCODE_RIGHT, SDL_SCANCODE_ESCAPE };
-int BTN_UP [] = { -1, -1 };
-int BTN_DOWN [] = { -1, -1 };
-int BTN_LEFT [] = { -1, -1 };
-int BTN_RIGHT [] = { -1, -1 };
-int BTN_A [] = { -1, -1 };
-int BTN_B [] = { -1, -1 };
-int BTN_SELECT[] = { -1, -1 };
-int BTN_START [] = { -1, -1 };
-bool useJoystick[] = { false, false };
-
-
-
-/* Ensure config directory exists */
-const char* get_config_path(char* buf, int buflen)
-{
- /* Bail on the complex stuff if we don't need it */
- if (!USE_CONFIG_DIR)
- return CONFIG_FALLBACK;
-
- /* First, get the home directory */
- char homepath[CONFIG_PATH_MAX];
- char path[CONFIG_PATH_MAX];
- char * home = getenv("HOME");
- if (home == NULL)
- return CONFIG_FALLBACK;
-
- snprintf(homepath, sizeof(homepath), "%s/.config", home);
-
- /* Then, .config as a folder */
- int res = mkdir(homepath, CONFIG_DIR_DEFAULT_MODE);
- int err = errno;
-
- if (res == -1 && err != EEXIST)
- return CONFIG_FALLBACK;
-
- snprintf(path, sizeof(path), "%s/%s", homepath, CONFIG_DIR_NAME);
-
- /* Finally, CONFIG_DIR_NAME as a sub-folder */
- res = mkdir(path, CONFIG_DIR_DEFAULT_MODE);
- err = errno;
-
- if (res == -1 && err != EEXIST)
- return CONFIG_FALLBACK;
-
- snprintf(buf, buflen, "%s/settings", path);
-
- return buf;
-}
-
-
-/* Load settings */
-void load_settings()
-{
- /* Files */
- char path[CONFIG_PATH_MAX];
- ini.LoadFile(get_config_path(path, sizeof(path)));
-
- /* Screen settings */
- int screen_size = atoi(ini.GetValue("screen", "size", "1"));
- if (screen_size < 1 || screen_size > 4)
- screen_size = 1;
-
- set_size(screen_size);
-
- /* Control settings */
- for (int p = 0; p <= 1; p++)
- {
- const char* section = (p == 0) ? "controls p1" : "controls p2";
-
- useJoystick[p] = (ini.GetValue(section, "usejoy", "no"))[0] == 'y';
- if (useJoystick[p])
- {
- BTN_UP[p] = atoi(ini.GetValue(section, "UP", "-1"));
- BTN_DOWN[p] = atoi(ini.GetValue(section, "DOWN", "-1"));
- BTN_LEFT[p] = atoi(ini.GetValue(section, "LEFT", "-1"));
- BTN_RIGHT[p] = atoi(ini.GetValue(section, "RIGHT", "-1"));
- BTN_A[p] = atoi(ini.GetValue(section, "A", "-1"));
- BTN_B[p] = atoi(ini.GetValue(section, "B", "-1"));
- BTN_SELECT[p] = atoi(ini.GetValue(section, "SELECT", "-1"));
- BTN_START[p] = atoi(ini.GetValue(section, "START", "-1"));
- }
- else
- {
- KEY_UP[p] = (SDL_Scancode)atoi(ini.GetValue(section, "UP", "82"));
- KEY_DOWN[p] = (SDL_Scancode)atoi(ini.GetValue(section, "DOWN", "81"));
- KEY_LEFT[p] = (SDL_Scancode)atoi(ini.GetValue(section, "LEFT", "80"));
- KEY_RIGHT[p] = (SDL_Scancode)atoi(ini.GetValue(section, "RIGHT", "79"));
- KEY_A[p] = (SDL_Scancode)atoi(ini.GetValue(section, "A", "4"));
- KEY_B[p] = (SDL_Scancode)atoi(ini.GetValue(section, "B", "22"));
- KEY_SELECT[p] = (SDL_Scancode)atoi(ini.GetValue(section, "SELECT", "44"));
- KEY_START[p] = (SDL_Scancode)atoi(ini.GetValue(section, "START", "40"));
- }
- }
-}
-
-
-/* Save settings */
-void save_settings()
-{
- /* Screen settings */
- char buf[10];
- sprintf(buf, "%d", last_window_size);
- ini.SetValue("screen", "size", buf);
-
- /* Control settings */
- for (int p = 0; p < 2; p++)
- {
- const char* section = (p == 0) ? "controls p1" : "controls p2";
-
- sprintf(buf, "%d", useJoystick[p] ? BTN_UP[p] : KEY_UP[p]);
- ini.SetValue(section, "UP", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_DOWN[p] : KEY_DOWN[p]);
- ini.SetValue(section, "DOWN", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_LEFT[p] : KEY_LEFT[p]);
- ini.SetValue(section, "LEFT", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_RIGHT[p] : KEY_RIGHT[p]);
- ini.SetValue(section, "RIGHT", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_A[p] : KEY_A[p]);
- ini.SetValue(section, "A", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_B[p] : KEY_B[p]);
- ini.SetValue(section, "B", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_SELECT[p] : KEY_SELECT[p]);
- ini.SetValue(section, "SELECT", buf);
- sprintf(buf, "%d", useJoystick[p] ? BTN_START[p] : KEY_START[p]);
- ini.SetValue(section, "START", buf);
- ini.SetValue(section, "usejoy", useJoystick[p] ? "yes" : "no");
- }
-
- char path[CONFIG_PATH_MAX];
- ini.SaveFile(get_config_path(path, sizeof(path)));
-}
-
-}
diff --git a/old/cpu.cpp b/old/cpu.cpp
deleted file mode 100644
index 444cfdf..0000000
--- a/old/cpu.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include "apu.hpp"
-#include "cartridge.hpp"
-#include "joypad.hpp"
-#include "ppu.hpp"
-#include "cpu.hpp"
-
-namespace CPU {
-
-
-/* CPU state */
-u8 ram[0x800];
-u8 A, X, Y, S;
-u16 PC;
-Flags P;
-bool nmi, irq;
-
-// Remaining clocks to end frame:
-const int TOTAL_CYCLES = 29781;
-int remainingCycles;
-inline int elapsed() { return TOTAL_CYCLES - remainingCycles; }
-
-/* Cycle emulation */
-#define T tick()
-inline void tick() { PPU::step(); PPU::step(); PPU::step(); remainingCycles--; }
-
-/* Flags updating */
-inline void upd_cv(u8 x, u8 y, s16 r) { P[C] = (r>0xFF); P[V] = ~(x^y) & (x^r) & 0x80; }
-inline void upd_nz(u8 x) { P[N] = x & 0x80; P[Z] = (x == 0); }
-// Does adding I to A cross a page?
-inline bool cross(u16 a, u8 i) { return ((a+i) & 0xFF00) != ((a & 0xFF00)); }
-
-/* Memory access */
-void dma_oam(u8 bank);
-template<bool wr> inline u8 access(u16 addr, u8 v = 0)
-{
- u8* r;
- switch (addr)
- {
- case 0x0000 ... 0x1FFF: r = &ram[addr % 0x800]; if (wr) *r = v; return *r; // RAM.
- case 0x2000 ... 0x3FFF: return PPU::access<wr>(addr % 8, v); // PPU.
-
- // APU:
- case 0x4000 ... 0x4013:
- case 0x4015: return APU::access<wr>(elapsed(), addr, v);
- case 0x4017: if (wr) return APU::access<wr>(elapsed(), addr, v);
- else return Joypad::read_state(1); // Joypad 1.
-
- case 0x4014: if (wr) dma_oam(v); break; // OAM DMA.
- case 0x4016: if (wr) { Joypad::write_strobe(v & 1); break; } // Joypad strobe.
- else return Joypad::read_state(0); // Joypad 0.
- case 0x4018 ... 0xFFFF: return Cartridge::access<wr>(addr, v); // Cartridge.
- }
- return 0;
-}
-inline u8 wr(u16 a, u8 v) { T; return access<1>(a, v); }
-inline u8 rd(u16 a) { T; return access<0>(a); }
-inline u16 rd16_d(u16 a, u16 b) { return rd(a) | (rd(b) << 8); } // Read from A and B and merge.
-inline u16 rd16(u16 a) { return rd16_d(a, a+1); }
-inline u8 push(u8 v) { return wr(0x100 + (S--), v); }
-inline u8 pop() { return rd(0x100 + (++S)); }
-void dma_oam(u8 bank) { for (int i = 0; i < 256; i++) wr(0x2014, rd(bank*0x100 + i)); }
-
-/* Addressing modes */
-inline u16 imm() { return PC++; }
-inline u16 imm16() { PC += 2; return PC - 2; }
-inline u16 abs() { return rd16(imm16()); }
-inline u16 _abx() { T; return abs() + X; } // Exception.
-inline u16 abx() { u16 a = abs(); if (cross(a, X)) T; return a + X; }
-inline u16 aby() { u16 a = abs(); if (cross(a, Y)) T; return a + Y; }
-inline u16 zp() { return rd(imm()); }
-inline u16 zpx() { T; return (zp() + X) % 0x100; }
-inline u16 zpy() { T; return (zp() + Y) % 0x100; }
-inline u16 izx() { u8 i = zpx(); return rd16_d(i, (i+1) % 0x100); }
-inline u16 _izy() { u8 i = zp(); return rd16_d(i, (i+1) % 0x100) + Y; } // Exception.
-inline u16 izy() { u16 a = _izy(); if (cross(a-Y, Y)) T; return a; }
-
-/* STx */
-template<u8& r, Mode m> void st() { wr( m() , r); }
-template<> void st<A,izy>() { T; wr(_izy() , A); } // Exceptions.
-template<> void st<A,abx>() { T; wr( abs() + X, A); } // ...
-template<> void st<A,aby>() { T; wr( abs() + Y, A); } // ...
-
-#define G u16 a = m(); u8 p = rd(a) /* Fetch parameter */
-template<u8& r, Mode m> void ld() { G; upd_nz(r = p); } // LDx
-template<u8& r, Mode m> void cmp() { G; upd_nz(r - p); P[C] = (r >= p); } // CMP, CPx
-/* Arithmetic and bitwise */
-template<Mode m> void ADC() { G ; s16 r = A + p + P[C]; upd_cv(A, p, r); upd_nz(A = r); }
-template<Mode m> void SBC() { G ^ 0xFF; s16 r = A + p + P[C]; upd_cv(A, p, r); upd_nz(A = r); }
-template<Mode m> void BIT() { G; P[Z] = !(A & p); P[N] = p & 0x80; P[V] = p & 0x40; }
-template<Mode m> void AND() { G; upd_nz(A &= p); }
-template<Mode m> void EOR() { G; upd_nz(A ^= p); }
-template<Mode m> void ORA() { G; upd_nz(A |= p); }
-/* Read-Modify-Write */
-template<Mode m> void ASL() { G; P[C] = p & 0x80; T; upd_nz(wr(a, p << 1)); }
-template<Mode m> void LSR() { G; P[C] = p & 0x01; T; upd_nz(wr(a, p >> 1)); }
-template<Mode m> void ROL() { G; u8 c = P[C] ; P[C] = p & 0x80; T; upd_nz(wr(a, (p << 1) | c) ); }
-template<Mode m> void ROR() { G; u8 c = P[C] << 7; P[C] = p & 0x01; T; upd_nz(wr(a, c | (p >> 1)) ); }
-template<Mode m> void DEC() { G; T; upd_nz(wr(a, --p)); }
-template<Mode m> void INC() { G; T; upd_nz(wr(a, ++p)); }
-#undef G
-
-/* DEx, INx */
-template<u8& r> void dec() { upd_nz(--r); T; }
-template<u8& r> void inc() { upd_nz(++r); T; }
-/* Bit shifting on the accumulator */
-void ASL_A() { P[C] = A & 0x80; upd_nz(A <<= 1); T; }
-void LSR_A() { P[C] = A & 0x01; upd_nz(A >>= 1); T; }
-void ROL_A() { u8 c = P[C] ; P[C] = A & 0x80; upd_nz(A = ((A << 1) | c) ); T; }
-void ROR_A() { u8 c = P[C] << 7; P[C] = A & 0x01; upd_nz(A = (c | (A >> 1)) ); T; }
-
-/* Txx (move values between registers) */
-template<u8& s, u8& d> void tr() { upd_nz(d = s); T; }
-template<> void tr<X,S>() { S = X; T; } // TSX, exception.
-
-/* Stack operations */
-void PLP() { T; T; P.set(pop()); }
-void PHP() { T; push(P.get() | (1 << 4)); } // B flag set.
-void PLA() { T; T; A = pop(); upd_nz(A); }
-void PHA() { T; push(A); }
-
-/* Flow control (branches, jumps) */
-template<Flag f, bool v> void br()
-{
- s8 j = rd(imm());
- if (P[f] == v) {
- if (cross(PC, j)) T;
- T; PC += j;
- }
-}
-void JMP_IND() { u16 i = rd16(imm16()); PC = rd16_d(i, (i&0xFF00) | ((i+1) % 0x100)); }
-void JMP() { PC = rd16(imm16()); }
-void JSR() { u16 t = PC+1; T; push(t >> 8); push(t); PC = rd16(imm16()); }
-
-/* Return instructions */
-void RTS() { T; T; PC = (pop() | (pop() << 8)) + 1; T; }
-void RTI() { PLP(); PC = pop() | (pop() << 8); }
-
-template<Flag f, bool v> void flag() { P[f] = v; T; } // Clear and set flags.
-template<IntType t> void INT()
-{
- T; if (t != BRK) T; // BRK already performed the fetch.
- if (t != RESET) // Writes on stack are inhibited on RESET.
- {
- push(PC >> 8); push(PC & 0xFF);
- push(P.get() | ((t == BRK) << 4)); // Set B if BRK.
- }
- else { S -= 3; T; T; T; }
- P[I] = true;
- /* NMI Reset IRQ BRK */
- constexpr u16 vect[] = { 0xFFFA, 0xFFFC, 0xFFFE, 0xFFFE };
- PC = rd16(vect[t]);
- if (t == NMI) nmi = false;
-}
-void NOP() { T; }
-
-/* Execute a CPU instruction */
-void exec()
-{
- switch (rd(PC++)) // Fetch the opcode.
- {
- // Select the right function to emulate the instruction:
- case 0x00: return INT<BRK>() ; case 0x01: return ORA<izx>() ;
- case 0x05: return ORA<zp>() ; case 0x06: return ASL<zp>() ;
- case 0x08: return PHP() ; case 0x09: return ORA<imm>() ;
- case 0x0A: return ASL_A() ; case 0x0D: return ORA<abs>() ;
- case 0x0E: return ASL<abs>() ; case 0x10: return br<N,0>() ;
- case 0x11: return ORA<izy>() ; case 0x15: return ORA<zpx>() ;
- case 0x16: return ASL<zpx>() ; case 0x18: return flag<C,0>() ;
- case 0x19: return ORA<aby>() ; case 0x1D: return ORA<abx>() ;
- case 0x1E: return ASL<_abx>() ; case 0x20: return JSR() ;
- case 0x21: return AND<izx>() ; case 0x24: return BIT<zp>() ;
- case 0x25: return AND<zp>() ; case 0x26: return ROL<zp>() ;
- case 0x28: return PLP() ; case 0x29: return AND<imm>() ;
- case 0x2A: return ROL_A() ; case 0x2C: return BIT<abs>() ;
- case 0x2D: return AND<abs>() ; case 0x2E: return ROL<abs>() ;
- case 0x30: return br<N,1>() ; case 0x31: return AND<izy>() ;
- case 0x35: return AND<zpx>() ; case 0x36: return ROL<zpx>() ;
- case 0x38: return flag<C,1>() ; case 0x39: return AND<aby>() ;
- case 0x3D: return AND<abx>() ; case 0x3E: return ROL<_abx>() ;
- case 0x40: return RTI() ; case 0x41: return EOR<izx>() ;
- case 0x45: return EOR<zp>() ; case 0x46: return LSR<zp>() ;
- case 0x48: return PHA() ; case 0x49: return EOR<imm>() ;
- case 0x4A: return LSR_A() ; case 0x4C: return JMP() ;
- case 0x4D: return EOR<abs>() ; case 0x4E: return LSR<abs>() ;
- case 0x50: return br<V,0>() ; case 0x51: return EOR<izy>() ;
- case 0x55: return EOR<zpx>() ; case 0x56: return LSR<zpx>() ;
- case 0x58: return flag<I,0>() ; case 0x59: return EOR<aby>() ;
- case 0x5D: return EOR<abx>() ; case 0x5E: return LSR<_abx>() ;
- case 0x60: return RTS() ; case 0x61: return ADC<izx>() ;
- case 0x65: return ADC<zp>() ; case 0x66: return ROR<zp>() ;
- case 0x68: return PLA() ; case 0x69: return ADC<imm>() ;
- case 0x6A: return ROR_A() ; case 0x6C: return JMP_IND() ;
- case 0x6D: return ADC<abs>() ; case 0x6E: return ROR<abs>() ;
- case 0x70: return br<V,1>() ; case 0x71: return ADC<izy>() ;
- case 0x75: return ADC<zpx>() ; case 0x76: return ROR<zpx>() ;
- case 0x78: return flag<I,1>() ; case 0x79: return ADC<aby>() ;
- case 0x7D: return ADC<abx>() ; case 0x7E: return ROR<_abx>() ;
- case 0x81: return st<A,izx>() ; case 0x84: return st<Y,zp>() ;
- case 0x85: return st<A,zp>() ; case 0x86: return st<X,zp>() ;
- case 0x88: return dec<Y>() ; case 0x8A: return tr<X,A>() ;
- case 0x8C: return st<Y,abs>() ; case 0x8D: return st<A,abs>() ;
- case 0x8E: return st<X,abs>() ; case 0x90: return br<C,0>() ;
- case 0x91: return st<A,izy>() ; case 0x94: return st<Y,zpx>() ;
- case 0x95: return st<A,zpx>() ; case 0x96: return st<X,zpy>() ;
- case 0x98: return tr<Y,A>() ; case 0x99: return st<A,aby>() ;
- case 0x9A: return tr<X,S>() ; case 0x9D: return st<A,abx>() ;
- case 0xA0: return ld<Y,imm>() ; case 0xA1: return ld<A,izx>() ;
- case 0xA2: return ld<X,imm>() ; case 0xA4: return ld<Y,zp>() ;
- case 0xA5: return ld<A,zp>() ; case 0xA6: return ld<X,zp>() ;
- case 0xA8: return tr<A,Y>() ; case 0xA9: return ld<A,imm>() ;
- case 0xAA: return tr<A,X>() ; case 0xAC: return ld<Y,abs>() ;
- case 0xAD: return ld<A,abs>() ; case 0xAE: return ld<X,abs>() ;
- case 0xB0: return br<C,1>() ; case 0xB1: return ld<A,izy>() ;
- case 0xB4: return ld<Y,zpx>() ; case 0xB5: return ld<A,zpx>() ;
- case 0xB6: return ld<X,zpy>() ; case 0xB8: return flag<V,0>() ;
- case 0xB9: return ld<A,aby>() ; case 0xBA: return tr<S,X>() ;
- case 0xBC: return ld<Y,abx>() ; case 0xBD: return ld<A,abx>() ;
- case 0xBE: return ld<X,aby>() ; case 0xC0: return cmp<Y,imm>();
- case 0xC1: return cmp<A,izx>(); case 0xC4: return cmp<Y,zp>() ;
- case 0xC5: return cmp<A,zp>() ; case 0xC6: return DEC<zp>() ;
- case 0xC8: return inc<Y>() ; case 0xC9: return cmp<A,imm>();
- case 0xCA: return dec<X>() ; case 0xCC: return cmp<Y,abs>();
- case 0xCD: return cmp<A,abs>(); case 0xCE: return DEC<abs>() ;
- case 0xD0: return br<Z,0>() ; case 0xD1: return cmp<A,izy>();
- case 0xD5: return cmp<A,zpx>(); case 0xD6: return DEC<zpx>() ;
- case 0xD8: return flag<D,0>() ; case 0xD9: return cmp<A,aby>();
- case 0xDD: return cmp<A,abx>(); case 0xDE: return DEC<_abx>() ;
- case 0xE0: return cmp<X,imm>(); case 0xE1: return SBC<izx>() ;
- case 0xE4: return cmp<X,zp>() ; case 0xE5: return SBC<zp>() ;
- case 0xE6: return INC<zp>() ; case 0xE8: return inc<X>() ;
- case 0xE9: return SBC<imm>() ; case 0xEA: return NOP() ;
- case 0xEC: return cmp<X,abs>(); case 0xED: return SBC<abs>() ;
- case 0xEE: return INC<abs>() ; case 0xF0: return br<Z,1>() ;
- case 0xF1: return SBC<izy>() ; case 0xF5: return SBC<zpx>() ;
- case 0xF6: return INC<zpx>() ; case 0xF8: return flag<D,1>() ;
- case 0xF9: return SBC<aby>() ; case 0xFD: return SBC<abx>() ;
- case 0xFE: return INC<_abx>() ;
- default:
- std::cout << "Invalid Opcode! PC: " << PC << " Opcode: 0x" << std::hex << (int)(rd(PC - 1)) << "\n";
- return NOP();
- }
-}
-
-void set_nmi(bool v) { nmi = v; }
-void set_irq(bool v) { irq = v; }
-
-int dmc_read(void*, cpu_addr_t addr) { return access<0>(addr); }
-
-/* Turn on the CPU */
-void power()
-{
- remainingCycles = 0;
-
- P.set(0x04);
- A = X = Y = S = 0x00;
- memset(ram, 0xFF, sizeof(ram));
-
- nmi = irq = false;
- INT<RESET>();
-}
-
-/* Run the CPU for roughly a frame */
-void run_frame()
-{
- remainingCycles += TOTAL_CYCLES;
-
- while (remainingCycles > 0)
- {
- if (nmi) INT<NMI>();
- else if (irq and !P[I]) INT<IRQ>();
-
- exec();
- }
-
- APU::run_frame(elapsed());
-}
-
-
-}
diff --git a/old/gui.cpp b/old/gui.cpp
deleted file mode 100644
index dd0692f..0000000
--- a/old/gui.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-#include <csignal>
-#include <SDL2/SDL_image.h>
-#include <SDL2/SDL_ttf.h>
-#include "Sound_Queue.h"
-#include "apu.hpp"
-#include "cartridge.hpp"
-#include "cpu.hpp"
-#include "menu.hpp"
-#include "gui.hpp"
-#include "config.hpp"
-
-namespace GUI {
-
-// SDL structures:
-SDL_Window* window;
-SDL_Renderer* renderer;
-SDL_Texture* gameTexture;
-SDL_Texture* background;
-TTF_Font* font;
-u8 const* keys;
-Sound_Queue* soundQueue;
-SDL_Joystick* joystick[] = { nullptr, nullptr };
-
-// Menus:
-Menu* menu;
-Menu* mainMenu;
-Menu* settingsMenu;
-Menu* videoMenu;
-Menu* keyboardMenu[2];
-Menu* joystickMenu[2];
-FileMenu* fileMenu;
-
-bool pause = true;
-
-/* Set the window size multiplier */
-void set_size(int mul)
-{
- last_window_size = mul;
- SDL_SetWindowSize(window, WIDTH * mul, HEIGHT * mul);
- SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
-}
-
-/* Initialize GUI */
-void init()
-{
- // Initialize graphics system:
- SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
- SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
- TTF_Init();
-
- for (int i = 0; i < SDL_NumJoysticks(); i++)
- joystick[i] = SDL_JoystickOpen(i);
-
- APU::init();
- soundQueue = new Sound_Queue;
- soundQueue->init(96000);
-
- // Initialize graphics structures:
- window = SDL_CreateWindow ("LaiNES",
- SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
- WIDTH * last_window_size, HEIGHT * last_window_size, 0);
-
- renderer = SDL_CreateRenderer(window, -1,
- SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- SDL_RenderSetLogicalSize(renderer, WIDTH, HEIGHT);
-
- gameTexture = SDL_CreateTexture (renderer,
- SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
- WIDTH, HEIGHT);
-
- font = TTF_OpenFont("res/font.ttf", FONT_SZ);
- keys = SDL_GetKeyboardState(0);
-
- // Initial background:
- SDL_Surface* backSurface = IMG_Load("res/init.png");
- background = SDL_CreateTextureFromSurface(renderer, backSurface);
- SDL_SetTextureColorMod(background, 60, 60, 60);
- SDL_FreeSurface(backSurface);
-
- // Menus:
- mainMenu = new Menu;
- mainMenu->add(new Entry("Load ROM", []{ menu = fileMenu; }));
- mainMenu->add(new Entry("Settings", []{ menu = settingsMenu; }));
- mainMenu->add(new Entry("Exit", []{ exit(0); }));
-
- settingsMenu = new Menu;
- settingsMenu->add(new Entry("<", []{ menu = mainMenu; }));
- settingsMenu->add(new Entry("Video", []{ menu = videoMenu; }));
- settingsMenu->add(new Entry("Controller 1", []{ menu = useJoystick[0] ? joystickMenu[0] : keyboardMenu[0]; }));
- settingsMenu->add(new Entry("Controller 2", []{ menu = useJoystick[1] ? joystickMenu[1] : keyboardMenu[1]; }));
- settingsMenu->add(new Entry("Save Settings", []{ save_settings(); menu = mainMenu; }));
-
- videoMenu = new Menu;
- videoMenu->add(new Entry("<", []{ menu = settingsMenu; }));
- videoMenu->add(new Entry("Size 1x", []{ set_size(1); }));
- videoMenu->add(new Entry("Size 2x", []{ set_size(2); }));
- videoMenu->add(new Entry("Size 3x", []{ set_size(3); }));
- videoMenu->add(new Entry("Size 4x", []{ set_size(4); }));
-
- for (int i = 0; i < 2; i++)
- {
- keyboardMenu[i] = new Menu;
- keyboardMenu[i]->add(new Entry("<", []{ menu = settingsMenu; }));
- if (joystick[i] != nullptr)
- keyboardMenu[i]->add(new Entry("Joystick >", [=]{ menu = joystickMenu[i]; useJoystick[i] = true; }));
- keyboardMenu[i]->add(new ControlEntry("Up", &KEY_UP[i]));
- keyboardMenu[i]->add(new ControlEntry("Down", &KEY_DOWN[i]));
- keyboardMenu[i]->add(new ControlEntry("Left", &KEY_LEFT[i]));
- keyboardMenu[i]->add(new ControlEntry("Right", &KEY_RIGHT[i]));
- keyboardMenu[i]->add(new ControlEntry("A", &KEY_A[i]));
- keyboardMenu[i]->add(new ControlEntry("B", &KEY_B[i]));
- keyboardMenu[i]->add(new ControlEntry("Start", &KEY_START[i]));
- keyboardMenu[i]->add(new ControlEntry("Select", &KEY_SELECT[i]));
-
- if (joystick[i] != nullptr)
- {
- joystickMenu[i] = new Menu;
- joystickMenu[i]->add(new Entry("<", []{ menu = settingsMenu; }));
- joystickMenu[i]->add(new Entry("< Keyboard", [=]{ menu = keyboardMenu[i]; useJoystick[i] = false; }));
- joystickMenu[i]->add(new ControlEntry("Up", &BTN_UP[i]));
- joystickMenu[i]->add(new ControlEntry("Down", &BTN_DOWN[i]));
- joystickMenu[i]->add(new ControlEntry("Left", &BTN_LEFT[i]));
- joystickMenu[i]->add(new ControlEntry("Right", &BTN_RIGHT[i]));
- joystickMenu[i]->add(new ControlEntry("A", &BTN_A[i]));
- joystickMenu[i]->add(new ControlEntry("B", &BTN_B[i]));
- joystickMenu[i]->add(new ControlEntry("Start", &BTN_START[i]));
- joystickMenu[i]->add(new ControlEntry("Select", &BTN_SELECT[i]));
- }
- }
-
- fileMenu = new FileMenu;
-
- menu = mainMenu;
-}
-
-/* Render a texture on screen */
-void render_texture(SDL_Texture* texture, int x, int y)
-{
- int w, h;
- SDL_Rect dest;
-
- SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);
- if (x == TEXT_CENTER)
- dest.x = WIDTH/2 - dest.w/2;
- else if (x == TEXT_RIGHT)
- dest.x = WIDTH - dest.w - 10;
- else
- dest.x = x + 10;
- dest.y = y + 5;
-
- SDL_RenderCopy(renderer, texture, NULL, &dest);
-}
-
-/* Generate a texture from text */
-SDL_Texture* gen_text(std::string text, SDL_Color color)
-{
- SDL_Surface* surface = TTF_RenderText_Blended(font, text.c_str(), color);
- SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
-
- SDL_FreeSurface(surface);
- return texture;
-}
-
-/* Get the joypad state from SDL */
-u8 get_joypad_state(int n)
-{
- const int DEAD_ZONE = 8000;
-
- u8 j = 0;
- if (useJoystick[n])
- {
- j |= (SDL_JoystickGetButton(joystick[n], BTN_A[n])) << 0; // A.
- j |= (SDL_JoystickGetButton(joystick[n], BTN_B[n])) << 1; // B.
- j |= (SDL_JoystickGetButton(joystick[n], BTN_SELECT[n])) << 2; // Select.
- j |= (SDL_JoystickGetButton(joystick[n], BTN_START[n])) << 3; // Start.
-
- j |= (SDL_JoystickGetButton(joystick[n], BTN_UP[n])) << 4; // Up.
- j |= (SDL_JoystickGetAxis(joystick[n], 1) < -DEAD_ZONE) << 4;
- j |= (SDL_JoystickGetButton(joystick[n], BTN_DOWN[n])) << 5; // Down.
- j |= (SDL_JoystickGetAxis(joystick[n], 1) > DEAD_ZONE) << 5;
- j |= (SDL_JoystickGetButton(joystick[n], BTN_LEFT[n])) << 6; // Left.
- j |= (SDL_JoystickGetAxis(joystick[n], 0) < -DEAD_ZONE) << 6;
- j |= (SDL_JoystickGetButton(joystick[n], BTN_RIGHT[n])) << 7; // Right.
- j |= (SDL_JoystickGetAxis(joystick[n], 0) > DEAD_ZONE) << 7;
- }
- else
- {
- j |= (keys[KEY_A[n]]) << 0;
- j |= (keys[KEY_B[n]]) << 1;
- j |= (keys[KEY_SELECT[n]]) << 2;
- j |= (keys[KEY_START[n]]) << 3;
- j |= (keys[KEY_UP[n]]) << 4;
- j |= (keys[KEY_DOWN[n]]) << 5;
- j |= (keys[KEY_LEFT[n]]) << 6;
- j |= (keys[KEY_RIGHT[n]]) << 7;
- }
- return j;
-}
-
-/* Send the rendered frame to the GUI */
-void new_frame(u32* pixels)
-{
- SDL_UpdateTexture(gameTexture, NULL, pixels, WIDTH * sizeof(u32));
-}
-
-void new_samples(const blip_sample_t* samples, size_t count)
-{
- soundQueue->write(samples, count);
-}
-
-/* Render the screen */
-void render()
-{
- SDL_RenderClear(renderer);
-
- // Draw the NES screen:
- if (Cartridge::loaded())
- SDL_RenderCopy(renderer, gameTexture, NULL, NULL);
- else
- SDL_RenderCopy(renderer, background, NULL, NULL);
-
- // Draw the menu:
- if (pause) menu->render();
-
- SDL_RenderPresent(renderer);
-}
-
-/* Play/stop the game */
-void toggle_pause()
-{
- pause = not pause;
- menu = mainMenu;
-
- if (pause)
- SDL_SetTextureColorMod(gameTexture, 60, 60, 60);
- else
- SDL_SetTextureColorMod(gameTexture, 255, 255, 255);
-}
-
-/* Prompt for a key, return the scancode */
-SDL_Scancode query_key()
-{
- SDL_Texture* prompt = gen_text("Press a key...", { 255, 255, 255 });
- render_texture(prompt, TEXT_CENTER, HEIGHT - FONT_SZ*4);
- SDL_RenderPresent(renderer);
-
- SDL_Event e;
- while (true)
- {
- SDL_PollEvent(&e);
- if (e.type == SDL_KEYDOWN)
- return e.key.keysym.scancode;
- }
-}
-
-int query_button()
-{
- SDL_Texture* prompt = gen_text("Press a button...", { 255, 255, 255 });
- render_texture(prompt, TEXT_CENTER, HEIGHT - FONT_SZ*4);
- SDL_RenderPresent(renderer);
-
- SDL_Event e;
- while (true)
- {
- SDL_PollEvent(&e);
- if (e.type == SDL_JOYBUTTONDOWN)
- return e.jbutton.button;
- }
-}
-
-/* Run the emulator */
-void run()
-{
- SDL_Event e;
-
- // Framerate control:
- u32 frameStart, frameTime;
- const int FPS = 60;
- const int DELAY = 1000.0f / FPS;
-
- while (true)
- {
- frameStart = SDL_GetTicks();
-
- // Handle events:
- while (SDL_PollEvent(&e))
- switch (e.type)
- {
- case SDL_QUIT: return;
- case SDL_KEYDOWN:
- if (keys[SDL_SCANCODE_ESCAPE] and Cartridge::loaded())
- toggle_pause();
- else if (pause)
- menu->update(keys);
- }
-
- if (not pause) CPU::run_frame();
- render();
-
- // Wait to mantain framerate:
- frameTime = SDL_GetTicks() - frameStart;
- if (frameTime < DELAY)
- SDL_Delay((int)(DELAY - frameTime));
- }
-}
-
-
-}
diff --git a/old/include/apu.hpp b/old/include/apu.hpp
deleted file mode 100644
index a5d15cb..0000000
--- a/old/include/apu.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "common.hpp"
-
-namespace APU {
-
-
-template <bool write> u8 access(int elapsed, u16 addr, u8 v = 0);
-void run_frame(int elapsed);
-void reset();
-void init();
-
-
-}
diff --git a/old/include/cartridge.hpp b/old/include/cartridge.hpp
deleted file mode 100644
index c49ec21..0000000
--- a/old/include/cartridge.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-#include "common.hpp"
-
-namespace Cartridge {
-
-
-template <bool wr> u8 access(u16 addr, u8 v = 0);
-template <bool wr> u8 chr_access(u16 addr, u8 v = 0);
-void signal_scanline();
-void load(const char* fileName);
-bool loaded();
-
-
-}
diff --git a/old/include/common.hpp b/old/include/common.hpp
deleted file mode 100644
index 5d5dc79..0000000
--- a/old/include/common.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma once
-#include <cstdint>
-
-#define NTH_BIT(x, n) (((x) >> (n)) & 1)
-
-/* Integer type shortcuts */
-typedef uint8_t u8; typedef int8_t s8;
-typedef uint16_t u16; typedef int16_t s16;
-typedef uint32_t u32; typedef int32_t s32;
-typedef uint64_t u64; typedef int64_t s64;
diff --git a/old/include/config.hpp b/old/include/config.hpp
deleted file mode 100644
index 03344df..0000000
--- a/old/include/config.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-#include <cerrno>
-#include <sys/stat.h>
-#include <SDL2/SDL.h>
-
-#define CONFIG_DIR_DEFAULT_MODE S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
-#define USE_CONFIG_DIR true
-#define CONFIG_DIR_NAME "LaiNES"
-#define CONFIG_FALLBACK ".laines-settings"
-/* PATH_MAX is a portability nightmare. */
-#define CONFIG_PATH_MAX 1024
-
-namespace GUI {
-
-/* Loading and saving */
-void load_settings();
-void save_settings();
-const char* get_config_path(char * buf, int buflen);
-
-extern int last_window_size;
-extern SDL_Scancode KEY_A [];
-extern SDL_Scancode KEY_B [];
-extern SDL_Scancode KEY_SELECT[];
-extern SDL_Scancode KEY_START [];
-extern SDL_Scancode KEY_UP [];
-extern SDL_Scancode KEY_DOWN [];
-extern SDL_Scancode KEY_LEFT [];
-extern SDL_Scancode KEY_RIGHT [];
-extern int BTN_UP [];
-extern int BTN_DOWN [];
-extern int BTN_LEFT [];
-extern int BTN_RIGHT [];
-extern int BTN_A [];
-extern int BTN_B [];
-extern int BTN_SELECT[];
-extern int BTN_START [];
-extern bool useJoystick[];
-
-}
diff --git a/old/include/cpu.hpp b/old/include/cpu.hpp
deleted file mode 100644
index 8b15e19..0000000
--- a/old/include/cpu.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-#include "common.hpp"
-#include <Nes_Apu.h>
-
-namespace CPU {
-
-
-enum IntType { NMI, RESET, IRQ, BRK }; // Interrupt type.
-typedef u16 (*Mode)(void); // Addressing mode.
-
-/* Processor flags */
-enum Flag {C, Z, I, D, V, N};
-class Flags
-{
- bool f[6];
-
- public:
- bool& operator[] (const int i) { return f[i]; }
-
- u8 get() { return f[C] | f[Z] << 1 | f[I] << 2 | f[D] << 3 | 1 << 5 | f[V] << 6 | f[N] << 7; }
- void set(u8 p) { f[C] = NTH_BIT(p, 0); f[Z] = NTH_BIT(p, 1); f[I] = NTH_BIT(p, 2);
- f[D] = NTH_BIT(p, 3); f[V] = NTH_BIT(p, 6); f[N] = NTH_BIT(p, 7); }
-};
-
-void set_nmi(bool v = true);
-void set_irq(bool v = true);
-int dmc_read(void*, cpu_addr_t addr);
-void power();
-void run_frame();
-
-
-}
diff --git a/old/include/gui.hpp b/old/include/gui.hpp
deleted file mode 100644
index 297d34e..0000000
--- a/old/include/gui.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-#include <SDL2/SDL.h>
-#include <string>
-#include <Nes_Apu.h>
-#include "common.hpp"
-
-namespace GUI {
-
-// Screen size:
-const unsigned WIDTH = 256;
-const unsigned HEIGHT = 240;
-const int TEXT_CENTER = -1;
-const int TEXT_RIGHT = -2;
-const unsigned FONT_SZ = 15;
-
-void init();
-void toggle_pause();
-SDL_Scancode query_key();
-int query_button();
-void run();
-
-SDL_Texture* gen_text(std::string text, SDL_Color color);
-void render_texture(SDL_Texture* texture, int x, int y);
-
-u8 get_joypad_state(int n);
-void new_frame(u32* pixels);
-void new_samples(const blip_sample_t* samples, size_t count);
-void set_size(int mul);
-
-}
diff --git a/old/include/joypad.hpp b/old/include/joypad.hpp
deleted file mode 100644
index fac0332..0000000
--- a/old/include/joypad.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-#include "common.hpp"
-
-namespace Joypad {
-
-
-u8 read_state(int n);
-void write_strobe(bool v);
-
-
-}
diff --git a/old/include/mapper.hpp b/old/include/mapper.hpp
deleted file mode 100644
index 76f441d..0000000
--- a/old/include/mapper.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-#include <cstring>
-#include "common.hpp"
-
-
-class Mapper
-{
- u8* rom;
- bool chrRam = false;
-
- protected:
- u32 prgMap[4];
- u32 chrMap[8];
-
- u8 *prg, *chr, *prgRam;
- u32 prgSize, chrSize, prgRamSize;
-
- template <int pageKBs> void map_prg(int slot, int bank);
- template <int pageKBs> void map_chr(int slot, int bank);
-
- public:
- Mapper(u8* rom);
- ~Mapper();
-
- u8 read(u16 addr);
- virtual u8 write(u16 addr, u8 v) { return v; }
-
- u8 chr_read(u16 addr);
- virtual u8 chr_write(u16 addr, u8 v) { return v; }
-
- virtual void signal_scanline() {}
-};
diff --git a/old/include/mappers/mapper0.hpp b/old/include/mappers/mapper0.hpp
deleted file mode 100644
index e5d5950..0000000
--- a/old/include/mappers/mapper0.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "mapper.hpp"
-
-
-class Mapper0 : public Mapper
-{
- public:
- Mapper0(u8* rom) : Mapper(rom)
- {
- map_prg<32>(0, 0);
- map_chr<8> (0, 0);
- }
-};
diff --git a/old/include/mappers/mapper1.hpp b/old/include/mappers/mapper1.hpp
deleted file mode 100644
index 756b21b..0000000
--- a/old/include/mappers/mapper1.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-#include "mapper.hpp"
-
-
-class Mapper1 : public Mapper
-{
- int writeN;
- u8 tmpReg;
- u8 regs[4];
-
- void apply();
-
- public:
- Mapper1(u8* rom) : Mapper(rom)
- {
- regs[0] = 0x0C;
- writeN = tmpReg = regs[1] = regs[2] = regs[3] = 0;
- apply();
- }
-
- u8 write(u16 addr, u8 v);
- u8 chr_write(u16 addr, u8 v);
-};
diff --git a/old/include/mappers/mapper2.hpp b/old/include/mappers/mapper2.hpp
deleted file mode 100644
index 0deea6e..0000000
--- a/old/include/mappers/mapper2.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include "mapper.hpp"
-
-
-class Mapper2 : public Mapper
-{
- u8 regs[1];
- bool vertical_mirroring;
-
- void apply();
-
- public:
- Mapper2(u8* rom) : Mapper(rom)
- {
- regs[0] = 0;
- vertical_mirroring = rom[6] & 0x01;
- apply();
- }
-
- u8 write(u16 addr, u8 v);
- u8 chr_write(u16 addr, u8 v);
-};
diff --git a/old/include/mappers/mapper3.hpp b/old/include/mappers/mapper3.hpp
deleted file mode 100644
index b159549..0000000
--- a/old/include/mappers/mapper3.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-#include "mapper.hpp"
-
-
-class Mapper3 : public Mapper
-{
- u8 regs[1];
- bool vertical_mirroring;
- bool PRG_size_16k;
- void apply();
-
- public:
- Mapper3(u8* rom) : Mapper(rom)
- {
- PRG_size_16k = rom[4] == 1;
- vertical_mirroring = rom[6] & 0x01;
- regs[0] = 0;
- apply();
- }
-
- u8 write(u16 addr, u8 v);
- u8 chr_write(u16 addr, u8 v);
-};
-
diff --git a/old/include/mappers/mapper4.hpp b/old/include/mappers/mapper4.hpp
deleted file mode 100644
index 5cb605c..0000000
--- a/old/include/mappers/mapper4.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-#include "mapper.hpp"
-
-
-class Mapper4 : public Mapper
-{
- u8 reg8000;
- u8 regs[8];
- bool horizMirroring;
-
- u8 irqPeriod;
- u8 irqCounter;
- bool irqEnabled;
-
- void apply();
-
- public:
- Mapper4(u8* rom) : Mapper(rom)
- {
- for (int i = 0; i < 8; i++)
- regs[i] = 0;
-
- horizMirroring = true;
- irqEnabled = false;
- irqPeriod = irqCounter = 0;
-
- map_prg<8>(3, -1);
- apply();
- }
-
- u8 write(u16 addr, u8 v);
- u8 chr_write(u16 addr, u8 v);
-
- void signal_scanline();
-};
diff --git a/old/include/menu.hpp b/old/include/menu.hpp
deleted file mode 100644
index 612ce91..0000000
--- a/old/include/menu.hpp
+++ /dev/null
@@ -1,73 +0,0 @@
-#pragma once
-#include <functional>
-#include <SDL2/SDL.h>
-#include <string>
-#include <vector>
-#include "gui.hpp"
-
-namespace GUI {
-
-
-class Entry
-{
- std::string label;
- std::function<void()> callback;
-
- bool selected = false;
- SDL_Texture* whiteTexture = nullptr;
- SDL_Texture* redTexture = nullptr;
-
- public:
- Entry(std::string label, std::function<void()> callback = []{});
- ~Entry();
-
- void set_label(std::string label);
- inline std::string& get_label() { return label; }
-
- virtual void select() { selected = true; };
- virtual void unselect() { selected = false; };
- void trigger() { callback(); };
- virtual void render(int x, int y);
-};
-
-class ControlEntry : public Entry
-{
- SDL_Scancode* key;
- int* button;
- Entry* keyEntry;
-
- public:
- ControlEntry(std::string action, SDL_Scancode* key);
- ControlEntry(std::string action, int* button);
- void select() { Entry::select(); keyEntry->select(); }
- void unselect() { Entry::unselect(); keyEntry->unselect(); }
- void render(int x, int y) { Entry::render(x, y); keyEntry->render(TEXT_RIGHT, y); }
-};
-
-class Menu
-{
- const int MAX_ENTRY = GUI::HEIGHT / FONT_SZ - 1;
- int cursor = 0;
- int top = 0;
- int bottom = MAX_ENTRY;
-
- public:
- std::vector<Entry*> entries;
-
- void add(Entry* entry);
- void clear();
- void sort_by_label();
- void update(u8 const* keys);
- void render();
-};
-
-class FileMenu : public Menu
-{
- void change_dir(std::string dir);
-
- public:
- FileMenu();
-};
-
-
-}
diff --git a/old/include/ppu.hpp b/old/include/ppu.hpp
deleted file mode 100644
index e3f5e14..0000000
--- a/old/include/ppu.hpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-#include "common.hpp"
-
-namespace PPU {
-
-
-enum Scanline { VISIBLE, POST, NMI, PRE };
-enum Mirroring { VERTICAL, HORIZONTAL };
-
-/* Sprite buffer */
-struct Sprite
-{
- u8 id; // Index in OAM.
- u8 x; // X position.
- u8 y; // Y position.
- u8 tile; // Tile index.
- u8 attr; // Attributes.
- u8 dataL; // Tile data (low).
- u8 dataH; // Tile data (high).
-};
-
-/* PPUCTRL ($2000) register */
-union Ctrl
-{
- struct
- {
- unsigned nt : 2; // Nametable ($2000 / $2400 / $2800 / $2C00).
- unsigned incr : 1; // Address increment (1 / 32).
- unsigned sprTbl : 1; // Sprite pattern table ($0000 / $1000).
- unsigned bgTbl : 1; // BG pattern table ($0000 / $1000).
- unsigned sprSz : 1; // Sprite size (8x8 / 8x16).
- unsigned slave : 1; // PPU master/slave.
- unsigned nmi : 1; // Enable NMI.
- };
- u8 r;
-};
-
-/* PPUMASK ($2001) register */
-union Mask
-{
- struct
- {
- unsigned gray : 1; // Grayscale.
- unsigned bgLeft : 1; // Show background in leftmost 8 pixels.
- unsigned sprLeft : 1; // Show sprite in leftmost 8 pixels.
- unsigned bg : 1; // Show background.
- unsigned spr : 1; // Show sprites.
- unsigned red : 1; // Intensify reds.
- unsigned green : 1; // Intensify greens.
- unsigned blue : 1; // Intensify blues.
- };
- u8 r;
-};
-
-/* PPUSTATUS ($2002) register */
-union Status
-{
- struct
- {
- unsigned bus : 5; // Not significant.
- unsigned sprOvf : 1; // Sprite overflow.
- unsigned sprHit : 1; // Sprite 0 Hit.
- unsigned vBlank : 1; // In VBlank?
- };
- u8 r;
-};
-
-/* Loopy's VRAM address */
-union Addr
-{
- struct
- {
- unsigned cX : 5; // Coarse X.
- unsigned cY : 5; // Coarse Y.
- unsigned nt : 2; // Nametable.
- unsigned fY : 3; // Fine Y.
- };
- struct
- {
- unsigned l : 8;
- unsigned h : 7;
- };
- unsigned addr : 14;
- unsigned r : 15;
-};
-
-template <bool write> u8 access(u16 index, u8 v = 0);
-void set_mirroring(Mirroring mode);
-void step();
-void reset();
-
-
-}
diff --git a/old/joypad.cpp b/old/joypad.cpp
deleted file mode 100644
index 35ae822..0000000
--- a/old/joypad.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "gui.hpp"
-
-namespace Joypad {
-
-
-u8 joypad_bits[2]; // Joypad shift registers.
-bool strobe; // Joypad strobe latch.
-
-/* Read joypad state (NES register format) */
-u8 read_state(int n)
-{
- // When strobe is high, it keeps reading A:
- if (strobe)
- return 0x40 | (GUI::get_joypad_state(n) & 1);
-
- // Get the status of a button and shift the register:
- u8 j = 0x40 | (joypad_bits[n] & 1);
- joypad_bits[n] = 0x80 | (joypad_bits[n] >> 1);
- return j;
-}
-
-void write_strobe(bool v)
-{
- // Read the joypad data on strobe's transition 1 -> 0.
- if (strobe and !v)
- for (int i = 0; i < 2; i++)
- joypad_bits[i] = GUI::get_joypad_state(i);
-
- strobe = v;
-}
-
-
-}
diff --git a/old/main.cpp b/old/main.cpp
deleted file mode 100644
index 787b006..0000000
--- a/old/main.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "gui.hpp"
-#include "config.hpp"
-
-int main(int argc, char *argv[])
-{
- GUI::load_settings();
- GUI::init();
- GUI::run();
-
- return 0;
-}
diff --git a/old/mapper.cpp b/old/mapper.cpp
deleted file mode 100644
index e7a2628..0000000
--- a/old/mapper.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "ppu.hpp"
-#include "mapper.hpp"
-
-
-Mapper::Mapper(u8* rom) : rom(rom)
-{
- // Read infos from header:
- prgSize = rom[4] * 0x4000;
- chrSize = rom[5] * 0x2000;
- prgRamSize = rom[8] ? rom[8] * 0x2000 : 0x2000;
- set_mirroring((rom[6] & 1) ? PPU::VERTICAL : PPU::HORIZONTAL);
-
- this->prg = rom + 16;
- this->prgRam = new u8[prgRamSize];
-
- // CHR ROM:
- if (chrSize)
- this->chr = rom + 16 + prgSize;
- // CHR RAM:
- else
- {
- chrRam = true;
- chrSize = 0x2000;
- this->chr = new u8[chrSize];
- }
-}
-
-Mapper::~Mapper()
-{
- delete rom;
- delete prgRam;
- if (chrRam)
- delete chr;
-}
-
-/* Access to memory */
-u8 Mapper::read(u16 addr)
-{
- if (addr >= 0x8000)
- return prg[prgMap[(addr - 0x8000) / 0x2000] + ((addr - 0x8000) % 0x2000)];
- else
- return prgRam[addr - 0x6000];
-}
-
-u8 Mapper::chr_read(u16 addr)
-{
- return chr[chrMap[addr / 0x400] + (addr % 0x400)];
-}
-
-/* PRG mapping functions */
-template <int pageKBs> void Mapper::map_prg(int slot, int bank)
-{
- if (bank < 0)
- bank = (prgSize / (0x400*pageKBs)) + bank;
-
- for (int i = 0; i < (pageKBs/8); i++)
- prgMap[(pageKBs/8) * slot + i] = (pageKBs*0x400*bank + 0x2000*i) % prgSize;
-}
-template void Mapper::map_prg<32>(int, int);
-template void Mapper::map_prg<16>(int, int);
-template void Mapper::map_prg<8> (int, int);
-
-/* CHR mapping functions */
-template <int pageKBs> void Mapper::map_chr(int slot, int bank)
-{
- for (int i = 0; i < pageKBs; i++)
- chrMap[pageKBs*slot + i] = (pageKBs*0x400*bank + 0x400*i) % chrSize;
-}
-template void Mapper::map_chr<8>(int, int);
-template void Mapper::map_chr<4>(int, int);
-template void Mapper::map_chr<2>(int, int);
-template void Mapper::map_chr<1>(int, int);
diff --git a/old/mappers/mapper1.cpp b/old/mappers/mapper1.cpp
deleted file mode 100644
index 827962d..0000000
--- a/old/mappers/mapper1.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "ppu.hpp"
-#include "mappers/mapper1.hpp"
-
-
-/* Apply the registers state */
-void Mapper1::apply()
-{
- // 16KB PRG:
- if (regs[0] & 0b1000)
- {
- // 0x8000 swappable, 0xC000 fixed to bank 0x0F:
- if (regs[0] & 0b100)
- {
- map_prg<16>(0, regs[3] & 0xF);
- map_prg<16>(1, 0xF);
- }
- // 0x8000 fixed to bank 0x00, 0xC000 swappable:
- else
- {
- map_prg<16>(0, 0);
- map_prg<16>(1, regs[3] & 0xF);
- }
- }
- // 32KB PRG:
- else
- map_prg<32>(0, (regs[3] & 0xF) >> 1);
-
- // 4KB CHR:
- if (regs[0] & 0b10000)
- {
- map_chr<4>(0, regs[1]);
- map_chr<4>(1, regs[2]);
- }
- // 8KB CHR:
- else
- map_chr<8>(0, regs[1] >> 1);
-
- // Set mirroring:
- switch (regs[0] & 0b11)
- {
- case 2: set_mirroring(PPU::VERTICAL); break;
- case 3: set_mirroring(PPU::HORIZONTAL); break;
- }
-}
-
-u8 Mapper1::write(u16 addr, u8 v)
-{
- // PRG RAM write;
- if (addr < 0x8000)
- prgRam[addr - 0x6000] = v;
- // Mapper register write:
- else if (addr & 0x8000)
- {
- // Reset:
- if (v & 0x80)
- {
- writeN = 0;
- tmpReg = 0;
- regs[0] |= 0x0C;
- apply();
- }
- else
- {
- // Write a bit into the temporary register:
- tmpReg = ((v & 1) << 4) | (tmpReg >> 1);
- // Finished writing all the bits:
- if (++writeN == 5)
- {
- regs[(addr >> 13) & 0b11] = tmpReg;
- writeN = 0;
- tmpReg = 0;
- apply();
- }
- }
- }
- return v;
-}
-
-u8 Mapper1::chr_write(u16 addr, u8 v)
-{
- return chr[addr] = v;
-}
diff --git a/old/mappers/mapper2.cpp b/old/mappers/mapper2.cpp
deleted file mode 100644
index 818cd80..0000000
--- a/old/mappers/mapper2.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "ppu.hpp"
-#include "mappers/mapper2.hpp"
-
-/* Based off of https://wiki.nesdev.com/w/index.php/UxROM */
-
-/* Apply the registers state */
-void Mapper2::apply()
-{
- /*
- * 16 kb PRG ROM Banks
- * 0x8000 - 0xBFFF swappable
- * 0xC000 - 0xFFFF fixed
- */
- map_prg<16>(0, regs[0] & 0xF);
- map_prg<16>(1, 0xF);
-
- /* 8k of CHR */
- map_chr<8>(0, 0);
-
- /* mirroring is based on the header (soldered) */
- set_mirroring(vertical_mirroring?PPU::VERTICAL:PPU::HORIZONTAL);
-}
-
-u8 Mapper2::write(u16 addr, u8 v)
-{
- /* check for bus contingency? (addr & 0x8000 == v?) nah */
-
- /* bank switching */
- if (addr & 0x8000)
- {
- regs[0] = v;
- apply();
- }
- return v;
-}
-
-u8 Mapper2::chr_write(u16 addr, u8 v)
-{
- return chr[addr] = v;
-}
diff --git a/old/mappers/mapper3.cpp b/old/mappers/mapper3.cpp
deleted file mode 100644
index 429a6a8..0000000
--- a/old/mappers/mapper3.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "ppu.hpp"
-#include "mappers/mapper3.hpp"
-
-/* Based off of https://wiki.nesdev.com/w/index.php/INES_Mapper_003 */
-
-/* Apply the registers state */
-void Mapper3::apply()
-{
- if (PRG_size_16k)
- {
- /*
- * mirror the bottom on the top
- * 0x8000 - 0xBFFF ==
- * 0xC000 - 0xFFFF
- */
- map_prg<16>(0,0);
- map_prg<16>(1,0);
- }
- else
- {
- /* no mirroring */
- map_prg<16>(0,0);
- map_prg<16>(1,1);
- }
-
- /* 8k bankswitched CHR */
- map_chr<8>(0, regs[0] & 0b11);
-
- /* mirroring is based on the header (soldered) */
- set_mirroring(vertical_mirroring?PPU::VERTICAL:PPU::HORIZONTAL);
-}
-
-u8 Mapper3::write(u16 addr, u8 v)
-{
- /* check for bus contingency? */
-
- /* chr bank switching */
- if (addr & 0x8000)
- {
- regs[0] = v;
- apply();
- }
- return v;
-}
-
-u8 Mapper3::chr_write(u16 addr, u8 v)
-{
- return chr[addr] = v;
-}
-
diff --git a/old/mappers/mapper4.cpp b/old/mappers/mapper4.cpp
deleted file mode 100644
index 3d40228..0000000
--- a/old/mappers/mapper4.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "cpu.hpp"
-#include "ppu.hpp"
-#include "mappers/mapper4.hpp"
-
-
-void Mapper4::apply()
-{
- map_prg<8>(1, regs[7]);
-
- // PRG Mode 0:
- if (!(reg8000 & (1 << 6)))
- {
- map_prg<8>(0, regs[6]);
- map_prg<8>(2, -2);
- }
- // PRG Mode 1:
- else
- {
- map_prg<8>(0, -2);
- map_prg<8>(2, regs[6]);
- }
-
- // CHR Mode 0:
- if (!(reg8000 & (1 << 7)))
- {
- map_chr<2>(0, regs[0] >> 1);
- map_chr<2>(1, regs[1] >> 1);
- for (int i = 0; i < 4; i++)
- map_chr<1>(4 + i, regs[2 + i]);
- }
- // CHR Mode 1:
- else
- {
- for (int i = 0; i < 4; i++)
- map_chr<1>(i, regs[2 + i]);
- map_chr<2>(2, regs[0] >> 1);
- map_chr<2>(3, regs[1] >> 1);
- }
-
- set_mirroring(horizMirroring ? PPU::HORIZONTAL : PPU::VERTICAL);
-}
-
-u8 Mapper4::write(u16 addr, u8 v)
-{
- if (addr < 0x8000)
- prgRam[addr - 0x6000] = v;
- else if (addr & 0x8000)
- {
- switch (addr & 0xE001)
- {
- case 0x8000: reg8000 = v; break;
- case 0x8001: regs[reg8000 & 0b111] = v; break;
- case 0xA000: horizMirroring = v & 1; break;
- case 0xC000: irqPeriod = v; break;
- case 0xC001: irqCounter = 0; break;
- case 0xE000: CPU::set_irq(irqEnabled = false); break;
- case 0xE001: irqEnabled = true; break;
- }
- apply();
- }
- return v;
-}
-
-u8 Mapper4::chr_write(u16 addr, u8 v)
-{
- return chr[addr] = v;
-}
-
-void Mapper4::signal_scanline()
-{
- if (irqCounter == 0)
- irqCounter = irqPeriod;
- else
- irqCounter--;
-
- if (irqEnabled and irqCounter == 0)
- CPU::set_irq();
-}
diff --git a/old/menu.cpp b/old/menu.cpp
deleted file mode 100644
index 7882ea0..0000000
--- a/old/menu.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-#include <algorithm>
-#include <dirent.h>
-#include <unistd.h>
-#include "cartridge.hpp"
-#include "menu.hpp"
-
-namespace GUI {
-
-using namespace std;
-
-
-Entry::Entry(string label, function<void()> callback) : callback(callback)
-{
- set_label(label);
-}
-
-Entry::~Entry()
-{
- SDL_DestroyTexture(whiteTexture);
- SDL_DestroyTexture(redTexture);
-}
-
-void Entry::set_label(string label)
-{
- this->label = label;
-
- if (whiteTexture != nullptr) SDL_DestroyTexture(whiteTexture);
- if (redTexture != nullptr) SDL_DestroyTexture(redTexture);
-
- whiteTexture = gen_text(label, { 255, 255, 255 });
- redTexture = gen_text(label, { 255, 0, 0 });
-}
-
-void Entry::render(int x, int y) {
- render_texture(selected ? redTexture : whiteTexture, x, y);
-}
-
-ControlEntry::ControlEntry(string action, SDL_Scancode* key) : key(key),
- Entry::Entry(
- action,
- [&]{ keyEntry->set_label(SDL_GetScancodeName(*(this->key) = query_key())); })
-{
- this->keyEntry = new Entry(SDL_GetScancodeName(*key), []{});
-}
-
-ControlEntry::ControlEntry(string action, int* button) : button(button),
- Entry::Entry(
- action,
- [&]{ keyEntry->set_label(to_string(*(this->button) = query_button())); })
-{
- this->keyEntry = new Entry(to_string(*button), []{});
-}
-
-
-void Menu::add(Entry* entry)
-{
- if (entries.empty())
- entry->select();
- entries.push_back(entry);
-}
-
-void Menu::clear()
-{
- for (auto entry : entries)
- delete entry;
- entries.clear();
- cursor = 0;
-}
-
-void Menu::sort_by_label()
-{
- if (entries.empty())
- return;
- entries[0]->unselect();
- sort(entries.begin(), entries.end(), [](Entry* a, Entry* b) {
- return a->get_label() < b->get_label();
- });
- entries[0]->select();
-}
-
-void Menu::update(u8 const* keys)
-{
- int oldCursor = cursor;
-
- if (keys[SDL_SCANCODE_DOWN] and cursor < entries.size() - 1)
- {
- cursor++;
- if (cursor == bottom) {
- bottom += 1;
- top += 1;
- }
- }
- else if (keys[SDL_SCANCODE_UP] and cursor > 0)
- {
- cursor--;
- if (cursor < top) {
- top -= 1;
- bottom -= 1;
- }
- }
- entries[oldCursor]->unselect();
- entries[cursor]->select();
-
- if (keys[SDL_SCANCODE_RETURN])
- entries[cursor]->trigger();
-}
-
-void Menu::render()
-{
- for (int i = top; i < entries.size() && i < bottom; ++i)
- {
- int y = (i - top) * FONT_SZ;
- entries[i]->render(TEXT_CENTER, y);
- }
-}
-
-void FileMenu::change_dir(string dir)
-{
- clear();
-
- struct dirent* dirp;
- DIR* dp = opendir(dir.c_str());
-
- while ((dirp = readdir(dp)) != NULL)
- {
- string name = dirp->d_name;
- string path = dir + "/" + name;
-
- if (name[0] == '.' and name != "..") continue;
-
- if (dirp->d_type == DT_DIR)
- add(new Entry(name + "/",
- [=]{ change_dir(path); }));
-
- else if (name.size() > 4 and name.substr(name.size() - 4) == ".nes")
- add(new Entry(name,
- [=]{ Cartridge::load(path.c_str()); toggle_pause(); }));
- }
- closedir(dp);
- sort_by_label();
-}
-
-FileMenu::FileMenu()
-{
- char cwd[512];
-
- change_dir(getcwd(cwd, 512));
-}
-
-
-}
diff --git a/old/palette.inc b/old/palette.inc
deleted file mode 100644
index b869d86..0000000
--- a/old/palette.inc
+++ /dev/null
@@ -1,9 +0,0 @@
-u32 nesRgb[] =
-{ 0x7C7C7C, 0x0000FC, 0x0000BC, 0x4428BC, 0x940084, 0xA80020, 0xA81000, 0x881400,
- 0x503000, 0x007800, 0x006800, 0x005800, 0x004058, 0x000000, 0x000000, 0x000000,
- 0xBCBCBC, 0x0078F8, 0x0058F8, 0x6844FC, 0xD800CC, 0xE40058, 0xF83800, 0xE45C10,
- 0xAC7C00, 0x00B800, 0x00A800, 0x00A844, 0x008888, 0x000000, 0x000000, 0x000000,
- 0xF8F8F8, 0x3CBCFC, 0x6888FC, 0x9878F8, 0xF878F8, 0xF85898, 0xF87858, 0xFCA044,
- 0xF8B800, 0xB8F818, 0x58D854, 0x58F898, 0x00E8D8, 0x787878, 0x000000, 0x000000,
- 0xFCFCFC, 0xA4E4FC, 0xB8B8F8, 0xD8B8F8, 0xF8B8F8, 0xF8A4C0, 0xF0D0B0, 0xFCE0A8,
- 0xF8D878, 0xD8F878, 0xB8F8B8, 0xB8F8D8, 0x00FCFC, 0xF8D8F8, 0x000000, 0x000000 };
diff --git a/old/ppu.cpp b/old/ppu.cpp
deleted file mode 100644
index 4ec4ec5..0000000
--- a/old/ppu.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-#include "cartridge.hpp"
-#include "cpu.hpp"
-#include "gui.hpp"
-#include "ppu.hpp"
-
-namespace PPU {
-#include "palette.inc"
-
-
-Mirroring mirroring; // Mirroring mode.
-u8 ciRam[0x800]; // VRAM for nametables.
-u8 cgRam[0x20]; // VRAM for palettes.
-u8 oamMem[0x100]; // VRAM for sprite properties.
-Sprite oam[8], secOam[8]; // Sprite buffers.
-u32 pixels[256 * 240]; // Video buffer.
-
-Addr vAddr, tAddr; // Loopy V, T.
-u8 fX; // Fine X.
-u8 oamAddr; // OAM address.
-
-Ctrl ctrl; // PPUCTRL ($2000) register.
-Mask mask; // PPUMASK ($2001) register.
-Status status; // PPUSTATUS ($2002) register.
-
-// Background latches:
-u8 nt, at, bgL, bgH;
-// Background shift registers:
-u8 atShiftL, atShiftH; u16 bgShiftL, bgShiftH;
-bool atLatchL, atLatchH;
-
-// Rendering counters:
-int scanline, dot;
-bool frameOdd;
-
-inline bool rendering() { return mask.bg || mask.spr; }
-inline int spr_height() { return ctrl.sprSz ? 16 : 8; }
-
-/* Get CIRAM address according to mirroring */
-u16 nt_mirror(u16 addr)
-{
- switch (mirroring)
- {
- case VERTICAL: return addr % 0x800;
- case HORIZONTAL: return ((addr / 2) & 0x400) + (addr % 0x400);
- default: return addr - 0x2000;
- }
-}
-void set_mirroring(Mirroring mode) { mirroring = mode; }
-
-/* Access PPU memory */
-u8 rd(u16 addr)
-{
- switch (addr)
- {
- case 0x0000 ... 0x1FFF: return Cartridge::chr_access<0>(addr); // CHR-ROM/RAM.
- case 0x2000 ... 0x3EFF: return ciRam[nt_mirror(addr)]; // Nametables.
- case 0x3F00 ... 0x3FFF: // Palettes:
- if ((addr & 0x13) == 0x10) addr &= ~0x10;
- return cgRam[addr & 0x1F] & (mask.gray ? 0x30 : 0xFF);
- default: return 0;
- }
-}
-void wr(u16 addr, u8 v)
-{
- switch (addr)
- {
- case 0x0000 ... 0x1FFF: Cartridge::chr_access<1>(addr, v); break; // CHR-ROM/RAM.
- case 0x2000 ... 0x3EFF: ciRam[nt_mirror(addr)] = v; break; // Nametables.
- case 0x3F00 ... 0x3FFF: // Palettes:
- if ((addr & 0x13) == 0x10) addr &= ~0x10;
- cgRam[addr & 0x1F] = v; break;
- }
-}
-
-/* Access PPU through registers. */
-template <bool write> u8 access(u16 index, u8 v)
-{
- static u8 res; // Result of the operation.
- static u8 buffer; // VRAM read buffer.
- static bool latch; // Detect second reading.
-
- /* Write into register */
- if (write)
- {
- res = v;
-
- switch (index)
- {
- case 0: ctrl.r = v; tAddr.nt = ctrl.nt; break; // PPUCTRL ($2000).
- case 1: mask.r = v; break; // PPUMASK ($2001).
- case 3: oamAddr = v; break; // OAMADDR ($2003).
- case 4: oamMem[oamAddr++] = v; break; // OAMDATA ($2004).
- case 5: // PPUSCROLL ($2005).
- if (!latch) { fX = v & 7; tAddr.cX = v >> 3; } // First write.
- else { tAddr.fY = v & 7; tAddr.cY = v >> 3; } // Second write.
- latch = !latch; break;
- case 6: // PPUADDR ($2006).
- if (!latch) { tAddr.h = v & 0x3F; } // First write.
- else { tAddr.l = v; vAddr.r = tAddr.r; } // Second write.
- latch = !latch; break;
- case 7: wr(vAddr.addr, v); vAddr.addr += ctrl.incr ? 32 : 1; // PPUDATA ($2007).
- }
- }
- /* Read from register */
- else
- switch (index)
- {
- // PPUSTATUS ($2002):
- case 2: res = (res & 0x1F) | status.r; status.vBlank = 0; latch = 0; break;
- case 4: res = oamMem[oamAddr]; break; // OAMDATA ($2004).
- case 7: // PPUDATA ($2007).
- if (vAddr.addr <= 0x3EFF)
- {
- res = buffer;
- buffer = rd(vAddr.addr);
- }
- else
- res = buffer = rd(vAddr.addr);
- vAddr.addr += ctrl.incr ? 32 : 1;
- }
- return res;
-}
-template u8 access<0>(u16, u8); template u8 access<1>(u16, u8);
-
-/* Calculate graphics addresses */
-inline u16 nt_addr() { return 0x2000 | (vAddr.r & 0xFFF); }
-inline u16 at_addr() { return 0x23C0 | (vAddr.nt << 10) | ((vAddr.cY / 4) << 3) | (vAddr.cX / 4); }
-inline u16 bg_addr() { return (ctrl.bgTbl * 0x1000) + (nt * 16) + vAddr.fY; }
-/* Increment the scroll by one pixel */
-inline void h_scroll() { if (!rendering()) return; if (vAddr.cX == 31) vAddr.r ^= 0x41F; else vAddr.cX++; }
-inline void v_scroll()
-{
- if (!rendering()) return;
- if (vAddr.fY < 7) vAddr.fY++;
- else
- {
- vAddr.fY = 0;
- if (vAddr.cY == 31) vAddr.cY = 0;
- else if (vAddr.cY == 29) { vAddr.cY = 0; vAddr.nt ^= 0b10; }
- else vAddr.cY++;
- }
-}
-/* Copy scrolling data from loopy T to loopy V */
-inline void h_update() { if (!rendering()) return; vAddr.r = (vAddr.r & ~0x041F) | (tAddr.r & 0x041F); }
-inline void v_update() { if (!rendering()) return; vAddr.r = (vAddr.r & ~0x7BE0) | (tAddr.r & 0x7BE0); }
-/* Put new data into the shift registers */
-inline void reload_shift()
-{
- bgShiftL = (bgShiftL & 0xFF00) | bgL;
- bgShiftH = (bgShiftH & 0xFF00) | bgH;
-
- atLatchL = (at & 1);
- atLatchH = (at & 2);
-}
-
-/* Clear secondary OAM */
-void clear_oam()
-{
- for (int i = 0; i < 8; i++)
- {
- secOam[i].id = 64;
- secOam[i].y = 0xFF;
- secOam[i].tile = 0xFF;
- secOam[i].attr = 0xFF;
- secOam[i].x = 0xFF;
- secOam[i].dataL = 0;
- secOam[i].dataH = 0;
- }
-}
-
-/* Fill secondary OAM with the sprite infos for the next scanline */
-void eval_sprites()
-{
- int n = 0;
- for (int i = 0; i < 64; i++)
- {
- int line = (scanline == 261 ? -1 : scanline) - oamMem[i*4 + 0];
- // If the sprite is in the scanline, copy its properties into secondary OAM:
- if (line >= 0 and line < spr_height())
- {
- secOam[n].id = i;
- secOam[n].y = oamMem[i*4 + 0];
- secOam[n].tile = oamMem[i*4 + 1];
- secOam[n].attr = oamMem[i*4 + 2];
- secOam[n].x = oamMem[i*4 + 3];
-
- if (++n >= 8)
- {
- status.sprOvf = true;
- break;
- }
- }
- }
-}
-
-/* Load the sprite info into primary OAM and fetch their tile data. */
-void load_sprites()
-{
- u16 addr;
- for (int i = 0; i < 8; i++)
- {
- oam[i] = secOam[i]; // Copy secondary OAM into primary.
-
- // Different address modes depending on the sprite height:
- if (spr_height() == 16)
- addr = ((oam[i].tile & 1) * 0x1000) + ((oam[i].tile & ~1) * 16);
- else
- addr = ( ctrl.sprTbl * 0x1000) + ( oam[i].tile * 16);
-
- unsigned sprY = (scanline - oam[i].y) % spr_height(); // Line inside the sprite.
- if (oam[i].attr & 0x80) sprY ^= spr_height() - 1; // Vertical flip.
- addr += sprY + (sprY & 8); // Select the second tile if on 8x16.
-
- oam[i].dataL = rd(addr + 0);
- oam[i].dataH = rd(addr + 8);
- }
-}
-
-/* Process a pixel, draw it if it's on screen */
-void pixel()
-{
- u8 palette = 0, objPalette = 0;
- bool objPriority = 0;
- int x = dot - 2;
-
- if (scanline < 240 and x >= 0 and x < 256)
- {
- if (mask.bg and not (!mask.bgLeft && x < 8))
- {
- // Background:
- palette = (NTH_BIT(bgShiftH, 15 - fX) << 1) |
- NTH_BIT(bgShiftL, 15 - fX);
- if (palette)
- palette |= ((NTH_BIT(atShiftH, 7 - fX) << 1) |
- NTH_BIT(atShiftL, 7 - fX)) << 2;
- }
- // Sprites:
- if (mask.spr and not (!mask.sprLeft && x < 8))
- for (int i = 7; i >= 0; i--)
- {
- if (oam[i].id == 64) continue; // Void entry.
- unsigned sprX = x - oam[i].x;
- if (sprX >= 8) continue; // Not in range.
- if (oam[i].attr & 0x40) sprX ^= 7; // Horizontal flip.
-
- u8 sprPalette = (NTH_BIT(oam[i].dataH, 7 - sprX) << 1) |
- NTH_BIT(oam[i].dataL, 7 - sprX);
- if (sprPalette == 0) continue; // Transparent pixel.
-
- if (oam[i].id == 0 && palette && x != 255) status.sprHit = true;
- sprPalette |= (oam[i].attr & 3) << 2;
- objPalette = sprPalette + 16;
- objPriority = oam[i].attr & 0x20;
- }
- // Evaluate priority:
- if (objPalette && (palette == 0 || objPriority == 0)) palette = objPalette;
-
- pixels[scanline*256 + x] = nesRgb[rd(0x3F00 + (rendering() ? palette : 0))];
- }
- // Perform background shifts:
- bgShiftL <<= 1; bgShiftH <<= 1;
- atShiftL = (atShiftL << 1) | atLatchL;
- atShiftH = (atShiftH << 1) | atLatchH;
-}
-
-/* Execute a cycle of a scanline */
-template<Scanline s> void scanline_cycle()
-{
- static u16 addr;
-
- if (s == NMI and dot == 1) { status.vBlank = true; if (ctrl.nmi) CPU::set_nmi(); }
- else if (s == POST and dot == 0) GUI::new_frame(pixels);
- else if (s == VISIBLE or s == PRE)
- {
- // Sprites:
- switch (dot)
- {
- case 1: clear_oam(); if (s == PRE) { status.sprOvf = status.sprHit = false; } break;
- case 257: eval_sprites(); break;
- case 321: load_sprites(); break;
- }
- // Background:
- switch (dot)
- {
- case 2 ... 255: case 322 ... 337:
- pixel();
- switch (dot % 8)
- {
- // Nametable:
- case 1: addr = nt_addr(); reload_shift(); break;
- case 2: nt = rd(addr); break;
- // Attribute:
- case 3: addr = at_addr(); break;
- case 4: at = rd(addr); if (vAddr.cY & 2) at >>= 4;
- if (vAddr.cX & 2) at >>= 2; break;
- // Background (low bits):
- case 5: addr = bg_addr(); break;
- case 6: bgL = rd(addr); break;
- // Background (high bits):
- case 7: addr += 8; break;
- case 0: bgH = rd(addr); h_scroll(); break;
- } break;
- case 256: pixel(); bgH = rd(addr); v_scroll(); break; // Vertical bump.
- case 257: pixel(); reload_shift(); h_update(); break; // Update horizontal position.
- case 280 ... 304: if (s == PRE) v_update(); break; // Update vertical position.
-
- // No shift reloading:
- case 1: addr = nt_addr(); if (s == PRE) status.vBlank = false; break;
- case 321: case 339: addr = nt_addr(); break;
- // Nametable fetch instead of attribute:
- case 338: nt = rd(addr); break;
- case 340: nt = rd(addr); if (s == PRE && rendering() && frameOdd) dot++;
- }
- // Signal scanline to mapper:
- if (dot == 260 && rendering()) Cartridge::signal_scanline();
- }
-}
-
-/* Execute a PPU cycle. */
-void step()
-{
- switch (scanline)
- {
- case 0 ... 239: scanline_cycle<VISIBLE>(); break;
- case 240: scanline_cycle<POST>(); break;
- case 241: scanline_cycle<NMI>(); break;
- case 261: scanline_cycle<PRE>(); break;
- }
- // Update dot and scanline counters:
- if (++dot > 340)
- {
- dot %= 341;
- if (++scanline > 261)
- {
- scanline = 0;
- frameOdd ^= 1;
- }
- }
-}
-
-void reset()
-{
- frameOdd = false;
- scanline = dot = 0;
- ctrl.r = mask.r = status.r = 0;
-
- memset(pixels, 0x00, sizeof(pixels));
- memset(ciRam, 0xFF, sizeof(ciRam));
- memset(oamMem, 0x00, sizeof(oamMem));
-}
-
-
-}
diff --git a/res/font.ttf b/res/font.ttf
deleted file mode 100644
index 9acccd4..0000000
--- a/res/font.ttf
+++ /dev/null
Binary files differ
diff --git a/res/init.png b/res/init.png
deleted file mode 100644
index e5a9785..0000000
--- a/res/init.png
+++ /dev/null
Binary files differ
diff --git a/src/palette.inc b/src/palette.inc
deleted file mode 100644
index b869d86..0000000
--- a/src/palette.inc
+++ /dev/null
@@ -1,9 +0,0 @@
-u32 nesRgb[] =
-{ 0x7C7C7C, 0x0000FC, 0x0000BC, 0x4428BC, 0x940084, 0xA80020, 0xA81000, 0x881400,
- 0x503000, 0x007800, 0x006800, 0x005800, 0x004058, 0x000000, 0x000000, 0x000000,
- 0xBCBCBC, 0x0078F8, 0x0058F8, 0x6844FC, 0xD800CC, 0xE40058, 0xF83800, 0xE45C10,
- 0xAC7C00, 0x00B800, 0x00A800, 0x00A844, 0x008888, 0x000000, 0x000000, 0x000000,
- 0xF8F8F8, 0x3CBCFC, 0x6888FC, 0x9878F8, 0xF878F8, 0xF85898, 0xF87858, 0xFCA044,
- 0xF8B800, 0xB8F818, 0x58D854, 0x58F898, 0x00E8D8, 0x787878, 0x000000, 0x000000,
- 0xFCFCFC, 0xA4E4FC, 0xB8B8F8, 0xD8B8F8, 0xF8B8F8, 0xF8A4C0, 0xF0D0B0, 0xFCE0A8,
- 0xF8D878, 0xD8F878, 0xB8F8B8, 0xB8F8D8, 0x00FCFC, 0xF8D8F8, 0x000000, 0x000000 };