Hello community, here is the log from the commit of package libretro-handy for openSUSE:Factory checked in at 2020-08-17 12:01:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libretro-handy (Old) and /work/SRC/openSUSE:Factory/.libretro-handy.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libretro-handy" Mon Aug 17 12:01:14 2020 rev:2 rq:826803 version:0~git20200625 Changes: -------- --- /work/SRC/openSUSE:Factory/libretro-handy/libretro-handy.changes 2020-02-11 22:24:08.671526127 +0100 +++ /work/SRC/openSUSE:Factory/.libretro-handy.new.3399/libretro-handy.changes 2020-08-17 12:01:38.662569343 +0200 @@ -1,0 +2,10 @@ +Sat Aug 08 09:53:47 UTC 2020 - i...@guoyunhe.me + +- Update to version 0~git20200625: + * libretro: Add CORE_DIR to include path + * color depth no restart, add 555 format + * use blargg blip buffer + * fix superclip renderer + * fix mikie irq + +------------------------------------------------------------------- Old: ---- libretro-handy-0~git20200107.tar.xz New: ---- libretro-handy-0~git20200625.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libretro-handy.spec ++++++ --- /var/tmp/diff_new_pack.npnDNO/_old 2020-08-17 12:01:40.370570295 +0200 +++ /var/tmp/diff_new_pack.npnDNO/_new 2020-08-17 12:01:40.370570295 +0200 @@ -17,10 +17,10 @@ Name: libretro-handy -Version: 0~git20200107 +Version: 0~git20200625 Release: 0 Summary: Handy libretro core for Atari Lynx -License: GPL-2.0 +License: GPL-2.0-only URL: http://www.retroarch.com Source: %{name}-%{version}.tar.xz ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.npnDNO/_old 2020-08-17 12:01:40.422570324 +0200 +++ /var/tmp/diff_new_pack.npnDNO/_new 2020-08-17 12:01:40.422570324 +0200 @@ -3,4 +3,4 @@ <param name="url">https://github.com/libretro/mgba.git</param> <param name="changesrevision">24fb0a5ba23689aa4c0c9620ae6b5659d419fefb</param></service><service name="tar_scm"> <param name="url">https://github.com/libretro/libretro-handy.git</param> - <param name="changesrevision">10f515163f875af5bd20c5170cb1ce7139de6fe4</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">128a3cdbdefa2d88168473290a45e1eaee97130b</param></service></servicedata> \ No newline at end of file ++++++ libretro-handy-0~git20200107.tar.xz -> libretro-handy-0~git20200625.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/Makefile new/libretro-handy-0~git20200625/Makefile --- old/libretro-handy-0~git20200107/Makefile 2020-01-07 17:39:39.000000000 +0100 +++ new/libretro-handy-0~git20200625/Makefile 2020-06-25 22:54:05.000000000 +0200 @@ -1,3 +1,6 @@ +DEBUG = 0 +FRONTEND_SUPPORTS_RGB565 = 1 + TARGET_NAME := handy GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" ifneq ($(GIT_VERSION)," unknown") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/Makefile.common new/libretro-handy-0~git20200625/Makefile.common --- old/libretro-handy-0~git20200107/Makefile.common 2020-01-07 17:39:39.000000000 +0100 +++ new/libretro-handy-0~git20200625/Makefile.common 2020-06-25 22:54:05.000000000 +0200 @@ -1,10 +1,13 @@ -LIBRETRO_COMM_DIR = $(CORE_DIR)/libretro-common - INCFLAGS = -I$(CORE_DIR)/lynx \ - -I$(CORE_DIR)/libretro + -I$(CORE_DIR)/libretro \ + -I$(CORE_DIR) ifneq (,$(findstring msvc2003,$(platform))) -INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc + INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc +endif + +ifeq ($(FRONTEND_SUPPORTS_RGB565), 1) + FLAGS += -DFRONTEND_SUPPORTS_RGB565 endif SOURCES_CXX := $(CORE_DIR)/lynx/lynxdec.cpp \ @@ -16,4 +19,6 @@ $(CORE_DIR)/lynx/susie.cpp \ $(CORE_DIR)/lynx/system.cpp \ $(CORE_DIR)/lynx/eeprom.cpp \ - $(CORE_DIR)/libretro/libretro.cpp + $(CORE_DIR)/libretro/libretro.cpp \ + $(CORE_DIR)/blip/Blip_Buffer.cpp \ + $(CORE_DIR)/blip/Stereo_Buffer.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/blip/Blip_Buffer.cpp new/libretro-handy-0~git20200625/blip/Blip_Buffer.cpp --- old/libretro-handy-0~git20200107/blip/Blip_Buffer.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libretro-handy-0~git20200625/blip/Blip_Buffer.cpp 2020-06-25 22:54:05.000000000 +0200 @@ -0,0 +1,240 @@ +// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ + +#include <blip/Blip_Buffer.h> + +#include <assert.h> +#include <climits> +#include <string.h> +#include <stdlib.h> +#include <math.h> + +/* 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 + +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; +} + +Blip_Buffer::~Blip_Buffer() +{ + if (buffer_) + free( buffer_ ); +} + +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 ) +{ + // 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"; + + buffer_ = (buf_t_*) p; + } + + buffer_size_ = new_size; + + // update things based on the sample rate + sample_rate_ = new_rate; + length_ = new_size * 1000 / new_rate - 1; + if ( msec ) + assert( length_ == msec ); // ensure length is same as that passed in + 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; +} + +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); +} + +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 ); + +#ifndef WANT_STEREO_SOUND + 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 +#endif + { + 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 ) +{ + 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/blip/Blip_Buffer.h new/libretro-handy-0~git20200625/blip/Blip_Buffer.h --- old/libretro-handy-0~git20200107/blip/Blip_Buffer.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libretro-handy-0~git20200625/blip/Blip_Buffer.h 2020-06-25 22:54:05.000000000 +0200 @@ -0,0 +1,384 @@ +// Band-limited sound synthesis buffer +// Various changes and hacks for use in Mednafen. + +#ifdef __GNUC__ + #define blip_inline inline __attribute__((always_inline)) +#else + #define blip_inline inline +#endif + +#include <limits.h> +#include <stdint.h> + +// Blip_Buffer 0.4.1 +#ifndef BLIP_BUFFER_H +#define BLIP_BUFFER_H + +// Internal +typedef int32_t blip_long; +typedef uint32_t blip_ulong; +typedef int64_t blip_s64; +typedef uint64_t blip_u64; + +// Time unit at source clock rate +typedef blip_long blip_time_t; + +// Output samples are 16-bit signed, with a range of -32768 to 32767 +typedef short blip_sample_t; +enum { blip_sample_max = 32767 }; + +class Blip_Buffer { +public: + typedef const char* blargg_err_t; + + // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults + // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there + // isn't enough memory, returns error without affecting current buffer setup. + blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 ); + + // Set number of source time units per second + void clock_rate( long ); + + // End current time frame of specified duration and make its samples available + // (along with any still-unread samples) for reading with read_samples(). Begins + // a new time frame at the end of the current frame. + void end_frame( blip_time_t time ); + + // Read at most 'max_samples' out of buffer into 'dest', removing them from from + // the buffer. Returns number of samples actually read and removed. If stereo is + // true, increments 'dest' one extra time after writing each sample, to allow + // easy interleving of two channels into a stereo output buffer. + long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 ); + +// Additional optional features + + // Current output sample rate + long sample_rate() const; + + // Length of buffer, in milliseconds + int length() const; + + // Number of source time units per second + long clock_rate() const; + + // Set frequency high-pass filter frequency, where higher values reduce bass more + void bass_freq( int frequency ); + + // Number of samples delay from synthesis to samples read out + int output_latency() const; + + // Remove all available samples and clear buffer to silence. If 'entire_buffer' is + // false, just clears out any samples waiting rather than the entire buffer. + void clear( int entire_buffer = 1 ); + + // Number of samples available for reading with read_samples() + long samples_avail() const; + + // Remove 'count' samples from those waiting to be read + void remove_samples( long count ); + +// Experimental features + + // Count number of clocks needed until 'count' samples will be available. + // If buffer can't even hold 'count' samples, returns number of clocks until + // buffer becomes full. + blip_time_t count_clocks( long count ) const; + + // Number of raw samples that can be mixed within frame of specified duration. + long count_samples( blip_time_t duration ) const; + + // Mix 'count' samples from 'buf' into buffer. + void mix_samples( blip_sample_t const* buf, long count ); + + // not documented yet + void set_modified() { modified_ = 1; } + int clear_modified() { int b = modified_; modified_ = 0; return b; } + typedef blip_u64 blip_resampled_time_t; + void remove_silence( long count ); + blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; } + blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; } + blip_resampled_time_t clock_rate_factor( long clock_rate ) const; +public: + Blip_Buffer(); + ~Blip_Buffer(); + + // Deprecated + typedef blip_resampled_time_t resampled_time_t; + blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); } + blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); } +private: + // noncopyable + Blip_Buffer( const Blip_Buffer& ); + Blip_Buffer& operator = ( const Blip_Buffer& ); +public: + typedef blip_time_t buf_t_; + blip_u64 factor_; + blip_resampled_time_t offset_; + buf_t_* buffer_; + blip_long buffer_size_; + blip_long reader_accum_; + int bass_shift_; +private: + long sample_rate_; + long clock_rate_; + int bass_freq_; + int length_; + int modified_; + friend class Blip_Reader; +}; + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#define BLIP_BUFFER_ACCURACY 32 +#define BLIP_PHASE_BITS 8 + +// Number of bits in resample ratio fraction. Higher values give a more accurate ratio +// but reduce maximum buffer size. +//#ifndef BLIP_BUFFER_ACCURACY +// #define BLIP_BUFFER_ACCURACY 16 +//#endif + +// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in +// noticeable broadband noise when synthesizing high frequency square waves. +// Affects size of Blip_Synth objects since they store the waveform directly. +//#ifndef BLIP_PHASE_BITS +// #if BLIP_BUFFER_FAST +// #define BLIP_PHASE_BITS 8 +// #else +// #define BLIP_PHASE_BITS 6 +// #endif +//#endif + + // Internal + typedef blip_u64 blip_resampled_time_t; + int const blip_widest_impulse_ = 16; + int const blip_buffer_extra_ = blip_widest_impulse_ + 2; + int const blip_res = 1 << BLIP_PHASE_BITS; + class blip_eq_t; + + class Blip_Synth_Fast_ { + public: + Blip_Buffer* buf; + int last_amp; + int delta_factor; + + void volume_unit( double ); + Blip_Synth_Fast_(); + void treble_eq( blip_eq_t const& ) { } + }; + + class Blip_Synth_ { + public: + Blip_Buffer* buf; + int last_amp; + int delta_factor; + + void volume_unit( double ); + Blip_Synth_( short* impulses, int width ); + void treble_eq( blip_eq_t const& ); + private: + double volume_unit_; + short* const impulses; + int const width; + blip_long kernel_unit; + int impulses_size() const { return blip_res / 2 * width + 1; } + void adjust_impulse(); + }; + +// Quality level. Start with blip_good_quality. +const int blip_med_quality = 8; +const int blip_good_quality = 12; +const int blip_high_quality = 16; + +// Range specifies the greatest expected change in amplitude. Calculate it +// by finding the difference between the maximum and minimum expected +// amplitudes (max - min). +template<int quality,int range> +class Blip_Synth { +public: + // Set overall volume of waveform + void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); } + + // Configure low-pass filter (see blip_buffer.txt) + void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); } + + // Get/set Blip_Buffer used for output + Blip_Buffer* output() const { return impl.buf; } + void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; } + + // Update amplitude of waveform at given time. Using this requires a separate + // Blip_Synth for each waveform. + void update( blip_time_t time, int amplitude ); + +// Low-level interface + + // Add an amplitude transition of specified delta, optionally into specified buffer + // rather than the one set with output(). Delta can be positive or negative. + // The actual change in amplitude is delta * (volume / range) + void offset( blip_time_t, int delta, Blip_Buffer* ) const; + void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); } + + // Works directly in terms of fractional output samples. Contact author for more info. + void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const; + + // Same as offset(), except code is inlined for higher performance + void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { + offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); + } + void offset_inline( blip_time_t t, int delta ) const { + offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); + } + +private: + Blip_Synth_Fast_ impl; +}; + +// Low-pass equalization parameters +class blip_eq_t { +public: + // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce + // treble, small positive values (0 to 5.0) increase treble. + blip_eq_t( double treble_db = 0 ); + + // See 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; + +#define BLIP_RESTRICT + +// Optimized reading from Blip_Buffer, for use in custom sample output + +// Begin reading from buffer. Name should be unique to the current block. +#define BLIP_READER_BEGIN( name, blip_buffer ) \ + const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\ + blip_long name##_reader_accum = (blip_buffer).reader_accum_ + +// Get value to pass to BLIP_READER_NEXT() +#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_) + +// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal +// code at the cost of having no bass control +int const blip_reader_default_bass = 9; + +// Current sample +#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16)) + +// Current raw sample in full internal resolution +#define BLIP_READER_READ_RAW( name ) (name##_reader_accum) + +// Advance to next sample +#define BLIP_READER_NEXT( name, bass ) \ + (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass))) + +// End reading samples from buffer. The number of samples read must now be removed +// using Blip_Buffer::remove_samples(). +#define BLIP_READER_END( name, blip_buffer ) \ + (void) ((blip_buffer).reader_accum_ = name##_reader_accum) + + +// Compatibility with older version +const long blip_unscaled = 65535; +const int blip_low_quality = blip_med_quality; +const int blip_best_quality = blip_high_quality; + +// Deprecated; use BLIP_READER macros as follows: +// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf ); +// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf ); +// r.read() -> BLIP_READER_READ( r ) +// r.read_raw() -> BLIP_READER_READ_RAW( r ) +// r.next( bass ) -> BLIP_READER_NEXT( r, bass ) +// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass ) +// r.end( buf ) -> BLIP_READER_END( r, buf ) +class Blip_Reader { +public: + int begin( Blip_Buffer& ); + blip_long read() const { return accum >> (blip_sample_bits - 16); } + blip_long read_raw() const { return accum; } + void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); } + void end( Blip_Buffer& b ) { b.reader_accum_ = accum; } + +private: + const Blip_Buffer::buf_t_* buf; + blip_long accum; +}; + +// End of public interface + +#include <assert.h> + +template<int quality,int range> +blip_inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time, + int delta, Blip_Buffer* blip_buf ) const +{ + // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the + // need for a longer buffer as set by set_sample_rate(). + assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ ); + delta *= impl.delta_factor; + blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY); + int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1)); + + 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; +} + +#undef BLIP_FWD +#undef BLIP_REV + +template<int quality,int range> +blip_inline void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const +{ + offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); +} + +template<int quality,int range> +blip_inline void Blip_Synth<quality,range>::update( blip_time_t t, int amp ) +{ + int delta = amp - impl.last_amp; + impl.last_amp = amp; + offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); +} + +blip_inline blip_eq_t::blip_eq_t( double t ) : + treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { } +blip_inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) : + treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { } + +blip_inline int Blip_Buffer::length() const { return length_; } +blip_inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); } +blip_inline long Blip_Buffer::sample_rate() const { return sample_rate_; } +blip_inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; } +blip_inline long Blip_Buffer::clock_rate() const { return clock_rate_; } +blip_inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); } + +blip_inline int Blip_Reader::begin( Blip_Buffer& blip_buf ) +{ + buf = blip_buf.buffer_; + accum = blip_buf.reader_accum_; + return blip_buf.bass_shift_; +} + +int const blip_max_length = 0; +int const blip_default_length = 250; + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/blip/Stereo_Buffer.cpp new/libretro-handy-0~git20200625/blip/Stereo_Buffer.cpp --- old/libretro-handy-0~git20200107/blip/Stereo_Buffer.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libretro-handy-0~git20200625/blip/Stereo_Buffer.cpp 2020-06-25 22:54:05.000000000 +0200 @@ -0,0 +1,191 @@ +// Blip_Buffer 0.3.0. http://www.slack.net/~ant/nes-emu/ + +#include <blip/Stereo_Buffer.h> + +/* Library Copyright (C) 2004 Shay Green. Blip_Buffer 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. +Stereo_Buffer 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 Stereo_Buffer; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +Stereo_Buffer::Stereo_Buffer() { +} + +Stereo_Buffer::~Stereo_Buffer() { +} + +bool Stereo_Buffer::set_sample_rate( long rate, int msec ) +{ + for ( int i = 0; i < buf_count; i++ ) { + if ( bufs [i].set_sample_rate( rate, msec ) ) + { + return false; + } + } + + return true; +} + +void Stereo_Buffer::clock_rate( long rate ) +{ + for ( int i = 0; i < buf_count; i++ ) + bufs [i].clock_rate( rate ); +} + +void Stereo_Buffer::bass_freq( int bass ) +{ + for ( unsigned i = 0; i < buf_count; i++ ) + bufs [i].bass_freq( bass ); +} + +void Stereo_Buffer::clear() +{ + stereo_added = false; + was_stereo = false; + for ( int i = 0; i < buf_count; i++ ) + bufs [i].clear(); +} + +void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo ) +{ + for ( unsigned i = 0; i < buf_count; i++ ) + { + bufs [i].end_frame( clock_count ); + } + stereo_added = stereo; +} + + + +long Stereo_Buffer::read_samples( blip_sample_t* out, long max_samples ) +{ + long count = bufs [0].samples_avail(); + if ( count > max_samples / 2 ) + count = max_samples / 2; + if ( count ) + { + if ( stereo_added || was_stereo ) + { + mix_stereo( out, count ); + + bufs [0].remove_samples( count ); + bufs [1].remove_samples( count ); + bufs [2].remove_samples( count ); + } +#ifndef WANT_STEREO_SOUND + else + { + mix_mono( out, count ); + + bufs [0].remove_samples( count ); + + bufs [1].remove_silence( count ); + bufs [2].remove_silence( count ); + } +#endif + + // to do: this might miss opportunities for optimization + if ( !bufs [0].samples_avail() ) { + was_stereo = stereo_added; + stereo_added = false; + } + } + + return count * 2; +} + +void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count ) +{ + Blip_Reader left; + Blip_Reader right; + Blip_Reader center; + + left.begin( bufs [1] ); + right.begin( bufs [2] ); + int bass = center.begin( bufs [0] ); + + while ( count-- ) + { + int c = center.read(); + out [0] = c + left.read(); + out [1] = c + right.read(); + out += 2; + + center.next( bass ); + left.next( bass ); + right.next( bass ); + } + + center.end( bufs [0] ); + right.end( bufs [2] ); + left.end( bufs [1] ); +} + +void Stereo_Buffer::mix_stereo( float* out, long count ) +{ + Blip_Reader left; + Blip_Reader right; + Blip_Reader center; + + left.begin( bufs [1] ); + right.begin( bufs [2] ); + int bass = center.begin( bufs [0] ); + + while ( count-- ) + { + int c = center.read(); + out [0] = (float)(c + left.read()) / 32768; + out [1] = (float)(c + right.read()) / 32768; + out += 2; + + center.next( bass ); + left.next( bass ); + right.next( bass ); + } + + center.end( bufs [0] ); + right.end( bufs [2] ); + left.end( bufs [1] ); +} + +#ifndef WANT_STEREO_SOUND +void Stereo_Buffer::mix_mono( blip_sample_t* out, long count ) +{ + Blip_Reader in; + int bass = in.begin( bufs [0] ); + + while ( count-- ) + { + int sample = in.read(); + out [0] = sample; + out [1] = sample; + out += 2; + in.next( bass ); + } + + in.end( bufs [0] ); +} + +void Stereo_Buffer::mix_mono( float* out, long count ) +{ + Blip_Reader in; + int bass = in.begin( bufs [0] ); + + while ( count-- ) + { + int sample = in.read(); + out [0] = (float)(sample) / 32768; + out [1] = (float)(sample) / 32768; + out += 2; + in.next( bass ); + } + + in.end( bufs [0] ); +} +#endif + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/blip/Stereo_Buffer.h new/libretro-handy-0~git20200625/blip/Stereo_Buffer.h --- old/libretro-handy-0~git20200107/blip/Stereo_Buffer.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libretro-handy-0~git20200625/blip/Stereo_Buffer.h 2020-06-25 22:54:05.000000000 +0200 @@ -0,0 +1,71 @@ + +// Simple stereo Blip_Buffer for sound emulators whose oscillators output +// either on the left only, center, or right only. + +// Blip_Buffer 0.3.0. Copyright (C) 2003-2004 Shay Green. GNU GPL license. + +#ifndef STEREO_BUFFER_H +#define STEREO_BUFFER_H + +#include "Blip_Buffer.h" + +class Stereo_Buffer { +public: + Stereo_Buffer(); + ~Stereo_Buffer(); + + // Same as in Blip_Buffer (see Blip_Buffer.h) + bool set_sample_rate( long, int msec = 0 ); + void clock_rate( long ); + void bass_freq( int ); + void clear(); + + // Buffers to output synthesis to + Blip_Buffer* left(); + Blip_Buffer* center(); + Blip_Buffer* right(); + + // Same as in Blip_Buffer. For more efficient operation, pass false + // for was_stereo if the left and right buffers had nothing added + // to them for this frame. + void end_frame( blip_time_t, bool was_stereo = true ); + + // Output is stereo with channels interleved, left before right. Counts + // are in samples, *not* pairs. + long samples_avail() const; + long read_samples( blip_sample_t*, long ); + +private: + // noncopyable + Stereo_Buffer( const Stereo_Buffer& ); + Stereo_Buffer& operator = ( const Stereo_Buffer& ); + + enum { buf_count = 3 }; + Blip_Buffer bufs [buf_count]; + bool stereo_added; + bool was_stereo; + + void mix_stereo( blip_sample_t*, long ); + void mix_mono( blip_sample_t*, long ); + void mix_stereo( float*, long ); + void mix_mono( float*, long ); +}; + + inline Blip_Buffer* Stereo_Buffer::left() { + return &bufs [1]; + } + + inline Blip_Buffer* Stereo_Buffer::center() { + return &bufs [0]; + } + + inline Blip_Buffer* Stereo_Buffer::right() { + return &bufs [2]; + } + + inline long Stereo_Buffer::samples_avail() const { + return bufs [0].samples_avail(); + } + +#endif + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/libretro/libretro.cpp new/libretro-handy-0~git20200625/libretro/libretro.cpp --- old/libretro-handy-0~git20200107/libretro/libretro.cpp 2020-01-07 17:39:39.000000000 +0100 +++ new/libretro-handy-0~git20200625/libretro/libretro.cpp 2020-06-25 22:54:05.000000000 +0200 @@ -20,7 +20,8 @@ static uint8_t lynx_width = 160; static uint8_t lynx_height = 102; -static int VIDEO_CORE_PIXELSIZE = 2; +static int RETRO_PIX_BYTES = 2; +static int RETRO_PIX_DEPTH = 15; static uint8_t framebuffer[160*160*4]; @@ -68,6 +69,47 @@ static map* btn_map; +static bool update_video = false; + +static void check_color_depth(void) +{ + if (RETRO_PIX_DEPTH == 24) + { + enum retro_pixel_format rgb888 = RETRO_PIXEL_FORMAT_XRGB8888; + + if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb888)) + { + if(log_cb) log_cb(RETRO_LOG_ERROR, "Pixel format XRGB8888 not supported by platform.\n"); + + RETRO_PIX_BYTES = 2; + RETRO_PIX_DEPTH = 15; + } + } + + if (RETRO_PIX_BYTES == 2) + { +#if defined(FRONTEND_SUPPORTS_RGB565) + enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565; + + if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) + { + if(log_cb) log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); + + RETRO_PIX_DEPTH = 16; + } +#else + enum retro_pixel_format rgb555 = RETRO_PIXEL_FORMAT_0RGB1555; + + if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb555)) + { + if(log_cb) log_cb(RETRO_LOG_INFO, "Using default 0RGB1555 pixel format.\n"); + + RETRO_PIX_DEPTH = 15; + } +#endif + } +} + unsigned retro_api_version(void) { return RETRO_API_VERSION; @@ -86,7 +128,7 @@ if(!initialized) return (UBYTE*)framebuffer; - video_cb(framebuffer, lynx_width, lynx_height, 160*VIDEO_CORE_PIXELSIZE); + video_cb(framebuffer, lynx_width, lynx_height, 160*RETRO_PIX_BYTES); for(int total = 0; total < gAudioBufferPointer/4; ) @@ -125,11 +167,12 @@ break; } - if(VIDEO_CORE_PIXELSIZE == 2) { - lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_16BPP_565, 160*2, lynx_display_callback, (ULONG)0); - } - else if(VIDEO_CORE_PIXELSIZE == 4) { - lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_32BPP, 160*4, lynx_display_callback, (ULONG)0); + switch (RETRO_PIX_DEPTH) + { + case 15: lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_16BPP_555, 160*2, lynx_display_callback, (ULONG)0); break; + case 16: lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_16BPP_565, 160*2, lynx_display_callback, (ULONG)0); break; + case 24: lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_32BPP, 160*4, lynx_display_callback, (ULONG)0); break; + default: lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_32BPP, 160*4, lynx_display_callback, (ULONG)0); break; } update_geometry(); @@ -159,16 +202,23 @@ var.key = "handy_gfx_colors"; var.value = NULL; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - static bool once = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int old_value = RETRO_PIX_BYTES; - if (!once) { - if (strcmp(var.value, "16bit") == 0) - VIDEO_CORE_PIXELSIZE = 2; - else if (strcmp(var.value, "24bit") == 0) - VIDEO_CORE_PIXELSIZE = 4; - once = true; + if (strcmp(var.value, "16bit") == 0) + { + RETRO_PIX_BYTES = 2; + RETRO_PIX_DEPTH = 16; } + else if (strcmp(var.value, "24bit") == 0) + { + RETRO_PIX_BYTES = 4; + RETRO_PIX_DEPTH = 24; + } + + if (old_value != RETRO_PIX_BYTES) + update_video = true; } } @@ -179,28 +229,6 @@ if (log.log) log_cb = log.log; - btn_map = btn_map_no_rot; - - - check_variables(); - - if(VIDEO_CORE_PIXELSIZE == 4) { - enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; - if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { - if(log_cb) - log_cb(RETRO_LOG_ERROR, "[could not set RGB8888]\n"); - VIDEO_CORE_PIXELSIZE = 2; - } - } - - if(VIDEO_CORE_PIXELSIZE == 2) { - enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; - if(!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt) && log_cb) { - log_cb(RETRO_LOG_ERROR, "[could not set RGB565]\n"); - } - } - - uint64_t serialization_quirks = RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION; environ_cb(RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS, &serialization_quirks); } @@ -228,7 +256,7 @@ { static const struct retro_variable vars[] = { { "handy_rot", "Display rotation; None|90|270" }, - { "handy_gfx_colors", "Color Depth (Restart); 16bit|24bit" }, + { "handy_gfx_colors", "Color depth; 16bit|24bit" }, { NULL, NULL }, }; @@ -337,13 +365,6 @@ lynx = new CSystem(gamepath, romfilename, true); - if(VIDEO_CORE_PIXELSIZE == 2) { - lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_16BPP_565, 160*2, lynx_display_callback, (ULONG)0); - } - else if(VIDEO_CORE_PIXELSIZE == 4) { - lynx->DisplaySetAttributes(lynx_rot, MIKIE_PIXEL_FORMAT_32BPP, 160*4, lynx_display_callback, (ULONG)0); - } - return true; } @@ -376,17 +397,38 @@ void retro_run(void) { + bool updated = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + check_variables(); + lynx_input(); + if (update_video /*|| update_audio*/) + { + struct retro_system_av_info system_av_info; + + if (update_video) + { + memset(&system_av_info, 0, sizeof(system_av_info)); + environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &system_av_info); + + check_color_depth(); + lynx_rotate(); + } + + retro_get_system_av_info(&system_av_info); + environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &system_av_info); + + update_video = false; + //update_audio = false; + } + + gAudioLastUpdateCycle = gSystemCycleCount; + while (!newFrame) lynx->Update(); newFrame = false; - - - bool updated = false; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - check_variables(); } size_t retro_serialize_size(void) @@ -445,15 +487,23 @@ environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + check_variables(); + check_color_depth(); + if (!lynx_initialize_system(info->path)) return false; if (!lynx_initialize_sound()) return false; - check_variables(); + btn_map = btn_map_no_rot; + lynx_rotate(); + + update_video = false; + //update_audio = false; initialized = true; + return true; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/lynx/mikie.cpp new/libretro-handy-0~git20200625/lynx/mikie.cpp --- old/libretro-handy-0~git20200107/lynx/mikie.cpp 2020-01-07 17:39:39.000000000 +0100 +++ new/libretro-handy-0~git20200625/lynx/mikie.cpp 2020-06-25 22:54:05.000000000 +0200 @@ -90,6 +90,12 @@ for(loop=0;loop<16;loop++) mPalette[loop].Index=loop; for(loop=0;loop<4096;loop++) mColourMap[loop]=0; + mikbuf.set_sample_rate(HANDY_AUDIO_SAMPLE_FREQ, 60); + mikbuf.clock_rate(HANDY_SYSTEM_FREQ / 4); + mikbuf.bass_freq(60); + miksynth.volume(0.50); + miksynth.treble_eq(0); + Reset(); } @@ -1304,6 +1310,10 @@ mpDisplayCurrent=mpDisplayBits; break; } + + mikbuf.end_frame((gSystemCycleCount - gAudioLastUpdateCycle) / 4); + gAudioBufferPointer = mikbuf.read_samples((blip_sample_t*) gAudioBuffer, HANDY_AUDIO_BUFFER_SIZE / 2) * 2; + return 0; } @@ -2066,6 +2076,9 @@ TRACE_MIKIE3("Poke(%04x,%02x) - Poke to illegal location at PC=%04x",addr,data,mSystem.mCpu->GetPC()); break; } + + if(addr >= AUD0VOL && addr <= MSTEREO) + UpdateSound(); } @@ -3336,8 +3349,6 @@ // If sound is enabled then update the sound subsystem // if(gAudioEnabled) { - UpdateSound(); - // // Audio 0 // @@ -3665,11 +3676,18 @@ // TRACE_MIKIE1("Update() - mAUDIO_3_LASTCNT = %012d",mAUDIO_3_LAST_COUNT); // TRACE_MIKIE1("Update() - mAUDIO_3_LINKING = %012d",mAUDIO_3_LINKING); } + + UpdateSound(); } // if(gSystemCycleCount==gNextTimerEvent) gError->Warning("CMikie::Update() - gSystemCycleCount==gNextTimerEvent, system lock likely"); // TRACE_MIKIE1("Update() - NextTimerEvent = %012d",gNextTimerEvent); + // Update system IRQ status as a result of timer activity + gSystemIRQ=(mTimerStatusFlags)?true:false; + if(gSystemIRQ && gSystemCPUSleep) { ClearCPUSleep(); /*puts("ARLARM"); */ } + //else if(gSuzieDoneTime) SetCPUSleep(); + // Now all the timer updates are done we can increment the system // counter for any work done within the Update() function, gSystemCycleCounter // cannot be updated until this point otherwise it screws up the counters. @@ -3705,26 +3723,16 @@ } } - // Upsample to 16 bit signed - SWORD sample_l, sample_r; - sample_l= (cur_lsample<<5); // koennte auch 6 sein - sample_r= (cur_rsample<<5); // keep cool - - for(;gAudioLastUpdateCycle+HANDY_AUDIO_SAMPLE_PERIOD<gSystemCycleCount;gAudioLastUpdateCycle+=HANDY_AUDIO_SAMPLE_PERIOD) { - // Output audio sample - // Stereo 16 bit signed - *(SWORD *) &(gAudioBuffer[gAudioBufferPointer])=sample_l; - *(SWORD *) &(gAudioBuffer[gAudioBufferPointer+2])=sample_r; - gAudioBufferPointer+=4; - - // Check buffer overflow condition, stick at the endpoint - // teh audio output system will reset the input pointer - // when it reads out the data. - - // We should NEVER overflow, this buffer holds 0.25 seconds - // of data if this happens the the multimedia system above - // has failed so the corruption of the buffer contents wont matter + static int last_lsample = 0; + static int last_rsample = 0; + + if(cur_lsample != last_lsample) { + miksynth.offset_inline((gSystemCycleCount - gAudioLastUpdateCycle) / 4, cur_lsample - last_lsample, mikbuf.left()); + last_lsample = cur_lsample; + } - gAudioBufferPointer%=HANDY_AUDIO_BUFFER_SIZE; + if(cur_rsample != last_rsample) { + miksynth.offset_inline((gSystemCycleCount - gAudioLastUpdateCycle) / 4, cur_rsample - last_rsample, mikbuf.right()); + last_rsample = cur_rsample; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/lynx/mikie.h new/libretro-handy-0~git20200625/lynx/mikie.h --- old/libretro-handy-0~git20200107/lynx/mikie.h 2020-01-07 17:39:39.000000000 +0100 +++ new/libretro-handy-0~git20200625/lynx/mikie.h 2020-06-25 22:54:05.000000000 +0200 @@ -180,12 +180,19 @@ MIKIE_PIXEL_FORMAT_32BPP, }; +#include <blip/Stereo_Buffer.h> + +typedef Blip_Synth<blip_good_quality, 256 * 4> Synth; + class CMikie : public CLynxBase { public: CMikie(CSystem& parent); ~CMikie(); + Synth miksynth; + Stereo_Buffer mikbuf; + bool ContextSave(LSS_FILE *fp); bool ContextLoad(LSS_FILE *fp); void Reset(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libretro-handy-0~git20200107/lynx/susie.cpp new/libretro-handy-0~git20200625/lynx/susie.cpp --- old/libretro-handy-0~git20200107/lynx/susie.cpp 2020-01-07 17:39:39.000000000 +0100 +++ new/libretro-handy-0~git20200625/lynx/susie.cpp 2020-06-25 22:54:05.000000000 +0200 @@ -649,8 +649,8 @@ int screen_v_start=(SWORD)mVOFF.Word; int screen_v_end=(SWORD)mVOFF.Word+SCREEN_HEIGHT; - int world_h_mid=screen_h_start+0x8000+(SCREEN_WIDTH/2); - int world_v_mid=screen_v_start+0x8000+(SCREEN_HEIGHT/2); + int world_h_mid=screen_h_start+(SCREEN_WIDTH/2); + int world_v_mid=screen_v_start+(SCREEN_HEIGHT/2); TRACE_SUSIE2("PaintSprites() screen_h_start $%04x screen_h_end $%04x",screen_h_start,screen_h_end); TRACE_SUSIE2("PaintSprites() screen_v_start $%04x screen_v_end $%04x",screen_v_start,screen_v_end); @@ -672,7 +672,7 @@ // Check ref is inside screen area if((SWORD)mHPOSSTRT.Word<screen_h_start || (SWORD)mHPOSSTRT.Word>=screen_h_end || - (SWORD)mVPOSSTRT.Word<screen_v_start || (SWORD)mVPOSSTRT.Word>=screen_v_end) superclip=TRUE; + (SWORD)mVPOSSTRT.Word<screen_v_start || (SWORD)mVPOSSTRT.Word>=screen_v_end) superclip=TRUE; TRACE_SUSIE1("PaintSprites() Superclip=%d",superclip); @@ -719,7 +719,7 @@ // line, BUT on superclip we draw all the way to the end of any // given line checking each pixel is on screen. - if(superclip & 0) { + if(superclip) { // Check on the basis of each quad, we only render the quad // IF the screen is in the quad, relative to the centre of // the screen which is calculated below. @@ -749,16 +749,16 @@ switch(modquad) { case 3: - if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE; + if((sprite_h>=screen_h_start || sprite_h<=world_h_mid) && (sprite_v<screen_v_end || sprite_v>=world_v_mid)) render=TRUE; break; case 2: - if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE; + if((sprite_h>=screen_h_start || sprite_h<=world_h_mid) && (sprite_v>=screen_v_start || sprite_v<=world_v_mid)) render=TRUE; break; case 1: - if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE; + if((sprite_h<screen_h_end || sprite_h>=world_h_mid) && (sprite_v>=screen_v_start || sprite_v<=world_v_mid)) render=TRUE; break; default: - if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE; + if((sprite_h<screen_h_end || sprite_h>=world_h_mid) && (sprite_v<screen_v_end || sprite_v>=world_v_mid)) render=TRUE; break; } } else {