This commit is contained in:
twinaphex 2015-08-06 11:30:34 +02:00
parent ec7e16ff84
commit d368ee0054
30 changed files with 976 additions and 6380 deletions

View File

@ -2,7 +2,7 @@ INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(CORE_DIR) -I$(CORE_DIR)/input -I$
FCEU_SRC_DIRS := $(CORE_DIR)/boards $(CORE_DIR)/input $(CORE_DIR)/mappers
SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
SOURCES_C += $(CORE_DIR)/drivers/libretro/fceu/ines.c $(CORE_DIR)/drivers/libretro/fceu/unif.c $(CORE_DIR)/x6502.c
SOURCES_C += $(CORE_DIR)/ines.c $(CORE_DIR)/unif.c $(CORE_DIR)/x6502.c
ifeq ($(WANT_GRIFFIN),1)
SOURCES_C += \
@ -16,21 +16,21 @@ SOURCES_C += \
$(CORE_DIR)/cheat.c \
$(CORE_DIR)/crc32.c \
$(CORE_DIR)/debug.c \
$(CORE_DIR)/drivers/libretro/fceu/fceu-endian.c \
$(CORE_DIR)/drivers/libretro/fceu/fceu-memory.c \
$(CORE_DIR)/drivers/libretro/fceu/misc.c \
$(CORE_DIR)/drivers/libretro/fceu/fceu.c \
$(CORE_DIR)/drivers/libretro/fceu/fds.c \
$(CORE_DIR)/drivers/libretro/fceu/file.c \
$(CORE_DIR)/fceu-endian.c \
$(CORE_DIR)/fceu-memory.c \
$(CORE_DIR)/misc.c \
$(CORE_DIR)/fceu.c \
$(CORE_DIR)/fds.c \
$(CORE_DIR)/file.c \
$(CORE_DIR)/filter.c \
$(CORE_DIR)/drivers/libretro/fceu/general.c \
$(CORE_DIR)/drivers/libretro/fceu/input.c \
$(CORE_DIR)/drivers/libretro/fceu/nsf.c \
$(CORE_DIR)/general.c \
$(CORE_DIR)/input.c \
$(CORE_DIR)/nsf.c \
$(CORE_DIR)/md5.c \
$(CORE_DIR)/palette.c \
$(CORE_DIR)/ppu.c \
$(CORE_DIR)/sound.c \
$(CORE_DIR)/vsuni.c \
$(CORE_DIR)/drivers/libretro/fceu/state.c \
$(CORE_DIR)/drivers/libretro/fceu/video.c
$(CORE_DIR)/state.c \
$(CORE_DIR)/video.c
endif

View File

