Made custom FCEU API integration code to fix reentrant ROM crashes

in console ports - goes through Griffin file now
This commit is contained in:
twinaphex
2014-04-18 19:16:52 +02:00
parent d1b62cdfe2
commit 216a88eda3
15 changed files with 2282 additions and 75 deletions

View File

@@ -0,0 +1,103 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Contains file I/O functions that write/read data */
/* LSB first. */
#include <stdio.h>
#include "fceu-memory.h"
#include "fceu-types.h"
#include "fceu-endian.h"
void FlipByteOrder(uint8 *src, uint32 count)
{
uint8 *start = src;
uint8 *end = src + count - 1;
if ((count & 1) || !count)
return; /* This shouldn't happen. */
while (count--)
{
uint8 tmp;
tmp = *end;
*end = *start;
*start = tmp;
end--;
start++;
}
}
int write16le(uint16 b, FILE *fp)
{
uint8 s[2];
s[0] = b;
s[1] = b >> 8;
return((fwrite(s, 1, 2, fp) < 2) ? 0 : 2);
}
int write32le(uint32 b, FILE *fp)
{
uint8 s[4];
s[0] = b;
s[1] = b >> 8;
s[2] = b >> 16;
s[3] = b >> 24;
return((fwrite(s, 1, 4, fp) < 4) ? 0 : 4);
}
int read32le(uint32 *Bufo, FILE *fp)
{
uint32 buf;
if (fread(&buf, 1, 4, fp) < 4)
return 0;
#ifdef LSB_FIRST
*(uint32*)Bufo = buf;
#else
*(uint32*)Bufo = ((buf & 0xFF) << 24) | ((buf & 0xFF00) << 8) | ((buf & 0xFF0000) >> 8) | ((buf & 0xFF000000) >> 24);
#endif
return 1;
}
int read16le(char *d, FILE *fp)
{
#ifdef LSB_FIRST
return((fread(d, 1, 2, fp) < 2) ? 0 : 2);
#else
int ret;
ret = fread(d + 1, 1, 1, fp);
ret += fread(d, 1, 1, fp);
return ret < 2 ? 0 : 2;
#endif
}
void FCEU_en32lsb(uint8 *buf, uint32 morp)
{
buf[0] = morp;
buf[1] = morp >> 8;
buf[2] = morp >> 16;
buf[3] = morp >> 24;
}
uint32 FCEU_de32lsb(uint8 *morp)
{
return(morp[0] | (morp[1] << 8) | (morp[2] << 16) | (morp[3] << 24));
}

View File

@@ -0,0 +1,14 @@
#ifndef _FCEU_ENDIAN_H
#define _FCEU_ENDIAN_H
#include "fceu-memory.h"
int write16le(uint16 b, FILE *fp);
int write32le(uint32 b, FILE *fp);
int read32le(uint32 *Bufo, FILE *fp);
void FlipByteOrder(uint8 *src, uint32 count);
void FCEU_en32lsb(uint8 *, uint32);
uint32 FCEU_de32lsb(uint8 *);
#endif

View File

@@ -0,0 +1,63 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include "fceu-types.h"
#include "fceu.h"
#include "fceu-memory.h"
#include "general.h"
void *FCEU_gmalloc(uint32 size)
{
void *ret;
ret = malloc(size);
if (!ret)
{
FCEU_PrintError("Error allocating memory! Doing a hard exit.");
exit(1);
}
return ret;
}
void *FCEU_malloc(uint32 size)
{
int retval = 0;
void *ret;
ret = (void*)malloc(size);
if (!ret)
{
FCEU_PrintError("Error allocating memory!");
ret = 0;
}
return ret;
}
void FCEU_free(void *ptr)
{
free(ptr);
}
void FCEU_gfree(void *ptr)
{
free(ptr);
}

View File

