Allow membased rom/state load/save, add libsnes interface (Themaister)

This commit is contained in:
OV2 2012-01-02 01:48:51 +01:00
parent 8a8d7b5646
commit dee8895db2
25 changed files with 3527 additions and 238 deletions

View File

@ -120,6 +120,8 @@ public:
uint8_t dsp_reg_value( int, int );
int dsp_envx_value( int );
uint8_t *apuram();
//// Snes9x Debugger
#ifdef DEBUGGER
@ -313,4 +315,6 @@ inline bool SNES_SPC::check_kon() { return dsp.check_kon(); }
inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; }
inline SNES_SPC::uint8_t * SNES_SPC::apuram() { return m.ram.ram; }
#endif

View File

@ -209,16 +209,16 @@ void ConfigFile::Clear(void){
}
bool ConfigFile::LoadFile(const char *filename){
STREAM s;
FSTREAM s;
bool ret=false;
const char *n, *n2;
if((s=OPEN_STREAM(filename, "r"))){
if((s=OPEN_FSTREAM(filename, "r"))){
n=filename;
n2=strrchr(n, '/'); if(n2!=NULL) n=n2+1;
n2=strrchr(n, '\\'); if(n2!=NULL) n=n2+1;
LoadFile(new fReader(s), n);
CLOSE_STREAM(s);
LoadFile(new fStream(s), n);
CLOSE_FSTREAM(s);
ret = true;
} else {
fprintf(stderr, "Couldn't open conffile ");
@ -228,7 +228,7 @@ bool ConfigFile::LoadFile(const char *filename){
}
void ConfigFile::LoadFile(Reader *r, const char *name){
void ConfigFile::LoadFile(Stream *r, const char *name){
curConfigFile = this;
string l, key, val;
string section;

View File

@ -188,7 +188,6 @@
#include "unzip/unzip.h"
#endif
#include "snes9x.h"
#include "reader.h"
#ifndef MAX
# define MAX(a,b) ((a) > (b)? (a) : (b))
@ -203,7 +202,7 @@ class ConfigFile {
// return false on failure
bool LoadFile(const char *filename);
void LoadFile(Reader *r, const char *name=NULL);
void LoadFile(Stream *r, const char *name=NULL);
// return false if key does not exist or is empty
bool Exists(const char *key);

View File

@ -157,7 +157,7 @@ snes9x_gtk_SOURCES += \
../dma.cpp \
../snes9x.cpp \
../globals.cpp \
../reader.cpp \
../stream.cpp \
../conffile.cpp \
../bsx.cpp \
../logger.cpp \

53
libsnes/Makefile Normal file
View File

@ -0,0 +1,53 @@
ifeq ($(platform),)
platform = unix
ifeq ($(shell uname -a),)
platform = win
else ifneq ($(findstring MINGW,$(shell uname -a)),)
platform = win
else ifneq ($(findstring win,$(shell uname -a)),)
platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
platform = osx
endif
endif
ifeq ($(platform), unix)
TARGET := libsnes.so
fpic := -fPIC
SHARED := -shared -Wl,--version-script=link.T
else ifeq ($(platform), osx)
TARGET := libsnes.dylib
fpic := -fPIC
SHARED := -dynamiclib
else
TARGET := snes.dll
CC = gcc
CXX = g++
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T
CXXFLAGS += -D__WIN32__ -D__WIN32_LIBSNES__
endif
OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o libsnes.o
CXX = g++
CC = gcc
INCLUDES = -I. -I.. -I../apu/
CXXFLAGS += -O3 -fomit-frame-pointer -fno-exceptions -fno-rtti -pedantic -Wall -W -Wno-unused-parameter $(fpic)
CXXFLAGS += -DHAVE_STRINGS_H -DHAVE_STDINT_H -DRIGHTSHIFT_IS_SAR
CFLAGS = $(CXXFLAGS)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CXX) $(fpic) $(SHARED) $(INCLUDES) -o $@ $(OBJECTS) -lm
%.o: %.cpp
$(CXX) $(INCLUDES) $(CXXFLAGS) -c -o $@ $<
%.o: %.c
$(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(OBJECTS) $(TARGET)

View File

@ -0,0 +1,794 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="libsnes-win32"
ProjectGUID="{4A2A7544-0547-4539-8B53-047FB9A15C75}"
RootNamespace="libsneswin32"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="libsnes Debug|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="__WIN32__;__WIN32_LIBSNES__"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="2"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\snes.dll"
LinkIncremental="2"
ModuleDefinitionFile="libsnes.def"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="libsnes Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="__WIN32__;__WIN32_LIBSNES__"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="2"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\snes.dll"
LinkIncremental="2"
ModuleDefinitionFile="libsnes.def"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="libsnes Release|Win32"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="__WIN32__;__WIN32_LIBSNES__"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="2"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\snes.dll"
LinkIncremental="1"
ModuleDefinitionFile="libsnes.def"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="libsnes Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="__WIN32__;__WIN32_LIBSNES__"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="2"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\snes.dll"
LinkIncremental="1"
ModuleDefinitionFile="libsnes.def"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="s9x-source"
>
<File
RelativePath="..\65c816.h"
>
</File>
<File
RelativePath="..\bsx.cpp"
>
</File>
<File
RelativePath="..\bsx.h"
>
</File>
<File
RelativePath="..\c4.cpp"
>
</File>
<File
RelativePath="..\c4.h"
>
</File>
<File
RelativePath="..\c4emu.cpp"
>
</File>
<File
RelativePath="..\cheats.cpp"
>
</File>
<File
RelativePath="..\cheats.h"
>
</File>
<File
RelativePath="..\cheats2.cpp"
>
</File>
<File
RelativePath="..\clip.cpp"
>
</File>
<File
RelativePath="..\conffile.cpp"
>
</File>
<File
RelativePath="..\conffile.h"
>
</File>
<File
RelativePath="..\controls.cpp"
>
</File>
<File
RelativePath="..\controls.h"
>
</File>
<File
RelativePath="..\cpu.cpp"
>
</File>
<File
RelativePath="..\cpuaddr.h"
>
</File>
<File
RelativePath="..\cpuexec.cpp"
>
</File>
<File
RelativePath="..\cpuexec.h"
>
</File>
<File
RelativePath="..\cpumacro.h"
>
</File>
<File
RelativePath="..\cpuops.cpp"
>
</File>
<File
RelativePath="..\cpuops.h"
>
</File>
<File
RelativePath="..\crosshairs.cpp"
>
</File>
<File
RelativePath="..\crosshairs.h"
>
</File>
<File
RelativePath="..\debug.cpp"
>
</File>
<File
RelativePath="..\debug.h"
>
</File>
<File
RelativePath="..\display.h"
>
</File>
<File
RelativePath="..\dma.cpp"
>
</File>
<File
RelativePath="..\dma.h"
>
</File>
<File
RelativePath="..\dsp.cpp"
>
</File>
<File
RelativePath="..\dsp.h"
>
</File>
<File
RelativePath="..\dsp1.cpp"
>
</File>
<File
RelativePath="..\dsp2.cpp"
>
</File>
<File
RelativePath="..\dsp3.cpp"
>
</File>
<File
RelativePath="..\dsp4.cpp"
>
</File>
<File
RelativePath="..\font.h"
>
</File>
<File
RelativePath="..\fxemu.cpp"
>
</File>
<File
RelativePath="..\fxemu.h"
>
</File>
<File
RelativePath="..\fxinst.cpp"
>
</File>
<File
RelativePath="..\fxinst.h"
>
</File>
<File
RelativePath="..\getset.h"
>
</File>
<File
RelativePath="..\gfx.cpp"
>
</File>
<File
RelativePath="..\gfx.h"
>
</File>
<File
RelativePath="..\globals.cpp"
>
</File>
<File
RelativePath="..\language.h"
>
</File>
<File
RelativePath="..\loadzip.cpp"
>
</File>
<File
RelativePath="..\logger.cpp"
>
</File>
<File
RelativePath="..\logger.h"
>
</File>
<File
RelativePath="..\memmap.cpp"
>
</File>
<File
RelativePath="..\memmap.h"
>
</File>
<File
RelativePath="..\messages.h"
>
</File>
<File
RelativePath="..\missing.h"
>
</File>
<File
RelativePath="..\movie.cpp"
>
</File>
<File
RelativePath="..\movie.h"
>
</File>
<File
RelativePath="..\netplay.cpp"
>
</File>
<File
RelativePath="..\netplay.h"
>
</File>
<File
RelativePath="..\obc1.cpp"
>
</File>
<File
RelativePath="..\obc1.h"
>
</File>
<File
RelativePath="..\pixform.h"
>
</File>
<File
RelativePath="..\port.h"
>
</File>
<File
RelativePath="..\ppu.cpp"
>
</File>
<File
RelativePath="..\ppu.h"
>
</File>
<File
RelativePath="..\sa1.cpp"
>
</File>
<File
RelativePath="..\sa1.h"
>
</File>
<File
RelativePath="..\sa1cpu.cpp"
>
</File>
<File
RelativePath="..\sar.h"
>
</File>
<File
RelativePath="..\screenshot.cpp"
>
</File>
<File
RelativePath="..\screenshot.h"
>
</File>
<File
RelativePath="..\sdd1.cpp"
>
</File>
<File
RelativePath="..\sdd1.h"
>
</File>
<File
RelativePath="..\sdd1emu.cpp"
>
</File>
<File
RelativePath="..\sdd1emu.h"
>
</File>
<File
RelativePath="..\server.cpp"
>
</File>
<File
RelativePath="..\seta.cpp"
>
</File>
<File
RelativePath="..\seta.h"
>
</File>
<File
RelativePath="..\seta010.cpp"
>
</File>
<File
RelativePath="..\seta011.cpp"
>
</File>
<File
RelativePath="..\seta018.cpp"
>
</File>
<File
RelativePath="..\snapshot.cpp"
>
</File>
<File
RelativePath="..\snapshot.h"
>
</File>
<File
RelativePath="..\snes9x.cpp"
>
</File>
<File
RelativePath="..\snes9x.h"
>
</File>
<File
RelativePath="..\spc7110.cpp"
>
</File>
<File
RelativePath="..\spc7110.h"
>
</File>
<File
RelativePath="..\srtc.cpp"
>
</File>
<File
RelativePath="..\srtc.h"
>
</File>
<File
RelativePath="..\stream.cpp"
>
</File>
<File
RelativePath="..\stream.h"
>
</File>
<File
RelativePath="..\tile.cpp"
>
</File>
<File
RelativePath="..\tile.h"
>
</File>
<Filter
Name="APU"
>
<File
RelativePath="..\apu\apu.cpp"
>
</File>
<File
RelativePath="..\apu\apu.h"
>
</File>
<File
RelativePath="..\apu\blargg_common.h"
>
</File>
<File
RelativePath="..\apu\blargg_config.h"
>
</File>
<File
RelativePath="..\apu\blargg_endian.h"
>
</File>
<File
RelativePath="..\apu\blargg_source.h"
>
</File>
<File
RelativePath="..\apu\hermite_resampler.h"
>
</File>
<File
RelativePath="..\apu\linear_resampler.h"
>
</File>
<File
RelativePath="..\apu\resampler.h"
>
</File>
<File
RelativePath="..\apu\ring_buffer.h"
>
</File>
<File
RelativePath="..\apu\SNES_SPC.cpp"
>
</File>
<File
RelativePath="..\apu\SNES_SPC.h"
>
</File>
<File
RelativePath="..\apu\SNES_SPC_misc.cpp"
>
</File>
<File
RelativePath="..\apu\SNES_SPC_state.cpp"
>
</File>
<File
RelativePath="..\apu\SPC_CPU.h"
>
</File>
<File
RelativePath="..\apu\SPC_DSP.cpp"
>
</File>
<File
RelativePath="..\apu\SPC_DSP.h"
>
</File>
<File
RelativePath="..\apu\SPC_Filter.cpp"
>
</File>
<File
RelativePath="..\apu\SPC_Filter.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="libsnes"
>
<File
RelativePath=".\libsnes.cpp"
>
</File>
<File
RelativePath=".\libsnes.def"
>
</File>
<File
RelativePath=".\libsnes.hpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

754
libsnes/libsnes.cpp Normal file
View File

@ -0,0 +1,754 @@
#include "libsnes.hpp"
#include "snes9x.h"
#include "memmap.h"
#include "srtc.h"
#include "apu/apu.h"
#include "gfx.h"
#include "snapshot.h"
#include "controls.h"
#include "cheats.h"
#include "movie.h"
#include "logger.h"
#include "display.h"
#include "conffile.h"
#include <stdio.h>
#ifndef __WIN32__
#include <unistd.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
static snes_video_refresh_t s9x_video_cb = NULL;
static snes_audio_sample_t s9x_audio_cb = NULL;
static snes_input_poll_t s9x_poller_cb = NULL;
static snes_input_state_t s9x_input_state_cb = NULL;
void snes_set_video_refresh(snes_video_refresh_t cb)
{
s9x_video_cb = cb;
}
void snes_set_audio_sample(snes_audio_sample_t cb)
{
s9x_audio_cb = cb;
}
void snes_set_input_poll(snes_input_poll_t cb)
{
s9x_poller_cb = cb;
}
void snes_set_input_state(snes_input_state_t cb)
{
s9x_input_state_cb = cb;
}
static snes_environment_t environ_cb;
static bool use_overscan;
void snes_set_environment(snes_environment_t cb)
{
environ_cb = cb;
}
static void S9xAudioCallback(void*)
{
// Just pick a big buffer. We won't use it all.
static int16_t audio_buf[0x10000];
S9xFinalizeSamples();
size_t avail = S9xGetSampleCount();
S9xMixSamples((uint8*)audio_buf, avail);
for (size_t i = 0; i < avail; i+=2)
s9x_audio_cb((uint16_t)audio_buf[i], (uint16_t)audio_buf[i + 1]);
}
const char *snes_library_id()
{
return "SNES9x v" VERSION;
}
unsigned snes_library_revision_major()
{
return 1;
}
unsigned snes_library_revision_minor()
{
return 3;
}
void snes_power()
{
S9xReset();
}
void snes_reset()
{
S9xMovieUpdateOnReset();
if (S9xMoviePlaying())
{
S9xMovieStop(true);
}
S9xSoftReset();
}
static unsigned snes_devices[2];
void snes_set_controller_port_device(bool in_port, unsigned device)
{
int port = in_port == SNES_PORT_1 ? 0 : 1;
switch (device)
{
case SNES_DEVICE_JOYPAD:
S9xSetController(port, CTL_JOYPAD, 0, 0, 0, 0);
snes_devices[port] = SNES_DEVICE_JOYPAD;
break;
case SNES_DEVICE_MULTITAP:
S9xSetController(port, CTL_MP5, 1, 2, 3, 4);
snes_devices[port] = SNES_DEVICE_MULTITAP;
break;
case SNES_DEVICE_MOUSE:
S9xSetController(port, CTL_MOUSE, 0, 0, 0, 0);
snes_devices[port] = SNES_DEVICE_MOUSE;
break;
case SNES_DEVICE_SUPER_SCOPE:
S9xSetController(port, CTL_SUPERSCOPE, 0, 0, 0, 0);
snes_devices[port] = SNES_DEVICE_SUPER_SCOPE;
break;
case SNES_DEVICE_JUSTIFIER:
S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0);
snes_devices[port] = SNES_DEVICE_JUSTIFIER;
break;
case SNES_DEVICE_JUSTIFIERS:
S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0);
snes_devices[port] = SNES_DEVICE_JUSTIFIERS;
break;
default:
fprintf(stderr, "[libsnes]: Invalid device!\n");
}
}
void snes_cheat_reset()
{}
void snes_cheat_set(unsigned, bool, const char*)
{}
bool snes_load_cartridge_bsx_slotted(
const char *, const uint8_t *, unsigned,
const char *, const uint8_t *, unsigned
)
{
return false;
}
bool snes_load_cartridge_bsx(
const char *, const uint8_t *, unsigned,
const char *, const uint8_t *, unsigned
)
{
return false;
}
bool snes_load_cartridge_sufami_turbo(
const char *, const uint8_t *, unsigned,
const char *, const uint8_t *, unsigned,
const char *, const uint8_t *, unsigned
)
{
return false;
}
bool snes_load_cartridge_super_game_boy(
const char *, const uint8_t *, unsigned,
const char *, const uint8_t *, unsigned
)
{
return false;
}
static void map_buttons();
void snes_init()
{
if (environ_cb)
{
if (!environ_cb(SNES_ENVIRONMENT_GET_OVERSCAN, &use_overscan))
use_overscan = false;
if (use_overscan)
{
snes_geometry geom = {256, 239, 512, 512};
environ_cb(SNES_ENVIRONMENT_SET_GEOMETRY, &geom);
unsigned pitch = 1024;
environ_cb(SNES_ENVIRONMENT_SET_PITCH, &pitch);
}
}
memset(&Settings, 0, sizeof(Settings));
Settings.MouseMaster = TRUE;
Settings.SuperScopeMaster = TRUE;
Settings.JustifierMaster = TRUE;
Settings.MultiPlayer5Master = TRUE;
Settings.FrameTimePAL = 20000;
Settings.FrameTimeNTSC = 16667;
Settings.SixteenBitSound = TRUE;
Settings.Stereo = TRUE;
Settings.SoundPlaybackRate = 32000;
Settings.SoundInputRate = 32000;
Settings.SupportHiRes = TRUE;
Settings.Transparency = TRUE;
Settings.AutoDisplayMessages = TRUE;
Settings.InitialInfoStringTimeout = 120;
Settings.HDMATimingHack = 100;
Settings.BlockInvalidVRAMAccessMaster = TRUE;
Settings.StopEmulation = TRUE;
Settings.WrongMovieStateProtection = TRUE;
Settings.DumpStreamsMaxFrames = -1;
Settings.StretchScreenshots = 0;
Settings.SnapshotScreenshots = FALSE;
Settings.SkipFrames = AUTO_FRAMERATE;
Settings.TurboSkipFrames = 15;
Settings.CartAName[0] = 0;
Settings.CartBName[0] = 0;
Settings.AutoSaveDelay = 1;
CPU.Flags = 0;
if (!Memory.Init() || !S9xInitAPU())
{
Memory.Deinit();
S9xDeinitAPU();
fprintf(stderr, "[libsnes]: Failed to init Memory or APU.\n");
exit(1);
}
S9xInitSound(16, 0);
S9xSetSoundMute(FALSE);
S9xSetSamplesAvailableCallback(S9xAudioCallback, NULL);
S9xSetRenderPixelFormat(RGB555);
GFX.Pitch = use_overscan ? 1024 : 2048;
GFX.Screen = (uint16*) calloc(1, GFX.Pitch * 512 * sizeof(uint16));
S9xGraphicsInit();
S9xInitInputDevices();
for (int i = 0; i < 2; i++)
{
S9xSetController(i, CTL_JOYPAD, i, 0, 0, 0);
snes_devices[i] = SNES_DEVICE_JOYPAD;
}
S9xUnmapAllControls();
map_buttons();
}
#define MAP_BUTTON(id, name) S9xMapButton((id), S9xGetCommandT((name)), false)
#define MAKE_BUTTON(pad, btn) (((pad)<<4)|(btn))
#define PAD_1 1
#define PAD_2 2
#define PAD_3 3
#define PAD_4 4
#define PAD_5 5
#define BTN_B SNES_DEVICE_ID_JOYPAD_B
#define BTN_Y SNES_DEVICE_ID_JOYPAD_Y
#define BTN_SELECT SNES_DEVICE_ID_JOYPAD_SELECT
#define BTN_START SNES_DEVICE_ID_JOYPAD_START
#define BTN_UP SNES_DEVICE_ID_JOYPAD_UP
#define BTN_DOWN SNES_DEVICE_ID_JOYPAD_DOWN
#define BTN_LEFT SNES_DEVICE_ID_JOYPAD_LEFT
#define BTN_RIGHT SNES_DEVICE_ID_JOYPAD_RIGHT
#define BTN_A SNES_DEVICE_ID_JOYPAD_A
#define BTN_X SNES_DEVICE_ID_JOYPAD_X
#define BTN_L SNES_DEVICE_ID_JOYPAD_L
#define BTN_R SNES_DEVICE_ID_JOYPAD_R
#define BTN_FIRST BTN_B
#define BTN_LAST BTN_R
#define MOUSE_X SNES_DEVICE_ID_MOUSE_X
#define MOUSE_Y SNES_DEVICE_ID_MOUSE_Y
#define MOUSE_LEFT SNES_DEVICE_ID_MOUSE_LEFT
#define MOUSE_RIGHT SNES_DEVICE_ID_MOUSE_RIGHT
#define MOUSE_FIRST MOUSE_X
#define MOUSE_LAST MOUSE_RIGHT
#define SCOPE_X SNES_DEVICE_ID_SUPER_SCOPE_X
#define SCOPE_Y SNES_DEVICE_ID_SUPER_SCOPE_Y
#define SCOPE_TRIGGER SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER
#define SCOPE_CURSOR SNES_DEVICE_ID_SUPER_SCOPE_CURSOR
#define SCOPE_TURBO SNES_DEVICE_ID_SUPER_SCOPE_TURBO
#define SCOPE_PAUSE SNES_DEVICE_ID_SUPER_SCOPE_PAUSE
#define SCOPE_FIRST SCOPE_X
#define SCOPE_LAST SCOPE_PAUSE
#define JUSTIFIER_X SNES_DEVICE_ID_JUSTIFIER_X
#define JUSTIFIER_Y SNES_DEVICE_ID_JUSTIFIER_Y
#define JUSTIFIER_TRIGGER SNES_DEVICE_ID_JUSTIFIER_TRIGGER
#define JUSTIFIER_START SNES_DEVICE_ID_JUSTIFIER_START
#define JUSTIFIER_FIRST JUSTIFIER_X
#define JUSTIFIER_LAST JUSTIFIER_START
#define BTN_POINTER (BTN_LAST + 1)
#define BTN_POINTER2 (BTN_POINTER + 1)
static void map_buttons()
{
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_A), "Joypad1 A");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_B), "Joypad1 B");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_X), "Joypad1 X");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_Y), "Joypad1 Y");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_SELECT), "{Joypad1 Select,Mouse1 L}");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_START), "{Joypad1 Start,Mouse1 R}");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_L), "Joypad1 L");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_R), "Joypad1 R");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_LEFT), "Joypad1 Left");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_RIGHT), "Joypad1 Right");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_UP), "Joypad1 Up");
MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_DOWN), "Joypad1 Down");
S9xMapPointer((BTN_POINTER), S9xGetCommandT("Pointer Mouse1+Superscope+Justifier1"), false);
S9xMapPointer((BTN_POINTER2), S9xGetCommandT("Pointer Mouse2"), false);
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_A), "Joypad2 A");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_B), "Joypad2 B");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_X), "Joypad2 X");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_Y), "Joypad2 Y");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_SELECT), "{Joypad2 Select,Mouse2 L,Superscope Fire,Justifier1 Trigger}");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_START), "{Joypad2 Start,Mouse2 R,Superscope Cursor,Justifier1 Start}");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_L), "Joypad2 L");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_R), "Joypad2 R");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_LEFT), "Joypad2 Left");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_RIGHT), "Joypad2 Right");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_UP), "{Joypad2 Up,Superscope ToggleTurbo}");
MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_DOWN), "{Joypad2 Down,Superscope Pause}");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_A), "Joypad3 A");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_B), "Joypad3 B");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_X), "Joypad3 X");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_Y), "Joypad3 Y");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_SELECT), "Joypad3 Select");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_START), "Joypad3 Start");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_L), "Joypad3 L");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_R), "Joypad3 R");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_LEFT), "Joypad3 Left");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_RIGHT), "Joypad3 Right");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_UP), "Joypad3 Up");
MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_DOWN), "Joypad3 Down");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_A), "Joypad4 A");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_B), "Joypad4 B");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_X), "Joypad4 X");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_Y), "Joypad4 Y");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_SELECT), "Joypad4 Select");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_START), "Joypad4 Start");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_L), "Joypad4 L");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_R), "Joypad4 R");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_LEFT), "Joypad4 Left");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_RIGHT), "Joypad4 Right");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_UP), "Joypad4 Up");
MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_DOWN), "Joypad4 Down");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_A), "Joypad5 A");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_B), "Joypad5 B");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_X), "Joypad5 X");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_Y), "Joypad5 Y");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_SELECT), "Joypad5 Select");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_START), "Joypad5 Start");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_L), "Joypad5 L");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_R), "Joypad5 R");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_LEFT), "Joypad5 Left");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_RIGHT), "Joypad5 Right");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_UP), "Joypad5 Up");
MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_DOWN), "Joypad5 Down");
}
// libsnes uses relative values for analogue devices.
// S9x seems to use absolute values, but do convert these into relative values in the core. (Why?!)
// Hack around it. :)
static int16_t snes_mouse_state[2][2] = {{0}, {0}};
static int16_t snes_scope_state[2] = {0};
static int16_t snes_justifier_state[2][2] = {{0}, {0}};
static void report_buttons()
{
int _x, _y;
for (int port = SNES_PORT_1; port <= SNES_PORT_2; port++)
{
switch (snes_devices[port])
{
case SNES_DEVICE_JOYPAD:
for (int i = BTN_FIRST; i <= BTN_LAST; i++)
S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JOYPAD, 0, i));
break;
case SNES_DEVICE_MULTITAP:
for (int j = 0; j < 4; j++)
for (int i = BTN_FIRST; i <= BTN_LAST; i++)
S9xReportButton(MAKE_BUTTON(j + 2, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MULTITAP, j, i));
break;
case SNES_DEVICE_MOUSE:
_x = s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, SNES_DEVICE_ID_MOUSE_X);
_y = s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, SNES_DEVICE_ID_MOUSE_Y);
snes_mouse_state[port][0] += _x;
snes_mouse_state[port][1] += _y;
S9xReportPointer(BTN_POINTER + port, snes_mouse_state[port][0], snes_mouse_state[port][1]);
for (int i = MOUSE_LEFT; i <= MOUSE_LAST; i++)
S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, i));
break;
case SNES_DEVICE_SUPER_SCOPE:
snes_scope_state[0] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, SNES_DEVICE_ID_SUPER_SCOPE_X);
snes_scope_state[1] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, SNES_DEVICE_ID_SUPER_SCOPE_Y);
S9xReportPointer(BTN_POINTER, snes_scope_state[0], snes_scope_state[1]);
for (int i = SCOPE_TRIGGER; i <= SCOPE_LAST; i++)
S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, i));
break;
case SNES_DEVICE_JUSTIFIER:
case SNES_DEVICE_JUSTIFIERS:
snes_justifier_state[0][0] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, SNES_DEVICE_ID_JUSTIFIER_X);
snes_justifier_state[0][1] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, SNES_DEVICE_ID_JUSTIFIER_Y);
S9xReportPointer(BTN_POINTER, snes_justifier_state[0][0], snes_justifier_state[0][1]);
for (int i = JUSTIFIER_TRIGGER; i <= JUSTIFIER_LAST; i++)
S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, i));
break;
default:
fprintf(stderr, "[libsnes]: Unknown device...\n");
}
}
}
bool snes_load_cartridge_normal(const char *, const uint8_t *rom_data, unsigned rom_size)
{
int loaded = Memory.LoadROMMem(rom_data,rom_size);
if (!loaded)
{
fprintf(stderr, "[libsnes]: Rom loading failed...\n");
return false;
}
if (environ_cb)
{
snes_system_timing timing;
timing.sample_rate = 32040.5;
if (!Settings.PAL)
timing.fps = 21477272.0 / 357366.0;
else
timing.fps = 21281370.0 / 425568.0;
environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing);
}
return true;
}
void snes_run()
{
s9x_poller_cb();
report_buttons();
S9xMainLoop();
}
void snes_term()
{
S9xDeinitAPU();
Memory.Deinit();
S9xGraphicsDeinit();
S9xUnmapAllControls();
}
bool snes_get_region()
{
return Settings.PAL ? SNES_REGION_PAL : SNES_REGION_NTSC;
}
uint8_t* snes_get_memory_data(unsigned type)
{
uint8_t* data;
switch(type) {
case SNES_MEMORY_CARTRIDGE_RAM:
data = Memory.SRAM;
break;
case SNES_MEMORY_CARTRIDGE_RTC:
data = RTCData.reg;
break;
case SNES_MEMORY_WRAM:
data = Memory.RAM;
break;
case SNES_MEMORY_APURAM:
data = spc_core->apuram();
break;
case SNES_MEMORY_VRAM:
data = Memory.VRAM;
break;
case SNES_MEMORY_CGRAM:
data = (uint8_t*)PPU.CGDATA;
break;
case SNES_MEMORY_OAM:
data = PPU.OAMData;
break;
default:
data = NULL;
break;
}
return data;
}
void snes_unload_cartridge()
{
}
unsigned snes_get_memory_size(unsigned type)
{
unsigned size;
switch(type) {
case SNES_MEMORY_CARTRIDGE_RAM:
size = (unsigned) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0);
if (size > 0x20000)
size = 0x20000;
break;
case SNES_MEMORY_CARTRIDGE_RTC:
size = (Settings.SRTC || Settings.SPC7110RTC)?20:0;
break;
case SNES_MEMORY_WRAM:
size = 128 * 1024;
break;
case SNES_MEMORY_VRAM:
case SNES_MEMORY_APURAM:
size = 64 * 1024;
break;
case SNES_MEMORY_CGRAM:
size = 512;
break;
case SNES_MEMORY_OAM:
size = 512 + 32;
break;
default:
size = 0;
break;
}
return size;
}
void snes_set_cartridge_basename(const char*)
{}
unsigned snes_serialize_size()
{
return S9xFreezeSize();
}
bool snes_serialize(uint8_t *data, unsigned size)
{
if (S9xFreezeGameMem(data,size) == FALSE)
return false;
return true;
}
bool snes_unserialize(const uint8_t* data, unsigned size)
{
if (S9xUnfreezeGameMem(data,size) != SUCCESS)
return false;
return true;
}
// Pitch 2048 -> 1024, only done once per res-change.
static void pack_frame(uint16_t *frame, int width, int height)
{
for (int y = 1; y < height; y++)
{
uint16_t *src = frame + y * 1024;
uint16_t *dst = frame + y * 512;
memcpy(dst, src, width * sizeof(uint16_t));
}
}
// Pitch 1024 -> 2048, only done once per res-change.
static void stretch_frame(uint16_t *frame, int width, int height)
{
for (int y = height - 1; y >= 0; y--)
{
uint16_t *src = frame + y * 512;
uint16_t *dst = frame + y * 1024;
memcpy(dst, src, width * sizeof(uint16_t));
}
}
bool8 S9xDeinitUpdate(int width, int height)
{
if (use_overscan)
{
if (height == 224)
{
memmove(GFX.Screen + (GFX.Pitch / 2) * 7, GFX.Screen, GFX.Pitch * height);
memset(GFX.Screen, 0x00, GFX.Pitch * 7);
memset(GFX.Screen + (GFX.Pitch / 2) * (7 + 224), 0, GFX.Pitch * 8);
height = 239;
}
else if (height == 448)
{
memmove(GFX.Screen + (GFX.Pitch / 2) * 15, GFX.Screen, GFX.Pitch * height);
memset(GFX.Screen, 0x00, GFX.Pitch * 15);
memset(GFX.Screen + (GFX.Pitch / 2) * (15 + 224), 0x00, GFX.Pitch * 17);
height = 478;
}
}
else // libsnes classic behavior
{
if (height == 448 || height == 478)
{
if (GFX.Pitch == 2048)
pack_frame(GFX.Screen, width, height);
GFX.Pitch = 1024;
}
else
{
if (GFX.Pitch == 1024)
stretch_frame(GFX.Screen, width, height);
GFX.Pitch = 2048;
}
}
s9x_video_cb(GFX.Screen, width, height);
return TRUE;
}
bool8 S9xContinueUpdate(int width, int height)
{
return S9xDeinitUpdate(width, height);
}
// Dummy functions that should probably be implemented correctly later.
void S9xParsePortConfig(ConfigFile&, int) {}
void S9xSyncSpeed() {}
//void S9xPollPointer(int, short*, short*) {}
const char* S9xStringInput(const char* in) { return in; }
const char* S9xGetFilename(const char* in, s9x_getdirtype) { return in; }
const char* S9xGetDirectory(s9x_getdirtype) { return NULL; }
void S9xInitInputDevices() {}
const char* S9xChooseFilename(unsigned char) { return NULL; }
void S9xHandlePortCommand(s9xcommand_t, short, short) {}
bool S9xPollButton(unsigned int, bool*) { return false; }
void S9xToggleSoundChannel(int) {}
const char* S9xGetFilenameInc(const char* in, s9x_getdirtype) { return NULL; }
const char* S9xBasename(const char* in) { return in; }
bool8 S9xInitUpdate() { return TRUE; }
void S9xExtraUsage() {}
bool8 S9xOpenSoundDevice() { return TRUE; }
void S9xMessage(int, int, const char*) {}
bool S9xPollAxis(unsigned int, short*) { return FALSE; }
void S9xSetPalette() {}
void S9xParseArg(char**, int&, int) {}
void S9xExit() {}
bool S9xPollPointer(unsigned int, short*, short*) { return false; }
const char *S9xChooseMovieFilename(unsigned char) { return NULL; }
bool8 S9xOpenSnapshotFile(const char* filepath, bool8 read_only, STREAM *file)
{
if(read_only)
{
if((*file = OPEN_STREAM(filepath, "rb")) != 0)
{
return (TRUE);
}
}
else
{
if((*file = OPEN_STREAM(filepath, "wb")) != 0)
{
return (TRUE);
}
}
return (FALSE);
}
void S9xCloseSnapshotFile(STREAM file)
{
CLOSE_STREAM(file);
}
void S9xAutoSaveSRAM()
{
return;
}
#ifndef __WIN32__
// S9x weirdness.
void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
{
*drive = 0;
const char *slash = strrchr(path, SLASH_CHAR),
*dot = strrchr(path, '.');
if (dot && slash && dot < slash)
dot = NULL;
if (!slash)
{
*dir = 0;
strcpy(fname, path);
if (dot)
{
fname[dot - path] = 0;
strcpy(ext, dot + 1);
}
else
*ext = 0;
}
else
{
strcpy(dir, path);
dir[slash - path] = 0;
strcpy(fname, slash + 1);
if (dot)
{
fname[dot - slash - 1] = 0;
strcpy(ext, dot + 1);
}
else
*ext = 0;
}
}
void _makepath (char *path, const char *, const char *dir, const char *fname, const char *ext)
{
if (dir && *dir)
{
strcpy(path, dir);
strcat(path, SLASH_STR);
}
else
*path = 0;
strcat(path, fname);
if (ext && *ext)
{
strcat(path, ".");
strcat(path, ext);
}
}
#endif // __WIN32__