@ -1,123 +0,0 @@
/* 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;
while(start < end)
{
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 MSB_FIRST
*(uint32*)Bufo = ((buf & 0xFF) << 24) | ((buf & 0xFF00) << 8) | ((buf & 0xFF0000) >> 8) | ((buf & 0xFF000000) >> 24);
#else
*(uint32*)Bufo = buf;
#endif
return 1;
}
int write32le_mem(uint32 b, memstream_t *mem)
{
uint8 s[4];
s[0]=b;
s[1]=b>>8;
s[2]=b>>16;
s[3]=b>>24;
return((memstream_write(mem, s, 4)<4)?0:4);
}
int read32le_mem(uint32 *Bufo, memstream_t *mem)
{
uint32 buf;
if(memstream_read(mem, &buf, 4)<4)
return 0;
#ifdef MSB_FIRST
*(uint32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
#else
*(uint32*)Bufo=buf;
#endif
return 1;
}
int read16le(char *d, FILE *fp)
{
#ifdef MSB_FIRST
int ret;
ret = fread(d + 1, 1, 1, fp);
ret += fread(d, 1, 1, fp);
return ret < 2 ? 0 : 2;
#else
return((fread(d, 1, 2, fp) < 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

@ -1,18 +0,0 @@
#ifndef _FCEU_ENDIAN_H
#define _FCEU_ENDIAN_H
#include "fceu-memory.h"
#include "../memstream.h"
int write32le_mem(uint32 b, memstream_t *mem);
int read32le_mem(uint32 *Bufo, memstream_t *mem);
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

@ -1,63 +0,0 @@
/* 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

@ -1,50 +0,0 @@
/* 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

@ -1,550 +0,0 @@
/* 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, uint8_t *databuf, size_t databufsize)
{
FCEUFILE *fp;
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);
fp = FCEU_fopen(name, NULL, "rb", 0, databuf, databufsize);
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

@ -1,772 +0,0 @@
/* 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 "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "fds.h"
#include "sound.h"
#include "general.h"
#include "state.h"
#include "file.h"
#include "fceu-memory.h"
#include "cart.h"
#include "md5.h"
#include "netplay.h"
// TODO: Add code to put a delay in between the time a disk is inserted
// and the when it can be successfully read/written to. This should
// prevent writes to wrong places OR add code to prevent disk ejects
// when the virtual motor is on(mmm...virtual motor).
static DECLFR(FDSRead4030);
static DECLFR(FDSRead4031);
static DECLFR(FDSRead4032);
static DECLFR(FDSRead4033);
static DECLFW(FDSWrite);
static DECLFW(FDSWaveWrite);
static DECLFR(FDSWaveRead);
static DECLFR(FDSSRead);
static DECLFW(FDSSWrite);
static void FDSInit(void);
static void FDSClose(void);
static void FP_FASTAPASS(1) FDSFix(int a);
static uint8 FDSRegs[6];
static int32 IRQLatch, IRQCount;
static uint8 IRQa;
static uint8 *FDSRAM = NULL;
static uint32 FDSRAMSize;
static uint8 *FDSBIOS = NULL;
static uint32 FDSBIOSsize;
static uint8 *CHRRAM = NULL;
static uint32 CHRRAMSize;
/* Original disk data backup, to help in creating save states. */
static uint8 *diskdatao[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static uint8 *diskdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static uint32 TotalSides;
static uint8 DiskWritten = 0; /* Set to 1 if disk was written to. */
static uint8 writeskip;
static int32 DiskPtr;
static int32 DiskSeekIRQ;
static uint8 SelectDisk, InDisk;
uint32 lastDiskPtrRead, lastDiskPtrWrite;
#define DC_INC 1
void FDSGI(int h) {
switch (h) {
case GI_CLOSE: FDSClose(); break;
case GI_POWER: FDSInit(); break;
}
}
static void FDSStateRestore(int version) {
int x;
setmirror(((FDSRegs[5] & 8) >> 3) ^ 1);
if (version >= 9810)
for (x = 0; x < TotalSides; x++) {
int b;
for (b = 0; b < 65500; b++)
diskdata[x][b] ^= diskdatao[x][b];
}
}
void FDSSound();
void FDSSoundReset(void);
void FDSSoundStateAdd(void);
static void RenderSound(void);
static void RenderSoundHQ(void);
static void FDSInit(void) {
memset(FDSRegs, 0, sizeof(FDSRegs));
lastDiskPtrRead = lastDiskPtrWrite = writeskip = DiskPtr = DiskSeekIRQ = 0;
setmirror(1);
setprg8(0xE000, 0); // BIOS
setprg32r(1, 0x6000, 0); // 32KB RAM
setchr8(0); // 8KB CHR RAM
MapIRQHook = FDSFix;
GameStateRestore = FDSStateRestore;
SetReadHandler(0x4030, 0x4030, FDSRead4030);
SetReadHandler(0x4031, 0x4031, FDSRead4031);
SetReadHandler(0x4032, 0x4032, FDSRead4032);
SetReadHandler(0x4033, 0x4033, FDSRead4033);
SetWriteHandler(0x4020, 0x4025, FDSWrite);
SetWriteHandler(0x6000, 0xDFFF, CartBW);
SetReadHandler(0x6000, 0xFFFF, CartBR);
IRQCount = IRQLatch = IRQa = 0;
FDSSoundReset();
InDisk = 0;
SelectDisk = 0;
}
void FCEU_FDSInsert(int oride) {
if (InDisk == 255) {
FCEU_DispMessage("Disk %d Side %s Inserted", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
InDisk = SelectDisk;
} else {
FCEU_DispMessage("Disk %d Side %s Ejected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
InDisk = 255;
}
}
void FCEU_FDSEject(void) {
InDisk = 255;
}
void FCEU_FDSSelect(void) {
if (InDisk != 255) {
FCEU_DispMessage("Eject disk before selecting.");
return;
}
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
FCEU_DispMessage("Disk %d Side %s Selected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
}
static void FP_FASTAPASS(1) FDSFix(int a) {
if ((IRQa & 2) && IRQCount) {
IRQCount -= a;
if (IRQCount <= 0) {
if (!(IRQa & 1)) {
IRQa &= ~2;
IRQCount = IRQLatch = 0;
} else
IRQCount = IRQLatch;
X6502_IRQBegin(FCEU_IQEXT);
}
}
if (DiskSeekIRQ > 0) {
DiskSeekIRQ -= a;
if (DiskSeekIRQ <= 0) {
if (FDSRegs[5] & 0x80) {
X6502_IRQBegin(FCEU_IQEXT2);
}
}
}
}
static DECLFR(FDSRead4030) {
uint8 ret = 0;
/* Cheap hack. */
if (X.IRQlow & FCEU_IQEXT) ret |= 1;
if (X.IRQlow & FCEU_IQEXT2) ret |= 2;
#ifdef FCEUDEF_DEBUGGER
if (!fceuindbg)
#endif
{
X6502_IRQEnd(FCEU_IQEXT);
X6502_IRQEnd(FCEU_IQEXT2);
}
return ret;
}
static DECLFR(FDSRead4031) {
static uint8 z = 0;
if (InDisk != 255) {
z = diskdata[InDisk][DiskPtr];
lastDiskPtrRead = DiskPtr;
#ifdef FCEUDEF_DEBUGGER
if (!fceuindbg)
#endif
{
if (DiskPtr < 64999) DiskPtr++;
DiskSeekIRQ = 150;
X6502_IRQEnd(FCEU_IQEXT2);
}
}
return z;
}
static DECLFR(FDSRead4032) {
uint8 ret;
ret = X.DB & ~7;
if (InDisk == 255)
ret |= 5;
if (InDisk == 255 || !(FDSRegs[5] & 1) || (FDSRegs[5] & 2))
ret |= 2;
return ret;
}
static DECLFR(FDSRead4033) {
return 0x80; // battery
}
/* Begin FDS sound */
#define FDSClock (1789772.7272727272727272 / 2)
typedef struct {
int64 cycles; // Cycles per PCM sample
int64 count; // Cycle counter
int64 envcount; // Envelope cycle counter
uint32 b19shiftreg60;
uint32 b24adder66;
uint32 b24latch68;
uint32 b17latch76;
int32 clockcount; // Counter to divide frequency by 8.
uint8 b8shiftreg88; // Modulation register.
uint8 amplitude[2]; // Current amplitudes.
uint8 speedo[2];
uint8 mwcount;
uint8 mwstart;
uint8 mwave[0x20]; // Modulation waveform
uint8 cwave[0x40]; // Game-defined waveform(carrier)
uint8 SPSG[0xB];
} FDSSOUND;
static FDSSOUND fdso;
#define SPSG fdso.SPSG
#define b19shiftreg60 fdso.b19shiftreg60
#define b24adder66 fdso.b24adder66
#define b24latch68 fdso.b24latch68
#define b17latch76 fdso.b17latch76
#define b8shiftreg88 fdso.b8shiftreg88
#define clockcount fdso.clockcount
#define amplitude fdso.amplitude
#define speedo fdso.speedo
void FDSSoundStateAdd(void) {
AddExState(fdso.cwave, 64, 0, "WAVE");
AddExState(fdso.mwave, 32, 0, "MWAV");
AddExState(amplitude, 2, 0, "AMPL");
AddExState(SPSG, 0xB, 0, "SPSG");
AddExState(&b8shiftreg88, 1, 0, "B88");
AddExState(&clockcount, 4, 1, "CLOC");
AddExState(&b19shiftreg60, 4, 1, "B60");
AddExState(&b24adder66, 4, 1, "B66");
AddExState(&b24latch68, 4, 1, "B68");
AddExState(&b17latch76, 4, 1, "B76");
}
static DECLFR(FDSSRead) {
switch (A & 0xF) {
case 0x0: return(amplitude[0] | (X.DB & 0xC0));
case 0x2: return(amplitude[1] | (X.DB & 0xC0));
}
return(X.DB);
}
static DECLFW(FDSSWrite) {
if (FSettings.SndRate) {
if (FSettings.soundq >= 1)
RenderSoundHQ();
else
RenderSound();
}
A -= 0x4080;
switch (A) {
case 0x0:
case 0x4:
if (V & 0x80)
amplitude[(A & 0xF) >> 2] = V & 0x3F;
break;
case 0x7:
b17latch76 = 0;
SPSG[0x5] = 0;
break;
case 0x8:
b17latch76 = 0;
fdso.mwave[SPSG[0x5] & 0x1F] = V & 0x7;
SPSG[0x5] = (SPSG[0x5] + 1) & 0x1F;
break;
}
SPSG[A] = V;
}
// $4080 - Fundamental wave amplitude data register 92
// $4082 - Fundamental wave frequency data register 58
// $4083 - Same as $4082($4083 is the upper 4 bits).
// $4084 - Modulation amplitude data register 78
// $4086 - Modulation frequency data register 72
// $4087 - Same as $4086($4087 is the upper 4 bits)
static void DoEnv() {
int x;
for (x = 0; x < 2; x++)
if (!(SPSG[x << 2] & 0x80) && !(SPSG[0x3] & 0x40)) {
static int counto[2] = { 0, 0 };
if (counto[x] <= 0) {
if (!(SPSG[x << 2] & 0x80)) {
if (SPSG[x << 2] & 0x40) {
if (amplitude[x] < 0x3F)
amplitude[x]++;
} else {
if (amplitude[x] > 0)
amplitude[x]--;
}
}
counto[x] = (SPSG[x << 2] & 0x3F);
} else
counto[x]--;
}
}
static DECLFR(FDSWaveRead) {
return(fdso.cwave[A & 0x3f] | (X.DB & 0xC0));
}
static DECLFW(FDSWaveWrite) {
if (SPSG[0x9] & 0x80)
fdso.cwave[A & 0x3f] = V & 0x3F;
}
static int ta;
static INLINE void ClockRise(void) {
if (!clockcount) {
ta++;
b19shiftreg60 = (SPSG[0x2] | ((SPSG[0x3] & 0xF) << 8));
b17latch76 = (SPSG[0x6] | ((SPSG[0x07] & 0xF) << 8)) + b17latch76;
if (!(SPSG[0x7] & 0x80)) {
int t = fdso.mwave[(b17latch76 >> 13) & 0x1F] & 7;
int t2 = amplitude[1];
int adj = 0;
if ((t & 3)) {
if ((t & 4))
adj -= (t2 * ((4 - (t & 3))));
else
adj += (t2 * ((t & 3)));
}
adj *= 2;
if (adj > 0x7F) adj = 0x7F;
if (adj < -0x80) adj = -0x80;
b8shiftreg88 = 0x80 + adj;
} else {
b8shiftreg88 = 0x80;
}
} else {
b19shiftreg60 <<= 1;
b8shiftreg88 >>= 1;
}
b24adder66 = (b24latch68 + b19shiftreg60) & 0x1FFFFFF;
}
static INLINE void ClockFall(void) {
if ((b8shiftreg88 & 1))
b24latch68 = b24adder66;
clockcount = (clockcount + 1) & 7;
}
static INLINE int32 FDSDoSound(void) {
fdso.count += fdso.cycles;
if (fdso.count >= ((int64)1 << 40)) {
dogk:
fdso.count -= (int64)1 << 40;
ClockRise();
ClockFall();
fdso.envcount--;
if (fdso.envcount <= 0) {
fdso.envcount += SPSG[0xA] * 3;
DoEnv();
}
}
if (fdso.count >= 32768) goto dogk;
// Might need to emulate applying the amplitude to the waveform a bit better...
{
int k = amplitude[0];
if (k > 0x20) k = 0x20;
return (fdso.cwave[b24latch68 >> 19] * k) * 4 / ((SPSG[0x9] & 0x3) + 2);
}
}
static int32 FBC = 0;
static void RenderSound(void) {
int32 end, start;
int32 x;
start = FBC;
end = (SOUNDTS << 16) / soundtsinc;
if (end <= start)
return;
FBC = end;
if (!(SPSG[0x9] & 0x80))
for (x = start; x < end; x++) {
uint32 t = FDSDoSound();
t += t >> 1;
t >>= 4;
Wave[x >> 4] += t; //(t>>2)-(t>>3); //>>3;
}
}
static void RenderSoundHQ(void) {
uint32 x;
if (!(SPSG[0x9] & 0x80))
for (x = FBC; x < SOUNDTS; x++) {
uint32 t = FDSDoSound();
t += t >> 1;
WaveHi[x] += t; //(t<<2)-(t<<1);
}
FBC = SOUNDTS;
}
static void HQSync(int32 ts) {
FBC = ts;
}
void FDSSound(int c) {
RenderSound();
FBC = c;
}
static void FDS_ESI(void) {
if (FSettings.SndRate) {
if (FSettings.soundq >= 1) {
fdso.cycles = (int64)1 << 39;
} else {
fdso.cycles = ((int64)1 << 40) * FDSClock;
fdso.cycles /= FSettings.SndRate * 16;
}
}
SetReadHandler(0x4040, 0x407f, FDSWaveRead);
SetWriteHandler(0x4040, 0x407f, FDSWaveWrite);
SetWriteHandler(0x4080, 0x408A, FDSSWrite);
SetReadHandler(0x4090, 0x4092, FDSSRead);
}
void FDSSoundReset(void) {
memset(&fdso, 0, sizeof(fdso));
FDS_ESI();
GameExpSound.HiSync = HQSync;
GameExpSound.HiFill = RenderSoundHQ;
GameExpSound.Fill = FDSSound;
GameExpSound.RChange = FDS_ESI;
}
static DECLFW(FDSWrite) {
switch (A) {
case 0x4020:
X6502_IRQEnd(FCEU_IQEXT);
IRQLatch &= 0xFF00;
IRQLatch |= V;
break;
case 0x4021:
X6502_IRQEnd(FCEU_IQEXT);
IRQLatch &= 0xFF;
IRQLatch |= V << 8;
break;
case 0x4022:
X6502_IRQEnd(FCEU_IQEXT);
IRQCount = IRQLatch;
IRQa = V & 3;
break;
case 0x4024:
if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) {
if (DiskPtr >= 0 && DiskPtr < 65500) {
if (writeskip)
writeskip--;
else if (DiskPtr >= 2) {
DiskWritten = 1;
diskdata[InDisk][DiskPtr - 2] = V;
lastDiskPtrWrite = DiskPtr - 2;
}
}
}
break;
case 0x4025:
X6502_IRQEnd(FCEU_IQEXT2);
if (InDisk != 255) {
if (!(V & 0x40)) {
if ((FDSRegs[5] & 0x40) && !(V & 0x10)) {
DiskSeekIRQ = 200;
DiskPtr -= 2;
}
if (DiskPtr < 0) DiskPtr = 0;
}
if (!(V & 0x4)) writeskip = 2;
if (V & 2) {
DiskPtr = 0; DiskSeekIRQ = 200;
}
if (V & 0x40) DiskSeekIRQ = 200;
}
setmirror(((V >> 3) & 1) ^ 1);
break;
}
FDSRegs[A & 7] = V;
}
static void FreeFDSMemory(void) {
int x;
for (x = 0; x < TotalSides; x++)
if (diskdata[x]) {
free(diskdata[x]);
diskdata[x] = 0;
}
}
static int SubLoad(FCEUFILE *fp) {
struct md5_context md5;
uint8 header[16];
int x;
FCEU_fread(header, 16, 1, fp);
if (memcmp(header, "FDS\x1a", 4)) {
if (!(memcmp(header + 1, "*NINTENDO-HVC*", 14))) {
long t;
t = FCEU_fgetsize(fp);
if (t < 65500)
t = 65500;
TotalSides = t / 65500;
FCEU_fseek(fp, 0, SEEK_SET);
} else
return(0);
} else
TotalSides = header[4];
md5_starts(&md5);
if (TotalSides > 8) TotalSides = 8;
if (TotalSides < 1) TotalSides = 1;
for (x = 0; x < TotalSides; x++) {
diskdata[x] = (uint8*)FCEU_malloc(65500);
if (!diskdata[x]) {
int zol;
for (zol = 0; zol < x; zol++)
free(diskdata[zol]);
return 0;
}
FCEU_fread(diskdata[x], 1, 65500, fp);
md5_update(&md5, diskdata[x], 65500);
}
md5_finish(&md5, GameInfo->MD5);
return(1);
}
static void PreSave(void) {
int x;
for (x = 0; x < TotalSides; x++) {
int b;
for (b = 0; b < 65500; b++)
diskdata[x][b] ^= diskdatao[x][b];
}
}
static void PostSave(void) {
int x;
for (x = 0; x < TotalSides; x++) {
int b;
for (b = 0; b < 65500; b++)
diskdata[x][b] ^= diskdatao[x][b];
}
}
int FDSLoad(const char *name, FCEUFILE *fp) {
FILE *zp;
int x;
char *fn = FCEU_MakeFName(FCEUMKF_FDSROM, 0, 0);
if (!(zp = fopen(fn, "rb"))) {
FCEU_PrintError("FDS BIOS ROM image missing!");
free(fn);
return 0;
}
free(fn);
ResetCartMapping();
if (FDSBIOS)
free(FDSBIOS);
FDSBIOS = NULL;
if (FDSRAM)
free(FDSRAM);
FDSRAM = NULL;
if (CHRRAM)
free(CHRRAM);
CHRRAM = NULL;
FDSBIOSsize = 8192;
FDSBIOS = (uint8*)FCEU_gmalloc(FDSBIOSsize);
SetupCartPRGMapping(0, FDSBIOS, FDSBIOSsize, 0);
if (fread(FDSBIOS, 1, FDSBIOSsize, zp) != FDSBIOSsize) {
if (FDSBIOS)
free(FDSBIOS);
FDSBIOS = NULL;
fclose(zp);
FCEU_PrintError("Error reading FDS BIOS ROM image.");
return 0;
}
fclose(zp);
FCEU_fseek(fp, 0, SEEK_SET);
FreeFDSMemory();
if (!SubLoad(fp)) {
if (FDSBIOS)
free(FDSBIOS);
FDSBIOS = NULL;
return(0);
}
{
FCEUFILE *tp;
char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0);
int x;
for (x = 0; x < TotalSides; x++) {
diskdatao[x] = (uint8*)FCEU_malloc(65500);
memcpy(diskdatao[x], diskdata[x], 65500);
}
if ((tp = FCEU_fopen(fn, 0, "rb", 0, NULL, 0))) {
FCEU_printf("Disk was written. Auxillary FDS file open \"%s\".\n", fn);
FreeFDSMemory();
if (!SubLoad(tp)) {
FCEU_PrintError("Error reading auxillary FDS file.");
if (FDSBIOS)
free(FDSBIOS);
FDSBIOS = NULL;
free(fn);
return(0);
}
FCEU_fclose(tp);
DiskWritten = 1; /* For save state handling. */
}
free(fn);
}
GameInfo->type = GIT_FDS;
GameInterface = FDSGI;
SelectDisk = 0;
InDisk = 255;
ResetExState(PreSave, PostSave);
FDSSoundStateAdd();
for (x = 0; x < TotalSides; x++) {
char temp[5];
sprintf(temp, "DDT%d", x);
AddExState(diskdata[x], 65500, 0, temp);
}
AddExState(FDSRegs, sizeof(FDSRegs), 0, "FREG");
AddExState(&IRQCount, 4, 1, "IRQC");
AddExState(&IRQLatch, 4, 1, "IQL1");
AddExState(&IRQa, 1, 0, "IRQA");
AddExState(&writeskip, 1, 0, "WSKI");
AddExState(&DiskPtr, 4, 1, "DPTR");
AddExState(&DiskSeekIRQ, 4, 1, "DSIR");
AddExState(&SelectDisk, 1, 0, "SELD");
AddExState(&InDisk, 1, 0, "INDI");
AddExState(&DiskWritten, 1, 0, "DSKW");
CHRRAMSize = 8192;
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
memset(CHRRAM, 0, CHRRAMSize);
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
FDSRAMSize = 32768;
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
memset(FDSRAM, 0, FDSRAMSize);
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");
SetupCartMirroring(0, 0, 0);
FCEU_printf(" Sides: %d\n\n", TotalSides);
return 1;
}
void FDSClose(void) {
FILE *fp;
int x;
char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0);
if (!DiskWritten) return;
if (!(fp = fopen(fn, "wb"))) {
free(fn);
return;
}
FCEU_printf("FDS Save \"%s\"\n", fn);
free(fn);
for (x = 0; x < TotalSides; x++) {
if (fwrite(diskdata[x], 1, 65500, fp) != 65500) {
FCEU_PrintError("Error saving FDS image!");
fclose(fp);
return;
}
}
for (x = 0; x < TotalSides; x++)
if (diskdatao[x]) {
free(diskdatao[x]);
diskdatao[x] = 0;
}
FreeFDSMemory();
if (FDSBIOS)
free(FDSBIOS);
FDSBIOS = NULL;
if (FDSRAM)
free(FDSRAM);
FDSRAM = NULL;
if (CHRRAM)
free(CHRRAM);
CHRRAM = NULL;
fclose(fp);
}

View File

@ -1,185 +0,0 @@
/* 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"
#ifndef __GNUC__
#define strcasecmp strcmp
#endif
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;
}
static MEMWRAP *MakeMemWrapBuffer(void *tz, int type, uint8 *buffer, size_t bufsize)
{
MEMWRAP *tmp = (MEMWRAP*)FCEU_malloc(sizeof(MEMWRAP));
if (!tmp)
return NULL;
tmp->location = 0;
tmp->size = bufsize;
tmp->data = buffer;
return tmp;
}
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn,
char *mode, char *ext, uint8 *buffer, size_t bufsize)
{
FCEUFILE *fceufp = (FCEUFILE*)malloc(sizeof(FCEUFILE));
void *t = fopen(path, mode);
if (!t)
{
free(fceufp);
return 0;
}
fseek((FILE*)t, 0, SEEK_SET);
fceufp->type = 0;
if (buffer)
fceufp->fp = MakeMemWrapBuffer(t, 0, buffer, bufsize);
else
fceufp->fp = MakeMemWrap(t, 0);
return fceufp;
}
int FCEU_fclose(FCEUFILE *fp)
{
if (fp->fp)
free(fp->fp);
fp->fp = NULL;
free(fp);
fp = 0;
return 1;
}
uint64 FCEU_fread(void *ptr, size_t element_size, size_t nmemb, FCEUFILE *fp)
{
uint32_t total = nmemb * element_size;
if (fp->fp->location >= fp->fp->size)
return 0;
if((fp->fp->location + total) > fp->fp->size)
{
int64_t ak = fp->fp->size - fp->fp->location;
memcpy((uint8_t*)ptr, fp->fp->data + fp->fp->location, ak);
fp->fp->location = fp->fp->size;
return (ak / element_size);
}
memcpy((uint8_t*)ptr, fp->fp->data + fp->fp->location, total);
fp->fp->location += total;
return nmemb;
}
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
{
switch (whence)
{
case SEEK_SET:
if (offset >= fp->fp->size)
return -1;
fp->fp->location = offset;
break;
case SEEK_CUR:
if ((offset + fp->fp->location) > fp->fp->size)
return -1;
fp->fp->location += offset;
break;
}
return 0;
}
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
{
if ((fp->fp->location + 4) > fp->fp->size)
return 0;
*Bufo = FCEU_de32lsb(fp->fp->data + fp->fp->location);
fp->fp->location += 4;
return 1;
}
int FCEU_fgetc(FCEUFILE *fp)
{
if (fp->fp->location < fp->fp->size)
return fp->fp->data[fp->fp->location++];
return EOF;
}
uint64 FCEU_ftell(FCEUFILE *fp)
{
return fp->fp->location;
}
uint64 FCEU_fgetsize(FCEUFILE *fp)
{
return fp->fp->size;
}

View File

@ -1,162 +0,0 @@
/* 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

@ -1,839 +0,0 @@
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "cart.h"
#include "ppu.h"
#include "ines.h"
#include "unif.h"
#include "state.h"
#include "file.h"
#include "general.h"
#include "fceu-memory.h"
#include "crc32.h"
#include "md5.h"
#include "cheat.h"
#include "vsuni.h"
extern SFORMAT FCEUVSUNI_STATEINFO[];
uint8 *trainerpoo = NULL;
uint8 *ROM = NULL;
uint8 *VROM = NULL;
uint8 *ExtraNTARAM = NULL;
iNES_HEADER head;
CartInfo iNESCart;
uint8 Mirroring = 0;
uint32 ROM_size = 0;
uint32 VROM_size = 0;
static int CHRRAMSize = -1;
static int iNES_Init(int num);
static int MapperNo = 0;
static DECLFR(TrainerRead) {
return(trainerpoo[A & 0x1FF]);
}
static void iNES_ExecPower() {
if (iNESCart.Power)
iNESCart.Power();
if (trainerpoo) {
int x;
for (x = 0; x < 512; x++) {
X6502_DMW(0x7000 + x, trainerpoo[x]);
if (X6502_DMR(0x7000 + x) != trainerpoo[x]) {
SetReadHandler(0x7000, 0x71FF, TrainerRead);
break;
}
}
}
}
static void iNESGI(int h) {
switch (h) {
case GI_RESETM2:
if (iNESCart.Reset)
iNESCart.Reset();
break;
case GI_POWER:
iNES_ExecPower();
break;
case GI_CLOSE:
{
FCEU_SaveGameSave(&iNESCart);
if (iNESCart.Close)
iNESCart.Close();
if (ROM) {
free(ROM);
ROM = NULL;
}
if (VROM) {
free(VROM);
VROM = NULL;
}
if (trainerpoo) {
free(trainerpoo);
trainerpoo = NULL;
}
if (ExtraNTARAM) {
free(ExtraNTARAM);
ExtraNTARAM = NULL;
}
}
break;
}
}
uint32 iNESGameCRC32 = 0;
struct CRCMATCH {
uint32 crc;
char *name;
};
struct INPSEL {
uint32 crc32;
int input1;
int input2;
int inputfc;
};
static void SetInput(void) {
static struct INPSEL moo[] =
{
{0x19b0a9f1, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // 6-in-1 (MGC-023)(Unl)[!]
{0x29de87af, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Aerobics Studio
{0xd89e5a67, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid (J)
{0x0f141525, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid 2(J)
{0x32fb0583, SI_UNSET, SI_ARKANOID, SIFC_NONE }, // Arkanoid(NES)
{0x60ad090a, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Athletic World
{0x48ca0ee1, SI_GAMEPAD, SI_GAMEPAD, SIFC_BWORLD }, // Barcode World
{0x4318a2f8, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Barker Bill's Trick Shooting
{0x6cca1c1f, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Dai Undoukai
{0x24598791, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Duck Hunt
{0xd5d6eac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Edu (As)
{0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Educational Computer 2000
{0x8f7b1669, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // FP BASIC 3.3 by maxzhou88
{0xf7606810, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.0A
{0x895037bc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.1a
{0xb2530afc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 3.0
{0xea90f3e2, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Family Trainer: Running Stadium
{0xbba58be5, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Family Trainer: Manhattan Police
{0x3e58a87e, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Freedom Force
{0xd9f45be9, SI_GAMEPAD, SI_GAMEPAD, SIFC_QUIZKING }, // Gimme a Break ...
{0x1545bd13, SI_GAMEPAD, SI_GAMEPAD, SIFC_QUIZKING }, // Gimme a Break ... 2
{0x4e959173, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Gotcha! - The Sport!
{0xbeb8ab01, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Gumshoe
{0xff24d794, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Hogan's Alley
{0x21f85681, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Olympic (Gentei Ban)
{0x980be936, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Olympic
{0x915a53a7, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Sports
{0x9fae4d46, SI_GAMEPAD, SI_GAMEPAD, SIFC_MAHJONG }, // Ide Yousuke Meijin no Jissen Mahjong
{0x7b44fb2a, SI_GAMEPAD, SI_GAMEPAD, SIFC_MAHJONG }, // Ide Yousuke Meijin no Jissen Mahjong 2
{0x2f128512, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Jogging Race
{0xbb33196f, SI_UNSET, SI_UNSET, SIFC_FKB }, // Keyboard Transformer
{0x8587ee00, SI_UNSET, SI_UNSET, SIFC_FKB }, // Keyboard Transformer
{0x543ab532, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // LIKO Color Lines
{0x368c19a8, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // LIKO Study Cartridge
{0x5ee6008e, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Mechanized Attack
{0x370ceb65, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Meiro Dai Sakusen
{0x3a1694f9, SI_GAMEPAD, SI_GAMEPAD, SIFC_4PLAYER }, // Nekketsu Kakutou Densetsu
{0x9d048ea4, SI_GAMEPAD, SI_GAMEPAD, SIFC_OEKAKIDS }, // Oeka Kids
{0x2a6559a1, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Operation Wolf (J)
{0xedc3662b, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Operation Wolf
{0x912989dc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Playbox BASIC
{0x9044550e, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Rairai Kyonshizu
{0xea90f3e2, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Running Stadium
{0x851eb9be, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Shooting Range
{0x6435c095, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Short Order/Eggsplode
{0xc043a8df, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Shu Qi Yu - Shu Xue Xiao Zhuan Yuan (Ch)
{0x2cf5db05, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Shu Qi Yu - Zhi Li Xiao Zhuan Yuan (Ch)
{0xad9c63e2, SI_GAMEPAD, SI_UNSET, SIFC_SHADOW }, // Space Shadow
{0x61d86167, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Street Cop
{0xabb2f974, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Study and Game 32-in-1
{0x41ef9ac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor
{0x8b265862, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor
{0x82f1fb96, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor 1.0 Russian
{0x9f8f200a, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Super Mogura Tataki!! - Pokkun Moguraa
{0xd74b2719, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Super Team Games
{0x74bea652, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Supergun 3-in-1
{0x5e073a1b, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Supor English (Chinese)
{0x589b6b0d, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // SuporV20
{0x41401c6d, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // SuporV40
{0x23d17f5e, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // The Lone Ranger
{0xc3c0811d, SI_GAMEPAD, SI_GAMEPAD, SIFC_OEKAKIDS }, // The two "Oeka Kids" games
{0xde8fd935, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // To the Earth
{0x47232739, SI_GAMEPAD, SI_GAMEPAD, SIFC_TOPRIDER }, // Top Rider
{0x8a12a7d9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Totsugeki Fuuun Takeshi Jou
{0xb8b9aca3, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman
{0x5112dc21, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman
{0xaf4010ea, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // World Class Track Meet
{0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET }
};
int x = 0;
while (moo[x].input1 >= 0 || moo[x].input2 >= 0 || moo[x].inputfc >= 0) {
if (moo[x].crc32 == iNESGameCRC32) {
GameInfo->input[0] = moo[x].input1;
GameInfo->input[1] = moo[x].input2;
GameInfo->inputfc = moo[x].inputfc;
break;
}
x++;
}
}
#define INESB_INCOMPLETE 1
#define INESB_CORRUPT 2
#define INESB_HACKED 4
struct BADINF {
uint64 md5partial;
uint8 *name;
uint32 type;
};
static struct BADINF BadROMImages[] =
{
#include "ines-bad.h"
};
void CheckBad(uint64 md5partial) {
int32 x = 0;
while (BadROMImages[x].name) {
if (BadROMImages[x].md5partial == md5partial) {
FCEU_PrintError("The copy game you have loaded, \"%s\", is bad, and will not work properly in FCE Ultra.", BadROMImages[x].name);
return;
}
x++;
}
}
struct CHINF {
uint32 crc32;
int32 mapper;
int32 mirror;
};
static void CheckHInfo(void) {
/* ROM images that have the battery-backed bit set in the header that really
don't have battery-backed RAM is not that big of a problem, so I'll
treat this differently by only listing games that should have battery-backed RAM.
Lower 64 bits of the MD5 hash.
*/
static uint64 savie[] =
{
0xc04361e499748382LL, /* AD&D Heroes of the Lance */
0xb72ee2337ced5792LL, /* AD&D Hillsfar */
0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */
0x498c10dc463cfe95LL, /* Battle Fleet */
0x854d7947a3177f57LL, /* Crystalis */
0x4a1f5336b86851b6LL, /* DW */
0xb0bcc02c843c1b79LL, /* DW */
0x2dcf3a98c7937c22LL, /* DW 2 */
0x98e55e09dfcc7533LL, /* DW 4*/
0x733026b6b72f2470LL, /* Dw 3 */
0x6917ffcaca2d8466LL, /* Famista '90 */
0x8da46db592a1fcf4LL, /* Faria */
0xedba17a2c4608d20LL, /* Final Fantasy */
0x91a6846d3202e3d6LL, /* Final Fantasy */
0x012df596e2b31174LL, /* Final Fantasy 1+2 */
0xf6b359a720549ecdLL, /* Final Fantasy 2 */
0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */
0xd63dcc68c2b20adcLL, /* Final Fantasy J */
0x2ee3417ba8b69706LL, /* Hydlide 3*/
0xebbce5a54cf3ecc0LL, /* Justbreed */
0x6a858da551ba239eLL, /* Kaijuu Monogatari */
0x2db8f5d16c10b925LL, /* Kyonshiizu 2 */
0x04a31647de80fdabLL, /* Legend of Zelda */
0x94b9484862a26cbaLL, /* Legend of Zelda */
0xa40666740b7d22feLL, /* Mindseeker */
0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */
0x77b811b2760104b9LL, /* Mouryou Senki Madara */
0x11b69122efe86e8cLL, /* RPG Jinsei Game */
0x9aa1dc16c05e7de5LL, /* Startropics */
0x1b084107d0878bd0LL, /* Startropics 2*/
0xa70b495314f4d075LL, /* Ys 3 */
0x836c0ff4f3e06e45LL, /* Zelda 2 */
0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */
};
static struct CHINF moo[] =
{
#include "ines-correct.h"
};
int32 tofix = 0, x;
uint64 partialmd5 = 0;
for (x = 0; x < 8; x++)
partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8);
CheckBad(partialmd5);
x = 0;
do {
if (moo[x].crc32 == iNESGameCRC32) {
if (moo[x].mapper >= 0) {
if (moo[x].mapper & 0x800 && VROM_size) {
VROM_size = 0;
free(VROM);
VROM = NULL;
tofix |= 8;
}
if (MapperNo != (moo[x].mapper & 0xFF)) {
tofix |= 1;
MapperNo = moo[x].mapper & 0xFF;
}
}
if (moo[x].mirror >= 0) {
if (moo[x].mirror == 8) {
if (Mirroring == 2) { /* Anything but hard-wired(four screen). */
tofix |= 2;
Mirroring = 0;
}
} else if (Mirroring != moo[x].mirror) {
if (Mirroring != (moo[x].mirror & ~4))
if ((moo[x].mirror & ~4) <= 2) /* Don't complain if one-screen mirroring
needs to be set(the iNES header can't
hold this information).
*/
tofix |= 2;
Mirroring = moo[x].mirror;
}
}
break;
}
x++;
} while (moo[x].mirror >= 0 || moo[x].mapper >= 0);
x = 0;
while (savie[x] != 0) {
if (savie[x] == partialmd5) {
if (!(head.ROM_type & 2)) {
tofix |= 4;
head.ROM_type |= 2;
}
}
x++;
}
/* Games that use these iNES mappers tend to have the four-screen bit set
when it should not be.
*/
if ((MapperNo == 118 || MapperNo == 24 || MapperNo == 26) && (Mirroring == 2)) {
Mirroring = 0;
tofix |= 2;
}
/* Four-screen mirroring implicitly set. */
if (MapperNo == 99)
Mirroring = 2;
if (tofix) {
char gigastr[768];
strcpy(gigastr, "The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");
if (tofix & 1)
sprintf(gigastr + strlen(gigastr), "The mapper number should be set to %d. ", MapperNo);
if (tofix & 2) {
uint8 *mstr[3] = { "Horizontal", "Vertical", "Four-screen" };
sprintf(gigastr + strlen(gigastr), "Mirroring should be set to \"%s\". ", mstr[Mirroring & 3]);
}
if (tofix & 4)
strcat(gigastr, "The battery-backed bit should be set. ");
if (tofix & 8)
strcat(gigastr, "This game should not have any CHR ROM. ");
strcat(gigastr, "\n");
FCEU_printf("%s", gigastr);
}
}
typedef struct {
int32 mapper;
void (*init)(CartInfo *);
} NewMI;
typedef struct {
uint8 *name;
int32 number;
void (*init)(CartInfo *);
} BMAPPINGLocal;
static BMAPPINGLocal bmap[] = {
{"NROM", 0, NROM_Init},
{"MMC1", 1, Mapper1_Init},
{"UNROM", 2, UNROM_Init},
{"CNROM", 3, CNROM_Init},
{"MMC3", 4, Mapper4_Init},
{"MMC5", 5, Mapper5_Init},
{"FFE Rev. A", 6, Mapper6_Init},
{"ANROM", 7, ANROM_Init},
{"", 8, Mapper8_Init}, // Nogaems, it's worthless
{"MMC2", 9, Mapper9_Init},
{"MMC4", 10, Mapper10_Init},
{"Color Dreams", 11, Mapper11_Init},
{"REX DBZ 5", 12, Mapper12_Init},
{"CPROM", 13, CPROM_Init},
{"REX SL-1632", 14, UNLSL1632_Init},
{"100-in-1", 15, Mapper15_Init},
{"BANDAI 24C02", 16, Mapper16_Init},
{"FFE Rev. B", 17, Mapper17_Init},
{"JALECO SS880006", 18, Mapper18_Init}, // JF-NNX (EB89018-30007) boards
{"Namcot 106", 19, Mapper19_Init},
// {"", 20, Mapper20_Init},
{"Konami VRC2/VRC4 A", 21, Mapper21_Init},
{"Konami VRC2/VRC4 B", 22, Mapper22_Init},
{"Konami VRC2/VRC4 C", 23, Mapper23_Init},
{"Konami VRC6 Rev. A", 24, Mapper24_Init},
{"Konami VRC2/VRC4 D", 25, Mapper25_Init},
{"Konami VRC6 Rev. B", 26, Mapper26_Init},
{"CC-21 MI HUN CHE", 27, UNLCC21_Init}, // Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards
// {"", 28, Mapper28_Init}, // Custom Multidiscrete mapper for PDs
// {"", 29, Mapper29_Init},
// {"", 30, Mapper30_Init},
// {"", 31, Mapper31_Init},
{"IREM G-101", 32, Mapper32_Init},
{"TC0190FMC/TC0350FMR", 33, Mapper33_Init},
{"IREM I-IM/BNROM", 34, Mapper34_Init},
{"Wario Land 2", 35, UNLSC127_Init},
{"TXC Policeman", 36, Mapper36_Init},
{"PAL-ZZ SMB/TETRIS/NWC",37, Mapper37_Init},
{"Bit Corp.", 38, Mapper38_Init}, // Crime Busters
// {"", 39, Mapper39_Init},
{"SMB2j FDS", 40, Mapper40_Init},
{"CALTRON 6-in-1", 41, Mapper41_Init},
{"BIO MIRACLE FDS", 42, Mapper42_Init},
{"FDS SMB2j LF36", 43, Mapper43_Init},
{"MMC3 BMC PIRATE A", 44, Mapper44_Init},
{"MMC3 BMC PIRATE B", 45, Mapper45_Init},
{"RUMBLESTATION 15-in-1",46, Mapper46_Init},
{"NES-QJ SSVB/NWC", 47, Mapper47_Init},
{"TAITO TCxxx", 48, Mapper48_Init},
{"MMC3 BMC PIRATE C", 49, Mapper49_Init},
{"SMB2j FDS Rev. A", 50, Mapper50_Init},
{"11-in-1 BALL SERIES", 51, Mapper51_Init}, // 1993 year version
{"MMC3 BMC PIRATE D", 52, Mapper52_Init},
{"SUPERVISION 16-in-1", 53, Supervision16_Init},
// {"", 54, Mapper54_Init},
// {"", 55, Mapper55_Init},
// {"", 56, Mapper56_Init},
{"SIMBPLE BMC PIRATE A", 57, Mapper57_Init},
{"SIMBPLE BMC PIRATE B", 58, BMCGK192_Init},
{"", 59, Mapper59_Init}, // Check this out
{"SIMBPLE BMC PIRATE C", 60, BMCD1038_Init},
{"20-in-1 KAISER Rev. A",61, Mapper61_Init},
{"700-in-1", 62, Mapper62_Init},
// {"", 63, Mapper63_Init},
{"TENGEN RAMBO1", 64, Mapper64_Init},
{"IREM-H3001", 65, Mapper65_Init},
{"MHROM", 66, MHROM_Init},
{"SUNSOFT-FZII", 67, Mapper67_Init},
{"Sunsoft Mapper #4", 68, Mapper68_Init},
{"SUNSOFT-5/FME-7", 69, Mapper69_Init},
{"BA KAMEN DISCRETE", 70, Mapper70_Init},
{"CAMERICA BF9093", 71, Mapper71_Init},
{"JALECO JF-17", 72, Mapper72_Init},
{"KONAMI VRC3", 73, Mapper73_Init},
{"TW MMC3+VRAM Rev. A", 74, Mapper74_Init},
{"KONAMI VRC1", 75, Mapper75_Init},
{"NAMCOT 108 Rev. A", 76, Mapper76_Init},
{"IREM LROG017", 77, Mapper77_Init},
{"Irem 74HC161/32", 78, Mapper78_Init},
{"AVE/C&E/TXC BOARD", 79, Mapper79_Init},
{"TAITO X1-005 Rev. A", 80, Mapper80_Init},
// {"", 81, Mapper81_Init},
{"TAITO X1-017", 82, Mapper82_Init},
{"YOKO VRC Rev. B", 83, Mapper83_Init},
// {"", 84, Mapper84_Init},
{"KONAMI VRC7", 85, Mapper85_Init},
{"JALECO JF-13", 86, Mapper86_Init},
{"74*139/74 DISCRETE", 87, Mapper87_Init},
{"NAMCO 3433", 88, Mapper88_Init},
{"SUNSOFT-3", 89, Mapper89_Init}, // SUNSOFT-2 mapper
{"HUMMER/JY BOARD", 90, Mapper90_Init},
{"EARLY HUMMER/JY BOARD",91, Mapper91_Init},
{"JALECO JF-19", 92, Mapper92_Init},
{"SUNSOFT-3R", 93, SUNSOFT_UNROM_Init},// SUNSOFT-2 mapper with VRAM, different wiring
{"HVC-UN1ROM", 94, Mapper94_Init},
{"NAMCOT 108 Rev. B", 95, Mapper95_Init},
{"BANDAI OEKAKIDS", 96, Mapper96_Init},
{"IREM TAM-S1", 97, Mapper97_Init},
// {"", 98, Mapper98_Init},
{"VS Uni/Dual- system", 99, Mapper99_Init},
// {"", 100, Mapper100_Init},
{"", 101, Mapper101_Init},
// {"", 102, Mapper102_Init},
{"FDS DOKIDOKI FULL", 103, Mapper103_Init},
// {"", 104, Mapper104_Init},
{"NES-EVENT NWC1990", 105, Mapper105_Init},
{"SMB3 PIRATE A", 106, Mapper106_Init},
{"MAGIC CORP A", 107, Mapper107_Init},
{"FDS UNROM BOARD", 108, Mapper108_Init},
// {"", 109, Mapper109_Init},
// {"", 110, Mapper110_Init},
// {"", 111, Mapper111_Init},
{"ASDER/NTDEC BOARD", 112, Mapper112_Init},
{"HACKER/SACHEN BOARD", 113, Mapper113_Init},
{"MMC3 SG PROT. A", 114, Mapper114_Init},
{"MMC3 PIRATE A", 115, Mapper115_Init},
{"MMC1/MMC3/VRC PIRATE",116, UNLSL12_Init},
{"FUTURE MEDIA BOARD", 117, Mapper117_Init},
{"TSKROM", 118, TKSROM_Init},
{"NES-TQROM", 119, Mapper119_Init},
{"FDS TOBIDASE", 120, Mapper120_Init},
{"MMC3 PIRATE PROT. A", 121, Mapper121_Init},
// {"", 122, Mapper122_Init},
{"MMC3 PIRATE H2288", 123, UNLH2288_Init},
// {"", 124, Mapper124_Init},
{"FDS LH32", 125, LH32_Init},
// {"", 126, Mapper126_Init},
// {"", 127, Mapper127_Init},
// {"", 128, Mapper128_Init},
// {"", 129, Mapper129_Init},
// {"", 130, Mapper130_Init},
// {"", 131, Mapper131_Init},
{"TXC/MGENIUS 22111", 132, UNL22211_Init},
{"SA72008", 133, SA72008_Init},
{"MMC3 BMC PIRATE", 134, Mapper134_Init},
// {"", 135, Mapper135_Init},
{"TCU02", 136, TCU02_Init},
{"S8259D", 137, S8259D_Init},
{"S8259B", 138, S8259B_Init},
{"S8259C", 139, S8259C_Init},
{"JALECO JF-11/14", 140, Mapper140_Init},
{"S8259A", 141, S8259A_Init},
{"UNLKS7032", 142, UNLKS7032_Init},
{"TCA01", 143, TCA01_Init},
{"AGCI 50282", 144, Mapper144_Init},
{"SA72007", 145, SA72007_Init},
{"SA0161M", 146, SA0161M_Init},
{"TCU01", 147, TCU01_Init},
{"SA0037", 148, SA0037_Init},
{"SA0036", 149, SA0036_Init},
{"S74LS374N", 150, S74LS374N_Init},
{"", 151, Mapper151_Init},
{"", 152, Mapper152_Init},
{"BANDAI SRAM", 153, Mapper153_Init}, // Bandai board 16 with SRAM instead of EEPROM
{"", 154, Mapper154_Init},
{"", 155, Mapper155_Init},
{"", 156, Mapper156_Init},
{"BANDAI BARCODE", 157, Mapper157_Init},
// {"", 158, Mapper158_Init},
{"BANDAI 24C01", 159, Mapper159_Init}, // Different type of EEPROM on the bandai board
{"SA009", 160, SA009_Init},
// {"", 161, Mapper161_Init},
{"", 162, UNLFS304_Init},
{"", 163, Mapper163_Init},
{"", 164, Mapper164_Init},
{"", 165, Mapper165_Init},
{"SUBOR Rev. A", 166, Mapper166_Init},
{"SUBOR Rev. B", 167, Mapper167_Init},
{"", 168, Mapper168_Init},
// {"", 169, Mapper169_Init},
{"", 170, Mapper170_Init},
{"", 171, Mapper171_Init},
{"", 172, Mapper172_Init},
{"", 173, Mapper173_Init},
// {"", 174, Mapper174_Init},
{"", 175, Mapper175_Init},
{"BMCFK23C", 176, BMCFK23C_Init}, // zero 26-may-2012 - well, i have some WXN junk games that use 176 for instance ????. i dont know what game uses this BMCFK23C as mapper 176. we'll have to make a note when we find it.
{"", 177, Mapper177_Init},
{"", 178, Mapper178_Init},
// {"", 179, Mapper179_Init},
{"", 180, Mapper180_Init},
{"", 181, Mapper181_Init},
// {"", 182, Mapper182_Init}, // Deprecated, dupe
{"", 183, Mapper183_Init},
{"", 184, Mapper184_Init},
{"", 185, Mapper185_Init},
{"", 186, Mapper186_Init},
{"", 187, Mapper187_Init},
{"", 188, Mapper188_Init},
{"", 189, Mapper189_Init},
// {"", 190, Mapper190_Init},
{"", 191, Mapper191_Init},
{"TW MMC3+VRAM Rev. B", 192, Mapper192_Init},
{"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf
{"TW MMC3+VRAM Rev. C", 194, Mapper194_Init},
{"TW MMC3+VRAM Rev. D", 195, Mapper195_Init},
{"", 196, Mapper196_Init},
{"", 197, Mapper197_Init},
{"TW MMC3+VRAM Rev. E", 198, Mapper198_Init},
{"", 199, Mapper199_Init},
{"", 200, Mapper200_Init},
{"", 201, Mapper201_Init},
{"", 202, Mapper202_Init},
{"", 203, Mapper203_Init},
{"", 204, Mapper204_Init},
{"", 205, Mapper205_Init},
{"NAMCOT 108 Rev. C", 206, Mapper206_Init}, // Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3
{"TAITO X1-005 Rev. B", 207, Mapper207_Init},
{"", 208, Mapper208_Init},
{"", 209, Mapper209_Init},
{"", 210, Mapper210_Init},
{"", 211, Mapper211_Init},
{"", 212, Mapper212_Init},
{"", 213, Mapper213_Init},
{"", 214, Mapper214_Init},
{"", 215, UNL8237_Init},
{"", 216, Mapper216_Init},
{"", 217, Mapper217_Init}, // Redefined to a new Discrete BMC mapper
// {"", 218, Mapper218_Init},
{"UNLA9746", 219, UNLA9746_Init},
{"Debug Mapper", 220, UNLPEC586Init}, // UNLKS7057_Init},
{"UNLN625092", 221, UNLN625092_Init},
{"", 222, Mapper222_Init},
// {"", 223, Mapper223_Init},
// {"", 224, Mapper224_Init},
{"", 225, Mapper225_Init},
{"BMC 22+20-in-1", 226, Mapper226_Init},
{"", 227, Mapper227_Init},
{"", 228, Mapper228_Init},
{"", 229, Mapper229_Init},
{"BMC Contra+22-in-1", 230, Mapper230_Init},
{"", 231, Mapper231_Init},
{"BMC QUATTRO", 232, Mapper232_Init},
{"BMC 22+20-in-1 RST", 233, Mapper233_Init},
{"BMC MAXI", 234, Mapper234_Init},
{"", 235, Mapper235_Init},
// {"", 236, Mapper236_Init},
// {"", 237, Mapper237_Init},
{"UNL6035052", 238, UNL6035052_Init},
// {"", 239, Mapper239_Init},
{"", 240, Mapper240_Init},
{"", 241, Mapper241_Init},
{"", 242, Mapper242_Init},
{"S74LS374NA", 243, S74LS374NA_Init},
{"DECATHLON", 244, Mapper244_Init},
{"", 245, Mapper245_Init},
{"FONG SHEN BANG", 246, Mapper246_Init},
// {"", 247, Mapper247_Init},
// {"", 248, Mapper248_Init},
{"", 249, Mapper249_Init},
{"", 250, Mapper250_Init},
// {"", 251, Mapper251_Init}, // No good dumps for this mapper, use UNIF version
{"SAN GUO ZHI PIRATE", 252, Mapper252_Init},
{"DRAGON BALL PIRATE", 253, Mapper253_Init},
{"", 254, Mapper254_Init},
// {"", 255, Mapper255_Init}, // No good dumps for this mapper
{"", 0, NULL}
};
int iNESLoad(const char *name, FCEUFILE *fp) {
struct md5_context md5;
char* mappername;
uint32 mappertest;
if (FCEU_fread(&head, 1, 16, fp) != 16)
return 0;
if (memcmp(&head, "NES\x1a", 4))
return 0;
memset(&iNESCart, 0, sizeof(iNESCart));
if (!memcmp((char*)(&head) + 0x7, "DiskDude", 8)) {
memset((char*)(&head) + 0x7, 0, 0x9);
}
if (!memcmp((char*)(&head) + 0x7, "demiforce", 9)) {
memset((char*)(&head) + 0x7, 0, 0x9);
}
if (!memcmp((char*)(&head) + 0xA, "Ni03", 4)) {
if (!memcmp((char*)(&head) + 0x7, "Dis", 3))
memset((char*)(&head) + 0x7, 0, 0x9);
else
memset((char*)(&head) + 0xA, 0, 0x6);
}
MapperNo = (head.ROM_type >> 4);
MapperNo |= (head.ROM_type2 & 0xF0);
if (head.ROM_type & 8) {
Mirroring = 2;
} else
Mirroring = (head.ROM_type & 1);
if (!head.ROM_size)
ROM_size = 256;
else
ROM_size = uppow2(head.ROM_size);
VROM_size = uppow2(head.VROM_size);
if ((ROM = (uint8*)FCEU_malloc(ROM_size << 14)) == NULL)
return 0;
memset(ROM, 0xFF, ROM_size << 14);
if (VROM_size) {
if ((VROM = (uint8*)FCEU_malloc(VROM_size << 13)) == NULL) {
free(ROM);
ROM = NULL;
return 0;
}
memset(VROM, 0xFF, VROM_size << 13);
}
if (head.ROM_type & 4) { /* Trainer */
trainerpoo = (uint8*)FCEU_gmalloc(512);
FCEU_fread(trainerpoo, 512, 1, fp);
}
ResetCartMapping();
ResetExState(0, 0);
SetupCartPRGMapping(0, ROM, ROM_size << 14, 0);
if (head.ROM_size)
FCEU_fread(ROM, 0x4000, head.ROM_size, fp);
else
FCEU_fread(ROM, 0x4000, ROM_size, fp);
if (VROM_size)
FCEU_fread(VROM, 0x2000, VROM_size, fp);
md5_starts(&md5);
md5_update(&md5, ROM, ROM_size << 14);
iNESGameCRC32 = CalcCRC32(0, ROM, ROM_size << 14);
if (VROM_size) {
iNESGameCRC32 = CalcCRC32(iNESGameCRC32, VROM, VROM_size << 13);
md5_update(&md5, VROM, VROM_size << 13);
}
md5_finish(&md5, iNESCart.MD5);
memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5));
iNESCart.CRC32 = iNESGameCRC32;
FCEU_printf(" PRG ROM: %3d x 16KiB\n", ROM_size);
FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size);
FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32);
FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5));
mappername = "Not Listed";
for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) {
if (bmap[mappertest].number == MapperNo) {
mappername = bmap[mappertest].name;
break;
}
}
FCEU_printf(" Mapper #: %d\n", MapperNo);
FCEU_printf(" Mapper name: %s\n", mappername);
FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal");
FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No");
FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No");
SetInput();
CheckHInfo();
{
int x;
uint64 partialmd5 = 0;
for (x = 0; x < 8; x++) {
partialmd5 |= (uint64)iNESCart.MD5[7 - x] << (x * 8);
}
FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
}
/* Must remain here because above functions might change value of
VROM_size and free(VROM).
*/
if (VROM_size)
SetupCartCHRMapping(0, VROM, VROM_size * 0x2000, 0);
if (Mirroring == 2) {
ExtraNTARAM = (uint8*)FCEU_gmalloc(2048);
SetupCartMirroring(4, 1, ExtraNTARAM);
} else if (Mirroring >= 0x10)
SetupCartMirroring(2 + (Mirroring & 1), 1, 0);
else
SetupCartMirroring(Mirroring & 1, (Mirroring & 4) >> 2, 0);
iNESCart.battery = (head.ROM_type & 2) ? 1 : 0;
iNESCart.mirror = Mirroring;
if (!iNES_Init(MapperNo))
FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo);
FCEU_LoadGameSave(&iNESCart);
GameInterface = iNESGI;
FCEU_printf("\n");
if (strstr(name, "(E)") || strstr(name, "(e)")
|| strstr(name, "(Europe)") || strstr(name, "(PAL)")
|| strstr(name, "(F)") || strstr(name, "(f)")
|| strstr(name, "(G)") || strstr(name, "(g)")
|| strstr(name, "(I)") || strstr(name, "(i)"))
GameInfo->vidsys = GIV_PAL;
return 1;
}
static int iNES_Init(int num) {
BMAPPINGLocal *tmp = bmap;
CHRRAMSize = -1;
if (GameInfo->type == GIT_VSUNI)
AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
while (tmp->init) {
if (num == tmp->number) {
UNIFchrrama = 0; // need here for compatibility with UNIF mapper code
if (!VROM_size) {
switch (num) { // FIXME, mapper or game data base with the board parameters and ROM/RAM sizes
case 13: CHRRAMSize = 16 * 1024; break;
case 6:
case 96: CHRRAMSize = 32 * 1024; break;
case 176: CHRRAMSize = 256 * 1024; break;
default: CHRRAMSize = 8 * 1024; break;
}
if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0;
UNIFchrrama = VROM;
SetupCartCHRMapping(0, VROM, CHRRAMSize, 1);
AddExState(VROM, CHRRAMSize, 0, "CHRR");
}
if (head.ROM_type & 8)
AddExState(ExtraNTARAM, 2048, 0, "EXNR");
tmp->init(&iNESCart);
return 1;
}
tmp++;
}
return 0;
}