@@ -0,0 +1,50 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Various macros for faster memory stuff
(at least that's the idea)
*/
#ifndef _FCEU_MEMORY_H_
#define _FCEU_MEMORY_H_
#include "fceu-types.h"
#include "../memstream.h"
#define FCEU_dwmemset(d, c, n) { int _x; for (_x = n - 4; _x >= 0; _x -= 4) *(uint32*)& (d)[_x] = c; }
#define HAVE_MEMSTREAM
#define MEM_TYPE memstream_t
#define fwrite(ptr, size, nmemb, stream) memstream_write((stream), (ptr), (nmemb))
#define fclose(fp) memstream_close((fp))
#define fgetc(stream) memstream_getc((stream))
#define fputc(c, stream) memstream_putc((stream), (c))
#define ftell(a) memstream_pos((a))
#define fread(ptr, size, nmemb, stream) memstream_read((stream), (ptr), (nmemb))
#define fseek(stream, offset, whence) memstream_seek((stream), (offset), (whence))
void *FCEU_malloc(uint32 size);
void *FCEU_gmalloc(uint32 size);
void FCEU_gfree(void *ptr);
void FCEU_free(void *ptr);
void FASTAPASS(3) FCEU_memmove(void *d, void *s, uint32 l);
#endif

View File

@@ -0,0 +1,553 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2003 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "ppu.h"
#include "sound.h"
#include "netplay.h"
#include "general.h"
#include "fceu-endian.h"
#include "fceu-memory.h"
#include "cart.h"
#include "nsf.h"
#include "fds.h"
#include "ines.h"
#include "unif.h"
#include "cheat.h"
#include "palette.h"
#include "state.h"
#include "video.h"
#include "input.h"
#include "file.h"
#include "crc32.h"
#include "vsuni.h"
uint64 timestampbase;
FCEUGI *GameInfo = NULL;
void (*GameInterface)(int h);
void (*GameStateRestore)(int version);
readfunc ARead[0x10000];
writefunc BWrite[0x10000];
static readfunc *AReadG;
static writefunc *BWriteG;
static int RWWrap = 0;
static DECLFW(BNull)
{
}
static DECLFR(ANull)
{
return(X.DB);
}
int AllocGenieRW(void)
{
if (!(AReadG = (readfunc*)FCEU_malloc(0x8000 * sizeof(readfunc))))
return 0;
if (!(BWriteG = (writefunc*)FCEU_malloc(0x8000 * sizeof(writefunc))))
return 0;
RWWrap = 1;
return 1;
}
void FlushGenieRW(void)
{
int32 x;
if (RWWrap)
{
for (x = 0; x < 0x8000; x++)
{
ARead[x + 0x8000] = AReadG[x];
BWrite[x + 0x8000] = BWriteG[x];
}
free(AReadG);
free(BWriteG);
AReadG = 0;
BWriteG = 0;
}
RWWrap = 0;
}
readfunc FASTAPASS(1) GetReadHandler(int32 a)
{
if (a >= 0x8000 && RWWrap)
return AReadG[a - 0x8000];
else
return ARead[a];
}
void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func)
{
int32 x;
if (!func)
func = ANull;
if (RWWrap)
for (x = end; x >= start; x--)
{
if (x >= 0x8000)
AReadG[x - 0x8000] = func;
else
ARead[x] = func;
}
else
for (x = end; x >= start; x--)
ARead[x] = func;
}
writefunc FASTAPASS(1) GetWriteHandler(int32 a)
{
if (RWWrap && a >= 0x8000)
return BWriteG[a - 0x8000];
else
return BWrite[a];
}
void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func)
{
int32 x;
if (!func)
func = BNull;
if (RWWrap)
for (x = end; x >= start; x--)
{
if (x >= 0x8000)
BWriteG[x - 0x8000] = func;
else
BWrite[x] = func;
}
else
for (x = end; x >= start; x--)
BWrite[x] = func;
}
#ifdef COPYFAMI
uint8 RAM[0x4000];
#else
uint8 RAM[0x800];
#endif
uint8 PAL = 0;
static DECLFW(BRAML)
{
RAM[A] = V;
}
static DECLFR(ARAML)
{
return RAM[A];
}
#ifndef COPYFAMI
static DECLFW(BRAMH)
{
RAM[A & 0x7FF] = V;
}
static DECLFR(ARAMH)
{
return RAM[A & 0x7FF];
}
#endif
void FCEUI_CloseGame(void)
{
if (!GameInfo)
return;
if (GameInfo->name)
free(GameInfo->name);
GameInfo->name = 0;
if (GameInfo->type != GIT_NSF)
FCEU_FlushGameCheats(0, 0);
GameInterface(GI_CLOSE);
ResetExState(0, 0);
FCEU_CloseGenie();
free(GameInfo);
GameInfo = 0;
}
void ResetGameLoaded(void)
{
if (GameInfo)
FCEUI_CloseGame();
GameStateRestore = NULL;
PPU_hook = NULL;
GameHBIRQHook = NULL;
if (GameExpSound.Kill)
GameExpSound.Kill();
memset(&GameExpSound, 0, sizeof(GameExpSound));
MapIRQHook = NULL;
MMC5Hack = 0;
PEC586Hack = 0;
PAL &= 1;
pale = 0;
}
int UNIFLoad(const char *name, FCEUFILE *fp);
int iNESLoad(const char *name, FCEUFILE *fp);
int FDSLoad(const char *name, FCEUFILE *fp);
int NSFLoad(FCEUFILE *fp);
FCEUGI *FCEUI_LoadGame(const char *name)
{
FCEUFILE *fp;
char *ipsfn;
ResetGameLoaded();
GameInfo = malloc(sizeof(FCEUGI));
memset(GameInfo, 0, sizeof(FCEUGI));
GameInfo->soundchan = 0;
GameInfo->soundrate = 0;
GameInfo->name = 0;
GameInfo->type = GIT_CART;
GameInfo->vidsys = GIV_USER;
GameInfo->input[0] = GameInfo->input[1] = -1;
GameInfo->inputfc = -1;
GameInfo->cspecial = 0;
FCEU_printf("Loading %s...\n\n", name);
GetFileBase(name);
ipsfn = FCEU_MakeFName(FCEUMKF_IPS, 0, 0);
fp = FCEU_fopen(name, ipsfn, "rb", 0);
free(ipsfn);
if (!fp) {
FCEU_PrintError("Error opening \"%s\"!", name);
return 0;
}
if (iNESLoad(name, fp))
goto endlseq;
if (NSFLoad(fp))
goto endlseq;
if (UNIFLoad(name, fp))
goto endlseq;
if (FDSLoad(name, fp))
goto endlseq;
FCEU_PrintError("An error occurred while loading the file.");
FCEU_fclose(fp);
return 0;
endlseq:
FCEU_fclose(fp);
FCEU_ResetVidSys();
if (GameInfo->type != GIT_NSF)
if (FSettings.GameGenie)
FCEU_OpenGenie();
PowerNES();
FCEUSS_CheckStates();
if (GameInfo->type != GIT_NSF) {
FCEU_LoadGamePalette();
FCEU_LoadGameCheats(0);
}
FCEU_ResetPalette();
FCEU_ResetMessages(); // Save state, status messages, etc.
return(GameInfo);
}
int CopyFamiLoad(void);
FCEUGI *FCEUI_CopyFamiStart(void)
{
ResetGameLoaded();
GameInfo = (FCEUGI*)malloc(sizeof(FCEUGI));
memset(GameInfo, 0, sizeof(FCEUGI));
GameInfo->soundchan = 0;
GameInfo->soundrate = 0;
GameInfo->name = "copyfami";
GameInfo->type = GIT_CART;
GameInfo->vidsys = GIV_USER;
GameInfo->input[0] = GameInfo->input[1] = -1;
GameInfo->inputfc = -1;
GameInfo->cspecial = 0;
FCEU_printf("Starting CopyFamicom...\n\n");
if (!CopyFamiLoad()) {
FCEU_PrintError("An error occurred while starting CopyFamicom.");
return 0;
}
FCEU_ResetVidSys();
if (GameInfo->type != GIT_NSF)
if (FSettings.GameGenie)
FCEU_OpenGenie();
PowerNES();
FCEUSS_CheckStates();
if (GameInfo->type != GIT_NSF) {
FCEU_LoadGamePalette();
FCEU_LoadGameCheats(0);
}
FCEU_ResetPalette();
FCEU_ResetMessages(); // Save state, status messages, etc.
return(GameInfo);
}
int FCEUI_Initialize(void) {
if (!FCEU_InitVirtualVideo())
return 0;
memset(&FSettings, 0, sizeof(FSettings));
FSettings.UsrFirstSLine[0] = 8;
FSettings.UsrFirstSLine[1] = 0;
FSettings.UsrLastSLine[0] = 231;
FSettings.UsrLastSLine[1] = 239;
FSettings.SoundVolume = 100;
FCEUPPU_Init();
X6502_Init();
return 1;
}
void FCEUI_Kill(void) {
FCEU_KillVirtualVideo();
FCEU_KillGenie();
}
void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) {
int r, ssize;
FCEU_UpdateInput();
if (geniestage != 1) FCEU_ApplyPeriodicCheats();
r = FCEUPPU_Loop(skip);
ssize = FlushEmulateSound();
timestampbase += timestamp;
timestamp = 0;
*pXBuf = skip ? 0 : XBuf;
*SoundBuf = WaveFinal;
*SoundBufSize = ssize;
}
void ResetNES(void)
{
if (!GameInfo)
return;
GameInterface(GI_RESETM2);
FCEUSND_Reset();
FCEUPPU_Reset();
X6502_Reset();
}
void FCEU_MemoryRand(uint8 *ptr, uint32 size)
{
int x = 0;
while (size) {
// *ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default
// Cybernoid NO MUSIC by default
// *ptr = (x & 4) ? 0x7F : 0x00; // Huang Di DEBUG MODE enabled by default
// Minna no Taabou no Nakayoshi Daisakusen DOESN'T BOOT
// Cybernoid NO MUSIC by default
// *ptr = (x & 1) ? 0x55 : 0xAA; // F-15 Sity War HISCORE is screwed...
// 1942 SCORE/HISCORE is screwed...
*ptr = 0xFF;
x++;
size--;
ptr++;
}
}
void hand(X6502 *X, int type, uint32 A)
{
}
void PowerNES(void)
{
if (!GameInfo)
return;
FCEU_CheatResetRAM();
FCEU_CheatAddRAM(2, 0, RAM);
FCEU_GeniePower();
#ifndef COPYFAMI
FCEU_MemoryRand(RAM, 0x800);
#endif
SetReadHandler(0x0000, 0xFFFF, ANull);
SetWriteHandler(0x0000, 0xFFFF, BNull);
#ifdef COPYFAMI
SetReadHandler(0, 0x3FFF, ARAML);
SetWriteHandler(0, 0x3FFF, BRAML);
#else
SetReadHandler(0, 0x7FF, ARAML);
SetWriteHandler(0, 0x7FF, BRAML);
SetReadHandler(0x800, 0x1FFF, ARAMH); /* Part of a little */
SetWriteHandler(0x800, 0x1FFF, BRAMH); /* hack for a small speed boost. */
#endif
InitializeInput();
FCEUSND_Power();
FCEUPPU_Power();
/* Have the external game hardware "powered" after the internal NES stuff.
Needed for the NSF code and VS System code.
*/
GameInterface(GI_POWER);
if (GameInfo->type == GIT_VSUNI)
FCEU_VSUniPower();
timestampbase = 0;
X6502_Power();
FCEU_PowerCheats();
}
void FCEU_ResetVidSys(void)
{
int w;
if (GameInfo->vidsys == GIV_NTSC)
w = 0;
else if (GameInfo->vidsys == GIV_PAL)
w = 1;
else
w = FSettings.PAL;
PAL = w ? 1 : 0;
FCEUPPU_SetVideoSystem(w);
SetSoundVariables();
}
FCEUS FSettings;
void FCEU_printf(char *format, ...)
{
char temp[2048];
va_list ap;
va_start(ap, format);
vsprintf(temp, format, ap);
FCEUD_Message(temp);
va_end(ap);
}
void FCEU_PrintError(char *format, ...)
{
char temp[2048];
va_list ap;
va_start(ap, format);
vsprintf(temp, format, ap);
FCEUD_PrintError(temp);
va_end(ap);
}
void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall)
{
FSettings.UsrFirstSLine[0] = ntscf;
FSettings.UsrLastSLine[0] = ntscl;
FSettings.UsrFirstSLine[1] = palf;
FSettings.UsrLastSLine[1] = pall;
if (PAL)
{
FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
FSettings.LastSLine = FSettings.UsrLastSLine[1];
}
else
{
FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
FSettings.LastSLine = FSettings.UsrLastSLine[0];
}
}
void FCEUI_SetVidSystem(int a)
{
FSettings.PAL = a ? 1 : 0;
if (!GameInfo)
return;
FCEU_ResetVidSys();
FCEU_ResetPalette();
}
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend)
{
if (slstart)
*slstart = FSettings.FirstSLine;
if (slend)
*slend = FSettings.LastSLine;
return(PAL);
}
void FCEUI_SetGameGenie(int a)
{
FSettings.GameGenie = a ? 1 : 0;
}
void FCEUI_SetSnapName(int a)
{
FSettings.SnapName = a;
}
int32 FCEUI_GetDesiredFPS(void)
{
if (PAL)
return(838977920); // ~50.007
else
return(1008307711); // ~60.1
}

