mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-27 13:04:21 +01:00
Merge pull request #710 from bladeoner/msu1
Add MSU1 audio support by qwertymodo
This commit is contained in:
commit
ecfc899496
@ -106,7 +106,7 @@ export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR)
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -106,7 +106,7 @@ export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR)
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -108,7 +108,7 @@ export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR)
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.xenon
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.xenon
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
|
@ -509,6 +509,7 @@ int BrowserLoadFile()
|
||||
// store the filename (w/o ext) - used for sram/freeze naming
|
||||
StripExt(Memory.ROMFilename, browserList[browser.selIndex].filename);
|
||||
snprintf(GCSettings.LastFileLoaded, MAXPATHLEN, "%s", browserList[browser.selIndex].filename);
|
||||
strncpy(Memory.ROMFilePath, browser.dir, PATH_MAX);
|
||||
|
||||
SNESROMSize = 0;
|
||||
S9xDeleteCheats();
|
||||
|
@ -472,8 +472,8 @@ DefaultSettings ()
|
||||
Settings.SixteenBitSound = true;
|
||||
Settings.Stereo = true;
|
||||
Settings.ReverseStereo = true;
|
||||
Settings.SoundPlaybackRate = 32000;
|
||||
Settings.SoundInputRate = 31953;
|
||||
Settings.SoundPlaybackRate = 32040;
|
||||
Settings.SoundInputRate = 32040;
|
||||
|
||||
// Graphics
|
||||
Settings.Transparency = true;
|
||||
|
@ -145,6 +145,9 @@
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
|
||||
MSU-1 code
|
||||
(c) Copyright 2016 qwertymodo
|
||||
|
||||
|
||||
Specific ports contains the works of other authors. See headers in
|
||||
individual files.
|
||||
@ -179,12 +182,13 @@
|
||||
#include <math.h>
|
||||
#include "snes9x.h"
|
||||
#include "apu.h"
|
||||
#include "msu1.h"
|
||||
#include "snapshot.h"
|
||||
#include "display.h"
|
||||
#include "linear_resampler.h"
|
||||
#include "hermite_resampler.h"
|
||||
|
||||
#define APU_DEFAULT_INPUT_RATE 32000
|
||||
#define APU_DEFAULT_INPUT_RATE 32040
|
||||
#define APU_MINIMUM_SAMPLE_COUNT 512
|
||||
#define APU_MINIMUM_SAMPLE_BLOCK 128
|
||||
#define APU_NUMERATOR_NTSC 15664
|
||||
@ -235,6 +239,15 @@ namespace spc
|
||||
static uint32 ratio_denominator = APU_DENOMINATOR_NTSC;
|
||||
}
|
||||
|
||||
namespace msu
|
||||
{
|
||||
static int buffer_size;
|
||||
static uint8 *landing_buffer = NULL;
|
||||
static Resampler *resampler = NULL;
|
||||
static int resample_buffer_size = -1;
|
||||
static uint8 *resample_buffer = NULL;
|
||||
}
|
||||
|
||||
static void EightBitize (uint8 *, int);
|
||||
static void DeStereo (uint8 *, int);
|
||||
static void ReverseStereo (uint8 *, int);
|
||||
@ -304,10 +317,18 @@ bool8 S9xMixSamples (uint8 *buffer, int sample_count)
|
||||
else
|
||||
dest = buffer;
|
||||
|
||||
if (Settings.MSU1 && msu::resample_buffer_size < (sample_count << 3))
|
||||
{
|
||||
delete[] msu::resample_buffer;
|
||||
msu::resample_buffer = new uint8[sample_count << 3];
|
||||
msu::resample_buffer_size = sample_count << 3;
|
||||
}
|
||||
|
||||
if (Settings.Mute)
|
||||
{
|
||||
memset(dest, 0, sample_count << 1);
|
||||
spc::resampler->clear();
|
||||
msu::resampler->clear();
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
@ -318,6 +339,18 @@ bool8 S9xMixSamples (uint8 *buffer, int sample_count)
|
||||
spc::resampler->read((short *) dest, sample_count);
|
||||
if (spc::lag == spc::lag_master)
|
||||
spc::lag = 0;
|
||||
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
if (msu::resampler->avail() >= sample_count)
|
||||
{
|
||||
msu::resampler->read((short *)msu::resample_buffer, sample_count);
|
||||
for (int32 i = 0; i < sample_count; ++i)
|
||||
*((int16*)(dest+(i * 2))) += *((int16*)(msu::resample_buffer+(i * 2)));
|
||||
}
|
||||
else // should never occur
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -356,8 +389,12 @@ int S9xGetSampleCount (void)
|
||||
|
||||
void S9xFinalizeSamples (void)
|
||||
{
|
||||
bool drop_current_msu1_samples = TRUE;
|
||||
|
||||
if (!Settings.Mute)
|
||||
{
|
||||
drop_current_msu1_samples = FALSE;
|
||||
|
||||
if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count()))
|
||||
{
|
||||
/* We weren't able to process the entire buffer. Potential overrun. */
|
||||
@ -365,6 +402,24 @@ void S9xFinalizeSamples (void)
|
||||
|
||||
if (Settings.SoundSync && !Settings.TurboMode)
|
||||
return;
|
||||
|
||||
// since we drop the current dsp samples we also want to drop generated msu1 samples
|
||||
drop_current_msu1_samples = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// only generate msu1 if we really consumed the dsp samples (sample_count() resets at end of function),
|
||||
// otherwise we will generate multiple times for the same samples - so this needs to be after all early
|
||||
// function returns
|
||||
if (Settings.MSU1)
|
||||
{
|
||||
// generate the same number of msu1 samples as dsp samples were generated
|
||||
S9xMSU1SetOutput((int16 *)msu::landing_buffer, msu::buffer_size);
|
||||
S9xMSU1Generate(spc_core->sample_count());
|
||||
if (!drop_current_msu1_samples && !msu::resampler->push((short *)msu::landing_buffer, S9xMSU1Samples()))
|
||||
{
|
||||
// should not occur, msu buffer is larger and we drop msu samples if spc buffer overruns
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,6 +445,8 @@ void S9xLandSamples (void)
|
||||
void S9xClearSamples (void)
|
||||
{
|
||||
spc::resampler->clear();
|
||||
if (Settings.MSU1)
|
||||
msu::resampler->clear();
|
||||
spc::lag = spc::lag_master;
|
||||
}
|
||||
|
||||
@ -416,6 +473,9 @@ void UpdatePlaybackRate (void)
|
||||
|
||||
double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator);
|
||||
spc::resampler->time_ratio(time_ratio);
|
||||
|
||||
time_ratio = (44100.0 / Settings.SoundPlaybackRate) * (Settings.SoundInputRate / 32040.0);
|
||||
msu::resampler->time_ratio(time_ratio);
|
||||
}
|
||||
|
||||
bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
||||
@ -423,8 +483,8 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
||||
// buffer_ms : buffer size given in millisecond
|
||||
// lag_ms : allowable time-lag given in millisecond
|
||||
|
||||
int sample_count = buffer_ms * 32000 / 1000;
|
||||
int lag_sample_count = lag_ms * 32000 / 1000;
|
||||
int sample_count = buffer_ms * 32040 / 1000;
|
||||
int lag_sample_count = lag_ms * 32040 / 1000;
|
||||
|
||||
spc::lag_master = lag_sample_count;
|
||||
if (Settings.Stereo)
|
||||
@ -439,6 +499,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
||||
spc::buffer_size <<= 1;
|
||||
if (Settings.SixteenBitSound)
|
||||
spc::buffer_size <<= 1;
|
||||
msu::buffer_size = sample_count << 3; // Always 16-bit, Stereo; x2 to never overflow before dsp buffer
|
||||
|
||||
printf("Sound buffer size: %d (%d samples)\n", spc::buffer_size, sample_count);
|
||||
|
||||
@ -447,6 +508,11 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
||||
spc::landing_buffer = new uint8[spc::buffer_size * 2];
|
||||
if (!spc::landing_buffer)
|
||||
return (FALSE);
|
||||
if (msu::landing_buffer)
|
||||
delete[] msu::landing_buffer;
|
||||
msu::landing_buffer = new uint8[msu::buffer_size * 2];
|
||||
if (!msu::landing_buffer)
|
||||
return (FALSE);
|
||||
|
||||
/* The resampler and spc unit use samples (16-bit short) as
|
||||
arguments. Use 2x in the resampler for buffer leveling with SoundSync */
|
||||
@ -462,6 +528,19 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
||||
else
|
||||
spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1));
|
||||
|
||||
|
||||
if (!msu::resampler)
|
||||
{
|
||||
msu::resampler = new APU_DEFAULT_RESAMPLER(msu::buffer_size >> (Settings.SoundSync ? 0 : 1));
|
||||
if (!msu::resampler)
|
||||
{
|
||||
delete[] msu::landing_buffer;
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
msu::resampler->resize(msu::buffer_size);
|
||||
|
||||
spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
|
||||
|
||||
UpdatePlaybackRate();
|
||||
@ -508,6 +587,7 @@ bool8 S9xInitAPU (void)
|
||||
spc::landing_buffer = NULL;
|
||||
spc::shrink_buffer = NULL;
|
||||
spc::resampler = NULL;
|
||||
msu::resampler = NULL;
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
@ -537,6 +617,24 @@ void S9xDeinitAPU (void)
|
||||
delete[] spc::shrink_buffer;
|
||||
spc::shrink_buffer = NULL;
|
||||
}
|
||||
|
||||
if (msu::resampler)
|
||||
{
|
||||
delete msu::resampler;
|
||||
msu::resampler = NULL;
|
||||
}
|
||||
|
||||
if (msu::landing_buffer)
|
||||
{
|
||||
delete[] msu::landing_buffer;
|
||||
msu::landing_buffer = NULL;
|
||||
}
|
||||
|
||||
if (msu::resample_buffer)
|
||||
{
|
||||
delete[] msu::resample_buffer;
|
||||
msu::resample_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int S9xAPUGetClock (int32 cpucycles)
|
||||
@ -612,6 +710,7 @@ void S9xResetAPU (void)
|
||||
spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
|
||||
|
||||
spc::resampler->clear();
|
||||
msu::resampler->clear();
|
||||
}
|
||||
|
||||
void S9xSoftResetAPU (void)
|
||||
@ -622,6 +721,7 @@ void S9xSoftResetAPU (void)
|
||||
spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
|
||||
|
||||
spc::resampler->clear();
|
||||
msu::resampler->clear();
|
||||
}
|
||||
|
||||
static void from_apu_to_state (uint8 **buf, void *var, size_t size)
|
||||
|
186
source/snes9x/apu/bapu/dsp/blargg_common.h
Normal file
186
source/snes9x/apu/bapu/dsp/blargg_common.h
Normal file
@ -0,0 +1,186 @@
|
||||
// Sets up common environment for Shay Green's libraries.
|
||||
// To change configuration options, modify blargg_config.h, not this file.
|
||||
|
||||
// snes_spc 0.9.0
|
||||
#ifndef BLARGG_COMMON_H
|
||||
#define BLARGG_COMMON_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#undef BLARGG_COMMON_H
|
||||
// allow blargg_config.h to #include blargg_common.h
|
||||
#include "blargg_config.h"
|
||||
#ifndef BLARGG_COMMON_H
|
||||
#define BLARGG_COMMON_H
|
||||
|
||||
// BLARGG_RESTRICT: equivalent to restrict, where supported
|
||||
#if defined (__GNUC__) || _MSC_VER >= 1100
|
||||
#define BLARGG_RESTRICT __restrict
|
||||
#else
|
||||
#define BLARGG_RESTRICT
|
||||
#endif
|
||||
|
||||
// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
|
||||
#ifndef STATIC_CAST
|
||||
#define STATIC_CAST(T,expr) ((T) (expr))
|
||||
#endif
|
||||
|
||||
// blargg_err_t (0 on success, otherwise error string)
|
||||
#ifndef blargg_err_t
|
||||
typedef const char* blargg_err_t;
|
||||
#endif
|
||||
|
||||
// blargg_vector - very lightweight vector of POD types (no constructor/destructor)
|
||||
template<class T>
|
||||
class blargg_vector {
|
||||
T* begin_;
|
||||
size_t size_;
|
||||
public:
|
||||
blargg_vector() : begin_( 0 ), size_( 0 ) { }
|
||||
~blargg_vector() { free( begin_ ); }
|
||||
size_t size() const { return size_; }
|
||||
T* begin() const { return begin_; }
|
||||
T* end() const { return begin_ + size_; }
|
||||
blargg_err_t resize( size_t n )
|
||||
{
|
||||
// TODO: blargg_common.cpp to hold this as an outline function, ugh
|
||||
void* p = realloc( begin_, n * sizeof (T) );
|
||||
if ( p )
|
||||
begin_ = (T*) p;
|
||||
else if ( n > size_ ) // realloc failure only a problem if expanding
|
||||
return "Out of memory";
|
||||
size_ = n;
|
||||
return 0;
|
||||
}
|
||||
void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); }
|
||||
T& operator [] ( size_t n ) const
|
||||
{
|
||||
assert( n <= size_ ); // <= to allow past-the-end value
|
||||
return begin_ [n];
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BLARGG_DISABLE_NOTHROW
|
||||
// throw spec mandatory in ISO C++ if operator new can return NULL
|
||||
#if __cplusplus >= 199711 || defined (__GNUC__)
|
||||
#define BLARGG_THROWS( spec ) throw spec
|
||||
#else
|
||||
#define BLARGG_THROWS( spec )
|
||||
#endif
|
||||
#define BLARGG_DISABLE_NOTHROW \
|
||||
void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
|
||||
void operator delete ( void* p ) { free( p ); }
|
||||
#define BLARGG_NEW new
|
||||
#else
|
||||
#include <new>
|
||||
#define BLARGG_NEW new (std::nothrow)
|
||||
#endif
|
||||
|
||||
// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant)
|
||||
#define BLARGG_4CHAR( a, b, c, d ) \
|
||||
((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
|
||||
|
||||
// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
|
||||
#ifndef BOOST_STATIC_ASSERT
|
||||
#ifdef _MSC_VER
|
||||
// MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified
|
||||
#define BOOST_STATIC_ASSERT( expr ) \
|
||||
void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
|
||||
#else
|
||||
// Some other compilers fail when declaring same function multiple times in class,
|
||||
// so differentiate them by line
|
||||
#define BOOST_STATIC_ASSERT( expr ) \
|
||||
void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1,
|
||||
// compiler is assumed to support bool. If undefined, availability is determined.
|
||||
#ifndef BLARGG_COMPILER_HAS_BOOL
|
||||
#if defined (__MWERKS__)
|
||||
#if !__option(bool)
|
||||
#define BLARGG_COMPILER_HAS_BOOL 0
|
||||
#endif
|
||||
#elif defined (_MSC_VER)
|
||||
#if _MSC_VER < 1100
|
||||
#define BLARGG_COMPILER_HAS_BOOL 0
|
||||
#endif
|
||||
#elif defined (__GNUC__)
|
||||
// supports bool
|
||||
#elif __cplusplus < 199711
|
||||
#define BLARGG_COMPILER_HAS_BOOL 0
|
||||
#endif
|
||||
#endif
|
||||
#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
|
||||
// If you get errors here, modify your blargg_config.h file
|
||||
typedef int bool;
|
||||
const bool true = 1;
|
||||
const bool false = 0;
|
||||
#endif
|
||||
|
||||
// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
|
||||
|
||||
#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
|
||||
typedef long blargg_long;
|
||||
#else
|
||||
typedef int blargg_long;
|
||||
#endif
|
||||
|
||||
#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long blargg_ulong;
|
||||
#else
|
||||
typedef unsigned blargg_ulong;
|
||||
#endif
|
||||
|
||||
// BOOST::int8_t etc.
|
||||
|
||||
// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
|
||||
#if defined (HAVE_STDINT_H)
|
||||
#include <stdint.h>
|
||||
#define BOOST
|
||||
|
||||
// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc.
|
||||
#elif defined (HAVE_INTTYPES_H)
|
||||
#include <inttypes.h>
|
||||
#define BOOST
|
||||
|
||||
#else
|
||||
struct BOOST
|
||||
{
|
||||
#if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#else
|
||||
// No suitable 8-bit type available
|
||||
typedef struct see_blargg_common_h int8_t;
|
||||
typedef struct see_blargg_common_h uint8_t;
|
||||
#endif
|
||||
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
#else
|
||||
// No suitable 16-bit type available
|
||||
typedef struct see_blargg_common_h int16_t;
|
||||
typedef struct see_blargg_common_h uint16_t;
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX == 0xFFFFFFFF
|
||||
typedef long int32_t;
|
||||
typedef unsigned long uint32_t;
|
||||
#elif UINT_MAX == 0xFFFFFFFF
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
// No suitable 32-bit type available
|
||||
typedef struct see_blargg_common_h int32_t;
|
||||
typedef struct see_blargg_common_h uint32_t;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
24
source/snes9x/apu/bapu/dsp/blargg_config.h
Normal file
24
source/snes9x/apu/bapu/dsp/blargg_config.h
Normal file
@ -0,0 +1,24 @@
|
||||
// snes_spc 0.9.0 user configuration file. Don't replace when updating library.
|
||||
|
||||
// snes_spc 0.9.0
|
||||
#ifndef BLARGG_CONFIG_H
|
||||
#define BLARGG_CONFIG_H
|
||||
|
||||
// Uncomment to disable debugging checks
|
||||
#define NDEBUG 1
|
||||
|
||||
// Uncomment to enable platform-specific (and possibly non-portable) optimizations
|
||||
//#define BLARGG_NONPORTABLE 1
|
||||
|
||||
// Uncomment if automatic byte-order determination doesn't work
|
||||
//#define BLARGG_BIG_ENDIAN 1
|
||||
|
||||
// Uncomment if you get errors in the bool section of blargg_common.h
|
||||
//#define BLARGG_COMPILER_HAS_BOOL 1
|
||||
|
||||
// Use standard config.h if present
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#endif
|
185
source/snes9x/apu/bapu/dsp/blargg_endian.h
Normal file
185
source/snes9x/apu/bapu/dsp/blargg_endian.h
Normal file
@ -0,0 +1,185 @@
|
||||
// CPU Byte Order Utilities
|
||||
|
||||
// snes_spc 0.9.0
|
||||
#ifndef BLARGG_ENDIAN
|
||||
#define BLARGG_ENDIAN
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
||||
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
|
||||
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
|
||||
#define BLARGG_CPU_X86 1
|
||||
#define BLARGG_CPU_CISC 1
|
||||
#endif
|
||||
|
||||
#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
|
||||
#define BLARGG_CPU_POWERPC 1
|
||||
#define BLARGG_CPU_RISC 1
|
||||
#endif
|
||||
|
||||
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
||||
// one may be #defined to 1. Only needed if something actually depends on byte order.
|
||||
#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
|
||||
#ifdef __GLIBC__
|
||||
// GCC handles this for us
|
||||
#include <endian.h>
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define BLARGG_BIG_ENDIAN 1
|
||||
#endif
|
||||
#else
|
||||
|
||||
#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
|
||||
(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
|
||||
defined (__sparc__) || BLARGG_CPU_POWERPC || \
|
||||
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
|
||||
#define BLARGG_BIG_ENDIAN 1
|
||||
#elif !defined (__mips__)
|
||||
// No endian specified; assume little-endian, since it's most common
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
|
||||
#undef BLARGG_LITTLE_ENDIAN
|
||||
#undef BLARGG_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
inline void blargg_verify_byte_order()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
#if BLARGG_BIG_ENDIAN
|
||||
volatile int i = 1;
|
||||
assert( *(volatile char*) &i == 0 );
|
||||
#elif BLARGG_LITTLE_ENDIAN
|
||||
volatile int i = 1;
|
||||
assert( *(volatile char*) &i != 0 );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned get_le16( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [1] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [0];
|
||||
}
|
||||
|
||||
inline unsigned get_be16( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [0] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [1];
|
||||
}
|
||||
|
||||
inline blargg_ulong get_le32( void const* p )
|
||||
{
|
||||
return (blargg_ulong) ((unsigned char const*) p) [3] << 24 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [2] << 16 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [1] << 8 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [0];
|
||||
}
|
||||
|
||||
inline blargg_ulong get_be32( void const* p )
|
||||
{
|
||||
return (blargg_ulong) ((unsigned char const*) p) [0] << 24 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [1] << 16 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [2] << 8 |
|
||||
(blargg_ulong) ((unsigned char const*) p) [3];
|
||||
}
|
||||
|
||||
inline void set_le16( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [0] = (unsigned char) n;
|
||||
}
|
||||
|
||||
inline void set_be16( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [1] = (unsigned char) n;
|
||||
}
|
||||
|
||||
inline void set_le32( void* p, blargg_ulong n )
|
||||
{
|
||||
((unsigned char*) p) [0] = (unsigned char) n;
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
||||
}
|
||||
|
||||
inline void set_be32( void* p, blargg_ulong n )
|
||||
{
|
||||
((unsigned char*) p) [3] = (unsigned char) n;
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
|
||||
}
|
||||
|
||||
#if BLARGG_NONPORTABLE
|
||||
// Optimized implementation if byte order is known
|
||||
#if BLARGG_LITTLE_ENDIAN
|
||||
#define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr))
|
||||
#define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr))
|
||||
#define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||
#define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||
#elif BLARGG_BIG_ENDIAN
|
||||
#define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr))
|
||||
#define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
|
||||
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||
|
||||
#if BLARGG_CPU_POWERPC
|
||||
// PowerPC has special byte-reversed instructions
|
||||
#if defined (__MWERKS__)
|
||||
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
|
||||
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
|
||||
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
|
||||
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
|
||||
#elif defined (__GNUC__)
|
||||
#define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;})
|
||||
#define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;})
|
||||
#define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );})
|
||||
#define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );})
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GET_LE16
|
||||
#define GET_LE16( addr ) get_le16( addr )
|
||||
#define SET_LE16( addr, data ) set_le16( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_LE32
|
||||
#define GET_LE32( addr ) get_le32( addr )
|
||||
#define SET_LE32( addr, data ) set_le32( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_BE16
|
||||
#define GET_BE16( addr ) get_be16( addr )
|
||||
#define SET_BE16( addr, data ) set_be16( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_BE32
|
||||
#define GET_BE32( addr ) get_be32( addr )
|
||||
#define SET_BE32( addr, data ) set_be32( addr, data )
|
||||
#endif
|
||||
|
||||
// auto-selecting versions
|
||||
|
||||
inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
|
||||
inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); }
|
||||
inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
|
||||
inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); }
|
||||
inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); }
|
||||
inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); }
|
||||
inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); }
|
||||
inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); }
|
||||
|
||||
#endif
|
@ -282,6 +282,7 @@ void S9xReset (void)
|
||||
S9xResetPPU();
|
||||
S9xResetDMA();
|
||||
S9xResetAPU();
|
||||
S9xResetMSU();
|
||||
|
||||
if (Settings.DSP)
|
||||
S9xResetDSP();
|
||||
@ -299,6 +300,8 @@ void S9xReset (void)
|
||||
S9xResetOBC1();
|
||||
if (Settings.SRTC)
|
||||
S9xResetSRTC();
|
||||
if (Settings.MSU1)
|
||||
S9xMSU1Init();
|
||||
|
||||
S9xInitCheatData();
|
||||
}
|
||||
@ -316,6 +319,7 @@ void S9xSoftReset (void)
|
||||
S9xSoftResetPPU();
|
||||
S9xResetDMA();
|
||||
S9xSoftResetAPU();
|
||||
S9xResetMSU();
|
||||
|
||||
if (Settings.DSP)
|
||||
S9xResetDSP();
|
||||
@ -333,6 +337,8 @@ void S9xSoftReset (void)
|
||||
S9xResetOBC1();
|
||||
if (Settings.SRTC)
|
||||
S9xResetSRTC();
|
||||
if (Settings.MSU1)
|
||||
S9xMSU1Init();
|
||||
|
||||
S9xInitCheatData();
|
||||
}
|
||||
|
@ -186,6 +186,7 @@
|
||||
#include "obc1.h"
|
||||
#include "seta.h"
|
||||
#include "bsx.h"
|
||||
#include "msu1.h"
|
||||
|
||||
#if (S9X_ACCURACY_LEVEL >= 2)
|
||||
|
||||
|
@ -219,6 +219,7 @@ struct SSPC7110Snapshot s7snap;
|
||||
struct SSRTCSnapshot srtcsnap;
|
||||
struct SRTCData RTCData;
|
||||
struct SBSX BSX;
|
||||
struct SMSU1 MSU1;
|
||||
struct SMulti Multi;
|
||||
struct SSettings Settings;
|
||||
struct SSNESGameFixes SNESGameFixes;
|
||||
|
@ -245,6 +245,7 @@ struct CMemory
|
||||
uint8 ExtendedFormat;
|
||||
|
||||
char ROMFilename[PATH_MAX + 1];
|
||||
char ROMFilePath[PATH_MAX + 1];
|
||||
char ROMName[ROM_NAME_LEN];
|
||||
char RawROMName[ROM_NAME_LEN];
|
||||
char ROMId[5];
|
||||
|
@ -495,6 +495,9 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte);
|
||||
#endif
|
||||
|
||||
if (Settings.MSU1 && (Address & 0xfff8) == 0x2000) // MSU-1
|
||||
S9xMSU1WritePort(Address & 7, Byte);
|
||||
else
|
||||
if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
|
||||
// write_port will run the APU until given clock before writing value
|
||||
S9xAPUWritePort(Address & 3, Byte);
|
||||
@ -1257,6 +1260,9 @@ uint8 S9xGetPPU (uint16 Address)
|
||||
{
|
||||
// MAP_PPU: $2000-$3FFF
|
||||
|
||||
if (Settings.MSU1 && (Address & 0xfff8) == 0x2000)
|
||||
return (S9xMSU1ReadPort(Address & 7));
|
||||
|
||||
if (Address < 0x2100)
|
||||
return (OpenBus);
|
||||
|
||||
|
@ -144,6 +144,9 @@
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
MSU-1 code
|
||||
(c) Copyright 2016 qwertymodo
|
||||
|
||||
|
||||
Specific ports contains the works of other authors. See headers in
|
||||
individual files.
|
||||
@ -1105,6 +1108,23 @@ static FreezeData SnapBSX[] =
|
||||
ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
#define STRUCT struct SMSU1
|
||||
|
||||
static FreezeData SnapMSU1[] =
|
||||
{
|
||||
INT_ENTRY(7, MSU1_STATUS),
|
||||
INT_ENTRY(7, MSU1_DATA_SEEK),
|
||||
INT_ENTRY(7, MSU1_DATA_POS),
|
||||
INT_ENTRY(7, MSU1_TRACK_SEEK),
|
||||
INT_ENTRY(7, MSU1_CURRENT_TRACK),
|
||||
INT_ENTRY(7, MSU1_RESUME_TRACK),
|
||||
INT_ENTRY(7, MSU1_VOLUME),
|
||||
INT_ENTRY(7, MSU1_CONTROL),
|
||||
INT_ENTRY(7, MSU1_AUDIO_POS),
|
||||
INT_ENTRY(7, MSU1_RESUME_POS)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
#define STRUCT struct SnapshotScreenshotInfo
|
||||
|
||||
@ -1341,6 +1361,9 @@ void S9xFreezeToStream (STREAM stream)
|
||||
if (Settings.BS)
|
||||
FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX));
|
||||
|
||||
if (Settings.MSU1)
|
||||
FreezeStruct(stream, "MSU", &MSU1, SnapMSU1, COUNT(SnapMSU1));
|
||||
|
||||
if (Settings.SnapshotScreenshots)
|
||||
{
|
||||
SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo;
|
||||
@ -1441,6 +1464,7 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
uint8 *local_srtc = NULL;
|
||||
uint8 *local_rtc_data = NULL;
|
||||
uint8 *local_bsx_data = NULL;
|
||||
uint8 *local_msu1_data = NULL;
|
||||
uint8 *local_screenshot = NULL;
|
||||
uint8 *local_movie_data = NULL;
|
||||
|
||||
@ -1546,6 +1570,10 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (result != SUCCESS && Settings.BS)
|
||||
break;
|
||||
|
||||
result = UnfreezeStructCopy(stream, "MSU", &local_msu1_data, SnapMSU1, COUNT(SnapMSU1), version);
|
||||
if (result != SUCCESS && Settings.MSU1)
|
||||
break;
|
||||
|
||||
result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version);
|
||||
|
||||
SnapshotMovieInfo mi;
|
||||
@ -1660,6 +1688,9 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (local_bsx_data)
|
||||
UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version);
|
||||
|
||||
if (local_msu1_data)
|
||||
UnfreezeStructFromCopy(&MSU1, SnapMSU1, COUNT(SnapMSU1), local_msu1_data, version);
|
||||
|
||||
CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG);
|
||||
ICPU.ShiftedPB = Registers.PB << 16;
|
||||
ICPU.ShiftedDB = Registers.DB << 16;
|
||||
@ -1707,6 +1738,9 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (local_bsx_data)
|
||||
S9xBSXPostLoadState();
|
||||
|
||||
if (local_msu1_data)
|
||||
S9xMSU1PostLoadState();
|
||||
|
||||
if (local_movie_data)
|
||||
{
|
||||
// restore last displayed pad_read status
|
||||
|
@ -144,6 +144,9 @@
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
MSU-1 code
|
||||
(c) Copyright 2016 qwertymodo
|
||||
|
||||
|
||||
Specific ports contains the works of other authors. See headers in
|
||||
individual files.
|
||||
@ -179,7 +182,7 @@
|
||||
#define _SNAPSHOT_H_
|
||||
|
||||
#define SNAPSHOT_MAGIC "#!s9xsnp"
|
||||
#define SNAPSHOT_VERSION 6
|
||||
#define SNAPSHOT_VERSION 7
|
||||
|
||||
#define SUCCESS 1
|
||||
#define WRONG_FORMAT (-1)
|
||||
|
@ -359,6 +359,7 @@ struct SSettings
|
||||
bool8 BS;
|
||||
bool8 BSXItself;
|
||||
bool8 BSXBootup;
|
||||
bool8 MSU1;
|
||||
bool8 MouseMaster;
|
||||
bool8 SuperScopeMaster;
|
||||
bool8 JustifierMaster;
|
||||
|
Loading…
Reference in New Issue
Block a user