From a6dc7abc9b8cc3986eda5a84141da7dc9e4e8f1a Mon Sep 17 00:00:00 2001 From: aliaspider Date: Wed, 29 Oct 2014 05:36:07 +0100 Subject: start moving everything to C --- libretro.c | 877 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 877 insertions(+) create mode 100644 libretro.c (limited to 'libretro.c') diff --git a/libretro.c b/libretro.c new file mode 100644 index 0000000..ded3dc9 --- /dev/null +++ b/libretro.c @@ -0,0 +1,877 @@ + +#include + +#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 +#else +#ifndef PSP_LEGACY_TYPES_DEFINED +#define PSP_LEGACY_TYPES_DEFINED +typedef uint8_t u8; +typedef uint16_t u16; + +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; + +typedef int32_t s32; +typedef int64_t s64; +#endif +#endif + +#include + +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) {} + +unsigned retro_api_version() { return RETRO_API_VERSION; } + + + +void S9xProcessSound (unsigned int); + +char *rom_filename = NULL; +char *SDD1_pack = NULL; + +/* + * 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 + +void S9xMessage (int /*type*/, int /*number*/, const char *message) +{ +#if 1 +#define MAX_MESSAGE_LEN (36 * 3) + + static char buffer [MAX_MESSAGE_LEN + 1]; + + printf ("%s\n", message); + strncpy (buffer, message, MAX_MESSAGE_LEN); + buffer [MAX_MESSAGE_LEN] = 0; + S9xSetInfoString (buffer); +#endif +} + +void S9xExtraUsage () +{ + /*empty*/ +} + +/* +* Release display device +*/ +void S9xDeinitDisplay (void) +{ +#ifdef DS2_DMA + if(GFX.Screen) AlignedFree(GFX.Screen, PtrAdj.GFXScreen); +#else + if(GFX.Screen) free(GFX.Screen); +#endif + if(GFX.SubScreen) free(GFX.SubScreen); + if(GFX.ZBuffer) free(GFX.ZBuffer); + if(GFX.SubZBuffer) free(GFX.SubZBuffer); +} + +void S9xInitDisplay (void) +{ + int h = IMAGE_HEIGHT; + + GFX.Pitch = IMAGE_WIDTH * 2; +#ifdef DS2_DMA + GFX.Screen = (unsigned char*) AlignedMalloc (GFX.Pitch * h, 32, &PtrAdj.GFXScreen); +#else + GFX.Screen = (unsigned char*) malloc (GFX.Pitch * h); +#endif + GFX.SubScreen = (unsigned char*) malloc (GFX.Pitch * h); + GFX.ZBuffer = (unsigned char*) malloc ((GFX.Pitch >> 1) * h); + GFX.SubZBuffer =(unsigned char*) malloc ((GFX.Pitch >> 1) * h); + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; +} + +void S9xParseArg (char **argv, int &i, int argc) +{ +} + +void S9xParseDisplayArg (char **argv, int &ind, int) +{ +} + +void S9xExit () +{ +// if(Settings.SPC7110) +// (*CleanUp7110)(); + +// S9xSetSoundMute (TRUE); +// S9xDeinitDisplay (); +// Memory.SaveSRAM (S9xGetFilename (".srm")); +// // S9xSaveCheatFile (S9xGetFilename (".chb")); // cheat binary file +// // Do this when loading a cheat file! +// Memory.Deinit (); +// S9xDeinitAPU (); + +// exit(0); +} + +const char *S9xBasename (const char *f) +{ + const char *p; + if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) + return (p + 1); + + return (f); +} + +bool8 S9xInitUpdate () +{ +// IPPU.RenderThisFrame = 0; +// video_cb(dummy_frame,256,224,512); +// return (FALSE); + + return (TRUE); +} + + +extern void NDSSFCDrawFrameAntialiased(void* screen_addr); + +#ifdef PSP +#include +#include +void S9xDeinitUpdate (int width, int height, bool8 /*sixteen_bit*/) +{ + static unsigned int __attribute__((aligned(16))) d_list[32]; + void* const texture_vram_p = (void*) (0x44200000 - (512 * 512)); // max VRAM address - frame size + + sceKernelDcacheWritebackRange(GFX.Screen, GFX.Pitch*height); + + sceGuStart(GU_DIRECT, d_list); + + sceGuCopyImage(GU_PSM_4444, 0, 0, width, height, GFX.Pitch>>1, GFX.Screen, 0, 0, 512, texture_vram_p); + + 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 +void S9xDeinitUpdate (int width, int height) +{ + video_cb(GFX.Screen, width, height, GFX.Pitch); +} + +#endif + +void _makepath (char *path, const char *, const char *dir, + const char *fname, const char *ext) +{ + if (dir && *dir) + { + strcpy (path, dir); + strcat (path, "/"); + } + else + *path = 0; + strcat (path, fname); + if (ext && *ext) + { + 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, ""); + } + else + { + 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, ""); + } +} + +void S9xProcessEvents (bool8 block) +{ + +} + +void OutOfMemory () +{ +} + + +const char *S9xGetROMDirectory () +{ + return "./"; +} + + +const char *S9xGetSnapshotDirectory () +{ + return "./"; +} + +const char *S9xGetFilename (const char *ex) +{ + 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]; + + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy (filename, S9xGetSnapshotDirectory ()); + strcat (filename, SLASH_STR); + strcat (filename, fname); + strcat (filename, ex); + + return (filename); +} + +const char *S9xGetFilenameInc (const char *e) +{ + return e; +#if 0 + static char filename [_MAX_PATH + 1]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char *ptr; + struct stat buf; + + if (strlen (S9xGetSnapshotDirectory())) + { + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcpy (filename, S9xGetSnapshotDirectory()); + strcat (filename, "/"); + strcat (filename, fname); + ptr = filename + strlen (filename); + strcat (filename, "00/"); + strcat (filename, e); + } + else + { + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + strcat (fname, "00/"); + _makepath (filename, drive, dir, fname, e); + ptr = strstr (filename, "00/"); + } + + do + { + if (++*(ptr + 2) > '9') + { + *(ptr + 2) = '0'; + if (++*(ptr + 1) > '9') + { + *(ptr + 1) = '0'; + if (++*ptr > '9') + break; + } + } + } while( stat(filename, &buf) == 0 ); + + return (filename); +#endif +} + +void S9xInitInputDevices () +{ +#ifdef JOYSTICK_SUPPORT + InitJoysticks (); +#endif +} + + +void init_sfc_setting(void) +{ + ZeroMemory (&Settings, sizeof (Settings)); +#ifdef JOYSTICK_SUPPORT + Settings.JoystickEnabled = TRUE; +#else + Settings.JoystickEnabled = FALSE; +#endif + + Settings.SoundPlaybackRate = 44100; // -> ds2sound.h for defs + Settings.SoundBufferSize = 512; + Settings.CyclesPercentage = 100; + Settings.DisableSoundEcho = FALSE; + //sound settings + Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; + // Settings.FixFrequency = 1; + + 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; + + Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; +} + +void S9xAutoSaveSRAM () +{ + Memory.SaveSRAM (S9xGetFilename (".srm")); +} + +int game_load_state(char* file) +{ + int flag; + + flag = 0; + if(S9xUnfreezeGame(file) == FALSE) + flag = -1; + + return flag; +} + +int game_save_state(char* file) +{ + int flag; + + flag = 0; + if(S9xFreezeGame(file) == FALSE) + flag = -1; + + S9xAutoSaveSRAM (); + + return flag; +} + +void game_restart(void) +{ + CPU.Flags = 0; + S9xReset (); +} + +int load_gamepak(const char* file) +{ + CPU.Flags = 0; + // mdelay(50); // Delete this delay + if (!Memory.LoadROM (file)) + return -1; + S9xReset (); + + Settings.FrameTime = (Settings.PAL ? Settings.FrameTimePAL : Settings.FrameTimeNTSC); + + Memory.LoadSRAM (S9xGetFilename (".srm")); + S9xLoadCheatFile (S9xGetFilename (".chb")); // cheat binary file, as opposed to text + + return 0; +} + +extern "C" void sfc_main(void); + +void retro_init (void) +{ + 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; + 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"); + + init_sfc_setting(); + + if (!Memory.Init () || !S9xInitAPU()) + OutOfMemory (); + + S9xInitDisplay (); + if (!S9xGraphicsInit()) + OutOfMemory (); + + S9xInitSound (Settings.SoundPlaybackRate, + TRUE, + Settings.SoundBufferSize); + +#ifdef JOYSTICK_SUPPORT + uint32 JoypadSkip = 0; +#endif + + +} + + +uint32 S9xReadJoypad (int port) +{ + 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 + }; + + int i; + uint32 joypad = 0; + + for ( i = RETRO_DEVICE_ID_JOYPAD_B; i <= RETRO_DEVICE_ID_JOYPAD_R; i++) + if (input_cb(port, RETRO_DEVICE_JOYPAD, 0, i)) + joypad |= snes_lut[i]; + + return joypad; +} + +//#define FRAMESKIP +void retro_run (void) +{ + int i, port; + +// IPPU.RenderThisFrame = FALSE; +// video_cb(GFX.Screen, 256, 224, 512); + + poll_cb(); + + S9xSetPlaybackRate(32040); + so.mute_sound = FALSE; + SoundData.echo_enable = FALSE; + + S9xMainLoop(); + + static s16 audio_buf[534 << 1]; + S9xMixSamples ((uint8*)audio_buf, 534 << 1); + 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 + +// if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) +// check_variables(); + +} + + +static unsigned int sync_last= 0; +static unsigned int sync_next = 0; + +static unsigned int skip_rate= 0; + +void S9xSyncSpeed () +{ +} + +bool8 S9xOpenSoundDevice (int mode, bool8 stereo, int buffer_size) +{ + return (TRUE); +} + +void S9xGenerateSound () +{ +// static s16 audio_buf[855 << 1]; +// S9xMixSamples ((uint8*)audio_buf, 855 << 1); +// audio_batch_cb(audio_buf, 855); + + + +} + +void S9xGenerateSound0 () +{ + 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; + samples_to_write <<= 1; + 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; + bytes_this_run <<= 1; + + 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; + samples_this_run >>= 1; + + S9xMixSamples (Buf + byte_offset, samples_this_run); + 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; + } while (samples_to_write > 0); + } +} + +#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)) +#define TRUE_SOUND_EMISSION_INTERVAL ((((double) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128) +#define SOUND_EMISSION_INTERVAL_ERROR ((int) ((TRUE_SOUND_EMISSION_INTERVAL - SOUND_EMISSION_INTERVAL) * FIXED_POINT)) +static unsigned int LastSoundEmissionTime = 0; + +/* + * Accumulated error in the sound emission time. The unit is as follows: + * FIXED_POINT = 42.667 microseconds. + * As the error goes past FIXED_POINT, the new target for sound emission + * becomes 42.667 microseconds LATER. This helps with sound buffer overruns, + * correctly dealing with the fact that 42.667 microseconds does not fit + * an integer number of times in 1/32000 second (or whatever sampling rate). + */ +static unsigned int SoundEmissionTimeError = 0; + +void S9xProcessSound (unsigned int) +{ + +} + +/* +const unsigned int keymap[12] = { + 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 + }; +*/ + +static bool8 SoundToggleWasHeld = FALSE; +static bool8 LoadStateWasHeld = FALSE; +static bool8 SaveStateWasHeld = FALSE; +static bool8 ToggleFullScreenWasHeld = FALSE; + +#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; + +void NDSSFCAccumulateJoypad () +{ + struct key_buf inputdata; + ds2_getrawInput(&inputdata); + + ControlsPressed |= inputdata.key & ~PreviousControls; + ControlsReleased |= PreviousControls & ~inputdata.key; +} +#endif // ACCUMULATE_JOYPAD + +static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) +{ + return (*(uint32 *) p1 - *(uint32 *) p2); +} + +void S9xLoadSDD1Data () +{ + +} + +bool8 S9xReadMousePosition (int which1, int &x, int &y, uint32 &buttons) +{ + return (FALSE); +} + +bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons) +{ + return (TRUE); +} + +bool JustifierOffscreen() +{ + return (FALSE); +} + +void JustifierButtons(uint32& justifiers) +{ +} + +START_EXTERN_C +char* osd_GetPackDir() +{ + 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; +} +END_EXTERN_C + + +void retro_deinit (void) +{ +} +unsigned retro_get_region (void) +{ + return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; +} +void retro_get_system_info(struct retro_system_info *info) +{ + 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; +} +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + 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; +// if (!Settings.PAL) +// info->timing.fps = 21477272.0 / 357366.0; +// else +// info->timing.fps = 21281370.0 / 425568.0; +// info->timing.sample_rate = 32040.5; + + + info->timing.fps = 60.0; + info->timing.sample_rate = 32040.0; +} + +void retro_reset(void) +{ + +} + + +size_t retro_serialize_size(void) +{ + return 0; +} + +bool retro_serialize(void *data, size_t size) +{ + return false; +} +bool retro_unserialize(const void *data, size_t size) +{ + return false; +} + +void retro_cheat_reset(void) +{ + +} +void retro_cheat_set(unsigned index, bool enabled, const char *code) +{ + +} + +bool retro_load_game(const struct retro_game_info *game) + +{ + Memory.LoadROM(game->path); + return true; +} + +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +) +{ + return false; +} +void retro_unload_game(void) +{ + +} + +void *retro_get_memory_data(unsigned id) +{ + return NULL; +} + +size_t retro_get_memory_size(unsigned id) +{ + return 0; +} -- cgit v1.2.3