View File

@@ -0,0 +1,161 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "fceu-types.h"
#include "file.h"
#include "fceu-endian.h"
#include "fceu-memory.h"
#include "driver.h"
#include "general.h"
typedef struct {
uint8 *data;
uint32 size;
uint32 location;
} MEMWRAP;
void ApplyIPS(FILE *ips, MEMWRAP *dest)
{
}
static MEMWRAP *MakeMemWrap(void *tz, int type)
{
MEMWRAP *tmp;
if (!(tmp = (MEMWRAP*)FCEU_malloc(sizeof(MEMWRAP))))
goto doret;
tmp->location = 0;
fseek((FILE*)tz, 0, SEEK_END);
tmp->size = ftell((FILE*)tz);
fseek((FILE*)tz, 0, SEEK_SET);
if (!(tmp->data = (uint8*)FCEU_malloc(tmp->size)))
{
free(tmp);
tmp = 0;
goto doret;
}
fread(tmp->data, 1, tmp->size, (FILE*)tz);
doret:
if (type == 0)
fclose((FILE*)tz);
return tmp;
}
#ifndef __GNUC__
#define strcasecmp strcmp
#endif
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext)
{
FCEUFILE *fceufp;
void *t;
fceufp = (FCEUFILE*)malloc(sizeof(FCEUFILE));
if ((t = FCEUD_UTF8fopen(path, mode)))
{
fseek((FILE*)t, 0, SEEK_SET);
fceufp->type = 0;
fceufp->fp = t;
return fceufp;
}
free(fceufp);
return 0;
}
int FCEU_fclose(FCEUFILE *fp)
{
fclose((FILE*)fp->fp);
free(fp);
fp = 0;
return 1;
}
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
{
return fread(ptr, size, nmemb, (FILE*)fp->fp);
}
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
{
return fwrite(ptr, size, nmemb, (FILE*)fp->fp);
}
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
{
return fseek((FILE*)fp->fp, offset, whence);
}
uint64 FCEU_ftell(FCEUFILE *fp)
{
return ftell((FILE*)fp->fp);
}
void FCEU_rewind(FCEUFILE *fp)
{
fseek(fp->fp, 0, SEEK_SET);
}
int FCEU_read16le(uint16 *val, FCEUFILE *fp)
{
uint8 t[2];
if (fread(t, 1, 2, (FILE*)fp->fp) != 2)
return(0);
*val = t[0] | (t[1] << 8);
return(1);
}
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
{
return read32le(Bufo, (FILE*)fp->fp);
}
int FCEU_fgetc(FCEUFILE *fp)
{
return fgetc((FILE*)fp->fp);
}
uint64 FCEU_fgetsize(FCEUFILE *fp)
{
long t, r;
t = ftell((FILE*)fp->fp);
fseek((FILE*)fp->fp, 0, SEEK_END);
r = ftell((FILE*)fp->fp);
fseek((FILE*)fp->fp, t, SEEK_SET);
return r;
}
int FCEU_fisarchive(FCEUFILE *fp)
{
return 0;
}