View File

@ -1,378 +0,0 @@
/* 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 "netplay.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

@ -1,20 +0,0 @@
#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

@ -1,519 +0,0 @@
/* 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 <math.h>
#include "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "video.h"
#include "sound.h"
#include "nsf.h"
#include "general.h"
#include "fceu-memory.h"
#include "file.h"
#include "fds.h"
#include "cart.h"
#include "input.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static uint8 SongReload;
static int CurrentSong;
static DECLFW(NSF_write);
static DECLFR(NSF_read);
static int vismode = 1;
static uint8 NSFROM[0x30 + 6] =
{
/* 0x00 - NMI */
0x8D, 0xF4, 0x3F, /* Stop play routine NMIs. */
0xA2, 0xFF, 0x9A, /* Initialize the stack pointer. */
0xAD, 0xF0, 0x3F, /* See if we need to init. */
0xF0, 0x09, /* If 0, go to play routine playing. */
0xAD, 0xF1, 0x3F, /* Confirm and load A */
0xAE, 0xF3, 0x3F, /* Load X with PAL/NTSC byte */
0x20, 0x00, 0x00, /* JSR to init routine */
0xA9, 0x00,
0xAA,
0xA8,
0x20, 0x00, 0x00, /* JSR to play routine */
0x8D, 0xF5, 0x3F, /* Start play routine NMIs. */
0x90, 0xFE, /* Loopie time. */
/* 0x20 */
0x8D, 0xF3, 0x3F, /* Init init NMIs */
0x18,
0x90, 0xFE /* Loopie time. */
};
static DECLFR(NSFROMRead) {
return (NSFROM - 0x3800)[A];
}
static int doreset = 0;
static int NSFNMIFlags;
static uint8 *NSFDATA = 0;
static int NSFMaxBank;
static int NSFSize;
static uint8 BSon;
static uint16 PlayAddr;
static uint16 InitAddr;
static uint16 LoadAddr;
static NSF_HEADER NSFHeader;
void NSFMMC5_Close(void);
static uint8 *ExWRAM = 0;
void NSFGI(int h) {
switch (h) {
case GI_CLOSE:
if (NSFDATA) {
free(NSFDATA); NSFDATA = 0;
}
if (ExWRAM) {
free(ExWRAM); ExWRAM = 0;
}
if (NSFHeader.SoundChip & 1) {
// NSFVRC6_Init();
} else if (NSFHeader.SoundChip & 2) {
// NSFVRC7_Init();
} else if (NSFHeader.SoundChip & 4) {
// FDSSoundReset();
} else if (NSFHeader.SoundChip & 8) {
NSFMMC5_Close();
} else if (NSFHeader.SoundChip & 0x10) {
// NSFN106_Init();
} else if (NSFHeader.SoundChip & 0x20) {
// NSFAY_Init();
}
break;
case GI_RESETM2:
case GI_POWER: NSF_init(); break;
}
}
// First 32KB is reserved for sound chip emulation in the iNES mapper code.
static INLINE void BANKSET(uint32 A, uint32 bank) {
bank &= NSFMaxBank;
if (NSFHeader.SoundChip & 4)
memcpy(ExWRAM + (A - 0x6000), NSFDATA + (bank << 12), 4096);
else
setprg4(A, bank);
}
int NSFLoad(FCEUFILE *fp) {
int x;
FCEU_fseek(fp, 0, SEEK_SET);
FCEU_fread(&NSFHeader, 1, 0x80, fp);
if (memcmp(NSFHeader.ID, "NESM\x1a", 5))
return 0;
NSFHeader.SongName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0;
LoadAddr = NSFHeader.LoadAddressLow;
LoadAddr |= NSFHeader.LoadAddressHigh << 8;
if (LoadAddr < 0x6000) {
FCEUD_PrintError("Invalid load address.");
return(0);
}
InitAddr = NSFHeader.InitAddressLow;
InitAddr |= NSFHeader.InitAddressHigh << 8;
PlayAddr = NSFHeader.PlayAddressLow;
PlayAddr |= NSFHeader.PlayAddressHigh << 8;
NSFSize = FCEU_fgetsize(fp) - 0x80;
NSFMaxBank = ((NSFSize + (LoadAddr & 0xfff) + 4095) / 4096);
NSFMaxBank = uppow2(NSFMaxBank);
if (!(NSFDATA = (uint8*)FCEU_malloc(NSFMaxBank * 4096)))
return 0;
FCEU_fseek(fp, 0x80, SEEK_SET);
memset(NSFDATA, 0x00, NSFMaxBank * 4096);
FCEU_fread(NSFDATA + (LoadAddr & 0xfff), 1, NSFSize, fp);
NSFMaxBank--;
BSon = 0;
for (x = 0; x < 8; x++)
BSon |= NSFHeader.BankSwitch[x];
GameInfo->type = GIT_NSF;
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
GameInfo->cspecial = SIS_NSF;
for (x = 0;; x++) {
if (NSFROM[x] == 0x20) {
NSFROM[x + 1] = InitAddr & 0xFF;
NSFROM[x + 2] = InitAddr >> 8;
NSFROM[x + 8] = PlayAddr & 0xFF;
NSFROM[x + 9] = PlayAddr >> 8;
break;
}
}
if (NSFHeader.VideoSystem == 0)
GameInfo->vidsys = GIV_NTSC;
else if (NSFHeader.VideoSystem == 1)
GameInfo->vidsys = GIV_PAL;
GameInterface = NSFGI;
FCEU_printf("NSF Loaded. File information:\n\n");
FCEU_printf(" Name: %s\n Artist: %s\n Copyright: %s\n\n", NSFHeader.SongName, NSFHeader.Artist, NSFHeader.Copyright);
if (NSFHeader.SoundChip) {
static char *tab[6] = { "Konami VRCVI", "Konami VRCVII", "Nintendo FDS", "Nintendo MMC5", "Namco 106", "Sunsoft FME-07" };
for (x = 0; x < 6; x++)
if (NSFHeader.SoundChip & (1 << x)) {
FCEU_printf(" Expansion hardware: %s\n", tab[x]);
NSFHeader.SoundChip = 1 << x; /* Prevent confusing weirdness if more than one bit is set. */
break;
}
}
if (BSon)
FCEU_printf(" Bank-switched.\n");
FCEU_printf(" Load address: $%04x\n Init address: $%04x\n Play address: $%04x\n", LoadAddr, InitAddr, PlayAddr);
FCEU_printf(" %s\n", (NSFHeader.VideoSystem & 1) ? "PAL" : "NTSC");
FCEU_printf(" Starting song: %d / %d\n\n", NSFHeader.StartingSong, NSFHeader.TotalSongs);
if (NSFHeader.SoundChip & 4)
ExWRAM = FCEU_gmalloc(32768 + 8192);
else
ExWRAM = FCEU_gmalloc(8192);
return 1;
}
static DECLFR(NSFVectorRead) {
if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2) || doreset) {
if (A == 0xFFFA) return(0x00);
else if (A == 0xFFFB) return(0x38);
else if (A == 0xFFFC) return(0x20);
else if (A == 0xFFFD) {
doreset = 0; return(0x38);
}
return(X.DB);
} else
return(CartBR(A));
}
void NSFVRC6_Init(void);
void NSFVRC7_Init(void);
void NSFMMC5_Init(void);
void NSFN106_Init(void);
void NSFAY_Init(void);
void NSF_init(void) {
doreset = 1;
ResetCartMapping();
if (NSFHeader.SoundChip & 4) {
SetupCartPRGMapping(0, ExWRAM, 32768 + 8192, 1);
setprg32(0x6000, 0);
setprg8(0xE000, 4);
memset(ExWRAM, 0x00, 32768 + 8192);
SetWriteHandler(0x6000, 0xDFFF, CartBW);
SetReadHandler(0x6000, 0xFFFF, CartBR);
} else {
memset(ExWRAM, 0x00, 8192);
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetupCartPRGMapping(0, NSFDATA, ((NSFMaxBank + 1) * 4096), 0);
SetupCartPRGMapping(1, ExWRAM, 8192, 1);
setprg8r(1, 0x6000, 0);
SetReadHandler(0x8000, 0xFFFF, CartBR);
}
if (BSon) {
int32 x;
for (x = 0; x < 8; x++) {
if (NSFHeader.SoundChip & 4 && x >= 6)
BANKSET(0x6000 + (x - 6) * 4096, NSFHeader.BankSwitch[x]);
BANKSET(0x8000 + x * 4096, NSFHeader.BankSwitch[x]);
}
} else {
int32 x;
for (x = (LoadAddr & 0xF000); x < 0x10000; x += 0x1000)
BANKSET(x, ((x - (LoadAddr & 0x7000)) >> 12));
}
SetReadHandler(0xFFFA, 0xFFFD, NSFVectorRead);
SetWriteHandler(0x2000, 0x3fff, 0);
SetReadHandler(0x2000, 0x37ff, 0);
SetReadHandler(0x3836, 0x3FFF, 0);
SetReadHandler(0x3800, 0x3835, NSFROMRead);
SetWriteHandler(0x5ff6, 0x5fff, NSF_write);
SetWriteHandler(0x3ff0, 0x3fff, NSF_write);
SetReadHandler(0x3ff0, 0x3fff, NSF_read);
if (NSFHeader.SoundChip & 1) {
NSFVRC6_Init();
} else if (NSFHeader.SoundChip & 2) {
NSFVRC7_Init();
} else if (NSFHeader.SoundChip & 4) {
FDSSoundReset();
} else if (NSFHeader.SoundChip & 8) {
NSFMMC5_Init();
} else if (NSFHeader.SoundChip & 0x10) {
NSFN106_Init();
} else if (NSFHeader.SoundChip & 0x20) {
NSFAY_Init();
}
CurrentSong = NSFHeader.StartingSong;
SongReload = 0xFF;
NSFNMIFlags = 0;
}
static DECLFW(NSF_write) {
switch (A) {
case 0x3FF3: NSFNMIFlags |= 1; break;
case 0x3FF4: NSFNMIFlags &= ~2; break;
case 0x3FF5: NSFNMIFlags |= 2; break;
case 0x5FF6:
case 0x5FF7: if (!(NSFHeader.SoundChip & 4)) return;
case 0x5FF8:
case 0x5FF9:
case 0x5FFA:
case 0x5FFB:
case 0x5FFC:
case 0x5FFD:
case 0x5FFE:
case 0x5FFF: if (!BSon) return;
A &= 0xF;
BANKSET((A * 4096), V);
break;
}
}
static DECLFR(NSF_read) {
int x;
switch (A) {
case 0x3ff0: x = SongReload;
#ifdef FCEUDEF_DEBUGGER
if (!fceuindbg)
#endif
SongReload = 0;
return x;
case 0x3ff1:
#ifdef FCEUDEF_DEBUGGER
if (!fceuindbg)
#endif
{
memset(RAM, 0x00, 0x800);
BWrite[0x4015](0x4015, 0x0);
for (x = 0; x < 0x14; x++)
BWrite[0x4000 + x](0x4000 + x, 0);
BWrite[0x4015](0x4015, 0xF);
if (NSFHeader.SoundChip & 4) {
BWrite[0x4017](0x4017, 0xC0); /* FDS BIOS writes $C0 */
BWrite[0x4089](0x4089, 0x80);
BWrite[0x408A](0x408A, 0xE8);
} else {
memset(ExWRAM, 0x00, 8192);
BWrite[0x4017](0x4017, 0xC0);
BWrite[0x4017](0x4017, 0xC0);
BWrite[0x4017](0x4017, 0x40);
}
if (BSon) {
for (x = 0; x < 8; x++)
BANKSET(0x8000 + x * 4096, NSFHeader.BankSwitch[x]);
}
return(CurrentSong - 1);
}
case 0x3FF3: return PAL;
}
return 0;
}
uint8 FCEU_GetJoyJoy(void);
static int special = 0;
void DrawNSF(uint8 *XBuf) {
char snbuf[16];
int x;
if (vismode == 0) return;
memset(XBuf, 0, 256 * 240);
{
int32 *Bufpl;
int32 mul = 0;
int l;
l = GetSoundBuffer(&Bufpl);
if (special == 0) {
if (FSettings.SoundVolume)
mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50);
for (x = 0; x < 256; x++) {
uint32 y;
y = 142 + ((Bufpl[(x * l) >> 8] * mul) >> 14);
if (y < 240)
XBuf[x + y * 256] = 3;
}
} else if (special == 1) {
if (FSettings.SoundVolume)
mul = 8192 * 240 / (8192 * FSettings.SoundVolume / 50);
for (x = 0; x < 256; x++) {
double r;
uint32 xp, yp;
r = (Bufpl[(x * l) >> 8] * mul) >> 14;
xp = 128 + r*cos(x*M_PI*2 / 256);
yp = 120 + r*sin(x*M_PI*2 / 256);
xp &= 255;
yp %= 240;
XBuf[xp + yp * 256] = 3;
}
} else if (special == 2) {
static double theta = 0;
if (FSettings.SoundVolume)
mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50);
for (x = 0; x < 128; x++) {
double xc, yc;
double r, t;
uint32 m, n;
xc = (double)128 - x;
yc = 0 - ((double)(((Bufpl[(x * l) >> 8]) * mul) >> 14));
t = M_PI + atan(yc / xc);
r = sqrt(xc * xc + yc * yc);
t += theta;
m = 128 + r*cos(t);
n = 120 + r*sin(t);
if (m < 256 && n < 240)
XBuf[m + n * 256] = 3;
}
for (x = 128; x < 256; x++) {
double xc, yc;
double r, t;
uint32 m, n;
xc = (double)x - 128;
yc = (double)((Bufpl[(x * l) >> 8] * mul) >> 14);
t = atan(yc / xc);
r = sqrt(xc * xc + yc * yc);
t += theta;
m = 128 + r*cos(t);
n = 120 + r*sin(t);
if (m < 256 && n < 240)
XBuf[m + n * 256] = 3;
}
theta += (double)M_PI / 256;
}
}
DrawTextTrans(XBuf + 10 * 256 + 4 + (((31 - strlen((char*)NSFHeader.SongName)) << 2)), 256, NSFHeader.SongName, 6);
DrawTextTrans(XBuf + 26 * 256 + 4 + (((31 - strlen((char*)NSFHeader.Artist)) << 2)), 256, NSFHeader.Artist, 6);
DrawTextTrans(XBuf + 42 * 256 + 4 + (((31 - strlen((char*)NSFHeader.Copyright)) << 2)), 256, NSFHeader.Copyright, 6);
DrawTextTrans(XBuf + 70 * 256 + 4 + (((31 - strlen("Song:")) << 2)), 256, (uint8*)"Song:", 6);
sprintf(snbuf, "<%d/%d>", CurrentSong, NSFHeader.TotalSongs);
DrawTextTrans(XBuf + 82 * 256 + 4 + (((31 - strlen(snbuf)) << 2)), 256, (uint8*)snbuf, 6);
{
static uint8 last = 0;
uint8 tmp;
tmp = FCEU_GetJoyJoy();
if ((tmp & JOY_RIGHT) && !(last & JOY_RIGHT)) {
if (CurrentSong < NSFHeader.TotalSongs) {
CurrentSong++;
SongReload = 0xFF;
}
} else if ((tmp & JOY_LEFT) && !(last & JOY_LEFT)) {
if (CurrentSong > 1) {
CurrentSong--;
SongReload = 0xFF;
}
} else if ((tmp & JOY_UP) && !(last & JOY_UP)) {
CurrentSong += 10;
if (CurrentSong > NSFHeader.TotalSongs) CurrentSong = NSFHeader.TotalSongs;
SongReload = 0xFF;
} else if ((tmp & JOY_DOWN) && !(last & JOY_DOWN)) {
CurrentSong -= 10;
if (CurrentSong < 1) CurrentSong = 1;
SongReload = 0xFF;
} else if ((tmp & JOY_START) && !(last & JOY_START))
SongReload = 0xFF;
else if ((tmp & JOY_A) && !(last & JOY_A)) {
special = (special + 1) % 3;
}
last = tmp;
}
}
void DoNSFFrame(void) {
if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2))
TriggerNMI();
}
void FCEUI_NSFSetVis(int mode) {
vismode = mode;
}
int FCEUI_NSFChange(int amount) {
CurrentSong += amount;
if (CurrentSong < 1) CurrentSong = 1;
else if (CurrentSong > NSFHeader.TotalSongs) CurrentSong = NSFHeader.TotalSongs;
SongReload = 0xFF;
return(CurrentSong);
}
/* Returns total songs */
int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen) {
strncpy(name, NSFHeader.SongName, maxlen);
strncpy(artist, NSFHeader.Artist, maxlen);
strncpy(copyright, NSFHeader.Copyright, maxlen);
return(NSFHeader.TotalSongs);
}

