diff --git a/Assets/dll/vb.wbx.gz b/Assets/dll/vb.wbx.gz index 19fe33ced0..ba0d7a6d71 100644 Binary files a/Assets/dll/vb.wbx.gz and b/Assets/dll/vb.wbx.gz differ diff --git a/waterbox/nyma/make-all-released-cores.sh b/waterbox/nyma/make-all-released-cores.sh index 3c802271a3..de328e99fe 100755 --- a/waterbox/nyma/make-all-released-cores.sh +++ b/waterbox/nyma/make-all-released-cores.sh @@ -9,5 +9,5 @@ make -f pcfx.mak $1 -j make -f ss.mak $1 -j make -f shock.mak $1 -j # make -f lynx.mak $1 -j -# make -f vb.mak $1 -j +make -f vb.mak $1 -j # make -f wswan.mak $1 -j diff --git a/waterbox/nyma/vb.cpp b/waterbox/nyma/vb.cpp new file mode 100644 index 0000000000..328fe4bca2 --- /dev/null +++ b/waterbox/nyma/vb.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include "nyma.h" +#include +#include + +using namespace MDFN_IEN_VB; + +extern Mednafen::MDFNGI EmulatedVB; + +void SetupMDFNGameInfo() +{ + Mednafen::MDFNGameInfo = &EmulatedVB; +} + +namespace MDFN_IEN_VB +{ + extern uint8* WRAM; + extern uint8* GPRAM; + extern uint32 GPRAM_Mask; + extern uint8* GPROM; + extern uint32 GPROM_Mask; + extern uint8 FB[2][2][0x6000]; + extern uint16 CHR_RAM[0x8000 / sizeof(uint16)]; + extern uint16 DRAM[0x20000 / sizeof(uint16)]; +} + +// todo +/*static void AccessSystemBus(uint8_t* buffer, int64_t address, int64_t count, bool write) +{ + if (write) + { + while (count--) + { + uint32_t addr = address++; + uint8_t* ret = buffer++; + } + } + else + { + while (count--) + { + uint32_t addr = address++; + uint8_t* ret = buffer++; + } + } +}*/ + +ECL_EXPORT void GetMemoryAreas(MemoryArea* m) +{ + int i = 0; + #define AddMemoryDomain(name,data,size,flags) do\ + {\ + m[i].Data = data;\ + m[i].Name = name;\ + m[i].Size = size;\ + m[i].Flags = flags;\ + i++;\ + }\ + while (0) + AddMemoryDomain("WRAM", WRAM, 65536, MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_PRIMARY); + AddMemoryDomain("CARTRAM", GPRAM, GPRAM_Mask + 1, MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_SAVERAMMABLE); + AddMemoryDomain("ROM", GPROM, GPROM_Mask + 1, MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4); + AddMemoryDomain("CHR RAM", CHR_RAM, sizeof(CHR_RAM), MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4); + AddMemoryDomain("DRAM", DRAM, sizeof(DRAM), MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4); + AddMemoryDomain("Framebuffer", FB, sizeof(FB), MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4); + //AddMemoryDomain("System Bus", (void*)AccessSystemBus, 1ull << 32, MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_FUNCTIONHOOK); +} diff --git a/waterbox/nyma/vb.mak b/waterbox/nyma/vb.mak index 36807a96c3..2baab55d03 100644 --- a/waterbox/nyma/vb.mak +++ b/waterbox/nyma/vb.mak @@ -2,6 +2,8 @@ include common.mak SRCS += \ $(filter-out %debug.cpp,$(call cppdir,vb)) \ - $(call cppdir,hw_cpu/v810) + $(call cppdir,hw_cpu/v810) \ + cdrom_dummy.cpp \ + vb.cpp include ../common.mak diff --git a/waterbox/vb/.vscode/settings.json b/waterbox/vb/.vscode/settings.json deleted file mode 100644 index edb0a83e80..0000000000 --- a/waterbox/vb/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "editor.detectIndentation": false, - "editor.insertSpaces": false, - "files.associations": { - "xiosbase": "cpp", - "xlocale": "cpp" - } -} \ No newline at end of file diff --git a/waterbox/vb/Makefile b/waterbox/vb/Makefile deleted file mode 100644 index 8abcd0561f..0000000000 --- a/waterbox/vb/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -CXXFLAGS := -I. \ - -Wall -Werror=int-to-pointer-cast \ - -std=c++0x -fomit-frame-pointer -fno-exceptions -fno-rtti \ - -DLSB_FIRST - -TARGET = vb.wbx - -SRCS = $(shell find $(ROOT_DIR) -type f -name '*.cpp') - -include ../common.mak diff --git a/waterbox/vb/blip/Blip_Buffer.cpp b/waterbox/vb/blip/Blip_Buffer.cpp deleted file mode 100644 index f04a1fc599..0000000000 --- a/waterbox/vb/blip/Blip_Buffer.cpp +++ /dev/null @@ -1,457 +0,0 @@ -// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ - -#include "Blip_Buffer.h" - -#include -#include -#include -#include -#include -#include - -/* Copyright (C) 2003-2006 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -int const silent_buf_size = 1; // size used for Silent_Blip_Buffer - -Blip_Buffer::Blip_Buffer() -{ - factor_ = (blip_u64)ULLONG_MAX; - offset_ = 0; - buffer_ = 0; - buffer_size_ = 0; - sample_rate_ = 0; - reader_accum_ = 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 -} - -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; - memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow -} - -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)"; - } - - // start with maximum length that resampled time can represent - blip_s64 new_size = (ULLONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64; - - // simple safety check, since code elsewhere may not be safe for sizes approaching (2 ^ 31). - if(new_size > ((1LL << 30) - 1)) - new_size = (1LL << 30) - 1; - - if ( msec != blip_max_length ) - { - blip_s64 s = ((blip_s64)new_rate * (msec + 1) + 999) / 1000; - 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"; - - //if(new_size > buffer_size_) - // memset(buffer_ + buffer_size_, 0, (new_size + blip_buffer_extra_) * sizeof *buffer_ - - buffer_ = (buf_t_*) p; - } - - buffer_size_ = new_size; - assert( buffer_size_ != silent_buf_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 - if ( clock_rate_ ) - clock_rate( clock_rate_ ); - bass_freq( bass_freq_ ); - - clear(); - - return 0; // success -} - -blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const -{ - double ratio = (double) sample_rate_ / rate; - blip_s64 factor = (blip_s64) floor( ratio * (1LL << 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; - int shift = 31; - if ( freq > 0 ) - { - shift = 13; - long f = (freq << 16) / sample_rate_; - while ( (f >>= 1) && --shift ) { } - } - bass_shift_ = shift; - //printf("%d\n", bass_shift_); -} - -void Blip_Buffer::end_frame( blip_time_t t ) -{ - offset_ += t * factor_; - assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length -} - -void Blip_Buffer::remove_silence( long count ) -{ - assert( count <= samples_avail() ); // tried to remove more samples than available - offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; -} - -long Blip_Buffer::count_samples( blip_time_t t ) const -{ - unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY; - unsigned long 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 - 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 ); - - // 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_ ); - } -} - -// Blip_Synth_ - -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); -} - -#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 ) - cutoff = 0.999; - - if ( treble < -300.0 ) - treble = -300.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 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 ); - - 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 -{ - // 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 ); -} - -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 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 ) - 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 ); - - 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]; - - // starts at 0 - for ( i = 0; i < blip_res; i++ ) - fimpulse [i] = 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 rescale = base_unit / 2 / total; - kernel_unit = (long) base_unit; - - // integrate, first difference, rescale, convert to int - double sum = 0.0; - double next = 0.0; - int const impulses_size_local = this->impulses_size(); - for ( i = 0; i < impulses_size_local; i++ ) - { - impulses [i] = (short) floor( (next - sum) * rescale + 0.5 ); - sum += fimpulse [i]; - next += fimpulse [i + blip_res]; - } - 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_ ) - { - // 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 ) - { - int shift = 0; - - // if unit is really small, might need to attenuate kernel - while ( factor < 2.0 ) - { - shift++; - factor *= 2.0; - } - - if ( shift ) - { - kernel_unit >>= shift; - assert( 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) (((impulses [i] + offset) >> shift) - offset2); - adjust_impulse(); - } - } - delta_factor = (int) floor( factor + 0.5 ); - //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit ); - } -} -#endif - -long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo ) -{ - long count = samples_avail(); - if ( count > max_samples ) - count = max_samples; - - if ( count ) - { - int const bass = BLIP_READER_BASS( *this ); - BLIP_READER_BEGIN( reader, *this ); - - if ( !stereo ) - { - for ( blip_long n = count; n; --n ) - { - blip_long s = BLIP_READER_READ( reader ); - if ( (blip_sample_t) s != s ) - s = 0x7FFF - (s >> 24); - *out++ = (blip_sample_t) s; - BLIP_READER_NEXT( reader, bass ); - } - } - else - { - for ( blip_long n = count; n; --n ) - { - blip_long s = BLIP_READER_READ( reader ); - if ( (blip_sample_t) s != s ) - s = 0x7FFF - (s >> 24); - *out = (blip_sample_t) s; - out += 2; - BLIP_READER_NEXT( reader, bass ); - } - } - BLIP_READER_END( reader, *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; - int prev = 0; - while ( count-- ) - { - blip_long s = (blip_long) *in++ << sample_shift; - *out += s - prev; - prev = s; - ++out; - } - *out -= prev; -} - diff --git a/waterbox/vb/blip/Blip_Buffer.h b/waterbox/vb/blip/Blip_Buffer.h deleted file mode 100644 index a8e90ee053..0000000000 --- a/waterbox/vb/blip/Blip_Buffer.h +++ /dev/null @@ -1,498 +0,0 @@ -// Band-limited sound synthesis buffer -// Various changes and hacks for use in Mednafen. - -#ifdef __GNUC__ - #define blip_inline inline __attribute__((always_inline)) -#else - #define blip_inline inline -#endif - -#include -#include - -// Blip_Buffer 0.4.1 -#ifndef BLIP_BUFFER_H -#define BLIP_BUFFER_H - -// Internal -typedef int32_t blip_long; -typedef uint32_t blip_ulong; -typedef int64_t blip_s64; -typedef uint64_t blip_u64; - -// Time unit at source clock rate -typedef blip_long blip_time_t; - -// Output samples are 16-bit signed, with a range of -32768 to 32767 -typedef short blip_sample_t; -enum { blip_sample_max = 32767 }; - -class Blip_Buffer { -public: - typedef const char* blargg_err_t; - - // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults - // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there - // isn't enough memory, returns error without affecting current buffer setup. - blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 ); - - // Set number of source time units per second - void clock_rate( long ); - - // End current time frame of specified duration and make its samples available - // (along with any still-unread samples) for reading with read_samples(). Begins - // a new time frame at the end of the current frame. - void end_frame( blip_time_t time ); - - // Read at most 'max_samples' out of buffer into 'dest', removing them from from - // the buffer. Returns number of samples actually read and removed. If stereo is - // true, increments 'dest' one extra time after writing each sample, to allow - // easy interleving of two channels into a stereo output buffer. - long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 ); - -// Additional optional features - - // Current output sample rate - long sample_rate() const; - - // Length of buffer, in milliseconds - int length() const; - - // Number of source time units per second - long clock_rate() const; - - // Set frequency high-pass filter frequency, where higher values reduce bass more - void bass_freq( int frequency ); - - // Number of samples delay from synthesis to samples read out - int output_latency() const; - - // Remove all available samples and clear buffer to silence. If 'entire_buffer' is - // false, just clears out any samples waiting rather than the entire buffer. - void clear( int entire_buffer = 1 ); - - // Number of samples available for reading with read_samples() - long samples_avail() const; - - // Remove 'count' samples from those waiting to be read - void remove_samples( long count ); - -// Experimental features - - // Count number of clocks needed until 'count' samples will be available. - // If buffer can't even hold 'count' samples, returns number of clocks until - // buffer becomes full. - blip_time_t count_clocks( long count ) const; - - // Number of raw samples that can be mixed within frame of specified duration. - long count_samples( blip_time_t duration ) const; - - // Mix 'count' samples from 'buf' into buffer. - void mix_samples( blip_sample_t const* buf, long count ); - - // not documented yet - void set_modified() { modified_ = 1; } - int clear_modified() { int b = modified_; modified_ = 0; return b; } - typedef blip_u64 blip_resampled_time_t; - void remove_silence( long count ); - blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; } - blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; } - blip_resampled_time_t clock_rate_factor( long clock_rate ) const; -public: - Blip_Buffer(); - ~Blip_Buffer(); - - // Deprecated - typedef blip_resampled_time_t resampled_time_t; - blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); } - blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); } -private: - // noncopyable - Blip_Buffer( const Blip_Buffer& ); - Blip_Buffer& operator = ( const Blip_Buffer& ); -public: - typedef blip_time_t buf_t_; - blip_u64 factor_; - blip_resampled_time_t offset_; - buf_t_* buffer_; - blip_long buffer_size_; - blip_long reader_accum_; - int bass_shift_; -private: - long sample_rate_; - long clock_rate_; - int bass_freq_; - int length_; - int modified_; - friend class Blip_Reader; -}; - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#define BLIP_BUFFER_ACCURACY 32 -#define BLIP_PHASE_BITS 8 - -// Number of bits in resample ratio fraction. Higher values give a more accurate ratio -// but reduce maximum buffer size. -//#ifndef BLIP_BUFFER_ACCURACY -// #define BLIP_BUFFER_ACCURACY 16 -//#endif - -// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in -// noticeable broadband noise when synthesizing high frequency square waves. -// Affects size of Blip_Synth objects since they store the waveform directly. -//#ifndef BLIP_PHASE_BITS -// #if BLIP_BUFFER_FAST -// #define BLIP_PHASE_BITS 8 -// #else -// #define BLIP_PHASE_BITS 6 -// #endif -//#endif - - // Internal - typedef blip_u64 blip_resampled_time_t; - int const blip_widest_impulse_ = 16; - int const blip_buffer_extra_ = blip_widest_impulse_ + 2; - int const blip_res = 1 << BLIP_PHASE_BITS; - class blip_eq_t; - - class Blip_Synth_Fast_ { - public: - Blip_Buffer* buf; - int last_amp; - int delta_factor; - - void volume_unit( double ); - Blip_Synth_Fast_(); - void treble_eq( blip_eq_t const& ) { } - }; - - class Blip_Synth_ { - public: - Blip_Buffer* buf; - int last_amp; - int delta_factor; - - void volume_unit( double ); - Blip_Synth_( short* impulses, int width ); - void treble_eq( blip_eq_t const& ); - private: - double volume_unit_; - short* const impulses; - int const width; - blip_long kernel_unit; - int impulses_size() const { return blip_res / 2 * width + 1; } - void adjust_impulse(); - }; - -// Quality level. Start with blip_good_quality. -const int blip_med_quality = 8; -const int blip_good_quality = 12; -const int blip_high_quality = 16; - -// Range specifies the greatest expected change in amplitude. Calculate it -// by finding the difference between the maximum and minimum expected -// amplitudes (max - min). -template -class Blip_Synth { -public: - // Set overall volume of waveform - void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); } - - // Configure low-pass filter (see blip_buffer.txt) - void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); } - - // Get/set Blip_Buffer used for output - Blip_Buffer* output() const { return impl.buf; } - void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; } - - // Update amplitude of waveform at given time. Using this requires a separate - // Blip_Synth for each waveform. - void update( blip_time_t time, int amplitude ); - -// Low-level interface - - // Add an amplitude transition of specified delta, optionally into specified buffer - // rather than the one set with output(). Delta can be positive or negative. - // The actual change in amplitude is delta * (volume / range) - void offset( blip_time_t, int delta, Blip_Buffer* ) const; - void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); } - - // Works directly in terms of fractional output samples. Contact author for more info. - void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const; - - // Same as offset(), except code is inlined for higher performance - void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { - offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); - } - void offset_inline( blip_time_t t, int delta ) const { - offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); - } - -private: -#if BLIP_BUFFER_FAST - Blip_Synth_Fast_ impl; -#else - Blip_Synth_ impl; - typedef short imp_t; - imp_t impulses [blip_res * (quality / 2) + 1]; -public: - Blip_Synth() : impl( impulses, quality ) { } -#endif -}; - -// Low-pass equalization parameters -class blip_eq_t { -public: - // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce - // treble, small positive values (0 to 5.0) increase treble. - blip_eq_t( double treble_db = 0 ); - - // See blip_buffer.txt - blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 ); - -private: - double treble; - long rolloff_freq; - long sample_rate; - long cutoff_freq; - void generate( float* out, int count ) const; - friend class Blip_Synth_; -}; - -int const blip_sample_bits = 30; - -// Dummy Blip_Buffer to direct sound output to, for easy muting without -// having to stop sound code. -class Silent_Blip_Buffer : public Blip_Buffer { - buf_t_ buf [blip_buffer_extra_ + 1]; -public: - // The following cannot be used (an assertion will fail if attempted): - blargg_err_t set_sample_rate( long samples_per_sec, int msec_length ); - blip_time_t count_clocks( long count ) const; - void mix_samples( blip_sample_t const* buf, long count ); - - Silent_Blip_Buffer(); -}; - - #if defined (__GNUC__) || _MSC_VER >= 1100 - #define BLIP_RESTRICT __restrict - #else - #define BLIP_RESTRICT - #endif - -// Optimized reading from Blip_Buffer, for use in custom sample output - -// Begin reading from buffer. Name should be unique to the current block. -#define BLIP_READER_BEGIN( name, blip_buffer ) \ - const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\ - blip_long name##_reader_accum = (blip_buffer).reader_accum_ - -// Get value to pass to BLIP_READER_NEXT() -#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_) - -// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal -// code at the cost of having no bass control -int const blip_reader_default_bass = 9; - -// Current sample -#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16)) - -// Current raw sample in full internal resolution -#define BLIP_READER_READ_RAW( name ) (name##_reader_accum) - -// Advance to next sample -#define BLIP_READER_NEXT( name, bass ) \ - (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass))) - -// End reading samples from buffer. The number of samples read must now be removed -// using Blip_Buffer::remove_samples(). -#define BLIP_READER_END( name, blip_buffer ) \ - (void) ((blip_buffer).reader_accum_ = name##_reader_accum) - - -// Compatibility with older version -const long blip_unscaled = 65535; -const int blip_low_quality = blip_med_quality; -const int blip_best_quality = blip_high_quality; - -// Deprecated; use BLIP_READER macros as follows: -// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf ); -// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf ); -// r.read() -> BLIP_READER_READ( r ) -// r.read_raw() -> BLIP_READER_READ_RAW( r ) -// r.next( bass ) -> BLIP_READER_NEXT( r, bass ) -// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass ) -// r.end( buf ) -> BLIP_READER_END( r, buf ) -class Blip_Reader { -public: - int begin( Blip_Buffer& ); - blip_long read() const { return accum >> (blip_sample_bits - 16); } - blip_long read_raw() const { return accum; } - void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); } - void end( Blip_Buffer& b ) { b.reader_accum_ = accum; } - -private: - const Blip_Buffer::buf_t_* buf; - blip_long accum; -}; - -// End of public interface - -#include - -template -blip_inline void Blip_Synth::offset_resampled( blip_resampled_time_t time, - int delta, Blip_Buffer* blip_buf ) const -{ - // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the - // need for a longer buffer as set by set_sample_rate(). - assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ ); - delta *= impl.delta_factor; - blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY); - int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1)); - -#if BLIP_BUFFER_FAST - blip_long left = buf [0] + delta; - - // Kind of crappy, but doing shift after multiply results in overflow. - // Alternate way of delaying multiply by delta_factor results in worse - // sub-sample resolution. - blip_long right = (delta >> BLIP_PHASE_BITS) * phase; - left -= right; - right += buf [1]; - - buf [0] = left; - buf [1] = right; -#else - - int const fwd = (blip_widest_impulse_ - quality) / 2; - int const rev = fwd + quality - 2; - int const mid = quality / 2 - 1; - - imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase; - - #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - - // straight forward implementation resulted in better code on GCC for x86 - - #define ADD_IMP( out, in ) \ - buf [out] += (blip_long) imp [blip_res * (in)] * delta - - #define BLIP_FWD( i ) {\ - ADD_IMP( fwd + i, i );\ - ADD_IMP( fwd + 1 + i, i + 1 );\ - } - #define BLIP_REV( r ) {\ - ADD_IMP( rev - r, r + 1 );\ - ADD_IMP( rev + 1 - r, r );\ - } - - BLIP_FWD( 0 ) - if ( quality > 8 ) BLIP_FWD( 2 ) - if ( quality > 12 ) BLIP_FWD( 4 ) - { - ADD_IMP( fwd + mid - 1, mid - 1 ); - ADD_IMP( fwd + mid , mid ); - imp = impulses + phase; - } - if ( quality > 12 ) BLIP_REV( 6 ) - if ( quality > 8 ) BLIP_REV( 4 ) - BLIP_REV( 2 ) - - ADD_IMP( rev , 1 ); - ADD_IMP( rev + 1, 0 ); - - #else - - // for RISC processors, help compiler by reading ahead of writes - - #define BLIP_FWD( i ) {\ - blip_long t0 = i0 * delta + buf [fwd + i];\ - blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\ - i0 = imp [blip_res * (i + 2)];\ - buf [fwd + i] = t0;\ - buf [fwd + 1 + i] = t1;\ - } - #define BLIP_REV( r ) {\ - blip_long t0 = i0 * delta + buf [rev - r];\ - blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\ - i0 = imp [blip_res * (r - 1)];\ - buf [rev - r] = t0;\ - buf [rev + 1 - r] = t1;\ - } - - blip_long i0 = *imp; - BLIP_FWD( 0 ) - if ( quality > 8 ) BLIP_FWD( 2 ) - if ( quality > 12 ) BLIP_FWD( 4 ) - { - blip_long t0 = i0 * delta + buf [fwd + mid - 1]; - blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ]; - imp = impulses + phase; - i0 = imp [blip_res * mid]; - buf [fwd + mid - 1] = t0; - buf [fwd + mid ] = t1; - } - if ( quality > 12 ) BLIP_REV( 6 ) - if ( quality > 8 ) BLIP_REV( 4 ) - BLIP_REV( 2 ) - - blip_long t0 = i0 * delta + buf [rev ]; - blip_long t1 = *imp * delta + buf [rev + 1]; - buf [rev ] = t0; - buf [rev + 1] = t1; - #endif - -#endif -} - -#undef BLIP_FWD -#undef BLIP_REV - -template -#if BLIP_BUFFER_FAST - blip_inline -#endif -void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const -{ - offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); -} - -template -#if BLIP_BUFFER_FAST - blip_inline -#endif -void Blip_Synth::update( blip_time_t t, int amp ) -{ - int delta = amp - impl.last_amp; - impl.last_amp = amp; - offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); -} - -blip_inline blip_eq_t::blip_eq_t( double t ) : - treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { } -blip_inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) : - treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { } - -blip_inline int Blip_Buffer::length() const { return length_; } -blip_inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); } -blip_inline long Blip_Buffer::sample_rate() const { return sample_rate_; } -blip_inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; } -blip_inline long Blip_Buffer::clock_rate() const { return clock_rate_; } -blip_inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); } - -blip_inline int Blip_Reader::begin( Blip_Buffer& blip_buf ) -{ - buf = blip_buf.buffer_; - accum = blip_buf.reader_accum_; - return blip_buf.bass_shift_; -} - -int const blip_max_length = 0; -int const blip_default_length = 250; - -#endif diff --git a/waterbox/vb/endian.h b/waterbox/vb/endian.h deleted file mode 100644 index e78a0c577f..0000000000 --- a/waterbox/vb/endian.h +++ /dev/null @@ -1,494 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* endian.h: -** Copyright (C) 2006-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_ENDIAN_H -#define __MDFN_ENDIAN_H - -void Endian_A16_Swap(void *src, uint32 nelements); -void Endian_A32_Swap(void *src, uint32 nelements); -void Endian_A64_Swap(void *src, uint32 nelements); - -void Endian_A16_NE_LE(void *src, uint32 nelements); -void Endian_A32_NE_LE(void *src, uint32 nelements); -void Endian_A64_NE_LE(void *src, uint32 nelements); - -void Endian_A16_NE_BE(void *src, uint32 nelements); -void Endian_A32_NE_BE(void *src, uint32 nelements); -void Endian_A64_NE_BE(void *src, uint32 nelements); - -void Endian_V_NE_LE(void* p, size_t len); -void Endian_V_NE_BE(void* p, size_t len); - -// -// -// - -static INLINE uint32 BitsExtract(const uint8* ptr, const size_t bit_offset, const size_t bit_count) -{ - uint32 ret = 0; - - for(size_t x = 0; x < bit_count; x++) - { - size_t co = bit_offset + x; - bool b = (ptr[co >> 3] >> (co & 7)) & 1; - - ret |= (uint64)b << x; - } - - return ret; -} - -static INLINE void BitsIntract(uint8* ptr, const size_t bit_offset, const size_t bit_count, uint32 value) -{ - for(size_t x = 0; x < bit_count; x++) - { - size_t co = bit_offset + x; - bool b = (value >> x) & 1; - uint8 tmp = ptr[co >> 3]; - - tmp &= ~(1 << (co & 7)); - tmp |= b << (co & 7); - - ptr[co >> 3] = tmp; - } -} - -/* - Regarding safety of calling MDFN_*sb on dynamically-allocated memory with new uint8[], see C++ standard 3.7.3.1(i.e. it should be - safe provided the offsets into the memory are aligned/multiples of the MDFN_*sb access type). malloc()'d and calloc()'d - memory should be safe as well. - - Statically-allocated arrays/memory should be unioned with a big POD type or C++11 "alignas"'d. (May need to audit code to ensure - this is being done). -*/ - -static INLINE uint16 MDFN_bswap16(uint16 v) -{ - return (v << 8) | (v >> 8); -} - -static INLINE uint32 MDFN_bswap32(uint32 v) -{ - return (v << 24) | ((v & 0xFF00) << 8) | ((v >> 8) & 0xFF00) | (v >> 24); -} - -static INLINE uint64 MDFN_bswap64(uint64 v) -{ - return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(v >> 16) << 16); -} - -#ifdef LSB_FIRST - #define MDFN_ENDIANH_IS_BIGENDIAN 0 -#else - #define MDFN_ENDIANH_IS_BIGENDIAN 1 -#endif - -// -// X endian. -// -template -static INLINE T MDFN_deXsb(const void* ptr) -{ - T tmp; - - memcpy(&tmp, MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), sizeof(T)); - - if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN) - { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins."); - - if(sizeof(T) == 8) - return MDFN_bswap64(tmp); - else if(sizeof(T) == 4) - return MDFN_bswap32(tmp); - else if(sizeof(T) == 2) - return MDFN_bswap16(tmp); - } - - return tmp; -} - -// -// Native endian. -// -template -static INLINE T MDFN_densb(const void* ptr) -{ - return MDFN_deXsb<-1, T, aligned>(ptr); -} - -// -// Little endian. -// -template -static INLINE T MDFN_delsb(const void* ptr) -{ - return MDFN_deXsb<0, T, aligned>(ptr); -} - -template -static INLINE uint16 MDFN_de16lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -static INLINE uint32 MDFN_de24lsb(const void* ptr) -{ - const uint8* ptr_u8 = (const uint8*)ptr; - - return (ptr_u8[0] << 0) | (ptr_u8[1] << 8) | (ptr_u8[2] << 16); -} - -template -static INLINE uint32 MDFN_de32lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -template -static INLINE uint64 MDFN_de64lsb(const void* ptr) -{ - return MDFN_delsb(ptr); -} - -// -// Big endian. -// -template -static INLINE T MDFN_demsb(const void* ptr) -{ - return MDFN_deXsb<1, T, aligned>(ptr); -} - -template -static INLINE uint16 MDFN_de16msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -static INLINE uint32 MDFN_de24msb(const void* ptr) -{ - const uint8* ptr_u8 = (const uint8*)ptr; - - return (ptr_u8[0] << 16) | (ptr_u8[1] << 8) | (ptr_u8[2] << 0); -} - -template -static INLINE uint32 MDFN_de32msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -template -static INLINE uint64 MDFN_de64msb(const void* ptr) -{ - return MDFN_demsb(ptr); -} - -// -// -// -// -// -// -// -// - -// -// X endian. -// -template -static INLINE void MDFN_enXsb(void* ptr, T value) -{ - T tmp = value; - - if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN) - { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins."); - - if(sizeof(T) == 8) - tmp = MDFN_bswap64(value); - else if(sizeof(T) == 4) - tmp = MDFN_bswap32(value); - else if(sizeof(T) == 2) - tmp = MDFN_bswap16(value); - } - - memcpy(MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), &tmp, sizeof(T)); -} - -// -// Native endian. -// -template -static INLINE void MDFN_ennsb(void* ptr, T value) -{ - MDFN_enXsb<-1, T, aligned>(ptr, value); -} - -// -// Little endian. -// -template -static INLINE void MDFN_enlsb(void* ptr, T value) -{ - MDFN_enXsb<0, T, aligned>(ptr, value); -} - -template -static INLINE void MDFN_en16lsb(void* ptr, uint16 value) -{ - MDFN_enlsb(ptr, value); -} - -static INLINE void MDFN_en24lsb(void* ptr, uint32 value) -{ - uint8* ptr_u8 = (uint8*)ptr; - - ptr_u8[0] = value >> 0; - ptr_u8[1] = value >> 8; - ptr_u8[2] = value >> 16; -} - -template -static INLINE void MDFN_en32lsb(void* ptr, uint32 value) -{ - MDFN_enlsb(ptr, value); -} - -template -static INLINE void MDFN_en64lsb(void* ptr, uint64 value) -{ - MDFN_enlsb(ptr, value); -} - - -// -// Big endian. -// -template -static INLINE void MDFN_enmsb(void* ptr, T value) -{ - MDFN_enXsb<1, T, aligned>(ptr, value); -} - -template -static INLINE void MDFN_en16msb(void* ptr, uint16 value) -{ - MDFN_enmsb(ptr, value); -} - -static INLINE void MDFN_en24msb(void* ptr, uint32 value) -{ - uint8* ptr_u8 = (uint8*)ptr; - - ptr_u8[0] = value >> 16; - ptr_u8[1] = value >> 8; - ptr_u8[2] = value >> 0; -} - -template -static INLINE void MDFN_en32msb(void* ptr, uint32 value) -{ - MDFN_enmsb(ptr, value); -} - -template -static INLINE void MDFN_en64msb(void* ptr, uint64 value) -{ - MDFN_enmsb(ptr, value); -} - - -// -// -// -// -// -// - -template -static INLINE uint8* ne16_ptr_be(BT* const base, const size_t byte_offset) -{ -#ifdef MSB_FIRST - return (uint8*)base + (byte_offset &~ (sizeof(T) - 1)); -#else - return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (2 - std::min(2, sizeof(T))))); -#endif -} - -template -static INLINE void ne16_wbo_be(uint16* const base, const size_t byte_offset, const T value) -{ - uint8* const ptr = ne16_ptr_be(base, byte_offset); - - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - - ptr16[0] = value >> 16; - ptr16[1] = value; - } - else - *(T*)ptr = value; -} - -template -static INLINE T ne16_rbo_be(const uint16* const base, const size_t byte_offset) -{ - uint8* const ptr = ne16_ptr_be(base, byte_offset); - - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - T tmp; - - tmp = ptr16[0] << 16; - tmp |= ptr16[1]; - - return tmp; - } - else - return *(T*)ptr; -} - -template -static INLINE void ne16_rwbo_be(uint16* const base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne16_wbo_be(base, byte_offset, *value); - else - *value = ne16_rbo_be(base, byte_offset); -} - -// -// -// - -template -static INLINE uint8* ne16_ptr_le(BT* const base, const size_t byte_offset) -{ -#ifdef LSB_FIRST - return (uint8*)base + (byte_offset &~ (sizeof(T) - 1)); -#else - return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (2 - std::min(2, sizeof(T))))); -#endif -} - -template -static INLINE void ne16_wbo_le(uint16* const base, const size_t byte_offset, const T value) -{ - uint8* const ptr = ne16_ptr_le(base, byte_offset); - - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - - ptr16[0] = value; - ptr16[1] = value >> 16; - } - else - *(T*)ptr = value; -} - -template -static INLINE T ne16_rbo_le(const uint16* const base, const size_t byte_offset) -{ - uint8* const ptr = ne16_ptr_le(base, byte_offset); - - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - - if(sizeof(T) == 4) - { - uint16* const ptr16 = (uint16*)ptr; - T tmp; - - tmp = ptr16[0]; - tmp |= ptr16[1] << 16; - - return tmp; - } - else - return *(T*)ptr; -} - - -template -static INLINE void ne16_rwbo_le(uint16* const base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne16_wbo_le(base, byte_offset, *value); - else - *value = ne16_rbo_le(base, byte_offset); -} - -// -// -// -template -static INLINE uint8* ne64_ptr_be(uint64* const base, const size_t byte_offset) -{ -#ifdef MSB_FIRST - return (uint8*)base + (byte_offset &~ (sizeof(T) - 1)); -#else - return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (8 - sizeof(T)))); -#endif -} - -template -static INLINE void ne64_wbo_be(uint64* const base, const size_t byte_offset, const T value) -{ - uint8* const ptr = ne64_ptr_be(base, byte_offset); - - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size"); - - memcpy(MDFN_ASSUME_ALIGNED(ptr, sizeof(T)), &value, sizeof(T)); -} - -template -static INLINE T ne64_rbo_be(uint64* const base, const size_t byte_offset) -{ - uint8* const ptr = ne64_ptr_be(base, byte_offset); - T ret; - - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size"); - - memcpy(&ret, MDFN_ASSUME_ALIGNED(ptr, sizeof(T)), sizeof(T)); - - return ret; -} - -template -static INLINE void ne64_rwbo_be(uint64* const base, const size_t byte_offset, T* value) -{ - if(IsWrite) - ne64_wbo_be(base, byte_offset, *value); - else - *value = ne64_rbo_be(base, byte_offset); -} - -#endif diff --git a/waterbox/vb/git.h b/waterbox/vb/git.h deleted file mode 100644 index d9e8108b3d..0000000000 --- a/waterbox/vb/git.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -struct MDFN_Surface -{ - uint32 *pixels; - int pitch32; -}; - -struct MDFN_Rect -{ - int x, y, w, h; -}; - -struct EmulateSpecStruct -{ - // Pitch(32-bit) must be equal to width and >= the "fb_width" specified in the MDFNGI struct for the emulated system. - // Height must be >= to the "fb_height" specified in the MDFNGI struct for the emulated system. - // The framebuffer pointed to by surface->pixels is written to by the system emulation code. - uint32 *pixels; - - // Pointer to sound buffer, set by the driver code, that the emulation code should render sound to. - // Guaranteed to be at least 500ms in length, but emulation code really shouldn't exceed 40ms or so. Additionally, if emulation code - // generates >= 100ms, - // DEPRECATED: Emulation code may set this pointer to a sound buffer internal to the emulation module. - int16 *SoundBuf; - - // Number of cycles that this frame consumed, using MDFNGI::MasterClock as a time base. - // Set by emulation code. - int64 MasterCycles; - - // Set by the system emulation code every frame, to denote the horizontal and vertical offsets of the image, and the size - // of the image. If the emulated system sets the elements of LineWidths, then the width(w) of this structure - // is ignored while drawing the image. - MDFN_Rect DisplayRect; - - // Maximum size of the sound buffer, in frames. Set by the driver code. - int32 SoundBufMaxSize; - - // Number of frames currently in internal sound buffer. Set by the system emulation code, to be read by the driver code. - int32 SoundBufSize; - - // 0 UDLR SelectStartBA UDLR(right dpad) LtrigRtrig 13 - int32 Buttons; - - // set by core, true if lagged - int32 Lagged; -}; - -/*typedef struct -{ - - void (*Emulate)(EmulateSpecStruct *espec); - void (*TransformInput)(void); // Called before Emulate, and within MDFN_MidSync(), to implement stuff like setting-controlled PC Engine SEL+RUN button exclusion in a way - // that won't cause desyncs with movies and netplay. - - void (*SetInput)(unsigned port, const char *type, uint8* data); - bool (*SetMedia)(uint32 drive_idx, uint32 state_idx, uint32 media_idx, uint32 orientation_idx); - - - // Called when netplay starts, or the controllers controlled by local players changes during - // an existing netplay session. Called with ~(uint64)0 when netplay ends. - // (For future use in implementing portable console netplay) - void (*NPControlNotif)(uint64 c); - - const MDFNSetting *Settings; - - // Time base for EmulateSpecStruct::MasterCycles - // MasterClock must be >= MDFN_MASTERCLOCK_FIXED(1.0) - // All or part of the fractional component may be ignored in some timekeeping operations in the emulator to prevent integer overflow, - // so it is unwise to have a fractional component when the integral component is very small(less than say, 10000). - #define MDFN_MASTERCLOCK_FIXED(n) ((int64)((double)(n) * (1LL << 32))) - int64 MasterClock; - - // Nominal frames per second * 65536 * 256, truncated. - // May be deprecated in the future due to many systems having slight frame rate programmability. - uint32 fps; - - // multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability - // to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver - // code to set the linear interpolation on by default. - // - // lcm_width and lcm_height are the least common multiples of all possible - // resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512, - // lcm = 1024) - // - // nominal_width and nominal_height specify the resolution that Mednafen should display - // the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array - // passed through espec to the Emulate() function. - // - bool multires; - - int lcm_width; - int lcm_height; - - - int nominal_width; - int nominal_height; - - int fb_width; // Width of the framebuffer(not necessarily width of the image). MDFN_Surface width should be >= this. - int fb_height; // Height of the framebuffer passed to the Emulate() function(not necessarily height of the image) - - int soundchan; // Number of output sound channels. Only values of 1 and 2 are currently supported. - - - int rotated; - - std::string name; // Game name, UTF-8 encoding - uint8 MD5[16]; - uint8 GameSetMD5[16]; // A unique ID for the game set this CD belongs to, only used in PC-FX emulation. - bool GameSetMD5Valid; // True if GameSetMD5 is valid. - - VideoSystems VideoSystem; - GameMediumTypes GameType; // Deprecated. - - RMD_Layout* RMD; - - const char *cspecial; // Special cart expansion: DIP switches, barcode reader, etc. - - std::vectorDesiredInput; // Desired input device for the input ports, NULL for don't care - - // For mouse relative motion. - double mouse_sensitivity; - - - // - // For absolute coordinates(IDIT_X_AXIS and IDIT_Y_AXIS), usually mapped to a mouse(hence the naming). - // - float mouse_scale_x, mouse_scale_y; - float mouse_offs_x, mouse_offs_y; -} MDFNGI;*/ diff --git a/waterbox/vb/input.cpp b/waterbox/vb/input.cpp deleted file mode 100644 index b895f9a5d9..0000000000 --- a/waterbox/vb/input.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* input.cpp: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "vb.h" -#include "input.h" - -namespace MDFN_IEN_VB -{ -static bool InstantReadHack; - -static bool IntPending; - -static uint16 PadData; -static uint16 PadLatched; - -static uint8 SCR; -static uint16 SDR; - -#define SCR_S_ABT_DIS 0x01 -#define SCR_SI_STAT 0x02 -#define SCR_HW_SI 0x04 -#define SCR_SOFT_CLK 0x10 - -#define SCR_PARA_SI 0x20 -#define SCR_K_INT_INH 0x80 - -static uint32 ReadBitPos; -static int32 ReadCounter; - -static v810_timestamp_t last_ts; - -void VBINPUT_Init(void) -{ - InstantReadHack = true; -} - -void VBINPUT_SetInstantReadHack(bool enabled) -{ - InstantReadHack = enabled; -} - -uint8 VBINPUT_Read(v810_timestamp_t ×tamp, uint32 A) -{ - uint8 ret = 0; - - VBINPUT_Update(timestamp); - - //if(((A & 0xFF) == 0x10 || (A & 0xFF) == 0x14)) - // printf("Read %d\n", timestamp); - - //if(((A & 0xFF) == 0x10 || (A & 0xFF) == 0x14) && ReadCounter > 0) - //{ - // printf("Input port read during hardware transfer: %08x %d\n", A, timestamp); - //} - - switch (A & 0xFF) - { - case 0x10: - if (InstantReadHack) - ret = PadData; - else - ret = SDR & 0xFF; - break; - - case 0x14: - if (InstantReadHack) - ret = PadData >> 8; - else - ret = SDR >> 8; - break; - - case 0x28: - ret = SCR | (0x40 | 0x08 | SCR_HW_SI); - if (ReadCounter > 0) - ret |= SCR_SI_STAT; - break; - } - - // printf("Input Read: %08x %02x\n", A, ret); - VB_SetEvent(VB_EVENT_INPUT, (ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); - - return (ret); -} - -void VBINPUT_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V) -{ - VBINPUT_Update(timestamp); - - //printf("Input write: %d, %08x %02x\n", timestamp, A, V); - switch (A & 0xFF) - { - case 0x28: - if ((V & SCR_HW_SI) && !(SCR & SCR_S_ABT_DIS) && ReadCounter <= 0) - { - //printf("Start Read: %d\n", timestamp); - PadLatched = PadData; - ReadBitPos = 0; - ReadCounter = 640; - } - - if (V & SCR_S_ABT_DIS) - { - ReadCounter = 0; - ReadBitPos = 0; - } - - if (V & SCR_K_INT_INH) - { - IntPending = false; - VBIRQ_Assert(VBIRQ_SOURCE_INPUT, IntPending); - } - - SCR = V & (0x80 | 0x20 | 0x10 | 1); - break; - } - - VB_SetEvent(VB_EVENT_INPUT, (ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); -} - -void VBINPUT_Frame(const void* ptr) -{ - PadData = (MDFN_de16lsb(ptr) << 2) | 0x2; -} - -v810_timestamp_t VBINPUT_Update(const v810_timestamp_t timestamp) -{ - int32 clocks = timestamp - last_ts; - - if (ReadCounter > 0) - { - ReadCounter -= clocks; - - while (ReadCounter <= 0) - { - SDR &= ~(1 << ReadBitPos); - SDR |= PadLatched & (1 << ReadBitPos); - - ReadBitPos++; - if (ReadBitPos < 16) - ReadCounter += 640; - else - { - //printf("Read End: %d\n", timestamp); - if (!(SCR & SCR_K_INT_INH)) - { - //printf("Input IRQ: %d\n", timestamp); - IntPending = true; - VBIRQ_Assert(VBIRQ_SOURCE_INPUT, IntPending); - } - break; - } - } - } - - last_ts = timestamp; - - return ((ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); -} - -void VBINPUT_ResetTS(void) -{ - last_ts = 0; -} - -void VBINPUT_Power(void) -{ - last_ts = 0; - PadData = 0; - PadLatched = 0; - SDR = 0; - SCR = 0; - ReadBitPos = 0; - ReadCounter = 0; - IntPending = false; - - VBIRQ_Assert(VBIRQ_SOURCE_INPUT, 0); -} -} diff --git a/waterbox/vb/input.h b/waterbox/vb/input.h deleted file mode 100644 index 1ee57c19d7..0000000000 --- a/waterbox/vb/input.h +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* input.h: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __VB_INPUT_H -#define __VB_INPUT_H - -namespace MDFN_IEN_VB -{ - -void VBINPUT_Init(void) MDFN_COLD; -void VBINPUT_SetInstantReadHack(bool); - -void VBINPUT_SetInput(unsigned port, const char *type, uint8 *ptr); - -uint8 VBINPUT_Read(v810_timestamp_t ×tamp, uint32 A); - -void VBINPUT_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V); - -void VBINPUT_Frame(const void* ptr); - -int32 VBINPUT_Update(const int32 timestamp); -void VBINPUT_ResetTS(void); - - -void VBINPUT_Power(void); -} -#endif diff --git a/waterbox/vb/math_ops.h b/waterbox/vb/math_ops.h deleted file mode 100644 index 4154f2d49b..0000000000 --- a/waterbox/vb/math_ops.h +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* math_ops.h: -** Copyright (C) 2007-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* -** Some ideas from: -** blargg -** http://graphics.stanford.edu/~seander/bithacks.html -*/ - -#ifndef __MDFN_MATH_OPS_H -#define __MDFN_MATH_OPS_H - -#if defined(_MSC_VER) - #include -#endif - -static INLINE unsigned MDFN_lzcount16_0UD(uint16 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return 15 ^ 31 ^ __builtin_clz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanReverse(&idx, v); - - return 15 ^ idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !(v & 0xFF00) << 3; v <<= tmp; ret += tmp; - tmp = !(v & 0xF000) << 2; v <<= tmp; ret += tmp; - tmp = !(v & 0xC000) << 1; v <<= tmp; ret += tmp; - tmp = !(v & 0x8000) << 0; ret += tmp; - - return(ret); - #endif -} - -static INLINE unsigned MDFN_lzcount32_0UD(uint32 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_clz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanReverse(&idx, v); - - return 31 ^ idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !(v & 0xFFFF0000) << 4; v <<= tmp; ret += tmp; - tmp = !(v & 0xFF000000) << 3; v <<= tmp; ret += tmp; - tmp = !(v & 0xF0000000) << 2; v <<= tmp; ret += tmp; - tmp = !(v & 0xC0000000) << 1; v <<= tmp; ret += tmp; - tmp = !(v & 0x80000000) << 0; ret += tmp; - - return(ret); - #endif -} - -static INLINE unsigned MDFN_lzcount64_0UD(uint64 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_clzll(v); - #elif defined(_MSC_VER) - #if defined(_WIN64) - unsigned long idx; - _BitScanReverse64(&idx, v); - return 63 ^ idx; - #else - unsigned long idx0; - unsigned long idx1; - - _BitScanReverse(&idx1, v >> 0); - idx1 -= 32; - if(!_BitScanReverse(&idx0, v >> 32)) - idx0 = idx1; - - idx0 += 32; - - return 63 ^ idx0; - #endif - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !(v & 0xFFFFFFFF00000000ULL) << 5; v <<= tmp; ret += tmp; - tmp = !(v & 0xFFFF000000000000ULL) << 4; v <<= tmp; ret += tmp; - tmp = !(v & 0xFF00000000000000ULL) << 3; v <<= tmp; ret += tmp; - tmp = !(v & 0xF000000000000000ULL) << 2; v <<= tmp; ret += tmp; - tmp = !(v & 0xC000000000000000ULL) << 1; v <<= tmp; ret += tmp; - tmp = !(v & 0x8000000000000000ULL) << 0; ret += tmp; - - return(ret); - #endif -} - -static INLINE unsigned MDFN_tzcount16_0UD(uint16 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_ctz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanForward(&idx, v); - - return idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !( (uint8)v) << 3; v >>= tmp; ret += tmp; - tmp = !(v & 0x000F) << 2; v >>= tmp; ret += tmp; - tmp = !(v & 0x0003) << 1; v >>= tmp; ret += tmp; - tmp = !(v & 0x0001) << 0; ret += tmp; - - return ret; - #endif -} - -static INLINE unsigned MDFN_tzcount32_0UD(uint32 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_ctz(v); - #elif defined(_MSC_VER) - unsigned long idx; - - _BitScanForward(&idx, v); - - return idx; - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !((uint16)v) << 4; v >>= tmp; ret += tmp; - tmp = !( (uint8)v) << 3; v >>= tmp; ret += tmp; - tmp = !(v & 0x000F) << 2; v >>= tmp; ret += tmp; - tmp = !(v & 0x0003) << 1; v >>= tmp; ret += tmp; - tmp = !(v & 0x0001) << 0; ret += tmp; - - return ret; - #endif -} - -static INLINE unsigned MDFN_tzcount64_0UD(uint64 v) -{ - #if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER) - return __builtin_ctzll(v); - #elif defined(_MSC_VER) - #if defined(_WIN64) - unsigned long idx; - _BitScanForward64(&idx, v); - return idx; - #else - unsigned long idx0, idx1; - - _BitScanForward(&idx1, v >> 32); - idx1 += 32; - if(!_BitScanForward(&idx0, v)) - idx0 = idx1; - - return idx0; - #endif - #else - unsigned ret = 0; - unsigned tmp; - - tmp = !((uint32)v) << 5; v >>= tmp; ret += tmp; - tmp = !((uint16)v) << 4; v >>= tmp; ret += tmp; - tmp = !( (uint8)v) << 3; v >>= tmp; ret += tmp; - tmp = !(v & 0x000F) << 2; v >>= tmp; ret += tmp; - tmp = !(v & 0x0003) << 1; v >>= tmp; ret += tmp; - tmp = !(v & 0x0001) << 0; ret += tmp; - - return ret; - #endif -} - -// -// Result is defined for all possible inputs(including 0). -// -static INLINE unsigned MDFN_lzcount16(uint16 v) { return !v ? 16 : MDFN_lzcount16_0UD(v); } -static INLINE unsigned MDFN_lzcount32(uint32 v) { return !v ? 32 : MDFN_lzcount32_0UD(v); } -static INLINE unsigned MDFN_lzcount64(uint64 v) { return !v ? 64 : MDFN_lzcount64_0UD(v); } - -static INLINE unsigned MDFN_tzcount16(uint16 v) { return !v ? 16 : MDFN_tzcount16_0UD(v); } -static INLINE unsigned MDFN_tzcount32(uint32 v) { return !v ? 32 : MDFN_tzcount32_0UD(v); } -static INLINE unsigned MDFN_tzcount64(uint64 v) { return !v ? 64 : MDFN_tzcount64_0UD(v); } - -static INLINE unsigned MDFN_log2(uint32 v) { return 31 ^ MDFN_lzcount32_0UD(v | 1); } -static INLINE unsigned MDFN_log2(uint64 v) { return 63 ^ MDFN_lzcount64_0UD(v | 1); } - -static INLINE unsigned MDFN_log2(int32 v) { return MDFN_log2((uint32)v); } -static INLINE unsigned MDFN_log2(int64 v) { return MDFN_log2((uint64)v); } - -// Rounds up to the nearest power of 2(treats input as unsigned to a degree, but be aware of integer promotion rules). -// Returns 0 on overflow. -static INLINE uint64 round_up_pow2(uint32 v) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (tmp < v); } -static INLINE uint64 round_up_pow2(uint64 v) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (tmp < v); } - -static INLINE uint64 round_up_pow2(int32 v) { return round_up_pow2((uint32)v); } -static INLINE uint64 round_up_pow2(int64 v) { return round_up_pow2((uint64)v); } - -// Rounds to the nearest power of 2(treats input as unsigned to a degree, but be aware of integer promotion rules). -static INLINE uint64 round_nearest_pow2(uint32 v, bool round_half_up = true) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (v && (((v - tmp) << 1) >= (tmp + !round_half_up))); } -static INLINE uint64 round_nearest_pow2(uint64 v, bool round_half_up = true) { uint64 tmp = (uint64)1 << MDFN_log2(v); return tmp << (v && (((v - tmp) << 1) >= (tmp + !round_half_up))); } - -static INLINE uint64 round_nearest_pow2(int32 v, bool round_half_up = true) { return round_nearest_pow2((uint32)v, round_half_up); } -static INLINE uint64 round_nearest_pow2(int64 v, bool round_half_up = true) { return round_nearest_pow2((uint64)v, round_half_up); } - -// Some compilers' optimizers and some platforms might fubar the generated code from these macros, -// so some tests are run in...tests.cpp -#define sign_8_to_s16(_value) ((int16)(int8)(_value)) -#define sign_9_to_s16(_value) (((int16)((unsigned int)(_value) << 7)) >> 7) -#define sign_10_to_s16(_value) (((int16)((uint32)(_value) << 6)) >> 6) -#define sign_11_to_s16(_value) (((int16)((uint32)(_value) << 5)) >> 5) -#define sign_12_to_s16(_value) (((int16)((uint32)(_value) << 4)) >> 4) -#define sign_13_to_s16(_value) (((int16)((uint32)(_value) << 3)) >> 3) -#define sign_14_to_s16(_value) (((int16)((uint32)(_value) << 2)) >> 2) -#define sign_15_to_s16(_value) (((int16)((uint32)(_value) << 1)) >> 1) - -// This obviously won't convert higher-than-32 bit numbers to signed 32-bit ;) -// Also, this shouldn't be used for 8-bit and 16-bit signed numbers, since you can -// convert those faster with typecasts... -#define sign_x_to_s32(_bits, _value) (((int32)((uint32)(_value) << (32 - _bits))) >> (32 - _bits)) - -static INLINE int32 clamp_to_u8(int32 i) -{ - if(i & 0xFFFFFF00) - i = (((~i) >> 30) & 0xFF); - - return(i); -} - -static INLINE int32 clamp_to_u16(int32 i) -{ - if(i & 0xFFFF0000) - i = (((~i) >> 31) & 0xFFFF); - - return(i); -} - -template static INLINE void clamp(T *val, U minimum, V maximum) -{ - if(*val < minimum) - { - //printf("Warning: clamping to minimum(%d)\n", (int)minimum); - *val = minimum; - } - if(*val > maximum) - { - //printf("Warning: clamping to maximum(%d)\n", (int)maximum); - *val = maximum; - } -} - -#endif diff --git a/waterbox/vb/timer.cpp b/waterbox/vb/timer.cpp deleted file mode 100644 index 43cfe5fd45..0000000000 --- a/waterbox/vb/timer.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* timer.cpp: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "vb.h" -#include "timer.h" - -namespace MDFN_IEN_VB -{ - -#define TC_TENABLE 0x01 -#define TC_ZSTAT 0x02 -#define TC_ZSTATCLR 0x04 -#define TC_TIMZINT 0x08 -#define TC_TCLKSEL 0x10 - -static uint8 TimerControl; -static uint16 TimerReloadValue; -static uint16 TimerCounter; -static int32 TimerDivider; -static v810_timestamp_t TimerLastTS; -static bool TimerStatus, TimerStatusShadow; -static bool ReloadPending; - -v810_timestamp_t TIMER_Update(v810_timestamp_t timestamp) -{ - int32 run_time = timestamp - TimerLastTS; - - if (TimerControl & TC_TENABLE) - { - TimerDivider -= run_time; - while (TimerDivider <= 0) - { - if (!TimerCounter || ReloadPending) - { - TimerCounter = TimerReloadValue; - ReloadPending = false; - } - - if (TimerCounter) - TimerCounter--; - - if (!TimerCounter || TimerStatus) - { - TimerStatusShadow = TimerStatus = true; - } - - VBIRQ_Assert(VBIRQ_SOURCE_TIMER, TimerStatusShadow && (TimerControl & TC_TIMZINT)); - TimerDivider += (TimerControl & TC_TCLKSEL) ? 500 : 2000; - } - } - - TimerLastTS = timestamp; - - return ((TimerControl & TC_TENABLE) ? (timestamp + TimerDivider) : VB_EVENT_NONONO); -} - -void TIMER_ResetTS(void) -{ - TimerLastTS = 0; -} - -uint8 TIMER_Read(const v810_timestamp_t ×tamp, uint32 A) -{ - uint8 ret = 0; - - //if(A <= 0x1C) - //printf("Read: %d, %08x\n", timestamp, A); - TIMER_Update(timestamp); - - switch (A & 0xFF) - { - case 0x18: - ret = TimerCounter; - break; - - case 0x1C: - ret = TimerCounter >> 8; - break; - - case 0x20: - ret = TimerControl | (0xE0 | TC_ZSTATCLR) | (TimerStatus ? TC_ZSTAT : 0); - break; - } - - return (ret); -} - -void TIMER_Write(const v810_timestamp_t ×tamp, uint32 A, uint8 V) -{ - if (A & 0x3) - { - puts("HWCtrl Bogus Write?"); - return; - } - - TIMER_Update(timestamp); - - //if((A & 0xFF) <= 0x1C) - //printf("Write: %d, %08x %02x\n", timestamp, A, V); - - switch (A & 0xFF) - { - case 0x18: - TimerReloadValue &= 0xFF00; - TimerReloadValue |= V; - ReloadPending = true; - break; - - case 0x1C: - TimerReloadValue &= 0x00FF; - TimerReloadValue |= V << 8; - ReloadPending = true; - break; - - case 0x20: - if (V & TC_ZSTATCLR) - { - if ((TimerControl & TC_TENABLE) && TimerCounter == 0) - { - //puts("Faulty Z-Stat-Clr"); - } - else - { - TimerStatus = false; - } - TimerStatusShadow = false; - } - if ((V & TC_TENABLE) && !(TimerControl & TC_TENABLE)) - { - //TimerCounter = TimerReloadValue; - TimerDivider = (V & TC_TCLKSEL) ? 500 : 2000; - } - TimerControl = V & (0x10 | 0x08 | 0x01); - - if (!(TimerControl & TC_TIMZINT)) - TimerStatus = TimerStatusShadow = false; - - VBIRQ_Assert(VBIRQ_SOURCE_TIMER, TimerStatusShadow && (TimerControl & TC_TIMZINT)); - - if (TimerControl & TC_TENABLE) - VB_SetEvent(VB_EVENT_TIMER, timestamp + TimerDivider); - break; - } -} - -void TIMER_Power(void) -{ - TimerLastTS = 0; - - TimerCounter = 0xFFFF; - TimerReloadValue = 0; - TimerDivider = 2000; //2150; //2000; - - TimerStatus = false; - TimerStatusShadow = false; - TimerControl = 0; - - ReloadPending = false; - - VBIRQ_Assert(VBIRQ_SOURCE_TIMER, false); -} - -uint32 TIMER_GetRegister(const unsigned int id, char *special, const uint32 special_len) -{ - uint32 ret = 0xDEADBEEF; - - switch (id) - { - case TIMER_GSREG_TCR: - ret = TimerControl; - if (special) - trio_snprintf(special, special_len, "TEnable: %d, TimZInt: %d, TClkSel: %d(%.3f KHz)", - (int)(bool)(ret & TC_TENABLE), - (int)(bool)(ret & TC_TIMZINT), - (int)(bool)(ret & TC_TCLKSEL), - (double)VB_MASTER_CLOCK / ((ret & TC_TCLKSEL) ? 500 : 2000) / 1000); - break; - - case TIMER_GSREG_DIVCOUNTER: - ret = TimerDivider; - break; - - case TIMER_GSREG_RELOAD_VALUE: - ret = TimerReloadValue; - break; - - case TIMER_GSREG_COUNTER: - ret = TimerCounter; - break; - } - return (ret); -} - -void TIMER_SetRegister(const unsigned int id, const uint32 value) -{ - switch (id) - { - case TIMER_GSREG_TCR: - TimerControl = value & (TC_TENABLE | TC_TIMZINT | TC_TCLKSEL); - break; - - case TIMER_GSREG_DIVCOUNTER: - TimerDivider = value % ((TimerControl & TC_TCLKSEL) ? 500 : 2000); - break; - - case TIMER_GSREG_RELOAD_VALUE: - TimerReloadValue = value; - break; - - case TIMER_GSREG_COUNTER: - TimerCounter = value; - break; - } -} -} diff --git a/waterbox/vb/timer.h b/waterbox/vb/timer.h deleted file mode 100644 index 20f0f7e9b6..0000000000 --- a/waterbox/vb/timer.h +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* timer.h: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef __MDFN_VB_TIMER_H -#define __MDFN_VB_TIMER_H - -namespace MDFN_IEN_VB -{ - -v810_timestamp_t TIMER_Update(v810_timestamp_t timestamp); -void TIMER_ResetTS(void); -uint8 TIMER_Read(const v810_timestamp_t ×tamp, uint32 A); -void TIMER_Write(const v810_timestamp_t ×tamp, uint32 A, uint8 V); - -void TIMER_Power(void) MDFN_COLD; - -enum -{ - TIMER_GSREG_TCR, - TIMER_GSREG_DIVCOUNTER, - TIMER_GSREG_RELOAD_VALUE, - TIMER_GSREG_COUNTER, -}; - -uint32 TIMER_GetRegister(const unsigned int id, char *special, const uint32 special_len); -void TIMER_SetRegister(const unsigned int id, const uint32 value); - -} - -#endif diff --git a/waterbox/vb/v810/v810_cpu.cpp b/waterbox/vb/v810/v810_cpu.cpp deleted file mode 100644 index 4620c3c7e4..0000000000 --- a/waterbox/vb/v810/v810_cpu.cpp +++ /dev/null @@ -1,1363 +0,0 @@ -/* V810 Emulator - * - * Copyright (C) 2006 David Tucker - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Alternatively, the V810 emulator code(and all V810 emulation header files) can be used/distributed under the following license(you can adopt either - license exclusively for your changes by removing one of these license headers, but it's STRONGLY preferable - to keep your changes dual-licensed as well): - -This Reality Boy emulator is copyright (C) David Tucker 1997-2008, all rights -reserved. You may use this code as long as you make no money from the use of -this code and you acknowledge the original author (Me). I reserve the right to -dictate who can use this code and how (Just so you don't do something stupid -with it). - Most Importantly, this code is swap ware. If you use It send along your new -program (with code) or some other interesting tidbits you wrote, that I might be -interested in. - This code is in beta, there are bugs! I am not responsible for any damage -done to your computer, reputation, ego, dog, or family life due to the use of -this code. All source is provided as is, I make no guaranties, and am not -responsible for anything you do with the code (legal or otherwise). - Virtual Boy is a trademark of Nintendo, and V810 is a trademark of NEC. I am -in no way affiliated with either party and all information contained hear was -found freely through public domain sources. -*/ - -////////////////////////////////////////////////////////// -// CPU routines - -#include "vb.h" -#include - -//#include "pcfx.h" -//#include "debug.h" - -#include -#include - -#include "v810_opt.h" -#include "v810_cpu.h" - -V810::V810() -{ - MemRead8 = NULL; - MemRead16 = NULL; - MemRead32 = NULL; - - IORead8 = NULL; - IORead16 = NULL; - IORead32 = NULL; - - MemWrite8 = NULL; - MemWrite16 = NULL; - MemWrite32 = NULL; - - IOWrite8 = NULL; - IOWrite16 = NULL; - IOWrite32 = NULL; - - FastMap = (uint8**)alloc_sealed((1ULL << 32) / V810_FAST_MAP_PSIZE * sizeof(*FastMap)); - - memset(MemReadBus32, 0, sizeof(MemReadBus32)); - memset(MemWriteBus32, 0, sizeof(MemWriteBus32)); - - v810_timestamp = 0; - next_event_ts = 0x7FFFFFFF; -} - -V810::~V810() -{ -} - -INLINE void V810::RecalcIPendingCache(void) -{ - IPendingCache = 0; - - // Of course don't generate an interrupt if there's not one pending! - if (ilevel < 0) - return; - - // If CPU is halted because of a fatal exception, don't let an interrupt - // take us out of this halted status. - if (Halted == HALT_FATAL_EXCEPTION) - return; - - // If the NMI pending, exception pending, and/or interrupt disabled bit - // is set, don't accept any interrupts. - if (S_REG[PSW] & (PSW_NP | PSW_EP | PSW_ID)) - return; - - // If the interrupt level is lower than the interrupt enable level, don't - // accept it. - if (ilevel < (int)((S_REG[PSW] & PSW_IA) >> 16)) - return; - - IPendingCache = 0xFF; -} - -// TODO: "An interrupt that occurs during restore/dump/clear operation is internally held and is accepted after the -// operation in progress is finished. The maskable interrupt is held internally only when the EP, NP, and ID flags -// of PSW are all 0." -// -// This behavior probably doesn't have any relevance on the PC-FX, unless we're sadistic -// and try to restore cache from an interrupt acknowledge register or dump it to a register -// controlling interrupt masks... I wanna be sadistic~ - -void V810::CacheClear(v810_timestamp_t ×tamp, uint32 start, uint32 count) -{ - //printf("Cache clear: %08x %08x\n", start, count); - for (uint32 i = 0; i < count && (i + start) < 128; i++) - memset(&Cache[i + start], 0, sizeof(V810_CacheEntry_t)); -} - -INLINE void V810::CacheOpMemStore(v810_timestamp_t ×tamp, uint32 A, uint32 V) -{ - if (MemWriteBus32[A >> 24]) - { - timestamp += 2; - MemWrite32(timestamp, A, V); - } - else - { - timestamp += 2; - MemWrite16(timestamp, A, V & 0xFFFF); - - timestamp += 2; - MemWrite16(timestamp, A | 2, V >> 16); - } -} - -INLINE uint32 V810::CacheOpMemLoad(v810_timestamp_t ×tamp, uint32 A) -{ - if (MemReadBus32[A >> 24]) - { - timestamp += 2; - return (MemRead32(timestamp, A)); - } - else - { - uint32 ret; - - timestamp += 2; - ret = MemRead16(timestamp, A); - - timestamp += 2; - ret |= MemRead16(timestamp, A | 2) << 16; - return (ret); - } -} - -void V810::CacheDump(v810_timestamp_t ×tamp, const uint32 SA) -{ - printf("Cache dump: %08x\n", SA); - - for (int i = 0; i < 128; i++) - { - CacheOpMemStore(timestamp, SA + i * 8 + 0, Cache[i].data[0]); - CacheOpMemStore(timestamp, SA + i * 8 + 4, Cache[i].data[1]); - } - - for (int i = 0; i < 128; i++) - { - uint32 icht = Cache[i].tag | ((int)Cache[i].data_valid[0] << 22) | ((int)Cache[i].data_valid[1] << 23); - - CacheOpMemStore(timestamp, SA + 1024 + i * 4, icht); - } -} - -void V810::CacheRestore(v810_timestamp_t ×tamp, const uint32 SA) -{ - printf("Cache restore: %08x\n", SA); - - for (int i = 0; i < 128; i++) - { - Cache[i].data[0] = CacheOpMemLoad(timestamp, SA + i * 8 + 0); - Cache[i].data[1] = CacheOpMemLoad(timestamp, SA + i * 8 + 4); - } - - for (int i = 0; i < 128; i++) - { - uint32 icht; - - icht = CacheOpMemLoad(timestamp, SA + 1024 + i * 4); - - Cache[i].tag = icht & ((1 << 22) - 1); - Cache[i].data_valid[0] = (icht >> 22) & 1; - Cache[i].data_valid[1] = (icht >> 23) & 1; - } -} - -INLINE uint32 V810::RDCACHE(v810_timestamp_t ×tamp, uint32 addr) -{ - const int CI = (addr >> 3) & 0x7F; - const int SBI = (addr & 4) >> 2; - - if (Cache[CI].tag == (addr >> 10)) - { - if (!Cache[CI].data_valid[SBI]) - { - timestamp += 2; // or higher? Penalty for cache miss seems to be higher than having cache disabled. - if (MemReadBus32[addr >> 24]) - Cache[CI].data[SBI] = MemRead32(timestamp, addr & ~0x3); - else - { - timestamp++; - - uint32 tmp; - - tmp = MemRead16(timestamp, addr & ~0x3); - tmp |= MemRead16(timestamp, (addr & ~0x3) | 0x2) << 16; - - Cache[CI].data[SBI] = tmp; - } - Cache[CI].data_valid[SBI] = TRUE; - } - } - else - { - Cache[CI].tag = addr >> 10; - - timestamp += 2; // or higher? Penalty for cache miss seems to be higher than having cache disabled. - if (MemReadBus32[addr >> 24]) - Cache[CI].data[SBI] = MemRead32(timestamp, addr & ~0x3); - else - { - timestamp++; - - uint32 tmp; - - tmp = MemRead16(timestamp, addr & ~0x3); - tmp |= MemRead16(timestamp, (addr & ~0x3) | 0x2) << 16; - - Cache[CI].data[SBI] = tmp; - } - //Cache[CI].data[SBI] = MemRead32(timestamp, addr & ~0x3); - Cache[CI].data_valid[SBI] = TRUE; - Cache[CI].data_valid[SBI ^ 1] = FALSE; - } - - //{ - // // Caution: This can mess up DRAM page change penalty timings - // uint32 dummy_timestamp = 0; - // if(Cache[CI].data[SBI] != mem_rword(addr & ~0x3, dummy_timestamp)) - // { - // printf("Cache/Real Memory Mismatch: %08x %08x/%08x\n", addr & ~0x3, Cache[CI].data[SBI], mem_rword(addr & ~0x3, dummy_timestamp)); - // } - //} - - return (Cache[CI].data[SBI]); -} - -INLINE uint16 V810::RDOP(v810_timestamp_t ×tamp, uint32 addr, uint32 meow) -{ - uint16 ret; - - if (S_REG[CHCW] & 0x2) - { - uint32 d32 = RDCACHE(timestamp, addr); - ret = d32 >> ((addr & 2) * 8); - } - else - { - timestamp += meow; //++; - ret = MemRead16(timestamp, addr); - } - return (ret); -} - -#define BRANCH_ALIGN_CHECK(x) \ - { \ - if ((S_REG[CHCW] & 0x2) && (x & 0x2)) \ - { \ - ADDCLOCK(1); \ - } \ - } - -// Reinitialize the defaults in the CPU -void V810::Reset() -{ - memset(&Cache, 0, sizeof(Cache)); - - memset(P_REG, 0, sizeof(P_REG)); - memset(S_REG, 0, sizeof(S_REG)); - memset(Cache, 0, sizeof(Cache)); - - P_REG[0] = 0x00000000; - SetPC(0xFFFFFFF0); - - S_REG[ECR] = 0x0000FFF0; - S_REG[PSW] = 0x00008000; - - if (VBMode) - S_REG[PIR] = 0x00005346; - else - S_REG[PIR] = 0x00008100; - - S_REG[TKCW] = 0x000000E0; - Halted = HALT_NONE; - ilevel = -1; - - lastop = 0; - - in_bstr = FALSE; - - RecalcIPendingCache(); -} - -bool V810::Init(V810_Emu_Mode mode, bool vb_mode) -{ - EmuMode = mode; - VBMode = vb_mode; - - in_bstr = FALSE; - in_bstr_to = 0; - - if (mode == V810_EMU_MODE_FAST) - { - memset(DummyRegion, 0, V810_FAST_MAP_PSIZE); - - for (unsigned int i = V810_FAST_MAP_PSIZE; i < V810_FAST_MAP_PSIZE + V810_FAST_MAP_TRAMPOLINE_SIZE; i += 2) - { - DummyRegion[i + 0] = 0; - DummyRegion[i + 1] = 0x36 << 2; - } - - for (uint64 A = 0; A < (1ULL << 32); A += V810_FAST_MAP_PSIZE) - FastMap[A / V810_FAST_MAP_PSIZE] = DummyRegion - A; - } - - return (TRUE); -} - -void V810::SetInt(int level) -{ - assert(level >= -1 && level <= 15); - - ilevel = level; - RecalcIPendingCache(); -} - -uint8* V810::SetFastMap(void *(*allocator)(size_t size), uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name) -{ - for (unsigned int i = 0; i < num_addresses; i++) - { - assert((addresses[i] & (V810_FAST_MAP_PSIZE - 1)) == 0); - } - assert((length & (V810_FAST_MAP_PSIZE - 1)) == 0); - - auto ret = (uint8*)allocator(length + V810_FAST_MAP_TRAMPOLINE_SIZE); - - for (unsigned int i = length; i < length + V810_FAST_MAP_TRAMPOLINE_SIZE; i += 2) - { - ret[i + 0] = 0; - ret[i + 1] = 0x36 << 2; - } - - for (unsigned int i = 0; i < num_addresses; i++) - { - for (uint64 addr = addresses[i]; addr != (uint64)addresses[i] + length; addr += V810_FAST_MAP_PSIZE) - { - //printf("%08x, %d, %s\n", addr, length, name); - - FastMap[addr / V810_FAST_MAP_PSIZE] = ret - addresses[i]; - } - } - - return ret; -} - -void V810::SetMemReadBus32(uint8 A, bool value) -{ - MemReadBus32[A] = value; -} - -void V810::SetMemWriteBus32(uint8 A, bool value) -{ - MemWriteBus32[A] = value; -} - -void V810::SetMemReadHandlers(uint8 MDFN_FASTCALL (*read8)(v810_timestamp_t &, uint32), uint16 MDFN_FASTCALL (*read16)(v810_timestamp_t &, uint32), uint32 MDFN_FASTCALL (*read32)(v810_timestamp_t &, uint32)) -{ - MemRead8 = read8; - MemRead16 = read16; - MemRead32 = read32; -} - -void V810::SetMemWriteHandlers(void MDFN_FASTCALL (*write8)(v810_timestamp_t &, uint32, uint8), void MDFN_FASTCALL (*write16)(v810_timestamp_t &, uint32, uint16), void MDFN_FASTCALL (*write32)(v810_timestamp_t &, uint32, uint32)) -{ - MemWrite8 = write8; - MemWrite16 = write16; - MemWrite32 = write32; -} - -void V810::SetIOReadHandlers(uint8 MDFN_FASTCALL (*read8)(v810_timestamp_t &, uint32), uint16 MDFN_FASTCALL (*read16)(v810_timestamp_t &, uint32), uint32 MDFN_FASTCALL (*read32)(v810_timestamp_t &, uint32)) -{ - IORead8 = read8; - IORead16 = read16; - IORead32 = read32; -} - -void V810::SetIOWriteHandlers(void MDFN_FASTCALL (*write8)(v810_timestamp_t &, uint32, uint8), void MDFN_FASTCALL (*write16)(v810_timestamp_t &, uint32, uint16), void MDFN_FASTCALL (*write32)(v810_timestamp_t &, uint32, uint32)) -{ - IOWrite8 = write8; - IOWrite16 = write16; - IOWrite32 = write32; -} - -INLINE void V810::SetFlag(uint32 n, bool condition) -{ - S_REG[PSW] &= ~n; - - if (condition) - S_REG[PSW] |= n; -} - -INLINE void V810::SetSZ(uint32 value) -{ - SetFlag(PSW_Z, !value); - SetFlag(PSW_S, value & 0x80000000); -} - -#define SetPREG(n, val) \ - { \ - P_REG[n] = val; \ - } - -INLINE void V810::SetSREG(v810_timestamp_t ×tamp, unsigned int which, uint32 value) -{ - switch (which) - { - default: // Reserved - printf("LDSR to reserved system register: 0x%02x : 0x%08x\n", which, value); - break; - - case ECR: // Read-only - break; - - case PIR: // Read-only (obviously) - break; - - case TKCW: // Read-only - break; - - case EIPSW: - case FEPSW: - S_REG[which] = value & 0xFF3FF; - break; - - case PSW: - S_REG[which] = value & 0xFF3FF; - RecalcIPendingCache(); - break; - - case EIPC: - case FEPC: - S_REG[which] = value & 0xFFFFFFFE; - break; - - case ADDTRE: - S_REG[ADDTRE] = value & 0xFFFFFFFE; - printf("Address trap(unemulated): %08x\n", value); - break; - - case CHCW: - S_REG[CHCW] = value & 0x2; - - switch (value & 0x31) - { - default: - printf("Undefined cache control bit combination: %08x\n", value); - break; - - case 0x00: - break; - - case 0x01: - CacheClear(timestamp, (value >> 20) & 0xFFF, (value >> 8) & 0xFFF); - break; - - case 0x10: - CacheDump(timestamp, value & ~0xFF); - break; - - case 0x20: - CacheRestore(timestamp, value & ~0xFF); - break; - } - break; - } -} - -INLINE uint32 V810::GetSREG(unsigned int which) -{ - uint32 ret; - - if (which != 24 && which != 25 && which >= 8) - { - printf("STSR from reserved system register: 0x%02x", which); - } - - ret = S_REG[which]; - - return (ret); -} - -#define RB_SETPC(new_pc_raw) \ - { \ - const uint32 new_pc = new_pc_raw; /* So RB_SETPC(RB_GETPC()) won't mess up */ \ - if (RB_AccurateMode) \ - PC = new_pc; \ - else \ - { \ - PC_ptr = &FastMap[(new_pc) >> V810_FAST_MAP_SHIFT][(new_pc)]; \ - PC_base = PC_ptr - (new_pc); \ - } \ - } - -#define RB_PCRELCHANGE(delta) \ - { \ - if (RB_AccurateMode) \ - PC += (delta); \ - else \ - { \ - uint32 PC_tmp = RB_GETPC(); \ - PC_tmp += (delta); \ - RB_SETPC(PC_tmp); \ - } \ - } - -#define RB_INCPCBY2() \ - { \ - if (RB_AccurateMode) \ - PC += 2; \ - else \ - PC_ptr += 2; \ - } -#define RB_INCPCBY4() \ - { \ - if (RB_AccurateMode) \ - PC += 4; \ - else \ - PC_ptr += 4; \ - } - -#define RB_DECPCBY2() \ - { \ - if (RB_AccurateMode) \ - PC -= 2; \ - else \ - PC_ptr -= 2; \ - } -#define RB_DECPCBY4() \ - { \ - if (RB_AccurateMode) \ - PC -= 4; \ - else \ - PC_ptr -= 4; \ - } - -// Define accurate mode defines -#define RB_GETPC() PC -#define RB_RDOP(PC_offset, ...) RDOP(timestamp, PC + PC_offset, ##__VA_ARGS__) - -void V810::Run_Accurate(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) -{ - const bool RB_AccurateMode = true; - -#define RB_ADDBT(n, o, p) -#define RB_CPUHOOK(n) - -#include "v810_oploop.inc" - -#undef RB_CPUHOOK -#undef RB_ADDBT -} - -// -// Undefine accurate mode defines -// -#undef RB_GETPC -#undef RB_RDOP - -// -// Define fast mode defines -// -#define RB_GETPC() ((uint32)(PC_ptr - PC_base)) - -#define RB_RDOP(PC_offset, ...) MDFN_de16lsb(&PC_ptr[PC_offset]) - -void V810::Run_Fast(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) -{ - const bool RB_AccurateMode = false; - -#define RB_ADDBT(n, o, p) -#define RB_CPUHOOK(n) - -#include "v810_oploop.inc" - -#undef RB_CPUHOOK -#undef RB_ADDBT -} - -// -// Undefine fast mode defines -// -#undef RB_GETPC -#undef RB_RDOP - -v810_timestamp_t V810::Run(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) -{ - Running = true; - if (EmuMode == V810_EMU_MODE_FAST) - Run_Fast(event_handler); - else - Run_Accurate(event_handler); - return (v810_timestamp); -} - -void V810::Exit(void) -{ - Running = false; -} - -uint32 V810::GetRegister(unsigned int which, char *special, const uint32 special_len) -{ - if (which >= GSREG_PR && which <= GSREG_PR + 31) - { - return GetPR(which - GSREG_PR); - } - else if (which >= GSREG_SR && which <= GSREG_SR + 31) - { - uint32 val = GetSREG(which - GSREG_SR); - - if (special && which == GSREG_SR + PSW) - { - trio_snprintf(special, special_len, "Z: %d, S: %d, OV: %d, CY: %d, ID: %d, AE: %d, EP: %d, NP: %d, IA: %2d", - (int)(bool)(val & PSW_Z), (int)(bool)(val & PSW_S), (int)(bool)(val & PSW_OV), (int)(bool)(val & PSW_CY), - (int)(bool)(val & PSW_ID), (int)(bool)(val & PSW_AE), (int)(bool)(val & PSW_EP), (int)(bool)(val & PSW_NP), - (val & PSW_IA) >> 16); - } - - return val; - } - else if (which == GSREG_PC) - { - return GetPC(); - } - else if (which == GSREG_TIMESTAMP) - { - return v810_timestamp; - } - - return 0xDEADBEEF; -} - -void V810::SetRegister(unsigned int which, uint32 value) -{ - if (which >= GSREG_PR && which <= GSREG_PR + 31) - { - if (which) - P_REG[which - GSREG_PR] = value; - } - else if (which >= GSREG_SR && which <= GSREG_SR + 31) - { - // SetSREG(timestamp, which - GSREG_SR, value); - } - else if (which == GSREG_PC) - { - SetPC(value & ~1); - } - else if (which == GSREG_TIMESTAMP) - { - //v810_timestamp = value; - } -} - -uint32 V810::GetPC(void) -{ - if (EmuMode == V810_EMU_MODE_ACCURATE) - return (PC); - else - { - return (PC_ptr - PC_base); - } -} - -void V810::SetPC(uint32 new_pc) -{ - if (EmuMode == V810_EMU_MODE_ACCURATE) - PC = new_pc; - else - { - PC_ptr = &FastMap[new_pc >> V810_FAST_MAP_SHIFT][new_pc]; - PC_base = PC_ptr - new_pc; - } -} - -#define BSTR_OP_MOV \ - dst_cache &= ~(1 << dstoff); \ - dst_cache |= ((src_cache >> srcoff) & 1) << dstoff; -#define BSTR_OP_NOT \ - dst_cache &= ~(1 << dstoff); \ - dst_cache |= (((src_cache >> srcoff) & 1) ^ 1) << dstoff; - -#define BSTR_OP_XOR dst_cache ^= ((src_cache >> srcoff) & 1) << dstoff; -#define BSTR_OP_OR dst_cache |= ((src_cache >> srcoff) & 1) << dstoff; -#define BSTR_OP_AND dst_cache &= ~((((src_cache >> srcoff) & 1) ^ 1) << dstoff); - -#define BSTR_OP_XORN dst_cache ^= (((src_cache >> srcoff) & 1) ^ 1) << dstoff; -#define BSTR_OP_ORN dst_cache |= (((src_cache >> srcoff) & 1) ^ 1) << dstoff; -#define BSTR_OP_ANDN dst_cache &= ~(((src_cache >> srcoff) & 1) << dstoff); - -INLINE uint32 V810::BSTR_RWORD(v810_timestamp_t ×tamp, uint32 A) -{ - if (MemReadBus32[A >> 24]) - { - timestamp += 2; - return (MemRead32(timestamp, A)); - } - else - { - uint32 ret; - - timestamp += 2; - ret = MemRead16(timestamp, A); - - timestamp += 2; - ret |= MemRead16(timestamp, A | 2) << 16; - return (ret); - } -} - -INLINE void V810::BSTR_WWORD(v810_timestamp_t ×tamp, uint32 A, uint32 V) -{ - if (MemWriteBus32[A >> 24]) - { - timestamp += 2; - MemWrite32(timestamp, A, V); - } - else - { - timestamp += 2; - MemWrite16(timestamp, A, V & 0xFFFF); - - timestamp += 2; - MemWrite16(timestamp, A | 2, V >> 16); - } -} - -#define DO_BSTR(op) \ - { \ - while (len) \ - { \ - if (!have_src_cache) \ - { \ - have_src_cache = TRUE; \ - src_cache = BSTR_RWORD(timestamp, src); \ - } \ - \ - if (!have_dst_cache) \ - { \ - have_dst_cache = TRUE; \ - dst_cache = BSTR_RWORD(timestamp, dst); \ - } \ - \ - op; \ - srcoff = (srcoff + 1) & 0x1F; \ - dstoff = (dstoff + 1) & 0x1F; \ - len--; \ - \ - if (!srcoff) \ - { \ - src += 4; \ - have_src_cache = FALSE; \ - } \ - \ - if (!dstoff) \ - { \ - BSTR_WWORD(timestamp, dst, dst_cache); \ - dst += 4; \ - have_dst_cache = FALSE; \ - if (timestamp >= next_event_ts) \ - break; \ - } \ - } \ - if (have_dst_cache) \ - BSTR_WWORD(timestamp, dst, dst_cache); \ - } - -INLINE bool V810::Do_BSTR_Search(v810_timestamp_t ×tamp, const int inc_mul, unsigned int bit_test) -{ - uint32 srcoff = (P_REG[27] & 0x1F); - uint32 len = P_REG[28]; - uint32 bits_skipped = P_REG[29]; - uint32 src = (P_REG[30] & 0xFFFFFFFC); - bool found = false; - -#if 0 - // TODO: Better timing. - if(!in_bstr) // If we're just starting the execution of this instruction(kind of spaghetti-code), so FIXME if we change - // bstr handling in v810_oploop.inc - { - timestamp += 13 - 1; - } -#endif - - while (len) - { - if (!have_src_cache) - { - have_src_cache = TRUE; - timestamp++; - src_cache = BSTR_RWORD(timestamp, src); - } - - if (((src_cache >> srcoff) & 1) == bit_test) - { - found = true; - - /* Fix the bit offset and word address to "1 bit before" it was found */ - srcoff -= inc_mul * 1; - if (srcoff & 0x20) /* Handles 0x1F->0x20(0x00) and 0x00->0xFFFF... */ - { - src -= inc_mul * 4; - srcoff &= 0x1F; - } - break; - } - srcoff = (srcoff + inc_mul * 1) & 0x1F; - bits_skipped++; - len--; - - if (!srcoff) - { - have_src_cache = FALSE; - src += inc_mul * 4; - if (timestamp >= next_event_ts) - break; - } - } - - P_REG[27] = srcoff; - P_REG[28] = len; - P_REG[29] = bits_skipped; - P_REG[30] = src; - - if (found) // Set Z flag to 0 if the bit was found - SetFlag(PSW_Z, 0); - else if (!len) // ...and if the search is over, and the bit was not found, set it to 1 - SetFlag(PSW_Z, 1); - - if (found) // Bit found, so don't continue the search. - return (false); - - return ((bool)len); // Continue the search if any bits are left to search. -} - -bool V810::bstr_subop(v810_timestamp_t ×tamp, int sub_op, int arg1) -{ - if ((sub_op >= 0x10) || (!(sub_op & 0x8) && sub_op >= 0x4)) - { - printf("%08x\tBSR Error: %04x\n", PC, sub_op); - - SetPC(GetPC() - 2); - Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); - - return (false); - } - - // printf("BSTR: %02x, %02x %02x; src: %08x, dst: %08x, len: %08x\n", sub_op, P_REG[27], P_REG[26], P_REG[30], P_REG[29], P_REG[28]); - - if (sub_op & 0x08) - { - uint32 dstoff = (P_REG[26] & 0x1F); - uint32 srcoff = (P_REG[27] & 0x1F); - uint32 len = P_REG[28]; - uint32 dst = (P_REG[29] & 0xFFFFFFFC); - uint32 src = (P_REG[30] & 0xFFFFFFFC); - -#if 0 - // Be careful not to cause 32-bit integer overflow, and careful about not shifting by 32. - // TODO: - - // Read src[0], src[4] into shifter. - // Read dest[0]. - DO_BSTR_PROLOGUE(); // if(len) { blah blah blah masking blah } - src_cache = BSTR_RWORD(timestamp, src); - - if((uint64)(srcoff + len) > 0x20) - src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; - - dst_cache = BSTR_RWORD(timestamp, dst); - - if(len) - { - uint32 dst_preserve_mask; - uint32 dst_change_mask; - - dst_preserve_mask = (1U << dstoff) - 1; - - if((uint64)(dstoff + len) < 0x20) - dst_preserve_mask |= ((1U << ((0x20 - (dstoff + len)) & 0x1F)) - 1) << (dstoff + len); - - dst_change_mask = ~dst_preserve_mask; - - src_cache = BSTR_RWORD(timestamp, src); - src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; - dst_cache = BSTR_RWORD(timestamp, dst); - - dst_cache = (dst_cache & dst_preserve_mask) | ((dst_cache OP_THINGY_HERE (src_cache >> srcoff)) & dst_change_mask); - BSTR_WWORD(timestamp, dst, dst_cache); - - if((uint64)(dstoff + len) < 0x20) - { - srcoff += len; - dstoff += len; - len = 0; - } - else - { - srcoff += (0x20 - dstoff); - dstoff = 0; - len -= (0x20 - dstoff); - dst += 4; - } - - if(srcoff >= 0x20) - { - srcoff &= 0x1F; - src += 4; - - if(len) - { - src_cache >>= 32; - src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; - } - } - } - - DO_BSTR_PRIMARY(); // while(len >= 32) (do allow interruption; interrupt and emulator-return - - // they must be handled differently!) - while(len >= 32) - { - dst_cache = BSTR_RWORD(timestamp, dst); - dst_cache = OP_THINGY_HERE(dst_cache, src_cache >> srcoff); - BSTR_WWORD(timestamp, dst, dst_cache); - len -= 32; - dst += 4; - src += 4; - src_cache >>= 32; - src_cache |= (uint64)BSTR_RWORD(timestamp, src + 4) << 32; - } - - DO_BSTR_EPILOGUE(); // if(len) { blah blah blah masking blah } - if(len) - { - uint32 dst_preserve_mask; - uint32 dst_change_mask; - - dst_preserve_mask = (1U << ((0x20 - len) & 0x1F) << len; - dst_change_mask = ~dst_preserve_mask; - - dst_cache = BSTR_RWORD(timestamp, dst); - dst_cache = OP_THINGY_HERE(dst_cache, src_cache >> srcoff); - BSTR_WWORD(timestamp, dst, dst_cache); - dstoff += len; - srcoff += len; - - if(srcoff >= 0x20) - { - srcoff &= 0x1F; - src += 4; - } - len = 0; - } -#endif - - switch (sub_op) - { - case ORBSU: - DO_BSTR(BSTR_OP_OR); - break; - - case ANDBSU: - DO_BSTR(BSTR_OP_AND); - break; - - case XORBSU: - DO_BSTR(BSTR_OP_XOR); - break; - - case MOVBSU: - DO_BSTR(BSTR_OP_MOV); - break; - - case ORNBSU: - DO_BSTR(BSTR_OP_ORN); - break; - - case ANDNBSU: - DO_BSTR(BSTR_OP_ANDN); - break; - - case XORNBSU: - DO_BSTR(BSTR_OP_XORN); - break; - - case NOTBSU: - DO_BSTR(BSTR_OP_NOT); - break; - } - - P_REG[26] = dstoff; - P_REG[27] = srcoff; - P_REG[28] = len; - P_REG[29] = dst; - P_REG[30] = src; - - return ((bool)P_REG[28]); - } - else - { - printf("BSTR Search: %02x\n", sub_op); - return (Do_BSTR_Search(timestamp, ((sub_op & 1) ? -1 : 1), (sub_op & 0x2) >> 1)); - } - assert(0); - return (false); -} - -INLINE void V810::SetFPUOPNonFPUFlags(uint32 result) -{ - // Now, handle flag setting - SetFlag(PSW_OV, 0); - - if (!(result & 0x7FFFFFFF)) // Check to see if exponent and mantissa are 0 - { - // If Z flag is set, S and CY should be clear, even if it's negative 0(confirmed on real thing with subf.s, at least). - SetFlag(PSW_Z, 1); - SetFlag(PSW_S, 0); - SetFlag(PSW_CY, 0); - } - else - { - SetFlag(PSW_Z, 0); - SetFlag(PSW_S, result & 0x80000000); - SetFlag(PSW_CY, result & 0x80000000); - } - //printf("MEOW: %08x\n", S_REG[PSW] & (PSW_S | PSW_CY)); -} - -bool V810::FPU_DoesExceptionKillResult(void) -{ - const uint32 float_exception_flags = fpo.get_flags(); - - if (float_exception_flags & V810_FP_Ops::flag_reserved) - return (true); - - if (float_exception_flags & V810_FP_Ops::flag_invalid) - return (true); - - if (float_exception_flags & V810_FP_Ops::flag_divbyzero) - return (true); - - // Return false here, so that the result of this calculation IS put in the output register. - // Wrap the exponent on overflow, rather than generating an infinity. The wrapping behavior is specified in IEE 754 AFAIK, - // and is useful in cases where you divide a huge number - // by another huge number, and fix the result afterwards based on the number of overflows that occurred. Probably requires some custom assembly code, - // though. And it's the kind of thing you'd see in an engineering or physics program, not in a perverted video game :b). - if (float_exception_flags & V810_FP_Ops::flag_overflow) - return (false); - - return (false); -} - -void V810::FPU_DoException(void) -{ - const uint32 float_exception_flags = fpo.get_flags(); - - if (float_exception_flags & V810_FP_Ops::flag_reserved) - { - S_REG[PSW] |= PSW_FRO; - - SetPC(GetPC() - 4); - Exception(FPU_HANDLER_ADDR, ECODE_FRO); - - return; - } - - if (float_exception_flags & V810_FP_Ops::flag_invalid) - { - S_REG[PSW] |= PSW_FIV; - - SetPC(GetPC() - 4); - Exception(FPU_HANDLER_ADDR, ECODE_FIV); - - return; - } - - if (float_exception_flags & V810_FP_Ops::flag_divbyzero) - { - S_REG[PSW] |= PSW_FZD; - - SetPC(GetPC() - 4); - Exception(FPU_HANDLER_ADDR, ECODE_FZD); - - return; - } - - if (float_exception_flags & V810_FP_Ops::flag_underflow) - { - S_REG[PSW] |= PSW_FUD; - } - - if (float_exception_flags & V810_FP_Ops::flag_inexact) - { - S_REG[PSW] |= PSW_FPR; - } - - // - // FPR can be set along with overflow, so put the overflow exception handling at the end here(for Exception() messes with PSW). - // - if (float_exception_flags & V810_FP_Ops::flag_overflow) - { - S_REG[PSW] |= PSW_FOV; - - SetPC(GetPC() - 4); - Exception(FPU_HANDLER_ADDR, ECODE_FOV); - } -} - -bool V810::IsSubnormal(uint32 fpval) -{ - if (((fpval >> 23) & 0xFF) == 0 && (fpval & ((1 << 23) - 1))) - return (true); - - return (false); -} - -INLINE void V810::FPU_Math_Template(uint32 (V810_FP_Ops::*func)(uint32, uint32), uint32 arg1, uint32 arg2) -{ - uint32 result; - - fpo.clear_flags(); - result = (fpo.*func)(P_REG[arg1], P_REG[arg2]); - - if (!FPU_DoesExceptionKillResult()) - { - SetFPUOPNonFPUFlags(result); - SetPREG(arg1, result); - } - FPU_DoException(); -} - -void V810::fpu_subop(v810_timestamp_t ×tamp, int sub_op, int arg1, int arg2) -{ - //printf("FPU: %02x\n", sub_op); - if (VBMode) - { - switch (sub_op) - { - case XB: - timestamp++; // Unknown - P_REG[arg1] = (P_REG[arg1] & 0xFFFF0000) | ((P_REG[arg1] & 0xFF) << 8) | ((P_REG[arg1] & 0xFF00) >> 8); - return; - - case XH: - timestamp++; // Unknown - P_REG[arg1] = (P_REG[arg1] << 16) | (P_REG[arg1] >> 16); - return; - - // Does REV use arg1 or arg2 for the source register? - case REV: - timestamp++; // Unknown - printf("Revvie bits\n"); - { - // Public-domain code snippet from: http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel - uint32 v = P_REG[arg2]; // 32-bit word to reverse bit order - - // swap odd and even bits - v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); - // swap consecutive pairs - v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); - // swap nibbles ... - v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); - // swap bytes - v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); - // swap 2-byte long pairs - v = (v >> 16) | (v << 16); - - P_REG[arg1] = v; - } - return; - - case MPYHW: - timestamp += 9 - 1; // Unknown? - P_REG[arg1] = (int32)(int16)(P_REG[arg1] & 0xFFFF) * (int32)(int16)(P_REG[arg2] & 0xFFFF); - return; - } - } - - switch (sub_op) - { - // Virtual-Boy specific(probably!) - default: - { - SetPC(GetPC() - 4); - Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); - } - break; - - case CVT_WS: - timestamp += 5; - { - uint32 result; - - fpo.clear_flags(); - result = fpo.itof(P_REG[arg2]); - - if (!FPU_DoesExceptionKillResult()) - { - SetPREG(arg1, result); - SetFPUOPNonFPUFlags(result); - } - FPU_DoException(); - } - break; // End CVT.WS - - case CVT_SW: - timestamp += 8; - { - int32 result; - - fpo.clear_flags(); - result = fpo.ftoi(P_REG[arg2], false); - - if (!FPU_DoesExceptionKillResult()) - { - SetPREG(arg1, result); - SetFlag(PSW_OV, 0); - SetSZ(result); - } - FPU_DoException(); - } - break; // End CVT.SW - - case ADDF_S: - timestamp += 8; - FPU_Math_Template(&V810_FP_Ops::add, arg1, arg2); - break; - - case SUBF_S: - timestamp += 11; - FPU_Math_Template(&V810_FP_Ops::sub, arg1, arg2); - break; - - case CMPF_S: - timestamp += 6; - // Don't handle this like subf.s because the flags - // have slightly different semantics(mostly regarding underflow/subnormal results) (confirmed on real V810). - fpo.clear_flags(); - { - int32 result; - - result = fpo.cmp(P_REG[arg1], P_REG[arg2]); - - if (!FPU_DoesExceptionKillResult()) - { - SetFPUOPNonFPUFlags(result); - } - FPU_DoException(); - } - break; - - case MULF_S: - timestamp += 7; - FPU_Math_Template(&V810_FP_Ops::mul, arg1, arg2); - break; - - case DIVF_S: - timestamp += 43; - FPU_Math_Template(&V810_FP_Ops::div, arg1, arg2); - break; - - case TRNC_SW: - timestamp += 7; - { - int32 result; - - fpo.clear_flags(); - result = fpo.ftoi(P_REG[arg2], true); - - if (!FPU_DoesExceptionKillResult()) - { - SetPREG(arg1, result); - SetFlag(PSW_OV, 0); - SetSZ(result); - } - FPU_DoException(); - } - break; // end TRNC.SW - } -} - -// Generate exception -void V810::Exception(uint32 handler, uint16 eCode) -{ -// Exception overhead is unknown. - printf("Exception: %08x %04x\n", handler, eCode); - - // Invalidate our bitstring state(forces the instruction to be re-read, and the r/w buffers reloaded). - in_bstr = FALSE; - have_src_cache = FALSE; - have_dst_cache = FALSE; - - if (S_REG[PSW] & PSW_NP) // Fatal exception - { - printf("Fatal exception; Code: %08x, ECR: %08x, PSW: %08x, PC: %08x\n", eCode, S_REG[ECR], S_REG[PSW], PC); - Halted = HALT_FATAL_EXCEPTION; - IPendingCache = 0; - return; - } - else if (S_REG[PSW] & PSW_EP) //Double Exception - { - S_REG[FEPC] = GetPC(); - S_REG[FEPSW] = S_REG[PSW]; - - S_REG[ECR] = (S_REG[ECR] & 0xFFFF) | (eCode << 16); - S_REG[PSW] |= PSW_NP; - S_REG[PSW] |= PSW_ID; - S_REG[PSW] &= ~PSW_AE; - - SetPC(0xFFFFFFD0); - IPendingCache = 0; - return; - } - else // Regular exception - { - S_REG[EIPC] = GetPC(); - S_REG[EIPSW] = S_REG[PSW]; - S_REG[ECR] = (S_REG[ECR] & 0xFFFF0000) | eCode; - S_REG[PSW] |= PSW_EP; - S_REG[PSW] |= PSW_ID; - S_REG[PSW] &= ~PSW_AE; - - SetPC(handler); - IPendingCache = 0; - return; - } -} diff --git a/waterbox/vb/v810/v810_cpu.h b/waterbox/vb/v810/v810_cpu.h deleted file mode 100644 index 4f3196a5c7..0000000000 --- a/waterbox/vb/v810/v810_cpu.h +++ /dev/null @@ -1,333 +0,0 @@ -//////////////////////////////////////////////////////////////// -// Defines for the V810 CPU - -#pragma once - -#include - -typedef int32 v810_timestamp_t; - -#define V810_FAST_MAP_SHIFT 16 -#define V810_FAST_MAP_PSIZE (1 << V810_FAST_MAP_SHIFT) -#define V810_FAST_MAP_TRAMPOLINE_SIZE 1024 - -// Exception codes -enum -{ - ECODE_TRAP_BASE = 0xFFA0, - ECODE_INVALID_OP = 0xFF90, - ECODE_ZERO_DIV = 0xFF80, // Integer divide by 0 - ECODE_FIV = 0xFF70, // Floating point invalid operation - ECODE_FZD = 0xFF68, // Floating point zero division - ECODE_FOV = 0xFF64, // Floating point overflow - //#define ECODE_FUD 0xFF62 // Floating point underflow(unused on V810) - //#define ECODE_FPR 0xFF61 // Floating point precision degradation(unused on V810) - ECODE_FRO = 0xFF60 // Floating point reserved operand -}; - -enum -{ - INVALID_OP_HANDLER_ADDR = 0xFFFFFF90, // Invalid opcode/instruction code! - ZERO_DIV_HANDLER_ADDR = 0xFFFFFF80, // Integer divide by 0 exception - FPU_HANDLER_ADDR = 0xFFFFFF60, // FPU exception - TRAP_HANDLER_BASE = 0xFFFFFFA0 // TRAP instruction -}; - -//System Register Defines (these are the only valid system registers!) -#define EIPC 0 //Exeption/Interupt PC -#define EIPSW 1 //Exeption/Interupt PSW - -#define FEPC 2 //Fatal Error PC -#define FEPSW 3 //Fatal Error PSW - -#define ECR 4 //Exception Cause Register -#define PSW 5 //Program Status Word -#define PIR 6 //Processor ID Register -#define TKCW 7 //Task Controll Word -#define CHCW 24 //Cashe Controll Word -#define ADDTRE 25 //ADDTRE - -//PSW Specifics -#define PSW_IA 0xF0000 // All Interupt bits... -#define PSW_I3 0x80000 -#define PSW_I2 0x40000 -#define PSW_I1 0x20000 -#define PSW_I0 0x10000 - -#define PSW_NP 0x08000 -#define PSW_EP 0x04000 - -#define PSW_AE 0x02000 - -#define PSW_ID 0x01000 - -#define PSW_FRO 0x00200 // Floating point reserved operand(set on denormal, NaN, or indefinite) -#define PSW_FIV 0x00100 // Floating point invalid operation(set when trying to convert a number too large to an (un)signed integer) - -#define PSW_FZD 0x00080 // Floating point divide by zero -#define PSW_FOV 0x00040 // Floating point overflow -#define PSW_FUD 0x00020 // Floating point underflow -#define PSW_FPR 0x00010 // Floating point precision degradation - -#define PSW_CY 0x00008 -#define PSW_OV 0x00004 -#define PSW_S 0x00002 -#define PSW_Z 0x00001 - -//condition codes -#define COND_V 0 -#define COND_C 1 -#define COND_Z 2 -#define COND_NH 3 -#define COND_S 4 -#define COND_T 5 -#define COND_LT 6 -#define COND_LE 7 -#define COND_NV 8 -#define COND_NC 9 -#define COND_NZ 10 -#define COND_H 11 -#define COND_NS 12 -#define COND_F 13 -#define COND_GE 14 -#define COND_GT 15 - -#define TESTCOND_V (S_REG[PSW] & PSW_OV) - -#define TESTCOND_L (S_REG[PSW] & PSW_CY) -#define TESTCOND_C TESTCOND_L - -#define TESTCOND_E (S_REG[PSW] & PSW_Z) -#define TESTCOND_Z TESTCOND_E - -#define TESTCOND_NH ((S_REG[PSW] & PSW_Z) || (S_REG[PSW] & PSW_CY)) -#define TESTCOND_N (S_REG[PSW] & PSW_S) -#define TESTCOND_S TESTCOND_N - -#define TESTCOND_LT ((!!(S_REG[PSW] & PSW_S)) ^ (!!(S_REG[PSW] & PSW_OV))) -#define TESTCOND_LE (((!!(S_REG[PSW] & PSW_S)) ^ (!!(S_REG[PSW] & PSW_OV))) || (S_REG[PSW] & PSW_Z)) -#define TESTCOND_NV (!(S_REG[PSW] & PSW_OV)) - -#define TESTCOND_NL (!(S_REG[PSW] & PSW_CY)) -#define TESTCOND_NC TESTCOND_NL - -#define TESTCOND_NE (!(S_REG[PSW] & PSW_Z)) -#define TESTCOND_NZ TESTCOND_NE - -#define TESTCOND_H (!((S_REG[PSW] & PSW_Z) || (S_REG[PSW] & PSW_CY))) -#define TESTCOND_P (!(S_REG[PSW] & PSW_S)) -#define TESTCOND_NS TESTCOND_P - -#define TESTCOND_GE (!((!!(S_REG[PSW] & PSW_S)) ^ (!!(S_REG[PSW] & PSW_OV)))) -#define TESTCOND_GT (!(((!!(S_REG[PSW] & PSW_S)) ^ (!!(S_REG[PSW] & PSW_OV))) || (S_REG[PSW] & PSW_Z))) - -// Tag layout -// Bit 0-21: TAG31-TAG10 -// Bit 22-23: Validity bits(one for each 4-byte subblock) -// Bit 24-27: NECRV("Reserved") -// Bit 28-31: 0 - -typedef enum { - V810_EMU_MODE_FAST = 0, - V810_EMU_MODE_ACCURATE = 1, - _V810_EMU_MODE_COUNT -} V810_Emu_Mode; - -class V810 -{ - public: - V810() - MDFN_COLD; - ~V810() MDFN_COLD; - - // Pass TRUE for vb_mode if we're emulating a VB-specific enhanced V810 CPU core - bool Init(V810_Emu_Mode mode, bool vb_mode) MDFN_COLD; - - void SetInt(int level); - - void SetMemWriteBus32(uint8 A, bool value) MDFN_COLD; - void SetMemReadBus32(uint8 A, bool value) MDFN_COLD; - - void SetMemReadHandlers(uint8 MDFN_FASTCALL (*read8)(v810_timestamp_t &, uint32), uint16 MDFN_FASTCALL (*read16)(v810_timestamp_t &, uint32), uint32 MDFN_FASTCALL (*read32)(v810_timestamp_t &, uint32)) MDFN_COLD; - void SetMemWriteHandlers(void MDFN_FASTCALL (*write8)(v810_timestamp_t &, uint32, uint8), void MDFN_FASTCALL (*write16)(v810_timestamp_t &, uint32, uint16), void MDFN_FASTCALL (*write32)(v810_timestamp_t &, uint32, uint32)) MDFN_COLD; - - void SetIOReadHandlers(uint8 MDFN_FASTCALL (*read8)(v810_timestamp_t &, uint32), uint16 MDFN_FASTCALL (*read16)(v810_timestamp_t &, uint32), uint32 MDFN_FASTCALL (*read32)(v810_timestamp_t &, uint32)) MDFN_COLD; - void SetIOWriteHandlers(void MDFN_FASTCALL (*write8)(v810_timestamp_t &, uint32, uint8), void MDFN_FASTCALL (*write16)(v810_timestamp_t &, uint32, uint16), void MDFN_FASTCALL (*write32)(v810_timestamp_t &, uint32, uint32)) MDFN_COLD; - - // Length specifies the number of bytes to map in, at each location specified by addresses[] (for mirroring) - uint8 *SetFastMap(void *(*allocator)(size_t size), uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name) MDFN_COLD; - - INLINE void ResetTS(v810_timestamp_t new_base_timestamp) - { - assert(next_event_ts > v810_timestamp); - - next_event_ts -= (v810_timestamp - new_base_timestamp); - v810_timestamp = new_base_timestamp; - } - - INLINE void SetEventNT(const v810_timestamp_t timestamp) - { - next_event_ts = timestamp; - } - - INLINE v810_timestamp_t GetEventNT(void) - { - return (next_event_ts); - } - - v810_timestamp_t Run(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)); - void Exit(void); - - void Reset(void) MDFN_COLD; - - enum - { - GSREG_PR = 0, - GSREG_SR = 32, - GSREG_PC = 64, - GSREG_TIMESTAMP - }; - - uint32 GetRegister(unsigned int which, char *special, const uint32 special_len); - void SetRegister(unsigned int which, uint32 value); - - uint32 GetPC(void); - void SetPC(uint32); - - INLINE uint32 GetPR(unsigned int which) - { - return which ? P_REG[which] : 0; - } - - private: - // Make sure P_REG[] is the first variable/array in this class, so non-zerfo offset encoding(at assembly level) isn't necessary to access it. - uint32 P_REG[32]; // Program registers pr0-pr31 - uint32 S_REG[32]; // System registers sr0-sr31 - uint32 PC; - uint8 *PC_ptr; - uint8 *PC_base; - - uint32 IPendingCache; - void RecalcIPendingCache(void); - - public: - v810_timestamp_t v810_timestamp; // Will never be less than 0. - - private: - v810_timestamp_t next_event_ts; - - enum - { - LASTOP_NORMAL = 0, - LASTOP_LOAD = 1, - LASTOP_STORE = 2, - LASTOP_IN = 3, - LASTOP_OUT = 4, - LASTOP_HEAVY_MATH = 5 - }; - - V810_Emu_Mode EmuMode; - bool VBMode; - - void Run_Fast(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) NO_INLINE; - void Run_Accurate(int32 MDFN_FASTCALL (*event_handler)(const v810_timestamp_t timestamp)) NO_INLINE; - - uint8 MDFN_FASTCALL (*MemRead8)(v810_timestamp_t ×tamp, uint32 A); - uint16 MDFN_FASTCALL (*MemRead16)(v810_timestamp_t ×tamp, uint32 A); - uint32 MDFN_FASTCALL (*MemRead32)(v810_timestamp_t ×tamp, uint32 A); - - void MDFN_FASTCALL (*MemWrite8)(v810_timestamp_t ×tamp, uint32 A, uint8 V); - void MDFN_FASTCALL (*MemWrite16)(v810_timestamp_t ×tamp, uint32 A, uint16 V); - void MDFN_FASTCALL (*MemWrite32)(v810_timestamp_t ×tamp, uint32 A, uint32 V); - - uint8 MDFN_FASTCALL (*IORead8)(v810_timestamp_t ×tamp, uint32 A); - uint16 MDFN_FASTCALL (*IORead16)(v810_timestamp_t ×tamp, uint32 A); - uint32 MDFN_FASTCALL (*IORead32)(v810_timestamp_t ×tamp, uint32 A); - - void MDFN_FASTCALL (*IOWrite8)(v810_timestamp_t ×tamp, uint32 A, uint8 V); - void MDFN_FASTCALL (*IOWrite16)(v810_timestamp_t ×tamp, uint32 A, uint16 V); - void MDFN_FASTCALL (*IOWrite32)(v810_timestamp_t ×tamp, uint32 A, uint32 V); - - bool MemReadBus32[256]; // Corresponding to the upper 8 bits of the memory address map. - bool MemWriteBus32[256]; - - int32 lastop; // Set to -1 on FP/MUL/DIV, 0x100 on LD, 0x200 on ST, 0x400 on in, 0x800 on out, and the actual opcode * 2(or >= 0) on everything else. - -#define LASTOP_LD 0x100 -#define LASTOP_ST 0x200 -#define LASTOP_IN 0x400 -#define LASTOP_OUT 0x800 - - enum - { - HALT_NONE = 0, - HALT_HALT = 1, - HALT_FATAL_EXCEPTION = 2 - }; - - uint8 Halted; - - bool Running; - - int ilevel; - - bool in_bstr; - uint16 in_bstr_to; - - bool bstr_subop(v810_timestamp_t ×tamp, int sub_op, int arg1); - void fpu_subop(v810_timestamp_t ×tamp, int sub_op, int arg1, int arg2); - - void Exception(uint32 handler, uint16 eCode); - - // Caching-related: - typedef struct - { - uint32 tag; - uint32 data[2]; - bool data_valid[2]; - } V810_CacheEntry_t; - - V810_CacheEntry_t Cache[128]; - - // Bitstring variables. - uint32 src_cache; - uint32 dst_cache; - bool have_src_cache, have_dst_cache; - - uint8** FastMap; - - // For CacheDump and CacheRestore - void CacheOpMemStore(v810_timestamp_t ×tamp, uint32 A, uint32 V); - uint32 CacheOpMemLoad(v810_timestamp_t ×tamp, uint32 A); - - void CacheClear(v810_timestamp_t ×tamp, uint32 start, uint32 count); - void CacheDump(v810_timestamp_t ×tamp, const uint32 SA); - void CacheRestore(v810_timestamp_t ×tamp, const uint32 SA); - - uint32 RDCACHE(v810_timestamp_t ×tamp, uint32 addr); - // - // End caching related - // - - uint16 RDOP(v810_timestamp_t ×tamp, uint32 addr, uint32 meow = 2); - void SetFlag(uint32 n, bool condition); - void SetSZ(uint32 value); - - void SetSREG(v810_timestamp_t ×tamp, unsigned int which, uint32 value); - uint32 GetSREG(unsigned int which); - - bool IsSubnormal(uint32 fpval); - void FPU_Math_Template(uint32 (V810_FP_Ops::*func)(uint32, uint32), uint32 arg1, uint32 arg2); - void FPU_DoException(void); - bool CheckFPInputException(uint32 fpval); - bool FPU_DoesExceptionKillResult(void); - void SetFPUOPNonFPUFlags(uint32 result); - - uint32 BSTR_RWORD(v810_timestamp_t ×tamp, uint32 A); - void BSTR_WWORD(v810_timestamp_t ×tamp, uint32 A, uint32 V); - bool Do_BSTR_Search(v810_timestamp_t ×tamp, const int inc_mul, unsigned int bit_test); - - V810_FP_Ops fpo; - - uint8 DummyRegion[V810_FAST_MAP_PSIZE + V810_FAST_MAP_TRAMPOLINE_SIZE]; -}; diff --git a/waterbox/vb/v810/v810_do_am.h b/waterbox/vb/v810/v810_do_am.h deleted file mode 100644 index 9cc01568d3..0000000000 --- a/waterbox/vb/v810/v810_do_am.h +++ /dev/null @@ -1,72 +0,0 @@ -#define DO_MOV_AM(); DO_AM_I(); -#define DO_ADD_AM(); DO_AM_I(); -#define DO_SUB_AM(); DO_AM_I(); -#define DO_CMP_AM(); DO_AM_I(); -#define DO_SHL_AM(); DO_AM_I(); -#define DO_SHR_AM(); DO_AM_I(); -#define DO_JMP_AM(); DO_AM_I(); -#define DO_SAR_AM(); DO_AM_I(); -#define DO_MUL_AM(); DO_AM_I(); -#define DO_DIV_AM(); DO_AM_I(); -#define DO_MULU_AM(); DO_AM_I(); -#define DO_DIVU_AM(); DO_AM_I(); -#define DO_OR_AM(); DO_AM_I(); -#define DO_AND_AM(); DO_AM_I(); -#define DO_XOR_AM(); DO_AM_I(); -#define DO_NOT_AM(); DO_AM_I(); -#define DO_MOV_I_AM(); DO_AM_II(); -#define DO_ADD_I_AM(); DO_AM_II(); -#define DO_SETF_AM(); DO_AM_II(); -#define DO_CMP_I_AM(); DO_AM_II(); -#define DO_SHL_I_AM(); DO_AM_II(); -#define DO_SHR_I_AM(); DO_AM_II(); -#define DO_EI_AM(); DO_AM_II(); -#define DO_SAR_I_AM(); DO_AM_II(); -#define DO_TRAP_AM(); DO_AM_II(); -#define DO_RETI_AM(); DO_AM_IX(); -#define DO_HALT_AM(); DO_AM_IX(); -#define DO_LDSR_AM(); DO_AM_II(); -#define DO_STSR_AM(); DO_AM_II(); -#define DO_DI_AM(); DO_AM_II(); -#define DO_BSTR_AM(); DO_AM_BSTR(); -#define DO_MOVEA_AM(); DO_AM_V(); -#define DO_ADDI_AM(); DO_AM_V(); -#define DO_JR_AM(); DO_AM_IV(); -#define DO_JAL_AM(); DO_AM_IV(); -#define DO_ORI_AM(); DO_AM_V(); -#define DO_ANDI_AM(); DO_AM_V(); -#define DO_XORI_AM(); DO_AM_V(); -#define DO_MOVHI_AM(); DO_AM_V(); -#define DO_LD_B_AM(); DO_AM_VIa(); -#define DO_LD_H_AM(); DO_AM_VIa(); -#define DO_LD_W_AM(); DO_AM_VIa(); -#define DO_ST_B_AM(); DO_AM_VIb(); -#define DO_ST_H_AM(); DO_AM_VIb(); -#define DO_ST_W_AM(); DO_AM_VIb(); -#define DO_IN_B_AM(); DO_AM_VIa(); -#define DO_IN_H_AM(); DO_AM_VIa(); -#define DO_CAXI_AM(); DO_AM_VIa(); -#define DO_IN_W_AM(); DO_AM_VIa(); -#define DO_OUT_B_AM(); DO_AM_VIb(); -#define DO_OUT_H_AM(); DO_AM_VIb(); -#define DO_FPP_AM(); DO_AM_FPP(); -#define DO_OUT_W_AM(); DO_AM_VIb(); -#define DO_BV_AM(); DO_AM_III(); -#define DO_BL_AM(); DO_AM_III(); -#define DO_BE_AM(); DO_AM_III(); -#define DO_BNH_AM(); DO_AM_III(); -#define DO_BN_AM(); DO_AM_III(); -#define DO_BR_AM(); DO_AM_III(); -#define DO_BLT_AM(); DO_AM_III(); -#define DO_BLE_AM(); DO_AM_III(); -#define DO_BNV_AM(); DO_AM_III(); -#define DO_BNL_AM(); DO_AM_III(); -#define DO_BNE_AM(); DO_AM_III(); -#define DO_BH_AM(); DO_AM_III(); -#define DO_BP_AM(); DO_AM_III(); -#define DO_NOP_AM(); DO_AM_III(); -#define DO_BGE_AM(); DO_AM_III(); -#define DO_BGT_AM(); DO_AM_III(); - - -#define DO_INVALID_AM(); DO_AM_UDEF(); diff --git a/waterbox/vb/v810/v810_fp_ops.cpp b/waterbox/vb/v810/v810_fp_ops.cpp deleted file mode 100644 index 53aa937fae..0000000000 --- a/waterbox/vb/v810/v810_fp_ops.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* v810_fp_ops.cpp: -** Copyright (C) 2014-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "vb.h" - -bool V810_FP_Ops::fp_is_zero(uint32 v) -{ - return ((v & 0x7FFFFFFF) == 0); -} - -#if 0 -bool V810_FP_Ops::fp_is_nan(uint32 v) -{ - return((v & 0x7FFFFFFF) > (255 << 23)); -} - -bool V810_FP_Ops::fp_is_inf(uint32 v) -{ - return((v & 0x7FFFFFFF) == (255 << 23)); -} -#endif - -bool V810_FP_Ops::fp_is_inf_nan_sub(uint32 v) -{ - if ((v & 0x7FFFFFFF) == 0) - return (false); - - switch ((v >> 23) & 0xFF) - { - case 0x00: - case 0xff: - return (true); - } - return (false); -} - -void V810_FP_Ops::fpim_decode(fpim *df, uint32 v) -{ - df->exp = ((v >> 23) & 0xFF) - 127; - df->f = (v & 0x7FFFFF) | ((v & 0x7FFFFFFF) ? 0x800000 : 0); - df->sign = v >> 31; -} - -void V810_FP_Ops::fpim_round(fpim *df) -{ - int vbc = 64 - MDFN_lzcount64(df->f); - - if (vbc > 24) - { - const unsigned sa = vbc - 24; - - if (1) // round to nearest - { - uint64 old_f = df->f; - - df->f = (df->f + ((df->f >> sa) & 1) + ((1ULL << (sa - 1)) - 1)) & ~((1ULL << sa) - 1); - - if (df->f != old_f) - { - //printf("Inexact mr\n"); - exception_flags |= flag_inexact; - } - } - else - abort(); - } -} - -void V810_FP_Ops::fpim_round_int(fpim *df, bool truncate) -{ - if (df->exp < 23) - { - const unsigned sa = 23 - df->exp; - uint64 old_f = df->f; - - //if(sa >= 2) - // printf("RI: %lld, %d\n", df->f, sa); - - // round to nearest - if (sa > 24) - df->f = 0; - else - { - if (truncate) - df->f = df->f & ~((1ULL << sa) - 1); - else - df->f = (df->f + ((df->f >> sa) & 1) + ((1ULL << (sa - 1)) - 1)) & ~((1ULL << sa) - 1); - } - - if (df->f != old_f) - { - //printf("Inexact\n"); - exception_flags |= flag_inexact; - } - } -} - -uint32 V810_FP_Ops::fpim_encode(fpim *df) -{ - const int lzc = MDFN_lzcount64(df->f); - int tmp_exp = df->exp - lzc; - uint64 tmp_walrus = df->f << (lzc & 0x3F); - int tmp_sign = df->sign; - - tmp_exp += 40; - tmp_walrus >>= 40; - - if (tmp_walrus == 0) - tmp_exp = -127; - else if (tmp_exp <= -127) - { - exception_flags |= flag_underflow | flag_inexact; - //printf("Subnormal: %lld. %d\n", tmp_walrus, tmp_exp); - if (1) - { - tmp_exp = -127; - tmp_walrus = 0; - } - else - { - tmp_walrus >>= -(tmp_exp + 126); - tmp_exp = -127; - } - } - else if (tmp_exp >= 128) - { - exception_flags |= flag_overflow; - //printf("Overflow!\n"); - - if (1) - tmp_exp -= 192; - else - { - tmp_exp = 128; - tmp_walrus = 0; - } - } - return (tmp_sign << 31) | ((tmp_exp + 127) << 23) | (tmp_walrus & 0x7FFFFF); -} - -uint32 V810_FP_Ops::mul(uint32 a, uint32 b) -{ - fpim ins[2]; - fpim res; - - if (fp_is_inf_nan_sub(a) || fp_is_inf_nan_sub(b)) - { - exception_flags |= flag_reserved; - return (~0U); - } - - fpim_decode(&ins[0], a); - fpim_decode(&ins[1], b); - - //printf("%08x %08x - %d %d %d - %d %d %d\n", a, b, a_exp, a_walrus, a_sign, b_exp, b_walrus, b_sign); - - res.exp = ins[0].exp + ins[1].exp - 23; - res.f = ins[0].f * ins[1].f; - res.sign = ins[0].sign ^ ins[1].sign; - - fpim_round(&res); - - return fpim_encode(&res); -} - -uint32 V810_FP_Ops::add(uint32 a, uint32 b) -{ - fpim ins[2]; - fpim res; - int64 ft[2]; - int64 tr; - int max_exp; - - if (fp_is_inf_nan_sub(a) || fp_is_inf_nan_sub(b)) - { - exception_flags |= flag_reserved; - return (~0U); - } - - if (a == b && !(a & 0x7FFFFFFF)) - { - return (a & 0x80000000); - } - - fpim_decode(&ins[0], a); - fpim_decode(&ins[1], b); - - max_exp = std::max(ins[0].exp, ins[1].exp); - - //printf("%d:%08llx %d:%08llx\n", ins[0].exp, ins[0].f, ins[1].exp, ins[1].f); - - for (unsigned i = 0; i < 2; i++) - { - unsigned sd = (max_exp - ins[i].exp); - - ft[i] = ins[i].f << 24; - - if (sd >= 48) - { - if (ft[i] != 0) - ft[i] = 1; - } - else - { - int64 nft = ft[i] >> sd; - - if (ft[i] != (nft << sd)) - { - nft |= 1; - } - //{ - // puts("FPR"); - // } - - ft[i] = nft; - } - - if (ins[i].sign) - ft[i] = -ft[i]; - } - - //printf("SOON: %08llx %08llx\n", ft[0], ft[1]); - - tr = ft[0] + ft[1]; - if (tr < 0) - { - tr = -tr; - res.sign = true; - } - else - res.sign = false; - - res.f = tr; - res.exp = max_exp - 24; - - fpim_round(&res); - - return fpim_encode(&res); -} - -uint32 V810_FP_Ops::sub(uint32 a, uint32 b) -{ - return add(a, b ^ 0x80000000); -} - -uint32 V810_FP_Ops::div(uint32 a, uint32 b) -{ - fpim ins[2]; - fpim res; - uint64 mtmp; - - if (fp_is_inf_nan_sub(a) || fp_is_inf_nan_sub(b)) - { - exception_flags |= flag_reserved; - return (~0U); - } - - if (fp_is_zero(a) && fp_is_zero(b)) - { - exception_flags |= flag_invalid; - return (~0U); - } - - fpim_decode(&ins[0], a); - fpim_decode(&ins[1], b); - - res.sign = ins[0].sign ^ ins[1].sign; - - if (ins[1].f == 0) - { - //puts("Divide by zero!"); - exception_flags |= flag_divbyzero; - return ((res.sign << 31) | (255 << 23)); - } - else - { - res.exp = ins[0].exp - ins[1].exp - 2 - 1; // + 23 - 2; - res.f = ((ins[0].f << 24) / ins[1].f) << 2; - mtmp = ((ins[0].f << 24) % ins[1].f) << 1; - - //printf("%lld %lld\n", (ins[0].f << 23) % ins[1].f, ins[1].f); - - if (mtmp > ins[1].f) - res.f |= 3; - else if (mtmp == ins[1].f) - res.f |= 2; - else if (mtmp > 0) - res.f |= 1; - } - - fpim_round(&res); - - return fpim_encode(&res); -} - -int V810_FP_Ops::cmp(uint32 a, uint32 b) -{ - fpim ins[2]; - - if (fp_is_inf_nan_sub(a) || fp_is_inf_nan_sub(b)) - { - exception_flags |= flag_reserved; - return (~0U); - } - - fpim_decode(&ins[0], a); - fpim_decode(&ins[1], b); - - if (ins[0].exp > ins[1].exp) - return (ins[0].sign ? -1 : 1); - - if (ins[0].exp < ins[1].exp) - return (ins[1].sign ? 1 : -1); - - if (ins[0].f > ins[1].f) - return (ins[0].sign ? -1 : 1); - - if (ins[0].f < ins[1].f) - return (ins[1].sign ? 1 : -1); - - if ((ins[0].sign ^ ins[1].sign) && ins[0].f != 0) - return (ins[0].sign ? -1 : 1); - - return (0); -} - -uint32 V810_FP_Ops::itof(uint32 v) -{ - fpim res; - - res.sign = (bool)(v & 0x80000000); - res.exp = 23; - res.f = res.sign ? (0x80000000 - (v & 0x7FFFFFFF)) : (v & 0x7FFFFFFF); - - fpim_round(&res); - - return fpim_encode(&res); -} - -uint32 V810_FP_Ops::ftoi(uint32 v, bool truncate) -{ - fpim ins; - int sa; - int ret; - - if (fp_is_inf_nan_sub(v)) - { - exception_flags |= flag_reserved; - return (~0U); - } - - fpim_decode(&ins, v); - fpim_round_int(&ins, truncate); - - sa = ins.exp - 23; - - if (sa < 0) - { - if (sa <= -32) - ret = 0; - else - ret = ins.f >> -sa; - } - else - { - if (sa >= 8) - { - if (sa == 8 && ins.f == 0x800000 && ins.sign) - return (0x80000000); - else - { - ret = ~0U; - exception_flags |= flag_invalid; - } - } - else - { - ret = ins.f << sa; - } - } - //printf("%d\n", sa); - - if (ins.sign) - ret = -ret; - - return (ret); -} diff --git a/waterbox/vb/v810/v810_fp_ops.h b/waterbox/vb/v810/v810_fp_ops.h deleted file mode 100644 index 20c607e7d2..0000000000 --- a/waterbox/vb/v810/v810_fp_ops.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************/ -/* Mednafen - Multi-system Emulator */ -/******************************************************************************/ -/* v810_fp_ops.h: -** Copyright (C) 2014-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -class V810_FP_Ops -{ - public: - uint32 mul(uint32 a, uint32 b); - uint32 div(uint32 a, uint32 b); - uint32 add(uint32 a, uint32 b); - uint32 sub(uint32 a, uint32 b); - int cmp(uint32 a, uint32 b); - - uint32 itof(uint32 v); - uint32 ftoi(uint32 v, bool truncate); - - enum - { - flag_invalid = 0x0001, - flag_divbyzero = 0x0002, - flag_overflow = 0x0004, - flag_underflow = 0x0008, - flag_inexact = 0x0010, - flag_reserved = 0x0020 - }; - - inline uint32 get_flags(void) - { - return exception_flags; - } - - inline void clear_flags(void) - { - exception_flags = 0; - } - - private: - unsigned exception_flags; - - struct fpim - { - uint64 f; - int exp; - bool sign; - }; - - bool fp_is_zero(uint32 v); - bool fp_is_inf_nan_sub(uint32 v); - - unsigned clz64(uint64 v); - void fpim_decode(fpim *df, uint32 v); - void fpim_round(fpim *df); - void fpim_round_int(fpim *df, bool truncate = false); - uint32 fpim_encode(fpim *df); -}; diff --git a/waterbox/vb/v810/v810_oploop.inc b/waterbox/vb/v810/v810_oploop.inc deleted file mode 100644 index 6b5015c744..0000000000 --- a/waterbox/vb/v810/v810_oploop.inc +++ /dev/null @@ -1,1130 +0,0 @@ -/* V810 Emulator - * - * Copyright (C) 2006 David Tucker - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - - // Macro test taken from http://gcc.gnu.org/viewcvs/trunk/gcc/testsuite/gcc.dg/20020919-1.c?view=markup&pathrev=142696 - //#if defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) - // register v810_timestamp_t timestamp_rl asm("15") = v810_timestamp; - //#elif defined(__x86_64__) - // register v810_timestamp_t timestamp_rl asm("r11") = v810_timestamp; - //#else - register v810_timestamp_t timestamp_rl = v810_timestamp; - //#endif - - uint32 opcode; - uint32 tmp2; - int val = 0; - - - #define ADDCLOCK(__n) { timestamp += __n; } - - #define CHECK_HALTED(); { if(Halted && timestamp < next_event_ts) { timestamp = next_event_ts; } } - - while(Running) - { - #ifdef RB_DEBUGMODE - uint32 old_PC = RB_GETPC(); - #endif - uint32 tmpop; - - assert(timestamp_rl <= next_event_ts); - - if(!IPendingCache) - { - if(Halted) - { - timestamp_rl = next_event_ts; - } - else if(in_bstr) - { - tmpop = in_bstr_to; - opcode = tmpop >> 9; - goto op_BSTR; - } - } - - while(timestamp_rl < next_event_ts) - { - #ifdef RB_DEBUGMODE - old_PC = RB_GETPC(); - #endif - - P_REG[0] = 0; //Zero the Zero Reg!!! - - RB_CPUHOOK(RB_GETPC()); - - { - //printf("%08x\n", RB_GETPC()); - { - v810_timestamp_t timestamp = timestamp_rl; - - tmpop = RB_RDOP(0, 0); - - timestamp_rl = timestamp; - } - - opcode = (tmpop >> 9) | IPendingCache; - - //printf("%02x\n", opcode >> 1); -#if HAVE_COMPUTED_GOTO - #define CGBEGIN static const void *const op_goto_table[256] = { - #define CGE(l) &&l, - #define CGEND }; goto *op_goto_table[opcode]; -#else - /* (uint8) cast for cheaper alternative to generated branch+compare bounds check instructions, but still more - expensive than computed goto which needs no masking nor bounds checking. - */ - #define CGBEGIN { enum { CGESB = 1 + __COUNTER__ }; switch((uint8)opcode) { - #define CGE(l) case __COUNTER__ - CGESB: goto l; - #define CGEND } } -#endif - - CGBEGIN - CGE(op_MOV) CGE(op_MOV) CGE(op_ADD) CGE(op_ADD) CGE(op_SUB) CGE(op_SUB) CGE(op_CMP) CGE(op_CMP) - CGE(op_SHL) CGE(op_SHL) CGE(op_SHR) CGE(op_SHR) CGE(op_JMP) CGE(op_JMP) CGE(op_SAR) CGE(op_SAR) - CGE(op_MUL) CGE(op_MUL) CGE(op_DIV) CGE(op_DIV) CGE(op_MULU) CGE(op_MULU) CGE(op_DIVU) CGE(op_DIVU) - CGE(op_OR) CGE(op_OR) CGE(op_AND) CGE(op_AND) CGE(op_XOR) CGE(op_XOR) CGE(op_NOT) CGE(op_NOT) - CGE(op_MOV_I) CGE(op_MOV_I) CGE(op_ADD_I) CGE(op_ADD_I) CGE(op_SETF) CGE(op_SETF) CGE(op_CMP_I) CGE(op_CMP_I) - CGE(op_SHL_I) CGE(op_SHL_I) CGE(op_SHR_I) CGE(op_SHR_I) CGE(op_EI) CGE(op_EI) CGE(op_SAR_I) CGE(op_SAR_I) - CGE(op_TRAP) CGE(op_TRAP) CGE(op_RETI) CGE(op_RETI) CGE(op_HALT) CGE(op_HALT) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_LDSR) CGE(op_LDSR) CGE(op_STSR) CGE(op_STSR) CGE(op_DI) CGE(op_DI) CGE(op_BSTR) CGE(op_BSTR) - CGE(op_BV) CGE(op_BL) CGE(op_BE) CGE(op_BNH) CGE(op_BN) CGE(op_BR) CGE(op_BLT) CGE(op_BLE) - CGE(op_BNV) CGE(op_BNL) CGE(op_BNE) CGE(op_BH) CGE(op_BP) CGE(op_NOP) CGE(op_BGE) CGE(op_BGT) - CGE(op_MOVEA) CGE(op_MOVEA) CGE(op_ADDI) CGE(op_ADDI) CGE(op_JR) CGE(op_JR) CGE(op_JAL) CGE(op_JAL) - CGE(op_ORI) CGE(op_ORI) CGE(op_ANDI) CGE(op_ANDI) CGE(op_XORI) CGE(op_XORI) CGE(op_MOVHI) CGE(op_MOVHI) - CGE(op_LD_B) CGE(op_LD_B) CGE(op_LD_H) CGE(op_LD_H) CGE(op_INVALID) CGE(op_INVALID) CGE(op_LD_W) CGE(op_LD_W) - CGE(op_ST_B) CGE(op_ST_B) CGE(op_ST_H) CGE(op_ST_H) CGE(op_INVALID) CGE(op_INVALID) CGE(op_ST_W) CGE(op_ST_W) - CGE(op_IN_B) CGE(op_IN_B) CGE(op_IN_H) CGE(op_IN_H) CGE(op_CAXI) CGE(op_CAXI) CGE(op_IN_W) CGE(op_IN_W) - CGE(op_OUT_B) CGE(op_OUT_B) CGE(op_OUT_H) CGE(op_OUT_H) CGE(op_FPP) CGE(op_FPP) CGE(op_OUT_W) CGE(op_OUT_W) - - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) - CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INT_HANDLER) - CGEND - - // Bit string subopcodes - #define DO_AM_BSTR() \ - const uint32 arg1 = (tmpop >> 5) & 0x1F; \ - const uint32 arg2 = (tmpop & 0x1F); \ - RB_INCPCBY2(); - - - #define DO_AM_FPP() \ - const uint32 arg1 = (tmpop >> 5) & 0x1F; \ - const uint32 arg2 = (tmpop & 0x1F); \ - const uint32 arg3 = ((RB_RDOP(2) >> 10)&0x3F); \ - RB_INCPCBY4(); - - - #define DO_AM_UDEF() \ - RB_INCPCBY2(); - - #define DO_AM_I() \ - const uint32 arg1 = tmpop & 0x1F; \ - const uint32 arg2 = (tmpop >> 5) & 0x1F; \ - RB_INCPCBY2(); - - #define DO_AM_II() DO_AM_I(); - - - #define DO_AM_IV() \ - const uint32 arg1 = ((tmpop & 0x000003FF) << 16) | RB_RDOP(2); \ - - - #define DO_AM_V() \ - const uint32 arg3 = (tmpop >> 5) & 0x1F; \ - const uint32 arg2 = tmpop & 0x1F; \ - const uint32 arg1 = RB_RDOP(2); \ - RB_INCPCBY4(); - - - #define DO_AM_VIa() \ - const uint32 arg1 = RB_RDOP(2); \ - const uint32 arg2 = tmpop & 0x1F; \ - const uint32 arg3 = (tmpop >> 5) & 0x1F; \ - RB_INCPCBY4(); \ - - - #define DO_AM_VIb() \ - const uint32 arg1 = (tmpop >> 5) & 0x1F; \ - const uint32 arg2 = RB_RDOP(2); \ - const uint32 arg3 = (tmpop & 0x1F); \ - RB_INCPCBY4(); \ - - #define DO_AM_IX() \ - const uint32 arg1 = (tmpop & 0x1); \ - RB_INCPCBY2(); \ - - #define DO_AM_III() \ - const uint32 arg1 = tmpop & 0x1FE; - - #include "v810_do_am.h" - - #define BEGIN_OP(meowtmpop) { op_##meowtmpop: v810_timestamp_t timestamp = timestamp_rl; DO_##meowtmpop ##_AM(); - #define END_OP() timestamp_rl = timestamp; goto OpFinished; } - #define END_OP_SKIPLO() timestamp_rl = timestamp; goto OpFinishedSkipLO; } - - BEGIN_OP(MOV); - ADDCLOCK(1); - SetPREG(arg2, P_REG[arg1]); - END_OP(); - - - BEGIN_OP(ADD); - ADDCLOCK(1); - uint32 temp = P_REG[arg2] + P_REG[arg1]; - - SetFlag(PSW_OV, ((P_REG[arg2]^(~P_REG[arg1]))&(P_REG[arg2]^temp))&0x80000000); - SetFlag(PSW_CY, temp < P_REG[arg2]); - - SetPREG(arg2, temp); - SetSZ(P_REG[arg2]); - END_OP(); - - - BEGIN_OP(SUB); - ADDCLOCK(1); - uint32 temp = P_REG[arg2] - P_REG[arg1]; - - SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000); - SetFlag(PSW_CY, temp > P_REG[arg2]); - - SetPREG(arg2, temp); - SetSZ(P_REG[arg2]); - END_OP(); - - - BEGIN_OP(CMP); - ADDCLOCK(1); - uint32 temp = P_REG[arg2] - P_REG[arg1]; - - SetSZ(temp); - SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000); - SetFlag(PSW_CY, temp > P_REG[arg2]); - END_OP(); - - - BEGIN_OP(SHL); - ADDCLOCK(1); - val = P_REG[arg1] & 0x1F; - - // set CY before we destroy the regisrer info.... - SetFlag(PSW_CY, (val != 0) && ((P_REG[arg2] >> (32 - val))&0x01) ); - SetFlag(PSW_OV, FALSE); - SetPREG(arg2, P_REG[arg2] << val); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(SHR); - ADDCLOCK(1); - val = P_REG[arg1] & 0x1F; - // set CY before we destroy the regisrer info.... - SetFlag(PSW_CY, (val) && ((P_REG[arg2] >> (val-1))&0x01)); - SetFlag(PSW_OV, FALSE); - SetPREG(arg2, P_REG[arg2] >> val); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(JMP); - - (void)arg2; // arg2 is unused. - - ADDCLOCK(3); - RB_SETPC((P_REG[arg1] & 0xFFFFFFFE)); - if(RB_AccurateMode) - { - BRANCH_ALIGN_CHECK(PC); - } - RB_ADDBT(old_PC, RB_GETPC(), 0); - END_OP(); - - BEGIN_OP(SAR); - ADDCLOCK(1); - val = P_REG[arg1] & 0x1F; - - SetFlag(PSW_CY, (val) && ((P_REG[arg2]>>(val-1))&0x01) ); - SetFlag(PSW_OV, FALSE); - - SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> val)); - - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(OR); - ADDCLOCK(1); - SetPREG(arg2, P_REG[arg1] | P_REG[arg2]); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(AND); - ADDCLOCK(1); - SetPREG(arg2, P_REG[arg1] & P_REG[arg2]); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(XOR); - ADDCLOCK(1); - SetPREG(arg2, P_REG[arg1] ^ P_REG[arg2]); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(NOT); - ADDCLOCK(1); - SetPREG(arg2, ~P_REG[arg1]); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(MOV_I); - ADDCLOCK(1); - SetPREG(arg2,sign_5(arg1)); - END_OP(); - - BEGIN_OP(ADD_I); - ADDCLOCK(1); - uint32 temp = P_REG[arg2] + sign_5(arg1); - - SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000); - SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]); - - SetPREG(arg2, (uint32)temp); - SetSZ(P_REG[arg2]); - END_OP(); - - - BEGIN_OP(SETF); - ADDCLOCK(1); - - P_REG[arg2] = 0; - - switch (arg1 & 0x0F) - { - case COND_V: - if (TESTCOND_V) P_REG[arg2] = 1; - break; - case COND_C: - if (TESTCOND_C) P_REG[arg2] = 1; - break; - case COND_Z: - if (TESTCOND_Z) P_REG[arg2] = 1; - break; - case COND_NH: - if (TESTCOND_NH) P_REG[arg2] = 1; - break; - case COND_S: - if (TESTCOND_S) P_REG[arg2] = 1; - break; - case COND_T: - P_REG[arg2] = 1; - break; - case COND_LT: - if (TESTCOND_LT) P_REG[arg2] = 1; - break; - case COND_LE: - if (TESTCOND_LE) P_REG[arg2] = 1; - break; - case COND_NV: - if (TESTCOND_NV) P_REG[arg2] = 1; - break; - case COND_NC: - if (TESTCOND_NC) P_REG[arg2] = 1; - break; - case COND_NZ: - if (TESTCOND_NZ) P_REG[arg2] = 1; - break; - case COND_H: - if (TESTCOND_H) P_REG[arg2] = 1; - break; - case COND_NS: - if (TESTCOND_NS) P_REG[arg2] = 1; - break; - case COND_F: - //always false! do nothing more - break; - case COND_GE: - if (TESTCOND_GE) P_REG[arg2] = 1; - break; - case COND_GT: - if (TESTCOND_GT) P_REG[arg2] = 1; - break; - } - END_OP(); - - BEGIN_OP(CMP_I); - ADDCLOCK(1); - uint32 temp = P_REG[arg2] - sign_5(arg1); - - SetSZ(temp); - SetFlag(PSW_OV, ((P_REG[arg2]^(sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000); - SetFlag(PSW_CY, temp > P_REG[arg2]); - END_OP(); - - BEGIN_OP(SHR_I); - ADDCLOCK(1); - SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (arg1-1))&0x01) ); - // set CY before we destroy the regisrer info.... - SetPREG(arg2, P_REG[arg2] >> arg1); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(SHL_I); - ADDCLOCK(1); - SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (32 - arg1))&0x01) ); - // set CY before we destroy the regisrer info.... - - SetPREG(arg2, P_REG[arg2] << arg1); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(SAR_I); - ADDCLOCK(1); - SetFlag(PSW_CY, arg1 && ((P_REG[arg2]>>(arg1-1))&0x01) ); - - SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> arg1)); - - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg2]); - END_OP(); - - BEGIN_OP(LDSR); // Loads a Sys Reg with the value in specified PR - ADDCLOCK(1); // ? - - SetSREG(timestamp, arg1 & 0x1F, P_REG[arg2 & 0x1F]); - END_OP(); - - BEGIN_OP(STSR); // Loads a PR with the value in specified Sys Reg - ADDCLOCK(1); // ? - P_REG[arg2 & 0x1F] = GetSREG(arg1 & 0x1F); - END_OP(); - - BEGIN_OP(EI); - (void)arg1; // arg1 is unused. - (void)arg2; // arg2 is unused. - - if(VBMode) - { - ADDCLOCK(1); - S_REG[PSW] = S_REG[PSW] &~ PSW_ID; - RecalcIPendingCache(); - } - else - { - ADDCLOCK(1); - RB_DECPCBY2(); - Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); - CHECK_HALTED(); - } - END_OP(); - - BEGIN_OP(DI); - (void)arg1; // arg1 is unused. - (void)arg2; // arg2 is unused. - - if(VBMode) - { - ADDCLOCK(1); - S_REG[PSW] |= PSW_ID; - IPendingCache = 0; - } - else - { - ADDCLOCK(1); - RB_DECPCBY2(); - Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); - CHECK_HALTED(); - } - END_OP(); - - - #define COND_BRANCH(cond) \ - if(cond) \ - { \ - ADDCLOCK(3); \ - RB_PCRELCHANGE(sign_9(arg1) & 0xFFFFFFFE); \ - if(RB_AccurateMode) \ - { \ - BRANCH_ALIGN_CHECK(PC); \ - } \ - RB_ADDBT(old_PC, RB_GETPC(), 0); \ - } \ - else \ - { \ - ADDCLOCK(1); \ - RB_INCPCBY2(); \ - } - - BEGIN_OP(BV); - COND_BRANCH(TESTCOND_V); - END_OP(); - - - BEGIN_OP(BL); - COND_BRANCH(TESTCOND_L); - END_OP(); - - BEGIN_OP(BE); - COND_BRANCH(TESTCOND_E); - END_OP(); - - BEGIN_OP(BNH); - COND_BRANCH(TESTCOND_NH); - END_OP(); - - BEGIN_OP(BN); - COND_BRANCH(TESTCOND_N); - END_OP(); - - BEGIN_OP(BR); - COND_BRANCH(TRUE); - END_OP(); - - BEGIN_OP(BLT); - COND_BRANCH(TESTCOND_LT); - END_OP(); - - BEGIN_OP(BLE); - COND_BRANCH(TESTCOND_LE); - END_OP(); - - BEGIN_OP(BNV); - COND_BRANCH(TESTCOND_NV); - END_OP(); - - BEGIN_OP(BNL); - COND_BRANCH(TESTCOND_NL); - END_OP(); - - BEGIN_OP(BNE); - COND_BRANCH(TESTCOND_NE); - END_OP(); - - BEGIN_OP(BH); - COND_BRANCH(TESTCOND_H); - END_OP(); - - BEGIN_OP(BP); - COND_BRANCH(TESTCOND_P); - END_OP(); - - BEGIN_OP(BGE); - COND_BRANCH(TESTCOND_GE); - END_OP(); - - BEGIN_OP(BGT); - COND_BRANCH(TESTCOND_GT); - END_OP(); - - BEGIN_OP(JR); - ADDCLOCK(3); - RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE); - if(RB_AccurateMode) - { - BRANCH_ALIGN_CHECK(PC); - } - RB_ADDBT(old_PC, RB_GETPC(), 0); - END_OP(); - - BEGIN_OP(JAL); - ADDCLOCK(3); - P_REG[31] = RB_GETPC() + 4; - RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE); - if(RB_AccurateMode) - { - BRANCH_ALIGN_CHECK(PC); - } - RB_ADDBT(old_PC, RB_GETPC(), 0); - END_OP(); - - BEGIN_OP(MOVEA); - ADDCLOCK(1); - SetPREG(arg3, P_REG[arg2] + sign_16(arg1)); - END_OP(); - - BEGIN_OP(ADDI); - ADDCLOCK(1); - uint32 temp = P_REG[arg2] + sign_16(arg1); - - SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_16(arg1)))&(P_REG[arg2]^temp))&0x80000000); - SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]); - - SetPREG(arg3, (uint32)temp); - SetSZ(P_REG[arg3]); - END_OP(); - - BEGIN_OP(ORI); - ADDCLOCK(1); - SetPREG(arg3, arg1 | P_REG[arg2]); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg3]); - END_OP(); - - BEGIN_OP(ANDI); - ADDCLOCK(1); - SetPREG(arg3, (arg1 & P_REG[arg2])); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg3]); - END_OP(); - - BEGIN_OP(XORI); - ADDCLOCK(1); - SetPREG(arg3, arg1 ^ P_REG[arg2]); - SetFlag(PSW_OV, FALSE); - SetSZ(P_REG[arg3]); - END_OP(); - - BEGIN_OP(MOVHI); - ADDCLOCK(1); - SetPREG(arg3, (arg1 << 16) + P_REG[arg2]); - END_OP(); - - // LD.B - BEGIN_OP(LD_B); - ADDCLOCK(1); - tmp2 = (sign_16(arg1)+P_REG[arg2])&0xFFFFFFFF; - - SetPREG(arg3, sign_8(MemRead8(timestamp, tmp2))); - - //should be 3 clocks when executed alone, 2 when precedes another LD, or 1 - //when precedes an instruction with many clocks (I'm guessing FP, MUL, DIV, etc) - if(lastop >= 0) - { - if(lastop == LASTOP_LD) - { - ADDCLOCK(1); - } - else - { - ADDCLOCK(2); - } - } - lastop = LASTOP_LD; - END_OP_SKIPLO(); - - // LD.H - BEGIN_OP(LD_H); - ADDCLOCK(1); - tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE; - SetPREG(arg3, sign_16(MemRead16(timestamp, tmp2))); - - if(lastop >= 0) - { - if(lastop == LASTOP_LD) - { - ADDCLOCK(1); - } - else - { - ADDCLOCK(2); - } - } - lastop = LASTOP_LD; - END_OP_SKIPLO(); - - - // LD.W - BEGIN_OP(LD_W); - ADDCLOCK(1); - - tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC; - - if(MemReadBus32[tmp2 >> 24]) - { - SetPREG(arg3, MemRead32(timestamp, tmp2)); - - if(lastop >= 0) - { - if(lastop == LASTOP_LD) - { - ADDCLOCK(1); - } - else - { - ADDCLOCK(2); - } - } - } - else - { - uint32 rv; - - rv = MemRead16(timestamp, tmp2); - rv |= MemRead16(timestamp, tmp2 | 2) << 16; - - SetPREG(arg3, rv); - - if(lastop >= 0) - { - if(lastop == LASTOP_LD) - { - ADDCLOCK(3); - } - else - { - ADDCLOCK(4); - } - } - } - lastop = LASTOP_LD; - END_OP_SKIPLO(); - - // ST.B - BEGIN_OP(ST_B); - ADDCLOCK(1); - MemWrite8(timestamp, sign_16(arg2)+P_REG[arg3], P_REG[arg1] & 0xFF); - - if(lastop == LASTOP_ST) - { - ADDCLOCK(1); - } - lastop = LASTOP_ST; - END_OP_SKIPLO(); - - // ST.H - BEGIN_OP(ST_H); - ADDCLOCK(1); - - MemWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE, P_REG[arg1] & 0xFFFF); - - if(lastop == LASTOP_ST) - { - ADDCLOCK(1); - } - lastop = LASTOP_ST; - END_OP_SKIPLO(); - - // ST.W - BEGIN_OP(ST_W); - ADDCLOCK(1); - tmp2 = (sign_16(arg2)+P_REG[arg3]) & 0xFFFFFFFC; - - if(MemWriteBus32[tmp2 >> 24]) - { - MemWrite32(timestamp, tmp2, P_REG[arg1]); - - if(lastop == LASTOP_ST) - { - ADDCLOCK(1); - } - } - else - { - MemWrite16(timestamp, tmp2, P_REG[arg1] & 0xFFFF); - MemWrite16(timestamp, tmp2 | 2, P_REG[arg1] >> 16); - - if(lastop == LASTOP_ST) - { - ADDCLOCK(3); - } - } - lastop = LASTOP_ST; - END_OP_SKIPLO(); - - // IN.B - BEGIN_OP(IN_B); - { - ADDCLOCK(3); - SetPREG(arg3, IORead8(timestamp, sign_16(arg1)+P_REG[arg2])); - } - lastop = LASTOP_IN; - END_OP_SKIPLO(); - - - // IN.H - BEGIN_OP(IN_H); - { - ADDCLOCK(3); - SetPREG(arg3, IORead16(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE)); - } - lastop = LASTOP_IN; - END_OP_SKIPLO(); - - - // IN.W - BEGIN_OP(IN_W); - if(IORead32) - { - ADDCLOCK(3); - SetPREG(arg3, IORead32(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC)); - } - else - { - uint32 eff_addr = (sign_16(arg1) + P_REG[arg2]) & 0xFFFFFFFC; - uint32 rv; - - ADDCLOCK(5); - - rv = IORead16(timestamp, eff_addr); - rv |= IORead16(timestamp, eff_addr | 2) << 16; - - SetPREG(arg3, rv); - } - lastop = LASTOP_IN; - END_OP_SKIPLO(); - - - // OUT.B - BEGIN_OP(OUT_B); - ADDCLOCK(1); - IOWrite8(timestamp, sign_16(arg2)+P_REG[arg3],P_REG[arg1]&0xFF); - - if(lastop == LASTOP_OUT) - { - ADDCLOCK(1); - } - lastop = LASTOP_OUT; - END_OP_SKIPLO(); - - - // OUT.H - BEGIN_OP(OUT_H); - ADDCLOCK(1); - IOWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE,P_REG[arg1]&0xFFFF); - - if(lastop == LASTOP_OUT) - { - ADDCLOCK(1); - } - lastop = LASTOP_OUT; - END_OP_SKIPLO(); - - - // OUT.W - BEGIN_OP(OUT_W); - ADDCLOCK(1); - - if(IOWrite32) - IOWrite32(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC,P_REG[arg1]); - else - { - uint32 eff_addr = (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC; - IOWrite16(timestamp, eff_addr, P_REG[arg1] & 0xFFFF); - IOWrite16(timestamp, eff_addr | 2, P_REG[arg1] >> 16); - } - - if(lastop == LASTOP_OUT) - { - if(IOWrite32) - { - ADDCLOCK(1); - } - else - { - ADDCLOCK(3); - } - } - lastop = LASTOP_OUT; - END_OP_SKIPLO(); - - BEGIN_OP(NOP); - (void)arg1; // arg1 is unused. - - ADDCLOCK(1); - RB_INCPCBY2(); - END_OP(); - - BEGIN_OP(RETI); - (void)arg1; // arg1 is unused. - - ADDCLOCK(10); - - //Return from Trap/Interupt - if(S_REG[PSW] & PSW_NP) { // Read the FE Reg - RB_SETPC(S_REG[FEPC] & 0xFFFFFFFE); - S_REG[PSW] = S_REG[FEPSW]; - } else { //Read the EI Reg Interupt - RB_SETPC(S_REG[EIPC] & 0xFFFFFFFE); - S_REG[PSW] = S_REG[EIPSW]; - } - RecalcIPendingCache(); - - RB_ADDBT(old_PC, RB_GETPC(), 0); - END_OP(); - - BEGIN_OP(MUL); - ADDCLOCK(13); - - uint64 temp = (int64)(int32)P_REG[arg1] * (int32)P_REG[arg2]; - - SetPREG(30, (uint32)(temp >> 32)); - SetPREG(arg2, temp); - SetSZ(P_REG[arg2]); - SetFlag(PSW_OV, temp != (uint64)(int64)(int32)(uint32)temp); - lastop = -1; - END_OP_SKIPLO(); - - BEGIN_OP(MULU); - ADDCLOCK(13); - uint64 temp = (uint64)P_REG[arg1] * (uint64)P_REG[arg2]; - - SetPREG(30, (uint32)(temp >> 32)); - SetPREG(arg2, (uint32)temp); - - SetSZ(P_REG[arg2]); - SetFlag(PSW_OV, temp != (uint32)temp); - lastop = -1; - END_OP_SKIPLO(); - - BEGIN_OP(DIVU); - ADDCLOCK(36); - if(P_REG[arg1] == 0) // Divide by zero! - { - RB_DECPCBY2(); - Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV); - CHECK_HALTED(); - } - else - { - // Careful here, since arg2 can be == 30 - uint32 quotient = (uint32)P_REG[arg2] / (uint32)P_REG[arg1]; - uint32 remainder = (uint32)P_REG[arg2] % (uint32)P_REG[arg1]; - - SetPREG(30, remainder); - SetPREG(arg2, quotient); - - SetFlag(PSW_OV, FALSE); - SetSZ(quotient); - } - lastop = -1; - END_OP_SKIPLO(); - - BEGIN_OP(DIV); - //if(P_REG[arg1] & P_REG[arg2] & 0x80000000) - //{ - // printf("Div: %08x %08x\n", P_REG[arg1], P_REG[arg2]); - //} - - ADDCLOCK(38); - if((uint32)P_REG[arg1] == 0) // Divide by zero! - { - RB_DECPCBY2(); - Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV); - CHECK_HALTED(); - } - else - { - if((P_REG[arg2]==0x80000000)&&(P_REG[arg1]==0xFFFFFFFF)) - { - SetFlag(PSW_OV, TRUE); - P_REG[30]=0; - SetPREG(arg2, 0x80000000); - SetSZ(P_REG[arg2]); - } - else - { - // Careful here, since arg2 can be == 30 - uint32 quotient = (int32)P_REG[arg2] / (int32)P_REG[arg1]; - uint32 remainder = (int32)P_REG[arg2] % (int32)P_REG[arg1]; - - SetPREG(30, remainder); - SetPREG(arg2, quotient); - - SetFlag(PSW_OV, FALSE); - SetSZ(quotient); - } - } - lastop = -1; - END_OP_SKIPLO(); - - BEGIN_OP(FPP); - ADDCLOCK(1); - fpu_subop(timestamp, arg3, arg1, arg2); - lastop = -1; - CHECK_HALTED(); - END_OP_SKIPLO(); - - BEGIN_OP(BSTR); - if(!in_bstr) - { - ADDCLOCK(1); - } - - if(bstr_subop(timestamp, arg2, arg1)) - { - RB_DECPCBY2(); - in_bstr = TRUE; - in_bstr_to = tmpop; - } - else - { - in_bstr = FALSE; - have_src_cache = have_dst_cache = FALSE; - } - END_OP(); - - BEGIN_OP(HALT); - (void)arg1; // arg1 is unused. - - ADDCLOCK(1); - Halted = HALT_HALT; - //printf("Untested opcode: HALT\n"); - END_OP(); - - BEGIN_OP(TRAP); - (void)arg2; // arg2 is unused. - - ADDCLOCK(15); - - Exception(TRAP_HANDLER_BASE + (arg1 & 0x10), ECODE_TRAP_BASE + (arg1 & 0x1F)); - CHECK_HALTED(); - END_OP(); - - BEGIN_OP(CAXI); - //printf("Untested opcode: caxi\n"); - - // Lock bus(N/A) - - ADDCLOCK(26); - - { - uint32 addr, tmp, compare_temp; - uint32 to_write; - - addr = sign_16(arg1) + P_REG[arg2]; - addr &= ~3; - - if(MemReadBus32[addr >> 24]) - tmp = MemRead32(timestamp, addr); - else - { - tmp = MemRead16(timestamp, addr); - tmp |= MemRead16(timestamp, addr | 2) << 16; - } - - compare_temp = P_REG[arg3] - tmp; - - SetSZ(compare_temp); - SetFlag(PSW_OV, ((P_REG[arg3]^tmp)&(P_REG[arg3]^compare_temp))&0x80000000); - SetFlag(PSW_CY, compare_temp > P_REG[arg3]); - - if(!compare_temp) // If they're equal... - to_write = P_REG[30]; - else - to_write = tmp; - - if(MemWriteBus32[addr >> 24]) - MemWrite32(timestamp, addr, to_write); - else - { - MemWrite16(timestamp, addr, to_write & 0xFFFF); - MemWrite16(timestamp, addr | 2, to_write >> 16); - } - P_REG[arg3] = tmp; - } - - // Unlock bus(N/A) - - END_OP(); - - - - op_INT_HANDLER: - { - int iNum = ilevel; - - S_REG[EIPC] = GetPC(); - S_REG[EIPSW] = S_REG[PSW]; - - SetPC(0xFFFFFE00 | (iNum << 4)); - - RB_ADDBT(old_PC, RB_GETPC(), 0xFE00 | (iNum << 4)); - - S_REG[ECR] = 0xFE00 | (iNum << 4); - - S_REG[PSW] |= PSW_EP; - S_REG[PSW] |= PSW_ID; - S_REG[PSW] &= ~PSW_AE; - - // Now, set need to set the interrupt enable level to he level that is being processed + 1, - // saturating at 15. - iNum++; - - if(iNum > 0x0F) - iNum = 0x0F; - - S_REG[PSW] &= ~PSW_IA; - S_REG[PSW] |= iNum << 16; - - // Accepting an interrupt takes us out of normal HALT status, of course! - Halted = HALT_NONE; - - // Invalidate our bitstring state(forces the instruction to be re-read, and the r/w buffers reloaded). - in_bstr = FALSE; - have_src_cache = FALSE; - have_dst_cache = FALSE; - - IPendingCache = 0; - - goto OpFinished; - } - - - BEGIN_OP(INVALID); - RB_DECPCBY2(); - if(!RB_AccurateMode) - { - RB_SETPC(RB_GETPC()); - if((uint32)(RB_RDOP(0, 0) >> 9) != opcode) - { - //printf("Trampoline: %08x %02x\n", RB_GETPC(), opcode >> 1); - } - else - { - ADDCLOCK(1); - Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); - CHECK_HALTED(); - } - } - else - { - ADDCLOCK(1); - Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); - CHECK_HALTED(); - } - END_OP(); - - } - - OpFinished: ; - lastop = opcode; - OpFinishedSkipLO: ; - } // end while(timestamp_rl < next_event_ts) - next_event_ts = event_handler(timestamp_rl); - //printf("Next: %d, Cur: %d\n", next_event_ts, timestamp); - } - -v810_timestamp = timestamp_rl; diff --git a/waterbox/vb/v810/v810_opt.h b/waterbox/vb/v810/v810_opt.h deleted file mode 100644 index 585c50b269..0000000000 --- a/waterbox/vb/v810/v810_opt.h +++ /dev/null @@ -1,170 +0,0 @@ -/////////////////////////////////////////////////////////////// -// File: v810_opt.h -// -// Description: Defines used in v810_dis.cpp -// - -#ifndef V810_OPT_H_ -#define V810_OPT_H_ - -#define sign_26(num) ((uint32)sign_x_to_s32(26, num)) -#define sign_16(num) ((uint32)(int16)(num)) -#define sign_14(num) ((uint32)sign_x_to_s32(14, num)) -#define sign_12(num) ((uint32)sign_x_to_s32(12, num)) -#define sign_9(num) ((uint32)sign_x_to_s32(9, num)) -#define sign_8(_value) ((uint32)(int8)(_value)) -#define sign_5(num) ((uint32)sign_x_to_s32(5, num)) - -/////////////////////////////////////////////////////////////////// -// Define Modes -#define AM_I 0x01 -#define AM_II 0x02 -#define AM_III 0x03 -#define AM_IV 0x04 -#define AM_V 0x05 -#define AM_VIa 0x06 // Mode6 form1 -#define AM_VIb 0x0A // Mode6 form2 -#define AM_VII 0x07 -#define AM_VIII 0x08 -#define AM_IX 0x09 -#define AM_BSTR 0x0B // Bit String Instructions -#define AM_FPP 0x0C // Floating Point Instructions -#define AM_UDEF 0x0D // Unknown/Undefined Instructions - -/////////////////////////////////////////////////////////////////// -// Table of Instructions Address Modes - -static const int addr_mode[80] = { - AM_I, AM_I, AM_I, AM_I, AM_I, AM_I, AM_I, AM_I, - AM_I, AM_I, AM_I, AM_I, AM_I, AM_I, AM_I, AM_I, - AM_II, AM_II, AM_II, AM_II, AM_II, AM_II, AM_II, AM_II, - AM_II, AM_IX, AM_IX, AM_UDEF, AM_II, AM_II, AM_II, AM_BSTR, - AM_UDEF, AM_UDEF, AM_UDEF, AM_UDEF, AM_UDEF, AM_UDEF, AM_UDEF, AM_UDEF, - AM_V, AM_V, AM_IV, AM_IV, AM_V, AM_V, AM_V, AM_V, - AM_VIa, AM_VIa, AM_UDEF, AM_VIa, AM_VIb, AM_VIb, AM_UDEF, AM_VIb, - AM_VIa, AM_VIa, AM_VIa, AM_VIa, AM_VIb, AM_VIb, AM_FPP, AM_VIb, - AM_III, AM_III, AM_III, AM_III, AM_III, AM_III, AM_III, AM_III, - AM_III, AM_III, AM_III, AM_III, AM_III, AM_III, AM_III, AM_III -}; -// All instructions greater than 0x50 are undefined (this should not be posible of cource) - - -/////////////////////////////////////////////////////////////////// -// Opcodes for V810 Instruction set -#define MOV 0x00 -#define ADD 0x01 -#define SUB 0x02 -#define CMP 0x03 -#define SHL 0x04 -#define SHR 0x05 -#define JMP 0x06 -#define SAR 0x07 -#define MUL 0x08 -#define DIV 0x09 -#define MULU 0x0A -#define DIVU 0x0B -#define OR 0x0C -#define AND 0x0D -#define XOR 0x0E -#define NOT 0x0F -#define MOV_I 0x10 -#define ADD_I 0x11 -#define SETF 0x12 -#define CMP_I 0x13 -#define SHL_I 0x14 -#define SHR_I 0x15 -#define EI 0x16 -#define SAR_I 0x17 -#define TRAP 0x18 -#define RETI 0x19 -#define HALT 0x1A - //0x1B -#define LDSR 0x1C -#define STSR 0x1D -#define DI 0x1E -#define BSTR 0x1F //Special Bit String Inst - //0x20 - 0x27 // Lost to Branch Instructions -#define MOVEA 0x28 -#define ADDI 0x29 -#define JR 0x2A -#define JAL 0x2B -#define ORI 0x2C -#define ANDI 0x2D -#define XORI 0x2E -#define MOVHI 0x2F -#define LD_B 0x30 -#define LD_H 0x31 - //0x32 -#define LD_W 0x33 -#define ST_B 0x34 -#define ST_H 0x35 - //0x36 -#define ST_W 0x37 -#define IN_B 0x38 -#define IN_H 0x39 -#define CAXI 0x3A -#define IN_W 0x3B -#define OUT_B 0x3C -#define OUT_H 0x3D -#define FPP 0x3E //Special Float Inst -#define OUT_W 0x3F - - -// Branch Instructions ( Extended opcode only for Branch command) -// Common instrcutions commented out - -#define BV 0x40 -#define BL 0x41 -#define BE 0x42 -#define BNH 0x43 -#define BN 0x44 -#define BR 0x45 -#define BLT 0x46 -#define BLE 0x47 -#define BNV 0x48 -#define BNL 0x49 -#define BNE 0x4A -#define BH 0x4B -#define BP 0x4C -#define NOP 0x4D -#define BGE 0x4E -#define BGT 0x4F - -//#define BC 0x41 -//#define BZ 0x42 -//#define BNC 0x49 -//#define BNZ 0x4A - -// Bit String Subopcodes -#define SCH0BSU 0x00 -#define SCH0BSD 0x01 -#define SCH1BSU 0x02 -#define SCH1BSD 0x03 - -#define ORBSU 0x08 -#define ANDBSU 0x09 -#define XORBSU 0x0A -#define MOVBSU 0x0B -#define ORNBSU 0x0C -#define ANDNBSU 0x0D -#define XORNBSU 0x0E -#define NOTBSU 0x0F - - -// Floating Point Subopcodes -#define CMPF_S 0x00 - -#define CVT_WS 0x02 -#define CVT_SW 0x03 -#define ADDF_S 0x04 -#define SUBF_S 0x05 -#define MULF_S 0x06 -#define DIVF_S 0x07 -#define XB 0x08 -#define XH 0x09 -#define REV 0x0A -#define TRNC_SW 0x0B -#define MPYHW 0x0C - -#endif //DEFINE_H - diff --git a/waterbox/vb/vb.cpp b/waterbox/vb/vb.cpp deleted file mode 100644 index b70042ae89..0000000000 --- a/waterbox/vb/vb.cpp +++ /dev/null @@ -1,829 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vb.cpp: -** Copyright (C) 2010-2017 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "vb.h" -#include "../emulibc/emulibc.h" -#include "../emulibc/waterboxcore.h" -#define EXPORT extern "C" ECL_EXPORT - -namespace MDFN_IEN_VB -{ -struct NativeSyncSettings -{ - int InstantReadHack; - int DisableParallax; -}; -struct NativeSettings -{ - int ThreeDeeMode; - int SwapViews; - int AnaglyphPreset; - int AnaglyphCustomLeftColor; - int AnaglyphCustomRightColor; - int NonAnaglyphColor; - int LedOnScale; - int InterlacePrescale; - int SideBySideSeparation; -}; - -static void (*input_callback)(); -static bool lagged; - -enum -{ - ANAGLYPH_PRESET_DISABLED = 0, - ANAGLYPH_PRESET_RED_BLUE, - ANAGLYPH_PRESET_RED_CYAN, - ANAGLYPH_PRESET_RED_ELECTRICCYAN, - ANAGLYPH_PRESET_RED_GREEN, - ANAGLYPH_PRESET_GREEN_MAGENTA, - ANAGLYPH_PRESET_YELLOW_BLUE, -}; - -static const uint32 AnaglyphPreset_Colors[][2] = - { - {0, 0}, - {0xFF0000, 0x0000FF}, - {0xFF0000, 0x00B7EB}, - {0xFF0000, 0x00FFFF}, - {0xFF0000, 0x00FF00}, - {0x00FF00, 0xFF00FF}, - {0xFFFF00, 0x0000FF}, -}; - -static uint32 VB3DMode; - -static uint8 *WRAM = NULL; - -static uint8 *GPRAM = NULL; -static const uint32 GPRAM_Mask = 0xFFFF; - -static uint8 *GPROM = NULL; -static uint32 GPROM_Mask; - -V810 *VB_V810 = NULL; - -VSU *VB_VSU = NULL; -static uint32 VSU_CycleFix; - -static uint8 WCR; - -static int32 next_vip_ts, next_timer_ts, next_input_ts; - -static uint32 IRQ_Asserted; - -static INLINE void RecalcIntLevel(void) -{ - int ilevel = -1; - - for (int i = 4; i >= 0; i--) - { - if (IRQ_Asserted & (1 << i)) - { - ilevel = i; - break; - } - } - - VB_V810->SetInt(ilevel); -} - -void VBIRQ_Assert(int source, bool assert) -{ - assert(source >= 0 && source <= 4); - - IRQ_Asserted &= ~(1 << source); - - if (assert) - IRQ_Asserted |= 1 << source; - - RecalcIntLevel(); -} - -static MDFN_FASTCALL uint8 HWCTRL_Read(v810_timestamp_t ×tamp, uint32 A) -{ - uint8 ret = 0; - - if (A & 0x3) - { - //puts("HWCtrl Bogus Read?"); - return (ret); - } - - switch (A & 0xFF) - { - default: //printf("Unknown HWCTRL Read: %08x\n", A); - break; - - case 0x18: - case 0x1C: - case 0x20: - ret = TIMER_Read(timestamp, A); - break; - - case 0x24: - ret = WCR | 0xFC; - break; - - case 0x10: - case 0x14: - case 0x28: - lagged = false; - if (input_callback) - input_callback(); - ret = VBINPUT_Read(timestamp, A); - break; - } - - return (ret); -} - -static MDFN_FASTCALL void HWCTRL_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V) -{ - if (A & 0x3) - { - puts("HWCtrl Bogus Write?"); - return; - } - - switch (A & 0xFF) - { - default: //printf("Unknown HWCTRL Write: %08x %02x\n", A, V); - break; - - case 0x18: - case 0x1C: - case 0x20: - TIMER_Write(timestamp, A, V); - break; - - case 0x24: - WCR = V & 0x3; - break; - - case 0x10: - case 0x14: - case 0x28: - VBINPUT_Write(timestamp, A, V); - break; - } -} - -uint8 MDFN_FASTCALL MemRead8(v810_timestamp_t ×tamp, uint32 A) -{ - uint8 ret = 0; - A &= (1 << 27) - 1; - - //if((A >> 24) <= 2) - // printf("Read8: %d %08x\n", timestamp, A); - - switch (A >> 24) - { - case 0: - ret = VIP_Read8(timestamp, A); - break; - - case 1: - break; - - case 2: - ret = HWCTRL_Read(timestamp, A); - break; - - case 3: - break; - case 4: - break; - - case 5: - ret = WRAM[A & 0xFFFF]; - break; - - case 6: - if (GPRAM) - ret = GPRAM[A & GPRAM_Mask]; - break; - - case 7: - ret = GPROM[A & GPROM_Mask]; - break; - } - return (ret); -} - -uint16 MDFN_FASTCALL MemRead16(v810_timestamp_t ×tamp, uint32 A) -{ - uint16 ret = 0; - - A &= (1 << 27) - 1; - - //if((A >> 24) <= 2) - // printf("Read16: %d %08x\n", timestamp, A); - - switch (A >> 24) - { - case 0: - ret = VIP_Read16(timestamp, A); - break; - - case 1: - break; - - case 2: - ret = HWCTRL_Read(timestamp, A); - break; - - case 3: - break; - - case 4: - break; - - case 5: - ret = MDFN_de16lsb(&WRAM[A & 0xFFFF]); - break; - - case 6: - if (GPRAM) - ret = MDFN_de16lsb(&GPRAM[A & GPRAM_Mask]); - break; - - case 7: - ret = MDFN_de16lsb(&GPROM[A & GPROM_Mask]); - break; - } - return ret; -} - -void MDFN_FASTCALL MemWrite8(v810_timestamp_t ×tamp, uint32 A, uint8 V) -{ - A &= (1 << 27) - 1; - - //if((A >> 24) <= 2) - // printf("Write8: %d %08x %02x\n", timestamp, A, V); - - switch (A >> 24) - { - case 0: - VIP_Write8(timestamp, A, V); - break; - - case 1: - VB_VSU->Write((timestamp + VSU_CycleFix) >> 2, A, V); - break; - - case 2: - HWCTRL_Write(timestamp, A, V); - break; - - case 3: - break; - - case 4: - break; - - case 5: - WRAM[A & 0xFFFF] = V; - break; - - case 6: - if (GPRAM) - GPRAM[A & GPRAM_Mask] = V; - break; - - case 7: // ROM, no writing allowed! - break; - } -} - -void MDFN_FASTCALL MemWrite16(v810_timestamp_t ×tamp, uint32 A, uint16 V) -{ - A &= (1 << 27) - 1; - - //if((A >> 24) <= 2) - // printf("Write16: %d %08x %04x\n", timestamp, A, V); - - switch (A >> 24) - { - case 0: - VIP_Write16(timestamp, A, V); - break; - - case 1: - VB_VSU->Write((timestamp + VSU_CycleFix) >> 2, A, V); - break; - - case 2: - HWCTRL_Write(timestamp, A, V); - break; - - case 3: - break; - - case 4: - break; - - case 5: - MDFN_en16lsb(&WRAM[A & 0xFFFF], V); - break; - - case 6: - if (GPRAM) - MDFN_en16lsb(&GPRAM[A & GPRAM_Mask], V); - break; - - case 7: // ROM, no writing allowed! - break; - } -} - -static void FixNonEvents(void) -{ - if (next_vip_ts & 0x40000000) - next_vip_ts = VB_EVENT_NONONO; - - if (next_timer_ts & 0x40000000) - next_timer_ts = VB_EVENT_NONONO; - - if (next_input_ts & 0x40000000) - next_input_ts = VB_EVENT_NONONO; -} - -static void EventReset(void) -{ - next_vip_ts = VB_EVENT_NONONO; - next_timer_ts = VB_EVENT_NONONO; - next_input_ts = VB_EVENT_NONONO; -} - -static INLINE int32 CalcNextTS(void) -{ - int32 next_timestamp = next_vip_ts; - - if (next_timestamp > next_timer_ts) - next_timestamp = next_timer_ts; - - if (next_timestamp > next_input_ts) - next_timestamp = next_input_ts; - - return (next_timestamp); -} - -static void RebaseTS(const v810_timestamp_t timestamp) -{ - //printf("Rebase: %08x %08x %08x\n", timestamp, next_vip_ts, next_timer_ts); - - assert(next_vip_ts > timestamp); - assert(next_timer_ts > timestamp); - assert(next_input_ts > timestamp); - - next_vip_ts -= timestamp; - next_timer_ts -= timestamp; - next_input_ts -= timestamp; -} - -void VB_SetEvent(const int type, const v810_timestamp_t next_timestamp) -{ - //assert(next_timestamp > VB_V810->v810_timestamp); - - if (type == VB_EVENT_VIP) - next_vip_ts = next_timestamp; - else if (type == VB_EVENT_TIMER) - next_timer_ts = next_timestamp; - else if (type == VB_EVENT_INPUT) - next_input_ts = next_timestamp; - - if (next_timestamp < VB_V810->GetEventNT()) - VB_V810->SetEventNT(next_timestamp); -} - -static int32 MDFN_FASTCALL EventHandler(const v810_timestamp_t timestamp) -{ - if (timestamp >= next_vip_ts) - next_vip_ts = VIP_Update(timestamp); - - if (timestamp >= next_timer_ts) - next_timer_ts = TIMER_Update(timestamp); - - if (timestamp >= next_input_ts) - next_input_ts = VBINPUT_Update(timestamp); - - return (CalcNextTS()); -} - -// Called externally from debug.cpp in some cases. -void ForceEventUpdates(const v810_timestamp_t timestamp) -{ - next_vip_ts = VIP_Update(timestamp); - next_timer_ts = TIMER_Update(timestamp); - next_input_ts = VBINPUT_Update(timestamp); - - VB_V810->SetEventNT(CalcNextTS()); - //printf("FEU: %d %d %d\n", next_vip_ts, next_timer_ts, next_input_ts); -} - -static void VB_Power(void) -{ - memset(WRAM, 0, 65536); - - VIP_Power(); - VB_VSU->Power(); - TIMER_Power(); - VBINPUT_Power(); - - EventReset(); - IRQ_Asserted = 0; - RecalcIntLevel(); - VB_V810->Reset(); - - VSU_CycleFix = 0; - WCR = 0; - - ForceEventUpdates(0); //VB_V810->v810_timestamp); -} - -/*struct VB_HeaderInfo -{ - char game_title[256]; - uint32 game_code; - uint16 manf_code; - uint8 version; -};*/ - -/*static void ReadHeader(const uint8 *const rom_data, const uint64 rom_size, VB_HeaderInfo *hi) -{ - iconv_t sjis_ict = iconv_open("UTF-8", "shift_jis"); - - if (sjis_ict != (iconv_t)-1) - { - char *in_ptr, *out_ptr; - size_t ibl, obl; - - ibl = 20; - obl = sizeof(hi->game_title) - 1; - - in_ptr = (char *)rom_data + (0xFFFFFDE0 & (rom_size - 1)); - out_ptr = hi->game_title; - - iconv(sjis_ict, (ICONV_CONST char **)&in_ptr, &ibl, &out_ptr, &obl); - iconv_close(sjis_ict); - - *out_ptr = 0; - - MDFN_zapctrlchars(hi->game_title); - MDFN_trim(hi->game_title); - } - else - hi->game_title[0] = 0; - - hi->game_code = MDFN_de32lsb(rom_data + (0xFFFFFDFB & (rom_size - 1))); - hi->manf_code = MDFN_de16lsb(rom_data + (0xFFFFFDF9 & (rom_size - 1))); - hi->version = rom_data[0xFFFFFDFF & (rom_size - 1)]; -}*/ - -void VB_ExitLoop(void) -{ - VB_V810->Exit(); -} - -/*MDFNGI EmulatedVB = - { - - PortInfo, - Load, - TestMagic, - NULL, - NULL, - CloseGame, - - SetLayerEnableMask, - NULL, // Layer names, null-delimited - - NULL, - NULL, - - VIP_CPInfo, - 1 << 0, - - CheatInfo_Empty, - - false, - StateAction, - Emulate, - NULL, - VBINPUT_SetInput, - NULL, - DoSimpleCommand, - NULL, - VBSettings, - MDFN_MASTERCLOCK_FIXED(VB_MASTER_CLOCK), - 0, - false, // Multires possible? - - 0, // lcm_width - 0, // lcm_height - NULL, // Dummy - - 384, // Nominal width - 224, // Nominal height - - 384, // Framebuffer width - 256, // Framebuffer height - - 2, // Number of output sound channels -};*/ -} - -using namespace MDFN_IEN_VB; - -EXPORT int Load(const uint8 *rom, int length, const NativeSyncSettings *syncSettings) -{ - const uint64 rom_size = length; - V810_Emu_Mode cpu_mode = V810_EMU_MODE_ACCURATE; - - if (rom_size != round_up_pow2(rom_size)) - { - return 0; - // throw MDFN_Error(0, _("VB ROM image size is not a power of 2.")); - } - - if (rom_size < 256) - { - return 0; - //throw MDFN_Error(0, _("VB ROM image size is too small.")); - } - - if (rom_size > (1 << 24)) - { - return 0; - //throw MDFN_Error(0, _("VB ROM image size is too large.")); - } - - VB_V810 = new V810(); - VB_V810->Init(cpu_mode, true); - - VB_V810->SetMemReadHandlers(MemRead8, MemRead16, NULL); - VB_V810->SetMemWriteHandlers(MemWrite8, MemWrite16, NULL); - - VB_V810->SetIOReadHandlers(MemRead8, MemRead16, NULL); - VB_V810->SetIOWriteHandlers(MemWrite8, MemWrite16, NULL); - - for (int i = 0; i < 256; i++) - { - VB_V810->SetMemReadBus32(i, false); - VB_V810->SetMemWriteBus32(i, false); - } - - std::vector Map_Addresses; - - for (uint64 A = 0; A < 1ULL << 32; A += (1 << 27)) - { - for (uint64 sub_A = 5 << 24; sub_A < (6 << 24); sub_A += 65536) - { - Map_Addresses.push_back(A + sub_A); - } - } - - WRAM = VB_V810->SetFastMap(alloc_plain, &Map_Addresses[0], 65536, Map_Addresses.size(), "WRAM"); - Map_Addresses.clear(); - - // Round up the ROM size to 65536(we mirror it a little later) - GPROM_Mask = (rom_size < 65536) ? (65536 - 1) : (rom_size - 1); - - for (uint64 A = 0; A < 1ULL << 32; A += (1 << 27)) - { - for (uint64 sub_A = 7 << 24; sub_A < (8 << 24); sub_A += GPROM_Mask + 1) - { - Map_Addresses.push_back(A + sub_A); - //printf("%08x\n", (uint32)(A + sub_A)); - } - } - - GPROM = VB_V810->SetFastMap(alloc_sealed, &Map_Addresses[0], GPROM_Mask + 1, Map_Addresses.size(), "Cart ROM"); - Map_Addresses.clear(); - - memcpy(GPROM, rom, rom_size); - - // Mirror ROM images < 64KiB to 64KiB - for (uint64 i = rom_size; i < 65536; i += rom_size) - { - memcpy(GPROM + i, GPROM, rom_size); - } - - /*VB_HeaderInfo hinfo; - - ReadHeader(GPROM, rom_size, &hinfo); - - MDFN_printf(_("Title: %s\n"), hinfo.game_title); - MDFN_printf(_("Game ID Code: %u\n"), hinfo.game_code); - MDFN_printf(_("Manufacturer Code: %d\n"), hinfo.manf_code); - MDFN_printf(_("Version: %u\n"), hinfo.version); - - MDFN_printf(_("ROM: %uKiB\n"), (unsigned)(rom_size / 1024)); - MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str());*/ - - /*MDFN_printf("\n"); - - MDFN_printf(_("V810 Emulation Mode: %s\n"), (cpu_mode == V810_EMU_MODE_ACCURATE) ? _("Accurate") : _("Fast"));*/ - - for (uint64 A = 0; A < 1ULL << 32; A += (1 << 27)) - { - for (uint64 sub_A = 6 << 24; sub_A < (7 << 24); sub_A += GPRAM_Mask + 1) - { - //printf("GPRAM: %08x\n", A + sub_A); - Map_Addresses.push_back(A + sub_A); - } - } - - GPRAM = VB_V810->SetFastMap(alloc_plain, &Map_Addresses[0], GPRAM_Mask + 1, Map_Addresses.size(), "Cart RAM"); - Map_Addresses.clear(); - - memset(GPRAM, 0, GPRAM_Mask + 1); - - VIP_Init(); - VB_VSU = new VSU(); - VBINPUT_Init(); - - VB3DMode = 0; - uint32 prescale = 1; - uint32 sbs_separation = 0; - bool reverse = false; - - VIP_Set3DMode(VB3DMode, reverse, prescale, sbs_separation); - - VIP_SetParallaxDisable(syncSettings->DisableParallax); - - { - auto presetColor = 1; - - uint32 lcolor = 0xff0000; - uint32 rcolor = 0x00ff00; - - if (presetColor != ANAGLYPH_PRESET_DISABLED) - { - lcolor = AnaglyphPreset_Colors[presetColor][0]; - rcolor = AnaglyphPreset_Colors[presetColor][1]; - } - VIP_SetAnaglyphColors(lcolor, rcolor); - VIP_SetDefaultColor(0xffffff); - } - - VBINPUT_SetInstantReadHack(syncSettings->InstantReadHack); - - VIP_SetLEDOnScale(1750 / 1000.0); - - VB_Power(); - - /*switch (VB3DMode) - { - default: - break; - - case VB3DMODE_VLI: - MDFNGameInfo->nominal_width = 768 * prescale; - MDFNGameInfo->nominal_height = 224; - MDFNGameInfo->fb_width = 768 * prescale; - MDFNGameInfo->fb_height = 224; - break; - - case VB3DMODE_HLI: - MDFNGameInfo->nominal_width = 384; - MDFNGameInfo->nominal_height = 448 * prescale; - MDFNGameInfo->fb_width = 384; - MDFNGameInfo->fb_height = 448 * prescale; - break; - - case VB3DMODE_CSCOPE: - MDFNGameInfo->nominal_width = 512; - MDFNGameInfo->nominal_height = 384; - MDFNGameInfo->fb_width = 512; - MDFNGameInfo->fb_height = 384; - break; - - case VB3DMODE_SIDEBYSIDE: - MDFNGameInfo->nominal_width = 384 * 2 + sbs_separation; - MDFNGameInfo->nominal_height = 224; - MDFNGameInfo->fb_width = 384 * 2 + sbs_separation; - MDFNGameInfo->fb_height = 224; - break; - } - MDFNGameInfo->lcm_width = MDFNGameInfo->fb_width; - MDFNGameInfo->lcm_height = MDFNGameInfo->fb_height;*/ - - VB_VSU->SetSoundRate(44100); - - return 1; -} - -EXPORT void SetSettings(const NativeSettings *settings) -{ - VB3DMode = settings->ThreeDeeMode; - uint32 prescale = settings->InterlacePrescale; - uint32 sbs_separation = settings->SideBySideSeparation; - bool reverse = settings->SwapViews; - - VIP_Set3DMode(VB3DMode, reverse, prescale, sbs_separation); - - { - auto presetColor = settings->AnaglyphPreset; - - uint32 lcolor = settings->AnaglyphCustomLeftColor; - uint32 rcolor = settings->AnaglyphCustomRightColor; - - if (presetColor != ANAGLYPH_PRESET_DISABLED) - { - lcolor = AnaglyphPreset_Colors[presetColor][0]; - rcolor = AnaglyphPreset_Colors[presetColor][1]; - } - VIP_SetAnaglyphColors(lcolor, rcolor); - VIP_SetDefaultColor(settings->NonAnaglyphColor); - } - - VIP_SetLEDOnScale(settings->LedOnScale / 1000.0); -} - -EXPORT void GetMemoryAreas(MemoryArea *m) -{ - m[0].Data = WRAM; - m[0].Name = "WRAM"; - m[0].Size = 65536; - m[0].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_PRIMARY | MEMORYAREA_FLAGS_WORDSIZE4; - - m[1].Data = GPRAM; - m[1].Name = "CARTRAM"; - m[1].Size = GPRAM_Mask + 1; - m[1].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_SAVERAMMABLE | MEMORYAREA_FLAGS_WORDSIZE4; - - m[2].Data = GPROM; - m[2].Name = "ROM"; - m[2].Size = GPROM_Mask + 1; - m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE4; -} - -EXPORT void FrameAdvance(MyFrameInfo *frame) -{ - v810_timestamp_t v810_timestamp; - lagged = true; - - VBINPUT_Frame(&frame->Buttons); - - VIP_StartFrame(frame); - - v810_timestamp = VB_V810->Run(EventHandler); - - FixNonEvents(); - ForceEventUpdates(v810_timestamp); - - frame->Samples = VB_VSU->EndFrame((v810_timestamp + VSU_CycleFix) >> 2, frame->SoundBuffer, 8192); - - VSU_CycleFix = (v810_timestamp + VSU_CycleFix) & 3; - - frame->Cycles = v810_timestamp; - frame->Lagged = lagged; - - TIMER_ResetTS(); - VBINPUT_ResetTS(); - VIP_ResetTS(); - - RebaseTS(v810_timestamp); - - VB_V810->ResetTS(0); -} - -EXPORT void PredictFrameSize(MyFrameInfo *frame) -{ - VIP_CalcFrameSize(frame); -} - -EXPORT void HardReset() -{ - VB_Power(); -} - -EXPORT void SetInputCallback(void (*callback)()) -{ - input_callback = callback; -} - -int main() -{ - return 0; -} diff --git a/waterbox/vb/vb.h b/waterbox/vb/vb.h deleted file mode 100644 index a73c5dd95f..0000000000 --- a/waterbox/vb/vb.h +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vb.h: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; - -#define MDFN_FASTCALL -#define INLINE inline -#define MDFN_COLD -#define NO_INLINE -//#define MDFN_ASSUME_ALIGNED(p, align) ((decltype(p))__builtin_assume_aligned((p), (align))) -#define MDFN_ASSUME_ALIGNED(p, align) (p) -#define trio_snprintf snprintf -#define TRUE true -#define FALSE false -#ifndef __alignas_is_defined -#define alignas(p) -#endif - -struct MyFrameInfo -{ - uint32_t* VideoBuffer; - int16_t* SoundBuffer; - int64_t Cycles; - int32_t Width; - int32_t Height; - int32_t Samples; - int32_t Lagged; - int32_t Buttons; -}; - -#include "endian.h" -#include "math_ops.h" -#include "blip/Blip_Buffer.h" -#include "v810/v810_fp_ops.h" -#include "v810/v810_cpu.h" - -#include "git.h" - -#include "vsu.h" -#include "vip.h" -#include "timer.h" -#include "input.h" - - -namespace MDFN_IEN_VB -{ - -enum -{ - VB3DMODE_ANAGLYPH = 0, - VB3DMODE_CSCOPE = 1, - VB3DMODE_SIDEBYSIDE = 2, - VB3DMODE_OVERUNDER = 3, - VB3DMODE_VLI, - VB3DMODE_HLI, - VB3DMODE_ONLYLEFT, - VB3DMODE_ONLYRIGHT -}; - -#define VB_MASTER_CLOCK 20000000.0 - -enum -{ - VB_EVENT_VIP = 0, - VB_EVENT_TIMER, - VB_EVENT_INPUT, - // VB_EVENT_COMM -}; - -#define VB_EVENT_NONONO 0x7fffffff - -void VB_SetEvent(const int type, const v810_timestamp_t next_timestamp); - -#define VBIRQ_SOURCE_INPUT 0 -#define VBIRQ_SOURCE_TIMER 1 -#define VBIRQ_SOURCE_EXPANSION 2 -#define VBIRQ_SOURCE_COMM 3 -#define VBIRQ_SOURCE_VIP 4 - -void VBIRQ_Assert(int source, bool assert); - -void VB_ExitLoop(void); - -void ForceEventUpdates(const v810_timestamp_t timestamp); - -uint8 MDFN_FASTCALL MemRead8(v810_timestamp_t ×tamp, uint32 A); -uint16 MDFN_FASTCALL MemRead16(v810_timestamp_t ×tamp, uint32 A); - -void MDFN_FASTCALL MemWrite8(v810_timestamp_t ×tamp, uint32 A, uint8 V); -void MDFN_FASTCALL MemWrite16(v810_timestamp_t ×tamp, uint32 A, uint16 V); -} diff --git a/waterbox/vb/vip.cpp b/waterbox/vb/vip.cpp deleted file mode 100644 index 76c8a40964..0000000000 --- a/waterbox/vb/vip.cpp +++ /dev/null @@ -1,1425 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vip.cpp: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "vb.h" -#include -#include "../emulibc/emulibc.h" - -#define VIP_DBGMSG(format, ...) \ - { \ - } -//#define VIP_DBGMSG(format, ...) printf(format "\n", ## __VA_ARGS__) - -namespace MDFN_IEN_VB -{ - -static uint8 FB[2][2][0x6000]; -static uint16 CHR_RAM[0x8000 / sizeof(uint16)]; -static uint16 DRAM[0x20000 / sizeof(uint16)]; - -#define INT_SCAN_ERR 0x0001 -#define INT_LFB_END 0x0002 -#define INT_RFB_END 0x0004 -#define INT_GAME_START 0x0008 -#define INT_FRAME_START 0x0010 - -#define INT_SB_HIT 0x2000 -#define INT_XP_END 0x4000 -#define INT_TIME_ERR 0x8000 - -static uint16 InterruptPending; -static uint16 InterruptEnable; - -static uint8 BRTA, BRTB, BRTC, REST; -static uint8 Repeat; - -static void CopyFBColumnToTarget_Anaglyph(void) NO_INLINE; -static void CopyFBColumnToTarget_AnaglyphSlow(void) NO_INLINE; -static void CopyFBColumnToTarget_CScope(void) NO_INLINE; -static void CopyFBColumnToTarget_SideBySide(void) NO_INLINE; -static void CopyFBColumnToTarget_VLI(void) NO_INLINE; -static void CopyFBColumnToTarget_HLI(void) NO_INLINE; -static void CopyFBColumnToTarget_OnlyLeftRight(void) NO_INLINE; -static void (*CopyFBColumnToTarget)(void) = NULL; -static float VBLEDOnScale; -static uint32 VB3DMode; -static uint32 VB3DReverse; -static uint32 VBPrescale; -static uint32 VBSBS_Separation; -static uint32 HLILUT[256]; -static uint32 ColorLUT[2][256]; -static int32 BrightnessCache[4]; -static uint32 BrightCLUT[2][4]; - -static float ECL_INVISIBLE ColorLUTNoGC[2][256][3]; -static uint32 ECL_INVISIBLE AnaSlowColorLUT[256][256]; - -static bool VidSettingsDirty; -static bool ParallaxDisabled; -static uint32 Anaglyph_Colors[2]; -static uint32 Default_Color; - -static void MakeColorLUT() -{ - for (int lr = 0; lr < 2; lr++) - { - for (int i = 0; i < 256; i++) - { - float r, g, b; - uint32 modcolor_prime; - - if (VB3DMode == VB3DMODE_ANAGLYPH) - modcolor_prime = Anaglyph_Colors[lr ^ VB3DReverse]; - else - modcolor_prime = Default_Color; - - r = g = b = std::min(1.0, i * VBLEDOnScale / 255.0); - - // Modulate. - r = r * pow(((modcolor_prime >> 16) & 0xFF) / 255.0, 2.2 / 1.0); - g = g * pow(((modcolor_prime >> 8) & 0xFF) / 255.0, 2.2 / 1.0); - b = b * pow(((modcolor_prime >> 0) & 0xFF) / 255.0, 2.2 / 1.0); - - ColorLUTNoGC[lr][i][0] = r; - ColorLUTNoGC[lr][i][1] = g; - ColorLUTNoGC[lr][i][2] = b; - - // Apply gamma correction - const float r_prime = pow(r, 1.0 / 2.2); - const float g_prime = pow(g, 1.0 / 2.2); - const float b_prime = pow(b, 1.0 / 2.2); - - ColorLUT[lr][i] = (int)(b_prime * 255) & 0xff | (int)(g_prime * 255) << 8 & 0xff00 | (int)(r_prime * 255) << 16 & 0xff0000 | 0xff000000; - } - } - - // Anaglyph slow-mode LUT calculation - for (int l_b = 0; l_b < 256; l_b++) - { - for (int r_b = 0; r_b < 256; r_b++) - { - float r, g, b; - float r_prime, g_prime, b_prime; - - r = ColorLUTNoGC[0][l_b][0] + ColorLUTNoGC[1][r_b][0]; - g = ColorLUTNoGC[0][l_b][1] + ColorLUTNoGC[1][r_b][1]; - b = ColorLUTNoGC[0][l_b][2] + ColorLUTNoGC[1][r_b][2]; - - if (r > 1.0) - r = 1.0; - if (g > 1.0) - g = 1.0; - if (b > 1.0) - b = 1.0; - - r_prime = pow(r, 1.0 / 2.2); - g_prime = pow(g, 1.0 / 2.2); - b_prime = pow(b, 1.0 / 2.2); - - AnaSlowColorLUT[l_b][r_b] = (int)(b_prime * 255) & 0xff | (int)(g_prime * 255) << 8 & 0xff00 | (int)(r_prime * 255) << 16 & 0xff0000 | 0xff000000; - } - } -} - -static void RecalcBrightnessCache(void) -{ - static const int32 MaxTime = 255; - int32 CumulativeTime = (BRTA + 1 + BRTB + 1 + BRTC + 1 + REST + 1) + 1; - - //printf("BRTA: %d, BRTB: %d, BRTC: %d, Rest: %d --- %d\n", BRTA, BRTB, BRTC, REST, BRTA + 1 + BRTB + 1 + BRTC); - - BrightnessCache[0] = 0; - BrightnessCache[1] = 0; - BrightnessCache[2] = 0; - BrightnessCache[3] = 0; - - for (int i = 0; i < Repeat + 1; i++) - { - int32 btemp[4]; - - if ((i * CumulativeTime) >= MaxTime) - break; - - btemp[1] = (i * CumulativeTime) + BRTA; - if (btemp[1] > MaxTime) - btemp[1] = MaxTime; - btemp[1] -= (i * CumulativeTime); - if (btemp[1] < 0) - btemp[1] = 0; - - btemp[2] = (i * CumulativeTime) + BRTA + 1 + BRTB; - if (btemp[2] > MaxTime) - btemp[2] = MaxTime; - btemp[2] -= (i * CumulativeTime) + BRTA + 1; - if (btemp[2] < 0) - btemp[2] = 0; - - //btemp[3] = (i * CumulativeTime) + BRTA + 1 + BRTB + 1 + BRTC; - //if(btemp[3] > MaxTime) - // btemp[3] = MaxTime; - //btemp[3] -= (i * CumulativeTime); - //if(btemp[3] < 0) - // btemp[3] = 0; - - btemp[3] = (i * CumulativeTime) + BRTA + BRTB + BRTC + 1; - if (btemp[3] > MaxTime) - btemp[3] = MaxTime; - btemp[3] -= (i * CumulativeTime) + 1; - if (btemp[3] < 0) - btemp[3] = 0; - - BrightnessCache[1] += btemp[1]; - BrightnessCache[2] += btemp[2]; - BrightnessCache[3] += btemp[3]; - } - - //printf("BC: %d %d %d %d\n", BrightnessCache[0], BrightnessCache[1], BrightnessCache[2], BrightnessCache[3]); - - for (int lr = 0; lr < 2; lr++) - for (int i = 0; i < 4; i++) - { - BrightCLUT[lr][i] = ColorLUT[lr][BrightnessCache[i]]; - //printf("%d %d, %08x\n", lr, i, BrightCLUT[lr][i]); - } -} - -static void Recalc3DModeStuff(bool non_rgb_output = false) -{ - switch (VB3DMode) - { - default: - if (((Anaglyph_Colors[0] & 0xFF) && (Anaglyph_Colors[1] & 0xFF)) || - ((Anaglyph_Colors[0] & 0xFF00) && (Anaglyph_Colors[1] & 0xFF00)) || - ((Anaglyph_Colors[0] & 0xFF0000) && (Anaglyph_Colors[1] & 0xFF0000)) || - non_rgb_output) - { - CopyFBColumnToTarget = CopyFBColumnToTarget_AnaglyphSlow; - } - else - CopyFBColumnToTarget = CopyFBColumnToTarget_Anaglyph; - break; - - case VB3DMODE_CSCOPE: - CopyFBColumnToTarget = CopyFBColumnToTarget_CScope; - break; - - case VB3DMODE_SIDEBYSIDE: - CopyFBColumnToTarget = CopyFBColumnToTarget_SideBySide; - break; - - case VB3DMODE_VLI: - CopyFBColumnToTarget = CopyFBColumnToTarget_VLI; - break; - - case VB3DMODE_HLI: - CopyFBColumnToTarget = CopyFBColumnToTarget_HLI; - break; - - case VB3DMODE_ONLYLEFT: - case VB3DMODE_ONLYRIGHT: - CopyFBColumnToTarget = CopyFBColumnToTarget_OnlyLeftRight; - break; - } - RecalcBrightnessCache(); -} - -void VIP_Set3DMode(uint32 mode, bool reverse, uint32 prescale, uint32 sbs_separation) -{ - VB3DMode = mode; - VB3DReverse = reverse ? 1 : 0; - VBPrescale = prescale; - VBSBS_Separation = sbs_separation; - - VidSettingsDirty = true; - - for (uint32 p = 0; p < 256; p++) - { - uint32 v; - uint8 s[4]; - - s[0] = (p >> 0) & 0x3; - s[1] = (p >> 2) & 0x3; - s[2] = (p >> 4) & 0x3; - s[3] = (p >> 6) & 0x3; - - v = 0; - for (unsigned int i = 0, shifty = 0; i < 4; i++) - { - for (unsigned int ps = 0; ps < prescale; ps++) - { - v |= s[i] << shifty; - shifty += 2; - } - } - - HLILUT[p] = v; - } -} - -void VIP_SetParallaxDisable(bool disabled) -{ - ParallaxDisabled = disabled; -} - -void VIP_SetDefaultColor(uint32 default_color) -{ - Default_Color = default_color; - - VidSettingsDirty = true; -} - -void VIP_SetLEDOnScale(float coeff) -{ - VBLEDOnScale = coeff; -} - -void VIP_SetAnaglyphColors(uint32 lcolor, uint32 rcolor) -{ - Anaglyph_Colors[0] = lcolor; - Anaglyph_Colors[1] = rcolor; - - VidSettingsDirty = true; -} - -static uint16 FRMCYC; - -static uint16 DPCTRL; -static bool DisplayActive; - -#define XPCTRL_XP_RST 0x0001 -#define XPCTRL_XP_EN 0x0002 -static uint16 XPCTRL; -static uint16 SBCMP; // Derived from XPCTRL - -static uint16 SPT[4]; // SPT0~SPT3, 5f848~5f84e -static uint16 GPLT[4]; -static uint8 GPLT_Cache[4][4]; - -static INLINE void Recalc_GPLT_Cache(int which) -{ - for (int i = 0; i < 4; i++) - GPLT_Cache[which][i] = (GPLT[which] >> (i * 2)) & 3; -} - -static uint16 JPLT[4]; -static uint8 JPLT_Cache[4][4]; - -static INLINE void Recalc_JPLT_Cache(int which) -{ - for (int i = 0; i < 4; i++) - JPLT_Cache[which][i] = (JPLT[which] >> (i * 2)) & 3; -} - -static uint16 BKCOL; - -// -// -// -static int32 CalcNextEvent(void); - -static int32 last_ts; - -static uint32 Column; -static int32 ColumnCounter; - -static int32 DisplayRegion; -static bool DisplayFB; - -static int32 GameFrameCounter; - -static int32 DrawingCounter; -static bool DrawingActive; -static bool DrawingFB; -static uint32 DrawingBlock; -static int32 SB_Latch; -static int32 SBOUT_InactiveTime; - -//static uint8 CTA_L, CTA_R; - -static void CheckIRQ(void) -{ - VBIRQ_Assert(VBIRQ_SOURCE_VIP, (bool)(InterruptEnable & InterruptPending)); - -#if 0 - printf("%08x\n", InterruptEnable & InterruptPending); - if((bool)(InterruptEnable & InterruptPending)) - puts("IRQ asserted"); - else - puts("IRQ not asserted"); -#endif -} - -void VIP_Init(void) -{ - ParallaxDisabled = false; - Anaglyph_Colors[0] = 0xFF0000; - Anaglyph_Colors[1] = 0x0000FF; - VB3DMode = VB3DMODE_ANAGLYPH; - Default_Color = 0xFFFFFF; - VB3DReverse = 0; - VBPrescale = 1; - VBSBS_Separation = 0; - - VidSettingsDirty = true; -} - -void VIP_Power(void) -{ - Repeat = 0; - SB_Latch = 0; - SBOUT_InactiveTime = -1; - last_ts = 0; - - Column = 0; - ColumnCounter = 259; - - DisplayRegion = 0; - DisplayFB = 0; - - GameFrameCounter = 0; - - DrawingCounter = 0; - DrawingActive = false; - DrawingFB = 0; - DrawingBlock = 0; - - DPCTRL = 2; - DisplayActive = false; - - memset(FB, 0, 0x6000 * 2 * 2); - memset(CHR_RAM, 0, 0x8000); - memset(DRAM, 0, 0x20000); - - InterruptPending = 0; - InterruptEnable = 0; - - BRTA = 0; - BRTB = 0; - BRTC = 0; - REST = 0; - - FRMCYC = 0; - - XPCTRL = 0; - SBCMP = 0; - - for (int i = 0; i < 4; i++) - { - SPT[i] = 0; - GPLT[i] = 0; - JPLT[i] = 0; - - Recalc_GPLT_Cache(i); - Recalc_JPLT_Cache(i); - } - - BKCOL = 0; -} - -static INLINE uint16 ReadRegister(int32 ×tamp, uint32 A) -{ - uint16 ret = 0; //0xFFFF; - - if (A & 1) - VIP_DBGMSG("Misaligned VIP Read: %08x", A); - - switch (A & 0xFE) - { - default: - VIP_DBGMSG("Unknown VIP register read: %08x", A); - break; - - case 0x00: - ret = InterruptPending; - break; - - case 0x02: - ret = InterruptEnable; - break; - - case 0x20: //printf("Read DPSTTS at %d\n", timestamp); - ret = DPCTRL & 0x702; - if ((DisplayRegion & 1) && DisplayActive) - { - unsigned int DPBSY = 1 << ((DisplayRegion >> 1) & 1); - - if (DisplayFB) - DPBSY <<= 2; - - ret |= DPBSY << 2; - } - //if(!(DisplayRegion & 1)) // FIXME? (Had to do it this way for Galactic Pinball...) - ret |= 1 << 6; - break; - - // Note: Upper bits of BRTA, BRTB, BRTC, and REST(?) are 0 when read(on real hardware) - case 0x24: - ret = BRTA; - break; - - case 0x26: - ret = BRTB; - break; - - case 0x28: - ret = BRTC; - break; - - case 0x2A: - ret = REST; - break; - - case 0x30: - ret = 0xFFFF; - break; - - case 0x40: - ret = XPCTRL & 0x2; - if (DrawingActive) - { - ret |= (1 + DrawingFB) << 2; - } - if (timestamp < SBOUT_InactiveTime) - { - ret |= 0x8000; - ret |= /*DrawingBlock*/ SB_Latch << 8; - } - break; // XPSTTS, read-only - - case 0x44: - ret = 2; // VIP version. 2 is a known valid version, while the validity of other numbers is unknown, so we'll just go with 2. - break; - - case 0x48: - case 0x4a: - case 0x4c: - case 0x4e: - ret = SPT[(A >> 1) & 3]; - break; - - case 0x60: - case 0x62: - case 0x64: - case 0x66: - ret = GPLT[(A >> 1) & 3]; - break; - - case 0x68: - case 0x6a: - case 0x6c: - case 0x6e: - ret = JPLT[(A >> 1) & 3]; - break; - - case 0x70: - ret = BKCOL; - break; - } - - return (ret); -} - -static INLINE void WriteRegister(int32 ×tamp, uint32 A, uint16 V) -{ - if (A & 1) - VIP_DBGMSG("Misaligned VIP Write: %08x %04x", A, V); - - switch (A & 0xFE) - { - default: - VIP_DBGMSG("Unknown VIP register write: %08x %04x", A, V); - break; - - case 0x00: - break; // Interrupt pending, read-only - - case 0x02: - { - InterruptEnable = V & 0xE01F; - - VIP_DBGMSG("Interrupt Enable: %04x", V); - - if (V & 0x2000) - VIP_DBGMSG("Warning: VIP SB Hit Interrupt enable: %04x\n", V); - CheckIRQ(); - } - break; - - case 0x04: - InterruptPending &= ~V; - CheckIRQ(); - break; - - case 0x20: - break; // Display control, read-only. - - case 0x22: - DPCTRL = V & (0x703); // Display-control, write-only - if (V & 1) - { - DisplayActive = false; - InterruptPending &= ~(INT_TIME_ERR | INT_FRAME_START | INT_GAME_START | INT_RFB_END | INT_LFB_END | INT_SCAN_ERR); - CheckIRQ(); - } - break; - - case 0x24: - BRTA = V & 0xFF; // BRTA - RecalcBrightnessCache(); - break; - - case 0x26: - BRTB = V & 0xFF; // BRTB - RecalcBrightnessCache(); - break; - - case 0x28: - BRTC = V & 0xFF; // BRTC - RecalcBrightnessCache(); - break; - - case 0x2A: - REST = V & 0xFF; // REST - RecalcBrightnessCache(); - break; - - case 0x2E: - FRMCYC = V & 0xF; // FRMCYC, write-only? - break; - - case 0x30: - break; // CTA, read-only( - - case 0x40: - break; // XPSTTS, read-only - - case 0x42: - XPCTRL = V & 0x0002; // XPCTRL, write-only - SBCMP = (V >> 8) & 0x1F; - - if (V & 1) - { - VIP_DBGMSG("XPRST"); - DrawingActive = 0; - DrawingCounter = 0; - InterruptPending &= ~(INT_SB_HIT | INT_XP_END | INT_TIME_ERR); - CheckIRQ(); - } - break; - - case 0x44: - break; // Version Control, read-only? - - case 0x48: - case 0x4a: - case 0x4c: - case 0x4e: - SPT[(A >> 1) & 3] = V & 0x3FF; - break; - - case 0x60: - case 0x62: - case 0x64: - case 0x66: - GPLT[(A >> 1) & 3] = V & 0xFC; - Recalc_GPLT_Cache((A >> 1) & 3); - break; - - case 0x68: - case 0x6a: - case 0x6c: - case 0x6e: - JPLT[(A >> 1) & 3] = V & 0xFC; - Recalc_JPLT_Cache((A >> 1) & 3); - break; - - case 0x70: - BKCOL = V & 0x3; - break; - } -} - -// -// Don't update the VIP state on reads/writes, the event system will update it with enough precision as far as VB software cares. -// - -MDFN_FASTCALL uint8 VIP_Read8(int32 ×tamp, uint32 A) -{ - uint8 ret = 0; //0xFF; - - //VIP_Update(timestamp); - - switch (A >> 16) - { - case 0x0: - case 0x1: - if ((A & 0x7FFF) >= 0x6000) - { - ret = ne16_rbo_le(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000)); - } - else - { - ret = FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF]; - } - break; - - case 0x2: - case 0x3: - ret = ne16_rbo_le(DRAM, A & 0x1FFFF); - break; - - case 0x4: - case 0x5: - if (A >= 0x5E000) - ret = ReadRegister(timestamp, A); - else - VIP_DBGMSG("Unknown VIP Read: %08x", A); - break; - - case 0x6: - break; - - case 0x7: - if (A >= 0x8000) - { - ret = ne16_rbo_le(CHR_RAM, A & 0x7FFF); - } - else - VIP_DBGMSG("Unknown VIP Read: %08x", A); - break; - - default: - VIP_DBGMSG("Unknown VIP Read: %08x", A); - break; - } - - //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); - - return (ret); -} - -MDFN_FASTCALL uint16 VIP_Read16(int32 ×tamp, uint32 A) -{ - uint16 ret = 0; //0xFFFF; - - //VIP_Update(timestamp); - - switch (A >> 16) - { - case 0x0: - case 0x1: - if ((A & 0x7FFF) >= 0x6000) - { - ret = ne16_rbo_le(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000)); - } - else - { - ret = MDFN_de16lsb(&FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF]); - } - break; - - case 0x2: - case 0x3: - ret = ne16_rbo_le(DRAM, A & 0x1FFFF); - break; - - case 0x4: - case 0x5: - if (A >= 0x5E000) - ret = ReadRegister(timestamp, A); - else - VIP_DBGMSG("Unknown VIP Read: %08x", A); - break; - - case 0x6: - break; - - case 0x7: - if (A >= 0x8000) - { - ret = ne16_rbo_le(CHR_RAM, A & 0x7FFF); - } - else - VIP_DBGMSG("Unknown VIP Read: %08x", A); - break; - - default: - VIP_DBGMSG("Unknown VIP Read: %08x", A); - break; - } - - //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); - return (ret); -} - -MDFN_FASTCALL void VIP_Write8(int32 ×tamp, uint32 A, uint8 V) -{ - //VIP_Update(timestamp); - - //if(A >= 0x3DC00 && A < 0x3E000) - // printf("%08x %02x\n", A, V); - - switch (A >> 16) - { - case 0x0: - case 0x1: - if ((A & 0x7FFF) >= 0x6000) - ne16_wbo_le(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000), V); - else - FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF] = V; - break; - - case 0x2: - case 0x3: - ne16_wbo_le(DRAM, A & 0x1FFFF, V); - break; - - case 0x4: - case 0x5: - if (A >= 0x5E000) - WriteRegister(timestamp, A, V); - else - VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); - break; - - case 0x6: - VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); - break; - - case 0x7: - if (A >= 0x8000) - ne16_wbo_le(CHR_RAM, A & 0x7FFF, V); - else - VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); - break; - - default: - VIP_DBGMSG("Unknown VIP Write: %08x %02x", A, V); - break; - } - - //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); -} - -MDFN_FASTCALL void VIP_Write16(int32 ×tamp, uint32 A, uint16 V) -{ - //VIP_Update(timestamp); - - //if(A >= 0x3DC00 && A < 0x3E000) - // printf("%08x %04x\n", A, V); - - switch (A >> 16) - { - case 0x0: - case 0x1: - if ((A & 0x7FFF) >= 0x6000) - ne16_wbo_le(CHR_RAM, (A & 0x1FFF) | ((A >> 2) & 0x6000), V); - else - MDFN_en16lsb(&FB[(A >> 15) & 1][(A >> 16) & 1][A & 0x7FFF], V); - break; - - case 0x2: - case 0x3: - ne16_wbo_le(DRAM, A & 0x1FFFF, V); - break; - - case 0x4: - case 0x5: - if (A >= 0x5E000) - WriteRegister(timestamp, A, V); - else - VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); - break; - - case 0x6: - VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); - break; - - case 0x7: - if (A >= 0x8000) - ne16_wbo_le(CHR_RAM, A & 0x7FFF, V); - else - VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); - break; - - default: - VIP_DBGMSG("Unknown VIP Write: %08x %04x", A, V); - break; - } - - //VB_SetEvent(VB_EVENT_VIP, timestamp + CalcNextEvent()); -} - -static MDFN_Surface real_surface; -static MDFN_Surface *surface; - -void VIP_CalcFrameSize(MyFrameInfo* frame) -{ - switch (VB3DMode) - { - default: - frame->Width = 384; - frame->Height = 224; - break; - - case VB3DMODE_VLI: - frame->Width = 768 * VBPrescale; - frame->Height = 224; - break; - - case VB3DMODE_HLI: - frame->Width = 384; - frame->Height = 448 * VBPrescale; - break; - - case VB3DMODE_CSCOPE: - frame->Width = 512; - frame->Height = 384; - break; - - case VB3DMODE_SIDEBYSIDE: - frame->Width = 768 + VBSBS_Separation; - frame->Height = 224; - break; - } -} - -void VIP_StartFrame(MyFrameInfo* frame) -{ - // puts("Start frame"); - - if (VidSettingsDirty) - { - MakeColorLUT(); - Recalc3DModeStuff(); - - VidSettingsDirty = false; - } - - VIP_CalcFrameSize(frame); - - - surface = &real_surface; - real_surface.pixels = frame->VideoBuffer; - real_surface.pitch32 = frame->Width; -} - -void VIP_ResetTS(void) -{ - if (SBOUT_InactiveTime >= 0) - SBOUT_InactiveTime -= last_ts; - last_ts = 0; -} - -static int32 CalcNextEvent(void) -{ - return (ColumnCounter); -} - -#include "vip_draw.inc" - -static INLINE void CopyFBColumnToTarget_Anaglyph_BASE(const bool DisplayActive_arg, const int lr) -{ - const int fb = DisplayFB; - uint32 *target = surface->pixels + Column; - const int32 pitch32 = surface->pitch32; - const uint8 *fb_source = &FB[fb][lr][64 * Column]; - - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - uint32 pixel = BrightCLUT[lr][source_bits & 3]; - - if (!DisplayActive_arg) - pixel = 0; - - if (lr) - *target |= pixel; - else - *target = pixel; - - source_bits >>= 2; - target += pitch32; - } - fb_source++; - } -} - -static void CopyFBColumnToTarget_Anaglyph(void) -{ - const int lr = (DisplayRegion & 2) >> 1; - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_Anaglyph_BASE(0, 0); - else - CopyFBColumnToTarget_Anaglyph_BASE(0, 1); - } - else - { - if (!lr) - CopyFBColumnToTarget_Anaglyph_BASE(1, 0); - else - CopyFBColumnToTarget_Anaglyph_BASE(1, 1); - } -} - -static uint32 AnaSlowBuf[384][224]; - -static INLINE void CopyFBColumnToTarget_AnaglyphSlow_BASE(const bool DisplayActive_arg, const int lr) -{ - const int fb = DisplayFB; - const uint8 *fb_source = &FB[fb][lr][64 * Column]; - - if (!lr) - { - uint32 *target = AnaSlowBuf[Column]; - - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - uint32 pixel = BrightnessCache[source_bits & 3]; - - if (!DisplayActive_arg) - pixel = 0; - - *target = pixel; - source_bits >>= 2; - target++; - } - fb_source++; - } - } - else - { - uint32 *target = surface->pixels + Column; - const uint32 *left_src = AnaSlowBuf[Column]; - const int32 pitch32 = surface->pitch32; - - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - uint32 pixel = AnaSlowColorLUT[*left_src][DisplayActive_arg ? BrightnessCache[source_bits & 3] : 0]; - - *target = pixel; - - source_bits >>= 2; - target += pitch32; - left_src++; - } - fb_source++; - } - } -} - -static void CopyFBColumnToTarget_AnaglyphSlow(void) -{ - const int lr = (DisplayRegion & 2) >> 1; - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_AnaglyphSlow_BASE(0, 0); - else - CopyFBColumnToTarget_AnaglyphSlow_BASE(0, 1); - } - else - { - if (!lr) - CopyFBColumnToTarget_AnaglyphSlow_BASE(1, 0); - else - CopyFBColumnToTarget_AnaglyphSlow_BASE(1, 1); - } -} - -static void CopyFBColumnToTarget_CScope_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) -{ - const int fb = DisplayFB; - uint32 *target = surface->pixels + (dest_lr ? 512 - 16 - 1 : 16) + (dest_lr ? Column : 383 - Column) * surface->pitch32; - const uint8 *fb_source = &FB[fb][lr][64 * Column]; - - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - if (DisplayActive_arg) - *target = BrightCLUT[lr][source_bits & 3]; - else - *target = 0; - - source_bits >>= 2; - if (dest_lr) - target--; - else - target++; - } - fb_source++; - } -} - -static void CopyFBColumnToTarget_CScope(void) -{ - const int lr = (DisplayRegion & 2) >> 1; - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_CScope_BASE(0, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_CScope_BASE(0, 1, 1 ^ VB3DReverse); - } - else - { - if (!lr) - CopyFBColumnToTarget_CScope_BASE(1, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_CScope_BASE(1, 1, 1 ^ VB3DReverse); - } -} - -static void CopyFBColumnToTarget_SideBySide_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) -{ - const int fb = DisplayFB; - uint32 *target = surface->pixels + Column + (dest_lr ? (384 + VBSBS_Separation) : 0); - const int32 pitch32 = surface->pitch32; - const uint8 *fb_source = &FB[fb][lr][64 * Column]; - - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - if (DisplayActive_arg) - *target = BrightCLUT[lr][source_bits & 3]; - else - *target = 0; - source_bits >>= 2; - target += pitch32; - } - fb_source++; - } -} - -static void CopyFBColumnToTarget_SideBySide(void) -{ - const int lr = (DisplayRegion & 2) >> 1; - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_SideBySide_BASE(0, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_SideBySide_BASE(0, 1, 1 ^ VB3DReverse); - } - else - { - if (!lr) - CopyFBColumnToTarget_SideBySide_BASE(1, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_SideBySide_BASE(1, 1, 1 ^ VB3DReverse); - } -} - -static INLINE void CopyFBColumnToTarget_VLI_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) -{ - const int fb = DisplayFB; - uint32 *target = surface->pixels + Column * 2 * VBPrescale + dest_lr; - const int32 pitch32 = surface->pitch32; - const uint8 *fb_source = &FB[fb][lr][64 * Column]; - - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - uint32 tv; - - if (DisplayActive_arg) - tv = BrightCLUT[lr][source_bits & 3]; - else - tv = 0; - - for (uint32 ps = 0; ps < VBPrescale; ps++) - target[ps * 2] = tv; - - source_bits >>= 2; - target += pitch32; - } - fb_source++; - } -} - -static void CopyFBColumnToTarget_VLI(void) -{ - const int lr = (DisplayRegion & 2) >> 1; - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_VLI_BASE(0, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_VLI_BASE(0, 1, 1 ^ VB3DReverse); - } - else - { - if (!lr) - CopyFBColumnToTarget_VLI_BASE(1, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_VLI_BASE(1, 1, 1 ^ VB3DReverse); - } -} - -static INLINE void CopyFBColumnToTarget_HLI_BASE(const bool DisplayActive_arg, const int lr, const int dest_lr) -{ - const int fb = DisplayFB; - const int32 pitch32 = surface->pitch32; - uint32 *target = surface->pixels + Column + dest_lr * pitch32; - const uint8 *fb_source = &FB[fb][lr][64 * Column]; - - if (VBPrescale <= 4) - for (int y = 56; y; y--) - { - uint32 source_bits = HLILUT[*fb_source]; - - for (int y_sub = 4 * VBPrescale; y_sub; y_sub--) - { - if (DisplayActive_arg) - *target = BrightCLUT[lr][source_bits & 3]; - else - *target = 0; - - target += pitch32 * 2; - source_bits >>= 2; - } - fb_source++; - } - else - for (int y = 56; y; y--) - { - uint32 source_bits = *fb_source; - - for (int y_sub = 4; y_sub; y_sub--) - { - for (uint32 ps = 0; ps < VBPrescale; ps++) - { - if (DisplayActive_arg) - *target = BrightCLUT[lr][source_bits & 3]; - else - *target = 0; - - target += pitch32 * 2; - } - - source_bits >>= 2; - } - fb_source++; - } -} - -static void CopyFBColumnToTarget_HLI(void) -{ - const int lr = (DisplayRegion & 2) >> 1; - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_HLI_BASE(0, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_HLI_BASE(0, 1, 1 ^ VB3DReverse); - } - else - { - if (!lr) - CopyFBColumnToTarget_HLI_BASE(1, 0, 0 ^ VB3DReverse); - else - CopyFBColumnToTarget_HLI_BASE(1, 1, 1 ^ VB3DReverse); - } -} - -static void CopyFBColumnToTarget_OnlyLeftRight(void) -{ - const int lr = (VB3DMode == VB3DMODE_ONLYLEFT ? 0 : 1); - - if (!DisplayActive) - { - if (!lr) - CopyFBColumnToTarget_SideBySide_BASE(0, 0, 0); - else - CopyFBColumnToTarget_SideBySide_BASE(0, 1, 0); - } - else - { - if (!lr) - CopyFBColumnToTarget_SideBySide_BASE(1, 0, 0); - else - CopyFBColumnToTarget_SideBySide_BASE(1, 1, 0); - } -} - -v810_timestamp_t MDFN_FASTCALL VIP_Update(const v810_timestamp_t timestamp) -{ - int32 clocks = timestamp - last_ts; - int32 running_timestamp = timestamp; - - while (clocks > 0) - { - int32 chunk_clocks = clocks; - - if (DrawingCounter > 0 && chunk_clocks > DrawingCounter) - chunk_clocks = DrawingCounter; - if (chunk_clocks > ColumnCounter) - chunk_clocks = ColumnCounter; - - running_timestamp += chunk_clocks; - - if (DrawingCounter > 0) - { - DrawingCounter -= chunk_clocks; - if (DrawingCounter <= 0) - { - alignas(8) uint8 DrawingBuffers[2][512 * 8]; // Don't decrease this from 512 unless you adjust vip_draw.inc(including areas that draw off-visible >= 384 and >= -7 for speed reasons) - - VIP_DrawBlock(DrawingBlock, DrawingBuffers[0] + 8, DrawingBuffers[1] + 8); - - for (int lr = 0; lr < 2; lr++) - { - uint8 *FB_Target = FB[DrawingFB][lr] + DrawingBlock * 2; - - for (int x = 0; x < 384; x++) - { - FB_Target[64 * x + 0] = (DrawingBuffers[lr][8 + x + 512 * 0] << 0) | (DrawingBuffers[lr][8 + x + 512 * 1] << 2) | (DrawingBuffers[lr][8 + x + 512 * 2] << 4) | (DrawingBuffers[lr][8 + x + 512 * 3] << 6); - FB_Target[64 * x + 1] = (DrawingBuffers[lr][8 + x + 512 * 4] << 0) | (DrawingBuffers[lr][8 + x + 512 * 5] << 2) | (DrawingBuffers[lr][8 + x + 512 * 6] << 4) | (DrawingBuffers[lr][8 + x + 512 * 7] << 6); - } - } - - SBOUT_InactiveTime = running_timestamp + 1120; - SB_Latch = DrawingBlock; // Not exactly correct, but probably doesn't matter. - - DrawingBlock++; - if (DrawingBlock == 28) - { - DrawingActive = false; - - InterruptPending |= INT_XP_END; - CheckIRQ(); - } - else - DrawingCounter += 1120 * 4; - } - } - - ColumnCounter -= chunk_clocks; - if (ColumnCounter == 0) - { - if (DisplayRegion & 1) - { - if (!(Column & 3)) - { - const int lr = (DisplayRegion & 2) >> 1; - uint16 ctdata = ne16_rbo_le(DRAM, 0x1DFFE - ((Column >> 2) * 2) - (lr ? 0 : 0x200)); - - //printf("%02x, repeat: %02x\n", ctdata & 0xFF, ctdata >> 8); - - if ((ctdata >> 8) != Repeat) - { - Repeat = ctdata >> 8; - RecalcBrightnessCache(); - } - } - CopyFBColumnToTarget(); - } - - ColumnCounter = 259; - Column++; - if (Column == 384) - { - Column = 0; - - if (DisplayActive) - { - if (DisplayRegion & 1) // Did we just finish displaying an active region? - { - if (DisplayRegion & 2) // finished displaying right eye - InterruptPending |= INT_RFB_END; - else // Otherwise, left eye - InterruptPending |= INT_LFB_END; - - CheckIRQ(); - } - } - - DisplayRegion = (DisplayRegion + 1) & 3; - - if (DisplayRegion == 0) // New frame start - { - DisplayActive = DPCTRL & 0x2; - - if (DisplayActive) - { - InterruptPending |= INT_FRAME_START; - CheckIRQ(); - } - GameFrameCounter++; - if (GameFrameCounter > FRMCYC) // New game frame start? - { - InterruptPending |= INT_GAME_START; - CheckIRQ(); - - if (XPCTRL & XPCTRL_XP_EN) - { - DisplayFB ^= 1; - - DrawingBlock = 0; - DrawingActive = true; - DrawingCounter = 1120 * 4; - DrawingFB = DisplayFB ^ 1; - } - - GameFrameCounter = 0; - } - - VB_ExitLoop(); - } - } - } - - clocks -= chunk_clocks; - } - - last_ts = timestamp; - - return (timestamp + CalcNextEvent()); -} -} diff --git a/waterbox/vb/vip.h b/waterbox/vb/vip.h deleted file mode 100644 index fcb5162be7..0000000000 --- a/waterbox/vb/vip.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vip.h: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -namespace MDFN_IEN_VB -{ -void VIP_Init(void) MDFN_COLD; -void VIP_Power(void) MDFN_COLD; - -void VIP_SetInstantDisplayHack(bool) MDFN_COLD; -void VIP_SetAllowDrawSkip(bool) MDFN_COLD; -void VIP_Set3DMode(uint32 mode, bool reverse, uint32 prescale, uint32 sbs_separation) MDFN_COLD; -void VIP_SetParallaxDisable(bool disabled) MDFN_COLD; -void VIP_SetDefaultColor(uint32 default_color) MDFN_COLD; -void VIP_SetAnaglyphColors(uint32 lcolor, uint32 rcolor) MDFN_COLD; // R << 16, G << 8, B << 0 -void VIP_SetLEDOnScale(float coeff) MDFN_COLD; - -v810_timestamp_t MDFN_FASTCALL VIP_Update(const v810_timestamp_t timestamp); -void VIP_ResetTS(void); - -void VIP_StartFrame(MyFrameInfo* frame); -void VIP_CalcFrameSize(MyFrameInfo* frame); - -MDFN_FASTCALL uint8 VIP_Read8(v810_timestamp_t ×tamp, uint32 A); -MDFN_FASTCALL uint16 VIP_Read16(v810_timestamp_t ×tamp, uint32 A); - -MDFN_FASTCALL void VIP_Write8(v810_timestamp_t ×tamp, uint32 A, uint8 V); -MDFN_FASTCALL void VIP_Write16(v810_timestamp_t ×tamp, uint32 A, uint16 V); - -enum -{ - VIP_GSREG_IPENDING = 0, // Current pending interrupt(bits) - VIP_GSREG_IENABLE, - - VIP_GSREG_DPCTRL, - - VIP_GSREG_BRTA, - VIP_GSREG_BRTB, - VIP_GSREG_BRTC, - VIP_GSREG_REST, - VIP_GSREG_FRMCYC, - VIP_GSREG_XPCTRL, - - VIP_GSREG_SPT0, - VIP_GSREG_SPT1, - VIP_GSREG_SPT2, - VIP_GSREG_SPT3, - - VIP_GSREG_GPLT0, - VIP_GSREG_GPLT1, - VIP_GSREG_GPLT2, - VIP_GSREG_GPLT3, - - VIP_GSREG_JPLT0, - VIP_GSREG_JPLT1, - VIP_GSREG_JPLT2, - VIP_GSREG_JPLT3, - - VIP_GSREG_BKCOL, -}; - -uint32 VIP_GetRegister(const unsigned int id, char *special, const uint32 special_len); -void VIP_SetRegister(const unsigned int id, const uint32 value); -} diff --git a/waterbox/vb/vip_draw.inc b/waterbox/vb/vip_draw.inc deleted file mode 100644 index f7eb222589..0000000000 --- a/waterbox/vb/vip_draw.inc +++ /dev/null @@ -1,493 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vip_draw.inc: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#define BGM_AFFINE 0x2 -#define BGM_OBJ 0x3 - - -static void DrawBG(uint8 *target, uint16 RealY, bool lr, uint8 bgmap_base_raw, bool overplane, uint16 overplane_char, uint32 SourceX, uint32 SourceY, uint32 scx, uint32 scy, uint16 DestX, uint16 DestY, uint16 DestWidth, uint16 DestHeight) -{ - const uint16 *CHR16 = CHR_RAM; - const uint16 *BGMap = DRAM; - uint32 BGMap_Base = bgmap_base_raw << 12; - int32 start_x, final_x; - const uint32 bgsc_overplane = DRAM[overplane_char]; - const uint32 BGMap_XCount = 1 << scx; - const uint32 BGMap_YCount = 1 << scy; - const uint32 SourceX_Size = 512 * BGMap_XCount; - const uint32 SourceY_Size = 512 * BGMap_YCount; - const uint32 SourceX_Mask = overplane ? 0x1FFF : (SourceX_Size - 1); - const uint32 SourceY_Mask = overplane ? 0x1FFF : (SourceY_Size - 1); - - if((uint16)(RealY - DestY) > DestHeight) - return; - - //printf("%d, %d, %d, %d\n", overplane, srcXSize, srcYSize, bgmap_base_raw); - - DestX = sign_10_to_s16(DestX); - - if(DestX & 0x8000) - SourceX -= DestX; - - start_x = (int16)DestX; - final_x = (int16)DestX + DestWidth; - - if(start_x < 0) - start_x = 0; - - if(final_x > 383) - final_x = 383; - - if(start_x > final_x) - return; - - // Optimization: - SourceY &= SourceY_Mask; - BGMap_Base |= (((SourceY >> 3) & 0x3F) * 0x40) | (((SourceY << 3) & ~0xFFF) << scx); - - for(int x = start_x; x <= final_x; x++) - { - uint32 bgsc; - uint32 char_no; - uint32 palette_selector; - uint32 hflip_xor; - uint32 vflip_xor; - - SourceX &= SourceX_Mask; - - bgsc = bgsc_overplane; - - if(SourceX < SourceX_Size && SourceY < SourceY_Size) - bgsc = BGMap[(BGMap_Base | ((SourceX << 3) & ~0xFFF) | ((SourceX >> 3) & 0x3F)) & 0xFFFF]; - - char_no = bgsc & 0x7FF; - palette_selector = bgsc >> 14; - hflip_xor = (bgsc & 0x2000) ? 7 : 0; //(((int32)bgsc << 18) >> 31) & 0x7; - vflip_xor = (bgsc & 0x1000) ? 7 : 0; //(((int32)bgsc << 19) >> 31) & 0x7; - - unsigned int char_sub_y = vflip_xor ^ (SourceY & 0x7); - - if(!(SourceX & 7) && (x + 7) <= final_x) - { - uint32 pixels = CHR16[char_no * 8 + char_sub_y]; - - #if 0 - unsigned int char_sub_x; - uint8 *sub_target = target + x + 8; - - for(int sub_x = -8; sub_x < 0; sub_x++) - { - if(pixels & 3) sub_target[sub_x] = GPLT_Cache[palette_selector][pixels & 3]; - pixels >>= 2; - } - #endif - - if(bgsc & 0x2000) - { - if((pixels >> 14) & 3) target[0 + x] = GPLT_Cache[palette_selector][(pixels >> 14) & 3]; - if((pixels >> 12) & 3) target[1 + x] = GPLT_Cache[palette_selector][(pixels >> 12) & 3]; - if((pixels >> 10) & 3) target[2 + x] = GPLT_Cache[palette_selector][(pixels >> 10) & 3]; - if((pixels >> 8) & 3) target[3 + x] = GPLT_Cache[palette_selector][(pixels >> 8) & 3]; - if((pixels >> 6) & 3) target[4 + x] = GPLT_Cache[palette_selector][(pixels >> 6) & 3]; - if((pixels >> 4) & 3) target[5 + x] = GPLT_Cache[palette_selector][(pixels >> 4) & 3]; - if((pixels >> 2) & 3) target[6 + x] = GPLT_Cache[palette_selector][(pixels >> 2) & 3]; - if((pixels >> 0) & 3) target[7 + x] = GPLT_Cache[palette_selector][(pixels >> 0) & 3]; - } - else - { - if((pixels >> 0) & 3) target[0 + x] = GPLT_Cache[palette_selector][(pixels >> 0) & 3]; - if((pixels >> 2) & 3) target[1 + x] = GPLT_Cache[palette_selector][(pixels >> 2) & 3]; - if((pixels >> 4) & 3) target[2 + x] = GPLT_Cache[palette_selector][(pixels >> 4) & 3]; - if((pixels >> 6) & 3) target[3 + x] = GPLT_Cache[palette_selector][(pixels >> 6) & 3]; - if((pixels >> 8) & 3) target[4 + x] = GPLT_Cache[palette_selector][(pixels >> 8) & 3]; - if((pixels >> 10) & 3) target[5 + x] = GPLT_Cache[palette_selector][(pixels >> 10) & 3]; - if((pixels >> 12) & 3) target[6 + x] = GPLT_Cache[palette_selector][(pixels >> 12) & 3]; - if((pixels >> 14) & 3) target[7 + x] = GPLT_Cache[palette_selector][(pixels >> 14) & 3]; - } - - x += 7; - SourceX += 8; - } - else - { - unsigned int char_sub_x; - - char_sub_x = hflip_xor ^ (SourceX & 0x7); - - uint8 pixel = (CHR16[char_no * 8 + char_sub_y] >> (char_sub_x * 2)) & 0x3; - - if(pixel) - target[x] = GPLT_Cache[palette_selector][pixel]; //target[x] = (GPLT[palette_selector] >> (pixel * 2)) & 0x3; - SourceX++; - } - } -} - -static void DrawAffine(uint8 *target, uint16 RealY, bool lr, uint32 ParamBase, uint32 BGMap_Base, bool OverplaneMode, uint16 OverplaneChar, uint32 scx, uint32 scy, - uint16 DestX, uint16 DestY, uint16 DestWidth, uint16 DestHeight) -{ - const uint16 *CHR16 = CHR_RAM; - const uint16 *BGMap = DRAM; - - const uint32 BGMap_XCount = 1 << scx; - const uint32 BGMap_YCount = 1 << scy; - const uint32 SourceX_Size = 512 * BGMap_XCount; - const uint32 SourceY_Size = 512 * BGMap_YCount; - - const uint16 *param_ptr = &DRAM[(ParamBase + 8 * (RealY - DestY)) & 0xFFFF]; - int16 mx = param_ptr[0], mp = (ParallaxDisabled ? 0 : param_ptr[1]), my = param_ptr[2], dx = param_ptr[3], dy = param_ptr[4]; - - uint32 SourceX, SourceY; - uint32 SourceX_Mask, SourceY_Mask; - - int32 start_x, final_x; - const uint32 bgsc_overplane = DRAM[OverplaneChar]; - - - DestX = sign_10_to_s16(DestX); - - if((uint16)(RealY - DestY) > DestHeight) - return; - - SourceX = (int32)mx << 6; - SourceY = (int32)my << 6; - - if(DestX & 0x8000) - { - SourceX += dx * (65536 - DestX); - SourceY += dy * (65536 - DestX); - } - - if(mp >= 0 && lr) - { - SourceX += dx * mp; - SourceY += dy * mp; - } - else if(mp < 0 && !lr) - { - SourceX += dx * -mp; - SourceY += dy * -mp; - } - - if(OverplaneMode) - { - SourceX_Mask = 0x3FFFFFF; //(((uint32)SourceX_Size << 9) * 2) - 1; - SourceY_Mask = 0x3FFFFFF; //(((uint32)SourceY_Size << 9) * 2) - 1; - } - else - { - SourceX_Mask = ((uint32)SourceX_Size << 9) - 1; - SourceY_Mask = ((uint32)SourceY_Size << 9) - 1; - } - - start_x = (int16)DestX; - final_x = (int16)DestX + DestWidth; - - if(start_x < 0) - start_x = 0; - - if(final_x > 383) - final_x = 383; - -if(dy == 0) // Optimization for no rotation. -{ - SourceY &= SourceY_Mask; - - if(SourceY >= (SourceY_Size << 9)) - return; - - BGMap_Base |= (((SourceY >> 6) & ~0xFFF) << scx) | (((SourceY >> 12) & 0x3F) * 0x40); - for(int x = start_x; x <= final_x; x++) - { - uint32 bgsc; - uint32 hflip_xor; - uint32 vflip_xor; - uint32 pixel = 0; - - SourceX &= SourceX_Mask; - - bgsc = bgsc_overplane; - - if(SourceX < (SourceX_Size << 9)) - bgsc = BGMap[(BGMap_Base | ((SourceX >> 6) & ~0xFFF) | ((SourceX >> 12) & 0x3F)) & 0xFFFF]; - - //hflip_xor = bgsc & 0x2000 ? 0xE : 0; - //vflip_xor = bgsc & 0x1000 ? 0x7 : 0; - hflip_xor = ((int32)(bgsc << 18) >> 30) & 0xE; - vflip_xor = ((int32)(bgsc << 19) >> 31) & 0x7; - - unsigned int char_sub_y = vflip_xor ^ ((SourceY >> 9) & 0x7); - unsigned int char_sub_x = hflip_xor ^ ((SourceX >> 8) & 0xE); - - pixel = (CHR16[((bgsc & 0x7FF) * 8) | char_sub_y] >> char_sub_x) & 0x3; - - if(pixel) - target[x] = GPLT_Cache[bgsc >> 14][pixel]; - - SourceX += dx; - } -} -else - for(int x = start_x; x <= final_x; x++) - { - uint32 bgsc; - uint32 char_no; - uint32 palette_selector; - uint32 hflip_xor; - uint32 vflip_xor; - uint8 pixel = 0; - - SourceX &= SourceX_Mask; - SourceY &= SourceY_Mask; - - bgsc = bgsc_overplane; - - if(SourceX < (SourceX_Size << 9) && SourceY < (SourceY_Size << 9)) - { - uint32 m_index = ((SourceX >> 6) & ~0xFFF) + (((SourceY >> 6) & ~0xFFF) << scx); - uint32 sub_index = ((SourceX >> 12) & 0x3F) + (((SourceY >> 12) & 0x3F) * 0x40); - - bgsc = BGMap[(BGMap_Base | m_index | sub_index) & 0xFFFF]; - - //bgsc = BGMap[(BGMapBase + (SourceX >> 12) + (SourceY >> 12) * (SourceX_Size >> 3)) & 0xFFFF ]; - } - char_no = bgsc & 0x7FF; - palette_selector = bgsc >> 14; - hflip_xor = bgsc & 0x2000 ? 7 : 0; //(((int32)bgsc << 18) >> 31) & 0x7; - vflip_xor = bgsc & 0x1000 ? 7 : 0; //(((int32)bgsc << 19) >> 31) & 0x7; - - unsigned int char_sub_y = vflip_xor ^ ((SourceY >> 9) & 0x7); - unsigned int char_sub_x = hflip_xor ^ ((SourceX >> 9) & 0x7); - - pixel = (CHR16[char_no * 8 + char_sub_y] >> (char_sub_x * 2)) & 0x3; - - if(pixel) - target[x] = GPLT_Cache[palette_selector][pixel]; - - SourceX += dx; - SourceY += dy; - } -} - -static int obj_search_which; - -static void DrawOBJ(uint8 *fb[2], uint16 Y, bool lron[2]) -{ - const uint16 *CHR16 = CHR_RAM; - - int32 start_oam; - int32 end_oam; - - start_oam = SPT[obj_search_which]; - - end_oam = 1023; - if(obj_search_which) - end_oam = SPT[obj_search_which - 1]; - - int32 oam = start_oam; - do - { - const uint16 *oam_ptr = &DRAM[(0x1E000 + (oam * 8)) >> 1]; - const uint32 jy = oam_ptr[2]; - const uint32 tile_y = (Y - jy) & 0xFF; // I think this mask is right. See: http://www.planetvb.com/modules/newbb/viewtopic.php?topic_id=3797&forum=2 - - if(tile_y >= 8) - continue; - - uint32 jx = oam_ptr[0]; - uint32 jp = ParallaxDisabled ? 0 : (oam_ptr[1] & 0x3FFF); - uint32 palette_selector = oam_ptr[3] >> 14; - uint32 vflip_xor = (oam_ptr[3] & 0x1000) ? 7 : 0; - uint32 char_sub_y = vflip_xor ^ tile_y; - bool jlron[2] = { (bool)(oam_ptr[1] & 0x8000), (bool)(oam_ptr[1] & 0x4000) }; - uint32 char_no = oam_ptr[3] & 0x7FF; - const uint32 pixels_save = CHR16[char_no * 8 + char_sub_y]; - - for(int lr = 0; lr < 2; lr++) - { - if(!(jlron[lr] & lron[lr])) - continue; - - uint32 pixels = pixels_save; - int32 x = sign_x_to_s32(10, (jx + (lr ? jp : -jp))); // It may actually be 9, TODO? - - if(x >= -7 && x < 384) // Make sure we always keep the pitch of our 384x8 buffer large enough(with padding before and after the visible space) - { - uint8 *target = &fb[lr][x]; - - if(oam_ptr[3] & 0x2000) - { - target += 7; - - for(int meow = 8; meow; meow--) - { - if(pixels & 3) - *target = JPLT_Cache[palette_selector][pixels & 3]; - target--; - pixels >>= 2; - } - } - else - { - for(int meow = 8; meow; meow--) - { - if(pixels & 3) - *target = JPLT_Cache[palette_selector][pixels & 3]; - target++; - pixels >>= 2; - } - } - #if 0 - if(oam_ptr[3] & 0x2000) - { - if((pixels >> 14) & 3) fb[lr][0 + x] = JPLT_Cache[palette_selector][(pixels >> 14) & 3]; - if((pixels >> 12) & 3) fb[lr][1 + x] = JPLT_Cache[palette_selector][(pixels >> 12) & 3]; - if((pixels >> 10) & 3) fb[lr][2 + x] = JPLT_Cache[palette_selector][(pixels >> 10) & 3]; - if((pixels >> 8) & 3) fb[lr][3 + x] = JPLT_Cache[palette_selector][(pixels >> 8) & 3]; - if((pixels >> 6) & 3) fb[lr][4 + x] = JPLT_Cache[palette_selector][(pixels >> 6) & 3]; - if((pixels >> 4) & 3) fb[lr][5 + x] = JPLT_Cache[palette_selector][(pixels >> 4) & 3]; - if((pixels >> 2) & 3) fb[lr][6 + x] = JPLT_Cache[palette_selector][(pixels >> 2) & 3]; - if((pixels >> 0) & 3) fb[lr][7 + x] = JPLT_Cache[palette_selector][(pixels >> 0) & 3]; - } - else - { - if((pixels >> 0) & 3) fb[lr][0 + x] = JPLT_Cache[palette_selector][(pixels >> 0) & 3]; - if((pixels >> 2) & 3) fb[lr][1 + x] = JPLT_Cache[palette_selector][(pixels >> 2) & 3]; - if((pixels >> 4) & 3) fb[lr][2 + x] = JPLT_Cache[palette_selector][(pixels >> 4) & 3]; - if((pixels >> 6) & 3) fb[lr][3 + x] = JPLT_Cache[palette_selector][(pixels >> 6) & 3]; - if((pixels >> 8) & 3) fb[lr][4 + x] = JPLT_Cache[palette_selector][(pixels >> 8) & 3]; - if((pixels >> 10) & 3) fb[lr][5 + x] = JPLT_Cache[palette_selector][(pixels >> 10) & 3]; - if((pixels >> 12) & 3) fb[lr][6 + x] = JPLT_Cache[palette_selector][(pixels >> 12) & 3]; - if((pixels >> 14) & 3) fb[lr][7 + x] = JPLT_Cache[palette_selector][(pixels >> 14) & 3]; - } -#endif - - } - - } - } while( (oam = (oam - 1) & 1023) != end_oam); - -} - - -void VIP_DrawBlock(uint8 block_no, uint8 *fb_l, uint8 *fb_r) -{ - for(int y = 0; y < 8; y++) - { - memset(fb_l + y * 512, BKCOL, 384); - memset(fb_r + y * 512, BKCOL, 384); - } - - obj_search_which = 3; - - for(int world = 31; world >= 0; world--) - { - const uint16 *world_ptr = &DRAM[(0x1D800 + world * 0x20) >> 1]; - - uint32 bgmap_base = world_ptr[0] & 0xF; - bool end = world_ptr[0] & 0x40; - bool over = world_ptr[0] & 0x80; - uint32 scy = (world_ptr[0] >> 8) & 3; - uint32 scx = (world_ptr[0] >> 10) & 3; - uint32 bgm = (world_ptr[0] >> 12) & 3; - bool lron[2] = { (bool)(world_ptr[0] & 0x8000), (bool)(world_ptr[0] & 0x4000) }; - - uint16 gx = sign_11_to_s16(world_ptr[1]); - uint16 gp = ParallaxDisabled ? 0 : sign_9_to_s16(world_ptr[2]); - uint16 gy = sign_11_to_s16(world_ptr[3]); - uint16 mx = world_ptr[4]; - uint16 mp = ParallaxDisabled ? 0 : sign_9_to_s16(world_ptr[5]); - uint16 my = world_ptr[6]; - uint16 window_width = sign_11_to_s16(world_ptr[7]); - uint16 window_height = (world_ptr[8] & 0x3FF); - uint32 param_base = (world_ptr[9] & 0xFFF0); - uint16 overplane_char = world_ptr[10]; - - if(end) - break; - - if(((512 << scx) + (512 << scy)) > 4096) - { - printf("BG Size too large for world: %d(scx=%d, scy=%d)\n", world, scx, scy); - } - -// if(world != 2) -// continue; - - // if(block_no == 8) - // printf("World: %d; gx: %d, gp: %d, gy: %d, mx: %d, mp: %d, my: %d, window_width: %d, window_height: %d\n", world, gx, gp, gy, mx, mp, my, window_width, window_height); - - for(int y = 0; y < 8; y++) - { - uint8 *fb[2] = { &fb_l[y * 512], &fb_r[y * 512] }; - - if(bgm == BGM_OBJ) - { - if(!lron[0] || !lron[1]) - printf("Bad OBJ World? %d(%d/%d) %d~%d\n", world, lron[0], lron[1], SPT[obj_search_which], obj_search_which ? (SPT[obj_search_which - 1] + 1) : 0); - - DrawOBJ(fb, (block_no * 8) + y, lron); - } - else if(bgm == BGM_AFFINE) - { - //if(((block_no * 8) + y) == 128) - // printf("Draw affine: %d %d\n", gx, gp); - for(int lr = 0; lr < 2; lr++) - { - if(lron[lr]) - { - DrawAffine(fb[lr], (block_no * 8) + y, lr, param_base, bgmap_base * 4096, over, overplane_char, scx, scy, - gx + (lr ? gp : -gp), gy, window_width, window_height); - } - } - } - else - for(int lr = 0; lr < 2; lr++) - { - uint16 srcX, srcY; - uint16 RealY = (block_no * 8) + y; - uint16 DestX; - uint16 DestY; - - srcX = mx + (lr ? mp : -mp); - srcY = my + (RealY - gy); - - DestX = gx + (lr ? gp : -gp); - DestY = gy; - - if(lron[lr]) - { - if(bgm == 1) // HBias - srcX += (int16)DRAM[(param_base + (((RealY - DestY) * 2) | lr)) & 0xFFFF]; - - DrawBG(fb[lr], RealY, lr, bgmap_base, over, overplane_char, (int32)(int16)srcX, (int32)(int16)srcY, scx, scy, DestX, DestY, window_width, window_height); - } - } - } - - if(bgm == BGM_OBJ) - if(obj_search_which) - obj_search_which--; - - } - - -} diff --git a/waterbox/vb/vsu.cpp b/waterbox/vb/vsu.cpp deleted file mode 100644 index e1588f570f..0000000000 --- a/waterbox/vb/vsu.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vsu.cpp: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "vb.h" - -static const unsigned int Tap_LUT[8] = {15 - 1, 11 - 1, 14 - 1, 5 - 1, 9 - 1, 7 - 1, 10 - 1, 12 - 1}; - -VSU::VSU() -{ - Synth.volume(1.0 / 6 / 2); - - for (int ch = 0; ch < 6; ch++) - { - for (int lr = 0; lr < 2; lr++) - last_output[ch][lr] = 0; - } -} - -VSU::~VSU() -{ -} - -void VSU::SetSoundRate(double rate) -{ - for (int y = 0; y < 2; y++) - { - sbuf[y].set_sample_rate(rate ? rate : 44100, 50); - sbuf[y].clock_rate((long)(VB_MASTER_CLOCK / 4)); - sbuf[y].bass_freq(20); - } -} - -void VSU::Power(void) -{ - SweepControl = 0; - SweepModCounter = 0; - SweepModClockDivider = 1; - - for (int ch = 0; ch < 6; ch++) - { - IntlControl[ch] = 0; - LeftLevel[ch] = 0; - RightLevel[ch] = 0; - Frequency[ch] = 0; - EnvControl[ch] = 0; - RAMAddress[ch] = 0; - - EffFreq[ch] = 0; - Envelope[ch] = 0; - WavePos[ch] = 0; - FreqCounter[ch] = 1; - IntervalCounter[ch] = 0; - EnvelopeCounter[ch] = 1; - - EffectsClockDivider[ch] = 4800; - IntervalClockDivider[ch] = 4; - EnvelopeClockDivider[ch] = 4; - - LatcherClockDivider[ch] = 120; - } - - ModWavePos = 0; - - NoiseLatcherClockDivider = 120; - NoiseLatcher = 0; - - lfsr = 0; - - memset(WaveData, 0, sizeof(WaveData)); - memset(ModData, 0, sizeof(ModData)); - - last_ts = 0; -} - -void VSU::Write(int32 timestamp, uint32 A, uint8 V) -{ - if(A & 0x3) - { - return; - } - - A &= 0x7FF; - - Update(timestamp); - - //printf("VSU Write: %d, %08x %02x\n", timestamp, A, V); - - if (A < 0x280) - WaveData[A >> 7][(A >> 2) & 0x1F] = V & 0x3F; - else if (A < 0x400) - { - //if(A >= 0x300) - // printf("Modulation mirror write? %08x %02x\n", A, V); - ModData[(A >> 2) & 0x1F] = V; - } - else if (A < 0x600) - { - int ch = (A >> 6) & 0xF; - - //if(ch < 6) - //printf("Ch: %d, Reg: %d, Value: %02x\n", ch, (A >> 2) & 0xF, V); - - if (ch > 5) - { - if (A == 0x580 && (V & 1)) - { - //puts("STOP, HAMMER TIME"); - for (int i = 0; i < 6; i++) - IntlControl[i] &= ~0x80; - } - } - else - switch ((A >> 2) & 0xF) - { - case 0x0: - IntlControl[ch] = V & ~0x40; - - if (V & 0x80) - { - EffFreq[ch] = Frequency[ch]; - if (ch == 5) - FreqCounter[ch] = 10 * (2048 - EffFreq[ch]); - else - FreqCounter[ch] = 2048 - EffFreq[ch]; - IntervalCounter[ch] = (V & 0x1F) + 1; - EnvelopeCounter[ch] = (EnvControl[ch] & 0x7) + 1; - - if (ch == 4) - { - SweepModCounter = (SweepControl >> 4) & 7; - SweepModClockDivider = (SweepControl & 0x80) ? 8 : 1; - ModWavePos = 0; - } - - WavePos[ch] = 0; - - if (ch == 5) // Not sure if this is correct. - lfsr = 1; - - //if(!(IntlControl[ch] & 0x80)) - // Envelope[ch] = (EnvControl[ch] >> 4) & 0xF; - - EffectsClockDivider[ch] = 4800; - IntervalClockDivider[ch] = 4; - EnvelopeClockDivider[ch] = 4; - } - break; - - case 0x1: - LeftLevel[ch] = (V >> 4) & 0xF; - RightLevel[ch] = (V >> 0) & 0xF; - break; - - case 0x2: - Frequency[ch] &= 0xFF00; - Frequency[ch] |= V << 0; - EffFreq[ch] &= 0xFF00; - EffFreq[ch] |= V << 0; - break; - - case 0x3: - Frequency[ch] &= 0x00FF; - Frequency[ch] |= (V & 0x7) << 8; - EffFreq[ch] &= 0x00FF; - EffFreq[ch] |= (V & 0x7) << 8; - break; - - case 0x4: - EnvControl[ch] &= 0xFF00; - EnvControl[ch] |= V << 0; - - Envelope[ch] = (V >> 4) & 0xF; - break; - - case 0x5: - EnvControl[ch] &= 0x00FF; - if (ch == 4) - EnvControl[ch] |= (V & 0x73) << 8; - else if (ch == 5) - { - EnvControl[ch] |= (V & 0x73) << 8; - lfsr = 1; - } - else - EnvControl[ch] |= (V & 0x03) << 8; - break; - - case 0x6: - RAMAddress[ch] = V & 0xF; - break; - - case 0x7: - if (ch == 4) - { - SweepControl = V; - } - break; - } - } -} - -INLINE void VSU::CalcCurrentOutput(int ch, int &left, int &right) -{ - if (!(IntlControl[ch] & 0x80)) - { - left = right = 0; - return; - } - - int WD; - int l_ol, r_ol; - - if (ch == 5) - WD = NoiseLatcher; //(NoiseLatcher << 6) - NoiseLatcher; - else - { - if (RAMAddress[ch] > 4) - WD = 0; - else - WD = WaveData[RAMAddress[ch]][WavePos[ch]]; // - 0x20; - } - l_ol = Envelope[ch] * LeftLevel[ch]; - if (l_ol) - { - l_ol >>= 3; - l_ol += 1; - } - - r_ol = Envelope[ch] * RightLevel[ch]; - if (r_ol) - { - r_ol >>= 3; - r_ol += 1; - } - - left = WD * l_ol; - right = WD * r_ol; -} - -void VSU::Update(int32 timestamp) -{ - //puts("VSU Start"); - int left, right; - - for (int ch = 0; ch < 6; ch++) - { - int32 clocks = timestamp - last_ts; - int32 running_timestamp = last_ts; - - // Output sound here - CalcCurrentOutput(ch, left, right); - Synth.offset_inline(running_timestamp, left - last_output[ch][0], &sbuf[0]); - Synth.offset_inline(running_timestamp, right - last_output[ch][1], &sbuf[1]); - last_output[ch][0] = left; - last_output[ch][1] = right; - - if (!(IntlControl[ch] & 0x80)) - continue; - - while (clocks > 0) - { - int32 chunk_clocks = clocks; - - if (chunk_clocks > EffectsClockDivider[ch]) - chunk_clocks = EffectsClockDivider[ch]; - - if (ch == 5) - { - if (chunk_clocks > NoiseLatcherClockDivider) - chunk_clocks = NoiseLatcherClockDivider; - } - else - { - if (EffFreq[ch] >= 2040) - { - if (chunk_clocks > LatcherClockDivider[ch]) - chunk_clocks = LatcherClockDivider[ch]; - } - else - { - if (chunk_clocks > FreqCounter[ch]) - chunk_clocks = FreqCounter[ch]; - } - } - - if (ch == 5 && chunk_clocks > NoiseLatcherClockDivider) - chunk_clocks = NoiseLatcherClockDivider; - - FreqCounter[ch] -= chunk_clocks; - while (FreqCounter[ch] <= 0) - { - if (ch == 5) - { - int feedback = ((lfsr >> 7) & 1) ^ ((lfsr >> Tap_LUT[(EnvControl[5] >> 12) & 0x7]) & 1) ^ 1; - lfsr = ((lfsr << 1) & 0x7FFF) | feedback; - - FreqCounter[ch] += 10 * (2048 - EffFreq[ch]); - } - else - { - FreqCounter[ch] += 2048 - EffFreq[ch]; - WavePos[ch] = (WavePos[ch] + 1) & 0x1F; - } - } - - LatcherClockDivider[ch] -= chunk_clocks; - while (LatcherClockDivider[ch] <= 0) - LatcherClockDivider[ch] += 120; - - if (ch == 5) - { - NoiseLatcherClockDivider -= chunk_clocks; - if (!NoiseLatcherClockDivider) - { - NoiseLatcherClockDivider = 120; - NoiseLatcher = ((lfsr & 1) << 6) - (lfsr & 1); - } - } - - EffectsClockDivider[ch] -= chunk_clocks; - while (EffectsClockDivider[ch] <= 0) - { - EffectsClockDivider[ch] += 4800; - - IntervalClockDivider[ch]--; - while (IntervalClockDivider[ch] <= 0) - { - IntervalClockDivider[ch] += 4; - - if (IntlControl[ch] & 0x20) - { - IntervalCounter[ch]--; - if (!IntervalCounter[ch]) - { - IntlControl[ch] &= ~0x80; - } - } - - EnvelopeClockDivider[ch]--; - while (EnvelopeClockDivider[ch] <= 0) - { - EnvelopeClockDivider[ch] += 4; - - if (EnvControl[ch] & 0x0100) // Enveloping enabled? - { - EnvelopeCounter[ch]--; - if (!EnvelopeCounter[ch]) - { - EnvelopeCounter[ch] = (EnvControl[ch] & 0x7) + 1; - - if (EnvControl[ch] & 0x0008) // Grow - { - if (Envelope[ch] < 0xF || (EnvControl[ch] & 0x200)) - Envelope[ch] = (Envelope[ch] + 1) & 0xF; - } - else // Decay - { - if (Envelope[ch] > 0 || (EnvControl[ch] & 0x200)) - Envelope[ch] = (Envelope[ch] - 1) & 0xF; - } - } - } - - } // end while(EnvelopeClockDivider[ch] <= 0) - } // end while(IntervalClockDivider[ch] <= 0) - - if (ch == 4) - { - SweepModClockDivider--; - while (SweepModClockDivider <= 0) - { - SweepModClockDivider += (SweepControl & 0x80) ? 8 : 1; - - if (((SweepControl >> 4) & 0x7) && (EnvControl[ch] & 0x4000)) - { - if (SweepModCounter) - SweepModCounter--; - - if (!SweepModCounter) - { - SweepModCounter = (SweepControl >> 4) & 0x7; - - if (EnvControl[ch] & 0x1000) // Modulation - { - if (ModWavePos < 32 || (EnvControl[ch] & 0x2000)) - { - ModWavePos &= 0x1F; - - EffFreq[ch] = (EffFreq[ch] + (int8)ModData[ModWavePos]); - if (EffFreq[ch] < 0) - { - //puts("Underflow"); - EffFreq[ch] = 0; - } - else if (EffFreq[ch] > 0x7FF) - { - //puts("Overflow"); - EffFreq[ch] = 0x7FF; - } - ModWavePos++; - } - //puts("Mod"); - } - else // Sweep - { - int32 delta = EffFreq[ch] >> (SweepControl & 0x7); - int32 NewFreq = EffFreq[ch] + ((SweepControl & 0x8) ? delta : -delta); - - //printf("Sweep(%d): Old: %d, New: %d\n", ch, EffFreq[ch], NewFreq); - - if (NewFreq < 0) - EffFreq[ch] = 0; - else if (NewFreq > 0x7FF) - { - //EffFreq[ch] = 0x7FF; - IntlControl[ch] &= ~0x80; - } - else - EffFreq[ch] = NewFreq; - } - } - } - } // end while(SweepModClockDivider <= 0) - } // end if(ch == 4) - } // end while(EffectsClockDivider[ch] <= 0) - clocks -= chunk_clocks; - running_timestamp += chunk_clocks; - - // Output sound here too. - CalcCurrentOutput(ch, left, right); - Synth.offset_inline(running_timestamp, left - last_output[ch][0], &sbuf[0]); - Synth.offset_inline(running_timestamp, right - last_output[ch][1], &sbuf[1]); - last_output[ch][0] = left; - last_output[ch][1] = right; - } - } - last_ts = timestamp; - //puts("VSU End"); -} - -int32 VSU::EndFrame(int32 timestamp, int16 *SoundBuf, int32 SoundBufMaxSize) -{ - int32 ret = 0; - - Update(timestamp); - last_ts = 0; - - if (SoundBuf) - { - for (int y = 0; y < 2; y++) - { - sbuf[y].end_frame(timestamp); - ret = sbuf[y].read_samples(SoundBuf + y, SoundBufMaxSize, 1); - } - } - - return ret; -} - -uint8 VSU::PeekWave(const unsigned int which, uint32 Address) -{ - assert(which <= 4); - - Address &= 0x1F; - - return (WaveData[which][Address]); -} - -void VSU::PokeWave(const unsigned int which, uint32 Address, uint8 value) -{ - assert(which <= 4); - - Address &= 0x1F; - - WaveData[which][Address] = value & 0x3F; -} - -uint8 VSU::PeekModWave(uint32 Address) -{ - Address &= 0x1F; - return (ModData[Address]); -} - -void VSU::PokeModWave(uint32 Address, uint8 value) -{ - Address &= 0x1F; - - ModData[Address] = value & 0xFF; -} diff --git a/waterbox/vb/vsu.h b/waterbox/vb/vsu.h deleted file mode 100644 index c8230beb85..0000000000 --- a/waterbox/vb/vsu.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************/ -/* Mednafen Virtual Boy Emulation Module */ -/******************************************************************************/ -/* vsu.h: -** Copyright (C) 2010-2016 Mednafen Team -** -** This program is free software; you can redistribute it and/or -** modify it under the terms of the GNU General Public License -** as published by the Free Software Foundation; either version 2 -** of the License, or (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#pragma once - -class VSU -{ - public: - VSU() - MDFN_COLD; - ~VSU() MDFN_COLD; - - void SetSoundRate(double rate) MDFN_COLD; - - void Power(void) MDFN_COLD; - - void Write(int32 timestamp, uint32 A, uint8 V); - - int32 EndFrame(int32 timestamp, int16 *SoundBuf, int32 SoundBufMaxSize); - - uint8 PeekWave(const unsigned int which, uint32 Address); - void PokeWave(const unsigned int which, uint32 Address, uint8 value); - - uint8 PeekModWave(uint32 Address); - void PokeModWave(uint32 Address, uint8 value); - - private: - void CalcCurrentOutput(int ch, int &left, int &right); - - void Update(int32 timestamp); - - uint8 IntlControl[6]; - uint8 LeftLevel[6]; - uint8 RightLevel[6]; - uint16 Frequency[6]; - uint16 EnvControl[6]; // Channel 5/6 extra functionality tacked on too. - - uint8 RAMAddress[6]; - - uint8 SweepControl; - - uint8 WaveData[5][0x20]; - - uint8 ModData[0x20]; - - int32 EffFreq[6]; - int32 Envelope[6]; - - int32 WavePos[6]; - int32 ModWavePos; - - int32 LatcherClockDivider[6]; - - int32 FreqCounter[6]; - int32 IntervalCounter[6]; - int32 EnvelopeCounter[6]; - int32 SweepModCounter; - - int32 EffectsClockDivider[6]; - int32 IntervalClockDivider[6]; - int32 EnvelopeClockDivider[6]; - int32 SweepModClockDivider; - - int32 NoiseLatcherClockDivider; - uint32 NoiseLatcher; - - uint32 lfsr; - - int32 last_output[6][2]; - int32 last_ts; - - Blip_Buffer sbuf[2]; - Blip_Synth Synth; - Blip_Synth NoiseSynth; -};