View File

@@ -0,0 +1,162 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "fceu-types.h"
#include "fceu.h"
#include "general.h"
#include "state.h"
#include "driver.h"
#include "md5.h"
static char BaseDirectory[2048];
static char FileBase[2048];
static char FileExt[2048]; /* Includes the . character, as in ".nes" */
static char FileBaseDirectory[2048];
void FCEUI_SetBaseDirectory(char *dir)
{
strncpy(BaseDirectory, dir, 2047);
BaseDirectory[2047] = 0;
}
static char *odirs[FCEUIOD__COUNT] = { 0, 0, 0, 0, 0, 0 }; // odirs, odors. ^_^
void FCEUI_SetDirOverride(int which, char *n)
{
odirs[which] = n;
/* Rebuild cache of present states/movies. */
if (GameInfo)
{
if (which == FCEUIOD_STATE)
FCEUSS_CheckStates();
}
}
#ifndef HAVE_ASPRINTF
static int asprintf(char **strp, const char *fmt, ...) {
va_list ap;
int ret;
va_start(ap, fmt);
if (!(*strp = malloc(2048)))
return(0);
ret = vsnprintf(*strp, 2048, fmt, ap);
va_end(ap);
return(ret);
}
#endif
char *FCEU_MakeFName(int type, int id1, char *cd1)
{
char *ret = 0;
struct stat tmpstat;
switch (type)
{
case FCEUMKF_GGROM:
asprintf(&ret, "%s"PSS "gg.rom", BaseDirectory);
break;
case FCEUMKF_FDSROM:
asprintf(&ret, "%s"PSS "disksys.rom", BaseDirectory);
break;
case FCEUMKF_PALETTE:
if (odirs[FCEUIOD_MISC])
asprintf(&ret, "%s"PSS "%s.pal", odirs[FCEUIOD_MISC], FileBase);
else
asprintf(&ret, "%s"PSS "gameinfo"PSS "%s.pal", BaseDirectory, FileBase);
break;
default:
ret = malloc(1);
*ret = '\0';
}
return(ret);
}
void GetFileBase(const char *f)
{
const char *tp1, *tp3;
#if PSS_STYLE == 4
tp1 = ((char*)strrchr(f, ':'));
#elif PSS_STYLE == 1
tp1 = ((char*)strrchr(f, '/'));
#else
tp1 = ((char*)strrchr(f, '\\'));
#if PSS_STYLE != 3
tp3 = ((char*)strrchr(f, '/'));
if (tp1 < tp3) tp1 = tp3;
#endif
#endif
if (!tp1)
{
tp1 = f;
strcpy(FileBaseDirectory, ".");
}
else
{
memcpy(FileBaseDirectory, f, tp1 - f);
FileBaseDirectory[tp1 - f] = 0;
tp1++;
}
if (((tp3 = strrchr(f, '.')) != NULL) && (tp3 > tp1))
{
memcpy(FileBase, tp1, tp3 - tp1);
FileBase[tp3 - tp1] = 0;
strcpy(FileExt, tp3);
}
else
{
strcpy(FileBase, tp1);
FileExt[0] = 0;
}
}
uint32 uppow2(uint32 n)
{
int x;
for (x = 31; x >= 0; x--)
if (n & (1 << x))
{
if ((1 << x) != n)
return(1 << (x + 1));
break;
}
return n;
}