47
libsnes/libsnes.def Normal file
View File

@ -0,0 +1,47 @@
LIBRARY snes
EXPORTS
snes_library_id
snes_library_revision_major
snes_library_revision_minor
snes_set_video_refresh
snes_set_audio_sample
snes_set_input_poll
snes_set_input_state
snes_set_environment
snes_set_controller_port_device
snes_set_cartridge_basename
snes_init
snes_term
snes_power
snes_reset
snes_run
snes_serialize_size
snes_serialize
snes_unserialize
snes_cheat_reset
snes_cheat_set
snes_load_cartridge_normal
snes_load_cartridge_bsx_slotted
snes_load_cartridge_bsx
snes_load_cartridge_sufami_turbo
snes_load_cartridge_super_game_boy
snes_unload_cartridge
snes_get_region
snes_get_memory_data
snes_get_memory_size

1264
libsnes/libsnes.hpp Normal file

File diff suppressed because it is too large Load Diff

4
libsnes/link.T Normal file
View File

@ -0,0 +1,4 @@
{
global: snes_*;
local: *;
};

View File

@ -185,10 +185,9 @@
#include "memmap.h"
bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 *buffer)
bool8 LoadZip (const char *zipname, uint32 *TotalFileSize, uint8 *buffer)
{
*TotalFileSize = 0;
*headers = 0;
unzFile file = unzOpen(zipname);
if (file == NULL)
@ -196,7 +195,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8
// find largest file in zip file (under MAX_ROM_SIZE) or a file with extension .1
char filename[132];
int filesize = 0;
uint32 filesize = 0;
int port = unzGoToFirstFile(file);
unz_file_info info;
@ -212,7 +211,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8
continue;
}
if ((int) info.uncompressed_size > filesize)
if (info.uncompressed_size > filesize)
{
strcpy(filename, name);
filesize = info.uncompressed_size;
@ -259,7 +258,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8
{
assert(info.uncompressed_size <= CMemory::MAX_ROM_SIZE + 512);
int FileSize = info.uncompressed_size;
uint32 FileSize = info.uncompressed_size;
int l = unzReadCurrentFile(file, ptr, FileSize);
if (unzCloseCurrentFile(file) == UNZ_CRCERROR)
@ -274,7 +273,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8
return (FALSE);
}
FileSize = (int) Memory.HeaderRemove((uint32) FileSize, *headers, ptr);
FileSize = Memory.HeaderRemove(FileSize, ptr);
ptr += FileSize;
*TotalFileSize += FileSize;

View File

@ -36,7 +36,7 @@
CF047D54109D0E0600FD0754 /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; };
CF047D55109D0E0600FD0754 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; };
CF047D56109D0E0600FD0754 /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; };
CF047D57109D0E0600FD0754 /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; };
CF047D57109D0E0600FD0754 /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* stream.h */; };
CF047D58109D0E0600FD0754 /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; };
CF047D59109D0E0600FD0754 /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; };
CF047D5A109D0E0600FD0754 /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; };
@ -145,7 +145,7 @@
CF047DC9109D0E0600FD0754 /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; };
CF047DCA109D0E0600FD0754 /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; };
CF047DCB109D0E0600FD0754 /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; };
CF047DCC109D0E0600FD0754 /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; };
CF047DCC109D0E0600FD0754 /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* stream.cpp */; };
CF047DCD109D0E0600FD0754 /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; };
CF047DCE109D0E0600FD0754 /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; };
CF047DCF109D0E0600FD0754 /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; };
@ -237,7 +237,7 @@
CF0566A90CF98E7E00C7877C /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; };
CF0566AA0CF98E7E00C7877C /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; };
CF0566AB0CF98E7E00C7877C /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; };
CF0566AC0CF98E7E00C7877C /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; };
CF0566AC0CF98E7E00C7877C /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* stream.h */; };
CF0566AD0CF98E7E00C7877C /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; };
CF0566AE0CF98E7E00C7877C /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; };
CF0566AF0CF98E7E00C7877C /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; };
@ -333,7 +333,7 @@
CF0567180CF98E7E00C7877C /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; };
CF0567190CF98E7E00C7877C /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; };
CF05671A0CF98E7E00C7877C /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; };
CF05671B0CF98E7E00C7877C /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; };
CF05671B0CF98E7E00C7877C /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* stream.cpp */; };
CF05671C0CF98E7E00C7877C /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; };
CF05671D0CF98E7E00C7877C /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; };
CF05671E0CF98E7E00C7877C /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; };
@ -424,7 +424,7 @@
CF2F462E1095EE72007D33FA /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; };
CF2F462F1095EE72007D33FA /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; };
CF2F46301095EE72007D33FA /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; };
CF2F46311095EE72007D33FA /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; };
CF2F46311095EE72007D33FA /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* stream.h */; };
CF2F46321095EE72007D33FA /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; };
CF2F46331095EE72007D33FA /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; };
CF2F46341095EE72007D33FA /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; };
@ -533,7 +533,7 @@
CF2F46A31095EE72007D33FA /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; };
CF2F46A41095EE72007D33FA /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; };
CF2F46A51095EE72007D33FA /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; };
CF2F46A61095EE72007D33FA /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; };
CF2F46A61095EE72007D33FA /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* stream.cpp */; };
CF2F46A71095EE72007D33FA /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; };
CF2F46A81095EE72007D33FA /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; };
CF2F46A91095EE72007D33FA /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; };
@ -817,11 +817,11 @@
EA6E6C0E08F9734500CB3555 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
EA809E9308F8D6C40072CDFB /* controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controls.h; sourceTree = "<group>"; };
EA809E9508F8D6E00072CDFB /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = language.h; sourceTree = "<group>"; };
EA809E9708F8D70D0072CDFB /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = "<group>"; };
EA809E9708F8D70D0072CDFB /* stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stream.h; sourceTree = "<group>"; };
EA809E9908F8D7240072CDFB /* controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = controls.cpp; sourceTree = "<group>"; };
EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crosshairs.cpp; sourceTree = "<group>"; };
EA809E9D08F8D73A0072CDFB /* crosshairs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crosshairs.h; sourceTree = "<group>"; };
EA809E9F08F8D7530072CDFB /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = "<group>"; };
EA809E9F08F8D7530072CDFB /* stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stream.cpp; sourceTree = "<group>"; };
EA809F9D08F8F2190072CDFB /* mac-controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-controls.h"; sourceTree = "<group>"; };
EA809FA108F8F2420072CDFB /* mac-controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-controls.cpp"; sourceTree = "<group>"; };
EA813E86066F5076004F99B5 /* movie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = movie.h; sourceTree = "<group>"; };
@ -1179,7 +1179,7 @@
EAE061C60526CCB900A80003 /* pixform.h */,
EAE061C70526CCB900A80003 /* port.h */,
EAE061C90526CCB900A80003 /* ppu.h */,
EA809E9708F8D70D0072CDFB /* reader.h */,
EA809E9708F8D70D0072CDFB /* stream.h */,
EAE061CC0526CCB900A80003 /* sa1.h */,
EAE061CE0526CCB900A80003 /* sar.h */,
EAE061D00526CCB900A80003 /* screenshot.h */,
@ -1222,7 +1222,7 @@
EA813E9A066F50A5004F99B5 /* movie.cpp */,
EAE061C30526CCB900A80003 /* obc1.cpp */,
EAE061C80526CCB900A80003 /* ppu.cpp */,
EA809E9F08F8D7530072CDFB /* reader.cpp */,
EA809E9F08F8D7530072CDFB /* stream.cpp */,
EAE061CB0526CCB900A80003 /* sa1.cpp */,
EAE061CD0526CCB900A80003 /* sa1cpu.cpp */,
EAE061D10526CCB900A80003 /* sdd1.cpp */,
@ -1384,7 +1384,7 @@
CF047D54109D0E0600FD0754 /* pixform.h in Headers */,
CF047D55109D0E0600FD0754 /* port.h in Headers */,
CF047D56109D0E0600FD0754 /* ppu.h in Headers */,
CF047D57109D0E0600FD0754 /* reader.h in Headers */,
CF047D57109D0E0600FD0754 /* stream.h in Headers */,
CF047D58109D0E0600FD0754 /* sa1.h in Headers */,
CF047D59109D0E0600FD0754 /* sar.h in Headers */,
CF047D5A109D0E0600FD0754 /* screenshot.h in Headers */,
@ -1503,7 +1503,7 @@
CF0566A90CF98E7E00C7877C /* pixform.h in Headers */,
CF0566AA0CF98E7E00C7877C /* port.h in Headers */,
CF0566AB0CF98E7E00C7877C /* ppu.h in Headers */,
CF0566AC0CF98E7E00C7877C /* reader.h in Headers */,
CF0566AC0CF98E7E00C7877C /* stream.h in Headers */,
CF0566AD0CF98E7E00C7877C /* sa1.h in Headers */,
CF0566AE0CF98E7E00C7877C /* sar.h in Headers */,
CF0566AF0CF98E7E00C7877C /* screenshot.h in Headers */,
@ -1622,7 +1622,7 @@
CF2F462E1095EE72007D33FA /* pixform.h in Headers */,
CF2F462F1095EE72007D33FA /* port.h in Headers */,
CF2F46301095EE72007D33FA /* ppu.h in Headers */,
CF2F46311095EE72007D33FA /* reader.h in Headers */,
CF2F46311095EE72007D33FA /* stream.h in Headers */,
CF2F46321095EE72007D33FA /* sa1.h in Headers */,
CF2F46331095EE72007D33FA /* sar.h in Headers */,
CF2F46341095EE72007D33FA /* screenshot.h in Headers */,
@ -1938,7 +1938,7 @@
CF047DC9109D0E0600FD0754 /* movie.cpp in Sources */,
CF047DCA109D0E0600FD0754 /* obc1.cpp in Sources */,
CF047DCB109D0E0600FD0754 /* ppu.cpp in Sources */,
CF047DCC109D0E0600FD0754 /* reader.cpp in Sources */,
CF047DCC109D0E0600FD0754 /* stream.cpp in Sources */,
CF047DCD109D0E0600FD0754 /* sa1.cpp in Sources */,
CF047DCE109D0E0600FD0754 /* sa1cpu.cpp in Sources */,
CF047DCF109D0E0600FD0754 /* sdd1.cpp in Sources */,
@ -2033,7 +2033,7 @@
CF0567180CF98E7E00C7877C /* movie.cpp in Sources */,
CF0567190CF98E7E00C7877C /* obc1.cpp in Sources */,
CF05671A0CF98E7E00C7877C /* ppu.cpp in Sources */,
CF05671B0CF98E7E00C7877C /* reader.cpp in Sources */,
CF05671B0CF98E7E00C7877C /* stream.cpp in Sources */,
CF05671C0CF98E7E00C7877C /* sa1.cpp in Sources */,
CF05671D0CF98E7E00C7877C /* sa1cpu.cpp in Sources */,
CF05671E0CF98E7E00C7877C /* sdd1.cpp in Sources */,
@ -2128,7 +2128,7 @@
CF2F46A31095EE72007D33FA /* movie.cpp in Sources */,
CF2F46A41095EE72007D33FA /* obc1.cpp in Sources */,
CF2F46A51095EE72007D33FA /* ppu.cpp in Sources */,
CF2F46A61095EE72007D33FA /* reader.cpp in Sources */,
CF2F46A61095EE72007D33FA /* stream.cpp in Sources */,
CF2F46A71095EE72007D33FA /* sa1.cpp in Sources */,
CF2F46A81095EE72007D33FA /* sa1cpu.cpp in Sources */,
CF2F46A91095EE72007D33FA /* sdd1.cpp in Sources */,