View File

@ -1,365 +0,0 @@
/* 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(memstream_t *mem, SFORMAT *sf)
{
uint32 acc=0;
while(sf->v)
{
if(sf->s==~0) /* Link to another struct. */
{
uint32 tmp;
if(!(tmp=SubWrite(mem, (SFORMAT *)sf->v)))
return(0);
acc+=tmp;
sf++;
continue;
}
acc+=8; /* Description + size */
acc+=sf->s&(~RLSB);
if(mem) /* Are we writing or calculating the size of this block? */
{
memstream_write(mem, sf->desc, 4);
write32le_mem(sf->s&(~RLSB), mem);
#ifdef MSB_FIRST
if(sf->s&RLSB)
FlipByteOrder(sf->v,sf->s&(~RLSB));
#endif
memstream_write(mem, (uint8 *)sf->v, sf->s&(~RLSB));
/* Now restore the original byte order. */
#ifdef MSB_FIRST
if(sf->s&RLSB)
FlipByteOrder(sf->v,sf->s&(~RLSB));
#endif
}
sf++;
}
return acc;
}
static int WriteStateChunk(memstream_t *mem, int type, SFORMAT *sf)
{
int bsize;
memstream_putc(mem, type);
bsize = SubWrite(0,sf);
write32le_mem(bsize, mem);
if (!SubWrite(mem, 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(memstream_t *mem, SFORMAT *sf, int size)
{
SFORMAT *tmp;
int temp;
temp=memstream_pos(mem);
while(memstream_pos(mem)<temp+size)
{
uint32 tsize;
char toa[4];
if(memstream_read(mem, toa, 4)<=0)
return 0;
read32le_mem(&tsize,mem);
if((tmp=CheckS(sf,tsize,toa)))
{
memstream_read(mem, (uint8 *)tmp->v, tmp->s&(~RLSB));
#ifdef MSB_FIRST
if(tmp->s&RLSB)
FlipByteOrder(tmp->v,tmp->s&(~RLSB));
#endif
}
else
memstream_seek(mem,tsize,SEEK_CUR);
}
return 1;
}
static int ReadStateChunks(memstream_t *st, int32 totalsize)
{
int t;
uint32 size;
int ret = 1;
while (totalsize > 0)
{
t = memstream_getc(st);
if (t == EOF)
break;
if (!read32le_mem(&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 (memstream_seek(st, size, SEEK_CUR) < 0)
goto endo;
break;
}
}
endo:
return ret;
}
int CurrentState = 0;
extern int geniestage;
void FCEUSS_Save_Mem(void)
{
memstream_t *mem = memstream_open(1);
uint32 totalsize;
uint8 header[16] = {0};
header[0] = 'F';
header[1] = 'C';
header[2] = 'S';
header[3] = 0xFF;
FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC);
memstream_write(mem, header, 16);
FCEUPPU_SaveState();
totalsize = WriteStateChunk(mem, 1, SFCPU);
totalsize += WriteStateChunk(mem, 2, SFCPUC);
totalsize += WriteStateChunk(mem, 3, FCEUPPU_STATEINFO);
totalsize += WriteStateChunk(mem, 4, FCEUCTRL_STATEINFO);
totalsize += WriteStateChunk(mem, 5, FCEUSND_STATEINFO);
if (SPreSave)
SPreSave();
totalsize += WriteStateChunk(mem, 0x10, SFMDATA);
if (SPreSave)
SPostSave();
memstream_seek(mem, 4, SEEK_SET);
write32le_mem(totalsize, mem);
memstream_close(mem);
}
void FCEUSS_Load_Mem(void)
{
memstream_t *mem = memstream_open(0);
uint8 header[16];
int stateversion;
int x;
memstream_read(mem, header, 16);
if (memcmp(header,"FCS",3) != 0)
return;
if (header[3] == 0xFF)
stateversion = FCEU_de32lsb(header + 8);
else
stateversion = header[3] * 100;
x = ReadStateChunks(mem, *(uint32*)(header + 4));
if (stateversion < 9500)
X.IRQlow=0;
if (GameStateRestore)
GameStateRestore(stateversion);
if (x)
{
FCEUPPU_LoadState(stateversion);
FCEUSND_LoadState(stateversion);
}
memstream_close(mem);
}
void FCEUSS_CheckStates(void)
{
MEM_TYPE *st = NULL;
char *fn;
int ssel;
for (ssel = 0; ssel < 10; ssel++)
{
st = fopen(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 FCEU_DrawSaveStates(uint8 *XBuf)
{
}

View File

@ -1,626 +0,0 @@
/* 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
*/
/* TODO: Battery backup file saving, mirror force */
/* **INCOMPLETE** */
/* Override stuff: CHR RAM instead of CHR ROM, mirroring. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fceu-types.h"
#include "fceu.h"
#include "cart.h"
#include "unif.h"
#include "ines.h"
#include "general.h"
#include "state.h"
#include "fceu-endian.h"
#include "file.h"
#include "fceu-memory.h"
#include "input.h"
#include "md5.h"
typedef struct {
char ID[4];
uint32 info;
} UNIF_HEADER;
typedef struct {
char *name;
void (*init)(CartInfo *);
int flags;
} BMAPPING;
typedef struct {
char *name;
int (*init)(FCEUFILE *fp);
} BFMAPPING;
CartInfo UNIFCart;
static int vramo;
static int mirrortodo;
static uint8 *boardname;
static uint8 *sboardname;
static uint32 CHRRAMSize;
uint8 *UNIFchrrama = 0;
static UNIF_HEADER unhead;
static UNIF_HEADER uchead;
static uint8 *malloced[32];
static uint32 mallocedsizes[32];
static int FixRomSize(uint32 size, uint32 minimum) {
uint32 x = 1;
if (size < minimum)
return minimum;
while (x < size)
x <<= 1;
return x;
}
static void FreeUNIF(void) {
int x;
if (UNIFchrrama) {
free(UNIFchrrama); UNIFchrrama = 0;
}
if (boardname) {
free(boardname); boardname = 0;
}
for (x = 0; x < 32; x++) {
if (malloced[x]) {
free(malloced[x]); malloced[x] = 0;
}
}
}
static void ResetUNIF(void) {
int x;
for (x = 0; x < 32; x++)
malloced[x] = 0;
vramo = 0;
boardname = 0;
mirrortodo = 0;
memset(&UNIFCart, 0, sizeof(UNIFCart));
UNIFchrrama = 0;
}
static uint8 exntar[2048];
static void MooMirroring(void) {
if (mirrortodo < 0x4)
SetupCartMirroring(mirrortodo, 1, 0);
else if (mirrortodo == 0x4) {
SetupCartMirroring(4, 1, exntar);
AddExState(exntar, 2048, 0, "EXNR");
} else
SetupCartMirroring(0, 0, 0);
}
static int DoMirroring(FCEUFILE *fp) {
int t;
uint32 i;
if (uchead.info == 1) {
if ((t = FCEU_fgetc(fp)) == EOF)
return(0);
mirrortodo = t;
{
static char *stuffo[6] = { "Horizontal", "Vertical", "$2000", "$2400", "\"Four-screen\"", "Controlled by Mapper Hardware" };
if (t < 6)
FCEU_printf(" Name/Attribute Table Mirroring: %s\n", stuffo[t]);
}
} else {
FCEU_printf(" Incorrect Mirroring Chunk Size (%d). Data is:", uchead.info);
for (i = 0; i < uchead.info; i++) {
if ((t = FCEU_fgetc(fp)) == EOF)
return(0);
FCEU_printf(" %02x", t);
}
FCEU_printf("\n Default Name/Attribute Table Mirroring: Horizontal\n", uchead.info);
mirrortodo = 0;
}
return(1);
}
static int NAME(FCEUFILE *fp) {
char namebuf[100];
int index;
int t;
FCEU_printf(" Name: ");
index = 0;
while ((t = FCEU_fgetc(fp)) > 0)
if (index < 99)
namebuf[index++] = t;
namebuf[index] = 0;
FCEU_printf("%s\n", namebuf);
if (!GameInfo->name) {
GameInfo->name = malloc(strlen(namebuf) + 1);
strcpy(GameInfo->name, namebuf);
}
return(1);
}
static int DINF(FCEUFILE *fp) {
char name[100], method[100];
uint8 d, m;
uint16 y;
int t;
if (FCEU_fread(name, 1, 100, fp) != 100)
return(0);
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
d = t;
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
m = t;
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
y = t;
if ((t = FCEU_fgetc(fp)) == EOF) return(0);
y |= t << 8;
if (FCEU_fread(method, 1, 100, fp) != 100)
return(0);
name[99] = method[99] = 0;
FCEU_printf(" Dumped by: %s\n", name);
FCEU_printf(" Dumped with: %s\n", method);
{
char *months[12] = {
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
};
FCEU_printf(" Dumped on: %s %d, %d\n", months[(m - 1) % 12], d, y);
}
return(1);
}
static int CTRL(FCEUFILE *fp) {
int t;
uint32 i;
if (uchead.info == 1) {
if ((t = FCEU_fgetc(fp)) == EOF)
return(0);
/* The information stored in this byte isn't very helpful, but it's
better than nothing...maybe.
*/
if (t & 1)
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
else
GameInfo->input[0] = GameInfo->input[1] = SI_NONE;
if (t & 2)
GameInfo->input[1] = SI_ZAPPER;
} else {
FCEU_printf(" Incorrect Control Chunk Size (%d). Data is:", uchead.info);
for (i = 0; i < uchead.info; i++) {
t = FCEU_fgetc(fp);
FCEU_printf(" %02x", t);
}
FCEU_printf("\n");
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
}
return(1);
}
static int TVCI(FCEUFILE *fp) {
int t;
if ((t = FCEU_fgetc(fp)) == EOF)
return(0);
if (t <= 2) {
char *stuffo[3] = { "NTSC", "PAL", "NTSC and PAL" };
if (t == 0)
GameInfo->vidsys = GIV_NTSC;
else if (t == 1)
GameInfo->vidsys = GIV_PAL;
FCEU_printf(" TV Standard Compatibility: %s\n", stuffo[t]);
}
return(1);
}
static int EnableBattery(FCEUFILE *fp) {
FCEU_printf(" Battery-backed.\n");
if (FCEU_fgetc(fp) == EOF)
return(0);
UNIFCart.battery = 1;
return(1);
}
static int LoadPRG(FCEUFILE *fp) {
int z, t;
z = uchead.ID[3] - '0';
if (z < 0 || z > 15)
return(0);
FCEU_printf(" PRG ROM %d size: %d", z, (int)uchead.info);
if (malloced[z])
free(malloced[z]);
t = FixRomSize(uchead.info, 2048);
if (!(malloced[z] = (uint8*)FCEU_malloc(t)))
return(0);
mallocedsizes[z] = t;
memset(malloced[z] + uchead.info, 0xFF, t - uchead.info);
if (FCEU_fread(malloced[z], 1, uchead.info, fp) != uchead.info) {
FCEU_printf("Read Error!\n");
return(0);
} else
FCEU_printf("\n");
SetupCartPRGMapping(z, malloced[z], t, 0);
return(1);
}
static int SetBoardName(FCEUFILE *fp) {
if (!(boardname = (uint8*)FCEU_malloc(uchead.info + 1)))
return(0);
FCEU_fread(boardname, 1, uchead.info, fp);
boardname[uchead.info] = 0;
FCEU_printf(" Board name: %s\n", boardname);
sboardname = boardname;
if (!memcmp(boardname, "NES-", 4) || !memcmp(boardname, "UNL-", 4) || !memcmp(boardname, "HVC-", 4) || !memcmp(boardname, "BTL-", 4) || !memcmp(boardname, "BMC-", 4))
sboardname += 4;
return(1);
}
static int LoadCHR(FCEUFILE *fp) {
int z, t;
z = uchead.ID[3] - '0';
if (z < 0 || z > 15)
return(0);
FCEU_printf(" CHR ROM %d size: %d", z, (int)uchead.info);
if (malloced[16 + z])
free(malloced[16 + z]);
t = FixRomSize(uchead.info, 8192);
if (!(malloced[16 + z] = (uint8*)FCEU_malloc(t)))
return(0);
mallocedsizes[16 + z] = t;
memset(malloced[16 + z] + uchead.info, 0xFF, t - uchead.info);
if (FCEU_fread(malloced[16 + z], 1, uchead.info, fp) != uchead.info) {
FCEU_printf("Read Error!\n");
return(0);
} else
FCEU_printf("\n");
SetupCartCHRMapping(z, malloced[16 + z], t, 0);
return(1);
}
#define BMCFLAG_FORCE4 0x01
#define BMCFLAG_16KCHRR 0x02
#define BMCFLAG_32KCHRR 0x04
#define BMCFLAG_128KCHRR 0x08
#define BMCFLAG_256KCHRR 0x10
static BMAPPING bmap[] = {
{ "11160", BMC11160_Init, 0 },
{ "12-IN-1", BMC12IN1_Init, 0 },
{ "13in1JY110", BMC13in1JY110_Init, 0 },
{ "190in1", BMC190in1_Init, 0 },
{ "22211", UNL22211_Init, 0 },
{ "3D-BLOCK", UNL3DBlock_Init, 0 },
{ "411120-C", BMC411120C_Init, 0 },
{ "42in1ResetSwitch", Mapper226_Init, 0 },
{ "43272", UNL43272_Init, 0 },
{ "603-5052", UNL6035052_Init, 0 },
{ "64in1NoRepeat", BMC64in1nr_Init, 0 },
{ "70in1", BMC70in1_Init, 0 },
{ "70in1B", BMC70in1B_Init, 0 },
{ "810544-C-A1", BMC810544CA1_Init, 0 },
{ "8157", UNL8157_Init, 0 },
{ "8237", UNL8237_Init, 0 },
{ "8237A", UNL8237A_Init, 0 },
{ "830118C", BMC830118C_Init, 0 },
{ "A65AS", BMCA65AS_Init, 0 },
{ "AC08", AC08_Init, 0 },
{ "ANROM", ANROM_Init, 0 },
{ "AX5705", UNLAX5705_Init, 0 },
{ "BB", UNLBB_Init, 0 },
{ "BS-5", BMCBS5_Init, 0 },
{ "CC-21", UNLCC21_Init, 0 },
{ "CITYFIGHT", UNLCITYFIGHT_Init, 0 },
{ "10-24-C-A1", BMC1024CA1_Init, 0 },
{ "CNROM", CNROM_Init, 0 },
{ "CPROM", CPROM_Init, BMCFLAG_16KCHRR },
{ "D1038", BMCD1038_Init, 0 },
{ "DANCE", UNLOneBus_Init, 0 }, // redundant
{ "DANCE2000", UNLD2000_Init, 0 },
{ "DREAMTECH01", DreamTech01_Init, 0 },
{ "EDU2000", UNLEDU2000_Init, 0 },
{ "EKROM", EKROM_Init, 0 },
{ "ELROM", ELROM_Init, 0 },
{ "ETROM", ETROM_Init, 0 },
{ "EWROM", EWROM_Init, 0 },
{ "FK23C", BMCFK23C_Init, BMCFLAG_256KCHRR },
{ "FK23CA", BMCFK23CA_Init, BMCFLAG_256KCHRR },
{ "FS304", UNLFS304_Init, 0 },
{ "G-146", BMCG146_Init, 0 },
{ "GK-192", BMCGK192_Init, 0 },
{ "GS-2004", BMCGS2004_Init, 0 },
{ "GS-2013", BMCGS2013_Init, 0 },
{ "Ghostbusters63in1", BMCGhostbusters63in1_Init, 0 },
{ "H2288", UNLH2288_Init, 0 },
{ "HKROM", HKROM_Init, 0 },
{ "KOF97", UNLKOF97_Init, 0 },
{ "KONAMI-QTAI", Mapper190_Init, 0 },
{ "KS7012", UNLKS7012_Init, 0 },
{ "KS7013B", UNLKS7013B_Init, 0 },
{ "KS7017", UNLKS7017_Init, 0 },
{ "KS7030", UNLKS7030_Init, 0 },
{ "KS7031", UNLKS7031_Init, 0 },
{ "KS7032", UNLKS7032_Init, 0 },
{ "KS7037", UNLKS7037_Init, 0 },
{ "KS7057", UNLKS7057_Init, 0 },
{ "LE05", LE05_Init, 0 },
{ "LH10", LH10_Init, 0 },
{ "LH32", LH32_Init, 0 },
{ "LH53", LH53_Init, 0 },
{ "MALISB", UNLMaliSB_Init, 0 },
{ "MARIO1-MALEE2", MALEE_Init, 0 },
{ "MHROM", MHROM_Init, 0 },
{ "N625092", UNLN625092_Init, 0 },
{ "NROM", NROM_Init, 0 },
{ "NROM-128", NROM_Init, 0 },
{ "NROM-256", NROM_Init, 0 },
{ "NTBROM", Mapper68_Init, 0 },
{ "NTD-03", BMCNTD03_Init, 0 },
{ "NovelDiamond9999999in1", Novel_Init, 0 },
{ "OneBus", UNLOneBus_Init, 0 },
{ "PEC-586", UNLPEC586Init, 0 },
{ "RROM", NROM_Init, 0 },
{ "RROM-128", NROM_Init, 0 },
{ "SA-002", TCU02_Init, 0 },
{ "SA-0036", SA0036_Init, 0 },
{ "SA-0037", SA0037_Init, 0 },
{ "SA-009", SA009_Init, 0 },
{ "SA-016-1M", SA0161M_Init, 0 },
{ "SA-72007", SA72007_Init, 0 },
{ "SA-72008", SA72008_Init, 0 },
{ "SA-9602B", SA9602B_Init, BMCFLAG_32KCHRR },
{ "SA-NROM", TCA01_Init, 0 },
{ "SAROM", SAROM_Init, 0 },
{ "SBROM", SBROM_Init, 0 },
{ "SC-127", UNLSC127_Init, 0 },
{ "SCROM", SCROM_Init, 0 },
{ "SEROM", SEROM_Init, 0 },
{ "SGROM", SGROM_Init, 0 },
{ "SHERO", UNLSHeroes_Init, 0 },
{ "SKROM", SKROM_Init, 0 },
{ "SL12", UNLSL12_Init, 0 },
{ "SL1632", UNLSL1632_Init, 0 },
{ "SL1ROM", SL1ROM_Init, 0 },
{ "SLROM", SLROM_Init, 0 },
{ "SMB2J", UNLSMB2J_Init, 0 },
{ "SNROM", SNROM_Init, 0 },
{ "SOROM", SOROM_Init, 0 },
{ "SSS-NROM-256", SSSNROM_Init, 0 },
{ "SUNSOFT_UNROM", SUNSOFT_UNROM_Init, 0 }, // fix me, real pcb name, real pcb type
{ "Sachen-74LS374N", S74LS374N_Init, 0 },
{ "Sachen-74LS374NA", S74LS374NA_Init, 0 }, //seems to be custom mapper
{ "Sachen-8259A", S8259A_Init, 0 },
{ "Sachen-8259B", S8259B_Init, 0 },
{ "Sachen-8259C", S8259C_Init, 0 },
{ "Sachen-8259D", S8259D_Init, 0 },
{ "Super24in1SC03", Super24_Init, 0 },
{ "SuperHIK8in1", Mapper45_Init, 0 },
{ "Supervision16in1", Supervision16_Init, 0 },
{ "T-227-1", BMCT2271_Init, 0 },
{ "T-230", UNLT230_Init, 0 },
{ "T-262", BMCT262_Init, 0 },
{ "TBROM", TBROM_Init, 0 },
{ "TC-U01-1.5M", TCU01_Init, 0 },
{ "TEK90", Mapper90_Init, 0 },
{ "TEROM", TEROM_Init, 0 },
{ "TF1201", UNLTF1201_Init, 0 },
{ "TFROM", TFROM_Init, 0 },
{ "TGROM", TGROM_Init, 0 },
{ "TKROM", TKROM_Init, 0 },
{ "TKSROM", TKSROM_Init, 0 },
{ "TLROM", TLROM_Init, 0 },
{ "TLSROM", TLSROM_Init, 0 },
{ "TQROM", TQROM_Init, 0 },
{ "TR1ROM", TFROM_Init, BMCFLAG_FORCE4 },
{ "TSROM", TSROM_Init, 0 },
{ "TVROM", TLROM_Init, BMCFLAG_FORCE4 },
{ "Transformer", Transformer_Init, 0 },
{ "UNROM", UNROM_Init, 0 },
{ "UOROM", UNROM_Init, 0 },
{ "VRC7", UNLVRC7_Init, 0 },
{ "YOKO", UNLYOKO_Init, 0 },
{ "COOLBOY", COOLBOY_Init, BMCFLAG_256KCHRR },
{ "158B", UNL158B_Init, 0 },
{ "DRAGONFIGHTER", UNLBMW8544_Init, 0},
#ifdef COPYFAMI
{ "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 },
{ "COPYFAMI", MapperCopyFami_Init, 0 },
#endif
{ NULL, NULL, 0 }
};
static BFMAPPING bfunc[] = {
{ "CTRL", CTRL },
{ "TVCI", TVCI },
{ "BATR", EnableBattery },
{ "MIRR", DoMirroring },
{ "PRG", LoadPRG },
{ "CHR", LoadCHR },
{ "NAME", NAME },
{ "MAPR", SetBoardName },
{ "DINF", DINF },
{ NULL, NULL }
};
int LoadUNIFChunks(FCEUFILE *fp) {
int x;
int t;
for (;; ) {
t = FCEU_fread(&uchead, 1, 4, fp);
if (t < 4) {
if (t > 0)
return 0;
return 1;
}
if (!(FCEU_read32le(&uchead.info, fp)))
return 0;
t = 0;
x = 0;
while (bfunc[x].name) {
if (!memcmp(&uchead, bfunc[x].name, strlen(bfunc[x].name))) {
if (!bfunc[x].init(fp))
return 0;
t = 1;
break;
}
x++;
}
if (!t)
if (FCEU_fseek(fp, uchead.info, SEEK_CUR))
return(0);
}
}
static int InitializeBoard(void) {
int x = 0;
if (!sboardname) return(0);
while (bmap[x].name) {
if (!strcmp((char*)sboardname, (char*)bmap[x].name)) {
if (!malloced[16]) {
if (bmap[x].flags & BMCFLAG_16KCHRR)
CHRRAMSize = 16;
else if (bmap[x].flags & BMCFLAG_32KCHRR)
CHRRAMSize = 32;
else if (bmap[x].flags & BMCFLAG_128KCHRR)
CHRRAMSize = 128;
else if (bmap[x].flags & BMCFLAG_256KCHRR)
CHRRAMSize = 256;
else
CHRRAMSize = 8;
CHRRAMSize <<= 10;
if ((UNIFchrrama = (uint8*)FCEU_malloc(CHRRAMSize))) {
SetupCartCHRMapping(0, UNIFchrrama, CHRRAMSize, 1);
AddExState(UNIFchrrama, CHRRAMSize, 0, "CHRR");
} else
return(-1);
}
if (bmap[x].flags & BMCFLAG_FORCE4)
mirrortodo = 4;
MooMirroring();
bmap[x].init(&UNIFCart);
return(1);
}
x++;
}
FCEU_PrintError("Board type not supported.");
return(0);
}
static void UNIFGI(int h) {
switch (h) {
case GI_RESETM2:
if (UNIFCart.Reset)
UNIFCart.Reset();
break;
case GI_POWER:
if (UNIFCart.Power)
UNIFCart.Power();
if (UNIFchrrama) memset(UNIFchrrama, 0, 8192);
break;
case GI_CLOSE:
FCEU_SaveGameSave(&UNIFCart);
if (UNIFCart.Close)
UNIFCart.Close();
FreeUNIF();
break;
}
}
int UNIFLoad(const char *name, FCEUFILE *fp) {
FCEU_fseek(fp, 0, SEEK_SET);
FCEU_fread(&unhead, 1, 4, fp);
if (memcmp(&unhead, "UNIF", 4))
return 0;
ResetCartMapping();
ResetExState(0, 0);
ResetUNIF();
if (!FCEU_read32le(&unhead.info, fp))
goto aborto;
if (FCEU_fseek(fp, 0x20, SEEK_SET) < 0)
goto aborto;
if (!LoadUNIFChunks(fp))
goto aborto;
{
int x;
struct md5_context md5;
md5_starts(&md5);
for (x = 0; x < 32; x++)
if (malloced[x]) {
md5_update(&md5, malloced[x], mallocedsizes[x]);
}
md5_finish(&md5, UNIFCart.MD5);
FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(UNIFCart.MD5));
memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5));
}
if (!InitializeBoard())
goto aborto;
FCEU_LoadGameSave(&UNIFCart);
GameInterface = UNIFGI;
return 1;
aborto:
FreeUNIF();
ResetUNIF();
return 0;
}
int CopyFamiLoad() {
ResetCartMapping();
ResetExState(0, 0);
sboardname = "COPYFAMI";
if (!InitializeBoard())
goto aborto;
FCEU_LoadGameSave(&UNIFCart);
GameInterface = UNIFGI;
return 1;
aborto:
FreeUNIF();
ResetUNIF();
return 0;
}

View File

@ -1,109 +0,0 @@
/* 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)
{
uintptr_t m;
m = (uintptr_t)*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);
}

View File

@ -8,22 +8,22 @@
#include "cheat.c"
#include "crc32.c"
#include "debug.c"
#include "drivers/libretro/fceu/fceu-endian.c"
#include "drivers/libretro/fceu/fceu-memory.c"
#include "drivers/libretro/fceu/misc.c"
#include "drivers/libretro/fceu/fceu.c"
#include "drivers/libretro/fceu/fds.c"
#include "drivers/libretro/fceu/file.c"
#include "fceu-endian.c"
#include "fceu-memory.c"
#include "misc.c"
#include "fceu.c"
#include "fds.c"
#include "file.c"
#include "filter.c"
#include "drivers/libretro/fceu/general.c"
#include "drivers/libretro/fceu/input.c"
#include "general.c"
#include "input.c"
#include "md5.c"
#include "drivers/libretro/fceu/nsf.c"
#include "nsf.c"
#include "palette.c"
#include "ppu.c"
#include "sound.c"
#include "drivers/libretro/fceu/state.c"
#include "drivers/libretro/fceu/video.c"
#include "state.c"
#include "video.c"
#include "vsuni.c"
#endif

View File

@ -26,70 +26,98 @@
#include "fceu-types.h"
#include "fceu-endian.h"
void FlipByteOrder(uint8 *src, uint32 count) {
uint8 *start = src;
uint8 *end = src + count - 1;
void FlipByteOrder(uint8 *src, uint32 count)
{
uint8 *start = src;
uint8 *end = src + count - 1;
if ((count & 1) || !count) return; /* This shouldn't happen. */
while(start < end)
{
uint8 tmp;
while (count--) {
uint8 tmp;
tmp = *end;
*end = *start;
*start = tmp;
end--;
start++;
}
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 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 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 MSB_FIRST
*(uint32*)Bufo = ((buf & 0xFF) << 24) | ((buf & 0xFF00) << 8) | ((buf & 0xFF0000) >> 8) | ((buf & 0xFF000000) >> 24);
#else
*(uint32*)Bufo = buf;
#endif
return 1;
int read32le(uint32 *Bufo, FILE *fp)
{
uint32 buf;
if (fread(&buf, 1, 4, fp) < 4)
return 0;
#ifdef MSB_FIRST
*(uint32*)Bufo = ((buf & 0xFF) << 24) | ((buf & 0xFF00) << 8) | ((buf & 0xFF0000) >> 8) | ((buf & 0xFF000000) >> 24);
#else
*(uint32*)Bufo = buf;
#endif
return 1;
}
int read16le(char *d, FILE *fp) {
#ifdef MSB_FIRST
int ret;
ret = fread(d + 1, 1, 1, fp);
ret += fread(d, 1, 1, fp);
return ret < 2 ? 0 : 2;
#else
return((fread(d, 1, 2, fp) < 2) ? 0 : 2);
#endif
int write32le_mem(uint32 b, memstream_t *mem)
{
uint8 s[4];
s[0]=b;
s[1]=b>>8;
s[2]=b>>16;
s[3]=b>>24;
return((memstream_write(mem, s, 4)<4)?0:4);
}
void FCEU_en32lsb(uint8 *buf, uint32 morp) {
buf[0] = morp;
buf[1] = morp >> 8;
buf[2] = morp >> 16;
buf[3] = morp >> 24;
int read32le_mem(uint32 *Bufo, memstream_t *mem)
{
uint32 buf;
if(memstream_read(mem, &buf, 4)<4)
return 0;
#ifdef MSB_FIRST
*(uint32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
#else
*(uint32*)Bufo=buf;
#endif
return 1;
}
uint32 FCEU_de32lsb(uint8 *morp) {
return(morp[0] | (morp[1] << 8) | (morp[2] << 16) | (morp[3] << 24));
int read16le(char *d, FILE *fp)
{
#ifdef MSB_FIRST
int ret;
ret = fread(d + 1, 1, 1, fp);
ret += fread(d, 1, 1, fp);
return ret < 2 ? 0 : 2;
#else
return((fread(d, 1, 2, fp) < 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

@ -2,6 +2,10 @@
#define _FCEU_ENDIAN_H
#include "fceu-memory.h"
#include <memstream.h>
int write32le_mem(uint32 b, memstream_t *mem);
int read32le_mem(uint32 *Bufo, memstream_t *mem);
int write16le(uint16 b, FILE *fp);
int write32le(uint32 b, FILE *fp);

View File

@ -25,64 +25,39 @@
#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_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) {
void *ret;
ret = malloc(size);
if (!ret) {
FCEU_PrintError("Error allocating memory!");
return(0);
}
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) { // Might do something with this and FCEU_malloc later...
void FCEU_free(void *ptr)
{
free(ptr);
}
void FCEU_gfree(void *ptr) {
void FCEU_gfree(void *ptr)
{
free(ptr);
}
void FASTAPASS(3) FCEU_memmove(void *d, void *s, uint32 l) {
uint32 x;
int t;
/* Type really doesn't matter. */
t = (int)d;
t |= (int)s;
t |= (int)l;
if (t & 3) { // Not 4-byte aligned and/or length is not a multiple of 4.
uint8 *tmpd, *tmps;
tmpd = (uint8*)d;
tmps = (uint8*)s;
for (x = l; x; x--) { // This could be optimized further, though(more tests could be performed).
*tmpd = *tmps;
tmpd++;
tmps++;
}
} else {
uint32 *tmpd, *tmps;
tmpd = (uint32*)d;
tmps = (uint32*)s;
for (x = l >> 2; x; x--) {
*tmpd = *tmps;
tmpd++;
tmps++;
}
}
}

View File

@ -26,12 +26,10 @@
#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; }
#if defined(STATE_LIBRETRO) || defined(ENDIAN_LIBRETRO) || defined(GENERAL_LIBRETRO)
#include "drivers/libretro/memstream.h"
#define HAVE_MEMSTREAM
#define MEM_TYPE memstream_t
@ -42,9 +40,6 @@
#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))
#else
#define MEM_TYPE FILE
#endif
void *FCEU_malloc(uint32 size);
void *FCEU_gmalloc(uint32 size);

View File

@ -41,7 +41,6 @@
#include "cheat.h"
#include "palette.h"
#include "state.h"
#include "movie.h"
#include "video.h"
#include "input.h"
#include "file.h"
@ -62,14 +61,17 @@ static readfunc *AReadG;
static writefunc *BWriteG;
static int RWWrap = 0;
static DECLFW(BNull) {
static DECLFW(BNull)
{
}
static DECLFR(ANull) {
static DECLFR(ANull)
{
return(X.DB);
}
int AllocGenieRW(void) {
int AllocGenieRW(void)
{
if (!(AReadG = (readfunc*)FCEU_malloc(0x8000 * sizeof(readfunc))))
return 0;
if (!(BWriteG = (writefunc*)FCEU_malloc(0x8000 * sizeof(writefunc))))
@ -78,62 +80,71 @@ int AllocGenieRW(void) {
return 1;
}
void FlushGenieRW(void) {
int32 x;
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;
}
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) {
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) {
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;
}
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) {
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) {
void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func)
{
int32 x;
if (!func)
func = BNull;
if (RWWrap)
for (x = end; x >= start; x--) {
for (x = end; x >= start; x--)
{
if (x >= 0x8000)
BWriteG[x - 0x8000] = func;
else
@ -152,50 +163,58 @@ uint8 RAM[0x800];
uint8 PAL = 0;
static DECLFW(BRAML) {
static DECLFW(BRAML)
{
RAM[A] = V;
}
static DECLFR(ARAML) {
static DECLFR(ARAML)
{
return RAM[A];
}
#ifndef COPYFAMI
static DECLFW(BRAMH) {
static DECLFW(BRAMH)
{
RAM[A & 0x7FF] = V;
}
static DECLFR(ARAMH) {
static DECLFR(ARAMH)
{
return RAM[A & 0x7FF];
}
#endif
static void CloseGame(void) {
if (GameInfo) {
if (FCEUnetplay)
FCEUD_NetworkClose();
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 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) CloseGame();
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;
@ -208,79 +227,77 @@ 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;
FCEUGI *FCEUI_LoadGame(const char *name, uint8_t *databuf, size_t databufsize)
{
FCEUFILE *fp;
ResetGameLoaded();
ResetGameLoaded();
GameInfo = malloc(sizeof(FCEUGI));
memset(GameInfo, 0, sizeof(FCEUGI));
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;
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);
FCEU_printf("Loading %s...\n\n", name);
GetFileBase(name);
GetFileBase(name);
ipsfn = FCEU_MakeFName(FCEUMKF_IPS, 0, 0);
fp = FCEU_fopen(name, ipsfn, "rb", 0);
free(ipsfn);
fp = FCEU_fopen(name, NULL, "rb", 0, databuf, databufsize);
if (!fp) {
FCEU_PrintError("Error opening \"%s\"!", name);
return 0;
}
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;
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;
FCEU_PrintError("An error occurred while loading the file.");
FCEU_fclose(fp);
return 0;
endlseq:
FCEU_fclose(fp);
endlseq:
FCEU_fclose(fp);
FCEU_ResetVidSys();
if (GameInfo->type != GIT_NSF)
if (FSettings.GameGenie)
FCEU_OpenGenie();
FCEU_ResetVidSys();
if (GameInfo->type != GIT_NSF)
if (FSettings.GameGenie)
FCEU_OpenGenie();
PowerNES();
FCEUSS_CheckStates();
FCEUMOV_CheckMovies();
PowerNES();
FCEUSS_CheckStates();
if (GameInfo->type != GIT_NSF) {
FCEU_LoadGamePalette();
FCEU_LoadGameCheats(0);
}
if (GameInfo->type != GIT_NSF) {
FCEU_LoadGamePalette();
FCEU_LoadGameCheats(0);
}
FCEU_ResetPalette();
FCEU_ResetMessages(); // Save state, status messages, etc.
FCEU_ResetPalette();
FCEU_ResetMessages(); // Save state, status messages, etc.
return(GameInfo);
return(GameInfo);
}
int CopyFamiLoad(void);
FCEUGI *FCEUI_CopyFamiStart(void) {
FCEUGI *FCEUI_CopyFamiStart(void)
{
ResetGameLoaded();
GameInfo = malloc(sizeof(FCEUGI));
GameInfo = (FCEUGI*)malloc(sizeof(FCEUGI));
memset(GameInfo, 0, sizeof(FCEUGI));
GameInfo->soundchan = 0;
@ -306,7 +323,6 @@ FCEUGI *FCEUI_CopyFamiStart(void) {
PowerNES();
FCEUSS_CheckStates();
FCEUMOV_CheckMovies();
if (GameInfo->type != GIT_NSF) {
FCEU_LoadGamePalette();
@ -356,20 +372,19 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
*SoundBufSize = ssize;
}
void FCEUI_CloseGame(void) {
CloseGame();
}
void ResetNES(void) {
FCEUMOV_AddCommand(FCEUNPCMD_RESET);
if (!GameInfo) return;
void ResetNES(void)
{
if (!GameInfo)
return;
GameInterface(GI_RESETM2);
FCEUSND_Reset();
FCEUPPU_Reset();
X6502_Reset();
}
void FCEU_MemoryRand(uint8 *ptr, uint32 size) {
void FCEU_MemoryRand(uint8 *ptr, uint32 size)
{
int x = 0;
while (size) {
// *ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default
@ -386,12 +401,14 @@ void FCEU_MemoryRand(uint8 *ptr, uint32 size) {
}
}
void hand(X6502 *X, int type, uint32 A) {
void hand(X6502 *X, int type, uint32 A)
{
}
void PowerNES(void) {
FCEUMOV_AddCommand(FCEUNPCMD_POWER);
if (!GameInfo) return;
void PowerNES(void)
{
if (!GameInfo)
return;
FCEU_CheatResetRAM();
FCEU_CheatAddRAM(2, 0, RAM);
@ -426,13 +443,13 @@ void PowerNES(void) {
if (GameInfo->type == GIT_VSUNI)
FCEU_VSUniPower();
timestampbase = 0;
X6502_Power();
FCEU_PowerCheats();
}
void FCEU_ResetVidSys(void) {
void FCEU_ResetVidSys(void)
{
int w;
if (GameInfo->vidsys == GIV_NTSC)
@ -450,8 +467,8 @@ void FCEU_ResetVidSys(void) {
FCEUS FSettings;
void FCEU_printf(char *format, ...) {
FILE *ofile;
void FCEU_printf(char *format, ...)
{
char temp[2048];
va_list ap;
@ -460,14 +477,11 @@ void FCEU_printf(char *format, ...) {
vsprintf(temp, format, ap);
FCEUD_Message(temp);
ofile = fopen("stdout.txt", "ab");
fwrite(temp, 1, strlen(temp), ofile);
fclose(ofile);
va_end(ap);
}
void FCEU_PrintError(char *format, ...) {
void FCEU_PrintError(char *format, ...)
{
char temp[2048];
va_list ap;
@ -479,29 +493,37 @@ void FCEU_PrintError(char *format, ...) {
va_end(ap);
}
void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall) {
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) {
if (PAL)
{
FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
FSettings.LastSLine = FSettings.UsrLastSLine[1];
} else {
}
else
{
FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
FSettings.LastSLine = FSettings.UsrLastSLine[0];
}
}
void FCEUI_SetVidSystem(int a) {
void FCEUI_SetVidSystem(int a)
{
FSettings.PAL = a ? 1 : 0;
if (GameInfo) {
FCEU_ResetVidSys();
FCEU_ResetPalette();
}
if (!GameInfo)
return;
FCEU_ResetVidSys();
FCEU_ResetPalette();
}
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend) {
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend)
{
if (slstart)
*slstart = FSettings.FirstSLine;
if (slend)
@ -509,15 +531,18 @@ int FCEUI_GetCurrentVidSystem(int *slstart, int *slend) {
return(PAL);
}
void FCEUI_SetGameGenie(int a) {
void FCEUI_SetGameGenie(int a)
{
FSettings.GameGenie = a ? 1 : 0;
}
void FCEUI_SetSnapName(int a) {
void FCEUI_SetSnapName(int a)
{
FSettings.SnapName = a;
}
int32 FCEUI_GetDesiredFPS(void) {
int32 FCEUI_GetDesiredFPS(void)
{
if (PAL)
return(838977920); // ~50.007
else

View File

@ -614,7 +614,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
char *fn = FCEU_MakeFName(FCEUMKF_FDSROM, 0, 0);
if (!(zp = FCEUD_UTF8fopen(fn, "rb"))) {
if (!(zp = fopen(fn, "rb"))) {
FCEU_PrintError("FDS BIOS ROM image missing!");
free(fn);
return 0;
@ -669,7 +669,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
memcpy(diskdatao[x], diskdata[x], 65500);
}
if ((tp = FCEU_fopen(fn, 0, "rb", 0))) {
if ((tp = FCEU_fopen(fn, 0, "rb", 0, NULL, 0))) {
FCEU_printf("Disk was written. Auxillary FDS file open \"%s\".\n", fn);
FreeFDSMemory();
if (!SubLoad(tp)) {
@ -737,7 +737,7 @@ void FDSClose(void) {
if (!DiskWritten) return;
if (!(fp = FCEUD_UTF8fopen(fn, "wb"))) {
if (!(fp = fopen(fn, "wb"))) {
free(fn);
return;
}

View File

@ -27,9 +27,6 @@
#include <unistd.h>
#endif
#include "zlib.h"
#include "unzip.h"
#include "fceu-types.h"
#include "file.h"
#include "fceu-endian.h"
@ -37,451 +34,152 @@
#include "driver.h"
#include "general.h"
typedef struct {
uint8 *data;
uint32 size;
uint32 location;
} MEMWRAP;
void ApplyIPS(FILE *ips, MEMWRAP *dest) {
uint8 header[5];
uint32 count = 0;
FCEU_printf(" Applying IPS...\n");
if (fread(header, 1, 5, ips) != 5) {
fclose(ips);
return;
}
if (memcmp(header, "PATCH", 5)) {
fclose(ips);
return;
}
while (fread(header, 1, 3, ips) == 3) {
uint32 offset = (header[0] << 16) | (header[1] << 8) | header[2];
uint16 size;
if (!memcmp(header, "EOF", 3)) {
FCEU_printf(" IPS EOF: Did %d patches\n\n", count);
fclose(ips);
return;
}
size = fgetc(ips) << 8;
size |= fgetc(ips);
if (!size) { /* RLE */
uint8 *start;
uint8 b;
size = fgetc(ips) << 8;
size |= fgetc(ips);
//FCEU_printf(" Offset: %8d Size: %5d RLE\n",offset,size);
if ((offset + size) > dest->size) {
uint8 *tmp;
// Probably a little slow.
tmp = (uint8*)realloc(dest->data, offset + size);
if (!tmp) {
FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n", count);
fclose(ips);
return;
}
dest->size = offset + size;
dest->data = tmp;
memset(dest->data + dest->size, 0, offset + size - dest->size);
}
b = fgetc(ips);
start = dest->data + offset;
do {
*start = b;
start++;
} while (--size);
} else { /* Normal patch */
//FCEU_printf(" Offset: %8d Size: %5d\n",offset,size);
if ((offset + size) > dest->size) {
uint8 *tmp;
// Probably a little slow.
tmp = (uint8*)realloc(dest->data, offset + size);
if (!tmp) {
FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n", count);
fclose(ips);
return;
}
dest->data = tmp;
memset(dest->data + dest->size, 0, offset + size - dest->size);
}
fread(dest->data + offset, 1, size, ips);
}
count++;
}
fclose(ips);
FCEU_printf(" Hard IPS end!\n");
}
static MEMWRAP *MakeMemWrap(void *tz, int type) {
MEMWRAP *tmp;
if (!(tmp = (MEMWRAP*)FCEU_malloc(sizeof(MEMWRAP))))
goto doret;
tmp->location = 0;
if (type == 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);
}
else if (type == 1) {
/* Bleck. The gzip file format has the size of the uncompressed data,
but I can't get to the info with the zlib interface(?). */
for (tmp->size = 0; gzgetc(tz) != EOF; tmp->size++) ;
gzseek(tz, 0, SEEK_SET);
if (!(tmp->data = (uint8*)FCEU_malloc(tmp->size))) {
free(tmp);
tmp = 0;
goto doret;
}
gzread(tz, tmp->data, tmp->size);
} else if (type == 2) {
unz_file_info ufo;
unzGetCurrentFileInfo(tz, &ufo, 0, 0, 0, 0, 0, 0);
tmp->size = ufo.uncompressed_size;
if (!(tmp->data = (uint8*)FCEU_malloc(ufo.uncompressed_size))) {
free(tmp);
tmp = 0;
goto doret;
}
unzReadCurrentFile(tz, tmp->data, ufo.uncompressed_size);
}
doret:
if (type == 0) {
fclose((FILE*)tz);
}
else if (type == 1) {
gzclose(tz);
} else if (type == 2) {
unzCloseCurrentFile(tz);
unzClose(tz);
}
return tmp;
}
#ifndef __GNUC__
#define strcasecmp strcmp
#endif
static MEMWRAP *MakeMemWrap(void *tz, int type)
{
MEMWRAP *tmp;
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext) {
FILE *ipsfile = 0;
FCEUFILE *fceufp;
void *t;
if (!(tmp = (MEMWRAP*)FCEU_malloc(sizeof(MEMWRAP))))
goto doret;
tmp->location = 0;
if (strchr(mode, 'r'))
ipsfile = FCEUD_UTF8fopen(ipsfn, "rb");
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);
fceufp = (FCEUFILE*)malloc(sizeof(FCEUFILE));
{
unzFile tz;
if ((tz = unzOpen(path))) { // If it's not a zip file, use regular file handlers.
// Assuming file type by extension usually works,
// but I don't like it. :)
if (unzGoToFirstFile(tz) == UNZ_OK) {
for (;; ) {
char tempu[512];// Longer filenames might be possible, but I don't
// think people would name files that long in zip files...
unzGetCurrentFileInfo(tz, 0, tempu, 512, 0, 0, 0, 0);
tempu[511] = 0;
if (strlen(tempu) >= 4) {
char *za = tempu + strlen(tempu) - 4;
if (!ext) {
if (!strcasecmp(za, ".nes") || !strcasecmp(za, ".fds") ||
!strcasecmp(za, ".nsf") || !strcasecmp(za, ".unf") ||
!strcasecmp(za, ".nez"))
break;
} else if (!strcasecmp(za, ext))
break;
}
if (strlen(tempu) >= 5) {
if (!strcasecmp(tempu + strlen(tempu) - 5, ".unif"))
break;
}
if (unzGoToNextFile(tz) != UNZ_OK) {
if (unzGoToFirstFile(tz) != UNZ_OK) goto zpfail;
break;
}
}
if (unzOpenCurrentFile(tz) != UNZ_OK)
goto zpfail;
} else {
zpfail:
free(fceufp);
unzClose(tz);
return 0;
}
if (!(fceufp->fp = MakeMemWrap(tz, 2))) {
free(fceufp);
return(0);
}
fceufp->type = 2;
if (ipsfile)
ApplyIPS(ipsfile, (MEMWRAP*)fceufp->fp);
return(fceufp);
}
}
if ((t = FCEUD_UTF8fopen(path, "rb"))) {
uint32 magic;
magic = fgetc((FILE*)t);
magic |= fgetc((FILE*)t) << 8;
magic |= fgetc((FILE*)t) << 16;
if (magic != 0x088b1f) /* Not gzip... */
fclose((FILE*)t);
else { /* Probably gzip */
int fd;
fd = dup(fileno((FILE*)t));
fclose(t);
lseek(fd, 0, SEEK_SET);
if ((t = gzdopen(fd, mode))) {
fceufp->type = 1;
fceufp->fp = t;
if (ipsfile) {
fceufp->fp = MakeMemWrap(t, 1);
gzclose(t);
if (fceufp->fp) {
free(fceufp);
return(0);
}
fceufp->type = 3;
ApplyIPS(ipsfile, (MEMWRAP*)fceufp->fp);
}
return(fceufp);
}
close(fd);
}
}
if ((t = FCEUD_UTF8fopen(path, mode))) {
fseek((FILE*)t, 0, SEEK_SET);
fceufp->type = 0;
fceufp->fp = t;
if (ipsfile) {
if (!(fceufp->fp = MakeMemWrap(t, 0))) {
free(fceufp);
return(0);
}
fceufp->type = 3;
ApplyIPS(ipsfile, (MEMWRAP*)fceufp->fp);
}
return(fceufp);
}
free(fceufp);
return 0;
doret:
if (type == 0)
fclose((FILE*)tz);
return tmp;
}
int FCEU_fclose(FCEUFILE *fp) {
if (fp->type == 1) {
gzclose(fp->fp);
} else if (fp->type >= 2) {
free(((MEMWRAP*)(fp->fp))->data);
((MEMWRAP*)(fp->fp))->data = 0;
free(fp->fp);
fp->fp = 0;
} else
{
fclose((FILE*)fp->fp);
}
static MEMWRAP *MakeMemWrapBuffer(void *tz, int type, uint8 *buffer, size_t bufsize)
{
MEMWRAP *tmp = (MEMWRAP*)FCEU_malloc(sizeof(MEMWRAP));
if (!tmp)
return NULL;
tmp->location = 0;
tmp->size = bufsize;
tmp->data = buffer;
return tmp;
}
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn,
char *mode, char *ext, uint8 *buffer, size_t bufsize)
{
FCEUFILE *fceufp = (FCEUFILE*)malloc(sizeof(FCEUFILE));
void *t = fopen(path, mode);
if (!t)
{
free(fceufp);
return 0;
}
fseek((FILE*)t, 0, SEEK_SET);
fceufp->type = 0;
if (buffer)
fceufp->fp = MakeMemWrapBuffer(t, 0, buffer, bufsize);
else
fceufp->fp = MakeMemWrap(t, 0);
return fceufp;
}
int FCEU_fclose(FCEUFILE *fp)
{
if (fp->fp)
free(fp->fp);
fp->fp = NULL;
free(fp);
fp = 0;
return 1;
}
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) {
if (fp->type == 1) {
return gzread(fp->fp, ptr, size * nmemb);
} else if (fp->type >= 2) {
MEMWRAP *wz;
uint32 total = size * nmemb;
uint64 FCEU_fread(void *ptr, size_t element_size, size_t nmemb, FCEUFILE *fp)
{
uint32_t total = nmemb * element_size;
wz = (MEMWRAP*)fp->fp;
if (wz->location >= wz->size) return 0;
if (fp->fp->location >= fp->fp->size)
return 0;
if ((wz->location + total) > wz->size) {
int ak = wz->size - wz->location;
memcpy((uint8*)ptr, wz->data + wz->location, ak);
wz->location = wz->size;
return(ak / size);
} else {
memcpy((uint8*)ptr, wz->data + wz->location, total);
wz->location += total;
return nmemb;
}
} else
{
return fread(ptr, size, nmemb, (FILE*)fp->fp);
}
if((fp->fp->location + total) > fp->fp->size)
{
int64_t ak = fp->fp->size - fp->fp->location;
memcpy((uint8_t*)ptr, fp->fp->data + fp->fp->location, ak);
fp->fp->location = fp->fp->size;
return (ak / element_size);
}
memcpy((uint8_t*)ptr, fp->fp->data + fp->fp->location, total);
fp->fp->location += total;
return nmemb;
}
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) {
if (fp->type == 1) {
return gzwrite(fp->fp, ptr, size * nmemb);
} else if (fp->type >= 2) {
return 0;
} else
return fwrite(ptr, size, nmemb, (FILE*)fp->fp);
}
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
{
switch (whence)
{
case SEEK_SET:
if (offset >= fp->fp->size)
return -1;
int FCEU_fseek(FCEUFILE *fp, long offset, int whence) {
if (fp->type == 1) {
return((gzseek(fp->fp, offset, whence) > 0) ? 0 : -1);
} else if (fp->type >= 2) {
MEMWRAP *wz;
wz = (MEMWRAP*)fp->fp;
fp->fp->location = offset;
break;
case SEEK_CUR:
if ((offset + fp->fp->location) > fp->fp->size)
return -1;
switch (whence) {
case SEEK_SET: if (offset >= wz->size)
return(-1);
wz->location = offset; break;
case SEEK_CUR: if (offset + wz->location > wz->size)
return(-1);
wz->location += offset;
break;
}
return 0;
} else
return fseek((FILE*)fp->fp, offset, whence);
}
fp->fp->location += offset;
break;
}
uint64 FCEU_ftell(FCEUFILE *fp) {
if (fp->type == 1) {
return gztell(fp->fp);
} else if (fp->type >= 2) {
return(((MEMWRAP*)(fp->fp))->location);
} else
return ftell((FILE*)fp->fp);
}
void FCEU_rewind(FCEUFILE *fp) {
if (fp->type == 1) {
gzrewind(fp->fp);
} else if (fp->type >= 2) {
((MEMWRAP*)(fp->fp))->location = 0;
} else
/* Rewind */
fseek(fp->fp, 0, SEEK_SET);
}
int FCEU_read16le(uint16 *val, FCEUFILE *fp) {
uint8 t[2];
if (fp->type >= 1) {
if (fp->type >= 2) {
MEMWRAP *wz;
wz = (MEMWRAP*)fp->fp;
if (wz->location + 2 > wz->size) {
return 0;
}
*(uint32*)t = *(uint32*)(wz->data + wz->location);
wz->location += 2;
} else if (fp->type == 1)
if (gzread(fp->fp, &t, 2) != 2) return(0);
return(1);
} else
{
if (fread(t, 1, 2, (FILE*)fp->fp) != 2) return(0);
}
*val = t[0] | (t[1] << 8);
return(1);
return 0;
}
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
{
if (fp->type >= 1) {
uint8 t[4];
#ifdef MSB_FIRST
uint8 x[4];
#endif
if (fp->type >= 2) {
MEMWRAP *wz;
wz = (MEMWRAP*)fp->fp;
if (wz->location + 4 > wz->size) {
return 0;
}
*(uint32*)t = *(uint32*)(wz->data + wz->location);
wz->location += 4;
} else if (fp->type == 1)
gzread(fp->fp, &t, 4);
#ifdef MSB_FIRST
x[0] = t[3];
x[1] = t[2];
x[2] = t[1];
x[3] = t[0];
*(uint32*)Bufo = *(uint32*)x;
#else
*(uint32*)Bufo = *(uint32*)t;
#endif
return 1;
} else
{
return read32le(Bufo, (FILE*)fp->fp);
}
if ((fp->fp->location + 4) > fp->fp->size)
return 0;
*Bufo = FCEU_de32lsb(fp->fp->data + fp->fp->location);
fp->fp->location += 4;
return 1;
}
int FCEU_fgetc(FCEUFILE *fp) {
if (fp->type == 1)
return gzgetc(fp->fp);
else if (fp->type >= 2) {
MEMWRAP *wz;
wz = (MEMWRAP*)fp->fp;
if (wz->location < wz->size)
return wz->data[wz->location++];
return EOF;
} else
return fgetc((FILE*)fp->fp);
int FCEU_fgetc(FCEUFILE *fp)
{
if (fp->fp->location < fp->fp->size)
return fp->fp->data[fp->fp->location++];
return EOF;
}
uint64 FCEU_fgetsize(FCEUFILE *fp) {
if (fp->type == 1) {
int x, t;
t = gztell(fp->fp);
gzrewind(fp->fp);
for (x = 0; gzgetc(fp->fp) != EOF; x++) ;
gzseek(fp->fp, t, SEEK_SET);
return(x);
} else if (fp->type >= 2)
return ((MEMWRAP*)(fp->fp))->size;
else
{
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;
}
uint64 FCEU_ftell(FCEUFILE *fp)
{
return fp->fp->location;
}
int FCEU_fisarchive(FCEUFILE *fp) {
if (fp->type == 2)
return 1;
return 0;
uint64 FCEU_fgetsize(FCEUFILE *fp)
{
return fp->fp->size;
}

View File

@ -36,7 +36,6 @@
#include "general.h"
#include "state.h"
#include "movie.h"
#include "driver.h"
@ -48,22 +47,24 @@ static char FileExt[2048]; /* Includes the . character, as in ".nes" */
static char FileBaseDirectory[2048];
void FCEUI_SetBaseDirectory(char *dir) {
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) {
void FCEUI_SetDirOverride(int which, char *n)
{
odirs[which] = n;
if (GameInfo) { /* Rebuild cache of present states/movies. */
if (which == FCEUIOD_STATE)
FCEUSS_CheckStates();
else if (which == FCEUIOD_MOVIE)
FCEUMOV_CheckMovies();
}
/* Rebuild cache of present states/movies. */
if (GameInfo)
{
if (which == FCEUIOD_STATE)
FCEUSS_CheckStates();
}
}
#ifndef HAVE_ASPRINTF
@ -80,136 +81,82 @@ static int asprintf(char **strp, const char *fmt, ...) {
}
#endif
char *FCEU_MakeFName(int type, int id1, char *cd1) {
char *ret = 0;
struct stat tmpstat;
char *FCEU_MakeFName(int type, int id1, char *cd1)
{
char *ret = 0;
struct stat tmpstat;
switch (type) {
case FCEUMKF_NPTEMP: asprintf(&ret, "%s"PSS "m590plqd94fo.tmp", BaseDirectory); break;
case FCEUMKF_MOVIE:
if (odirs[FCEUIOD_STATE])
asprintf(&ret, "%s"PSS "%s.%d.fcm", odirs[FCEUIOD_STATE], FileBase, id1);
else
asprintf(&ret, "%s"PSS "fcs"PSS "%s.%d.fcm", BaseDirectory, FileBase, id1);
if (stat(ret, &tmpstat) == -1) {
if (odirs[FCEUIOD_STATE])
asprintf(&ret, "%s"PSS "%s.%s.%d.fcm", odirs[FCEUIOD_STATE], FileBase, md5_asciistr(GameInfo->MD5), id1);
else
asprintf(&ret, "%s"PSS "fcs"PSS "%s.%s.%d.fcm", BaseDirectory, FileBase, md5_asciistr(GameInfo->MD5), id1);
}
break;
case FCEUMKF_STATE:
if (odirs[FCEUIOD_STATE])
asprintf(&ret, "%s"PSS "%s.fc%d", odirs[FCEUIOD_STATE], FileBase, id1);
else
asprintf(&ret, "%s"PSS "fcs"PSS "%s.fc%d", BaseDirectory, FileBase, id1);
if (stat(ret, &tmpstat) == -1) {
// if(odirs[FCEUIOD_STATE])
// asprintf(&ret,"%s"PSS"%s.%s.fc%d",odirs[FCEUIOD_STATE],FileBase,md5_asciistr(GameInfo->MD5),id1);
// else
// asprintf(&ret,"%s"PSS"fcs"PSS"%s.%s.fc%d",BaseDirectory,FileBase,md5_asciistr(GameInfo->MD5),id1);
if (odirs[FCEUIOD_STATE])
asprintf(&ret, "%s"PSS "%s.fc%d", odirs[FCEUIOD_STATE], FileBase, id1);
else
asprintf(&ret, "%s"PSS "fcs"PSS "%s.fc%d", BaseDirectory, FileBase, id1);
}
break;
case FCEUMKF_SNAP:
if (FSettings.SnapName) {
if (odirs[FCEUIOD_SNAPS])
asprintf(&ret, "%s"PSS "%s-%d.%s", odirs[FCEUIOD_SNAPS], FileBase, id1, cd1);
else
asprintf(&ret, "%s"PSS "snaps"PSS "%s-%d.%s", BaseDirectory, FileBase, id1, cd1);
} else {
if (odirs[FCEUIOD_SNAPS])
asprintf(&ret, "%s"PSS "%d.%s", odirs[FCEUIOD_SNAPS], id1, cd1);
else
asprintf(&ret, "%s"PSS "snaps"PSS "%d.%s", BaseDirectory, id1, cd1);
}
break;
case FCEUMKF_FDS:
if (odirs[FCEUIOD_NV])
asprintf(&ret, "%s"PSS "%s.%s.fds", odirs[FCEUIOD_NV], FileBase, md5_asciistr(GameInfo->MD5));
else
asprintf(&ret, "%s"PSS "sav"PSS "%s.%s.fds", BaseDirectory, FileBase, md5_asciistr(GameInfo->MD5));
break;
case FCEUMKF_SAV:
if (odirs[FCEUIOD_NV])
asprintf(&ret, "%s"PSS "%s.%s", odirs[FCEUIOD_NV], FileBase, cd1);
else
asprintf(&ret, "%s"PSS "sav"PSS "%s.%s", BaseDirectory, FileBase, cd1);
if (stat(ret, &tmpstat) == -1) {
if (odirs[FCEUIOD_NV])
asprintf(&ret, "%s"PSS "%s.%s.%s", odirs[FCEUIOD_NV], FileBase, md5_asciistr(GameInfo->MD5), cd1);
else
asprintf(&ret, "%s"PSS "sav"PSS "%s.%s.%s", BaseDirectory, FileBase, md5_asciistr(GameInfo->MD5), cd1);
}
break;
case FCEUMKF_CHEAT:
if (odirs[FCEUIOD_CHEATS])
asprintf(&ret, "%s"PSS "%s.cht", odirs[FCEUIOD_CHEATS], FileBase);
else
asprintf(&ret, "%s"PSS "cheats"PSS "%s.cht", BaseDirectory, FileBase);
break;
case FCEUMKF_IPS: asprintf(&ret, "%s"PSS "%s%s.ips", FileBaseDirectory, FileBase, FileExt);
break;
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);
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;
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 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;
}
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;
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;
for (x = 31; x >= 0; x--)
if (n & (1 << x))
{
if ((1 << x) != n)
return(1 << (x + 1));
break;
}
return n;
}

View File

@ -48,7 +48,7 @@ uint8 *VROM = NULL;
uint8 *ExtraNTARAM = NULL;
iNES_HEADER head;
static CartInfo iNESCart;
CartInfo iNESCart;
uint8 Mirroring = 0;
uint32 ROM_size = 0;

View File

@ -25,8 +25,6 @@
#include "fceu.h"
#include "netplay.h"
#include "movie.h"
#include "input.h"
#include "vsuni.h"
#include "fds.h"
@ -70,127 +68,8 @@ static INPUTCFC *FCExp = 0;
void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
/*
#define DI 01
#define CLK 02
#define CS 04
#define OUT0 01
#define D3 01
#define D4 02
typedef struct {
uint8 state;
uint8 cmd;
uint8 addr;
uint8 iswritable;
uint16 acc;
uint16 data[128];
} EEPROM;
EEPROM serialROM[2];
uint8 oldCLK, bankFlip, DIFlip, OUT0state;
uint8 serialROMautomat(uint8 chip, uint16 data) {
uint8 resp = 1;
chip &= 1;
if (!(data & CS)) {
if (!(data & CLK)) {
uint8 state = serialROM[chip].state;
uint8 mask, i;
FCEU_printf("> state = %02x\n", serialROM[chip].state);
switch (serialROM[chip].cmd) {
case 0x00:
mask = ~(1 << (state & 7));
if (state < 8) {
serialROM[chip].addr &= mask;
serialROM[chip].addr |= ((data & 1) << (state & 7));
if (state == 7)
FCEU_printf("> addr = %02x\n", serialROM[chip].addr);
} else if (state < 15) {
serialROM[chip].acc &= mask;
serialROM[chip].acc |= ((data & 1) << (state & 7));
} else {
serialROM[chip].acc &= mask;
serialROM[chip].acc |= ((data & 1) << (state & 7));
serialROM[chip].cmd = serialROM[chip].acc;
FCEU_printf("> cmd = %02x\n", serialROM[chip].cmd);
}
break;
case 0x01:
if (state < 30)
resp = (serialROM[chip].data[serialROM[chip].addr] >> (state & 15)) & 1;
else {
resp = (serialROM[chip].data[serialROM[chip].addr] >> (state & 15)) & 1;
serialROM[chip].cmd = 0;
}
break;
case 0x06:
mask = ~(1 << (state & 15));
if (state < 30) {
serialROM[chip].acc &= mask;
serialROM[chip].acc |= ((data & 1) << (state & 15));
} else {
serialROM[chip].acc &= mask;
serialROM[chip].acc |= ((data & 1) << (state & 15));
if (serialROM[chip].iswritable)
serialROM[chip].data[serialROM[chip].addr] = serialROM[chip].acc;
serialROM[chip].cmd = 0;
}
break;
case 0x0C:
for (i = 0; i < 128; i++)
serialROM[chip].data[i] = 0xFFFF;
serialROM[chip].cmd = 0;
resp = 1;
break;
case 0x0D:
serialROM[chip].cmd = 0;
resp = 1;
break;
case 0x09:
serialROM[chip].cmd = 0;
serialROM[chip].iswritable = 1;
break;
case 0x0B:
serialROM[chip].cmd = 0;
serialROM[chip].iswritable = 0;
break;
default:
serialROM[chip].cmd = 0;
serialROM[chip].state = 0;
break;
}
} else {
if (serialROM[chip].cmd == 0) {
if (serialROM[chip].state > 15)
serialROM[chip].state = 0;
} else
serialROM[chip].state++;
}
} else {
serialROM[chip].cmd = 0;
serialROM[chip].state = 0;
}
return resp;
}
uint8 serialROMstate(uint8 linestate) {
uint8 answ = 0, newCLK = linestate & CLK;
if ((!oldCLK) && newCLK) {
DIFlip ^= 1;
if (linestate && OUT0) {
serialROMautomat(bankFlip, 04 + DIFlip);
bankFlip ^= 1;
serialROMautomat(bankFlip, 02 + DIFlip);
}
}
answ = DIFlip ^ 1;
answ |= (serialROMautomat(bankFlip, newCLK + DIFlip) << 1);
oldCLK = newCLK;
return answ << 3;
}*/
static DECLFR(JPRead) {
static DECLFR(JPRead)
{
uint8 ret = 0;
if (JPorts[A & 1]->Read)
@ -202,21 +81,11 @@ static DECLFR(JPRead) {
ret |= X.DB & 0xC0;
// if(A==0x4017)
//{
// ret |= serialROMstate(OUT0);
// serialROMstate(OUT0|CLK);
// FCEU_printf("> 4017 read %02x\n",ret);
// }
return(ret);
}
static DECLFW(B4016) {
// OUT0state = V;
// serialROMstate(OUT0state|CLK);
// FCEU_printf("> 4016 write %02x\n",V);
static DECLFW(B4016)
{
if (FCExp)
if (FCExp->Write)
FCExp->Write(V & 7);
@ -226,208 +95,284 @@ static DECLFW(B4016) {
if (JPorts[1]->Write)
JPorts[1]->Write(V & 1);
if ((LastStrobe & 1) && (!(V & 1))) {
// FCEUD_UpdateInput();
if (JPorts[0]->Strobe)
JPorts[0]->Strobe(0);
if (JPorts[1]->Strobe)
JPorts[1]->Strobe(1);
if (FCExp)
if (FCExp->Strobe)
FCExp->Strobe();
}
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_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;
void FCEU_UpdateInput(void)
{
int x;
for (x = 0; x < 2; x++) {
if (JPorts[x]->Update)
JPorts[x]->Update(x, InputDataPtr[x], JPAttrib[x]);
}
if (FCExp)
if (FCExp->Update)
FCExp->Update(InputDataPtrFC, JPAttribFC);
for (x = 0; x < 2; x++)
{
if (JPorts[x] && JPorts[x]->Update)
JPorts[x]->Update(x, InputDataPtr[x], JPAttrib[x]);
}
if (GameInfo->type == GIT_VSUNI)
if (coinon) coinon--;
if (FCExp && FCExp->Update)
FCExp->Update(InputDataPtrFC, JPAttribFC);
if (GameInfo && GameInfo->type == GIT_VSUNI)
if (coinon) coinon--;
}
static DECLFR(VSUNIRead0) {
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[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]->Read)
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]->SLHook)
JPorts[x]->SLHook(x, bg, spr, linets, final);
if (FCExp)
if (FCExp->SLHook)
FCExp->SLHook(bg, spr, linets, final);
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]->SLHook || JPorts[1]->SLHook)
InputScanlineHook = SLHLHook;
if (FCExp)
if (FCExp->SLHook)
InputScanlineHook = SLHLHook;
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;
}
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;
}
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->type == GIT_VSUNI) {
SetReadHandler(0x4016, 0x4016, VSUNIRead0);
SetReadHandler(0x4017, 0x4017, VSUNIRead1);
} else
SetReadHandler(0x4016, 0x4017, JPRead);
void InitializeInput(void)
{
LastStrobe = 0;
SetWriteHandler(0x4016, 0x4016, B4016);
if (GameInfo && GameInfo->type == GIT_VSUNI)
{
SetReadHandler(0x4016, 0x4016, VSUNIRead0);
SetReadHandler(0x4017, 0x4017, VSUNIRead1);
}
else
SetReadHandler(0x4016, 0x4017, JPRead);
SetInputStuff(0);
SetInputStuff(1);
SetInputStuffFC();
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_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) {
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_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) {
#ifdef NETWORK
if (FCEUnetplay)
FCEUNET_SendCommand(cmd, 0);
else
#endif
{
if (!FCEUMOV_IsPlaying())
FCEU_DoSimpleCommand(cmd);
else
FCEUMOV_AddCommand(cmd);
}
void FCEU_QSimpleCommand(int cmd)
{
FCEU_DoSimpleCommand(cmd);
}
void FCEUI_FDSSelect(void) {
void FCEUI_FDSSelect(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_FDSSELECT);
}
int FCEUI_FDSInsert(int oride) {
int FCEUI_FDSInsert(int oride)
{
FCEU_QSimpleCommand(FCEUNPCMD_FDSINSERT);
return(1);
}
int FCEUI_FDSEject(void) {
int FCEUI_FDSEject(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_FDSEJECT);
return(1);
}
void FCEUI_VSUniToggleDIP(int w) {
void FCEUI_VSUniToggleDIP(int w)
{
FCEU_QSimpleCommand(FCEUNPCMD_VSUNIDIP0 + w);
}
void FCEUI_VSUniCoin(void) {
void FCEUI_VSUniCoin(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN);
}
void FCEUI_ResetNES(void) {
void FCEUI_ResetNES(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_RESET);
}
void FCEUI_PowerNES(void) {
void FCEUI_PowerNES(void)
{
FCEU_QSimpleCommand(FCEUNPCMD_POWER);
}

View File

@ -18,9 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* TODO: Add (better) file io error checking */
/* TODO: Change save state file format. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -48,15 +45,12 @@ static void (*SPreSave)(void);
static void (*SPostSave)(void);
static int SaveStateStatus[10];
static int StateShow;
static SFORMAT SFMDATA[64];
static int SFEXINDEX;
#define RLSB FCEUSTATE_RLSB //0x80000000
extern SFORMAT FCEUPPU_STATEINFO[];
extern SFORMAT FCEUSND_STATEINFO[];
extern SFORMAT FCEUCTRL_STATEINFO[];
@ -87,281 +81,274 @@ SFORMAT SFCPUC[] = {
{ 0 }
};
static int SubWrite(MEM_TYPE *st, SFORMAT *sf) {
uint32 acc = 0;
static int SubWrite(memstream_t *mem, SFORMAT *sf)
{
uint32 acc=0;
while (sf->v) {
if (sf->s == ~0) { // Link to another struct.
uint32 tmp;
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;
}
if(!(tmp=SubWrite(mem, (SFORMAT *)sf->v)))
return(0);
acc+=tmp;
sf++;
continue;
}
acc += 8; // Description + size
acc += sf->s & (~RLSB);
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);
if(mem) /* Are we writing or calculating the size of this block? */
{
memstream_write(mem, sf->desc, 4);
write32le_mem(sf->s&(~RLSB), mem);
#ifdef MSB_FIRST
if (sf->s & RLSB)
FlipByteOrder(sf->v, sf->s & (~RLSB));
#endif
#ifdef MSB_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. */
#ifdef MSB_FIRST
if (sf->s & RLSB)
FlipByteOrder(sf->v, sf->s & (~RLSB));
#endif
}
sf++;
}
memstream_write(mem, (uint8 *)sf->v, sf->s&(~RLSB));
/* Now restore the original byte order. */
#ifdef MSB_FIRST
if(sf->s&RLSB)
FlipByteOrder(sf->v,sf->s&(~RLSB));
#endif
}
sf++;
}
return(acc);
return acc;
}
static int WriteStateChunk(MEM_TYPE *st, int type, SFORMAT *sf) {
int bsize;
static int WriteStateChunk(memstream_t *mem, int type, SFORMAT *sf)
{
int bsize;
fputc(type, st);
memstream_putc(mem, type);
bsize = SubWrite(0, sf);
write32le(bsize, st);
bsize = SubWrite(0,sf);
write32le_mem(bsize, mem);
if (!SubWrite(st, sf)) return(0);
return(bsize + 5);
if (!SubWrite(mem, 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 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);
static int ReadStateChunk(memstream_t *mem, SFORMAT *sf, int size)
{
SFORMAT *tmp;
int temp;
temp=memstream_pos(mem);
while (ftell(st) < temp + size) {
uint32 tsize;
char toa[4];
if (fread(toa, 1, 4, st) <= 0)
return 0;
while(memstream_pos(mem)<temp+size)
{
uint32 tsize;
char toa[4];
if(memstream_read(mem, toa, 4)<=0)
return 0;
read32le(&tsize, st);
read32le_mem(&tsize,mem);
if ((tmp = CheckS(sf, tsize, toa))) {
fread((uint8*)tmp->v, 1, tmp->s & (~RLSB), st);
if((tmp=CheckS(sf,tsize,toa)))
{
memstream_read(mem, (uint8 *)tmp->v, tmp->s&(~RLSB));
#ifdef MSB_FIRST
if (tmp->s & RLSB)
FlipByteOrder(tmp->v, tmp->s & (~RLSB));
#endif
} else
fseek(st, tsize, SEEK_CUR);
} // while(...)
return 1;
#ifdef MSB_FIRST
if(tmp->s&RLSB)
FlipByteOrder(tmp->v,tmp->s&(~RLSB));
#endif
}
else
memstream_seek(mem,tsize,SEEK_CUR);
}
return 1;
}
static int ReadStateChunks(MEM_TYPE *st, int32 totalsize) {
int t;
uint32 size;
int ret = 1;
static int ReadStateChunks(memstream_t *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;
while (totalsize > 0)
{
t = memstream_getc(st);
if (t == EOF)
break;
if (!read32le_mem(&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;
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 (memstream_seek(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 };
void FCEUSS_Save_Mem(void)
{
memstream_t *mem = memstream_open(1);
header[0] = 'F';
header[1] = 'C';
header[2] = 'S';
header[3] = 0xFF;
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();
FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC);
memstream_write(mem, header, 16);
fseek(st, 4, SEEK_SET);
write32le(totalsize, st);
return(1);
FCEUPPU_SaveState();
totalsize = WriteStateChunk(mem, 1, SFCPU);
totalsize += WriteStateChunk(mem, 2, SFCPUC);
totalsize += WriteStateChunk(mem, 3, FCEUPPU_STATEINFO);
totalsize += WriteStateChunk(mem, 4, FCEUCTRL_STATEINFO);
totalsize += WriteStateChunk(mem, 5, FCEUSND_STATEINFO);
if (SPreSave)
SPreSave();
totalsize += WriteStateChunk(mem, 0x10, SFMDATA);
if (SPreSave)
SPostSave();
memstream_seek(mem, 4, SEEK_SET);
write32le_mem(totalsize, mem);
memstream_close(mem);
}
void FCEUSS_Save(char *fname) {
MEM_TYPE *st = NULL;
char *fn;
void FCEUSS_Load_Mem(void)
{
memstream_t *mem = memstream_open(0);
if (geniestage == 1) {
FCEU_DispMessage("Cannot save FCS in GG screen.");
return;
}
uint8 header[16];
int stateversion;
int x;
memstream_read(mem, header, 16);
if (fname)
st = FCEUD_UTF8fopen(fname, "wb");
else {
st = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_STATE, CurrentState, 0), "wb");
free(fn);
}
if (memcmp(header,"FCS",3) != 0)
return;
if (st == NULL) {
FCEU_DispMessage("State %d save error.", CurrentState);
return;
}
if (header[3] == 0xFF)
stateversion = FCEU_de32lsb(header + 8);
else
stateversion = header[3] * 100;
FCEUSS_SaveFP(st);
x = ReadStateChunks(mem, *(uint32*)(header + 4));
SaveStateStatus[CurrentState] = 1;
fclose(st);
FCEU_DispMessage("State %d saved.", CurrentState);
if (stateversion < 9500)
X.IRQlow=0;
if (GameStateRestore)
GameStateRestore(stateversion);
if (x)
{
FCEUPPU_LoadState(stateversion);
FCEUSND_LoadState(stateversion);
}
memstream_close(mem);
}
int FCEUSS_LoadFP(MEM_TYPE *st) {
int x;
uint8 header[16];
int stateversion;
void FCEUSS_CheckStates(void)
{
MEM_TYPE *st = NULL;
char *fn;
int ssel;
fread(&header, 1, 16, st);
if (memcmp(header, "FCS", 3))
return(0);
for (ssel = 0; ssel < 10; ssel++)
{
st = fopen(fn = FCEU_MakeFName(FCEUMKF_STATE, ssel, 0), "rb");
free(fn);
if (st)
{
SaveStateStatus[ssel] = 1;
fclose(st);
}
else
SaveStateStatus[ssel] = 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);
CurrentState = 0;
}
int FCEUSS_Load(char *fname) {
MEM_TYPE *st;
char *fn;
if (geniestage == 1) {
FCEU_DispMessage("Cannot load FCS in GG screen.");
return(0);
}
if (fname)
st = FCEUD_UTF8fopen(fname, "rb");
else {
st = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_STATE, CurrentState, fname), "rb");
free(fn);
}
if (st == NULL) {
FCEU_DispMessage("State %d load error.", CurrentState);
SaveStateStatus[CurrentState] = 0;
return(0);
}
if (FCEUSS_LoadFP(st)) {
SaveStateStatus[CurrentState] = 1;
FCEU_DispMessage("State %d loaded.", CurrentState);
SaveStateStatus[CurrentState] = 1;
fclose(st);
return(1);
} else {
SaveStateStatus[CurrentState] = 1;
FCEU_DispMessage("Error(s) reading state %d!", CurrentState);
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;
StateShow = 0;
}
void ResetExState(void (*PreSave)(void), void (*PostSave)(void)) {
void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
{
SPreSave = PreSave;
SPostSave = PostSave;
SFEXINDEX = 0;
}
void AddExState(void *v, uint32 s, int type, char *desc) {
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));
@ -372,52 +359,7 @@ void AddExState(void *v, uint32 s, int type, char *desc) {
SFMDATA[SFEXINDEX].v = 0; // End marker.
}
void FCEUI_SelectState(int w) {
if (w == -1) {
StateShow = 0; return;
}
FCEUI_SelectMovie(-1);
CurrentState = w;
StateShow = 180;
FCEU_DispMessage("-select state-");
}
void FCEUI_SaveState(char *fname) {
StateShow = 0;
FCEUSS_Save(fname);
}
void FCEUI_LoadState(char *fname) {
StateShow = 0;
FCEUMOV_Stop();
/* For network play, be load the state locally, and then save the state to a temporary file,
and send that. This insures that if an older state is loaded that is missing some
information expected in newer save states, desynchronization won't occur(at least not
from this ;)).
*/
if (FCEUSS_Load(fname))
if (FCEUnetplay) {
char *fn = FCEU_MakeFName(FCEUMKF_NPTEMP, 0, 0);
MEM_TYPE *fp;
if ((fp = fopen(fn, "wb"))) {
if (FCEUSS_SaveFP(fp)) {
fclose(fp);
FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn);
} else fclose(fp);
unlink(fn);
}
free(fn);
}
}
void FCEU_DrawSaveStates(uint8 *XBuf) {
if (!StateShow) return;
FCEU_DrawNumberRow(XBuf, SaveStateStatus, CurrentState);
StateShow--;
void FCEU_DrawSaveStates(uint8 *XBuf)
{
}

View File

@ -56,7 +56,7 @@ typedef struct {
int (*init)(FCEUFILE *fp);
} BFMAPPING;
static CartInfo UNIFCart;
CartInfo UNIFCart;
static int vramo;
static int mirrortodo;

View File

@ -22,7 +22,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <zlib.h>
#include "fceu-types.h"
#include "video.h"
@ -31,102 +30,65 @@
#include "fceu-memory.h"
#include "crc32.h"
#include "state.h"
#include "movie.h"
#include "palette.h"
#include "nsf.h"
#include "input.h"
#include "vsuni.h"
uint8 *XBuf = NULL;
static uint8 *xbsave = NULL;
void FCEU_KillVirtualVideo(void) {
if (xbsave) {
free(xbsave);
xbsave = 0;
}
void FCEU_KillVirtualVideo(void)
{
if (XBuf)
free(XBuf);
XBuf = 0;
}
int FCEU_InitVirtualVideo(void) {
if (!XBuf) // Some driver code may allocate XBuf externally.
// 256 bytes per scanline, * 240 scanline maximum, +8 for alignment,
if (!(XBuf = (uint8*)(FCEU_malloc(256 * 256 + 8))))
return 0;
xbsave = XBuf;
int FCEU_InitVirtualVideo(void)
{
// 256 bytes per scanline, * 240 scanline maximum, +8 for alignment,
if (!XBuf)
XBuf = (uint8*)(FCEU_malloc(256 * 256 + 8));
if (sizeof(uint8*) == 4) {
uint32 m;
m = (uint32)XBuf;
m = (4 - m) & 3;
XBuf += m;
}
memset(XBuf, 128, 256 * 256);
return 1;
if (!XBuf)
return 0;
if (sizeof(uint8*) == 4)
{
uintptr_t m;
m = (uintptr_t)*XBuf;
m = (4 - m) & 3;
XBuf += m;
}
memset(XBuf, 128, 256 * 256);
return 1;
}
static int howlong;
static char errmsg[65];
#include "drawing.h"
#ifdef FRAMESKIP
//#define SHOWFPS
void ShowFPS(void);
void FCEU_PutImageDummy(void) {
#ifdef SHOWFPS
ShowFPS();
#endif
if (GameInfo->type != GIT_NSF) {
FCEU_DrawNTSCControlBars(XBuf);
FCEU_DrawSaveStates(XBuf);
FCEU_DrawMovies(XBuf);
}
if (howlong) howlong--; /* DrawMessage() */
}
#endif
void FCEUI_SaveSnapshot(void) { }
static int dosnapsave = 0;
void FCEUI_SaveSnapshot(void) {
dosnapsave = 1;
}
static void ReallySnap(void) {
int x = SaveSnapshot();
if (!x)
FCEU_DispMessage("Error saving screen snapshot.");
else
FCEU_DispMessage("Screen snapshot %d saved.", x - 1);
}
void FCEU_PutImage(void) {
#ifdef SHOWFPS
ShowFPS();
#endif
if (GameInfo->type == GIT_NSF) {
void FCEU_PutImage(void)
{
if (GameInfo->type == GIT_NSF)
DrawNSF(XBuf);
// Save snapshot after NSF screen is drawn. Why would we want to
// do it before?
if (dosnapsave) {
ReallySnap();
dosnapsave = 0;
}
} else {
// Save snapshot before overlay stuff is written.
if (dosnapsave) {
ReallySnap();
dosnapsave = 0;
}
else
{
if (GameInfo->type == GIT_VSUNI)
FCEU_VSUniDraw(XBuf);
FCEU_DrawSaveStates(XBuf);
FCEU_DrawMovies(XBuf);
FCEU_DrawNTSCControlBars(XBuf);
}
DrawMessage();
FCEU_DrawInput(XBuf);
if (howlong) howlong--;
}
void FCEU_DispMessage(char *format, ...) {
void FCEU_PutImageDummy(void)
{
}
void FCEU_DispMessage(char *format, ...)
{
va_list ap;
va_start(ap, format);
@ -136,158 +98,12 @@ void FCEU_DispMessage(char *format, ...) {
howlong = 180;
}
void FCEU_ResetMessages(void) {
howlong = 0;
void FCEU_ResetMessages(void)
{
howlong = 180;
}
static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data) {
uint32 crc;
uint8 tempo[4];
tempo[0] = size >> 24;
tempo[1] = size >> 16;
tempo[2] = size >> 8;
tempo[3] = size;
if (fwrite(tempo, 4, 1, fp) != 1)
return 0;
if (fwrite(type, 4, 1, fp) != 1)
return 0;
if (size)
if (fwrite(data, 1, size, fp) != size)
return 0;
crc = CalcCRC32(0, (uint8*)type, 4);
if (size)
crc = CalcCRC32(crc, data, size);
tempo[0] = crc >> 24;
tempo[1] = crc >> 16;
tempo[2] = crc >> 8;
tempo[3] = crc;
if (fwrite(tempo, 4, 1, fp) != 1)
return 0;
return 1;
}
int SaveSnapshot(void) {
static uint32 lastu = 0;
char *fn = 0;
int totallines = FSettings.LastSLine - FSettings.FirstSLine + 1;
int x, u, y;
FILE *pp = NULL;
uint8 *compmem = NULL;
uLongf compmemsize = totallines * 263 + 12;
if (!(compmem = (uint8*)FCEU_malloc(compmemsize)))
return 0;
for (u = lastu; u < 99999; u++) {
pp = FCEUD_UTF8fopen((fn = FCEU_MakeFName(FCEUMKF_SNAP, u, "png")), "rb");
if (pp == NULL) break;
fclose(pp);
}
lastu = u;
if (!(pp = FCEUD_UTF8fopen(fn, "wb"))) {
free(fn);
return 0;
}
free(fn);
{
static uint8 header[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
if (fwrite(header, 8, 1, pp) != 1)
goto PNGerr;
}
{
uint8 chunko[13];
chunko[0] = chunko[1] = chunko[3] = 0;
chunko[2] = 0x1; // Width of 256
chunko[4] = chunko[5] = chunko[6] = 0;
chunko[7] = totallines; // Height
chunko[8] = 8; // bit depth
chunko[9] = 3; // Color type; indexed 8-bit
chunko[10] = 0; // compression: deflate
chunko[11] = 0; // Basic adapative filter set(though none are used).
chunko[12] = 0; // No interlace.
if (!WritePNGChunk(pp, 13, "IHDR", chunko))
goto PNGerr;
}
{
uint8 pdata[256 * 3];
for (x = 0; x < 256; x++)
FCEUD_GetPalette(x, pdata + x * 3, pdata + x * 3 + 1, pdata + x * 3 + 2);
if (!WritePNGChunk(pp, 256 * 3, "PLTE", pdata))
goto PNGerr;
}
{
uint8 *tmp = XBuf + FSettings.FirstSLine * 256;
uint8 *dest, *mal, *mork;
if (!(mal = mork = dest = (uint8*)malloc((totallines << 8) + totallines)))
goto PNGerr;
// mork=dest=XBuf;
for (y = 0; y < totallines; y++) {
*dest = 0; // No filter.
dest++;
for (x = 256; x; x--, tmp++, dest++)
*dest = *tmp;
}
if (compress(compmem, &compmemsize, mork, (totallines << 8) + totallines) != Z_OK) {
if (mal) free(mal);
goto PNGerr;
}
if (mal) free(mal);
if (!WritePNGChunk(pp, compmemsize, "IDAT", compmem))
goto PNGerr;
}
if (!WritePNGChunk(pp, 0, "IEND", 0))
goto PNGerr;
free(compmem);
fclose(pp);
return u + 1;
PNGerr:
if (compmem)
free(compmem);
if (pp)
fclose(pp);
int SaveSnapshot(void)
{
return(0);
}
#ifdef SHOWFPS
uint64 FCEUD_GetTime(void);
uint64 FCEUD_GetTimeFreq(void);
static uint64 boop[60];
static int boopcount = 0;
void ShowFPS(void) {
uint64 da = FCEUD_GetTime() - boop[boopcount];
char fpsmsg[16];
int booplimit = PAL ? 50 : 60;
boop[boopcount] = FCEUD_GetTime();
sprintf(fpsmsg, "%8.1f", (double)booplimit / ((double)da / FCEUD_GetTimeFreq()));
DrawTextTrans(XBuf + (256 - 8 - 8 * 8) + (FSettings.FirstSLine + 4) * 256, 256, fpsmsg, 4);
// It's not averaging FPS over exactly 1 second, but it's close enough.
boopcount = (boopcount + 1) % booplimit;
}
#endif