View File

@@ -0,0 +1,378 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 1998 BERO
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "input.h"
#include "vsuni.h"
#include "fds.h"
extern INPUTC *FCEU_InitJoyPad(int w);
extern INPUTC *FCEU_InitZapper(int w);
extern INPUTC *FCEU_InitMouse(int w);
extern INPUTC *FCEU_InitPowerpadA(int w);
extern INPUTC *FCEU_InitPowerpadB(int w);
extern INPUTC *FCEU_InitArkanoid(int w);
extern INPUTCFC *FCEU_InitFami4(void);
extern INPUTCFC *FCEU_InitArkanoidFC(void);
extern INPUTCFC *FCEU_InitSpaceShadow(void);
extern INPUTCFC *FCEU_InitFKB(void);
extern INPUTCFC *FCEU_InitSuborKB(void);
extern INPUTCFC *FCEU_InitPEC586KB(void);
extern INPUTCFC *FCEU_InitHS(void);
extern INPUTCFC *FCEU_InitMahjong(void);
extern INPUTCFC *FCEU_InitQuizKing(void);
extern INPUTCFC *FCEU_InitFamilyTrainerA(void);
extern INPUTCFC *FCEU_InitFamilyTrainerB(void);
extern INPUTCFC *FCEU_InitOekaKids(void);
extern INPUTCFC *FCEU_InitTopRider(void);
extern INPUTCFC *FCEU_InitBarcodeWorld(void);
extern uint8 coinon;
static void *InputDataPtr[2];
uint8 LastStrobe;
static int JPAttrib[2] = { 0, 0 };
static int JPType[2] = { 0, 0 };
static INPUTC DummyJPort = { 0, 0, 0, 0, 0 };
static INPUTC *JPorts[2] = { &DummyJPort, &DummyJPort };
static int JPAttribFC = 0;
static int JPTypeFC = 0;
static void *InputDataPtrFC;
static INPUTCFC *FCExp = 0;
void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
static DECLFR(JPRead)
{
uint8 ret = 0;
if (JPorts[A & 1]->Read)
ret |= JPorts[A & 1]->Read(A & 1);
if (FCExp)
if (FCExp->Read)
ret = FCExp->Read(A & 1, ret);
ret |= X.DB & 0xC0;
return(ret);
}
static DECLFW(B4016)
{
if (FCExp)
if (FCExp->Write)
FCExp->Write(V & 7);
if (JPorts[0]->Write)
JPorts[0]->Write(V & 1);
if (JPorts[1]->Write)
JPorts[1]->Write(V & 1);
if ((LastStrobe & 1) && (!(V & 1)))
{
if (JPorts[0]->Strobe)
JPorts[0]->Strobe(0);
if (JPorts[1]->Strobe)
JPorts[1]->Strobe(1);
if (FCExp)
if (FCExp->Strobe)
FCExp->Strobe();
}
LastStrobe = V & 0x1;
}
void FCEU_DrawInput(uint8 *buf)
{
int x;
for (x = 0; x < 2; x++)
if (JPorts[x]->Draw)
JPorts[x]->Draw(x, buf, JPAttrib[x]);
if (FCExp)
if (FCExp->Draw)
FCExp->Draw(buf, JPAttribFC);
}
void FCEU_UpdateInput(void)
{
int x;
for (x = 0; x < 2; x++)
{
if (JPorts[x] && JPorts[x]->Update)
JPorts[x]->Update(x, InputDataPtr[x], JPAttrib[x]);
}
if (FCExp && FCExp->Update)
FCExp->Update(InputDataPtrFC, JPAttribFC);
if (GameInfo && GameInfo->type == GIT_VSUNI)
if (coinon) coinon--;
}
static DECLFR(VSUNIRead0)
{
uint8 ret = 0;
if (JPorts[0]->Read)
ret |= (JPorts[0]->Read(0)) & 1;
ret |= (vsdip & 3) << 3;
if (coinon)
ret |= 0x4;
return ret;
}
static DECLFR(VSUNIRead1)
{
uint8 ret = 0;
if (JPorts[1] && JPorts[1]->Read)
ret |= (JPorts[1]->Read(1)) & 1;
ret |= vsdip & 0xFC;
return ret;
}
static void SLHLHook(uint8 *bg, uint8 *spr, uint32 linets, int final)
{
int x;
for (x = 0; x < 2; x++)
if (JPorts[x] && JPorts[x]->SLHook)
JPorts[x]->SLHook(x, bg, spr, linets, final);
if (FCExp && FCExp->SLHook)
FCExp->SLHook(bg, spr, linets, final);
}
static void CheckSLHook(void)
{
InputScanlineHook = 0;
if (JPorts[0] && JPorts[0]->SLHook || JPorts[1] && JPorts[1]->SLHook)
InputScanlineHook = SLHLHook;
if (FCExp && FCExp->SLHook)
InputScanlineHook = SLHLHook;
}
static void FASTAPASS(1) SetInputStuff(int x)
{
switch (JPType[x])
{
case SI_NONE:
JPorts[x] = &DummyJPort;
break;
case SI_GAMEPAD:
JPorts[x] = FCEU_InitJoyPad(x);
break;
case SI_ARKANOID:
JPorts[x] = FCEU_InitArkanoid(x);
break;
case SI_MOUSE:
JPorts[x] = FCEU_InitMouse(x);
break;
case SI_ZAPPER:
JPorts[x] = FCEU_InitZapper(x);
break;
case SI_POWERPADA:
JPorts[x] = FCEU_InitPowerpadA(x);
break;
case SI_POWERPADB:
JPorts[x] = FCEU_InitPowerpadB(x);
break;
}
CheckSLHook();
}
static void SetInputStuffFC(void)
{
switch (JPTypeFC)
{
case SIFC_NONE:
FCExp = 0;
break;
case SIFC_ARKANOID:
FCExp = FCEU_InitArkanoidFC();
break;
case SIFC_SHADOW:
FCExp = FCEU_InitSpaceShadow();
break;
case SIFC_OEKAKIDS:
FCExp = FCEU_InitOekaKids();
break;
case SIFC_4PLAYER:
FCExp = FCEU_InitFami4();
break;
case SIFC_FKB:
FCExp = FCEU_InitFKB();
break;
case SIFC_SUBORKB:
FCExp = FCEU_InitSuborKB();
break;
case SIFC_PEC586KB:
FCExp = FCEU_InitPEC586KB();
break;
case SIFC_HYPERSHOT:
FCExp = FCEU_InitHS();
break;
case SIFC_MAHJONG:
FCExp = FCEU_InitMahjong();
break;
case SIFC_QUIZKING:
FCExp = FCEU_InitQuizKing();
break;
case SIFC_FTRAINERA:
FCExp = FCEU_InitFamilyTrainerA();
break;
case SIFC_FTRAINERB:
FCExp = FCEU_InitFamilyTrainerB();
break;
case SIFC_BWORLD:
FCExp = FCEU_InitBarcodeWorld();
break;
case SIFC_TOPRIDER:
FCExp = FCEU_InitTopRider();
break;
}
CheckSLHook();
}
void InitializeInput(void)
{
LastStrobe = 0;
if (GameInfo && GameInfo->type == GIT_VSUNI)
{
SetReadHandler(0x4016, 0x4016, VSUNIRead0);
SetReadHandler(0x4017, 0x4017, VSUNIRead1);
}
else
SetReadHandler(0x4016, 0x4017, JPRead);
SetWriteHandler(0x4016, 0x4016, B4016);
SetInputStuff(0);
SetInputStuff(1);
SetInputStuffFC();
}
void FCEUI_SetInput(int port, int type, void *ptr, int attrib)
{
JPAttrib[port] = attrib;
JPType[port] = type;
InputDataPtr[port] = ptr;
SetInputStuff(port);
}
void FCEUI_SetInputFC(int type, void *ptr, int attrib)
{
JPAttribFC = attrib;
JPTypeFC = type;
InputDataPtrFC = ptr;
SetInputStuffFC();
}
void FCEU_DoSimpleCommand(int cmd)
{
switch (cmd)
{
case FCEUNPCMD_FDSINSERT:
FCEU_FDSInsert(-1);
break;
case FCEUNPCMD_FDSSELECT:
FCEU_FDSSelect();
break;
case FCEUNPCMD_FDSEJECT:
FCEU_FDSEject();
break;
case FCEUNPCMD_VSUNICOIN:
FCEU_VSUniCoin();
break;
case FCEUNPCMD_VSUNIDIP0:
case (FCEUNPCMD_VSUNIDIP0 + 1):
case (FCEUNPCMD_VSUNIDIP0 + 2):
case (FCEUNPCMD_VSUNIDIP0 + 3):
case (FCEUNPCMD_VSUNIDIP0 + 4):
case (FCEUNPCMD_VSUNIDIP0 + 5):
case (FCEUNPCMD_VSUNIDIP0 + 6):
case (FCEUNPCMD_VSUNIDIP0 + 7):
FCEU_VSUniToggleDIP(cmd - FCEUNPCMD_VSUNIDIP0);
break;
case FCEUNPCMD_POWER:
PowerNES();
break;
case FCEUNPCMD_RESET:
ResetNES();
break;
}
}
void FCEU_QSimpleCommand(int cmd)
{
FCEU_DoSimpleCommand(cmd);
}
void FCEUI_FDSSelect(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_FDSSELECT);
}
int FCEUI_FDSInsert(int oride)
{
FCEU_QSimpleCommand(FCEUNPCMD_FDSINSERT);
return(1);
}
int FCEUI_FDSEject(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_FDSEJECT);
return(1);
}
void FCEUI_VSUniToggleDIP(int w)
{
FCEU_QSimpleCommand(FCEUNPCMD_VSUNIDIP0 + w);
}
void FCEUI_VSUniCoin(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN);
}
void FCEUI_ResetNES(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_RESET);
}
void FCEUI_PowerNES(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_POWER);
}

