2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "snes9x.h"
|
|
|
|
#include "soundux.h"
|
|
|
|
#include "memmap.h"
|
|
|
|
#include "apu.h"
|
|
|
|
#include "cheats.h"
|
|
|
|
#include "snapshot.h"
|
|
|
|
#include "display.h"
|
|
|
|
#include "gfx.h"
|
|
|
|
#include "cpuexec.h"
|
|
|
|
#include "spc7110.h"
|
|
|
|
|
|
|
|
#ifdef PSP
|
|
|
|
#include <psptypes.h>
|
|
|
|
#else
|
|
|
|
#ifndef PSP_LEGACY_TYPES_DEFINED
|
|
|
|
#define PSP_LEGACY_TYPES_DEFINED
|
2014-10-29 23:23:30 +00:00
|
|
|
typedef uint8_t u8;
|
|
|
|
typedef uint16_t u16;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
typedef uint32_t u32;
|
|
|
|
typedef uint64_t u64;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
typedef int8_t s8;
|
|
|
|
typedef int16_t s16;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
typedef int32_t s32;
|
|
|
|
typedef int64_t s64;
|
2014-10-28 02:13:05 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <libretro.h>
|
|
|
|
|
|
|
|
static retro_log_printf_t log_cb = NULL;
|
|
|
|
static retro_video_refresh_t video_cb = NULL;
|
|
|
|
static retro_input_poll_t poll_cb = NULL;
|
|
|
|
static retro_input_state_t input_cb = NULL;
|
|
|
|
static retro_audio_sample_batch_t audio_batch_cb = NULL;
|
|
|
|
static retro_environment_t environ_cb = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
struct retro_perf_callback perf_cb;
|
|
|
|
|
|
|
|
void retro_set_environment(retro_environment_t cb)
|
|
|
|
{
|
|
|
|
struct retro_log_callback log;
|
|
|
|
|
|
|
|
environ_cb = cb;
|
|
|
|
|
|
|
|
if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
|
|
|
|
log_cb = log.log;
|
|
|
|
else
|
|
|
|
log_cb = NULL;
|
|
|
|
|
|
|
|
environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void retro_set_video_refresh(retro_video_refresh_t cb)
|
|
|
|
{
|
|
|
|
video_cb = cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_set_audio_sample(retro_audio_sample_t cb)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
|
|
|
|
{
|
|
|
|
audio_batch_cb = cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_set_input_poll(retro_input_poll_t cb)
|
|
|
|
{
|
|
|
|
poll_cb = cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_set_input_state(retro_input_state_t cb)
|
|
|
|
{
|
|
|
|
input_cb = cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_set_controller_port_device(unsigned port, unsigned device) {}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
unsigned retro_api_version()
|
|
|
|
{
|
|
|
|
return RETRO_API_VERSION;
|
|
|
|
}
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xProcessSound(unsigned int samples);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
char* rom_filename = NULL;
|
|
|
|
char* SDD1_pack = NULL;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* It is only safe to manipulate saved states between frames.
|
|
|
|
*/
|
|
|
|
static bool8 LoadStateNeeded = FALSE;
|
|
|
|
static bool8 SaveStateNeeded = FALSE;
|
|
|
|
|
|
|
|
static u8 Buf[MAX_BUFFER_SIZE];
|
|
|
|
|
|
|
|
#define FIXED_POINT 0x10000
|
|
|
|
#define FIXED_POINT_SHIFT 16
|
|
|
|
#define FIXED_POINT_REMAINDER 0xffff
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xMessage(int type, int number, const char* message)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
#if 1
|
|
|
|
#define MAX_MESSAGE_LEN (36 * 3)
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
static char buffer [MAX_MESSAGE_LEN + 1];
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
printf("%s\n", message);
|
|
|
|
strncpy(buffer, message, MAX_MESSAGE_LEN);
|
|
|
|
buffer [MAX_MESSAGE_LEN] = 0;
|
|
|
|
S9xSetInfoString(buffer);
|
2014-10-28 02:13:05 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xExtraUsage()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
/*empty*/
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Release display device
|
|
|
|
*/
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xDeinitDisplay(void)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
#ifdef DS2_DMA
|
2014-10-30 00:51:26 +00:00
|
|
|
if (GFX.Screen_buffer) AlignedFree(GFX.Screen, PtrAdj.GFXScreen);
|
2014-10-28 02:13:05 +00:00
|
|
|
#else
|
2014-10-30 00:51:26 +00:00
|
|
|
if (GFX.Screen_buffer) free(GFX.Screen_buffer);
|
2014-10-28 02:13:05 +00:00
|
|
|
#endif
|
2014-10-30 00:51:26 +00:00
|
|
|
if (GFX.SubScreen_buffer) free(GFX.SubScreen_buffer);
|
|
|
|
if (GFX.ZBuffer_buffer) free(GFX.ZBuffer_buffer);
|
|
|
|
if (GFX.SubZBuffer_buffer) free(GFX.SubZBuffer_buffer);
|
|
|
|
|
|
|
|
GFX.Screen = NULL;
|
|
|
|
GFX.Screen_buffer = NULL;
|
|
|
|
GFX.SubScreen = NULL;
|
|
|
|
GFX.SubScreen_buffer = NULL;
|
|
|
|
GFX.ZBuffer = NULL;
|
|
|
|
GFX.ZBuffer_buffer = NULL;
|
|
|
|
GFX.SubZBuffer = NULL;
|
|
|
|
GFX.SubZBuffer_buffer = NULL;
|
|
|
|
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xInitDisplay(void)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
int h = IMAGE_HEIGHT;
|
2014-10-30 00:51:26 +00:00
|
|
|
const int safety = 32;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
GFX.Pitch = IMAGE_WIDTH * 2;
|
|
|
|
#ifdef DS2_DMA
|
2014-10-30 00:51:26 +00:00
|
|
|
GFX.Screen_buffer = (unsigned char*) AlignedMalloc(GFX.Pitch * h + safety, 32,
|
2014-10-29 23:23:30 +00:00
|
|
|
&PtrAdj.GFXScreen);
|
2014-10-28 02:13:05 +00:00
|
|
|
#else
|
2014-10-30 00:51:26 +00:00
|
|
|
GFX.Screen_buffer = (unsigned char*) malloc(GFX.Pitch * h + safety);
|
2014-10-28 02:13:05 +00:00
|
|
|
#endif
|
2014-10-30 00:51:26 +00:00
|
|
|
GFX.SubScreen_buffer = (unsigned char*) malloc(GFX.Pitch * h + safety);
|
|
|
|
GFX.ZBuffer_buffer = (unsigned char*) malloc((GFX.Pitch >> 1) * h + safety);
|
|
|
|
GFX.SubZBuffer_buffer = (unsigned char*) malloc((GFX.Pitch >> 1) * h + safety);
|
|
|
|
|
|
|
|
GFX.Screen = GFX.Screen_buffer + safety;
|
|
|
|
GFX.SubScreen = GFX.SubScreen_buffer + safety;
|
|
|
|
GFX.ZBuffer = GFX.ZBuffer_buffer + safety;
|
|
|
|
GFX.SubZBuffer = GFX.SubZBuffer_buffer + safety;
|
|
|
|
|
|
|
|
|
2014-10-28 02:13:05 +00:00
|
|
|
GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1;
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xExit()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
// if(Settings.SPC7110)
|
|
|
|
// (*CleanUp7110)();
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
// S9xDeinitDisplay ();
|
|
|
|
// Memory.SaveSRAM (S9xGetFilename (".srm"));
|
|
|
|
// // S9xSaveCheatFile (S9xGetFilename (".chb")); // cheat binary file
|
|
|
|
// // Do this when loading a cheat file!
|
|
|
|
// Memory.Deinit ();
|
|
|
|
// S9xDeinitAPU ();
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
// exit(0);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
const char* S9xBasename(const char* f)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
const char* p;
|
|
|
|
if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL)
|
|
|
|
return (p + 1);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
return (f);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
bool8 S9xInitUpdate()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
// IPPU.RenderThisFrame = 0;
|
|
|
|
// video_cb(dummy_frame,256,224,512);
|
|
|
|
// return (FALSE);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
return (TRUE);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef PSP
|
|
|
|
#include <pspkernel.h>
|
|
|
|
#include <pspgu.h>
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xDeinitUpdate(int width, int height)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
static unsigned int __attribute__((aligned(16))) d_list[32];
|
2014-10-29 23:23:30 +00:00
|
|
|
void* const texture_vram_p = (void*)(0x44200000 - (512 *
|
|
|
|
512)); // max VRAM address - frame size
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
sceKernelDcacheWritebackRange(GFX.Screen, GFX.Pitch * height);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
sceGuStart(GU_DIRECT, d_list);
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
sceGuCopyImage(GU_PSM_4444, 0, 0, width, height, GFX.Pitch >> 1, GFX.Screen, 0,
|
|
|
|
0,
|
|
|
|
512, texture_vram_p);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
sceGuTexSync();
|
|
|
|
sceGuTexImage(0, 512, 512, 512, texture_vram_p);
|
|
|
|
sceGuTexMode(GU_PSM_5551, 0, 0, GU_FALSE);
|
|
|
|
sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
|
|
|
|
sceGuDisable(GU_BLEND);
|
|
|
|
|
|
|
|
sceGuFinish();
|
|
|
|
|
|
|
|
|
|
|
|
video_cb(texture_vram_p, width, height, GFX.Pitch);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xDeinitUpdate(int width, int height)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
video_cb(GFX.Screen, width, height, GFX.Pitch);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void _makepath(char* path, const char* drive, const char* dir,
|
|
|
|
const char* fname, const char* ext)
|
|
|
|
{
|
|
|
|
if (dir && *dir)
|
|
|
|
{
|
|
|
|
strcpy(path, dir);
|
|
|
|
strcat(path, "/");
|
|
|
|
}
|
2014-10-28 02:13:05 +00:00
|
|
|
else
|
2014-10-29 23:23:30 +00:00
|
|
|
*path = 0;
|
|
|
|
strcat(path, fname);
|
|
|
|
if (ext && *ext)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
strcat(path, ".");
|
|
|
|
strcat(path, ext);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _splitpath(const char* path, char* drive, char* dir, char* fname,
|
|
|
|
char* ext)
|
|
|
|
{
|
|
|
|
*drive = 0;
|
|
|
|
|
|
|
|
char* slash = strrchr((char*)path, '/');
|
|
|
|
if (!slash)
|
|
|
|
slash = strrchr((char*)path, '\\');
|
|
|
|
|
|
|
|
char* dot = strrchr((char*)path, '.');
|
|
|
|
|
|
|
|
if (dot && slash && dot < slash)
|
|
|
|
dot = NULL;
|
|
|
|
|
|
|
|
if (!slash)
|
|
|
|
{
|
|
|
|
strcpy(dir, "");
|
|
|
|
strcpy(fname, path);
|
|
|
|
if (dot)
|
|
|
|
{
|
|
|
|
* (fname + (dot - path)) = 0;
|
|
|
|
strcpy(ext, dot + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy(ext, "");
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
else
|
2014-10-29 23:23:30 +00:00
|
|
|
{
|
|
|
|
strcpy(dir, path);
|
|
|
|
* (dir + (slash - path)) = 0;
|
|
|
|
strcpy(fname, slash + 1);
|
|
|
|
if (dot)
|
|
|
|
{
|
|
|
|
* (fname + (dot - slash) - 1) = 0;
|
|
|
|
strcpy(ext, dot + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy(ext, "");
|
|
|
|
}
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
const char* S9xGetSnapshotDirectory()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-30 02:10:39 +00:00
|
|
|
return ".";
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
const char* S9xGetFilename(const char* ex)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
static char filename [PATH_MAX + 1];
|
|
|
|
char drive [_MAX_DRIVE + 1];
|
|
|
|
char dir [_MAX_DIR + 1];
|
|
|
|
char fname [_MAX_FNAME + 1];
|
|
|
|
char ext [_MAX_EXT + 1];
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
|
|
|
|
strcpy(filename, S9xGetSnapshotDirectory());
|
|
|
|
strcat(filename, SLASH_STR);
|
|
|
|
strcat(filename, fname);
|
|
|
|
strcat(filename, ex);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
return (filename);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void init_sfc_setting(void)
|
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
ZeroMemory(&Settings, sizeof(Settings));
|
|
|
|
Settings.JoystickEnabled = FALSE;
|
|
|
|
Settings.SoundPlaybackRate = 44100; // -> ds2sound.h for defs
|
|
|
|
Settings.SoundBufferSize = 512;
|
|
|
|
Settings.CyclesPercentage = 100;
|
|
|
|
Settings.DisableSoundEcho = FALSE;
|
2014-10-28 02:13:05 +00:00
|
|
|
//sound settings
|
2014-10-29 23:23:30 +00:00
|
|
|
Settings.APUEnabled = Settings.NextAPUEnabled = TRUE;
|
2014-10-28 02:13:05 +00:00
|
|
|
// Settings.FixFrequency = 1;
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
Settings.H_Max = SNES_CYCLES_PER_SCANLINE;
|
|
|
|
Settings.SkipFrames = AUTO_FRAMERATE;
|
|
|
|
Settings.ShutdownMaster = TRUE;
|
|
|
|
Settings.FrameTimePAL = 20000;
|
|
|
|
Settings.FrameTimeNTSC = 16667;
|
|
|
|
Settings.DisableMasterVolume = FALSE;
|
|
|
|
Settings.Mouse = TRUE;
|
|
|
|
Settings.SuperScope = TRUE;
|
|
|
|
Settings.MultiPlayer5 = TRUE;
|
|
|
|
Settings.ControllerOption = SNES_JOYPAD;
|
|
|
|
|
|
|
|
Settings.Transparency = TRUE;
|
|
|
|
Settings.SupportHiRes = FALSE;
|
|
|
|
Settings.ThreadSound = FALSE;
|
|
|
|
Settings.SoundSync = TRUE;
|
|
|
|
Settings.ApplyCheats = TRUE;
|
|
|
|
Settings.StretchScreenshots = 1;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX;
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xAutoSaveSRAM()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
SaveSRAM(S9xGetFilename(".srm"));
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int game_load_state(char* file)
|
|
|
|
{
|
|
|
|
int flag;
|
|
|
|
|
|
|
|
flag = 0;
|
2014-10-29 23:23:30 +00:00
|
|
|
if (S9xUnfreezeGame(file) == FALSE)
|
2014-10-28 02:13:05 +00:00
|
|
|
flag = -1;
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
int game_save_state(char* file)
|
|
|
|
{
|
|
|
|
int flag;
|
|
|
|
|
|
|
|
flag = 0;
|
2014-10-29 23:23:30 +00:00
|
|
|
if (S9xFreezeGame(file) == FALSE)
|
2014-10-28 02:13:05 +00:00
|
|
|
flag = -1;
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xAutoSaveSRAM();
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
void game_restart(void)
|
|
|
|
{
|
|
|
|
CPU.Flags = 0;
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xReset();
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int load_gamepak(const char* file)
|
|
|
|
{
|
|
|
|
CPU.Flags = 0;
|
|
|
|
// mdelay(50); // Delete this delay
|
2014-10-29 23:23:30 +00:00
|
|
|
if (!LoadROM(file))
|
2014-10-28 02:13:05 +00:00
|
|
|
return -1;
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xReset();
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
Settings.FrameTime = (Settings.PAL ? Settings.FrameTimePAL :
|
|
|
|
Settings.FrameTimeNTSC);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
LoadSRAM(S9xGetFilename(".srm"));
|
|
|
|
S9xLoadCheatFile(
|
|
|
|
S9xGetFilename(".chb")); // cheat binary file, as opposed to text
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-29 05:47:46 +00:00
|
|
|
void sfc_main(void);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void retro_init(void)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
struct retro_log_callback log;
|
|
|
|
enum retro_pixel_format rgb565;
|
|
|
|
|
|
|
|
if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
|
|
|
|
log_cb = log.log;
|
|
|
|
else
|
|
|
|
log_cb = NULL;
|
|
|
|
|
|
|
|
rgb565 = RETRO_PIXEL_FORMAT_RGB565;
|
2014-10-29 23:23:30 +00:00
|
|
|
if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb)
|
|
|
|
log_cb(RETRO_LOG_INFO,
|
|
|
|
"Frontend supports RGB565 - will use that instead of XRGB1555.\n");
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
init_sfc_setting();
|
2014-10-30 02:10:39 +00:00
|
|
|
Init();
|
|
|
|
S9xInitAPU();
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xInitDisplay();
|
2014-10-30 02:10:39 +00:00
|
|
|
S9xGraphicsInit();
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xInitSound(Settings.SoundPlaybackRate,
|
|
|
|
TRUE,
|
|
|
|
Settings.SoundBufferSize);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
uint32 S9xReadJoypad(int port)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
static const uint32 snes_lut[] =
|
|
|
|
{
|
|
|
|
SNES_B_MASK,
|
|
|
|
SNES_Y_MASK,
|
|
|
|
SNES_SELECT_MASK,
|
|
|
|
SNES_START_MASK,
|
|
|
|
SNES_UP_MASK,
|
|
|
|
SNES_DOWN_MASK,
|
|
|
|
SNES_LEFT_MASK,
|
|
|
|
SNES_RIGHT_MASK,
|
|
|
|
SNES_A_MASK,
|
|
|
|
SNES_X_MASK,
|
|
|
|
SNES_TL_MASK,
|
|
|
|
SNES_TR_MASK
|
2014-10-28 02:13:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int i;
|
|
|
|
uint32 joypad = 0;
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
for (i = RETRO_DEVICE_ID_JOYPAD_B; i <= RETRO_DEVICE_ID_JOYPAD_R; i++)
|
2014-10-28 02:13:05 +00:00
|
|
|
if (input_cb(port, RETRO_DEVICE_JOYPAD, 0, i))
|
|
|
|
joypad |= snes_lut[i];
|
|
|
|
|
|
|
|
return joypad;
|
|
|
|
}
|
|
|
|
|
|
|
|
//#define FRAMESKIP
|
2014-10-29 23:23:30 +00:00
|
|
|
void retro_run(void)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
int i, port;
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
// IPPU.RenderThisFrame = FALSE;
|
|
|
|
// video_cb(GFX.Screen, 256, 224, 512);
|
2014-10-28 05:47:04 +00:00
|
|
|
|
2014-10-28 02:13:05 +00:00
|
|
|
poll_cb();
|
|
|
|
|
|
|
|
S9xSetPlaybackRate(32040);
|
|
|
|
SoundData.echo_enable = FALSE;
|
|
|
|
|
|
|
|
S9xMainLoop();
|
|
|
|
|
|
|
|
static s16 audio_buf[534 << 1];
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xMixSamples((uint8*)audio_buf, 534 << 1);
|
2014-10-28 02:13:05 +00:00
|
|
|
audio_batch_cb(audio_buf, 534);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef FRAMESKIP
|
|
|
|
if (IPPU.RenderThisFrame)
|
|
|
|
IPPU.RenderThisFrame = false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
video_cb(NULL, 256, 224, GFX.Pitch);
|
|
|
|
IPPU.RenderThisFrame = true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
// if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
|
|
|
|
// check_variables();
|
2014-10-28 05:47:04 +00:00
|
|
|
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
static unsigned int sync_last = 0;
|
2014-10-28 02:13:05 +00:00
|
|
|
static unsigned int sync_next = 0;
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
static unsigned int skip_rate = 0;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xSyncSpeed()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xGenerateSound()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
// static s16 audio_buf[855 << 1];
|
|
|
|
// S9xMixSamples ((uint8*)audio_buf, 855 << 1);
|
|
|
|
// audio_batch_cb(audio_buf, 855);
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xGenerateSound0()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
int bytes_so_far = so.samples_mixed_so_far << 1;
|
|
|
|
|
|
|
|
if (bytes_so_far >= so.buffer_size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
so.err_counter += so.err_rate;
|
|
|
|
if (so.err_counter >= FIXED_POINT)
|
|
|
|
{
|
|
|
|
// Write this many samples overall
|
|
|
|
int samples_to_write = so.err_counter >> FIXED_POINT_SHIFT;
|
2014-10-29 04:28:04 +00:00
|
|
|
samples_to_write <<= 1;
|
2014-10-28 02:13:05 +00:00
|
|
|
int byte_offset = (bytes_so_far + so.play_position) & SOUND_BUFFER_SIZE_MASK;
|
|
|
|
|
|
|
|
so.err_counter &= FIXED_POINT_REMAINDER;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int bytes_this_run = samples_to_write;
|
2014-10-29 04:28:04 +00:00
|
|
|
bytes_this_run <<= 1;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE)
|
|
|
|
bytes_this_run = SOUND_BUFFER_SIZE - byte_offset;
|
|
|
|
|
|
|
|
if (bytes_so_far + bytes_this_run > so.buffer_size)
|
|
|
|
{
|
|
|
|
bytes_this_run = so.buffer_size - bytes_so_far;
|
|
|
|
if (bytes_this_run == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int samples_this_run = bytes_this_run;
|
2014-10-29 04:28:04 +00:00
|
|
|
samples_this_run >>= 1;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
S9xMixSamples(Buf + byte_offset, samples_this_run);
|
2014-10-28 02:13:05 +00:00
|
|
|
so.samples_mixed_so_far += samples_this_run;
|
|
|
|
samples_to_write -= samples_this_run;
|
|
|
|
bytes_so_far += samples_this_run << 1;
|
|
|
|
byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK;
|
2014-10-29 23:23:30 +00:00
|
|
|
}
|
|
|
|
while (samples_to_write > 0);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xProcessSound(unsigned int samples)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
const unsigned int keymap[12] = {
|
2014-10-29 23:23:30 +00:00
|
|
|
0x80, //KEY_A
|
|
|
|
0x8000, //KEY_B
|
|
|
|
0x2000, //KEY_SELECT
|
|
|
|
0x1000, //KEY_START
|
|
|
|
0x100, //KEY_RIGHT
|
|
|
|
0x200, //KEY_LEFT
|
|
|
|
0x800, //KEY_UP
|
|
|
|
0x400, //KEY_DOWN
|
|
|
|
0x10, //KEY_R
|
|
|
|
0x20, //KEY_L
|
|
|
|
0x40, //KEY_X
|
|
|
|
0x4000 //KEY_Y
|
2014-10-28 02:13:05 +00:00
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef ACCUMULATE_JOYPAD
|
|
|
|
// These are kept as DS key bitfields until it's time to send them to Snes9x.
|
|
|
|
static uint32 PreviousControls = 0x00000000;
|
|
|
|
static uint32 ControlsPressed = 0x00000000;
|
|
|
|
static uint32 ControlsReleased = 0x00000000;
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void NDSSFCAccumulateJoypad()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
struct key_buf inputdata;
|
|
|
|
ds2_getrawInput(&inputdata);
|
|
|
|
|
|
|
|
ControlsPressed |= inputdata.key & ~PreviousControls;
|
|
|
|
ControlsReleased |= PreviousControls & ~inputdata.key;
|
|
|
|
}
|
|
|
|
#endif // ACCUMULATE_JOYPAD
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
static int S9xCompareSDD1IndexEntries(const void* p1, const void* p2)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
return (* (uint32*) p1 - * (uint32*) p2);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void S9xLoadSDD1Data()
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
bool8 S9xReadMousePosition(int which1, int* x, int* y, uint32* buttons)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
return (FALSE);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
bool8 S9xReadSuperScopePosition(int* x, int* y, uint32* buttons)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
return (TRUE);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool JustifierOffscreen()
|
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
return (FALSE);
|
2014-10-28 02:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 05:47:46 +00:00
|
|
|
void JustifierButtons(uint32* justifiers)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
char* osd_GetPackDir()
|
|
|
|
{
|
2014-10-29 23:23:30 +00:00
|
|
|
static char filename[_MAX_PATH];
|
|
|
|
memset(filename, 0, _MAX_PATH);
|
|
|
|
|
|
|
|
if (strlen(S9xGetSnapshotDirectory()) != 0)
|
|
|
|
strcpy(filename, S9xGetSnapshotDirectory());
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char dir [_MAX_DIR + 1];
|
|
|
|
char drive [_MAX_DRIVE + 1];
|
|
|
|
char name [_MAX_FNAME + 1];
|
|
|
|
char ext [_MAX_EXT + 1];
|
|
|
|
_splitpath(Memory.ROMFilename, drive, dir, name, ext);
|
|
|
|
_makepath(filename, drive, dir, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strncmp((char*)&Memory.ROM [0xffc0], "SUPER POWER LEAG 4 ", 21))
|
|
|
|
{
|
|
|
|
if (getenv("SPL4PACK"))
|
|
|
|
return getenv("SPL4PACK");
|
|
|
|
else
|
|
|
|
strcat(filename, "/SPL4-SP7");
|
|
|
|
}
|
|
|
|
else if (!strncmp((char*)&Memory.ROM [0xffc0], "MOMOTETSU HAPPY ", 21))
|
|
|
|
{
|
|
|
|
if (getenv("MDHPACK"))
|
|
|
|
return getenv("MDHPACK");
|
|
|
|
else
|
|
|
|
strcat(filename, "/SMHT-SP7");
|
|
|
|
}
|
|
|
|
else if (!strncmp((char*)&Memory.ROM [0xffc0], "HU TENGAI MAKYO ZERO ", 21))
|
|
|
|
{
|
|
|
|
if (getenv("FEOEZPACK"))
|
|
|
|
return getenv("FEOEZPACK");
|
|
|
|
else
|
|
|
|
strcat(filename, "/FEOEZSP7");
|
|
|
|
}
|
|
|
|
else if (!strncmp((char*)&Memory.ROM [0xffc0], "JUMP TENGAIMAKYO ZERO", 21))
|
|
|
|
{
|
|
|
|
if (getenv("SJNSPACK"))
|
|
|
|
return getenv("SJNSPACK");
|
|
|
|
else
|
|
|
|
strcat(filename, "/SJUMPSP7");
|
|
|
|
}
|
|
|
|
else strcat(filename, "/MISC-SP7");
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_deinit(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
unsigned retro_get_region(void)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC;
|
|
|
|
}
|
2014-10-29 23:23:30 +00:00
|
|
|
void retro_get_system_info(struct retro_system_info* info)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
info->need_fullpath = true;
|
|
|
|
info->valid_extensions = "smc|fig|sfc|gd3|gd7|dx2|bsx|swc";
|
|
|
|
info->library_version = "v1.4";
|
|
|
|
info->library_name = "SNES9x(CATSFC)";
|
|
|
|
info->block_extract = false;
|
|
|
|
}
|
2014-10-29 23:23:30 +00:00
|
|
|
void retro_get_system_av_info(struct retro_system_av_info* info)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
info->geometry.base_width = 256;
|
|
|
|
info->geometry.base_height = 224;
|
|
|
|
info->geometry.max_width = 512;
|
|
|
|
info->geometry.max_height = 512;
|
|
|
|
info->geometry.aspect_ratio = 4.0 / 3.0;
|
2014-10-29 23:23:30 +00:00
|
|
|
// if (!Settings.PAL)
|
|
|
|
// info->timing.fps = 21477272.0 / 357366.0;
|
|
|
|
// else
|
|
|
|
// info->timing.fps = 21281370.0 / 425568.0;
|
|
|
|
// info->timing.sample_rate = 32040.5;
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
info->timing.fps = 60.0;
|
|
|
|
info->timing.sample_rate = 32040.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_reset(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-28 07:42:58 +00:00
|
|
|
|
2014-10-28 02:13:05 +00:00
|
|
|
size_t retro_serialize_size(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
bool retro_serialize(void* data, size_t size)
|
|
|
|
{
|
2014-10-28 02:13:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
2014-10-29 23:23:30 +00:00
|
|
|
bool retro_unserialize(const void* data, size_t size)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void retro_cheat_reset(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2014-10-29 23:23:30 +00:00
|
|
|
void retro_cheat_set(unsigned index, bool enabled, const char* code)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
bool retro_load_game(const struct retro_game_info* game)
|
2014-10-28 02:13:05 +00:00
|
|
|
|
|
|
|
{
|
2014-10-29 09:11:16 +00:00
|
|
|
LoadROM(game->path);
|
2014-10-28 02:13:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
bool retro_load_game_special(unsigned game_type,
|
|
|
|
const struct retro_game_info* info, size_t num_info)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
void retro_unload_game(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-29 23:23:30 +00:00
|
|
|
void* retro_get_memory_data(unsigned id)
|
2014-10-28 02:13:05 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t retro_get_memory_size(unsigned id)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|