[GSF] Massive code cleanup.
(As an aside, blargg's code style makes me go blarg myself.)
--- a/src/in_gsf/XSFPlayer_GSF.cpp
+++ b/src/in_gsf/XSFPlayer_GSF.cpp
@@ -207,14 +207,14 @@
cpuIsMultiBoot = (loaderwork.entry >> 24) == 2;
- CPULoadRom(nullptr);
+ CPULoadRom();
soundSetSampleRate(this->sampleRate);
soundInit();
soundReset();
- soundSetEnable(0x3FF);
-
- CPUInit(nullptr, false);
+ soundSetEnable(0x30F);
+
+ CPUInit();
CPUReset();
return XSFPlayer::Load();
@@ -245,7 +245,6 @@
void XSFPlayer_GSF::Terminate()
{
- CPUCleanUp();
soundShutdown();
loaderwork.rom.clear();
--- a/src/in_gsf/vbam/apu/Blip_Buffer.cpp
+++ b/src/in_gsf/vbam/apu/Blip_Buffer.cpp
@@ -2,11 +2,11 @@
#include "Blip_Buffer.h"
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
+#include <numeric>
+#include <cassert>
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
/* Copyright (C) 2003-2007 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
@@ -21,167 +21,139 @@
// TODO: use scoped for variables in treble_eq()
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
+Blip_Buffer::Blip_Buffer()
+{
+ this->factor_ = LONG_MAX;
+ this->buffer_.clear();
+ this->buffer_size_ = 0;
+ this->sample_rate_ = 0;
+ this->bass_shift_ = 0;
+ this->clock_rate_ = 0;
+ this->bass_freq_ = 16;
+ this->length_ = 0;
+
+ // assumptions code makes about implementation-defined features
+#ifndef NDEBUG
+ // right shift of negative value preserves sign
+ buf_t_ i = -0x7FFFFFFE;
+ assert((i >> 1) == -0x3FFFFFFF);
+
+ // casting to short truncates to 16 bits and sign-extends
+ i = 0x18000;
+ assert(static_cast<short>(i) == -0x8000);
#endif
-int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
-
-Blip_Buffer::Blip_Buffer()
-{
- factor_ = LONG_MAX;
- buffer_ = 0;
- buffer_size_ = 0;
- sample_rate_ = 0;
- bass_shift_ = 0;
- clock_rate_ = 0;
- bass_freq_ = 16;
- length_ = 0;
-
- // assumptions code makes about implementation-defined features
- #ifndef NDEBUG
- // right shift of negative value preserves sign
- buf_t_ i = -0x7FFFFFFE;
- assert( (i >> 1) == -0x3FFFFFFF );
-
- // casting to short truncates to 16 bits and sign-extends
- i = 0x18000;
- assert( (short) i == -0x8000 );
- #endif
-
- clear();
+ this->clear();
}
Blip_Buffer::~Blip_Buffer()
{
- if ( buffer_size_ != silent_buf_size )
- free( buffer_ );
-}
-
-Silent_Blip_Buffer::Silent_Blip_Buffer()
-{
- factor_ = 0;
- buffer_ = buf;
- buffer_size_ = silent_buf_size;
- clear();
-}
-
-void Blip_Buffer::clear( int entire_buffer )
-{
- offset_ = 0;
- reader_accum_ = 0;
- modified_ = 0;
- if ( buffer_ )
- {
- long count = (entire_buffer ? buffer_size_ : samples_avail());
- memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
- }
-}
-
-Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return "Internal (tried to resize Silent_Blip_Buffer)";
- }
-
+}
+
+void Blip_Buffer::clear(int entire_buffer)
+{
+ this->offset_ = 0;
+ this->reader_accum_ = 0;
+ this->modified_ = nullptr;
+ if (!this->buffer_.empty())
+ {
+ long count = entire_buffer ? this->buffer_size_ : this->samples_avail();
+ memset(&this->buffer_[0], 0, (count + blip_buffer_extra_) * sizeof(buf_t_));
+ }
+}
+
+Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate(long new_rate, int msec)
+{
// start with maximum length that resampled time can represent
long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
- if ( msec != blip_max_length )
+ if (msec != blip_max_length)
{
long s = (new_rate * (msec + 1) + 999) / 1000;
- if ( s < new_size )
+ if (s < new_size)
new_size = s;
else
- assert( 0 ); // fails if requested buffer length exceeds limit
- }
-
- if ( buffer_size_ != new_size )
- {
- void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
- if ( !p )
- return "Out of memory";
- buffer_ = (buf_t_*) p;
- }
-
- buffer_size_ = new_size;
- assert( buffer_size_ != silent_buf_size ); // size should never happen to match this
+ assert(0); // fails if requested buffer length exceeds limit
+ }
+
+ if (this->buffer_size_ != new_size)
+ this->buffer_.resize(new_size + blip_buffer_extra_);
+
+ this->buffer_size_ = new_size;
// update things based on the sample rate
- sample_rate_ = new_rate;
- length_ = new_size * 1000 / new_rate - 1;
- if ( msec )
- assert( length_ == msec ); // ensure length is same as that passed in
+ this->sample_rate_ = new_rate;
+ this->length_ = new_size * 1000 / new_rate - 1;
+ if (msec)
+ assert(this->length_ == msec); // ensure length is same as that passed in
// update these since they depend on sample rate
- if ( clock_rate_ )
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
-
- clear();
+ if (this->clock_rate_)
+ this->clock_rate(this->clock_rate_);
+ this->bass_freq(this->bass_freq_);
+
+ this->clear();
return 0; // success
}
-blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
-{
- double ratio = (double) sample_rate_ / rate;
- blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
- assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
- return (blip_resampled_time_t) factor;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
+blip_resampled_time_t Blip_Buffer::clock_rate_factor(long rate) const
+{
+ double ratio = static_cast<double>(this->sample_rate_) / rate;
+ int32_t factor = static_cast<int32_t>(std::floor(ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5));
+ assert(factor > 0 || !this->sample_rate_); // fails if clock/output ratio is too large
+ return static_cast<blip_resampled_time_t>(factor);
+}
+
+void Blip_Buffer::bass_freq(int freq)
+{
+ this->bass_freq_ = freq;
int shift = 31;
- if ( freq > 0 )
+ if (freq > 0)
{
shift = 13;
- long f = (freq << 16) / sample_rate_;
- while ( (f >>= 1) && --shift ) { }
- }
- bass_shift_ = shift;
-}
-
-void Blip_Buffer::end_frame( blip_time_t t )
-{
- offset_ += t * factor_;
- assert( samples_avail() <= (long) buffer_size_ ); // fails if time is past end of buffer
-}
-
-long Blip_Buffer::count_samples( blip_time_t t ) const
-{
- blip_resampled_time_t last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
- blip_resampled_time_t first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
- return long (last_sample - first_sample);
-}
-
-blip_time_t Blip_Buffer::count_clocks( long count ) const
-{
- if ( !factor_ )
- {
- assert( 0 ); // sample rate and clock rates must be set first
+ long f = (freq << 16) / this->sample_rate_;
+ while ((f >>= 1) && --shift);
+ }
+ this->bass_shift_ = shift;
+}
+
+void Blip_Buffer::end_frame(blip_time_t t)
+{
+ this->offset_ += t * this->factor_;
+ assert(this->samples_avail() <= static_cast<long>(this->buffer_size_)); // fails if time is past end of buffer
+}
+
+long Blip_Buffer::count_samples(blip_time_t t) const
+{
+ auto last_sample = this->resampled_time(t) >> BLIP_BUFFER_ACCURACY;
+ auto first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY;
+ return static_cast<long>(last_sample - first_sample);
+}
+
+blip_time_t Blip_Buffer::count_clocks(long count) const
+{
+ if (!this->factor_)
+ {
+ assert(0); // sample rate and clock rates must be set first
return 0;
}
- if ( count > buffer_size_ )
- count = buffer_size_;
- blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
- return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
-}
-
-void Blip_Buffer::remove_samples( long count )
-{
- if ( count )
- {
- remove_silence( count );
+ if (count > this->buffer_size_)
+ count = this->buffer_size_;
+ auto time = static_cast<blip_resampled_time_t>(count) << BLIP_BUFFER_ACCURACY;
+ return static_cast<blip_time_t>((time - this->offset_ + this->factor_ - 1) / this->factor_);
+}
+
+void Blip_Buffer::remove_samples(long count)
+{
+ if (count)
+ {
+ this->remove_silence(count);
// copy remaining samples to beginning and clear old samples
- long remain = samples_avail() + blip_buffer_extra_;
- memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
- memset( buffer_ + remain, 0, count * sizeof *buffer_ );
+ long remain = this->samples_avail() + blip_buffer_extra_;
+ memmove(&this->buffer_[0], &this->buffer_[count], remain * sizeof(this->buffer_[0]));
+ memset(&this->buffer_[0] + remain, 0, count * sizeof(this->buffer_[0]));
}
}
@@ -189,255 +161,226 @@
Blip_Synth_Fast_::Blip_Synth_Fast_()
{
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-void Blip_Synth_Fast_::volume_unit( double new_unit )
-{
- delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
+ this->buf = nullptr;
+ this->last_amp = 0;
+ this->delta_factor = 0;
+}
+
+void Blip_Synth_Fast_::volume_unit(double new_unit)
+{
+ this->delta_factor = static_cast<int>(new_unit * (1L << blip_sample_bits) + 0.5);
}
#if !BLIP_BUFFER_FAST
-Blip_Synth_::Blip_Synth_( short* p, int w ) :
- impulses( p ),
- width( w )
-{
- volume_unit_ = 0.0;
- kernel_unit = 0;
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
-{
- if ( cutoff >= 0.999 )
+Blip_Synth_::Blip_Synth_(short *p, int w) : impulses(p), width(w)
+{
+ this->volume_unit_ = 0.0;
+ this->kernel_unit = 0;
+ this->buf = nullptr;
+ this->last_amp = 0;
+ this->delta_factor = 0;
+}
+
+#undef M_PI
+static const double M_PI = 3.1415926535897932384626433832795029;
+
+static void gen_sinc(float *out, int count, double oversample, double treble, double cutoff)
+{
+ if (cutoff >= 0.999)
cutoff = 0.999;
- if ( treble < -300.0 )
+ if (treble < -300.0)
treble = -300.0;
- if ( treble > 5.0 )
+ if (treble > 5.0)
treble = 5.0;
double const maxh = 4096.0;
- double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
- double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
- double const to_angle = PI / 2 / maxh / oversample;
- for ( int i = 0; i < count; i++ )
+ double const rolloff = std::pow(10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff));
+ double const pow_a_n = std::pow(rolloff, maxh - maxh * cutoff);
+ double const to_angle = M_PI / 2 / maxh / oversample;
+ for (int i = 0; i < count; ++i)
{
double angle = ((i - count) * 2 + 1) * to_angle;
- double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
- double cos_nc_angle = cos( maxh * cutoff * angle );
- double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
- double cos_angle = cos( angle );
+ double c = rolloff * std::cos((maxh - 1.0) * angle) - std::cos(maxh * angle);
+ double cos_nc_angle = std::cos(maxh * cutoff * angle);
+ double cos_nc1_angle = std::cos((maxh * cutoff - 1.0) * angle);
+ double cos_angle = std::cos(angle);
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
double b = 2.0 - cos_angle - cos_angle;
double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
- out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
- }
-}
-
-void blip_eq_t::generate( float* out, int count ) const
+ out[i] = static_cast<float>((a * d + c * b) / (b * d)); // a / b + c / d
+ }
+}
+
+void blip_eq_t::generate(float *out, int count) const
{
// lower cutoff freq for narrow kernels with their wider transition band
// (8 points->1.49, 16 points->1.15)
double oversample = blip_res * 2.25 / count + 0.85;
- double half_rate = sample_rate * 0.5;
- if ( cutoff_freq )
- oversample = half_rate / cutoff_freq;
- double cutoff = rolloff_freq * oversample / half_rate;
-
- gen_sinc( out, count, blip_res * oversample, treble, cutoff );
-
- // apply (half of) hamming window
- double to_fraction = PI / (count - 1);
- for ( int i = count; i--; )
- out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
+ double half_rate = this->sample_rate * 0.5;
+ if (this->cutoff_freq)
+ oversample = half_rate / this->cutoff_freq;
+ double cutoff = this->rolloff_freq * oversample / half_rate;
+
+ gen_sinc(out, count, blip_res * oversample, this->treble, cutoff);
+
+ // apply (half of) hann window
+ double to_fraction = M_PI / (count - 1);
+ for (int i = count; i--; )
+ out[i] *= 0.5f * (1.0f - static_cast<float>(std::cos(i * to_fraction)));
}
void Blip_Synth_::adjust_impulse()
{
// sum pairs for each phase and add error correction to end of first half
- int const size = impulses_size();
- for ( int p = blip_res; p-- >= blip_res / 2; )
+ int size = this->impulses_size();
+ for (int p = blip_res; p-- >= blip_res / 2; )
{
int p2 = blip_res - 2 - p;
- long error = kernel_unit;
- for ( int i = 1; i < size; i += blip_res )
- {
- error -= impulses [i + p ];
- error -= impulses [i + p2];
- }
- if ( p == p2 )
+ long error = this->kernel_unit;
+ for (int i = 1; i < size; i += blip_res)
+ error -= this->impulses[i + p] + this->impulses[i + p2];
+ if (p == p2)
error /= 2; // phase = 0.5 impulse uses same half for both sides
- impulses [size - blip_res + p] += (short) error;
- //printf( "error: %ld\n", error );
- }
-
- //for ( int i = blip_res; i--; printf( "\n" ) )
- // for ( int j = 0; j < width / 2; j++ )
- // printf( "%5ld,", impulses [j * blip_res + i + 1] );
-}
-
-void Blip_Synth_::treble_eq( blip_eq_t const& eq )
-{
- float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
-
- int const half_size = blip_res / 2 * (width - 1);
- eq.generate( &fimpulse [blip_res], half_size );
+ this->impulses[size - blip_res + p] += static_cast<short>(error);
+ //printf("error: %ld\n", error);
+ }
+
+ //for (int i = blip_res; i--; printf("\n"))
+ //for (int j = 0; j < width / 2; ++j)
+ //printf("%5ld,", this->impulses[j * blip_res + i + 1]);
+}
+
+void Blip_Synth_::treble_eq(const blip_eq_t &eq)
+{
+ float fimpulse[blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
+
+ static const int half_size = blip_res / 2 * (this->width - 1);
+ eq.generate(&fimpulse[blip_res], half_size);
int i;
// need mirror slightly past center for calculation
- for ( i = blip_res; i--; )
- fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
+ for (i = blip_res; i--; )
+ fimpulse[blip_res + half_size + i] = fimpulse[blip_res + half_size - 1 - i];
// starts at 0
- for ( i = 0; i < blip_res; i++ )
- fimpulse [i] = 0.0f;
+ std::fill(&fimpulse[0], &fimpulse[blip_res], 0.0f);
// find rescale factor
- double total = 0.0;
- for ( i = 0; i < half_size; i++ )
- total += fimpulse [blip_res + i];
-
- //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
- //double const base_unit = 37888.0; // allows treble to +5 dB
- double const base_unit = 32768.0; // necessary for blip_unscaled to work
+ double total = std::accumulate(&fimpulse[blip_res], &fimpulse[blip_res + half_size], 0.0);
+
+ //static const double base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
+ //static const double base_unit = 37888.0; // allows treble to +5 dB
+ static const double base_unit = 32768.0; // necessary for blip_unscaled to work
double rescale = base_unit / 2 / total;
- kernel_unit = (long) base_unit;
+ this->kernel_unit = static_cast<long>(base_unit);
// integrate, first difference, rescale, convert to int
double sum = 0.0;
double next = 0.0;
- int const size = this->impulses_size();
- for ( i = 0; i < size; i++ )
- {
- impulses [i] = (short) (int) floor( (next - sum) * rescale + 0.5 );
- sum += fimpulse [i];
- next += fimpulse [i + blip_res];
- }
- adjust_impulse();
+ int size = this->impulses_size();
+ for (i = 0; i < size; ++i)
+ {
+ this->impulses[i] = static_cast<short>(std::floor((next - sum) * rescale + 0.5));
+ sum += fimpulse[i];
+ next += fimpulse[i + blip_res];
+ }
+ this->adjust_impulse();
// volume might require rescaling
- double vol = volume_unit_;
- if ( vol )
- {
- volume_unit_ = 0.0;
- volume_unit( vol );
- }
-}
-
-void Blip_Synth_::volume_unit( double new_unit )
-{
- if ( new_unit != volume_unit_ )
+ double vol = this->volume_unit_;
+ if (vol)
+ {
+ this->volume_unit_ = 0.0;
+ this->volume_unit(vol);
+ }
+}
+
+void Blip_Synth_::volume_unit(double new_unit)
+{
+ if (new_unit != this->volume_unit_)
{
// use default eq if it hasn't been set yet
- if ( !kernel_unit )
- treble_eq( -8.0 );
-
- volume_unit_ = new_unit;
- double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
-
- if ( factor > 0.0 )
+ if (!this->kernel_unit)
+ this->treble_eq(-8.0);
+
+ this->volume_unit_ = new_unit;
+ double factor = new_unit * (1L << blip_sample_bits) / this->kernel_unit;
+
+ if (factor > 0.0)
{
int shift = 0;
// if unit is really small, might need to attenuate kernel
- while ( factor < 2.0 )
+ while (factor < 2.0)
{
- shift++;
+ ++shift;
factor *= 2.0;
}
- if ( shift )
+ if (shift)
{
- kernel_unit >>= shift;
- assert( kernel_unit > 0 ); // fails if volume unit is too low
+ this->kernel_unit >>= shift;
+ assert(this->kernel_unit > 0); // fails if volume unit is too low
// keep values positive to avoid round-towards-zero of sign-preserving
// right shift for negative values
long offset = 0x8000 + (1 << (shift - 1));
long offset2 = 0x8000 >> shift;
- for ( int i = impulses_size(); i--; )
- impulses [i] = (short) (int) (((impulses [i] + offset) >> shift) - offset2);
- adjust_impulse();
+ for (int i = this->impulses_size(); i--; )
+ this->impulses[i] = static_cast<short>(((this->impulses[i] + offset) >> shift) - offset2);
+ this->adjust_impulse();
}
}
- delta_factor = (int) floor( factor + 0.5 );
- //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
+ this->delta_factor = static_cast<int>(std::floor(factor + 0.5));
+ //printf("delta_factor: %d, kernel_unit: %d\n", this->delta_factor, this->kernel_unit);
}
}
#endif
-long Blip_Buffer::read_samples( blip_sample_t* out_, long max_samples, int stereo )
-{
- long count = samples_avail();
- if ( count > max_samples )
+long Blip_Buffer::read_samples(blip_sample_t *out_, long max_samples, bool stereo)
+{
+ long count = this->samples_avail();
+ if (count > max_samples)
count = max_samples;
- if ( count )
- {
- int const bass = BLIP_READER_BASS( *this );
- BLIP_READER_BEGIN( reader, *this );
- BLIP_READER_ADJ_( reader, count );
- blip_sample_t* BLIP_RESTRICT out = out_ + count;
- blip_long offset = (blip_long) -count;
-
- if ( !stereo )
+ if (count)
+ {
+ int bass = BLIP_READER_BASS(*this);
+ BLIP_READER_BEGIN(reader, *this);
+ BLIP_READER_ADJ_(reader, count);
+ auto out = out_ + count;
+ int32_t offset = static_cast<int32_t>(-count);
+
+ do
{
- do
- {
- blip_long s = BLIP_READER_READ( reader );
- BLIP_READER_NEXT_IDX_( reader, bass, offset );
- BLIP_CLAMP( s, s );
- out [offset] = (blip_sample_t) s;
- }
- while ( ++offset );
- }
- else
- {
- do
- {
- blip_long s = BLIP_READER_READ( reader );
- BLIP_READER_NEXT_IDX_( reader, bass, offset );
- BLIP_CLAMP( s, s );
- out [offset * 2] = (blip_sample_t) s;
- }
- while ( ++offset );
- }
-
- BLIP_READER_END( reader, *this );
-
- remove_samples( count );
+ int32_t s = BLIP_READER_READ(reader);
+ BLIP_READER_NEXT_IDX_(reader, bass, offset);
+ BLIP_CLAMP(s, s);
+ out[offset * (stereo ? 2 : 1)] = static_cast<blip_sample_t>(s);
+ } while (++offset);
+
+ BLIP_READER_END(reader, *this);
+
+ this->remove_samples(count);
}
return count;
}
-void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return;
- }
-
- buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
-
- int const sample_shift = blip_sample_bits - 16;
+void Blip_Buffer::mix_samples(const blip_sample_t *in, long count)
+{
+ auto out = &this->buffer_[(this->offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2];
+
+ int sample_shift = blip_sample_bits - 16;
int prev = 0;
- while ( count-- )
- {
- blip_long s = (blip_long) *in++ << sample_shift;
+ while (count--)
+ {
+ int32_t s = static_cast<int32_t>(*in++) << sample_shift;
*out += s - prev;
prev = s;
++out;
@@ -445,22 +388,3 @@
*out -= prev;
}
-blip_ulong const subsample_mask = (1L << BLIP_BUFFER_ACCURACY) - 1;
-
-void Blip_Buffer::save_state( blip_buffer_state_t* out )
-{
- assert( samples_avail() == 0 );
- out->offset_ = offset_;
- out->reader_accum_ = reader_accum_;
- memcpy( out->buf, &buffer_ [offset_ >> BLIP_BUFFER_ACCURACY], sizeof out->buf );
-}
-
-void Blip_Buffer::load_state( blip_buffer_state_t const& in )
-{
- clear( false );
-
- offset_ = in.offset_;
- reader_accum_ = in.reader_accum_;
- memcpy( buffer_, in.buf, sizeof in.buf );
-}
-
--- a/src/in_gsf/vbam/apu/Blip_Buffer.h
+++ b/src/in_gsf/vbam/apu/Blip_Buffer.h
@@ -4,62 +4,54 @@
#ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H
- // internal
- #include <limits.h>
- #if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
- typedef long blip_long;
- typedef unsigned long blip_ulong;
- #else
- typedef int blip_long;
- typedef unsigned blip_ulong;
- #endif
+#include <vector>
+#include <cstdint>
// Time unit at source clock rate
-typedef blip_long blip_time_t;
+typedef int32_t blip_time_t;
// Output samples are 16-bit signed, with a range of -32768 to 32767
typedef short blip_sample_t;
enum { blip_sample_max = 32767 };
-struct blip_buffer_state_t;
-
-class Blip_Buffer {
-public:
- typedef const char* blargg_err_t;
+class Blip_Buffer
+{
+public:
+ typedef const char *blargg_err_t;
// Sets output sample rate and buffer length in milliseconds (1/1000 sec, defaults
// to 1/4 second) and clears buffer. If there isn't enough memory, leaves buffer
// untouched and returns "Out of memory", otherwise returns NULL.
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
+ blargg_err_t set_sample_rate(long samples_per_sec, int msec_length = 1000 / 4);
// Sets number of source time units per second
- void clock_rate( long clocks_per_sec );
+ void clock_rate(long clocks_per_sec);
// Ends current time frame of specified duration and makes its samples available
// (along with any still-unread samples) for reading with read_samples(). Begins
// a new time frame at the end of the current frame.
- void end_frame( blip_time_t time );
+ virtual void end_frame(blip_time_t time);
// Reads at most 'max_samples' out of buffer into 'dest', removing them from
// the buffer. Returns number of samples actually read and removed. If stereo is
// true, increments 'dest' one extra time after writing each sample, to allow
// easy interleving of two channels into a stereo output buffer.
- long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
-
-// Additional features
+ long read_samples(blip_sample_t *dest, long max_samples, bool stereo = false);
+
+ // Additional features
// Removes all available samples and clear buffer to silence. If 'entire_buffer' is
// false, just clears out any samples waiting rather than the entire buffer.
- void clear( int entire_buffer = 1 );
+ void clear(int entire_buffer = 1);
// Number of samples available for reading with read_samples()
long samples_avail() const;
// Removes 'count' samples from those waiting to be read
- void remove_samples( long count );
+ virtual void remove_samples(long count);
// Sets frequency high-pass filter frequency, where higher values reduce bass more
- void bass_freq( int frequency );
+ void bass_freq(int frequency);
// Current output sample rate
long sample_rate() const;
@@ -70,16 +62,7 @@
// Number of source time units per second
long clock_rate() const;
-// Experimental features
-
- // Saves state, including high-pass filter and tails of last deltas.
- // All samples must have been read from buffer before calling this.
- void save_state( blip_buffer_state_t* out );
-
- // Loads state. State must have been saved from Blip_Buffer with same
- // settings during same run of program. States can NOT be stored on disk.
- // Clears buffer before loading state.
- void load_state( blip_buffer_state_t const& in );
+ // Experimental features
// Number of samples delay from synthesis to samples read out
int output_latency() const;
@@ -87,113 +70,105 @@
// Counts number of clocks needed until 'count' samples will be available.
// If buffer can't even hold 'count' samples, returns number of clocks until
// buffer becomes full.
- blip_time_t count_clocks( long count ) const;
+ blip_time_t count_clocks(long count) const;
// Number of raw samples that can be mixed within frame of specified duration.
- long count_samples( blip_time_t duration ) const;
+ long count_samples(blip_time_t duration) const;
// Mixes in 'count' samples from 'buf_in'
- void mix_samples( blip_sample_t const* buf_in, long count );
-
+ void mix_samples(const blip_sample_t *buf_in, long count);
// Signals that sound has been added to buffer. Could be done automatically in
// Blip_Synth, but that would affect performance more, as you can arrange that
// this is called only once per time frame rather than for every delta.
- void set_modified() { modified_ = this; }
+ void set_modified() { this->modified_ = this; }
// not documented yet
- blip_ulong unsettled() const;
- Blip_Buffer* clear_modified() { Blip_Buffer* b = modified_; modified_ = 0; return b; }
- void remove_silence( long count );
- typedef blip_ulong blip_resampled_time_t;
- blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
- blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
- blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
-public:
+ uint32_t unsettled() const;
+ Blip_Buffer *clear_modified() { auto b = this->modified_; this->modified_ = nullptr; return b; }
+ virtual void remove_silence(long count);
+ typedef uint32_t blip_resampled_time_t;
+ blip_resampled_time_t resampled_duration(int t) const { return t * this->factor_; }
+ blip_resampled_time_t resampled_time(blip_time_t t) const { return t * this->factor_ + this->offset_; }
+ blip_resampled_time_t clock_rate_factor(long clock_rate) const;
Blip_Buffer();
- ~Blip_Buffer();
+ virtual ~Blip_Buffer();
// Deprecated
typedef blip_resampled_time_t resampled_time_t;
- blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
- blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
+ blargg_err_t sample_rate(long r) { return this->set_sample_rate(r); }
+ blargg_err_t sample_rate(long r, int msec) { return this->set_sample_rate(r, msec); }
private:
// noncopyable
- Blip_Buffer( const Blip_Buffer& );
- Blip_Buffer& operator = ( const Blip_Buffer& );
-public:
- typedef blip_long buf_t_;
- blip_ulong factor_;
+ Blip_Buffer(const Blip_Buffer &);
+ Blip_Buffer &operator=(const Blip_Buffer &);
+public:
+ typedef int32_t buf_t_;
+ uint32_t factor_;
blip_resampled_time_t offset_;
- buf_t_* buffer_;
- blip_long buffer_size_;
- blip_long reader_accum_;
+ std::vector<buf_t_> buffer_;
+ int32_t buffer_size_;
+ int32_t reader_accum_;
int bass_shift_;
private:
long sample_rate_;
long clock_rate_;
int bass_freq_;
int length_;
- Blip_Buffer* modified_; // non-zero = true (more optimal than using bool, heh)
+ Blip_Buffer *modified_; // non-zero = true (more optimal than using bool, heh)
friend class Blip_Reader;
};
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
// but reduce maximum buffer size.
-#ifndef BLIP_BUFFER_ACCURACY
- #define BLIP_BUFFER_ACCURACY 16
-#endif
+const int BLIP_BUFFER_ACCURACY = 16;
// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
// noticeable broadband noise when synthesizing high frequency square waves.
// Affects size of Blip_Synth objects since they store the waveform directly.
-#ifndef BLIP_PHASE_BITS
- #if BLIP_BUFFER_FAST
- #define BLIP_PHASE_BITS 8
- #else
- #define BLIP_PHASE_BITS 6
- #endif
-#endif
-
- // Internal
- typedef blip_ulong blip_resampled_time_t;
- int const blip_widest_impulse_ = 16;
- int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
- int const blip_res = 1 << BLIP_PHASE_BITS;
- class blip_eq_t;
-
- class Blip_Synth_Fast_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_Fast_();
- void treble_eq( blip_eq_t const& ) { }
- };
-
- class Blip_Synth_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_( short* impulses, int width );
- void treble_eq( blip_eq_t const& );
- private:
- double volume_unit_;
- short* const impulses;
- int const width;
- blip_long kernel_unit;
- int impulses_size() const { return blip_res / 2 * width + 1; }
- void adjust_impulse();
- };
+#if BLIP_BUFFER_FAST
+const int BLIP_PHASE_BITS = 8;
+#else
+const int BLIP_PHASE_BITS = 6;
+#endif
+
+// Internal
+typedef uint32_t blip_resampled_time_t;
+const int blip_widest_impulse_ = 16;
+const int blip_buffer_extra_ = blip_widest_impulse_ + 2;
+const int blip_res = 1 << BLIP_PHASE_BITS;
+class blip_eq_t;
+
+class Blip_Synth_Fast_
+{
+public:
+ Blip_Buffer *buf;
+ int last_amp;
+ int delta_factor;
+
+ void volume_unit(double);
+ Blip_Synth_Fast_();
+ void treble_eq(const blip_eq_t &) { }
+};
+
+class Blip_Synth_
+{
+public:
+ Blip_Buffer *buf;
+ int last_amp;
+ int delta_factor;
+
+ void volume_unit(double);
+ Blip_Synth_(short *impulses, int width);
+ void treble_eq(const blip_eq_t &);
+private:
+ double volume_unit_;
+ short *const impulses;
+ const int width;
+ int32_t kernel_unit;
+ int impulses_size() const { return blip_res / 2 * this->width + 1; }
+ void adjust_impulse();
+};
// Quality level, better = slower. In general, use blip_good_quality.
const int blip_med_quality = 8;
@@ -203,40 +178,42 @@
// Range specifies the greatest expected change in amplitude. Calculate it
// by finding the difference between the maximum and minimum expected
// amplitudes (max - min).
-template<int quality,int range>
-class Blip_Synth {
+template<int quality, int range> class Blip_Synth
+{
public:
// Sets overall volume of waveform
- void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
+ void volume(double v) { this->impl.volume_unit(v * (1.0 / (range < 0 ? -range : range))); }
// Configures low-pass filter (see blip_buffer.txt)
- void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
+ void treble_eq(const blip_eq_t &eq) { this->impl.treble_eq(eq); }
// Gets/sets Blip_Buffer used for output
- Blip_Buffer* output() const { return impl.buf; }
- void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
+ Blip_Buffer *output() const { return this->impl.buf; }
+ void output(Blip_Buffer *b) { this->impl.buf = b; this->impl.last_amp = 0; }
// Updates amplitude of waveform at given time. Using this requires a separate
// Blip_Synth for each waveform.
- void update( blip_time_t time, int amplitude );
-
-// Low-level interface
+ void update(blip_time_t time, int amplitude);
+
+ // Low-level interface
// Adds an amplitude transition of specified delta, optionally into specified buffer
// rather than the one set with output(). Delta can be positive or negative.
// The actual change in amplitude is delta * (volume / range)
- void offset( blip_time_t, int delta, Blip_Buffer* ) const;
- void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
+ void offset(blip_time_t, int delta, Blip_Buffer *) const;
+ void offset(blip_time_t t, int delta) const { this->offset(t, delta, this->impl.buf); }
// Works directly in terms of fractional output samples. Contact author for more info.
- void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
+ void offset_resampled(blip_resampled_time_t, int delta, Blip_Buffer *) const;
// Same as offset(), except code is inlined for higher performance
- void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
+ void offset_inline(blip_time_t t, int delta, Blip_Buffer *buf) const
+ {
+ this->offset_resampled(t * buf->factor_ + buf->offset_, delta, buf);
}
- void offset_inline( blip_time_t t, int delta ) const {
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
+ void offset_inline(blip_time_t t, int delta) const
+ {
+ this->offset_resampled(t * this->impl.buf->factor_ + this->impl.buf->offset_, delta, this->impl.buf);
}
private:
@@ -245,313 +222,240 @@
#else
Blip_Synth_ impl;
typedef short imp_t;
- imp_t impulses [blip_res * (quality / 2) + 1];
-public:
- Blip_Synth() : impl( impulses, quality ) { }
+ imp_t impulses[blip_res * (quality / 2) + 1];
+public:
+ Blip_Synth() : impl(impulses, quality) { }
#endif
};
// Low-pass equalization parameters
-class blip_eq_t {
+class blip_eq_t
+{
public:
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
// treble, small positive values (0 to 5.0) increase treble.
- blip_eq_t( double treble_db = 0 );
+ blip_eq_t(double treble_db = 0);
// See blip_buffer.txt
- blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
+ blip_eq_t(double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0);
private:
double treble;
long rolloff_freq;
long sample_rate;
long cutoff_freq;
- void generate( float* out, int count ) const;
+ void generate(float *out, int count) const;
friend class Blip_Synth_;
};
-int const blip_sample_bits = 30;
-
-// Dummy Blip_Buffer to direct sound output to, for easy muting without
-// having to stop sound code.
-class Silent_Blip_Buffer : public Blip_Buffer {
- buf_t_ buf [blip_buffer_extra_ + 1];
-public:
- // The following cannot be used (an assertion will fail if attempted):
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
- blip_time_t count_clocks( long count ) const;
- void mix_samples( blip_sample_t const* buf, long count );
-
- Silent_Blip_Buffer();
-};
-
- #if __GNUC__ >= 3 || _MSC_VER >= 1100
- #define BLIP_RESTRICT __restrict
- #else
- #define BLIP_RESTRICT
- #endif
+const int blip_sample_bits = 30;
// Optimized reading from Blip_Buffer, for use in custom sample output
// Begins reading from buffer. Name should be unique to the current block.
-#define BLIP_READER_BEGIN( name, blip_buffer ) \
- const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
- blip_long name##_reader_accum = (blip_buffer).reader_accum_
+#define BLIP_READER_BEGIN(name, blip_buffer) \
+ auto name##_reader_buf = &(blip_buffer).buffer_[0]; \
+ int32_t name##_reader_accum = (blip_buffer).reader_accum_
// Gets value to pass to BLIP_READER_NEXT()
-#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
+inline int BLIP_READER_BASS(const Blip_Buffer &blip_buffer) { return blip_buffer.bass_shift_; }
// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
// code at the cost of having no bass control
-int const blip_reader_default_bass = 9;
+const int blip_reader_default_bass = 9;
// Current sample
-#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
+#define BLIP_READER_READ(name) (name##_reader_accum >> (blip_sample_bits - 16))
// Current raw sample in full internal resolution
-#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
+#define BLIP_READER_READ_RAW(name) (name##_reader_accum)
// Advances to next sample
-#define BLIP_READER_NEXT( name, bass ) \
- (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
+#define BLIP_READER_NEXT(name, bass) \
+ (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
// Ends reading samples from buffer. The number of samples read must now be removed
// using Blip_Buffer::remove_samples().
-#define BLIP_READER_END( name, blip_buffer ) \
- (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
-
+#define BLIP_READER_END(name, blip_buffer) \
+ ((blip_buffer).reader_accum_ = name##_reader_accum)
// experimental
-#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset)
-
-blip_long const blip_reader_idx_factor = sizeof (Blip_Buffer::buf_t_);
-
-#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\
+#define BLIP_READER_ADJ_(name, offset) (name##_reader_buf += offset)
+
+const int32_t blip_reader_idx_factor = sizeof(Blip_Buffer::buf_t_);
+
+#define BLIP_READER_NEXT_IDX_(name, bass, idx) \
+{ \
+ name##_reader_accum -= name##_reader_accum >> (bass); \
+ name##_reader_accum += name##_reader_buf[(idx)]; \
+}
+
+#define BLIP_READER_NEXT_RAW_IDX_(name, bass, idx) \
+{ \
name##_reader_accum -= name##_reader_accum >> (bass);\
- name##_reader_accum += name##_reader_buf [(idx)];\
-}
-
-#define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\
- name##_reader_accum -= name##_reader_accum >> (bass);\
- name##_reader_accum +=\
- *(Blip_Buffer::buf_t_ const*) ((char const*) name##_reader_buf + (idx));\
+ name##_reader_accum += *reinterpret_cast<const Blip_Buffer::buf_t_ *>(reinterpret_cast<const char *>(name##_reader_buf) + (idx));\
}
// Compatibility with older version
const long blip_unscaled = 65535;
-const int blip_low_quality = blip_med_quality;
+const int blip_low_quality = blip_med_quality;
const int blip_best_quality = blip_high_quality;
-// Deprecated; use BLIP_READER macros as follows:
-// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
-// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
-// r.read() -> BLIP_READER_READ( r )
-// r.read_raw() -> BLIP_READER_READ_RAW( r )
-// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
-// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
-// r.end( buf ) -> BLIP_READER_END( r, buf )
-class Blip_Reader {
-public:
- int begin( Blip_Buffer& );
- blip_long read() const { return accum >> (blip_sample_bits - 16); }
- blip_long read_raw() const { return accum; }
- void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
- void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
-private:
- const Blip_Buffer::buf_t_* buf;
- blip_long accum;
-};
-
-#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
- #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in
+#if defined(_M_IX86) || defined(_M_IA64) || defined(__i486__) || defined(__x86_64__) || defined(__ia64__) || defined(__i386__)
+template<typename T> inline bool BLIP_CLAMP_(const T &in) { return in < -0x8000 || 0x7FFF < in; }
#else
- #define BLIP_CLAMP_( in ) (blip_sample_t) in != in
+template<typename T> inline bool BLIP_CLAMP_(const T &in) { return static_cast<blip_sample_t>(in) != in; }
#endif
// Clamp sample to blip_sample_t range
-#define BLIP_CLAMP( sample, out )\
- { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 24) ^ 0x7FFF; }
-
-struct blip_buffer_state_t
-{
- blip_resampled_time_t offset_;
- blip_long reader_accum_;
- blip_long buf [blip_buffer_extra_];
-};
+template<typename T1, typename T2> inline void BLIP_CLAMP(const T1 &sample, T2 &out)
+{
+ if (BLIP_CLAMP_(sample))
+ out = (sample >> 24) ^ 0x7FFF;
+}
// End of public interface
#ifndef assert
- #include <assert.h>
-#endif
-
-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
+# include <cassert>
+#endif
+
+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
{
// If this assertion fails, it means that an attempt was made to add a delta
// at a negative time or past the end of the buffer.
- assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
-
- delta *= impl.delta_factor;
- blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
- int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
+ assert(static_cast<int32_t>(time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_);
+
+ delta *= this->impl.delta_factor;
+ auto buf = &blip_buf->buffer_[time >> BLIP_BUFFER_ACCURACY];
+ int phase = static_cast<int>((time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS)) & (blip_res - 1));
#if BLIP_BUFFER_FAST
- blip_long left = buf [0] + delta;
+ int32_t left = buf[0] + delta;
// Kind of crappy, but doing shift after multiply results in overflow.
// Alternate way of delaying multiply by delta_factor results in worse
// sub-sample resolution.
- blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
- left -= right;
+ int32_t right = (delta >> BLIP_PHASE_BITS) * phase;
+ left -= right;
right += buf [1];
- buf [0] = left;
- buf [1] = right;
+ buf[0] = left;
+ buf[1] = right;
#else
-
- int const fwd = (blip_widest_impulse_ - quality) / 2;
- int const rev = fwd + quality - 2;
- int const mid = quality / 2 - 1;
-
- imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
-
- #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
-
+ int fwd = (blip_widest_impulse_ - quality) / 2;
+ int rev = fwd + quality - 2;
+ int mid = quality / 2 - 1;
+
+ auto imp = this->impulses + blip_res - phase;
+
+# if defined(_M_IX86) || defined(_M_IA64) || defined(__i486__) || defined(__x86_64__) || defined(__ia64__) || defined(__i386__)
// this straight forward version gave in better code on GCC for x86
- #define ADD_IMP( out, in ) \
- buf [out] += (blip_long) imp [blip_res * (in)] * delta
-
- #define BLIP_FWD( i ) {\
- ADD_IMP( fwd + i, i );\
- ADD_IMP( fwd + 1 + i, i + 1 );\
- }
- #define BLIP_REV( r ) {\
- ADD_IMP( rev - r, r + 1 );\
- ADD_IMP( rev + 1 - r, r );\
- }
-
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- ADD_IMP( fwd + mid - 1, mid - 1 );
- ADD_IMP( fwd + mid , mid );
- imp = impulses + phase;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- ADD_IMP( rev , 1 );
- ADD_IMP( rev + 1, 0 );
-
- #undef ADD_IMP
-
- #else
-
+ auto ADD_IMP = [&](int out, int in) { buf[out] += static_cast<int32_t>(imp[blip_res * in] * delta); };
+
+ auto BLIP_FWD = [&](int i) { ADD_IMP(fwd + i, i); ADD_IMP(fwd + 1 + i, i + 1); };
+ auto BLIP_REV = [&](int r) { ADD_IMP(rev - r, r + 1); ADD_IMP(rev + 1 - r, r); };
+
+ BLIP_FWD(0);
+ if (quality > 8)
+ BLIP_FWD(2);
+ if (quality > 12)
+ BLIP_FWD(4);
+ ADD_IMP(fwd + mid - 1, mid - 1);
+ ADD_IMP(fwd + mid, mid);
+ imp = this->impulses + phase;
+ if (quality > 12)
+ BLIP_REV(6);
+ if (quality > 8)
+ BLIP_REV(4);
+ BLIP_REV(2);
+
+ ADD_IMP(rev, 1);
+ ADD_IMP(rev + 1, 0);
+# else
// for RISC processors, help compiler by reading ahead of writes
- #define BLIP_FWD( i ) {\
- blip_long t0 = i0 * delta + buf [fwd + i];\
- blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
- i0 = imp [blip_res * (i + 2)];\
- buf [fwd + i] = t0;\
- buf [fwd + 1 + i] = t1;\
- }
- #define BLIP_REV( r ) {\
- blip_long t0 = i0 * delta + buf [rev - r];\
- blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
- i0 = imp [blip_res * (r - 1)];\
- buf [rev - r] = t0;\
- buf [rev + 1 - r] = t1;\
- }
-
- blip_long i0 = *imp;
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- blip_long t0 = i0 * delta + buf [fwd + mid - 1];
- blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
- imp = impulses + phase;
- i0 = imp [blip_res * mid];
- buf [fwd + mid - 1] = t0;
- buf [fwd + mid ] = t1;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- blip_long t0 = i0 * delta + buf [rev ];
- blip_long t1 = *imp * delta + buf [rev + 1];
- buf [rev ] = t0;
- buf [rev + 1] = t1;
- #endif
-
-#endif
-}
-
-#undef BLIP_FWD
-#undef BLIP_REV
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
-{
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
-}
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
-{
- int delta = amp - impl.last_amp;
- impl.last_amp = amp;
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
-}
-
-inline blip_eq_t::blip_eq_t( double t ) :
- treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
-inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
- treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
-
-inline int Blip_Buffer::length() const { return length_; }
-inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
-inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
-inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
-inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
-inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
-
-inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
-{
- buf = blip_buf.buffer_;
- accum = blip_buf.reader_accum_;
- return blip_buf.bass_shift_;
-}
-
-inline void Blip_Buffer::remove_silence( long count )
+ int32_t i0 = *imp;
+
+ auto BLIP_FWD = [&](int i)
+ {
+ int32_t t0 = i0 * delta + buf[fwd + i];
+ int32_t t1 = imp[blip_res * (i + 1)] * delta + buf[fwd + 1 + i];
+ i0 = imp[blip_res * (i + 2)];
+ buf[fwd + i] = t0;
+ buf[fwd + 1 + i] = t1;
+ };
+ auto BLIP_REV = [&](int r)
+ {
+ int32_t t0 = i0 * delta + buf[rev - r];
+ int32_t t1 = imp[blip_res * r] * delta + buf[rev + 1 - r];
+ i0 = imp[blip_res * (r - 1)];
+ buf[rev - r] = t0;
+ buf[rev + 1 - r] = t1;
+ };
+
+ BLIP_FWD(0);
+ if (quality > 8)
+ BLIP_FWD(2);
+ if (quality > 12)
+ BLIP_FWD(4);
+ int32_t t0 = i0 * delta + buf[fwd + mid - 1];
+ int32_t t1 = imp[blip_res * mid] * delta + buf[fwd + mid];
+ imp = this->impulses + phase;
+ i0 = imp[blip_res * mid];
+ buf[fwd + mid - 1] = t0;
+ buf[fwd + mid] = t1;
+ if (quality > 12)
+ BLIP_REV(6);
+ if (quality > 8)
+ BLIP_REV(4);
+ BLIP_REV(2);
+
+ t0 = i0 * delta + buf[rev];
+ t1 = *imp * delta + buf[rev + 1];
+ buf[rev] = t0;
+ buf[rev + 1] = t1;
+# endif
+#endif
+}
+
+template<int quality, int range> inline void Blip_Synth<quality, range>::offset(blip_time_t t, int delta, Blip_Buffer *buf) const
+{
+ this->offset_resampled(t * buf->factor_ + buf->offset_, delta, buf);
+}
+
+template<int quality, int range> inline void Blip_Synth<quality, range>::update(blip_time_t t, int amp)
+{
+ int delta = amp - this->impl.last_amp;
+ this->impl.last_amp = amp;
+ this->offset_resampled(t * this->impl.buf->factor_ + this->impl.buf->offset_, delta, this->impl.buf);
+}
+
+inline blip_eq_t::blip_eq_t(double t) : treble(t), rolloff_freq(0), sample_rate(44100), cutoff_freq(0) { }
+inline blip_eq_t::blip_eq_t(double t, long rf, long sr, long cf) : treble(t), rolloff_freq(rf), sample_rate(sr), cutoff_freq(cf) { }
+
+inline int Blip_Buffer::length() const { return this->length_; }
+inline long Blip_Buffer::samples_avail() const { return static_cast<long>(this->offset_ >> BLIP_BUFFER_ACCURACY); }
+inline long Blip_Buffer::sample_rate() const { return this->sample_rate_; }
+inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
+inline long Blip_Buffer::clock_rate() const { return this->clock_rate_; }
+inline void Blip_Buffer::clock_rate(long cps) { this->factor_ = this->clock_rate_factor(this->clock_rate_ = cps); }
+
+inline void Blip_Buffer::remove_silence(long count)
{
// fails if you try to remove more samples than available
- assert( count <= samples_avail() );
- offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-}
-
-inline blip_ulong Blip_Buffer::unsettled() const
-{
- return reader_accum_ >> (blip_sample_bits - 16);
-}
-
-int const blip_max_length = 0;
-int const blip_default_length = 250; // 1/4 second
-
-#endif
-
+ assert(count <= this->samples_avail());
+ this->offset_ -= static_cast<blip_resampled_time_t>(count) << BLIP_BUFFER_ACCURACY;
+}
+
+inline uint32_t Blip_Buffer::unsettled() const
+{
+ return this->reader_accum_ >> (blip_sample_bits - 16);
+}
+
+const int blip_max_length = 0;
+const int blip_default_length = 250; // 1/4 second
+
+#endif
+
--- a/src/in_gsf/vbam/apu/Effects_Buffer.cpp
+++ b/src/in_gsf/vbam/apu/Effects_Buffer.cpp
@@ -2,7 +2,8 @@
#include "Effects_Buffer.h"
-#include <string.h>
+#include <cmath>
+#include <cstring>
/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
@@ -17,213 +18,198 @@
#include "blargg_source.h"
-int const fixed_shift = 12;
-#define TO_FIXED( f ) fixed_t ((f) * ((fixed_t) 1 << fixed_shift))
-#define FROM_FIXED( f ) ((f) >> fixed_shift)
-
-int const max_read = 2560; // determines minimum delay
-
-Effects_Buffer::Effects_Buffer( int max_bufs, long echo_size_ ) : Multi_Buffer( stereo )
-{
- echo_size = max( max_read * (long) stereo, echo_size_ & ~1 );
- clock_rate_ = 0;
- bass_freq_ = 90;
- bufs = 0;
- bufs_size = 0;
- bufs_max = max( max_bufs, (int) extra_chans );
- no_echo = true;
- no_effects = true;
+static const int fixed_shift = 12;
+template<typename T> static inline Effects_Buffer::fixed_t TO_FIXED(const T &f) { return static_cast<Effects_Buffer::fixed_t>(f * (static_cast<Effects_Buffer::fixed_t>(1) << fixed_shift)); }
+static inline Effects_Buffer::fixed_t FROM_FIXED(Effects_Buffer::fixed_t f) { return f >> fixed_shift; }
+
+static const int max_read = 2560; // determines minimum delay
+
+Effects_Buffer::Effects_Buffer(int max_bufs, long echo_size_) : Multi_Buffer(stereo)
+{
+ this->echo_size = std::max<long>(max_read * stereo, echo_size_ & ~1);
+ this->clock_rate_ = 0;
+ this->bass_freq_ = 90;
+ this->bufs.clear();
+ this->bufs_size = 0;
+ this->bufs_max = std::max<int>(max_bufs, extra_chans);
+ this->no_echo = this->no_effects = true;
// defaults
- config_.enabled = false;
- config_.delay [0] = 120;
- config_.delay [1] = 122;
- config_.feedback = 0.2f;
- config_.treble = 0.4f;
-
- static float const sep = 0.8f;
- config_.side_chans [0].pan = -sep;
- config_.side_chans [1].pan = +sep;
- config_.side_chans [0].vol = 1.0f;
- config_.side_chans [1].vol = 1.0f;
-
- memset( &s, 0, sizeof s );
- clear();
+ this->config_.enabled = false;
+ this->config_.delay[0] = 120;
+ this->config_.delay[1] = 122;
+ this->config_.feedback = 0.2f;
+ this->config_.treble = 0.4f;
+
+ static const float sep = 0.8f;
+ this->config_.side_chans[0].pan = -sep;
+ this->config_.side_chans[1].pan = sep;
+ this->config_.side_chans[0].vol = this->config_.side_chans[1].vol = 1.0f;
+
+ memset(&this->s, 0, sizeof(this->s));
+ this->clear();
}
Effects_Buffer::~Effects_Buffer()
{
- delete_bufs();
+ this->delete_bufs();
}
// avoid using new []
-blargg_err_t Effects_Buffer::new_bufs( int size )
-{
- bufs = (buf_t*) malloc( size * sizeof *bufs );
- CHECK_ALLOC( bufs );
- for ( int i = 0; i < size; i++ )
- new (bufs + i) buf_t;
- bufs_size = size;
+blargg_err_t Effects_Buffer::new_bufs(int size)
+{
+ this->delete_bufs();
+ this->bufs.resize(size);
+ for (int i = 0; i < size; ++i)
+ this->bufs[i].reset(new buf_t);
+ this->bufs_size = size;
return 0;
}
void Effects_Buffer::delete_bufs()
{
- if ( bufs )
- {
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].~buf_t();
- free( bufs );
- bufs = 0;
- }
- bufs_size = 0;
-}
-
-blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
+ this->bufs.clear();
+ this->bufs_size = 0;
+}
+
+blargg_err_t Effects_Buffer::set_sample_rate(long rate, int msec)
{
// extra to allow farther past-the-end pointers
- mixer.samples_read = 0;
- RETURN_ERR( echo.resize( echo_size + stereo ) );
- return Multi_Buffer::set_sample_rate( rate, msec );
-}
-
-void Effects_Buffer::clock_rate( long rate )
-{
- clock_rate_ = rate;
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clock_rate( clock_rate_ );
-}
-
-void Effects_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].bass_freq( bass_freq_ );
-}
-
-blargg_err_t Effects_Buffer::set_channel_count( int count, int const* types )
-{
- RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) );
-
- delete_bufs();
-
- mixer.samples_read = 0;
-
- RETURN_ERR( chans.resize( count + extra_chans ) );
-
- RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) );
-
- for ( int i = bufs_size; --i >= 0; )
- RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) );
-
- for ( int i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.cfg.vol = 1.0f;
- ch.cfg.pan = 0.0f;
- ch.cfg.surround = false;
- ch.cfg.echo = false;
+ this->mixer.samples_read = 0;
+ this->echo.resize(echo_size + stereo);
+ return Multi_Buffer::set_sample_rate(rate, msec);
+}
+
+void Effects_Buffer::clock_rate(long rate)
+{
+ this->clock_rate_ = rate;
+ for (int i = this->bufs_size; --i >= 0; )
+ this->bufs[i]->clock_rate(this->clock_rate_);
+}
+
+void Effects_Buffer::bass_freq(int freq)
+{
+ this->bass_freq_ = freq;
+ for (int i = this->bufs_size; --i >= 0; )
+ this->bufs[i]->bass_freq(this->bass_freq_);
+}
+
+blargg_err_t Effects_Buffer::set_channel_count(int count, const int *types)
+{
+ Multi_Buffer::set_channel_count(count, types);
+
+ this->delete_bufs();
+
+ this->mixer.samples_read = 0;
+
+ this->chans.resize(count + extra_chans);
+
+ this->new_bufs(std::min(this->bufs_max, count + extra_chans));
+
+ for (int i = this->bufs_size; --i >= 0; )
+ RETURN_ERR(this->bufs[i]->set_sample_rate(this->sample_rate(), this->length()));
+
+ for (int i = this->chans.size(); --i >= 0; )
+ {
+ auto &ch = this->chans[i];
+ ch.cfg.vol = 1.0f;
+ ch.cfg.pan = 0.0f;
+ ch.cfg.surround = ch.cfg.echo = false;
}
// side channels with echo
- chans [2].cfg.echo = true;
- chans [3].cfg.echo = true;
-
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
- apply_config();
- clear();
+ this->chans[2].cfg.echo = this->chans[3].cfg.echo = true;
+
+ this->clock_rate(this->clock_rate_);
+ this->bass_freq(this->bass_freq_);
+ this->apply_config();
+ this->clear();
return 0;
}
void Effects_Buffer::clear_echo()
{
- if ( echo.size() )
- memset( echo.begin(), 0, echo.size() * sizeof echo [0] );
+ if (!this->echo.empty())
+ memset(&this->echo[0], 0, this->echo.size() * sizeof(echo[0]));
}
void Effects_Buffer::clear()
{
- echo_pos = 0;
- s.low_pass [0] = 0;
- s.low_pass [1] = 0;
- mixer.samples_read = 0;
-
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clear();
- clear_echo();
-}
-
-Effects_Buffer::channel_t Effects_Buffer::channel( int i )
+ this->echo_pos = 0;
+ this->s.low_pass[0] = this->s.low_pass[1] = 0;
+ this->mixer.samples_read = 0;
+
+ for (int i = this->bufs_size; --i >= 0; )
+ this->bufs[i]->clear();
+ this->clear_echo();
+}
+
+auto Effects_Buffer::channel(int i) -> channel_t
{
i += extra_chans;
- require( extra_chans <= i && i < (int) chans.size() );
- return chans [i].channel;
-}
-
+ assert(extra_chans <= i && i < static_cast<int>(this->chans.size()));
+ return this->chans[i].channel;
+}
// Configuration
// 3 wave positions with/without surround, 2 multi (one with same config as wave)
-int const simple_bufs = 3 * 2 + 2 - 1;
-
-Simple_Effects_Buffer::Simple_Effects_Buffer() :
- Effects_Buffer( extra_chans + simple_bufs, 18 * 1024L )
-{
- config_.echo = 0.20f;
- config_.stereo = 0.20f;
- config_.surround = true;
- config_.enabled = false;
+static const int simple_bufs = 3 * 2 + 2 - 1;
+
+Simple_Effects_Buffer::Simple_Effects_Buffer() : Effects_Buffer(extra_chans + simple_bufs, 18 * 1024L)
+{
+ this->config_.echo = 0.20f;
+ this->config_.stereo = 0.20f;
+ this->config_.surround = true;
+ this->config_.enabled = false;
}
void Simple_Effects_Buffer::apply_config()
{
- Effects_Buffer::config_t& c = Effects_Buffer::config();
-
- c.enabled = config_.enabled;
- if ( c.enabled )
- {
- c.delay [0] = 120;
- c.delay [1] = 122;
- c.feedback = config_.echo * 0.7f;
- c.treble = 0.6f - 0.3f * config_.echo;
-
- float sep = config_.stereo + 0.80f;
- if ( sep > 1.0f )
+ auto &c = Effects_Buffer::config();
+
+ c.enabled = this->config_.enabled;
+ if (c.enabled)
+ {
+ c.delay[0] = 120;
+ c.delay[1] = 122;
+ c.feedback = this->config_.echo * 0.7f;
+ c.treble = 0.6f - 0.3f * this->config_.echo;
+
+ float sep = this->config_.stereo + 0.80f;
+ if (sep > 1.0f)
sep = 1.0f;
- c.side_chans [0].pan = -sep;
- c.side_chans [1].pan = +sep;
-
- for ( int i = channel_count(); --i >= 0; )
- {
- chan_config_t& ch = Effects_Buffer::chan_config( i );
-
- ch.pan = 0.0f;
- ch.surround = config_.surround;
- ch.echo = false;
-
- int const type = (channel_types() ? channel_types() [i] : 0);
- if ( !(type & noise_type) )
+ c.side_chans[0].pan = -sep;
+ c.side_chans[1].pan = sep;
+
+ for (int i = this->channel_count(); --i >= 0; )
+ {
+ auto &ch = Effects_Buffer::chan_config(i);
+
+ ch.pan = 0.0f;
+ ch.surround = this->config_.surround;
+ ch.echo = false;
+
+ int type = this->channel_types() ? this->channel_types()[i] : 0;
+ if (!(type & noise_type))
{
int index = (type & type_index_mask) % 6 - 3;
- if ( index < 0 )
+ if (index < 0)
{
index += 3;
ch.surround = false;
- ch.echo = true;
+ ch.echo = true;
}
- if ( index >= 1 )
+ if (index >= 1)
{
- ch.pan = config_.stereo;
- if ( index == 1 )
+ ch.pan = this->config_.stereo;
+ if (index == 1)
ch.pan = -ch.pan;
}
}
- else if ( type & 1 )
- {
+ else if (type & 1)
ch.surround = false;
- }
}
}
@@ -232,183 +218,183 @@
int Effects_Buffer::min_delay() const
{
- require( sample_rate() );
- return max_read * 1000L / sample_rate();
+ assert(this->sample_rate());
+ return max_read * 1000L / this->sample_rate();
}
int Effects_Buffer::max_delay() const
{
- require( sample_rate() );
- return (echo_size / stereo - max_read) * 1000L / sample_rate();
+ assert(this->sample_rate());
+ return (this->echo_size / stereo - max_read) * 1000L / this->sample_rate();
}
void Effects_Buffer::apply_config()
{
+ if (!this->bufs_size)
+ return;
+
+ this->s.treble = TO_FIXED(this->config_.treble);
+
+ bool echo_dirty = false;
+
+ fixed_t old_feedback = this->s.feedback;
+ this->s.feedback = TO_FIXED(this->config_.feedback);
+ if (!old_feedback && this->s.feedback)
+ echo_dirty = true;
+
+ // delays
int i;
-
- if ( !bufs_size )
- return;
-
- s.treble = TO_FIXED( config_.treble );
-
- bool echo_dirty = false;
-
- fixed_t old_feedback = s.feedback;
- s.feedback = TO_FIXED( config_.feedback );
- if ( !old_feedback && s.feedback )
- echo_dirty = true;
-
- // delays
- for ( i = stereo; --i >= 0; )
- {
- long delay = config_.delay [i] * sample_rate() / 1000 * stereo;
- delay = max( delay, long (max_read * stereo) );
- delay = min( delay, long (echo_size - max_read * stereo) );
- if ( s.delay [i] != delay )
- {
- s.delay [i] = delay;
+ for (i = stereo; --i >= 0;)
+ {
+ long delay = this->config_.delay[i] * this->sample_rate() / 1000 * stereo;
+ delay = std::max<long>(delay, max_read * stereo);
+ delay = std::min<long>(delay, this->echo_size - max_read * stereo);
+ if (this->s.delay[i] != delay)
+ {
+ this->s.delay[i] = delay;
echo_dirty = true;
}
}
// side channels
- for ( i = 2; --i >= 0; )
- {
- chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f;
- chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan;
+ for (i = 2; --i >= 0; )
+ {
+ this->chans[i + 2].cfg.vol = this->chans[i].cfg.vol = this->config_.side_chans[i].vol * 0.5f;
+ this->chans[i + 2].cfg.pan = this->chans[i].cfg.pan = this->config_.side_chans[i].pan;
}
// convert volumes
- for ( i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan );
- ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan );
- if ( ch.cfg.surround )
- ch.vol [0] = -ch.vol [0];
- }
-
- assign_buffers();
+ for (i = this->chans.size(); --i >= 0; )
+ {
+ auto &ch = this->chans[i];
+ ch.vol[0] = TO_FIXED(ch.cfg.vol - ch.cfg.vol * ch.cfg.pan);
+ ch.vol[1] = TO_FIXED(ch.cfg.vol + ch.cfg.vol * ch.cfg.pan);
+ if (ch.cfg.surround)
+ ch.vol[0] = -ch.vol [0];
+ }
+
+ this->assign_buffers();
// set side channels
- for ( i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.channel.left = chans [ch.cfg.echo*2 ].channel.center;
- ch.channel.right = chans [ch.cfg.echo*2+1].channel.center;
- }
-
- bool old_echo = !no_echo && !no_effects;
+ for (i = this->chans.size(); --i >= 0; )
+ {
+ auto &ch = chans[i];
+ ch.channel.left = this->chans[ch.cfg.echo * 2].channel.center;
+ ch.channel.right = this->chans[ch.cfg.echo * 2 + 1].channel.center;
+ }
+
+ bool old_echo = !this->no_echo && !this->no_effects;
// determine whether effects and echo are needed at all
- no_effects = true;
- no_echo = true;
- for ( i = chans.size(); --i >= extra_chans; )
- {
- chan_t& ch = chans [i];
- if ( ch.cfg.echo && s.feedback )
- no_echo = false;
-
- if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) )
- no_effects = false;
- }
- if ( !no_echo )
- no_effects = false;
-
- if ( chans [0].vol [0] != TO_FIXED( 1 ) ||
- chans [0].vol [1] != TO_FIXED( 0 ) ||
- chans [1].vol [0] != TO_FIXED( 0 ) ||
- chans [1].vol [1] != TO_FIXED( 1 ) )
- no_effects = false;
-
- if ( !config_.enabled )
- no_effects = true;
-
- if ( no_effects )
- {
- for ( i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.channel.center = &bufs [2];
- ch.channel.left = &bufs [0];
- ch.channel.right = &bufs [1];
- }
- }
-
- mixer.bufs [0] = &bufs [0];
- mixer.bufs [1] = &bufs [1];
- mixer.bufs [2] = &bufs [2];
-
- if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) )
- clear_echo();
-
- channels_changed();
+ this->no_effects = this->no_echo = true;
+ for (i = this->chans.size(); --i >= extra_chans; )
+ {
+ auto &ch = this->chans[i];
+ if (ch.cfg.echo && this->s.feedback)
+ this->no_echo = false;
+
+ if (ch.vol[0] != TO_FIXED(1) || ch.vol[1] != TO_FIXED(1))
+ this->no_effects = false;
+ }
+ if (!this->no_echo)
+ this->no_effects = false;
+
+ if (this->chans[0].vol[0] != TO_FIXED(1) || this->chans[0].vol[1] != TO_FIXED(0) || this->chans[1].vol[0] != TO_FIXED(0) || this->chans[1].vol[1] != TO_FIXED(1))
+ this->no_effects = false;
+
+ if (!this->config_.enabled)
+ this->no_effects = true;
+
+ if (this->no_effects)
+ {
+ for (i = this->chans.size(); --i >= 0; )
+ {
+ auto &ch = this->chans[i];
+ ch.channel.center = this->bufs[2].get();
+ ch.channel.left = this->bufs[0].get();
+ ch.channel.right = this->bufs[1].get();
+ }
+ }
+
+ this->mixer.bufs[0] = this->bufs[0].get();
+ this->mixer.bufs[1] = this->bufs[1].get();
+ this->mixer.bufs[2] = this->bufs[2].get();
+
+ if (echo_dirty || (!old_echo && (!this->no_echo && !this->no_effects)))
+ this->clear_echo();
+
+ this->channels_changed();
}
void Effects_Buffer::assign_buffers()
{
// assign channels to buffers
int buf_count = 0;
- for ( int i = 0; i < (int) chans.size(); i++ )
+ for (int i = 0; i < static_cast<int>(this->chans.size()); ++i)
{
// put second two side channels at end to give priority to main channels
// in case closest matching is necessary
int x = i;
- if ( i > 1 )
+ if (i > 1)
x += 2;
- if ( x >= (int) chans.size() )
- x -= (chans.size() - 2);
- chan_t& ch = chans [x];
+ if (x >= static_cast<int>(this->chans.size()))
+ x -= this->chans.size() - 2;
+ auto &ch = this->chans[x];
int b = 0;
- for ( ; b < buf_count; b++ )
- {
- if ( ch.vol [0] == bufs [b].vol [0] &&
- ch.vol [1] == bufs [b].vol [1] &&
- (ch.cfg.echo == bufs [b].echo || !s.feedback) )
+ for (; b < buf_count; ++b)
+ {
+ if (ch.vol[0] == this->bufs[b]->vol[0] && ch.vol[1] == this->bufs[b]->vol[1] && (ch.cfg.echo == this->bufs[b]->echo || !this->s.feedback))
break;
}
- if ( b >= buf_count )
- {
- if ( buf_count < bufs_max )
+ if (b >= buf_count)
+ {
+ if (buf_count < this->bufs_max)
{
- bufs [b].vol [0] = ch.vol [0];
- bufs [b].vol [1] = ch.vol [1];
- bufs [b].echo = ch.cfg.echo;
- buf_count++;
+ this->bufs[b]->vol[0] = ch.vol[0];
+ this->bufs[b]->vol[1] = ch.vol[1];
+ this->bufs[b]->echo = ch.cfg.echo;
+ ++buf_count;
}
else
{
// TODO: this is a mess, needs refinement
- dprintf( "Effects_Buffer ran out of buffers; using closest match\n" );
b = 0;
- fixed_t best_dist = TO_FIXED( 8 );
- for ( int h = buf_count; --h >= 0; )
+ fixed_t best_dist = TO_FIXED(8);
+ for (int h = buf_count; --h >= 0; )
{
- #define CALC_LEVELS( vols, sum, diff, surround ) \
- fixed_t sum, diff;\
- bool surround = false;\
- {\
- fixed_t vol_0 = vols [0];\
- if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\
- fixed_t vol_1 = vols [1];\
- if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\
- sum = vol_0 + vol_1;\
- diff = vol_0 - vol_1;\
- }
- CALC_LEVELS( ch.vol, ch_sum, ch_diff, ch_surround );
- CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround );
-
- fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff );
-
- if ( ch_surround != buf_surround )
- dist += TO_FIXED( 1 ) / 2;
-
- if ( s.feedback && ch.cfg.echo != bufs [h].echo )
- dist += TO_FIXED( 1 ) / 2;
-
- if ( best_dist > dist )
+ auto CALC_LEVELS = [&](fixed_t vols[], fixed_t &sum, fixed_t &diff, bool &surround)
+ {
+ fixed_t vol_0 = vols[0];
+ if (vol_0 < 0)
+ {
+ vol_0 = -vol_0;
+ surround = true;
+ }
+ fixed_t vol_1 = vols[1];
+ if (vol_1 < 0)
+ {
+ vol_1 = -vol_1;
+ surround = true;
+ }
+ sum = vol_0 + vol_1;
+ diff = vol_0 - vol_1;
+ };
+ fixed_t ch_sum, ch_diff, buf_sum, buf_diff;
+ bool ch_surround, buf_surround;
+ CALC_LEVELS(ch.vol, ch_sum, ch_diff, ch_surround);
+ CALC_LEVELS(this->bufs[h]->vol, buf_sum, buf_diff, buf_surround);
+
+ fixed_t dist = std::abs(ch_sum - buf_sum) + std::abs(ch_diff - buf_diff);
+
+ if (ch_surround != buf_surround)
+ dist += TO_FIXED(1) / 2;
+
+ if (this->s.feedback && ch.cfg.echo != this->bufs[h]->echo)
+ dist += TO_FIXED(1) / 2;
+
+ if (best_dist > dist)
{
best_dist = dist;
b = h;
@@ -417,32 +403,28 @@
}
}
- //dprintf( "ch %d->buf %d\n", x, b );
- ch.channel.center = &bufs [b];
- }
-}
-
+ ch.channel.center = this->bufs[b].get();
+ }
+}
// Mixing
-void Effects_Buffer::end_frame( blip_time_t time )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].end_frame( time );
-}
-
-long Effects_Buffer::read_samples( blip_sample_t* out, long out_size )
-{
- out_size = min( out_size, samples_avail() );
-
- int pair_count = int (out_size >> 1);
- require( pair_count * stereo == out_size ); // must read an even number of samples
- if ( pair_count )
- {
- if ( no_effects )
- {
- mixer.read_pairs( out, pair_count );
- }
+void Effects_Buffer::end_frame(blip_time_t time)
+{
+ for (int i = bufs_size; --i >= 0; )
+ this->bufs[i]->end_frame(time);
+}
+
+long Effects_Buffer::read_samples(blip_sample_t *out, long out_size)
+{
+ out_size = std::min(out_size, this->samples_avail());
+
+ int pair_count = static_cast<int>(out_size >> 1);
+ assert(pair_count * stereo == out_size); // must read an even number of samples
+ if (pair_count)
+ {
+ if (this->no_effects)
+ this->mixer.read_pairs(out, pair_count);
else
{
int pairs_remain = pair_count;
@@ -450,50 +432,49 @@
{
// mix at most max_read pairs at a time
int count = max_read;
- if ( count > pairs_remain )
+ if (count > pairs_remain)
count = pairs_remain;
- if ( no_echo )
+ if (this->no_echo)
{
// optimization: clear echo here to keep mix_effects() a leaf function
- echo_pos = 0;
- memset( echo.begin(), 0, count * stereo * sizeof echo [0] );
+ this->echo_pos = 0;
+ memset(&this->echo[0], 0, count * stereo * sizeof(this->echo[0]));
}
- mix_effects( out, count );
-
- blargg_long new_echo_pos = echo_pos + count * stereo;
- if ( new_echo_pos >= echo_size )
- new_echo_pos -= echo_size;
- echo_pos = new_echo_pos;
- assert( echo_pos < echo_size );
+ this->mix_effects(out, count);
+
+ int32_t new_echo_pos = this->echo_pos + count * stereo;
+ if (new_echo_pos >= this->echo_size)
+ new_echo_pos -= this->echo_size;
+ this->echo_pos = new_echo_pos;
+ assert(this->echo_pos < this->echo_size);
out += count * stereo;
- mixer.samples_read += count;
+ this->mixer.samples_read += count;
pairs_remain -= count;
+ } while (pairs_remain);
+ }
+
+ if (this->samples_avail() <= 0 || this->immediate_removal())
+ {
+ for (int i = this->bufs_size; --i >= 0; )
+ {
+ auto &b = this->bufs[i];
+ // TODO: might miss non-silence settling since it checks END of last read
+ if (b->non_silent())
+ b->remove_samples(this->mixer.samples_read);
+ else
+ b->remove_silence(this->mixer.samples_read);
}
- while ( pairs_remain );
- }
-
- if ( samples_avail() <= 0 || immediate_removal() )
- {
- for ( int i = bufs_size; --i >= 0; )
- {
- buf_t& b = bufs [i];
- // TODO: might miss non-silence settling since it checks END of last read
- if ( b.non_silent() )
- b.remove_samples( mixer.samples_read );
- else
- b.remove_silence( mixer.samples_read );
- }
- mixer.samples_read = 0;
+ this->mixer.samples_read = 0;
}
}
return out_size;
}
-void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count )
-{
- typedef fixed_t stereo_fixed_t [stereo];
+void Effects_Buffer::mix_effects(blip_sample_t *out_, int pair_count)
+{
+ typedef fixed_t stereo_fixed_t[stereo];
// add channels with echo, do echo, add channels without echo, then convert to 16-bit and output
int echo_phase = 1;
@@ -501,139 +482,129 @@
{
// mix any modified buffers
{
- buf_t* buf = bufs;
- int bufs_remain = bufs_size;
+ size_t bufNum = 0;
+ int bufs_remain = this->bufs_size;
do
{
- if ( buf->non_silent() && ( buf->echo == !!echo_phase ) )
+ auto &buf = this->bufs[bufNum++];
+ if (buf->non_silent() && (buf->echo == !!echo_phase))
{
- stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
- int const bass = BLIP_READER_BASS( *buf );
- BLIP_READER_BEGIN( in, *buf );
- BLIP_READER_ADJ_( in, mixer.samples_read );
- fixed_t const vol_0 = buf->vol [0];
- fixed_t const vol_1 = buf->vol [1];
-
- int count = unsigned (echo_size - echo_pos) / stereo;
+ auto out = reinterpret_cast<stereo_fixed_t *>(&this->echo[this->echo_pos]);
+ int bass = BLIP_READER_BASS(*buf);
+ BLIP_READER_BEGIN(in, *buf);
+ BLIP_READER_ADJ_(in, this->mixer.samples_read);
+ fixed_t vol_0 = buf->vol[0];
+ fixed_t vol_1 = buf->vol[1];
+
+ int count = static_cast<unsigned>(echo_size - echo_pos) / stereo;
int remain = pair_count;
- if ( count > remain )
+ if (count > remain)
count = remain;
do
{
remain -= count;
- BLIP_READER_ADJ_( in, count );
+ BLIP_READER_ADJ_(in, count);
out += count;
int offset = -count;
do
{
- fixed_t s = BLIP_READER_READ( in );
- BLIP_READER_NEXT_IDX_( in, bass, offset );
-
- out [offset] [0] += s * vol_0;
- out [offset] [1] += s * vol_1;
- }
- while ( ++offset );
-
- out = (stereo_fixed_t*) echo.begin();
+ fixed_t s = BLIP_READER_READ(in);
+ BLIP_READER_NEXT_IDX_(in, bass, offset);
+
+ out[offset][0] += s * vol_0;
+ out[offset][1] += s * vol_1;
+ } while ( ++offset );
+
+ out = reinterpret_cast<stereo_fixed_t *>(&this->echo[0]);
count = remain;
- }
- while ( remain );
-
- BLIP_READER_END( in, *buf );
+ } while (remain);
+
+ BLIP_READER_END(in, *buf);
}
- buf++;
- }
- while ( --bufs_remain );
+ } while (--bufs_remain);
}
// add echo
- if ( echo_phase && !no_echo )
- {
- fixed_t const feedback = s.feedback;
- fixed_t const treble = s.treble;
+ if (echo_phase && !this->no_echo)
+ {
+ fixed_t feedback = this->s.feedback;
+ fixed_t treble = this->s.treble;
int i = 1;
do
{
- fixed_t low_pass = s.low_pass [i];
-
- fixed_t* echo_end = &echo [echo_size + i];
- fixed_t const* BLIP_RESTRICT in_pos = &echo [echo_pos + i];
- blargg_long out_offset = echo_pos + i + s.delay [i];
- if ( out_offset >= echo_size )
- out_offset -= echo_size;
- assert( out_offset < echo_size );
- fixed_t* BLIP_RESTRICT out_pos = &echo [out_offset];
+ fixed_t low_pass = this->s.low_pass[i];
+
+ auto echo_end = &this->echo[this->echo_size + i];
+ auto in_pos = &this->echo[this->echo_pos + i];
+ int32_t out_offset = this->echo_pos + i + this->s.delay[i];
+ if (out_offset >= this->echo_size)
+ out_offset -= this->echo_size;
+ assert(out_offset < this->echo_size);
+ auto out_pos = &this->echo[out_offset];
// break into up to three chunks to avoid having to handle wrap-around
// in middle of core loop
int remain = pair_count;
do
{
- fixed_t const* pos = in_pos;
- if ( pos < out_pos )
+ auto pos = in_pos;
+ if (pos < out_pos)
pos = out_pos;
- int count = blargg_ulong ((char*) echo_end - (char const*) pos) /
- unsigned (stereo * sizeof (fixed_t));
- if ( count > remain )
+ int count = static_cast<uint32_t>(reinterpret_cast<char *>(echo_end) - reinterpret_cast<const char *>(pos)) / (stereo * sizeof(fixed_t));
+ if (count > remain)
count = remain;
remain -= count;
- in_pos += count * stereo;
+ in_pos += count * stereo;
out_pos += count * stereo;
int offset = -count;
do
{
- low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble;
- out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback;
- }
- while ( ++offset );
-
- if ( in_pos >= echo_end ) in_pos -= echo_size;
- if ( out_pos >= echo_end ) out_pos -= echo_size;
- }
- while ( remain );
-
- s.low_pass [i] = low_pass;
- }
- while ( --i >= 0 );
- }
- }
- while ( --echo_phase >= 0 );
+ low_pass += FROM_FIXED(in_pos[offset * stereo] - low_pass) * treble;
+ out_pos[offset * stereo] = FROM_FIXED(low_pass) * feedback;
+ } while (++offset);
+
+ if (in_pos >= echo_end)
+ in_pos -= echo_size;
+ if (out_pos >= echo_end)
+ out_pos -= echo_size;
+ } while (remain);
+
+ this->s.low_pass [i] = low_pass;
+ } while (--i >= 0);
+ }
+ } while (--echo_phase >= 0);
// clamp to 16 bits
- {
- stereo_fixed_t const* BLIP_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos];
- typedef blip_sample_t stereo_blip_sample_t [stereo];
- stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_;
- int count = unsigned (echo_size - echo_pos) / (unsigned) stereo;
- int remain = pair_count;
- if ( count > remain )
- count = remain;
+ auto in = reinterpret_cast<stereo_fixed_t *>(&this->echo[this->echo_pos]);
+ typedef blip_sample_t stereo_blip_sample_t[stereo];
+ auto out = reinterpret_cast<stereo_blip_sample_t *>(out_);
+ int count = static_cast<unsigned>(this->echo_size - this->echo_pos) / stereo;
+ int remain = pair_count;
+ if (count > remain)
+ count = remain;
+ do
+ {
+ remain -= count;
+ in += count;
+ out += count;
+ int offset = -count;
do
{
- remain -= count;
- in += count;
- out += count;
- int offset = -count;
- do
- {
- fixed_t in_0 = FROM_FIXED( in [offset] [0] );
- fixed_t in_1 = FROM_FIXED( in [offset] [1] );
-
- BLIP_CLAMP( in_0, in_0 );
- out [offset] [0] = (blip_sample_t) in_0;
-
- BLIP_CLAMP( in_1, in_1 );
- out [offset] [1] = (blip_sample_t) in_1;
- }
- while ( ++offset );
-
- in = (stereo_fixed_t*) echo.begin();
- count = remain;
- }
- while ( remain );
- }
-}
-
+ fixed_t in_0 = FROM_FIXED(in[offset][0]);
+ fixed_t in_1 = FROM_FIXED(in[offset][1]);
+
+ BLIP_CLAMP(in_0, in_0);
+ out[offset][0] = static_cast<blip_sample_t>(in_0);
+
+ BLIP_CLAMP(in_1, in_1);
+ out[offset][1] = static_cast<blip_sample_t>(in_1);
+ } while (++offset);
+
+ in = reinterpret_cast<stereo_fixed_t *>(&this->echo[0]);
+ count = remain;
+ } while (remain);
+}
+
--- a/src/in_gsf/vbam/apu/Effects_Buffer.h
+++ b/src/in_gsf/vbam/apu/Effects_Buffer.h
@@ -4,15 +4,17 @@
#ifndef EFFECTS_BUFFER_H
#define EFFECTS_BUFFER_H
+#include <vector>
#include "Multi_Buffer.h"
// See Simple_Effects_Buffer (below) for a simpler interface
-class Effects_Buffer : public Multi_Buffer {
+class Effects_Buffer : public Multi_Buffer
+{
public:
// To reduce memory usage, fewer buffers can be used (with a best-fit
// approach if there are too few), and maximum echo delay can be reduced
- Effects_Buffer( int max_bufs = 32, long echo_size = 24 * 1024L );
+ Effects_Buffer(int max_bufs = 32, long echo_size = 24 * 1024L);
struct pan_vol_t
{
@@ -27,12 +29,12 @@
// Current sound is echoed at adjustable left/right delay,
// with reduced treble and volume (feedback).
- float treble; // 1.0 = full treble, 0.1 = very little, 0.0 = silent
- int delay [2]; // left, right delays (msec)
+ float treble; // 1.0 = full treble, 0.1 = very little, 0.0 = silent
+ int delay [2]; // left, right delays (msec)
float feedback; // 0.0 = no echo, 0.5 = each echo half previous, 1.0 = cacophony
- pan_vol_t side_chans [2]; // left and right side channel volume and pan
+ pan_vol_t side_chans[2]; // left and right side channel volume and pan
};
- config_t& config() { return config_; }
+ config_t &config() { return this->config_; }
// Limits of delay (msec)
int min_delay() const;
@@ -43,29 +45,28 @@
struct chan_config_t : pan_vol_t
{
// (inherited from pan_vol_t)
- //float vol; // these only affect center channel
+ //float vol; // these only affect center channel
//float pan;
- bool surround; // if true, negates left volume to put sound in back
- bool echo; // false = channel doesn't have any echo
+ bool surround; // if true, negates left volume to put sound in back
+ bool echo; // false = channel doesn't have any echo
};
- chan_config_t& chan_config( int i ) { return chans [i + extra_chans].cfg; }
+ chan_config_t &chan_config(int i) { return this->chans[i + extra_chans].cfg; }
// Apply any changes made to config() and chan_config()
virtual void apply_config();
-public:
~Effects_Buffer();
- blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length );
- blargg_err_t set_channel_count( int, int const* = 0 );
- void clock_rate( long );
- void bass_freq( int );
+ blargg_err_t set_sample_rate(long samples_per_sec, int msec = blip_default_length);
+ blargg_err_t set_channel_count(int, const int * = nullptr);
+ void clock_rate(long);
+ void bass_freq(int);
void clear();
- channel_t channel( int );
- void end_frame( blip_time_t );
- long read_samples( blip_sample_t*, long );
- long samples_avail() const { return (bufs [0].samples_avail() - mixer.samples_read) * 2; }
+ channel_t channel(int);
+ void end_frame(blip_time_t);
+ long read_samples(blip_sample_t *, long);
+ long samples_avail() const { return (this->bufs[0]->samples_avail() - this->mixer.samples_read) * 2; }
enum { stereo = 2 };
- typedef blargg_long fixed_t;
+ typedef int32_t fixed_t;
protected:
enum { extra_chans = stereo * stereo };
private:
@@ -73,7 +74,7 @@
long clock_rate_;
int bass_freq_;
- blargg_long echo_size;
+ int32_t echo_size;
struct chan_t
{
@@ -81,54 +82,51 @@
chan_config_t cfg;
channel_t channel;
};
- blargg_vector<chan_t> chans;
+ std::vector<chan_t> chans;
struct buf_t : Tracked_Blip_Buffer
{
- fixed_t vol [stereo];
+ fixed_t vol[stereo];
bool echo;
-
- void* operator new ( size_t, void* p ) { return p; }
- void operator delete ( void* ) { }
-
- ~buf_t() { }
};
- buf_t* bufs;
+ std::vector<std::unique_ptr<buf_t>> bufs;
int bufs_size;
int bufs_max; // bufs_size <= bufs_max, to limit memory usage
Stereo_Mixer mixer;
- struct {
- long delay [stereo];
+ struct
+ {
+ long delay[stereo];
fixed_t treble;
fixed_t feedback;
- fixed_t low_pass [stereo];
+ fixed_t low_pass[stereo];
} s;
- blargg_vector<fixed_t> echo;
- blargg_long echo_pos;
+ std::vector<fixed_t> echo;
+ int32_t echo_pos;
bool no_effects;
bool no_echo;
void assign_buffers();
void clear_echo();
- void mix_effects( blip_sample_t* out, int pair_count );
- blargg_err_t new_bufs( int size );
+ void mix_effects(blip_sample_t *out, int pair_count);
+ blargg_err_t new_bufs(int size);
void delete_bufs();
};
// Simpler interface and lower memory usage
-class Simple_Effects_Buffer : public Effects_Buffer {
+class Simple_Effects_Buffer : public Effects_Buffer
+{
public:
struct config_t
{
- bool enabled; // false = disable all effects
- float echo; // 0.0 = none, 1.0 = lots
- float stereo; // 0.0 = channels in center, 1.0 = channels on left/right
- bool surround; // true = put some channels in back
+ bool enabled; // false = disable all effects
+ float echo; // 0.0 = none, 1.0 = lots
+ float stereo; // 0.0 = channels in center, 1.0 = channels on left/right
+ bool surround; // true = put some channels in back
};
- config_t& config() { return config_; }
+ config_t &config() { return this->config_; }
// Apply any changes made to config()
void apply_config();
--- a/src/in_gsf/vbam/apu/Gb_Apu.cpp
+++ b/src/in_gsf/vbam/apu/Gb_Apu.cpp
@@ -1,5 +1,6 @@
// Gb_Snd_Emu 0.2.0. http://www.slack.net/~ant/
+#include <algorithm>
#include "Gb_Apu.h"
/* Copyright (C) 2003-2007 Shay Green. This module is free software; you
@@ -15,379 +16,370 @@
#include "blargg_source.h"
-unsigned const vol_reg = 0xFF24;
-unsigned const stereo_reg = 0xFF25;
-unsigned const status_reg = 0xFF26;
-unsigned const wave_ram = 0xFF30;
-
-int const power_mask = 0x80;
-
-void Gb_Apu::treble_eq( blip_eq_t const& eq )
-{
- good_synth.treble_eq( eq );
- med_synth .treble_eq( eq );
-}
-
-inline int Gb_Apu::calc_output( int osc ) const
-{
- int bits = regs [stereo_reg - start_addr] >> osc;
- return (bits >> 3 & 2) | (bits & 1);
-}
-
-void Gb_Apu::set_output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right, int osc )
+static const unsigned vol_reg = 0xFF24;
+static const unsigned stereo_reg = 0xFF25;
+static const unsigned status_reg = 0xFF26;
+static const unsigned wave_ram = 0xFF30;
+
+static const int power_mask = 0x80;
+
+void Gb_Apu::treble_eq(const blip_eq_t &eq)
+{
+ this->good_synth.treble_eq(eq);
+ this->med_synth.treble_eq(eq);
+}
+
+int Gb_Apu::calc_output(int osc) const
+{
+ int bits = this->regs[stereo_reg - start_addr] >> osc;
+ return ((bits >> 3) & 2) | (bits & 1);
+}
+
+void Gb_Apu::set_output(Blip_Buffer *center, Blip_Buffer *left, Blip_Buffer *right, int osc)
{
// Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
- require( !center || (center && !left && !right) || (center && left && right) );
- require( (unsigned) osc <= osc_count ); // fails if you pass invalid osc index
-
- if ( !center || !left || !right )
- {
- left = center;
- right = center;
- }
-
- int i = (unsigned) osc % osc_count;
+ assert(!center || (center && !left && !right) || (center && left && right));
+ assert(static_cast<unsigned>(osc) <= osc_count); // fails if you pass invalid osc index
+
+ if (!center || !left || !right)
+ left = right = center;
+
+ int i = static_cast<unsigned>(osc) % osc_count;
do
{
- Gb_Osc& o = *oscs [i];
- o.outputs [1] = right;
- o.outputs [2] = left;
- o.outputs [3] = center;
- o.output = o.outputs [calc_output( i )];
- }
- while ( ++i < osc );
-}
-
-void Gb_Apu::synth_volume( int iv )
-{
- double v = volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
- good_synth.volume( v );
- med_synth .volume( v );
+ auto &o = *this->oscs[i];
+ o.outputs[1] = right;
+ o.outputs[2] = left;
+ o.outputs[3] = center;
+ o.output = o.outputs[this->calc_output(i)];
+ } while (++i < osc);
+}
+
+void Gb_Apu::synth_volume(int iv)
+{
+ double v = this->volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
+ this->good_synth.volume(v);
+ this->med_synth.volume(v);
}
void Gb_Apu::apply_volume()
{
// TODO: Doesn't handle differing left and right volumes (panning).
// Not worth the complexity.
- int data = regs [vol_reg - start_addr];
- int left = data >> 4 & 7;
+ int data = this->regs[vol_reg - start_addr];
+ int left = (data >> 4) & 7;
int right = data & 7;
//if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
//if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
- synth_volume( max( left, right ) + 1 );
-}
-
-void Gb_Apu::volume( double v )
-{
- if ( volume_ != v )
- {
- volume_ = v;
- apply_volume();
+ this->synth_volume(std::max(left, right) + 1);
+}
+
+void Gb_Apu::volume(double v)
+{
+ if (volume_ != v)
+ {
+ this->volume_ = v;
+ this->apply_volume();
}
}
void Gb_Apu::reset_regs()
{
- for ( int i = 0; i < 0x20; i++ )
- regs [i] = 0;
-
- square1.reset();
- square2.reset();
- wave .reset();
- noise .reset();
-
- apply_volume();
+ for (int i = 0; i < 0x20; ++i)
+ this->regs[i] = 0;
+
+ this->square1.reset();
+ this->square2.reset();
+ this->wave.reset();
+ this->noise.reset();
+
+ this->apply_volume();
}
void Gb_Apu::reset_lengths()
{
- square1.length_ctr = 64;
- square2.length_ctr = 64;
- wave .length_ctr = 256;
- noise .length_ctr = 64;
-}
-
-void Gb_Apu::reduce_clicks( bool reduce )
-{
- reduce_clicks_ = reduce;
+ this->square1.length_ctr = 64;
+ this->square2.length_ctr = 64;
+ this->wave.length_ctr = 256;
+ this->noise.length_ctr = 64;
+}
+
+void Gb_Apu::reduce_clicks(bool reduce)
+{
+ this->reduce_clicks_ = reduce;
// Click reduction makes DAC off generate same output as volume 0
int dac_off_amp = 0;
- if ( reduce && wave.mode != mode_agb ) // AGB already eliminates clicks
+ if (reduce && this->wave.mode != mode_agb) // AGB already eliminates clicks
dac_off_amp = -Gb_Osc::dac_bias;
- for ( int i = 0; i < osc_count; i++ )
- oscs [i]->dac_off_amp = dac_off_amp;
+ for (int i = 0; i < osc_count; ++i)
+ this->oscs[i]->dac_off_amp = dac_off_amp;
// AGB always eliminates clicks on wave channel using same method
- if ( wave.mode == mode_agb )
- wave.dac_off_amp = -Gb_Osc::dac_bias;
-}
-
-void Gb_Apu::reset( mode_t mode, bool agb_wave )
+ if (wave.mode == mode_agb)
+ this->wave.dac_off_amp = -Gb_Osc::dac_bias;
+}
+
+void Gb_Apu::reset(mode_t mode, bool agb_wave)
{
// Hardware mode
- if ( agb_wave )
+ if (agb_wave)
mode = mode_agb; // using AGB wave features implies AGB hardware
- wave.agb_mask = agb_wave ? 0xFF : 0;
- for ( int i = 0; i < osc_count; i++ )
- oscs [i]->mode = mode;
- reduce_clicks( reduce_clicks_ );
+ this->wave.agb_mask = agb_wave ? 0xFF : 0;
+ for (int i = 0; i < osc_count; ++i)
+ this->oscs[i]->mode = mode;
+ this->reduce_clicks(this->reduce_clicks_);
// Reset state
- frame_time = 0;
- last_time = 0;
- frame_phase = 0;
-
- reset_regs();
- reset_lengths();
+ this->frame_time = 0;
+ this->last_time = 0;
+ this->frame_phase = 0;
+
+ this->reset_regs();
+ this->reset_lengths();
// Load initial wave RAM
- static byte const initial_wave [2] [16] = {
- {0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
- {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
+ static const uint8_t initial_wave[][16] =
+ {
+ { 0x84, 0x40, 0x43, 0xAA, 0x2D, 0x78, 0x92, 0x3C, 0x60, 0x59, 0x59, 0xB0, 0x34, 0xB8, 0x2E, 0xDA },
+ { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF }
};
- for ( int b = 2; --b >= 0; )
+ for (int b = 2; --b >= 0; )
{
// Init both banks (does nothing if not in AGB mode)
// TODO: verify that this works
- write_register( 0, 0xFF1A, b * 0x40 );
- for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ )
- write_register( 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] );
- }
-}
-
-void Gb_Apu::set_tempo( double t )
-{
- frame_period = 4194304 / 512; // 512 Hz
- if ( t != 1.0 )
- frame_period = blip_time_t (frame_period / t);
+ this->write_register(0, 0xFF1A, b * 0x40);
+ for (unsigned i = 0; i < sizeof(initial_wave[0]); ++i)
+ this->write_register(0, i + wave_ram, initial_wave[mode != mode_dmg][i]);
+ }
+}
+
+void Gb_Apu::set_tempo(double t)
+{
+ this->frame_period = 4194304 / 512; // 512 Hz
+ if (t != 1.0)
+ this->frame_period = static_cast<blip_time_t>(this->frame_period / t);
}
Gb_Apu::Gb_Apu()
{
- wave.wave_ram = ®s [wave_ram - start_addr];
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &wave;
- oscs [3] = &noise;
-
- for ( int i = osc_count; --i >= 0; )
- {
- Gb_Osc& o = *oscs [i];
- o.regs = ®s [i * 5];
- o.output = 0;
- o.outputs [0] = 0;
- o.outputs [1] = 0;
- o.outputs [2] = 0;
- o.outputs [3] = 0;
- o.good_synth = &good_synth;
- o.med_synth = &med_synth;
- }
-
- reduce_clicks_ = false;
- set_tempo( 1.0 );
- volume_ = 1.0;
- reset();
-}
-
-void Gb_Apu::run_until_( blip_time_t end_time )
-{
- while ( true )
+ this->wave.wave_ram = &this->regs[wave_ram - start_addr];
+
+ this->oscs [0] = &this->square1;
+ this->oscs [1] = &this->square2;
+ this->oscs [2] = &this->wave;
+ this->oscs [3] = &this->noise;
+
+ for (int i = osc_count; --i >= 0; )
+ {
+ auto &o = *this->oscs[i];
+ o.regs = &this->regs[i * 5];
+ o.output = nullptr;
+ o.outputs[0] = nullptr;
+ o.outputs[1] = nullptr;
+ o.outputs[2] = nullptr;
+ o.outputs[3] = nullptr;
+ o.good_synth = &this->good_synth;
+ o.med_synth = &this->med_synth;
+ }
+
+ this->reduce_clicks_ = false;
+ this->set_tempo(1.0);
+ this->volume_ = 1.0;
+ this->reset();
+}
+
+void Gb_Apu::run_until_(blip_time_t end_time)
+{
+ while (1)
{
// run oscillators
blip_time_t time = end_time;
- if ( time > frame_time )
- time = frame_time;
-
- square1.run( last_time, time );
- square2.run( last_time, time );
- wave .run( last_time, time );
- noise .run( last_time, time );
- last_time = time;
-
- if ( time == end_time )
+ if (time > this->frame_time)
+ time = this->frame_time;
+
+ this->square1.run(last_time, time);
+ this->square2.run(last_time, time);
+ this->wave.run(last_time, time);
+ this->noise.run(last_time, time);
+ this->last_time = time;
+
+ if (time == end_time)
break;
// run frame sequencer
- frame_time += frame_period * Gb_Osc::clk_mul;
- switch ( frame_phase++ )
- {
- case 2:
- case 6:
- // 128 Hz
- square1.clock_sweep();
- case 0:
- case 4:
- // 256 Hz
- square1.clock_length();
- square2.clock_length();
- wave .clock_length();
- noise .clock_length();
- break;
-
- case 7:
- // 64 Hz
- frame_phase = 0;
- square1.clock_envelope();
- square2.clock_envelope();
- noise .clock_envelope();
- }
- }
-}
-
-inline void Gb_Apu::run_until( blip_time_t time )
-{
- require( time >= last_time ); // end_time must not be before previous time
- if ( time > last_time )
- run_until_( time );
-}
-
-void Gb_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- frame_time -= end_time;
- assert( frame_time >= 0 );
-
- last_time -= end_time;
- assert( last_time >= 0 );
-}
-
-void Gb_Apu::silence_osc( Gb_Osc& o )
+ this->frame_time += this->frame_period * Gb_Osc::clk_mul;
+ switch (this->frame_phase++)
+ {
+ case 2:
+ case 6:
+ // 128 Hz
+ this->square1.clock_sweep();
+ case 0:
+ case 4:
+ // 256 Hz
+ this->square1.clock_length();
+ this->square2.clock_length();
+ this->wave.clock_length();
+ this->noise.clock_length();
+ break;
+ case 7:
+ // 64 Hz
+ this->frame_phase = 0;
+ this->square1.clock_envelope();
+ this->square2.clock_envelope();
+ this->noise.clock_envelope();
+ }
+ }
+}
+
+void Gb_Apu::run_until(blip_time_t time)
+{
+ assert(time >= this->last_time); // end_time must not be before previous time
+ if (time > this->last_time)
+ this->run_until_(time);
+}
+
+void Gb_Apu::end_frame(blip_time_t end_time)
+{
+ if (end_time > this->last_time)
+ this->run_until(end_time);
+
+ this->frame_time -= end_time;
+ assert(this->frame_time >= 0);
+
+ this->last_time -= end_time;
+ assert(this->last_time >= 0);
+}
+
+void Gb_Apu::silence_osc(Gb_Osc &o)
{
int delta = -o.last_amp;
- if ( delta )
+ if (delta)
{
o.last_amp = 0;
- if ( o.output )
+ if (o.output)
{
o.output->set_modified();
- med_synth.offset( last_time, delta, o.output );
+ this->med_synth.offset(this->last_time, delta, o.output);
}
}
}
void Gb_Apu::apply_stereo()
{
- for ( int i = osc_count; --i >= 0; )
- {
- Gb_Osc& o = *oscs [i];
- Blip_Buffer* out = o.outputs [calc_output( i )];
- if ( o.output != out )
- {
- silence_osc( o );
+ for (int i = osc_count; --i >= 0; )
+ {
+ auto &o = *this->oscs[i];
+ auto out = o.outputs[this->calc_output(i)];
+ if (o.output != out)
+ {
+ this->silence_osc(o);
o.output = out;
}
}
}
-void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
-{
- require( (unsigned) data < 0x100 );
+void Gb_Apu::write_register(blip_time_t time, unsigned addr, int data)
+{
+ assert(static_cast<unsigned>(data) < 0x100);
int reg = addr - start_addr;
- if ( (unsigned) reg >= register_count )
- {
- require( false );
+ if (static_cast<unsigned>(reg) >= register_count)
+ {
+ assert(false);
return;
}
- if ( addr < status_reg && !(regs [status_reg - start_addr] & power_mask) )
+ if (addr < status_reg && !(this->regs[status_reg - start_addr] & power_mask))
{
// Power is off
// length counters can only be written in DMG mode
- if ( wave.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) )
+ if (this->wave.mode != mode_dmg || (reg != 1 && reg != 6 && reg != 11 && reg != 16))
return;
- if ( reg < 10 )
+ if (reg < 10)
data &= 0x3F; // clear square duty
}
- run_until( time );
-
- if ( addr >= wave_ram )
- {
- wave.write( addr, data );
- }
+ this->run_until(time);
+
+ if (addr >= wave_ram)
+ this->wave.write(addr, data);
else
{
- int old_data = regs [reg];
- regs [reg] = data;
-
- if ( addr < vol_reg )
- {
+ int old_data = this->regs[reg];
+ this->regs[reg] = data;
+
+ if (addr < vol_reg)
// Oscillator
- write_osc( reg / 5, reg, old_data, data );
- }
- else if ( addr == vol_reg && data != old_data )
+ this->write_osc(reg / 5, reg, old_data, data);
+ else if (addr == vol_reg && data != old_data)
{
// Master volume
- for ( int i = osc_count; --i >= 0; )
- silence_osc( *oscs [i] );
-
- apply_volume();
- }
- else if ( addr == stereo_reg )
- {
+ for (int i = osc_count; --i >= 0; )
+ this->silence_osc(*this->oscs[i]);
+
+ this->apply_volume();
+ }
+ else if (addr == stereo_reg)
// Stereo panning
- apply_stereo();
- }
- else if ( addr == status_reg && (data ^ old_data) & power_mask )
+ this->apply_stereo();
+ else if (addr == status_reg && ((data ^ old_data) & power_mask))
{
// Power control
- frame_phase = 0;
- for ( int i = osc_count; --i >= 0; )
- silence_osc( *oscs [i] );
-
- reset_regs();
- if ( wave.mode != mode_dmg )
- reset_lengths();
-
- regs [status_reg - start_addr] = data;
- }
- }
-}
-
-int Gb_Apu::read_register( blip_time_t time, unsigned addr )
-{
- run_until( time );
+ this->frame_phase = 0;
+ for (int i = osc_count; --i >= 0; )
+ this->silence_osc(*this->oscs[i]);
+
+ this->reset_regs();
+ if (this->wave.mode != mode_dmg)
+ this->reset_lengths();
+
+ this->regs[status_reg - start_addr] = data;
+ }
+ }
+}
+
+int Gb_Apu::read_register(blip_time_t time, unsigned addr)
+{
+ this->run_until(time);
int reg = addr - start_addr;
- if ( (unsigned) reg >= register_count )
- {
- require( false );
+ if (static_cast<unsigned>(reg) >= register_count)
+ {
+ assert(false);
return 0;
}
- if ( addr >= wave_ram )
- return wave.read( addr );
+ if (addr >= wave_ram)
+ return this->wave.read(addr);
// Value read back has some bits always set
- static byte const masks [] = {
- 0x80,0x3F,0x00,0xFF,0xBF,
- 0xFF,0x3F,0x00,0xFF,0xBF,
- 0x7F,0xFF,0x9F,0xFF,0xBF,
- 0xFF,0xFF,0x00,0x00,0xBF,
- 0x00,0x00,0x70,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ static const uint8_t masks [] =
+ {
+ 0x80, 0x3F, 0x00, 0xFF, 0xBF,
+ 0xFF, 0x3F, 0x00, 0xFF, 0xBF,
+ 0x7F, 0xFF, 0x9F, 0xFF, 0xBF,
+ 0xFF, 0xFF, 0x00, 0x00, 0xBF,
+ 0x00, 0x00, 0x70,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
- int mask = masks [reg];
- if ( wave.agb_mask && (reg == 10 || reg == 12) )
+ int mask = masks[reg];
+ if (this->wave.agb_mask && (reg == 10 || reg == 12))
mask = 0x1F; // extra implemented bits in wave regs on AGB
- int data = regs [reg] | mask;
+ int data = this->regs[reg] | mask;
// Status register
- if ( addr == status_reg )
+ if (addr == status_reg)
{
data &= 0xF0;
- data |= (int) square1.enabled << 0;
- data |= (int) square2.enabled << 1;
- data |= (int) wave .enabled << 2;
- data |= (int) noise .enabled << 3;
+ data |= static_cast<int>(this->square1.enabled);
+ data |= static_cast<int>(this->square2.enabled) << 1;
+ data |= static_cast<int>(this->wave.enabled) << 2;
+ data |= static_cast<int>(this->noise.enabled) << 3;
}
return data;
@@ -395,11 +387,10 @@
int Gb_Apu::read_status()
{
- int data = 0;
- data |= (int) square1.enabled << 0;
- data |= (int) square2.enabled << 1;
- data |= (int) wave .enabled << 2;
- data |= (int) noise .enabled << 3;
+ int data = static_cast<int>(this->square1.enabled);
+ data |= static_cast<int>(this->square2.enabled) << 1;
+ data |= static_cast<int>(this->wave.enabled) << 2;
+ data |= static_cast<int>(this->noise.enabled) << 3;
return data;
}
--- a/src/in_gsf/vbam/apu/Gb_Apu.h
+++ b/src/in_gsf/vbam/apu/Gb_Apu.h
@@ -6,11 +6,10 @@
#include "Gb_Oscs.h"
-struct gb_apu_state_t;
-
-class Gb_Apu {
+class Gb_Apu
+{
public:
-// Basics
+ // Basics
// Clock rate that sound hardware runs at.
enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
@@ -19,156 +18,107 @@
// If all are NULL, no output is generated but other emulation still runs.
// If chan is specified, only that channel's output is changed, otherwise all are.
enum { osc_count = 4 }; // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
- void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL,
- int chan = osc_count );
+ void set_output(Blip_Buffer *center, Blip_Buffer *left = nullptr, Blip_Buffer *right = nullptr, int chan = osc_count);
// Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects
// sound hardware. Additional AGB wave features are enabled separately.
- enum mode_t {
- mode_dmg, // Game Boy monochrome
- mode_cgb, // Game Boy Color
- mode_agb // Game Boy Advance
+ enum mode_t
+ {
+ mode_dmg, // Game Boy monochrome
+ mode_cgb, // Game Boy Color
+ mode_agb // Game Boy Advance
};
- void reset( mode_t mode = mode_cgb, bool agb_wave = false );
+ void reset(mode_t mode = mode_cgb, bool agb_wave = false);
// Reads and writes must be within the start_addr to end_addr range, inclusive.
// Addresses outside this range are not mapped to the sound hardware.
enum { start_addr = 0xFF10 };
- enum { end_addr = 0xFF3F };
+ enum { end_addr = 0xFF3F };
enum { register_count = end_addr - start_addr + 1 };
// Times are specified as the number of clocks since the beginning of the
// current time frame.
// Emulates CPU write of data to addr at specified time.
- void write_register( blip_time_t time, unsigned addr, int data );
+ void write_register(blip_time_t time, unsigned addr, int data);
// Emulates CPU read from addr at specified time.
- int read_register( blip_time_t time, unsigned addr );
+ int read_register(blip_time_t time, unsigned addr);
// Emulates sound hardware up to specified time, ends current time frame, then
// starts a new frame at time 0.
- void end_frame( blip_time_t frame_length );
+ void end_frame(blip_time_t frame_length);
-// Sound adjustments
+ // Sound adjustments
// Sets overall volume, where 1.0 is normal.
- void volume( double );
+ void volume(double);
// If true, reduces clicking by disabling DAC biasing. Note that this reduces
// emulation accuracy, since the clicks are authentic.
- void reduce_clicks( bool reduce = true );
+ void reduce_clicks(bool reduce = true);
// Sets treble equalization.
- void treble_eq( blip_eq_t const& );
+ void treble_eq(const blip_eq_t &);
// Treble and bass values for various hardware.
- enum {
+ enum
+ {
speaker_treble = -47, // speaker on system
- speaker_bass = 2000,
- dmg_treble = 0, // headphones on each system
- dmg_bass = 30,
- cgb_treble = 0,
- cgb_bass = 300, // CGB has much less bass
- agb_treble = 0,
- agb_bass = 30
+ speaker_bass = 2000,
+ dmg_treble = 0, // headphones on each system
+ dmg_bass = 30,
+ cgb_treble = 0,
+ cgb_bass = 300, // CGB has much less bass
+ agb_treble = 0,
+ agb_bass = 30
};
// Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the
// tempo in a game music player.
- void set_tempo( double );
+ void set_tempo(double);
-public:
Gb_Apu();
-
- // Use set_output() in place of these
- BLARGG_DEPRECATED void output ( Blip_Buffer* c ) { set_output( c, c, c ); }
- BLARGG_DEPRECATED void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); }
- BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c ) { set_output( c, c, c, i ); }
- BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r, i ); }
private:
// noncopyable
- Gb_Apu( const Gb_Apu& );
- Gb_Apu& operator = ( const Gb_Apu& );
+ Gb_Apu(const Gb_Apu &);
+ Gb_Apu &operator=(const Gb_Apu &);
- Gb_Osc* oscs [osc_count];
- blip_time_t last_time; // time sound emulator has been run to
- blip_time_t frame_period; // clocks between each frame sequencer step
- double volume_;
- bool reduce_clicks_;
+ Gb_Osc *oscs[osc_count];
+ blip_time_t last_time; // time sound emulator has been run to
+ blip_time_t frame_period; // clocks between each frame sequencer step
+ double volume_;
+ bool reduce_clicks_;
Gb_Sweep_Square square1;
- Gb_Square square2;
- Gb_Wave wave;
- Gb_Noise noise;
- blip_time_t frame_time; // time of next frame sequencer action
- int frame_phase; // phase of next frame sequencer step
+ Gb_Square square2;
+ Gb_Wave wave;
+ Gb_Noise noise;
+ blip_time_t frame_time; // time of next frame sequencer action
+ int frame_phase; // phase of next frame sequencer step
enum { regs_size = register_count + 0x10 };
- BOOST::uint8_t regs [regs_size];// last values written to registers
+ uint8_t regs[regs_size];// last values written to registers
// large objects after everything else
- Gb_Osc::Good_Synth good_synth;
- Gb_Osc::Med_Synth med_synth;
+ Gb_Osc::Good_Synth good_synth;
+ Gb_Osc::Med_Synth med_synth;
void reset_lengths();
void reset_regs();
- int calc_output( int osc ) const;
+ int calc_output(int osc) const;
void apply_stereo();
void apply_volume();
- void synth_volume( int );
- void run_until_( blip_time_t );
- void run_until( blip_time_t );
- void silence_osc( Gb_Osc& );
- void write_osc( int index, int reg, int old_data, int data );
+ void synth_volume(int);
+ void run_until_(blip_time_t);
+ void run_until(blip_time_t);
+ void silence_osc(Gb_Osc &);
+ void write_osc(int index, int reg, int old_data, int data);
friend class Gb_Apu_Tester;
public:
int read_status();
};
-// Format of save state. Should be stable across versions of the library,
-// with earlier versions properly opening later save states. Includes some
-// room for expansion so the state size shouldn't increase.
-struct gb_apu_state_t
-{
-#if GB_APU_CUSTOM_STATE
- // Values stored as plain int so your code can read/write them easily.
- // Structure can NOT be written to disk, since format is not portable.
- typedef int val_t;
-#else
- // Values written in portable little-endian format, allowing structure
- // to be written directly to disk.
- typedef unsigned char val_t [4];
#endif
- enum { format0 = 0x50414247 };
-
- val_t format; // format of all following data
- val_t version; // later versions just add fields to end
-
- unsigned char regs [0x40];
- val_t frame_time;
- val_t frame_phase;
-
- val_t sweep_freq;
- val_t sweep_delay;
- val_t sweep_enabled;
- val_t sweep_neg;
- val_t noise_divider;
- val_t wave_buf;
-
- val_t delay [4];
- val_t length_ctr [4];
- val_t phase [4];
- val_t enabled [4];
-
- val_t env_delay [3];
- val_t env_volume [3];
- val_t env_enabled [3];
-
- val_t unused [13]; // for future expansion
-};
-
-#endif
-
--- a/src/in_gsf/vbam/apu/Gb_Oscs.cpp
+++ b/src/in_gsf/vbam/apu/Gb_Oscs.cpp
@@ -15,29 +15,29 @@
#include "blargg_source.h"
-bool const cgb_02 = false; // enables bug in early CGB units that causes problems in some games
-bool const cgb_05 = false; // enables CGB-05 zombie behavior
-
-int const trigger_mask = 0x80;
-int const length_enabled = 0x40;
+static const bool cgb_02 = false; // enables bug in early CGB units that causes problems in some games
+static const bool cgb_05 = false; // enables CGB-05 zombie behavior
+
+static const int trigger_mask = 0x80;
+static const int length_enabled = 0x40;
void Gb_Osc::reset()
{
- output = 0;
- last_amp = 0;
- delay = 0;
- phase = 0;
- enabled = false;
-}
-
-inline void Gb_Osc::update_amp( blip_time_t time, int new_amp )
-{
- output->set_modified();
- int delta = new_amp - last_amp;
- if ( delta )
- {
- last_amp = new_amp;
- med_synth->offset( time, delta, output );
+ this->output = nullptr;
+ this->last_amp = 0;
+ this->delay = 0;
+ this->phase = 0;
+ this->enabled = false;
+}
+
+void Gb_Osc::update_amp(blip_time_t time, int new_amp)
+{
+ this->output->set_modified();
+ int delta = new_amp - this->last_amp;
+ if (delta)
+ {
+ this->last_amp = new_amp;
+ this->med_synth->offset(time, delta, this->output);
}
}
@@ -45,81 +45,79 @@
void Gb_Osc::clock_length()
{
- if ( (regs [4] & length_enabled) && length_ctr )
- {
- if ( --length_ctr <= 0 )
- enabled = false;
+ if ((this->regs [4] & length_enabled) && this->length_ctr)
+ {
+ if (--this->length_ctr <= 0)
+ this->enabled = false;
}
}
inline int Gb_Env::reload_env_timer()
{
- int raw = regs [2] & 7;
- env_delay = (raw ? raw : 8);
+ int raw = this->regs[2] & 7;
+ this->env_delay = raw ? raw : 8;
return raw;
}
void Gb_Env::clock_envelope()
{
- if ( env_enabled && --env_delay <= 0 && reload_env_timer() )
- {
- int v = volume + (regs [2] & 0x08 ? +1 : -1);
- if ( 0 <= v && v <= 15 )
- volume = v;
+ if (this->env_enabled && --this->env_delay <= 0 && this->reload_env_timer())
+ {
+ int v = this->volume + (this->regs[2] & 0x08 ? 1 : -1);
+ if (0 <= v && v <= 15)
+ this->volume = v;
else
- env_enabled = false;
- }
-}
-
-inline void Gb_Sweep_Square::reload_sweep_timer()
-{
- sweep_delay = (regs [0] & period_mask) >> 4;
- if ( !sweep_delay )
- sweep_delay = 8;
-}
-
-void Gb_Sweep_Square::calc_sweep( bool update )
-{
- int const shift = regs [0] & shift_mask;
- int const delta = sweep_freq >> shift;
- sweep_neg = (regs [0] & 0x08) != 0;
- int const freq = sweep_freq + (sweep_neg ? -delta : delta);
-
- if ( freq > 0x7FF )
- {
- enabled = false;
- }
- else if ( shift && update )
- {
- sweep_freq = freq;
-
- regs [3] = freq & 0xFF;
- regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07);
+ this->env_enabled = false;
+ }
+}
+
+void Gb_Sweep_Square::reload_sweep_timer()
+{
+ this->sweep_delay = (this->regs[0] & period_mask) >> 4;
+ if (!this->sweep_delay)
+ this->sweep_delay = 8;
+}
+
+void Gb_Sweep_Square::calc_sweep(bool update)
+{
+ int shift = this->regs[0] & shift_mask;
+ int delta = this->sweep_freq >> shift;
+ this->sweep_neg = !!(this->regs[0] & 0x08);
+ int freq = this->sweep_freq + (this->sweep_neg ? -delta : delta);
+
+ if (freq > 0x7FF)
+ this->enabled = false;
+ else if (shift && update)
+ {
+ this->sweep_freq = freq;
+
+ this->regs[3] = freq & 0xFF;
+ this->regs[4] = (this->regs[4] & ~0x07) | ((freq >> 8) & 0x07);
}
}
void Gb_Sweep_Square::clock_sweep()
{
- if ( --sweep_delay <= 0 )
- {
- reload_sweep_timer();
- if ( sweep_enabled && (regs [0] & period_mask) )
- {
- calc_sweep( true );
- calc_sweep( false );
- }
- }
-}
-
-int Gb_Wave::access( unsigned addr ) const
-{
- if ( enabled && mode != Gb_Apu::mode_agb )
- {
- addr = phase & (bank_size - 1);
- if ( mode == Gb_Apu::mode_dmg )
- {
- addr++;
- if ( delay > clk_mul )
+ if (--this->sweep_delay <= 0)
+ {
+ this->reload_sweep_timer();
+ if (this->sweep_enabled && (this->regs[0] & period_mask))
+ {
+ this->calc_sweep(true);
+ this->calc_sweep(false);
+ }
+ }
+}
+
+int Gb_Wave::access(unsigned addr) const
+{
+ if (this->enabled && this->mode != Gb_Apu::mode_agb)
+ {
+ addr = this->phase & (bank_size - 1);
+ if (this->mode == Gb_Apu::mode_dmg)
+ {
+ ++addr;
+ if (this->delay > clk_mul)
return -1; // can only access within narrow time window while playing
}
addr >>= 1;
@@ -129,205 +127,209 @@
// write_register
-int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data )
-{
- int data = regs [4];
-
- if ( (frame_phase & 1) && !(old_data & length_enabled) && length_ctr )
- {
- if ( (data & length_enabled) || cgb_02 )
- length_ctr--;
- }
-
- if ( data & trigger_mask )
- {
- enabled = true;
- if ( !length_ctr )
- {
- length_ctr = max_len;
- if ( (frame_phase & 1) && (data & length_enabled) )
- length_ctr--;
- }
- }
-
- if ( !length_ctr )
- enabled = false;
+int Gb_Osc::write_trig(int frame_phase, int max_len, int old_data)
+{
+ int data = this->regs[4];
+
+ if ((frame_phase & 1) && !(old_data & length_enabled) && this->length_ctr)
+ {
+ if ((data & length_enabled) || cgb_02)
+ --this->length_ctr;
+ }
+
+ if (data & trigger_mask)
+ {
+ this->enabled = true;
+ if (!this->length_ctr)
+ {
+ this->length_ctr = max_len;
+ if ((frame_phase & 1) && (data & length_enabled))
+ --this->length_ctr;
+ }
+ }
+
+ if (!this->length_ctr)
+ this->enabled = false;
return data & trigger_mask;
}
-inline void Gb_Env::zombie_volume( int old, int data )
-{
- int v = volume;
- if ( mode == Gb_Apu::mode_agb || cgb_05 )
+inline void Gb_Env::zombie_volume(int old, int data)
+{
+ int v = this->volume;
+ if (this->mode == Gb_Apu::mode_agb || cgb_05)
{
// CGB-05 behavior, very close to AGB behavior as well
- if ( (old ^ data) & 8 )
- {
- if ( !(old & 8) )
- {
- v++;
- if ( old & 7 )
- v++;
+ if ((old ^ data) & 8)
+ {
+ if (!(old & 8))
+ {
+ ++v;
+ if (old & 7)
+ ++v;
}
v = 16 - v;
}
- else if ( (old & 0x0F) == 8 )
- {
- v++;
- }
+ else if ((old & 0x0F) == 8)
+ ++v;
}
else
{
// CGB-04&02 behavior, very close to MGB behavior as well
- if ( !(old & 7) && env_enabled )
- v++;
- else if ( !(old & 8) )
+ if (!(old & 7) && this->env_enabled)
+ ++v;
+ else if (!(old & 8))
v += 2;
- if ( (old ^ data) & 8 )
+ if ((old ^ data) & 8)
v = 16 - v;
}
- volume = v & 0x0F;
+ this->volume = v & 0x0F;
}
bool Gb_Env::write_register( int frame_phase, int reg, int old, int data )
{
- int const max_len = 64;
-
- switch ( reg )
- {
- case 1:
- length_ctr = max_len - (data & (max_len - 1));
- break;
-
- case 2:
- if ( !dac_enabled() )
- enabled = false;
-
- zombie_volume( old, data );
-
- if ( (data & 7) && env_delay == 8 )
- {
- env_delay = 1;
- clock_envelope(); // TODO: really happens at next length clock
- }
- break;
-
- case 4:
- if ( write_trig( frame_phase, max_len, old ) )
- {
- volume = regs [2] >> 4;
- reload_env_timer();
- env_enabled = true;
- if ( frame_phase == 7 )
- env_delay++;
- if ( !dac_enabled() )
- enabled = false;
- return true;
- }
+ static const int max_len = 64;
+
+ switch (reg)
+ {
+ case 1:
+ this->length_ctr = max_len - (data & (max_len - 1));
+ break;
+
+ case 2:
+ if (!this->dac_enabled())
+ this->enabled = false;
+
+ this->zombie_volume(old, data);
+
+ if ((data & 7) && this->env_delay == 8)
+ {
+ this->env_delay = 1;
+ this->clock_envelope(); // TODO: really happens at next length clock
+ }
+ break;
+
+ case 4:
+ if (this->write_trig(frame_phase, max_len, old))
+ {
+ this->volume = this->regs[2] >> 4;
+ this->reload_env_timer();
+ this->env_enabled = true;
+ if (frame_phase == 7)
+ ++this->env_delay;
+ if (!this->dac_enabled())
+ this->enabled = false;
+ return true;
+ }
}
return false;
}
-bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data )
-{
- bool result = Gb_Env::write_register( frame_phase, reg, old_data, data );
- if ( result )
- delay = (delay & (4 * clk_mul - 1)) + period();
+bool Gb_Square::write_register(int frame_phase, int reg, int old_data, int data)
+{
+ bool result = Gb_Env::write_register(frame_phase, reg, old_data, data);
+ if (result)
+ this->delay = (this->delay & (4 * clk_mul - 1)) + this->period();
return result;
}
inline void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data )
{
- if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) )
- {
- phase = 0x7FFF;
- delay += 8 * clk_mul;
- }
-}
-
-inline void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data )
-{
- if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) )
- enabled = false; // sweep negate disabled after used
-
- if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) )
- {
- sweep_freq = frequency();
- sweep_neg = false;
- reload_sweep_timer();
- sweep_enabled = (regs [0] & (period_mask | shift_mask)) != 0;
- if ( regs [0] & shift_mask )
- calc_sweep( false );
+ if (Gb_Env::write_register(frame_phase, reg, old_data, data))
+ {
+ this->phase = 0x7FFF;
+ this->delay += 8 * clk_mul;
+ }
+}
+
+inline void Gb_Sweep_Square::write_register(int frame_phase, int reg, int old_data, int data)
+{
+ if (!reg && this->sweep_enabled && this->sweep_neg && !(data & 0x08))
+ this->enabled = false; // sweep negate disabled after used
+
+ if (Gb_Square::write_register(frame_phase, reg, old_data, data))
+ {
+ this->sweep_freq = this->frequency();
+ this->sweep_neg = false;
+ this->reload_sweep_timer();
+ this->sweep_enabled = !!(this->regs[0] & (period_mask | shift_mask));
+ if (this->regs[0] & shift_mask)
+ this->calc_sweep(false);
}
}
void Gb_Wave::corrupt_wave()
{
- int pos = ((phase + 1) & (bank_size - 1)) >> 1;
- if ( pos < 4 )
- wave_ram [0] = wave_ram [pos];
+ int pos = ((this->phase + 1) & (bank_size - 1)) >> 1;
+ if (pos < 4)
+ this->wave_ram[0] = this->wave_ram[pos];
else
- for ( int i = 4; --i >= 0; )
- wave_ram [i] = wave_ram [(pos & ~3) + i];
-}
-
-inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data )
-{
- int const max_len = 256;
-
- switch ( reg )
- {
- case 0:
- if ( !dac_enabled() )
- enabled = false;
- break;
-
- case 1:
- length_ctr = max_len - data;
- break;
-
- case 4:
- bool was_enabled = enabled;
- if ( write_trig( frame_phase, max_len, old_data ) )
- {
- if ( !dac_enabled() )
- enabled = false;
- else if ( mode == Gb_Apu::mode_dmg && was_enabled &&
- (unsigned) (delay - 2 * clk_mul) < 2 * clk_mul )
- corrupt_wave();
-
- phase = 0;
- delay = period() + 6 * clk_mul;
- }
- }
-}
-
-void Gb_Apu::write_osc( int index, int reg, int old_data, int data )
+ for (int i = 4; --i >= 0; )
+ this->wave_ram[i] = this->wave_ram[(pos & ~3) + i];
+}
+
+inline void Gb_Wave::write_register(int frame_phase, int reg, int old_data, int data)
+{
+ static const int max_len = 256;
+
+ switch (reg)
+ {
+ case 0:
+ if (!this->dac_enabled())
+ this->enabled = false;
+ break;
+
+ case 1:
+ this->length_ctr = max_len - data;
+ break;
+
+ case 4:
+ bool was_enabled = this->enabled;
+ if (this->write_trig(frame_phase, max_len, old_data))
+ {
+ if (!this->dac_enabled())
+ this->enabled = false;
+ else if (this->mode == Gb_Apu::mode_dmg && was_enabled && static_cast<unsigned>(this->delay - 2 * clk_mul) < 2 * clk_mul)
+ this->corrupt_wave();
+
+ this->phase = 0;
+ this->delay = this->period() + 6 * clk_mul;
+ }
+ }
+}
+
+void Gb_Apu::write_osc(int index, int reg, int old_data, int data)
{
reg -= index * 5;
- switch ( index )
- {
- case 0: square1.write_register( frame_phase, reg, old_data, data ); break;
- case 1: square2.write_register( frame_phase, reg, old_data, data ); break;
- case 2: wave .write_register( frame_phase, reg, old_data, data ); break;
- case 3: noise .write_register( frame_phase, reg, old_data, data ); break;
+ switch (index)
+ {
+ case 0:
+ this->square1.write_register(this->frame_phase, reg, old_data, data);
+ break;
+ case 1:
+ this->square2.write_register(this->frame_phase, reg, old_data, data);
+ break;
+ case 2:
+ this->wave.write_register(this->frame_phase, reg, old_data, data);
+ break;
+ case 3:
+ this->noise.write_register(this->frame_phase, reg, old_data, data);
}
}
// Synthesis
-void Gb_Square::run( blip_time_t time, blip_time_t end_time )
+void Gb_Square::run(blip_time_t time, blip_time_t end_time)
{
// Calc duty and phase
- static byte const duty_offsets [4] = { 1, 1, 3, 7 };
- static byte const duties [4] = { 1, 2, 4, 6 };
- int const duty_code = regs [1] >> 6;
- int duty_offset = duty_offsets [duty_code];
- int duty = duties [duty_code];
- if ( mode == Gb_Apu::mode_agb )
+ static const uint8_t duty_offsets[] = { 1, 1, 3, 7 };
+ static const uint8_t duties[] = { 1, 2, 4, 6 };
+ int duty_code = this->regs[1] >> 6;
+ int duty_offset = duty_offsets[duty_code];
+ int duty = duties[duty_code];
+ if (this->mode == Gb_Apu::mode_agb)
{
// AGB uses inverted duty
duty_offset -= duty;
@@ -337,46 +339,46 @@
// Determine what will be generated
int vol = 0;
- Blip_Buffer* const out = this->output;
- if ( out )
- {
- int amp = dac_off_amp;
- if ( dac_enabled() )
- {
- if ( enabled )
+ auto out = this->output;
+ if (out)
+ {
+ int amp = this->dac_off_amp;
+ if (this->dac_enabled())
+ {
+ if (this->enabled)
vol = this->volume;
amp = -dac_bias;
- if ( mode == Gb_Apu::mode_agb )
+ if (this->mode == Gb_Apu::mode_agb)
amp = -(vol >> 1);
// Play inaudible frequencies as constant amplitude
- if ( frequency() >= 0x7FA && delay < 32 * clk_mul )
+ if (this->frequency() >= 0x7FA && this->delay < 32 * clk_mul)
{
amp += (vol * duty) >> 3;
vol = 0;
}
- if ( ph < duty )
+ if (ph < duty)
{
amp += vol;
vol = -vol;
}
}
- update_amp( time, amp );
+ this->update_amp(time, amp);
}
// Generate wave
- time += delay;
- if ( time < end_time )
- {
- int const per = this->period();
- if ( !vol )
+ time += this->delay;
+ if (time < end_time)
+ {
+ int per = this->period();
+ if (!vol)
{
// Maintain phase when not playing
int count = (end_time - time + per - 1) / per;
ph += count; // will be masked below
- time += (blip_time_t) count * per;
+ time += static_cast<blip_time_t>(count) * per;
}
else
{
@@ -385,35 +387,34 @@
do
{
ph = (ph + 1) & 7;
- if ( ph == 0 || ph == duty )
+ if (!ph || ph == duty)
{
- good_synth->offset_inline( time, delta, out );
+ this->good_synth->offset_inline(time, delta, out);
delta = -delta;
}
time += per;
- }
- while ( time < end_time );
-
- if ( delta != vol )
- last_amp -= delta;
+ } while (time < end_time);
+
+ if (delta != vol)
+ this->last_amp -= delta;
}
this->phase = (ph - duty_offset) & 7;
}
- delay = time - end_time;
+ this->delay = time - end_time;
}
// Quickly runs LFSR for a large number of clocks. For use when noise is generating
// no sound.
-static unsigned run_lfsr( unsigned s, unsigned mask, int count )
-{
- bool const optimized = true; // set to false to use only unoptimized loop in middle
+static unsigned run_lfsr(unsigned s, unsigned mask, int count)
+{
+ static const bool optimized = true; // set to false to use only unoptimized loop in middle
// optimization used in several places:
// ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)
- if ( mask == 0x4000 && optimized )
- {
- if ( count >= 32767 )
+ if (mask == 0x4000 && optimized)
+ {
+ if (count >= 32767)
count %= 32767;
// Convert from Fibonacci to Galois configuration,
@@ -421,35 +422,35 @@
s ^= (s & 1) * 0x8000;
// Each iteration is equivalent to clocking LFSR 255 times
- while ( (count -= 255) > 0 )
+ while ((count -= 255) > 0)
s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3);
count += 255;
// Each iteration is equivalent to clocking LFSR 15 times
// (interesting similarity to single clocking below)
- while ( (count -= 15) > 0 )
+ while ((count -= 15) > 0)
s ^= ((s & 2) * (3 << 13)) ^ (s >> 1);
count += 15;
// Remaining singles
- while ( --count >= 0 )
+ while (--count >= 0)
s = ((s & 2) * (3 << 13)) ^ (s >> 1);
// Convert back to Fibonacci configuration
s &= 0x7FFF;
}
- else if ( count < 8 || !optimized )
+ else if (count < 8 || !optimized)
{
// won't fully replace upper 8 bits, so have to do the unoptimized way
- while ( --count >= 0 )
- s = (s >> 1 | mask) ^ (mask & (0 - ((s - 1) & 2)));
+ while (--count >= 0)
+ s = ((s >> 1) | mask) ^ (mask & (0 - ((s - 1) & 2)));
}
else
{
- if ( count > 127 )
+ if (count > 127)
{
count %= 127;
- if ( !count )
+ if (!count)
count = 127; // must run at least once
}
@@ -462,40 +463,40 @@
// Each iteration is equivalent to clocking LFSR 7 times
// (interesting similarity to single clocking below)
- while ( (count -= 7) > 0 )
+ while ((count -= 7) > 0)
s ^= ((s & 4) * (3 << 5)) ^ (s >> 1);
count += 7;
// Remaining singles
- while ( --count >= 0 )
+ while (--count >= 0)
s = ((s & 4) * (3 << 5)) ^ (s >> 1);
// Convert back to Fibonacci configuration and
// repeat last 8 bits above significant 7
- s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F);
+ s = ((s << 7) & 0x7F80) | ((s >> 1) & 0x7F);
}
return s;
}
-void Gb_Noise::run( blip_time_t time, blip_time_t end_time )
+void Gb_Noise::run(blip_time_t time, blip_time_t end_time)
{
// Determine what will be generated
int vol = 0;
- Blip_Buffer* const out = this->output;
- if ( out )
- {
- int amp = dac_off_amp;
- if ( dac_enabled() )
- {
- if ( enabled )
+ auto out = this->output;
+ if (out)
+ {
+ int amp = this->dac_off_amp;
+ if (this->dac_enabled())
+ {
+ if (this->enabled)
vol = this->volume;
amp = -dac_bias;
- if ( mode == Gb_Apu::mode_agb )
+ if (this->mode == Gb_Apu::mode_agb)
amp = -(vol >> 1);
- if ( !(phase & 1) )
+ if (!(this->phase & 1))
{
amp += vol;
vol = -vol;
@@ -503,45 +504,43 @@
}
// AGB negates final output
- if ( mode == Gb_Apu::mode_agb )
+ if (this->mode == Gb_Apu::mode_agb)
{
vol = -vol;
- amp = -amp;
- }
-
- update_amp( time, amp );
+ amp = -amp;
+ }
+
+ this->update_amp(time, amp);
}
// Run timer and calculate time of next LFSR clock
- static byte const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
- int const period1 = period1s [regs [3] & 7] * clk_mul;
- {
- int extra = (end_time - time) - delay;
- int const per2 = this->period2();
- time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
+ static const uint8_t period1s[] = { 1, 2, 4, 6, 8, 10, 12, 14 };
+ int period1 = period1s[this->regs[3] & 7] * clk_mul;
+ {
+ int extra = (end_time - time) - this->delay;
+ int per2 = this->period2();
+ time += this->delay + ((this->divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1);
- divider = (divider - count) & period2_mask;
- delay = count * period1 - extra;
+ this->divider = (this->divider - count) & period2_mask;
+ this->delay = count * period1 - extra;
}
// Generate wave
- if ( time < end_time )
- {
- unsigned const mask = this->lfsr_mask();
+ if (time < end_time)
+ {
+ unsigned mask = this->lfsr_mask();
unsigned bits = this->phase;
- int per = period2( period1 * 8 );
- if ( period2_index() >= 0xE )
- {
+ int per = this->period2(period1 * 8);
+ if (this->period2_index() >= 0xE)
time = end_time;
- }
- else if ( !vol )
+ else if (!vol)
{
// Maintain phase when not playing
int count = (end_time - time + per - 1) / per;
- time += (blip_time_t) count * per;
- bits = run_lfsr( bits, ~mask, count );
+ time += static_cast<blip_time_t>(count) * per;
+ bits = run_lfsr(bits, ~mask, count);
}
else
{
@@ -550,84 +549,83 @@
do
{
unsigned changed = bits + 1;
- bits = bits >> 1 & mask;
- if ( changed & 2 )
+ bits = (bits >> 1) & mask;
+ if (changed & 2)
{
bits |= ~mask;
delta = -delta;
- med_synth->offset_inline( time, delta, out );
+ this->med_synth->offset_inline(time, delta, out);
}
time += per;
- }
- while ( time < end_time );
-
- if ( delta == vol )
- last_amp += delta;
+ } while (time < end_time);
+
+ if (delta == vol)
+ this->last_amp += delta;
}
this->phase = bits;
}
}
-void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
+void Gb_Wave::run(blip_time_t time, blip_time_t end_time)
{
// Calc volume
- static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
- int const volume_shift = 2;
- int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
- int const volume_mul = volumes [volume_idx];
+ static const uint8_t volumes[] = { 0, 4, 2, 1, 3, 3, 3, 3 };
+ static const int volume_shift = 2;
+ int volume_idx = (this->regs[2] >> 5) & (this->agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
+ int volume_mul = volumes[volume_idx];
// Determine what will be generated
int playing = false;
- Blip_Buffer* const out = this->output;
- if ( out )
+ auto out = this->output;
+ if (out)
{
int amp = dac_off_amp;
- if ( dac_enabled() )
+ if (this->dac_enabled())
{
// Play inaudible frequencies as constant amplitude
amp = 8 << 4; // really depends on average of all samples in wave
// if delay is larger, constant amplitude won't start yet
- if ( frequency() <= 0x7FB || delay > 15 * clk_mul )
- {
- if ( volume_mul )
- playing = (int) enabled;
-
- amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing;
+ if (this->frequency() <= 0x7FB || this->delay > 15 * clk_mul)
+ {
+ if (volume_mul)
+ playing = enabled;
+
+ amp = (this->sample_buf << ((this->phase << 2) & 4) & 0xF0) * playing;
}
amp = ((amp * volume_mul) >> (volume_shift + 4)) - dac_bias;
}
- update_amp( time, amp );
+ this->update_amp(time, amp);
}
// Generate wave
- time += delay;
- if ( time < end_time )
- {
- byte const* wave = this->wave_ram;
+ time += this->delay;
+ if (time < end_time)
+ {
+ auto wave = this->wave_ram;
// wave size and bank
- int const size20_mask = 0x20;
- int const flags = regs [0] & agb_mask;
- int const wave_mask = (flags & size20_mask) | 0x1F;
+ static const int size20_mask = 0x20;
+ int flags = this->regs[0] & this->agb_mask;
+ int wave_mask = (flags & size20_mask) | 0x1F;
int swap_banks = 0;
- if ( flags & bank40_mask )
+ if (flags & bank40_mask)
{
swap_banks = flags & size20_mask;
- wave += bank_size/2 - (swap_banks >> 1);
+ wave += bank_size / 2 - (swap_banks >> 1);
}
int ph = this->phase ^ swap_banks;
ph = (ph + 1) & wave_mask; // pre-advance
- int const per = this->period();
- if ( !playing )
+ int per = this->period();
+ if (!playing)
{
// Maintain phase when not playing
int count = (end_time - time + per - 1) / per;
ph += count; // will be masked below
- time += (blip_time_t) count * per;
+ time += static_cast<blip_time_t>(count) * per;
}
else
{
@@ -636,31 +634,30 @@
do
{
// Extract nybble
- int nybble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0;
+ int nybble = wave[ph >> 1] << ((ph << 2) & 4) & 0xF0;
ph = (ph + 1) & wave_mask;
// Scale by volume
int amp = (nybble * volume_mul) >> (volume_shift + 4);
int delta = amp - lamp;
- if ( delta )
+ if (delta)
{
lamp = amp;
- med_synth->offset_inline( time, delta, out );
+ this->med_synth->offset_inline(time, delta, out);
}
time += per;
- }
- while ( time < end_time );
+ } while (time < end_time);
this->last_amp = lamp - dac_bias;
}
ph = (ph - 1) & wave_mask; // undo pre-advance and mask position
// Keep track of last byte read
- if ( enabled )
- sample_buf = wave [ph >> 1];
+ if (this->enabled)
+ this->sample_buf = wave[ph >> 1];
this->phase = ph ^ swap_banks; // undo swapped banks
}
- delay = time - end_time;
-}
-
+ this->delay = time - end_time;
+}
+
--- a/src/in_gsf/vbam/apu/Gb_Oscs.h
+++ b/src/in_gsf/vbam/apu/Gb_Oscs.h
@@ -8,184 +8,185 @@
#include "Blip_Buffer.h"
#ifndef GB_APU_OVERCLOCK
- #define GB_APU_OVERCLOCK 1
+# define GB_APU_OVERCLOCK 1
#endif
#if GB_APU_OVERCLOCK & (GB_APU_OVERCLOCK - 1)
- #error "GB_APU_OVERCLOCK must be a power of 2"
+# error "GB_APU_OVERCLOCK must be a power of 2"
#endif
-class Gb_Osc {
+class Gb_Osc
+{
protected:
+ // 11-bit frequency in NRx3 and NRx4
+ int frequency() const { return (this->regs[4] & 7) * 0x100 + this->regs[3]; }
- // 11-bit frequency in NRx3 and NRx4
- int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; }
-
- void update_amp( blip_time_t, int new_amp );
- int write_trig( int frame_phase, int max_len, int old_data );
+ void update_amp(blip_time_t, int new_amp);
+ int write_trig(int frame_phase, int max_len, int old_data);
public:
-
- enum { clk_mul = GB_APU_OVERCLOCK };
+ enum { clk_mul = GB_APU_OVERCLOCK };
enum { dac_bias = 7 };
- Blip_Buffer* outputs [4];// NULL, right, left, center
- Blip_Buffer* output; // where to output sound
- BOOST::uint8_t* regs; // osc's 5 registers
- int mode; // mode_dmg, mode_cgb, mode_agb
- int dac_off_amp;// amplitude when DAC is off
- int last_amp; // current amplitude in Blip_Buffer
- typedef Blip_Synth<blip_good_quality,1> Good_Synth;
- typedef Blip_Synth<blip_med_quality ,1> Med_Synth;
- Good_Synth const* good_synth;
- Med_Synth const* med_synth;
+ Blip_Buffer *outputs[4];// NULL, right, left, center
+ Blip_Buffer *output; // where to output sound
+ uint8_t *regs; // osc's 5 registers
+ int mode; // mode_dmg, mode_cgb, mode_agb
+ int dac_off_amp; // amplitude when DAC is off
+ int last_amp; // current amplitude in Blip_Buffer
+ typedef Blip_Synth<blip_good_quality, 1> Good_Synth;
+ typedef Blip_Synth<blip_med_quality, 1> Med_Synth;
+ const Good_Synth *good_synth;
+ const Med_Synth *med_synth;
- int delay; // clocks until frequency timer expires
- int length_ctr; // length counter
- unsigned phase; // waveform phase (or equivalent)
- bool enabled; // internal enabled flag
+ int delay; // clocks until frequency timer expires
+ int length_ctr; // length counter
+ unsigned phase; // waveform phase (or equivalent)
+ bool enabled; // internal enabled flag
void clock_length();
void reset();
};
-class Gb_Env : public Gb_Osc {
+class Gb_Env : public Gb_Osc
+{
public:
- Gb_Env() : env_enabled(false), env_delay(0) {}
- int env_delay;
- int volume;
+ Gb_Env() : env_enabled(false), env_delay(0) { }
+ int env_delay;
+ int volume;
bool env_enabled;
void clock_envelope();
- bool write_register( int frame_phase, int reg, int old_data, int data );
+ bool write_register(int frame_phase, int reg, int old_data, int data);
void reset()
{
- env_delay = 0;
- volume = 0;
+ this->env_delay = 0;
+ this->volume = 0;
Gb_Osc::reset();
}
protected:
// Non-zero if DAC is enabled
- int dac_enabled() const { return regs [2] & 0xF8; }
+ int dac_enabled() const { return this->regs[2] & 0xF8; }
private:
- void zombie_volume( int old, int data );
+ void zombie_volume(int old, int data);
int reload_env_timer();
};
-class Gb_Square : public Gb_Env {
+class Gb_Square : public Gb_Env
+{
public:
- bool write_register( int frame_phase, int reg, int old_data, int data );
- void run( blip_time_t, blip_time_t );
+ bool write_register(int frame_phase, int reg, int old_data, int data);
+ void run(blip_time_t, blip_time_t);
void reset()
{
Gb_Env::reset();
- delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
+ this->delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
}
private:
// Frequency timer period
- int period() const { return (2048 - frequency()) * (4 * clk_mul); }
+ int period() const { return (2048 - this->frequency()) * (4 * clk_mul); }
};
-class Gb_Sweep_Square : public Gb_Square {
+class Gb_Sweep_Square : public Gb_Square
+{
public:
- int sweep_freq;
- int sweep_delay;
+ int sweep_freq;
+ int sweep_delay;
bool sweep_enabled;
bool sweep_neg;
void clock_sweep();
- void write_register( int frame_phase, int reg, int old_data, int data );
+ void write_register(int frame_phase, int reg, int old_data, int data);
void reset()
{
- sweep_freq = 0;
- sweep_delay = 0;
- sweep_enabled = false;
- sweep_neg = false;
+ this->sweep_freq = this->sweep_delay = 0;
+ this->sweep_enabled = this->sweep_neg = false;
Gb_Square::reset();
}
private:
enum { period_mask = 0x70 };
enum { shift_mask = 0x07 };
- void calc_sweep( bool update );
+ void calc_sweep(bool update);
void reload_sweep_timer();
};
-class Gb_Noise : public Gb_Env {
+class Gb_Noise : public Gb_Env
+{
public:
-
int divider; // noise has more complex frequency divider setup
- void run( blip_time_t, blip_time_t );
- void write_register( int frame_phase, int reg, int old_data, int data );
+ void run(blip_time_t, blip_time_t);
+ void write_register(int frame_phase, int reg, int old_data, int data);
void reset()
{
- divider = 0;
+ this->divider = 0;
Gb_Env::reset();
- delay = 4 * clk_mul; // TODO: remove?
+ this->delay = 4 * clk_mul; // TODO: remove?
}
private:
enum { period2_mask = 0x1FFFF };
- int period2_index() const { return regs [3] >> 4; }
- int period2( int base = 8 ) const { return base << period2_index(); }
- unsigned lfsr_mask() const { return (regs [3] & 0x08) ? ~0x4040 : ~0x4000; }
+ int period2_index() const { return this->regs[3] >> 4; }
+ int period2(int base = 8) const { return base << this->period2_index(); }
+ unsigned lfsr_mask() const { return (this->regs[3] & 0x08) ? ~0x4040 : ~0x4000; }
};
-class Gb_Wave : public Gb_Osc {
+class Gb_Wave : public Gb_Osc
+{
public:
int sample_buf; // last wave RAM byte read (hardware has this as well)
- void write_register( int frame_phase, int reg, int old_data, int data );
- void run( blip_time_t, blip_time_t );
+ void write_register(int frame_phase, int reg, int old_data, int data);
+ void run(blip_time_t, blip_time_t);
// Reads/writes wave RAM
- int read( unsigned addr ) const;
- void write( unsigned addr, int data );
+ int read(unsigned addr) const;
+ void write(unsigned addr, int data);
void reset()
{
- sample_buf = 0;
+ this->sample_buf = 0;
Gb_Osc::reset();
}
private:
enum { bank40_mask = 0x40 };
- enum { bank_size = 32 };
+ enum { bank_size = 32 };
- int agb_mask; // 0xFF if AGB features enabled, 0 otherwise
- BOOST::uint8_t* wave_ram; // 32 bytes (64 nybbles), stored in APU
+ int agb_mask; // 0xFF if AGB features enabled, 0 otherwise
+ uint8_t *wave_ram; // 32 bytes (64 nybbles), stored in APU
friend class Gb_Apu;
// Frequency timer period
- int period() const { return (2048 - frequency()) * (2 * clk_mul); }
+ int period() const { return (2048 - this->frequency()) * (2 * clk_mul); }
// Non-zero if DAC is enabled
- int dac_enabled() const { return regs [0] & 0x80; }
+ int dac_enabled() const { return this->regs[0] & 0x80; }
void corrupt_wave();
- BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; }
+ uint8_t *wave_bank() const { return &this->wave_ram[((~this->regs[0] & bank40_mask) >> 2) & agb_mask]; }
// Wave index that would be accessed, or -1 if no access would occur
- int access( unsigned addr ) const;
+ int access(unsigned addr) const;
};
-inline int Gb_Wave::read( unsigned addr ) const
+inline int Gb_Wave::read(unsigned addr) const
{
- int index = access( addr );
- return (index < 0 ? 0xFF : wave_bank() [index]);
+ int index = this->access(addr);
+ return index < 0 ? 0xFF : this->wave_bank()[index];
}
-inline void Gb_Wave::write( unsigned addr, int data )
+inline void Gb_Wave::write(unsigned addr, int data)
{
- int index = access( addr );
- if ( index >= 0 )
- wave_bank() [index] = data;;
+ int index = this->access(addr);
+ if (index >= 0)
+ this->wave_bank()[index] = data;;
}
#endif
--- a/src/in_gsf/vbam/apu/Multi_Buffer.cpp
+++ b/src/in_gsf/vbam/apu/Multi_Buffer.cpp
@@ -1,5 +1,6 @@
// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
+#include <algorithm>
#include "Multi_Buffer.h"
/* Copyright (C) 2003-2007 Shay Green. This module is free software; you
@@ -16,266 +17,250 @@
#include "blargg_source.h"
#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
+# include BLARGG_ENABLE_OPTIMIZER
#endif
-Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
-{
- length_ = 0;
- sample_rate_ = 0;
- channels_changed_count_ = 1;
- channel_types_ = 0;
- channel_count_ = 0;
- immediate_removal_ = true;
-}
-
-Multi_Buffer::channel_t Multi_Buffer::channel( int /*index*/ )
-{
- static channel_t const ch = { 0, 0, 0 };
+Multi_Buffer::Multi_Buffer(int spf) : samples_per_frame_(spf)
+{
+ this->length_ = 0;
+ this->sample_rate_ = 0;
+ this->channels_changed_count_ = 1;
+ this->channel_types_ = nullptr;
+ this->channel_count_ = 0;
+ this->immediate_removal_ = true;
+}
+
+Multi_Buffer::channel_t Multi_Buffer::channel(int /*index*/)
+{
+ static const channel_t ch = { 0, 0, 0 };
return ch;
}
// Silent_Buffer
-Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
+Silent_Buffer::Silent_Buffer() : Multi_Buffer(1) // 0 channels would probably confuse
{
// TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
- chan.left = 0;
- chan.center = 0;
- chan.right = 0;
+ this->chan.left = this->chan.center = this->chan.right = nullptr;
}
// Mono_Buffer
-Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
-{
- chan.center = &buf;
- chan.left = &buf;
- chan.right = &buf;
+Mono_Buffer::Mono_Buffer() : Multi_Buffer(1)
+{
+ this->chan.center = &this->buf;
+ this->chan.left = &this->buf;
+ this->chan.right = &this->buf;
}
Mono_Buffer::~Mono_Buffer() { }
-blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec )
-{
- RETURN_ERR( buf.set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
-}
-
+blargg_err_t Mono_Buffer::set_sample_rate(long rate, int msec)
+{
+ RETURN_ERR(this->buf.set_sample_rate(rate, msec));
+ return Multi_Buffer::set_sample_rate(this->buf.sample_rate(), this->buf.length());
+}
// Tracked_Blip_Buffer
Tracked_Blip_Buffer::Tracked_Blip_Buffer()
{
- last_non_silence = 0;
+ this->last_non_silence = 0;
}
void Tracked_Blip_Buffer::clear()
{
- last_non_silence = 0;
+ this->last_non_silence = 0;
Blip_Buffer::clear();
}
-void Tracked_Blip_Buffer::end_frame( blip_time_t t )
-{
- Blip_Buffer::end_frame( t );
- if ( clear_modified() )
- last_non_silence = samples_avail() + blip_buffer_extra_;
-}
-
-blip_ulong Tracked_Blip_Buffer::non_silent() const
-{
- return last_non_silence | unsettled();
-}
-
-inline void Tracked_Blip_Buffer::remove_( long n )
-{
- if ( (last_non_silence -= n) < 0 )
- last_non_silence = 0;
-}
-
-void Tracked_Blip_Buffer::remove_silence( long n )
-{
- remove_( n );
- Blip_Buffer::remove_silence( n );
-}
-
-void Tracked_Blip_Buffer::remove_samples( long n )
-{
- remove_( n );
- Blip_Buffer::remove_samples( n );
-}
-
-void Tracked_Blip_Buffer::remove_all_samples()
-{
- long avail = samples_avail();
- if ( !non_silent() )
- remove_silence( avail );
- else
- remove_samples( avail );
-}
-
-long Tracked_Blip_Buffer::read_samples( blip_sample_t* out, long count )
-{
- count = Blip_Buffer::read_samples( out, count );
- remove_( count );
+void Tracked_Blip_Buffer::end_frame(blip_time_t t)
+{
+ Blip_Buffer::end_frame(t);
+ if (this->clear_modified())
+ this->last_non_silence = this->samples_avail() + blip_buffer_extra_;
+}
+
+uint32_t Tracked_Blip_Buffer::non_silent() const
+{
+ return this->last_non_silence | this->unsettled();
+}
+
+inline void Tracked_Blip_Buffer::remove_(long n)
+{
+ if ((this->last_non_silence -= n) < 0)
+ this->last_non_silence = 0;
+}
+
+void Tracked_Blip_Buffer::remove_silence(long n)
+{
+ this->remove_(n);
+ Blip_Buffer::remove_silence(n);
+}
+
+void Tracked_Blip_Buffer::remove_samples(long n)
+{
+ this->remove_(n);
+ Blip_Buffer::remove_samples(n);
+}
+
+long Tracked_Blip_Buffer::read_samples(blip_sample_t *out, long count)
+{
+ count = Blip_Buffer::read_samples(out, count);
+ this->remove_(count);
return count;
}
// Stereo_Buffer
-int const stereo = 2;
-
-Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
-{
- chan.center = mixer.bufs [2] = &bufs [2];
- chan.left = mixer.bufs [0] = &bufs [0];
- chan.right = mixer.bufs [1] = &bufs [1];
- mixer.samples_read = 0;
+static const int stereo = 2;
+
+Stereo_Buffer::Stereo_Buffer() : Multi_Buffer(2)
+{
+ this->chan.center = this->mixer.bufs[2] = &this->bufs[2];
+ this->chan.left = this->mixer.bufs[0] = &this->bufs[0];
+ this->chan.right = this->mixer.bufs[1] = &this->bufs[1];
+ this->mixer.samples_read = 0;
}
Stereo_Buffer::~Stereo_Buffer() { }
-blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec )
-{
- mixer.samples_read = 0;
- for ( int i = bufs_size; --i >= 0; )
- RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Stereo_Buffer::clock_rate( long rate )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clock_rate( rate );
-}
-
-void Stereo_Buffer::bass_freq( int bass )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].bass_freq( bass );
+blargg_err_t Stereo_Buffer::set_sample_rate(long rate, int msec)
+{
+ this->mixer.samples_read = 0;
+ for (int i = bufs_size; --i >= 0; )
+ RETURN_ERR(this->bufs[i].set_sample_rate(rate, msec));
+ return Multi_Buffer::set_sample_rate(this->bufs[0].sample_rate(), this->bufs[0].length());
+}
+
+void Stereo_Buffer::clock_rate(long rate)
+{
+ for (int i = bufs_size; --i >= 0; )
+ this->bufs[i].clock_rate(rate);
+}
+
+void Stereo_Buffer::bass_freq(int bass)
+{
+ for (int i = bufs_size; --i >= 0; )
+ this->bufs[i].bass_freq(bass);
}
void Stereo_Buffer::clear()
{
- mixer.samples_read = 0;
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clear();
-}
-
-void Stereo_Buffer::end_frame( blip_time_t time )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].end_frame( time );
-}
-
-long Stereo_Buffer::read_samples( blip_sample_t* out, long out_size )
-{
- require( (out_size & 1) == 0 ); // must read an even number of samples
- out_size = min( out_size, samples_avail() );
-
- int pair_count = int (out_size >> 1);
- if ( pair_count )
+ this->mixer.samples_read = 0;
+ for (int i = bufs_size; --i >= 0; )
+ this->bufs[i].clear();
+}
+
+void Stereo_Buffer::end_frame(blip_time_t time)
+{
+ for (int i = bufs_size; --i >= 0; )
+ this->bufs[i].end_frame(time);
+}
+
+long Stereo_Buffer::read_samples(blip_sample_t *out, long out_size)
+{
+ assert(!(out_size & 1)); // must read an even number of samples
+ out_size = std::min(out_size, this->samples_avail());
+
+ int pair_count = static_cast<int>(out_size >> 1);
+ if (pair_count)
{
- mixer.read_pairs( out, pair_count );
-
- if ( samples_avail() <= 0 || immediate_removal() )
+ this->mixer.read_pairs(out, pair_count);
+
+ if (this->samples_avail() <= 0 || this->immediate_removal())
{
- for ( int i = bufs_size; --i >= 0; )
+ for (int i = bufs_size; --i >= 0; )
{
- buf_t& b = bufs [i];
+ auto &b = this->bufs[i];
// TODO: might miss non-silence settling since it checks END of last read
- if ( !b.non_silent() )
- b.remove_silence( mixer.samples_read );
+ if (!b.non_silent())
+ b.remove_silence(this->mixer.samples_read);
else
- b.remove_samples( mixer.samples_read );
+ b.remove_samples(this->mixer.samples_read);
}
- mixer.samples_read = 0;
+ this->mixer.samples_read = 0;
}
}
return out_size;
}
-
// Stereo_Mixer
// mixers use a single index value to improve performance on register-challenged processors
// offset goes from negative to zero
-void Stereo_Mixer::read_pairs( blip_sample_t* out, int count )
+void Stereo_Mixer::read_pairs(blip_sample_t *out, int count)
{
// TODO: if caller never marks buffers as modified, uses mono
// except that buffer isn't cleared, so caller can encounter
// subtle problems and not realize the cause.
- samples_read += count;
- if ( bufs [0]->non_silent() | bufs [1]->non_silent() )
- mix_stereo( out, count );
+ this->samples_read += count;
+ if (this->bufs[0]->non_silent() || this->bufs[1]->non_silent())
+ this->mix_stereo(out, count);
else
- mix_mono( out, count );
-}
-
-void Stereo_Mixer::mix_mono( blip_sample_t* out_, int count )
-{
- int const bass = BLIP_READER_BASS( *bufs [2] );
- BLIP_READER_BEGIN( center, *bufs [2] );
- BLIP_READER_ADJ_( center, samples_read );
-
- typedef blip_sample_t stereo_blip_sample_t [stereo];
- stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_ + count;
+ this->mix_mono(out, count);
+}
+
+void Stereo_Mixer::mix_mono(blip_sample_t *out_, int count)
+{
+ int bass = BLIP_READER_BASS(*this->bufs[2]);
+ BLIP_READER_BEGIN(center, *this->bufs[2]);
+ BLIP_READER_ADJ_(center, this->samples_read);
+
+ typedef blip_sample_t stereo_blip_sample_t[stereo];
+ auto out = reinterpret_cast<stereo_blip_sample_t *>(out_) + count;
int offset = -count;
do
{
- blargg_long s = BLIP_READER_READ( center );
- BLIP_READER_NEXT_IDX_( center, bass, offset );
- BLIP_CLAMP( s, s );
-
- out [offset] [0] = (blip_sample_t) s;
- out [offset] [1] = (blip_sample_t) s;
- }
- while ( ++offset );
-
- BLIP_READER_END( center, *bufs [2] );
-}
-
-void Stereo_Mixer::mix_stereo( blip_sample_t* out_, int count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_ + count * stereo;
+ int32_t s = BLIP_READER_READ(center);
+ BLIP_READER_NEXT_IDX_(center, bass, offset);
+ BLIP_CLAMP(s, s);
+
+ out[offset][0] = out[offset][1] = static_cast<blip_sample_t>(s);
+ } while (++offset);
+
+ BLIP_READER_END(center, *this->bufs[2]);
+}
+
+void Stereo_Mixer::mix_stereo(blip_sample_t *out_, int count)
+{
+ auto out = out_ + count * stereo;
// do left + center and right + center separately to reduce register load
- Tracked_Blip_Buffer* const* buf = &bufs [2];
- while ( true ) // loop runs twice
+ auto buf = &this->bufs[2];
+ while (1) // loop runs twice
{
--buf;
--out;
- int const bass = BLIP_READER_BASS( *bufs [2] );
- BLIP_READER_BEGIN( side, **buf );
- BLIP_READER_BEGIN( center, *bufs [2] );
-
- BLIP_READER_ADJ_( side, samples_read );
- BLIP_READER_ADJ_( center, samples_read );
+ int bass = BLIP_READER_BASS(*this->bufs[2]);
+ BLIP_READER_BEGIN(side, **buf);
+ BLIP_READER_BEGIN(center, *this->bufs[2]);
+
+ BLIP_READER_ADJ_(side, samples_read);
+ BLIP_READER_ADJ_(center, samples_read);
int offset = -count;
do
{
- blargg_long s = BLIP_READER_READ_RAW( center ) + BLIP_READER_READ_RAW( side );
+ int32_t s = BLIP_READER_READ_RAW(center) + BLIP_READER_READ_RAW(side);
s >>= blip_sample_bits - 16;
- BLIP_READER_NEXT_IDX_( side, bass, offset );
- BLIP_READER_NEXT_IDX_( center, bass, offset );
- BLIP_CLAMP( s, s );
+ BLIP_READER_NEXT_IDX_(side, bass, offset);
+ BLIP_READER_NEXT_IDX_(center, bass, offset);
+ BLIP_CLAMP(s, s);
++offset; // before write since out is decremented to slightly before end
- out [offset * stereo] = (blip_sample_t) s;
- }
- while ( offset );
-
- BLIP_READER_END( side, **buf );
-
- if ( buf != bufs )
+ out[offset * stereo] = static_cast<blip_sample_t>(s);
+ } while (offset);
+
+ BLIP_READER_END(side, **buf);
+
+ if (buf != bufs)
continue;
// only end center once
- BLIP_READER_END( center, *bufs [2] );
+ BLIP_READER_END(center, *this->bufs[2]);
break;
}
}
--- a/src/in_gsf/vbam/apu/Multi_Buffer.h
+++ b/src/in_gsf/vbam/apu/Multi_Buffer.h
@@ -9,196 +9,191 @@
// 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 );
+class Multi_Buffer
+{
+public:
+ Multi_Buffer(int samples_per_frame);
virtual ~Multi_Buffer() { }
// Sets the number of channels available and optionally their types
// (type information used by Effects_Buffer)
enum { type_index_mask = 0xFF };
enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
- virtual blargg_err_t set_channel_count( int, int const* types = 0 );
- int channel_count() const { return channel_count_; }
+ virtual blargg_err_t set_channel_count(int, const int* types = nullptr);
+ int channel_count() const { return this->channel_count_; }
// Gets indexed channel, from 0 to channel count - 1
- struct channel_t {
- Blip_Buffer* center;
- Blip_Buffer* left;
- Blip_Buffer* right;
+ struct channel_t
+ {
+ Blip_Buffer *center;
+ Blip_Buffer *left;
+ Blip_Buffer *right;
};
- virtual channel_t channel( int index ) BLARGG_PURE( ; )
+ virtual channel_t channel(int index);
// See Blip_Buffer.h
- virtual blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ) BLARGG_PURE( ; )
- virtual void clock_rate( long ) BLARGG_PURE( { } )
- virtual void bass_freq( int ) BLARGG_PURE( { } )
- virtual void clear() BLARGG_PURE( { } )
+ virtual blargg_err_t set_sample_rate(long rate, int msec = blip_default_length);
+ virtual void clock_rate(long) { }
+ virtual void bass_freq(int) { }
+ virtual void clear() { }
long sample_rate() const;
// Length of buffer, in milliseconds
int length() const;
// See Blip_Buffer.h
- virtual void end_frame( blip_time_t ) BLARGG_PURE( { } )
+ virtual void end_frame(blip_time_t) { }
// Number of samples per output frame (1 = mono, 2 = stereo)
int samples_per_frame() const;
// Count of changes to channel configuration. Incremented whenever
// a change is made to any of the Blip_Buffers for any channel.
- unsigned channels_changed_count() { return channels_changed_count_; }
+ unsigned channels_changed_count() { return this->channels_changed_count_; }
// See Blip_Buffer.h
- virtual long read_samples( blip_sample_t*, long ) BLARGG_PURE( { return 0; } )
- virtual long samples_avail() const BLARGG_PURE( { return 0; } )
-
-public:
- BLARGG_DISABLE_NOTHROW
- void disable_immediate_removal() { immediate_removal_ = false; }
+ virtual long read_samples(blip_sample_t *, long) { return 0; }
+ virtual long samples_avail() const { return 0; }
+
+ void disable_immediate_removal() { this->immediate_removal_ = false; }
protected:
- bool immediate_removal() const { return immediate_removal_; }
- int const* channel_types() const { return channel_types_; }
- void channels_changed() { channels_changed_count_++; }
+ bool immediate_removal() const { return this->immediate_removal_; }
+ const int *channel_types() const { return this->channel_types_; }
+ void channels_changed() { ++this->channels_changed_count_; }
private:
// noncopyable
- Multi_Buffer( const Multi_Buffer& );
- Multi_Buffer& operator = ( const Multi_Buffer& );
+ Multi_Buffer(const Multi_Buffer &);
+ Multi_Buffer &operator=(const Multi_Buffer &);
unsigned channels_changed_count_;
long sample_rate_;
int length_;
int channel_count_;
- int const samples_per_frame_;
- int const* channel_types_;
+ const int samples_per_frame_;
+ const int *channel_types_;
bool immediate_removal_;
};
// Uses a single buffer and outputs mono samples.
-class Mono_Buffer : public Multi_Buffer {
+class Mono_Buffer : public Multi_Buffer
+{
Blip_Buffer buf;
channel_t chan;
public:
// Buffer used for all channels
- Blip_Buffer* center() { return &buf; }
-
-public:
+ Blip_Buffer *center() { return &this->buf; }
+
Mono_Buffer();
~Mono_Buffer();
- blargg_err_t set_sample_rate( long rate, int msec = blip_default_length );
- void clock_rate( long rate ) { buf.clock_rate( rate ); }
- void bass_freq( int freq ) { buf.bass_freq( freq ); }
- void clear() { buf.clear(); }
- long samples_avail() const { return buf.samples_avail(); }
- long read_samples( blip_sample_t* p, long s ) { return buf.read_samples( p, s ); }
- channel_t channel( int ) { return chan; }
- void end_frame( blip_time_t t ) { buf.end_frame( t ); }
-};
-
- class Tracked_Blip_Buffer : public Blip_Buffer {
- public:
- // Non-zero if buffer still has non-silent samples in it. Requires that you call
- // set_modified() appropriately.
- blip_ulong non_silent() const;
-
- // remove_samples( samples_avail() )
- void remove_all_samples();
-
- public:
- BLARGG_DISABLE_NOTHROW
-
- long read_samples( blip_sample_t*, long );
- void remove_silence( long );
- void remove_samples( long );
- Tracked_Blip_Buffer();
- void clear();
- void end_frame( blip_time_t );
- private:
- blip_long last_non_silence;
- void remove_( long );
- };
-
- class Stereo_Mixer {
- public:
- Tracked_Blip_Buffer* bufs [3];
- blargg_long samples_read;
-
- Stereo_Mixer() : samples_read( 0 ) { }
- void read_pairs( blip_sample_t* out, int count );
- private:
- void mix_mono ( blip_sample_t* out, int pair_count );
- void mix_stereo( blip_sample_t* out, int pair_count );
- };
+ blargg_err_t set_sample_rate(long rate, int msec = blip_default_length);
+ void clock_rate(long rate) { this->buf.clock_rate(rate); }
+ void bass_freq(int freq) { this->buf.bass_freq(freq); }
+ void clear() { this->buf.clear(); }
+ long samples_avail() const { return this->buf.samples_avail(); }
+ long read_samples(blip_sample_t *p, long s) { return this->buf.read_samples(p, s); }
+ channel_t channel(int) { return this->chan; }
+ void end_frame(blip_time_t t) { this->buf.end_frame(t); }
+};
+
+class Tracked_Blip_Buffer : public Blip_Buffer
+{
+public:
+ // Non-zero if buffer still has non-silent samples in it. Requires that you call
+ // set_modified() appropriately.
+ uint32_t non_silent() const;
+
+ long read_samples(blip_sample_t *, long);
+ void remove_silence(long);
+ void remove_samples(long);
+ Tracked_Blip_Buffer();
+ void clear();
+ void end_frame(blip_time_t);
+private:
+ int32_t last_non_silence;
+ void remove_(long);
+};
+
+class Stereo_Mixer
+{
+public:
+ Tracked_Blip_Buffer *bufs[3];
+ int32_t samples_read;
+
+ Stereo_Mixer() : samples_read(0) { }
+ void read_pairs(blip_sample_t *out, int count);
+private:
+ void mix_mono(blip_sample_t *out, int pair_count);
+ void mix_stereo(blip_sample_t *out, int pair_count);
+};
// Uses three buffers (one for center) and outputs stereo sample pairs.
-class Stereo_Buffer : public Multi_Buffer {
-public:
-
+class Stereo_Buffer : public Multi_Buffer
+{
+public:
// Buffers used for all channels
- Blip_Buffer* center() { return &bufs [2]; }
- Blip_Buffer* left() { return &bufs [0]; }
- Blip_Buffer* right() { return &bufs [1]; }
-
-public:
+ Blip_Buffer *center() { return &this->bufs[2]; }
+ Blip_Buffer *left() { return &this->bufs[0]; }
+ Blip_Buffer *right() { return &this->bufs[1]; }
+
Stereo_Buffer();
~Stereo_Buffer();
- blargg_err_t set_sample_rate( long, int msec = blip_default_length );
- void clock_rate( long );
- void bass_freq( int );
+ blargg_err_t set_sample_rate(long, int msec = blip_default_length);
+ void clock_rate(long);
+ void bass_freq(int);
void clear();
- channel_t channel( int ) { return chan; }
- void end_frame( blip_time_t );
-
- long samples_avail() const { return (bufs [0].samples_avail() - mixer.samples_read) * 2; }
- long read_samples( blip_sample_t*, long );
+ channel_t channel(int) { return this->chan; }
+ void end_frame(blip_time_t);
+
+ long samples_avail() const { return (this->bufs[0].samples_avail() - this->mixer.samples_read) * 2; }
+ long read_samples(blip_sample_t *, long);
private:
enum { bufs_size = 3 };
typedef Tracked_Blip_Buffer buf_t;
- buf_t bufs [bufs_size];
+ buf_t bufs[bufs_size];
Stereo_Mixer mixer;
channel_t chan;
long samples_avail_;
};
// Silent_Buffer generates no samples, useful where no sound is wanted
-class Silent_Buffer : public Multi_Buffer {
+class Silent_Buffer : public Multi_Buffer
+{
channel_t chan;
public:
Silent_Buffer();
- blargg_err_t set_sample_rate( long rate, int msec = blip_default_length );
- void clock_rate( long ) { }
- void bass_freq( int ) { }
+ blargg_err_t set_sample_rate(long rate, int msec = blip_default_length);
+ void clock_rate(long) { }
+ void bass_freq(int) { }
void clear() { }
- channel_t channel( int ) { return chan; }
- void end_frame( blip_time_t ) { }
+ channel_t channel(int) { return this->chan; }
+ void end_frame(blip_time_t) { }
long samples_avail() const { return 0; }
- long read_samples( blip_sample_t*, long ) { return 0; }
-};
-
-
-inline blargg_err_t Multi_Buffer::set_sample_rate( long rate, int msec )
-{
- sample_rate_ = rate;
- length_ = msec;
+ long read_samples(blip_sample_t *, long) { return 0; }
+};
+
+inline blargg_err_t Multi_Buffer::set_sample_rate(long rate, int msec)
+{
+ this->sample_rate_ = rate;
+ this->length_ = msec;
return 0;
}
-inline blargg_err_t Silent_Buffer::set_sample_rate( long rate, int msec )
-{
- return Multi_Buffer::set_sample_rate( rate, msec );
+inline blargg_err_t Silent_Buffer::set_sample_rate(long rate, int msec)
+{
+ return Multi_Buffer::set_sample_rate(rate, msec);
}
-inline int Multi_Buffer::samples_per_frame() const { return samples_per_frame_; }
-
-inline long Multi_Buffer::sample_rate() const { return sample_rate_; }
-
-inline int Multi_Buffer::length() const { return length_; }
-
-inline blargg_err_t Multi_Buffer::set_channel_count( int n, int const* types )
-{
- channel_count_ = n;
- channel_types_ = types;
+inline int Multi_Buffer::samples_per_frame() const { return this->samples_per_frame_; }
+
+inline long Multi_Buffer::sample_rate() const { return this->sample_rate_; }
+
+inline int Multi_Buffer::length() const { return this->length_; }
+
+inline blargg_err_t Multi_Buffer::set_channel_count(int n, const int *types)
+{
+ this->channel_count_ = n;
+ this->channel_types_ = types;
return 0;
}
--- a/src/in_gsf/vbam/apu/blargg_common.h
+++ b/src/in_gsf/vbam/apu/blargg_common.h
@@ -5,10 +5,9 @@
#ifndef BLARGG_COMMON_H
#define BLARGG_COMMON_H
-#include <stddef.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
+#include <cstdlib>
+#include <cassert>
+#include <cstdint>
#undef BLARGG_COMMON_H
// allow blargg_config.h to #include blargg_common.h
@@ -16,190 +15,33 @@
#ifndef BLARGG_COMMON_H
#define BLARGG_COMMON_H
-// BLARGG_RESTRICT: equivalent to restrict, where supported
-#if __GNUC__ >= 3 || _MSC_VER >= 1100
- #define BLARGG_RESTRICT __restrict
-#else
- #define BLARGG_RESTRICT
-#endif
-
-// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
-// CONST_CAST( T,expr): Used in place of const_cast<T> (expr)
-#ifndef STATIC_CAST
- #if __GNUC__ >= 4
- #define STATIC_CAST(T,expr) static_cast<T> (expr)
- #define CONST_CAST( T,expr) const_cast<T> (expr)
- #else
- #define STATIC_CAST(T,expr) ((T) (expr))
- #define CONST_CAST( T,expr) ((T) (expr))
- #endif
-#endif
-
// blargg_err_t (0 on success, otherwise error string)
#ifndef blargg_err_t
- typedef const char* blargg_err_t;
-#endif
-
-// blargg_vector - very lightweight vector of POD types (no constructor/destructor)
-template<class T>
-class blargg_vector {
- T* begin_;
- size_t size_;
-public:
- blargg_vector() : begin_( 0 ), size_( 0 ) { }
- ~blargg_vector() { free( begin_ ); }
- size_t size() const { return size_; }
- T* begin() const { return begin_; }
- T* end() const { return begin_ + size_; }
- blargg_err_t resize( size_t n )
- {
- // TODO: blargg_common.cpp to hold this as an outline function, ugh
- void* p = realloc( begin_, n * sizeof (T) );
- if ( p )
- begin_ = (T*) p;
- else if ( n > size_ ) // realloc failure only a problem if expanding
- return "Out of memory";
- size_ = n;
- return 0;
- }
- void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); }
- T& operator [] ( size_t n ) const
- {
- assert( n <= size_ ); // <= to allow past-the-end value
- return begin_ [n];
- }
-};
-
-#ifndef BLARGG_DISABLE_NOTHROW
- // throw spec mandatory in ISO C++ if operator new can return NULL
- #if __cplusplus >= 199711 || __GNUC__ >= 3
- #define BLARGG_THROWS( spec ) throw spec
- #else
- #define BLARGG_THROWS( spec )
- #endif
- #define BLARGG_DISABLE_NOTHROW \
- void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
- void operator delete ( void* p ) { free( p ); }
- #define BLARGG_NEW new
-#else
- #include <new>
- #define BLARGG_NEW new (std::nothrow)
-#endif
-
-// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant)
-#define BLARGG_4CHAR( a, b, c, d ) \
- ((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
-
-// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
-#ifndef BOOST_STATIC_ASSERT
- #ifdef _MSC_VER
- // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified
- #define BOOST_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
- #else
- // Some other compilers fail when declaring same function multiple times in class,
- // so differentiate them by line
- #define BOOST_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
- #endif
+typedef const char *blargg_err_t;
#endif
// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1,
// compiler is assumed to support bool. If undefined, availability is determined.
#ifndef BLARGG_COMPILER_HAS_BOOL
- #if defined (__MWERKS__)
- #if !__option(bool)
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
- #elif defined (_MSC_VER)
- #if _MSC_VER < 1100
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
- #elif defined (__GNUC__)
- // supports bool
- #elif __cplusplus < 199711
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
+# ifdef __MWERKS__
+# if !__option(bool)
+# define BLARGG_COMPILER_HAS_BOOL 0
+# endif
+# elif defined(_MSC_VER)
+# if _MSC_VER < 1100
+# define BLARGG_COMPILER_HAS_BOOL 0
+# endif
+# elif defined(__GNUC__)
+// supports bool
+# elif __cplusplus < 199711
+# define BLARGG_COMPILER_HAS_BOOL 0
+# endif
#endif
-#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
- // If you get errors here, modify your blargg_config.h file
- typedef int bool;
- const bool true = 1;
- const bool false = 0;
-#endif
-
-// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
-
-#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
- typedef long blargg_long;
-#else
- typedef int blargg_long;
-#endif
-
-#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
- typedef unsigned long blargg_ulong;
-#else
- typedef unsigned blargg_ulong;
-#endif
-
-// BOOST::int8_t etc.
-
-// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
-#if defined (HAVE_STDINT_H)
- #include <stdint.h>
- #define BOOST
-
-// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc.
-#elif defined (HAVE_INTTYPES_H)
- #include <inttypes.h>
- #define BOOST
-
-#else
- struct BOOST
- {
- #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F
- typedef signed char int8_t;
- typedef unsigned char uint8_t;
- #else
- // No suitable 8-bit type available
- typedef struct see_blargg_common_h int8_t;
- typedef struct see_blargg_common_h uint8_t;
- #endif
-
- #if USHRT_MAX == 0xFFFF
- typedef short int16_t;
- typedef unsigned short uint16_t;
- #else
- // No suitable 16-bit type available
- typedef struct see_blargg_common_h int16_t;
- typedef struct see_blargg_common_h uint16_t;
- #endif
-
- #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
- // No suitable 32-bit type available
- typedef struct see_blargg_common_h int32_t;
- typedef struct see_blargg_common_h uint32_t;
- #endif
- };
-#endif
-
-#if __GNUC__ >= 3
- #define BLARGG_DEPRECATED __attribute__ ((deprecated))
-#else
- #define BLARGG_DEPRECATED
-#endif
-
-// Use in place of "= 0;" for a pure virtual, since these cause calls to std C++ lib.
-// During development, BLARGG_PURE( x ) expands to = 0;
-// virtual int func() BLARGG_PURE( { return 0; } )
-#ifndef BLARGG_PURE
- #define BLARGG_PURE( def ) def
+#if defined(BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
+// If you get errors here, modify your blargg_config.h file
+typedef int bool;
+const bool true = 1;
+const bool false = 0;
#endif
#endif
--- a/src/in_gsf/vbam/apu/blargg_config.h
+++ b/src/in_gsf/vbam/apu/blargg_config.h
@@ -7,28 +7,8 @@
// a Game Boy Advance emulator.
#define GB_APU_OVERCLOCK 4
-#define GB_APU_CUSTOM_STATE 1
-
-// Uncomment to enable platform-specific (and possibly non-portable) optimizations.
-//#define BLARGG_NONPORTABLE 1
-
-// Uncomment if automatic byte-order determination doesn't work
-//#define BLARGG_BIG_ENDIAN 1
-
-// Uncomment to use zlib for transparent decompression of gzipped files
-//#define HAVE_ZLIB_H
-
// Uncomment if you get errors in the bool section of blargg_common.h
//#define BLARGG_COMPILER_HAS_BOOL 1
-// Uncomment to disable out-of-memory exceptions
-//#include <memory>
-//#define BLARGG_NEW new (std::nothrow)
-
-// Use standard config.h if present
-#ifdef HAVE_CONFIG_H
- #include "config.h"
#endif
-#endif
-
--- a/src/in_gsf/vbam/apu/blargg_source.h
+++ b/src/in_gsf/vbam/apu/blargg_source.h
@@ -17,77 +17,18 @@
// in MY code.
//
// void assert( bool expr );
-#include <assert.h>
-
-// If expr is false, prints file and line number, then aborts program. Meant for
-// checking caller-supplied parameters and operations that are outside the control
-// of the module. A failed requirement probably indicates a bug in YOUR code.
-//
-// void require( bool expr );
-#undef require
-#define require( expr ) assert( expr )
-
-// Like printf() except output goes to debugging console/file.
-//
-// void dprintf( const char* format, ... );
-static inline void blargg_dprintf_( const char*, ... ) { }
-#undef dprintf
-#define dprintf (1) ? (void) 0 : blargg_dprintf_
-
-// If expr is false, prints file and line number to debug console/log, then
-// continues execution normally. Meant for flagging potential problems or things
-// that should be looked into, but that aren't serious problems.
-//
-// void check( bool expr );
-#undef check
-#define check( expr ) ((void) 0)
+#include <cassert>
// If expr yields non-NULL error string, returns it from current function,
// otherwise continues normally.
-#undef RETURN_ERR
-#define 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, returns "Out of memory" error string, otherwise continues normally.
-#undef CHECK_ALLOC
-#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 )
-
-// The usual min/max functions for built-in types.
-//
-// template<typename T> T min( T x, T y ) { return x < y ? x : y; }
-// template<typename T> T max( T x, T y ) { return x > y ? x : y; }
-#define BLARGG_DEF_MIN_MAX( type ) \
- static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
- static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
-
-BLARGG_DEF_MIN_MAX( int )
-BLARGG_DEF_MIN_MAX( unsigned )
-BLARGG_DEF_MIN_MAX( long )
-BLARGG_DEF_MIN_MAX( unsigned long )
-BLARGG_DEF_MIN_MAX( float )
-BLARGG_DEF_MIN_MAX( double )
-
-#undef min
-#define min blargg_min
-
-#undef max
-#define max blargg_max
-
-// typedef unsigned char byte;
-typedef unsigned char blargg_byte;
-#undef byte
-#define byte blargg_byte
-
-// deprecated
-#define BLARGG_CHECK_ALLOC CHECK_ALLOC
-#define BLARGG_RETURN_ERR RETURN_ERR
-
-// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check
-#ifdef BLARGG_SOURCE_BEGIN
- #include BLARGG_SOURCE_BEGIN
-#endif
+#undef RETURN_ERR
+#define RETURN_ERR(expr) \
+do \
+{ \
+ blargg_err_t blargg_return_err_ = (expr); \
+ if (blargg_return_err_) \
+ return blargg_return_err_; \
+} while (0)
#endif
--- a/src/in_gsf/vbam/common/Port.h
+++ b/src/in_gsf/vbam/common/Port.h
@@ -3,56 +3,48 @@
#include <cstdint>
+#ifdef WORDS_BIGENDIAN
+#if defined(__GNUC__) && defined(__ppc__)
+#define READ16LE(base) \
+ ({ \
+ unsigned short lhbrxResult; \
+ __asm__("lhbrx %0, 0, %1" : "=r" (lhbrxResult) : "r" (base) : "memory"); \
+ lhbrxResult; \
+ })
+
+#define READ32LE(base) \
+ ({ \
+ unsigned long lwbrxResult; \
+ __asm__("lwbrx %0, 0, %1" : "=r" (lwbrxResult) : "r" (base) : "memory"); \
+ lwbrxResult; \
+ })
+
+#define WRITE16LE(base, value) __asm__("sthbrx %0, 0, %1" : : "r" (value), "r" (base) : "memory")
+
+#define WRITE32LE(base, value) __asm__("stwbrx %0, 0, %1" : : "r" (value), "r" (base) : "memory")
+#else
// swaps a 16-bit value
-static inline uint16_t swap16(uint16_t v)
+inline uint16_t swap16(uint16_t v)
{
- return (v<<8)|(v>>8);
+ return (v << 8) | (v >> 8);
}
// swaps a 32-bit value
-static inline uint32_t swap32(uint32_t v)
+inline uint32_t swap32(uint32_t v)
{
- return (v<<24)|((v<<8)&0xff0000)|((v>>8)&0xff00)|(v>>24);
+ return (v << 24) | ((v << 8) & 0xff0000) | ((v >> 8) & 0xff00) | (v >> 24);
}
-#ifdef WORDS_BIGENDIAN
-#if defined(__GNUC__) && defined(__ppc__)
-
-#define READ16LE(base) \
- ({ unsigned short lhbrxResult; \
- __asm__ ("lhbrx %0, 0, %1" : "=r" (lhbrxResult) : "r" (base) : "memory"); \
- lhbrxResult; })
-
-#define READ32LE(base) \
- ({ unsigned long lwbrxResult; \
- __asm__ ("lwbrx %0, 0, %1" : "=r" (lwbrxResult) : "r" (base) : "memory"); \
- lwbrxResult; })
-
-#define WRITE16LE(base, value) \
- __asm__ ("sthbrx %0, 0, %1" : : "r" (value), "r" (base) : "memory")
-
-#define WRITE32LE(base, value) \
- __asm__ ("stwbrx %0, 0, %1" : : "r" (value), "r" (base) : "memory")
-
-#else
-#define READ16LE(x) \
- swap16(*((uint16_t *)(x)))
-#define READ32LE(x) \
- swap32(*((uint32_t *)(x)))
-#define WRITE16LE(x,v) \
- *((uint16_t *)x) = swap16((v))
-#define WRITE32LE(x,v) \
- *((uint32_t *)x) = swap32((v))
+template<typename T> inline uint16_t READ16LE(T *x) { return swap16(*reinterpret_cast<uint16_t *>(x)); }
+template<typename T> inline uint32_t READ32LE(T *x) { return swap32(*reinterpret_cast<uint32_t *>(x)); }
+template<typename T> inline void WRITE16LE(T *x, uint16_t v) { *reinterpret_cast<uint16_t *>(x) = swap16(v); }
+template<typename T> inline void WRITE32LE(T *x, uint32_t v) { *reinterpret_cast<uint32_t *>(x) = swap32(v); }
#endif
#else
-#define READ16LE(x) \
- *((uint16_t *)x)
-#define READ32LE(x) \
- *((uint32_t *)x)
-#define WRITE16LE(x,v) \
- *((uint16_t *)x) = (v)
-#define WRITE32LE(x,v) \
- *((uint32_t *)x) = (v)
+template<typename T> inline uint16_t READ16LE(T *x) { return *reinterpret_cast<uint16_t *>(x); }
+template<typename T> inline uint32_t READ32LE(T *x) { return *reinterpret_cast<uint32_t *>(x); }
+template<typename T> inline void WRITE16LE(T *x, uint16_t v) { *reinterpret_cast<uint16_t *>(x) = v; }
+template<typename T> inline void WRITE32LE(T *x, uint32_t v) { *reinterpret_cast<uint32_t *>(x) = v; }
#endif
#endif // PORT_H
--- a/src/in_gsf/vbam/common/SoundDriver.h
+++ b/src/in_gsf/vbam/common/SoundDriver.h
@@ -27,11 +27,10 @@
class SoundDriver
{
public:
-
/**
* Destructor. Free the resources allocated by the sound driver.
*/
- virtual ~SoundDriver() { };
+ virtual ~SoundDriver() { }
/**
* Initialize the sound driver.
@@ -57,9 +56,9 @@
/**
* Write length bytes of data from the finalWave buffer to the driver output buffer.
*/
- virtual void write(uint16_t * finalWave, int length) = 0;
+ virtual void write(uint16_t *finalWave, int length) = 0;
- virtual void setThrottle(unsigned short throttle) { };
+ virtual void setThrottle(unsigned short throttle) { }
};
#endif // __VBA_SOUND_DRIVER_H__
--- a/src/in_gsf/vbam/gba/GBA-arm.cpp
+++ b/src/in_gsf/vbam/gba/GBA-arm.cpp
@@ -1,34 +1,16 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <stdarg.h>
-#include <string.h>
-
#include "GBA.h"
#include "GBAcpu.h"
#include "GBAinline.h"
#include "Globals.h"
-//#include "EEprom.h"
-//#include "Flash.h"
#include "Sound.h"
-//#include "Sram.h"
#include "bios.h"
-//#include "Cheats.h"
-//#include "../NLS.h"
-//#include "elf.h"
-//#include "../Util.h"
-//#include "../System.h"
-//#include "agbprint.h"
-#ifdef PROFILING
-#include "prof/prof.h"
-#endif
#ifdef _MSC_VER
- // Disable "empty statement" warnings
- #pragma warning(disable: 4390)
- // Visual C's inline assembler treats "offset" as a reserved word, so we
- // tell it otherwise. If you want to use it, write "OFFSET" in capitals.
- #define offset offset_
+// Disable "empty statement" warnings
+# pragma warning(disable: 4390)
+// Visual C's inline assembler treats "offset" as a reserved word, so we
+// tell it otherwise. If you want to use it, write "OFFSET" in capitals.
+# define offset offset_
#endif
///////////////////////////////////////////////////////////////////////////
@@ -37,77 +19,13 @@
static INSN_REGPARM void armUnknownInsn(uint32_t opcode)
{
-#ifdef GBA_LOGGING
- if (systemVerbose & VERBOSE_UNDEFINED) {
- log("Undefined ARM instruction %08x at %08x\n", opcode,
- armNextPC-4);
- }
-#endif
- CPUUndefinedException();
-}
-
-#ifdef BKPT_SUPPORT
-static INSN_REGPARM void armBreakpoint(uint32_t opcode)
-{
- reg[15].I -= 4;
- armNextPC -= 4;
- dbgSignal(5, (opcode & 0x0f) | ((opcode>>4) & 0xfff0));
- clockTicks = -1;
-}
-#endif
-
-
-// Subroutine to count instructions (for debugging/optimizing)
-//#define INSN_COUNTER // comment out if you don't want it
-#ifdef INSN_COUNTER
-static void count(uint32_t opcode, int cond_res)
-{
- static int insncount = 0; // number of insns seen
- static int executed = 0; // number of insns executed
- static int mergewith[4096]; // map instructions to routines
- static int count[4096]; // count of each 12-bit code
- int index = ((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F);
- static FILE *outfile = NULL;
-
- if (!insncount) {
- for (int i = 0; i < 4096; i++) {
- for (int j = 0; j < i; j++) {
- if (armInsnTable[i] == armInsnTable[j])
- break;
- }
- mergewith[i] = j;
- }
- outfile = fopen("VBA-armcount.txt", "w");
- }
- if (cond_res) {
- count[mergewith[index]]++;
- executed++;
- }
- insncount++;
- if (outfile && insncount%1000000 == 0) {
- fprintf(outfile, "Total instructions: %d\n", insncount);
- fprintf(outfile, "Instructions executed: %d\n", executed);
- for (int i = 0; i < 4096; i++) {
- if (count[i])
- fprintf(outfile, "arm%03X: %d\n", i, count[i]);
- }
- }
-}
-#endif
+ CPUUndefinedException();
+}
// Common macros //////////////////////////////////////////////////////////
-#ifdef BKPT_SUPPORT
-#define CONSOLE_OUTPUT(a,b) do { \
- if ((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) { \
- dbgOutput((a), (b)); \
-} while (0)
-#else
-#define CONSOLE_OUTPUT(a,b) /* nothing */
-#endif
-
-#define NEG(i) ((i) >> 31)
-#define POS(i) ((~(i)) >> 31)
+static inline uint32_t NEG(uint32_t i) { return i >> 31; }
+static inline uint32_t POS(uint32_t i) { return ~i >> 31; }
// The following macros are used for optimization; any not defined for a
// particular compiler/CPU combination default to the C core versions.
@@ -135,210 +53,207 @@
// STR instructions.
#ifndef C_CORE
-
-#if 0 // definitions have changed
+# if 0 // definitions have changed
//#ifdef __POWERPC__
- #define OP_SUBS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_RSBS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subfco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_ADDS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("addco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_ADCS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("mtspr xer, %4\n" \
- "addeo. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value), \
- "r" (C_FLAG << 29) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_SBCS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("mtspr xer, %4\n" \
- "subfeo. %0, %3, %2\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value), \
- "r" (C_FLAG << 29) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_RSCS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("mtspr xer, %4\n" \
- "subfeo. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value), \
- "r" (C_FLAG << 29) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_CMP \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define OP_CMN \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("addco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[base].I), \
- "r" (value) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
-
-#else // !__POWERPC__
-
+# define OP_SUBS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_RSBS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subfco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_ADDS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("addco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_ADCS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("mtspr xer, %4\n" \
+ "addeo. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value), \
+ "r" (C_FLAG << 29) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_SBCS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("mtspr xer, %4\n" \
+ "subfeo. %0, %3, %2\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value), \
+ "r" (C_FLAG << 29) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_RSCS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("mtspr xer, %4\n"\
+ "subfeo. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value), \
+ "r" (C_FLAG << 29) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_CMP \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value) \
+ ); \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define OP_CMN \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("addco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[base].I), \
+ "r" (value) \
+ ); \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# else // !__POWERPC__
// Macros to emit instructions in the format used by the particular compiler.
// We use GNU assembler syntax: "op src, dest" rather than "op dest, src"
-#ifdef __GNUC__
- #define ALU_HEADER asm("mov %%ecx, %%edi; "
- #define ALU_TRAILER : "=D" (opcode) : "c" (opcode) : "eax", "ebx", "edx", "esi")
- #define EMIT0(op) #op"; "
- #define EMIT1(op,arg) #op" "arg"; "
- #define EMIT2(op,src,dest) #op" "src", "dest"; "
- #define KONST(val) "$"#val
- #define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
- #define ASMVAR2(prefix,cvar) STRING (prefix) cvar
- #define STRING(x) #x
- #define VAR(var) ASMVAR(#var)
- #define VARL(var) ASMVAR(#var)
- #define REGREF1(index) ASMVAR("reg("index")")
- #define REGREF2(index,scale) ASMVAR("reg(,"index","#scale")")
- #define LABEL(n) #n": "
- #define LABELREF(n,dir) #n#dir
- #define al "%%al"
- #define ah "%%ah"
- #define eax "%%eax"
- #define bl "%%bl"
- #define bh "%%bh"
- #define ebx "%%ebx"
- #define cl "%%cl"
- #define ch "%%ch"
- #define ecx "%%ecx"
- #define dl "%%dl"
- #define dh "%%dh"
- #define edx "%%edx"
- #define esp "%%esp"
- #define ebp "%%ebp"
- #define esi "%%esi"
- #define edi "%%edi"
- #define movzx movzb
+# ifdef __GNUC__
+# define ALU_HEADER asm("mov %%ecx, %%edi; "
+# define ALU_TRAILER : "=D" (opcode) : "c" (opcode) : "eax", "ebx", "edx", "esi")
+# define EMIT0(op) #op "; "
+# define EMIT1(op, arg) #op " " arg "; "
+# define EMIT2(op, src, dest) #op " " src ", " dest "; "
+# define KONST(val) "$" #val
+# define ASMVAR(cvar) ASMVAR2(__USER_LABEL_PREFIX__, cvar)
+# define ASMVAR2(prefix, cvar) STRING(prefix) cvar
+# define STRING(x) #x
+# define VAR(var) ASMVAR(#var)
+# define VARL(var) ASMVAR(#var)
+# define REGREF1(index) ASMVAR("reg(" index ")")
+# define REGREF2(index, scale) ASMVAR("reg(," index "," #scale ")")
+# define LABEL(n) #n ": "
+# define LABELREF(n, dir) #n#dir
+# define al "%%al"
+# define ah "%%ah"
+# define eax "%%eax"
+# define bl "%%bl"
+# define bh "%%bh"
+# define ebx "%%ebx"
+# define cl "%%cl"
+# define ch "%%ch"
+# define ecx "%%ecx"
+# define dl "%%dl"
+# define dh "%%dh"
+# define edx "%%edx"
+# define esp "%%esp"
+# define ebp "%%ebp"
+# define esi "%%esi"
+# define edi "%%edi"
+# define movzx movzb
#else
- #define ALU_HEADER __asm { __asm mov ecx, opcode
- #define ALU_TRAILER }
- #define EMIT0(op) __asm op
- #define EMIT1(op,arg) __asm op arg
- #define EMIT2(op,src,dest) __asm op dest, src
- #define KONST(val) val
- #define VAR(var) var
- #define VARL(var) dword ptr var
- #define REGREF1(index) reg[index]
- #define REGREF2(index,scale) reg[index*scale]
- #define LABEL(n) __asm l##n:
- #define LABELREF(n,dir) l##n
-#endif
+# define ALU_HEADER __asm { __asm mov ecx, opcode
+# define ALU_TRAILER }
+# define EMIT0(op) __asm op
+# define EMIT1(op,arg) __asm op arg
+# define EMIT2(op, src, dest) __asm op dest, src
+# define KONST(val) val
+# define VAR(var) var
+# define VARL(var) dword ptr var
+# define REGREF1(index) reg[index]
+# define REGREF2(index, scale) reg[index * scale]
+# define LABEL(n) __asm l##n:
+# define LABELREF(n, dir) l##n
+# endif
//X//#ifndef _MSC_VER
// ALU op register usage:
@@ -349,763 +264,783 @@
// ESI -> Rd (destination) index * 4
// Helper macros for loading value / shift count
-#define VALUE_LOAD_IMM \
- EMIT2(and, KONST(0x0F), eax) \
- EMIT2(mov, REGREF2(eax,4), eax) \
- EMIT2(shr, KONST(7), ecx) \
- EMIT2(and, KONST(0x1F), ecx)
-#define VALUE_LOAD_REG \
- EMIT2(and, KONST(0x0F), eax) \
- EMIT2(cmp, KONST(0x0F), eax) \
- EMIT2(mov, REGREF2(eax,4), eax) \
- EMIT1(jne, LABELREF(3,f)) \
- EMIT2(add, KONST(4), eax) \
- LABEL(3) \
- EMIT2(movzx, ch, ecx) \
- EMIT2(and, KONST(0x0F), ecx) \
- EMIT2(mov, REGREF2(ecx,4), ecx)
+# define VALUE_LOAD_IMM \
+ EMIT2(and, KONST(0x0F), eax) \
+ EMIT2(mov, REGREF2(eax, 4), eax) \
+ EMIT2(shr, KONST(7), ecx) \
+ EMIT2(and, KONST(0x1F), ecx)
+# define VALUE_LOAD_REG \
+ EMIT2(and, KONST(0x0F), eax) \
+ EMIT2(cmp, KONST(0x0F), eax) \
+ EMIT2(mov, REGREF2(eax, 4), eax) \
+ EMIT1(jne, LABELREF(3, f)) \
+ EMIT2(add, KONST(4), eax) \
+ LABEL(3) \
+ EMIT2(movzx, ch, ecx) \
+ EMIT2(and, KONST(0x0F), ecx) \
+ EMIT2(mov, REGREF2(ecx, 4), ecx)
// Helper macros for setting flags
-#define SETCOND_LOGICAL \
- EMIT1(sets, VAR(N_FLAG)) \
- EMIT1(setz, VAR(Z_FLAG)) \
- EMIT2(mov, bl, VAR(C_FLAG))
-#define SETCOND_ADD \
- EMIT1(sets, VAR(N_FLAG)) \
- EMIT1(setz, VAR(Z_FLAG)) \
- EMIT1(seto, VAR(V_FLAG)) \
- EMIT1(setc, VAR(C_FLAG))
-#define SETCOND_SUB \
- EMIT1(sets, VAR(N_FLAG)) \
- EMIT1(setz, VAR(Z_FLAG)) \
- EMIT1(seto, VAR(V_FLAG)) \
- EMIT1(setnc, VAR(C_FLAG))
+# define SETCOND_LOGICAL \
+ EMIT1(sets, VAR(N_FLAG)) \
+ EMIT1(setz, VAR(Z_FLAG)) \
+ EMIT2(mov, bl, VAR(C_FLAG))
+# define SETCOND_ADD \
+ EMIT1(sets, VAR(N_FLAG)) \
+ EMIT1(setz, VAR(Z_FLAG)) \
+ EMIT1(seto, VAR(V_FLAG)) \
+ EMIT1(setc, VAR(C_FLAG))
+# define SETCOND_SUB \
+ EMIT1(sets, VAR(N_FLAG)) \
+ EMIT1(setz, VAR(Z_FLAG)) \
+ EMIT1(seto, VAR(V_FLAG)) \
+ EMIT1(setnc, VAR(C_FLAG))
// ALU initialization
-#define ALU_INIT(LOAD_C_FLAG) \
- ALU_HEADER \
- LOAD_C_FLAG \
- EMIT2(mov, ecx, edx) \
- EMIT2(shr, KONST(14), edx) \
- EMIT2(mov, ecx, eax) \
- EMIT2(mov, ecx, esi) \
- EMIT2(shr, KONST(10), esi) \
- EMIT2(and, KONST(0x3C), edx) \
- EMIT2(mov, REGREF1(edx), edx) \
- EMIT2(and, KONST(0x3C), esi)
-
-#define LOAD_C_FLAG_YES EMIT2(mov, VAR(C_FLAG), bl)
-#define LOAD_C_FLAG_NO /*nothing*/
-#define ALU_INIT_C ALU_INIT(LOAD_C_FLAG_YES)
-#define ALU_INIT_NC ALU_INIT(LOAD_C_FLAG_NO)
+# define ALU_INIT(LOAD_C_FLAG) \
+ ALU_HEADER \
+ LOAD_C_FLAG \
+ EMIT2(mov, ecx, edx) \
+ EMIT2(shr, KONST(14), edx) \
+ EMIT2(mov, ecx, eax) \
+ EMIT2(mov, ecx, esi) \
+ EMIT2(shr, KONST(10), esi) \
+ EMIT2(and, KONST(0x3C), edx) \
+ EMIT2(mov, REGREF1(edx), edx) \
+ EMIT2(and, KONST(0x3C), esi)
+
+# define LOAD_C_FLAG_YES EMIT2(mov, VAR(C_FLAG), bl)
+# define LOAD_C_FLAG_NO /*nothing*/
+# define ALU_INIT_C ALU_INIT(LOAD_C_FLAG_YES)
+# define ALU_INIT_NC ALU_INIT(LOAD_C_FLAG_NO)
// Macros to load the value operand for an ALU op; these all set N/Z
// according to the value
// OP Rd,Rb,Rm LSL #
-#define VALUE_LSL_IMM_C \
- VALUE_LOAD_IMM \
- EMIT1(jnz, LABELREF(1,f)) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(shl, cl, eax) \
- EMIT1(setc, bl) \
- LABEL(0)
-#define VALUE_LSL_IMM_NC \
- VALUE_LOAD_IMM \
- EMIT2(shl, cl, eax)
+# define VALUE_LSL_IMM_C \
+ VALUE_LOAD_IMM \
+ EMIT1(jnz, LABELREF(1, f)) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(shl, cl, eax) \
+ EMIT1(setc, bl) \
+ LABEL(0)
+# define VALUE_LSL_IMM_NC \
+ VALUE_LOAD_IMM \
+ EMIT2(shl, cl, eax)
// OP Rd,Rb,Rm LSL Rs
-#define VALUE_LSL_REG_C \
- VALUE_LOAD_REG \
- EMIT2(test, cl, cl) \
- EMIT1(jz, LABELREF(0,f)) \
- EMIT2(cmp, KONST(0x20), cl) \
- EMIT1(je, LABELREF(1,f)) \
- EMIT1(ja, LABELREF(2,f)) \
- EMIT2(shl, cl, eax) \
- EMIT1(setc, bl) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(test, KONST(1), al) \
- EMIT1(setnz, bl) \
- EMIT2(xor, eax, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(2) \
- EMIT2(xor, ebx, ebx) \
- EMIT2(xor, eax, eax) \
- LABEL(0)
-#define VALUE_LSL_REG_NC \
- VALUE_LOAD_REG \
- EMIT2(cmp, KONST(0x20), cl) \
- EMIT1(jae, LABELREF(1,f)) \
- EMIT2(shl, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(xor, eax, eax) \
- LABEL(0)
+# define VALUE_LSL_REG_C \
+ VALUE_LOAD_REG \
+ EMIT2(test, cl, cl) \
+ EMIT1(jz, LABELREF(0, f)) \
+ EMIT2(cmp, KONST(0x20), cl) \
+ EMIT1(je, LABELREF(1, f)) \
+ EMIT1(ja, LABELREF(2, f)) \
+ EMIT2(shl, cl, eax) \
+ EMIT1(setc, bl) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(test, KONST(1), al) \
+ EMIT1(setnz, bl) \
+ EMIT2(xor, eax, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(2) \
+ EMIT2(xor, ebx, ebx) \
+ EMIT2(xor, eax, eax) \
+ LABEL(0)
+# define VALUE_LSL_REG_NC \
+ VALUE_LOAD_REG \
+ EMIT2(cmp, KONST(0x20), cl) \
+ EMIT1(jae, LABELREF(1, f)) \
+ EMIT2(shl, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(xor, eax, eax) \
+ LABEL(0)
// OP Rd,Rb,Rm LSR #
-#define VALUE_LSR_IMM_C \
- VALUE_LOAD_IMM \
- EMIT1(jz, LABELREF(1,f)) \
- EMIT2(shr, cl, eax) \
- EMIT1(setc, bl) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(test, eax, eax) \
- EMIT1(sets, bl) \
- EMIT2(xor, eax, eax) \
- LABEL(0)
-#define VALUE_LSR_IMM_NC \
- VALUE_LOAD_IMM \
- EMIT1(jz, LABELREF(1,f)) \
- EMIT2(shr, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(xor, eax, eax) \
- LABEL(0)
+# define VALUE_LSR_IMM_C \
+ VALUE_LOAD_IMM \
+ EMIT1(jz, LABELREF(1, f)) \
+ EMIT2(shr, cl, eax) \
+ EMIT1(setc, bl) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(test, eax, eax) \
+ EMIT1(sets, bl) \
+ EMIT2(xor, eax, eax) \
+ LABEL(0)
+# define VALUE_LSR_IMM_NC \
+ VALUE_LOAD_IMM \
+ EMIT1(jz, LABELREF(1, f)) \
+ EMIT2(shr, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(xor, eax, eax) \
+ LABEL(0)
// OP Rd,Rb,Rm LSR Rs
-#define VALUE_LSR_REG_C \
- VALUE_LOAD_REG \
- EMIT2(test, cl, cl) \
- EMIT1(jz, LABELREF(0,f)) \
- EMIT2(cmp, KONST(0x20), cl) \
- EMIT1(je, LABELREF(1,f)) \
- EMIT1(ja, LABELREF(2,f)) \
- EMIT2(shr, cl, eax) \
- EMIT1(setc, bl) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(test, eax, eax) \
- EMIT1(sets, bl) \
- EMIT2(xor, eax, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(2) \
- EMIT2(xor, ebx, ebx) \
- EMIT2(xor, eax, eax) \
- LABEL(0)
-#define VALUE_LSR_REG_NC \
- VALUE_LOAD_REG \
- EMIT2(cmp, KONST(0x20), cl) \
- EMIT1(jae, LABELREF(1,f)) \
- EMIT2(shr, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(xor, eax, eax) \
- LABEL(0)
+# define VALUE_LSR_REG_C \
+ VALUE_LOAD_REG \
+ EMIT2(test, cl, cl) \
+ EMIT1(jz, LABELREF(0, f)) \
+ EMIT2(cmp, KONST(0x20), cl) \
+ EMIT1(je, LABELREF(1, f)) \
+ EMIT1(ja, LABELREF(2, f)) \
+ EMIT2(shr, cl, eax) \
+ EMIT1(setc, bl) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(test, eax, eax) \
+ EMIT1(sets, bl) \
+ EMIT2(xor, eax, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(2) \
+ EMIT2(xor, ebx, ebx) \
+ EMIT2(xor, eax, eax) \
+ LABEL(0)
+# define VALUE_LSR_REG_NC \
+ VALUE_LOAD_REG \
+ EMIT2(cmp, KONST(0x20), cl) \
+ EMIT1(jae, LABELREF(1, f)) \
+ EMIT2(shr, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(xor, eax, eax) \
+ LABEL(0)
// OP Rd,Rb,Rm ASR #
-#define VALUE_ASR_IMM_C \
- VALUE_LOAD_IMM \
- EMIT1(jz, LABELREF(1,f)) \
- EMIT2(sar, cl, eax) \
- EMIT1(setc, bl) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(sar, KONST(31), eax) \
- EMIT1(sets, bl) \
- LABEL(0)
-#define VALUE_ASR_IMM_NC \
- VALUE_LOAD_IMM \
- EMIT1(jz, LABELREF(1,f)) \
- EMIT2(sar, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(sar, KONST(31), eax) \
- LABEL(0)
+# define VALUE_ASR_IMM_C \
+ VALUE_LOAD_IMM \
+ EMIT1(jz, LABELREF(1, f)) \
+ EMIT2(sar, cl, eax) \
+ EMIT1(setc, bl) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(sar, KONST(31), eax) \
+ EMIT1(sets, bl) \
+ LABEL(0)
+# define VALUE_ASR_IMM_NC \
+ VALUE_LOAD_IMM \
+ EMIT1(jz, LABELREF(1, f)) \
+ EMIT2(sar, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(sar, KONST(31), eax) \
+ LABEL(0)
// OP Rd,Rb,Rm ASR Rs
-#define VALUE_ASR_REG_C \
- VALUE_LOAD_REG \
- EMIT2(test, cl, cl) \
- EMIT1(jz, LABELREF(0,f)) \
- EMIT2(cmp, KONST(0x20), cl) \
- EMIT1(jae, LABELREF(1,f)) \
- EMIT2(sar, cl, eax) \
- EMIT1(setc, bl) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(sar, KONST(31), eax) \
- EMIT1(sets, bl) \
- LABEL(0)
-#define VALUE_ASR_REG_NC \
- VALUE_LOAD_REG \
- EMIT2(cmp, KONST(0x20), cl) \
- EMIT1(jae, LABELREF(1,f)) \
- EMIT2(sar, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(sar, KONST(31), eax) \
- LABEL(0)
+# define VALUE_ASR_REG_C \
+ VALUE_LOAD_REG \
+ EMIT2(test, cl, cl) \
+ EMIT1(jz, LABELREF(0, f)) \
+ EMIT2(cmp, KONST(0x20), cl) \
+ EMIT1(jae, LABELREF(1, f)) \
+ EMIT2(sar, cl, eax) \
+ EMIT1(setc, bl) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(sar, KONST(31), eax) \
+ EMIT1(sets, bl) \
+ LABEL(0)
+# define VALUE_ASR_REG_NC \
+ VALUE_LOAD_REG \
+ EMIT2(cmp, KONST(0x20), cl) \
+ EMIT1(jae, LABELREF(1, f)) \
+ EMIT2(sar, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(sar, KONST(31), eax) \
+ LABEL(0)
// OP Rd,Rb,Rm ROR #
-#define VALUE_ROR_IMM_C \
- VALUE_LOAD_IMM \
- EMIT1(jz, LABELREF(1,f)) \
- EMIT2(ror, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(bt, KONST(0), ebx) \
- EMIT2(rcr, KONST(1), eax) \
- LABEL(0) \
- EMIT1(setc, bl)
-#define VALUE_ROR_IMM_NC \
- VALUE_LOAD_IMM \
- EMIT1(jz, LABELREF(1,f)) \
- EMIT2(ror, cl, eax) \
- EMIT1(jmp, LABELREF(0,f)) \
- LABEL(1) \
- EMIT2(bt, KONST(0), VARL(C_FLAG)) \
- EMIT2(rcr, KONST(1), eax) \
- LABEL(0)
+# define VALUE_ROR_IMM_C \
+ VALUE_LOAD_IMM \
+ EMIT1(jz, LABELREF(1, f)) \
+ EMIT2(ror, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(bt, KONST(0), ebx) \
+ EMIT2(rcr, KONST(1), eax) \
+ LABEL(0) \
+ EMIT1(setc, bl)
+# define VALUE_ROR_IMM_NC \
+ VALUE_LOAD_IMM \
+ EMIT1(jz, LABELREF(1, f)) \
+ EMIT2(ror, cl, eax) \
+ EMIT1(jmp, LABELREF(0, f)) \
+ LABEL(1) \
+ EMIT2(bt, KONST(0), VARL(C_FLAG)) \
+ EMIT2(rcr, KONST(1), eax) \
+ LABEL(0)
// OP Rd,Rb,Rm ROR Rs
-#define VALUE_ROR_REG_C \
- VALUE_LOAD_REG \
- EMIT2(bt, KONST(0), ebx) \
- EMIT2(ror, cl, eax) \
- EMIT1(setc, bl)
-#define VALUE_ROR_REG_NC \
- VALUE_LOAD_REG \
- EMIT2(ror, cl, eax)
+# define VALUE_ROR_REG_C \
+ VALUE_LOAD_REG \
+ EMIT2(bt, KONST(0), ebx) \
+ EMIT2(ror, cl, eax) \
+ EMIT1(setc, bl)
+# define VALUE_ROR_REG_NC \
+ VALUE_LOAD_REG \
+ EMIT2(ror, cl, eax)
// OP Rd,Rb,# ROR #
-#define VALUE_IMM_C \
- EMIT2(movzx, ch, ecx) \
- EMIT2(add, ecx, ecx) \
- EMIT2(movzx, al, eax) \
- EMIT2(bt, KONST(0), ebx) \
- EMIT2(ror, cl, eax) \
- EMIT1(setc, bl)
-#define VALUE_IMM_NC \
- EMIT2(movzx, ch, ecx) \
- EMIT2(add, ecx, ecx) \
- EMIT2(movzx, al, eax) \
- EMIT2(ror, cl, eax)
+# define VALUE_IMM_C \
+ EMIT2(movzx, ch, ecx) \
+ EMIT2(add, ecx, ecx) \
+ EMIT2(movzx, al, eax) \
+ EMIT2(bt, KONST(0), ebx) \
+ EMIT2(ror, cl, eax) \
+ EMIT1(setc, bl)
+# define VALUE_IMM_NC \
+ EMIT2(movzx, ch, ecx) \
+ EMIT2(add, ecx, ecx) \
+ EMIT2(movzx, al, eax) \
+ EMIT2(ror, cl, eax)
// Macros to perform ALU ops
// Set condition codes iff the destination register is not R15 (PC)
-#define CHECK_PC(OP, SETCOND) \
- EMIT2(cmp, KONST(0x3C), esi) \
- EMIT1(je, LABELREF(8,f)) \
- OP SETCOND \
- EMIT1(jmp, LABELREF(9,f)) \
- LABEL(8) \
- OP \
- LABEL(9)
-
-#define OP_AND \
- EMIT2(and, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_ANDS CHECK_PC(OP_AND, SETCOND_LOGICAL)
-#define OP_EOR \
- EMIT2(xor, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_EORS CHECK_PC(OP_EOR, SETCOND_LOGICAL)
-#define OP_SUB \
- EMIT2(sub, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_SUBS CHECK_PC(OP_SUB, SETCOND_SUB)
-#define OP_RSB \
- EMIT2(sub, edx, eax) \
- EMIT2(mov, eax, REGREF1(esi))
-#define OP_RSBS CHECK_PC(OP_RSB, SETCOND_SUB)
-#define OP_ADD \
- EMIT2(add, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_ADDS CHECK_PC(OP_ADD, SETCOND_ADD)
-#define OP_ADC \
- EMIT2(bt, KONST(0), VARL(C_FLAG)) \
- EMIT2(adc, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_ADCS CHECK_PC(OP_ADC, SETCOND_ADD)
-#define OP_SBC \
- EMIT2(bt, KONST(0), VARL(C_FLAG)) \
- EMIT0(cmc) \
- EMIT2(sbb, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_SBCS CHECK_PC(OP_SBC, SETCOND_SUB)
-#define OP_RSC \
- EMIT2(bt, KONST(0), VARL(C_FLAG)) \
- EMIT0(cmc) \
- EMIT2(sbb, edx, eax) \
- EMIT2(mov, eax, REGREF1(esi))
-#define OP_RSCS CHECK_PC(OP_RSC, SETCOND_SUB)
-#define OP_TST \
- EMIT2(and, eax, edx) \
- SETCOND_LOGICAL
-#define OP_TEQ \
- EMIT2(xor, eax, edx) \
- SETCOND_LOGICAL
-#define OP_CMP \
- EMIT2(sub, eax, edx) \
- SETCOND_SUB
-#define OP_CMN \
- EMIT2(add, eax, edx) \
- SETCOND_ADD
-#define OP_ORR \
- EMIT2(or, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_ORRS CHECK_PC(OP_ORR, SETCOND_LOGICAL)
-#define OP_MOV \
- EMIT2(mov, eax, REGREF1(esi))
-#define OP_MOVS CHECK_PC(EMIT2(test,eax,eax) EMIT2(mov,eax,REGREF1(esi)), SETCOND_LOGICAL)
-#define OP_BIC \
- EMIT1(not, eax) \
- EMIT2(and, eax, edx) \
- EMIT2(mov, edx, REGREF1(esi))
-#define OP_BICS CHECK_PC(OP_BIC, SETCOND_LOGICAL)
-#define OP_MVN \
- EMIT1(not, eax) \
- EMIT2(mov, eax, REGREF1(esi))
-#define OP_MVNS CHECK_PC(OP_MVN EMIT2(test,eax,eax), SETCOND_LOGICAL)
+# define CHECK_PC(OP, SETCOND) \
+ EMIT2(cmp, KONST(0x3C), esi) \
+ EMIT1(je, LABELREF(8, f)) \
+ OP SETCOND \
+ EMIT1(jmp, LABELREF(9, f)) \
+ LABEL(8) \
+ OP \
+ LABEL(9)
+
+# define OP_AND \
+ EMIT2(and, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_ANDS CHECK_PC(OP_AND, SETCOND_LOGICAL)
+# define OP_EOR \
+ EMIT2(xor, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_EORS CHECK_PC(OP_EOR, SETCOND_LOGICAL)
+# define OP_SUB \
+ EMIT2(sub, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_SUBS CHECK_PC(OP_SUB, SETCOND_SUB)
+# define OP_RSB \
+ EMIT2(sub, edx, eax) \
+ EMIT2(mov, eax, REGREF1(esi))
+# define OP_RSBS CHECK_PC(OP_RSB, SETCOND_SUB)
+# define OP_ADD \
+ EMIT2(add, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_ADDS CHECK_PC(OP_ADD, SETCOND_ADD)
+# define OP_ADC \
+ EMIT2(bt, KONST(0), VARL(C_FLAG)) \
+ EMIT2(adc, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_ADCS CHECK_PC(OP_ADC, SETCOND_ADD)
+# define OP_SBC \
+ EMIT2(bt, KONST(0), VARL(C_FLAG)) \
+ EMIT0(cmc) \
+ EMIT2(sbb, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_SBCS CHECK_PC(OP_SBC, SETCOND_SUB)
+# define OP_RSC \
+ EMIT2(bt, KONST(0), VARL(C_FLAG)) \
+ EMIT0(cmc) \
+ EMIT2(sbb, edx, eax) \
+ EMIT2(mov, eax, REGREF1(esi))
+# define OP_RSCS CHECK_PC(OP_RSC, SETCOND_SUB)
+# define OP_TST \
+ EMIT2(and, eax, edx) \
+ SETCOND_LOGICAL
+# define OP_TEQ \
+ EMIT2(xor, eax, edx) \
+ SETCOND_LOGICAL
+# define OP_CMP \
+ EMIT2(sub, eax, edx) \
+ SETCOND_SUB
+# define OP_CMN \
+ EMIT2(add, eax, edx) \
+ SETCOND_ADD
+# define OP_ORR \
+ EMIT2(or, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_ORRS CHECK_PC(OP_ORR, SETCOND_LOGICAL)
+# define OP_MOV \
+ EMIT2(mov, eax, REGREF1(esi))
+# define OP_MOVS CHECK_PC(EMIT2(test, eax, eax) EMIT2(mov, eax, REGREF1(esi)), SETCOND_LOGICAL)
+# define OP_BIC \
+ EMIT1(not, eax) \
+ EMIT2(and, eax, edx) \
+ EMIT2(mov, edx, REGREF1(esi))
+# define OP_BICS CHECK_PC(OP_BIC, SETCOND_LOGICAL)
+# define OP_MVN \
+ EMIT1(not, eax) \
+ EMIT2(mov, eax, REGREF1(esi))
+# define OP_MVNS CHECK_PC(OP_MVN EMIT2(test, eax, eax), SETCOND_LOGICAL)
// ALU cleanup macro
-#define ALU_FINISH ALU_TRAILER
+# define ALU_FINISH ALU_TRAILER
// End of ALU macros
//X//#endif //_MSC_VER
-
-#ifdef __GNUC__
-
-#define ROR_IMM_MSR \
- asm ("ror %%cl, %%eax;" \
- : "=a" (value) \
- : "a" (opcode & 0xFF), "c" (shift));
-
-#define ROR_OFFSET \
- asm("ror %%cl, %0" \
- : "=r" (offset) \
- : "0" (offset), "c" (shift));
-
-#define RRX_OFFSET \
- asm(EMIT2(btl,KONST(0),VAR(C_FLAG)) \
- "rcr $1, %0" \
- : "=r" (offset) \
- : "0" (offset));
-
-#else // !__GNUC__, i.e. Visual C++
-
-#define ROR_IMM_MSR \
- __asm { \
- __asm mov ecx, shift \
- __asm ror value, cl \
- }
-
-
-#define ROR_OFFSET \
- __asm { \
- __asm mov ecx, shift \
- __asm ror offset, cl \
- }
-
-#define RRX_OFFSET \
- __asm { \
- __asm bt dword ptr C_FLAG, 0 \
- __asm rcr offset, 1 \
- }
-
-#endif // !__GNUC__
-
-#endif // !__POWERPC__
+# ifdef __GNUC__
+# define ROR_IMM_MSR \
+ asm("ror %%cl, %%eax;" \
+ : "=a" (value) \
+ : "a" (opcode & 0xFF), "c" (shift));
+
+# define ROR_OFFSET \
+ asm("ror %%cl, %0" \
+ : "=r" (offset) \
+ : "0" (offset), "c" (shift));
+
+# define RRX_OFFSET \
+ asm(EMIT2(btl, KONST(0), VAR(C_FLAG)) \
+ "rcr $1, %0" \
+ : "=r" (offset) \
+ : "0" (offset));
+
+# else // !__GNUC__, i.e. Visual C++
+# define ROR_IMM_MSR \
+ __asm \
+ { \
+ __asm mov ecx, shift \
+ __asm ror value, cl \
+ }
+
+# define ROR_OFFSET \
+ __asm \
+ { \
+ __asm mov ecx, shift \
+ __asm ror offset, cl \
+ }
+
+# define RRX_OFFSET \
+ __asm \
+ { \
+ __asm bt dword ptr C_FLAG, 0 \
+ __asm rcr offset, 1 \
+ }
+
+# endif // !__GNUC__
+# endif // !__POWERPC__
#endif // !C_CORE
// C core
#define C_SETCOND_LOGICAL \
- N_FLAG = ((int32_t)res < 0) ? true : false; \
- Z_FLAG = (res == 0) ? true : false; \
- C_FLAG = C_OUT;
+ N_FLAG = static_cast<int32_t>(res) < 0; \
+ Z_FLAG = !res; \
+ C_FLAG = C_OUT;
#define C_SETCOND_ADD \
- N_FLAG = ((int32_t)res < 0) ? true : false; \
- Z_FLAG = (res == 0) ? true : false; \
- V_FLAG = ((NEG(lhs) & NEG(rhs) & POS(res)) | \
- (POS(lhs) & POS(rhs) & NEG(res))) ? true : false;\
- C_FLAG = ((NEG(lhs) & NEG(rhs)) | \
- (NEG(lhs) & POS(res)) | \
- (NEG(rhs) & POS(res))) ? true : false;
+ N_FLAG = static_cast<int32_t>(res) < 0; \
+ Z_FLAG = !res; \
+ V_FLAG = !!((NEG(lhs) & NEG(rhs) & POS(res)) | (POS(lhs) & POS(rhs) & NEG(res))); \
+ C_FLAG = !!((NEG(lhs) & NEG(rhs)) | (NEG(lhs) & POS(res)) | (NEG(rhs) & POS(res)));
#define C_SETCOND_SUB \
- N_FLAG = ((int32_t)res < 0) ? true : false; \
- Z_FLAG = (res == 0) ? true : false; \
- V_FLAG = ((NEG(lhs) & POS(rhs) & POS(res)) | \
- (POS(lhs) & NEG(rhs) & NEG(res))) ? true : false;\
- C_FLAG = ((NEG(lhs) & POS(rhs)) | \
- (NEG(lhs) & POS(res)) | \
- (POS(rhs) & POS(res))) ? true : false;
+ N_FLAG = static_cast<int32_t>(res) < 0; \
+ Z_FLAG = !res; \
+ V_FLAG = !!((NEG(lhs) & POS(rhs) & POS(res)) | (POS(lhs) & NEG(rhs) & NEG(res))); \
+ C_FLAG = !!((NEG(lhs) & POS(rhs)) | (NEG(lhs) & POS(res)) | (POS(rhs) & POS(res)));
#ifndef ALU_INIT_C
- #define ALU_INIT_C \
- int dest = (opcode>>12) & 15; \
- bool C_OUT = C_FLAG; \
- uint32_t value;
+# define ALU_INIT_C \
+ int dest = (opcode >> 12) & 15; \
+ bool C_OUT = C_FLAG; \
+ uint32_t value;
#endif
// OP Rd,Rb,Rm LSL #
#ifndef VALUE_LSL_IMM_C
- #define VALUE_LSL_IMM_C \
- unsigned int shift = (opcode >> 7) & 0x1F; \
- if (LIKELY(!shift)) { /* LSL #0 most common? */ \
- value = reg[opcode & 0x0F].I; \
- } else { \
- uint32_t v = reg[opcode & 0x0F].I; \
- C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
- value = v << shift; \
- }
+# define VALUE_LSL_IMM_C \
+ unsigned shift = (opcode >> 7) & 0x1F; \
+ if (LIKELY(!shift)) /* LSL #0 most common? */ \
+ value = reg[opcode & 0x0F].I; \
+ else \
+ { \
+ uint32_t v = reg[opcode & 0x0F].I; \
+ C_OUT = !!((v >> (32 - shift)) & 1); \
+ value = v << shift; \
+ }
#endif
// OP Rd,Rb,Rm LSL Rs
#ifndef VALUE_LSL_REG_C
- #define VALUE_LSL_REG_C \
- uint32_t shift = reg[(opcode >> 8)&15].B.B0; \
- uint32_t rm = reg[opcode & 0x0F].I; \
- if((opcode & 0x0F) == 15) { \
- rm += 4; \
- } \
- if (LIKELY(shift)) { \
- if (shift == 32) { \
- value = 0; \
- C_OUT = (rm & 1 ? true : false); \
- } else if (LIKELY(shift < 32)) { \
- uint32_t v = rm; \
- C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
- value = v << shift; \
- } else { \
- value = 0; \
- C_OUT = false; \
- } \
- } else { \
- value = rm; \
- }
+# define VALUE_LSL_REG_C \
+ uint32_t shift = reg[(opcode >> 8) & 15].B.B0; \
+ uint32_t rm = reg[opcode & 0x0F].I; \
+ if ((opcode & 0x0F) == 15) \
+ rm += 4; \
+ if (LIKELY(shift)) \
+ { \
+ if (shift == 32) \
+ { \
+ value = 0; \
+ C_OUT = !!(rm & 1); \
+ } \
+ else if (LIKELY(shift < 32)) \
+ { \
+ uint32_t v = rm; \
+ C_OUT = !!((v >> (32 - shift)) & 1); \
+ value = v << shift; \
+ } \
+ else \
+ { \
+ value = 0; \
+ C_OUT = false; \
+ } \
+ } \
+ else
+ value = rm;
#endif
// OP Rd,Rb,Rm LSR #
#ifndef VALUE_LSR_IMM_C
- #define VALUE_LSR_IMM_C \
- uint32_t shift = (opcode >> 7) & 0x1F; \
- if (LIKELY(shift)) { \
- uint32_t v = reg[opcode & 0x0F].I; \
- C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
- value = v >> shift; \
- } else { \
- value = 0; \
- C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
- }
+# define VALUE_LSR_IMM_C \
+ uint32_t shift = (opcode >> 7) & 0x1F; \
+ if (LIKELY(shift)) \
+ { \
+ uint32_t v = reg[opcode & 0x0F].I; \
+ C_OUT = !!((v >> (shift - 1)) & 1); \
+ value = v >> shift; \
+ } \
+ else \
+ { \
+ value = 0; \
+ C_OUT = !!(reg[opcode & 0x0F].I & 0x80000000); \
+ }
#endif
// OP Rd,Rb,Rm LSR Rs
#ifndef VALUE_LSR_REG_C
- #define VALUE_LSR_REG_C \
- unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
- uint32_t rm = reg[opcode & 0x0F].I; \
- if((opcode & 0x0F) == 15) { \
- rm += 4; \
- } \
- if (LIKELY(shift)) { \
- if (shift == 32) { \
- value = 0; \
- C_OUT = (rm & 0x80000000 ? true : false);\
- } else if (LIKELY(shift < 32)) { \
- uint32_t v = rm; \
- C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
- value = v >> shift; \
- } else { \
- value = 0; \
- C_OUT = false; \
- } \
- } else { \
- value = rm; \
- }
+# define VALUE_LSR_REG_C \
+ unsigned shift = reg[(opcode >> 8) & 15].B.B0; \
+ uint32_t rm = reg[opcode & 0x0F].I; \
+ if ((opcode & 0x0F) == 15) \
+ rm += 4; \
+ if (LIKELY(shift)) \
+ { \
+ if (shift == 32) \
+ { \
+ value = 0; \
+ C_OUT = !!(rm & 0x80000000); \
+ } \
+ else if (LIKELY(shift < 32)) \
+ { \
+ uint32_t v = rm; \
+ C_OUT = !!((v >> (shift - 1)) & 1); \
+ value = v >> shift; \
+ } \
+ else \
+ { \
+ value = 0; \
+ C_OUT = false; \
+ } \
+ } \
+ else
+ value = rm;
#endif
// OP Rd,Rb,Rm ASR #
#ifndef VALUE_ASR_IMM_C
- #define VALUE_ASR_IMM_C \
- unsigned int shift = (opcode >> 7) & 0x1F; \
- if (LIKELY(shift)) { \
- /* VC++ BUG: u32 v; (s32)v>>n is optimized to shr! */ \
- int32_t v = reg[opcode & 0x0F].I; \
- C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
- value = v >> (int)shift; \
- } else { \
- if (reg[opcode & 0x0F].I & 0x80000000) { \
- value = 0xFFFFFFFF; \
- C_OUT = true; \
- } else { \
- value = 0; \
- C_OUT = false; \
- } \
- }
+# define VALUE_ASR_IMM_C \
+ unsigned shift = (opcode >> 7) & 0x1F; \
+ if (LIKELY(shift)) \
+ { \
+ /* VC++ BUG: u32 v; (s32)v>>n is optimized to shr! */ \
+ int32_t v = reg[opcode & 0x0F].I; \
+ C_OUT = !!((v >> static_cast<int>(shift - 1)) & 1); \
+ value = v >> static_cast<int>(shift); \
+ } \
+ else \
+ { \
+ if (reg[opcode & 0x0F].I & 0x80000000) \
+ { \
+ value = 0xFFFFFFFF; \
+ C_OUT = true; \
+ } \
+ else \
+ { \
+ value = 0; \
+ C_OUT = false; \
+ } \
+ }
#endif
// OP Rd,Rb,Rm ASR Rs
#ifndef VALUE_ASR_REG_C
- #define VALUE_ASR_REG_C \
- unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
- uint32_t rm = reg[opcode & 0x0F].I; \
- if((opcode & 0x0F) == 15) { \
- rm += 4; \
- } \
- if (LIKELY(shift < 32)) { \
- if (LIKELY(shift)) { \
- int32_t v = rm; \
- C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
- value = v >> (int)shift; \
- } else { \
- value = rm; \
- } \
- } else { \
- if (reg[opcode & 0x0F].I & 0x80000000) { \
- value = 0xFFFFFFFF; \
- C_OUT = true; \
- } else { \
- value = 0; \
- C_OUT = false; \
- } \
- }
+# define VALUE_ASR_REG_C \
+ unsigned shift = reg[(opcode >> 8) & 15].B.B0; \
+ uint32_t rm = reg[opcode & 0x0F].I; \
+ if ((opcode & 0x0F) == 15) \
+ rm += 4; \
+ if (LIKELY(shift < 32)) \
+ { \
+ if (LIKELY(shift)) \
+ { \
+ int32_t v = rm; \
+ C_OUT = !!((v >> static_cast<int>(shift - 1)) & 1); \
+ value = v >> static_cast<int>(shift); \
+ } \
+ else \
+ value = rm; \
+ } \
+ else \
+ { \
+ if (reg[opcode & 0x0F].I & 0x80000000) \
+ { \
+ value = 0xFFFFFFFF; \
+ C_OUT = true; \
+ } \
+ else \
+ { \
+ value = 0; \
+ C_OUT = false; \
+ } \
+ }
#endif
// OP Rd,Rb,Rm ROR #
#ifndef VALUE_ROR_IMM_C
- #define VALUE_ROR_IMM_C \
- unsigned int shift = (opcode >> 7) & 0x1F; \
- if (LIKELY(shift)) { \
- uint32_t v = reg[opcode & 0x0F].I; \
- C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
- value = ((v << (32 - shift)) | \
- (v >> shift)); \
- } else { \
- uint32_t v = reg[opcode & 0x0F].I; \
- C_OUT = (v & 1) ? true : false; \
- value = ((v >> 1) | \
- (C_FLAG << 31)); \
- }
+# define VALUE_ROR_IMM_C \
+ unsigned shift = (opcode >> 7) & 0x1F; \
+ if (LIKELY(shift)) \
+ { \
+ uint32_t v = reg[opcode & 0x0F].I; \
+ C_OUT = !!((v >> (shift - 1)) & 1); \
+ value = (v << (32 - shift)) | (v >> shift); \
+ } \
+ else \
+ { \
+ uint32_t v = reg[opcode & 0x0F].I; \
+ C_OUT = !!(v & 1); \
+ value = (v >> 1) | (C_FLAG << 31); \
+ }
#endif
// OP Rd,Rb,Rm ROR Rs
#ifndef VALUE_ROR_REG_C
- #define VALUE_ROR_REG_C \
- unsigned int shift = reg[(opcode >> 8)&15].B.B0; \
- uint32_t rm = reg[opcode & 0x0F].I; \
- if((opcode & 0x0F) == 15) { \
- rm += 4; \
- } \
- if (LIKELY(shift & 0x1F)) { \
- uint32_t v = rm; \
- C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
- value = ((v << (32 - shift)) | \
- (v >> shift)); \
- } else { \
- value = rm; \
- if (shift) \
- C_OUT = (value & 0x80000000 ? true : false);\
- }
+# define VALUE_ROR_REG_C \
+ unsigned shift = reg[(opcode >> 8) & 15].B.B0; \
+ uint32_t rm = reg[opcode & 0x0F].I; \
+ if ((opcode & 0x0F) == 15)
+ rm += 4; \
+ if (LIKELY(shift & 0x1F)) \
+ { \
+ uint32_t v = rm; \
+ C_OUT = !((v >> (shift - 1)) & 1); \
+ value = (v << (32 - shift)) | (v >> shift); \
+ } \
+ else \
+ { \
+ value = rm; \
+ if (shift) \
+ C_OUT = !!(value & 0x80000000); \
+ }
#endif
// OP Rd,Rb,# ROR #
#ifndef VALUE_IMM_C
- #define VALUE_IMM_C \
- int shift = (opcode & 0xF00) >> 7; \
- if (UNLIKELY(shift)) { \
- uint32_t v = opcode & 0xFF; \
- C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
- value = ((v << (32 - shift)) | \
- (v >> shift)); \
- } else { \
- value = opcode & 0xFF; \
- }
+# define VALUE_IMM_C \
+ int shift = (opcode & 0xF00) >> 7; \
+ if (UNLIKELY(shift)) \
+ { \
+ uint32_t v = opcode & 0xFF; \
+ C_OUT = !!((v >> (shift - 1)) & 1); \
+ value = (v << (32 - shift)) | (v >> shift); \
+ } \
+ else \
+ value = opcode & 0xFF;
#endif
// Make the non-carry versions default to the carry versions
// (this is fine for C--the compiler will optimize the dead code out)
#ifndef ALU_INIT_NC
- #define ALU_INIT_NC ALU_INIT_C
+# define ALU_INIT_NC ALU_INIT_C
#endif
#ifndef VALUE_LSL_IMM_NC
- #define VALUE_LSL_IMM_NC VALUE_LSL_IMM_C
+# define VALUE_LSL_IMM_NC VALUE_LSL_IMM_C
#endif
#ifndef VALUE_LSL_REG_NC
- #define VALUE_LSL_REG_NC VALUE_LSL_REG_C
+# define VALUE_LSL_REG_NC VALUE_LSL_REG_C
#endif
#ifndef VALUE_LSR_IMM_NC
- #define VALUE_LSR_IMM_NC VALUE_LSR_IMM_C
+# define VALUE_LSR_IMM_NC VALUE_LSR_IMM_C
#endif
#ifndef VALUE_LSR_REG_NC
- #define VALUE_LSR_REG_NC VALUE_LSR_REG_C
+# define VALUE_LSR_REG_NC VALUE_LSR_REG_C
#endif
#ifndef VALUE_ASR_IMM_NC
- #define VALUE_ASR_IMM_NC VALUE_ASR_IMM_C
+# define VALUE_ASR_IMM_NC VALUE_ASR_IMM_C
#endif
#ifndef VALUE_ASR_REG_NC
- #define VALUE_ASR_REG_NC VALUE_ASR_REG_C
+# define VALUE_ASR_REG_NC VALUE_ASR_REG_C
#endif
#ifndef VALUE_ROR_IMM_NC
- #define VALUE_ROR_IMM_NC VALUE_ROR_IMM_C
+# define VALUE_ROR_IMM_NC VALUE_ROR_IMM_C
#endif
#ifndef VALUE_ROR_REG_NC
- #define VALUE_ROR_REG_NC VALUE_ROR_REG_C
+# define VALUE_ROR_REG_NC VALUE_ROR_REG_C
#endif
#ifndef VALUE_IMM_NC
- #define VALUE_IMM_NC VALUE_IMM_C
+# define VALUE_IMM_NC VALUE_IMM_C
#endif
#define C_CHECK_PC(SETCOND) if (LIKELY(dest != 15)) { SETCOND }
#ifndef OP_AND
- #define OP_AND \
- uint32_t res = reg[(opcode>>16)&15].I & value; \
- reg[dest].I = res;
+# define OP_AND \
+ uint32_t res = reg[(opcode >> 16) & 15].I & value; \
+ reg[dest].I = res;
#endif
#ifndef OP_ANDS
- #define OP_ANDS OP_AND C_CHECK_PC(C_SETCOND_LOGICAL)
+# define OP_ANDS OP_AND C_CHECK_PC(C_SETCOND_LOGICAL)
#endif
#ifndef OP_EOR
- #define OP_EOR \
- uint32_t res = reg[(opcode>>16)&15].I ^ value; \
- reg[dest].I = res;
+# define OP_EOR \
+ uint32_t res = reg[(opcode >> 16) & 15].I ^ value; \
+ reg[dest].I = res;
#endif
#ifndef OP_EORS
- #define OP_EORS OP_EOR C_CHECK_PC(C_SETCOND_LOGICAL)
+# define OP_EORS OP_EOR C_CHECK_PC(C_SETCOND_LOGICAL)
#endif
#ifndef OP_SUB
- #define OP_SUB \
- uint32_t lhs = reg[(opcode>>16)&15].I; \
- uint32_t rhs = value; \
- uint32_t res = lhs - rhs; \
- reg[dest].I = res;
+# define OP_SUB \
+ uint32_t lhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs - rhs; \
+ reg[dest].I = res;
#endif
#ifndef OP_SUBS
- #define OP_SUBS OP_SUB C_CHECK_PC(C_SETCOND_SUB)
+# define OP_SUBS OP_SUB C_CHECK_PC(C_SETCOND_SUB)
#endif
#ifndef OP_RSB
- #define OP_RSB \
- uint32_t lhs = value; \
- uint32_t rhs = reg[(opcode>>16)&15].I; \
- uint32_t res = lhs - rhs; \
- reg[dest].I = res;
+# define OP_RSB \
+ uint32_t lhs = value; \
+ uint32_t rhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t res = lhs - rhs; \
+ reg[dest].I = res;
#endif
#ifndef OP_RSBS
- #define OP_RSBS OP_RSB C_CHECK_PC(C_SETCOND_SUB)
+# define OP_RSBS OP_RSB C_CHECK_PC(C_SETCOND_SUB)
#endif
#ifndef OP_ADD
- #define OP_ADD \
- uint32_t lhs = reg[(opcode>>16)&15].I; \
- uint32_t rhs = value; \
- uint32_t res = lhs + rhs; \
- reg[dest].I = res;
+# define OP_ADD \
+ uint32_t lhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs + rhs; \
+ reg[dest].I = res;
#endif
#ifndef OP_ADDS
- #define OP_ADDS OP_ADD C_CHECK_PC(C_SETCOND_ADD)
+# define OP_ADDS OP_ADD C_CHECK_PC(C_SETCOND_ADD)
#endif
#ifndef OP_ADC
- #define OP_ADC \
- uint32_t lhs = reg[(opcode>>16)&15].I; \
- uint32_t rhs = value; \
- uint32_t res = lhs + rhs + (uint32_t)C_FLAG; \
- reg[dest].I = res;
+# define OP_ADC \
+ uint32_t lhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs + rhs + static_cast<uint32_t>(C_FLAG); \
+ reg[dest].I = res;
#endif
#ifndef OP_ADCS
- #define OP_ADCS OP_ADC C_CHECK_PC(C_SETCOND_ADD)
+# define OP_ADCS OP_ADC C_CHECK_PC(C_SETCOND_ADD)
#endif
#ifndef OP_SBC
- #define OP_SBC \
- uint32_t lhs = reg[(opcode>>16)&15].I; \
- uint32_t rhs = value; \
- uint32_t res = lhs - rhs - !((uint32_t)C_FLAG); \
- reg[dest].I = res;
+# define OP_SBC \
+ uint32_t lhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs - rhs - !static_cast<uint32_t>(C_FLAG); \
+ reg[dest].I = res;
#endif
#ifndef OP_SBCS
- #define OP_SBCS OP_SBC C_CHECK_PC(C_SETCOND_SUB)
+# define OP_SBCS OP_SBC C_CHECK_PC(C_SETCOND_SUB)
#endif
#ifndef OP_RSC
- #define OP_RSC \
- uint32_t lhs = value; \
- uint32_t rhs = reg[(opcode>>16)&15].I; \
- uint32_t res = lhs - rhs - !((uint32_t)C_FLAG); \
- reg[dest].I = res;
+# define OP_RSC \
+ uint32_t lhs = value; \
+ uint32_t rhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t res = lhs - rhs - !static_cast<uint32_t>(C_FLAG); \
+ reg[dest].I = res;
#endif
#ifndef OP_RSCS
- #define OP_RSCS OP_RSC C_CHECK_PC(C_SETCOND_SUB)
+# define OP_RSCS OP_RSC C_CHECK_PC(C_SETCOND_SUB)
#endif
#ifndef OP_TST
- #define OP_TST \
- uint32_t res = reg[(opcode >> 16) & 0x0F].I & value; \
- C_SETCOND_LOGICAL;
+# define OP_TST \
+ uint32_t res = reg[(opcode >> 16) & 0x0F].I & value; \
+ C_SETCOND_LOGICAL;
#endif
#ifndef OP_TEQ
- #define OP_TEQ \
- uint32_t res = reg[(opcode >> 16) & 0x0F].I ^ value; \
- C_SETCOND_LOGICAL;
+# define OP_TEQ \
+ uint32_t res = reg[(opcode >> 16) & 0x0F].I ^ value; \
+ C_SETCOND_LOGICAL;
#endif
#ifndef OP_CMP
- #define OP_CMP \
- uint32_t lhs = reg[(opcode>>16)&15].I; \
- uint32_t rhs = value; \
- uint32_t res = lhs - rhs; \
- C_SETCOND_SUB;
+# define OP_CMP \
+ uint32_t lhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs - rhs; \
+ C_SETCOND_SUB;
#endif
#ifndef OP_CMN
- #define OP_CMN \
- uint32_t lhs = reg[(opcode>>16)&15].I; \
- uint32_t rhs = value; \
- uint32_t res = lhs + rhs; \
- C_SETCOND_ADD;
+# define OP_CMN \
+ uint32_t lhs = reg[(opcode >> 16) & 15].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs + rhs; \
+ C_SETCOND_ADD;
#endif
#ifndef OP_ORR
- #define OP_ORR \
- uint32_t res = reg[(opcode >> 16) & 0x0F].I | value; \
- reg[dest].I = res;
+# define OP_ORR \
+ uint32_t res = reg[(opcode >> 16) & 0x0F].I | value; \
+ reg[dest].I = res;
#endif
#ifndef OP_ORRS
- #define OP_ORRS OP_ORR C_CHECK_PC(C_SETCOND_LOGICAL)
+# define OP_ORRS OP_ORR C_CHECK_PC(C_SETCOND_LOGICAL)
#endif
#ifndef OP_MOV
- #define OP_MOV \
- uint32_t res = value; \
- reg[dest].I = res;
+# define OP_MOV \
+ uint32_t res = value; \
+ reg[dest].I = res;
#endif
#ifndef OP_MOVS
- #define OP_MOVS OP_MOV C_CHECK_PC(C_SETCOND_LOGICAL)
+# define OP_MOVS OP_MOV C_CHECK_PC(C_SETCOND_LOGICAL)
#endif
#ifndef OP_BIC
- #define OP_BIC \
- uint32_t res = reg[(opcode >> 16) & 0x0F].I & (~value); \
- reg[dest].I = res;
+# define OP_BIC \
+ uint32_t res = reg[(opcode >> 16) & 0x0F].I & ~value; \
+ reg[dest].I = res;
#endif
#ifndef OP_BICS
- #define OP_BICS OP_BIC C_CHECK_PC(C_SETCOND_LOGICAL)
+# define OP_BICS OP_BIC C_CHECK_PC(C_SETCOND_LOGICAL)
#endif
#ifndef OP_MVN
- #define OP_MVN \
- uint32_t res = ~value; \
- reg[dest].I = res;
+# define OP_MVN \
+ uint32_t res = ~value; \
+ reg[dest].I = res;
#endif
#ifndef OP_MVNS
- #define OP_MVNS OP_MVN C_CHECK_PC(C_SETCOND_LOGICAL)
+# define OP_MVNS OP_MVN C_CHECK_PC(C_SETCOND_LOGICAL)
#endif
#ifndef SETCOND_NONE
- #define SETCOND_NONE /*nothing*/
+# define SETCOND_NONE /*nothing*/
#endif
#ifndef SETCOND_MUL
- #define SETCOND_MUL \
- N_FLAG = ((int32_t)reg[dest].I < 0) ? true : false; \
- Z_FLAG = reg[dest].I ? false : true;
+# define SETCOND_MUL \
+ N_FLAG = static_cast<int32_t>(reg[dest].I) < 0; \
+ Z_FLAG = !reg[dest].I;
#endif
#ifndef SETCOND_MULL
- #define SETCOND_MULL \
- N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
- Z_FLAG = reg[dest].I || reg[acc].I ? false : true;
+# define SETCOND_MULL \
+ N_FLAG = !!(reg[dest].I & 0x80000000); \
+ Z_FLAG = !(reg[dest].I || reg[acc].I);
#endif
#ifndef ALU_FINISH
- #define ALU_FINISH /*nothing*/
+# define ALU_FINISH /*nothing*/
#endif
#ifndef ROR_IMM_MSR
- #define ROR_IMM_MSR \
- uint32_t v = opcode & 0xff; \
- value = ((v << (32 - shift)) | (v >> shift));
+# define ROR_IMM_MSR \
+ uint32_t v = opcode & 0xff; \
+ value = (v << (32 - shift)) | (v >> shift);
#endif
#ifndef ROR_OFFSET
- #define ROR_OFFSET \
- offset = ((offset << (32 - shift)) | (offset >> shift));
+# define ROR_OFFSET \
+ offset = (offset << (32 - shift)) | (offset >> shift);
#endif
#ifndef RRX_OFFSET
- #define RRX_OFFSET \
- offset = ((offset >> 1) | ((int)C_FLAG << 31));
+# define RRX_OFFSET \
+ offset = (offset >> 1) | (static_cast<int>(C_FLAG) << 31);
#endif
// ALU ops (except multiply) //////////////////////////////////////////////
@@ -1117,62 +1052,62 @@
// ISREGSHIFT: 1 for insns of the form ...,Rn LSL/etc Rs; 0 otherwise
// ALU_INIT, GETVALUE, OP, and ALU_FINISH are concatenated in order.
#define ALU_INSN(ALU_INIT, GETVALUE, OP, MODECHANGE, ISREGSHIFT) \
- ALU_INIT GETVALUE OP ALU_FINISH; \
- if (LIKELY((opcode & 0x0000F000) != 0x0000F000)) { \
- clockTicks = 1 + ISREGSHIFT \
- + codeTicksAccessSeq32(armNextPC); \
- } else { \
- MODECHANGE; \
- if (armState) { \
- reg[15].I &= 0xFFFFFFFC; \
- armNextPC = reg[15].I; \
- reg[15].I += 4; \
- ARM_PREFETCH; \
- } else { \
- reg[15].I &= 0xFFFFFFFE; \
- armNextPC = reg[15].I; \
- reg[15].I += 2; \
- THUMB_PREFETCH; \
- } \
- clockTicks = 3 + ISREGSHIFT \
- + codeTicksAccess32(armNextPC) \
- + codeTicksAccessSeq32(armNextPC) \
- + codeTicksAccessSeq32(armNextPC); \
- }
+ ALU_INIT GETVALUE OP ALU_FINISH; \
+ if (LIKELY((opcode & 0x0000F000) != 0x0000F000)) \
+ clockTicks = 1 + ISREGSHIFT + codeTicksAccessSeq32(armNextPC); \
+ else \
+ { \
+ MODECHANGE; \
+ if (armState) \
+ { \
+ reg[15].I &= 0xFFFFFFFC; \
+ armNextPC = reg[15].I; \
+ reg[15].I += 4; \
+ ARM_PREFETCH(); \
+ } \
+ else \
+ { \
+ reg[15].I &= 0xFFFFFFFE; \
+ armNextPC = reg[15].I; \
+ reg[15].I += 2; \
+ THUMB_PREFETCH(); \
+ } \
+ clockTicks = 3 + ISREGSHIFT + codeTicksAccess32(armNextPC) + codeTicksAccessSeq32(armNextPC) + codeTicksAccessSeq32(armNextPC); \
+ }
#define MODECHANGE_NO /*nothing*/
#define MODECHANGE_YES CPUSwitchMode(reg[17].I & 0x1f, false);
#define DEFINE_ALU_INSN_C(CODE1, CODE2, OP, MODECHANGE) \
- static INSN_REGPARM void arm##CODE1##0(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##1(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE1##2(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##3(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE1##4(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##5(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE1##6(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##7(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE2##0(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
+ static INSN_REGPARM void arm##CODE1##0(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##1(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE1##2(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##3(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE1##4(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##5(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE1##6(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##7(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE2##0(uint32_t opcode) { ALU_INSN(ALU_INIT_C, VALUE_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
#define DEFINE_ALU_INSN_NC(CODE1, CODE2, OP, MODECHANGE) \
- static INSN_REGPARM void arm##CODE1##0(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##1(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE1##2(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##3(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE1##4(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##5(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE1##6(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
- static INSN_REGPARM void arm##CODE1##7(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
- static INSN_REGPARM void arm##CODE2##0(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
+ static INSN_REGPARM void arm##CODE1##0(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##1(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE1##2(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##3(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE1##4(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##5(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE1##6(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); } \
+ static INSN_REGPARM void arm##CODE1##7(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); } \
+ static INSN_REGPARM void arm##CODE2##0(uint32_t opcode) { ALU_INSN(ALU_INIT_NC, VALUE_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
// AND
DEFINE_ALU_INSN_NC(00, 20, AND, NO)
// ANDS
-DEFINE_ALU_INSN_C (01, 21, ANDS, YES)
+DEFINE_ALU_INSN_C(01, 21, ANDS, YES)
// EOR
DEFINE_ALU_INSN_NC(02, 22, EOR, NO)
// EORS
-DEFINE_ALU_INSN_C (03, 23, EORS, YES)
+DEFINE_ALU_INSN_C(03, 23, EORS, YES)
// SUB
DEFINE_ALU_INSN_NC(04, 24, SUB, NO)
@@ -1205,10 +1140,10 @@
DEFINE_ALU_INSN_NC(0F, 2F, RSCS, YES)
// TST
-DEFINE_ALU_INSN_C (11, 31, TST, NO)
+DEFINE_ALU_INSN_C(11, 31, TST, NO)
// TEQ
-DEFINE_ALU_INSN_C (13, 33, TEQ, NO)
+DEFINE_ALU_INSN_C(13, 33, TEQ, NO)
// CMP
DEFINE_ALU_INSN_NC(15, 35, CMP, NO)
@@ -1219,22 +1154,22 @@
// ORR
DEFINE_ALU_INSN_NC(18, 38, ORR, NO)
// ORRS
-DEFINE_ALU_INSN_C (19, 39, ORRS, YES)
+DEFINE_ALU_INSN_C(19, 39, ORRS, YES)
// MOV
DEFINE_ALU_INSN_NC(1A, 3A, MOV, NO)
// MOVS
-DEFINE_ALU_INSN_C (1B, 3B, MOVS, YES)
+DEFINE_ALU_INSN_C(1B, 3B, MOVS, YES)
// BIC
DEFINE_ALU_INSN_NC(1C, 3C, BIC, NO)
// BICS
-DEFINE_ALU_INSN_C (1D, 3D, BICS, YES)
+DEFINE_ALU_INSN_C(1D, 3D, BICS, YES)
// MVN
DEFINE_ALU_INSN_NC(1E, 3E, MVN, NO)
// MVNS
-DEFINE_ALU_INSN_C (1F, 3F, MVNS, YES)
+DEFINE_ALU_INSN_C(1F, 3F, MVNS, YES)
// Multiply instructions //////////////////////////////////////////////////
@@ -1242,41 +1177,38 @@
// SETCOND: SETCOND_NONE, SETCOND_MUL, or SETCOND_MULL
// CYCLES: base cycle count (1, 2, or 3)
#define MUL_INSN(OP, SETCOND, CYCLES) \
- int mult = (opcode & 0x0F); \
- uint32_t rs = reg[(opcode >> 8) & 0x0F].I; \
- int acc = (opcode >> 12) & 0x0F; /* or destLo */ \
- int dest = (opcode >> 16) & 0x0F; /* or destHi */ \
- OP; \
- SETCOND; \
- if ((int32_t)rs < 0) \
- rs = ~rs; \
- if ((rs & 0xFFFFFF00) == 0) \
- clockTicks += 0; \
- else if ((rs & 0xFFFF0000) == 0) \
- clockTicks += 1; \
- else if ((rs & 0xFF000000) == 0) \
- clockTicks += 2; \
- else \
- clockTicks += 3; \
- if (busPrefetchCount == 0) \
- busPrefetchCount = ((busPrefetchCount+1)<<clockTicks) - 1; \
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ int mult = opcode & 0x0F; \
+ uint32_t rs = reg[(opcode >> 8) & 0x0F].I; \
+ int acc = (opcode >> 12) & 0x0F; /* or destLo */ \
+ int dest = (opcode >> 16) & 0x0F; /* or destHi */ \
+ OP; \
+ SETCOND; \
+ if (static_cast<int32_t>(rs) < 0) \
+ rs = ~rs; \
+ if (!(rs & 0xFFFFFF00)) \
+ ; /* No-op */ \
+ else if (!(rs & 0xFFFF0000)) \
+ clockTicks += 1; \
+ else if (!(rs & 0xFF000000)) \
+ clockTicks += 2; \
+ else \
+ clockTicks += 3; \
+ if (!busPrefetchCount) \
+ busPrefetchCount = ((busPrefetchCount + 1) << clockTicks) - 1; \
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
#define OP_MUL \
- reg[dest].I = reg[mult].I * rs;
+ reg[dest].I = reg[mult].I * rs;
#define OP_MLA \
- reg[dest].I = reg[mult].I * rs + reg[acc].I;
+ reg[dest].I = reg[mult].I * rs + reg[acc].I;
#define OP_MULL(SIGN) \
- SIGN##64_t res = (SIGN##64_t)(SIGN##32_t)reg[mult].I \
- * (SIGN##64_t)(SIGN##32_t)rs; \
- reg[acc].I = (uint32_t)res; \
- reg[dest].I = (uint32_t)(res >> 32);
+ SIGN##64_t res = static_cast<SIGN##64_t>(reg[mult].I) * static_cast<SIGN##64_t>(rs); \
+ reg[acc].I = static_cast<uint32_t>(res); \
+ reg[dest].I = static_cast<uint32_t>(res >> 32);
#define OP_MLAL(SIGN) \
- SIGN##64_t res = ((SIGN##64_t)reg[dest].I<<32 | reg[acc].I)\
- + ((SIGN##64_t)(SIGN##32_t)reg[mult].I \
- * (SIGN##64_t)(SIGN##32_t)rs); \
- reg[acc].I = (uint32_t)res; \
- reg[dest].I = (uint32_t)(res >> 32);
+ SIGN##64_t res = (static_cast<SIGN##64_t>(reg[dest].I) << 32 | reg[acc].I) + (static_cast<SIGN##64_t>(reg[mult].I) * static_cast<SIGN##64_t>(rs)); \
+ reg[acc].I = static_cast<uint32_t>(res); \
+ reg[dest].I = static_cast<uint32_t>(res >> 32);
#define OP_UMULL OP_MULL(uint)
#define OP_UMLAL OP_MLAL(uint)
#define OP_SMULL OP_MULL(int)
@@ -1317,291 +1249,302 @@
// SWP Rd, Rm, [Rn]
static INSN_REGPARM void arm109(uint32_t opcode)
{
- uint32_t address = reg[(opcode >> 16) & 15].I;
- uint32_t temp = CPUReadMemory(address);
- CPUWriteMemory(address, reg[opcode&15].I);
- reg[(opcode >> 12) & 15].I = temp;
- clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address)
- + codeTicksAccess32(armNextPC);
+ uint32_t address = reg[(opcode >> 16) & 15].I;
+ uint32_t temp = CPUReadMemory(address);
+ CPUWriteMemory(address, reg[opcode & 15].I);
+ reg[(opcode >> 12) & 15].I = temp;
+ clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) + codeTicksAccess32(armNextPC);
}
// SWPB Rd, Rm, [Rn]
static INSN_REGPARM void arm149(uint32_t opcode)
{
- uint32_t address = reg[(opcode >> 16) & 15].I;
- uint32_t temp = CPUReadByte(address);
- CPUWriteByte(address, reg[opcode&15].B.B0);
- reg[(opcode>>12)&15].I = temp;
- clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address)
- + codeTicksAccess32(armNextPC);
+ uint32_t address = reg[(opcode >> 16) & 15].I;
+ uint32_t temp = CPUReadByte(address);
+ CPUWriteByte(address, reg[opcode&15].B.B0);
+ reg[(opcode >> 12) & 15].I = temp;
+ clockTicks = 4 + dataTicksAccess32(address) + dataTicksAccess32(address) + codeTicksAccess32(armNextPC);
}
// MRS Rd, CPSR
static INSN_REGPARM void arm100(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FFF0FFF) == 0x010F0000)) {
- CPUUpdateCPSR();
- reg[(opcode >> 12) & 0x0F].I = reg[16].I;
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FFF0FFF) == 0x010F0000))
+ {
+ CPUUpdateCPSR();
+ reg[(opcode >> 12) & 0x0F].I = reg[16].I;
+ }
+ else
+ armUnknownInsn(opcode);
}
// MRS Rd, SPSR
static INSN_REGPARM void arm140(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FFF0FFF) == 0x014F0000)) {
- reg[(opcode >> 12) & 0x0F].I = reg[17].I;
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FFF0FFF) == 0x014F0000))
+ reg[(opcode >> 12) & 0x0F].I = reg[17].I;
+ else
+ armUnknownInsn(opcode);
}
// MSR CPSR_fields, Rm
static INSN_REGPARM void arm120(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FF0FFF0) == 0x0120F000)) {
- CPUUpdateCPSR();
- uint32_t value = reg[opcode & 15].I;
- uint32_t newValue = reg[16].I;
- if (armMode > 0x10) {
- if (opcode & 0x00010000)
- newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
- if (opcode & 0x00020000)
- newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
- if (opcode & 0x00040000)
- newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
- }
- if (opcode & 0x00080000)
- newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
- newValue |= 0x10;
- CPUSwitchMode(newValue & 0x1F, false);
- reg[16].I = newValue;
- CPUUpdateFlags();
- if (!armState) { // this should not be allowed, but it seems to work
- THUMB_PREFETCH;
- reg[15].I = armNextPC + 2;
- }
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FF0FFF0) == 0x0120F000))
+ {
+ CPUUpdateCPSR();
+ uint32_t value = reg[opcode & 15].I;
+ uint32_t newValue = reg[16].I;
+ if (armMode > 0x10)
+ {
+ if (opcode & 0x00010000)
+ newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
+ if (opcode & 0x00020000)
+ newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
+ if (opcode & 0x00040000)
+ newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
+ }
+ if (opcode & 0x00080000)
+ newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
+ newValue |= 0x10;
+ CPUSwitchMode(newValue & 0x1F, false);
+ reg[16].I = newValue;
+ CPUUpdateFlags();
+ if (!armState) // this should not be allowed, but it seems to work
+ {
+ THUMB_PREFETCH();
+ reg[15].I = armNextPC + 2;
+ }
+ }
+ else
+ armUnknownInsn(opcode);
}
// MSR SPSR_fields, Rm
static INSN_REGPARM void arm160(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FF0FFF0) == 0x0160F000)) {
- uint32_t value = reg[opcode & 15].I;
- if (armMode > 0x10 && armMode < 0x1F) {
- if (opcode & 0x00010000)
- reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
- if (opcode & 0x00020000)
- reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
- if (opcode & 0x00040000)
- reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
- if (opcode & 0x00080000)
- reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
- }
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FF0FFF0) == 0x0160F000))
+ {
+ uint32_t value = reg[opcode & 15].I;
+ if (armMode > 0x10 && armMode < 0x1F)
+ {
+ if (opcode & 0x00010000)
+ reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
+ if (opcode & 0x00020000)
+ reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
+ if (opcode & 0x00040000)
+ reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
+ if (opcode & 0x00080000)
+ reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
+ }
+ }
+ else
+ armUnknownInsn(opcode);
}
// MSR CPSR_fields, #
static INSN_REGPARM void arm320(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FF0F000) == 0x0320F000)) {
- CPUUpdateCPSR();
- uint32_t value = opcode & 0xFF;
- int shift = (opcode & 0xF00) >> 7;
- if (shift) {
- ROR_IMM_MSR;
- }
- uint32_t newValue = reg[16].I;
- if (armMode > 0x10) {
- if (opcode & 0x00010000)
- newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
- if (opcode & 0x00020000)
- newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
- if (opcode & 0x00040000)
- newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
- }
- if (opcode & 0x00080000)
- newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
-
- newValue |= 0x10;
-
- CPUSwitchMode(newValue & 0x1F, false);
- reg[16].I = newValue;
- CPUUpdateFlags();
- if (!armState) { // this should not be allowed, but it seems to work
- THUMB_PREFETCH;
- reg[15].I = armNextPC + 2;
- }
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FF0F000) == 0x0320F000))
+ {
+ CPUUpdateCPSR();
+ uint32_t value = opcode & 0xFF;
+ int shift = (opcode & 0xF00) >> 7;
+ if (shift)
+ {
+ ROR_IMM_MSR;
+ }
+ uint32_t newValue = reg[16].I;
+ if (armMode > 0x10)
+ {
+ if (opcode & 0x00010000)
+ newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
+ if (opcode & 0x00020000)
+ newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
+ if (opcode & 0x00040000)
+ newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
+ }
+ if (opcode & 0x00080000)
+ newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
+
+ newValue |= 0x10;
+
+ CPUSwitchMode(newValue & 0x1F, false);
+ reg[16].I = newValue;
+ CPUUpdateFlags();
+ if (!armState) // this should not be allowed, but it seems to work
+ {
+ THUMB_PREFETCH();
+ reg[15].I = armNextPC + 2;
+ }
+ }
+ else
+ armUnknownInsn(opcode);
}
// MSR SPSR_fields, #
static INSN_REGPARM void arm360(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FF0F000) == 0x0360F000)) {
- if (armMode > 0x10 && armMode < 0x1F) {
- uint32_t value = opcode & 0xFF;
- int shift = (opcode & 0xF00) >> 7;
- if (shift) {
- ROR_IMM_MSR;
- }
- if (opcode & 0x00010000)
- reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
- if (opcode & 0x00020000)
- reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
- if (opcode & 0x00040000)
- reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
- if (opcode & 0x00080000)
- reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
- }
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FF0F000) == 0x0360F000))
+ {
+ if (armMode > 0x10 && armMode < 0x1F)
+ {
+ uint32_t value = opcode & 0xFF;
+ int shift = (opcode & 0xF00) >> 7;
+ if (shift)
+ {
+ ROR_IMM_MSR;
+ }
+ if (opcode & 0x00010000)
+ reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
+ if (opcode & 0x00020000)
+ reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
+ if (opcode & 0x00040000)
+ reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
+ if (opcode & 0x00080000)
+ reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
+ }
+ }
+ else
+ armUnknownInsn(opcode);
}
// BX Rm
static INSN_REGPARM void arm121(uint32_t opcode)
{
- if (LIKELY((opcode & 0x0FFFFFF0) == 0x012FFF10)) {
- int base = opcode & 0x0F;
- busPrefetchCount = 0;
- armState = reg[base].I & 1 ? false : true;
- if (armState) {
- reg[15].I = reg[base].I & 0xFFFFFFFC;
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH;
- clockTicks = 3 + codeTicksAccessSeq32(armNextPC)
- + codeTicksAccessSeq32(armNextPC)
- + codeTicksAccess32(armNextPC);
- } else {
- reg[15].I = reg[base].I & 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = 3 + codeTicksAccessSeq16(armNextPC)
- + codeTicksAccessSeq16(armNextPC)
- + codeTicksAccess16(armNextPC);
- }
- } else {
- armUnknownInsn(opcode);
- }
+ if (LIKELY((opcode & 0x0FFFFFF0) == 0x012FFF10))
+ {
+ int base = opcode & 0x0F;
+ busPrefetchCount = 0;
+ armState = !(reg[base].I & 1);
+ if (armState)
+ {
+ reg[15].I = reg[base].I & 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH();
+ clockTicks = 3 + codeTicksAccessSeq32(armNextPC) + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC);
+ }
+ else
+ {
+ reg[15].I = reg[base].I & 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = 3 + codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC);
+ }
+ }
+ else
+ armUnknownInsn(opcode);
}
// Load/store /////////////////////////////////////////////////////////////
#define OFFSET_IMM \
- int offset = opcode & 0xFFF;
+ int offset = opcode & 0xFFF;
#define OFFSET_IMM8 \
- int offset = ((opcode & 0x0F) | ((opcode>>4) & 0xF0));
+ int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
#define OFFSET_REG \
- int offset = reg[opcode & 15].I;
+ int offset = reg[opcode & 15].I;
#define OFFSET_LSL \
- int offset = reg[opcode & 15].I << ((opcode>>7) & 31);
+ int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
#define OFFSET_LSR \
- int shift = (opcode >> 7) & 31; \
- int offset = shift ? reg[opcode & 15].I >> shift : 0;
+ int shift = (opcode >> 7) & 31; \
+ int offset = shift ? reg[opcode & 15].I >> shift : 0;
#define OFFSET_ASR \
- int shift = (opcode >> 7) & 31; \
- int offset; \
- if (shift) \
- offset = (int)((int32_t)reg[opcode & 15].I >> shift);\
- else if (reg[opcode & 15].I & 0x80000000) \
- offset = 0xFFFFFFFF; \
- else \
- offset = 0;
+ int shift = (opcode >> 7) & 31; \
+ int offset; \
+ if (shift) \
+ offset = static_cast<int>(static_cast<int32_t>(reg[opcode & 15].I) >> shift); \
+ else if (reg[opcode & 15].I & 0x80000000) \
+ offset = 0xFFFFFFFF; \
+ else \
+ offset = 0;
#define OFFSET_ROR \
- int shift = (opcode >> 7) & 31; \
- uint32_t offset = reg[opcode & 15].I; \
- if (shift) { \
- ROR_OFFSET; \
- } else { \
- RRX_OFFSET; \
- }
+ int shift = (opcode >> 7) & 31; \
+ uint32_t offset = reg[opcode & 15].I; \
+ if (shift) \
+ { \
+ ROR_OFFSET; \
+ } \
+ else \
+ { \
+ RRX_OFFSET; \
+ }
#define ADDRESS_POST (reg[base].I)
#define ADDRESS_PREDEC (reg[base].I - offset)
#define ADDRESS_PREINC (reg[base].I + offset)
-#define OP_STR CPUWriteMemory(address, reg[dest].I)
-#define OP_STRH CPUWriteHalfWord(address, reg[dest].W.W0)
-#define OP_STRB CPUWriteByte(address, reg[dest].B.B0)
-#define OP_LDR reg[dest].I = CPUReadMemory(address)
-#define OP_LDRH reg[dest].I = CPUReadHalfWord(address)
-#define OP_LDRB reg[dest].I = CPUReadByte(address)
-#define OP_LDRSH reg[dest].I = (uint32_t)CPUReadHalfWordSigned(address)
-#define OP_LDRSB reg[dest].I = (int8_t)CPUReadByte(address)
-
-#define WRITEBACK_NONE /*nothing*/
-#define WRITEBACK_PRE reg[base].I = address
-#define WRITEBACK_POSTDEC reg[base].I = address - offset
-#define WRITEBACK_POSTINC reg[base].I = address + offset
+#define OP_STR CPUWriteMemory(address, reg[dest].I)
+#define OP_STRH CPUWriteHalfWord(address, reg[dest].W.W0)
+#define OP_STRB CPUWriteByte(address, reg[dest].B.B0)
+#define OP_LDR reg[dest].I = CPUReadMemory(address)
+#define OP_LDRH reg[dest].I = CPUReadHalfWord(address)
+#define OP_LDRB reg[dest].I = CPUReadByte(address)
+#define OP_LDRSH reg[dest].I = static_cast<uint32_t>(CPUReadHalfWordSigned(address))
+#define OP_LDRSB reg[dest].I = static_cast<int8_t>(CPUReadByte(address))
+
+#define WRITEBACK_NONE /*nothing*/
+#define WRITEBACK_PRE reg[base].I = address
+#define WRITEBACK_POSTDEC reg[base].I = address - offset
+#define WRITEBACK_POSTINC reg[base].I = address + offset
#define LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS) \
- if (busPrefetchCount == 0) \
- busPrefetch = busPrefetchEnable; \
- int dest = (opcode >> 12) & 15; \
- int base = (opcode >> 16) & 15; \
- CALC_OFFSET; \
- uint32_t address = CALC_ADDRESS;
+ if (!busPrefetchCount) \
+ busPrefetch = busPrefetchEnable; \
+ int dest = (opcode >> 12) & 15; \
+ int base = (opcode >> 16) & 15; \
+ CALC_OFFSET; \
+ uint32_t address = CALC_ADDRESS;
#define STR(CALC_OFFSET, CALC_ADDRESS, STORE_DATA, WRITEBACK1, WRITEBACK2, SIZE) \
- LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
- WRITEBACK1; \
- STORE_DATA; \
- WRITEBACK2; \
- clockTicks = 2 + dataTicksAccess##SIZE(address) \
- + codeTicksAccess32(armNextPC);
+ LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
+ WRITEBACK1; \
+ STORE_DATA; \
+ WRITEBACK2; \
+ clockTicks = 2 + dataTicksAccess##SIZE(address) + codeTicksAccess32(armNextPC);
#define LDR(CALC_OFFSET, CALC_ADDRESS, LOAD_DATA, WRITEBACK, SIZE) \
- LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
- LOAD_DATA; \
- if (dest != base) \
- { \
- WRITEBACK; \
- } \
- clockTicks = 0; \
- if (dest == 15) { \
- reg[15].I &= 0xFFFFFFFC; \
- armNextPC = reg[15].I; \
- reg[15].I += 4; \
- ARM_PREFETCH; \
- clockTicks += 2 + dataTicksAccessSeq32(address) \
- + dataTicksAccessSeq32(address);\
- } \
- clockTicks += 3 + dataTicksAccess##SIZE(address) \
- + codeTicksAccess32(armNextPC);
+ LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
+ LOAD_DATA; \
+ if (dest != base) \
+ { \
+ WRITEBACK; \
+ } \
+ clockTicks = 0; \
+ if (dest == 15) \
+ { \
+ reg[15].I &= 0xFFFFFFFC; \
+ armNextPC = reg[15].I; \
+ reg[15].I += 4; \
+ ARM_PREFETCH(); \
+ clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); \
+ } \
+ clockTicks += 3 + dataTicksAccess##SIZE(address) + codeTicksAccess32(armNextPC);
#define STR_POSTDEC(CALC_OFFSET, STORE_DATA, SIZE) \
- STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTDEC, SIZE)
+ STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTDEC, SIZE)
#define STR_POSTINC(CALC_OFFSET, STORE_DATA, SIZE) \
- STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTINC, SIZE)
+ STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTINC, SIZE)
#define STR_PREDEC(CALC_OFFSET, STORE_DATA, SIZE) \
- STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
+ STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
#define STR_PREDEC_WB(CALC_OFFSET, STORE_DATA, SIZE) \
- STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
+ STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
#define STR_PREINC(CALC_OFFSET, STORE_DATA, SIZE) \
- STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
+ STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
#define STR_PREINC_WB(CALC_OFFSET, STORE_DATA, SIZE) \
- STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
+ STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
#define LDR_POSTDEC(CALC_OFFSET, LOAD_DATA, SIZE) \
- LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTDEC, SIZE)
+ LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTDEC, SIZE)
#define LDR_POSTINC(CALC_OFFSET, LOAD_DATA, SIZE) \
- LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTINC, SIZE)
+ LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTINC, SIZE)
#define LDR_PREDEC(CALC_OFFSET, LOAD_DATA, SIZE) \
- LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_NONE, SIZE)
+ LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_NONE, SIZE)
#define LDR_PREDEC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \
- LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_PRE, SIZE)
+ LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_PRE, SIZE)
#define LDR_PREINC(CALC_OFFSET, LOAD_DATA, SIZE) \
- LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_NONE, SIZE)
+ LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_NONE, SIZE)
#define LDR_PREINC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \
- LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_PRE, SIZE)
+ LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_PRE, SIZE)
// STRH Rd, [Rn], -Rm
static INSN_REGPARM void arm00B(uint32_t opcode) { STR_POSTDEC(OFFSET_REG, OP_STRH, 16); }
@@ -1948,655 +1891,649 @@
// STM/LDM ////////////////////////////////////////////////////////////////
-#define STM_REG(bit,num) \
- if (opcode & (1U<<(bit))) { \
- CPUWriteMemory(address, reg[(num)].I); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address);\
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address);\
- } \
- count++; \
- address += 4; \
- }
-#define STMW_REG(bit,num) \
- if (opcode & (1U<<(bit))) { \
- CPUWriteMemory(address, reg[(num)].I); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address);\
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address);\
- } \
- reg[base].I = temp; \
- count++; \
- address += 4; \
- }
-#define LDM_REG(bit,num) \
- if (opcode & (1U<<(bit))) { \
- reg[(num)].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address);\
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address);\
- } \
- count++; \
- address += 4; \
- }
+#define STM_REG(bit, num) \
+ if (opcode & (1U << (bit))) \
+ { \
+ CPUWriteMemory(address, reg[(num)].I); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ address += 4; \
+ }
+#define STMW_REG(bit, num) \
+ if (opcode & (1U << (bit))) \
+ { \
+ CPUWriteMemory(address, reg[(num)].I); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ reg[base].I = temp; \
+ ++count; \
+ address += 4; \
+ }
+#define LDM_REG(bit, num) \
+ if (opcode & (1U << (bit))) \
+ { \
+ reg[(num)].I = CPUReadMemory(address); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ address += 4; \
+ }
#define STM_LOW(STORE_REG) \
- STORE_REG(0, 0); \
- STORE_REG(1, 1); \
- STORE_REG(2, 2); \
- STORE_REG(3, 3); \
- STORE_REG(4, 4); \
- STORE_REG(5, 5); \
- STORE_REG(6, 6); \
- STORE_REG(7, 7);
+ STORE_REG(0, 0); \
+ STORE_REG(1, 1); \
+ STORE_REG(2, 2); \
+ STORE_REG(3, 3); \
+ STORE_REG(4, 4); \
+ STORE_REG(5, 5); \
+ STORE_REG(6, 6); \
+ STORE_REG(7, 7);
#define STM_HIGH(STORE_REG) \
- STORE_REG(8, 8); \
- STORE_REG(9, 9); \
- STORE_REG(10, 10); \
- STORE_REG(11, 11); \
- STORE_REG(12, 12); \
- STORE_REG(13, 13); \
- STORE_REG(14, 14);
+ STORE_REG(8, 8); \
+ STORE_REG(9, 9); \
+ STORE_REG(10, 10); \
+ STORE_REG(11, 11); \
+ STORE_REG(12, 12); \
+ STORE_REG(13, 13); \
+ STORE_REG(14, 14);
#define STM_HIGH_2(STORE_REG) \
- if (armMode == 0x11) { \
- STORE_REG(8, R8_FIQ); \
- STORE_REG(9, R9_FIQ); \
- STORE_REG(10, R10_FIQ); \
- STORE_REG(11, R11_FIQ); \
- STORE_REG(12, R12_FIQ); \
- } else { \
- STORE_REG(8, 8); \
- STORE_REG(9, 9); \
- STORE_REG(10, 10); \
- STORE_REG(11, 11); \
- STORE_REG(12, 12); \
- } \
- if (armMode != 0x10 && armMode != 0x1F) { \
- STORE_REG(13, R13_USR); \
- STORE_REG(14, R14_USR); \
- } else { \
- STORE_REG(13, 13); \
- STORE_REG(14, 14); \
- }
+ if (armMode == 0x11) \
+ { \
+ STORE_REG(8, R8_FIQ); \
+ STORE_REG(9, R9_FIQ); \
+ STORE_REG(10, R10_FIQ); \
+ STORE_REG(11, R11_FIQ); \
+ STORE_REG(12, R12_FIQ); \
+ } \
+ else \
+ { \
+ STORE_REG(8, 8); \
+ STORE_REG(9, 9); \
+ STORE_REG(10, 10); \
+ STORE_REG(11, 11); \
+ STORE_REG(12, 12); \
+ } \
+ if (armMode != 0x10 && armMode != 0x1F) \
+ { \
+ STORE_REG(13, R13_USR); \
+ STORE_REG(14, R14_USR); \
+ } \
+ else \
+ { \
+ STORE_REG(13, 13); \
+ STORE_REG(14, 14); \
+ }
#define STM_PC \
- if (opcode & (1U<<15)) { \
- CPUWriteMemory(address, reg[15].I+4); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address);\
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address);\
- } \
- count++; \
- }
+ if (opcode & (1U << 15)) \
+ { \
+ CPUWriteMemory(address, reg[15].I + 4); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ }
#define STMW_PC \
- if (opcode & (1U<<15)) { \
- CPUWriteMemory(address, reg[15].I+4); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address);\
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address);\
- } \
- reg[base].I = temp; \
- count++; \
- }
+ if (opcode & (1U << 15)) \
+ { \
+ CPUWriteMemory(address, reg[15].I + 4); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ reg[base].I = temp; \
+ ++count; \
+ }
#define LDM_LOW \
- LDM_REG(0, 0); \
- LDM_REG(1, 1); \
- LDM_REG(2, 2); \
- LDM_REG(3, 3); \
- LDM_REG(4, 4); \
- LDM_REG(5, 5); \
- LDM_REG(6, 6); \
- LDM_REG(7, 7);
+ LDM_REG(0, 0); \
+ LDM_REG(1, 1); \
+ LDM_REG(2, 2); \
+ LDM_REG(3, 3); \
+ LDM_REG(4, 4); \
+ LDM_REG(5, 5); \
+ LDM_REG(6, 6); \
+ LDM_REG(7, 7);
#define LDM_HIGH \
- LDM_REG(8, 8); \
- LDM_REG(9, 9); \
- LDM_REG(10, 10); \
- LDM_REG(11, 11); \
- LDM_REG(12, 12); \
- LDM_REG(13, 13); \
- LDM_REG(14, 14);
+ LDM_REG(8, 8); \
+ LDM_REG(9, 9); \
+ LDM_REG(10, 10); \
+ LDM_REG(11, 11); \
+ LDM_REG(12, 12); \
+ LDM_REG(13, 13); \
+ LDM_REG(14, 14);
#define LDM_HIGH_2 \
- if (armMode == 0x11) { \
- LDM_REG(8, R8_FIQ); \
- LDM_REG(9, R9_FIQ); \
- LDM_REG(10, R10_FIQ); \
- LDM_REG(11, R11_FIQ); \
- LDM_REG(12, R12_FIQ); \
- } else { \
- LDM_REG(8, 8); \
- LDM_REG(9, 9); \
- LDM_REG(10, 10); \
- LDM_REG(11, 11); \
- LDM_REG(12, 12); \
- } \
- if (armMode != 0x10 && armMode != 0x1F) { \
- LDM_REG(13, R13_USR); \
- LDM_REG(14, R14_USR); \
- } else { \
- LDM_REG(13, 13); \
- LDM_REG(14, 14); \
- }
+ if (armMode == 0x11) \
+ { \
+ LDM_REG(8, R8_FIQ); \
+ LDM_REG(9, R9_FIQ); \
+ LDM_REG(10, R10_FIQ); \
+ LDM_REG(11, R11_FIQ); \
+ LDM_REG(12, R12_FIQ); \
+ } \
+ else \
+ { \
+ LDM_REG(8, 8); \
+ LDM_REG(9, 9); \
+ LDM_REG(10, 10); \
+ LDM_REG(11, 11); \
+ LDM_REG(12, 12); \
+ } \
+ if (armMode != 0x10 && armMode != 0x1F) \
+ { \
+ LDM_REG(13, R13_USR); \
+ LDM_REG(14, R14_USR); \
+ } \
+ else \
+ { \
+ LDM_REG(13, 13); \
+ LDM_REG(14, 14); \
+ }
#define STM_ALL \
- STM_LOW(STM_REG); \
- STM_HIGH(STM_REG); \
- STM_PC;
+ STM_LOW(STM_REG); \
+ STM_HIGH(STM_REG); \
+ STM_PC;
#define STMW_ALL \
- STM_LOW(STMW_REG); \
- STM_HIGH(STMW_REG); \
- STMW_PC;
+ STM_LOW(STMW_REG); \
+ STM_HIGH(STMW_REG); \
+ STMW_PC;
#define LDM_ALL \
- LDM_LOW; \
- LDM_HIGH; \
- if (opcode & (1U<<15)) { \
- reg[15].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address);\
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address);\
- } \
- count++; \
- } \
- if (opcode & (1U<<15)) { \
- armNextPC = reg[15].I; \
- reg[15].I += 4; \
- ARM_PREFETCH; \
- clockTicks += 1 + codeTicksAccessSeq32(armNextPC);\
- }
+ LDM_LOW \
+ LDM_HIGH; \
+ if (opcode & (1U << 15)) \
+ { \
+ reg[15].I = CPUReadMemory(address); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ } \
+ if (opcode & (1U << 15)) \
+ { \
+ armNextPC = reg[15].I; \
+ reg[15].I += 4; \
+ ARM_PREFETCH(); \
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC); \
+ }
#define STM_ALL_2 \
- STM_LOW(STM_REG); \
- STM_HIGH_2(STM_REG); \
- STM_PC;
+ STM_LOW(STM_REG) \
+ STM_HIGH_2(STM_REG); \
+ STM_PC;
#define STMW_ALL_2 \
- STM_LOW(STMW_REG); \
- STM_HIGH_2(STMW_REG); \
- STMW_PC;
+ STM_LOW(STMW_REG); \
+ STM_HIGH_2(STMW_REG); \
+ STMW_PC;
#define LDM_ALL_2 \
- LDM_LOW; \
- if (opcode & (1U<<15)) { \
- LDM_HIGH; \
- reg[15].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- } else { \
- LDM_HIGH_2; \
- }
+ LDM_LOW; \
+ if (opcode & (1U << 15)) \
+ { \
+ LDM_HIGH; \
+ reg[15].I = CPUReadMemory(address); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ } \
+ else \
+ { \
+ LDM_HIGH_2; \
+ }
#define LDM_ALL_2B \
- if (opcode & (1U<<15)) { \
- CPUSwitchMode(reg[17].I & 0x1F, false); \
- if (armState) { \
- armNextPC = reg[15].I & 0xFFFFFFFC; \
- reg[15].I = armNextPC + 4; \
- ARM_PREFETCH; \
- } else { \
- armNextPC = reg[15].I & 0xFFFFFFFE; \
- reg[15].I = armNextPC + 2; \
- THUMB_PREFETCH; \
- } \
- clockTicks += 1 + codeTicksAccessSeq32(armNextPC);\
- }
-
+ if (opcode & (1U << 15)) \
+ { \
+ CPUSwitchMode(reg[17].I & 0x1F, false); \
+ if (armState) \
+ { \
+ armNextPC = reg[15].I & 0xFFFFFFFC; \
+ reg[15].I = armNextPC + 4; \
+ ARM_PREFETCH(); \
+ } \
+ else \
+ { \
+ armNextPC = reg[15].I & 0xFFFFFFFE; \
+ reg[15].I = armNextPC + 2; \
+ THUMB_PREFETCH(); \
+ } \
+ clockTicks += 1 + codeTicksAccessSeq32(armNextPC); \
+ }
// STMDA Rn, {Rlist}
static INSN_REGPARM void arm800(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp + 4) & 0xFFFFFFFC;
- int count = 0;
- STM_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDA Rn, {Rlist}
static INSN_REGPARM void arm810(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp + 4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMDA Rn!, {Rlist}
static INSN_REGPARM void arm820(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp+4) & 0xFFFFFFFC;
- int count = 0;
- STMW_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ STMW_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDA Rn!, {Rlist}
static INSN_REGPARM void arm830(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp + 4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
}
// STMDA Rn, {Rlist}^
static INSN_REGPARM void arm840(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp+4) & 0xFFFFFFFC;
- int count = 0;
- STM_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDA Rn, {Rlist}^
static INSN_REGPARM void arm850(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp + 4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMDA Rn!, {Rlist}^
static INSN_REGPARM void arm860(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp+4) & 0xFFFFFFFC;
- int count = 0;
- STMW_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ STMW_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDA Rn!, {Rlist}^
static INSN_REGPARM void arm870(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (temp + 4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (temp + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMIA Rn, {Rlist}
static INSN_REGPARM void arm880(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- STM_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIA Rn, {Rlist}
static INSN_REGPARM void arm890(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMIA Rn!, {Rlist}
static INSN_REGPARM void arm8A0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
- STMW_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
+ STMW_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIA Rn!, {Rlist}
static INSN_REGPARM void arm8B0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
}
// STMIA Rn, {Rlist}^
static INSN_REGPARM void arm8C0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- STM_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIA Rn, {Rlist}^
static INSN_REGPARM void arm8D0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMIA Rn!, {Rlist}^
static INSN_REGPARM void arm8E0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
- STMW_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
+ STMW_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIA Rn!, {Rlist}^
static INSN_REGPARM void arm8F0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = reg[base].I & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = reg[base].I & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMDB Rn, {Rlist}
static INSN_REGPARM void arm900(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- STM_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDB Rn, {Rlist}
static INSN_REGPARM void arm910(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMDB Rn!, {Rlist}
static INSN_REGPARM void arm920(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- STMW_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ STMW_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDB Rn!, {Rlist}
static INSN_REGPARM void arm930(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
}
// STMDB Rn, {Rlist}^
static INSN_REGPARM void arm940(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- STM_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDB Rn, {Rlist}^
static INSN_REGPARM void arm950(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMDB Rn!, {Rlist}^
static INSN_REGPARM void arm960(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- STMW_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ STMW_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMDB Rn!, {Rlist}^
static INSN_REGPARM void arm970(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I -
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = temp & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = temp & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMIB Rn, {Rlist}
static INSN_REGPARM void arm980(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- STM_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIB Rn, {Rlist}
static INSN_REGPARM void arm990(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMIB Rn!, {Rlist}
static INSN_REGPARM void arm9A0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
- STMW_ALL;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
+ STMW_ALL;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIB Rn!, {Rlist}
static INSN_REGPARM void arm9B0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
}
// STMIB Rn, {Rlist}^
static INSN_REGPARM void arm9C0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- STM_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ STM_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIB Rn, {Rlist}^
static INSN_REGPARM void arm9D0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// STMIB Rn!, {Rlist}^
static INSN_REGPARM void arm9E0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
- STMW_ALL_2;
- clockTicks += 1 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
+ STMW_ALL_2;
+ clockTicks += 1 + codeTicksAccess32(armNextPC);
}
// LDMIB Rn!, {Rlist}^
static INSN_REGPARM void arm9F0(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int base = (opcode & 0x000F0000) >> 16;
- uint32_t temp = reg[base].I +
- 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
- uint32_t address = (reg[base].I+4) & 0xFFFFFFFC;
- int count = 0;
- LDM_ALL_2;
- if (!(opcode & (1U << base)))
- reg[base].I = temp;
- LDM_ALL_2B;
- clockTicks += 2 + codeTicksAccess32(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int base = (opcode & 0x000F0000) >> 16;
+ uint32_t temp = reg[base].I + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
+ uint32_t address = (reg[base].I + 4) & 0xFFFFFFFC;
+ int count = 0;
+ LDM_ALL_2;
+ if (!(opcode & (1U << base)))
+ reg[base].I = temp;
+ LDM_ALL_2B;
+ clockTicks += 2 + codeTicksAccess32(armNextPC);
}
// B/BL/SWI and (unimplemented) coproc support ////////////////////////////
@@ -2604,366 +2541,327 @@
// B <offset>
static INSN_REGPARM void armA00(uint32_t opcode)
{
- int offset = opcode & 0x00FFFFFF;
- if (offset & 0x00800000)
- offset |= 0xFF000000; // negative offset
- reg[15].I += offset<<2;
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH;
- clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
- clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
- busPrefetchCount = 0;
+ int offset = opcode & 0x00FFFFFF;
+ if (offset & 0x00800000)
+ offset |= 0xFF000000; // negative offset
+ reg[15].I += offset << 2;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH();
+ clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
+ clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
+ busPrefetchCount = 0;
}
// BL <offset>
static INSN_REGPARM void armB00(uint32_t opcode)
{
- int offset = opcode & 0x00FFFFFF;
- if (offset & 0x00800000)
- offset |= 0xFF000000; // negative offset
- reg[14].I = reg[15].I - 4;
- reg[15].I += offset<<2;
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH;
- clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
- clockTicks += 2 + codeTicksAccess32(armNextPC)
- + codeTicksAccessSeq32(armNextPC);
- busPrefetchCount = 0;
-}
-
-
-#ifdef GP_SUPPORT
-// MRC
-static INSN_REGPARM void armE01(uint32_t opcode)
-{
-}
-#else
- #define armE01 armUnknownInsn
-#endif
-
+ int offset = opcode & 0x00FFFFFF;
+ if (offset & 0x00800000)
+ offset |= 0xFF000000; // negative offset
+ reg[14].I = reg[15].I - 4;
+ reg[15].I += offset << 2;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH();
+ clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
+ clockTicks += 2 + codeTicksAccess32(armNextPC) + codeTicksAccessSeq32(armNextPC);
+ busPrefetchCount = 0;
+}
+
+#define armE01 armUnknownInsn
// SWI <comment>
static INSN_REGPARM void armF00(uint32_t opcode)
{
- clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
- clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
- busPrefetchCount = 0;
- CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
+ clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
+ clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
+ busPrefetchCount = 0;
+ CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
}
// Instruction table //////////////////////////////////////////////////////
typedef INSN_REGPARM void (*insnfunc_t)(uint32_t opcode);
#define REP16(insn) \
- insn,insn,insn,insn,insn,insn,insn,insn,\
- insn,insn,insn,insn,insn,insn,insn,insn
+ insn, insn, insn, insn, insn, insn, insn, insn, \
+ insn, insn, insn, insn, insn, insn, insn, insn
#define REP256(insn) \
- REP16(insn),REP16(insn),REP16(insn),REP16(insn),\
- REP16(insn),REP16(insn),REP16(insn),REP16(insn),\
- REP16(insn),REP16(insn),REP16(insn),REP16(insn),\
- REP16(insn),REP16(insn),REP16(insn),REP16(insn)
+ REP16(insn), REP16(insn), REP16(insn), REP16(insn), \
+ REP16(insn), REP16(insn), REP16(insn), REP16(insn), \
+ REP16(insn), REP16(insn), REP16(insn), REP16(insn), \
+ REP16(insn), REP16(insn), REP16(insn), REP16(insn)
#define arm_UI armUnknownInsn
-#ifdef BKPT_SUPPORT
- #define arm_BP armBreakpoint
-#else
- #define arm_BP armUnknownInsn
-#endif
-static insnfunc_t armInsnTable[4096] = {
- arm000,arm001,arm002,arm003,arm004,arm005,arm006,arm007, // 000
- arm000,arm009,arm002,arm00B,arm004,arm_UI,arm006,arm_UI, // 008
- arm010,arm011,arm012,arm013,arm014,arm015,arm016,arm017, // 010
- arm010,arm019,arm012,arm01B,arm014,arm01D,arm016,arm01F, // 018
- arm020,arm021,arm022,arm023,arm024,arm025,arm026,arm027, // 020
- arm020,arm029,arm022,arm_UI,arm024,arm_UI,arm026,arm_UI, // 028
- arm030,arm031,arm032,arm033,arm034,arm035,arm036,arm037, // 030
- arm030,arm039,arm032,arm_UI,arm034,arm01D,arm036,arm01F, // 038
- arm040,arm041,arm042,arm043,arm044,arm045,arm046,arm047, // 040
- arm040,arm_UI,arm042,arm04B,arm044,arm_UI,arm046,arm_UI, // 048
- arm050,arm051,arm052,arm053,arm054,arm055,arm056,arm057, // 050
- arm050,arm_UI,arm052,arm05B,arm054,arm05D,arm056,arm05F, // 058
- arm060,arm061,arm062,arm063,arm064,arm065,arm066,arm067, // 060
- arm060,arm_UI,arm062,arm_UI,arm064,arm_UI,arm066,arm_UI, // 068
- arm070,arm071,arm072,arm073,arm074,arm075,arm076,arm077, // 070
- arm070,arm_UI,arm072,arm_UI,arm074,arm05D,arm076,arm05F, // 078
- arm080,arm081,arm082,arm083,arm084,arm085,arm086,arm087, // 080
- arm080,arm089,arm082,arm08B,arm084,arm_UI,arm086,arm_UI, // 088
- arm090,arm091,arm092,arm093,arm094,arm095,arm096,arm097, // 090
- arm090,arm099,arm092,arm09B,arm094,arm09D,arm096,arm09F, // 098
- arm0A0,arm0A1,arm0A2,arm0A3,arm0A4,arm0A5,arm0A6,arm0A7, // 0A0
- arm0A0,arm0A9,arm0A2,arm_UI,arm0A4,arm_UI,arm0A6,arm_UI, // 0A8
- arm0B0,arm0B1,arm0B2,arm0B3,arm0B4,arm0B5,arm0B6,arm0B7, // 0B0
- arm0B0,arm0B9,arm0B2,arm_UI,arm0B4,arm09D,arm0B6,arm09F, // 0B8
- arm0C0,arm0C1,arm0C2,arm0C3,arm0C4,arm0C5,arm0C6,arm0C7, // 0C0
- arm0C0,arm0C9,arm0C2,arm0CB,arm0C4,arm_UI,arm0C6,arm_UI, // 0C8
- arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0
- arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8
- arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
- arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
- arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0
- arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8
-
- arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100
- arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108
- arm110,arm111,arm112,arm113,arm114,arm115,arm116,arm117, // 110
- arm110,arm_UI,arm112,arm11B,arm114,arm11D,arm116,arm11F, // 118
- arm120,arm121,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_BP, // 120
- arm_UI,arm_UI,arm_UI,arm12B,arm_UI,arm_UI,arm_UI,arm_UI, // 128
- arm130,arm131,arm132,arm133,arm134,arm135,arm136,arm137, // 130
- arm130,arm_UI,arm132,arm13B,arm134,arm13D,arm136,arm13F, // 138
- arm140,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 140
- arm_UI,arm149,arm_UI,arm14B,arm_UI,arm_UI,arm_UI,arm_UI, // 148
- arm150,arm151,arm152,arm153,arm154,arm155,arm156,arm157, // 150
- arm150,arm_UI,arm152,arm15B,arm154,arm15D,arm156,arm15F, // 158
- arm160,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 160
- arm_UI,arm_UI,arm_UI,arm16B,arm_UI,arm_UI,arm_UI,arm_UI, // 168
- arm170,arm171,arm172,arm173,arm174,arm175,arm176,arm177, // 170
- arm170,arm_UI,arm172,arm17B,arm174,arm17D,arm176,arm17F, // 178
- arm180,arm181,arm182,arm183,arm184,arm185,arm186,arm187, // 180
- arm180,arm_UI,arm182,arm18B,arm184,arm_UI,arm186,arm_UI, // 188
- arm190,arm191,arm192,arm193,arm194,arm195,arm196,arm197, // 190
- arm190,arm_UI,arm192,arm19B,arm194,arm19D,arm196,arm19F, // 198
- arm1A0,arm1A1,arm1A2,arm1A3,arm1A4,arm1A5,arm1A6,arm1A7, // 1A0
- arm1A0,arm_UI,arm1A2,arm1AB,arm1A4,arm_UI,arm1A6,arm_UI, // 1A8
- arm1B0,arm1B1,arm1B2,arm1B3,arm1B4,arm1B5,arm1B6,arm1B7, // 1B0
- arm1B0,arm_UI,arm1B2,arm1BB,arm1B4,arm1BD,arm1B6,arm1BF, // 1B8
- arm1C0,arm1C1,arm1C2,arm1C3,arm1C4,arm1C5,arm1C6,arm1C7, // 1C0
- arm1C0,arm_UI,arm1C2,arm1CB,arm1C4,arm_UI,arm1C6,arm_UI, // 1C8
- arm1D0,arm1D1,arm1D2,arm1D3,arm1D4,arm1D5,arm1D6,arm1D7, // 1D0
- arm1D0,arm_UI,arm1D2,arm1DB,arm1D4,arm1DD,arm1D6,arm1DF, // 1D8
- arm1E0,arm1E1,arm1E2,arm1E3,arm1E4,arm1E5,arm1E6,arm1E7, // 1E0
- arm1E0,arm_UI,arm1E2,arm1EB,arm1E4,arm_UI,arm1E6,arm_UI, // 1E8
- arm1F0,arm1F1,arm1F2,arm1F3,arm1F4,arm1F5,arm1F6,arm1F7, // 1F0
- arm1F0,arm_UI,arm1F2,arm1FB,arm1F4,arm1FD,arm1F6,arm1FF, // 1F8
-
- REP16(arm200),REP16(arm210),REP16(arm220),REP16(arm230), // 200
- REP16(arm240),REP16(arm250),REP16(arm260),REP16(arm270), // 240
- REP16(arm280),REP16(arm290),REP16(arm2A0),REP16(arm2B0), // 280
- REP16(arm2C0),REP16(arm2D0),REP16(arm2E0),REP16(arm2F0), // 2C0
- REP16(arm_UI),REP16(arm310),REP16(arm320),REP16(arm330), // 300
- REP16(arm_UI),REP16(arm350),REP16(arm360),REP16(arm370), // 340
- REP16(arm380),REP16(arm390),REP16(arm3A0),REP16(arm3B0), // 380
- REP16(arm3C0),REP16(arm3D0),REP16(arm3E0),REP16(arm3F0), // 3C0
-
- REP16(arm400),REP16(arm410),REP16(arm400),REP16(arm410), // 400
- REP16(arm440),REP16(arm450),REP16(arm440),REP16(arm450), // 440
- REP16(arm480),REP16(arm490),REP16(arm480),REP16(arm490), // 480
- REP16(arm4C0),REP16(arm4D0),REP16(arm4C0),REP16(arm4D0), // 4C0
- REP16(arm500),REP16(arm510),REP16(arm520),REP16(arm530), // 500
- REP16(arm540),REP16(arm550),REP16(arm560),REP16(arm570), // 540
- REP16(arm580),REP16(arm590),REP16(arm5A0),REP16(arm5B0), // 580
- REP16(arm5C0),REP16(arm5D0),REP16(arm5E0),REP16(arm5F0), // 5C0
-
- arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 600
- arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 608
- arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 610
- arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 618
- arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 620
- arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 628
- arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 630
- arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 638
- arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 640
- arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 648
- arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 650
- arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 658
- arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 660
- arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 668
- arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 670
- arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 678
- arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 680
- arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 688
- arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 690
- arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 698
- arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A0
- arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A8
- arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B0
- arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B8
- arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C0
- arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C8
- arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D0
- arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D8
- arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E0
- arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E8
- arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F0
- arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F8
-
- arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 700
- arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 708
- arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 710
- arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 718
- arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 720
- arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 728
- arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 730
- arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 738
- arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 740
- arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 748
- arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 750
- arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 758
- arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 760
- arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 768
- arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 770
- arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 778
- arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 780
- arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 788
- arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 790
- arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 798
- arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A0
- arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A8
- arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B0
- arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B8
- arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C0
- arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C8
- arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D0
- arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D8
- arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E0
- arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E8
- arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_UI, // 7F0
- arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_BP, // 7F8
-
- REP16(arm800),REP16(arm810),REP16(arm820),REP16(arm830), // 800
- REP16(arm840),REP16(arm850),REP16(arm860),REP16(arm870), // 840
- REP16(arm880),REP16(arm890),REP16(arm8A0),REP16(arm8B0), // 880
- REP16(arm8C0),REP16(arm8D0),REP16(arm8E0),REP16(arm8F0), // 8C0
- REP16(arm900),REP16(arm910),REP16(arm920),REP16(arm930), // 900
- REP16(arm940),REP16(arm950),REP16(arm960),REP16(arm970), // 940
- REP16(arm980),REP16(arm990),REP16(arm9A0),REP16(arm9B0), // 980
- REP16(arm9C0),REP16(arm9D0),REP16(arm9E0),REP16(arm9F0), // 9C0
-
- REP256(armA00), // A00
- REP256(armB00), // B00
- REP256(arm_UI), // C00
- REP256(arm_UI), // D00
-
- arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E00
- arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E08
- arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E10
- arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E18
- REP16(arm_UI), // E20
- REP16(arm_UI), // E30
- REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E40
- REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E80
- REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // EC0
-
- REP256(armF00), // F00
+#define arm_BP armUnknownInsn
+static insnfunc_t armInsnTable[] =
+{
+ arm000,arm001,arm002,arm003,arm004,arm005,arm006,arm007, // 000
+ arm000,arm009,arm002,arm00B,arm004,arm_UI,arm006,arm_UI, // 008
+ arm010,arm011,arm012,arm013,arm014,arm015,arm016,arm017, // 010
+ arm010,arm019,arm012,arm01B,arm014,arm01D,arm016,arm01F, // 018
+ arm020,arm021,arm022,arm023,arm024,arm025,arm026,arm027, // 020
+ arm020,arm029,arm022,arm_UI,arm024,arm_UI,arm026,arm_UI, // 028
+ arm030,arm031,arm032,arm033,arm034,arm035,arm036,arm037, // 030
+ arm030,arm039,arm032,arm_UI,arm034,arm01D,arm036,arm01F, // 038
+ arm040,arm041,arm042,arm043,arm044,arm045,arm046,arm047, // 040
+ arm040,arm_UI,arm042,arm04B,arm044,arm_UI,arm046,arm_UI, // 048
+ arm050,arm051,arm052,arm053,arm054,arm055,arm056,arm057, // 050
+ arm050,arm_UI,arm052,arm05B,arm054,arm05D,arm056,arm05F, // 058
+ arm060,arm061,arm062,arm063,arm064,arm065,arm066,arm067, // 060
+ arm060,arm_UI,arm062,arm_UI,arm064,arm_UI,arm066,arm_UI, // 068
+ arm070,arm071,arm072,arm073,arm074,arm075,arm076,arm077, // 070
+ arm070,arm_UI,arm072,arm_UI,arm074,arm05D,arm076,arm05F, // 078
+ arm080,arm081,arm082,arm083,arm084,arm085,arm086,arm087, // 080
+ arm080,arm089,arm082,arm08B,arm084,arm_UI,arm086,arm_UI, // 088
+ arm090,arm091,arm092,arm093,arm094,arm095,arm096,arm097, // 090
+ arm090,arm099,arm092,arm09B,arm094,arm09D,arm096,arm09F, // 098
+ arm0A0,arm0A1,arm0A2,arm0A3,arm0A4,arm0A5,arm0A6,arm0A7, // 0A0
+ arm0A0,arm0A9,arm0A2,arm_UI,arm0A4,arm_UI,arm0A6,arm_UI, // 0A8
+ arm0B0,arm0B1,arm0B2,arm0B3,arm0B4,arm0B5,arm0B6,arm0B7, // 0B0
+ arm0B0,arm0B9,arm0B2,arm_UI,arm0B4,arm09D,arm0B6,arm09F, // 0B8
+ arm0C0,arm0C1,arm0C2,arm0C3,arm0C4,arm0C5,arm0C6,arm0C7, // 0C0
+ arm0C0,arm0C9,arm0C2,arm0CB,arm0C4,arm_UI,arm0C6,arm_UI, // 0C8
+ arm0D0,arm0D1,arm0D2,arm0D3,arm0D4,arm0D5,arm0D6,arm0D7, // 0D0
+ arm0D0,arm0D9,arm0D2,arm0DB,arm0D4,arm0DD,arm0D6,arm0DF, // 0D8
+ arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
+ arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
+ arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0
+ arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8
+
+ arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100
+ arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108
+ arm110,arm111,arm112,arm113,arm114,arm115,arm116,arm117, // 110
+ arm110,arm_UI,arm112,arm11B,arm114,arm11D,arm116,arm11F, // 118
+ arm120,arm121,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_BP, // 120
+ arm_UI,arm_UI,arm_UI,arm12B,arm_UI,arm_UI,arm_UI,arm_UI, // 128
+ arm130,arm131,arm132,arm133,arm134,arm135,arm136,arm137, // 130
+ arm130,arm_UI,arm132,arm13B,arm134,arm13D,arm136,arm13F, // 138
+ arm140,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 140
+ arm_UI,arm149,arm_UI,arm14B,arm_UI,arm_UI,arm_UI,arm_UI, // 148
+ arm150,arm151,arm152,arm153,arm154,arm155,arm156,arm157, // 150
+ arm150,arm_UI,arm152,arm15B,arm154,arm15D,arm156,arm15F, // 158
+ arm160,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 160
+ arm_UI,arm_UI,arm_UI,arm16B,arm_UI,arm_UI,arm_UI,arm_UI, // 168
+ arm170,arm171,arm172,arm173,arm174,arm175,arm176,arm177, // 170
+ arm170,arm_UI,arm172,arm17B,arm174,arm17D,arm176,arm17F, // 178
+ arm180,arm181,arm182,arm183,arm184,arm185,arm186,arm187, // 180
+ arm180,arm_UI,arm182,arm18B,arm184,arm_UI,arm186,arm_UI, // 188
+ arm190,arm191,arm192,arm193,arm194,arm195,arm196,arm197, // 190
+ arm190,arm_UI,arm192,arm19B,arm194,arm19D,arm196,arm19F, // 198
+ arm1A0,arm1A1,arm1A2,arm1A3,arm1A4,arm1A5,arm1A6,arm1A7, // 1A0
+ arm1A0,arm_UI,arm1A2,arm1AB,arm1A4,arm_UI,arm1A6,arm_UI, // 1A8
+ arm1B0,arm1B1,arm1B2,arm1B3,arm1B4,arm1B5,arm1B6,arm1B7, // 1B0
+ arm1B0,arm_UI,arm1B2,arm1BB,arm1B4,arm1BD,arm1B6,arm1BF, // 1B8
+ arm1C0,arm1C1,arm1C2,arm1C3,arm1C4,arm1C5,arm1C6,arm1C7, // 1C0
+ arm1C0,arm_UI,arm1C2,arm1CB,arm1C4,arm_UI,arm1C6,arm_UI, // 1C8
+ arm1D0,arm1D1,arm1D2,arm1D3,arm1D4,arm1D5,arm1D6,arm1D7, // 1D0
+ arm1D0,arm_UI,arm1D2,arm1DB,arm1D4,arm1DD,arm1D6,arm1DF, // 1D8
+ arm1E0,arm1E1,arm1E2,arm1E3,arm1E4,arm1E5,arm1E6,arm1E7, // 1E0
+ arm1E0,arm_UI,arm1E2,arm1EB,arm1E4,arm_UI,arm1E6,arm_UI, // 1E8
+ arm1F0,arm1F1,arm1F2,arm1F3,arm1F4,arm1F5,arm1F6,arm1F7, // 1F0
+ arm1F0,arm_UI,arm1F2,arm1FB,arm1F4,arm1FD,arm1F6,arm1FF, // 1F8
+
+ REP16(arm200),REP16(arm210),REP16(arm220),REP16(arm230), // 200
+ REP16(arm240),REP16(arm250),REP16(arm260),REP16(arm270), // 240
+ REP16(arm280),REP16(arm290),REP16(arm2A0),REP16(arm2B0), // 280
+ REP16(arm2C0),REP16(arm2D0),REP16(arm2E0),REP16(arm2F0), // 2C0
+ REP16(arm_UI),REP16(arm310),REP16(arm320),REP16(arm330), // 300
+ REP16(arm_UI),REP16(arm350),REP16(arm360),REP16(arm370), // 340
+ REP16(arm380),REP16(arm390),REP16(arm3A0),REP16(arm3B0), // 380
+ REP16(arm3C0),REP16(arm3D0),REP16(arm3E0),REP16(arm3F0), // 3C0
+
+ REP16(arm400),REP16(arm410),REP16(arm400),REP16(arm410), // 400
+ REP16(arm440),REP16(arm450),REP16(arm440),REP16(arm450), // 440
+ REP16(arm480),REP16(arm490),REP16(arm480),REP16(arm490), // 480
+ REP16(arm4C0),REP16(arm4D0),REP16(arm4C0),REP16(arm4D0), // 4C0
+ REP16(arm500),REP16(arm510),REP16(arm520),REP16(arm530), // 500
+ REP16(arm540),REP16(arm550),REP16(arm560),REP16(arm570), // 540
+ REP16(arm580),REP16(arm590),REP16(arm5A0),REP16(arm5B0), // 580
+ REP16(arm5C0),REP16(arm5D0),REP16(arm5E0),REP16(arm5F0), // 5C0
+
+ arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 600
+ arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 608
+ arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 610
+ arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 618
+ arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 620
+ arm600,arm_UI,arm602,arm_UI,arm604,arm_UI,arm606,arm_UI, // 628
+ arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 630
+ arm610,arm_UI,arm612,arm_UI,arm614,arm_UI,arm616,arm_UI, // 638
+ arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 640
+ arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 648
+ arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 650
+ arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 658
+ arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 660
+ arm640,arm_UI,arm642,arm_UI,arm644,arm_UI,arm646,arm_UI, // 668
+ arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 670
+ arm650,arm_UI,arm652,arm_UI,arm654,arm_UI,arm656,arm_UI, // 678
+ arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 680
+ arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 688
+ arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 690
+ arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 698
+ arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A0
+ arm680,arm_UI,arm682,arm_UI,arm684,arm_UI,arm686,arm_UI, // 6A8
+ arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B0
+ arm690,arm_UI,arm692,arm_UI,arm694,arm_UI,arm696,arm_UI, // 6B8
+ arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C0
+ arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6C8
+ arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D0
+ arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6D8
+ arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E0
+ arm6C0,arm_UI,arm6C2,arm_UI,arm6C4,arm_UI,arm6C6,arm_UI, // 6E8
+ arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F0
+ arm6D0,arm_UI,arm6D2,arm_UI,arm6D4,arm_UI,arm6D6,arm_UI, // 6F8
+
+ arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 700
+ arm700,arm_UI,arm702,arm_UI,arm704,arm_UI,arm706,arm_UI, // 708
+ arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 710
+ arm710,arm_UI,arm712,arm_UI,arm714,arm_UI,arm716,arm_UI, // 718
+ arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 720
+ arm720,arm_UI,arm722,arm_UI,arm724,arm_UI,arm726,arm_UI, // 728
+ arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 730
+ arm730,arm_UI,arm732,arm_UI,arm734,arm_UI,arm736,arm_UI, // 738
+ arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 740
+ arm740,arm_UI,arm742,arm_UI,arm744,arm_UI,arm746,arm_UI, // 748
+ arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 750
+ arm750,arm_UI,arm752,arm_UI,arm754,arm_UI,arm756,arm_UI, // 758
+ arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 760
+ arm760,arm_UI,arm762,arm_UI,arm764,arm_UI,arm766,arm_UI, // 768
+ arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 770
+ arm770,arm_UI,arm772,arm_UI,arm774,arm_UI,arm776,arm_UI, // 778
+ arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 780
+ arm780,arm_UI,arm782,arm_UI,arm784,arm_UI,arm786,arm_UI, // 788
+ arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 790
+ arm790,arm_UI,arm792,arm_UI,arm794,arm_UI,arm796,arm_UI, // 798
+ arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A0
+ arm7A0,arm_UI,arm7A2,arm_UI,arm7A4,arm_UI,arm7A6,arm_UI, // 7A8
+ arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B0
+ arm7B0,arm_UI,arm7B2,arm_UI,arm7B4,arm_UI,arm7B6,arm_UI, // 7B8
+ arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C0
+ arm7C0,arm_UI,arm7C2,arm_UI,arm7C4,arm_UI,arm7C6,arm_UI, // 7C8
+ arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D0
+ arm7D0,arm_UI,arm7D2,arm_UI,arm7D4,arm_UI,arm7D6,arm_UI, // 7D8
+ arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E0
+ arm7E0,arm_UI,arm7E2,arm_UI,arm7E4,arm_UI,arm7E6,arm_UI, // 7E8
+ arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_UI, // 7F0
+ arm7F0,arm_UI,arm7F2,arm_UI,arm7F4,arm_UI,arm7F6,arm_BP, // 7F8
+
+ REP16(arm800),REP16(arm810),REP16(arm820),REP16(arm830), // 800
+ REP16(arm840),REP16(arm850),REP16(arm860),REP16(arm870), // 840
+ REP16(arm880),REP16(arm890),REP16(arm8A0),REP16(arm8B0), // 880
+ REP16(arm8C0),REP16(arm8D0),REP16(arm8E0),REP16(arm8F0), // 8C0
+ REP16(arm900),REP16(arm910),REP16(arm920),REP16(arm930), // 900
+ REP16(arm940),REP16(arm950),REP16(arm960),REP16(arm970), // 940
+ REP16(arm980),REP16(arm990),REP16(arm9A0),REP16(arm9B0), // 980
+ REP16(arm9C0),REP16(arm9D0),REP16(arm9E0),REP16(arm9F0), // 9C0
+
+ REP256(armA00), // A00
+ REP256(armB00), // B00
+ REP256(arm_UI), // C00
+ REP256(arm_UI), // D00
+
+ arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E00
+ arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E08
+ arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E10
+ arm_UI,armE01,arm_UI,armE01,arm_UI,armE01,arm_UI,armE01, // E18
+ REP16(arm_UI), // E20
+ REP16(arm_UI), // E30
+ REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E40
+ REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E80
+ REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // EC0
+
+ REP256(armF00), // F00
};
// Wrapper routine (execution loop) ///////////////////////////////////////
-#if 0
-#include<time.h>
-static void tester(void) {
- static int ran=0;if(ran)return;ran=1;
- FILE*f=fopen("p:\\timing.txt","w");if(!f)return;
- for (int op=/*0*/9; op</*0xF00*/10;op++){if(armInsnTable[op]==arm_UI)continue;
- int i;for(i=0;i<op;i++)if(armInsnTable[op]==armInsnTable[i])break;if(i<op)continue;
- for(i=0;i<16;i++)reg[i].I=0x3100000;
- clock_t s=clock();for(i=0;i<10000000;i++)armInsnTable[op](0);clock_t e=clock();
- fprintf(f,"arm%03X %6ld\n",op,e-s);fflush(f);
- }fclose(f);
-}
-#endif
-
int armExecute()
{
- do {
- /*if( cheatsEnabled ) {
- cpuMasterCodeCheck();
- }*/
-
- if ((armNextPC & 0x0803FFFF) == 0x08020000)
- busPrefetchCount = 0x100;
-
- uint32_t opcode = cpuPrefetch[0];
- cpuPrefetch[0] = cpuPrefetch[1];
-
- busPrefetch = false;
- if (busPrefetchCount & 0xFFFFFE00)
- busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF);
-
- clockTicks = 0;
- int oldArmNextPC = armNextPC;
-
-#ifndef FINAL_VERSION
- if (armNextPC == stop) {
- armNextPC++;
- }
-#endif
-
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH_NEXT;
-
- int cond = opcode >> 28;
- bool cond_res = true;
- if (UNLIKELY(cond != 0x0E)) { // most opcodes are AL (always)
- switch(cond) {
- case 0x00: // EQ
- cond_res = Z_FLAG;
- break;
- case 0x01: // NE
- cond_res = !Z_FLAG;
- break;
- case 0x02: // CS
- cond_res = C_FLAG;
- break;
- case 0x03: // CC
- cond_res = !C_FLAG;
- break;
- case 0x04: // MI
- cond_res = N_FLAG;
- break;
- case 0x05: // PL
- cond_res = !N_FLAG;
- break;
- case 0x06: // VS
- cond_res = V_FLAG;
- break;
- case 0x07: // VC
- cond_res = !V_FLAG;
- break;
- case 0x08: // HI
- cond_res = C_FLAG && !Z_FLAG;
- break;
- case 0x09: // LS
- cond_res = !C_FLAG || Z_FLAG;
- break;
- case 0x0A: // GE
- cond_res = N_FLAG == V_FLAG;
- break;
- case 0x0B: // LT
- cond_res = N_FLAG != V_FLAG;
- break;
- case 0x0C: // GT
- cond_res = !Z_FLAG &&(N_FLAG == V_FLAG);
- break;
- case 0x0D: // LE
- cond_res = Z_FLAG || (N_FLAG != V_FLAG);
- break;
- case 0x0E: // AL (impossible, checked above)
- cond_res = true;
- break;
- case 0x0F:
- default:
- // ???
- cond_res = false;
- break;
- }
- }
-
- if (cond_res)
- (*armInsnTable[((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F)])(opcode);
-#ifdef INSN_COUNTER
- count(opcode, cond_res);
-#endif
- if (clockTicks < 0)
- return 0;
- if (clockTicks == 0)
- clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC);
- cpuTotalTicks += clockTicks;
-
- } while (cpuTotalTicks<cpuNextEvent && armState && !holdState && !SWITicks);
-
- return 1;
-}
-
+ do
+ {
+ if ((armNextPC & 0x0803FFFF) == 0x08020000)
+ busPrefetchCount = 0x100;
+
+ uint32_t opcode = cpuPrefetch[0];
+ cpuPrefetch[0] = cpuPrefetch[1];
+
+ busPrefetch = false;
+ if (busPrefetchCount & 0xFFFFFE00)
+ busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF);
+
+ clockTicks = 0;
+ int oldArmNextPC = armNextPC;
+
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH_NEXT();
+
+ int cond = opcode >> 28;
+ bool cond_res = true;
+ if (UNLIKELY(cond != 0x0E)) // most opcodes are AL (always)
+ {
+ switch (cond)
+ {
+ case 0x00: // EQ
+ cond_res = Z_FLAG;
+ break;
+ case 0x01: // NE
+ cond_res = !Z_FLAG;
+ break;
+ case 0x02: // CS
+ cond_res = C_FLAG;
+ break;
+ case 0x03: // CC
+ cond_res = !C_FLAG;
+ break;
+ case 0x04: // MI
+ cond_res = N_FLAG;
+ break;
+ case 0x05: // PL
+ cond_res = !N_FLAG;
+ break;
+ case 0x06: // VS
+ cond_res = V_FLAG;
+ break;
+ case 0x07: // VC
+ cond_res = !V_FLAG;
+ break;
+ case 0x08: // HI
+ cond_res = C_FLAG && !Z_FLAG;
+ break;
+ case 0x09: // LS
+ cond_res = !C_FLAG || Z_FLAG;
+ break;
+ case 0x0A: // GE
+ cond_res = N_FLAG == V_FLAG;
+ break;
+ case 0x0B: // LT
+ cond_res = N_FLAG != V_FLAG;
+ break;
+ case 0x0C: // GT
+ cond_res = !Z_FLAG && N_FLAG == V_FLAG;
+ break;
+ case 0x0D: // LE
+ cond_res = Z_FLAG || N_FLAG != V_FLAG;
+ break;
+ case 0x0E: // AL (impossible, checked above)
+ cond_res = true;
+ break;
+ case 0x0F:
+ default:
+ // ???
+ cond_res = false;
+ }
+ }
+
+ if (cond_res)
+ (*armInsnTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x0F)])(opcode);
+ if (clockTicks < 0)
+ return 0;
+ if (!clockTicks)
+ clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC);
+ cpuTotalTicks += clockTicks;
+ } while (cpuTotalTicks < cpuNextEvent && armState && !holdState && !SWITicks);
+
+ return 1;
+}
+
--- a/src/in_gsf/vbam/gba/GBA-thumb.cpp
+++ b/src/in_gsf/vbam/gba/GBA-thumb.cpp
@@ -1,30 +1,12 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <stdarg.h>
-#include <string.h>
-
#include "GBA.h"
#include "GBAcpu.h"
#include "GBAinline.h"
#include "Globals.h"
-//#include "EEprom.h"
-//#include "Flash.h"
#include "Sound.h"
-//#include "Sram.h"
#include "bios.h"
-//#include "Cheats.h"
-//#include "../NLS.h"
-//#include "elf.h"
-//#include "../Util.h"
-//#include "../System.h"
-//#include "agbprint.h"
-#ifdef PROFILING
-#include "prof/prof.h"
-#endif
#ifdef _MSC_VER
-#define snprintf _snprintf
+# define snprintf _snprintf
#endif
///////////////////////////////////////////////////////////////////////////
@@ -33,1052 +15,1013 @@
static INSN_REGPARM void thumbUnknownInsn(uint32_t opcode)
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_UNDEFINED)
- log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC-2);
-#endif
- CPUUndefinedException();
-}
-
-#ifdef BKPT_SUPPORT
-static INSN_REGPARM void thumbBreakpoint(uint32_t opcode)
-{
- reg[15].I -= 2;
- armNextPC -= 2;
- dbgSignal(5, opcode & 255);
- clockTicks = -1;
-}
-#endif
+ CPUUndefinedException();
+}
// Common macros //////////////////////////////////////////////////////////
-#ifdef BKPT_SUPPORT
-# define THUMB_CONSOLE_OUTPUT(a,b) do { \
- if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \
- dbgOutput((a), (b)); \
- } \
-} while (0)
-# define UPDATE_OLDREG do { \
- if (debugger_last) { \
- snprintf(oldbuffer, sizeof(oldbuffer), "%08X", \
- armState ? reg[15].I - 4 : reg[15].I - 2); \
- int i; \
- for (i = 0; i < 18; i++) { \
- oldreg[i] = reg[i].I; \
- } \
- } \
-} while (0)
-#else
-# define THUMB_CONSOLE_OUTPUT(a,b)
-# define UPDATE_OLDREG
-#endif
-
-#define NEG(i) ((i) >> 31)
-#define POS(i) ((~(i)) >> 31)
+static inline uint32_t NEG(uint32_t i) { return i >> 31; }
+static inline uint32_t POS(uint32_t i) { return ~i >> 31; }
#ifndef C_CORE
-#ifdef __GNUC__
-#ifdef __POWERPC__
- #define ADD_RD_RS_RN(N) \
- { \
- register int Flags; \
- register int Result; \
- asm volatile("addco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[source].I), \
- "r" (reg[N].I) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define ADD_RD_RS_O3(N) \
- { \
- register int Flags; \
- register int Result; \
- asm volatile("addco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[source].I), \
- "r" (N) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define ADD_RD_RS_O3_0 ADD_RD_RS_O3
- #define ADD_RN_O8(d) \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("addco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[(d)].I), \
- "r" (opcode & 255) \
- ); \
- reg[(d)].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define CMN_RD_RS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("addco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[dest].I), \
- "r" (value) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define ADC_RD_RS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("mtspr 1, %4\n" \ /* reg 1 is xer */
- "addeo. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[dest].I), \
- "r" (value), \
- "r" (C_FLAG << 29) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define SUB_RD_RS_RN(N) \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[source].I), \
- "r" (reg[N].I) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define SUB_RD_RS_O3(N) \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[source].I), \
- "r" (N) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define SUB_RD_RS_O3_0 SUB_RD_RS_O3
- #define SUB_RN_O8(d) \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[(d)].I), \
- "r" (opcode & 255) \
- ); \
- reg[(d)].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define CMP_RN_O8(d) \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[(d)].I), \
- "r" (opcode & 255) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define SBC_RD_RS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("mtspr 1, %4\n" \ /* reg 1 is xer */
- "subfeo. %0, %3, %2\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[dest].I), \
- "r" (value), \
- "r" (C_FLAG << 29) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define NEG_RD_RS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subfco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[source].I), \
- "r" (0) \
- ); \
- reg[dest].I = Result; \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
- #define CMP_RD_RS \
- {\
- register int Flags; \
- register int Result; \
- asm volatile("subco. %0, %2, %3\n" \
- "mcrxr cr1\n" \
- "mfcr %1\n" \
- : "=r" (Result), \
- "=r" (Flags) \
- : "r" (reg[dest].I), \
- "r" (value) \
- ); \
- Z_FLAG = (Flags >> 29) & 1; \
- N_FLAG = (Flags >> 31) & 1; \
- C_FLAG = (Flags >> 25) & 1; \
- V_FLAG = (Flags >> 26) & 1; \
- }
-#else
- #define EMIT1(op,arg) #op" "arg"; "
- #define EMIT2(op,src,dest) #op" "src", "dest"; "
- #define KONST(val) "$"#val
- #define ASMVAR(cvar) ASMVAR2 (__USER_LABEL_PREFIX__, cvar)
- #define ASMVAR2(prefix,cvar) STRING (prefix) cvar
- #define STRING(x) #x
- #define VAR(var) ASMVAR(#var)
- #define REGREF1(index) ASMVAR("reg("index")")
- #define REGREF2(index,scale) ASMVAR("reg(,"index","#scale")")
- #define eax "%%eax"
- #define ecx "%%ecx"
- #define edx "%%edx"
- #define ADD_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- "addl %%eax, %0;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=m" (reg[(d)].I));
- #define CMN_RD_RS \
- asm ("add %0, %1;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : \
- : "r" (value), "r" (reg[dest].I):"1");
- #define ADC_RD_RS \
- asm (EMIT2(bt,KONST(0),VAR(C_FLAG)) \
- "adc %1, %%ebx;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=b" (reg[dest].I)\
- : "r" (value), "b" (reg[dest].I));
- #define SUB_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- "subl %%eax, %0;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=m" (reg[(d)].I));
- #define MOV_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- EMIT2(movb,KONST(0),VAR(N_FLAG)) \
- "movl %%eax, %0;"\
- EMIT1(setzb, VAR(Z_FLAG)) \
- : "=m" (reg[(d)].I));
- #define CMP_RN_O8(d) \
- asm ("andl $0xFF, %%eax;"\
- "cmpl %%eax, %0;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : \
- : "m" (reg[(d)].I));
- #define SBC_RD_RS \
- asm volatile (EMIT2(bt,KONST(0),VAR(C_FLAG)) \
- "cmc;"\
- "sbb %1, %%ebx;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=b" (reg[dest].I)\
- : "r" (value), "b" (reg[dest].I) : "cc", "memory");
- #define LSL_RD_RS \
- asm ("shl %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define LSR_RD_RS \
- asm ("shr %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define ASR_RD_RS \
- asm ("sar %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define ROR_RD_RS \
- asm ("ror %%cl, %%eax;"\
- EMIT1(setcb, VAR(C_FLAG)) \
- : "=a" (value)\
- : "a" (reg[dest].I), "c" (value));
- #define NEG_RD_RS \
- asm ("neg %%ebx;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : "=b" (reg[dest].I)\
- : "b" (reg[source].I));
- #define CMP_RD_RS \
- asm ("sub %0, %1;"\
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG)) \
- : \
- : "r" (value), "r" (reg[dest].I):"1");
- #define IMM5_INSN(OP,N) \
- asm("movl %%eax,%%ecx;" \
- "shrl $1,%%eax;" \
- "andl $7,%%ecx;" \
- "andl $0x1C,%%eax;" \
- EMIT2(movl, REGREF1(eax), edx) \
- OP \
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT2(movl, edx, REGREF2(ecx,4)) \
- : : "i" (N))
- #define IMM5_INSN_0(OP) \
- asm("movl %%eax,%%ecx;" \
- "shrl $1,%%eax;" \
- "andl $7,%%ecx;" \
- "andl $0x1C,%%eax;" \
- EMIT2(movl, REGREF1(eax), edx) \
- OP \
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT2(movl, edx, REGREF2(ecx,4)) \
- : : )
- #define IMM5_LSL \
- "shll %0,%%edx;"\
- EMIT1(setcb, VAR(C_FLAG))
- #define IMM5_LSL_0 \
- "testl %%edx,%%edx;"
- #define IMM5_LSR \
- "shrl %0,%%edx;"\
- EMIT1(setcb, VAR(C_FLAG))
- #define IMM5_LSR_0 \
- "testl %%edx,%%edx;"\
- EMIT1(setsb, VAR(C_FLAG)) \
- "xorl %%edx,%%edx;"
- #define IMM5_ASR \
- "sarl %0,%%edx;"\
- EMIT1(setcb, VAR(C_FLAG))
- #define IMM5_ASR_0 \
- "sarl $31,%%edx;"\
- EMIT1(setsb, VAR(C_FLAG))
- #define THREEARG_INSN(OP,N) \
- asm("movl %%eax,%%edx;" \
- "shrl $1,%%edx;" \
- "andl $0x1C,%%edx;" \
- "andl $7,%%eax;" \
- EMIT2(movl, REGREF1(edx), ecx) \
- OP(N) \
- EMIT1(setsb, VAR(N_FLAG)) \
- EMIT1(setzb, VAR(Z_FLAG)) \
- EMIT2(movl, ecx, REGREF2(eax,4)) \
- : : )
- #define ADD_RD_RS_RN(N) \
- EMIT2(add,VAR(reg)"+"#N"*4",ecx) \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define ADD_RD_RS_O3(N) \
- "add $"#N",%%ecx;" \
- EMIT1(setcb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define ADD_RD_RS_O3_0(N) \
- EMIT2(movb,KONST(0),VAR(C_FLAG)) \
- "add $0,%%ecx;" \
- EMIT2(movb,KONST(0),VAR(V_FLAG))
- #define SUB_RD_RS_RN(N) \
- EMIT2(sub,VAR(reg)"+"#N"*4",ecx) \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define SUB_RD_RS_O3(N) \
- "sub $"#N",%%ecx;" \
- EMIT1(setncb, VAR(C_FLAG)) \
- EMIT1(setob, VAR(V_FLAG))
- #define SUB_RD_RS_O3_0(N) \
- EMIT2(movb,KONST(1),VAR(C_FLAG)) \
- "sub $0,%%ecx;" \
- EMIT2(movb,KONST(0),VAR(V_FLAG))
-#endif
-#else // !__GNUC__
- #define ADD_RD_RS_RN(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, dword ptr [OFFSET reg+4*N]\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define ADD_RD_RS_O3(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, N\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define ADD_RD_RS_O3_0 \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, 0\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm mov byte ptr C_FLAG, 0\
- __asm mov byte ptr V_FLAG, 0\
- }
- #define ADD_RN_O8(d) \
- {\
- __asm mov ebx, opcode\
- __asm and ebx, 255\
- __asm add dword ptr [OFFSET reg+4*(d)], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define CMN_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm add ebx, value\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define ADC_RD_RS \
- {\
- __asm mov ebx, dest\
- __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
- __asm bt word ptr C_FLAG, 0\
- __asm adc ebx, value\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define SUB_RD_RS_RN(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, dword ptr [OFFSET reg+4*N]\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define SUB_RD_RS_O3(N) \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, N\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define SUB_RD_RS_O3_0 \
- {\
- __asm mov eax, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, 0\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm mov byte ptr C_FLAG, 1\
- __asm mov byte ptr V_FLAG, 0\
- }
- #define SUB_RN_O8(d) \
- {\
- __asm mov ebx, opcode\
- __asm and ebx, 255\
- __asm sub dword ptr [OFFSET reg + 4*(d)], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define MOV_RN_O8(d) \
- {\
- __asm mov eax, opcode\
- __asm and eax, 255\
- __asm mov dword ptr [OFFSET reg+4*(d)], eax\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- }
- #define CMP_RN_O8(d) \
- {\
- __asm mov eax, dword ptr [OFFSET reg+4*(d)]\
- __asm mov ebx, opcode\
- __asm and ebx, 255\
- __asm sub eax, ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define SBC_RD_RS \
- {\
- __asm mov ebx, dest\
- __asm mov ebx, dword ptr [OFFSET reg + 4*ebx]\
- __asm mov eax, value\
- __asm bt word ptr C_FLAG, 0\
- __asm cmc\
- __asm sbb ebx, eax\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg + 4*eax], ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define LSL_RD_RM_I5 \
- {\
- __asm mov eax, source\
- __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
- __asm mov cl, byte ptr shift\
- __asm shl eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define LSL_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
- __asm mov cl, byte ptr value\
- __asm shl eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define LSR_RD_RM_I5 \
- {\
- __asm mov eax, source\
- __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
- __asm mov cl, byte ptr shift\
- __asm shr eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define LSR_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4 * eax]\
- __asm mov cl, byte ptr value\
- __asm shr eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define ASR_RD_RM_I5 \
- {\
- __asm mov eax, source\
- __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
- __asm mov cl, byte ptr shift\
- __asm sar eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define ASR_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
- __asm mov cl, byte ptr value\
- __asm sar eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define ROR_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov eax, dword ptr [OFFSET reg + 4*eax]\
- __asm mov cl, byte ptr value\
- __asm ror eax, cl\
- __asm mov value, eax\
- __asm setc byte ptr C_FLAG\
- }
- #define NEG_RD_RS \
- {\
- __asm mov ebx, source\
- __asm mov ebx, dword ptr [OFFSET reg+4*ebx]\
- __asm neg ebx\
- __asm mov eax, dest\
- __asm mov dword ptr [OFFSET reg+4*eax],ebx\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
- #define CMP_RD_RS \
- {\
- __asm mov eax, dest\
- __asm mov ebx, dword ptr [OFFSET reg+4*eax]\
- __asm sub ebx, value\
- __asm sets byte ptr N_FLAG\
- __asm setz byte ptr Z_FLAG\
- __asm setnc byte ptr C_FLAG\
- __asm seto byte ptr V_FLAG\
- }
-#endif
+# ifdef __GNUC__
+# ifdef __POWERPC__
+# define ADD_RD_RS_RN(N) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("addco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[source].I), \
+ "r" (reg[N].I) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define ADD_RD_RS_O3(N) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("addco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[source].I), \
+ "r" (N) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define ADD_RD_RS_O3_0 ADD_RD_RS_O3
+# define ADD_RN_O8(d) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("addco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[(d)].I), \
+ "r" (opcode & 255) \
+ ); \
+ reg[(d)].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define CMN_RD_RS \
+{\
+ register int Flags; \
+ register int Result; \
+ asm volatile("addco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[dest].I), \
+ "r" (value) \
+ ); \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define ADC_RD_RS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("mtspr 1, %4\n" \ /* reg 1 is xer */
+ "addeo. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[dest].I), \
+ "r" (value), \
+ "r" (C_FLAG << 29) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define SUB_RD_RS_RN(N) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[source].I), \
+ "r" (reg[N].I) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define SUB_RD_RS_O3(N) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[source].I), \
+ "r" (N) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define SUB_RD_RS_O3_0 SUB_RD_RS_O3
+# define SUB_RN_O8(d) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[(d)].I), \
+ "r" (opcode & 255) \
+ ); \
+ reg[(d)].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define CMP_RN_O8(d) \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[(d)].I), \
+ "r" (opcode & 255) \
+ ); \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define SBC_RD_RS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("mtspr 1, %4\n" \ /* reg 1 is xer */
+ "subfeo. %0, %3, %2\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[dest].I), \
+ "r" (value), \
+ "r" (C_FLAG << 29) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define NEG_RD_RS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subfco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[source].I), \
+ "r" (0) \
+ ); \
+ reg[dest].I = Result; \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# define CMP_RD_RS \
+{ \
+ register int Flags; \
+ register int Result; \
+ asm volatile("subco. %0, %2, %3\n" \
+ "mcrxr cr1\n" \
+ "mfcr %1\n" \
+ : "=r" (Result), \
+ "=r" (Flags) \
+ : "r" (reg[dest].I), \
+ "r" (value) \
+ ); \
+ Z_FLAG = (Flags >> 29) & 1; \
+ N_FLAG = (Flags >> 31) & 1; \
+ C_FLAG = (Flags >> 25) & 1; \
+ V_FLAG = (Flags >> 26) & 1; \
+}
+# else
+# define EMIT1(op, arg) #op " " arg "; "
+# define EMIT2(op, src, dest) #op " " src ", " dest "; "
+# define KONST(val) "$" #val
+# define ASMVAR(cvar) ASMVAR2(__USER_LABEL_PREFIX__, cvar)
+# define ASMVAR2(prefix, cvar) STRING(prefix) cvar
+# define STRING(x) #x
+# define VAR(var) ASMVAR(#var)
+# define REGREF1(index) ASMVAR("reg(" index ")")
+# define REGREF2(index, scale) ASMVAR("reg(," index "," #scale ")")
+# define eax "%%eax"
+# define ecx "%%ecx"
+# define edx "%%edx"
+# define ADD_RN_O8(d) \
+ asm("andl $0xFF, %%eax;"\
+ "addl %%eax, %0;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : "=m" (reg[(d)].I));
+# define CMN_RD_RS \
+ asm("add %0, %1;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : \
+ : "r" (value), "r" (reg[dest].I) : "1");
+# define ADC_RD_RS \
+ asm(EMIT2(bt, KONST(0), VAR(C_FLAG)) \
+ "adc %1, %%ebx;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : "=b" (reg[dest].I) \
+ : "r" (value), "b" (reg[dest].I));
+# define SUB_RN_O8(d) \
+ asm("andl $0xFF, %%eax;" \
+ "subl %%eax, %0;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : "=m" (reg[(d)].I));
+# define MOV_RN_O8(d) \
+ asm("andl $0xFF, %%eax;" \
+ EMIT2(movb, KONST(0), VAR(N_FLAG)) \
+ "movl %%eax, %0;" \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ : "=m" (reg[(d)].I));
+# define CMP_RN_O8(d) \
+ asm("andl $0xFF, %%eax;" \
+ "cmpl %%eax, %0;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : \
+ : "m" (reg[(d)].I));
+# define SBC_RD_RS \
+ asm volatile(EMIT2(bt, KONST(0), VAR(C_FLAG)) \
+ "cmc;" \
+ "sbb %1, %%ebx;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : "=b" (reg[dest].I) \
+ : "r" (value), "b" (reg[dest].I) : "cc", "memory");
+# define LSL_RD_RS \
+ asm("shl %%cl, %%eax;" \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ : "=a" (value) \
+ : "a" (reg[dest].I), "c" (value));
+# define LSR_RD_RS \
+ asm("shr %%cl, %%eax;" \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ : "=a" (value) \
+ : "a" (reg[dest].I), "c" (value));
+# define ASR_RD_RS \
+ asm("sar %%cl, %%eax;" \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ : "=a" (value) \
+ : "a" (reg[dest].I), "c" (value));
+# define ROR_RD_RS \
+ asm("ror %%cl, %%eax;" \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ : "=a" (value) \
+ : "a" (reg[dest].I), "c" (value));
+# define NEG_RD_RS \
+ asm("neg %%ebx;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : "=b" (reg[dest].I) \
+ : "b" (reg[source].I));
+# define CMP_RD_RS \
+ asm("sub %0, %1;" \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG)) \
+ : \
+ : "r" (value), "r" (reg[dest].I) : "1");
+# define IMM5_INSN(OP,N) \
+ asm("movl %%eax,%%ecx;" \
+ "shrl $1,%%eax;" \
+ "andl $7,%%ecx;" \
+ "andl $0x1C,%%eax;" \
+ EMIT2(movl, REGREF1(eax), edx) \
+ OP \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT2(movl, edx, REGREF2(ecx,4)) \
+ : : "i" (N))
+# define IMM5_INSN_0(OP) \
+ asm("movl %%eax,%%ecx;" \
+ "shrl $1,%%eax;" \
+ "andl $7,%%ecx;" \
+ "andl $0x1C,%%eax;" \
+ EMIT2(movl, REGREF1(eax), edx) \
+ OP \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT2(movl, edx, REGREF2(ecx,4)) \
+ : : )
+# define IMM5_LSL \
+ "shll %0,%%edx;"\
+ EMIT1(setcb, VAR(C_FLAG))
+# define IMM5_LSL_0 \
+ "testl %%edx,%%edx;"
+# define IMM5_LSR \
+ "shrl %0,%%edx;"\
+ EMIT1(setcb, VAR(C_FLAG))
+# define IMM5_LSR_0 \
+ "testl %%edx,%%edx;"\
+ EMIT1(setsb, VAR(C_FLAG)) \
+ "xorl %%edx,%%edx;"
+# define IMM5_ASR \
+ "sarl %0,%%edx;"\
+ EMIT1(setcb, VAR(C_FLAG))
+# define IMM5_ASR_0 \
+ "sarl $31,%%edx;"\
+ EMIT1(setsb, VAR(C_FLAG))
+# define THREEARG_INSN(OP, N) \
+ asm("movl %%eax,%%edx;" \
+ "shrl $1,%%edx;" \
+ "andl $0x1C,%%edx;" \
+ "andl $7,%%eax;" \
+ EMIT2(movl, REGREF1(edx), ecx) \
+ OP(N) \
+ EMIT1(setsb, VAR(N_FLAG)) \
+ EMIT1(setzb, VAR(Z_FLAG)) \
+ EMIT2(movl, ecx, REGREF2(eax,4)) \
+ : : )
+# define ADD_RD_RS_RN(N) \
+ EMIT2(add, VAR(reg) "+" #N "*4", ecx) \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG))
+# define ADD_RD_RS_O3(N) \
+ "add $" #N ",%%ecx;" \
+ EMIT1(setcb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG))
+# define ADD_RD_RS_O3_0(N) \
+ EMIT2(movb, KONST(0), VAR(C_FLAG)) \
+ "add $0,%%ecx;" \
+ EMIT2(movb, KONST(0), VAR(V_FLAG))
+# define SUB_RD_RS_RN(N) \
+ EMIT2(sub, VAR(reg) "+" #N "*4", ecx) \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG))
+# define SUB_RD_RS_O3(N) \
+ "sub $"#N",%%ecx;" \
+ EMIT1(setncb, VAR(C_FLAG)) \
+ EMIT1(setob, VAR(V_FLAG))
+# define SUB_RD_RS_O3_0(N) \
+ EMIT2(movb, KONST(1), VAR(C_FLAG)) \
+ "sub $0,%%ecx;" \
+ EMIT2(movb, KONST(0), VAR(V_FLAG))
+# endif
+# else // !__GNUC__
+# define ADD_RD_RS_RN(N) \
+{ \
+ __asm mov eax, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm add ebx, dword ptr [OFFSET reg + 4 * N] \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define ADD_RD_RS_O3(N) \
+{ \
+ __asm mov eax, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm add ebx, N \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define ADD_RD_RS_O3_0 \
+{ \
+ __asm mov eax, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm add ebx, 0 \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm mov byte ptr C_FLAG, 0 \
+ __asm mov byte ptr V_FLAG, 0 \
+}
+# define ADD_RN_O8(d) \
+{ \
+ __asm mov ebx, opcode \
+ __asm and ebx, 255 \
+ __asm add dword ptr [OFFSET reg + 4 * (d)], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define CMN_RD_RS \
+{ \
+ __asm mov eax, dest \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm add ebx, value \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define ADC_RD_RS \
+{ \
+ __asm mov ebx, dest \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
+ __asm bt word ptr C_FLAG, 0 \
+ __asm adc ebx, value \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define SUB_RD_RS_RN(N) \
+{ \
+ __asm mov eax, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm sub ebx, dword ptr [OFFSET reg + 4 * N] \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define SUB_RD_RS_O3(N) \
+{ \
+ __asm mov eax, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm sub ebx, N \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define SUB_RD_RS_O3_0 \
+{ \
+ __asm mov eax, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm sub ebx, 0 \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm mov byte ptr C_FLAG, 1 \
+ __asm mov byte ptr V_FLAG, 0 \
+}
+# define SUB_RN_O8(d) \
+{ \
+ __asm mov ebx, opcode \
+ __asm and ebx, 255 \
+ __asm sub dword ptr [OFFSET reg + 4 * (d)], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define MOV_RN_O8(d) \
+{ \
+ __asm mov eax, opcode \
+ __asm and eax, 255 \
+ __asm mov dword ptr [OFFSET reg + 4 * (d)], eax \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+}
+# define CMP_RN_O8(d) \
+{ \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * (d)] \
+ __asm mov ebx, opcode \
+ __asm and ebx, 255 \
+ __asm sub eax, ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define SBC_RD_RS \
+{ \
+ __asm mov ebx, dest \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
+ __asm mov eax, value \
+ __asm bt word ptr C_FLAG, 0 \
+ __asm cmc \
+ __asm sbb ebx, eax \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define LSL_RD_RM_I5 \
+{ \
+ __asm mov eax, source \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr shift \
+ __asm shl eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define LSL_RD_RS \
+{ \
+ __asm mov eax, dest \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr value \
+ __asm shl eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define LSR_RD_RM_I5 \
+{ \
+ __asm mov eax, source \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr shift \
+ __asm shr eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define LSR_RD_RS \
+{ \
+ __asm mov eax, dest \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr value \
+ __asm shr eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define ASR_RD_RM_I5 \
+{ \
+ __asm mov eax, source \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr shift \
+ __asm sar eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define ASR_RD_RS \
+{ \
+ __asm mov eax, dest \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr value \
+ __asm sar eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define ROR_RD_RS \
+{ \
+ __asm mov eax, dest \
+ __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
+ __asm mov cl, byte ptr value \
+ __asm ror eax, cl \
+ __asm mov value, eax \
+ __asm setc byte ptr C_FLAG \
+}
+# define NEG_RD_RS \
+{ \
+ __asm mov ebx, source \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
+ __asm neg ebx \
+ __asm mov eax, dest \
+ __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# define CMP_RD_RS \
+{ \
+ __asm mov eax, dest \
+ __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
+ __asm sub ebx, value \
+ __asm sets byte ptr N_FLAG \
+ __asm setz byte ptr Z_FLAG \
+ __asm setnc byte ptr C_FLAG \
+ __asm seto byte ptr V_FLAG \
+}
+# endif
#endif
// C core
#ifndef ADDCARRY
- #define ADDCARRY(a, b, c) \
- C_FLAG = ((NEG(a) & NEG(b)) |\
- (NEG(a) & POS(c)) |\
- (NEG(b) & POS(c))) ? true : false;
+# define ADDCARRY(a, b, c) \
+ C_FLAG = !!((NEG(a) & NEG(b)) | (NEG(a) & POS(c)) | (NEG(b) & POS(c)));
#endif
#ifndef ADDOVERFLOW
- #define ADDOVERFLOW(a, b, c) \
- V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
- (POS(a) & POS(b) & NEG(c))) ? true : false;
+# define ADDOVERFLOW(a, b, c) \
+ V_FLAG = !!((NEG(a) & NEG(b) & POS(c)) | (POS(a) & POS(b) & NEG(c)));
#endif
#ifndef SUBCARRY
- #define SUBCARRY(a, b, c) \
- C_FLAG = ((NEG(a) & POS(b)) |\
- (NEG(a) & POS(c)) |\
- (POS(b) & POS(c))) ? true : false;
+# define SUBCARRY(a, b, c) \
+ C_FLAG = !!((NEG(a) & POS(b)) | (NEG(a) & POS(c)) | (POS(b) & POS(c)));
#endif
#ifndef SUBOVERFLOW
- #define SUBOVERFLOW(a, b, c)\
- V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
- (POS(a) & NEG(b) & NEG(c))) ? true : false;
+# define SUBOVERFLOW(a, b, c) \
+ V_FLAG = !!((NEG(a) & POS(b) & POS(c)) | (POS(a) & NEG(b) & NEG(c)));
#endif
#ifndef ADD_RD_RS_RN
- #define ADD_RD_RS_RN(N) \
- {\
- uint32_t lhs = reg[source].I;\
- uint32_t rhs = reg[N].I;\
- uint32_t res = lhs + rhs;\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- ADDCARRY(lhs, rhs, res);\
- ADDOVERFLOW(lhs, rhs, res);\
- }
+# define ADD_RD_RS_RN(N) \
+{ \
+ uint32_t lhs = reg[source].I; \
+ uint32_t rhs = reg[N].I; \
+ uint32_t res = lhs + rhs; \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ ADDCARRY(lhs, rhs, res); \
+ ADDOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef ADD_RD_RS_O3
- #define ADD_RD_RS_O3(N) \
- {\
- uint32_t lhs = reg[source].I;\
- uint32_t rhs = N;\
- uint32_t res = lhs + rhs;\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- ADDCARRY(lhs, rhs, res);\
- ADDOVERFLOW(lhs, rhs, res);\
- }
+# define ADD_RD_RS_O3(N) \
+{ \
+ uint32_t lhs = reg[source].I; \
+ uint32_t rhs = N; \
+ uint32_t res = lhs + rhs; \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ ADDCARRY(lhs, rhs, res); \
+ ADDOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef ADD_RD_RS_O3_0
# define ADD_RD_RS_O3_0 ADD_RD_RS_O3
#endif
#ifndef ADD_RN_O8
- #define ADD_RN_O8(d) \
- {\
- uint32_t lhs = reg[(d)].I;\
- uint32_t rhs = (opcode & 255);\
- uint32_t res = lhs + rhs;\
- reg[(d)].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- ADDCARRY(lhs, rhs, res);\
- ADDOVERFLOW(lhs, rhs, res);\
- }
+# define ADD_RN_O8(d) \
+{ \
+ uint32_t lhs = reg[(d)].I; \
+ uint32_t rhs = opcode & 255; \
+ uint32_t res = lhs + rhs; \
+ reg[(d)].I = res;\
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ ADDCARRY(lhs, rhs, res); \
+ ADDOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef CMN_RD_RS
- #define CMN_RD_RS \
- {\
- uint32_t lhs = reg[dest].I;\
- uint32_t rhs = value;\
- uint32_t res = lhs + rhs;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- ADDCARRY(lhs, rhs, res);\
- ADDOVERFLOW(lhs, rhs, res);\
- }
+# define CMN_RD_RS \
+{ \
+ uint32_t lhs = reg[dest].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs + rhs; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ ADDCARRY(lhs, rhs, res); \
+ ADDOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef ADC_RD_RS
- #define ADC_RD_RS \
- {\
- uint32_t lhs = reg[dest].I;\
- uint32_t rhs = value;\
- uint32_t res = lhs + rhs + (uint32_t)C_FLAG;\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- ADDCARRY(lhs, rhs, res);\
- ADDOVERFLOW(lhs, rhs, res);\
- }
+# define ADC_RD_RS \
+{ \
+ uint32_t lhs = reg[dest].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs + rhs + static_cast<uint32_t>(C_FLAG); \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ ADDCARRY(lhs, rhs, res); \
+ ADDOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef SUB_RD_RS_RN
- #define SUB_RD_RS_RN(N) \
- {\
- uint32_t lhs = reg[source].I;\
- uint32_t rhs = reg[N].I;\
- uint32_t res = lhs - rhs;\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
+# define SUB_RD_RS_RN(N) \
+{ \
+ uint32_t lhs = reg[source].I; \
+ uint32_t rhs = reg[N].I; \
+ uint32_t res = lhs - rhs; \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(lhs, rhs, res); \
+ SUBOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef SUB_RD_RS_O3
- #define SUB_RD_RS_O3(N) \
- {\
- uint32_t lhs = reg[source].I;\
- uint32_t rhs = N;\
- uint32_t res = lhs - rhs;\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
+# define SUB_RD_RS_O3(N) \
+{ \
+ uint32_t lhs = reg[source].I; \
+ uint32_t rhs = N; \
+ uint32_t res = lhs - rhs; \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(lhs, rhs, res); \
+ SUBOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef SUB_RD_RS_O3_0
# define SUB_RD_RS_O3_0 SUB_RD_RS_O3
#endif
#ifndef SUB_RN_O8
- #define SUB_RN_O8(d) \
- {\
- uint32_t lhs = reg[(d)].I;\
- uint32_t rhs = (opcode & 255);\
- uint32_t res = lhs - rhs;\
- reg[(d)].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
+# define SUB_RN_O8(d) \
+{ \
+ uint32_t lhs = reg[(d)].I; \
+ uint32_t rhs = opcode & 255; \
+ uint32_t res = lhs - rhs; \
+ reg[(d)].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(lhs, rhs, res); \
+ SUBOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef MOV_RN_O8
- #define MOV_RN_O8(d) \
- {\
- reg[d].I = opcode & 255;\
- N_FLAG = false;\
- Z_FLAG = (reg[d].I ? false : true);\
- }
+# define MOV_RN_O8(d) \
+{ \
+ reg[d].I = opcode & 255; \
+ N_FLAG = false; \
+ Z_FLAG = !reg[d].I; \
+}
#endif
#ifndef CMP_RN_O8
- #define CMP_RN_O8(d) \
- {\
- uint32_t lhs = reg[(d)].I;\
- uint32_t rhs = (opcode & 255);\
- uint32_t res = lhs - rhs;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
+# define CMP_RN_O8(d) \
+{ \
+ uint32_t lhs = reg[(d)].I; \
+ uint32_t rhs = opcode & 255; \
+ uint32_t res = lhs - rhs; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(lhs, rhs, res); \
+ SUBOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef SBC_RD_RS
- #define SBC_RD_RS \
- {\
- uint32_t lhs = reg[dest].I;\
- uint32_t rhs = value;\
- uint32_t res = lhs - rhs - !((uint32_t)C_FLAG);\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
+# define SBC_RD_RS \
+{ \
+ uint32_t lhs = reg[dest].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs - rhs - !static_cast<uint32_t>(C_FLAG); \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(lhs, rhs, res); \
+ SUBOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef LSL_RD_RM_I5
- #define LSL_RD_RM_I5 \
- {\
- C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\
- value = reg[source].I << shift;\
- }
+# define LSL_RD_RM_I5 \
+{ \
+ C_FLAG = !!((reg[source].I >> (32 - shift)) & 1); \
+ value = reg[source].I << shift; \
+}
#endif
#ifndef LSL_RD_RS
- #define LSL_RD_RS \
- {\
- C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\
- value = reg[dest].I << value;\
- }
+# define LSL_RD_RS \
+{ \
+ C_FLAG = !!((reg[dest].I >> (32 - value)) & 1); \
+ value = reg[dest].I << value; \
+}
#endif
#ifndef LSR_RD_RM_I5
- #define LSR_RD_RM_I5 \
- {\
- C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\
- value = reg[source].I >> shift;\
- }
+# define LSR_RD_RM_I5 \
+{ \
+ C_FLAG = !!((reg[source].I >> (shift - 1)) & 1); \
+ value = reg[source].I >> shift; \
+}
#endif
#ifndef LSR_RD_RS
- #define LSR_RD_RS \
- {\
- C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
- value = reg[dest].I >> value;\
- }
+# define LSR_RD_RS \
+{ \
+ C_FLAG = !!((reg[dest].I >> (value - 1)) & 1); \
+ value = reg[dest].I >> value; \
+}
#endif
#ifndef ASR_RD_RM_I5
- #define ASR_RD_RM_I5 \
- {\
- C_FLAG = ((int32_t)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
- value = (int32_t)reg[source].I >> (int)shift;\
- }
+# define ASR_RD_RM_I5 \
+{ \
+ C_FLAG = !!((static_cast<int32_t>(reg[source].I) >> static_cast<int>(shift - 1)) & 1); \
+ value = static_cast<int32_t>(reg[source].I) >> static_cast<int>(shift); \
+}
#endif
#ifndef ASR_RD_RS
- #define ASR_RD_RS \
- {\
- C_FLAG = ((int32_t)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
- value = (int32_t)reg[dest].I >> (int)value;\
- }
+# define ASR_RD_RS \
+{ \
+ C_FLAG = !!((static_cast<int32_t>(reg[dest].I >> static_cast<int>(value - 1)) & 1); \
+ value = static_cast<int32_t>(reg[dest].I) >> static_cast<int>(value); \
+}
#endif
#ifndef ROR_RD_RS
- #define ROR_RD_RS \
- {\
- C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\
- value = ((reg[dest].I << (32 - value)) |\
- (reg[dest].I >> value));\
- }
+# define ROR_RD_RS \
+{ \
+ C_FLAG = !!((reg[dest].I >> (value - 1)) & 1); \
+ value = (reg[dest].I << (32 - value)) | (reg[dest].I >> value); \
+}
#endif
#ifndef NEG_RD_RS
- #define NEG_RD_RS \
- {\
- uint32_t lhs = reg[source].I;\
- uint32_t rhs = 0;\
- uint32_t res = rhs - lhs;\
- reg[dest].I = res;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(rhs, lhs, res);\
- SUBOVERFLOW(rhs, lhs, res);\
- }
+# define NEG_RD_RS \
+{ \
+ uint32_t lhs = reg[source].I; \
+ uint32_t rhs = 0; \
+ uint32_t res = rhs - lhs; \
+ reg[dest].I = res; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(rhs, lhs, res); \
+ SUBOVERFLOW(rhs, lhs, res); \
+}
#endif
#ifndef CMP_RD_RS
- #define CMP_RD_RS \
- {\
- uint32_t lhs = reg[dest].I;\
- uint32_t rhs = value;\
- uint32_t res = lhs - rhs;\
- Z_FLAG = (res == 0) ? true : false;\
- N_FLAG = NEG(res) ? true : false;\
- SUBCARRY(lhs, rhs, res);\
- SUBOVERFLOW(lhs, rhs, res);\
- }
+# define CMP_RD_RS \
+{ \
+ uint32_t lhs = reg[dest].I; \
+ uint32_t rhs = value; \
+ uint32_t res = lhs - rhs; \
+ Z_FLAG = !res; \
+ N_FLAG = !!NEG(res); \
+ SUBCARRY(lhs, rhs, res); \
+ SUBOVERFLOW(lhs, rhs, res); \
+}
#endif
#ifndef IMM5_INSN
- #define IMM5_INSN(OP,N) \
- int dest = opcode & 0x07;\
- int source = (opcode >> 3) & 0x07;\
- uint32_t value;\
- OP(N);\
- reg[dest].I = value;\
- N_FLAG = (value & 0x80000000 ? true : false);\
- Z_FLAG = (value ? false : true);
- #define IMM5_INSN_0(OP) \
- int dest = opcode & 0x07;\
- int source = (opcode >> 3) & 0x07;\
- uint32_t value;\
- OP;\
- reg[dest].I = value;\
- N_FLAG = (value & 0x80000000 ? true : false);\
- Z_FLAG = (value ? false : true);
- #define IMM5_LSL(N) \
- int shift = N;\
- LSL_RD_RM_I5;
- #define IMM5_LSL_0 \
- value = reg[source].I;
- #define IMM5_LSR(N) \
- int shift = N;\
- LSR_RD_RM_I5;
- #define IMM5_LSR_0 \
- C_FLAG = reg[source].I & 0x80000000 ? true : false;\
- value = 0;
- #define IMM5_ASR(N) \
- int shift = N;\
- ASR_RD_RM_I5;
- #define IMM5_ASR_0 \
- if(reg[source].I & 0x80000000) {\
- value = 0xFFFFFFFF;\
- C_FLAG = true;\
- } else {\
- value = 0;\
- C_FLAG = false;\
- }
+# define IMM5_INSN(OP, N) \
+ int dest = opcode & 0x07; \
+ int source = (opcode >> 3) & 0x07; \
+ uint32_t value; \
+ OP(N); \
+ reg[dest].I = value; \
+ N_FLAG = !!(value & 0x80000000); \
+ Z_FLAG = !value;
+# define IMM5_INSN_0(OP) \
+ int dest = opcode & 0x07; \
+ int source = (opcode >> 3) & 0x07; \
+ uint32_t value; \
+ OP; \
+ reg[dest].I = value; \
+ N_FLAG = !!(value & 0x80000000); \
+ Z_FLAG = !value;
+# define IMM5_LSL(N) \
+ int shift = N; \
+ LSL_RD_RM_I5;
+# define IMM5_LSL_0 \
+ value = reg[source].I;
+# define IMM5_LSR(N) \
+ int shift = N; \
+ LSR_RD_RM_I5;
+# define IMM5_LSR_0 \
+ C_FLAG = !!(reg[source].I & 0x80000000); \
+ value = 0;
+# define IMM5_ASR(N) \
+ int shift = N; \
+ ASR_RD_RM_I5;
+# define IMM5_ASR_0 \
+ if (reg[source].I & 0x80000000) \
+ { \
+ value = 0xFFFFFFFF; \
+ C_FLAG = true; \
+ } \
+ else \
+ { \
+ value = 0; \
+ C_FLAG = false; \
+ }
#endif
#ifndef THREEARG_INSN
- #define THREEARG_INSN(OP,N) \
- int dest = opcode & 0x07; \
- int source = (opcode >> 3) & 0x07; \
- OP(N);
+# define THREEARG_INSN(OP, N) \
+ int dest = opcode & 0x07; \
+ int source = (opcode >> 3) & 0x07; \
+ OP(N);
#endif
// Shift instructions /////////////////////////////////////////////////////
-#define DEFINE_IMM5_INSN(OP,BASE) \
- static INSN_REGPARM void thumb##BASE##_00(uint32_t opcode) { IMM5_INSN_0(OP##_0); } \
- static INSN_REGPARM void thumb##BASE##_01(uint32_t opcode) { IMM5_INSN(OP, 1); } \
- static INSN_REGPARM void thumb##BASE##_02(uint32_t opcode) { IMM5_INSN(OP, 2); } \
- static INSN_REGPARM void thumb##BASE##_03(uint32_t opcode) { IMM5_INSN(OP, 3); } \
- static INSN_REGPARM void thumb##BASE##_04(uint32_t opcode) { IMM5_INSN(OP, 4); } \
- static INSN_REGPARM void thumb##BASE##_05(uint32_t opcode) { IMM5_INSN(OP, 5); } \
- static INSN_REGPARM void thumb##BASE##_06(uint32_t opcode) { IMM5_INSN(OP, 6); } \
- static INSN_REGPARM void thumb##BASE##_07(uint32_t opcode) { IMM5_INSN(OP, 7); } \
- static INSN_REGPARM void thumb##BASE##_08(uint32_t opcode) { IMM5_INSN(OP, 8); } \
- static INSN_REGPARM void thumb##BASE##_09(uint32_t opcode) { IMM5_INSN(OP, 9); } \
- static INSN_REGPARM void thumb##BASE##_0A(uint32_t opcode) { IMM5_INSN(OP,10); } \
- static INSN_REGPARM void thumb##BASE##_0B(uint32_t opcode) { IMM5_INSN(OP,11); } \
- static INSN_REGPARM void thumb##BASE##_0C(uint32_t opcode) { IMM5_INSN(OP,12); } \
- static INSN_REGPARM void thumb##BASE##_0D(uint32_t opcode) { IMM5_INSN(OP,13); } \
- static INSN_REGPARM void thumb##BASE##_0E(uint32_t opcode) { IMM5_INSN(OP,14); } \
- static INSN_REGPARM void thumb##BASE##_0F(uint32_t opcode) { IMM5_INSN(OP,15); } \
- static INSN_REGPARM void thumb##BASE##_10(uint32_t opcode) { IMM5_INSN(OP,16); } \
- static INSN_REGPARM void thumb##BASE##_11(uint32_t opcode) { IMM5_INSN(OP,17); } \
- static INSN_REGPARM void thumb##BASE##_12(uint32_t opcode) { IMM5_INSN(OP,18); } \
- static INSN_REGPARM void thumb##BASE##_13(uint32_t opcode) { IMM5_INSN(OP,19); } \
- static INSN_REGPARM void thumb##BASE##_14(uint32_t opcode) { IMM5_INSN(OP,20); } \
- static INSN_REGPARM void thumb##BASE##_15(uint32_t opcode) { IMM5_INSN(OP,21); } \
- static INSN_REGPARM void thumb##BASE##_16(uint32_t opcode) { IMM5_INSN(OP,22); } \
- static INSN_REGPARM void thumb##BASE##_17(uint32_t opcode) { IMM5_INSN(OP,23); } \
- static INSN_REGPARM void thumb##BASE##_18(uint32_t opcode) { IMM5_INSN(OP,24); } \
- static INSN_REGPARM void thumb##BASE##_19(uint32_t opcode) { IMM5_INSN(OP,25); } \
- static INSN_REGPARM void thumb##BASE##_1A(uint32_t opcode) { IMM5_INSN(OP,26); } \
- static INSN_REGPARM void thumb##BASE##_1B(uint32_t opcode) { IMM5_INSN(OP,27); } \
- static INSN_REGPARM void thumb##BASE##_1C(uint32_t opcode) { IMM5_INSN(OP,28); } \
- static INSN_REGPARM void thumb##BASE##_1D(uint32_t opcode) { IMM5_INSN(OP,29); } \
- static INSN_REGPARM void thumb##BASE##_1E(uint32_t opcode) { IMM5_INSN(OP,30); } \
- static INSN_REGPARM void thumb##BASE##_1F(uint32_t opcode) { IMM5_INSN(OP,31); }
+#define DEFINE_IMM5_INSN(OP, BASE) \
+ static INSN_REGPARM void thumb##BASE##_00(uint32_t opcode) { IMM5_INSN_0(OP##_0); } \
+ static INSN_REGPARM void thumb##BASE##_01(uint32_t opcode) { IMM5_INSN(OP, 1); } \
+ static INSN_REGPARM void thumb##BASE##_02(uint32_t opcode) { IMM5_INSN(OP, 2); } \
+ static INSN_REGPARM void thumb##BASE##_03(uint32_t opcode) { IMM5_INSN(OP, 3); } \
+ static INSN_REGPARM void thumb##BASE##_04(uint32_t opcode) { IMM5_INSN(OP, 4); } \
+ static INSN_REGPARM void thumb##BASE##_05(uint32_t opcode) { IMM5_INSN(OP, 5); } \
+ static INSN_REGPARM void thumb##BASE##_06(uint32_t opcode) { IMM5_INSN(OP, 6); } \
+ static INSN_REGPARM void thumb##BASE##_07(uint32_t opcode) { IMM5_INSN(OP, 7); } \
+ static INSN_REGPARM void thumb##BASE##_08(uint32_t opcode) { IMM5_INSN(OP, 8); } \
+ static INSN_REGPARM void thumb##BASE##_09(uint32_t opcode) { IMM5_INSN(OP, 9); } \
+ static INSN_REGPARM void thumb##BASE##_0A(uint32_t opcode) { IMM5_INSN(OP, 10); } \
+ static INSN_REGPARM void thumb##BASE##_0B(uint32_t opcode) { IMM5_INSN(OP, 11); } \
+ static INSN_REGPARM void thumb##BASE##_0C(uint32_t opcode) { IMM5_INSN(OP, 12); } \
+ static INSN_REGPARM void thumb##BASE##_0D(uint32_t opcode) { IMM5_INSN(OP, 13); } \
+ static INSN_REGPARM void thumb##BASE##_0E(uint32_t opcode) { IMM5_INSN(OP, 14); } \
+ static INSN_REGPARM void thumb##BASE##_0F(uint32_t opcode) { IMM5_INSN(OP, 15); } \
+ static INSN_REGPARM void thumb##BASE##_10(uint32_t opcode) { IMM5_INSN(OP, 16); } \
+ static INSN_REGPARM void thumb##BASE##_11(uint32_t opcode) { IMM5_INSN(OP, 17); } \
+ static INSN_REGPARM void thumb##BASE##_12(uint32_t opcode) { IMM5_INSN(OP, 18); } \
+ static INSN_REGPARM void thumb##BASE##_13(uint32_t opcode) { IMM5_INSN(OP, 19); } \
+ static INSN_REGPARM void thumb##BASE##_14(uint32_t opcode) { IMM5_INSN(OP, 20); } \
+ static INSN_REGPARM void thumb##BASE##_15(uint32_t opcode) { IMM5_INSN(OP, 21); } \
+ static INSN_REGPARM void thumb##BASE##_16(uint32_t opcode) { IMM5_INSN(OP, 22); } \
+ static INSN_REGPARM void thumb##BASE##_17(uint32_t opcode) { IMM5_INSN(OP, 23); } \
+ static INSN_REGPARM void thumb##BASE##_18(uint32_t opcode) { IMM5_INSN(OP, 24); } \
+ static INSN_REGPARM void thumb##BASE##_19(uint32_t opcode) { IMM5_INSN(OP, 25); } \
+ static INSN_REGPARM void thumb##BASE##_1A(uint32_t opcode) { IMM5_INSN(OP, 26); } \
+ static INSN_REGPARM void thumb##BASE##_1B(uint32_t opcode) { IMM5_INSN(OP, 27); } \
+ static INSN_REGPARM void thumb##BASE##_1C(uint32_t opcode) { IMM5_INSN(OP, 28); } \
+ static INSN_REGPARM void thumb##BASE##_1D(uint32_t opcode) { IMM5_INSN(OP, 29); } \
+ static INSN_REGPARM void thumb##BASE##_1E(uint32_t opcode) { IMM5_INSN(OP, 30); } \
+ static INSN_REGPARM void thumb##BASE##_1F(uint32_t opcode) { IMM5_INSN(OP, 31); }
// LSL Rd, Rm, #Imm 5
-DEFINE_IMM5_INSN(IMM5_LSL,00)
+DEFINE_IMM5_INSN(IMM5_LSL, 00)
// LSR Rd, Rm, #Imm 5
-DEFINE_IMM5_INSN(IMM5_LSR,08)
+DEFINE_IMM5_INSN(IMM5_LSR, 08)
// ASR Rd, Rm, #Imm 5
-DEFINE_IMM5_INSN(IMM5_ASR,10)
+DEFINE_IMM5_INSN(IMM5_ASR, 10)
// 3-argument ADD/SUB /////////////////////////////////////////////////////
-#define DEFINE_REG3_INSN(OP,BASE) \
- static INSN_REGPARM void thumb##BASE##_0(uint32_t opcode) { THREEARG_INSN(OP,0); } \
- static INSN_REGPARM void thumb##BASE##_1(uint32_t opcode) { THREEARG_INSN(OP,1); } \
- static INSN_REGPARM void thumb##BASE##_2(uint32_t opcode) { THREEARG_INSN(OP,2); } \
- static INSN_REGPARM void thumb##BASE##_3(uint32_t opcode) { THREEARG_INSN(OP,3); } \
- static INSN_REGPARM void thumb##BASE##_4(uint32_t opcode) { THREEARG_INSN(OP,4); } \
- static INSN_REGPARM void thumb##BASE##_5(uint32_t opcode) { THREEARG_INSN(OP,5); } \
- static INSN_REGPARM void thumb##BASE##_6(uint32_t opcode) { THREEARG_INSN(OP,6); } \
- static INSN_REGPARM void thumb##BASE##_7(uint32_t opcode) { THREEARG_INSN(OP,7); }
-
-#define DEFINE_IMM3_INSN(OP,BASE) \
- static INSN_REGPARM void thumb##BASE##_0(uint32_t opcode) { THREEARG_INSN(OP##_0,0); } \
- static INSN_REGPARM void thumb##BASE##_1(uint32_t opcode) { THREEARG_INSN(OP,1); } \
- static INSN_REGPARM void thumb##BASE##_2(uint32_t opcode) { THREEARG_INSN(OP,2); } \
- static INSN_REGPARM void thumb##BASE##_3(uint32_t opcode) { THREEARG_INSN(OP,3); } \
- static INSN_REGPARM void thumb##BASE##_4(uint32_t opcode) { THREEARG_INSN(OP,4); } \
- static INSN_REGPARM void thumb##BASE##_5(uint32_t opcode) { THREEARG_INSN(OP,5); } \
- static INSN_REGPARM void thumb##BASE##_6(uint32_t opcode) { THREEARG_INSN(OP,6); } \
- static INSN_REGPARM void thumb##BASE##_7(uint32_t opcode) { THREEARG_INSN(OP,7); }
+#define DEFINE_REG3_INSN(OP, BASE) \
+ static INSN_REGPARM void thumb##BASE##_0(uint32_t opcode) { THREEARG_INSN(OP, 0); } \
+ static INSN_REGPARM void thumb##BASE##_1(uint32_t opcode) { THREEARG_INSN(OP, 1); } \
+ static INSN_REGPARM void thumb##BASE##_2(uint32_t opcode) { THREEARG_INSN(OP, 2); } \
+ static INSN_REGPARM void thumb##BASE##_3(uint32_t opcode) { THREEARG_INSN(OP, 3); } \
+ static INSN_REGPARM void thumb##BASE##_4(uint32_t opcode) { THREEARG_INSN(OP, 4); } \
+ static INSN_REGPARM void thumb##BASE##_5(uint32_t opcode) { THREEARG_INSN(OP, 5); } \
+ static INSN_REGPARM void thumb##BASE##_6(uint32_t opcode) { THREEARG_INSN(OP, 6); } \
+ static INSN_REGPARM void thumb##BASE##_7(uint32_t opcode) { THREEARG_INSN(OP, 7); }
+
+#define DEFINE_IMM3_INSN(OP, BASE) \
+ static INSN_REGPARM void thumb##BASE##_0(uint32_t opcode) { THREEARG_INSN(OP##_0, 0); } \
+ static INSN_REGPARM void thumb##BASE##_1(uint32_t opcode) { THREEARG_INSN(OP, 1); } \
+ static INSN_REGPARM void thumb##BASE##_2(uint32_t opcode) { THREEARG_INSN(OP, 2); } \
+ static INSN_REGPARM void thumb##BASE##_3(uint32_t opcode) { THREEARG_INSN(OP, 3); } \
+ static INSN_REGPARM void thumb##BASE##_4(uint32_t opcode) { THREEARG_INSN(OP, 4); } \
+ static INSN_REGPARM void thumb##BASE##_5(uint32_t opcode) { THREEARG_INSN(OP, 5); } \
+ static INSN_REGPARM void thumb##BASE##_6(uint32_t opcode) { THREEARG_INSN(OP, 6); } \
+ static INSN_REGPARM void thumb##BASE##_7(uint32_t opcode) { THREEARG_INSN(OP, 7); }
// ADD Rd, Rs, Rn
-DEFINE_REG3_INSN(ADD_RD_RS_RN,18)
+DEFINE_REG3_INSN(ADD_RD_RS_RN, 18)
// SUB Rd, Rs, Rn
-DEFINE_REG3_INSN(SUB_RD_RS_RN,1A)
+DEFINE_REG3_INSN(SUB_RD_RS_RN, 1A)
// ADD Rd, Rs, #Offset3
-DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C)
+DEFINE_IMM3_INSN(ADD_RD_RS_O3, 1C)
// SUB Rd, Rs, #Offset3
-DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E)
+DEFINE_IMM3_INSN(SUB_RD_RS_O3, 1E)
// MOV/CMP/ADD/SUB immediate //////////////////////////////////////////////
@@ -1155,206 +1098,226 @@
// AND Rd, Rs
static INSN_REGPARM void thumb40_0(uint32_t opcode)
{
- int dest = opcode & 7;
- reg[dest].I &= reg[(opcode >> 3)&7].I;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- THUMB_CONSOLE_OUTPUT(NULL, reg[2].I);
+ int dest = opcode & 7;
+ reg[dest].I &= reg[(opcode >> 3) & 7].I;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
+ Z_FLAG = !reg[dest].I;
}
// EOR Rd, Rs
static INSN_REGPARM void thumb40_1(uint32_t opcode)
{
- int dest = opcode & 7;
- reg[dest].I ^= reg[(opcode >> 3)&7].I;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
+ int dest = opcode & 7;
+ reg[dest].I ^= reg[(opcode >> 3) & 7].I;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
+ Z_FLAG = !reg[dest].I;
}
// LSL Rd, Rs
static INSN_REGPARM void thumb40_2(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- if(value == 32) {
- value = 0;
- C_FLAG = (reg[dest].I & 1 ? true : false);
- } else if(value < 32) {
- LSL_RD_RS;
- } else {
- value = 0;
- C_FLAG = false;
- }
- reg[dest].I = value;
- }
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- clockTicks = codeTicksAccess16(armNextPC)+2;
+ int dest = opcode & 7;
+ uint32_t value = reg[(opcode >> 3) & 7].B.B0;
+ if (value)
+ {
+ if (value == 32)
+ {
+ value = 0;
+ C_FLAG = !!(reg[dest].I & 1);
+ }
+ else if (value < 32)
+ {
+ LSL_RD_RS;
+ }
+ else
+ {
+ value = 0;
+ C_FLAG = false;
+ }
+ reg[dest].I = value;
+ }
+ N_FLAG = !!(reg[dest].I & 0x80000000);
+ Z_FLAG = !reg[dest].I;
+ clockTicks = codeTicksAccess16(armNextPC) + 2;
}
// LSR Rd, Rs
static INSN_REGPARM void thumb40_3(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- if(value == 32) {
- value = 0;
- C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
- } else if(value < 32) {
- LSR_RD_RS;
- } else {
- value = 0;
- C_FLAG = false;
- }
- reg[dest].I = value;
- }
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- clockTicks = codeTicksAccess16(armNextPC)+2;
+ int dest = opcode & 7;
+ uint32_t value = reg[(opcode >> 3) & 7].B.B0;
+ if (value)
+ {
+ if (value == 32)
+ {
+ value = 0;
+ C_FLAG = !!(reg[dest].I & 0x80000000);
+ }
+ else if (value < 32)
+ {
+ LSR_RD_RS;
+ }
+ else
+ {
+ value = 0;
+ C_FLAG = false;
+ }
+ reg[dest].I = value;
+ }
+ N_FLAG = !!(reg[dest].I & 0x80000000);
+ Z_FLAG = !reg[dest].I;
+ clockTicks = codeTicksAccess16(armNextPC) + 2;
}
// ASR Rd, Rs
static INSN_REGPARM void thumb41_0(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[(opcode >> 3)&7].B.B0;
- if(value) {
- if(value < 32) {
- ASR_RD_RS;
- reg[dest].I = value;
- } else {
- if(reg[dest].I & 0x80000000){
- reg[dest].I = 0xFFFFFFFF;
- C_FLAG = true;
- } else {
- reg[dest].I = 0x00000000;
- C_FLAG = false;
- }
- }
- }
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
- clockTicks = codeTicksAccess16(armNextPC)+2;
+ int dest = opcode & 7;
+ uint32_t value = reg[(opcode >> 3) & 7].B.B0;
+ if (value)
+ {
+ if (value < 32)
+ {
+ ASR_RD_RS;
+ reg[dest].I = value;
+ }
+ else
+ {
+ if (reg[dest].I & 0x80000000)
+ {
+ reg[dest].I = 0xFFFFFFFF;
+ C_FLAG = true;
+ }
+ else
+ {
+ reg[dest].I = 0x00000000;
+ C_FLAG = false;
+ }
+ }
+ }
+ N_FLAG = !!(reg[dest].I & 0x80000000);
+ Z_FLAG = !reg[dest].I;
+ clockTicks = codeTicksAccess16(armNextPC) + 2;
}
// ADC Rd, Rs
static INSN_REGPARM void thumb41_1(uint32_t opcode)
{
- int dest = opcode & 0x07;
- uint32_t value = reg[(opcode >> 3)&7].I;
- ADC_RD_RS;
+ int dest = opcode & 0x07;
+ uint32_t value = reg[(opcode >> 3) & 7].I;
+ ADC_RD_RS;
}
// SBC Rd, Rs
static INSN_REGPARM void thumb41_2(uint32_t opcode)
{
- int dest = opcode & 0x07;
- uint32_t value = reg[(opcode >> 3)&7].I;
- SBC_RD_RS;
+ int dest = opcode & 0x07;
+ uint32_t value = reg[(opcode >> 3) & 7].I;
+ SBC_RD_RS;
}
// ROR Rd, Rs
static INSN_REGPARM void thumb41_3(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[(opcode >> 3)&7].B.B0;
-
- if(value) {
- value = value & 0x1f;
- if(value == 0) {
- C_FLAG = (reg[dest].I & 0x80000000 ? true : false);
- } else {
- ROR_RD_RS;
- reg[dest].I = value;
- }
- }
- clockTicks = codeTicksAccess16(armNextPC)+2;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
- Z_FLAG = reg[dest].I ? false : true;
+ int dest = opcode & 7;
+ uint32_t value = reg[(opcode >> 3) & 7].B.B0;
+
+ if (value)
+ {
+ value &= 0x1f;
+ if (!value)
+ C_FLAG = !!(reg[dest].I & 0x80000000);
+ else
+ {
+ ROR_RD_RS;
+ reg[dest].I = value;
+ }
+ }
+ clockTicks = codeTicksAccess16(armNextPC) + 2;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
+ Z_FLAG = !reg[dest].I;
}
// TST Rd, Rs
static INSN_REGPARM void thumb42_0(uint32_t opcode)
{
- uint32_t value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
- N_FLAG = value & 0x80000000 ? true : false;
- Z_FLAG = value ? false : true;
+ uint32_t value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I;
+ N_FLAG = !!(value & 0x80000000);
+ Z_FLAG = !value;
}
// NEG Rd, Rs
static INSN_REGPARM void thumb42_1(uint32_t opcode)
{
- int dest = opcode & 7;
- int source = (opcode >> 3) & 7;
- NEG_RD_RS;
+ int dest = opcode & 7;
+ int source = (opcode >> 3) & 7;
+ NEG_RD_RS;
}
// CMP Rd, Rs
static INSN_REGPARM void thumb42_2(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[(opcode >> 3)&7].I;
- CMP_RD_RS;
+ int dest = opcode & 7;
+ uint32_t value = reg[(opcode >> 3) & 7].I;
+ CMP_RD_RS;
}
// CMN Rd, Rs
static INSN_REGPARM void thumb42_3(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[(opcode >> 3)&7].I;
- CMN_RD_RS;
+ int dest = opcode & 7;
+ uint32_t value = reg[(opcode >> 3) & 7].I;
+ CMN_RD_RS;
}
// ORR Rd, Rs
static INSN_REGPARM void thumb43_0(uint32_t opcode)
{
- int dest = opcode & 7;
- reg[dest].I |= reg[(opcode >> 3) & 7].I;
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
+ int dest = opcode & 7;
+ reg[dest].I |= reg[(opcode >> 3) & 7].I;
+ Z_FLAG = !reg[dest].I;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
}
// MUL Rd, Rs
static INSN_REGPARM void thumb43_1(uint32_t opcode)
{
- clockTicks = 1;
- int dest = opcode & 7;
- uint32_t rm = reg[dest].I;
- reg[dest].I = reg[(opcode >> 3) & 7].I * rm;
- if (((int32_t)rm) < 0)
- rm = ~rm;
- if ((rm & 0xFFFFFF00) == 0)
- clockTicks += 0;
- else if ((rm & 0xFFFF0000) == 0)
- clockTicks += 1;
- else if ((rm & 0xFF000000) == 0)
- clockTicks += 2;
- else
- clockTicks += 3;
- busPrefetchCount = (busPrefetchCount<<clockTicks) | (0xFF>>(8-clockTicks));
- clockTicks += codeTicksAccess16(armNextPC) + 1;
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
+ clockTicks = 1;
+ int dest = opcode & 7;
+ uint32_t rm = reg[dest].I;
+ reg[dest].I = reg[(opcode >> 3) & 7].I * rm;
+ if (static_cast<int32_t>(rm) < 0)
+ rm = ~rm;
+ if (!(rm & 0xFFFFFF00))
+ ; // No-op
+ else if (!(rm & 0xFFFF0000))
+ ++clockTicks;
+ else if (!(rm & 0xFF000000))
+ clockTicks += 2;
+ else
+ clockTicks += 3;
+ busPrefetchCount = (busPrefetchCount << clockTicks) | (0xFF >> (8 - clockTicks));
+ clockTicks += codeTicksAccess16(armNextPC) + 1;
+ Z_FLAG = !reg[dest].I;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
}
// BIC Rd, Rs
static INSN_REGPARM void thumb43_2(uint32_t opcode)
{
- int dest = opcode & 7;
- reg[dest].I &= (~reg[(opcode >> 3) & 7].I);
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
+ int dest = opcode & 7;
+ reg[dest].I &= ~reg[(opcode >> 3) & 7].I;
+ Z_FLAG = !reg[dest].I;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
}
// MVN Rd, Rs
static INSN_REGPARM void thumb43_3(uint32_t opcode)
{
- int dest = opcode & 7;
- reg[dest].I = ~reg[(opcode >> 3) & 7].I;
- Z_FLAG = reg[dest].I ? false : true;
- N_FLAG = reg[dest].I & 0x80000000 ? true : false;
+ int dest = opcode & 7;
+ reg[dest].I = ~reg[(opcode >> 3) & 7].I;
+ Z_FLAG = !reg[dest].I;
+ N_FLAG = !!(reg[dest].I & 0x80000000);
}
// High-register instructions and BX //////////////////////////////////////
@@ -1362,128 +1325,127 @@
// ADD Rd, Hs
static INSN_REGPARM void thumb44_1(uint32_t opcode)
{
- reg[opcode&7].I += reg[((opcode>>3)&7)+8].I;
+ reg[opcode & 7].I += reg[((opcode >> 3) & 7) + 8].I;
}
// ADD Hd, Rs
static INSN_REGPARM void thumb44_2(uint32_t opcode)
{
- reg[(opcode&7)+8].I += reg[(opcode>>3)&7].I;
- if((opcode&7) == 7) {
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
+ reg[(opcode & 7) + 8].I += reg[(opcode >> 3) & 7].I;
+ if ((opcode & 7) == 7)
+ {
+ reg[15].I &= 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
}
}
// ADD Hd, Hs
static INSN_REGPARM void thumb44_3(uint32_t opcode)
{
- reg[(opcode&7)+8].I += reg[((opcode>>3)&7)+8].I;
- if((opcode&7) == 7) {
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
+ reg[(opcode & 7) + 8].I += reg[((opcode >> 3) & 7) + 8].I;
+ if ((opcode & 7) == 7)
+ {
+ reg[15].I &= 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
+ }
}
// CMP Rd, Hs
static INSN_REGPARM void thumb45_1(uint32_t opcode)
{
- int dest = opcode & 7;
- uint32_t value = reg[((opcode>>3)&7)+8].I;
- CMP_RD_RS;
+ int dest = opcode & 7;
+ uint32_t value = reg[((opcode >> 3) & 7) + 8].I;
+ CMP_RD_RS;
}
// CMP Hd, Rs
static INSN_REGPARM void thumb45_2(uint32_t opcode)
{
- int dest = (opcode & 7) + 8;
- uint32_t value = reg[(opcode>>3)&7].I;
- CMP_RD_RS;
+ int dest = (opcode & 7) + 8;
+ uint32_t value = reg[(opcode >> 3) & 7].I;
+ CMP_RD_RS;
}
// CMP Hd, Hs
static INSN_REGPARM void thumb45_3(uint32_t opcode)
{
- int dest = (opcode & 7) + 8;
- uint32_t value = reg[((opcode>>3)&7)+8].I;
- CMP_RD_RS;
+ int dest = (opcode & 7) + 8;
+ uint32_t value = reg[((opcode >> 3) & 7) + 8].I;
+ CMP_RD_RS;
}
// MOV Rd, Rs
static INSN_REGPARM void thumb46_0(uint32_t opcode)
{
- reg[opcode&7].I = reg[((opcode>>3)&7)].I;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ reg[opcode & 7].I = reg[(opcode >> 3) & 7].I;
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
}
// MOV Rd, Hs
static INSN_REGPARM void thumb46_1(uint32_t opcode)
{
- reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ reg[opcode & 7].I = reg[((opcode >> 3) & 7) + 8].I;
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
}
// MOV Hd, Rs
static INSN_REGPARM void thumb46_2(uint32_t opcode)
{
- reg[(opcode&7)+8].I = reg[(opcode>>3)&7].I;
- if((opcode&7) == 7) {
- UPDATE_OLDREG;
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
+ reg[(opcode & 7) + 8].I = reg[(opcode >> 3) & 7].I;
+ if ((opcode & 7) == 7)
+ {
+ reg[15].I &= 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
+ }
}
// MOV Hd, Hs
static INSN_REGPARM void thumb46_3(uint32_t opcode)
{
- reg[(opcode&7)+8].I = reg[((opcode>>3)&7)+8].I;
- if((opcode&7) == 7) {
- UPDATE_OLDREG;
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2
- + codeTicksAccess16(armNextPC) + 3;
- }
-}
-
+ reg[(opcode & 7) + 8].I = reg[((opcode >> 3) & 7) + 8].I;
+ if ((opcode & 7) == 7)
+ {
+ reg[15].I &= 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
+ }
+}
// BX Rs
static INSN_REGPARM void thumb47(uint32_t opcode)
{
- int base = (opcode >> 3) & 15;
- busPrefetchCount=0;
- UPDATE_OLDREG;
- reg[15].I = reg[base].I;
- if(reg[base].I & 1) {
- armState = false;
- reg[15].I &= 0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
- } else {
- armState = true;
- reg[15].I &= 0xFFFFFFFC;
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH;
- clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3;
- }
+ int base = (opcode >> 3) & 15;
+ busPrefetchCount = 0;
+ reg[15].I = reg[base].I;
+ if (reg[base].I & 1)
+ {
+ armState = false;
+ reg[15].I &= 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
+ }
+ else
+ {
+ armState = true;
+ reg[15].I &= 0xFFFFFFFC;
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH();
+ clockTicks = codeTicksAccessSeq32(armNextPC) * 2 + codeTicksAccess32(armNextPC) + 3;
+ }
}
// Load/store instructions ////////////////////////////////////////////////
@@ -1491,175 +1453,175 @@
// LDR R0~R7,[PC, #Imm]
static INSN_REGPARM void thumb48(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
- reg[regist].I = CPUReadMemoryQuick(address);
- busPrefetchCount=0;
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
+ uint8_t regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
+ reg[regist].I = CPUReadMemoryQuick(address);
+ busPrefetchCount = 0;
+ clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
}
// STR Rd, [Rs, Rn]
static INSN_REGPARM void thumb50(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- CPUWriteMemory(address, reg[opcode & 7].I);
- clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ CPUWriteMemory(address, reg[opcode & 7].I);
+ clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
}
// STRH Rd, [Rs, Rn]
static INSN_REGPARM void thumb52(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- CPUWriteHalfWord(address, reg[opcode&7].W.W0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ CPUWriteHalfWord(address, reg[opcode & 7].W.W0);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
// STRB Rd, [Rs, Rn]
static INSN_REGPARM void thumb54(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I;
- CPUWriteByte(address, reg[opcode & 7].B.B0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ CPUWriteByte(address, reg[opcode & 7].B.B0);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
// LDSB Rd, [Rs, Rn]
static INSN_REGPARM void thumb56(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = (int8_t)CPUReadByte(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ reg[opcode & 7].I = static_cast<int8_t>(CPUReadByte(address));
+ clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
}
// LDR Rd, [Rs, Rn]
static INSN_REGPARM void thumb58(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = CPUReadMemory(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ reg[opcode & 7].I = CPUReadMemory(address);
+ clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
}
// LDRH Rd, [Rs, Rn]
static INSN_REGPARM void thumb5A(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = CPUReadHalfWord(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ reg[opcode & 7].I = CPUReadHalfWord(address);
+ clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
}
// LDRB Rd, [Rs, Rn]
static INSN_REGPARM void thumb5C(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = CPUReadByte(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ reg[opcode & 7].I = CPUReadByte(address);
+ clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
}
// LDSH Rd, [Rs, Rn]
static INSN_REGPARM void thumb5E(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
- reg[opcode&7].I = (uint32_t)CPUReadHalfWordSigned(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I;
+ reg[opcode & 7].I = (uint32_t)CPUReadHalfWordSigned(address);
+ clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
}
// STR Rd, [Rs, #Imm]
static INSN_REGPARM void thumb60(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
- CPUWriteMemory(address, reg[opcode&7].I);
- clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2);
+ CPUWriteMemory(address, reg[opcode & 7].I);
+ clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
}
// LDR Rd, [Rs, #Imm]
static INSN_REGPARM void thumb68(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
- reg[opcode&7].I = CPUReadMemory(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2);
+ reg[opcode & 7].I = CPUReadMemory(address);
+ clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
}
// STRB Rd, [Rs, #Imm]
static INSN_REGPARM void thumb70(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
- CPUWriteByte(address, reg[opcode&7].B.B0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + ((opcode >> 6) & 31);
+ CPUWriteByte(address, reg[opcode & 7].B.B0);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
// LDRB Rd, [Rs, #Imm]
static INSN_REGPARM void thumb78(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + (((opcode>>6)&31));
- reg[opcode&7].I = CPUReadByte(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + ((opcode >> 6) & 31);
+ reg[opcode & 7].I = CPUReadByte(address);
+ clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
}
// STRH Rd, [Rs, #Imm]
static INSN_REGPARM void thumb80(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
- CPUWriteHalfWord(address, reg[opcode&7].W.W0);
- clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1);
+ CPUWriteHalfWord(address, reg[opcode & 7].W.W0);
+ clockTicks = dataTicksAccess16(address) + codeTicksAccess16(armNextPC) + 2;
}
// LDRH Rd, [Rs, #Imm]
static INSN_REGPARM void thumb88(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
- reg[opcode&7].I = CPUReadHalfWord(address);
- clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1);
+ reg[opcode & 7].I = CPUReadHalfWord(address);
+ clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
}
// STR R0~R7, [SP, #Imm]
static INSN_REGPARM void thumb90(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[13].I + ((opcode&255)<<2);
- CPUWriteMemory(address, reg[regist].I);
- clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
+ uint8_t regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[13].I + ((opcode & 255) << 2);
+ CPUWriteMemory(address, reg[regist].I);
+ clockTicks = dataTicksAccess32(address) + codeTicksAccess16(armNextPC) + 2;
}
// LDR R0~R7, [SP, #Imm]
static INSN_REGPARM void thumb98(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[13].I + ((opcode&255)<<2);
- reg[regist].I = CPUReadMemoryQuick(address);
- clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
+ uint8_t regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[13].I + ((opcode & 255) << 2);
+ reg[regist].I = CPUReadMemoryQuick(address);
+ clockTicks = 3 + dataTicksAccess32(address) + codeTicksAccess16(armNextPC);
}
// PC/stack-related ///////////////////////////////////////////////////////
@@ -1667,216 +1629,215 @@
// ADD R0~R7, PC, Imm
static INSN_REGPARM void thumbA0(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
- clockTicks = 1 + codeTicksAccess16(armNextPC);
+ uint8_t regist = (opcode >> 8) & 7;
+ reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2);
+ clockTicks = 1 + codeTicksAccess16(armNextPC);
}
// ADD R0~R7, SP, Imm
static INSN_REGPARM void thumbA8(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- reg[regist].I = reg[13].I + ((opcode&255)<<2);
- clockTicks = 1 + codeTicksAccess16(armNextPC);
+ uint8_t regist = (opcode >> 8) & 7;
+ reg[regist].I = reg[13].I + ((opcode & 255) << 2);
+ clockTicks = 1 + codeTicksAccess16(armNextPC);
}
// ADD SP, Imm
static INSN_REGPARM void thumbB0(uint32_t opcode)
{
- int offset = (opcode & 127) << 2;
- if(opcode & 0x80)
- offset = -offset;
- reg[13].I += offset;
- clockTicks = 1 + codeTicksAccess16(armNextPC);
+ int offset = (opcode & 127) << 2;
+ if (opcode & 0x80)
+ offset = -offset;
+ reg[13].I += offset;
+ clockTicks = 1 + codeTicksAccess16(armNextPC);
}
// Push and pop ///////////////////////////////////////////////////////////
-#define PUSH_REG(val, r) \
- if (opcode & (val)) { \
- CPUWriteMemory(address, reg[(r)].I); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
-
-#define POP_REG(val, r) \
- if (opcode & (val)) { \
- reg[(r)].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
+#define PUSH_REG(val, r) \
+ if (opcode & (val)) \
+ { \
+ CPUWriteMemory(address, reg[(r)].I); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ address += 4; \
+ }
+
+#define POP_REG(val, r) \
+ if (opcode & (val)) \
+ { \
+ reg[(r)].I = CPUReadMemory(address); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ address += 4; \
+ }
// PUSH {Rlist}
static INSN_REGPARM void thumbB4(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- uint32_t temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
- uint32_t address = temp & 0xFFFFFFFC;
- PUSH_REG(1, 0);
- PUSH_REG(2, 1);
- PUSH_REG(4, 2);
- PUSH_REG(8, 3);
- PUSH_REG(16, 4);
- PUSH_REG(32, 5);
- PUSH_REG(64, 6);
- PUSH_REG(128, 7);
- clockTicks += 1 + codeTicksAccess16(armNextPC);
- reg[13].I = temp;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int count = 0;
+ uint32_t temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
+ uint32_t address = temp & 0xFFFFFFFC;
+ PUSH_REG(1, 0);
+ PUSH_REG(2, 1);
+ PUSH_REG(4, 2);
+ PUSH_REG(8, 3);
+ PUSH_REG(16, 4);
+ PUSH_REG(32, 5);
+ PUSH_REG(64, 6);
+ PUSH_REG(128, 7);
+ clockTicks += 1 + codeTicksAccess16(armNextPC);
+ reg[13].I = temp;
}
// PUSH {Rlist, LR}
static INSN_REGPARM void thumbB5(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- uint32_t temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
- uint32_t address = temp & 0xFFFFFFFC;
- PUSH_REG(1, 0);
- PUSH_REG(2, 1);
- PUSH_REG(4, 2);
- PUSH_REG(8, 3);
- PUSH_REG(16, 4);
- PUSH_REG(32, 5);
- PUSH_REG(64, 6);
- PUSH_REG(128, 7);
- PUSH_REG(256, 14);
- clockTicks += 1 + codeTicksAccess16(armNextPC);
- reg[13].I = temp;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int count = 0;
+ uint32_t temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
+ uint32_t address = temp & 0xFFFFFFFC;
+ PUSH_REG(1, 0);
+ PUSH_REG(2, 1);
+ PUSH_REG(4, 2);
+ PUSH_REG(8, 3);
+ PUSH_REG(16, 4);
+ PUSH_REG(32, 5);
+ PUSH_REG(64, 6);
+ PUSH_REG(128, 7);
+ PUSH_REG(256, 14);
+ clockTicks += 1 + codeTicksAccess16(armNextPC);
+ reg[13].I = temp;
}
// POP {Rlist}
static INSN_REGPARM void thumbBC(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- uint32_t address = reg[13].I & 0xFFFFFFFC;
- uint32_t temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
- POP_REG(1, 0);
- POP_REG(2, 1);
- POP_REG(4, 2);
- POP_REG(8, 3);
- POP_REG(16, 4);
- POP_REG(32, 5);
- POP_REG(64, 6);
- POP_REG(128, 7);
- reg[13].I = temp;
- clockTicks = 2 + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int count = 0;
+ uint32_t address = reg[13].I & 0xFFFFFFFC;
+ uint32_t temp = reg[13].I + 4 * cpuBitsSet[opcode & 0xFF];
+ POP_REG(1, 0);
+ POP_REG(2, 1);
+ POP_REG(4, 2);
+ POP_REG(8, 3);
+ POP_REG(16, 4);
+ POP_REG(32, 5);
+ POP_REG(64, 6);
+ POP_REG(128, 7);
+ reg[13].I = temp;
+ clockTicks = 2 + codeTicksAccess16(armNextPC);
}
// POP {Rlist, PC}
static INSN_REGPARM void thumbBD(uint32_t opcode)
{
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- int count = 0;
- uint32_t address = reg[13].I & 0xFFFFFFFC;
- uint32_t temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
- POP_REG(1, 0);
- POP_REG(2, 1);
- POP_REG(4, 2);
- POP_REG(8, 3);
- POP_REG(16, 4);
- POP_REG(32, 5);
- POP_REG(64, 6);
- POP_REG(128, 7);
- reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
- if (!count) {
- clockTicks += 1 + dataTicksAccess32(address);
- } else {
- clockTicks += 1 + dataTicksAccessSeq32(address);
- }
- count++;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- reg[13].I = temp;
- THUMB_PREFETCH;
- busPrefetchCount = 0;
- clockTicks += 3 + codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC);
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ int count = 0;
+ uint32_t address = reg[13].I & 0xFFFFFFFC;
+ uint32_t temp = reg[13].I + 4 + 4 * cpuBitsSet[opcode & 0xFF];
+ POP_REG(1, 0);
+ POP_REG(2, 1);
+ POP_REG(4, 2);
+ POP_REG(8, 3);
+ POP_REG(16, 4);
+ POP_REG(32, 5);
+ POP_REG(64, 6);
+ POP_REG(128, 7);
+ reg[15].I = CPUReadMemory(address) & 0xFFFFFFFE;
+ if (!count)
+ clockTicks += 1 + dataTicksAccess32(address);
+ else
+ clockTicks += 1 + dataTicksAccessSeq32(address);
+ ++count;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ reg[13].I = temp;
+ THUMB_PREFETCH();
+ busPrefetchCount = 0;
+ clockTicks += 3 + codeTicksAccess16(armNextPC) + codeTicksAccess16(armNextPC);
}
// Load/store multiple ////////////////////////////////////////////////////
-#define THUMB_STM_REG(val,r,b) \
- if(opcode & (val)) { \
- CPUWriteMemory(address, reg[(r)].I); \
- reg[(b)].I = temp; \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
-
-#define THUMB_LDM_REG(val,r) \
- if(opcode & (val)) { \
- reg[(r)].I = CPUReadMemory(address); \
- if (!count) { \
- clockTicks += 1 + dataTicksAccess32(address); \
- } else { \
- clockTicks += 1 + dataTicksAccessSeq32(address); \
- } \
- count++; \
- address += 4; \
- }
+#define THUMB_STM_REG(val, r, b) \
+ if (opcode & (val)) \
+ { \
+ CPUWriteMemory(address, reg[(r)].I); \
+ reg[(b)].I = temp; \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ address += 4; \
+ }
+
+#define THUMB_LDM_REG(val, r) \
+ if (opcode & (val)) \
+ { \
+ reg[(r)].I = CPUReadMemory(address); \
+ if (!count) \
+ clockTicks += 1 + dataTicksAccess32(address); \
+ else \
+ clockTicks += 1 + dataTicksAccessSeq32(address); \
+ ++count; \
+ address += 4; \
+ }
// STM R0~7!, {Rlist}
static INSN_REGPARM void thumbC0(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[regist].I & 0xFFFFFFFC;
- uint32_t temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
- int count = 0;
- // store
- THUMB_STM_REG(1, 0, regist);
- THUMB_STM_REG(2, 1, regist);
- THUMB_STM_REG(4, 2, regist);
- THUMB_STM_REG(8, 3, regist);
- THUMB_STM_REG(16, 4, regist);
- THUMB_STM_REG(32, 5, regist);
- THUMB_STM_REG(64, 6, regist);
- THUMB_STM_REG(128, 7, regist);
- clockTicks = 1 + codeTicksAccess16(armNextPC);
+ uint8_t regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[regist].I & 0xFFFFFFFC;
+ uint32_t temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
+ int count = 0;
+ // store
+ THUMB_STM_REG(1, 0, regist);
+ THUMB_STM_REG(2, 1, regist);
+ THUMB_STM_REG(4, 2, regist);
+ THUMB_STM_REG(8, 3, regist);
+ THUMB_STM_REG(16, 4, regist);
+ THUMB_STM_REG(32, 5, regist);
+ THUMB_STM_REG(64, 6, regist);
+ THUMB_STM_REG(128, 7, regist);
+ clockTicks = 1 + codeTicksAccess16(armNextPC);
}
// LDM R0~R7!, {Rlist}
static INSN_REGPARM void thumbC8(uint32_t opcode)
{
- uint8_t regist = (opcode >> 8) & 7;
- if (busPrefetchCount == 0)
- busPrefetch = busPrefetchEnable;
- uint32_t address = reg[regist].I & 0xFFFFFFFC;
- uint32_t temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
- int count = 0;
- // load
- THUMB_LDM_REG(1, 0);
- THUMB_LDM_REG(2, 1);
- THUMB_LDM_REG(4, 2);
- THUMB_LDM_REG(8, 3);
- THUMB_LDM_REG(16, 4);
- THUMB_LDM_REG(32, 5);
- THUMB_LDM_REG(64, 6);
- THUMB_LDM_REG(128, 7);
- clockTicks = 2 + codeTicksAccess16(armNextPC);
- if(!(opcode & (1<<regist)))
- reg[regist].I = temp;
+ uint8_t regist = (opcode >> 8) & 7;
+ if (!busPrefetchCount)
+ busPrefetch = busPrefetchEnable;
+ uint32_t address = reg[regist].I & 0xFFFFFFFC;
+ uint32_t temp = reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
+ int count = 0;
+ // load
+ THUMB_LDM_REG(1, 0);
+ THUMB_LDM_REG(2, 1);
+ THUMB_LDM_REG(4, 2);
+ THUMB_LDM_REG(8, 3);
+ THUMB_LDM_REG(16, 4);
+ THUMB_LDM_REG(32, 5);
+ THUMB_LDM_REG(64, 6);
+ THUMB_LDM_REG(128, 7);
+ clockTicks = 2 + codeTicksAccess16(armNextPC);
+ if (!(opcode & (1 << regist)))
+ reg[regist].I = temp;
}
// Conditional branches ///////////////////////////////////////////////////
@@ -1884,211 +1845,211 @@
// BEQ offset
static INSN_REGPARM void thumbD0(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(Z_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (Z_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BNE offset
static INSN_REGPARM void thumbD1(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(!Z_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (!Z_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BCS offset
static INSN_REGPARM void thumbD2(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(C_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (C_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BCC offset
static INSN_REGPARM void thumbD3(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(!C_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (!C_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BMI offset
static INSN_REGPARM void thumbD4(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(N_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (N_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BPL offset
static INSN_REGPARM void thumbD5(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(!N_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (!N_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BVS offset
static INSN_REGPARM void thumbD6(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(V_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (V_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BVC offset
static INSN_REGPARM void thumbD7(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(!V_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (!V_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BHI offset
static INSN_REGPARM void thumbD8(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(C_FLAG && !Z_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (C_FLAG && !Z_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BLS offset
static INSN_REGPARM void thumbD9(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(!C_FLAG || Z_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (!C_FLAG || Z_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BGE offset
static INSN_REGPARM void thumbDA(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(N_FLAG == V_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (N_FLAG == V_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BLT offset
static INSN_REGPARM void thumbDB(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(N_FLAG != V_FLAG) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (N_FLAG != V_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BGT offset
static INSN_REGPARM void thumbDC(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
- if(!Z_FLAG && (N_FLAG == V_FLAG)) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ if (!Z_FLAG && N_FLAG == V_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// BLE offset
static INSN_REGPARM void thumbDD(uint32_t opcode)
{
- UPDATE_OLDREG;
- clockTicks = codeTicksAccessSeq16(armNextPC);
- if(Z_FLAG || (N_FLAG != V_FLAG)) {
- reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
- busPrefetchCount=0;
- }
+ clockTicks = codeTicksAccessSeq16(armNextPC);
+ if (Z_FLAG || N_FLAG != V_FLAG)
+ {
+ reg[15].I += static_cast<int8_t>(opcode & 0xFF) << 1;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
+ busPrefetchCount = 0;
+ }
}
// SWI, B, BL /////////////////////////////////////////////////////////////
@@ -2096,236 +2057,220 @@
// SWI #comment
static INSN_REGPARM void thumbDF(uint32_t opcode)
{
- uint32_t address = 0;
- //clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3;
- clockTicks = 3;
- busPrefetchCount=0;
- CPUSoftwareInterrupt(opcode & 0xFF);
+ uint32_t address = 0;
+ clockTicks = 3;
+ busPrefetchCount = 0;
+ CPUSoftwareInterrupt(opcode & 0xFF);
}
// B offset
static INSN_REGPARM void thumbE0(uint32_t opcode)
{
- int offset = (opcode & 0x3FF) << 1;
- if(opcode & 0x0400)
- offset |= 0xFFFFF800;
- reg[15].I += offset;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3;
- busPrefetchCount=0;
+ int offset = (opcode & 0x3FF) << 1;
+ if (opcode & 0x0400)
+ offset |= 0xFFFFF800;
+ reg[15].I += offset;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
+ busPrefetchCount = 0;
}
// BLL #offset (forward)
static INSN_REGPARM void thumbF0(uint32_t opcode)
{
- int offset = (opcode & 0x7FF);
- reg[14].I = reg[15].I + (offset << 12);
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ int offset = opcode & 0x7FF;
+ reg[14].I = reg[15].I + (offset << 12);
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
}
// BLL #offset (backward)
static INSN_REGPARM void thumbF4(uint32_t opcode)
{
- int offset = (opcode & 0x7FF);
- reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000);
- clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
+ int offset = opcode & 0x7FF;
+ reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000);
+ clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
}
// BLH #offset
static INSN_REGPARM void thumbF8(uint32_t opcode)
{
- int offset = (opcode & 0x7FF);
- uint32_t temp = reg[15].I-2;
- reg[15].I = (reg[14].I + (offset<<1))&0xFFFFFFFE;
- armNextPC = reg[15].I;
- reg[15].I += 2;
- reg[14].I = temp|1;
- THUMB_PREFETCH;
- clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
- busPrefetchCount = 0;
+ int offset = opcode & 0x7FF;
+ uint32_t temp = reg[15].I - 2;
+ reg[15].I = (reg[14].I + (offset << 1)) & 0xFFFFFFFE;
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ reg[14].I = temp | 1;
+ THUMB_PREFETCH();
+ clockTicks = codeTicksAccessSeq16(armNextPC) * 2 + codeTicksAccess16(armNextPC) + 3;
+ busPrefetchCount = 0;
}
// Instruction table //////////////////////////////////////////////////////
typedef INSN_REGPARM void (*insnfunc_t)(uint32_t opcode);
#define thumbUI thumbUnknownInsn
-#ifdef BKPT_SUPPORT
- #define thumbBP thumbBreakpoint
-#else
- #define thumbBP thumbUnknownInsn
-#endif
-static insnfunc_t thumbInsnTable[1024] = {
- thumb00_00,thumb00_01,thumb00_02,thumb00_03,thumb00_04,thumb00_05,thumb00_06,thumb00_07, // 00
- thumb00_08,thumb00_09,thumb00_0A,thumb00_0B,thumb00_0C,thumb00_0D,thumb00_0E,thumb00_0F,
- thumb00_10,thumb00_11,thumb00_12,thumb00_13,thumb00_14,thumb00_15,thumb00_16,thumb00_17,
- thumb00_18,thumb00_19,thumb00_1A,thumb00_1B,thumb00_1C,thumb00_1D,thumb00_1E,thumb00_1F,
- thumb08_00,thumb08_01,thumb08_02,thumb08_03,thumb08_04,thumb08_05,thumb08_06,thumb08_07, // 08
- thumb08_08,thumb08_09,thumb08_0A,thumb08_0B,thumb08_0C,thumb08_0D,thumb08_0E,thumb08_0F,
- thumb08_10,thumb08_11,thumb08_12,thumb08_13,thumb08_14,thumb08_15,thumb08_16,thumb08_17,
- thumb08_18,thumb08_19,thumb08_1A,thumb08_1B,thumb08_1C,thumb08_1D,thumb08_1E,thumb08_1F,
- thumb10_00,thumb10_01,thumb10_02,thumb10_03,thumb10_04,thumb10_05,thumb10_06,thumb10_07, // 10
- thumb10_08,thumb10_09,thumb10_0A,thumb10_0B,thumb10_0C,thumb10_0D,thumb10_0E,thumb10_0F,
- thumb10_10,thumb10_11,thumb10_12,thumb10_13,thumb10_14,thumb10_15,thumb10_16,thumb10_17,
- thumb10_18,thumb10_19,thumb10_1A,thumb10_1B,thumb10_1C,thumb10_1D,thumb10_1E,thumb10_1F,
- thumb18_0,thumb18_1,thumb18_2,thumb18_3,thumb18_4,thumb18_5,thumb18_6,thumb18_7, // 18
- thumb1A_0,thumb1A_1,thumb1A_2,thumb1A_3,thumb1A_4,thumb1A_5,thumb1A_6,thumb1A_7,
- thumb1C_0,thumb1C_1,thumb1C_2,thumb1C_3,thumb1C_4,thumb1C_5,thumb1C_6,thumb1C_7,
- thumb1E_0,thumb1E_1,thumb1E_2,thumb1E_3,thumb1E_4,thumb1E_5,thumb1E_6,thumb1E_7,
- thumb20,thumb20,thumb20,thumb20,thumb21,thumb21,thumb21,thumb21, // 20
- thumb22,thumb22,thumb22,thumb22,thumb23,thumb23,thumb23,thumb23,
- thumb24,thumb24,thumb24,thumb24,thumb25,thumb25,thumb25,thumb25,
- thumb26,thumb26,thumb26,thumb26,thumb27,thumb27,thumb27,thumb27,
- thumb28,thumb28,thumb28,thumb28,thumb29,thumb29,thumb29,thumb29, // 28
- thumb2A,thumb2A,thumb2A,thumb2A,thumb2B,thumb2B,thumb2B,thumb2B,
- thumb2C,thumb2C,thumb2C,thumb2C,thumb2D,thumb2D,thumb2D,thumb2D,
- thumb2E,thumb2E,thumb2E,thumb2E,thumb2F,thumb2F,thumb2F,thumb2F,
- thumb30,thumb30,thumb30,thumb30,thumb31,thumb31,thumb31,thumb31, // 30
- thumb32,thumb32,thumb32,thumb32,thumb33,thumb33,thumb33,thumb33,
- thumb34,thumb34,thumb34,thumb34,thumb35,thumb35,thumb35,thumb35,
- thumb36,thumb36,thumb36,thumb36,thumb37,thumb37,thumb37,thumb37,
- thumb38,thumb38,thumb38,thumb38,thumb39,thumb39,thumb39,thumb39, // 38
- thumb3A,thumb3A,thumb3A,thumb3A,thumb3B,thumb3B,thumb3B,thumb3B,
- thumb3C,thumb3C,thumb3C,thumb3C,thumb3D,thumb3D,thumb3D,thumb3D,
- thumb3E,thumb3E,thumb3E,thumb3E,thumb3F,thumb3F,thumb3F,thumb3F,
- thumb40_0,thumb40_1,thumb40_2,thumb40_3,thumb41_0,thumb41_1,thumb41_2,thumb41_3, // 40
- thumb42_0,thumb42_1,thumb42_2,thumb42_3,thumb43_0,thumb43_1,thumb43_2,thumb43_3,
- thumbUI,thumb44_1,thumb44_2,thumb44_3,thumbUI,thumb45_1,thumb45_2,thumb45_3,
- thumb46_0,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
- thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48, // 48
- thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
- thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
- thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
- thumb50,thumb50,thumb50,thumb50,thumb50,thumb50,thumb50,thumb50, // 50
- thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,
- thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,
- thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,
- thumb58,thumb58,thumb58,thumb58,thumb58,thumb58,thumb58,thumb58, // 58
- thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,
- thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,
- thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,
- thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60, // 60
- thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
- thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
- thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
- thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68, // 68
- thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
- thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
- thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
- thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70, // 70
- thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
- thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
- thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
- thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78, // 78
- thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
- thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
- thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
- thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80, // 80
- thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
- thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
- thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
- thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88, // 88
- thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
- thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
- thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
- thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90, // 90
- thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
- thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
- thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
- thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98, // 98
- thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
- thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
- thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
- thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0, // A0
- thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
- thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
- thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
- thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8, // A8
- thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
- thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
- thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
- thumbB0,thumbB0,thumbB0,thumbB0,thumbUI,thumbUI,thumbUI,thumbUI, // B0
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbB4,thumbB4,thumbB4,thumbB4,thumbB5,thumbB5,thumbB5,thumbB5,
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI, // B8
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbBC,thumbBC,thumbBC,thumbBC,thumbBD,thumbBD,thumbBD,thumbBD,
- thumbBP,thumbBP,thumbBP,thumbBP,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0, // C0
- thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
- thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
- thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
- thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8, // C8
- thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
- thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
- thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
- thumbD0,thumbD0,thumbD0,thumbD0,thumbD1,thumbD1,thumbD1,thumbD1, // D0
- thumbD2,thumbD2,thumbD2,thumbD2,thumbD3,thumbD3,thumbD3,thumbD3,
- thumbD4,thumbD4,thumbD4,thumbD4,thumbD5,thumbD5,thumbD5,thumbD5,
- thumbD6,thumbD6,thumbD6,thumbD6,thumbD7,thumbD7,thumbD7,thumbD7,
- thumbD8,thumbD8,thumbD8,thumbD8,thumbD9,thumbD9,thumbD9,thumbD9, // D8
- thumbDA,thumbDA,thumbDA,thumbDA,thumbDB,thumbDB,thumbDB,thumbDB,
- thumbDC,thumbDC,thumbDC,thumbDC,thumbDD,thumbDD,thumbDD,thumbDD,
- thumbUI,thumbUI,thumbUI,thumbUI,thumbDF,thumbDF,thumbDF,thumbDF,
- thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0, // E0
- thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
- thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
- thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI, // E8
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
- thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0, // F0
- thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,
- thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,
- thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,
- thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8, // F8
- thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
- thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
- thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
+#define thumbBP thumbUnknownInsn
+static insnfunc_t thumbInsnTable[] =
+{
+ thumb00_00,thumb00_01,thumb00_02,thumb00_03,thumb00_04,thumb00_05,thumb00_06,thumb00_07, // 00
+ thumb00_08,thumb00_09,thumb00_0A,thumb00_0B,thumb00_0C,thumb00_0D,thumb00_0E,thumb00_0F,
+ thumb00_10,thumb00_11,thumb00_12,thumb00_13,thumb00_14,thumb00_15,thumb00_16,thumb00_17,
+ thumb00_18,thumb00_19,thumb00_1A,thumb00_1B,thumb00_1C,thumb00_1D,thumb00_1E,thumb00_1F,
+ thumb08_00,thumb08_01,thumb08_02,thumb08_03,thumb08_04,thumb08_05,thumb08_06,thumb08_07, // 08
+ thumb08_08,thumb08_09,thumb08_0A,thumb08_0B,thumb08_0C,thumb08_0D,thumb08_0E,thumb08_0F,
+ thumb08_10,thumb08_11,thumb08_12,thumb08_13,thumb08_14,thumb08_15,thumb08_16,thumb08_17,
+ thumb08_18,thumb08_19,thumb08_1A,thumb08_1B,thumb08_1C,thumb08_1D,thumb08_1E,thumb08_1F,
+ thumb10_00,thumb10_01,thumb10_02,thumb10_03,thumb10_04,thumb10_05,thumb10_06,thumb10_07, // 10
+ thumb10_08,thumb10_09,thumb10_0A,thumb10_0B,thumb10_0C,thumb10_0D,thumb10_0E,thumb10_0F,
+ thumb10_10,thumb10_11,thumb10_12,thumb10_13,thumb10_14,thumb10_15,thumb10_16,thumb10_17,
+ thumb10_18,thumb10_19,thumb10_1A,thumb10_1B,thumb10_1C,thumb10_1D,thumb10_1E,thumb10_1F,
+ thumb18_0,thumb18_1,thumb18_2,thumb18_3,thumb18_4,thumb18_5,thumb18_6,thumb18_7, // 18
+ thumb1A_0,thumb1A_1,thumb1A_2,thumb1A_3,thumb1A_4,thumb1A_5,thumb1A_6,thumb1A_7,
+ thumb1C_0,thumb1C_1,thumb1C_2,thumb1C_3,thumb1C_4,thumb1C_5,thumb1C_6,thumb1C_7,
+ thumb1E_0,thumb1E_1,thumb1E_2,thumb1E_3,thumb1E_4,thumb1E_5,thumb1E_6,thumb1E_7,
+ thumb20,thumb20,thumb20,thumb20,thumb21,thumb21,thumb21,thumb21, // 20
+ thumb22,thumb22,thumb22,thumb22,thumb23,thumb23,thumb23,thumb23,
+ thumb24,thumb24,thumb24,thumb24,thumb25,thumb25,thumb25,thumb25,
+ thumb26,thumb26,thumb26,thumb26,thumb27,thumb27,thumb27,thumb27,
+ thumb28,thumb28,thumb28,thumb28,thumb29,thumb29,thumb29,thumb29, // 28
+ thumb2A,thumb2A,thumb2A,thumb2A,thumb2B,thumb2B,thumb2B,thumb2B,
+ thumb2C,thumb2C,thumb2C,thumb2C,thumb2D,thumb2D,thumb2D,thumb2D,
+ thumb2E,thumb2E,thumb2E,thumb2E,thumb2F,thumb2F,thumb2F,thumb2F,
+ thumb30,thumb30,thumb30,thumb30,thumb31,thumb31,thumb31,thumb31, // 30
+ thumb32,thumb32,thumb32,thumb32,thumb33,thumb33,thumb33,thumb33,
+ thumb34,thumb34,thumb34,thumb34,thumb35,thumb35,thumb35,thumb35,
+ thumb36,thumb36,thumb36,thumb36,thumb37,thumb37,thumb37,thumb37,
+ thumb38,thumb38,thumb38,thumb38,thumb39,thumb39,thumb39,thumb39, // 38
+ thumb3A,thumb3A,thumb3A,thumb3A,thumb3B,thumb3B,thumb3B,thumb3B,
+ thumb3C,thumb3C,thumb3C,thumb3C,thumb3D,thumb3D,thumb3D,thumb3D,
+ thumb3E,thumb3E,thumb3E,thumb3E,thumb3F,thumb3F,thumb3F,thumb3F,
+ thumb40_0,thumb40_1,thumb40_2,thumb40_3,thumb41_0,thumb41_1,thumb41_2,thumb41_3, // 40
+ thumb42_0,thumb42_1,thumb42_2,thumb42_3,thumb43_0,thumb43_1,thumb43_2,thumb43_3,
+ thumbUI,thumb44_1,thumb44_2,thumb44_3,thumbUI,thumb45_1,thumb45_2,thumb45_3,
+ thumb46_0,thumb46_1,thumb46_2,thumb46_3,thumb47,thumb47,thumbUI,thumbUI,
+ thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48, // 48
+ thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
+ thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
+ thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,thumb48,
+ thumb50,thumb50,thumb50,thumb50,thumb50,thumb50,thumb50,thumb50, // 50
+ thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,thumb52,
+ thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,thumb54,
+ thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,thumb56,
+ thumb58,thumb58,thumb58,thumb58,thumb58,thumb58,thumb58,thumb58, // 58
+ thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,thumb5A,
+ thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,thumb5C,
+ thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,thumb5E,
+ thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60, // 60
+ thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
+ thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
+ thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,thumb60,
+ thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68, // 68
+ thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
+ thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
+ thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,thumb68,
+ thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70, // 70
+ thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
+ thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
+ thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,thumb70,
+ thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78, // 78
+ thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
+ thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
+ thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,thumb78,
+ thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80, // 80
+ thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
+ thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
+ thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,thumb80,
+ thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88, // 88
+ thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
+ thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
+ thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,thumb88,
+ thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90, // 90
+ thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
+ thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
+ thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,thumb90,
+ thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98, // 98
+ thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
+ thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
+ thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,thumb98,
+ thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0, // A0
+ thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
+ thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
+ thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,thumbA0,
+ thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8, // A8
+ thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
+ thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
+ thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,thumbA8,
+ thumbB0,thumbB0,thumbB0,thumbB0,thumbUI,thumbUI,thumbUI,thumbUI, // B0
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbB4,thumbB4,thumbB4,thumbB4,thumbB5,thumbB5,thumbB5,thumbB5,
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI, // B8
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbBC,thumbBC,thumbBC,thumbBC,thumbBD,thumbBD,thumbBD,thumbBD,
+ thumbBP,thumbBP,thumbBP,thumbBP,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0, // C0
+ thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
+ thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
+ thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,thumbC0,
+ thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8, // C8
+ thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
+ thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
+ thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,thumbC8,
+ thumbD0,thumbD0,thumbD0,thumbD0,thumbD1,thumbD1,thumbD1,thumbD1, // D0
+ thumbD2,thumbD2,thumbD2,thumbD2,thumbD3,thumbD3,thumbD3,thumbD3,
+ thumbD4,thumbD4,thumbD4,thumbD4,thumbD5,thumbD5,thumbD5,thumbD5,
+ thumbD6,thumbD6,thumbD6,thumbD6,thumbD7,thumbD7,thumbD7,thumbD7,
+ thumbD8,thumbD8,thumbD8,thumbD8,thumbD9,thumbD9,thumbD9,thumbD9, // D8
+ thumbDA,thumbDA,thumbDA,thumbDA,thumbDB,thumbDB,thumbDB,thumbDB,
+ thumbDC,thumbDC,thumbDC,thumbDC,thumbDD,thumbDD,thumbDD,thumbDD,
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbDF,thumbDF,thumbDF,thumbDF,
+ thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0, // E0
+ thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
+ thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
+ thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,thumbE0,
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI, // E8
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,thumbUI,
+ thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0, // F0
+ thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,thumbF0,
+ thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,
+ thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,thumbF4,
+ thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8, // F8
+ thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
+ thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
+ thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,thumbF8,
};
// Wrapper routine (execution loop) ///////////////////////////////////////
int thumbExecute()
{
- do {
- /*if( cheatsEnabled ) {
- cpuMasterCodeCheck();
- }*/
-
- //if ((armNextPC & 0x0803FFFF) == 0x08020000)
- // busPrefetchCount=0x100;
-
- uint32_t opcode = cpuPrefetch[0];
- cpuPrefetch[0] = cpuPrefetch[1];
-
- busPrefetch = false;
- if (busPrefetchCount & 0xFFFFFF00)
- busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF);
- clockTicks = 0;
- uint32_t oldArmNextPC = armNextPC;
-#ifndef FINAL_VERSION
- if(armNextPC == stop) {
- armNextPC++;
- }
-#endif
-
- armNextPC = reg[15].I;
- reg[15].I += 2;
- THUMB_PREFETCH_NEXT;
-
- (*thumbInsnTable[opcode>>6])(opcode);
-
- if (clockTicks < 0)
- return 0;
- if (clockTicks==0)
- clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1;
- cpuTotalTicks += clockTicks;
-
- } while (cpuTotalTicks < cpuNextEvent && !armState && !holdState && !SWITicks);
- return 1;
-}
-
+ do
+ {
+ uint32_t opcode = cpuPrefetch[0];
+ cpuPrefetch[0] = cpuPrefetch[1];
+
+ busPrefetch = false;
+ if (busPrefetchCount & 0xFFFFFF00)
+ busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF);
+ clockTicks = 0;
+ uint32_t oldArmNextPC = armNextPC;
+
+ armNextPC = reg[15].I;
+ reg[15].I += 2;
+ THUMB_PREFETCH_NEXT();
+
+ (*thumbInsnTable[opcode >> 6])(opcode);
+
+ if (clockTicks < 0)
+ return 0;
+ if (!clockTicks)
+ clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1;
+ cpuTotalTicks += clockTicks;
+ } while (cpuTotalTicks < cpuNextEvent && !armState && !holdState && !SWITicks);
+ return 1;
+}
+
--- a/src/in_gsf/vbam/gba/GBA.cpp
+++ b/src/in_gsf/vbam/gba/GBA.cpp
@@ -1,84 +1,43 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <stdarg.h>
-#include <string.h>
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
#include "GBA.h"
#include "GBAcpu.h"
#include "GBAinline.h"
#include "Globals.h"
-//#include "GBAGfx.h"
-//#include "EEprom.h"
-//#include "Flash.h"
#include "Sound.h"
-//#include "Sram.h"
#include "bios.h"
-//#include "Cheats.h"
-//#include "../NLS.h"
-//#include "elf.h"
-//#include "../Util.h"
#include "../common/Port.h"
-//#include "../System.h"
-//#include "agbprint.h"
-//#include "GBALink.h"
-
-extern int mapgsf(uint8_t* a, int l, int &s);
-
-#ifdef PROFILING
-#include "prof/prof.h"
-#endif
+
+extern int mapgsf(uint8_t *a, int l, int &s);
#ifdef __GNUC__
#define _stricmp strcasecmp
#endif
-extern int emulating;
-
int SWITicks = 0;
-int IRQTicks = 0;
-
-uint32_t mastercode = 0;
-int layerEnableDelay = 0;
+static int IRQTicks = 0;
+
+static int layerEnableDelay = 0;
bool busPrefetch = false;
bool busPrefetchEnable = false;
uint32_t busPrefetchCount = 0;
-int cpuDmaTicksToUpdate = 0;
-int cpuDmaCount = 0;
-uint32_t cpuDmaLast = 0;
-int dummyAddress = 0;
-
-bool cpuBreakLoop = false;
+static int cpuDmaTicksToUpdate = 0;
+static uint32_t cpuDmaLast = 0;
+static int dummyAddress = 0;
+
int cpuNextEvent = 0;
-int gbaSaveType = 0; // used to remember the save type on reset
-bool intState = false;
+static bool intState = false;
bool stopState = false;
bool holdState = false;
int holdType = 0;
-bool cpuSramEnabled = true;
-bool cpuFlashEnabled = true;
-bool cpuEEPROMEnabled = true;
-bool cpuEEPROMSensorEnabled = false;
uint32_t cpuPrefetch[2];
int cpuTotalTicks = 0;
-#ifdef PROFILING
-int profilingTicks = 0;
-int profilingTicksReload = 0;
-static profile_segment *profilSegment = NULL;
-#endif
-
-#ifdef BKPT_SUPPORT
-uint8_t freezeWorkRAM[0x40000];
-uint8_t freezeInternalRAM[0x8000];
-uint8_t freezeVRAM[0x18000];
-uint8_t freezePRAM[0x400];
-uint8_t freezeOAM[0x400];
-bool debugger_last;
-#endif
-
-int lcdTicks = (useBios && !skipBios) ? 1008 : 208;
+
+int lcdTicks = 208;
uint8_t timerOnOffDelay = 0;
uint16_t timer0Value = 0;
bool timer0On = false;
@@ -108,52 +67,22 @@
uint32_t dma2Dest = 0;
uint32_t dma3Source = 0;
uint32_t dma3Dest = 0;
-//void (*cpuSaveGameFunc)(u32,u8) = /*flashSaveDecide*/0;
-//void (*renderLine)() = /*mode0RenderLine*/0;
-bool fxOn = false;
-bool windowOn = false;
-int frameCount = 0;
char buffer[1024];
-uint32_t lastTime = 0;
int count = 0;
-int capture = 0;
-int capturePrevious = 0;
-int captureNumber = 0;
-
-const int TIMER_TICKS[4] = {
- 0,
- 6,
- 8,
- 10
-};
-
-const uint32_t objTilesAddress [3] = {0x010000, 0x014000, 0x014000};
-const uint8_t gamepakRamWaitState[4] = { 4, 3, 2, 8 };
-const uint8_t gamepakWaitState[4] = { 4, 3, 2, 8 };
-const uint8_t gamepakWaitState0[2] = { 2, 1 };
-const uint8_t gamepakWaitState1[2] = { 4, 1 };
-const uint8_t gamepakWaitState2[2] = { 8, 1 };
-const bool isInRom [16]=
- { false, false, false, false, false, false, false, false,
- true, true, true, true, true, true, false, false };
-
-uint8_t memoryWait[16] =
- { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 };
-uint8_t memoryWait32[16] =
- { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 };
-uint8_t memoryWaitSeq[16] =
- { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 };
-uint8_t memoryWaitSeq32[16] =
- { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 };
-
-// The videoMemoryWait constants are used to add some waitstates
-// if the opcode access video memory data outside of vblank/hblank
-// It seems to happen on only one ticks for each pixel.
-// Not used for now (too problematic with current code).
-//const u8 videoMemoryWait[16] =
-// {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
+static const int TIMER_TICKS[] = { 0, 6, 8, 10 };
+
+const uint32_t objTilesAddress[] = { 0x010000, 0x014000, 0x014000 };
+static const uint8_t gamepakRamWaitState[] = { 4, 3, 2, 8 };
+static const uint8_t gamepakWaitState[] = { 4, 3, 2, 8 };
+static const uint8_t gamepakWaitState0[] = { 2, 1 };
+static const uint8_t gamepakWaitState1[] = { 4, 1 };
+static const uint8_t gamepakWaitState2[] = { 8, 1 };
+
+uint8_t memoryWait[] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 };
+uint8_t memoryWait32[] = { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 };
+uint8_t memoryWaitSeq[] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 };
+uint8_t memoryWaitSeq32[] = { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 };
uint8_t biosProtected[4];
@@ -161,3858 +90,2055 @@
bool cpuBiosSwapped = false;
#endif
-uint32_t myROM[] = {
-0xEA000006,
-0xEA000093,
-0xEA000006,
-0x00000000,
-0x00000000,
-0x00000000,
-0xEA000088,
-0x00000000,
-0xE3A00302,
-0xE1A0F000,
-0xE92D5800,
-0xE55EC002,
-0xE28FB03C,
-0xE79BC10C,
-0xE14FB000,
-0xE92D0800,
-0xE20BB080,
-0xE38BB01F,
-0xE129F00B,
-0xE92D4004,
-0xE1A0E00F,
-0xE12FFF1C,
-0xE8BD4004,
-0xE3A0C0D3,
-0xE129F00C,
-0xE8BD0800,
-0xE169F00B,
-0xE8BD5800,
-0xE1B0F00E,
-0x0000009C,
-0x0000009C,
-0x0000009C,
-0x0000009C,
-0x000001F8,
-0x000001F0,
-0x000000AC,
-0x000000A0,
-0x000000FC,
-0x00000168,
-0xE12FFF1E,
-0xE1A03000,
-0xE1A00001,
-0xE1A01003,
-0xE2113102,
-0x42611000,
-0xE033C040,
-0x22600000,
-0xE1B02001,
-0xE15200A0,
-0x91A02082,
-0x3AFFFFFC,
-0xE1500002,
-0xE0A33003,
-0x20400002,
-0xE1320001,
-0x11A020A2,
-0x1AFFFFF9,
-0xE1A01000,
-0xE1A00003,
-0xE1B0C08C,
-0x22600000,
-0x42611000,
-0xE12FFF1E,
-0xE92D0010,
-0xE1A0C000,
-0xE3A01001,
-0xE1500001,
-0x81A000A0,
-0x81A01081,
-0x8AFFFFFB,
-0xE1A0000C,
-0xE1A04001,
-0xE3A03000,
-0xE1A02001,
-0xE15200A0,
-0x91A02082,
-0x3AFFFFFC,
-0xE1500002,
-0xE0A33003,
-0x20400002,
-0xE1320001,
-0x11A020A2,
-0x1AFFFFF9,
-0xE0811003,
-0xE1B010A1,
-0xE1510004,
-0x3AFFFFEE,
-0xE1A00004,
-0xE8BD0010,
-0xE12FFF1E,
-0xE0010090,
-0xE1A01741,
-0xE2611000,
-0xE3A030A9,
-0xE0030391,
-0xE1A03743,
-0xE2833E39,
-0xE0030391,
-0xE1A03743,
-0xE2833C09,
-0xE283301C,
-0xE0030391,
-0xE1A03743,
-0xE2833C0F,
-0xE28330B6,
-0xE0030391,
-0xE1A03743,
-0xE2833C16,
-0xE28330AA,
-0xE0030391,
-0xE1A03743,
-0xE2833A02,
-0xE2833081,
-0xE0030391,
-0xE1A03743,
-0xE2833C36,
-0xE2833051,
-0xE0030391,
-0xE1A03743,
-0xE2833CA2,
-0xE28330F9,
-0xE0000093,
-0xE1A00840,
-0xE12FFF1E,
-0xE3A00001,
-0xE3A01001,
-0xE92D4010,
-0xE3A03000,
-0xE3A04001,
-0xE3500000,
-0x1B000004,
-0xE5CC3301,
-0xEB000002,
-0x0AFFFFFC,
-0xE8BD4010,
-0xE12FFF1E,
-0xE3A0C301,
-0xE5CC3208,
-0xE15C20B8,
-0xE0110002,
-0x10222000,
-0x114C20B8,
-0xE5CC4208,
-0xE12FFF1E,
-0xE92D500F,
-0xE3A00301,
-0xE1A0E00F,
-0xE510F004,
-0xE8BD500F,
-0xE25EF004,
-0xE59FD044,
-0xE92D5000,
-0xE14FC000,
-0xE10FE000,
-0xE92D5000,
-0xE3A0C302,
-0xE5DCE09C,
-0xE35E00A5,
-0x1A000004,
-0x05DCE0B4,
-0x021EE080,
-0xE28FE004,
-0x159FF018,
-0x059FF018,
-0xE59FD018,
-0xE8BD5000,
-0xE169F00C,
-0xE8BD5000,
-0xE25EF004,
-0x03007FF0,
-0x09FE2000,
-0x09FFC000,
-0x03007FE0
+uint32_t myROM[] =
+{
+ 0xEA000006,
+ 0xEA000093,
+ 0xEA000006,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xEA000088,
+ 0x00000000,
+ 0xE3A00302,
+ 0xE1A0F000,
+ 0xE92D5800,
+ 0xE55EC002,
+ 0xE28FB03C,
+ 0xE79BC10C,
+ 0xE14FB000,
+ 0xE92D0800,
+ 0xE20BB080,
+ 0xE38BB01F,
+ 0xE129F00B,
+ 0xE92D4004,
+ 0xE1A0E00F,
+ 0xE12FFF1C,
+ 0xE8BD4004,
+ 0xE3A0C0D3,
+ 0xE129F00C,
+ 0xE8BD0800,
+ 0xE169F00B,
+ 0xE8BD5800,
+ 0xE1B0F00E,
+ 0x0000009C,
+ 0x0000009C,
+ 0x0000009C,
+ 0x0000009C,
+ 0x000001F8,
+ 0x000001F0,
+ 0x000000AC,
+ 0x000000A0,
+ 0x000000FC,
+ 0x00000168,
+ 0xE12FFF1E,
+ 0xE1A03000,
+ 0xE1A00001,
+ 0xE1A01003,
+ 0xE2113102,
+ 0x42611000,
+ 0xE033C040,
+ 0x22600000,
+ 0xE1B02001,
+ 0xE15200A0,
+ 0x91A02082,
+ 0x3AFFFFFC,
+ 0xE1500002,
+ 0xE0A33003,
+ 0x20400002,
+ 0xE1320001,
+ 0x11A020A2,
+ 0x1AFFFFF9,
+ 0xE1A01000,
+ 0xE1A00003,
+ 0xE1B0C08C,
+ 0x22600000,
+ 0x42611000,
+ 0xE12FFF1E,
+ 0xE92D0010,
+ 0xE1A0C000,
+ 0xE3A01001,
+ 0xE1500001,
+ 0x81A000A0,
+ 0x81A01081,
+ 0x8AFFFFFB,
+ 0xE1A0000C,
+ 0xE1A04001,
+ 0xE3A03000,
+ 0xE1A02001,
+ 0xE15200A0,
+ 0x91A02082,
+ 0x3AFFFFFC,
+ 0xE1500002,
+ 0xE0A33003,
+ 0x20400002,
+ 0xE1320001,
+ 0x11A020A2,
+ 0x1AFFFFF9,
+ 0xE0811003,
+ 0xE1B010A1,
+ 0xE1510004,
+ 0x3AFFFFEE,
+ 0xE1A00004,
+ 0xE8BD0010,
+ 0xE12FFF1E,
+ 0xE0010090,
+ 0xE1A01741,
+ 0xE2611000,
+ 0xE3A030A9,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833E39,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833C09,
+ 0xE283301C,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833C0F,
+ 0xE28330B6,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833C16,
+ 0xE28330AA,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833A02,
+ 0xE2833081,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833C36,
+ 0xE2833051,
+ 0xE0030391,
+ 0xE1A03743,
+ 0xE2833CA2,
+ 0xE28330F9,
+ 0xE0000093,
+ 0xE1A00840,
+ 0xE12FFF1E,
+ 0xE3A00001,
+ 0xE3A01001,
+ 0xE92D4010,
+ 0xE3A03000,
+ 0xE3A04001,
+ 0xE3500000,
+ 0x1B000004,
+ 0xE5CC3301,
+ 0xEB000002,
+ 0x0AFFFFFC,
+ 0xE8BD4010,
+ 0xE12FFF1E,
+ 0xE3A0C301,
+ 0xE5CC3208,
+ 0xE15C20B8,
+ 0xE0110002,
+ 0x10222000,
+ 0x114C20B8,
+ 0xE5CC4208,
+ 0xE12FFF1E,
+ 0xE92D500F,
+ 0xE3A00301,
+ 0xE1A0E00F,
+ 0xE510F004,
+ 0xE8BD500F,
+ 0xE25EF004,
+ 0xE59FD044,
+ 0xE92D5000,
+ 0xE14FC000,
+ 0xE10FE000,
+ 0xE92D5000,
+ 0xE3A0C302,
+ 0xE5DCE09C,
+ 0xE35E00A5,
+ 0x1A000004,
+ 0x05DCE0B4,
+ 0x021EE080,
+ 0xE28FE004,
+ 0x159FF018,
+ 0x059FF018,
+ 0xE59FD018,
+ 0xE8BD5000,
+ 0xE169F00C,
+ 0xE8BD5000,
+ 0xE25EF004,
+ 0x03007FF0,
+ 0x09FE2000,
+ 0x09FFC000,
+ 0x03007FE0
};
-/*variable_desc saveGameStruct[] = {
- { &DISPCNT , sizeof(u16) },
- { &DISPSTAT , sizeof(u16) },
- { &VCOUNT , sizeof(u16) },
- { &BG0CNT , sizeof(u16) },
- { &BG1CNT , sizeof(u16) },
- { &BG2CNT , sizeof(u16) },
- { &BG3CNT , sizeof(u16) },
- { &BG0HOFS , sizeof(u16) },
- { &BG0VOFS , sizeof(u16) },
- { &BG1HOFS , sizeof(u16) },
- { &BG1VOFS , sizeof(u16) },
- { &BG2HOFS , sizeof(u16) },
- { &BG2VOFS , sizeof(u16) },
- { &BG3HOFS , sizeof(u16) },
- { &BG3VOFS , sizeof(u16) },
- { &BG2PA , sizeof(u16) },
- { &BG2PB , sizeof(u16) },
- { &BG2PC , sizeof(u16) },
- { &BG2PD , sizeof(u16) },
- { &BG2X_L , sizeof(u16) },
- { &BG2X_H , sizeof(u16) },
- { &BG2Y_L , sizeof(u16) },
- { &BG2Y_H , sizeof(u16) },
- { &BG3PA , sizeof(u16) },
- { &BG3PB , sizeof(u16) },
- { &BG3PC , sizeof(u16) },
- { &BG3PD , sizeof(u16) },
- { &BG3X_L , sizeof(u16) },
- { &BG3X_H , sizeof(u16) },
- { &BG3Y_L , sizeof(u16) },
- { &BG3Y_H , sizeof(u16) },
- { &WIN0H , sizeof(u16) },
- { &WIN1H , sizeof(u16) },
- { &WIN0V , sizeof(u16) },
- { &WIN1V , sizeof(u16) },
- { &WININ , sizeof(u16) },
- { &WINOUT , sizeof(u16) },
- { &MOSAIC , sizeof(u16) },
- { &BLDMOD , sizeof(u16) },
- { &COLEV , sizeof(u16) },
- { &COLY , sizeof(u16) },
- { &DM0SAD_L , sizeof(u16) },
- { &DM0SAD_H , sizeof(u16) },
- { &DM0DAD_L , sizeof(u16) },
- { &DM0DAD_H , sizeof(u16) },
- { &DM0CNT_L , sizeof(u16) },
- { &DM0CNT_H , sizeof(u16) },
- { &DM1SAD_L , sizeof(u16) },
- { &DM1SAD_H , sizeof(u16) },
- { &DM1DAD_L , sizeof(u16) },
- { &DM1DAD_H , sizeof(u16) },
- { &DM1CNT_L , sizeof(u16) },
- { &DM1CNT_H , sizeof(u16) },
- { &DM2SAD_L , sizeof(u16) },
- { &DM2SAD_H , sizeof(u16) },
- { &DM2DAD_L , sizeof(u16) },
- { &DM2DAD_H , sizeof(u16) },
- { &DM2CNT_L , sizeof(u16) },
- { &DM2CNT_H , sizeof(u16) },
- { &DM3SAD_L , sizeof(u16) },
- { &DM3SAD_H , sizeof(u16) },
- { &DM3DAD_L , sizeof(u16) },
- { &DM3DAD_H , sizeof(u16) },
- { &DM3CNT_L , sizeof(u16) },
- { &DM3CNT_H , sizeof(u16) },
- { &TM0D , sizeof(u16) },
- { &TM0CNT , sizeof(u16) },
- { &TM1D , sizeof(u16) },
- { &TM1CNT , sizeof(u16) },
- { &TM2D , sizeof(u16) },
- { &TM2CNT , sizeof(u16) },
- { &TM3D , sizeof(u16) },
- { &TM3CNT , sizeof(u16) },
- { &P1 , sizeof(u16) },
- { &IE , sizeof(u16) },
- { &IF , sizeof(u16) },
- { &IME , sizeof(u16) },
- { &holdState, sizeof(bool) },
- { &holdType, sizeof(int) },
- { &lcdTicks, sizeof(int) },
- { &timer0On , sizeof(bool) },
- { &timer0Ticks , sizeof(int) },
- { &timer0Reload , sizeof(int) },
- { &timer0ClockReload , sizeof(int) },
- { &timer1On , sizeof(bool) },
- { &timer1Ticks , sizeof(int) },
- { &timer1Reload , sizeof(int) },
- { &timer1ClockReload , sizeof(int) },
- { &timer2On , sizeof(bool) },
- { &timer2Ticks , sizeof(int) },
- { &timer2Reload , sizeof(int) },
- { &timer2ClockReload , sizeof(int) },
- { &timer3On , sizeof(bool) },
- { &timer3Ticks , sizeof(int) },
- { &timer3Reload , sizeof(int) },
- { &timer3ClockReload , sizeof(int) },
- { &dma0Source , sizeof(u32) },
- { &dma0Dest , sizeof(u32) },
- { &dma1Source , sizeof(u32) },
- { &dma1Dest , sizeof(u32) },
- { &dma2Source , sizeof(u32) },
- { &dma2Dest , sizeof(u32) },
- { &dma3Source , sizeof(u32) },
- { &dma3Dest , sizeof(u32) },
- { &fxOn, sizeof(bool) },
- { &windowOn, sizeof(bool) },
- { &N_FLAG , sizeof(bool) },
- { &C_FLAG , sizeof(bool) },
- { &Z_FLAG , sizeof(bool) },
- { &V_FLAG , sizeof(bool) },
- { &armState , sizeof(bool) },
- { &armIrqEnable , sizeof(bool) },
- { &armNextPC , sizeof(u32) },
- { &armMode , sizeof(int) },
- { &saveType , sizeof(int) },
- { NULL, 0 }
-};*/
-
static int romSize = 0x2000000;
-#ifdef PROFILING
-void cpuProfil(profile_segment *seg)
+static inline int CPUUpdateTicks()
{
- profilSegment = seg;
+ int cpuLoopTicks = lcdTicks;
+
+ if (soundTicks < cpuLoopTicks)
+ cpuLoopTicks = soundTicks;
+
+ if (timer0On && timer0Ticks < cpuLoopTicks)
+ cpuLoopTicks = timer0Ticks;
+ if (timer1On && !(TM1CNT & 4) && timer1Ticks < cpuLoopTicks)
+ cpuLoopTicks = timer1Ticks;
+ if (timer2On && !(TM2CNT & 4) && timer2Ticks < cpuLoopTicks)
+ cpuLoopTicks = timer2Ticks;
+ if (timer3On && !(TM3CNT & 4) && timer3Ticks < cpuLoopTicks)
+ cpuLoopTicks = timer3Ticks;
+
+ if (SWITicks && SWITicks < cpuLoopTicks)
+ cpuLoopTicks = SWITicks;
+
+ if (IRQTicks && IRQTicks < cpuLoopTicks)
+ cpuLoopTicks = IRQTicks;
+
+ return cpuLoopTicks;
}
-void cpuEnableProfiling(int hz)
+int CPULoadRom()
{
- if(hz == 0)
- hz = 100;
- profilingTicks = profilingTicksReload = 16777216 / hz;
- profSetHertz(hz);
+ romSize = 0x2000000;
+
+ memset(&workRAM[0], 0, 0x40000);
+
+ if (cpuIsMultiBoot)
+ mapgsf(workRAM, 0x40000, romSize);
+ else
+ mapgsf(rom, 0x2000000, romSize);
+
+ uint16_t *temp = reinterpret_cast<uint16_t *>(rom + ((romSize + 1) & ~1));
+ int i;
+ for (i = (romSize + 1) & ~1; i < 0x2000000; i += 2)
+ {
+ WRITE16LE(temp, (i >> 1) & 0xFFFF);
+ ++temp;
+ }
+
+ memset(&bios[0], 0, 0x4000);
+ memset(&internalRAM[0], 0, 0x8000);
+ memset(&paletteRAM[0], 0, 0x400);
+ memset(&vram[0], 0, 0x20000);
+ memset(&oam[0], 0, 0x400);
+ memset(&ioMem[0], 0, 0x400);
+
+ return romSize;
}
-#endif
-
-
-inline int CPUUpdateTicks()
-{
- int cpuLoopTicks = lcdTicks;
-
- if(soundTicks < cpuLoopTicks)
- cpuLoopTicks = soundTicks;
-
- if(timer0On && (timer0Ticks < cpuLoopTicks)) {
- cpuLoopTicks = timer0Ticks;
- }
- if(timer1On && !(TM1CNT & 4) && (timer1Ticks < cpuLoopTicks)) {
- cpuLoopTicks = timer1Ticks;
- }
- if(timer2On && !(TM2CNT & 4) && (timer2Ticks < cpuLoopTicks)) {
- cpuLoopTicks = timer2Ticks;
- }
- if(timer3On && !(TM3CNT & 4) && (timer3Ticks < cpuLoopTicks)) {
- cpuLoopTicks = timer3Ticks;
- }
-#ifdef PROFILING
- if(profilingTicksReload != 0) {
- if(profilingTicks < cpuLoopTicks) {
- cpuLoopTicks = profilingTicks;
- }
- }
-#endif
-
- if (SWITicks) {
- if (SWITicks < cpuLoopTicks)
- cpuLoopTicks = SWITicks;
- }
-
- if (IRQTicks) {
- if (IRQTicks < cpuLoopTicks)
- cpuLoopTicks = IRQTicks;
- }
-
- return cpuLoopTicks;
-}
-
-/*void CPUUpdateWindow0()
-{
- int x00 = WIN0H>>8;
- int x01 = WIN0H & 255;
-
- if(x00 <= x01) {
- for(int i = 0; i < 240; i++) {
- gfxInWin0[i] = (i >= x00 && i < x01);
- }
- } else {
- for(int i = 0; i < 240; i++) {
- gfxInWin0[i] = (i >= x00 || i < x01);
- }
- }
-}*/
-
-/*void CPUUpdateWindow1()
-{
- int x00 = WIN1H>>8;
- int x01 = WIN1H & 255;
-
- if(x00 <= x01) {
- for(int i = 0; i < 240; i++) {
- gfxInWin1[i] = (i >= x00 && i < x01);
- }
- } else {
- for(int i = 0; i < 240; i++) {
- gfxInWin1[i] = (i >= x00 || i < x01);
- }
- }
-}*/
-
-/*extern uint32_t line0[240];
-extern uint32_t line1[240];
-extern uint32_t line2[240];
-extern uint32_t line3[240];
-
-#define CLEAR_ARRAY(a) \
- {\
- u32 *array = (a);\
- for(int i = 0; i < 240; i++) {\
- *array++ = 0x80000000;\
- }\
- }\*/
-
-/*void CPUUpdateRenderBuffers(bool force)
-{
- if(!(layerEnable & 0x0100) || force) {
- CLEAR_ARRAY(line0);
- }
- if(!(layerEnable & 0x0200) || force) {
- CLEAR_ARRAY(line1);
- }
- if(!(layerEnable & 0x0400) || force) {
- CLEAR_ARRAY(line2);
- }
- if(!(layerEnable & 0x0800) || force) {
- CLEAR_ARRAY(line3);
- }
-}*/
-
-/*static bool CPUWriteState(gzFile gzFile)
-{
- utilWriteInt(gzFile, SAVE_GAME_VERSION);
-
- utilGzWrite(gzFile, &rom[0xa0], 16);
-
- utilWriteInt(gzFile, useBios);
-
- utilGzWrite(gzFile, ®[0], sizeof(reg));
-
- utilWriteData(gzFile, saveGameStruct);
-
- // new to version 0.7.1
- utilWriteInt(gzFile, stopState);
- // new to version 0.8
- utilWriteInt(gzFile, IRQTicks);
-
- utilGzWrite(gzFile, internalRAM, 0x8000);
- utilGzWrite(gzFile, paletteRAM, 0x400);
- utilGzWrite(gzFile, workRAM, 0x40000);
- utilGzWrite(gzFile, vram, 0x20000);
- utilGzWrite(gzFile, oam, 0x400);
- utilGzWrite(gzFile, pix, 4*241*162);
- utilGzWrite(gzFile, ioMem, 0x400);
-
- eepromSaveGame(gzFile);
- flashSaveGame(gzFile);
- soundSaveGame(gzFile);
-
- cheatsSaveGame(gzFile);
-
- // version 1.5
- rtcSaveGame(gzFile);
-
- return true;
-}
-
-bool CPUWriteState(const char *file)
-{
- gzFile gzFile = utilGzOpen(file, "wb");
-
- if(gzFile == NULL) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), file);
- return false;
- }
-
- bool res = CPUWriteState(gzFile);
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-bool CPUWriteMemState(char *memory, int available)
-{
- gzFile gzFile = utilMemGzOpen(memory, available, "w");
-
- if(gzFile == NULL) {
- return false;
- }
-
- bool res = CPUWriteState(gzFile);
-
- long pos = utilGzMemTell(gzFile)+8;
-
- if(pos >= (available))
- res = false;
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-static bool CPUReadState(gzFile gzFile)
-{
- int version = utilReadInt(gzFile);
-
- if(version > SAVE_GAME_VERSION || version < SAVE_GAME_VERSION_1) {
- systemMessage(MSG_UNSUPPORTED_VBA_SGM,
- N_("Unsupported VisualBoyAdvance save game version %d"),
- version);
- return false;
- }
-
- u8 romname[17];
-
- utilGzRead(gzFile, romname, 16);
-
- if(memcmp(&rom[0xa0], romname, 16) != 0) {
- romname[16]=0;
- for(int i = 0; i < 16; i++)
- if(romname[i] < 32)
- romname[i] = 32;
- systemMessage(MSG_CANNOT_LOAD_SGM, N_("Cannot load save game for %s"), romname);
- return false;
- }
-
- bool ub = utilReadInt(gzFile) ? true : false;
-
- if(ub != useBios) {
- if(useBios)
- systemMessage(MSG_SAVE_GAME_NOT_USING_BIOS,
- N_("Save game is not using the BIOS files"));
- else
- systemMessage(MSG_SAVE_GAME_USING_BIOS,
- N_("Save game is using the BIOS file"));
- return false;
- }
-
- utilGzRead(gzFile, ®[0], sizeof(reg));
-
- utilReadData(gzFile, saveGameStruct);
-
- if(version < SAVE_GAME_VERSION_3)
- stopState = false;
- else
- stopState = utilReadInt(gzFile) ? true : false;
-
- if(version < SAVE_GAME_VERSION_4)
- {
- IRQTicks = 0;
- intState = false;
- }
- else
- {
- IRQTicks = utilReadInt(gzFile);
- if (IRQTicks>0)
- intState = true;
- else
- {
- intState = false;
- IRQTicks = 0;
- }
- }
-
- utilGzRead(gzFile, internalRAM, 0x8000);
- utilGzRead(gzFile, paletteRAM, 0x400);
- utilGzRead(gzFile, workRAM, 0x40000);
- utilGzRead(gzFile, vram, 0x20000);
- utilGzRead(gzFile, oam, 0x400);
- if(version < SAVE_GAME_VERSION_6)
- utilGzRead(gzFile, pix, 4*240*160);
- else
- utilGzRead(gzFile, pix, 4*241*162);
- utilGzRead(gzFile, ioMem, 0x400);
-
- if(skipSaveGameBattery) {
- // skip eeprom data
- eepromReadGameSkip(gzFile, version);
- // skip flash data
- flashReadGameSkip(gzFile, version);
- } else {
- eepromReadGame(gzFile, version);
- flashReadGame(gzFile, version);
- }
- soundReadGame(gzFile, version);
-
- if(version > SAVE_GAME_VERSION_1) {
- if(skipSaveGameCheats) {
- // skip cheats list data
- cheatsReadGameSkip(gzFile, version);
- } else {
- cheatsReadGame(gzFile, version);
- }
- }
- if(version > SAVE_GAME_VERSION_6) {
- rtcReadGame(gzFile);
- }
-
- if(version <= SAVE_GAME_VERSION_7) {
- u32 temp;
-#define SWAP(a,b,c) \
- temp = (a);\
- (a) = (b)<<16|(c);\
- (b) = (temp) >> 16;\
- (c) = (temp) & 0xFFFF;
-
- SWAP(dma0Source, DM0SAD_H, DM0SAD_L);
- SWAP(dma0Dest, DM0DAD_H, DM0DAD_L);
- SWAP(dma1Source, DM1SAD_H, DM1SAD_L);
- SWAP(dma1Dest, DM1DAD_H, DM1DAD_L);
- SWAP(dma2Source, DM2SAD_H, DM2SAD_L);
- SWAP(dma2Dest, DM2DAD_H, DM2DAD_L);
- SWAP(dma3Source, DM3SAD_H, DM3SAD_L);
- SWAP(dma3Dest, DM3DAD_H, DM3DAD_L);
- }
-
- if(version <= SAVE_GAME_VERSION_8) {
- timer0ClockReload = TIMER_TICKS[TM0CNT & 3];
- timer1ClockReload = TIMER_TICKS[TM1CNT & 3];
- timer2ClockReload = TIMER_TICKS[TM2CNT & 3];
- timer3ClockReload = TIMER_TICKS[TM3CNT & 3];
-
- timer0Ticks = ((0x10000 - TM0D) << timer0ClockReload) - timer0Ticks;
- timer1Ticks = ((0x10000 - TM1D) << timer1ClockReload) - timer1Ticks;
- timer2Ticks = ((0x10000 - TM2D) << timer2ClockReload) - timer2Ticks;
- timer3Ticks = ((0x10000 - TM3D) << timer3ClockReload) - timer3Ticks;
- interp_rate();
- }
-
- // set pointers!
- layerEnable = layerSettings & DISPCNT;
-
- CPUUpdateRender();
- //CPUUpdateRenderBuffers(true);
- //CPUUpdateWindow0();
- //CPUUpdateWindow1();
- gbaSaveType = 0;
- switch(saveType) {
- case 0:
- cpuSaveGameFunc = flashSaveDecide;
- break;
- case 1:
- cpuSaveGameFunc = sramWrite;
- gbaSaveType = 1;
- break;
- case 2:
- cpuSaveGameFunc = flashWrite;
- gbaSaveType = 2;
- break;
- case 3:
- break;
- case 5:
- gbaSaveType = 5;
- break;
- default:
- systemMessage(MSG_UNSUPPORTED_SAVE_TYPE,
- N_("Unsupported save type %d"), saveType);
- break;
- }
- if(eepromInUse)
- gbaSaveType = 3;
-
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
- if(armState) {
- ARM_PREFETCH;
- } else {
- THUMB_PREFETCH;
- }
-
- CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
-
- return true;
-}
-
-bool CPUReadMemState(char *memory, int available)
-{
- gzFile gzFile = utilMemGzOpen(memory, available, "r");
-
- bool res = CPUReadState(gzFile);
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-bool CPUReadState(const char * file)
-{
- gzFile gzFile = utilGzOpen(file, "rb");
-
- if(gzFile == NULL)
- return false;
-
- bool res = CPUReadState(gzFile);
-
- utilGzClose(gzFile);
-
- return res;
-}
-
-bool CPUExportEepromFile(const char *fileName)
-{
- if(eepromInUse) {
- FILE *file = fopen(fileName, "wb");
-
- if(!file) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"),
- fileName);
- return false;
- }
-
- for(int i = 0; i < eepromSize;) {
- for(int j = 0; j < 8; j++) {
- if(fwrite(&eepromData[i+7-j], 1, 1, file) != 1) {
- fclose(file);
- return false;
- }
- }
- i += 8;
- }
- fclose(file);
- }
- return true;
-}
-
-bool CPUWriteBatteryFile(const char *fileName)
-{
- if(gbaSaveType == 0) {
- if(eepromInUse)
- gbaSaveType = 3;
- else switch(saveType) {
- case 1:
- gbaSaveType = 1;
- break;
- case 2:
- gbaSaveType = 2;
- break;
- }
- }
-
- if((gbaSaveType) && (gbaSaveType!=5)) {
- FILE *file = fopen(fileName, "wb");
-
- if(!file) {
- systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"),
- fileName);
- return false;
- }
-
- // only save if Flash/Sram in use or EEprom in use
- if(gbaSaveType != 3) {
- if(gbaSaveType == 2) {
- if(fwrite(flashSaveMemory, 1, flashSize, file) != (size_t)flashSize) {
- fclose(file);
- return false;
- }
- } else {
- if(fwrite(flashSaveMemory, 1, 0x10000, file) != 0x10000) {
- fclose(file);
- return false;
- }
- }
- } else {
- if(fwrite(eepromData, 1, eepromSize, file) != (size_t)eepromSize) {
- fclose(file);
- return false;
- }
- }
- fclose(file);
- }
- return true;
-}
-
-bool CPUReadGSASnapshot(const char *fileName)
-{
- int i;
- FILE *file = fopen(fileName, "rb");
-
- if(!file) {
- systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
- return false;
- }
-
- // check file size to know what we should read
- fseek(file, 0, SEEK_END);
-
- // long size = ftell(file);
- fseek(file, 0x0, SEEK_SET);
- fread(&i, 1, 4, file);
- fseek(file, i, SEEK_CUR); // Skip SharkPortSave
-// fseek(file, 4, SEEK_CUR); // skip some sort of flag
- fread(&i, 1, 4, file); // name length
- fseek(file, i, SEEK_CUR); // skip name
- fread(&i, 1, 4, file); // desc length
- fseek(file, i, SEEK_CUR); // skip desc
- fread(&i, 1, 4, file); // notes length
- fseek(file, i, SEEK_CUR); // skip notes
- int saveSize;
- fread(&saveSize, 1, 4, file); // read length
- saveSize -= 0x1c; // remove header size
- char buffer[17];
- char buffer2[17];
- fread(buffer, 1, 16, file);
- buffer[16] = 0;
- for(i = 0; i < 16; i++)
- if(buffer[i] < 32)
- buffer[i] = 32;
- memcpy(buffer2, &rom[0xa0], 16);
- buffer2[16] = 0;
- for(i = 0; i < 16; i++)
- if(buffer2[i] < 32)
- buffer2[i] = 32;
- if(memcmp(buffer, buffer2, 16)) {
- systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR,
- N_("Cannot import snapshot for %s. Current game is %s"),
- buffer,
- buffer2);
- fclose(file);
- return false;
- }
- fseek(file, 12, SEEK_CUR); // skip some flags
- if(saveSize >= 65536) {
- if(fread(flashSaveMemory, 1, saveSize, file) != (size_t)saveSize) {
- fclose(file);
- return false;
- }
- } else {
- systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE,
- N_("Unsupported snapshot file %s"),
- fileName);
- fclose(file);
- return false;
- }
- fclose(file);
- CPUReset();
- return true;
-}
-
-bool CPUReadGSASPSnapshot(const char *fileName)
-{
- const char gsvfooter[] = "xV4\x12";
- const size_t namepos=0x0c, namesz=12;
- const size_t footerpos=0x42c, footersz=4;
-
- char footer[footersz+1], romname[namesz+1], savename[namesz+1];;
- FILE *file = fopen(fileName, "rb");
-
- if(!file) {
- systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
- return false;
- }
-
- // read save name
- fseek(file, namepos, SEEK_SET);
- fread(savename, 1, namesz, file);
- savename[namesz] = 0;
-
- memcpy(romname, &rom[0xa0], namesz);
- romname[namesz] = 0;
-
- if(memcmp(romname, savename, namesz)) {
- systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR,
- N_("Cannot import snapshot for %s. Current game is %s"),
- savename,
- romname);
- fclose(file);
- return false;
- }
-
- // read footer tag
- fseek(file, footerpos, SEEK_SET);
- fread(footer, 1, footersz, file);
- footer[footersz] = 0;
-
- if(memcmp(footer, gsvfooter, footersz)) {
- systemMessage(0,
- N_("Unsupported snapshot file %s. Footer '%s' at %u should be '%s'"),
- fileName,
- footer,
- footerpos,
- gsvfooter);
- fclose(file);
- return false;
- }
-
- // Read up to 128k save
- fread(flashSaveMemory, 1, FLASH_128K_SZ, file);
-
- fclose(file);
- CPUReset();
- return true;
-}
-
-
-bool CPUWriteGSASnapshot(const char *fileName,
- const char *title,
- const char *desc,
- const char *notes)
-{
- FILE *file = fopen(fileName, "wb");
-
- if(!file) {
- systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
- return false;
- }
-
- u8 buffer[17];
-
- utilPutDword(buffer, 0x0d); // SharkPortSave length
- fwrite(buffer, 1, 4, file);
- fwrite("SharkPortSave", 1, 0x0d, file);
- utilPutDword(buffer, 0x000f0000);
- fwrite(buffer, 1, 4, file); // save type 0x000f0000 = GBA save
- utilPutDword(buffer, (u32)strlen(title));
- fwrite(buffer, 1, 4, file); // title length
- fwrite(title, 1, strlen(title), file);
- utilPutDword(buffer, (u32)strlen(desc));
- fwrite(buffer, 1, 4, file); // desc length
- fwrite(desc, 1, strlen(desc), file);
- utilPutDword(buffer, (u32)strlen(notes));
- fwrite(buffer, 1, 4, file); // notes length
- fwrite(notes, 1, strlen(notes), file);
- int saveSize = 0x10000;
- if(gbaSaveType == 2)
- saveSize = flashSize;
- int totalSize = saveSize + 0x1c;
-
- utilPutDword(buffer, totalSize); // length of remainder of save - CRC
- fwrite(buffer, 1, 4, file);
-
- char *temp = new char[0x2001c];
- memset(temp, 0, 28);
- memcpy(temp, &rom[0xa0], 16); // copy internal name
- temp[0x10] = rom[0xbe]; // reserved area (old checksum)
- temp[0x11] = rom[0xbf]; // reserved area (old checksum)
- temp[0x12] = rom[0xbd]; // complement check
- temp[0x13] = rom[0xb0]; // maker
- temp[0x14] = 1; // 1 save ?
- memcpy(&temp[0x1c], flashSaveMemory, saveSize); // copy save
- fwrite(temp, 1, totalSize, file); // write save + header
- u32 crc = 0;
-
- for(int i = 0; i < totalSize; i++) {
- crc += ((u32)temp[i] << (crc % 0x18));
- }
-
- utilPutDword(buffer, crc);
- fwrite(buffer, 1, 4, file); // CRC?
-
- fclose(file);
- delete [] temp;
- return true;
-}
-
-bool CPUImportEepromFile(const char *fileName)
-{
- FILE *file = fopen(fileName, "rb");
-
- if(!file)
- return false;
-
- // check file size to know what we should read
- fseek(file, 0, SEEK_END);
-
- long size = ftell(file);
- fseek(file, 0, SEEK_SET);
- if(size == 512 || size == 0x2000) {
- if(fread(eepromData, 1, size, file) != (size_t)size) {
- fclose(file);
- return false;
- }
- for(int i = 0; i < size;) {
- u8 tmp = eepromData[i];
- eepromData[i] = eepromData[7-i];
- eepromData[7-i] = tmp;
- i++;
- tmp = eepromData[i];
- eepromData[i] = eepromData[7-i];
- eepromData[7-i] = tmp;
- i++;
- tmp = eepromData[i];
- eepromData[i] = eepromData[7-i];
- eepromData[7-i] = tmp;
- i++;
- tmp = eepromData[i];
- eepromData[i] = eepromData[7-i];
- eepromData[7-i] = tmp;
- i++;
- i += 4;
- }
- } else {
- fclose(file);
- return false;
- }
- fclose(file);
- return true;
-}
-
-bool CPUReadBatteryFile(const char *fileName)
-{
- FILE *file = fopen(fileName, "rb");
-
- if(!file)
- return false;
-
- // check file size to know what we should read
- fseek(file, 0, SEEK_END);
-
- long size = ftell(file);
- fseek(file, 0, SEEK_SET);
- systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- if(size == 512 || size == 0x2000) {
- if(fread(eepromData, 1, size, file) != (size_t)size) {
- fclose(file);
- return false;
- }
- } else {
- if(size == 0x20000) {
- if(fread(flashSaveMemory, 1, 0x20000, file) != 0x20000) {
- fclose(file);
- return false;
- }
- flashSetSize(0x20000);
- } else {
- if(fread(flashSaveMemory, 1, 0x10000, file) != 0x10000) {
- fclose(file);
- return false;
- }
- flashSetSize(0x10000);
- }
- }
- fclose(file);
- return true;
-}
-
-bool CPUWritePNGFile(const char *fileName)
-{
- return utilWritePNGFile(fileName, 240, 160, pix);
-}
-
-bool CPUWriteBMPFile(const char *fileName)
-{
- return utilWriteBMPFile(fileName, 240, 160, pix);
-}*/
-
-bool CPUIsZipFile(const char * file)
-{
- if(strlen(file) > 4) {
- const char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".zip") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-bool CPUIsGBAImage(const char * file)
-{
- cpuIsMultiBoot = false;
- if(strlen(file) > 4) {
- const char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".gba") == 0)
- return true;
- if(_stricmp(p, ".agb") == 0)
- return true;
- if(_stricmp(p, ".bin") == 0)
- return true;
- if(_stricmp(p, ".elf") == 0)
- return true;
- if(_stricmp(p, ".mb") == 0) {
- cpuIsMultiBoot = true;
- return true;
- }
- }
- }
-
- return false;
-}
-
-bool CPUIsGBABios(const char * file)
-{
- if(strlen(file) > 4) {
- const char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".gba") == 0)
- return true;
- if(_stricmp(p, ".agb") == 0)
- return true;
- if(_stricmp(p, ".bin") == 0)
- return true;
- if(_stricmp(p, ".bios") == 0)
- return true;
- if(_stricmp(p, ".rom") == 0)
- return true;
- }
- }
-
- return false;
-}
-
-bool CPUIsELF(const char *file)
-{
- if(file == NULL)
- return false;
-
- if(strlen(file) > 4) {
- const char * p = strrchr(file,'.');
-
- if(p != NULL) {
- if(_stricmp(p, ".elf") == 0)
- return true;
- }
- }
- return false;
-}
-
-void CPUCleanUp()
-{
-#ifdef PROFILING
- if(profilingTicksReload) {
- profCleanup();
- }
-#endif
-
- if(rom != NULL) {
- free(rom);
- rom = NULL;
- }
-
- if(vram != NULL) {
- free(vram);
- vram = NULL;
- }
-
- if(paletteRAM != NULL) {
- free(paletteRAM);
- paletteRAM = NULL;
- }
-
- if(internalRAM != NULL) {
- free(internalRAM);
- internalRAM = NULL;
- }
-
- if(workRAM != NULL) {
- free(workRAM);
- workRAM = NULL;
- }
-
- if(bios != NULL) {
- free(bios);
- bios = NULL;
- }
-
- if(pix != NULL) {
- free(pix);
- pix = NULL;
- }
-
- if(oam != NULL) {
- free(oam);
- oam = NULL;
- }
-
- if(ioMem != NULL) {
- free(ioMem);
- ioMem = NULL;
- }
-
-#ifndef NO_DEBUGGER
- elfCleanUp();
-#endif //NO_DEBUGGER
-
- //systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- //emulating = 0;
-}
-
-int CPULoadRom(const char *szFile)
-{
- romSize = 0x2000000;
- if(rom != NULL) {
- CPUCleanUp();
- }
-
- //systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- rom = (uint8_t *)malloc(0x2000000);
- if(rom == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "ROM");*/
- return 0;
- }
- workRAM = (uint8_t *)calloc(1, 0x40000);
- if(workRAM == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "WRAM");*/
- return 0;
- }
-
- //u8 *whereToLoad = cpuIsMultiBoot ? workRAM : rom;
-
-#ifndef NO_DEBUGGER
- if(CPUIsELF(szFile)) {
- FILE *f = fopen(szFile, "rb");
- if(!f) {
- systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"),
- szFile);
- free(rom);
- rom = NULL;
- free(workRAM);
- workRAM = NULL;
- return 0;
- }
- bool res = elfRead(szFile, romSize, f);
- if(!res || romSize == 0) {
- free(rom);
- rom = NULL;
- free(workRAM);
- workRAM = NULL;
- elfCleanUp();
- return 0;
- }
- } else
-#endif //NO_DEBUGGER
- /*if(szFile!=NULL)
- {
- if(!utilLoad(szFile,
- utilIsGBAImage,
- whereToLoad,
- romSize)) {
- free(rom);
- rom = NULL;
- free(workRAM);
- workRAM = NULL;
- return 0;
- }
- }*/
- if (cpuIsMultiBoot)
- mapgsf(workRAM,0x40000,romSize);
- else
- mapgsf(rom, 0x2000000,romSize);
-
- uint16_t *temp = (uint16_t *)(rom+((romSize+1)&~1));
- int i;
- for(i = (romSize+1)&~1; i < 0x2000000; i+=2) {
- WRITE16LE(temp, (i >> 1) & 0xFFFF);
- temp++;
- }
-
- bios = (uint8_t *)calloc(1,0x4000);
- if(bios == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "BIOS");*/
- CPUCleanUp();
- return 0;
- }
- internalRAM = (uint8_t *)calloc(1,0x8000);
- if(internalRAM == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "IRAM");*/
- CPUCleanUp();
- return 0;
- }
- paletteRAM = (uint8_t *)calloc(1,0x400);
- if(paletteRAM == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "PRAM");*/
- CPUCleanUp();
- return 0;
- }
- vram = (uint8_t *)calloc(1, 0x20000);
- if(vram == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "VRAM");*/
- CPUCleanUp();
- return 0;
- }
- oam = (uint8_t *)calloc(1, 0x400);
- if(oam == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "OAM");*/
- CPUCleanUp();
- return 0;
- }
- pix = (uint8_t *)calloc(1, 4 * 241 * 162);
- if(pix == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "PIX");*/
- CPUCleanUp();
- return 0;
- }
- ioMem = (uint8_t *)calloc(1, 0x400);
- if(ioMem == NULL) {
- /*systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
- "IO");*/
- CPUCleanUp();
- return 0;
- }
-
- //flashInit();
- //eepromInit();
-
- //CPUUpdateRenderBuffers(true);
-
- return romSize;
-}
-
-void doMirroring (bool b)
-{
- uint32_t mirroredRomSize = (((romSize)>>20) & 0x3F)<<20;
- uint32_t mirroredRomAddress = romSize;
- if ((mirroredRomSize <=0x800000) && (b))
- {
- mirroredRomAddress = mirroredRomSize;
- if (mirroredRomSize==0)
- mirroredRomSize=0x100000;
- while (mirroredRomAddress<0x01000000)
- {
- memcpy ((uint16_t *)(rom+mirroredRomAddress), (uint16_t *)(rom), mirroredRomSize);
- mirroredRomAddress+=mirroredRomSize;
- }
- }
-}
-
-/*void CPUUpdateRender()
-{
- switch(DISPCNT & 7) {
- case 0:
- if((!fxOn && !windowOn && !(layerEnable & 0x8000)) ||
- cpuDisableSfx)
- renderLine = mode0RenderLine;
- else if(fxOn && !windowOn && !(layerEnable & 0x8000))
- renderLine = mode0RenderLineNoWindow;
- else
- renderLine = mode0RenderLineAll;
- break;
- case 1:
- if((!fxOn && !windowOn && !(layerEnable & 0x8000)) ||
- cpuDisableSfx)
- renderLine = mode1RenderLine;
- else if(fxOn && !windowOn && !(layerEnable & 0x8000))
- renderLine = mode1RenderLineNoWindow;
- else
- renderLine = mode1RenderLineAll;
- break;
- case 2:
- if((!fxOn && !windowOn && !(layerEnable & 0x8000)) ||
- cpuDisableSfx)
- renderLine = mode2RenderLine;
- else if(fxOn && !windowOn && !(layerEnable & 0x8000))
- renderLine = mode2RenderLineNoWindow;
- else
- renderLine = mode2RenderLineAll;
- break;
- case 3:
- if((!fxOn && !windowOn && !(layerEnable & 0x8000)) ||
- cpuDisableSfx)
- renderLine = mode3RenderLine;
- else if(fxOn && !windowOn && !(layerEnable & 0x8000))
- renderLine = mode3RenderLineNoWindow;
- else
- renderLine = mode3RenderLineAll;
- break;
- case 4:
- if((!fxOn && !windowOn && !(layerEnable & 0x8000)) ||
- cpuDisableSfx)
- renderLine = mode4RenderLine;
- else if(fxOn && !windowOn && !(layerEnable & 0x8000))
- renderLine = mode4RenderLineNoWindow;
- else
- renderLine = mode4RenderLineAll;
- break;
- case 5:
- if((!fxOn && !windowOn && !(layerEnable & 0x8000)) ||
- cpuDisableSfx)
- renderLine = mode5RenderLine;
- else if(fxOn && !windowOn && !(layerEnable & 0x8000))
- renderLine = mode5RenderLineNoWindow;
- else
- renderLine = mode5RenderLineAll;
- default:
- break;
- }
-}*/
void CPUUpdateCPSR()
{
- uint32_t CPSR = reg[16].I & 0x40;
- if(N_FLAG)
- CPSR |= 0x80000000;
- if(Z_FLAG)
- CPSR |= 0x40000000;
- if(C_FLAG)
- CPSR |= 0x20000000;
- if(V_FLAG)
- CPSR |= 0x10000000;
- if(!armState)
- CPSR |= 0x00000020;
- if(!armIrqEnable)
- CPSR |= 0x80;
- CPSR |= (armMode & 0x1F);
- reg[16].I = CPSR;
+ uint32_t CPSR = reg[16].I & 0x40;
+ if (N_FLAG)
+ CPSR |= 0x80000000;
+ if (Z_FLAG)
+ CPSR |= 0x40000000;
+ if (C_FLAG)
+ CPSR |= 0x20000000;
+ if (V_FLAG)
+ CPSR |= 0x10000000;
+ if (!armState)
+ CPSR |= 0x00000020;
+ if (!armIrqEnable)
+ CPSR |= 0x80;
+ CPSR |= armMode & 0x1F;
+ reg[16].I = CPSR;
}
void CPUUpdateFlags(bool breakLoop)
{
- uint32_t CPSR = reg[16].I;
-
- N_FLAG = (CPSR & 0x80000000) ? true: false;
- Z_FLAG = (CPSR & 0x40000000) ? true: false;
- C_FLAG = (CPSR & 0x20000000) ? true: false;
- V_FLAG = (CPSR & 0x10000000) ? true: false;
- armState = (CPSR & 0x20) ? false : true;
- armIrqEnable = (CPSR & 0x80) ? false : true;
- if(breakLoop) {
- if (armIrqEnable && (IF & IE) && (IME & 1))
- cpuNextEvent = cpuTotalTicks;
- }
+ uint32_t CPSR = reg[16].I;
+
+ N_FLAG = !!(CPSR & 0x80000000);
+ Z_FLAG = !!(CPSR & 0x40000000);
+ C_FLAG = !!(CPSR & 0x20000000);
+ V_FLAG = !!(CPSR & 0x10000000);
+ armState = !(CPSR & 0x20);
+ armIrqEnable = !(CPSR & 0x80);
+ if (breakLoop && armIrqEnable && (IF & IE) && (IME & 1))
+ cpuNextEvent = cpuTotalTicks;
}
-
-void CPUUpdateFlags()
-{
- CPUUpdateFlags(true);
-}
-
-#ifdef WORDS_BIGENDIAN
-static void CPUSwap(volatile uint32_t *a, volatile uint32_t *b)
-{
- volatile uint32_t c = *b;
- *b = *a;
- *a = c;
-}
-#else
-static void CPUSwap(uint32_t *a, uint32_t *b)
-{
- uint32_t c = *b;
- *b = *a;
- *a = c;
-}
-#endif
void CPUSwitchMode(int mode, bool saveState, bool breakLoop)
{
- // if(armMode == mode)
- // return;
-
- CPUUpdateCPSR();
-
- switch(armMode) {
- case 0x10:
- case 0x1F:
- reg[R13_USR].I = reg[13].I;
- reg[R14_USR].I = reg[14].I;
- reg[17].I = reg[16].I;
- break;
- case 0x11:
- CPUSwap(®[R8_FIQ].I, ®[8].I);
- CPUSwap(®[R9_FIQ].I, ®[9].I);
- CPUSwap(®[R10_FIQ].I, ®[10].I);
- CPUSwap(®[R11_FIQ].I, ®[11].I);
- CPUSwap(®[R12_FIQ].I, ®[12].I);
- reg[R13_FIQ].I = reg[13].I;
- reg[R14_FIQ].I = reg[14].I;
- reg[SPSR_FIQ].I = reg[17].I;
- break;
- case 0x12:
- reg[R13_IRQ].I = reg[13].I;
- reg[R14_IRQ].I = reg[14].I;
- reg[SPSR_IRQ].I = reg[17].I;
- break;
- case 0x13:
- reg[R13_SVC].I = reg[13].I;
- reg[R14_SVC].I = reg[14].I;
- reg[SPSR_SVC].I = reg[17].I;
- break;
- case 0x17:
- reg[R13_ABT].I = reg[13].I;
- reg[R14_ABT].I = reg[14].I;
- reg[SPSR_ABT].I = reg[17].I;
- break;
- case 0x1b:
- reg[R13_UND].I = reg[13].I;
- reg[R14_UND].I = reg[14].I;
- reg[SPSR_UND].I = reg[17].I;
- break;
- }
-
- uint32_t CPSR = reg[16].I;
- uint32_t SPSR = reg[17].I;
-
- switch(mode) {
- case 0x10:
- case 0x1F:
- reg[13].I = reg[R13_USR].I;
- reg[14].I = reg[R14_USR].I;
- reg[16].I = SPSR;
- break;
- case 0x11:
- CPUSwap(®[8].I, ®[R8_FIQ].I);
- CPUSwap(®[9].I, ®[R9_FIQ].I);
- CPUSwap(®[10].I, ®[R10_FIQ].I);
- CPUSwap(®[11].I, ®[R11_FIQ].I);
- CPUSwap(®[12].I, ®[R12_FIQ].I);
- reg[13].I = reg[R13_FIQ].I;
- reg[14].I = reg[R14_FIQ].I;
- if(saveState)
- reg[17].I = CPSR;
- else
- reg[17].I = reg[SPSR_FIQ].I;
- break;
- case 0x12:
- reg[13].I = reg[R13_IRQ].I;
- reg[14].I = reg[R14_IRQ].I;
- reg[16].I = SPSR;
- if(saveState)
- reg[17].I = CPSR;
- else
- reg[17].I = reg[SPSR_IRQ].I;
- break;
- case 0x13:
- reg[13].I = reg[R13_SVC].I;
- reg[14].I = reg[R14_SVC].I;
- reg[16].I = SPSR;
- if(saveState)
- reg[17].I = CPSR;
- else
- reg[17].I = reg[SPSR_SVC].I;
- break;
- case 0x17:
- reg[13].I = reg[R13_ABT].I;
- reg[14].I = reg[R14_ABT].I;
- reg[16].I = SPSR;
- if(saveState)
- reg[17].I = CPSR;
- else
- reg[17].I = reg[SPSR_ABT].I;
- break;
- case 0x1b:
- reg[13].I = reg[R13_UND].I;
- reg[14].I = reg[R14_UND].I;
- reg[16].I = SPSR;
- if(saveState)
- reg[17].I = CPSR;
- else
- reg[17].I = reg[SPSR_UND].I;
- break;
- default:
- //systemMessage(MSG_UNSUPPORTED_ARM_MODE, N_("Unsupported ARM mode %02x"), mode);
- break;
- }
- armMode = mode;
- CPUUpdateFlags(breakLoop);
- CPUUpdateCPSR();
-}
-
-void CPUSwitchMode(int mode, bool saveState)
-{
- CPUSwitchMode(mode, saveState, true);
+ CPUUpdateCPSR();
+
+ switch (armMode)
+ {
+ case 0x10:
+ case 0x1F:
+ reg[R13_USR].I = reg[13].I;
+ reg[R14_USR].I = reg[14].I;
+ reg[17].I = reg[16].I;
+ break;
+ case 0x11:
+ std::swap(reg[R8_FIQ].I, reg[8].I);
+ std::swap(reg[R9_FIQ].I, reg[9].I);
+ std::swap(reg[R10_FIQ].I, reg[10].I);
+ std::swap(reg[R11_FIQ].I, reg[11].I);
+ std::swap(reg[R12_FIQ].I, reg[12].I);
+ reg[R13_FIQ].I = reg[13].I;
+ reg[R14_FIQ].I = reg[14].I;
+ reg[SPSR_FIQ].I = reg[17].I;
+ break;
+ case 0x12:
+ reg[R13_IRQ].I = reg[13].I;
+ reg[R14_IRQ].I = reg[14].I;
+ reg[SPSR_IRQ].I = reg[17].I;
+ break;
+ case 0x13:
+ reg[R13_SVC].I = reg[13].I;
+ reg[R14_SVC].I = reg[14].I;
+ reg[SPSR_SVC].I = reg[17].I;
+ break;
+ case 0x17:
+ reg[R13_ABT].I = reg[13].I;
+ reg[R14_ABT].I = reg[14].I;
+ reg[SPSR_ABT].I = reg[17].I;
+ break;
+ case 0x1b:
+ reg[R13_UND].I = reg[13].I;
+ reg[R14_UND].I = reg[14].I;
+ reg[SPSR_UND].I = reg[17].I;
+ }
+
+ uint32_t CPSR = reg[16].I;
+ uint32_t SPSR = reg[17].I;
+
+ switch (mode)
+ {
+ case 0x10:
+ case 0x1F:
+ reg[13].I = reg[R13_USR].I;
+ reg[14].I = reg[R14_USR].I;
+ reg[16].I = SPSR;
+ break;
+ case 0x11:
+ std::swap(reg[8].I, reg[R8_FIQ].I);
+ std::swap(reg[9].I, reg[R9_FIQ].I);
+ std::swap(reg[10].I, reg[R10_FIQ].I);
+ std::swap(reg[11].I, reg[R11_FIQ].I);
+ std::swap(reg[12].I, reg[R12_FIQ].I);
+ reg[13].I = reg[R13_FIQ].I;
+ reg[14].I = reg[R14_FIQ].I;
+ if (saveState)
+ reg[17].I = CPSR;
+ else
+ reg[17].I = reg[SPSR_FIQ].I;
+ break;
+ case 0x12:
+ reg[13].I = reg[R13_IRQ].I;
+ reg[14].I = reg[R14_IRQ].I;
+ reg[16].I = SPSR;
+ if (saveState)
+ reg[17].I = CPSR;
+ else
+ reg[17].I = reg[SPSR_IRQ].I;
+ break;
+ case 0x13:
+ reg[13].I = reg[R13_SVC].I;
+ reg[14].I = reg[R14_SVC].I;
+ reg[16].I = SPSR;
+ if (saveState)
+ reg[17].I = CPSR;
+ else
+ reg[17].I = reg[SPSR_SVC].I;
+ break;
+ case 0x17:
+ reg[13].I = reg[R13_ABT].I;
+ reg[14].I = reg[R14_ABT].I;
+ reg[16].I = SPSR;
+ if (saveState)
+ reg[17].I = CPSR;
+ else
+ reg[17].I = reg[SPSR_ABT].I;
+ break;
+ case 0x1b:
+ reg[13].I = reg[R13_UND].I;
+ reg[14].I = reg[R14_UND].I;
+ reg[16].I = SPSR;
+ if (saveState)
+ reg[17].I = CPSR;
+ else
+ reg[17].I = reg[SPSR_UND].I;
+ }
+ armMode = mode;
+ CPUUpdateFlags(breakLoop);
+ CPUUpdateCPSR();
}
void CPUUndefinedException()
{
- uint32_t PC = reg[15].I;
- bool savedArmState = armState;
- CPUSwitchMode(0x1b, true, false);
- reg[14].I = PC - (savedArmState ? 4 : 2);
- reg[15].I = 0x04;
- armState = true;
- armIrqEnable = false;
- armNextPC = 0x04;
- ARM_PREFETCH;
- reg[15].I += 4;
+ uint32_t PC = reg[15].I;
+ bool savedArmState = armState;
+ CPUSwitchMode(0x1b, true, false);
+ reg[14].I = PC - (savedArmState ? 4 : 2);
+ reg[15].I = 0x04;
+ armState = true;
+ armIrqEnable = false;
+ armNextPC = 0x04;
+ ARM_PREFETCH();
+ reg[15].I += 4;
}
void CPUSoftwareInterrupt()
{
- uint32_t PC = reg[15].I;
- bool savedArmState = armState;
- CPUSwitchMode(0x13, true, false);
- reg[14].I = PC - (savedArmState ? 4 : 2);
- reg[15].I = 0x08;
- armState = true;
- armIrqEnable = false;
- armNextPC = 0x08;
- ARM_PREFETCH;
- reg[15].I += 4;
+ uint32_t PC = reg[15].I;
+ bool savedArmState = armState;
+ CPUSwitchMode(0x13, true, false);
+ reg[14].I = PC - (savedArmState ? 4 : 2);
+ reg[15].I = 0x08;
+ armState = true;
+ armIrqEnable = false;
+ armNextPC = 0x08;
+ ARM_PREFETCH();
+ reg[15].I += 4;
}
void CPUSoftwareInterrupt(int comment)
{
- static bool disableMessage = false;
- if(armState) comment >>= 16;
-#ifdef BKPT_SUPPORT
- if(comment == 0xff) {
- dbgOutput(NULL, reg[0].I);
- return;
- }
-#endif
-#ifdef PROFILING
- if(comment == 0xfe) {
- profStartup(reg[0].I, reg[1].I);
- return;
- }
- if(comment == 0xfd) {
- profControl(reg[0].I);
- return;
- }
- if(comment == 0xfc) {
- profCleanup();
- return;
- }
- if(comment == 0xfb) {
- profCount();
- return;
- }
-#endif
- if(comment == 0xfa) {
- //agbPrintFlush();
- return;
- }
-#ifdef SDL
- if(comment == 0xf9) {
- emulating = 0;
- cpuNextEvent = cpuTotalTicks;
- cpuBreakLoop = true;
- return;
- }
-#endif
- if(useBios) {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
- armState ? armNextPC - 4: armNextPC -2,
- reg[0].I,
- reg[1].I,
- reg[2].I,
- VCOUNT);
- }
-#endif
- CPUSoftwareInterrupt();
- return;
- }
- // This would be correct, but it causes problems if uncommented
- // else {
- // biosProtected = 0xe3a02004;
- // }
-
- switch(comment) {
- case 0x00:
- BIOS_SoftReset();
- ARM_PREFETCH;
- break;
- case 0x01:
- BIOS_RegisterRamReset();
- break;
- case 0x02:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- /*log("Halt: (VCOUNT = %2d)\n",
- VCOUNT);*/
- }
-#endif
- holdState = true;
- holdType = -1;
- cpuNextEvent = cpuTotalTicks;
- break;
- case 0x03:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- /*log("Stop: (VCOUNT = %2d)\n",
- VCOUNT);*/
- }
-#endif
- /*holdState = true;
- holdType = -1;
- stopState = true;
- cpuNextEvent = cpuTotalTicks;*/
- break;
- case 0x04:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("IntrWait: 0x%08x,0x%08x (VCOUNT = %2d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
- CPUSoftwareInterrupt();
- break;
- case 0x05:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("VBlankIntrWait: (VCOUNT = %2d)\n",
- VCOUNT);
- }
-#endif
- CPUSoftwareInterrupt();
- break;
- case 0x06:
- CPUSoftwareInterrupt();
- break;
- case 0x07:
- CPUSoftwareInterrupt();
- break;
- case 0x08:
- BIOS_Sqrt();
- break;
- case 0x09:
- BIOS_ArcTan();
- break;
- case 0x0A:
- BIOS_ArcTan2();
- break;
- case 0x0B:
- {
- int len = (reg[2].I & 0x1FFFFF) >>1;
- if (!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + len) & 0xe000000) == 0))
- {
- if ((reg[2].I >> 24) & 1)
- {
- if ((reg[2].I >> 26) & 1)
- SWITicks = (7 + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1);
- else
- SWITicks = (8 + memoryWait[(reg[1].I>>24) & 0xF]) * (len);
- }
- else
- {
- if ((reg[2].I >> 26) & 1)
- SWITicks = (10 + memoryWait32[(reg[0].I>>24) & 0xF] +
- memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1);
- else
- SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] +
- memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- }
- }
- BIOS_CpuSet();
- break;
- case 0x0C:
- {
- int len = (reg[2].I & 0x1FFFFF) >>5;
- if (!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + len) & 0xe000000) == 0))
- {
- if ((reg[2].I >> 24) & 1)
- SWITicks = (6 + memoryWait32[(reg[1].I>>24) & 0xF] +
- 7 * (memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 1)) * len;
- else
- SWITicks = (9 + memoryWait32[(reg[0].I>>24) & 0xF] +
- memoryWait32[(reg[1].I>>24) & 0xF] +
- 7 * (memoryWaitSeq32[(reg[0].I>>24) & 0xF] +
- memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 2)) * len;
- }
- }
- BIOS_CpuFastSet();
- break;
- case 0x0D:
- BIOS_GetBiosChecksum();
- break;
- case 0x0E:
- BIOS_BgAffineSet();
- break;
- case 0x0F:
- BIOS_ObjAffineSet();
- break;
- case 0x10:
- {
- int len = CPUReadHalfWord(reg[2].I);
- if (!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + len) & 0xe000000) == 0))
- SWITicks = (32 + memoryWait[(reg[0].I>>24) & 0xF]) * len;
- }
- BIOS_BitUnPack();
- break;
- case 0x11:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 8;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (9 + memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_LZ77UnCompWram();
- break;
- case 0x12:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 8;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (19 + memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_LZ77UnCompVram();
- break;
- case 0x13:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 8;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (29 + (memoryWait[(reg[0].I>>24) & 0xF]<<1)) * len;
- }
- BIOS_HuffUnComp();
- break;
- case 0x14:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 8;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] +
- memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_RLUnCompWram();
- break;
- case 0x15:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 9;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (34 + (memoryWait[(reg[0].I>>24) & 0xF] << 1) +
- memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_RLUnCompVram();
- break;
- case 0x16:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 8;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] +
- memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_Diff8bitUnFilterWram();
- break;
- case 0x17:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 9;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (39 + (memoryWait[(reg[0].I>>24) & 0xF]<<1) +
- memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_Diff8bitUnFilterVram();
- break;
- case 0x18:
- {
- uint32_t len = CPUReadMemory(reg[0].I) >> 9;
- if(!(((reg[0].I & 0xe000000) == 0) ||
- ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0))
- SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] +
- memoryWait[(reg[1].I>>24) & 0xF]) * len;
- }
- BIOS_Diff16bitUnFilter();
- break;
- case 0x19:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("SoundBiasSet: 0x%08x (VCOUNT = %2d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
- if(reg[0].I)
- soundPause();
- else
- soundResume();
- break;
- case 0x1F:
- BIOS_MidiKey2Freq();
- break;
- case 0x2A:
- BIOS_SndDriverJmpTableCopy();
- // let it go, because we don't really emulate this function
- default:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
- armState ? armNextPC - 4: armNextPC -2,
- reg[0].I,
- reg[1].I,
- reg[2].I,
- VCOUNT);
- }
-#endif
-
- if(!disableMessage) {
- /*systemMessage(MSG_UNSUPPORTED_BIOS_FUNCTION,
- N_("Unsupported BIOS function %02x called from %08x. A BIOS file is needed in order to get correct behaviour."),
- comment,
- armMode ? armNextPC - 4: armNextPC - 2);*/
- disableMessage = true;
- }
- break;
- }
+ if (armState)
+ comment >>= 16;
+ if (comment == 0xfa)
+ return;
+ // This would be correct, but it causes problems if uncommented
+ //else
+ //biosProtected = 0xe3a02004;
+
+ switch (comment)
+ {
+ case 0x00:
+ BIOS_SoftReset();
+ ARM_PREFETCH();
+ break;
+ case 0x01:
+ BIOS_RegisterRamReset();
+ break;
+ case 0x02:
+ holdState = true;
+ holdType = -1;
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ case 0x03:
+ break;
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ CPUSoftwareInterrupt();
+ break;
+ case 0x08:
+ BIOS_Sqrt();
+ break;
+ case 0x09:
+ BIOS_ArcTan();
+ break;
+ case 0x0A:
+ BIOS_ArcTan2();
+ break;
+ case 0x0B:
+ {
+ int len = (reg[2].I & 0x1FFFFF) >> 1;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + len) & 0xe000000)))
+ {
+ if ((reg[2].I >> 24) & 1)
+ {
+ if ((reg[2].I >> 26) & 1)
+ SWITicks = (7 + memoryWait32[(reg[1].I >> 24) & 0xF]) * (len >> 1);
+ else
+ SWITicks = (8 + memoryWait[(reg[1].I >> 24) & 0xF]) * (len);
+ }
+ else
+ {
+ if ((reg[2].I >> 26) & 1)
+ SWITicks = (10 + memoryWait32[(reg[0].I >> 24) & 0xF] + memoryWait32[(reg[1].I >> 24) & 0xF]) * (len >> 1);
+ else
+ SWITicks = (11 + memoryWait[(reg[0].I >> 24) & 0xF] + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ }
+ }
+ BIOS_CpuSet();
+ break;
+ }
+ case 0x0C:
+ {
+ int len = (reg[2].I & 0x1FFFFF) >> 5;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + len) & 0xe000000)))
+ {
+ if ((reg[2].I >> 24) & 1)
+ SWITicks = (6 + memoryWait32[(reg[1].I >> 24) & 0xF] + 7 * (memoryWaitSeq32[(reg[1].I >> 24) & 0xF] + 1)) * len;
+ else
+ SWITicks = (9 + memoryWait32[(reg[0].I >> 24) & 0xF] + memoryWait32[(reg[1].I >> 24) & 0xF] + 7 * (memoryWaitSeq32[(reg[0].I >> 24) & 0xF] + memoryWaitSeq32[(reg[1].I >> 24) & 0xF] + 2)) * len;
+ }
+ BIOS_CpuFastSet();
+ break;
+ }
+ case 0x0D:
+ BIOS_GetBiosChecksum();
+ break;
+ case 0x0E:
+ BIOS_BgAffineSet();
+ break;
+ case 0x0F:
+ BIOS_ObjAffineSet();
+ break;
+ case 0x10:
+ {
+ int len = CPUReadHalfWord(reg[2].I);
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + len) & 0xe000000)))
+ SWITicks = (32 + memoryWait[(reg[0].I >> 24) & 0xF]) * len;
+ BIOS_BitUnPack();
+ break;
+ }
+ case 0x11:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 8;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (9 + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_LZ77UnCompWram();
+ break;
+ }
+ case 0x12:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 8;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (19 + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_LZ77UnCompVram();
+ break;
+ }
+ case 0x13:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 8;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (29 + (memoryWait[(reg[0].I >> 24) & 0xF] << 1)) * len;
+ BIOS_HuffUnComp();
+ break;
+ }
+ case 0x14:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 8;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (11 + memoryWait[(reg[0].I >> 24) & 0xF] + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_RLUnCompWram();
+ break;
+ }
+ case 0x15:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 9;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (34 + (memoryWait[(reg[0].I >> 24) & 0xF] << 1) + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_RLUnCompVram();
+ break;
+ }
+ case 0x16:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 8;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (13 + memoryWait[(reg[0].I >> 24) & 0xF] + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_Diff8bitUnFilterWram();
+ break;
+ }
+ case 0x17:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 9;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (39 + (memoryWait[(reg[0].I >> 24) & 0xF]<<1) + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_Diff8bitUnFilterVram();
+ break;
+ }
+ case 0x18:
+ {
+ uint32_t len = CPUReadMemory(reg[0].I) >> 9;
+ if (!(!(reg[0].I & 0xe000000) || !((reg[0].I + (len & 0x1fffff)) & 0xe000000)))
+ SWITicks = (13 + memoryWait[(reg[0].I >> 24) & 0xF] + memoryWait[(reg[1].I >> 24) & 0xF]) * len;
+ BIOS_Diff16bitUnFilter();
+ break;
+ }
+ case 0x19:
+ if (reg[0].I)
+ soundPause();
+ else
+ soundResume();
+ break;
+ case 0x1F:
+ BIOS_MidiKey2Freq();
+ break;
+ case 0x2A:
+ BIOS_SndDriverJmpTableCopy();
+ // let it go, because we don't really emulate this function
+ }
}
void CPUCompareVCOUNT()
{
- if(VCOUNT == (DISPSTAT >> 8)) {
- DISPSTAT |= 4;
- UPDATE_REG(0x04, DISPSTAT);
-
- if(DISPSTAT & 0x20) {
- IF |= 4;
- UPDATE_REG(0x202, IF);
- }
- } else {
- DISPSTAT &= 0xFFFB;
- UPDATE_REG(0x4, DISPSTAT);
- }
- if (layerEnableDelay>0)
- {
- layerEnableDelay--;
- if (layerEnableDelay==1)
- layerEnable = layerSettings & DISPCNT;
- }
-
+ if (VCOUNT == (DISPSTAT >> 8))
+ {
+ DISPSTAT |= 4;
+ UPDATE_REG(0x04, DISPSTAT);
+
+ if (DISPSTAT & 0x20)
+ {
+ IF |= 4;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ else
+ {
+ DISPSTAT &= 0xFFFB;
+ UPDATE_REG(0x4, DISPSTAT);
+ }
+ if (layerEnableDelay > 0)
+ {
+ --layerEnableDelay;
+ if (layerEnableDelay == 1)
+ layerEnable = layerSettings & DISPCNT;
+ }
}
void doDMA(uint32_t &s, uint32_t &d, uint32_t si, uint32_t di, uint32_t c, int transfer32)
{
- int sm = s >> 24;
- int dm = d >> 24;
- int sw = 0;
- int dw = 0;
- int sc = c;
-
- cpuDmaCount = c;
- // This is done to get the correct waitstates.
- if (sm>15)
- sm=15;
- if (dm>15)
- dm=15;
-
- //if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07))
- // blank = (((DISPSTAT | ((DISPSTAT>>1)&1))==1) ? true : false);
-
- if(transfer32) {
- s &= 0xFFFFFFFC;
- if(s < 0x02000000 && (reg[15].I >> 24)) {
- while(c != 0) {
- CPUWriteMemory(d, 0);
- d += di;
- c--;
- }
- } else {
- while(c != 0) {
- cpuDmaLast = CPUReadMemory(s);
- CPUWriteMemory(d, cpuDmaLast);
- d += di;
- s += si;
- c--;
- }
- }
- } else {
- s &= 0xFFFFFFFE;
- si = (int)si >> 1;
- di = (int)di >> 1;
- if(s < 0x02000000 && (reg[15].I >> 24)) {
- while(c != 0) {
- CPUWriteHalfWord(d, 0);
- d += di;
- c--;
- }
- } else {
- while(c != 0) {
- cpuDmaLast = CPUReadHalfWord(s);
- CPUWriteHalfWord(d, cpuDmaLast);
- cpuDmaLast |= (cpuDmaLast<<16);
- d += di;
- s += si;
- c--;
- }
- }
- }
-
- cpuDmaCount = 0;
-
- int totalTicks = 0;
-
- if(transfer32) {
- sw =1+memoryWaitSeq32[sm & 15];
- dw =1+memoryWaitSeq32[dm & 15];
- totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] +
- memoryWaitSeq32[dm & 15];
- }
- else
- {
- sw = 1+memoryWaitSeq[sm & 15];
- dw = 1+memoryWaitSeq[dm & 15];
- totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] +
- memoryWaitSeq[dm & 15];
- }
-
- cpuDmaTicksToUpdate += totalTicks;
-
+ int sm = s >> 24;
+ int dm = d >> 24;
+ int sw = 0;
+ int dw = 0;
+ int sc = c;
+
+ // This is done to get the correct waitstates.
+ if (sm > 15)
+ sm = 15;
+ if (dm > 15)
+ dm = 15;
+
+ if (transfer32)
+ {
+ s &= 0xFFFFFFFC;
+ if (s < 0x02000000 && (reg[15].I >> 24))
+ {
+ while (c)
+ {
+ CPUWriteMemory(d, 0);
+ d += di;
+ --c;
+ }
+ }
+ else
+ {
+ while (c)
+ {
+ cpuDmaLast = CPUReadMemory(s);
+ CPUWriteMemory(d, cpuDmaLast);
+ d += di;
+ s += si;
+ --c;
+ }
+ }
+ }
+ else
+ {
+ s &= 0xFFFFFFFE;
+ si = static_cast<int>(si) >> 1;
+ di = static_cast<int>(di) >> 1;
+ if (s < 0x02000000 && (reg[15].I >> 24))
+ {
+ while (c)
+ {
+ CPUWriteHalfWord(d, 0);
+ d += di;
+ --c;
+ }
+ }
+ else
+ {
+ while (c)
+ {
+ cpuDmaLast = CPUReadHalfWord(s);
+ CPUWriteHalfWord(d, cpuDmaLast);
+ cpuDmaLast |= cpuDmaLast << 16;
+ d += di;
+ s += si;
+ --c;
+ }
+ }
+ }
+
+ int totalTicks = 0;
+
+ if (transfer32)
+ {
+ sw = 1 + memoryWaitSeq32[sm & 15];
+ dw = 1 + memoryWaitSeq32[dm & 15];
+ totalTicks = (sw + dw) * (sc - 1) + 6 + memoryWait32[sm & 15] + memoryWaitSeq32[dm & 15];
+ }
+ else
+ {
+ sw = 1 + memoryWaitSeq[sm & 15];
+ dw = 1 + memoryWaitSeq[dm & 15];
+ totalTicks = (sw + dw) * (sc - 1) + 6 + memoryWait[sm & 15] + memoryWaitSeq[dm & 15];
+ }
+
+ cpuDmaTicksToUpdate += totalTicks;
}
void CPUCheckDMA(int reason, int dmamask)
{
- // DMA 0
- if((DM0CNT_H & 0x8000) && (dmamask & 1)) {
- if(((DM0CNT_H >> 12) & 3) == reason) {
- uint32_t sourceIncrement = 4;
- uint32_t destIncrement = 4;
- switch((DM0CNT_H >> 7) & 3) {
- case 0:
- break;
- case 1:
- sourceIncrement = (uint32_t)-4;
- break;
- case 2:
- sourceIncrement = 0;
- break;
- }
- switch((DM0CNT_H >> 5) & 3) {
- case 0:
- break;
- case 1:
- destIncrement = (uint32_t)-4;
- break;
- case 2:
- destIncrement = 0;
- break;
- }
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_DMA0) {
- int count = (DM0CNT_L ? DM0CNT_L : 0x4000) << 1;
- if(DM0CNT_H & 0x0400)
- count <<= 1;
- log("DMA0: s=%08x d=%08x c=%04x count=%08x\n", dma0Source, dma0Dest,
- DM0CNT_H,
- count);
- }
-#endif
- doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement,
- DM0CNT_L ? DM0CNT_L : 0x4000,
- DM0CNT_H & 0x0400);
-
- if(DM0CNT_H & 0x4000) {
- IF |= 0x0100;
- UPDATE_REG(0x202, IF);
- cpuNextEvent = cpuTotalTicks;
- }
-
- if(((DM0CNT_H >> 5) & 3) == 3) {
- dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
- }
-
- if(!(DM0CNT_H & 0x0200) || (reason == 0)) {
- DM0CNT_H &= 0x7FFF;
- UPDATE_REG(0xBA, DM0CNT_H);
- }
- }
- }
-
- // DMA 1
- if((DM1CNT_H & 0x8000) && (dmamask & 2)) {
- if(((DM1CNT_H >> 12) & 3) == reason) {
- uint32_t sourceIncrement = 4;
- uint32_t destIncrement = 4;
- switch((DM1CNT_H >> 7) & 3) {
- case 0:
- break;
- case 1:
- sourceIncrement = (uint32_t)-4;
- break;
- case 2:
- sourceIncrement = 0;
- break;
- }
- switch((DM1CNT_H >> 5) & 3) {
- case 0:
- break;
- case 1:
- destIncrement = (uint32_t)-4;
- break;
- case 2:
- destIncrement = 0;
- break;
- }
- if(reason == 3) {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_DMA1) {
- log("DMA1: s=%08x d=%08x c=%04x count=%08x\n", dma1Source, dma1Dest,
- DM1CNT_H,
- 16);
- }
-#endif
- doDMA(dma1Source, dma1Dest, sourceIncrement, 0, 4,
- 0x0400);
- } else {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_DMA1) {
- int count = (DM1CNT_L ? DM1CNT_L : 0x4000) << 1;
- if(DM1CNT_H & 0x0400)
- count <<= 1;
- log("DMA1: s=%08x d=%08x c=%04x count=%08x\n", dma1Source, dma1Dest,
- DM1CNT_H,
- count);
- }
-#endif
- doDMA(dma1Source, dma1Dest, sourceIncrement, destIncrement,
- DM1CNT_L ? DM1CNT_L : 0x4000,
- DM1CNT_H & 0x0400);
- }
-
- if(DM1CNT_H & 0x4000) {
- IF |= 0x0200;
- UPDATE_REG(0x202, IF);
- cpuNextEvent = cpuTotalTicks;
- }
-
- if(((DM1CNT_H >> 5) & 3) == 3) {
- dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
- }
-
- if(!(DM1CNT_H & 0x0200) || (reason == 0)) {
- DM1CNT_H &= 0x7FFF;
- UPDATE_REG(0xC6, DM1CNT_H);
- }
- }
- }
-
- // DMA 2
- if((DM2CNT_H & 0x8000) && (dmamask & 4)) {
- if(((DM2CNT_H >> 12) & 3) == reason) {
- uint32_t sourceIncrement = 4;
- uint32_t destIncrement = 4;
- switch((DM2CNT_H >> 7) & 3) {
- case 0:
- break;
- case 1:
- sourceIncrement = (uint32_t)-4;
- break;
- case 2:
- sourceIncrement = 0;
- break;
- }
- switch((DM2CNT_H >> 5) & 3) {
- case 0:
- break;
- case 1:
- destIncrement = (uint32_t)-4;
- break;
- case 2:
- destIncrement = 0;
- break;
- }
- if(reason == 3) {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_DMA2) {
- int count = (4) << 2;
- log("DMA2: s=%08x d=%08x c=%04x count=%08x\n", dma2Source, dma2Dest,
- DM2CNT_H,
- count);
- }
-#endif
- doDMA(dma2Source, dma2Dest, sourceIncrement, 0, 4,
- 0x0400);
- } else {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_DMA2) {
- int count = (DM2CNT_L ? DM2CNT_L : 0x4000) << 1;
- if(DM2CNT_H & 0x0400)
- count <<= 1;
- log("DMA2: s=%08x d=%08x c=%04x count=%08x\n", dma2Source, dma2Dest,
- DM2CNT_H,
- count);
- }
-#endif
- doDMA(dma2Source, dma2Dest, sourceIncrement, destIncrement,
- DM2CNT_L ? DM2CNT_L : 0x4000,
- DM2CNT_H & 0x0400);
- }
-
- if(DM2CNT_H & 0x4000) {
- IF |= 0x0400;
- UPDATE_REG(0x202, IF);
- cpuNextEvent = cpuTotalTicks;
- }
-
- if(((DM2CNT_H >> 5) & 3) == 3) {
- dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
- }
-
- if(!(DM2CNT_H & 0x0200) || (reason == 0)) {
- DM2CNT_H &= 0x7FFF;
- UPDATE_REG(0xD2, DM2CNT_H);
- }
- }
- }
-
- // DMA 3
- if((DM3CNT_H & 0x8000) && (dmamask & 8)) {
- if(((DM3CNT_H >> 12) & 3) == reason) {
- uint32_t sourceIncrement = 4;
- uint32_t destIncrement = 4;
- switch((DM3CNT_H >> 7) & 3) {
- case 0:
- break;
- case 1:
- sourceIncrement = (uint32_t)-4;
- break;
- case 2:
- sourceIncrement = 0;
- break;
- }
- switch((DM3CNT_H >> 5) & 3) {
- case 0:
- break;
- case 1:
- destIncrement = (uint32_t)-4;
- break;
- case 2:
- destIncrement = 0;
- break;
- }
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_DMA3) {
- int count = (DM3CNT_L ? DM3CNT_L : 0x10000) << 1;
- if(DM3CNT_H & 0x0400)
- count <<= 1;
- log("DMA3: s=%08x d=%08x c=%04x count=%08x\n", dma3Source, dma3Dest,
- DM3CNT_H,
- count);
- }
-#endif
- doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement,
- DM3CNT_L ? DM3CNT_L : 0x10000,
- DM3CNT_H & 0x0400);
- if(DM3CNT_H & 0x4000) {
- IF |= 0x0800;
- UPDATE_REG(0x202, IF);
- cpuNextEvent = cpuTotalTicks;
- }
-
- if(((DM3CNT_H >> 5) & 3) == 3) {
- dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
- }
-
- if(!(DM3CNT_H & 0x0200) || (reason == 0)) {
- DM3CNT_H &= 0x7FFF;
- UPDATE_REG(0xDE, DM3CNT_H);
- }
- }
- }
+ // DMA 0
+ if ((DM0CNT_H & 0x8000) && (dmamask & 1))
+ {
+ if (((DM0CNT_H >> 12) & 3) == reason)
+ {
+ uint32_t sourceIncrement = 4;
+ uint32_t destIncrement = 4;
+ switch ((DM0CNT_H >> 7) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ sourceIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ sourceIncrement = 0;
+ }
+ switch ((DM0CNT_H >> 5) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ destIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ destIncrement = 0;
+ }
+ doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, DM0CNT_L ? DM0CNT_L : 0x4000, DM0CNT_H & 0x0400);
+
+ if (DM0CNT_H & 0x4000)
+ {
+ IF |= 0x0100;
+ UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
+ }
+
+ if (((DM0CNT_H >> 5) & 3) == 3)
+ dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
+
+ if (!(DM0CNT_H & 0x0200) || !reason)
+ {
+ DM0CNT_H &= 0x7FFF;
+ UPDATE_REG(0xBA, DM0CNT_H);
+ }
+ }
+ }
+
+ // DMA 1
+ if ((DM1CNT_H & 0x8000) && (dmamask & 2))
+ {
+ if (((DM1CNT_H >> 12) & 3) == reason)
+ {
+ uint32_t sourceIncrement = 4;
+ uint32_t destIncrement = 4;
+ switch ((DM1CNT_H >> 7) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ sourceIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ sourceIncrement = 0;
+ }
+ switch ((DM1CNT_H >> 5) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ destIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ destIncrement = 0;
+ }
+ if (reason == 3)
+ doDMA(dma1Source, dma1Dest, sourceIncrement, 0, 4, 0x0400);
+ else
+ doDMA(dma1Source, dma1Dest, sourceIncrement, destIncrement, DM1CNT_L ? DM1CNT_L : 0x4000, DM1CNT_H & 0x0400);
+
+ if (DM1CNT_H & 0x4000)
+ {
+ IF |= 0x0200;
+ UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
+ }
+
+ if (((DM1CNT_H >> 5) & 3) == 3)
+ dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
+
+ if (!(DM1CNT_H & 0x0200) || !reason)
+ {
+ DM1CNT_H &= 0x7FFF;
+ UPDATE_REG(0xC6, DM1CNT_H);
+ }
+ }
+ }
+
+ // DMA 2
+ if ((DM2CNT_H & 0x8000) && (dmamask & 4))
+ {
+ if (((DM2CNT_H >> 12) & 3) == reason)
+ {
+ uint32_t sourceIncrement = 4;
+ uint32_t destIncrement = 4;
+ switch ((DM2CNT_H >> 7) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ sourceIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ sourceIncrement = 0;
+ }
+ switch ((DM2CNT_H >> 5) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ destIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ destIncrement = 0;
+ }
+ if (reason == 3)
+ doDMA(dma2Source, dma2Dest, sourceIncrement, 0, 4, 0x0400);
+ else
+ doDMA(dma2Source, dma2Dest, sourceIncrement, destIncrement, DM2CNT_L ? DM2CNT_L : 0x4000, DM2CNT_H & 0x0400);
+
+ if (DM2CNT_H & 0x4000)
+ {
+ IF |= 0x0400;
+ UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
+ }
+
+ if (((DM2CNT_H >> 5) & 3) == 3)
+ dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
+
+ if (!(DM2CNT_H & 0x0200) || !reason)
+ {
+ DM2CNT_H &= 0x7FFF;
+ UPDATE_REG(0xD2, DM2CNT_H);
+ }
+ }
+ }
+
+ // DMA 3
+ if ((DM3CNT_H & 0x8000) && (dmamask & 8))
+ {
+ if (((DM3CNT_H >> 12) & 3) == reason)
+ {
+ uint32_t sourceIncrement = 4;
+ uint32_t destIncrement = 4;
+ switch ((DM3CNT_H >> 7) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ sourceIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ sourceIncrement = 0;
+ }
+ switch ((DM3CNT_H >> 5) & 3)
+ {
+ case 0:
+ break;
+ case 1:
+ destIncrement = static_cast<uint32_t>(-4);
+ break;
+ case 2:
+ destIncrement = 0;
+ }
+ doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, DM3CNT_L ? DM3CNT_L : 0x10000, DM3CNT_H & 0x0400);
+ if (DM3CNT_H & 0x4000)
+ {
+ IF |= 0x0800;
+ UPDATE_REG(0x202, IF);
+ cpuNextEvent = cpuTotalTicks;
+ }
+
+ if (((DM3CNT_H >> 5) & 3) == 3)
+ dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
+
+ if (!(DM3CNT_H & 0x0200) || !reason)
+ {
+ DM3CNT_H &= 0x7FFF;
+ UPDATE_REG(0xDE, DM3CNT_H);
+ }
+ }
+ }
}
void CPUUpdateRegister(uint32_t address, uint16_t value)
{
- switch(address)
- {
- case 0x00:
- { // we need to place the following code in { } because we declare & initialize variables in a case statement
- if((value & 7) > 5) {
- // display modes above 0-5 are prohibited
- DISPCNT = (value & 7);
- }
- bool change = (0 != ((DISPCNT ^ value) & 0x80));
- bool changeBG = (0 != ((DISPCNT ^ value) & 0x0F00));
- uint16_t changeBGon = ((~DISPCNT) & value) & 0x0F00; // these layers are being activated
-
- DISPCNT = (value & 0xFFF7); // bit 3 can only be accessed by the BIOS to enable GBC mode
- UPDATE_REG(0x00, DISPCNT);
-
- if(changeBGon) {
- layerEnableDelay = 4;
- layerEnable = layerSettings & value & (~changeBGon);
- } else {
- layerEnable = layerSettings & value;
- // CPUUpdateTicks();
- }
-
- windowOn = (layerEnable & 0x6000) ? true : false;
- if(change && !((value & 0x80))) {
- if(!(DISPSTAT & 1)) {
- lcdTicks = 1008;
- // VCOUNT = 0;
- // UPDATE_REG(0x06, VCOUNT);
- DISPSTAT &= 0xFFFC;
- UPDATE_REG(0x04, DISPSTAT);
- CPUCompareVCOUNT();
- }
- // (*renderLine)();
- }
- //CPUUpdateRender();
- // we only care about changes in BG0-BG3
- if(changeBG) {
- //CPUUpdateRenderBuffers(false);
- }
- break;
- }
- case 0x04:
- DISPSTAT = (value & 0xFF38) | (DISPSTAT & 7);
- UPDATE_REG(0x04, DISPSTAT);
- break;
- case 0x06:
- // not writable
- break;
- case 0x08:
- BG0CNT = (value & 0xDFCF);
- UPDATE_REG(0x08, BG0CNT);
- break;
- case 0x0A:
- BG1CNT = (value & 0xDFCF);
- UPDATE_REG(0x0A, BG1CNT);
- break;
- case 0x0C:
- BG2CNT = (value & 0xFFCF);
- UPDATE_REG(0x0C, BG2CNT);
- break;
- case 0x0E:
- BG3CNT = (value & 0xFFCF);
- UPDATE_REG(0x0E, BG3CNT);
- break;
- case 0x10:
- BG0HOFS = value & 511;
- UPDATE_REG(0x10, BG0HOFS);
- break;
- case 0x12:
- BG0VOFS = value & 511;
- UPDATE_REG(0x12, BG0VOFS);
- break;
- case 0x14:
- BG1HOFS = value & 511;
- UPDATE_REG(0x14, BG1HOFS);
- break;
- case 0x16:
- BG1VOFS = value & 511;
- UPDATE_REG(0x16, BG1VOFS);
- break;
- case 0x18:
- BG2HOFS = value & 511;
- UPDATE_REG(0x18, BG2HOFS);
- break;
- case 0x1A:
- BG2VOFS = value & 511;
- UPDATE_REG(0x1A, BG2VOFS);
- break;
- case 0x1C:
- BG3HOFS = value & 511;
- UPDATE_REG(0x1C, BG3HOFS);
- break;
- case 0x1E:
- BG3VOFS = value & 511;
- UPDATE_REG(0x1E, BG3VOFS);
- break;
- case 0x20:
- BG2PA = value;
- UPDATE_REG(0x20, BG2PA);
- break;
- case 0x22:
- BG2PB = value;
- UPDATE_REG(0x22, BG2PB);
- break;
- case 0x24:
- BG2PC = value;
- UPDATE_REG(0x24, BG2PC);
- break;
- case 0x26:
- BG2PD = value;
- UPDATE_REG(0x26, BG2PD);
- break;
- case 0x28:
- BG2X_L = value;
- UPDATE_REG(0x28, BG2X_L);
- //gfxBG2Changed |= 1;
- break;
- case 0x2A:
- BG2X_H = (value & 0xFFF);
- UPDATE_REG(0x2A, BG2X_H);
- //gfxBG2Changed |= 1;
- break;
- case 0x2C:
- BG2Y_L = value;
- UPDATE_REG(0x2C, BG2Y_L);
- //gfxBG2Changed |= 2;
- break;
- case 0x2E:
- BG2Y_H = value & 0xFFF;
- UPDATE_REG(0x2E, BG2Y_H);
- //gfxBG2Changed |= 2;
- break;
- case 0x30:
- BG3PA = value;
- UPDATE_REG(0x30, BG3PA);
- break;
- case 0x32:
- BG3PB = value;
- UPDATE_REG(0x32, BG3PB);
- break;
- case 0x34:
- BG3PC = value;
- UPDATE_REG(0x34, BG3PC);
- break;
- case 0x36:
- BG3PD = value;
- UPDATE_REG(0x36, BG3PD);
- break;
- case 0x38:
- BG3X_L = value;
- UPDATE_REG(0x38, BG3X_L);
- //gfxBG3Changed |= 1;
- break;
- case 0x3A:
- BG3X_H = value & 0xFFF;
- UPDATE_REG(0x3A, BG3X_H);
- //gfxBG3Changed |= 1;
- break;
- case 0x3C:
- BG3Y_L = value;
- UPDATE_REG(0x3C, BG3Y_L);
- //gfxBG3Changed |= 2;
- break;
- case 0x3E:
- BG3Y_H = value & 0xFFF;
- UPDATE_REG(0x3E, BG3Y_H);
- //gfxBG3Changed |= 2;
- break;
- case 0x40:
- WIN0H = value;
- UPDATE_REG(0x40, WIN0H);
- //CPUUpdateWindow0();
- break;
- case 0x42:
- WIN1H = value;
- UPDATE_REG(0x42, WIN1H);
- //CPUUpdateWindow1();
- break;
- case 0x44:
- WIN0V = value;
- UPDATE_REG(0x44, WIN0V);
- break;
- case 0x46:
- WIN1V = value;
- UPDATE_REG(0x46, WIN1V);
- break;
- case 0x48:
- WININ = value & 0x3F3F;
- UPDATE_REG(0x48, WININ);
- break;
- case 0x4A:
- WINOUT = value & 0x3F3F;
- UPDATE_REG(0x4A, WINOUT);
- break;
- case 0x4C:
- MOSAIC = value;
- UPDATE_REG(0x4C, MOSAIC);
- break;
- case 0x50:
- BLDMOD = value & 0x3FFF;
- UPDATE_REG(0x50, BLDMOD);
- fxOn = ((BLDMOD>>6)&3) != 0;
- //CPUUpdateRender();
- break;
- case 0x52:
- COLEV = value & 0x1F1F;
- UPDATE_REG(0x52, COLEV);
- break;
- case 0x54:
- COLY = value & 0x1F;
- UPDATE_REG(0x54, COLY);
- break;
- case 0x60:
- case 0x62:
- case 0x64:
- case 0x68:
- case 0x6c:
- case 0x70:
- case 0x72:
- case 0x74:
- case 0x78:
- case 0x7c:
- case 0x80:
- case 0x84:
- soundEvent(address&0xFF, (uint8_t)(value & 0xFF));
- soundEvent((address&0xFF)+1, (uint8_t)(value>>8));
- break;
- case 0x82:
- case 0x88:
- case 0xa0:
- case 0xa2:
- case 0xa4:
- case 0xa6:
- case 0x90:
- case 0x92:
- case 0x94:
- case 0x96:
- case 0x98:
- case 0x9a:
- case 0x9c:
- case 0x9e:
- soundEvent(address&0xFF, value);
- break;
- case 0xB0:
- DM0SAD_L = value;
- UPDATE_REG(0xB0, DM0SAD_L);
- break;
- case 0xB2:
- DM0SAD_H = value & 0x07FF;
- UPDATE_REG(0xB2, DM0SAD_H);
- break;
- case 0xB4:
- DM0DAD_L = value;
- UPDATE_REG(0xB4, DM0DAD_L);
- break;
- case 0xB6:
- DM0DAD_H = value & 0x07FF;
- UPDATE_REG(0xB6, DM0DAD_H);
- break;
- case 0xB8:
- DM0CNT_L = value & 0x3FFF;
- UPDATE_REG(0xB8, 0);
- break;
- case 0xBA:
- {
- bool start = ((DM0CNT_H ^ value) & 0x8000) ? true : false;
- value &= 0xF7E0;
-
- DM0CNT_H = value;
- UPDATE_REG(0xBA, DM0CNT_H);
-
- if(start && (value & 0x8000)) {
- dma0Source = DM0SAD_L | (DM0SAD_H << 16);
- dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
- CPUCheckDMA(0, 1);
- }
- }
- break;
- case 0xBC:
- DM1SAD_L = value;
- UPDATE_REG(0xBC, DM1SAD_L);
- break;
- case 0xBE:
- DM1SAD_H = value & 0x0FFF;
- UPDATE_REG(0xBE, DM1SAD_H);
- break;
- case 0xC0:
- DM1DAD_L = value;
- UPDATE_REG(0xC0, DM1DAD_L);
- break;
- case 0xC2:
- DM1DAD_H = value & 0x07FF;
- UPDATE_REG(0xC2, DM1DAD_H);
- break;
- case 0xC4:
- DM1CNT_L = value & 0x3FFF;
- UPDATE_REG(0xC4, 0);
- break;
- case 0xC6:
- {
- bool start = ((DM1CNT_H ^ value) & 0x8000) ? true : false;
- value &= 0xF7E0;
-
- DM1CNT_H = value;
- UPDATE_REG(0xC6, DM1CNT_H);
-
- if(start && (value & 0x8000)) {
- dma1Source = DM1SAD_L | (DM1SAD_H << 16);
- dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
- CPUCheckDMA(0, 2);
- }
- }
- break;
- case 0xC8:
- DM2SAD_L = value;
- UPDATE_REG(0xC8, DM2SAD_L);
- break;
- case 0xCA:
- DM2SAD_H = value & 0x0FFF;
- UPDATE_REG(0xCA, DM2SAD_H);
- break;
- case 0xCC:
- DM2DAD_L = value;
- UPDATE_REG(0xCC, DM2DAD_L);
- break;
- case 0xCE:
- DM2DAD_H = value & 0x07FF;
- UPDATE_REG(0xCE, DM2DAD_H);
- break;
- case 0xD0:
- DM2CNT_L = value & 0x3FFF;
- UPDATE_REG(0xD0, 0);
- break;
- case 0xD2:
- {
- bool start = ((DM2CNT_H ^ value) & 0x8000) ? true : false;
-
- value &= 0xF7E0;
-
- DM2CNT_H = value;
- UPDATE_REG(0xD2, DM2CNT_H);
-
- if(start && (value & 0x8000)) {
- dma2Source = DM2SAD_L | (DM2SAD_H << 16);
- dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
-
- CPUCheckDMA(0, 4);
- }
- }
- break;
- case 0xD4:
- DM3SAD_L = value;
- UPDATE_REG(0xD4, DM3SAD_L);
- break;
- case 0xD6:
- DM3SAD_H = value & 0x0FFF;
- UPDATE_REG(0xD6, DM3SAD_H);
- break;
- case 0xD8:
- DM3DAD_L = value;
- UPDATE_REG(0xD8, DM3DAD_L);
- break;
- case 0xDA:
- DM3DAD_H = value & 0x0FFF;
- UPDATE_REG(0xDA, DM3DAD_H);
- break;
- case 0xDC:
- DM3CNT_L = value;
- UPDATE_REG(0xDC, 0);
- break;
- case 0xDE:
- {
- bool start = ((DM3CNT_H ^ value) & 0x8000) ? true : false;
-
- value &= 0xFFE0;
-
- DM3CNT_H = value;
- UPDATE_REG(0xDE, DM3CNT_H);
-
- if(start && (value & 0x8000)) {
- dma3Source = DM3SAD_L | (DM3SAD_H << 16);
- dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
- CPUCheckDMA(0,8);
- }
- }
- break;
- case 0x100:
- timer0Reload = value;
- interp_rate();
- break;
- case 0x102:
- timer0Value = value;
- timerOnOffDelay|=1;
- cpuNextEvent = cpuTotalTicks;
- break;
- case 0x104:
- timer1Reload = value;
- interp_rate();
- break;
- case 0x106:
- timer1Value = value;
- timerOnOffDelay|=2;
- cpuNextEvent = cpuTotalTicks;
- break;
- case 0x108:
- timer2Reload = value;
- break;
- case 0x10A:
- timer2Value = value;
- timerOnOffDelay|=4;
- cpuNextEvent = cpuTotalTicks;
- break;
- case 0x10C:
- timer3Reload = value;
- break;
- case 0x10E:
- timer3Value = value;
- timerOnOffDelay|=8;
- cpuNextEvent = cpuTotalTicks;
- break;
-
-
- /*case COMM_SIOCNT:
- StartLink(value);
- break;
-
- case COMM_SIODATA8:
- if (gba_link_enabled)
- LinkSSend(value);
- UPDATE_REG(COMM_SIODATA8, value);
- break;*/
-
- case 0x130:
- P1 |= (value & 0x3FF);
- UPDATE_REG(0x130, P1);
- break;
-
- case 0x132:
- UPDATE_REG(0x132, value & 0xC3FF);
- break;
-
- /*case COMM_RCNT:
- StartGPLink(value);
- break;
-
- case COMM_JOYCNT:
- {
- u16 cur = READ16LE(&ioMem[COMM_JOYCNT]);
-
- if (value & JOYCNT_RESET) cur &= ~JOYCNT_RESET;
- if (value & JOYCNT_RECV_COMPLETE) cur &= ~JOYCNT_RECV_COMPLETE;
- if (value & JOYCNT_SEND_COMPLETE) cur &= ~JOYCNT_SEND_COMPLETE;
- if (value & JOYCNT_INT_ENABLE) cur |= JOYCNT_INT_ENABLE;
-
- UPDATE_REG(COMM_JOYCNT, cur);
- }
- break;
-
- case COMM_JOY_RECV_L:
- UPDATE_REG(COMM_JOY_RECV_L, value);
- break;
- case COMM_JOY_RECV_H:
- UPDATE_REG(COMM_JOY_RECV_H, value);
- break;
-
- case COMM_JOY_TRANS_L:
- UPDATE_REG(COMM_JOY_TRANS_L, value);
- UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) | JOYSTAT_SEND);
- break;
- case COMM_JOY_TRANS_H:
- UPDATE_REG(COMM_JOY_TRANS_H, value);
- break;
-
- case COMM_JOYSTAT:
- UPDATE_REG(COMM_JOYSTAT, (READ16LE(&ioMem[COMM_JOYSTAT]) & 0xf) | (value & 0xf0));
- break;*/
-
- case 0x200:
- IE = value & 0x3FFF;
- UPDATE_REG(0x200, IE);
- if ((IME & 1) && (IF & IE) && armIrqEnable)
- cpuNextEvent = cpuTotalTicks;
- break;
- case 0x202:
- IF ^= (value & IF);
- UPDATE_REG(0x202, IF);
- break;
- case 0x204:
- {
- memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3];
-
- if(!speedHack) {
- memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3];
- memoryWaitSeq[0x08] = memoryWaitSeq[0x09] =
- gamepakWaitState0[(value >> 4) & 1];
-
- memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3];
- memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] =
- gamepakWaitState1[(value >> 7) & 1];
-
- memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3];
- memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] =
- gamepakWaitState2[(value >> 10) & 1];
- } else {
- memoryWait[0x08] = memoryWait[0x09] = 3;
- memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1;
-
- memoryWait[0x0a] = memoryWait[0x0b] = 3;
- memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1;
-
- memoryWait[0x0c] = memoryWait[0x0d] = 3;
- memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1;
- }
-
- for(int i = 8; i < 15; i++) {
- memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1;
- memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1;
- }
-
- if((value & 0x4000) == 0x4000) {
- busPrefetchEnable = true;
- busPrefetch = false;
- busPrefetchCount = 0;
- } else {
- busPrefetchEnable = false;
- busPrefetch = false;
- busPrefetchCount = 0;
- }
- UPDATE_REG(0x204, value & 0x7FFF);
-
- }
- break;
- case 0x208:
- IME = value & 1;
- UPDATE_REG(0x208, IME);
- if ((IME & 1) && (IF & IE) && armIrqEnable)
- cpuNextEvent = cpuTotalTicks;
- break;
- case 0x300:
- if(value != 0)
- value &= 0xFFFE;
- UPDATE_REG(0x300, value);
- break;
- default:
- UPDATE_REG(address&0x3FE, value);
- break;
- }
+ switch (address)
+ {
+ case 0x00:
+ {
+ if ((value & 7) > 5)
+ // display modes above 0-5 are prohibited
+ DISPCNT = value & 7;
+ bool change = !!((DISPCNT ^ value) & 0x80);
+ uint16_t changeBGon = (~DISPCNT & value) & 0x0F00; // these layers are being activated
+
+ DISPCNT = value & 0xFFF7; // bit 3 can only be accessed by the BIOS to enable GBC mode
+ UPDATE_REG(0x00, DISPCNT);
+
+ if (changeBGon)
+ {
+ layerEnableDelay = 4;
+ layerEnable = layerSettings & value & ~changeBGon;
+ }
+ else
+ {
+ layerEnable = layerSettings & value;
+ //CPUUpdateTicks();
+ }
+
+ if (change && !(value & 0x80))
+ {
+ if (!(DISPSTAT & 1))
+ {
+ lcdTicks = 1008;
+ DISPSTAT &= 0xFFFC;
+ UPDATE_REG(0x04, DISPSTAT);
+ CPUCompareVCOUNT();
+ }
+ }
+ break;
+ }
+ case 0x04:
+ DISPSTAT = (value & 0xFF38) | (DISPSTAT & 7);
+ UPDATE_REG(0x04, DISPSTAT);
+ break;
+ case 0x06:
+ // not writable
+ break;
+ case 0x08:
+ BG0CNT = value & 0xDFCF;
+ UPDATE_REG(0x08, BG0CNT);
+ break;
+ case 0x0A:
+ BG1CNT = value & 0xDFCF;
+ UPDATE_REG(0x0A, BG1CNT);
+ break;
+ case 0x0C:
+ BG2CNT = value & 0xFFCF;
+ UPDATE_REG(0x0C, BG2CNT);
+ break;
+ case 0x0E:
+ BG3CNT = value & 0xFFCF;
+ UPDATE_REG(0x0E, BG3CNT);
+ break;
+ case 0x10:
+ BG0HOFS = value & 511;
+ UPDATE_REG(0x10, BG0HOFS);
+ break;
+ case 0x12:
+ BG0VOFS = value & 511;
+ UPDATE_REG(0x12, BG0VOFS);
+ break;
+ case 0x14:
+ BG1HOFS = value & 511;
+ UPDATE_REG(0x14, BG1HOFS);
+ break;
+ case 0x16:
+ BG1VOFS = value & 511;
+ UPDATE_REG(0x16, BG1VOFS);
+ break;
+ case 0x18:
+ BG2HOFS = value & 511;
+ UPDATE_REG(0x18, BG2HOFS);
+ break;
+ case 0x1A:
+ BG2VOFS = value & 511;
+ UPDATE_REG(0x1A, BG2VOFS);
+ break;
+ case 0x1C:
+ BG3HOFS = value & 511;
+ UPDATE_REG(0x1C, BG3HOFS);
+ break;
+ case 0x1E:
+ BG3VOFS = value & 511;
+ UPDATE_REG(0x1E, BG3VOFS);
+ break;
+ case 0x20:
+ BG2PA = value;
+ UPDATE_REG(0x20, BG2PA);
+ break;
+ case 0x22:
+ BG2PB = value;
+ UPDATE_REG(0x22, BG2PB);
+ break;
+ case 0x24:
+ BG2PC = value;
+ UPDATE_REG(0x24, BG2PC);
+ break;
+ case 0x26:
+ BG2PD = value;
+ UPDATE_REG(0x26, BG2PD);
+ break;
+ case 0x28:
+ BG2X_L = value;
+ UPDATE_REG(0x28, BG2X_L);
+ break;
+ case 0x2A:
+ BG2X_H = (value & 0xFFF);
+ UPDATE_REG(0x2A, BG2X_H);
+ break;
+ case 0x2C:
+ BG2Y_L = value;
+ UPDATE_REG(0x2C, BG2Y_L);
+ break;
+ case 0x2E:
+ BG2Y_H = value & 0xFFF;
+ UPDATE_REG(0x2E, BG2Y_H);
+ break;
+ case 0x30:
+ BG3PA = value;
+ UPDATE_REG(0x30, BG3PA);
+ break;
+ case 0x32:
+ BG3PB = value;
+ UPDATE_REG(0x32, BG3PB);
+ break;
+ case 0x34:
+ BG3PC = value;
+ UPDATE_REG(0x34, BG3PC);
+ break;
+ case 0x36:
+ BG3PD = value;
+ UPDATE_REG(0x36, BG3PD);
+ break;
+ case 0x38:
+ BG3X_L = value;
+ UPDATE_REG(0x38, BG3X_L);
+ break;
+ case 0x3A:
+ BG3X_H = value & 0xFFF;
+ UPDATE_REG(0x3A, BG3X_H);
+ break;
+ case 0x3C:
+ BG3Y_L = value;
+ UPDATE_REG(0x3C, BG3Y_L);
+ break;
+ case 0x3E:
+ BG3Y_H = value & 0xFFF;
+ UPDATE_REG(0x3E, BG3Y_H);
+ break;
+ case 0x40:
+ WIN0H = value;
+ UPDATE_REG(0x40, WIN0H);
+ break;
+ case 0x42:
+ WIN1H = value;
+ UPDATE_REG(0x42, WIN1H);
+ break;
+ case 0x44:
+ WIN0V = value;
+ UPDATE_REG(0x44, WIN0V);
+ break;
+ case 0x46:
+ WIN1V = value;
+ UPDATE_REG(0x46, WIN1V);
+ break;
+ case 0x48:
+ WININ = value & 0x3F3F;
+ UPDATE_REG(0x48, WININ);
+ break;
+ case 0x4A:
+ WINOUT = value & 0x3F3F;
+ UPDATE_REG(0x4A, WINOUT);
+ break;
+ case 0x4C:
+ MOSAIC = value;
+ UPDATE_REG(0x4C, MOSAIC);
+ break;
+ case 0x50:
+ BLDMOD = value & 0x3FFF;
+ UPDATE_REG(0x50, BLDMOD);
+ break;
+ case 0x52:
+ COLEV = value & 0x1F1F;
+ UPDATE_REG(0x52, COLEV);
+ break;
+ case 0x54:
+ COLY = value & 0x1F;
+ UPDATE_REG(0x54, COLY);
+ break;
+ case 0x60:
+ case 0x62:
+ case 0x64:
+ case 0x68:
+ case 0x6c:
+ case 0x70:
+ case 0x72:
+ case 0x74:
+ case 0x78:
+ case 0x7c:
+ case 0x80:
+ case 0x84:
+ soundEvent(address & 0xFF, static_cast<uint8_t>(value & 0xFF));
+ soundEvent((address & 0xFF) + 1, static_cast<uint8_t>(value >> 8));
+ break;
+ case 0x82:
+ case 0x88:
+ case 0xa0:
+ case 0xa2:
+ case 0xa4:
+ case 0xa6:
+ case 0x90:
+ case 0x92:
+ case 0x94:
+ case 0x96:
+ case 0x98:
+ case 0x9a:
+ case 0x9c:
+ case 0x9e:
+ soundEvent(address & 0xFF, value);
+ break;
+ case 0xB0:
+ DM0SAD_L = value;
+ UPDATE_REG(0xB0, DM0SAD_L);
+ break;
+ case 0xB2:
+ DM0SAD_H = value & 0x07FF;
+ UPDATE_REG(0xB2, DM0SAD_H);
+ break;
+ case 0xB4:
+ DM0DAD_L = value;
+ UPDATE_REG(0xB4, DM0DAD_L);
+ break;
+ case 0xB6:
+ DM0DAD_H = value & 0x07FF;
+ UPDATE_REG(0xB6, DM0DAD_H);
+ break;
+ case 0xB8:
+ DM0CNT_L = value & 0x3FFF;
+ UPDATE_REG(0xB8, 0);
+ break;
+ case 0xBA:
+ {
+ bool start = !!((DM0CNT_H ^ value) & 0x8000);
+ value &= 0xF7E0;
+
+ DM0CNT_H = value;
+ UPDATE_REG(0xBA, DM0CNT_H);
+
+ if (start && (value & 0x8000))
+ {
+ dma0Source = DM0SAD_L | (DM0SAD_H << 16);
+ dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
+ CPUCheckDMA(0, 1);
+ }
+ break;
+ }
+ case 0xBC:
+ DM1SAD_L = value;
+ UPDATE_REG(0xBC, DM1SAD_L);
+ break;
+ case 0xBE:
+ DM1SAD_H = value & 0x0FFF;
+ UPDATE_REG(0xBE, DM1SAD_H);
+ break;
+ case 0xC0:
+ DM1DAD_L = value;
+ UPDATE_REG(0xC0, DM1DAD_L);
+ break;
+ case 0xC2:
+ DM1DAD_H = value & 0x07FF;
+ UPDATE_REG(0xC2, DM1DAD_H);
+ break;
+ case 0xC4:
+ DM1CNT_L = value & 0x3FFF;
+ UPDATE_REG(0xC4, 0);
+ break;
+ case 0xC6:
+ {
+ bool start = !!((DM1CNT_H ^ value) & 0x8000);
+ value &= 0xF7E0;
+
+ DM1CNT_H = value;
+ UPDATE_REG(0xC6, DM1CNT_H);
+
+ if (start && (value & 0x8000))
+ {
+ dma1Source = DM1SAD_L | (DM1SAD_H << 16);
+ dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
+ CPUCheckDMA(0, 2);
+ }
+ break;
+ }
+ case 0xC8:
+ DM2SAD_L = value;
+ UPDATE_REG(0xC8, DM2SAD_L);
+ break;
+ case 0xCA:
+ DM2SAD_H = value & 0x0FFF;
+ UPDATE_REG(0xCA, DM2SAD_H);
+ break;
+ case 0xCC:
+ DM2DAD_L = value;
+ UPDATE_REG(0xCC, DM2DAD_L);
+ break;
+ case 0xCE:
+ DM2DAD_H = value & 0x07FF;
+ UPDATE_REG(0xCE, DM2DAD_H);
+ break;
+ case 0xD0:
+ DM2CNT_L = value & 0x3FFF;
+ UPDATE_REG(0xD0, 0);
+ break;
+ case 0xD2:
+ {
+ bool start = !!((DM2CNT_H ^ value) & 0x8000);
+ value &= 0xF7E0;
+
+ DM2CNT_H = value;
+ UPDATE_REG(0xD2, DM2CNT_H);
+
+ if (start && (value & 0x8000))
+ {
+ dma2Source = DM2SAD_L | (DM2SAD_H << 16);
+ dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
+ CPUCheckDMA(0, 4);
+ }
+ break;
+ }
+ case 0xD4:
+ DM3SAD_L = value;
+ UPDATE_REG(0xD4, DM3SAD_L);
+ break;
+ case 0xD6:
+ DM3SAD_H = value & 0x0FFF;
+ UPDATE_REG(0xD6, DM3SAD_H);
+ break;
+ case 0xD8:
+ DM3DAD_L = value;
+ UPDATE_REG(0xD8, DM3DAD_L);
+ break;
+ case 0xDA:
+ DM3DAD_H = value & 0x0FFF;
+ UPDATE_REG(0xDA, DM3DAD_H);
+ break;
+ case 0xDC:
+ DM3CNT_L = value;
+ UPDATE_REG(0xDC, 0);
+ break;
+ case 0xDE:
+ {
+ bool start = !!((DM3CNT_H ^ value) & 0x8000);
+ value &= 0xFFE0;
+
+ DM3CNT_H = value;
+ UPDATE_REG(0xDE, DM3CNT_H);
+
+ if (start && (value & 0x8000))
+ {
+ dma3Source = DM3SAD_L | (DM3SAD_H << 16);
+ dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
+ CPUCheckDMA(0, 8);
+ }
+ break;
+ }
+ case 0x100:
+ timer0Reload = value;
+ break;
+ case 0x102:
+ timer0Value = value;
+ timerOnOffDelay |= 1;
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ case 0x104:
+ timer1Reload = value;
+ break;
+ case 0x106:
+ timer1Value = value;
+ timerOnOffDelay |= 2;
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ case 0x108:
+ timer2Reload = value;
+ break;
+ case 0x10A:
+ timer2Value = value;
+ timerOnOffDelay |= 4;
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ case 0x10C:
+ timer3Reload = value;
+ break;
+ case 0x10E:
+ timer3Value = value;
+ timerOnOffDelay |= 8;
+ cpuNextEvent = cpuTotalTicks;
+ break;
+
+ case 0x130:
+ P1 |= value & 0x3FF;
+ UPDATE_REG(0x130, P1);
+ break;
+
+ case 0x132:
+ UPDATE_REG(0x132, value & 0xC3FF);
+ break;
+
+ case 0x200:
+ IE = value & 0x3FFF;
+ UPDATE_REG(0x200, IE);
+ if ((IME & 1) && (IF & IE) && armIrqEnable)
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ case 0x202:
+ IF ^= value & IF;
+ UPDATE_REG(0x202, IF);
+ break;
+ case 0x204:
+ memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3];
+
+ memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3];
+ memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = gamepakWaitState0[(value >> 4) & 1];
+
+ memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3];
+ memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = gamepakWaitState1[(value >> 7) & 1];
+
+ memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3];
+ memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = gamepakWaitState2[(value >> 10) & 1];
+
+ for (int i = 8; i < 15; ++i)
+ {
+ memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1;
+ memoryWaitSeq32[i] = memoryWaitSeq[i] * 2 + 1;
+ }
+
+ busPrefetchEnable = (value & 0x4000) == 0x4000;
+ busPrefetch = false;
+ busPrefetchCount = 0;
+ UPDATE_REG(0x204, value & 0x7FFF);
+
+ break;
+ case 0x208:
+ IME = value & 1;
+ UPDATE_REG(0x208, IME);
+ if ((IME & 1) && (IF & IE) && armIrqEnable)
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ case 0x300:
+ if (value)
+ value &= 0xFFFE;
+ UPDATE_REG(0x300, value);
+ break;
+ default:
+ UPDATE_REG(address & 0x3FE, value);
+ }
}
-void applyTimer ()
+void applyTimer()
{
- if (timerOnOffDelay & 1)
- {
- timer0ClockReload = TIMER_TICKS[timer0Value & 3];
- if(!timer0On && (timer0Value & 0x80)) {
- // reload the counter
- TM0D = timer0Reload;
- timer0Ticks = (0x10000 - TM0D) << timer0ClockReload;
- UPDATE_REG(0x100, TM0D);
- }
- timer0On = timer0Value & 0x80 ? true : false;
- TM0CNT = timer0Value & 0xC7;
- interp_rate();
- UPDATE_REG(0x102, TM0CNT);
- // CPUUpdateTicks();
- }
- if (timerOnOffDelay & 2)
- {
- timer1ClockReload = TIMER_TICKS[timer1Value & 3];
- if(!timer1On && (timer1Value & 0x80)) {
- // reload the counter
- TM1D = timer1Reload;
- timer1Ticks = (0x10000 - TM1D) << timer1ClockReload;
- UPDATE_REG(0x104, TM1D);
- }
- timer1On = timer1Value & 0x80 ? true : false;
- TM1CNT = timer1Value & 0xC7;
- interp_rate();
- UPDATE_REG(0x106, TM1CNT);
- }
- if (timerOnOffDelay & 4)
- {
- timer2ClockReload = TIMER_TICKS[timer2Value & 3];
- if(!timer2On && (timer2Value & 0x80)) {
- // reload the counter
- TM2D = timer2Reload;
- timer2Ticks = (0x10000 - TM2D) << timer2ClockReload;
- UPDATE_REG(0x108, TM2D);
- }
- timer2On = timer2Value & 0x80 ? true : false;
- TM2CNT = timer2Value & 0xC7;
- UPDATE_REG(0x10A, TM2CNT);
- }
- if (timerOnOffDelay & 8)
- {
- timer3ClockReload = TIMER_TICKS[timer3Value & 3];
- if(!timer3On && (timer3Value & 0x80)) {
- // reload the counter
- TM3D = timer3Reload;
- timer3Ticks = (0x10000 - TM3D) << timer3ClockReload;
- UPDATE_REG(0x10C, TM3D);
- }
- timer3On = timer3Value & 0x80 ? true : false;
- TM3CNT = timer3Value & 0xC7;
- UPDATE_REG(0x10E, TM3CNT);
- }
- cpuNextEvent = CPUUpdateTicks();
- timerOnOffDelay = 0;
+ if (timerOnOffDelay & 1)
+ {
+ timer0ClockReload = TIMER_TICKS[timer0Value & 3];
+ if (!timer0On && (timer0Value & 0x80))
+ {
+ // reload the counter
+ TM0D = timer0Reload;
+ timer0Ticks = (0x10000 - TM0D) << timer0ClockReload;
+ UPDATE_REG(0x100, TM0D);
+ }
+ timer0On = !!(timer0Value & 0x80);
+ TM0CNT = timer0Value & 0xC7;
+ UPDATE_REG(0x102, TM0CNT);
+ //CPUUpdateTicks();
+ }
+ if (timerOnOffDelay & 2)
+ {
+ timer1ClockReload = TIMER_TICKS[timer1Value & 3];
+ if (!timer1On && (timer1Value & 0x80))
+ {
+ // reload the counter
+ TM1D = timer1Reload;
+ timer1Ticks = (0x10000 - TM1D) << timer1ClockReload;
+ UPDATE_REG(0x104, TM1D);
+ }
+ timer1On = !!(timer1Value & 0x80);
+ TM1CNT = timer1Value & 0xC7;
+ UPDATE_REG(0x106, TM1CNT);
+ }
+ if (timerOnOffDelay & 4)
+ {
+ timer2ClockReload = TIMER_TICKS[timer2Value & 3];
+ if (!timer2On && (timer2Value & 0x80))
+ {
+ // reload the counter
+ TM2D = timer2Reload;
+ timer2Ticks = (0x10000 - TM2D) << timer2ClockReload;
+ UPDATE_REG(0x108, TM2D);
+ }
+ timer2On = !(timer2Value & 0x80);
+ TM2CNT = timer2Value & 0xC7;
+ UPDATE_REG(0x10A, TM2CNT);
+ }
+ if (timerOnOffDelay & 8)
+ {
+ timer3ClockReload = TIMER_TICKS[timer3Value & 3];
+ if (!timer3On && (timer3Value & 0x80))
+ {
+ // reload the counter
+ TM3D = timer3Reload;
+ timer3Ticks = (0x10000 - TM3D) << timer3ClockReload;
+ UPDATE_REG(0x10C, TM3D);
+ }
+ timer3On = !!(timer3Value & 0x80);
+ TM3CNT = timer3Value & 0xC7;
+ UPDATE_REG(0x10E, TM3CNT);
+ }
+ cpuNextEvent = CPUUpdateTicks();
+ timerOnOffDelay = 0;
}
uint8_t cpuBitsSet[256];
uint8_t cpuLowestBitSet[256];
-void CPUInit(const char *biosFileName, bool useBiosFile)
+void CPUInit()
{
#ifdef WORDS_BIGENDIAN
- if(!cpuBiosSwapped) {
- for(unsigned int i = 0; i < sizeof(myROM)/4; i++) {
- WRITE32LE(&myROM[i], myROM[i]);
- }
- cpuBiosSwapped = true;
- }
+ if (!cpuBiosSwapped)
+ {
+ for (unsigned i = 0; i < sizeof(myROM) / 4; ++i)
+ WRITE32LE(&myROM[i], myROM[i]);
+ cpuBiosSwapped = true;
+ }
#endif
- gbaSaveType = 0;
- //eepromInUse = 0;
- saveType = 0;
- useBios = false;
-
- /*if(useBiosFile) {
- int size = 0x4000;
- if(utilLoad(biosFileName,
- CPUIsGBABios,
- bios,
- size)) {
- if(size == 0x4000)
- useBios = true;
- else
- systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BIOS file size"));
- }
- }*/
-
- if(!useBios) {
- memcpy(bios, myROM, sizeof(myROM));
- }
-
- int i = 0;
-
- biosProtected[0] = 0x00;
- biosProtected[1] = 0xf0;
- biosProtected[2] = 0x29;
- biosProtected[3] = 0xe1;
-
- for(i = 0; i < 256; i++) {
- int count = 0;
- int j;
- for(j = 0; j < 8; j++)
- if(i & (1 << j))
- count++;
- cpuBitsSet[i] = count;
-
- for(j = 0; j < 8; j++)
- if(i & (1 << j))
- break;
- cpuLowestBitSet[i] = j;
- }
-
- for(i = 0; i < 0x400; i++)
- ioReadable[i] = true;
- for(i = 0x10; i < 0x48; i++)
- ioReadable[i] = false;
- for(i = 0x4c; i < 0x50; i++)
- ioReadable[i] = false;
- for(i = 0x54; i < 0x60; i++)
- ioReadable[i] = false;
- for(i = 0x8c; i < 0x90; i++)
- ioReadable[i] = false;
- for(i = 0xa0; i < 0xb8; i++)
- ioReadable[i] = false;
- for(i = 0xbc; i < 0xc4; i++)
- ioReadable[i] = false;
- for(i = 0xc8; i < 0xd0; i++)
- ioReadable[i] = false;
- for(i = 0xd4; i < 0xdc; i++)
- ioReadable[i] = false;
- for(i = 0xe0; i < 0x100; i++)
- ioReadable[i] = false;
- for(i = 0x110; i < 0x120; i++)
- ioReadable[i] = false;
- for(i = 0x12c; i < 0x130; i++)
- ioReadable[i] = false;
- for(i = 0x138; i < 0x140; i++)
- ioReadable[i] = false;
- for(i = 0x144; i < 0x150; i++)
- ioReadable[i] = false;
- for(i = 0x15c; i < 0x200; i++)
- ioReadable[i] = false;
- for(i = 0x20c; i < 0x300; i++)
- ioReadable[i] = false;
- for(i = 0x304; i < 0x400; i++)
- ioReadable[i] = false;
-
- if(romSize < 0x1fe2000) {
- *((uint16_t *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA
- *((uint16_t *)&rom[0x1fe209e]) = 0x4770; // BX LR
- } else {
- //agbPrintEnable(false);
- }
+ memcpy(&bios[0], myROM, sizeof(myROM));
+
+ biosProtected[0] = 0x00;
+ biosProtected[1] = 0xf0;
+ biosProtected[2] = 0x29;
+ biosProtected[3] = 0xe1;
+
+ for (int i = 0; i < 256; ++i)
+ {
+ int count = 0;
+ int j;
+ for (j = 0; j < 8; ++j)
+ if (i & (1 << j))
+ ++count;
+ cpuBitsSet[i] = count;
+
+ for (j = 0; j < 8; ++j)
+ if (i & (1 << j))
+ break;
+ cpuLowestBitSet[i] = j;
+ }
+
+ std::fill(&ioReadable[0], &ioReadable[0x304], true);
+ std::fill(&ioReadable[0x10], &ioReadable[0x48], false);
+ std::fill(&ioReadable[0x4c], &ioReadable[0x50], false);
+ std::fill(&ioReadable[0x54], &ioReadable[0x60], false);
+ std::fill(&ioReadable[0x8c], &ioReadable[0x90], false);
+ std::fill(&ioReadable[0xa0], &ioReadable[0xb8], false);
+ std::fill(&ioReadable[0xbc], &ioReadable[0xc4], false);
+ std::fill(&ioReadable[0xc8], &ioReadable[0xd0], false);
+ std::fill(&ioReadable[0xd4], &ioReadable[0xdc], false);
+ std::fill(&ioReadable[0xe0], &ioReadable[0x100], false);
+ std::fill(&ioReadable[0x110], &ioReadable[0x120], false);
+ std::fill(&ioReadable[0x12c], &ioReadable[0x130], false);
+ std::fill(&ioReadable[0x138], &ioReadable[0x140], false);
+ std::fill(&ioReadable[0x144], &ioReadable[0x150], false);
+ std::fill(&ioReadable[0x15c], &ioReadable[0x200], false);
+ std::fill(&ioReadable[0x20c], &ioReadable[0x300], false);
+ std::fill(&ioReadable[0x304], &ioReadable[0x400], false);
+
+ if (romSize < 0x1fe2000)
+ {
+ *reinterpret_cast<uint16_t *>(&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA
+ *reinterpret_cast<uint16_t *>(&rom[0x1fe209e]) = 0x4770; // BX LR
+ }
}
void CPUReset()
{
- /*if(gbaSaveType == 0) {
- if(eepromInUse)
- gbaSaveType = 3;
- else
- switch(saveType) {
- case 1:
- gbaSaveType = 1;
- break;
- case 2:
- gbaSaveType = 2;
- break;
- }
- }
- rtcReset();*/
- // clean registers
- memset(®[0], 0, sizeof(reg));
- // clean OAM
- memset(oam, 0, 0x400);
- // clean palette
- memset(paletteRAM, 0, 0x400);
- // clean picture
- memset(pix, 0, 4*160*240);
- // clean vram
- memset(vram, 0, 0x20000);
- // clean io memory
- memset(ioMem, 0, 0x400);
-
- DISPCNT = 0x0080;
- DISPSTAT = 0x0000;
- VCOUNT = (useBios && !skipBios) ? 0 :0x007E;
- BG0CNT = 0x0000;
- BG1CNT = 0x0000;
- BG2CNT = 0x0000;
- BG3CNT = 0x0000;
- BG0HOFS = 0x0000;
- BG0VOFS = 0x0000;
- BG1HOFS = 0x0000;
- BG1VOFS = 0x0000;
- BG2HOFS = 0x0000;
- BG2VOFS = 0x0000;
- BG3HOFS = 0x0000;
- BG3VOFS = 0x0000;
- BG2PA = 0x0100;
- BG2PB = 0x0000;
- BG2PC = 0x0000;
- BG2PD = 0x0100;
- BG2X_L = 0x0000;
- BG2X_H = 0x0000;
- BG2Y_L = 0x0000;
- BG2Y_H = 0x0000;
- BG3PA = 0x0100;
- BG3PB = 0x0000;
- BG3PC = 0x0000;
- BG3PD = 0x0100;
- BG3X_L = 0x0000;
- BG3X_H = 0x0000;
- BG3Y_L = 0x0000;
- BG3Y_H = 0x0000;
- WIN0H = 0x0000;
- WIN1H = 0x0000;
- WIN0V = 0x0000;
- WIN1V = 0x0000;
- WININ = 0x0000;
- WINOUT = 0x0000;
- MOSAIC = 0x0000;
- BLDMOD = 0x0000;
- COLEV = 0x0000;
- COLY = 0x0000;
- DM0SAD_L = 0x0000;
- DM0SAD_H = 0x0000;
- DM0DAD_L = 0x0000;
- DM0DAD_H = 0x0000;
- DM0CNT_L = 0x0000;
- DM0CNT_H = 0x0000;
- DM1SAD_L = 0x0000;
- DM1SAD_H = 0x0000;
- DM1DAD_L = 0x0000;
- DM1DAD_H = 0x0000;
- DM1CNT_L = 0x0000;
- DM1CNT_H = 0x0000;
- DM2SAD_L = 0x0000;
- DM2SAD_H = 0x0000;
- DM2DAD_L = 0x0000;
- DM2DAD_H = 0x0000;
- DM2CNT_L = 0x0000;
- DM2CNT_H = 0x0000;
- DM3SAD_L = 0x0000;
- DM3SAD_H = 0x0000;
- DM3DAD_L = 0x0000;
- DM3DAD_H = 0x0000;
- DM3CNT_L = 0x0000;
- DM3CNT_H = 0x0000;
- TM0D = 0x0000;
- TM0CNT = 0x0000;
- TM1D = 0x0000;
- TM1CNT = 0x0000;
- TM2D = 0x0000;
- TM2CNT = 0x0000;
- TM3D = 0x0000;
- TM3CNT = 0x0000;
- P1 = 0x03FF;
- IE = 0x0000;
- IF = 0x0000;
- IME = 0x0000;
-
- armMode = 0x1F;
-
- if(cpuIsMultiBoot) {
- reg[13].I = 0x03007F00;
- reg[15].I = 0x02000000;
- reg[16].I = 0x00000000;
- reg[R13_IRQ].I = 0x03007FA0;
- reg[R13_SVC].I = 0x03007FE0;
- armIrqEnable = true;
- } else {
- if(useBios && !skipBios) {
- reg[15].I = 0x00000000;
- armMode = 0x13;
- armIrqEnable = false;
- } else {
- reg[13].I = 0x03007F00;
- reg[15].I = 0x08000000;
- reg[16].I = 0x00000000;
- reg[R13_IRQ].I = 0x03007FA0;
- reg[R13_SVC].I = 0x03007FE0;
- armIrqEnable = true;
- }
- }
- armState = true;
- C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
- UPDATE_REG(0x00, DISPCNT);
- UPDATE_REG(0x06, VCOUNT);
- UPDATE_REG(0x20, BG2PA);
- UPDATE_REG(0x26, BG2PD);
- UPDATE_REG(0x30, BG3PA);
- UPDATE_REG(0x36, BG3PD);
- UPDATE_REG(0x130, P1);
- UPDATE_REG(0x88, 0x200);
-
- // disable FIQ
- reg[16].I |= 0x40;
-
- CPUUpdateCPSR();
-
- armNextPC = reg[15].I;
- reg[15].I += 4;
-
- // reset internal state
- holdState = false;
- holdType = 0;
-
- biosProtected[0] = 0x00;
- biosProtected[1] = 0xf0;
- biosProtected[2] = 0x29;
- biosProtected[3] = 0xe1;
-
- lcdTicks = (useBios && !skipBios) ? 1008 : 208;
- timer0On = false;
- timer0Ticks = 0;
- timer0Reload = 0;
- timer0ClockReload = 0;
- timer1On = false;
- timer1Ticks = 0;
- timer1Reload = 0;
- timer1ClockReload = 0;
- timer2On = false;
- timer2Ticks = 0;
- timer2Reload = 0;
- timer2ClockReload = 0;
- timer3On = false;
- timer3Ticks = 0;
- timer3Reload = 0;
- timer3ClockReload = 0;
- dma0Source = 0;
- dma0Dest = 0;
- dma1Source = 0;
- dma1Dest = 0;
- dma2Source = 0;
- dma2Dest = 0;
- dma3Source = 0;
- dma3Dest = 0;
- //cpuSaveGameFunc = flashSaveDecide;
- //renderLine = mode0RenderLine;
- fxOn = false;
- windowOn = false;
- frameCount = 0;
- saveType = 0;
- layerEnable = DISPCNT & layerSettings;
-
- //CPUUpdateRenderBuffers(true);
-
- for(int i = 0; i < 256; i++) {
- map[i].address = (uint8_t *)&dummyAddress;
- map[i].mask = 0;
- }
-
- map[0].address = bios;
- map[0].mask = 0x3FFF;
- map[2].address = workRAM;
- map[2].mask = 0x3FFFF;
- map[3].address = internalRAM;
- map[3].mask = 0x7FFF;
- map[4].address = ioMem;
- map[4].mask = 0x3FF;
- map[5].address = paletteRAM;
- map[5].mask = 0x3FF;
- map[6].address = vram;
- map[6].mask = 0x1FFFF;
- map[7].address = oam;
- map[7].mask = 0x3FF;
- map[8].address = rom;
- map[8].mask = 0x1FFFFFF;
- map[9].address = rom;
- map[9].mask = 0x1FFFFFF;
- map[10].address = rom;
- map[10].mask = 0x1FFFFFF;
- map[12].address = rom;
- map[12].mask = 0x1FFFFFF;
- map[14].address = /*flashSaveMemory*/0;
- map[14].mask = 0xFFFF;
-
- //eepromReset();
- //flashReset();
-
- soundReset();
-
- //CPUUpdateWindow0();
- //CPUUpdateWindow1();
-
- // make sure registers are correctly initialized if not using BIOS
- if(!useBios) {
- if(cpuIsMultiBoot)
- BIOS_RegisterRamReset(0xfe);
- else
- BIOS_RegisterRamReset(0xff);
- } else {
- if(cpuIsMultiBoot)
- BIOS_RegisterRamReset(0xfe);
- }
-
- /*switch(cpuSaveType) {
- case 0: // automatic
- cpuSramEnabled = true;
- cpuFlashEnabled = true;
- cpuEEPROMEnabled = true;
- cpuEEPROMSensorEnabled = false;
- saveType = gbaSaveType = 0;
- break;
- case 1: // EEPROM
- cpuSramEnabled = false;
- cpuFlashEnabled = false;
- cpuEEPROMEnabled = true;
- cpuEEPROMSensorEnabled = false;
- saveType = gbaSaveType = 3;
- // EEPROM usage is automatically detected
- break;
- case 2: // SRAM
- cpuSramEnabled = true;
- cpuFlashEnabled = false;
- cpuEEPROMEnabled = false;
- cpuEEPROMSensorEnabled = false;
- cpuSaveGameFunc = sramDelayedWrite; // to insure we detect the write
- saveType = gbaSaveType = 1;
- break;
- case 3: // FLASH
- cpuSramEnabled = false;
- cpuFlashEnabled = true;
- cpuEEPROMEnabled = false;
- cpuEEPROMSensorEnabled = false;
- cpuSaveGameFunc = flashDelayedWrite; // to insure we detect the write
- saveType = gbaSaveType = 2;
- break;
- case 4: // EEPROM+Sensor
- cpuSramEnabled = false;
- cpuFlashEnabled = false;
- cpuEEPROMEnabled = true;
- cpuEEPROMSensorEnabled = true;
- // EEPROM usage is automatically detected
- saveType = gbaSaveType = 3;
- break;
- case 5: // NONE
- cpuSramEnabled = false;
- cpuFlashEnabled = false;
- cpuEEPROMEnabled = false;
- cpuEEPROMSensorEnabled = false;
- // no save at all
- saveType = gbaSaveType = 5;
- break;
- }*/
-
- ARM_PREFETCH;
-
- //systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
-
- lastTime = /*systemGetClock()*/0;
-
- SWITicks = 0;
+ // clean registers
+ memset(®[0], 0, sizeof(reg));
+ // clean OAM
+ memset(&oam[0], 0, 0x400);
+ // clean palette
+ memset(&paletteRAM[0], 0, 0x400);
+ // clean vram
+ memset(&vram[0], 0, 0x20000);
+ // clean io memory
+ memset(&ioMem[0], 0, 0x400);
+
+ DISPCNT = 0x0080;
+ DISPSTAT = 0x0000;
+ VCOUNT = 0x007E;
+ BG0CNT = 0x0000;
+ BG1CNT = 0x0000;
+ BG2CNT = 0x0000;
+ BG3CNT = 0x0000;
+ BG0HOFS = 0x0000;
+ BG0VOFS = 0x0000;
+ BG1HOFS = 0x0000;
+ BG1VOFS = 0x0000;
+ BG2HOFS = 0x0000;
+ BG2VOFS = 0x0000;
+ BG3HOFS = 0x0000;
+ BG3VOFS = 0x0000;
+ BG2PA = 0x0100;
+ BG2PB = 0x0000;
+ BG2PC = 0x0000;
+ BG2PD = 0x0100;
+ BG2X_L = 0x0000;
+ BG2X_H = 0x0000;
+ BG2Y_L = 0x0000;
+ BG2Y_H = 0x0000;
+ BG3PA = 0x0100;
+ BG3PB = 0x0000;
+ BG3PC = 0x0000;
+ BG3PD = 0x0100;
+ BG3X_L = 0x0000;
+ BG3X_H = 0x0000;
+ BG3Y_L = 0x0000;
+ BG3Y_H = 0x0000;
+ WIN0H = 0x0000;
+ WIN1H = 0x0000;
+ WIN0V = 0x0000;
+ WIN1V = 0x0000;
+ WININ = 0x0000;
+ WINOUT = 0x0000;
+ MOSAIC = 0x0000;
+ BLDMOD = 0x0000;
+ COLEV = 0x0000;
+ COLY = 0x0000;
+ DM0SAD_L = 0x0000;
+ DM0SAD_H = 0x0000;
+ DM0DAD_L = 0x0000;
+ DM0DAD_H = 0x0000;
+ DM0CNT_L = 0x0000;
+ DM0CNT_H = 0x0000;
+ DM1SAD_L = 0x0000;
+ DM1SAD_H = 0x0000;
+ DM1DAD_L = 0x0000;
+ DM1DAD_H = 0x0000;
+ DM1CNT_L = 0x0000;
+ DM1CNT_H = 0x0000;
+ DM2SAD_L = 0x0000;
+ DM2SAD_H = 0x0000;
+ DM2DAD_L = 0x0000;
+ DM2DAD_H = 0x0000;
+ DM2CNT_L = 0x0000;
+ DM2CNT_H = 0x0000;
+ DM3SAD_L = 0x0000;
+ DM3SAD_H = 0x0000;
+ DM3DAD_L = 0x0000;
+ DM3DAD_H = 0x0000;
+ DM3CNT_L = 0x0000;
+ DM3CNT_H = 0x0000;
+ TM0D = 0x0000;
+ TM0CNT = 0x0000;
+ TM1D = 0x0000;
+ TM1CNT = 0x0000;
+ TM2D = 0x0000;
+ TM2CNT = 0x0000;
+ TM3D = 0x0000;
+ TM3CNT = 0x0000;
+ P1 = 0x03FF;
+ IE = 0x0000;
+ IF = 0x0000;
+ IME = 0x0000;
+
+ armMode = 0x1F;
+
+ reg[13].I = 0x03007F00;
+ reg[15].I = cpuIsMultiBoot ? 0x02000000 : 0x08000000;
+ reg[16].I = 0x00000000;
+ reg[R13_IRQ].I = 0x03007FA0;
+ reg[R13_SVC].I = 0x03007FE0;
+ armIrqEnable = true;
+ armState = true;
+ C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
+ UPDATE_REG(0x00, DISPCNT);
+ UPDATE_REG(0x06, VCOUNT);
+ UPDATE_REG(0x20, BG2PA);
+ UPDATE_REG(0x26, BG2PD);
+ UPDATE_REG(0x30, BG3PA);
+ UPDATE_REG(0x36, BG3PD);
+ UPDATE_REG(0x130, P1);
+ UPDATE_REG(0x88, 0x200);
+
+ // disable FIQ
+ reg[16].I |= 0x40;
+
+ CPUUpdateCPSR();
+
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+
+ // reset internal state
+ holdState = false;
+ holdType = 0;
+
+ biosProtected[0] = 0x00;
+ biosProtected[1] = 0xf0;
+ biosProtected[2] = 0x29;
+ biosProtected[3] = 0xe1;
+
+ lcdTicks = 208;
+ timer0On = false;
+ timer0Ticks = 0;
+ timer0Reload = 0;
+ timer0ClockReload = 0;
+ timer1On = false;
+ timer1Ticks = 0;
+ timer1Reload = 0;
+ timer1ClockReload = 0;
+ timer2On = false;
+ timer2Ticks = 0;
+ timer2Reload = 0;
+ timer2ClockReload = 0;
+ timer3On = false;
+ timer3Ticks = 0;
+ timer3Reload = 0;
+ timer3ClockReload = 0;
+ dma0Source = 0;
+ dma0Dest = 0;
+ dma1Source = 0;
+ dma1Dest = 0;
+ dma2Source = 0;
+ dma2Dest = 0;
+ dma3Source = 0;
+ dma3Dest = 0;
+ layerEnable = DISPCNT & layerSettings;
+
+ for (int i = 0; i < 256; ++i)
+ {
+ map[i].address = reinterpret_cast<uint8_t *>(&dummyAddress);
+ map[i].mask = 0;
+ }
+
+ map[0].address = &bios[0];
+ map[0].mask = 0x3FFF;
+ map[2].address = &workRAM[0];
+ map[2].mask = 0x3FFFF;
+ map[3].address = &internalRAM[0];
+ map[3].mask = 0x7FFF;
+ map[4].address = ioMem;
+ map[4].mask = 0x3FF;
+ map[5].address = &paletteRAM[0];
+ map[5].mask = 0x3FF;
+ map[6].address = &vram[0];
+ map[6].mask = 0x1FFFF;
+ map[7].address = &oam[0];
+ map[7].mask = 0x3FF;
+ map[8].address = &rom[0];
+ map[8].mask = 0x1FFFFFF;
+ map[9].address = &rom[0];
+ map[9].mask = 0x1FFFFFF;
+ map[10].address = &rom[0];
+ map[10].mask = 0x1FFFFFF;
+ map[12].address = &rom[0];
+ map[12].mask = 0x1FFFFFF;
+
+ soundReset();
+
+ // make sure registers are correctly initialized if not using BIOS
+ BIOS_RegisterRamReset(cpuIsMultiBoot ? 0xfe : 0xff);
+
+ ARM_PREFETCH();
+
+ SWITicks = 0;
}
void CPUInterrupt()
{
- uint32_t PC = reg[15].I;
- bool savedState = armState;
- CPUSwitchMode(0x12, true, false);
- reg[14].I = PC;
- if(!savedState)
- reg[14].I += 2;
- reg[15].I = 0x18;
- armState = true;
- armIrqEnable = false;
-
- armNextPC = reg[15].I;
- reg[15].I += 4;
- ARM_PREFETCH;
-
- // if(!holdState)
- biosProtected[0] = 0x02;
- biosProtected[1] = 0xc0;
- biosProtected[2] = 0x5e;
- biosProtected[3] = 0xe5;
+ uint32_t PC = reg[15].I;
+ bool savedState = armState;
+ CPUSwitchMode(0x12, true, false);
+ reg[14].I = PC;
+ if (!savedState)
+ reg[14].I += 2;
+ reg[15].I = 0x18;
+ armState = true;
+ armIrqEnable = false;
+
+ armNextPC = reg[15].I;
+ reg[15].I += 4;
+ ARM_PREFETCH();
+
+ //if(!holdState)
+ biosProtected[0] = 0x02;
+ biosProtected[1] = 0xc0;
+ biosProtected[2] = 0x5e;
+ biosProtected[3] = 0xe5;
}
void CPULoop(int ticks)
{
- int clockTicks;
- int timerOverflow = 0;
- // variable used by the CPU core
- cpuTotalTicks = 0;
-
- // shuffle2: what's the purpose?
- /*if(gba_link_enabled)
- cpuNextEvent = 1;*/
-
- cpuBreakLoop = false;
- cpuNextEvent = CPUUpdateTicks();
- if(cpuNextEvent > ticks)
- cpuNextEvent = ticks;
-
-
- for(;;) {
-#ifndef FINAL_VERSION
- if(systemDebug) {
- if(systemDebug >= 10 && !holdState) {
- CPUUpdateCPSR();
-#ifdef BKPT_SUPPORT
- if (debugger_last)
- {
- winlog("R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n",
- oldreg[0], oldreg[1], oldreg[2], oldreg[3], oldreg[4], oldreg[5],
- oldreg[6], oldreg[7], oldreg[8], oldreg[9], oldreg[10], oldreg[11],
- oldreg[12], oldreg[13], oldreg[14], oldreg[15], oldreg[16],
- oldreg[17]);
- }
-#endif
- winlog("R00=%08x R01=%08x R02=%08x R03=%08x R04=%08x R05=%08x R06=%08x R07=%08x R08=%08x R09=%08x R10=%08x R11=%08x R12=%08x R13=%08x R14=%08x R15=%08x R16=%08x R17=%08x\n",
- reg[0].I, reg[1].I, reg[2].I, reg[3].I, reg[4].I, reg[5].I,
- reg[6].I, reg[7].I, reg[8].I, reg[9].I, reg[10].I, reg[11].I,
- reg[12].I, reg[13].I, reg[14].I, reg[15].I, reg[16].I,
- reg[17].I);
- } else if(!holdState) {
- winlog("PC=%08x\n", armNextPC);
- }
- }
-#endif /* FINAL_VERSION */
-
- if(!holdState && !SWITicks) {
- if(armState) {
- if (!armExecute())
- return;
- } else {
- if (!thumbExecute())
- return;
- }
- clockTicks = 0;
- } else
- clockTicks = CPUUpdateTicks();
-
- cpuTotalTicks += clockTicks;
-
-
- if(cpuTotalTicks >= cpuNextEvent) {
- int remainingTicks = cpuTotalTicks - cpuNextEvent;
-
- if (SWITicks)
- {
- SWITicks-=clockTicks;
- if (SWITicks<0)
- SWITicks = 0;
- }
-
- clockTicks = cpuNextEvent;
- cpuTotalTicks = 0;
-
- updateLoop:
-
- if (IRQTicks)
- {
- IRQTicks -= clockTicks;
- if (IRQTicks<0)
- IRQTicks = 0;
- }
-
- lcdTicks -= clockTicks;
-
-
- if(lcdTicks <= 0) {
- if(DISPSTAT & 1) { // V-BLANK
- // if in V-Blank mode, keep computing...
- if(DISPSTAT & 2) {
- lcdTicks += 1008;
- VCOUNT++;
- UPDATE_REG(0x06, VCOUNT);
- DISPSTAT &= 0xFFFD;
- UPDATE_REG(0x04, DISPSTAT);
- CPUCompareVCOUNT();
- } else {
- lcdTicks += 224;
- DISPSTAT |= 2;
- UPDATE_REG(0x04, DISPSTAT);
- if(DISPSTAT & 16) {
- IF |= 2;
- UPDATE_REG(0x202, IF);
- }
- }
-
- if(VCOUNT >= 228) { //Reaching last line
- DISPSTAT &= 0xFFFC;
- UPDATE_REG(0x04, DISPSTAT);
- VCOUNT = 0;
- UPDATE_REG(0x06, VCOUNT);
- CPUCompareVCOUNT();
- }
- } else {
- /*int framesToSkip = *//*systemFrameSkip*//*0;
- if(speedup)
- framesToSkip = 9;*/ // try 6 FPS during speedup
-
- if(DISPSTAT & 2) {
- // if in H-Blank, leave it and move to drawing mode
- VCOUNT++;
- UPDATE_REG(0x06, VCOUNT);
-
- lcdTicks += 1008;
- DISPSTAT &= 0xFFFD;
- if(VCOUNT == 160) {
- count++;
- //systemFrame();
-
- /*if((count % 10) == 0) {
- //system10Frames(60);
- }*/
- if(count == 60) {
- /*u32 time = *//*systemGetClock()*//*0;
- if(time != lastTime) {
- //u32 t = 100000/(time - lastTime);
- //systemShowSpeed(t);
- } else
- //systemShowSpeed(0);
- lastTime = time;*/
- count = 0;
- }
- //u32 joy = 0;
- // update joystick information
- /*if(systemReadJoypads())
- // read default joystick
- joy = systemReadJoypad(-1);*/
- //P1 = 0x03FF ^ (joy & 0x3FF);
- /*if(cpuEEPROMSensorEnabled)
- systemUpdateMotionSensor();*/
- /*UPDATE_REG(0x130, P1);
- u16 P1CNT = READ16LE(((u16 *)&ioMem[0x132]));
- // this seems wrong, but there are cases where the game
- // can enter the stop state without requesting an IRQ from
- // the joypad.
- if((P1CNT & 0x4000) || stopState) {
- u16 p1 = (0x3FF ^ P1) & 0x3FF;
- if(P1CNT & 0x8000) {
- if(p1 == (P1CNT & 0x3FF)) {
- IF |= 0x1000;
- UPDATE_REG(0x202, IF);
- }
- } else {
- if(p1 & P1CNT) {
- IF |= 0x1000;
- UPDATE_REG(0x202, IF);
- }
- }
- }
-
- u32 ext = (joy >> 10);*/
- // If no (m) code is enabled, apply the cheats at each LCDline
- /*if((cheatsEnabled) && (mastercode==0))
- remainingTicks += cheatsCheckKeys(P1^0x3FF, ext);*/
- /*speedup = (ext & 1) ? true : false;
- capture = (ext & 2) ? true : false;
-
- if(capture && !capturePrevious) {
- captureNumber++;
- //systemScreenCapture(captureNumber);
- }
- capturePrevious = capture;*/
-
- DISPSTAT |= 1;
- DISPSTAT &= 0xFFFD;
- UPDATE_REG(0x04, DISPSTAT);
- if(DISPSTAT & 0x0008) {
- IF |= 1;
- UPDATE_REG(0x202, IF);
- }
- CPUCheckDMA(1, 0x0f);
- /*if(frameCount >= framesToSkip) {
- //systemDrawScreen();
- frameCount = 0;
- } else*/
- frameCount++;
- /*if(systemPauseOnFrame())
- ticks = 0;*/
- }
-
- UPDATE_REG(0x04, DISPSTAT);
- CPUCompareVCOUNT();
-
- } else {
- /*if(frameCount >= framesToSkip)
- {*/
- /*(*renderLine)();
- switch(systemColorDepth) {
- case 16:
- {
- u16 *dest = (u16 *)pix + 242 * (VCOUNT+1);
- for(int x = 0; x < 240;) {
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
-
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
-
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
-
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- *dest++ = systemColorMap16[lineMix[x++]&0xFFFF];
- }
- // for filters that read past the screen
- *dest++ = 0;
- }
- break;
- case 24:
- {
- u8 *dest = (u8 *)pix + 240 * VCOUNT * 3;
- for(int x = 0; x < 240;) {
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
-
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
-
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
-
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- *((u32 *)dest) = systemColorMap32[lineMix[x++] & 0xFFFF];
- dest += 3;
- }
- }
- break;
- case 32:
- {
- u32 *dest = (u32 *)pix + 241 * (VCOUNT+1);
- for(int x = 0; x < 240; ) {
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
-
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
-
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
-
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- *dest++ = systemColorMap32[lineMix[x++] & 0xFFFF];
- }
- }
- break;
- }*/
- /*}*/
- // entering H-Blank
- DISPSTAT |= 2;
- UPDATE_REG(0x04, DISPSTAT);
- lcdTicks += 224;
- CPUCheckDMA(2, 0x0f);
- if(DISPSTAT & 16) {
- IF |= 2;
- UPDATE_REG(0x202, IF);
- }
- }
- }
- }
-
- // we shouldn't be doing sound in stop state, but we loose synchronization
- // if sound is disabled, so in stop state, soundTick will just produce
- // mute sound
- soundTicks -= clockTicks;
- if(soundTicks <= 0) {
- psoundTickfn();
- soundTicks += SOUND_CLOCK_TICKS;
- }
-
- if(!stopState) {
- if(timer0On) {
- timer0Ticks -= clockTicks;
- if(timer0Ticks <= 0) {
- timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload;
- timerOverflow |= 1;
- soundTimerOverflow(0);
- if(TM0CNT & 0x40) {
- IF |= 0x08;
- UPDATE_REG(0x202, IF);
- }
- }
- TM0D = 0xFFFF - (timer0Ticks >> timer0ClockReload);
- UPDATE_REG(0x100, TM0D);
- }
-
- if(timer1On) {
- if(TM1CNT & 4) {
- if(timerOverflow & 1) {
- TM1D++;
- if(TM1D == 0) {
- TM1D += timer1Reload;
- timerOverflow |= 2;
- soundTimerOverflow(1);
- if(TM1CNT & 0x40) {
- IF |= 0x10;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x104, TM1D);
- }
- } else {
- timer1Ticks -= clockTicks;
- if(timer1Ticks <= 0) {
- timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload;
- timerOverflow |= 2;
- soundTimerOverflow(1);
- if(TM1CNT & 0x40) {
- IF |= 0x10;
- UPDATE_REG(0x202, IF);
- }
- }
- TM1D = 0xFFFF - (timer1Ticks >> timer1ClockReload);
- UPDATE_REG(0x104, TM1D);
- }
- }
-
- if(timer2On) {
- if(TM2CNT & 4) {
- if(timerOverflow & 2) {
- TM2D++;
- if(TM2D == 0) {
- TM2D += timer2Reload;
- timerOverflow |= 4;
- if(TM2CNT & 0x40) {
- IF |= 0x20;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x108, TM2D);
- }
- } else {
- timer2Ticks -= clockTicks;
- if(timer2Ticks <= 0) {
- timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload;
- timerOverflow |= 4;
- if(TM2CNT & 0x40) {
- IF |= 0x20;
- UPDATE_REG(0x202, IF);
- }
- }
- TM2D = 0xFFFF - (timer2Ticks >> timer2ClockReload);
- UPDATE_REG(0x108, TM2D);
- }
- }
-
- if(timer3On) {
- if(TM3CNT & 4) {
- if(timerOverflow & 4) {
- TM3D++;
- if(TM3D == 0) {
- TM3D += timer3Reload;
- if(TM3CNT & 0x40) {
- IF |= 0x40;
- UPDATE_REG(0x202, IF);
- }
- }
- UPDATE_REG(0x10C, TM3D);
- }
- } else {
- timer3Ticks -= clockTicks;
- if(timer3Ticks <= 0) {
- timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload;
- if(TM3CNT & 0x40) {
- IF |= 0x40;
- UPDATE_REG(0x202, IF);
- }
- }
- TM3D = 0xFFFF - (timer3Ticks >> timer3ClockReload);
- UPDATE_REG(0x10C, TM3D);
- }
- }
- }
-
- timerOverflow = 0;
-
-
-
-#ifdef PROFILING
- profilingTicks -= clockTicks;
- if(profilingTicks <= 0) {
- profilingTicks += profilingTicksReload;
- if(profilSegment) {
- profile_segment *seg = profilSegment;
- do {
- uint16_t *b = (uint16_t *)seg->sbuf;
- int pc = ((reg[15].I - seg->s_lowpc) * seg->s_scale)/0x10000;
- if(pc >= 0 && pc < seg->ssiz) {
- b[pc]++;
- break;
- }
-
- seg = seg->next;
- } while(seg);
- }
- }
-#endif
-
- ticks -= clockTicks;
-
- /*if (gba_joybus_enabled)
- JoyBusUpdate(clockTicks);
-
- if (gba_link_enabled)
- LinkUpdate(clockTicks);*/
-
- cpuNextEvent = CPUUpdateTicks();
-
- if(cpuDmaTicksToUpdate > 0) {
- if(cpuDmaTicksToUpdate > cpuNextEvent)
- clockTicks = cpuNextEvent;
- else
- clockTicks = cpuDmaTicksToUpdate;
- cpuDmaTicksToUpdate -= clockTicks;
- if(cpuDmaTicksToUpdate < 0)
- cpuDmaTicksToUpdate = 0;
- goto updateLoop;
- }
-
- // shuffle2: what's the purpose?
- /*if(gba_link_enabled)
- cpuNextEvent = 1;*/
-
- if(IF && (IME & 1) && armIrqEnable) {
- int res = IF & IE;
- if(stopState)
- res &= 0x3080;
- if(res) {
- if (intState)
- {
- if (!IRQTicks)
- {
- CPUInterrupt();
- intState = false;
- holdState = false;
- stopState = false;
- holdType = 0;
- }
- }
- else
- {
- if (!holdState)
- {
- intState = true;
- IRQTicks=7;
- if (cpuNextEvent> IRQTicks)
- cpuNextEvent = IRQTicks;
- }
- else
- {
- CPUInterrupt();
- holdState = false;
- stopState = false;
- holdType = 0;
- }
- }
-
- // Stops the SWI Ticks emulation if an IRQ is executed
- //(to avoid problems with nested IRQ/SWI)
- if (SWITicks)
- SWITicks = 0;
- }
- }
-
- if(remainingTicks > 0) {
- if(remainingTicks > cpuNextEvent)
- clockTicks = cpuNextEvent;
- else
- clockTicks = remainingTicks;
- remainingTicks -= clockTicks;
- if(remainingTicks < 0)
- remainingTicks = 0;
- goto updateLoop;
- }
-
- if (timerOnOffDelay)
- applyTimer();
-
- if(cpuNextEvent > ticks)
- cpuNextEvent = ticks;
-
- if(ticks <= 0 || cpuBreakLoop)
- break;
-
- }
- }
+ int clockTicks;
+ int timerOverflow = 0;
+ // variable used by the CPU core
+ cpuTotalTicks = 0;
+
+ cpuNextEvent = CPUUpdateTicks();
+ if (cpuNextEvent > ticks)
+ cpuNextEvent = ticks;
+
+ for (;;)
+ {
+ if (!holdState && !SWITicks)
+ {
+ if (armState)
+ {
+ if (!armExecute())
+ return;
+ }
+ else
+ {
+ if (!thumbExecute())
+ return;
+ }
+ clockTicks = 0;
+ }
+ else
+ clockTicks = CPUUpdateTicks();
+
+ cpuTotalTicks += clockTicks;
+
+ if (cpuTotalTicks >= cpuNextEvent)
+ {
+ int remainingTicks = cpuTotalTicks - cpuNextEvent;
+
+ if (SWITicks)
+ {
+ SWITicks -= clockTicks;
+ if (SWITicks < 0)
+ SWITicks = 0;
+ }
+
+ clockTicks = cpuNextEvent;
+ cpuTotalTicks = 0;
+
+ updateLoop:
+
+ if (IRQTicks)
+ {
+ IRQTicks -= clockTicks;
+ if (IRQTicks < 0)
+ IRQTicks = 0;
+ }
+
+ lcdTicks -= clockTicks;
+
+ if (lcdTicks <= 0)
+ {
+ if (DISPSTAT & 1) // V-BLANK
+ {
+ // if in V-Blank mode, keep computing...
+ if (DISPSTAT & 2)
+ {
+ lcdTicks += 1008;
+ ++VCOUNT;
+ UPDATE_REG(0x06, VCOUNT);
+ DISPSTAT &= 0xFFFD;
+ UPDATE_REG(0x04, DISPSTAT);
+ CPUCompareVCOUNT();
+ }
+ else
+ {
+ lcdTicks += 224;
+ DISPSTAT |= 2;
+ UPDATE_REG(0x04, DISPSTAT);
+ if (DISPSTAT & 16)
+ {
+ IF |= 2;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+
+ if (VCOUNT >= 228) //Reaching last line
+ {
+ DISPSTAT &= 0xFFFC;
+ UPDATE_REG(0x04, DISPSTAT);
+ VCOUNT = 0;
+ UPDATE_REG(0x06, VCOUNT);
+ CPUCompareVCOUNT();
+ }
+ }
+ else
+ {
+ if (DISPSTAT & 2)
+ {
+ // if in H-Blank, leave it and move to drawing mode
+ ++VCOUNT;
+ UPDATE_REG(0x06, VCOUNT);
+
+ lcdTicks += 1008;
+ DISPSTAT &= 0xFFFD;
+ if (VCOUNT == 160)
+ {
+ ++count;
+ if (count == 60)
+ count = 0;
+
+ DISPSTAT |= 1;
+ DISPSTAT &= 0xFFFD;
+ UPDATE_REG(0x04, DISPSTAT);
+ if (DISPSTAT & 0x0008)
+ {
+ IF |= 1;
+ UPDATE_REG(0x202, IF);
+ }
+ CPUCheckDMA(1, 0x0f);
+ }
+
+ UPDATE_REG(0x04, DISPSTAT);
+ CPUCompareVCOUNT();
+ }
+ else
+ {
+ // entering H-Blank
+ DISPSTAT |= 2;
+ UPDATE_REG(0x04, DISPSTAT);
+ lcdTicks += 224;
+ CPUCheckDMA(2, 0x0f);
+ if (DISPSTAT & 16)
+ {
+ IF |= 2;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ }
+ }
+
+ // we shouldn't be doing sound in stop state, but we loose synchronization
+ // if sound is disabled, so in stop state, soundTick will just produce
+ // mute sound
+ soundTicks -= clockTicks;
+ if (soundTicks <= 0)
+ {
+ psoundTickfn();
+ soundTicks += SOUND_CLOCK_TICKS;
+ }
+
+ if (!stopState)
+ {
+ if (timer0On)
+ {
+ timer0Ticks -= clockTicks;
+ if (timer0Ticks <= 0)
+ {
+ timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload;
+ timerOverflow |= 1;
+ soundTimerOverflow(0);
+ if (TM0CNT & 0x40)
+ {
+ IF |= 0x08;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ TM0D = 0xFFFF - (timer0Ticks >> timer0ClockReload);
+ UPDATE_REG(0x100, TM0D);
+ }
+
+ if (timer1On)
+ {
+ if (TM1CNT & 4)
+ {
+ if (timerOverflow & 1)
+ {
+ ++TM1D;
+ if (!TM1D)
+ {
+ TM1D += timer1Reload;
+ timerOverflow |= 2;
+ soundTimerOverflow(1);
+ if (TM1CNT & 0x40)
+ {
+ IF |= 0x10;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ UPDATE_REG(0x104, TM1D);
+ }
+ }
+ else
+ {
+ timer1Ticks -= clockTicks;
+ if (timer1Ticks <= 0)
+ {
+ timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload;
+ timerOverflow |= 2;
+ soundTimerOverflow(1);
+ if (TM1CNT & 0x40)
+ {
+ IF |= 0x10;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ TM1D = 0xFFFF - (timer1Ticks >> timer1ClockReload);
+ UPDATE_REG(0x104, TM1D);
+ }
+ }
+
+ if (timer2On)
+ {
+ if (TM2CNT & 4)
+ {
+ if (timerOverflow & 2)
+ {
+ ++TM2D;
+ if (!TM2D)
+ {
+ TM2D += timer2Reload;
+ timerOverflow |= 4;
+ if (TM2CNT & 0x40)
+ {
+ IF |= 0x20;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ UPDATE_REG(0x108, TM2D);
+ }
+ }
+ else
+ {
+ timer2Ticks -= clockTicks;
+ if (timer2Ticks <= 0)
+ {
+ timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload;
+ timerOverflow |= 4;
+ if (TM2CNT & 0x40)
+ {
+ IF |= 0x20;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ TM2D = 0xFFFF - (timer2Ticks >> timer2ClockReload);
+ UPDATE_REG(0x108, TM2D);
+ }
+ }
+
+ if (timer3On)
+ {
+ if (TM3CNT & 4)
+ {
+ if (timerOverflow & 4)
+ {
+ ++TM3D;
+ if (!TM3D)
+ {
+ TM3D += timer3Reload;
+ if (TM3CNT & 0x40)
+ {
+ IF |= 0x40;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ UPDATE_REG(0x10C, TM3D);
+ }
+ }
+ else
+ {
+ timer3Ticks -= clockTicks;
+ if (timer3Ticks <= 0)
+ {
+ timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload;
+ if (TM3CNT & 0x40)
+ {
+ IF |= 0x40;
+ UPDATE_REG(0x202, IF);
+ }
+ }
+ TM3D = 0xFFFF - (timer3Ticks >> timer3ClockReload);
+ UPDATE_REG(0x10C, TM3D);
+ }
+ }
+ }
+
+ timerOverflow = 0;
+
+ ticks -= clockTicks;
+
+ cpuNextEvent = CPUUpdateTicks();
+
+ if (cpuDmaTicksToUpdate > 0)
+ {
+ if (cpuDmaTicksToUpdate > cpuNextEvent)
+ clockTicks = cpuNextEvent;
+ else
+ clockTicks = cpuDmaTicksToUpdate;
+ cpuDmaTicksToUpdate -= clockTicks;
+ if (cpuDmaTicksToUpdate < 0)
+ cpuDmaTicksToUpdate = 0;
+ goto updateLoop;
+ }
+
+ if (IF && (IME & 1) && armIrqEnable)
+ {
+ int res = IF & IE;
+ if (stopState)
+ res &= 0x3080;
+ if (res)
+ {
+ if (intState)
+ {
+ if (!IRQTicks)
+ {
+ CPUInterrupt();
+ intState = false;
+ holdState = false;
+ stopState = false;
+ holdType = 0;
+ }
+ }
+ else
+ {
+ if (!holdState)
+ {
+ intState = true;
+ IRQTicks = 7;
+ if (cpuNextEvent> IRQTicks)
+ cpuNextEvent = IRQTicks;
+ }
+ else
+ {
+ CPUInterrupt();
+ holdState = false;
+ stopState = false;
+ holdType = 0;
+ }
+ }
+
+ // Stops the SWI Ticks emulation if an IRQ is executed
+ // (to avoid problems with nested IRQ/SWI)
+ if (SWITicks)
+ SWITicks = 0;
+ }
+ }
+
+ if (remainingTicks > 0)
+ {
+ if (remainingTicks > cpuNextEvent)
+ clockTicks = cpuNextEvent;
+ else
+ clockTicks = remainingTicks;
+ remainingTicks -= clockTicks;
+ if (remainingTicks < 0)
+ remainingTicks = 0;
+ goto updateLoop;
+ }
+
+ if (timerOnOffDelay)
+ applyTimer();
+
+ if (cpuNextEvent > ticks)
+ cpuNextEvent = ticks;
+
+ if (ticks <= 0)
+ break;
+ }
+ }
}
-
-
-/*struct EmulatedSystem GBASystem = {
- // emuMain
- CPULoop,
- // emuReset
- CPUReset,
- // emuCleanUp
- CPUCleanUp,
- // emuReadBattery
- CPUReadBatteryFile,
- // emuWriteBattery
- CPUWriteBatteryFile,
- // emuReadState
- CPUReadState,
- // emuWriteState
- CPUWriteState,
- // emuReadMemState
- CPUReadMemState,
- // emuWriteMemState
- CPUWriteMemState,
- // emuWritePNG
- CPUWritePNGFile,
- // emuWriteBMP
- CPUWriteBMPFile,
- // emuUpdateCPSR
- CPUUpdateCPSR,
- // emuHasDebugger
- true,
- // emuCount
-#ifdef FINAL_VERSION
- 250000
-#else
- 5000
-#endif
-};*/
-
--- a/src/in_gsf/vbam/gba/GBA.h
+++ b/src/in_gsf/vbam/gba/GBA.h
@@ -3,52 +3,44 @@
#include <cstdint>
-/*#define SAVE_GAME_VERSION_1 1
-#define SAVE_GAME_VERSION_2 2
-#define SAVE_GAME_VERSION_3 3
-#define SAVE_GAME_VERSION_4 4
-#define SAVE_GAME_VERSION_5 5
-#define SAVE_GAME_VERSION_6 6
-#define SAVE_GAME_VERSION_7 7
-#define SAVE_GAME_VERSION_8 8
-#define SAVE_GAME_VERSION_9 9
-#define SAVE_GAME_VERSION_10 10
-#define SAVE_GAME_VERSION SAVE_GAME_VERSION_10*/
+struct memoryMap
+{
+ uint8_t *address;
+ uint32_t mask;
+};
-typedef struct {
- uint8_t *address;
- uint32_t mask;
-} memoryMap;
-
-typedef union {
- struct {
+union reg_pair
+{
+ struct
+ {
#ifdef WORDS_BIGENDIAN
- uint8_t B3;
- uint8_t B2;
- uint8_t B1;
- uint8_t B0;
+ uint8_t B3;
+ uint8_t B2;
+ uint8_t B1;
+ uint8_t B0;
#else
- uint8_t B0;
- uint8_t B1;
- uint8_t B2;
- uint8_t B3;
+ uint8_t B0;
+ uint8_t B1;
+ uint8_t B2;
+ uint8_t B3;
#endif
- } B;
- struct {
+ } B;
+ struct
+ {
#ifdef WORDS_BIGENDIAN
- uint16_t W1;
- uint16_t W0;
+ uint16_t W1;
+ uint16_t W0;
#else
- uint16_t W0;
- uint16_t W1;
+ uint16_t W0;
+ uint16_t W1;
#endif
- } W;
+ } W;
#ifdef WORDS_BIGENDIAN
- volatile uint32_t I;
+ volatile uint32_t I;
#else
uint32_t I;
#endif
-} reg_pair;
+};
#ifndef NO_GBA_MAP
extern memoryMap map[256];
@@ -64,80 +56,38 @@
extern bool armIrqEnable;
extern bool armState;
extern int armMode;
-//extern void (*cpuSaveGameFunc)(u32,u8);
-#ifdef BKPT_SUPPORT
-extern uint8_t freezeWorkRAM[0x40000];
-extern uint8_t freezeInternalRAM[0x8000];
-extern uint8_t freezeVRAM[0x18000];
-extern uint8_t freezeOAM[0x400];
-extern uint8_t freezePRAM[0x400];
-extern bool debugger_last;
-extern int oldreg[18];
-extern char oldbuffer[10];
-#endif
-
-extern bool CPUReadGSASnapshot(const char *);
-extern bool CPUReadGSASPSnapshot(const char *);
-extern bool CPUWriteGSASnapshot(const char *, const char *, const char *, const char *);
-extern bool CPUWriteBatteryFile(const char *);
-extern bool CPUReadBatteryFile(const char *);
-extern bool CPUExportEepromFile(const char *);
-extern bool CPUImportEepromFile(const char *);
-extern bool CPUWritePNGFile(const char *);
-extern bool CPUWriteBMPFile(const char *);
-extern void CPUCleanUp();
-//extern void CPUUpdateRender();
-//extern void CPUUpdateRenderBuffers(bool);
-extern bool CPUReadMemState(char *, int);
-extern bool CPUReadState(const char *);
-extern bool CPUWriteMemState(char *, int);
-extern bool CPUWriteState(const char *);
-extern int CPULoadRom(const char *);
-extern void doMirroring(bool);
+extern int CPULoadRom();
extern void CPUUpdateRegister(uint32_t, uint16_t);
-extern void applyTimer ();
-extern void CPUInit(const char *,bool);
+extern void CPUInit();
extern void CPUReset();
extern void CPULoop(int);
-extern void CPUCheckDMA(int,int);
-extern bool CPUIsGBAImage(const char *);
-extern bool CPUIsZipFile(const char *);
-#ifdef PROFILING
-#include "prof/prof.h"
-extern void cpuProfil(profile_segment *seg);
-extern void cpuEnableProfiling(int hz);
-#endif
+extern void CPUCheckDMA(int, int);
-extern struct EmulatedSystem GBASystem;
+const uint32_t R13_IRQ = 18;
+const uint32_t R14_IRQ = 19;
+const uint32_t SPSR_IRQ = 20;
+const uint32_t R13_USR = 26;
+const uint32_t R14_USR = 27;
+const uint32_t R13_SVC = 28;
+const uint32_t R14_SVC = 29;
+const uint32_t SPSR_SVC = 30;
+const uint32_t R13_ABT = 31;
+const uint32_t R14_ABT = 32;
+const uint32_t SPSR_ABT = 33;
+const uint32_t R13_UND = 34;
+const uint32_t R14_UND = 35;
+const uint32_t SPSR_UND = 36;
+const uint32_t R8_FIQ = 37;
+const uint32_t R9_FIQ = 38;
+const uint32_t R10_FIQ = 39;
+const uint32_t R11_FIQ = 40;
+const uint32_t R12_FIQ = 41;
+const uint32_t R13_FIQ = 42;
+const uint32_t R14_FIQ = 43;
+const uint32_t SPSR_FIQ = 44;
-#define R13_IRQ 18
-#define R14_IRQ 19
-#define SPSR_IRQ 20
-#define R13_USR 26
-#define R14_USR 27
-#define R13_SVC 28
-#define R14_SVC 29
-#define SPSR_SVC 30
-#define R13_ABT 31
-#define R14_ABT 32
-#define SPSR_ABT 33
-#define R13_UND 34
-#define R14_UND 35
-#define SPSR_UND 36
-#define R8_FIQ 37
-#define R9_FIQ 38
-#define R10_FIQ 39
-#define R11_FIQ 40
-#define R12_FIQ 41
-#define R13_FIQ 42
-#define R14_FIQ 43
-#define SPSR_FIQ 44
-
-//#include "Cheats.h"
#include "Globals.h"
-//#include "EEprom.h"
-//#include "Flash.h"
#endif // GBA_H
--- a/src/in_gsf/vbam/gba/GBAcpu.h
+++ b/src/in_gsf/vbam/gba/GBAcpu.h
@@ -1,15 +1,17 @@
#ifndef GBACPU_H
#define GBACPU_H
+#include "GBAinline.h"
+
extern int armExecute();
extern int thumbExecute();
#ifdef __GNUC__
-#ifndef __APPLE__
-# define INSN_REGPARM __attribute__((regparm(1)))
-#else
-# define INSN_REGPARM /*nothing*/
-#endif
+# ifndef __APPLE__
+# define INSN_REGPARM __attribute__((regparm(1)))
+# else
+# define INSN_REGPARM /*nothing*/
+# endif
# define LIKELY(x) __builtin_expect(!!(x),1)
# define UNLIKELY(x) __builtin_expect(!!(x),0)
#else
@@ -18,271 +20,238 @@
# define UNLIKELY(x) (x)
#endif
-#define UPDATE_REG(address, value)\
- {\
- WRITE16LE(((uint16_t *)&ioMem[address]),value);\
- }\
-
-#define ARM_PREFETCH \
- {\
- cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);\
- cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);\
- }
-
-#define THUMB_PREFETCH \
- {\
- cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);\
- cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);\
- }
-
-#define ARM_PREFETCH_NEXT \
- cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);
-
-#define THUMB_PREFETCH_NEXT\
- cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);
-
+inline void UPDATE_REG(uint32_t address, uint16_t value) { WRITE16LE(&ioMem[address],value); }
+
+extern uint32_t cpuPrefetch[2];
+
+inline void ARM_PREFETCH()
+{
+ cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);
+ cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC + 4);
+}
+
+inline void THUMB_PREFETCH()
+{
+ cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);
+ cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC + 2);
+}
+
+inline void ARM_PREFETCH_NEXT() { cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC + 4); }
+
+inline void THUMB_PREFETCH_NEXT() { cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC + 2); }
extern int SWITicks;
-extern uint32_t mastercode;
extern bool busPrefetch;
extern bool busPrefetchEnable;
extern uint32_t busPrefetchCount;
-extern int cpuNextEvent;
-extern bool holdState;
-extern uint32_t cpuPrefetch[2];
-extern int cpuTotalTicks;
extern uint8_t memoryWait[16];
extern uint8_t memoryWait32[16];
extern uint8_t memoryWaitSeq[16];
extern uint8_t memoryWaitSeq32[16];
extern uint8_t cpuBitsSet[256];
-extern uint8_t cpuLowestBitSet[256];
-extern void CPUSwitchMode(int mode, bool saveState, bool breakLoop);
-extern void CPUSwitchMode(int mode, bool saveState);
+extern void CPUSwitchMode(int mode, bool saveState, bool breakLoop = true);
extern void CPUUpdateCPSR();
-extern void CPUUpdateFlags(bool breakLoop);
-extern void CPUUpdateFlags();
+extern void CPUUpdateFlags(bool breakLoop = true);
extern void CPUUndefinedException();
-extern void CPUSoftwareInterrupt();
extern void CPUSoftwareInterrupt(int comment);
-
// Waitstates when accessing data
inline int dataTicksAccess16(uint32_t address) // DATA 8/16bits NON SEQ
{
- int addr = (address>>24)&15;
- int value = memoryWait[addr];
-
- if ((addr>=0x08) || (addr < 0x02))
- {
- busPrefetchCount=0;
- busPrefetch=false;
- }
- else if (busPrefetch)
- {
- int waitState = value;
- if (!waitState)
- waitState = 1;
- busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
- }
-
- return value;
+ int addr = (address >> 24) & 15;
+ int value = memoryWait[addr];
+
+ if (addr >= 0x08 || addr < 0x02)
+ {
+ busPrefetchCount = 0;
+ busPrefetch = false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((busPrefetchCount + 1) << waitState) - 1;
+ }
+
+ return value;
}
inline int dataTicksAccess32(uint32_t address) // DATA 32bits NON SEQ
{
- int addr = (address>>24)&15;
- int value = memoryWait32[addr];
-
- if ((addr>=0x08) || (addr < 0x02))
- {
- busPrefetchCount=0;
- busPrefetch=false;
- }
- else if (busPrefetch)
- {
- int waitState = value;
- if (!waitState)
- waitState = 1;
- busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
- }
-
- return value;
-}
-
-inline int dataTicksAccessSeq16(uint32_t address)// DATA 8/16bits SEQ
-{
- int addr = (address>>24)&15;
- int value = memoryWaitSeq[addr];
-
- if ((addr>=0x08) || (addr < 0x02))
- {
- busPrefetchCount=0;
- busPrefetch=false;
- }
- else if (busPrefetch)
- {
- int waitState = value;
- if (!waitState)
- waitState = 1;
- busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
- }
-
- return value;
-}
-
-inline int dataTicksAccessSeq32(uint32_t address)// DATA 32bits SEQ
-{
- int addr = (address>>24)&15;
- int value = memoryWaitSeq32[addr];
-
- if ((addr>=0x08) || (addr < 0x02))
- {
- busPrefetchCount=0;
- busPrefetch=false;
- }
- else if (busPrefetch)
- {
- int waitState = value;
- if (!waitState)
- waitState = 1;
- busPrefetchCount = ((busPrefetchCount+1)<<waitState) - 1;
- }
-
- return value;
-}
-
+ int addr = (address >> 24) & 15;
+ int value = memoryWait32[addr];
+
+ if (addr >= 0x08 || addr < 0x02)
+ {
+ busPrefetchCount = 0;
+ busPrefetch = false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((busPrefetchCount + 1) << waitState) - 1;
+ }
+
+ return value;
+}
+
+inline int dataTicksAccessSeq16(uint32_t address) // DATA 8/16bits SEQ
+{
+ int addr = (address >> 24) & 15;
+ int value = memoryWaitSeq[addr];
+
+ if (addr >= 0x08 || addr < 0x02)
+ {
+ busPrefetchCount = 0;
+ busPrefetch = false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((busPrefetchCount + 1) << waitState) - 1;
+ }
+
+ return value;
+}
+
+inline int dataTicksAccessSeq32(uint32_t address) // DATA 32bits SEQ
+{
+ int addr = (address >> 24) & 15;
+ int value = memoryWaitSeq32[addr];
+
+ if (addr >= 0x08 || addr < 0x02)
+ {
+ busPrefetchCount = 0;
+ busPrefetch = false;
+ }
+ else if (busPrefetch)
+ {
+ int waitState = value;
+ if (!waitState)
+ waitState = 1;
+ busPrefetchCount = ((busPrefetchCount + 1) << waitState) - 1;
+ }
+
+ return value;
+}
// Waitstates when executing opcode
inline int codeTicksAccess16(uint32_t address) // THUMB NON SEQ
{
- int addr = (address>>24)&15;
-
- if ((addr>=0x08) && (addr<=0x0D))
- {
- if (busPrefetchCount&0x1)
- {
- if (busPrefetchCount&0x2)
- {
- busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
- return 0;
- }
- busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
- return memoryWaitSeq[addr]-1;
- }
- else
- {
- busPrefetchCount=0;
- return memoryWait[addr];
- }
- }
- else
- {
- busPrefetchCount = 0;
- return memoryWait[addr];
- }
+ int addr = (address >> 24) & 15;
+
+ if (addr >= 0x08 && addr <= 0x0D)
+ {
+ if (busPrefetchCount & 0x1)
+ {
+ if (busPrefetchCount & 0x2)
+ {
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 2) | (busPrefetchCount & 0xFFFFFF00);
+ return 0;
+ }
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
+ return memoryWaitSeq[addr] - 1;
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait[addr];
+ }
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait[addr];
+ }
}
inline int codeTicksAccess32(uint32_t address) // ARM NON SEQ
{
- int addr = (address>>24)&15;
-
- if ((addr>=0x08) && (addr<=0x0D))
- {
- if (busPrefetchCount&0x1)
- {
- if (busPrefetchCount&0x2)
- {
- busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
- return 0;
- }
- busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
- return memoryWaitSeq[addr] - 1;
- }
- else
- {
- busPrefetchCount = 0;
- return memoryWait32[addr];
- }
- }
- else
- {
- busPrefetchCount = 0;
- return memoryWait32[addr];
- }
+ int addr = (address >> 24) & 15;
+
+ if (addr >= 0x08 && addr <= 0x0D)
+ {
+ if (busPrefetchCount & 0x1)
+ {
+ if (busPrefetchCount & 0x2)
+ {
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 2) | (busPrefetchCount & 0xFFFFFF00);
+ return 0;
+ }
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
+ return memoryWaitSeq[addr] - 1;
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait32[addr];
+ }
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWait32[addr];
+ }
}
inline int codeTicksAccessSeq16(uint32_t address) // THUMB SEQ
{
- int addr = (address>>24)&15;
-
- if ((addr>=0x08) && (addr<=0x0D))
- {
- if (busPrefetchCount&0x1)
- {
- busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
- return 0;
- }
- else
- if (busPrefetchCount>0xFF)
- {
- busPrefetchCount=0;
- return memoryWait[addr];
- }
- else
- return memoryWaitSeq[addr];
- }
- else
- {
- busPrefetchCount = 0;
- return memoryWaitSeq[addr];
- }
+ int addr = (address >> 24) & 15;
+
+ if (addr >= 0x08 && addr <= 0x0D)
+ {
+ if (busPrefetchCount & 0x1)
+ {
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
+ return 0;
+ }
+ else if (busPrefetchCount > 0xFF)
+ {
+ busPrefetchCount = 0;
+ return memoryWait[addr];
+ }
+ else
+ return memoryWaitSeq[addr];
+ }
+ else
+ {
+ busPrefetchCount = 0;
+ return memoryWaitSeq[addr];
+ }
}
inline int codeTicksAccessSeq32(uint32_t address) // ARM SEQ
{
- int addr = (address>>24)&15;
-
- if ((addr>=0x08) && (addr<=0x0D))
- {
- if (busPrefetchCount&0x1)
- {
- if (busPrefetchCount&0x2)
- {
- busPrefetchCount = ((busPrefetchCount&0xFF)>>2) | (busPrefetchCount&0xFFFFFF00);
- return 0;
- }
- busPrefetchCount = ((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00);
- return memoryWaitSeq[addr];
- }
- else
- if (busPrefetchCount>0xFF)
- {
- busPrefetchCount=0;
- return memoryWait32[addr];
- }
- else
- return memoryWaitSeq32[addr];
- }
- else
- {
- return memoryWaitSeq32[addr];
- }
-}
-
-
-// Emulates the Cheat System (m) code
-/*inline void cpuMasterCodeCheck()
-{
- if((mastercode) && (mastercode == armNextPC))
- {
- u32 joy = 0;
- if(systemReadJoypads())
- joy = systemReadJoypad(-1);
- u32 ext = (joy >> 10);
- cpuTotalTicks += cheatsCheckKeys(P1^0x3FF, ext);
- }
-}*/
+ int addr = (address >> 24) & 15;
+
+ if (addr >= 0x08 && addr <= 0x0D)
+ {
+ if (busPrefetchCount & 0x1)
+ {
+ if (busPrefetchCount & 0x2)
+ {
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 2) | (busPrefetchCount & 0xFFFFFF00);
+ return 0;
+ }
+ busPrefetchCount = ((busPrefetchCount & 0xFF) >> 1) | (busPrefetchCount & 0xFFFFFF00);
+ return memoryWaitSeq[addr];
+ }
+ else if (busPrefetchCount > 0xFF)
+ {
+ busPrefetchCount = 0;
+ return memoryWait32[addr];
+ }
+ else
+ return memoryWaitSeq32[addr];
+ }
+ else
+ return memoryWaitSeq32[addr];
+}
#endif // GBACPU_H
--- a/src/in_gsf/vbam/gba/GBAinline.h
+++ b/src/in_gsf/vbam/gba/GBAinline.h
@@ -1,13 +1,8 @@
#ifndef GBAINLINE_H
#define GBAINLINE_H
-//#include "../System.h"
#include "../common/Port.h"
-//#include "RTC.h"
#include "Sound.h"
-//#include "agbprint.h"
-#include "GBAcpu.h"
-//#include "GBALink.h"
extern const uint32_t objTilesAddress[3];
@@ -15,11 +10,6 @@
extern bool holdState;
extern int holdType;
extern int cpuNextEvent;
-extern bool cpuSramEnabled;
-extern bool cpuFlashEnabled;
-extern bool cpuEEPROMEnabled;
-extern bool cpuEEPROMSensorEnabled;
-extern uint32_t cpuDmaLast;
extern bool timer0On;
extern int timer0Ticks;
extern int timer0ClockReload;
@@ -34,702 +24,430 @@
extern int timer3ClockReload;
extern int cpuTotalTicks;
-#define CPUReadByteQuick(addr) \
- map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
-
-#define CPUReadHalfWordQuick(addr) \
- READ16LE(((uint16_t*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-#define CPUReadMemoryQuick(addr) \
- READ32LE(((uint32_t*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
-
-static inline uint32_t CPUReadMemory(uint32_t address)
-{
- uint32_t value;
- uint32_t oldAddress = address;
-
- if(address & 3) {
- address &= ~0x03;
- }
-
- switch(address >> 24) {
- case 0:
- if(reg[15].I >> 24) {
- if(address < 0x4000) {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal word read from bios: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
-
- value = READ32LE(((uint32_t *)&biosProtected));
- }
- else goto unreadable;
- } else
- value = READ32LE(((uint32_t *)&bios[address & 0x3FFC]));
- break;
- case 2:
- value = READ32LE(((uint32_t *)&workRAM[address & 0x3FFFC]));
- break;
- case 3:
- value = READ32LE(((uint32_t *)&internalRAM[address & 0x7ffC]));
- break;
- case 4:
- if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
- if(ioReadable[(address & 0x3fc) + 2]) {
- value = READ32LE(((uint32_t *)&ioMem[address & 0x3fC]));
- /*if ((address & 0x3fc) == COMM_JOY_RECV_L)
- UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV);*/
- } else {
- value = READ16LE(((uint16_t *)&ioMem[address & 0x3fc]));
- }
- }
- else
- goto unreadable;
- break;
- case 5:
- value = READ32LE(((uint32_t *)&paletteRAM[address & 0x3fC]));
- break;
- case 6:
- address = (address & 0x1fffc);
- if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
- {
- value = 0;
- break;
- }
- if ((address & 0x18000) == 0x18000)
- address &= 0x17fff;
- value = READ32LE(((uint32_t *)&vram[address]));
- break;
- case 7:
- value = READ32LE(((uint32_t *)&oam[address & 0x3FC]));
- break;
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- value = READ32LE(((uint32_t *)&rom[address&0x1FFFFFC]));
- break;
- case 13:
- if(cpuEEPROMEnabled)
- // no need to swap this
- return /*eepromRead(address)*/0;
- goto unreadable;
- case 14:
- if(cpuFlashEnabled | cpuSramEnabled)
- // no need to swap this
- return /*flashRead(address)*/0;
- // default
- default:
-unreadable:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal word read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
-
- if(armState) {
- return CPUReadMemoryQuick(reg[15].I);
- } else {
- return CPUReadHalfWordQuick(reg[15].I) |
- CPUReadHalfWordQuick(reg[15].I) << 16;
- }
- }
-
- if(oldAddress & 3) {
+inline uint16_t CPUReadHalfWordQuick(uint32_t addr) { return READ16LE(&map[addr >> 24].address[addr & map[addr >> 24].mask]); }
+
+inline uint32_t CPUReadMemoryQuick(uint32_t addr) { return READ32LE(&map[addr >> 24].address[addr & map[addr >> 24].mask]); }
+
+inline uint32_t CPUReadMemory(uint32_t address)
+{
+ uint32_t value;
+ uint32_t oldAddress = address;
+
+ if (address & 3)
+ address &= ~0x03;
+
+ switch (address >> 24)
+ {
+ case 0:
+ if (reg[15].I >> 24)
+ {
+ if (address < 0x4000)
+ value = READ32LE(&biosProtected);
+ else
+ goto unreadable;
+ }
+ else
+ value = READ32LE(&bios[address & 0x3FFC]);
+ break;
+ case 2:
+ value = READ32LE(&workRAM[address & 0x3FFFC]);
+ break;
+ case 3:
+ value = READ32LE(&internalRAM[address & 0x7ffC]);
+ break;
+ case 4:
+ if (address < 0x4000400 && ioReadable[address & 0x3fc])
+ {
+ if (ioReadable[(address & 0x3fc) + 2])
+ value = READ32LE(&ioMem[address & 0x3fC]);
+ else
+ value = READ16LE(&ioMem[address & 0x3fc]);
+ }
+ else
+ goto unreadable;
+ break;
+ case 5:
+ value = READ32LE(&paletteRAM[address & 0x3fC]);
+ break;
+ case 6:
+ address &= 0x1fffc;
+ if ((DISPCNT & 7) > 2 && (address & 0x1C000) == 0x18000)
+ {
+ value = 0;
+ break;
+ }
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ value = READ32LE(&vram[address]);
+ break;
+ case 7:
+ value = READ32LE(&oam[address & 0x3FC]);
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ value = READ32LE(&rom[address & 0x1FFFFFC]);
+ break;
+ case 13:
+ case 14:
+ return 0;
+ // default
+ default:
+ unreadable:
+ if (armState)
+ return CPUReadMemoryQuick(reg[15].I);
+ else
+ return CPUReadHalfWordQuick(reg[15].I) | CPUReadHalfWordQuick(reg[15].I) << 16;
+ }
+
+ if (oldAddress & 3)
+ {
#ifdef C_CORE
- int shift = (oldAddress & 3) << 3;
- value = (value >> shift) | (value << (32 - shift));
+ int shift = (oldAddress & 3) << 3;
+ value = (value >> shift) | (value << (32 - shift));
#else
#ifdef __GNUC__
- asm("and $3, %%ecx;"
- "shl $3 ,%%ecx;"
- "ror %%cl, %0"
- : "=r" (value)
- : "r" (value), "c" (oldAddress));
+ asm("and $3, %%ecx;"
+ "shl $3 ,%%ecx;"
+ "ror %%cl, %0"
+ : "=r" (value)
+ : "r" (value), "c" (oldAddress));
#else
- __asm {
- mov ecx, oldAddress;
- and ecx, 3;
- shl ecx, 3;
- ror [dword ptr value], cl;
- }
+ __asm
+ {
+ mov ecx, oldAddress;
+ and ecx, 3;
+ shl ecx, 3;
+ ror [dword ptr value], cl;
+ }
#endif
#endif
- }
-
-#ifdef GBA_LOGGING
- if(oldAddress & 3) {
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned word read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
- armNextPC - 4 : armNextPC - 2, value);
- }
- }
-#endif
- return value;
+ }
+
+ return value;
}
extern uint32_t myROM[];
-static inline uint32_t CPUReadHalfWord(uint32_t address)
-{
- uint32_t value;
- uint32_t oldAddress = address;
-
- if(address & 1) {
- address &= ~0x01;
- }
-
- switch(address >> 24) {
- case 0:
- if (reg[15].I >> 24) {
- if(address < 0x4000) {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal halfword read from bios: %08x at %08x\n", oldAddress, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- value = READ16LE(((uint16_t *)&biosProtected[address&2]));
- } else goto unreadable;
- } else
- value = READ16LE(((uint16_t *)&bios[address & 0x3FFE]));
- break;
- case 2:
- value = READ16LE(((uint16_t *)&workRAM[address & 0x3FFFE]));
- break;
- case 3:
- value = READ16LE(((uint16_t *)&internalRAM[address & 0x7ffe]));
- break;
- case 4:
- if((address < 0x4000400) && ioReadable[address & 0x3fe])
- {
- value = READ16LE(((uint16_t *)&ioMem[address & 0x3fe]));
- if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
- {
- if (((address & 0x3fe) == 0x100) && timer0On)
- value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
- else
- if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4))
- value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
- else
- if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4))
- value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
- else
- if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4))
- value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
- }
- }
- else goto unreadable;
- break;
- case 5:
- value = READ16LE(((uint16_t *)&paletteRAM[address & 0x3fe]));
- break;
- case 6:
- address = (address & 0x1fffe);
- if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
- {
- value = 0;
- break;
- }
- if ((address & 0x18000) == 0x18000)
- address &= 0x17fff;
- value = READ16LE(((uint16_t *)&vram[address]));
- break;
- case 7:
- value = READ16LE(((uint16_t *)&oam[address & 0x3fe]));
- break;
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
- value = /*rtcRead(address)*/0;
- else
- value = READ16LE(((uint16_t *)&rom[address & 0x1FFFFFE]));
- break;
- case 13:
- if(cpuEEPROMEnabled)
- // no need to swap this
- return /*eepromRead(address)*/0;
- goto unreadable;
- case 14:
- if(cpuFlashEnabled | cpuSramEnabled)
- // no need to swap this
- return /*flashRead(address)*/0;
- // default
- default:
-unreadable:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal halfword read: %08x at %08x\n", oldAddress, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- if(armState) {
- return CPUReadMemoryQuick(reg[15].I);
- } else {
- return CPUReadHalfWordQuick(reg[15].I) |
- CPUReadHalfWordQuick(reg[15].I) << 16;
- }
- }
-
- if(oldAddress & 1) {
- value = (value >> 8) | (value << 24);
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
- armNextPC - 4 : armNextPC - 2, value);
- }
-#endif
- }
-
- return value;
-}
-
-static inline int16_t CPUReadHalfWordSigned(uint32_t address)
-{
- uint32_t oldAddress = address;
- if(address & 1) {
- address &= ~0x01;
- }
- int16_t value = (int16_t)CPUReadHalfWord(address);
- if((oldAddress & 1))
- {
- value = (int8_t)value;
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ?
- armNextPC - 4 : armNextPC - 2, value);
- }
-#endif
- }
- return value;
-}
-
-static inline uint8_t CPUReadByte(uint32_t address)
-{
- switch(address >> 24) {
- case 0:
- if (reg[15].I >> 24) {
- if(address < 0x4000) {
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal byte read from bios: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- return biosProtected[address & 3];
- } else goto unreadable;
- }
- return bios[address & 0x3FFF];
- case 2:
- return workRAM[address & 0x3FFFF];
- case 3:
- return internalRAM[address & 0x7fff];
- case 4:
- if((address < 0x4000400) && ioReadable[address & 0x3ff])
- return ioMem[address & 0x3ff];
- else goto unreadable;
- case 5:
- return paletteRAM[address & 0x3ff];
- case 6:
- address = (address & 0x1ffff);
- if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
- return 0;
- if ((address & 0x18000) == 0x18000)
- address &= 0x17fff;
- return vram[address];
- case 7:
- return oam[address & 0x3ff];
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- return rom[address & 0x1FFFFFF];
- case 13:
- if(cpuEEPROMEnabled)
- return /*eepromRead(address)*/0;
- goto unreadable;
- case 14:
- if(cpuSramEnabled | cpuFlashEnabled)
- return /*flashRead(address)*/0;
- if(cpuEEPROMSensorEnabled) {
- switch(address & 0x00008f00) {
- case 0x8200:
- return /*systemGetSensorX() & 255*/0;
- case 0x8300:
- return /*(systemGetSensorX() >> 8)|0x80*/0;
- case 0x8400:
- return /*systemGetSensorY() & 255*/0;
- case 0x8500:
- return /*systemGetSensorY() >> 8*/0;
- }
- }
- // default
- default:
-unreadable:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_READ) {
- log("Illegal byte read: %08x at %08x\n", address, armMode ?
- armNextPC - 4 : armNextPC - 2);
- }
-#endif
- if(armState) {
- return CPUReadMemoryQuick(reg[15].I);
- } else {
- return CPUReadHalfWordQuick(reg[15].I) |
- CPUReadHalfWordQuick(reg[15].I) << 16;
- }
- }
-}
-
-static inline void CPUWriteMemory(uint32_t address, uint32_t value)
-{
-
-#ifdef GBA_LOGGING
- if(address & 3) {
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned word write: %08x to %08x from %08x\n",
- value,
- address,
- armMode ? armNextPC - 4 : armNextPC - 2);
- }
- }
-#endif
-
- address &= 0xFFFFFFFC;
-
- switch(address >> 24) {
- case 0x02:
-#ifdef BKPT_SUPPORT
- if(*((uint32_t *)&freezeWorkRAM[address & 0x3FFFC]))
- cheatsWriteMemory(address & 0x203FFFC,
- value);
- else
-#endif
- WRITE32LE(((uint32_t *)&workRAM[address & 0x3FFFC]), value);
- break;
- case 0x03:
-#ifdef BKPT_SUPPORT
- if(*((uint32_t *)&freezeInternalRAM[address & 0x7ffc]))
- cheatsWriteMemory(address & 0x3007FFC,
- value);
- else
-#endif
- WRITE32LE(((uint32_t *)&internalRAM[address & 0x7ffC]), value);
- break;
- case 0x04:
- if(address < 0x4000400) {
- CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
- CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
- } else goto unwritable;
- break;
- case 0x05:
-#ifdef BKPT_SUPPORT
- if(*((uint32_t *)&freezePRAM[address & 0x3fc]))
- cheatsWriteMemory(address & 0x70003FC,
- value);
- else
-#endif
- WRITE32LE(((uint32_t *)&paletteRAM[address & 0x3FC]), value);
- break;
- case 0x06:
- address = (address & 0x1fffc);
- if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
- return;
- if ((address & 0x18000) == 0x18000)
- address &= 0x17fff;
-
-#ifdef BKPT_SUPPORT
- if(*((uint32_t *)&freezeVRAM[address]))
- cheatsWriteMemory(address + 0x06000000, value);
- else
-#endif
-
- WRITE32LE(((uint32_t *)&vram[address]), value);
- break;
- case 0x07:
-#ifdef BKPT_SUPPORT
- if(*((uint32_t *)&freezeOAM[address & 0x3fc]))
- cheatsWriteMemory(address & 0x70003FC,
- value);
- else
-#endif
- WRITE32LE(((uint32_t *)&oam[address & 0x3fc]), value);
- break;
- case 0x0D:
- if(cpuEEPROMEnabled) {
- //eepromWrite(address, value);
- break;
- }
- goto unwritable;
- /*case 0x0E:
- if(*//*(!eepromInUse) | *//*cpuSramEnabled | cpuFlashEnabled) {
- //(*cpuSaveGameFunc)(address, (u8)value);
- break;
- }*/
- // default
- default:
-unwritable:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
- log("Illegal word write: %08x to %08x from %08x\n",
- value,
- address,
- armMode ? armNextPC - 4 : armNextPC - 2);
- }
-#endif
- break;
- }
-}
-
-static inline void CPUWriteHalfWord(uint32_t address, uint16_t value)
-{
-#ifdef GBA_LOGGING
- if(address & 1) {
- if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
- log("Unaligned halfword write: %04x to %08x from %08x\n",
- value,
- address,
- armMode ? armNextPC - 4 : armNextPC - 2);
- }
- }
-#endif
-
- address &= 0xFFFFFFFE;
-
- switch(address >> 24) {
- case 2:
-#ifdef BKPT_SUPPORT
- if(*((uint16_t *)&freezeWorkRAM[address & 0x3FFFE]))
- cheatsWriteHalfWord(address & 0x203FFFE,
- value);
- else
-#endif
- WRITE16LE(((uint16_t *)&workRAM[address & 0x3FFFE]),value);
- break;
- case 3:
-#ifdef BKPT_SUPPORT
- if(*((uint16_t *)&freezeInternalRAM[address & 0x7ffe]))
- cheatsWriteHalfWord(address & 0x3007ffe,
- value);
- else
-#endif
- WRITE16LE(((uint16_t *)&internalRAM[address & 0x7ffe]), value);
- break;
- case 4:
- if(address < 0x4000400)
- CPUUpdateRegister(address & 0x3fe, value);
- else goto unwritable;
- break;
- case 5:
-#ifdef BKPT_SUPPORT
- if(*((uint16_t *)&freezePRAM[address & 0x03fe]))
- cheatsWriteHalfWord(address & 0x70003fe,
- value);
- else
-#endif
- WRITE16LE(((uint16_t *)&paletteRAM[address & 0x3fe]), value);
- break;
- case 6:
- address = (address & 0x1fffe);
- if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
- return;
- if ((address & 0x18000) == 0x18000)
- address &= 0x17fff;
-#ifdef BKPT_SUPPORT
- if(*((uint16_t *)&freezeVRAM[address]))
- cheatsWriteHalfWord(address + 0x06000000,
- value);
- else
-#endif
- WRITE16LE(((uint16_t *)&vram[address]), value);
- break;
- case 7:
-#ifdef BKPT_SUPPORT
- if(*((uint16_t *)&freezeOAM[address & 0x03fe]))
- cheatsWriteHalfWord(address & 0x70003fe,
- value);
- else
-#endif
- WRITE16LE(((uint16_t *)&oam[address & 0x3fe]), value);
- break;
- case 8:
- case 9:
- /* if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) {
- if(!rtcWrite(address, value))
- goto unwritable;
- } else if(!agbPrintWrite(address, value)) goto unwritable;*/
- break;
- case 13:
- if(cpuEEPROMEnabled) {
- //eepromWrite(address, (u8)value);
- break;
- }
- goto unwritable;
- /*case 14:
- if(*//*(!eepromInUse) | *//*cpuSramEnabled | cpuFlashEnabled) {
- //(*cpuSaveGameFunc)(address, (u8)value);
- break;
- }
- goto unwritable;*/
- default:
-unwritable:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
- log("Illegal halfword write: %04x to %08x from %08x\n",
- value,
- address,
- armMode ? armNextPC - 4 : armNextPC - 2);
- }
-#endif
- break;
- }
-}
-
-static inline void CPUWriteByte(uint32_t address, uint8_t b)
-{
- switch(address >> 24) {
- case 2:
-#ifdef BKPT_SUPPORT
- if(freezeWorkRAM[address & 0x3FFFF])
- cheatsWriteByte(address & 0x203FFFF, b);
- else
-#endif
- workRAM[address & 0x3FFFF] = b;
- break;
- case 3:
-#ifdef BKPT_SUPPORT
- if(freezeInternalRAM[address & 0x7fff])
- cheatsWriteByte(address & 0x3007fff, b);
- else
-#endif
- internalRAM[address & 0x7fff] = b;
- break;
- case 4:
- if(address < 0x4000400) {
- switch(address & 0x3FF) {
- case 0x60:
- case 0x61:
- case 0x62:
- case 0x63:
- case 0x64:
- case 0x65:
- case 0x68:
- case 0x69:
- case 0x6c:
- case 0x6d:
- case 0x70:
- case 0x71:
- case 0x72:
- case 0x73:
- case 0x74:
- case 0x75:
- case 0x78:
- case 0x79:
- case 0x7c:
- case 0x7d:
- case 0x80:
- case 0x81:
- case 0x84:
- case 0x85:
- case 0x90:
- case 0x91:
- case 0x92:
- case 0x93:
- case 0x94:
- case 0x95:
- case 0x96:
- case 0x97:
- case 0x98:
- case 0x99:
- case 0x9a:
- case 0x9b:
- case 0x9c:
- case 0x9d:
- case 0x9e:
- case 0x9f:
- soundEvent(address&0xFF, b);
- break;
- case 0x301: // HALTCNT, undocumented
- if(b == 0x80)
- stopState = true;
- holdState = 1;
- holdType = -1;
- cpuNextEvent = cpuTotalTicks;
- break;
- default: // every other register
- uint32_t lowerBits = address & 0x3fe;
- if(address & 1) {
- CPUUpdateRegister(lowerBits, (READ16LE(&ioMem[lowerBits]) & 0x00FF) | (b << 8));
- } else {
- CPUUpdateRegister(lowerBits, (READ16LE(&ioMem[lowerBits]) & 0xFF00) | b);
- }
- }
- break;
- } else goto unwritable;
- break;
- case 5:
- // no need to switch
- *((uint16_t *)&paletteRAM[address & 0x3FE]) = (b << 8) | b;
- break;
- case 6:
- address = (address & 0x1fffe);
- if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
- return;
- if ((address & 0x18000) == 0x18000)
- address &= 0x17fff;
-
- // no need to switch
- // byte writes to OBJ VRAM are ignored
- if ((address) < objTilesAddress[((DISPCNT&7)+1)>>2])
- {
-#ifdef BKPT_SUPPORT
- if(freezeVRAM[address])
- cheatsWriteByte(address + 0x06000000, b);
- else
-#endif
- *((uint16_t *)&vram[address]) = (b << 8) | b;
- }
- break;
- case 7:
- // no need to switch
- // byte writes to OAM are ignored
- // *((uint16_t *)&oam[address & 0x3FE]) = (b << 8) | b;
- break;
- case 13:
- if(cpuEEPROMEnabled) {
- //eepromWrite(address, b);
- break;
- }
- goto unwritable;
- /*case 14:
- if ((saveType != 5) && (*//*(!eepromInUse) | *//*cpuSramEnabled | cpuFlashEnabled)) {
-
- //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) {
-
- //(*cpuSaveGameFunc)(address, b);
- break;
- }*/
- // default
- default:
-unwritable:
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
- log("Illegal byte write: %02x to %08x from %08x\n",
- b,
- address,
- armMode ? armNextPC - 4 : armNextPC -2 );
- }
-#endif
- break;
- }
+inline uint32_t CPUReadHalfWord(uint32_t address)
+{
+ uint32_t value;
+ uint32_t oldAddress = address;
+
+ if (address & 1)
+ address &= ~0x01;
+
+ switch (address >> 24)
+ {
+ case 0:
+ if (reg[15].I >> 24)
+ {
+ if (address < 0x4000)
+ value = READ16LE(&biosProtected[address & 2]);
+ else
+ goto unreadable;
+ }
+ else
+ value = READ16LE(&bios[address & 0x3FFE]);
+ break;
+ case 2:
+ value = READ16LE(&workRAM[address & 0x3FFFE]);
+ break;
+ case 3:
+ value = READ16LE(&internalRAM[address & 0x7ffe]);
+ break;
+ case 4:
+ if (address < 0x4000400 && ioReadable[address & 0x3fe])
+ {
+ value = READ16LE(&ioMem[address & 0x3fe]);
+ if ((address & 0x3fe) > 0xFF && (address & 0x3fe) < 0x10E)
+ {
+ if ((address & 0x3fe) == 0x100 && timer0On)
+ value = 0xFFFF - ((timer0Ticks - cpuTotalTicks) >> timer0ClockReload);
+ else if ((address & 0x3fe) == 0x104 && timer1On && !(TM1CNT & 4))
+ value = 0xFFFF - ((timer1Ticks - cpuTotalTicks) >> timer1ClockReload);
+ else if ((address & 0x3fe) == 0x108 && timer2On && !(TM2CNT & 4))
+ value = 0xFFFF - ((timer2Ticks - cpuTotalTicks) >> timer2ClockReload);
+ else if ((address & 0x3fe) == 0x10C && timer3On && !(TM3CNT & 4))
+ value = 0xFFFF - ((timer3Ticks - cpuTotalTicks) >> timer3ClockReload);
+ }
+ }
+ else
+ goto unreadable;
+ break;
+ case 5:
+ value = READ16LE(&paletteRAM[address & 0x3fe]);
+ break;
+ case 6:
+ address &= 0x1fffe;
+ if ((DISPCNT & 7) > 2 && (address & 0x1C000) == 0x18000)
+ {
+ value = 0;
+ break;
+ }
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ value = READ16LE(&vram[address]);
+ break;
+ case 7:
+ value = READ16LE(&oam[address & 0x3fe]);
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ if (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
+ value = 0;
+ else
+ value = READ16LE(&rom[address & 0x1FFFFFE]);
+ break;
+ case 13:
+ case 14:
+ return 0;
+ // default
+ default:
+ unreadable:
+ if (armState)
+ return CPUReadMemoryQuick(reg[15].I);
+ else
+ return CPUReadHalfWordQuick(reg[15].I) | CPUReadHalfWordQuick(reg[15].I) << 16;
+ }
+
+ if (oldAddress & 1)
+ value = (value >> 8) | (value << 24);
+
+ return value;
+}
+
+inline int16_t CPUReadHalfWordSigned(uint32_t address)
+{
+ uint32_t oldAddress = address;
+ if (address & 1)
+ address &= ~0x01;
+ int16_t value = static_cast<int16_t>(CPUReadHalfWord(address));
+ if (oldAddress & 1)
+ value = static_cast<int8_t>(value);
+ return value;
+}
+
+inline uint8_t CPUReadByte(uint32_t address)
+{
+ switch (address >> 24)
+ {
+ case 0:
+ if (reg[15].I >> 24)
+ {
+ if (address < 0x4000)
+ return biosProtected[address & 3];
+ else
+ goto unreadable;
+ }
+ return bios[address & 0x3FFF];
+ case 2:
+ return workRAM[address & 0x3FFFF];
+ case 3:
+ return internalRAM[address & 0x7fff];
+ case 4:
+ if (address < 0x4000400 && ioReadable[address & 0x3ff])
+ return ioMem[address & 0x3ff];
+ else
+ goto unreadable;
+ case 5:
+ return paletteRAM[address & 0x3ff];
+ case 6:
+ address &= 0x1ffff;
+ if ((DISPCNT & 7) > 2 && (address & 0x1C000) == 0x18000)
+ return 0;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ return vram[address];
+ case 7:
+ return oam[address & 0x3ff];
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ return rom[address & 0x1FFFFFF];
+ case 13:
+ case 14:
+ return 0;
+ // default
+ default:
+ unreadable:
+ if (armState)
+ return CPUReadMemoryQuick(reg[15].I);
+ else
+ return CPUReadHalfWordQuick(reg[15].I) | CPUReadHalfWordQuick(reg[15].I) << 16;
+ }
+}
+
+inline void CPUWriteMemory(uint32_t address, uint32_t value)
+{
+ address &= 0xFFFFFFFC;
+
+ switch (address >> 24)
+ {
+ case 0x02:
+ WRITE32LE(&workRAM[address & 0x3FFFC], value);
+ break;
+ case 0x03:
+ WRITE32LE(&internalRAM[address & 0x7ffC], value);
+ break;
+ case 0x04:
+ if (address < 0x4000400)
+ {
+ CPUUpdateRegister(address & 0x3FC, value & 0xFFFF);
+ CPUUpdateRegister((address & 0x3FC) + 2, value >> 16);
+ }
+ break;
+ case 0x05:
+ WRITE32LE(&paletteRAM[address & 0x3FC], value);
+ break;
+ case 0x06:
+ address &= 0x1fffc;
+ if ((DISPCNT & 7) > 2 && (address & 0x1C000) == 0x18000)
+ return;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ WRITE32LE(&vram[address], value);
+ break;
+ case 0x07:
+ WRITE32LE(&oam[address & 0x3fc], value);
+ }
+}
+
+inline void CPUWriteHalfWord(uint32_t address, uint16_t value)
+{
+ address &= 0xFFFFFFFE;
+
+ switch (address >> 24)
+ {
+ case 2:
+ WRITE16LE(&workRAM[address & 0x3FFFE], value);
+ break;
+ case 3:
+ WRITE16LE(&internalRAM[address & 0x7ffe], value);
+ break;
+ case 4:
+ if (address < 0x4000400)
+ CPUUpdateRegister(address & 0x3fe, value);
+ break;
+ case 5:
+ WRITE16LE(&paletteRAM[address & 0x3fe], value);
+ break;
+ case 6:
+ address &= 0x1fffe;
+ if ((DISPCNT & 7) > 2 && (address & 0x1C000) == 0x18000)
+ return;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+ WRITE16LE(&vram[address], value);
+ break;
+ case 7:
+ WRITE16LE(&oam[address & 0x3fe], value);
+ }
+}
+
+inline void CPUWriteByte(uint32_t address, uint8_t b)
+{
+ switch (address >> 24)
+ {
+ case 2:
+ workRAM[address & 0x3FFFF] = b;
+ break;
+ case 3:
+ internalRAM[address & 0x7fff] = b;
+ break;
+ case 4:
+ if (address < 0x4000400)
+ {
+ switch (address & 0x3FF)
+ {
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x68:
+ case 0x69:
+ case 0x6c:
+ case 0x6d:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x78:
+ case 0x79:
+ case 0x7c:
+ case 0x7d:
+ case 0x80:
+ case 0x81:
+ case 0x84:
+ case 0x85:
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ case 0x98:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0x9f:
+ soundEvent(address & 0xFF, b);
+ break;
+ case 0x301: // HALTCNT, undocumented
+ if (b == 0x80)
+ stopState = true;
+ holdState = true;
+ holdType = -1;
+ cpuNextEvent = cpuTotalTicks;
+ break;
+ default: // every other register
+ uint32_t lowerBits = address & 0x3fe;
+ if (address & 1)
+ CPUUpdateRegister(lowerBits, (READ16LE(&ioMem[lowerBits]) & 0x00FF) | (b << 8));
+ else
+ CPUUpdateRegister(lowerBits, (READ16LE(&ioMem[lowerBits]) & 0xFF00) | b);
+ }
+ break;
+ }
+ break;
+ case 5:
+ // no need to switch
+ *reinterpret_cast<uint16_t *>(&paletteRAM[address & 0x3FE]) = (b << 8) | b;
+ break;
+ case 6:
+ address &= 0x1fffe;
+ if ((DISPCNT & 7) > 2 && (address & 0x1C000) == 0x18000)
+ return;
+ if ((address & 0x18000) == 0x18000)
+ address &= 0x17fff;
+
+ // no need to switch
+ // byte writes to OBJ VRAM are ignored
+ if (address < objTilesAddress[((DISPCNT & 7) + 1) >> 2])
+ *reinterpret_cast<uint16_t *>(&vram[address]) = (b << 8) | b;
+ break;
+ case 7:
+ // no need to switch
+ // byte writes to OAM are ignored
+ //*reinterpret_cast<uint16_t *>(&oam[address & 0x3FE]) = (b << 8) | b;
+ break;
+ }
}
#endif // GBAINLINE_H
--- a/src/in_gsf/vbam/gba/Globals.cpp
+++ b/src/in_gsf/vbam/gba/Globals.cpp
@@ -1,96 +1,70 @@
#include "GBA.h"
-
-#ifdef BKPT_SUPPORT
-int oldreg[18];
-char oldbuffer[10];
-#endif
reg_pair reg[45];
memoryMap map[256];
bool ioReadable[0x400];
-bool N_FLAG = 0;
-bool C_FLAG = 0;
-bool Z_FLAG = 0;
-bool V_FLAG = 0;
+bool N_FLAG = false;
+bool C_FLAG = false;
+bool Z_FLAG = false;
+bool V_FLAG = false;
bool armState = true;
bool armIrqEnable = true;
uint32_t armNextPC = 0x00000000;
int armMode = 0x1f;
-uint32_t stop = 0x08000568;
-int saveType = 0;
-bool useBios = false;
-bool skipBios = false;
-int frameSkip = 1;
-bool speedup = false;
-bool synchronize = true;
-bool cpuDisableSfx = false;
bool cpuIsMultiBoot = false;
-bool parseDebug = true;
int layerSettings = 0xff00;
int layerEnable = 0xff00;
-bool speedHack = false;
-int cpuSaveType = 0;
-bool cheatsEnabled = true;
-bool mirroringEnable = false;
-bool skipSaveGameBattery = false;
-bool skipSaveGameCheats = false;
-// this is an optional hack to change the backdrop/background color:
-// -1: disabled
-// 0x0000 to 0x7FFF: set custom 15 bit color
-int customBackdropColor = -1;
+uint8_t bios[0x4000];
+uint8_t rom[0x2000000];
+uint8_t internalRAM[0x8000];
+uint8_t workRAM[0x40000];
+uint8_t paletteRAM[0x400];
+uint8_t vram[0x20000];
+uint8_t oam[0x400];
+uint8_t ioMem[0x400];
-uint8_t *bios = 0;
-uint8_t *rom = 0;
-uint8_t *internalRAM = 0;
-uint8_t *workRAM = 0;
-uint8_t *paletteRAM = 0;
-uint8_t *vram = 0;
-uint8_t *pix = 0;
-uint8_t *oam = 0;
-uint8_t *ioMem = 0;
-
-uint16_t DISPCNT = 0x0080;
+uint16_t DISPCNT = 0x0080;
uint16_t DISPSTAT = 0x0000;
-uint16_t VCOUNT = 0x0000;
-uint16_t BG0CNT = 0x0000;
-uint16_t BG1CNT = 0x0000;
-uint16_t BG2CNT = 0x0000;
-uint16_t BG3CNT = 0x0000;
-uint16_t BG0HOFS = 0x0000;
-uint16_t BG0VOFS = 0x0000;
-uint16_t BG1HOFS = 0x0000;
-uint16_t BG1VOFS = 0x0000;
-uint16_t BG2HOFS = 0x0000;
-uint16_t BG2VOFS = 0x0000;
-uint16_t BG3HOFS = 0x0000;
-uint16_t BG3VOFS = 0x0000;
-uint16_t BG2PA = 0x0100;
-uint16_t BG2PB = 0x0000;
-uint16_t BG2PC = 0x0000;
-uint16_t BG2PD = 0x0100;
-uint16_t BG2X_L = 0x0000;
-uint16_t BG2X_H = 0x0000;
-uint16_t BG2Y_L = 0x0000;
-uint16_t BG2Y_H = 0x0000;
-uint16_t BG3PA = 0x0100;
-uint16_t BG3PB = 0x0000;
-uint16_t BG3PC = 0x0000;
-uint16_t BG3PD = 0x0100;
-uint16_t BG3X_L = 0x0000;
-uint16_t BG3X_H = 0x0000;
-uint16_t BG3Y_L = 0x0000;
-uint16_t BG3Y_H = 0x0000;
-uint16_t WIN0H = 0x0000;
-uint16_t WIN1H = 0x0000;
-uint16_t WIN0V = 0x0000;
-uint16_t WIN1V = 0x0000;
-uint16_t WININ = 0x0000;
-uint16_t WINOUT = 0x0000;
-uint16_t MOSAIC = 0x0000;
-uint16_t BLDMOD = 0x0000;
-uint16_t COLEV = 0x0000;
-uint16_t COLY = 0x0000;
+uint16_t VCOUNT = 0x0000;
+uint16_t BG0CNT = 0x0000;
+uint16_t BG1CNT = 0x0000;
+uint16_t BG2CNT = 0x0000;
+uint16_t BG3CNT = 0x0000;
+uint16_t BG0HOFS = 0x0000;
+uint16_t BG0VOFS = 0x0000;
+uint16_t BG1HOFS = 0x0000;
+uint16_t BG1VOFS = 0x0000;
+uint16_t BG2HOFS = 0x0000;
+uint16_t BG2VOFS = 0x0000;
+uint16_t BG3HOFS = 0x0000;
+uint16_t BG3VOFS = 0x0000;
+uint16_t BG2PA = 0x0100;
+uint16_t BG2PB = 0x0000;
+uint16_t BG2PC = 0x0000;
+uint16_t BG2PD = 0x0100;
+uint16_t BG2X_L = 0x0000;
+uint16_t BG2X_H = 0x0000;
+uint16_t BG2Y_L = 0x0000;
+uint16_t BG2Y_H = 0x0000;
+uint16_t BG3PA = 0x0100;
+uint16_t BG3PB = 0x0000;
+uint16_t BG3PC = 0x0000;
+uint16_t BG3PD = 0x0100;
+uint16_t BG3X_L = 0x0000;
+uint16_t BG3X_H = 0x0000;
+uint16_t BG3Y_L = 0x0000;
+uint16_t BG3Y_H = 0x0000;
+uint16_t WIN0H = 0x0000;
+uint16_t WIN1H = 0x0000;
+uint16_t WIN0V = 0x0000;
+uint16_t WIN1V = 0x0000;
+uint16_t WININ = 0x0000;
+uint16_t WINOUT = 0x0000;
+uint16_t MOSAIC = 0x0000;
+uint16_t BLDMOD = 0x0000;
+uint16_t COLEV = 0x0000;
+uint16_t COLY = 0x0000;
uint16_t DM0SAD_L = 0x0000;
uint16_t DM0SAD_H = 0x0000;
uint16_t DM0DAD_L = 0x0000;
@@ -115,16 +89,16 @@
uint16_t DM3DAD_H = 0x0000;
uint16_t DM3CNT_L = 0x0000;
uint16_t DM3CNT_H = 0x0000;
-uint16_t TM0D = 0x0000;
-uint16_t TM0CNT = 0x0000;
-uint16_t TM1D = 0x0000;
-uint16_t TM1CNT = 0x0000;
-uint16_t TM2D = 0x0000;
-uint16_t TM2CNT = 0x0000;
-uint16_t TM3D = 0x0000;
-uint16_t TM3CNT = 0x0000;
-uint16_t P1 = 0xFFFF;
-uint16_t IE = 0x0000;
-uint16_t IF = 0x0000;
-uint16_t IME = 0x0000;
+uint16_t TM0D = 0x0000;
+uint16_t TM0CNT = 0x0000;
+uint16_t TM1D = 0x0000;
+uint16_t TM1CNT = 0x0000;
+uint16_t TM2D = 0x0000;
+uint16_t TM2CNT = 0x0000;
+uint16_t TM3D = 0x0000;
+uint16_t TM3CNT = 0x0000;
+uint16_t P1 = 0xFFFF;
+uint16_t IE = 0x0000;
+uint16_t IF = 0x0000;
+uint16_t IME = 0x0000;
--- a/src/in_gsf/vbam/gba/Globals.h
+++ b/src/in_gsf/vbam/gba/Globals.h
@@ -3,18 +3,6 @@
#include <cstdint>
#include "GBA.h"
-
-#define VERBOSE_SWI 1
-#define VERBOSE_UNALIGNED_MEMORY 2
-#define VERBOSE_ILLEGAL_WRITE 4
-#define VERBOSE_ILLEGAL_READ 8
-#define VERBOSE_DMA0 16
-#define VERBOSE_DMA1 32
-#define VERBOSE_DMA2 64
-#define VERBOSE_DMA3 128
-#define VERBOSE_UNDEFINED 256
-#define VERBOSE_AGBPRINT 512
-#define VERBOSE_SOUNDOUTPUT 1024
extern reg_pair reg[45];
extern bool ioReadable[0x400];
@@ -26,35 +14,18 @@
extern bool armIrqEnable;
extern uint32_t armNextPC;
extern int armMode;
-extern uint32_t stop;
-extern int saveType;
-extern bool useBios;
-extern bool skipBios;
-extern int frameSkip;
-extern bool speedup;
-extern bool synchronize;
-extern bool cpuDisableSfx;
extern bool cpuIsMultiBoot;
-extern bool parseDebug;
extern int layerSettings;
extern int layerEnable;
-extern bool speedHack;
-extern int cpuSaveType;
-extern bool cheatsEnabled;
-extern bool mirroringEnable;
-extern bool skipSaveGameBattery; // skip battery data when reading save states
-extern bool skipSaveGameCheats; // skip cheat list data when reading save states
-extern int customBackdropColor;
-extern uint8_t *bios;
-extern uint8_t *rom;
-extern uint8_t *internalRAM;
-extern uint8_t *workRAM;
-extern uint8_t *paletteRAM;
-extern uint8_t *vram;
-extern uint8_t *pix;
-extern uint8_t *oam;
-extern uint8_t *ioMem;
+extern uint8_t bios[0x4000];
+extern uint8_t rom[0x2000000];
+extern uint8_t internalRAM[0x8000];
+extern uint8_t workRAM[0x40000];
+extern uint8_t paletteRAM[0x400];
+extern uint8_t vram[0x20000];
+extern uint8_t oam[0x400];
+extern uint8_t ioMem[0x400];
extern uint16_t DISPCNT;
extern uint16_t DISPSTAT;
--- a/src/in_gsf/vbam/gba/Sound.cpp
+++ b/src/in_gsf/vbam/gba/Sound.cpp
@@ -1,275 +1,268 @@
-#include <string.h>
-
+#include <memory>
#include "Sound.h"
-
#include "GBA.h"
#include "Globals.h"
-//#include "../Util.h"
#include "../common/Port.h"
-
#include "../apu/Gb_Apu.h"
#include "../apu/Multi_Buffer.h"
-
#include "../common/SoundDriver.h"
extern SoundDriver *systemSoundInit();
bool soundDeclicking = true;
-#define NR10 0x60
-#define NR11 0x62
-#define NR12 0x63
-#define NR13 0x64
-#define NR14 0x65
-#define NR21 0x68
-#define NR22 0x69
-#define NR23 0x6c
-#define NR24 0x6d
-#define NR30 0x70
-#define NR31 0x72
-#define NR32 0x73
-#define NR33 0x74
-#define NR34 0x75
-#define NR41 0x78
-#define NR42 0x79
-#define NR43 0x7c
-#define NR44 0x7d
-#define NR50 0x80
-#define NR51 0x81
-#define NR52 0x84
-
-SoundDriver * soundDriver = 0;
-
-extern bool stopState; // TODO: silence sound when true
-
-int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
-
-static uint16_t soundFinalWave [6400];
-long soundSampleRate = 44100;
-bool soundInterpolation = true;
-bool soundPaused = true;
-float soundFiltering = 0.5f;
-int SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
-int soundTicks = SOUND_CLOCK_TICKS_;
-
-static float soundVolume = 1.0f;
-static int soundEnableFlag = 0x3ff; // emulator channels enabled
+static const uint32_t NR52 = 0x84;
+
+static std::unique_ptr<SoundDriver> soundDriver;
+
+static const int SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
+
+static uint16_t soundFinalWave[6400];
+static long soundSampleRate = 44100;
+bool soundInterpolation = true;
+static bool soundPaused = true;
+static float soundFiltering = 0.5f; // 0.0 = none, 1.0 = max
+int SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
+int soundTicks = SOUND_CLOCK_TICKS_;
+
+static float soundVolume = 1.0f;
+static int soundEnableFlag = 0x30f; // emulator channels enabled
static float soundFiltering_ = -1;
-static float soundVolume_ = -1;
-
-void interp_rate() { /* empty for now */ }
-
-class Gba_Pcm {
+static float soundVolume_ = -1;
+
+class Gba_Pcm
+{
public:
void init();
- void apply_control( int idx );
- void update( int dac );
- void end_frame( blip_time_t );
+ void apply_control(int idx);
+ void update(int dac);
+ void end_frame(blip_time_t);
private:
- Blip_Buffer* output;
+ Blip_Buffer *output;
blip_time_t last_time;
int last_amp;
int shift;
};
-class Gba_Pcm_Fifo {
+class Gba_Pcm_Fifo
+{
public:
- int which;
+ int which;
Gba_Pcm pcm;
- void write_control( int data );
- void write_fifo( int data );
- void timer_overflowed( int which_timer );
-
- // public only so save state routines can access it
- int readIndex;
- int count;
- int writeIndex;
- uint8_t fifo [32];
- int dac;
+ void write_control(int data);
+ void write_fifo(int data);
+ void timer_overflowed(int which_timer);
+
private:
-
- int timer;
+ int readIndex;
+ int count;
+ int writeIndex;
+ uint8_t fifo[32];
+ int dac;
+ int timer;
bool enabled;
};
-static Gba_Pcm_Fifo pcm [2];
-static Gb_Apu* gb_apu;
-static Stereo_Buffer* stereo_buffer;
-
-static Blip_Synth<blip_best_quality,1> pcm_synth [3]; // 32 kHz, 16 kHz, 8 kHz
+static Gba_Pcm_Fifo pcm[2];
+static std::unique_ptr<Gb_Apu> gb_apu;
+static std::unique_ptr<Stereo_Buffer> stereo_buffer;
+
+static Blip_Synth<blip_best_quality, 1> pcm_synth[3]; // 32 kHz, 16 kHz, 8 kHz
static inline blip_time_t blip_time()
{
return SOUND_CLOCK_TICKS - soundTicks;
}
-void Gba_Pcm::init()
-{
- output = 0;
- last_time = 0;
- last_amp = 0;
- shift = 0;
-}
-
-void Gba_Pcm::apply_control( int idx )
-{
- shift = ~ioMem [SGCNT0_H] >> (2 + idx) & 1;
+inline void Gba_Pcm::init()
+{
+ this->output = nullptr;
+ this->last_time = 0;
+ this->last_amp = 0;
+ this->shift = 0;
+}
+
+void Gba_Pcm::apply_control(int idx)
+{
+ this->shift = (~ioMem[SGCNT0_H] >> (2 + idx)) & 1;
int ch = 0;
- if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) )
- ch = ioMem [SGCNT0_H+1] >> (idx * 4) & 3;
-
- Blip_Buffer* out = 0;
- switch ( ch )
- {
- case 1: out = stereo_buffer->right(); break;
- case 2: out = stereo_buffer->left(); break;
- case 3: out = stereo_buffer->center(); break;
- }
-
- if ( output != out )
- {
- if ( output )
+ if (((soundEnableFlag >> idx) & 0x100) && (ioMem[NR52] & 0x80))
+ ch = (ioMem[SGCNT0_H + 1] >> (idx * 4)) & 3;
+
+ Blip_Buffer *out = nullptr;
+ switch (ch)
+ {
+ case 1:
+ out = stereo_buffer->right();
+ break;
+ case 2:
+ out = stereo_buffer->left();
+ break;
+ case 3:
+ out = stereo_buffer->center();
+ }
+
+ if (this->output != out)
+ {
+ if (this->output)
{
- output->set_modified();
- pcm_synth [0].offset( blip_time(), -last_amp, output );
- }
- last_amp = 0;
- output = out;
- }
-}
-
-void Gba_Pcm::end_frame( blip_time_t time )
-{
- last_time -= time;
- if ( last_time < -2048 )
- last_time = -2048;
-
- if ( output )
- output->set_modified();
-}
-
-void Gba_Pcm::update( int dac )
-{
- if ( output )
- {
- blip_time_t time = blip_time();
-
- dac = (int8_t) dac >> shift;
- int delta = dac - last_amp;
- if ( delta )
- {
- last_amp = dac;
+ blip_time_t time = blip_time();
+
+ this->output->set_modified();
int filter = 0;
- if ( soundInterpolation )
+ if (soundInterpolation)
{
// base filtering on how long since last sample was output
- int period = time - last_time;
-
- int idx = (unsigned) period / 512;
- if ( idx >= 3 )
+ int period = time - this->last_time;
+
+ int idx = period / 512;
+ if (idx >= 3)
idx = 3;
- static int const filters [4] = { 0, 0, 1, 2 };
- filter = filters [idx];
+ static const int filters[] = { 0, 0, 1, 2 };
+ filter = filters[idx];
}
- pcm_synth [filter].offset( time, delta, output );
+ pcm_synth[filter].offset(time, -this->last_amp, this->output);
}
- last_time = time;
- }
-}
-
-void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
-{
- if ( which_timer == timer && enabled )
- {
- if ( count <= 16 )
+ this->last_amp = 0;
+ this->output = out;
+ }
+}
+
+inline void Gba_Pcm::end_frame(blip_time_t time)
+{
+ this->last_time -= time;
+ if (this->last_time < -2048)
+ this->last_time = -2048;
+
+ if (this->output)
+ this->output->set_modified();
+}
+
+void Gba_Pcm::update(int dac)
+{
+ if (this->output)
+ {
+ blip_time_t time = blip_time();
+
+ dac = static_cast<int8_t>(dac) >> this->shift;
+ int delta = dac - this->last_amp;
+ if (delta)
+ {
+ this->last_amp = dac;
+
+ int filter = 0;
+ if (soundInterpolation)
+ {
+ // base filtering on how long since last sample was output
+ int period = time - this->last_time;
+
+ int idx = period / 512;
+ if (idx >= 3)
+ idx = 3;
+
+ static const int filters[] = { 0, 0, 1, 2 };
+ filter = filters[idx];
+ }
+
+ pcm_synth[filter].offset(time, delta, this->output);
+ }
+ this->last_time = time;
+ }
+}
+
+void Gba_Pcm_Fifo::timer_overflowed(int which_timer)
+{
+ if (which_timer == this->timer && this->enabled)
+ {
+ if (this->count <= 16)
{
// Need to fill FIFO
- CPUCheckDMA( 3, which ? 4 : 2 );
- if ( count <= 16 )
+ CPUCheckDMA(3, this->which ? 4 : 2);
+ if (this->count <= 16)
{
// Not filled by DMA, so fill with 16 bytes of silence
- int reg = which ? FIFOB_L : FIFOA_L;
- for ( int n = 4; n--; )
+ int reg = this->which ? FIFOB_L : FIFOA_L;
+ for (int n = 4; n--; )
{
- soundEvent(reg , (uint16_t)0);
- soundEvent(reg+2, (uint16_t)0);
+ soundEvent(reg, static_cast<uint16_t>(0));
+ soundEvent(reg + 2, static_cast<uint16_t>(0));
}
}
}
// Read next sample from FIFO
- count--;
- dac = fifo [readIndex];
- readIndex = (readIndex + 1) & 31;
- pcm.update( dac );
- }
-}
-
-void Gba_Pcm_Fifo::write_control( int data )
-{
- enabled = (data & 0x0300) ? true : false;
- timer = (data & 0x0400) ? 1 : 0;
-
- if ( data & 0x0800 )
+ --this->count;
+ this->dac = this->fifo[this->readIndex];
+ this->readIndex = (this->readIndex + 1) & 31;
+ this->pcm.update(this->dac);
+ }
+}
+
+void Gba_Pcm_Fifo::write_control(int data)
+{
+ this->enabled = !!(data & 0x0300);
+ this->timer = !!(data & 0x0400);
+
+ if (data & 0x0800)
{
// Reset
- writeIndex = 0;
- readIndex = 0;
- count = 0;
- dac = 0;
- memset( fifo, 0, sizeof fifo );
- }
-
- pcm.apply_control( which );
- pcm.update( dac );
-}
-
-void Gba_Pcm_Fifo::write_fifo( int data )
-{
- fifo [writeIndex ] = data & 0xFF;
- fifo [writeIndex+1] = data >> 8;
- count += 2;
- writeIndex = (writeIndex + 2) & 31;
+ this->writeIndex = 0;
+ this->readIndex = 0;
+ this->count = 0;
+ this->dac = 0;
+ memset(this->fifo, 0, sizeof(this->fifo));
+ }
+
+ this->pcm.apply_control(this->which);
+ this->pcm.update(this->dac);
+}
+
+inline void Gba_Pcm_Fifo::write_fifo(int data)
+{
+ this->fifo[this->writeIndex] = data & 0xFF;
+ this->fifo[this->writeIndex + 1] = data >> 8;
+ this->count += 2;
+ this->writeIndex = (this->writeIndex + 2) & 31;
}
static void apply_control()
{
- pcm [0].pcm.apply_control( 0 );
- pcm [1].pcm.apply_control( 1 );
-}
-
-static int gba_to_gb_sound( int addr )
-{
- static const int table [0x40] =
- {
- 0xFF10, 0,0xFF11,0xFF12,0xFF13,0xFF14, 0, 0,
- 0xFF16,0xFF17, 0, 0,0xFF18,0xFF19, 0, 0,
- 0xFF1A, 0,0xFF1B,0xFF1C,0xFF1D,0xFF1E, 0, 0,
- 0xFF20,0xFF21, 0, 0,0xFF22,0xFF23, 0, 0,
- 0xFF24,0xFF25, 0, 0,0xFF26, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
- 0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,
+ pcm[0].pcm.apply_control(0);
+ pcm[1].pcm.apply_control(1);
+}
+
+static int gba_to_gb_sound(int addr)
+{
+ static const int table[] =
+ {
+ 0xFF10, 0, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0, 0,
+ 0xFF16, 0xFF17, 0, 0, 0xFF18, 0xFF19, 0, 0,
+ 0xFF1A, 0, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0, 0,
+ 0xFF20, 0xFF21, 0, 0, 0xFF22, 0xFF23, 0, 0,
+ 0xFF24, 0xFF25, 0, 0, 0xFF26, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
+ 0xFF38, 0xFF39, 0xFF3A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
};
- if ( addr >= 0x60 && addr < 0xA0 )
- return table [addr - 0x60];
+ if (addr >= 0x60 && addr < 0xA0)
+ return table[addr - 0x60];
return 0;
}
void soundEvent(uint32_t address, uint8_t data)
{
- int gb_addr = gba_to_gb_sound( address );
- if ( gb_addr )
+ int gb_addr = gba_to_gb_sound(address);
+ if (gb_addr)
{
ioMem[address] = data;
- gb_apu->write_register( blip_time(), gb_addr, data );
-
- if ( address == NR52 )
+ gb_apu->write_register(blip_time(), gb_addr, data);
+
+ if (address == NR52)
apply_control();
}
@@ -278,102 +271,98 @@
// TODO: what about byte writes to SGCNT0_H etc.?
}
-static void apply_volume( bool apu_only = false )
-{
- if ( !apu_only )
+static void apply_volume(bool apu_only = false)
+{
+ if (!apu_only)
soundVolume_ = soundVolume;
- if ( gb_apu )
- {
- static float const apu_vols [4] = { 0.25, 0.5, 1, 0.25 };
- gb_apu->volume( soundVolume_ * apu_vols [ioMem [SGCNT0_H] & 3] );
- }
-
- if ( !apu_only )
- {
- for ( int i = 0; i < 3; i++ )
- pcm_synth [i].volume( 0.66 / 256 * soundVolume_ );
- }
-}
-
-static void write_SGCNT0_H( int data )
-{
- WRITE16LE( &ioMem [SGCNT0_H], data & 0x770F );
- pcm [0].write_control( data );
- pcm [1].write_control( data >> 4 );
- apply_volume( true );
+ if (gb_apu)
+ {
+ static const float apu_vols[] = { 0.25, 0.5, 1, 0.25 };
+ gb_apu->volume(soundVolume_ * apu_vols[ioMem[SGCNT0_H] & 3]);
+ }
+
+ if (!apu_only)
+ for (int i = 0; i < 3; ++i)
+ pcm_synth[i].volume(0.66 / 256 * soundVolume_);
+}
+
+static void write_SGCNT0_H(int data)
+{
+ WRITE16LE(&ioMem[SGCNT0_H], data & 0x770F);
+ pcm[0].write_control(data);
+ pcm[1].write_control(data >> 4);
+ apply_volume(true);
}
void soundEvent(uint32_t address, uint16_t data)
{
- switch ( address )
- {
- case SGCNT0_H:
- write_SGCNT0_H( data );
- break;
-
- case FIFOA_L:
- case FIFOA_H:
- pcm [0].write_fifo( data );
- WRITE16LE( &ioMem[address], data );
- break;
-
- case FIFOB_L:
- case FIFOB_H:
- pcm [1].write_fifo( data );
- WRITE16LE( &ioMem[address], data );
- break;
-
- case 0x88:
- data &= 0xC3FF;
- WRITE16LE( &ioMem[address], data );
- break;
-
- default:
- soundEvent( address & ~1, (uint8_t) (data ) ); // even
- soundEvent( address | 1, (uint8_t) (data >> 8) ); // odd
- break;
+ switch (address)
+ {
+ case SGCNT0_H:
+ write_SGCNT0_H(data);
+ break;
+
+ case FIFOA_L:
+ case FIFOA_H:
+ pcm[0].write_fifo(data);
+ WRITE16LE(&ioMem[address], data);
+ break;
+
+ case FIFOB_L:
+ case FIFOB_H:
+ pcm[1].write_fifo(data);
+ WRITE16LE(&ioMem[address], data);
+ break;
+
+ case 0x88:
+ data &= 0xC3FF;
+ WRITE16LE(&ioMem[address], data);
+ break;
+
+ default:
+ soundEvent(address & ~1, static_cast<uint8_t>(data)); // even
+ soundEvent(address | 1, static_cast<uint8_t>(data >> 8)); // odd
}
}
void soundTimerOverflow(int timer)
{
- pcm [0].timer_overflowed( timer );
- pcm [1].timer_overflowed( timer );
-}
-
-static void end_frame( blip_time_t time )
-{
- pcm [0].pcm.end_frame( time );
- pcm [1].pcm.end_frame( time );
-
- gb_apu ->end_frame( time );
- stereo_buffer->end_frame( time );
-}
-
-void flush_samples(Multi_Buffer * buffer)
+ pcm[0].timer_overflowed(timer);
+ pcm[1].timer_overflowed(timer);
+}
+
+static void end_frame(blip_time_t time)
+{
+ pcm[0].pcm.end_frame(time);
+ pcm[1].pcm.end_frame(time);
+
+ gb_apu->end_frame(time);
+ stereo_buffer->end_frame(time);
+}
+
+void flush_samples(Multi_Buffer *buffer)
{
// We want to write the data frame by frame to support legacy audio drivers
// that don't use the length parameter of the write method.
// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
// samples at once to help reducing the audio delay on all platforms.
- int soundBufferLen = ( soundSampleRate / 60 ) * 4;
+ int soundBufferLen = (soundSampleRate / 60) * 4;
// soundBufferLen should have a whole number of sample pairs
- assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 );
+ assert(!(soundBufferLen % (2 * sizeof(*soundFinalWave))));
// number of samples in output buffer
- int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
+ int out_buf_size = soundBufferLen / sizeof(*soundFinalWave);
// Keep filling and writing soundFinalWave until it can't be fully filled
- while ( buffer->samples_avail() >= out_buf_size )
- {
- buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size );
- if(soundPaused)
+ while (buffer->samples_avail() >= out_buf_size)
+ {
+ buffer->read_samples(reinterpret_cast<blip_sample_t *>(soundFinalWave), out_buf_size);
+ if (soundPaused)
soundResume();
soundDriver->write(soundFinalWave, soundBufferLen);
- //systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
}
}
@@ -381,31 +370,31 @@
{
soundFiltering_ = soundFiltering;
- int const base_freq = (int) (32768 - soundFiltering_ * 16384);
- int const nyquist = stereo_buffer->sample_rate() / 2;
-
- for ( int i = 0; i < 3; i++ )
+ int base_freq = static_cast<int>(32768 - soundFiltering_ * 16384);
+ int nyquist = stereo_buffer->sample_rate() / 2;
+
+ for (int i = 0; i < 3; ++i)
{
int cutoff = base_freq >> i;
- if ( cutoff > nyquist )
+ if (cutoff > nyquist)
cutoff = nyquist;
- pcm_synth [i].treble_eq( blip_eq_t( 0, 0, stereo_buffer->sample_rate(), cutoff ) );
+ pcm_synth[i].treble_eq(blip_eq_t(0, 0, stereo_buffer->sample_rate(), cutoff));
}
}
void psoundTickfn()
{
- if ( gb_apu && stereo_buffer )
+ if (gb_apu && stereo_buffer)
{
// Run sound hardware to present
- end_frame( SOUND_CLOCK_TICKS );
-
- flush_samples(stereo_buffer);
-
- if ( soundFiltering_ != soundFiltering )
+ end_frame(SOUND_CLOCK_TICKS);
+
+ flush_samples(stereo_buffer.get());
+
+ if (soundFiltering_ != soundFiltering)
apply_filtering();
- if ( soundVolume_ != soundVolume )
+ if (soundVolume_ != soundVolume)
apply_volume();
}
@@ -414,32 +403,27 @@
static void apply_muting()
{
- if ( !stereo_buffer || !ioMem )
+ if (!stereo_buffer)
return;
// PCM
apply_control();
- if ( gb_apu )
- {
+ if (gb_apu)
// APU
- for ( int i = 0; i < 4; i++ )
- {
- if ( soundEnableFlag >> i & 1 )
- gb_apu->set_output( stereo_buffer->center(),
- stereo_buffer->left(), stereo_buffer->right(), i );
+ for (int i = 0; i < 4; ++i)
+ if ((soundEnableFlag >> i) & 1)
+ gb_apu->set_output(stereo_buffer->center(), stereo_buffer->left(), stereo_buffer->right(), i);
else
- gb_apu->set_output( 0, 0, 0, i );
- }
- }
+ gb_apu->set_output(nullptr, nullptr, nullptr, i);
}
static void reset_apu()
{
gb_apu->reduce_clicks(soundDeclicking);
- gb_apu->reset( gb_apu->mode_agb, true );
-
- if ( stereo_buffer )
+ gb_apu->reset(gb_apu->mode_agb, true);
+
+ if (stereo_buffer)
stereo_buffer->clear();
soundTicks = SOUND_CLOCK_TICKS;
@@ -447,31 +431,25 @@
static void remake_stereo_buffer()
{
- if ( !ioMem )
- return;
-
// Clears pointers kept to old stereo_buffer
- pcm [0].pcm.init();
- pcm [1].pcm.init();
+ pcm[0].pcm.init();
+ pcm[1].pcm.init();
// APU
- if ( !gb_apu )
- {
- gb_apu = new Gb_Apu; // TODO: handle out of memory
+ if (!gb_apu)
+ {
+ gb_apu.reset(new Gb_Apu); // TODO: handle out of memory
reset_apu();
}
// Stereo_Buffer
- delete stereo_buffer;
- stereo_buffer = 0;
-
- stereo_buffer = new Stereo_Buffer; // TODO: handle out of memory
- stereo_buffer->set_sample_rate( soundSampleRate ); // TODO: handle out of memory
- stereo_buffer->clock_rate( gb_apu->clock_rate );
+ stereo_buffer.reset(new Stereo_Buffer); // TODO: handle out of memory
+ stereo_buffer->set_sample_rate(soundSampleRate); // TODO: handle out of memory
+ stereo_buffer->clock_rate(gb_apu->clock_rate);
// PCM
- pcm [0].which = 0;
- pcm [1].which = 1;
+ pcm[0].which = 0;
+ pcm[1].which = 1;
apply_filtering();
// Volume Level
@@ -481,27 +459,13 @@
void soundShutdown()
{
- if (soundDriver)
- {
- delete soundDriver;
- soundDriver = 0;
- }
+ soundDriver.reset();
// APU
- if ( gb_apu )
- {
- delete gb_apu;
- gb_apu = 0;
- }
+ gb_apu.reset();
// Stereo_Buffer
- if (stereo_buffer)
- {
- delete stereo_buffer;
- stereo_buffer = 0;
- }
-
- //systemOnSoundShutdown();
+ stereo_buffer.reset();
}
void soundPause()
@@ -518,27 +482,12 @@
soundDriver->resume();
}
-void soundSetVolume( float volume )
-{
- soundVolume = volume;
-}
-
-float soundGetVolume()
-{
- return soundVolume;
-}
-
void soundSetEnable(int channels)
{
soundEnableFlag = channels;
apply_muting();
}
-int soundGetEnable()
-{
- return (soundEnableFlag & 0x30f);
-}
-
void soundReset()
{
soundDriver->reset();
@@ -547,16 +496,15 @@
reset_apu();
soundPaused = true;
- SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
- soundTicks = SOUND_CLOCK_TICKS_;
-
- soundEvent( NR52, (uint8_t) 0x80 );
+ SOUND_CLOCK_TICKS = soundTicks = SOUND_CLOCK_TICKS_;
+
+ soundEvent(NR52, static_cast<uint8_t>(0x80));
}
bool soundInit()
{
- soundDriver = systemSoundInit();
- if ( !soundDriver )
+ soundDriver.reset(systemSoundInit());
+ if (!soundDriver)
return false;
if (!soundDriver->init(soundSampleRate))
@@ -566,267 +514,13 @@
return true;
}
-void soundSetThrottle(unsigned short throttle)
-{
- if(!soundDriver)
- return;
- soundDriver->setThrottle(throttle);
-}
-
-long soundGetSampleRate()
-{
- return soundSampleRate;
-}
-
void soundSetSampleRate(long sampleRate)
{
- if ( soundSampleRate != sampleRate )
- {
- /*if ( systemCanChangeSoundQuality() )
- {
- soundShutdown();
- soundSampleRate = sampleRate;
- soundInit();
- }
- else*/
- {
- soundSampleRate = sampleRate;
- }
+ if (soundSampleRate != sampleRate)
+ {
+ soundSampleRate = sampleRate;
remake_stereo_buffer();
}
}
-/*static int dummy_state [16];
-
-#define SKIP( type, name ) { dummy_state, sizeof (type) }
-
-#define LOAD( type, name ) { &name, sizeof (type) }
-
-static struct {
- gb_apu_state_t apu;
-
- // old state
- u8 soundDSAValue;
- int soundDSBValue;
-} state;
-
-// Old GBA sound state format
-static variable_desc old_gba_state [] =
-{
- SKIP( int, soundPaused ),
- SKIP( int, soundPlay ),
- SKIP( int, soundTicks ),
- SKIP( int, SOUND_CLOCK_TICKS ),
- SKIP( int, soundLevel1 ),
- SKIP( int, soundLevel2 ),
- SKIP( int, soundBalance ),
- SKIP( int, soundMasterOn ),
- SKIP( int, soundIndex ),
- SKIP( int, sound1On ),
- SKIP( int, sound1ATL ),
- SKIP( int, sound1Skip ),
- SKIP( int, sound1Index ),
- SKIP( int, sound1Continue ),
- SKIP( int, sound1EnvelopeVolume ),
- SKIP( int, sound1EnvelopeATL ),
- SKIP( int, sound1EnvelopeATLReload ),
- SKIP( int, sound1EnvelopeUpDown ),
- SKIP( int, sound1SweepATL ),
- SKIP( int, sound1SweepATLReload ),
- SKIP( int, sound1SweepSteps ),
- SKIP( int, sound1SweepUpDown ),
- SKIP( int, sound1SweepStep ),
- SKIP( int, sound2On ),
- SKIP( int, sound2ATL ),
- SKIP( int, sound2Skip ),
- SKIP( int, sound2Index ),
- SKIP( int, sound2Continue ),
- SKIP( int, sound2EnvelopeVolume ),
- SKIP( int, sound2EnvelopeATL ),
- SKIP( int, sound2EnvelopeATLReload ),
- SKIP( int, sound2EnvelopeUpDown ),
- SKIP( int, sound3On ),
- SKIP( int, sound3ATL ),
- SKIP( int, sound3Skip ),
- SKIP( int, sound3Index ),
- SKIP( int, sound3Continue ),
- SKIP( int, sound3OutputLevel ),
- SKIP( int, sound4On ),
- SKIP( int, sound4ATL ),
- SKIP( int, sound4Skip ),
- SKIP( int, sound4Index ),
- SKIP( int, sound4Clock ),
- SKIP( int, sound4ShiftRight ),
- SKIP( int, sound4ShiftSkip ),
- SKIP( int, sound4ShiftIndex ),
- SKIP( int, sound4NSteps ),
- SKIP( int, sound4CountDown ),
- SKIP( int, sound4Continue ),
- SKIP( int, sound4EnvelopeVolume ),
- SKIP( int, sound4EnvelopeATL ),
- SKIP( int, sound4EnvelopeATLReload ),
- SKIP( int, sound4EnvelopeUpDown ),
- LOAD( int, soundEnableFlag ),
- SKIP( int, soundControl ),
- LOAD( int, pcm [0].readIndex ),
- LOAD( int, pcm [0].count ),
- LOAD( int, pcm [0].writeIndex ),
- SKIP( u8, soundDSAEnabled ), // was bool, which was one byte on MS compiler
- SKIP( int, soundDSATimer ),
- LOAD( u8 [32], pcm [0].fifo ),
- LOAD( u8, state.soundDSAValue ),
- LOAD( int, pcm [1].readIndex ),
- LOAD( int, pcm [1].count ),
- LOAD( int, pcm [1].writeIndex ),
- SKIP( int, soundDSBEnabled ),
- SKIP( int, soundDSBTimer ),
- LOAD( u8 [32], pcm [1].fifo ),
- LOAD( int, state.soundDSBValue ),
-
- // skipped manually
- //LOAD( int, soundBuffer[0][0], 6*735 },
- //LOAD( int, soundFinalWave[0], 2*735 },
- { NULL, 0 }
-};
-
-variable_desc old_gba_state2 [] =
-{
- LOAD( u8 [0x20], state.apu.regs [0x20] ),
- SKIP( int, sound3Bank ),
- SKIP( int, sound3DataSize ),
- SKIP( int, sound3ForcedOutput ),
- { NULL, 0 }
-};
-
-// New state format
-static variable_desc gba_state [] =
-{
- // PCM
- LOAD( int, pcm [0].readIndex ),
- LOAD( int, pcm [0].count ),
- LOAD( int, pcm [0].writeIndex ),
- LOAD(u8[32],pcm[0].fifo ),
- LOAD( int, pcm [0].dac ),
-
- SKIP( int [4], room_for_expansion ),
-
- LOAD( int, pcm [1].readIndex ),
- LOAD( int, pcm [1].count ),
- LOAD( int, pcm [1].writeIndex ),
- LOAD(u8[32],pcm[1].fifo ),
- LOAD( int, pcm [1].dac ),
-
- SKIP( int [4], room_for_expansion ),
-
- // APU
- LOAD( u8 [0x40], state.apu.regs ), // last values written to registers and wave RAM (both banks)
- LOAD( int, state.apu.frame_time ), // clocks until next frame sequencer action
- LOAD( int, state.apu.frame_phase ), // next step frame sequencer will run
-
- LOAD( int, state.apu.sweep_freq ), // sweep's internal frequency register
- LOAD( int, state.apu.sweep_delay ), // clocks until next sweep action
- LOAD( int, state.apu.sweep_enabled ),
- LOAD( int, state.apu.sweep_neg ), // obscure internal flag
- LOAD( int, state.apu.noise_divider ),
- LOAD( int, state.apu.wave_buf ), // last read byte of wave RAM
-
- LOAD( int [4], state.apu.delay ), // clocks until next channel action
- LOAD( int [4], state.apu.length_ctr ),
- LOAD( int [4], state.apu.phase ), // square/wave phase, noise LFSR
- LOAD( int [4], state.apu.enabled ), // internal enabled flag
-
- LOAD( int [3], state.apu.env_delay ), // clocks until next envelope action
- LOAD( int [3], state.apu.env_volume ),
- LOAD( int [3], state.apu.env_enabled ),
-
- SKIP( int [13], room_for_expansion ),
-
- // Emulator
- LOAD( int, soundEnableFlag ),
-
- SKIP( int [15], room_for_expansion ),
-
- { NULL, 0 }
-};
-
-// Reads and discards count bytes from in
-static void skip_read( gzFile in, int count )
-{
- char buf [512];
-
- while ( count )
- {
- int n = sizeof buf;
- if ( n > count )
- n = count;
-
- count -= n;
- utilGzRead( in, buf, n );
- }
-}
-
-void soundSaveGame( gzFile out )
-{
- gb_apu->save_state( &state.apu );
-
- // Be sure areas for expansion get written as zero
- memset( dummy_state, 0, sizeof dummy_state );
-
- utilWriteData( out, gba_state );
-}
-
-static void soundReadGameOld( gzFile in, int version )
-{
- // Read main data
- utilReadData( in, old_gba_state );
- skip_read( in, 6*735 + 2*735 );
-
- // Copy APU regs
- static int const regs_to_copy [] = {
- NR10, NR11, NR12, NR13, NR14,
- NR21, NR22, NR23, NR24,
- NR30, NR31, NR32, NR33, NR34,
- NR41, NR42, NR43, NR44,
- NR50, NR51, NR52, -1
- };
-
- ioMem [NR52] |= 0x80; // old sound played even when this wasn't set (power on)
-
- for ( int i = 0; regs_to_copy [i] >= 0; i++ )
- state.apu.regs [gba_to_gb_sound( regs_to_copy [i] ) - 0xFF10] = ioMem [regs_to_copy [i]];
-
- // Copy wave RAM to both banks
- memcpy( &state.apu.regs [0x20], &ioMem [0x90], 0x10 );
- memcpy( &state.apu.regs [0x30], &ioMem [0x90], 0x10 );
-
- // Read both banks of wave RAM if available
- if ( version >= SAVE_GAME_VERSION_3 )
- utilReadData( in, old_gba_state2 );
-
- // Restore PCM
- pcm [0].dac = state.soundDSAValue;
- pcm [1].dac = state.soundDSBValue;
-
- (void) utilReadInt( in ); // ignore quality
-}
-
-#include <stdio.h>
-
-void soundReadGame( gzFile in, int version )
-{
- // Prepare APU and default state
- reset_apu();
- gb_apu->save_state( &state.apu );
-
- if ( version > SAVE_GAME_VERSION_9 )
- utilReadData( in, gba_state );
- else
- soundReadGameOld( in, version );
-
- gb_apu->load_state( state.apu );
- write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );
-
- apply_muting();
-}*/
-
--- a/src/in_gsf/vbam/gba/Sound.h
+++ b/src/in_gsf/vbam/gba/Sound.h
@@ -5,20 +5,11 @@
#include <cstdint>
-extern bool soundDeclicking;
-
//// Setup/options (these affect GBA and GB sound)
// Initializes sound and returns true if successful. Sets sound quality to
// current value in soundQuality global.
bool soundInit();
-
-// sets the Sound throttle
-void soundSetThrottle(unsigned short throttle);
-
-// Manages sound volume, where 1.0 is normal
-void soundSetVolume( float );
-float soundGetVolume();
// Manages muting bitmask. The bits control the following channels:
// 0x001 Pulse 1
@@ -27,61 +18,49 @@
// 0x008 Noise
// 0x100 PCM 1
// 0x200 PCM 2
-void soundSetEnable( int mask );
-int soundGetEnable();
+void soundSetEnable(int mask);
// Pauses/resumes system sound output
void soundPause();
void soundResume();
-extern bool soundPaused; // current paused state
// Cleans up sound. Afterwards, soundInit() can be called again.
void soundShutdown();
//// GBA sound options
-long soundGetSampleRate();
void soundSetSampleRate(long sampleRate);
// Sound settings
extern bool soundInterpolation; // 1 if PCM should have low-pass filtering
-extern float soundFiltering; // 0.0 = none, 1.0 = max
-
//// GBA sound emulation
// GBA sound registers
-#define SGCNT0_H 0x82
-#define FIFOA_L 0xa0
-#define FIFOA_H 0xa2
-#define FIFOB_L 0xa4
-#define FIFOB_H 0xa6
+const uint32_t SGCNT0_H = 0x82;
+const uint32_t FIFOA_L = 0xa0;
+const uint32_t FIFOA_H = 0xa2;
+const uint32_t FIFOB_L = 0xa4;
+const uint32_t FIFOB_H = 0xa6;
// Resets emulated sound hardware
void soundReset();
// Emulates write to sound hardware
-void soundEvent( uint32_t addr, uint8_t data );
-void soundEvent( uint32_t addr, uint16_t data ); // TODO: error-prone to overload like this
+void soundEvent(uint32_t addr, uint8_t data);
+void soundEvent(uint32_t addr, uint16_t data); // TODO: error-prone to overload like this
// Notifies emulator that a timer has overflowed
-void soundTimerOverflow( int which );
-
-// Notifies emulator that PCM rate may have changed
-void interp_rate();
+void soundTimerOverflow(int which);
// Notifies emulator that SOUND_CLOCK_TICKS clocks have passed
void psoundTickfn();
-extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to soundTick()
-extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called
-
-// Saves/loads emulator state
-//void soundSaveGame( gzFile );
-//void soundReadGame( gzFile, int version );
+extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to soundTick()
+extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called
class Multi_Buffer;
-void flush_samples(Multi_Buffer * buffer);
+void flush_samples(Multi_Buffer *buffer);
#endif // SOUND_H
--- a/src/in_gsf/vbam/gba/bios.cpp
+++ b/src/in_gsf/vbam/gba/bios.cpp
@@ -1,1148 +1,1006 @@
-#include <math.h>
-#include <memory.h>
-#include <stdlib.h>
-
+#include <cmath>
+#include <cstring>
#include "GBA.h"
#include "bios.h"
#include "GBAinline.h"
#include "Globals.h"
-int16_t sineTable[256] = {
- (int16_t)0x0000, (int16_t)0x0192, (int16_t)0x0323, (int16_t)0x04B5, (int16_t)0x0645, (int16_t)0x07D5, (int16_t)0x0964, (int16_t)0x0AF1,
- (int16_t)0x0C7C, (int16_t)0x0E05, (int16_t)0x0F8C, (int16_t)0x1111, (int16_t)0x1294, (int16_t)0x1413, (int16_t)0x158F, (int16_t)0x1708,
- (int16_t)0x187D, (int16_t)0x19EF, (int16_t)0x1B5D, (int16_t)0x1CC6, (int16_t)0x1E2B, (int16_t)0x1F8B, (int16_t)0x20E7, (int16_t)0x223D,
- (int16_t)0x238E, (int16_t)0x24DA, (int16_t)0x261F, (int16_t)0x275F, (int16_t)0x2899, (int16_t)0x29CD, (int16_t)0x2AFA, (int16_t)0x2C21,
- (int16_t)0x2D41, (int16_t)0x2E5A, (int16_t)0x2F6B, (int16_t)0x3076, (int16_t)0x3179, (int16_t)0x3274, (int16_t)0x3367, (int16_t)0x3453,
- (int16_t)0x3536, (int16_t)0x3612, (int16_t)0x36E5, (int16_t)0x37AF, (int16_t)0x3871, (int16_t)0x392A, (int16_t)0x39DA, (int16_t)0x3A82,
- (int16_t)0x3B20, (int16_t)0x3BB6, (int16_t)0x3C42, (int16_t)0x3CC5, (int16_t)0x3D3E, (int16_t)0x3DAE, (int16_t)0x3E14, (int16_t)0x3E71,
- (int16_t)0x3EC5, (int16_t)0x3F0E, (int16_t)0x3F4E, (int16_t)0x3F84, (int16_t)0x3FB1, (int16_t)0x3FD3, (int16_t)0x3FEC, (int16_t)0x3FFB,
- (int16_t)0x4000, (int16_t)0x3FFB, (int16_t)0x3FEC, (int16_t)0x3FD3, (int16_t)0x3FB1, (int16_t)0x3F84, (int16_t)0x3F4E, (int16_t)0x3F0E,
- (int16_t)0x3EC5, (int16_t)0x3E71, (int16_t)0x3E14, (int16_t)0x3DAE, (int16_t)0x3D3E, (int16_t)0x3CC5, (int16_t)0x3C42, (int16_t)0x3BB6,
- (int16_t)0x3B20, (int16_t)0x3A82, (int16_t)0x39DA, (int16_t)0x392A, (int16_t)0x3871, (int16_t)0x37AF, (int16_t)0x36E5, (int16_t)0x3612,
- (int16_t)0x3536, (int16_t)0x3453, (int16_t)0x3367, (int16_t)0x3274, (int16_t)0x3179, (int16_t)0x3076, (int16_t)0x2F6B, (int16_t)0x2E5A,
- (int16_t)0x2D41, (int16_t)0x2C21, (int16_t)0x2AFA, (int16_t)0x29CD, (int16_t)0x2899, (int16_t)0x275F, (int16_t)0x261F, (int16_t)0x24DA,
- (int16_t)0x238E, (int16_t)0x223D, (int16_t)0x20E7, (int16_t)0x1F8B, (int16_t)0x1E2B, (int16_t)0x1CC6, (int16_t)0x1B5D, (int16_t)0x19EF,
- (int16_t)0x187D, (int16_t)0x1708, (int16_t)0x158F, (int16_t)0x1413, (int16_t)0x1294, (int16_t)0x1111, (int16_t)0x0F8C, (int16_t)0x0E05,
- (int16_t)0x0C7C, (int16_t)0x0AF1, (int16_t)0x0964, (int16_t)0x07D5, (int16_t)0x0645, (int16_t)0x04B5, (int16_t)0x0323, (int16_t)0x0192,
- (int16_t)0x0000, (int16_t)0xFE6E, (int16_t)0xFCDD, (int16_t)0xFB4B, (int16_t)0xF9BB, (int16_t)0xF82B, (int16_t)0xF69C, (int16_t)0xF50F,
- (int16_t)0xF384, (int16_t)0xF1FB, (int16_t)0xF074, (int16_t)0xEEEF, (int16_t)0xED6C, (int16_t)0xEBED, (int16_t)0xEA71, (int16_t)0xE8F8,
- (int16_t)0xE783, (int16_t)0xE611, (int16_t)0xE4A3, (int16_t)0xE33A, (int16_t)0xE1D5, (int16_t)0xE075, (int16_t)0xDF19, (int16_t)0xDDC3,
- (int16_t)0xDC72, (int16_t)0xDB26, (int16_t)0xD9E1, (int16_t)0xD8A1, (int16_t)0xD767, (int16_t)0xD633, (int16_t)0xD506, (int16_t)0xD3DF,
- (int16_t)0xD2BF, (int16_t)0xD1A6, (int16_t)0xD095, (int16_t)0xCF8A, (int16_t)0xCE87, (int16_t)0xCD8C, (int16_t)0xCC99, (int16_t)0xCBAD,
- (int16_t)0xCACA, (int16_t)0xC9EE, (int16_t)0xC91B, (int16_t)0xC851, (int16_t)0xC78F, (int16_t)0xC6D6, (int16_t)0xC626, (int16_t)0xC57E,
- (int16_t)0xC4E0, (int16_t)0xC44A, (int16_t)0xC3BE, (int16_t)0xC33B, (int16_t)0xC2C2, (int16_t)0xC252, (int16_t)0xC1EC, (int16_t)0xC18F,
- (int16_t)0xC13B, (int16_t)0xC0F2, (int16_t)0xC0B2, (int16_t)0xC07C, (int16_t)0xC04F, (int16_t)0xC02D, (int16_t)0xC014, (int16_t)0xC005,
- (int16_t)0xC000, (int16_t)0xC005, (int16_t)0xC014, (int16_t)0xC02D, (int16_t)0xC04F, (int16_t)0xC07C, (int16_t)0xC0B2, (int16_t)0xC0F2,
- (int16_t)0xC13B, (int16_t)0xC18F, (int16_t)0xC1EC, (int16_t)0xC252, (int16_t)0xC2C2, (int16_t)0xC33B, (int16_t)0xC3BE, (int16_t)0xC44A,
- (int16_t)0xC4E0, (int16_t)0xC57E, (int16_t)0xC626, (int16_t)0xC6D6, (int16_t)0xC78F, (int16_t)0xC851, (int16_t)0xC91B, (int16_t)0xC9EE,
- (int16_t)0xCACA, (int16_t)0xCBAD, (int16_t)0xCC99, (int16_t)0xCD8C, (int16_t)0xCE87, (int16_t)0xCF8A, (int16_t)0xD095, (int16_t)0xD1A6,
- (int16_t)0xD2BF, (int16_t)0xD3DF, (int16_t)0xD506, (int16_t)0xD633, (int16_t)0xD767, (int16_t)0xD8A1, (int16_t)0xD9E1, (int16_t)0xDB26,
- (int16_t)0xDC72, (int16_t)0xDDC3, (int16_t)0xDF19, (int16_t)0xE075, (int16_t)0xE1D5, (int16_t)0xE33A, (int16_t)0xE4A3, (int16_t)0xE611,
- (int16_t)0xE783, (int16_t)0xE8F8, (int16_t)0xEA71, (int16_t)0xEBED, (int16_t)0xED6C, (int16_t)0xEEEF, (int16_t)0xF074, (int16_t)0xF1FB,
- (int16_t)0xF384, (int16_t)0xF50F, (int16_t)0xF69C, (int16_t)0xF82B, (int16_t)0xF9BB, (int16_t)0xFB4B, (int16_t)0xFCDD, (int16_t)0xFE6E
+int32_t sineTable[] =
+{
+ 0x0000, 0x0192, 0x0323, 0x04B5, 0x0645, 0x07D5, 0x0964, 0x0AF1,
+ 0x0C7C, 0x0E05, 0x0F8C, 0x1111, 0x1294, 0x1413, 0x158F, 0x1708,
+ 0x187D, 0x19EF, 0x1B5D, 0x1CC6, 0x1E2B, 0x1F8B, 0x20E7, 0x223D,
+ 0x238E, 0x24DA, 0x261F, 0x275F, 0x2899, 0x29CD, 0x2AFA, 0x2C21,
+ 0x2D41, 0x2E5A, 0x2F6B, 0x3076, 0x3179, 0x3274, 0x3367, 0x3453,
+ 0x3536, 0x3612, 0x36E5, 0x37AF, 0x3871, 0x392A, 0x39DA, 0x3A82,
+ 0x3B20, 0x3BB6, 0x3C42, 0x3CC5, 0x3D3E, 0x3DAE, 0x3E14, 0x3E71,
+ 0x3EC5, 0x3F0E, 0x3F4E, 0x3F84, 0x3FB1, 0x3FD3, 0x3FEC, 0x3FFB,
+ 0x4000, 0x3FFB, 0x3FEC, 0x3FD3, 0x3FB1, 0x3F84, 0x3F4E, 0x3F0E,
+ 0x3EC5, 0x3E71, 0x3E14, 0x3DAE, 0x3D3E, 0x3CC5, 0x3C42, 0x3BB6,
+ 0x3B20, 0x3A82, 0x39DA, 0x392A, 0x3871, 0x37AF, 0x36E5, 0x3612,
+ 0x3536, 0x3453, 0x3367, 0x3274, 0x3179, 0x3076, 0x2F6B, 0x2E5A,
+ 0x2D41, 0x2C21, 0x2AFA, 0x29CD, 0x2899, 0x275F, 0x261F, 0x24DA,
+ 0x238E, 0x223D, 0x20E7, 0x1F8B, 0x1E2B, 0x1CC6, 0x1B5D, 0x19EF,
+ 0x187D, 0x1708, 0x158F, 0x1413, 0x1294, 0x1111, 0x0F8C, 0x0E05,
+ 0x0C7C, 0x0AF1, 0x0964, 0x07D5, 0x0645, 0x04B5, 0x0323, 0x0192,
+ 0x0000, 0xFE6E, 0xFCDD, 0xFB4B, 0xF9BB, 0xF82B, 0xF69C, 0xF50F,
+ 0xF384, 0xF1FB, 0xF074, 0xEEEF, 0xED6C, 0xEBED, 0xEA71, 0xE8F8,
+ 0xE783, 0xE611, 0xE4A3, 0xE33A, 0xE1D5, 0xE075, 0xDF19, 0xDDC3,
+ 0xDC72, 0xDB26, 0xD9E1, 0xD8A1, 0xD767, 0xD633, 0xD506, 0xD3DF,
+ 0xD2BF, 0xD1A6, 0xD095, 0xCF8A, 0xCE87, 0xCD8C, 0xCC99, 0xCBAD,
+ 0xCACA, 0xC9EE, 0xC91B, 0xC851, 0xC78F, 0xC6D6, 0xC626, 0xC57E,
+ 0xC4E0, 0xC44A, 0xC3BE, 0xC33B, 0xC2C2, 0xC252, 0xC1EC, 0xC18F,
+ 0xC13B, 0xC0F2, 0xC0B2, 0xC07C, 0xC04F, 0xC02D, 0xC014, 0xC005,
+ 0xC000, 0xC005, 0xC014, 0xC02D, 0xC04F, 0xC07C, 0xC0B2, 0xC0F2,
+ 0xC13B, 0xC18F, 0xC1EC, 0xC252, 0xC2C2, 0xC33B, 0xC3BE, 0xC44A,
+ 0xC4E0, 0xC57E, 0xC626, 0xC6D6, 0xC78F, 0xC851, 0xC91B, 0xC9EE,
+ 0xCACA, 0xCBAD, 0xCC99, 0xCD8C, 0xCE87, 0xCF8A, 0xD095, 0xD1A6,
+ 0xD2BF, 0xD3DF, 0xD506, 0xD633, 0xD767, 0xD8A1, 0xD9E1, 0xDB26,
+ 0xDC72, 0xDDC3, 0xDF19, 0xE075, 0xE1D5, 0xE33A, 0xE4A3, 0xE611,
+ 0xE783, 0xE8F8, 0xEA71, 0xEBED, 0xED6C, 0xEEEF, 0xF074, 0xF1FB,
+ 0xF384, 0xF50F, 0xF69C, 0xF82B, 0xF9BB, 0xFB4B, 0xFCDD, 0xFE6E
};
void BIOS_ArcTan()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan: %08x (VCOUNT=%2d)\n",
- reg[0].I,
- VCOUNT);
+ int32_t a = -(static_cast<int32_t>(reg[0].I * reg[0].I) >> 14);
+ int32_t b = ((0xA9 * a) >> 14) + 0x390;
+ b = ((b * a) >> 14) + 0x91C;
+ b = ((b * a) >> 14) + 0xFB6;
+ b = ((b * a) >> 14) + 0x16AA;
+ b = ((b * a) >> 14) + 0x2081;
+ b = ((b * a) >> 14) + 0x3651;
+ b = ((b * a) >> 14) + 0xA2F9;
+ a = (static_cast<int32_t>(reg[0].I) * b) >> 16;
+ reg[0].I = a;
+}
+
+void BIOS_ArcTan2()
+{
+ int32_t x = reg[0].I;
+ int32_t y = reg[1].I;
+ uint32_t res = 0;
+ if (!y)
+ res = (x >> 16) & 0x8000;
+ else
+ {
+ if (!x)
+ res = ((y >> 16) & 0x8000) + 0x4000;
+ else
+ {
+ if (std::abs(x) > std::abs(y) || (std::abs(x) == std::abs(y) && !(x < 0 && y < 0)))
+ {
+ reg[1].I = x;
+ reg[0].I = y << 14;
+ BIOS_Div();
+ BIOS_ArcTan();
+ if (x < 0)
+ res = 0x8000 + reg[0].I;
+ else
+ res = (((y >> 16) & 0x8000) << 1) + reg[0].I;
+ }
+ else
+ {
+ reg[0].I = x << 14;
+ BIOS_Div();
+ BIOS_ArcTan();
+ res = (0x4000 + ((y >> 16) & 0x8000)) - reg[0].I;
+ }
+ }
+ }
+ reg[0].I = res;
+}
+
+void BIOS_BitUnPack()
+{
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+ uint32_t header = reg[2].I;
+
+ int len = CPUReadHalfWord(header);
+ // check address
+ if (!(source & 0xe000000) || !((source + len) & 0xe000000))
+ return;
+
+ int bits = CPUReadByte(header + 2);
+ int revbits = 8 - bits;
+ // u32 value = 0;
+ uint32_t base = CPUReadMemory(header + 4);
+ bool addBase = !!(base & 0x80000000);
+ base &= 0x7fffffff;
+ int dataSize = CPUReadByte(header + 3);
+
+ int data = 0;
+ int bitwritecount = 0;
+ while (1)
+ {
+ --len;
+ if (len < 0)
+ break;
+ int mask = 0xff >> revbits;
+ uint8_t b = CPUReadByte(source);
+ ++source;
+ int bitcount = 0;
+ while (1)
+ {
+ if (bitcount >= 8)
+ break;
+ uint32_t d = b & mask;
+ uint32_t temp = d >> bitcount;
+ if (d || addBase)
+ temp += base;
+ data |= temp << bitwritecount;
+ bitwritecount += dataSize;
+ if (bitwritecount >= 32)
+ {
+ CPUWriteMemory(dest, data);
+ dest += 4;
+ data = 0;
+ bitwritecount = 0;
+ }
+ mask <<= bits;
+ bitcount += bits;
+ }
+ }
+}
+
+void BIOS_GetBiosChecksum()
+{
+ reg[0].I = 0xBAAE187F;
+}
+
+void BIOS_BgAffineSet()
+{
+ uint32_t src = reg[0].I;
+ uint32_t dest = reg[1].I;
+ int num = reg[2].I;
+
+ for (int i = 0; i < num; ++i)
+ {
+ int32_t cx = CPUReadMemory(src);
+ src += 4;
+ int32_t cy = CPUReadMemory(src);
+ src += 4;
+ int16_t dispx = CPUReadHalfWord(src);
+ src += 2;
+ int16_t dispy = CPUReadHalfWord(src);
+ src += 2;
+ int16_t rx = CPUReadHalfWord(src);
+ src += 2;
+ int16_t ry = CPUReadHalfWord(src);
+ src += 2;
+ uint16_t theta = CPUReadHalfWord(src) >> 8;
+ src += 4; // keep structure alignment
+ int32_t a = sineTable[(theta + 0x40) & 255];
+ int32_t b = sineTable[theta];
+
+ int16_t dx = (rx * a) >> 14;
+ int16_t dmx = (rx * b) >> 14;
+ int16_t dy = (ry * b) >> 14;
+ int16_t dmy = (ry * a) >> 14;
+
+ CPUWriteHalfWord(dest, dx);
+ dest += 2;
+ CPUWriteHalfWord(dest, -dmx);
+ dest += 2;
+ CPUWriteHalfWord(dest, dy);
+ dest += 2;
+ CPUWriteHalfWord(dest, dmy);
+ dest += 2;
+
+ int32_t startx = cx - dx * dispx + dmx * dispy;
+ int32_t starty = cy - dy * dispx - dmy * dispy;
+
+ CPUWriteMemory(dest, startx);
+ dest += 4;
+ CPUWriteMemory(dest, starty);
+ dest += 4;
+ }
+}
+
+void BIOS_CpuSet()
+{
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+ uint32_t cnt = reg[2].I;
+
+ if (!(source & 0xe000000) || !((source + (((cnt << 11) >> 9) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int count = cnt & 0x1FFFFF;
+
+ // 32-bit ?
+ if ((cnt >> 26) & 1)
+ {
+ // needed for 32-bit mode!
+ source &= 0xFFFFFFFC;
+ dest &= 0xFFFFFFFC;
+ // fill ?
+ if ((cnt >> 24) & 1)
+ {
+ uint32_t value = source > 0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source);
+ while (count)
+ {
+ CPUWriteMemory(dest, value);
+ dest += 4;
+ --count;
+ }
+ }
+ else
+ {
+ // copy
+ while (count)
+ {
+ CPUWriteMemory(dest, source > 0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source));
+ source += 4;
+ dest += 4;
+ --count;
+ }
+ }
+ }
+ else
+ {
+ // 16-bit fill?
+ if ((cnt >> 24) & 1)
+ {
+ uint16_t value = source > 0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source);
+ while (count)
+ {
+ CPUWriteHalfWord(dest, value);
+ dest += 2;
+ --count;
+ }
+ }
+ else
+ {
+ // copy
+ while (count)
+ {
+ CPUWriteHalfWord(dest, source > 0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source));
+ source += 2;
+ dest += 2;
+ --count;
+ }
+ }
+ }
+}
+
+void BIOS_CpuFastSet()
+{
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+ uint32_t cnt = reg[2].I;
+
+ if (!(source & 0xe000000) || !((source + (((cnt << 11) >> 9) & 0x1fffff)) & 0xe000000))
+ return;
+
+ // needed for 32-bit mode!
+ source &= 0xFFFFFFFC;
+ dest &= 0xFFFFFFFC;
+
+ int count = cnt & 0x1FFFFF;
+
+ // fill?
+ if ((cnt >> 24) & 1)
+ {
+ while (count > 0)
+ {
+ // BIOS always transfers 32 bytes at a time
+ uint32_t value = source > 0x0EFFFFFF ? 0xBAFFFFFB : CPUReadMemory(source);
+ for (int i = 0; i < 8; ++i)
+ {
+ CPUWriteMemory(dest, value);
+ dest += 4;
+ }
+ count -= 8;
+ }
+ }
+ else
+ {
+ // copy
+ while (count > 0)
+ {
+ // BIOS always transfers 32 bytes at a time
+ for (int i = 0; i < 8; ++i)
+ {
+ CPUWriteMemory(dest, source > 0x0EFFFFFF ? 0xBAFFFFFB :CPUReadMemory(source));
+ source += 4;
+ dest += 4;
+ }
+ count -= 8;
+ }
+ }
+}
+
+void BIOS_Diff8bitUnFilterWram()
+{
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int len = header >> 8;
+
+ uint8_t data = CPUReadByte(source++);
+ CPUWriteByte(dest++, data);
+ --len;
+
+ while (len > 0)
+ {
+ uint8_t diff = CPUReadByte(source++);
+ data += diff;
+ CPUWriteByte(dest++, data);
+ --len;
+ }
+}
+
+void BIOS_Diff8bitUnFilterVram()
+{
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source);
+ source += 4;
+
+ if (!(source & 0xe000000) | !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int len = header >> 8;
+
+ uint8_t data = CPUReadByte(source++);
+ uint16_t writeData = data;
+ int shift = 8;
+ int bytes = 1;
+
+ while (len >= 2)
+ {
+ uint8_t diff = CPUReadByte(source++);
+ data += diff;
+ writeData |= data << shift;
+ ++bytes;
+ shift += 8;
+ if (bytes == 2)
+ {
+ CPUWriteHalfWord(dest, writeData);
+ dest += 2;
+ len -= 2;
+ bytes = 0;
+ writeData = 0;
+ shift = 0;
+ }
+ }
+}
+
+void BIOS_Diff16bitUnFilter()
+{
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int len = header >> 8;
+
+ uint16_t data = CPUReadHalfWord(source);
+ source += 2;
+ CPUWriteHalfWord(dest, data);
+ dest += 2;
+ len -= 2;
+
+ while (len >= 2)
+ {
+ uint16_t diff = CPUReadHalfWord(source);
+ source += 2;
+ data += diff;
+ CPUWriteHalfWord(dest, data);
+ dest += 2;
+ len -= 2;
+ }
+}
+
+void BIOS_Div()
+{
+ int number = reg[0].I;
+ int denom = reg[1].I;
+
+ if (denom)
+ {
+ reg[0].I = number / denom;
+ reg[1].I = number % denom;
+ int32_t temp = static_cast<int32_t>(reg[0].I);
+ reg[3].I = static_cast<uint32_t>(temp < 0 ? -temp : temp);
}
-#endif
-
- int32_t a = -(((int32_t)(reg[0].I*reg[0].I)) >> 14);
- int32_t b = ((0xA9 * a) >> 14) + 0x390;
- b = ((b * a) >> 14) + 0x91C;
- b = ((b * a) >> 14) + 0xFB6;
- b = ((b * a) >> 14) + 0x16AA;
- b = ((b * a) >> 14) + 0x2081;
- b = ((b * a) >> 14) + 0x3651;
- b = ((b * a) >> 14) + 0xA2F9;
- a = ((int32_t)reg[0].I * b) >> 16;
- reg[0].I = a;
-
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan: return=%08x\n",
- reg[0].I);
- }
-#endif
-}
-
-void BIOS_ArcTan2()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan2: %08x,%08x (VCOUNT=%2d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- int32_t x = reg[0].I;
- int32_t y = reg[1].I;
- uint32_t res = 0;
- if (y == 0) {
- res = ((x>>16) & 0x8000);
- } else {
- if (x == 0) {
- res = ((y>>16) & 0x8000) + 0x4000;
- } else {
- if ((abs(x) > abs(y)) || ((abs(x) == abs(y)) && (!((x<0) && (y<0))))) {
- reg[1].I = x;
- reg[0].I = y << 14;
- BIOS_Div();
- BIOS_ArcTan();
- if (x < 0)
- res = 0x8000 + reg[0].I;
- else
- res = (((y>>16) & 0x8000)<<1) + reg[0].I;
- } else {
- reg[0].I = x << 14;
- BIOS_Div();
- BIOS_ArcTan();
- res = (0x4000 + ((y>>16) & 0x8000)) - reg[0].I;
- }
- }
- }
- reg[0].I = res;
-
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("ArcTan2: return=%08x\n",
- reg[0].I);
- }
-#endif
-}
-
-void BIOS_BitUnPack()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("BitUnPack: %08x,%08x,%08x (VCOUNT=%2d)\n",
- reg[0].I,
- reg[1].I,
- reg[2].I,
- VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
- uint32_t header = reg[2].I;
-
- int len = CPUReadHalfWord(header);
- // check address
- if(((source & 0xe000000) == 0) ||
- ((source + len) & 0xe000000) == 0)
- return;
-
- int bits = CPUReadByte(header+2);
- int revbits = 8 - bits;
- // u32 value = 0;
- uint32_t base = CPUReadMemory(header+4);
- bool addBase = (base & 0x80000000) ? true : false;
- base &= 0x7fffffff;
- int dataSize = CPUReadByte(header+3);
-
- int data = 0;
- int bitwritecount = 0;
- while(1) {
- len -= 1;
- if(len < 0)
- break;
- int mask = 0xff >> revbits;
- uint8_t b = CPUReadByte(source);
- source++;
- int bitcount = 0;
- while(1) {
- if(bitcount >= 8)
- break;
- uint32_t d = b & mask;
- uint32_t temp = d >> bitcount;
- if(d || addBase) {
- temp += base;
- }
- data |= temp << bitwritecount;
- bitwritecount += dataSize;
- if(bitwritecount >= 32) {
- CPUWriteMemory(dest, data);
- dest += 4;
- data = 0;
- bitwritecount = 0;
- }
- mask <<= bits;
- bitcount += bits;
- }
- }
-}
-
-void BIOS_GetBiosChecksum()
-{
- reg[0].I=0xBAAE187F;
-}
-
-void BIOS_BgAffineSet()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("BgAffineSet: %08x,%08x,%08x (VCOUNT=%2d)\n",
- reg[0].I,
- reg[1].I,
- reg[2].I,
- VCOUNT);
- }
-#endif
-
- uint32_t src = reg[0].I;
- uint32_t dest = reg[1].I;
- int num = reg[2].I;
-
- for(int i = 0; i < num; i++) {
- int32_t cx = CPUReadMemory(src);
- src+=4;
- int32_t cy = CPUReadMemory(src);
- src+=4;
- int16_t dispx = CPUReadHalfWord(src);
- src+=2;
- int16_t dispy = CPUReadHalfWord(src);
- src+=2;
- int16_t rx = CPUReadHalfWord(src);
- src+=2;
- int16_t ry = CPUReadHalfWord(src);
- src+=2;
- uint16_t theta = CPUReadHalfWord(src)>>8;
- src+=4; // keep structure alignment
- int32_t a = sineTable[(theta+0x40)&255];
- int32_t b = sineTable[theta];
-
- int16_t dx = (rx * a)>>14;
- int16_t dmx = (rx * b)>>14;
- int16_t dy = (ry * b)>>14;
- int16_t dmy = (ry * a)>>14;
-
- CPUWriteHalfWord(dest, dx);
- dest += 2;
- CPUWriteHalfWord(dest, -dmx);
- dest += 2;
- CPUWriteHalfWord(dest, dy);
- dest += 2;
- CPUWriteHalfWord(dest, dmy);
- dest += 2;
-
- int32_t startx = cx - dx * dispx + dmx * dispy;
- int32_t starty = cy - dy * dispx - dmy * dispy;
-
- CPUWriteMemory(dest, startx);
- dest += 4;
- CPUWriteMemory(dest, starty);
- dest += 4;
- }
-}
-
-void BIOS_CpuSet()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("CpuSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
- reg[2].I, VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
- uint32_t cnt = reg[2].I;
-
- if(((source & 0xe000000) == 0) ||
- ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int count = cnt & 0x1FFFFF;
-
- // 32-bit ?
- if((cnt >> 26) & 1) {
- // needed for 32-bit mode!
- source &= 0xFFFFFFFC;
- dest &= 0xFFFFFFFC;
- // fill ?
- if((cnt >> 24) & 1) {
- uint32_t value = (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source));
- while(count) {
- CPUWriteMemory(dest, value);
- dest += 4;
- count--;
- }
- } else {
- // copy
- while(count) {
- CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source)));
- source += 4;
- dest += 4;
- count--;
- }
- }
- } else {
- // 16-bit fill?
- if((cnt >> 24) & 1) {
- uint16_t value = (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source));
- while(count) {
- CPUWriteHalfWord(dest, value);
- dest += 2;
- count--;
- }
- } else {
- // copy
- while(count) {
- CPUWriteHalfWord(dest, (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source)));
- source += 2;
- dest += 2;
- count--;
- }
- }
- }
-}
-
-void BIOS_CpuFastSet()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("CpuFastSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
- reg[2].I, VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
- uint32_t cnt = reg[2].I;
-
- if(((source & 0xe000000) == 0) ||
- ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- // needed for 32-bit mode!
- source &= 0xFFFFFFFC;
- dest &= 0xFFFFFFFC;
-
- int count = cnt & 0x1FFFFF;
-
- // fill?
- if((cnt >> 24) & 1) {
- while(count > 0) {
- // BIOS always transfers 32 bytes at a time
- uint32_t value = (source>0x0EFFFFFF ? 0xBAFFFFFB : CPUReadMemory(source));
- for(int i = 0; i < 8; i++) {
- CPUWriteMemory(dest, value);
- dest += 4;
- }
- count -= 8;
- }
- } else {
- // copy
- while(count > 0) {
- // BIOS always transfers 32 bytes at a time
- for(int i = 0; i < 8; i++) {
- CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0xBAFFFFFB :CPUReadMemory(source)));
- source += 4;
- dest += 4;
- }
- count -= 8;
- }
- }
-}
-
-void BIOS_Diff8bitUnFilterWram()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Diff8bitUnFilterWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
- reg[1].I, VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- (((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0))
- return;
-
- int len = header >> 8;
-
- uint8_t data = CPUReadByte(source++);
- CPUWriteByte(dest++, data);
- len--;
-
- while(len > 0) {
- uint8_t diff = CPUReadByte(source++);
- data += diff;
- CPUWriteByte(dest++, data);
- len--;
- }
-}
-
-void BIOS_Diff8bitUnFilterVram()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Diff8bitUnFilterVram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
- reg[1].I, VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- uint8_t data = CPUReadByte(source++);
- uint16_t writeData = data;
- int shift = 8;
- int bytes = 1;
-
- while(len >= 2) {
- uint8_t diff = CPUReadByte(source++);
- data += diff;
- writeData |= (data << shift);
- bytes++;
- shift += 8;
- if(bytes == 2) {
- CPUWriteHalfWord(dest, writeData);
- dest += 2;
- len -= 2;
- bytes = 0;
- writeData = 0;
- shift = 0;
- }
- }
-}
-
-void BIOS_Diff16bitUnFilter()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Diff16bitUnFilter: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I,
- reg[1].I, VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- uint16_t data = CPUReadHalfWord(source);
- source += 2;
- CPUWriteHalfWord(dest, data);
- dest += 2;
- len -= 2;
-
- while(len >= 2) {
- uint16_t diff = CPUReadHalfWord(source);
- source += 2;
- data += diff;
- CPUWriteHalfWord(dest, data);
- dest += 2;
- len -= 2;
- }
-}
-
-void BIOS_Div()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Div: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- int number = reg[0].I;
- int denom = reg[1].I;
-
- if(denom != 0) {
- reg[0].I = number / denom;
- reg[1].I = number % denom;
- int32_t temp = (int32_t)reg[0].I;
- reg[3].I = temp < 0 ? (uint32_t)-temp : (uint32_t)temp;
- }
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Div: return=0x%08x,0x%08x,0x%08x\n",
- reg[0].I,
- reg[1].I,
- reg[3].I);
- }
-#endif
-}
-
-void BIOS_DivARM()
-{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("DivARM: 0x%08x, (VCOUNT=%d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
-
- uint32_t temp = reg[0].I;
- reg[0].I = reg[1].I;
- reg[1].I = temp;
- BIOS_Div();
}
void BIOS_HuffUnComp()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("HuffUnComp: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- uint8_t treeSize = CPUReadByte(source++);
-
- uint32_t treeStart = source;
-
- source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte
-
- int len = header >> 8;
-
- uint32_t mask = 0x80000000;
- uint32_t data = CPUReadMemory(source);
- source += 4;
-
- int pos = 0;
- uint8_t rootNode = CPUReadByte(treeStart);
- uint8_t currentNode = rootNode;
- bool writeData = false;
- int byteShift = 0;
- int byteCount = 0;
- uint32_t writeValue = 0;
-
- if((header & 0x0F) == 8) {
- while(len > 0) {
- // take left
- if(pos == 0)
- pos++;
- else
- pos += (((currentNode & 0x3F)+1)<<1);
-
- if(data & mask) {
- // right
- if(currentNode & 0x40)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos+1);
- } else {
- // left
- if(currentNode & 0x80)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos);
- }
-
- if(writeData) {
- writeValue |= (currentNode << byteShift);
- byteCount++;
- byteShift += 8;
-
- pos = 0;
- currentNode = rootNode;
- writeData = false;
-
- if(byteCount == 4) {
- byteCount = 0;
- byteShift = 0;
- CPUWriteMemory(dest, writeValue);
- writeValue = 0;
- dest += 4;
- len -= 4;
- }
- }
- mask >>= 1;
- if(mask == 0) {
- mask = 0x80000000;
- data = CPUReadMemory(source);
- source += 4;
- }
- }
- } else {
- int halfLen = 0;
- int value = 0;
- while(len > 0) {
- // take left
- if(pos == 0)
- pos++;
- else
- pos += (((currentNode & 0x3F)+1)<<1);
-
- if((data & mask)) {
- // right
- if(currentNode & 0x40)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos+1);
- } else {
- // left
- if(currentNode & 0x80)
- writeData = true;
- currentNode = CPUReadByte(treeStart+pos);
- }
-
- if(writeData) {
- if(halfLen == 0)
- value |= currentNode;
- else
- value |= (currentNode<<4);
-
- halfLen += 4;
- if(halfLen == 8) {
- writeValue |= (value << byteShift);
- byteCount++;
- byteShift += 8;
-
- halfLen = 0;
- value = 0;
-
- if(byteCount == 4) {
- byteCount = 0;
- byteShift = 0;
- CPUWriteMemory(dest, writeValue);
- dest += 4;
- writeValue = 0;
- len -= 4;
- }
- }
- pos = 0;
- currentNode = rootNode;
- writeData = false;
- }
- mask >>= 1;
- if(mask == 0) {
- mask = 0x80000000;
- data = CPUReadMemory(source);
- source += 4;
- }
- }
- }
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ uint8_t treeSize = CPUReadByte(source++);
+
+ uint32_t treeStart = source;
+
+ source += ((treeSize + 1) << 1) - 1; // minus because we already skipped one byte
+
+ int len = header >> 8;
+
+ uint32_t mask = 0x80000000;
+ uint32_t data = CPUReadMemory(source);
+ source += 4;
+
+ int pos = 0;
+ uint8_t rootNode = CPUReadByte(treeStart);
+ uint8_t currentNode = rootNode;
+ bool writeData = false;
+ int byteShift = 0;
+ int byteCount = 0;
+ uint32_t writeValue = 0;
+
+ if ((header & 0x0F) == 8)
+ {
+ while (len > 0)
+ {
+ // take left
+ if (!pos)
+ ++pos;
+ else
+ pos += ((currentNode & 0x3F) + 1) << 1;
+
+ if (data & mask)
+ {
+ // right
+ if (currentNode & 0x40)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart + pos + 1);
+ }
+ else
+ {
+ // left
+ if (currentNode & 0x80)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart + pos);
+ }
+
+ if (writeData)
+ {
+ writeValue |= currentNode << byteShift;
+ ++byteCount;
+ byteShift += 8;
+
+ pos = 0;
+ currentNode = rootNode;
+ writeData = false;
+
+ if (byteCount == 4)
+ {
+ byteCount = 0;
+ byteShift = 0;
+ CPUWriteMemory(dest, writeValue);
+ writeValue = 0;
+ dest += 4;
+ len -= 4;
+ }
+ }
+ mask >>= 1;
+ if (!mask)
+ {
+ mask = 0x80000000;
+ data = CPUReadMemory(source);
+ source += 4;
+ }
+ }
+ }
+ else
+ {
+ int halfLen = 0;
+ int value = 0;
+ while (len > 0)
+ {
+ // take left
+ if (!pos)
+ ++pos;
+ else
+ pos += ((currentNode & 0x3F) + 1) << 1;
+
+ if (data & mask)
+ {
+ // right
+ if (currentNode & 0x40)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart + pos + 1);
+ }
+ else
+ {
+ // left
+ if (currentNode & 0x80)
+ writeData = true;
+ currentNode = CPUReadByte(treeStart + pos);
+ }
+
+ if (writeData)
+ {
+ if (!halfLen)
+ value |= currentNode;
+ else
+ value |= currentNode << 4;
+
+ halfLen += 4;
+ if (halfLen == 8)
+ {
+ writeValue |= value << byteShift;
+ ++byteCount;
+ byteShift += 8;
+
+ halfLen = 0;
+ value = 0;
+
+ if (byteCount == 4)
+ {
+ byteCount = 0;
+ byteShift = 0;
+ CPUWriteMemory(dest, writeValue);
+ dest += 4;
+ writeValue = 0;
+ len -= 4;
+ }
+ }
+ pos = 0;
+ currentNode = rootNode;
+ writeData = false;
+ }
+ mask >>= 1;
+ if (!mask)
+ {
+ mask = 0x80000000;
+ data = CPUReadMemory(source);
+ source += 4;
+ }
+ }
+ }
}
void BIOS_LZ77UnCompVram()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("LZ77UnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int byteCount = 0;
- int byteShift = 0;
- uint32_t writeValue = 0;
-
- int len = header >> 8;
-
- while(len > 0) {
- uint8_t d = CPUReadByte(source++);
-
- if(d) {
- for(int i = 0; i < 8; i++) {
- if(d & 0x80) {
- uint16_t data = CPUReadByte(source++) << 8;
- data |= CPUReadByte(source++);
- int length = (data >> 12) + 3;
- int offset = (data & 0x0FFF);
- uint32_t windowOffset = dest + byteCount - offset - 1;
- for(int i2 = 0; i2 < length; i2++) {
- writeValue |= (CPUReadByte(windowOffset++) << byteShift);
- byteShift += 8;
- byteCount++;
-
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- } else {
- writeValue |= (CPUReadByte(source++) << byteShift);
- byteShift += 8;
- byteCount++;
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- d <<= 1;
- }
- } else {
- for(int i = 0; i < 8; i++) {
- writeValue |= (CPUReadByte(source++) << byteShift);
- byteShift += 8;
- byteCount++;
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteShift = 0;
- byteCount = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- }
- }
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int byteCount = 0;
+ int byteShift = 0;
+ uint32_t writeValue = 0;
+
+ int len = header >> 8;
+
+ while (len > 0)
+ {
+ uint8_t d = CPUReadByte(source++);
+
+ if (d)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ if (d & 0x80)
+ {
+ uint16_t data = CPUReadByte(source++) << 8;
+ data |= CPUReadByte(source++);
+ int length = (data >> 12) + 3;
+ int offset = data & 0x0FFF;
+ uint32_t windowOffset = dest + byteCount - offset - 1;
+ for (int i2 = 0; i2 < length; ++i2)
+ {
+ writeValue |= CPUReadByte(windowOffset++) << byteShift;
+ byteShift += 8;
+ ++byteCount;
+
+ if (byteCount == 2)
+ {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ else
+ {
+ writeValue |= CPUReadByte(source++) << byteShift;
+ byteShift += 8;
+ ++byteCount;
+ if (byteCount == 2)
+ {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ --len;
+ if (!len)
+ return;
+ }
+ d <<= 1;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ writeValue |= CPUReadByte(source++) << byteShift;
+ byteShift += 8;
+ ++byteCount;
+ if (byteCount == 2)
+ {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteShift = 0;
+ byteCount = 0;
+ writeValue = 0;
+ }
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ }
}
void BIOS_LZ77UnCompWram()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("LZ77UnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I,
- VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- while(len > 0) {
- uint8_t d = CPUReadByte(source++);
-
- if(d) {
- for(int i = 0; i < 8; i++) {
- if(d & 0x80) {
- uint16_t data = CPUReadByte(source++) << 8;
- data |= CPUReadByte(source++);
- int length = (data >> 12) + 3;
- int offset = (data & 0x0FFF);
- uint32_t windowOffset = dest - offset - 1;
- for(int i2 = 0; i2 < length; i2++) {
- CPUWriteByte(dest++, CPUReadByte(windowOffset++));
- len--;
- if(len == 0)
- return;
- }
- } else {
- CPUWriteByte(dest++, CPUReadByte(source++));
- len--;
- if(len == 0)
- return;
- }
- d <<= 1;
- }
- } else {
- for(int i = 0; i < 8; i++) {
- CPUWriteByte(dest++, CPUReadByte(source++));
- len--;
- if(len == 0)
- return;
- }
- }
- }
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int len = header >> 8;
+
+ while (len > 0)
+ {
+ uint8_t d = CPUReadByte(source++);
+
+ if (d)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ if (d & 0x80)
+ {
+ uint16_t data = CPUReadByte(source++) << 8;
+ data |= CPUReadByte(source++);
+ int length = (data >> 12) + 3;
+ int offset = data & 0x0FFF;
+ uint32_t windowOffset = dest - offset - 1;
+ for (int i2 = 0; i2 < length; ++i2)
+ {
+ CPUWriteByte(dest++, CPUReadByte(windowOffset++));
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ else
+ {
+ CPUWriteByte(dest++, CPUReadByte(source++));
+ --len;
+ if (!len)
+ return;
+ }
+ d <<= 1;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ CPUWriteByte(dest++, CPUReadByte(source++));
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ }
}
void BIOS_ObjAffineSet()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("ObjAffineSet: 0x%08x,0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- reg[2].I,
- reg[3].I,
- VCOUNT);
- }
-#endif
-
- uint32_t src = reg[0].I;
- uint32_t dest = reg[1].I;
- int num = reg[2].I;
- int offset = reg[3].I;
-
- for(int i = 0; i < num; i++) {
- int16_t rx = CPUReadHalfWord(src);
- src+=2;
- int16_t ry = CPUReadHalfWord(src);
- src+=2;
- uint16_t theta = CPUReadHalfWord(src)>>8;
- src+=4; // keep structure alignment
-
- int32_t a = (int32_t)sineTable[(theta+0x40)&255];
- int32_t b = (int32_t)sineTable[theta];
-
- int16_t dx = ((int32_t)rx * a)>>14;
- int16_t dmx = ((int32_t)rx * b)>>14;
- int16_t dy = ((int32_t)ry * b)>>14;
- int16_t dmy = ((int32_t)ry * a)>>14;
-
- CPUWriteHalfWord(dest, dx);
- dest += offset;
- CPUWriteHalfWord(dest, -dmx);
- dest += offset;
- CPUWriteHalfWord(dest, dy);
- dest += offset;
- CPUWriteHalfWord(dest, dmy);
- dest += offset;
- }
+ uint32_t src = reg[0].I;
+ uint32_t dest = reg[1].I;
+ int num = reg[2].I;
+ int offset = reg[3].I;
+
+ for (int i = 0; i < num; ++i)
+ {
+ int16_t rx = CPUReadHalfWord(src);
+ src += 2;
+ int16_t ry = CPUReadHalfWord(src);
+ src += 2;
+ uint16_t theta = CPUReadHalfWord(src) >> 8;
+ src += 4; // keep structure alignment
+
+ int32_t a = sineTable[(theta + 0x40) & 255];
+ int32_t b = sineTable[theta];
+
+ int16_t dx = (static_cast<int32_t>(rx) * a) >> 14;
+ int16_t dmx = (static_cast<int32_t>(rx) * b) >> 14;
+ int16_t dy = (static_cast<int32_t>(ry) * b) >> 14;
+ int16_t dmy = (static_cast<int32_t>(ry) * a) >> 14;
+
+ CPUWriteHalfWord(dest, dx);
+ dest += offset;
+ CPUWriteHalfWord(dest, -dmx);
+ dest += offset;
+ CPUWriteHalfWord(dest, dy);
+ dest += offset;
+ CPUWriteHalfWord(dest, dmy);
+ dest += offset;
+ }
}
void BIOS_RegisterRamReset(uint32_t flags)
{
- // no need to trace here. this is only called directly from GBA.cpp
- // to emulate bios initialization
-
- CPUUpdateRegister(0x0, 0x80);
-
- if(flags) {
- if(flags & 0x01) {
- // clear work RAM
- memset(workRAM, 0, 0x40000);
- }
- if(flags & 0x02) {
- // clear internal RAM
- memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff
- }
- if(flags & 0x04) {
- // clear palette RAM
- memset(paletteRAM, 0, 0x400);
- }
- if(flags & 0x08) {
- // clear VRAM
- memset(vram, 0, 0x18000);
- }
- if(flags & 0x10) {
- // clean OAM
- memset(oam, 0, 0x400);
- }
-
- if(flags & 0x80) {
- int i;
- for(i = 0; i < 0x10; i++)
- CPUUpdateRegister(0x200+i*2, 0);
-
- for(i = 0; i < 0xF; i++)
- CPUUpdateRegister(0x4+i*2, 0);
-
- for(i = 0; i < 0x20; i++)
- CPUUpdateRegister(0x20+i*2, 0);
-
- for(i = 0; i < 0x18; i++)
- CPUUpdateRegister(0xb0+i*2, 0);
-
- CPUUpdateRegister(0x130, 0);
- CPUUpdateRegister(0x20, 0x100);
- CPUUpdateRegister(0x30, 0x100);
- CPUUpdateRegister(0x26, 0x100);
- CPUUpdateRegister(0x36, 0x100);
- }
-
- if(flags & 0x20) {
- int i;
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x110+i*2, 0);
- CPUUpdateRegister(0x134, 0x8000);
- for(i = 0; i < 7; i++)
- CPUUpdateRegister(0x140+i*2, 0);
- }
-
- if(flags & 0x40) {
- int i;
- CPUWriteByte(0x4000084, 0);
- CPUWriteByte(0x4000084, 0x80);
- CPUWriteMemory(0x4000080, 0x880e0000);
- CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
- CPUWriteByte(0x4000070, 0x70);
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x90+i*2, 0);
- CPUWriteByte(0x4000070, 0);
- for(i = 0; i < 8; i++)
- CPUUpdateRegister(0x90+i*2, 0);
- CPUWriteByte(0x4000084, 0);
- }
- }
+ // no need to trace here. this is only called directly from GBA.cpp
+ // to emulate bios initialization
+
+ CPUUpdateRegister(0x0, 0x80);
+
+ if (flags)
+ {
+ if (flags & 0x01)
+ // clear work RAM
+ memset(&workRAM[0], 0, 0x40000);
+ if (flags & 0x02)
+ // clear internal RAM
+ memset(&internalRAM[0], 0, 0x7e00); // don't clear 0x7e00-0x7fff
+ if (flags & 0x04)
+ // clear palette RAM
+ memset(&paletteRAM[0], 0, 0x400);
+ if (flags & 0x08)
+ // clear VRAM
+ memset(&vram[0], 0, 0x18000);
+ if (flags & 0x10)
+ // clean OAM
+ memset(&oam[0], 0, 0x400);
+
+ if (flags & 0x80)
+ {
+ int i;
+ for (i = 0; i < 0x10; ++i)
+ CPUUpdateRegister(0x200 + i * 2, 0);
+
+ for (i = 0; i < 0xF; ++i)
+ CPUUpdateRegister(0x4 + i * 2, 0);
+
+ for (i = 0; i < 0x20; ++i)
+ CPUUpdateRegister(0x20 + i * 2, 0);
+
+ for (i = 0; i < 0x18; ++i)
+ CPUUpdateRegister(0xb0 + i * 2, 0);
+
+ CPUUpdateRegister(0x130, 0);
+ CPUUpdateRegister(0x20, 0x100);
+ CPUUpdateRegister(0x30, 0x100);
+ CPUUpdateRegister(0x26, 0x100);
+ CPUUpdateRegister(0x36, 0x100);
+ }
+
+ if (flags & 0x20)
+ {
+ int i;
+ for (i = 0; i < 8; ++i)
+ CPUUpdateRegister(0x110 + i * 2, 0);
+ CPUUpdateRegister(0x134, 0x8000);
+ for (i = 0; i < 7; ++i)
+ CPUUpdateRegister(0x140 + i * 2, 0);
+ }
+
+ if (flags & 0x40)
+ {
+ CPUWriteByte(0x4000084, 0);
+ CPUWriteByte(0x4000084, 0x80);
+ CPUWriteMemory(0x4000080, 0x880e0000);
+ CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088) & 0x3ff);
+ CPUWriteByte(0x4000070, 0x70);
+ int i;
+ for (i = 0; i < 8; ++i)
+ CPUUpdateRegister(0x90 + i * 2, 0);
+ CPUWriteByte(0x4000070, 0);
+ for (i = 0; i < 8; ++i)
+ CPUUpdateRegister(0x90 + i * 2, 0);
+ CPUWriteByte(0x4000084, 0);
+ }
+ }
}
void BIOS_RegisterRamReset()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("RegisterRamReset: 0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
-
- BIOS_RegisterRamReset(reg[0].I);
+ BIOS_RegisterRamReset(reg[0].I);
}
void BIOS_RLUnCompVram()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("RLUnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source & 0xFFFFFFFC);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
- int byteCount = 0;
- int byteShift = 0;
- uint32_t writeValue = 0;
-
- while(len > 0) {
- uint8_t d = CPUReadByte(source++);
- int l = d & 0x7F;
- if(d & 0x80) {
- uint8_t data = CPUReadByte(source++);
- l += 3;
- for(int i = 0;i < l; i++) {
- writeValue |= (data << byteShift);
- byteShift += 8;
- byteCount++;
-
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- } else {
- l++;
- for(int i = 0; i < l; i++) {
- writeValue |= (CPUReadByte(source++) << byteShift);
- byteShift += 8;
- byteCount++;
- if(byteCount == 2) {
- CPUWriteHalfWord(dest, writeValue);
- dest += 2;
- byteCount = 0;
- byteShift = 0;
- writeValue = 0;
- }
- len--;
- if(len == 0)
- return;
- }
- }
- }
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source & 0xFFFFFFFC);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int len = header >> 8;
+ int byteCount = 0;
+ int byteShift = 0;
+ uint32_t writeValue = 0;
+
+ while (len > 0)
+ {
+ uint8_t d = CPUReadByte(source++);
+ int l = d & 0x7F;
+ if (d & 0x80)
+ {
+ uint8_t data = CPUReadByte(source++);
+ l += 3;
+ for (int i = 0;i < l; ++i)
+ {
+ writeValue |= data << byteShift;
+ byteShift += 8;
+ ++byteCount;
+
+ if (byteCount == 2)
+ {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ else
+ {
+ ++l;
+ for (int i = 0; i < l; ++i)
+ {
+ writeValue |= CPUReadByte(source++) << byteShift;
+ byteShift += 8;
+ ++byteCount;
+ if (byteCount == 2)
+ {
+ CPUWriteHalfWord(dest, writeValue);
+ dest += 2;
+ byteCount = 0;
+ byteShift = 0;
+ writeValue = 0;
+ }
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ }
}
void BIOS_RLUnCompWram()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("RLUnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n",
- reg[0].I,
- reg[1].I,
- VCOUNT);
- }
-#endif
-
- uint32_t source = reg[0].I;
- uint32_t dest = reg[1].I;
-
- uint32_t header = CPUReadMemory(source & 0xFFFFFFFC);
- source += 4;
-
- if(((source & 0xe000000) == 0) ||
- ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
- return;
-
- int len = header >> 8;
-
- while(len > 0) {
- uint8_t d = CPUReadByte(source++);
- int l = d & 0x7F;
- if(d & 0x80) {
- uint8_t data = CPUReadByte(source++);
- l += 3;
- for(int i = 0;i < l; i++) {
- CPUWriteByte(dest++, data);
- len--;
- if(len == 0)
- return;
- }
- } else {
- l++;
- for(int i = 0; i < l; i++) {
- CPUWriteByte(dest++, CPUReadByte(source++));
- len--;
- if(len == 0)
- return;
- }
- }
- }
+ uint32_t source = reg[0].I;
+ uint32_t dest = reg[1].I;
+
+ uint32_t header = CPUReadMemory(source & 0xFFFFFFFC);
+ source += 4;
+
+ if (!(source & 0xe000000) || !((source + ((header >> 8) & 0x1fffff)) & 0xe000000))
+ return;
+
+ int len = header >> 8;
+
+ while (len > 0)
+ {
+ uint8_t d = CPUReadByte(source++);
+ int l = d & 0x7F;
+ if (d & 0x80)
+ {
+ uint8_t data = CPUReadByte(source++);
+ l += 3;
+ for (int i = 0; i < l; ++i)
+ {
+ CPUWriteByte(dest++, data);
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ else
+ {
+ ++l;
+ for (int i = 0; i < l; ++i)
+ {
+ CPUWriteByte(dest++, CPUReadByte(source++));
+ --len;
+ if (!len)
+ return;
+ }
+ }
+ }
}
void BIOS_SoftReset()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("SoftReset: (VCOUNT=%d)\n", VCOUNT);
- }
-#endif
-
- armState = true;
- armMode = 0x1F;
- armIrqEnable = false;
- C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
- reg[13].I = 0x03007F00;
- reg[14].I = 0x00000000;
- reg[16].I = 0x00000000;
- reg[R13_IRQ].I = 0x03007FA0;
- reg[R14_IRQ].I = 0x00000000;
- reg[SPSR_IRQ].I = 0x00000000;
- reg[R13_SVC].I = 0x03007FE0;
- reg[R14_SVC].I = 0x00000000;
- reg[SPSR_SVC].I = 0x00000000;
- uint8_t b = internalRAM[0x7ffa];
-
- memset(&internalRAM[0x7e00], 0, 0x200);
-
- if(b) {
- armNextPC = 0x02000000;
- reg[15].I = 0x02000004;
- } else {
- armNextPC = 0x08000000;
- reg[15].I = 0x08000004;
- }
+ armState = true;
+ armMode = 0x1F;
+ armIrqEnable = false;
+ C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
+ reg[13].I = 0x03007F00;
+ reg[14].I = 0x00000000;
+ reg[16].I = 0x00000000;
+ reg[R13_IRQ].I = 0x03007FA0;
+ reg[R14_IRQ].I = 0x00000000;
+ reg[SPSR_IRQ].I = 0x00000000;
+ reg[R13_SVC].I = 0x03007FE0;
+ reg[R14_SVC].I = 0x00000000;
+ reg[SPSR_SVC].I = 0x00000000;
+ uint8_t b = internalRAM[0x7ffa];
+
+ memset(&internalRAM[0x7e00], 0, 0x200);
+
+ if (b)
+ {
+ armNextPC = 0x02000000;
+ reg[15].I = 0x02000004;
+ }
+ else
+ {
+ armNextPC = 0x08000000;
+ reg[15].I = 0x08000004;
+ }
}
void BIOS_Sqrt()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Sqrt: %08x (VCOUNT=%2d)\n",
- reg[0].I,
- VCOUNT);
- }
-#endif
- reg[0].I = (uint32_t)sqrt((double)reg[0].I);
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("Sqrt: return=%08x\n",
- reg[0].I);
- }
-#endif
+ reg[0].I = static_cast<uint32_t>(std::sqrt(static_cast<double>(reg[0].I)));
}
void BIOS_MidiKey2Freq()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("MidiKey2Freq: WaveData=%08x mk=%08x fp=%08x\n",
- reg[0].I,
- reg[1].I,
- reg[2].I);
- }
-#endif
- int freq = CPUReadMemory(reg[0].I+4);
- double tmp;
- tmp = ((double)(180 - reg[1].I)) - ((double)reg[2].I / 256.f);
- tmp = pow((double)2.f, tmp / 12.f);
- reg[0].I = (int)((double)freq / tmp);
-
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("MidiKey2Freq: return %08x\n",
- reg[0].I);
- }
-#endif
+ int freq = CPUReadMemory(reg[0].I + 4);
+ double tmp = (180 - reg[1].I) - (reg[2].I / 256.0);
+ tmp = std::pow(2.0, tmp / 12.0);
+ reg[0].I = static_cast<int>(freq / tmp);
}
void BIOS_SndDriverJmpTableCopy()
{
-#ifdef GBA_LOGGING
- if(systemVerbose & VERBOSE_SWI) {
- log("SndDriverJmpTableCopy: dest=%08x\n",
- reg[0].I);
- }
-#endif
- for(int i = 0; i < 0x24; i++) {
- CPUWriteMemory(reg[0].I, 0x9c);
- reg[0].I += 4;
- }
-}
-
+ for (int i = 0; i < 0x24; ++i)
+ {
+ CPUWriteMemory(reg[0].I, 0x9c);
+ reg[0].I += 4;
+ }
+}
+
--- a/src/in_gsf/vbam/gba/bios.h
+++ b/src/in_gsf/vbam/gba/bios.h
@@ -12,7 +12,6 @@
extern void BIOS_Diff8bitUnFilterVram();
extern void BIOS_Diff16bitUnFilter();
extern void BIOS_Div();
-extern void BIOS_DivARM();
extern void BIOS_HuffUnComp();
extern void BIOS_LZ77UnCompVram();
extern void BIOS_LZ77UnCompWram();