View File

@@ -0,0 +1,20 @@
#include <stdio.h>
#include "fceu-types.h"
#include "fceu.h"
#include "driver.h"
/* wave.c */
void FCEU_WriteWaveData(int32 *Buffer, int Count) { }
int FCEUI_EndWaveRecord(void) { return 0; }
int FCEUI_BeginWaveRecord(char *fn) { return 0; }
/* netplay.c */
int FCEUNET_SendFile(uint8 cmd, char *fn) { return 0; }
/* movie.c */
void FCEUMOV_AddJoy(uint8 *js) { }
void FCEUMOV_Stop(void) {}
void FCEUI_SelectMovie(int w) { }

View File

@@ -0,0 +1,409 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "sound.h"
#include "fceu-endian.h"
#include "fds.h"
#include "general.h"
#include "state.h"
#include "movie.h"
#include "fceu-memory.h"
#include "ppu.h"
#include "netplay.h"
#include "video.h"
static void (*SPreSave)(void);
static void (*SPostSave)(void);
static int SaveStateStatus[10];
static SFORMAT SFMDATA[64];
static int SFEXINDEX;
#define RLSB FCEUSTATE_RLSB //0x80000000
extern SFORMAT FCEUPPU_STATEINFO[];
extern SFORMAT FCEUSND_STATEINFO[];
extern SFORMAT FCEUCTRL_STATEINFO[];
SFORMAT SFCPU[] = {
{ &X.PC, 2 | RLSB, "PC\0" },
{ &X.A, 1, "A\0\0" },
{ &X.X, 1, "X\0\0" },
{ &X.Y, 1, "Y\0\0" },
{ &X.S, 1, "S\0\0" },
{ &X.P, 1, "P\0\0" },
{ &X.DB, 1, "DB"},
#ifdef COPYFAMI
{ RAM, 0x4000, "RAM" },
#else
{ RAM, 0x800, "RAM" },
#endif
{ 0 }
};
SFORMAT SFCPUC[] = {
{ &X.jammed, 1, "JAMM" },
{ &X.IRQlow, 4 | RLSB, "IQLB" },
{ &X.tcount, 4 | RLSB, "ICoa" },
{ &X.count, 4 | RLSB, "ICou" },
{ &timestampbase, sizeof(timestampbase) | RLSB, "TSBS" },
{ 0 }
};
static int SubWrite(MEM_TYPE *st, SFORMAT *sf) {
uint32 acc = 0;
while (sf->v) {
if (sf->s == ~0) { // Link to another struct.
uint32 tmp;
if (!(tmp = SubWrite(st, (SFORMAT*)sf->v)))
return(0);
acc += tmp;
sf++;
continue;
}
acc += 8; // Description + size
acc += sf->s & (~RLSB);
if (st) { // Are we writing or calculating the size of this block? */
fwrite(sf->desc, 1, 4, st);
write32le(sf->s & (~RLSB), st);
#ifndef LSB_FIRST
if (sf->s & RLSB)
FlipByteOrder(sf->v, sf->s & (~RLSB));
#endif
fwrite((uint8*)sf->v, 1, sf->s & (~RLSB), st);
/* Now restore the original byte order. */
#ifndef LSB_FIRST
if (sf->s & RLSB)
FlipByteOrder(sf->v, sf->s & (~RLSB));
#endif
}
sf++;
}
return(acc);
}
static int WriteStateChunk(MEM_TYPE *st, int type, SFORMAT *sf)
{
int bsize;
fputc(type, st);
bsize = SubWrite(0, sf);
write32le(bsize, st);
if (!SubWrite(st, sf))
return(0);
return(bsize + 5);
}
static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
{
while (sf->v)
{
if (sf->s == ~0)
{ /* Link to another SFORMAT structure. */
SFORMAT *tmp;
if ((tmp = CheckS((SFORMAT*)sf->v, tsize, desc)))
return(tmp);
sf++;
continue;
}
if (!strncmp(desc, sf->desc, 4))
{
if (tsize != (sf->s & (~RLSB)))
return(0);
return(sf);
}
sf++;
}
return(0);
}
static int ReadStateChunk(MEM_TYPE *st, SFORMAT *sf, int size)
{
SFORMAT *tmp;
int temp;
temp = ftell(st);
while (ftell(st) < temp + size)
{
uint32 tsize;
char toa[4];
if (fread(toa, 1, 4, st) <= 0)
return 0;
read32le(&tsize, st);
if ((tmp = CheckS(sf, tsize, toa))) {
fread((uint8*)tmp->v, 1, tmp->s & (~RLSB), st);
#ifndef LSB_FIRST
if (tmp->s & RLSB)
FlipByteOrder(tmp->v, tmp->s & (~RLSB));
#endif
}
else
fseek(st, tsize, SEEK_CUR);
}
return 1;
}
static int ReadStateChunks(MEM_TYPE *st, int32 totalsize)
{
int t;
uint32 size;
int ret = 1;
while (totalsize > 0)
{
t = fgetc(st);
if (t == EOF)
break;
if (!read32le(&size, st))
break;
totalsize -= size + 5;
switch (t)
{
case 1:
if (!ReadStateChunk(st, SFCPU, size))
ret = 0;
break;
case 2:
if (!ReadStateChunk(st, SFCPUC, size))
ret = 0;
else
X.mooPI = X.P; // Quick and dirty hack.
break;
case 3:
if (!ReadStateChunk(st, FCEUPPU_STATEINFO, size))
ret = 0;
break;
case 4:
if (!ReadStateChunk(st, FCEUCTRL_STATEINFO, size))
ret = 0;
break;
case 5:
if (!ReadStateChunk(st, FCEUSND_STATEINFO, size))
ret = 0;
break;
case 0x10:
if (!ReadStateChunk(st, SFMDATA, size))
ret = 0;
break;
default:
if (fseek(st, size, SEEK_CUR) < 0)
goto endo;
break;
}
}
endo:
return ret;
}
int CurrentState = 0;
extern int geniestage;
int FCEUSS_SaveFP(MEM_TYPE *st)
{
static uint32 totalsize;
uint8 header[16] = { 0 };
header[0] = 'F';
header[1] = 'C';
header[2] = 'S';
header[3] = 0xFF;
header[3] = 0xFF;
FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC);
fwrite(header, 1, 16, st);
FCEUPPU_SaveState();
FCEUSND_SaveState();
totalsize = WriteStateChunk(st, 1, SFCPU);
totalsize += WriteStateChunk(st, 2, SFCPUC);
totalsize += WriteStateChunk(st, 3, FCEUPPU_STATEINFO);
totalsize += WriteStateChunk(st, 4, FCEUCTRL_STATEINFO);
totalsize += WriteStateChunk(st, 5, FCEUSND_STATEINFO);
if (SPreSave)
SPreSave();
totalsize += WriteStateChunk(st, 0x10, SFMDATA);
if (SPreSave)
SPostSave();
fseek(st, 4, SEEK_SET);
write32le(totalsize, st);
return(1);
}
void FCEUSS_Save(char *fname)
{
MEM_TYPE *st = NULL;
char *fn;
if (geniestage == 1)
{
FCEU_DispMessage("Cannot save FCS in GG screen.");
return;
}
st = (MEM_TYPE*)memstream_open(1);
FCEUSS_SaveFP(st);
SaveStateStatus[CurrentState] = 1;
fclose(st);
}
int FCEUSS_LoadFP(MEM_TYPE *st)
{
int x;
uint8 header[16];
int stateversion;
fread(&header, 1, 16, st);
if (memcmp(header, "FCS", 3))
return(0);
if (header[3] == 0xFF)
stateversion = FCEU_de32lsb(header + 8);
else
stateversion = header[3] * 100;
x = ReadStateChunks(st, *(uint32*)(header + 4));
if (stateversion < 9500)
X.IRQlow = 0;
if (GameStateRestore)
GameStateRestore(stateversion);
if (x)
{
FCEUPPU_LoadState(stateversion);
FCEUSND_LoadState(stateversion);
}
return(x);
}
int FCEUSS_Load(char *fname)
{
MEM_TYPE *st;
char *fn;
st = (MEM_TYPE*)memstream_open(0);
if (FCEUSS_LoadFP(st))
{
SaveStateStatus[CurrentState] = 1;
fclose(st);
return(1);
}
else
{
SaveStateStatus[CurrentState] = 1;
fclose(st);
return(0);
}
}
void FCEUSS_CheckStates(void)
{
MEM_TYPE *st = NULL;
char *fn;
int ssel;
for (ssel = 0; ssel < 10; ssel++)
{
st = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_STATE, ssel, 0), "rb");
free(fn);
if (st)
{
SaveStateStatus[ssel] = 1;
fclose(st);
}
else
SaveStateStatus[ssel] = 0;
}
CurrentState = 0;
}
void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
{
SPreSave = PreSave;
SPostSave = PostSave;
SFEXINDEX = 0;
}
void AddExState(void *v, uint32 s, int type, char *desc)
{
memset(SFMDATA[SFEXINDEX].desc, 0, sizeof(SFMDATA[SFEXINDEX].desc));
if (desc)
strncpy(SFMDATA[SFEXINDEX].desc, desc, sizeof(SFMDATA[SFEXINDEX].desc));
SFMDATA[SFEXINDEX].v = v;
SFMDATA[SFEXINDEX].s = s;
if (type) SFMDATA[SFEXINDEX].s |= RLSB;
if (SFEXINDEX < 63) SFEXINDEX++;
SFMDATA[SFEXINDEX].v = 0; // End marker.
}
void FCEUI_SelectState(int w)
{
if (w == -1)
return;
CurrentState = w;
FCEU_DispMessage("-select state-");
}
void FCEUI_SaveState(char *fname)
{
FCEUSS_Save(fname);
}
void FCEUI_LoadState(char *fname)
{
FCEUSS_Load(fname);
}
void FCEU_DrawSaveStates(uint8 *XBuf)
{
}