View File

@ -197,7 +197,6 @@
#include "controls.h"
#include "cheats.h"
#include "movie.h"
#include "reader.h"
#include "display.h"
#ifndef SET_UI_COLOR
@ -945,9 +944,9 @@ static bool8 is_GNEXT_BIOS (uint8 *, uint32);
static bool8 is_GNEXT_Add_On (uint8 *, uint32);
static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff);
static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned);
static bool8 ReadUPSPatch (Reader *, long, int32 &);
static long ReadInt (Reader *, unsigned);
static bool8 ReadIPSPatch (Reader *, long, int32 &);
static bool8 ReadUPSPatch (Stream *, long, int32 &);
static long ReadInt (Stream *, unsigned);
static bool8 ReadIPSPatch (Stream *, long, int32 &);
#ifdef UNZIP_SUPPORT
static int unzFindExtension (unzFile &, const char *, bool restart = TRUE, bool print = TRUE);
#endif
@ -1352,7 +1351,7 @@ int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff)
return (score);
}
uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf)
uint32 CMemory::HeaderRemove (uint32 size, uint8 *buf)
{
uint32 calc_size = (size / 0x2000) * 0x2000;
@ -1373,20 +1372,20 @@ uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf)
}
memmove(buf, buf + 512, calc_size);
headerCount++;
HeaderCount++;
size -= 512;
}
return (size);
}
uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, uint32 maxsize)
{
// <- ROM size without header
// ** Memory.HeaderCount
// ** Memory.ROMFilename
int32 totalSize = 0;
uint32 totalSize = 0;
char fname[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1];
char *ext;
@ -1415,7 +1414,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
case FILE_ZIP:
{
#ifdef UNZIP_SUPPORT
if (!LoadZip(fname, &totalSize, &HeaderCount, buffer))
if (!LoadZip(fname, &totalSize, buffer))
{
S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive.");
return (0);
@ -1439,7 +1438,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
return (0);
}
totalSize = HeaderRemove(size, HeaderCount, buffer);
totalSize = HeaderRemove(size, buffer);
strcpy(ROMFilename, fname);
#else
@ -1468,7 +1467,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp);
CLOSE_STREAM(fp);
size = HeaderRemove(size, HeaderCount, ptr);
size = HeaderRemove(size, ptr);
totalSize += size;
ptr += size;
@ -1511,31 +1510,55 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize)
return ((uint32) totalSize);
}
bool8 CMemory::LoadROMMem (const uint8 *source, uint32 sourceSize)
{
if(!source || sourceSize > MAX_ROM_SIZE)
return FALSE;
strcpy(ROMFilename,"MemoryROM");
do
{
memset(ROM,0, MAX_ROM_SIZE);
memset(&Multi, 0,sizeof(Multi));
memcpy(ROM,source,sourceSize);
}
while(!LoadROMInt(sourceSize));
return TRUE;
}
bool8 CMemory::LoadROM (const char *filename)
{
int retry_count = 0;
if(!filename || !*filename)
return FALSE;
if (!filename || !*filename)
return (FALSE);
int32 totalFileSize;
ZeroMemory(ROM, MAX_ROM_SIZE);
ZeroMemory(&Multi, sizeof(Multi));
again:
do
{
memset(ROM,0, MAX_ROM_SIZE);
memset(&Multi, 0,sizeof(Multi));
totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE);
if (!totalFileSize)
return (FALSE);
}
while(!LoadROMInt(totalFileSize));
return TRUE;
}
bool8 CMemory::LoadROMInt (int32 ROMfillSize)
{
Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
SET_UI_COLOR(255, 255, 255);
CalculatedSize = 0;
ExtendedFormat = NOPE;
int32 totalFileSize;
totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE);
if (!totalFileSize)
return (FALSE);
if (!Settings.NoPatch)
CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize);
CheckForAnyPatch(ROMFilename, HeaderCount != 0, ROMfillSize);
int hi_score, lo_score;
@ -1546,15 +1569,15 @@ again:
((hi_score > lo_score && ScoreHiROM(TRUE) > hi_score) ||
(hi_score <= lo_score && ScoreLoROM(TRUE) > lo_score)))
{
memmove(ROM, ROM + 512, totalFileSize - 512);
totalFileSize -= 512;
memmove(ROM, ROM + 512, ROMfillSize - 512);
ROMfillSize -= 512;
S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work");
// modifying ROM, so we need to rescore
hi_score = ScoreHiROM(FALSE);
lo_score = ScoreLoROM(FALSE);
}
CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
CalculatedSize = (ROMfillSize / 0x2000) * 0x2000;
if (CalculatedSize > 0x400000 &&
(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x3423 && // exclude SA-1
@ -1571,7 +1594,7 @@ again:
((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000))
{
if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved)
S9xDeinterleaveType1(totalFileSize, ROM);
S9xDeinterleaveType1(ROMfillSize, ROM);
}
// CalculatedSize is now set, so rescore
@ -1699,14 +1722,10 @@ again:
if ((HiROM && (lo_score >= hi_score || hi_score < 0)) ||
(LoROM && (hi_score > lo_score || lo_score < 0)))
{
if (retry_count == 0)
{
S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again.");
Settings.ForceNotInterleaved = TRUE;
Settings.ForceInterleaved = FALSE;
retry_count++;
goto again;
}
S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again.");
Settings.ForceNotInterleaved = TRUE;
Settings.ForceInterleaved = FALSE;
return (FALSE);
}
}
@ -1726,9 +1745,9 @@ again:
}
}
if (strncmp(LastRomFilename, filename, PATH_MAX + 1))
if (strncmp(LastRomFilename, ROMFilename, PATH_MAX + 1))
{
strncpy(LastRomFilename, filename, PATH_MAX + 1);
strncpy(LastRomFilename, ROMFilename, PATH_MAX + 1);
LastRomFilename[PATH_MAX] = 0;
}
@ -3775,7 +3794,7 @@ static uint32 XPSdecode (const uint8 *data, unsigned &addr, unsigned size)
//no-header patching errors that result in IPS patches having a 50/50 chance of
//being applied correctly.
static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size)
static bool8 ReadUPSPatch (Stream *r, long, int32 &rom_size)
{
//Reader lacks size() and rewind(), so we need to read in the file to get its size
uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ...
@ -3857,7 +3876,7 @@ static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size)
//
// logic taken from http://byuu.org/programming/bps and the accompanying source
//
static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size)
static bool8 ReadBPSPatch (Stream *r, long, int32 &rom_size)
{
uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ...
uint32 size = 0;
@ -3948,7 +3967,7 @@ static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size)
}
}
static long ReadInt (Reader *r, unsigned nbytes)
static long ReadInt (Stream *r, unsigned nbytes)
{
long v = 0;
@ -3963,7 +3982,7 @@ static long ReadInt (Reader *r, unsigned nbytes)
return (v);
}
static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size)
static bool8 ReadIPSPatch (Stream *r, long offset, int32 &rom_size)
{
const int32 IPS_EOF = 0x00454F46l;
int32 ofs;
@ -4082,7 +4101,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
if (Settings.NoPatch)
return;
STREAM patch_file = NULL;
FSTREAM patch_file = NULL;
uint32 i;
long offset = header ? 512 : 0;
int ret;
@ -4095,12 +4114,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
// BPS
_makepath(fname, drive, dir, name, "bps");
if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL)
{
printf("Using BPS patch %s", fname);
ret = ReadBPSPatch(new fReader(patch_file), 0, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadBPSPatch(new fStream(patch_file), 0, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4122,7 +4141,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
{
printf(" in %s", rom_filename);
ret = ReadBPSPatch(new unzReader(file), offset, rom_size);
ret = ReadBPSPatch(new unzStream(file), offset, rom_size);
unzCloseCurrentFile(file);
if (ret)
@ -4136,12 +4155,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
n = S9xGetFilename(".bps", IPS_DIR);
if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL)
{
printf("Using BPS patch %s", n);
ret = ReadBPSPatch(new fReader(patch_file), 0, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadBPSPatch(new fStream(patch_file), 0, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4156,12 +4175,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
_makepath(fname, drive, dir, name, "ups");
if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL)
{
printf("Using UPS patch %s", fname);
ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadUPSPatch(new fStream(patch_file), 0, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4183,7 +4202,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
{
printf(" in %s", rom_filename);
ret = ReadUPSPatch(new unzReader(file), offset, rom_size);
ret = ReadUPSPatch(new unzStream(file), offset, rom_size);
unzCloseCurrentFile(file);
if (ret)
@ -4197,12 +4216,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
n = S9xGetFilename(".ups", IPS_DIR);
if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL)
{
printf("Using UPS patch %s", n);
ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadUPSPatch(new fStream(patch_file), 0, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4217,12 +4236,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
_makepath(fname, drive, dir, name, "ips");
if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL)
{
printf("Using IPS patch %s", fname);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4243,13 +4262,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
snprintf(ips, 8, "%03d.ips", i);
_makepath(fname, drive, dir, name, ips);
if (!(patch_file = OPEN_STREAM(fname, "rb")))
if (!(patch_file = OPEN_FSTREAM(fname, "rb")))
break;
printf("Using IPS patch %s", fname);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4279,13 +4298,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
break;
_makepath(fname, drive, dir, name, ips);
if (!(patch_file = OPEN_STREAM(fname, "rb")))
if (!(patch_file = OPEN_FSTREAM(fname, "rb")))
break;
printf("Using IPS patch %s", fname);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4313,13 +4332,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
snprintf(ips, 4, "ip%d", i);
_makepath(fname, drive, dir, name, ips);
if (!(patch_file = OPEN_STREAM(fname, "rb")))
if (!(patch_file = OPEN_FSTREAM(fname, "rb")))
break;
printf("Using IPS patch %s", fname);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4348,7 +4367,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
{
printf(" in %s", rom_filename);
ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
ret = ReadIPSPatch(new unzStream(file), offset, rom_size);
unzCloseCurrentFile(file);
if (ret)
@ -4375,7 +4394,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
printf(" in %s", rom_filename);
ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
ret = ReadIPSPatch(new unzStream(file), offset, rom_size);
unzCloseCurrentFile(file);
if (ret)
@ -4409,7 +4428,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
printf(" in %s", rom_filename);
ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
ret = ReadIPSPatch(new unzStream(file), offset, rom_size);
unzCloseCurrentFile(file);
if (ret)
@ -4441,7 +4460,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
printf(" in %s", rom_filename);
ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
ret = ReadIPSPatch(new unzStream(file), offset, rom_size);
unzCloseCurrentFile(file);
if (ret)
@ -4470,12 +4489,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
n = S9xGetFilename(".ips", IPS_DIR);
if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL)
{
printf("Using IPS patch %s", n);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4496,13 +4515,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
snprintf(ips, 9, ".%03d.ips", i);
n = S9xGetFilename(ips, IPS_DIR);
if (!(patch_file = OPEN_STREAM(n, "rb")))
if (!(patch_file = OPEN_FSTREAM(n, "rb")))
break;
printf("Using IPS patch %s", n);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4532,13 +4551,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
break;
n = S9xGetFilename(ips, IPS_DIR);
if (!(patch_file = OPEN_STREAM(n, "rb")))
if (!(patch_file = OPEN_FSTREAM(n, "rb")))
break;
printf("Using IPS patch %s", n);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{
@ -4566,13 +4585,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r
snprintf(ips, 5, ".ip%d", i);
n = S9xGetFilename(ips, IPS_DIR);
if (!(patch_file = OPEN_STREAM(n, "rb")))
if (!(patch_file = OPEN_FSTREAM(n, "rb")))
break;
printf("Using IPS patch %s", n);
ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
CLOSE_STREAM(patch_file);
ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size);
CLOSE_FSTREAM(patch_file);
if (ret)
{

View File

@ -271,9 +271,12 @@ struct CMemory
int ScoreHiROM (bool8, int32 romoff = 0);
int ScoreLoROM (bool8, int32 romoff = 0);
uint32 HeaderRemove (uint32, int32 &, uint8 *);
uint32 FileLoader (uint8 *, const char *, int32);
uint32 HeaderRemove (uint32, uint8 *);
uint32 FileLoader (uint8 *, const char *, uint32);
uint32 MemLoader (uint8 *, const char*, uint32);
bool8 LoadROMMem (const uint8 *, uint32);
bool8 LoadROM (const char *);
bool8 LoadROMInt (int32);
bool8 LoadMultiCart (const char *, const char *);
bool8 LoadSufamiTurbo (const char *, const char *);
bool8 LoadSameGame (const char *, const char *);
@ -361,7 +364,7 @@ extern CMemory Memory;
extern SMulti Multi;
void S9xAutoSaveSRAM (void);
bool8 LoadZip(const char *, int32 *, int32 *, uint8 *);
bool8 LoadZip(const char *, uint32 *, uint8 *);
enum s9xwrap_t
{

View File

@ -189,6 +189,8 @@
#include <memory.h>
#include <sys/types.h>
#include "snes9x.h"
#ifdef __WIN32__
#include <winsock.h>
#include <process.h>
@ -222,7 +224,6 @@
#include <semaphore.h>
#endif
#include "snes9x.h"
#include "memmap.h"
#include "netplay.h"
#include "snapshot.h"

42
port.h
View File

@ -202,7 +202,9 @@
#define RIGHTSHIFT_int8_IS_SAR
#define RIGHTSHIFT_int16_IS_SAR
#define RIGHTSHIFT_int32_IS_SAR
#ifndef __WIN32_LIBSNES__
#define SNES_JOY_READ_CALLBACKS
#endif //__WIN32_LIBSNES__
#endif
#ifdef __MACOSX__
@ -227,31 +229,22 @@ typedef uint64_t uint64;
#else // HAVE_STDINT_H
#ifdef __WIN32__
typedef intptr_t pint;
#else // __WIN32__
#ifdef PTR_NOT_INT
typedef long pint;
#else
typedef int pint;
#endif
#endif // __WIN32__
#ifdef __WIN32__
#ifdef __BORLANDC__
#include <systypes.h>
#else
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
#ifndef WSAAP
// winsock2.h typedefs int32 as well
typedef signed int int32;
#endif
typedef signed int int32;
typedef unsigned int uint32;
#endif
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef signed __int64 int64;
typedef unsigned __int64 uint64;
typedef int8 int8_t;
typedef uint8 uint8_t;
typedef int16 int16_t;
typedef uint16 uint16_t;
typedef int32 int32_t;
typedef uint32 uint32_t;
typedef int64 int64_t;
typedef uint64 uint64_t;
typedef int socklen_t;
#else // __WIN32__
typedef signed char int8;
@ -266,6 +259,11 @@ __extension__
#endif
typedef long long int64;
typedef unsigned long long uint64;
#ifdef PTR_NOT_INT
typedef long pint;
#else // __PTR_NOT_INT
typedef int pint;
#endif // __PTR_NOT_INT
#endif // __WIN32__
#endif // HAVE_STDINT_H
#endif // snes9x_types_defined
@ -300,15 +298,19 @@ typedef unsigned long long uint64;
void _splitpath (const char *, char *, char *, char *, char *);
void _makepath (char *, const char *, const char *, const char *, const char *);
#define S9xDisplayString DisplayStringFromBottom
#else
#else // __WIN32__
#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
#ifndef __WIN32_LIBSNES__
void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap);
#define S9xDisplayString WinDisplayStringFromBottom
void SetInfoDlgColor(unsigned char, unsigned char, unsigned char);
#define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b)
#endif
#else // __WIN32_LIBSNES__
#define S9xDisplayString DisplayStringFromBottom
#endif // __WIN32_LIBSNES__
#endif // __WIN32__
#ifdef __DJGPP
#define SLASH_STR "\\"

View File

@ -190,6 +190,8 @@
#include <strings.h>
#endif
#include "snes9x.h"
#ifdef __WIN32__
#include <winsock.h>
@ -219,7 +221,6 @@
#endif // !__WIN32__
#include "snes9x.h"
#include "memmap.h"
#include "snapshot.h"
#include "netplay.h"

View File

@ -1169,6 +1169,21 @@ void S9xResetSaveTimer (bool8 dontsave)
t = time(NULL);
}
uint32 S9xFreezeSize()
{
nulStream stream;
S9xFreezeToStream(&stream);
return stream.size();
}
bool8 S9xFreezeGameMem (uint8 *buf, uint32 bufSize)
{
memStream mStream(buf, bufSize);
S9xFreezeToStream(&mStream);
return (TRUE);
}
bool8 S9xFreezeGame (const char *filename)
{
STREAM stream = NULL;
@ -1194,6 +1209,14 @@ bool8 S9xFreezeGame (const char *filename)
return (FALSE);
}
int S9xUnfreezeGameMem (const uint8 *buf, uint32 bufSize)
{
memStream stream(buf, bufSize);
int result = S9xUnfreezeFromStream(&stream);
return result;
}
bool8 S9xUnfreezeGame (const char *filename)
{
STREAM stream = NULL;

View File

@ -192,7 +192,10 @@
void S9xResetSaveTimer (bool8);
bool8 S9xFreezeGame (const char *);
uint32 S9xFreezeSize (void);
bool8 S9xFreezeGameMem (uint8 *,uint32);
bool8 S9xUnfreezeGame (const char *);
int S9xUnfreezeGameMem (const uint8 *,uint32);
void S9xFreezeToStream (STREAM);
int S9xUnfreezeFromStream (STREAM);
bool8 S9xSPCDump (const char *);

View File

@ -315,14 +315,14 @@ static void parse_crosshair_spec (enum crosscontrols ctl, const char *spec)
static bool try_load_config_file (const char *fname, ConfigFile &conf)
{
STREAM fp;
FSTREAM fp;
fp = OPEN_STREAM(fname, "r");
fp = OPEN_FSTREAM(fname, "r");
if (fp)
{
fprintf(stdout, "Reading config file %s.\n", fname);
conf.LoadFile(new fReader(fp));
CLOSE_STREAM(fp);
conf.LoadFile(new fStream(fp));
CLOSE_FSTREAM(fp);
return (true);
}

View File

@ -189,29 +189,42 @@
#ifdef ZLIB
#include <zlib.h>
#define STREAM gzFile
#define READ_STREAM(p, l, s) gzread(s, p, l)
#define WRITE_STREAM(p, l, s) gzwrite(s, p, l)
#define GETS_STREAM(p, l, s) gzgets(s, p, l)
#define GETC_STREAM(s) gzgetc(s)
#define OPEN_STREAM(f, m) gzopen(f, m)
#define REOPEN_STREAM(f, m) gzdopen(f, m)
#define FIND_STREAM(f) gztell(f)
#define REVERT_STREAM(f, o, s) gzseek(f, o, s)
#define CLOSE_STREAM(s) gzclose(s)
#define FSTREAM gzFile
#define READ_FSTREAM(p, l, s) gzread(s, p, l)
#define WRITE_FSTREAM(p, l, s) gzwrite(s, p, l)
#define GETS_FSTREAM(p, l, s) gzgets(s, p, l)
#define GETC_FSTREAM(s) gzgetc(s)
#define OPEN_FSTREAM(f, m) gzopen(f, m)
#define REOPEN_FSTREAM(f, m) gzdopen(f, m)
#define FIND_FSTREAM(f) gztell(f)
#define REVERT_FSTREAM(s, o, p) gzseek(s, o, p)
#define CLOSE_FSTREAM(s) gzclose(s)
#else
#define STREAM FILE *
#define READ_STREAM(p, l, s) fread(p, 1, l, s)
#define WRITE_STREAM(p, l, s) fwrite(p, 1, l, s)
#define GETS_STREAM(p, l, s) fgets(p, l, s)
#define GETC_STREAM(s) fgetc(s)
#define OPEN_STREAM(f, m) fopen(f, m)
#define REOPEN_STREAM(f, m) fdopen(f, m)
#define FIND_STREAM(f) ftell(f)
#define REVERT_STREAM(f, o, s) fseek(f, o, s)
#define CLOSE_STREAM(s) fclose(s)
#define FSTREAM FILE *
#define READ_FSTREAM(p, l, s) fread(p, 1, l, s)
#define WRITE_FSTREAM(p, l, s) fwrite(p, 1, l, s)
#define GETS_FSTREAM(p, l, s) fgets(p, l, s)
#define GETC_FSTREAM(s) fgetc(s)
#define OPEN_FSTREAM(f, m) fopen(f, m)
#define REOPEN_FSTREAM(f, m) fdopen(f, m)
#define FIND_FSTREAM(s) ftell(s)
#define REVERT_FSTREAM(s, o, p) fseek(s, o, p)
#define CLOSE_FSTREAM(s) fclose(s)
#endif
#include "stream.h"
#define STREAM Stream *
#define READ_STREAM(p, l, s) s->read(p,l)
#define WRITE_STREAM(p, l, s) s->write(p,l)
#define GETS_STREAM(p, l, s) s->gets(p,l)
#define GETC_STREAM(s) s->get_char()
#define OPEN_STREAM(f, m) openStreamFromFSTREAM(f, m)
#define REOPEN_STREAM(f, m) reopenStreamFromFd(f, m)
#define FIND_STREAM(s) s->pos()
#define REVERT_STREAM(s, o, p) s->revert(p, o)
#define CLOSE_STREAM(s) s->closeStream()
#define SNES_WIDTH 256
#define SNES_HEIGHT 224
#define SNES_HEIGHT_EXTENDED 239

View File

@ -183,24 +183,24 @@
#include "unzip.h"
#endif
#include "snes9x.h"
#include "reader.h"
#include "stream.h"
// Generic constructor/destructor
Reader::Reader (void)
Stream::Stream (void)
{
return;
}
Reader::~Reader (void)
Stream::~Stream (void)
{
return;
}
// Generic getline function, based on gets. Reimlpement if you can do better.
char * Reader::getline (void)
char * Stream::getline (void)
{
bool eof;
std::string ret;
@ -212,7 +212,7 @@ char * Reader::getline (void)
return (strdup(ret.c_str()));
}
std::string Reader::getline (bool &eof)
std::string Stream::getline (bool &eof)
{
char buf[1024];
std::string ret;
@ -235,50 +235,81 @@ std::string Reader::getline (bool &eof)
return (ret);
}
// snes9x.h STREAM reader
// snes9x.h FSTREAM Stream
fReader::fReader (STREAM f)
fStream::fStream (FSTREAM f)
{
fp = f;
}
fReader::~fReader (void)
fStream::~fStream (void)
{
CLOSE_FSTREAM(fp);
return;
}
int fReader::get_char (void)
int fStream::get_char (void)
{
return (GETC_STREAM(fp));
return (GETC_FSTREAM(fp));
}
char * fReader::gets (char *buf, size_t len)
char * fStream::gets (char *buf, size_t len)
{
return (GETS_STREAM(buf, len, fp));
return (GETS_FSTREAM(buf, len, fp));
}
size_t fReader::read (char *buf, size_t len)
size_t fStream::read (void *buf, size_t len)
{
return (READ_STREAM(buf, len, fp));
return (READ_FSTREAM(buf, len, fp));
}
// unzip reader
size_t fStream::write (void *buf, size_t len)
{
return (WRITE_FSTREAM(buf, len, fp));
}
size_t fStream::pos (void)
{
return (FIND_FSTREAM(fp));
}
size_t fStream::size (void)
{
size_t sz;
REVERT_FSTREAM(fp,0L,SEEK_END);
sz = FIND_FSTREAM(fp);
REVERT_FSTREAM(fp,0L,SEEK_SET);
return sz;
}
int fStream::revert (size_t from, size_t offset)
{
return (REVERT_FSTREAM(fp, from, offset));
}
void fStream::closeStream()
{
CLOSE_FSTREAM(fp);
delete this;
}
// unzip Stream
#ifdef UNZIP_SUPPORT
unzReader::unzReader (unzFile &v)
unzStream::unzStream (unzFile &v)
{
file = v;
head = NULL;
numbytes = 0;
}
unzReader::~unzReader (void)
unzStream::~unzStream (void)
{
return;
}
int unzReader::get_char (void)
int unzStream::get_char (void)
{
unsigned char c;
@ -297,7 +328,7 @@ int unzReader::get_char (void)
return ((int) c);
}
char * unzReader::gets (char *buf, size_t len)
char * unzStream::gets (char *buf, size_t len)
{
size_t i;
int c;
@ -322,7 +353,7 @@ char * unzReader::gets (char *buf, size_t len)
return (buf);
}
size_t unzReader::read (char *buf, size_t len)
size_t unzStream::read (void *buf, size_t len)
{
if (len == 0)
return (len);
@ -344,11 +375,219 @@ size_t unzReader::read (char *buf, size_t len)
numbytes = 0;
}
int l = unzReadCurrentFile(file, buf + numread, len - numread);
int l = unzReadCurrentFile(file, (uint8 *)buf + numread, len - numread);
if (l > 0)
numread += l;
return (numread);
}
// not supported
size_t unzStream::write (void *buf, size_t len)
{
return (0);
}
size_t unzStream::pos (void)
{
return (unztell(file));
}
size_t unzStream::size (void)
{
unz_file_info info;
unzGetCurrentFileInfo(file,&info,NULL,0,NULL,0,NULL,0);
return info.uncompressed_size;
}
// not supported
int unzStream::revert (size_t from, size_t offset)
{
return -1;
}
void unzStream::closeStream()
{
unzCloseCurrentFile(file);
delete this;
}
#endif
// memory Stream
memStream::memStream (uint8 *source, size_t sourceSize)
{
mem = head = source;
msize = remaining = sourceSize;
readonly = false;
}
memStream::memStream (const uint8 *source, size_t sourceSize)
{
mem = head = const_cast<uint8 *>(source);
msize = remaining = sourceSize;
readonly = true;
}
memStream::~memStream (void)
{
return;
}
int memStream::get_char (void)
{
if(!remaining)
return EOF;
remaining--;
return *head++;
}
char * memStream::gets (char *buf, size_t len)
{
size_t i;
int c;
for (i = 0; i < len - 1; i++)
{
c = get_char();
if (c == EOF)
{
if (i == 0)
return (NULL);
break;
}
buf[i] = (char) c;
if (buf[i] == '\n')
break;
}
buf[i] = '\0';
return (buf);
}
size_t memStream::read (void *buf, size_t len)
{
size_t bytes = len < remaining ? len : remaining;
memcpy(buf,head,bytes);
head += bytes;
remaining -= bytes;
return bytes;
}
size_t memStream::write (void *buf, size_t len)
{
if(readonly)
return 0;
size_t bytes = len < remaining ? len : remaining;
memcpy(head,buf,bytes);
head += bytes;
remaining -= bytes;
return bytes;
}
size_t memStream::pos (void)
{
return msize - remaining;
}
size_t memStream::size (void)
{
return msize;
}
int memStream::revert (size_t from, size_t offset)
{
size_t pos = from + offset;
if(pos > msize)
return -1;
head = mem + pos;
remaining = msize - pos;
return 0;
}
void memStream::closeStream()
{
delete [] mem;
delete this;
}
// dummy Stream
nulStream::nulStream (void)
{
bytes_written = 0;
}
nulStream::~nulStream (void)
{
return;
}
int nulStream::get_char (void)
{
return 0;
}
char * nulStream::gets (char *buf, size_t len)
{
*buf = '\0';
return NULL;
}
size_t nulStream::read (void *buf, size_t len)
{
return 0;
}
size_t nulStream::write (void *buf, size_t len)
{
bytes_written += len;
return len;
}
size_t nulStream::pos (void)
{
return 0;
}
size_t nulStream::size (void)
{
return bytes_written;
}
int nulStream::revert (size_t from, size_t offset)
{
bytes_written = from + offset;
return 0;
}
void nulStream::closeStream()
{
delete this;
}
Stream *openStreamFromFSTREAM(const char* filename, const char* mode)
{
FSTREAM f = OPEN_FSTREAM(filename,mode);
if(!f)
return NULL;
return new fStream(f);
}
Stream *reopenStreamFromFd(int fd, const char* mode)
{
FSTREAM f = REOPEN_FSTREAM(fd,mode);
if(!f)
return NULL;
return new fStream(f);
}

View File

@ -176,46 +176,65 @@
***********************************************************************************/
#ifndef _READER_H_
#define _READER_H_
#ifndef _STREAM_H_
#define _STREAM_H_
class Reader
#include <string>
class Stream
{
public:
Reader (void);
virtual ~Reader (void);
Stream (void);
virtual ~Stream (void);
virtual int get_char (void) = 0;
virtual char * gets (char *, size_t) = 0;
virtual char * getline (void); // free() when done
virtual std::string getline (bool &);
virtual size_t read (char *, size_t) = 0;
virtual size_t read (void *, size_t) = 0;
virtual size_t write (void *, size_t) = 0;
virtual size_t pos (void) = 0;
virtual size_t size (void) = 0;
virtual int revert (size_t from, size_t offset) = 0;
virtual void closeStream() = 0;
};
class fReader : public Reader
class fStream : public Stream
{
public:
fReader (STREAM);
virtual ~fReader (void);
fStream (FSTREAM);
virtual ~fStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
STREAM fp;
FSTREAM fp;
};
#ifdef UNZIP_SUPPORT
#include "unzip.h"
#define unz_BUFFSIZ 1024
class unzReader : public Reader
class unzStream : public Stream
{
public:
unzReader (unzFile &);
virtual ~unzReader (void);
unzStream (unzFile &);
virtual ~unzStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
unzFile file;
@ -226,4 +245,52 @@ class unzReader : public Reader
#endif
class memStream : public Stream
{
public:
memStream (uint8 *,size_t);
memStream (const uint8 *,size_t);
virtual ~memStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
uint8 *mem;
size_t msize;
size_t remaining;
uint8 *head;
bool readonly;
};
/* dummy stream that always reads 0 and writes nowhere
but counts bytes written
*/
class nulStream : public Stream
{
public:
nulStream (void);
virtual ~nulStream (void);
virtual int get_char (void);
virtual char * gets (char *, size_t);
virtual size_t read (void *, size_t);
virtual size_t write (void *, size_t);
virtual size_t pos (void);
virtual size_t size (void);
virtual int revert (size_t from, size_t offset);
virtual void closeStream();
private:
size_t bytes_written;
};
Stream *openStreamFromFSTREAM(const char* filename, const char* mode);
Stream *reopenStreamFromFd(int fd, const char* mode);
#endif

View File

@ -7,7 +7,7 @@
OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"`
BUILDDIR = .
OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o
OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o
DEFS = -DMITSHM
ifdef S9XDEBUGGER

View File

@ -2082,42 +2082,6 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\reader.cpp"
>
</File>
<File
RelativePath="..\reader.h"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode|Win32"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode|x64"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\sa1.cpp"
>
@ -2902,6 +2866,42 @@
/>
</FileConfiguration>
</File>
<File
RelativePath="..\stream.cpp"
>
</File>
<File
RelativePath="..\stream.h"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode|Win32"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode|x64"
>
<Tool
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\tile.cpp"
>