View File

@@ -0,0 +1,109 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "fceu-types.h"
#include "video.h"
#include "fceu.h"
#include "general.h"
#include "fceu-memory.h"
#include "crc32.h"
#include "state.h"
#include "palette.h"
#include "nsf.h"
#include "input.h"
#include "vsuni.h"
uint8 *XBuf = NULL;
void FCEU_KillVirtualVideo(void)
{
if (XBuf)
free(XBuf);
XBuf = 0;
}
int FCEU_InitVirtualVideo(void)
{
// 256 bytes per scanline, * 240 scanline maximum, +8 for alignment,
if (!XBuf)
XBuf = (uint8*)(FCEU_malloc(256 * 256 + 8));
if (!XBuf)
return 0;
if (sizeof(uint8*) == 4)
{
uint32 m;
m = *XBuf;
m = (4 - m) & 3;
XBuf += m;
}
memset(XBuf, 128, 256 * 256);
return 1;
}
static int howlong;
static char errmsg[65];
#include "drawing.h"
void FCEUI_SaveSnapshot(void) { }
void FCEU_PutImage(void)
{
if (GameInfo->type == GIT_NSF)
DrawNSF(XBuf);
else
{
if (GameInfo->type == GIT_VSUNI)
FCEU_VSUniDraw(XBuf);
}
if (howlong) howlong--;
}
void FCEU_PutImageDummy(void)
{
}
void FCEU_DispMessage(char *format, ...)
{
va_list ap;
va_start(ap, format);
vsprintf(errmsg, format, ap);
va_end(ap);
howlong = 180;
}
void FCEU_ResetMessages(void)
{
howlong = 180;
}
int SaveSnapshot(void)
{
return(0);
}