Made custom FCEU API integration code to fix reentrant ROM crashes
in console ports - goes through Griffin file now
This commit is contained in:
@@ -163,15 +163,10 @@ endif
|
|||||||
LIBRETRO_DIR := ./src/drivers/libretro
|
LIBRETRO_DIR := ./src/drivers/libretro
|
||||||
FCEU_DIR := ./src
|
FCEU_DIR := ./src
|
||||||
|
|
||||||
ifeq ($(WANT_GRIFFIN), 1)
|
CFLAGS += -DWANT_GRIFFIN
|
||||||
CFLAGS += -DWANT_GRIFFIN
|
FCEU_SRC_DIRS := $(FCEU_DIR)/boards $(FCEU_DIR)/input $(FCEU_DIR)/mappers $(ZLIB_DIR)
|
||||||
FCEU_SRC_DIRS := $(FCEU_DIR)/boards $(FCEU_DIR)/input $(FCEU_DIR)/mappers $(ZLIB_DIR)
|
FCEU_CSRCS := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||||
FCEU_CSRCS := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
|
FCEU_CSRCS += $(LIBRETRO_DIR)/griffin.c $(FCEU_DIR)/ines.c $(FCEU_DIR)/unif.c $(FCEU_DIR)/x6502.c
|
||||||
FCEU_CSRCS += $(LIBRETRO_DIR)/griffin.c $(FCEU_DIR)/ines.c $(FCEU_DIR)/unif.c $(FCEU_DIR)/x6502.c
|
|
||||||
else
|
|
||||||
FCEU_SRC_DIRS := $(LIBRETRO_DIR) $(FCEU_DIR) $(FCEU_DIR)/boards $(FCEU_DIR)/input $(FCEU_DIR)/mappers $(ZLIB_DIR)
|
|
||||||
FCEU_CSRCS := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c))
|
|
||||||
endif
|
|
||||||
|
|
||||||
FCEU_COBJ := $(FCEU_CSRCS:.c=.o)
|
FCEU_COBJ := $(FCEU_CSRCS:.c=.o)
|
||||||
|
|
||||||
|
|||||||
103
src/drivers/libretro/fceu/fceu-endian.c
Normal file
103
src/drivers/libretro/fceu/fceu-endian.c
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Contains file I/O functions that write/read data */
|
||||||
|
/* LSB first. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "fceu-endian.h"
|
||||||
|
|
||||||
|
void FlipByteOrder(uint8 *src, uint32 count)
|
||||||
|
{
|
||||||
|
uint8 *start = src;
|
||||||
|
uint8 *end = src + count - 1;
|
||||||
|
|
||||||
|
if ((count & 1) || !count)
|
||||||
|
return; /* This shouldn't happen. */
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
uint8 tmp;
|
||||||
|
|
||||||
|
tmp = *end;
|
||||||
|
*end = *start;
|
||||||
|
*start = tmp;
|
||||||
|
end--;
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int write16le(uint16 b, FILE *fp)
|
||||||
|
{
|
||||||
|
uint8 s[2];
|
||||||
|
s[0] = b;
|
||||||
|
s[1] = b >> 8;
|
||||||
|
return((fwrite(s, 1, 2, fp) < 2) ? 0 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int write32le(uint32 b, FILE *fp)
|
||||||
|
{
|
||||||
|
uint8 s[4];
|
||||||
|
s[0] = b;
|
||||||
|
s[1] = b >> 8;
|
||||||
|
s[2] = b >> 16;
|
||||||
|
s[3] = b >> 24;
|
||||||
|
return((fwrite(s, 1, 4, fp) < 4) ? 0 : 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read32le(uint32 *Bufo, FILE *fp)
|
||||||
|
{
|
||||||
|
uint32 buf;
|
||||||
|
if (fread(&buf, 1, 4, fp) < 4)
|
||||||
|
return 0;
|
||||||
|
#ifdef LSB_FIRST
|
||||||
|
*(uint32*)Bufo = buf;
|
||||||
|
#else
|
||||||
|
*(uint32*)Bufo = ((buf & 0xFF) << 24) | ((buf & 0xFF00) << 8) | ((buf & 0xFF0000) >> 8) | ((buf & 0xFF000000) >> 24);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read16le(char *d, FILE *fp)
|
||||||
|
{
|
||||||
|
#ifdef LSB_FIRST
|
||||||
|
return((fread(d, 1, 2, fp) < 2) ? 0 : 2);
|
||||||
|
#else
|
||||||
|
int ret;
|
||||||
|
ret = fread(d + 1, 1, 1, fp);
|
||||||
|
ret += fread(d, 1, 1, fp);
|
||||||
|
return ret < 2 ? 0 : 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_en32lsb(uint8 *buf, uint32 morp)
|
||||||
|
{
|
||||||
|
buf[0] = morp;
|
||||||
|
buf[1] = morp >> 8;
|
||||||
|
buf[2] = morp >> 16;
|
||||||
|
buf[3] = morp >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 FCEU_de32lsb(uint8 *morp)
|
||||||
|
{
|
||||||
|
return(morp[0] | (morp[1] << 8) | (morp[2] << 16) | (morp[3] << 24));
|
||||||
|
}
|
||||||
14
src/drivers/libretro/fceu/fceu-endian.h
Normal file
14
src/drivers/libretro/fceu/fceu-endian.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _FCEU_ENDIAN_H
|
||||||
|
#define _FCEU_ENDIAN_H
|
||||||
|
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
|
||||||
|
int write16le(uint16 b, FILE *fp);
|
||||||
|
int write32le(uint32 b, FILE *fp);
|
||||||
|
int read32le(uint32 *Bufo, FILE *fp);
|
||||||
|
void FlipByteOrder(uint8 *src, uint32 count);
|
||||||
|
|
||||||
|
void FCEU_en32lsb(uint8 *, uint32);
|
||||||
|
uint32 FCEU_de32lsb(uint8 *);
|
||||||
|
|
||||||
|
#endif
|
||||||
63
src/drivers/libretro/fceu/fceu-memory.c
Normal file
63
src/drivers/libretro/fceu/fceu-memory.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "fceu.h"
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
|
void *FCEU_gmalloc(uint32 size)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
ret = malloc(size);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
FCEU_PrintError("Error allocating memory! Doing a hard exit.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *FCEU_malloc(uint32 size)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
void *ret;
|
||||||
|
ret = (void*)malloc(size);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
FCEU_PrintError("Error allocating memory!");
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_free(void *ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_gfree(void *ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
50
src/drivers/libretro/fceu/fceu-memory.h
Normal file
50
src/drivers/libretro/fceu/fceu-memory.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Various macros for faster memory stuff
|
||||||
|
(at least that's the idea)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FCEU_MEMORY_H_
|
||||||
|
#define _FCEU_MEMORY_H_
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "../memstream.h"
|
||||||
|
|
||||||
|
#define FCEU_dwmemset(d, c, n) { int _x; for (_x = n - 4; _x >= 0; _x -= 4) *(uint32*)& (d)[_x] = c; }
|
||||||
|
|
||||||
|
#define HAVE_MEMSTREAM
|
||||||
|
#define MEM_TYPE memstream_t
|
||||||
|
|
||||||
|
#define fwrite(ptr, size, nmemb, stream) memstream_write((stream), (ptr), (nmemb))
|
||||||
|
#define fclose(fp) memstream_close((fp))
|
||||||
|
#define fgetc(stream) memstream_getc((stream))
|
||||||
|
#define fputc(c, stream) memstream_putc((stream), (c))
|
||||||
|
#define ftell(a) memstream_pos((a))
|
||||||
|
#define fread(ptr, size, nmemb, stream) memstream_read((stream), (ptr), (nmemb))
|
||||||
|
#define fseek(stream, offset, whence) memstream_seek((stream), (offset), (whence))
|
||||||
|
|
||||||
|
void *FCEU_malloc(uint32 size);
|
||||||
|
void *FCEU_gmalloc(uint32 size);
|
||||||
|
void FCEU_gfree(void *ptr);
|
||||||
|
void FCEU_free(void *ptr);
|
||||||
|
void FASTAPASS(3) FCEU_memmove(void *d, void *s, uint32 l);
|
||||||
|
|
||||||
|
#endif
|
||||||
553
src/drivers/libretro/fceu/fceu.c
Normal file
553
src/drivers/libretro/fceu/fceu.c
Normal file
@@ -0,0 +1,553 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2003 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "x6502.h"
|
||||||
|
#include "fceu.h"
|
||||||
|
#include "ppu.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "netplay.h"
|
||||||
|
#include "general.h"
|
||||||
|
#include "fceu-endian.h"
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
|
||||||
|
#include "cart.h"
|
||||||
|
#include "nsf.h"
|
||||||
|
#include "fds.h"
|
||||||
|
#include "ines.h"
|
||||||
|
#include "unif.h"
|
||||||
|
#include "cheat.h"
|
||||||
|
#include "palette.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "crc32.h"
|
||||||
|
#include "vsuni.h"
|
||||||
|
|
||||||
|
uint64 timestampbase;
|
||||||
|
|
||||||
|
|
||||||
|
FCEUGI *GameInfo = NULL;
|
||||||
|
void (*GameInterface)(int h);
|
||||||
|
|
||||||
|
void (*GameStateRestore)(int version);
|
||||||
|
|
||||||
|
readfunc ARead[0x10000];
|
||||||
|
writefunc BWrite[0x10000];
|
||||||
|
static readfunc *AReadG;
|
||||||
|
static writefunc *BWriteG;
|
||||||
|
static int RWWrap = 0;
|
||||||
|
|
||||||
|
static DECLFW(BNull)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static DECLFR(ANull)
|
||||||
|
{
|
||||||
|
return(X.DB);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AllocGenieRW(void)
|
||||||
|
{
|
||||||
|
if (!(AReadG = (readfunc*)FCEU_malloc(0x8000 * sizeof(readfunc))))
|
||||||
|
return 0;
|
||||||
|
if (!(BWriteG = (writefunc*)FCEU_malloc(0x8000 * sizeof(writefunc))))
|
||||||
|
return 0;
|
||||||
|
RWWrap = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlushGenieRW(void)
|
||||||
|
{
|
||||||
|
int32 x;
|
||||||
|
|
||||||
|
if (RWWrap)
|
||||||
|
{
|
||||||
|
for (x = 0; x < 0x8000; x++)
|
||||||
|
{
|
||||||
|
ARead[x + 0x8000] = AReadG[x];
|
||||||
|
BWrite[x + 0x8000] = BWriteG[x];
|
||||||
|
}
|
||||||
|
free(AReadG);
|
||||||
|
free(BWriteG);
|
||||||
|
AReadG = 0;
|
||||||
|
BWriteG = 0;
|
||||||
|
}
|
||||||
|
RWWrap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
readfunc FASTAPASS(1) GetReadHandler(int32 a)
|
||||||
|
{
|
||||||
|
if (a >= 0x8000 && RWWrap)
|
||||||
|
return AReadG[a - 0x8000];
|
||||||
|
else
|
||||||
|
return ARead[a];
|
||||||
|
}
|
||||||
|
|
||||||
|
void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func)
|
||||||
|
{
|
||||||
|
int32 x;
|
||||||
|
|
||||||
|
if (!func)
|
||||||
|
func = ANull;
|
||||||
|
|
||||||
|
if (RWWrap)
|
||||||
|
for (x = end; x >= start; x--)
|
||||||
|
{
|
||||||
|
if (x >= 0x8000)
|
||||||
|
AReadG[x - 0x8000] = func;
|
||||||
|
else
|
||||||
|
ARead[x] = func;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (x = end; x >= start; x--)
|
||||||
|
ARead[x] = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
writefunc FASTAPASS(1) GetWriteHandler(int32 a)
|
||||||
|
{
|
||||||
|
if (RWWrap && a >= 0x8000)
|
||||||
|
return BWriteG[a - 0x8000];
|
||||||
|
else
|
||||||
|
return BWrite[a];
|
||||||
|
}
|
||||||
|
|
||||||
|
void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func)
|
||||||
|
{
|
||||||
|
int32 x;
|
||||||
|
|
||||||
|
if (!func)
|
||||||
|
func = BNull;
|
||||||
|
|
||||||
|
if (RWWrap)
|
||||||
|
for (x = end; x >= start; x--)
|
||||||
|
{
|
||||||
|
if (x >= 0x8000)
|
||||||
|
BWriteG[x - 0x8000] = func;
|
||||||
|
else
|
||||||
|
BWrite[x] = func;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (x = end; x >= start; x--)
|
||||||
|
BWrite[x] = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COPYFAMI
|
||||||
|
uint8 RAM[0x4000];
|
||||||
|
#else
|
||||||
|
uint8 RAM[0x800];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8 PAL = 0;
|
||||||
|
|
||||||
|
static DECLFW(BRAML)
|
||||||
|
{
|
||||||
|
RAM[A] = V;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DECLFR(ARAML)
|
||||||
|
{
|
||||||
|
return RAM[A];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef COPYFAMI
|
||||||
|
static DECLFW(BRAMH)
|
||||||
|
{
|
||||||
|
RAM[A & 0x7FF] = V;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DECLFR(ARAMH)
|
||||||
|
{
|
||||||
|
return RAM[A & 0x7FF];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FCEUI_CloseGame(void)
|
||||||
|
{
|
||||||
|
if (!GameInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (GameInfo->name)
|
||||||
|
free(GameInfo->name);
|
||||||
|
GameInfo->name = 0;
|
||||||
|
if (GameInfo->type != GIT_NSF)
|
||||||
|
FCEU_FlushGameCheats(0, 0);
|
||||||
|
GameInterface(GI_CLOSE);
|
||||||
|
ResetExState(0, 0);
|
||||||
|
FCEU_CloseGenie();
|
||||||
|
free(GameInfo);
|
||||||
|
GameInfo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetGameLoaded(void)
|
||||||
|
{
|
||||||
|
if (GameInfo)
|
||||||
|
FCEUI_CloseGame();
|
||||||
|
|
||||||
|
GameStateRestore = NULL;
|
||||||
|
PPU_hook = NULL;
|
||||||
|
GameHBIRQHook = NULL;
|
||||||
|
|
||||||
|
if (GameExpSound.Kill)
|
||||||
|
GameExpSound.Kill();
|
||||||
|
memset(&GameExpSound, 0, sizeof(GameExpSound));
|
||||||
|
|
||||||
|
MapIRQHook = NULL;
|
||||||
|
MMC5Hack = 0;
|
||||||
|
PEC586Hack = 0;
|
||||||
|
PAL &= 1;
|
||||||
|
pale = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UNIFLoad(const char *name, FCEUFILE *fp);
|
||||||
|
int iNESLoad(const char *name, FCEUFILE *fp);
|
||||||
|
int FDSLoad(const char *name, FCEUFILE *fp);
|
||||||
|
int NSFLoad(FCEUFILE *fp);
|
||||||
|
|
||||||
|
FCEUGI *FCEUI_LoadGame(const char *name)
|
||||||
|
{
|
||||||
|
FCEUFILE *fp;
|
||||||
|
char *ipsfn;
|
||||||
|
|
||||||
|
ResetGameLoaded();
|
||||||
|
|
||||||
|
GameInfo = malloc(sizeof(FCEUGI));
|
||||||
|
memset(GameInfo, 0, sizeof(FCEUGI));
|
||||||
|
|
||||||
|
GameInfo->soundchan = 0;
|
||||||
|
GameInfo->soundrate = 0;
|
||||||
|
GameInfo->name = 0;
|
||||||
|
GameInfo->type = GIT_CART;
|
||||||
|
GameInfo->vidsys = GIV_USER;
|
||||||
|
GameInfo->input[0] = GameInfo->input[1] = -1;
|
||||||
|
GameInfo->inputfc = -1;
|
||||||
|
GameInfo->cspecial = 0;
|
||||||
|
|
||||||
|
FCEU_printf("Loading %s...\n\n", name);
|
||||||
|
|
||||||
|
GetFileBase(name);
|
||||||
|
|
||||||
|
ipsfn = FCEU_MakeFName(FCEUMKF_IPS, 0, 0);
|
||||||
|
fp = FCEU_fopen(name, ipsfn, "rb", 0);
|
||||||
|
free(ipsfn);
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
FCEU_PrintError("Error opening \"%s\"!", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iNESLoad(name, fp))
|
||||||
|
goto endlseq;
|
||||||
|
if (NSFLoad(fp))
|
||||||
|
goto endlseq;
|
||||||
|
if (UNIFLoad(name, fp))
|
||||||
|
goto endlseq;
|
||||||
|
if (FDSLoad(name, fp))
|
||||||
|
goto endlseq;
|
||||||
|
|
||||||
|
FCEU_PrintError("An error occurred while loading the file.");
|
||||||
|
FCEU_fclose(fp);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
endlseq:
|
||||||
|
FCEU_fclose(fp);
|
||||||
|
|
||||||
|
FCEU_ResetVidSys();
|
||||||
|
if (GameInfo->type != GIT_NSF)
|
||||||
|
if (FSettings.GameGenie)
|
||||||
|
FCEU_OpenGenie();
|
||||||
|
|
||||||
|
PowerNES();
|
||||||
|
FCEUSS_CheckStates();
|
||||||
|
|
||||||
|
if (GameInfo->type != GIT_NSF) {
|
||||||
|
FCEU_LoadGamePalette();
|
||||||
|
FCEU_LoadGameCheats(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FCEU_ResetPalette();
|
||||||
|
FCEU_ResetMessages(); // Save state, status messages, etc.
|
||||||
|
|
||||||
|
return(GameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CopyFamiLoad(void);
|
||||||
|
|
||||||
|
FCEUGI *FCEUI_CopyFamiStart(void)
|
||||||
|
{
|
||||||
|
ResetGameLoaded();
|
||||||
|
|
||||||
|
GameInfo = (FCEUGI*)malloc(sizeof(FCEUGI));
|
||||||
|
memset(GameInfo, 0, sizeof(FCEUGI));
|
||||||
|
|
||||||
|
GameInfo->soundchan = 0;
|
||||||
|
GameInfo->soundrate = 0;
|
||||||
|
GameInfo->name = "copyfami";
|
||||||
|
GameInfo->type = GIT_CART;
|
||||||
|
GameInfo->vidsys = GIV_USER;
|
||||||
|
GameInfo->input[0] = GameInfo->input[1] = -1;
|
||||||
|
GameInfo->inputfc = -1;
|
||||||
|
GameInfo->cspecial = 0;
|
||||||
|
|
||||||
|
FCEU_printf("Starting CopyFamicom...\n\n");
|
||||||
|
|
||||||
|
if (!CopyFamiLoad()) {
|
||||||
|
FCEU_PrintError("An error occurred while starting CopyFamicom.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FCEU_ResetVidSys();
|
||||||
|
if (GameInfo->type != GIT_NSF)
|
||||||
|
if (FSettings.GameGenie)
|
||||||
|
FCEU_OpenGenie();
|
||||||
|
|
||||||
|
PowerNES();
|
||||||
|
FCEUSS_CheckStates();
|
||||||
|
|
||||||
|
if (GameInfo->type != GIT_NSF) {
|
||||||
|
FCEU_LoadGamePalette();
|
||||||
|
FCEU_LoadGameCheats(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FCEU_ResetPalette();
|
||||||
|
FCEU_ResetMessages(); // Save state, status messages, etc.
|
||||||
|
|
||||||
|
return(GameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEUI_Initialize(void) {
|
||||||
|
if (!FCEU_InitVirtualVideo())
|
||||||
|
return 0;
|
||||||
|
memset(&FSettings, 0, sizeof(FSettings));
|
||||||
|
FSettings.UsrFirstSLine[0] = 8;
|
||||||
|
FSettings.UsrFirstSLine[1] = 0;
|
||||||
|
FSettings.UsrLastSLine[0] = 231;
|
||||||
|
FSettings.UsrLastSLine[1] = 239;
|
||||||
|
FSettings.SoundVolume = 100;
|
||||||
|
FCEUPPU_Init();
|
||||||
|
X6502_Init();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_Kill(void) {
|
||||||
|
FCEU_KillVirtualVideo();
|
||||||
|
FCEU_KillGenie();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) {
|
||||||
|
int r, ssize;
|
||||||
|
|
||||||
|
FCEU_UpdateInput();
|
||||||
|
if (geniestage != 1) FCEU_ApplyPeriodicCheats();
|
||||||
|
r = FCEUPPU_Loop(skip);
|
||||||
|
|
||||||
|
ssize = FlushEmulateSound();
|
||||||
|
|
||||||
|
timestampbase += timestamp;
|
||||||
|
|
||||||
|
timestamp = 0;
|
||||||
|
|
||||||
|
*pXBuf = skip ? 0 : XBuf;
|
||||||
|
*SoundBuf = WaveFinal;
|
||||||
|
*SoundBufSize = ssize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ResetNES(void)
|
||||||
|
{
|
||||||
|
if (!GameInfo)
|
||||||
|
return;
|
||||||
|
GameInterface(GI_RESETM2);
|
||||||
|
FCEUSND_Reset();
|
||||||
|
FCEUPPU_Reset();
|
||||||
|
X6502_Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_MemoryRand(uint8 *ptr, uint32 size)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
while (size) {
|
||||||
|
// *ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default
|
||||||
|
// Cybernoid NO MUSIC by default
|
||||||
|
// *ptr = (x & 4) ? 0x7F : 0x00; // Huang Di DEBUG MODE enabled by default
|
||||||
|
// Minna no Taabou no Nakayoshi Daisakusen DOESN'T BOOT
|
||||||
|
// Cybernoid NO MUSIC by default
|
||||||
|
// *ptr = (x & 1) ? 0x55 : 0xAA; // F-15 Sity War HISCORE is screwed...
|
||||||
|
// 1942 SCORE/HISCORE is screwed...
|
||||||
|
*ptr = 0xFF;
|
||||||
|
x++;
|
||||||
|
size--;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hand(X6502 *X, int type, uint32 A)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PowerNES(void)
|
||||||
|
{
|
||||||
|
if (!GameInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FCEU_CheatResetRAM();
|
||||||
|
FCEU_CheatAddRAM(2, 0, RAM);
|
||||||
|
|
||||||
|
FCEU_GeniePower();
|
||||||
|
|
||||||
|
#ifndef COPYFAMI
|
||||||
|
FCEU_MemoryRand(RAM, 0x800);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SetReadHandler(0x0000, 0xFFFF, ANull);
|
||||||
|
SetWriteHandler(0x0000, 0xFFFF, BNull);
|
||||||
|
|
||||||
|
#ifdef COPYFAMI
|
||||||
|
SetReadHandler(0, 0x3FFF, ARAML);
|
||||||
|
SetWriteHandler(0, 0x3FFF, BRAML);
|
||||||
|
#else
|
||||||
|
SetReadHandler(0, 0x7FF, ARAML);
|
||||||
|
SetWriteHandler(0, 0x7FF, BRAML);
|
||||||
|
|
||||||
|
SetReadHandler(0x800, 0x1FFF, ARAMH); /* Part of a little */
|
||||||
|
SetWriteHandler(0x800, 0x1FFF, BRAMH); /* hack for a small speed boost. */
|
||||||
|
#endif
|
||||||
|
InitializeInput();
|
||||||
|
FCEUSND_Power();
|
||||||
|
FCEUPPU_Power();
|
||||||
|
|
||||||
|
/* Have the external game hardware "powered" after the internal NES stuff.
|
||||||
|
Needed for the NSF code and VS System code.
|
||||||
|
*/
|
||||||
|
GameInterface(GI_POWER);
|
||||||
|
if (GameInfo->type == GIT_VSUNI)
|
||||||
|
FCEU_VSUniPower();
|
||||||
|
|
||||||
|
timestampbase = 0;
|
||||||
|
X6502_Power();
|
||||||
|
FCEU_PowerCheats();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_ResetVidSys(void)
|
||||||
|
{
|
||||||
|
int w;
|
||||||
|
|
||||||
|
if (GameInfo->vidsys == GIV_NTSC)
|
||||||
|
w = 0;
|
||||||
|
else if (GameInfo->vidsys == GIV_PAL)
|
||||||
|
w = 1;
|
||||||
|
else
|
||||||
|
w = FSettings.PAL;
|
||||||
|
|
||||||
|
PAL = w ? 1 : 0;
|
||||||
|
|
||||||
|
FCEUPPU_SetVideoSystem(w);
|
||||||
|
SetSoundVariables();
|
||||||
|
}
|
||||||
|
|
||||||
|
FCEUS FSettings;
|
||||||
|
|
||||||
|
void FCEU_printf(char *format, ...)
|
||||||
|
{
|
||||||
|
char temp[2048];
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vsprintf(temp, format, ap);
|
||||||
|
FCEUD_Message(temp);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_PrintError(char *format, ...)
|
||||||
|
{
|
||||||
|
char temp[2048];
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vsprintf(temp, format, ap);
|
||||||
|
FCEUD_PrintError(temp);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall)
|
||||||
|
{
|
||||||
|
FSettings.UsrFirstSLine[0] = ntscf;
|
||||||
|
FSettings.UsrLastSLine[0] = ntscl;
|
||||||
|
FSettings.UsrFirstSLine[1] = palf;
|
||||||
|
FSettings.UsrLastSLine[1] = pall;
|
||||||
|
if (PAL)
|
||||||
|
{
|
||||||
|
FSettings.FirstSLine = FSettings.UsrFirstSLine[1];
|
||||||
|
FSettings.LastSLine = FSettings.UsrLastSLine[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FSettings.FirstSLine = FSettings.UsrFirstSLine[0];
|
||||||
|
FSettings.LastSLine = FSettings.UsrLastSLine[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetVidSystem(int a)
|
||||||
|
{
|
||||||
|
FSettings.PAL = a ? 1 : 0;
|
||||||
|
|
||||||
|
if (!GameInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FCEU_ResetVidSys();
|
||||||
|
FCEU_ResetPalette();
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend)
|
||||||
|
{
|
||||||
|
if (slstart)
|
||||||
|
*slstart = FSettings.FirstSLine;
|
||||||
|
if (slend)
|
||||||
|
*slend = FSettings.LastSLine;
|
||||||
|
return(PAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetGameGenie(int a)
|
||||||
|
{
|
||||||
|
FSettings.GameGenie = a ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetSnapName(int a)
|
||||||
|
{
|
||||||
|
FSettings.SnapName = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 FCEUI_GetDesiredFPS(void)
|
||||||
|
{
|
||||||
|
if (PAL)
|
||||||
|
return(838977920); // ~50.007
|
||||||
|
else
|
||||||
|
return(1008307711); // ~60.1
|
||||||
|
}
|
||||||
161
src/drivers/libretro/fceu/file.c
Normal file
161
src/drivers/libretro/fceu/file.c
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "fceu-endian.h"
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
#include "driver.h"
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8 *data;
|
||||||
|
uint32 size;
|
||||||
|
uint32 location;
|
||||||
|
} MEMWRAP;
|
||||||
|
|
||||||
|
void ApplyIPS(FILE *ips, MEMWRAP *dest)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static MEMWRAP *MakeMemWrap(void *tz, int type)
|
||||||
|
{
|
||||||
|
MEMWRAP *tmp;
|
||||||
|
|
||||||
|
if (!(tmp = (MEMWRAP*)FCEU_malloc(sizeof(MEMWRAP))))
|
||||||
|
goto doret;
|
||||||
|
tmp->location = 0;
|
||||||
|
|
||||||
|
fseek((FILE*)tz, 0, SEEK_END);
|
||||||
|
tmp->size = ftell((FILE*)tz);
|
||||||
|
fseek((FILE*)tz, 0, SEEK_SET);
|
||||||
|
if (!(tmp->data = (uint8*)FCEU_malloc(tmp->size)))
|
||||||
|
{
|
||||||
|
free(tmp);
|
||||||
|
tmp = 0;
|
||||||
|
goto doret;
|
||||||
|
}
|
||||||
|
fread(tmp->data, 1, tmp->size, (FILE*)tz);
|
||||||
|
|
||||||
|
doret:
|
||||||
|
if (type == 0)
|
||||||
|
fclose((FILE*)tz);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#define strcasecmp strcmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext)
|
||||||
|
{
|
||||||
|
FCEUFILE *fceufp;
|
||||||
|
void *t;
|
||||||
|
|
||||||
|
fceufp = (FCEUFILE*)malloc(sizeof(FCEUFILE));
|
||||||
|
|
||||||
|
if ((t = FCEUD_UTF8fopen(path, mode)))
|
||||||
|
{
|
||||||
|
fseek((FILE*)t, 0, SEEK_SET);
|
||||||
|
fceufp->type = 0;
|
||||||
|
fceufp->fp = t;
|
||||||
|
return fceufp;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fceufp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_fclose(FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
fclose((FILE*)fp->fp);
|
||||||
|
free(fp);
|
||||||
|
fp = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
return fread(ptr, size, nmemb, (FILE*)fp->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
return fwrite(ptr, size, nmemb, (FILE*)fp->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
|
||||||
|
{
|
||||||
|
return fseek((FILE*)fp->fp, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 FCEU_ftell(FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
return ftell((FILE*)fp->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_rewind(FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
fseek(fp->fp, 0, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_read16le(uint16 *val, FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
uint8 t[2];
|
||||||
|
|
||||||
|
if (fread(t, 1, 2, (FILE*)fp->fp) != 2)
|
||||||
|
return(0);
|
||||||
|
*val = t[0] | (t[1] << 8);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
return read32le(Bufo, (FILE*)fp->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_fgetc(FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
return fgetc((FILE*)fp->fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 FCEU_fgetsize(FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
long t, r;
|
||||||
|
t = ftell((FILE*)fp->fp);
|
||||||
|
fseek((FILE*)fp->fp, 0, SEEK_END);
|
||||||
|
r = ftell((FILE*)fp->fp);
|
||||||
|
fseek((FILE*)fp->fp, t, SEEK_SET);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_fisarchive(FCEUFILE *fp)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
162
src/drivers/libretro/fceu/general.c
Normal file
162
src/drivers/libretro/fceu/general.c
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "fceu.h"
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
#include "md5.h"
|
||||||
|
|
||||||
|
static char BaseDirectory[2048];
|
||||||
|
static char FileBase[2048];
|
||||||
|
static char FileExt[2048]; /* Includes the . character, as in ".nes" */
|
||||||
|
|
||||||
|
static char FileBaseDirectory[2048];
|
||||||
|
|
||||||
|
void FCEUI_SetBaseDirectory(char *dir)
|
||||||
|
{
|
||||||
|
strncpy(BaseDirectory, dir, 2047);
|
||||||
|
BaseDirectory[2047] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *odirs[FCEUIOD__COUNT] = { 0, 0, 0, 0, 0, 0 }; // odirs, odors. ^_^
|
||||||
|
|
||||||
|
void FCEUI_SetDirOverride(int which, char *n)
|
||||||
|
{
|
||||||
|
odirs[which] = n;
|
||||||
|
|
||||||
|
/* Rebuild cache of present states/movies. */
|
||||||
|
if (GameInfo)
|
||||||
|
{
|
||||||
|
if (which == FCEUIOD_STATE)
|
||||||
|
FCEUSS_CheckStates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_ASPRINTF
|
||||||
|
static int asprintf(char **strp, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (!(*strp = malloc(2048)))
|
||||||
|
return(0);
|
||||||
|
ret = vsnprintf(*strp, 2048, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *FCEU_MakeFName(int type, int id1, char *cd1)
|
||||||
|
{
|
||||||
|
char *ret = 0;
|
||||||
|
struct stat tmpstat;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case FCEUMKF_GGROM:
|
||||||
|
asprintf(&ret, "%s"PSS "gg.rom", BaseDirectory);
|
||||||
|
break;
|
||||||
|
case FCEUMKF_FDSROM:
|
||||||
|
asprintf(&ret, "%s"PSS "disksys.rom", BaseDirectory);
|
||||||
|
break;
|
||||||
|
case FCEUMKF_PALETTE:
|
||||||
|
if (odirs[FCEUIOD_MISC])
|
||||||
|
asprintf(&ret, "%s"PSS "%s.pal", odirs[FCEUIOD_MISC], FileBase);
|
||||||
|
else
|
||||||
|
asprintf(&ret, "%s"PSS "gameinfo"PSS "%s.pal", BaseDirectory, FileBase);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = malloc(1);
|
||||||
|
*ret = '\0';
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetFileBase(const char *f)
|
||||||
|
{
|
||||||
|
const char *tp1, *tp3;
|
||||||
|
|
||||||
|
#if PSS_STYLE == 4
|
||||||
|
tp1 = ((char*)strrchr(f, ':'));
|
||||||
|
#elif PSS_STYLE == 1
|
||||||
|
tp1 = ((char*)strrchr(f, '/'));
|
||||||
|
#else
|
||||||
|
tp1 = ((char*)strrchr(f, '\\'));
|
||||||
|
#if PSS_STYLE != 3
|
||||||
|
tp3 = ((char*)strrchr(f, '/'));
|
||||||
|
if (tp1 < tp3) tp1 = tp3;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (!tp1)
|
||||||
|
{
|
||||||
|
tp1 = f;
|
||||||
|
strcpy(FileBaseDirectory, ".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(FileBaseDirectory, f, tp1 - f);
|
||||||
|
FileBaseDirectory[tp1 - f] = 0;
|
||||||
|
tp1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((tp3 = strrchr(f, '.')) != NULL) && (tp3 > tp1))
|
||||||
|
{
|
||||||
|
memcpy(FileBase, tp1, tp3 - tp1);
|
||||||
|
FileBase[tp3 - tp1] = 0;
|
||||||
|
strcpy(FileExt, tp3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(FileBase, tp1);
|
||||||
|
FileExt[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 uppow2(uint32 n)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (x = 31; x >= 0; x--)
|
||||||
|
if (n & (1 << x))
|
||||||
|
{
|
||||||
|
if ((1 << x) != n)
|
||||||
|
return(1 << (x + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
378
src/drivers/libretro/fceu/input.c
Normal file
378
src/drivers/libretro/fceu/input.c
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 1998 BERO
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "x6502.h"
|
||||||
|
|
||||||
|
#include "fceu.h"
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
|
#include "vsuni.h"
|
||||||
|
#include "fds.h"
|
||||||
|
|
||||||
|
extern INPUTC *FCEU_InitJoyPad(int w);
|
||||||
|
extern INPUTC *FCEU_InitZapper(int w);
|
||||||
|
extern INPUTC *FCEU_InitMouse(int w);
|
||||||
|
extern INPUTC *FCEU_InitPowerpadA(int w);
|
||||||
|
extern INPUTC *FCEU_InitPowerpadB(int w);
|
||||||
|
extern INPUTC *FCEU_InitArkanoid(int w);
|
||||||
|
|
||||||
|
extern INPUTCFC *FCEU_InitFami4(void);
|
||||||
|
extern INPUTCFC *FCEU_InitArkanoidFC(void);
|
||||||
|
extern INPUTCFC *FCEU_InitSpaceShadow(void);
|
||||||
|
extern INPUTCFC *FCEU_InitFKB(void);
|
||||||
|
extern INPUTCFC *FCEU_InitSuborKB(void);
|
||||||
|
extern INPUTCFC *FCEU_InitPEC586KB(void);
|
||||||
|
extern INPUTCFC *FCEU_InitHS(void);
|
||||||
|
extern INPUTCFC *FCEU_InitMahjong(void);
|
||||||
|
extern INPUTCFC *FCEU_InitQuizKing(void);
|
||||||
|
extern INPUTCFC *FCEU_InitFamilyTrainerA(void);
|
||||||
|
extern INPUTCFC *FCEU_InitFamilyTrainerB(void);
|
||||||
|
extern INPUTCFC *FCEU_InitOekaKids(void);
|
||||||
|
extern INPUTCFC *FCEU_InitTopRider(void);
|
||||||
|
extern INPUTCFC *FCEU_InitBarcodeWorld(void);
|
||||||
|
|
||||||
|
extern uint8 coinon;
|
||||||
|
|
||||||
|
static void *InputDataPtr[2];
|
||||||
|
uint8 LastStrobe;
|
||||||
|
|
||||||
|
static int JPAttrib[2] = { 0, 0 };
|
||||||
|
static int JPType[2] = { 0, 0 };
|
||||||
|
static INPUTC DummyJPort = { 0, 0, 0, 0, 0 };
|
||||||
|
static INPUTC *JPorts[2] = { &DummyJPort, &DummyJPort };
|
||||||
|
|
||||||
|
static int JPAttribFC = 0;
|
||||||
|
static int JPTypeFC = 0;
|
||||||
|
static void *InputDataPtrFC;
|
||||||
|
static INPUTCFC *FCExp = 0;
|
||||||
|
|
||||||
|
void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
|
||||||
|
|
||||||
|
static DECLFR(JPRead)
|
||||||
|
{
|
||||||
|
uint8 ret = 0;
|
||||||
|
|
||||||
|
if (JPorts[A & 1]->Read)
|
||||||
|
ret |= JPorts[A & 1]->Read(A & 1);
|
||||||
|
|
||||||
|
if (FCExp)
|
||||||
|
if (FCExp->Read)
|
||||||
|
ret = FCExp->Read(A & 1, ret);
|
||||||
|
|
||||||
|
ret |= X.DB & 0xC0;
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DECLFW(B4016)
|
||||||
|
{
|
||||||
|
if (FCExp)
|
||||||
|
if (FCExp->Write)
|
||||||
|
FCExp->Write(V & 7);
|
||||||
|
|
||||||
|
if (JPorts[0]->Write)
|
||||||
|
JPorts[0]->Write(V & 1);
|
||||||
|
if (JPorts[1]->Write)
|
||||||
|
JPorts[1]->Write(V & 1);
|
||||||
|
|
||||||
|
if ((LastStrobe & 1) && (!(V & 1)))
|
||||||
|
{
|
||||||
|
if (JPorts[0]->Strobe)
|
||||||
|
JPorts[0]->Strobe(0);
|
||||||
|
if (JPorts[1]->Strobe)
|
||||||
|
JPorts[1]->Strobe(1);
|
||||||
|
if (FCExp)
|
||||||
|
if (FCExp->Strobe)
|
||||||
|
FCExp->Strobe();
|
||||||
|
}
|
||||||
|
LastStrobe = V & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_DrawInput(uint8 *buf)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; x < 2; x++)
|
||||||
|
if (JPorts[x]->Draw)
|
||||||
|
JPorts[x]->Draw(x, buf, JPAttrib[x]);
|
||||||
|
if (FCExp)
|
||||||
|
if (FCExp->Draw)
|
||||||
|
FCExp->Draw(buf, JPAttribFC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_UpdateInput(void)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (x = 0; x < 2; x++)
|
||||||
|
{
|
||||||
|
if (JPorts[x] && JPorts[x]->Update)
|
||||||
|
JPorts[x]->Update(x, InputDataPtr[x], JPAttrib[x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FCExp && FCExp->Update)
|
||||||
|
FCExp->Update(InputDataPtrFC, JPAttribFC);
|
||||||
|
|
||||||
|
if (GameInfo && GameInfo->type == GIT_VSUNI)
|
||||||
|
if (coinon) coinon--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DECLFR(VSUNIRead0)
|
||||||
|
{
|
||||||
|
uint8 ret = 0;
|
||||||
|
|
||||||
|
if (JPorts[0]->Read)
|
||||||
|
ret |= (JPorts[0]->Read(0)) & 1;
|
||||||
|
|
||||||
|
ret |= (vsdip & 3) << 3;
|
||||||
|
if (coinon)
|
||||||
|
ret |= 0x4;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DECLFR(VSUNIRead1)
|
||||||
|
{
|
||||||
|
uint8 ret = 0;
|
||||||
|
|
||||||
|
if (JPorts[1] && JPorts[1]->Read)
|
||||||
|
ret |= (JPorts[1]->Read(1)) & 1;
|
||||||
|
ret |= vsdip & 0xFC;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SLHLHook(uint8 *bg, uint8 *spr, uint32 linets, int final)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (x = 0; x < 2; x++)
|
||||||
|
if (JPorts[x] && JPorts[x]->SLHook)
|
||||||
|
JPorts[x]->SLHook(x, bg, spr, linets, final);
|
||||||
|
|
||||||
|
if (FCExp && FCExp->SLHook)
|
||||||
|
FCExp->SLHook(bg, spr, linets, final);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CheckSLHook(void)
|
||||||
|
{
|
||||||
|
InputScanlineHook = 0;
|
||||||
|
|
||||||
|
if (JPorts[0] && JPorts[0]->SLHook || JPorts[1] && JPorts[1]->SLHook)
|
||||||
|
InputScanlineHook = SLHLHook;
|
||||||
|
|
||||||
|
if (FCExp && FCExp->SLHook)
|
||||||
|
InputScanlineHook = SLHLHook;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FASTAPASS(1) SetInputStuff(int x)
|
||||||
|
{
|
||||||
|
switch (JPType[x])
|
||||||
|
{
|
||||||
|
case SI_NONE:
|
||||||
|
JPorts[x] = &DummyJPort;
|
||||||
|
break;
|
||||||
|
case SI_GAMEPAD:
|
||||||
|
JPorts[x] = FCEU_InitJoyPad(x);
|
||||||
|
break;
|
||||||
|
case SI_ARKANOID:
|
||||||
|
JPorts[x] = FCEU_InitArkanoid(x);
|
||||||
|
break;
|
||||||
|
case SI_MOUSE:
|
||||||
|
JPorts[x] = FCEU_InitMouse(x);
|
||||||
|
break;
|
||||||
|
case SI_ZAPPER:
|
||||||
|
JPorts[x] = FCEU_InitZapper(x);
|
||||||
|
break;
|
||||||
|
case SI_POWERPADA:
|
||||||
|
JPorts[x] = FCEU_InitPowerpadA(x);
|
||||||
|
break;
|
||||||
|
case SI_POWERPADB:
|
||||||
|
JPorts[x] = FCEU_InitPowerpadB(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CheckSLHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetInputStuffFC(void)
|
||||||
|
{
|
||||||
|
switch (JPTypeFC)
|
||||||
|
{
|
||||||
|
case SIFC_NONE:
|
||||||
|
FCExp = 0;
|
||||||
|
break;
|
||||||
|
case SIFC_ARKANOID:
|
||||||
|
FCExp = FCEU_InitArkanoidFC();
|
||||||
|
break;
|
||||||
|
case SIFC_SHADOW:
|
||||||
|
FCExp = FCEU_InitSpaceShadow();
|
||||||
|
break;
|
||||||
|
case SIFC_OEKAKIDS:
|
||||||
|
FCExp = FCEU_InitOekaKids();
|
||||||
|
break;
|
||||||
|
case SIFC_4PLAYER:
|
||||||
|
FCExp = FCEU_InitFami4();
|
||||||
|
break;
|
||||||
|
case SIFC_FKB:
|
||||||
|
FCExp = FCEU_InitFKB();
|
||||||
|
break;
|
||||||
|
case SIFC_SUBORKB:
|
||||||
|
FCExp = FCEU_InitSuborKB();
|
||||||
|
break;
|
||||||
|
case SIFC_PEC586KB:
|
||||||
|
FCExp = FCEU_InitPEC586KB();
|
||||||
|
break;
|
||||||
|
case SIFC_HYPERSHOT:
|
||||||
|
FCExp = FCEU_InitHS();
|
||||||
|
break;
|
||||||
|
case SIFC_MAHJONG:
|
||||||
|
FCExp = FCEU_InitMahjong();
|
||||||
|
break;
|
||||||
|
case SIFC_QUIZKING:
|
||||||
|
FCExp = FCEU_InitQuizKing();
|
||||||
|
break;
|
||||||
|
case SIFC_FTRAINERA:
|
||||||
|
FCExp = FCEU_InitFamilyTrainerA();
|
||||||
|
break;
|
||||||
|
case SIFC_FTRAINERB:
|
||||||
|
FCExp = FCEU_InitFamilyTrainerB();
|
||||||
|
break;
|
||||||
|
case SIFC_BWORLD:
|
||||||
|
FCExp = FCEU_InitBarcodeWorld();
|
||||||
|
break;
|
||||||
|
case SIFC_TOPRIDER:
|
||||||
|
FCExp = FCEU_InitTopRider();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CheckSLHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeInput(void)
|
||||||
|
{
|
||||||
|
LastStrobe = 0;
|
||||||
|
|
||||||
|
if (GameInfo && GameInfo->type == GIT_VSUNI)
|
||||||
|
{
|
||||||
|
SetReadHandler(0x4016, 0x4016, VSUNIRead0);
|
||||||
|
SetReadHandler(0x4017, 0x4017, VSUNIRead1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetReadHandler(0x4016, 0x4017, JPRead);
|
||||||
|
|
||||||
|
SetWriteHandler(0x4016, 0x4016, B4016);
|
||||||
|
|
||||||
|
SetInputStuff(0);
|
||||||
|
SetInputStuff(1);
|
||||||
|
SetInputStuffFC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetInput(int port, int type, void *ptr, int attrib)
|
||||||
|
{
|
||||||
|
JPAttrib[port] = attrib;
|
||||||
|
JPType[port] = type;
|
||||||
|
InputDataPtr[port] = ptr;
|
||||||
|
SetInputStuff(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SetInputFC(int type, void *ptr, int attrib)
|
||||||
|
{
|
||||||
|
JPAttribFC = attrib;
|
||||||
|
JPTypeFC = type;
|
||||||
|
InputDataPtrFC = ptr;
|
||||||
|
SetInputStuffFC();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_DoSimpleCommand(int cmd)
|
||||||
|
{
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case FCEUNPCMD_FDSINSERT:
|
||||||
|
FCEU_FDSInsert(-1);
|
||||||
|
break;
|
||||||
|
case FCEUNPCMD_FDSSELECT:
|
||||||
|
FCEU_FDSSelect();
|
||||||
|
break;
|
||||||
|
case FCEUNPCMD_FDSEJECT:
|
||||||
|
FCEU_FDSEject();
|
||||||
|
break;
|
||||||
|
case FCEUNPCMD_VSUNICOIN:
|
||||||
|
FCEU_VSUniCoin();
|
||||||
|
break;
|
||||||
|
case FCEUNPCMD_VSUNIDIP0:
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 1):
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 2):
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 3):
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 4):
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 5):
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 6):
|
||||||
|
case (FCEUNPCMD_VSUNIDIP0 + 7):
|
||||||
|
FCEU_VSUniToggleDIP(cmd - FCEUNPCMD_VSUNIDIP0);
|
||||||
|
break;
|
||||||
|
case FCEUNPCMD_POWER:
|
||||||
|
PowerNES();
|
||||||
|
break;
|
||||||
|
case FCEUNPCMD_RESET:
|
||||||
|
ResetNES();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_QSimpleCommand(int cmd)
|
||||||
|
{
|
||||||
|
FCEU_DoSimpleCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_FDSSelect(void)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_FDSSELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEUI_FDSInsert(int oride)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_FDSINSERT);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEUI_FDSEject(void)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_FDSEJECT);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_VSUniToggleDIP(int w)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_VSUNIDIP0 + w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_VSUniCoin(void)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_ResetNES(void)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_PowerNES(void)
|
||||||
|
{
|
||||||
|
FCEU_QSimpleCommand(FCEUNPCMD_POWER);
|
||||||
|
}
|
||||||
|
|
||||||
20
src/drivers/libretro/fceu/misc.c
Normal file
20
src/drivers/libretro/fceu/misc.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "fceu.h"
|
||||||
|
|
||||||
|
#include "driver.h"
|
||||||
|
|
||||||
|
/* wave.c */
|
||||||
|
|
||||||
|
void FCEU_WriteWaveData(int32 *Buffer, int Count) { }
|
||||||
|
int FCEUI_EndWaveRecord(void) { return 0; }
|
||||||
|
int FCEUI_BeginWaveRecord(char *fn) { return 0; }
|
||||||
|
|
||||||
|
/* netplay.c */
|
||||||
|
int FCEUNET_SendFile(uint8 cmd, char *fn) { return 0; }
|
||||||
|
|
||||||
|
/* movie.c */
|
||||||
|
void FCEUMOV_AddJoy(uint8 *js) { }
|
||||||
|
void FCEUMOV_Stop(void) {}
|
||||||
|
void FCEUI_SelectMovie(int w) { }
|
||||||
409
src/drivers/libretro/fceu/state.c
Normal file
409
src/drivers/libretro/fceu/state.c
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "x6502.h"
|
||||||
|
#include "fceu.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "fceu-endian.h"
|
||||||
|
#include "fds.h"
|
||||||
|
#include "general.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "movie.h"
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
#include "ppu.h"
|
||||||
|
#include "netplay.h"
|
||||||
|
#include "video.h"
|
||||||
|
|
||||||
|
static void (*SPreSave)(void);
|
||||||
|
static void (*SPostSave)(void);
|
||||||
|
|
||||||
|
static int SaveStateStatus[10];
|
||||||
|
|
||||||
|
static SFORMAT SFMDATA[64];
|
||||||
|
static int SFEXINDEX;
|
||||||
|
|
||||||
|
#define RLSB FCEUSTATE_RLSB //0x80000000
|
||||||
|
|
||||||
|
extern SFORMAT FCEUPPU_STATEINFO[];
|
||||||
|
extern SFORMAT FCEUSND_STATEINFO[];
|
||||||
|
extern SFORMAT FCEUCTRL_STATEINFO[];
|
||||||
|
|
||||||
|
|
||||||
|
SFORMAT SFCPU[] = {
|
||||||
|
{ &X.PC, 2 | RLSB, "PC\0" },
|
||||||
|
{ &X.A, 1, "A\0\0" },
|
||||||
|
{ &X.X, 1, "X\0\0" },
|
||||||
|
{ &X.Y, 1, "Y\0\0" },
|
||||||
|
{ &X.S, 1, "S\0\0" },
|
||||||
|
{ &X.P, 1, "P\0\0" },
|
||||||
|
{ &X.DB, 1, "DB"},
|
||||||
|
#ifdef COPYFAMI
|
||||||
|
{ RAM, 0x4000, "RAM" },
|
||||||
|
#else
|
||||||
|
{ RAM, 0x800, "RAM" },
|
||||||
|
#endif
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
SFORMAT SFCPUC[] = {
|
||||||
|
{ &X.jammed, 1, "JAMM" },
|
||||||
|
{ &X.IRQlow, 4 | RLSB, "IQLB" },
|
||||||
|
{ &X.tcount, 4 | RLSB, "ICoa" },
|
||||||
|
{ &X.count, 4 | RLSB, "ICou" },
|
||||||
|
{ ×tampbase, sizeof(timestampbase) | RLSB, "TSBS" },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int SubWrite(MEM_TYPE *st, SFORMAT *sf) {
|
||||||
|
uint32 acc = 0;
|
||||||
|
|
||||||
|
while (sf->v) {
|
||||||
|
if (sf->s == ~0) { // Link to another struct.
|
||||||
|
uint32 tmp;
|
||||||
|
|
||||||
|
if (!(tmp = SubWrite(st, (SFORMAT*)sf->v)))
|
||||||
|
return(0);
|
||||||
|
acc += tmp;
|
||||||
|
sf++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
acc += 8; // Description + size
|
||||||
|
acc += sf->s & (~RLSB);
|
||||||
|
|
||||||
|
if (st) { // Are we writing or calculating the size of this block? */
|
||||||
|
fwrite(sf->desc, 1, 4, st);
|
||||||
|
write32le(sf->s & (~RLSB), st);
|
||||||
|
|
||||||
|
#ifndef LSB_FIRST
|
||||||
|
if (sf->s & RLSB)
|
||||||
|
FlipByteOrder(sf->v, sf->s & (~RLSB));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fwrite((uint8*)sf->v, 1, sf->s & (~RLSB), st);
|
||||||
|
/* Now restore the original byte order. */
|
||||||
|
#ifndef LSB_FIRST
|
||||||
|
if (sf->s & RLSB)
|
||||||
|
FlipByteOrder(sf->v, sf->s & (~RLSB));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
sf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int WriteStateChunk(MEM_TYPE *st, int type, SFORMAT *sf)
|
||||||
|
{
|
||||||
|
int bsize;
|
||||||
|
|
||||||
|
fputc(type, st);
|
||||||
|
|
||||||
|
bsize = SubWrite(0, sf);
|
||||||
|
write32le(bsize, st);
|
||||||
|
|
||||||
|
if (!SubWrite(st, sf))
|
||||||
|
return(0);
|
||||||
|
return(bsize + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
|
||||||
|
{
|
||||||
|
while (sf->v)
|
||||||
|
{
|
||||||
|
if (sf->s == ~0)
|
||||||
|
{ /* Link to another SFORMAT structure. */
|
||||||
|
SFORMAT *tmp;
|
||||||
|
if ((tmp = CheckS((SFORMAT*)sf->v, tsize, desc)))
|
||||||
|
return(tmp);
|
||||||
|
sf++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(desc, sf->desc, 4))
|
||||||
|
{
|
||||||
|
if (tsize != (sf->s & (~RLSB)))
|
||||||
|
return(0);
|
||||||
|
return(sf);
|
||||||
|
}
|
||||||
|
sf++;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReadStateChunk(MEM_TYPE *st, SFORMAT *sf, int size)
|
||||||
|
{
|
||||||
|
SFORMAT *tmp;
|
||||||
|
int temp;
|
||||||
|
temp = ftell(st);
|
||||||
|
|
||||||
|
while (ftell(st) < temp + size)
|
||||||
|
{
|
||||||
|
uint32 tsize;
|
||||||
|
char toa[4];
|
||||||
|
if (fread(toa, 1, 4, st) <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
read32le(&tsize, st);
|
||||||
|
|
||||||
|
if ((tmp = CheckS(sf, tsize, toa))) {
|
||||||
|
fread((uint8*)tmp->v, 1, tmp->s & (~RLSB), st);
|
||||||
|
|
||||||
|
#ifndef LSB_FIRST
|
||||||
|
if (tmp->s & RLSB)
|
||||||
|
FlipByteOrder(tmp->v, tmp->s & (~RLSB));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fseek(st, tsize, SEEK_CUR);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ReadStateChunks(MEM_TYPE *st, int32 totalsize)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
uint32 size;
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
while (totalsize > 0)
|
||||||
|
{
|
||||||
|
t = fgetc(st);
|
||||||
|
if (t == EOF)
|
||||||
|
break;
|
||||||
|
if (!read32le(&size, st))
|
||||||
|
break;
|
||||||
|
totalsize -= size + 5;
|
||||||
|
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (!ReadStateChunk(st, SFCPU, size))
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!ReadStateChunk(st, SFCPUC, size))
|
||||||
|
ret = 0;
|
||||||
|
else
|
||||||
|
X.mooPI = X.P; // Quick and dirty hack.
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!ReadStateChunk(st, FCEUPPU_STATEINFO, size))
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (!ReadStateChunk(st, FCEUCTRL_STATEINFO, size))
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if (!ReadStateChunk(st, FCEUSND_STATEINFO, size))
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
if (!ReadStateChunk(st, SFMDATA, size))
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (fseek(st, size, SEEK_CUR) < 0)
|
||||||
|
goto endo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endo:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int CurrentState = 0;
|
||||||
|
extern int geniestage;
|
||||||
|
|
||||||
|
int FCEUSS_SaveFP(MEM_TYPE *st)
|
||||||
|
{
|
||||||
|
static uint32 totalsize;
|
||||||
|
uint8 header[16] = { 0 };
|
||||||
|
|
||||||
|
header[0] = 'F';
|
||||||
|
header[1] = 'C';
|
||||||
|
header[2] = 'S';
|
||||||
|
header[3] = 0xFF;
|
||||||
|
|
||||||
|
header[3] = 0xFF;
|
||||||
|
FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC);
|
||||||
|
fwrite(header, 1, 16, st);
|
||||||
|
FCEUPPU_SaveState();
|
||||||
|
FCEUSND_SaveState();
|
||||||
|
totalsize = WriteStateChunk(st, 1, SFCPU);
|
||||||
|
totalsize += WriteStateChunk(st, 2, SFCPUC);
|
||||||
|
totalsize += WriteStateChunk(st, 3, FCEUPPU_STATEINFO);
|
||||||
|
totalsize += WriteStateChunk(st, 4, FCEUCTRL_STATEINFO);
|
||||||
|
totalsize += WriteStateChunk(st, 5, FCEUSND_STATEINFO);
|
||||||
|
if (SPreSave)
|
||||||
|
SPreSave();
|
||||||
|
totalsize += WriteStateChunk(st, 0x10, SFMDATA);
|
||||||
|
if (SPreSave)
|
||||||
|
SPostSave();
|
||||||
|
|
||||||
|
fseek(st, 4, SEEK_SET);
|
||||||
|
write32le(totalsize, st);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUSS_Save(char *fname)
|
||||||
|
{
|
||||||
|
MEM_TYPE *st = NULL;
|
||||||
|
char *fn;
|
||||||
|
|
||||||
|
if (geniestage == 1)
|
||||||
|
{
|
||||||
|
FCEU_DispMessage("Cannot save FCS in GG screen.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
st = (MEM_TYPE*)memstream_open(1);
|
||||||
|
|
||||||
|
FCEUSS_SaveFP(st);
|
||||||
|
|
||||||
|
SaveStateStatus[CurrentState] = 1;
|
||||||
|
fclose(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEUSS_LoadFP(MEM_TYPE *st)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
uint8 header[16];
|
||||||
|
int stateversion;
|
||||||
|
|
||||||
|
fread(&header, 1, 16, st);
|
||||||
|
if (memcmp(header, "FCS", 3))
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
if (header[3] == 0xFF)
|
||||||
|
stateversion = FCEU_de32lsb(header + 8);
|
||||||
|
else
|
||||||
|
stateversion = header[3] * 100;
|
||||||
|
|
||||||
|
x = ReadStateChunks(st, *(uint32*)(header + 4));
|
||||||
|
if (stateversion < 9500)
|
||||||
|
X.IRQlow = 0;
|
||||||
|
|
||||||
|
if (GameStateRestore)
|
||||||
|
GameStateRestore(stateversion);
|
||||||
|
if (x)
|
||||||
|
{
|
||||||
|
FCEUPPU_LoadState(stateversion);
|
||||||
|
FCEUSND_LoadState(stateversion);
|
||||||
|
}
|
||||||
|
return(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEUSS_Load(char *fname)
|
||||||
|
{
|
||||||
|
MEM_TYPE *st;
|
||||||
|
char *fn;
|
||||||
|
|
||||||
|
st = (MEM_TYPE*)memstream_open(0);
|
||||||
|
|
||||||
|
if (FCEUSS_LoadFP(st))
|
||||||
|
{
|
||||||
|
SaveStateStatus[CurrentState] = 1;
|
||||||
|
fclose(st);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SaveStateStatus[CurrentState] = 1;
|
||||||
|
fclose(st);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUSS_CheckStates(void)
|
||||||
|
{
|
||||||
|
MEM_TYPE *st = NULL;
|
||||||
|
char *fn;
|
||||||
|
int ssel;
|
||||||
|
|
||||||
|
for (ssel = 0; ssel < 10; ssel++)
|
||||||
|
{
|
||||||
|
st = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_STATE, ssel, 0), "rb");
|
||||||
|
free(fn);
|
||||||
|
if (st)
|
||||||
|
{
|
||||||
|
SaveStateStatus[ssel] = 1;
|
||||||
|
fclose(st);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SaveStateStatus[ssel] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentState = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
|
||||||
|
{
|
||||||
|
SPreSave = PreSave;
|
||||||
|
SPostSave = PostSave;
|
||||||
|
SFEXINDEX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddExState(void *v, uint32 s, int type, char *desc)
|
||||||
|
{
|
||||||
|
memset(SFMDATA[SFEXINDEX].desc, 0, sizeof(SFMDATA[SFEXINDEX].desc));
|
||||||
|
if (desc)
|
||||||
|
strncpy(SFMDATA[SFEXINDEX].desc, desc, sizeof(SFMDATA[SFEXINDEX].desc));
|
||||||
|
SFMDATA[SFEXINDEX].v = v;
|
||||||
|
SFMDATA[SFEXINDEX].s = s;
|
||||||
|
if (type) SFMDATA[SFEXINDEX].s |= RLSB;
|
||||||
|
if (SFEXINDEX < 63) SFEXINDEX++;
|
||||||
|
SFMDATA[SFEXINDEX].v = 0; // End marker.
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SelectState(int w)
|
||||||
|
{
|
||||||
|
if (w == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CurrentState = w;
|
||||||
|
FCEU_DispMessage("-select state-");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_SaveState(char *fname)
|
||||||
|
{
|
||||||
|
FCEUSS_Save(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEUI_LoadState(char *fname)
|
||||||
|
{
|
||||||
|
FCEUSS_Load(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_DrawSaveStates(uint8 *XBuf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
109
src/drivers/libretro/fceu/video.c
Normal file
109
src/drivers/libretro/fceu/video.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/* FCE Ultra - NES/Famicom Emulator
|
||||||
|
*
|
||||||
|
* Copyright notice for this file:
|
||||||
|
* Copyright (C) 2002 Xodnizel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "fceu-types.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "fceu.h"
|
||||||
|
#include "general.h"
|
||||||
|
#include "fceu-memory.h"
|
||||||
|
#include "crc32.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "palette.h"
|
||||||
|
#include "nsf.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "vsuni.h"
|
||||||
|
|
||||||
|
uint8 *XBuf = NULL;
|
||||||
|
|
||||||
|
void FCEU_KillVirtualVideo(void)
|
||||||
|
{
|
||||||
|
if (XBuf)
|
||||||
|
free(XBuf);
|
||||||
|
XBuf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCEU_InitVirtualVideo(void)
|
||||||
|
{
|
||||||
|
// 256 bytes per scanline, * 240 scanline maximum, +8 for alignment,
|
||||||
|
if (!XBuf)
|
||||||
|
XBuf = (uint8*)(FCEU_malloc(256 * 256 + 8));
|
||||||
|
|
||||||
|
if (!XBuf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (sizeof(uint8*) == 4)
|
||||||
|
{
|
||||||
|
uint32 m;
|
||||||
|
m = *XBuf;
|
||||||
|
m = (4 - m) & 3;
|
||||||
|
XBuf += m;
|
||||||
|
}
|
||||||
|
memset(XBuf, 128, 256 * 256);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int howlong;
|
||||||
|
static char errmsg[65];
|
||||||
|
|
||||||
|
#include "drawing.h"
|
||||||
|
|
||||||
|
void FCEUI_SaveSnapshot(void) { }
|
||||||
|
|
||||||
|
void FCEU_PutImage(void)
|
||||||
|
{
|
||||||
|
if (GameInfo->type == GIT_NSF)
|
||||||
|
DrawNSF(XBuf);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GameInfo->type == GIT_VSUNI)
|
||||||
|
FCEU_VSUniDraw(XBuf);
|
||||||
|
}
|
||||||
|
if (howlong) howlong--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_PutImageDummy(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_DispMessage(char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vsprintf(errmsg, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
howlong = 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCEU_ResetMessages(void)
|
||||||
|
{
|
||||||
|
howlong = 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SaveSnapshot(void)
|
||||||
|
{
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
@@ -7,26 +7,27 @@
|
|||||||
#include "cheat.c"
|
#include "cheat.c"
|
||||||
#include "crc32.c"
|
#include "crc32.c"
|
||||||
#include "debug.c"
|
#include "debug.c"
|
||||||
#include "fceu-endian.c"
|
#include "drivers/libretro/fceu/fceu-endian.c"
|
||||||
#include "fceu-memory.c"
|
#include "drivers/libretro/fceu/fceu-memory.c"
|
||||||
#include "fceu.c"
|
#include "drivers/libretro/fceu/misc.c"
|
||||||
#include "fceustr.c"
|
#include "drivers/libretro/fceu/fceu.c"
|
||||||
|
//#include "fceustr.c"
|
||||||
#include "fds.c"
|
#include "fds.c"
|
||||||
#include "file.c"
|
#include "drivers/libretro/fceu/file.c"
|
||||||
#include "filter.c"
|
#include "filter.c"
|
||||||
#include "general.c"
|
#include "drivers/libretro/fceu/general.c"
|
||||||
#include "input.c"
|
#include "drivers/libretro/fceu/input.c"
|
||||||
#include "md5.c"
|
#include "md5.c"
|
||||||
#include "movie.c"
|
//#include "movie.c"
|
||||||
#include "netplay.c"
|
//#include "netplay.c"
|
||||||
#include "nsf.c"
|
#include "nsf.c"
|
||||||
#include "palette.c"
|
#include "palette.c"
|
||||||
#include "ppu.c"
|
#include "ppu.c"
|
||||||
#include "sound.c"
|
#include "sound.c"
|
||||||
#include "state.c"
|
#include "drivers/libretro/fceu/state.c"
|
||||||
#include "video.c"
|
#include "drivers/libretro/fceu/video.c"
|
||||||
#include "vsuni.c"
|
#include "vsuni.c"
|
||||||
#include "wave.c"
|
//#include "wave.c"
|
||||||
|
|
||||||
|
|
||||||
//#include "x6502.c"
|
//#include "x6502.c"
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ static bool use_overscan;
|
|||||||
|
|
||||||
/* emulator-specific variables */
|
/* emulator-specific variables */
|
||||||
|
|
||||||
|
int FCEUnetplay;
|
||||||
#ifdef PSP
|
#ifdef PSP
|
||||||
#include "pspgu.h"
|
#include "pspgu.h"
|
||||||
static __attribute__((aligned(16))) uint16_t retro_palette[256];
|
static __attribute__((aligned(16))) uint16_t retro_palette[256];
|
||||||
@@ -126,18 +127,18 @@ bool FCEUD_ShouldDrawInputAids (void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct retro_log_callback log;
|
static struct retro_log_callback log_cb;
|
||||||
|
|
||||||
static void default_logger(enum retro_log_level level, const char *fmt, ...) {}
|
static void default_logger(enum retro_log_level level, const char *fmt, ...) {}
|
||||||
|
|
||||||
void FCEUD_PrintError(char *c)
|
void FCEUD_PrintError(char *c)
|
||||||
{
|
{
|
||||||
log.log(RETRO_LOG_WARNING, "%s", c);
|
log_cb.log(RETRO_LOG_WARN, "%s", c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUD_Message(char *s)
|
void FCEUD_Message(char *s)
|
||||||
{
|
{
|
||||||
log.log(RETRO_LOG_INFO, "%s", s);
|
log_cb.log(RETRO_LOG_INFO, "%s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCEUD_NetworkClose(void)
|
void FCEUD_NetworkClose(void)
|
||||||
@@ -476,12 +477,12 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
|
|||||||
|
|
||||||
void retro_init(void)
|
void retro_init(void)
|
||||||
{
|
{
|
||||||
log.log=default_logger;
|
log_cb.log=default_logger;
|
||||||
environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log);
|
environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log_cb);
|
||||||
#ifdef FRONTEND_SUPPORTS_RGB565
|
#ifdef FRONTEND_SUPPORTS_RGB565
|
||||||
enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565;
|
enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565;
|
||||||
if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565))
|
if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565))
|
||||||
log.log(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
|
log_cb.log(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
|
||||||
#endif
|
#endif
|
||||||
PowerNES();
|
PowerNES();
|
||||||
}
|
}
|
||||||
@@ -520,9 +521,7 @@ static bool fceu_init(const char * full_path)
|
|||||||
{
|
{
|
||||||
char* dir=NULL;
|
char* dir=NULL;
|
||||||
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
|
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
|
||||||
{
|
|
||||||
FCEUI_SetBaseDirectory(dir);
|
FCEUI_SetBaseDirectory(dir);
|
||||||
}
|
|
||||||
|
|
||||||
FCEUI_Initialize();
|
FCEUI_Initialize();
|
||||||
|
|
||||||
@@ -532,6 +531,7 @@ static bool fceu_init(const char * full_path)
|
|||||||
GameInfo = (FCEUGI*)FCEUI_LoadGame(full_path);
|
GameInfo = (FCEUGI*)FCEUI_LoadGame(full_path);
|
||||||
if (!GameInfo)
|
if (!GameInfo)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
emulator_set_input();
|
emulator_set_input();
|
||||||
emulator_set_custom_palette();
|
emulator_set_custom_palette();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2013 The RetroArch team
|
/* Copyright (C) 2010-2014 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro API header (libretro.h).
|
* The following license statement only applies to this libretro API header (libretro.h).
|
||||||
@@ -27,11 +27,13 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
// Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant.
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#else
|
#endif
|
||||||
#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) && !defined(__cplusplus)
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
|
||||||
|
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
|
||||||
#define bool unsigned char
|
#define bool unsigned char
|
||||||
#define true 1
|
#define true 1
|
||||||
#define false 0
|
#define false 0
|
||||||
@@ -44,8 +46,22 @@ extern "C" {
|
|||||||
// It is not incremented for compatible changes to the API.
|
// It is not incremented for compatible changes to the API.
|
||||||
#define RETRO_API_VERSION 1
|
#define RETRO_API_VERSION 1
|
||||||
|
|
||||||
// Libretro's fundamental device abstractions.
|
//
|
||||||
#define RETRO_DEVICE_MASK 0xff
|
// Libretros fundamental device abstractions.
|
||||||
|
/////////
|
||||||
|
//
|
||||||
|
// Libretros input system consists of some standardized device types such as a joypad (with/without analog),
|
||||||
|
// mouse, keyboard, lightgun and a pointer. The functionality of these devices are fixed, and individual cores map
|
||||||
|
// their own concept of a controller to libretros abstractions.
|
||||||
|
// This makes it possible for frontends to map the abstract types to a real input device,
|
||||||
|
// and not having to worry about binding input correctly to arbitrary controller layouts.
|
||||||
|
|
||||||
|
|
||||||
|
#define RETRO_DEVICE_TYPE_SHIFT 8
|
||||||
|
#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1)
|
||||||
|
#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base)
|
||||||
|
|
||||||
|
// Input disabled.
|
||||||
#define RETRO_DEVICE_NONE 0
|
#define RETRO_DEVICE_NONE 0
|
||||||
|
|
||||||
// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller,
|
// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller,
|
||||||
@@ -60,6 +76,7 @@ extern "C" {
|
|||||||
|
|
||||||
// KEYBOARD device lets one poll for raw key pressed.
|
// KEYBOARD device lets one poll for raw key pressed.
|
||||||
// It is poll based, so input callback will return with the current pressed state.
|
// It is poll based, so input callback will return with the current pressed state.
|
||||||
|
// For event/text based keyboard input, see RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK.
|
||||||
#define RETRO_DEVICE_KEYBOARD 3
|
#define RETRO_DEVICE_KEYBOARD 3
|
||||||
|
|
||||||
// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse.
|
// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse.
|
||||||
@@ -85,7 +102,7 @@ extern "C" {
|
|||||||
//
|
//
|
||||||
// To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
|
// To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
|
||||||
// PRESSED returns 1 or 0.
|
// PRESSED returns 1 or 0.
|
||||||
// If using a mouse, PRESSED will usually correspond to the left mouse button.
|
// If using a mouse on a desktop, PRESSED will usually correspond to the left mouse button, but this is a frontend decision.
|
||||||
// PRESSED will only return 1 if the pointer is inside the game screen.
|
// PRESSED will only return 1 if the pointer is inside the game screen.
|
||||||
//
|
//
|
||||||
// For multi-touch, the index variable can be used to successively query more presses.
|
// For multi-touch, the index variable can be used to successively query more presses.
|
||||||
@@ -94,19 +111,6 @@ extern "C" {
|
|||||||
// Eventually _PRESSED will return false for an index. No further presses are registered at this point.
|
// Eventually _PRESSED will return false for an index. No further presses are registered at this point.
|
||||||
#define RETRO_DEVICE_POINTER 6
|
#define RETRO_DEVICE_POINTER 6
|
||||||
|
|
||||||
// FIXME: Document this.
|
|
||||||
#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7
|
|
||||||
|
|
||||||
// These device types are specializations of the base types above.
|
|
||||||
// They should only be used in retro_set_controller_type() to inform libretro implementations
|
|
||||||
// about use of a very specific device type.
|
|
||||||
//
|
|
||||||
// In input state callback, however, only the base type should be used in the 'device' field.
|
|
||||||
#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD)
|
|
||||||
#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN)
|
|
||||||
#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN)
|
|
||||||
#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN)
|
|
||||||
|
|
||||||
// Buttons for the RetroPad (JOYPAD).
|
// Buttons for the RetroPad (JOYPAD).
|
||||||
// The placement of these is equivalent to placements on the Super Nintendo controller.
|
// The placement of these is equivalent to placements on the Super Nintendo controller.
|
||||||
// L2/R2/L3/R3 buttons correspond to the PS1 DualShock.
|
// L2/R2/L3/R3 buttons correspond to the PS1 DualShock.
|
||||||
@@ -153,11 +157,6 @@ extern "C" {
|
|||||||
#define RETRO_DEVICE_ID_POINTER_Y 1
|
#define RETRO_DEVICE_ID_POINTER_Y 1
|
||||||
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
|
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
|
||||||
|
|
||||||
// Id values for SENSOR types.
|
|
||||||
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0
|
|
||||||
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1
|
|
||||||
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2
|
|
||||||
|
|
||||||
// Returned from retro_get_region().
|
// Returned from retro_get_region().
|
||||||
#define RETRO_REGION_NTSC 0
|
#define RETRO_REGION_NTSC 0
|
||||||
#define RETRO_REGION_PAL 1
|
#define RETRO_REGION_PAL 1
|
||||||
@@ -168,7 +167,7 @@ extern "C" {
|
|||||||
|
|
||||||
// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery.
|
// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery.
|
||||||
// If save game data is too complex for a single memory buffer,
|
// If save game data is too complex for a single memory buffer,
|
||||||
// the SYSTEM_DIRECTORY environment callback can be used.
|
// the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment callback can be used.
|
||||||
#define RETRO_MEMORY_SAVE_RAM 0
|
#define RETRO_MEMORY_SAVE_RAM 0
|
||||||
|
|
||||||
// Some games have a built-in clock to keep track of time.
|
// Some games have a built-in clock to keep track of time.
|
||||||
@@ -181,21 +180,6 @@ extern "C" {
|
|||||||
// Video ram lets a frontend peek into a game systems video RAM (VRAM).
|
// Video ram lets a frontend peek into a game systems video RAM (VRAM).
|
||||||
#define RETRO_MEMORY_VIDEO_RAM 3
|
#define RETRO_MEMORY_VIDEO_RAM 3
|
||||||
|
|
||||||
// Special memory types.
|
|
||||||
#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM)
|
|
||||||
#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM)
|
|
||||||
#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM)
|
|
||||||
#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM)
|
|
||||||
#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM)
|
|
||||||
#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC)
|
|
||||||
|
|
||||||
// Special game types passed into retro_load_game_special().
|
|
||||||
// Only used when multiple ROMs are required.
|
|
||||||
#define RETRO_GAME_TYPE_BSX 0x101
|
|
||||||
#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102
|
|
||||||
#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103
|
|
||||||
#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104
|
|
||||||
|
|
||||||
// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD.
|
// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD.
|
||||||
enum retro_key
|
enum retro_key
|
||||||
{
|
{
|
||||||
@@ -385,7 +369,7 @@ enum retro_mod
|
|||||||
// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash.
|
// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash.
|
||||||
#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * --
|
#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * --
|
||||||
// Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'.
|
// Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'.
|
||||||
// Should not be used for trivial messages, which should simply be logged to stderr.
|
// Should not be used for trivial messages, which should simply be logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a fallback, stderr).
|
||||||
#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) --
|
#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) --
|
||||||
// Requests the frontend to shutdown.
|
// Requests the frontend to shutdown.
|
||||||
// Should only be used if game has a specific
|
// Should only be used if game has a specific
|
||||||
@@ -421,6 +405,9 @@ enum retro_mod
|
|||||||
// If so, no such directory is defined,
|
// If so, no such directory is defined,
|
||||||
// and it's up to the implementation to find a suitable directory.
|
// and it's up to the implementation to find a suitable directory.
|
||||||
//
|
//
|
||||||
|
// NOTE: Some cores used this folder also for "save" data such as memory cards, etc, for lack of a better place to put it.
|
||||||
|
// This is now discouraged, and if possible, cores should try to use the new GET_SAVE_DIRECTORY.
|
||||||
|
//
|
||||||
#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10
|
#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10
|
||||||
// const enum retro_pixel_format * --
|
// const enum retro_pixel_format * --
|
||||||
// Sets the internal pixel format used by the implementation.
|
// Sets the internal pixel format used by the implementation.
|
||||||
@@ -568,6 +555,158 @@ enum retro_mod
|
|||||||
// struct retro_perf_callback * --
|
// struct retro_perf_callback * --
|
||||||
// Gets an interface for performance counters. This is useful for performance logging in a
|
// Gets an interface for performance counters. This is useful for performance logging in a
|
||||||
// cross-platform way and for detecting architecture-specific features, such as SIMD support.
|
// cross-platform way and for detecting architecture-specific features, such as SIMD support.
|
||||||
|
#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29
|
||||||
|
// struct retro_location_callback * --
|
||||||
|
// Gets access to the location interface.
|
||||||
|
// The purpose of this interface is to be able to retrieve location-based information from the host device,
|
||||||
|
// such as current latitude / longitude.
|
||||||
|
//
|
||||||
|
#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30
|
||||||
|
// const char ** --
|
||||||
|
// Returns the "content" directory of the frontend.
|
||||||
|
// This directory can be used to store specific assets that the core relies upon, such as art assets,
|
||||||
|
// input data, etc etc.
|
||||||
|
// The returned value can be NULL.
|
||||||
|
// If so, no such directory is defined,
|
||||||
|
// and it's up to the implementation to find a suitable directory.
|
||||||
|
//
|
||||||
|
#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31
|
||||||
|
// const char ** --
|
||||||
|
// Returns the "save" directory of the frontend.
|
||||||
|
// This directory can be used to store SRAM, memory cards, high scores, etc, if the libretro core
|
||||||
|
// cannot use the regular memory interface (retro_get_memory_data()).
|
||||||
|
//
|
||||||
|
// NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for similar things before.
|
||||||
|
// They should still check GET_SYSTEM_DIRECTORY if they want to be backwards compatible.
|
||||||
|
// The path here can be NULL. It should only be non-NULL if the frontend user has set a specific save path.
|
||||||
|
//
|
||||||
|
#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32
|
||||||
|
// const struct retro_system_av_info * --
|
||||||
|
// Sets a new av_info structure. This can only be called from within retro_run().
|
||||||
|
// This should *only* be used if the core is completely altering the internal resolutions, aspect ratios, timings, sampling rate, etc.
|
||||||
|
// Calling this can require a full reinitialization of video/audio drivers in the frontend,
|
||||||
|
// so it is important to call it very sparingly, and usually only with the users explicit consent.
|
||||||
|
// An eventual driver reinit will happen so that video and audio callbacks
|
||||||
|
// happening after this call within the same retro_run() call will target the newly initialized driver.
|
||||||
|
//
|
||||||
|
// This callback makes it possible to support configurable resolutions in games, which can be useful to
|
||||||
|
// avoid setting the "worst case" in max_width/max_height.
|
||||||
|
//
|
||||||
|
// ***HIGHLY RECOMMENDED*** Do not call this callback every time resolution changes in an emulator core if it's
|
||||||
|
// expected to be a temporary change, for the reasons of possible driver reinit.
|
||||||
|
// This call is not a free pass for not trying to provide correct values in retro_get_system_av_info().
|
||||||
|
//
|
||||||
|
// If this returns false, the frontend does not acknowledge a changed av_info struct.
|
||||||
|
#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33
|
||||||
|
// const struct retro_get_proc_address_interface * --
|
||||||
|
// Allows a libretro core to announce support for the get_proc_address() interface.
|
||||||
|
// This interface allows for a standard way to extend libretro where use of environment calls are too indirect,
|
||||||
|
// e.g. for cases where the frontend wants to call directly into the core.
|
||||||
|
//
|
||||||
|
// If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK **MUST** be called from within retro_set_environment().
|
||||||
|
//
|
||||||
|
#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34
|
||||||
|
// const struct retro_subsystem_info * --
|
||||||
|
// This environment call introduces the concept of libretro "subsystems".
|
||||||
|
// A subsystem is a variant of a libretro core which supports different kinds of games.
|
||||||
|
// The purpose of this is to support e.g. emulators which might have special needs, e.g. Super Nintendos Super GameBoy, Sufami Turbo.
|
||||||
|
// It can also be used to pick among subsystems in an explicit way if the libretro implementation is a multi-system emulator itself.
|
||||||
|
//
|
||||||
|
// Loading a game via a subsystem is done with retro_load_game_special(),
|
||||||
|
// and this environment call allows a libretro core to expose which subsystems are supported for use with retro_load_game_special().
|
||||||
|
// A core passes an array of retro_game_special_info which is terminated with a zeroed out retro_game_special_info struct.
|
||||||
|
//
|
||||||
|
// If a core wants to use this functionality, SET_SUBSYSTEM_INFO **MUST** be called from within retro_set_environment().
|
||||||
|
//
|
||||||
|
#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35
|
||||||
|
// const struct retro_controller_info * --
|
||||||
|
// This environment call lets a libretro core tell the frontend which
|
||||||
|
// controller types are recognized in calls to retro_set_controller_port_device().
|
||||||
|
//
|
||||||
|
// Some emulators such as Super Nintendo
|
||||||
|
// support multiple lightgun types which must be specifically selected from.
|
||||||
|
// It is therefore sometimes necessary for a frontend to be able to tell
|
||||||
|
// the core about a special kind of input device which is not covered by the
|
||||||
|
// libretro input API.
|
||||||
|
//
|
||||||
|
// In order for a frontend to understand the workings of an input device,
|
||||||
|
// it must be a specialized type
|
||||||
|
// of the generic device types already defined in the libretro API.
|
||||||
|
//
|
||||||
|
// Which devices are supported can vary per input port.
|
||||||
|
// The core must pass an array of const struct retro_controller_info which is terminated with
|
||||||
|
// a blanked out struct. Each element of the struct corresponds to an ascending port index to retro_set_controller_port_device().
|
||||||
|
// Even if special device types are set in the libretro core, libretro should only poll input based on the base input device types.
|
||||||
|
|
||||||
|
struct retro_controller_description
|
||||||
|
{
|
||||||
|
// Human-readable description of the controller. Even if using a generic input device type, this can be
|
||||||
|
// set to the particular device type the core uses.
|
||||||
|
const char *desc;
|
||||||
|
|
||||||
|
// Device type passed to retro_set_controller_port_device(). If the device type is a sub-class of a generic input device type,
|
||||||
|
// use the RETRO_DEVICE_SUBCLASS macro to create an ID. E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1).
|
||||||
|
unsigned id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_controller_info
|
||||||
|
{
|
||||||
|
const struct retro_controller_description *types;
|
||||||
|
unsigned num_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_subsystem_memory_info
|
||||||
|
{
|
||||||
|
const char *extension; // The extension associated with a memory type, e.g. "psram".
|
||||||
|
unsigned type; // The memory type for retro_get_memory(). This should be at least 0x100 to avoid conflict with standardized libretro memory types.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_subsystem_rom_info
|
||||||
|
{
|
||||||
|
const char *desc; // Describes what the ROM is (SGB bios, GB rom, etc).
|
||||||
|
const char *valid_extensions; // Same definition as retro_get_system_info().
|
||||||
|
bool need_fullpath; // Same definition as retro_get_system_info().
|
||||||
|
bool block_extract; // Same definition as retro_get_system_info().
|
||||||
|
bool required; // This is set if the ROM is required to load a game. If this is set to false, a zeroed-out retro_game_info can be passed.
|
||||||
|
|
||||||
|
// ROMs can have multiple associated persistent memory types (retro_get_memory()).
|
||||||
|
const struct retro_subsystem_memory_info *memory;
|
||||||
|
unsigned num_memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_subsystem_info
|
||||||
|
{
|
||||||
|
const char *desc; // Human-readable string of the subsystem type, e.g. "Super GameBoy"
|
||||||
|
// A computer friendly short string identifier for the subsystem type.
|
||||||
|
// This name must be [a-z].
|
||||||
|
// E.g. if desc is "Super GameBoy", this can be "sgb".
|
||||||
|
// This identifier can be used for command-line interfaces, etc.
|
||||||
|
const char *ident;
|
||||||
|
|
||||||
|
// Infos for each ROM. The first entry is assumed to be the "most significant" ROM for frontend purposes.
|
||||||
|
// E.g. with Super GameBoy, the first ROM should be the GameBoy ROM, as it is the most "significant" ROM to a user.
|
||||||
|
// If a frontend creates new file paths based on the ROM used (e.g. savestates), it should use the path for the first ROM to do so.
|
||||||
|
const struct retro_subsystem_rom_info *roms;
|
||||||
|
|
||||||
|
unsigned num_roms; // Number of ROMs associated with a subsystem.
|
||||||
|
unsigned id; // The type passed to retro_load_game_special().
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*retro_proc_address_t)(void);
|
||||||
|
// libretro API extension functions:
|
||||||
|
// (None here so far).
|
||||||
|
//////
|
||||||
|
|
||||||
|
// Get a symbol from a libretro core.
|
||||||
|
// Cores should only return symbols which are actual extensions to the libretro API.
|
||||||
|
// Frontends should not use this to obtain symbols to standard libretro entry points (static linking or dlsym).
|
||||||
|
// The symbol name must be equal to the function name, e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo".
|
||||||
|
// The returned function pointer must be cast to the corresponding type.
|
||||||
|
typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym);
|
||||||
|
struct retro_get_proc_address_interface
|
||||||
|
{
|
||||||
|
retro_get_proc_address_t get_proc_address;
|
||||||
|
};
|
||||||
|
|
||||||
enum retro_log_level
|
enum retro_log_level
|
||||||
{
|
{
|
||||||
@@ -598,6 +737,13 @@ struct retro_log_callback
|
|||||||
#define RETRO_SIMD_NEON (1 << 5)
|
#define RETRO_SIMD_NEON (1 << 5)
|
||||||
#define RETRO_SIMD_SSE3 (1 << 6)
|
#define RETRO_SIMD_SSE3 (1 << 6)
|
||||||
#define RETRO_SIMD_SSSE3 (1 << 7)
|
#define RETRO_SIMD_SSSE3 (1 << 7)
|
||||||
|
#define RETRO_SIMD_MMX (1 << 8)
|
||||||
|
#define RETRO_SIMD_MMXEXT (1 << 9)
|
||||||
|
#define RETRO_SIMD_SSE4 (1 << 10)
|
||||||
|
#define RETRO_SIMD_SSE42 (1 << 11)
|
||||||
|
#define RETRO_SIMD_AVX2 (1 << 12)
|
||||||
|
#define RETRO_SIMD_VFPU (1 << 13)
|
||||||
|
#define RETRO_SIMD_PS (1 << 14)
|
||||||
|
|
||||||
typedef uint64_t retro_perf_tick_t;
|
typedef uint64_t retro_perf_tick_t;
|
||||||
typedef int64_t retro_time_t;
|
typedef int64_t retro_time_t;
|
||||||
@@ -683,10 +829,17 @@ enum retro_sensor_action
|
|||||||
RETRO_SENSOR_DUMMY = INT_MAX
|
RETRO_SENSOR_DUMMY = INT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Id values for SENSOR types.
|
||||||
|
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
||||||
|
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
||||||
|
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
||||||
|
|
||||||
typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate);
|
typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate);
|
||||||
|
typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id);
|
||||||
struct retro_sensor_interface
|
struct retro_sensor_interface
|
||||||
{
|
{
|
||||||
retro_set_sensor_state_t set_sensor_state;
|
retro_set_sensor_state_t set_sensor_state;
|
||||||
|
retro_sensor_get_input_t get_sensor_input;
|
||||||
};
|
};
|
||||||
////
|
////
|
||||||
|
|
||||||
@@ -743,6 +896,41 @@ struct retro_camera_callback
|
|||||||
retro_camera_lifetime_status_t deinitialized;
|
retro_camera_lifetime_status_t deinitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Sets the interval of time and/or distance at which to update/poll location-based data.
|
||||||
|
// To ensure compatibility with all location-based implementations, values for both
|
||||||
|
// interval_ms and interval_distance should be provided.
|
||||||
|
// interval_ms is the interval expressed in milliseconds.
|
||||||
|
// interval_distance is the distance interval expressed in meters.
|
||||||
|
typedef void (*retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance);
|
||||||
|
|
||||||
|
// Start location services. The device will start listening for changes to the
|
||||||
|
// current location at regular intervals (which are defined with retro_location_set_interval_t).
|
||||||
|
typedef bool (*retro_location_start_t)(void);
|
||||||
|
|
||||||
|
// Stop location services. The device will stop listening for changes to the current
|
||||||
|
// location.
|
||||||
|
typedef void (*retro_location_stop_t)(void);
|
||||||
|
|
||||||
|
// Get the position of the current location. Will set parameters to 0 if no new
|
||||||
|
// location update has happened since the last time.
|
||||||
|
typedef bool (*retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy,
|
||||||
|
double *vert_accuracy);
|
||||||
|
|
||||||
|
// Callback which signals when the location driver is initialized and/or deinitialized.
|
||||||
|
// retro_location_start_t can be called in initialized callback.
|
||||||
|
typedef void (*retro_location_lifetime_status_t)(void);
|
||||||
|
|
||||||
|
struct retro_location_callback
|
||||||
|
{
|
||||||
|
retro_location_start_t start;
|
||||||
|
retro_location_stop_t stop;
|
||||||
|
retro_location_get_position_t get_position;
|
||||||
|
retro_location_set_interval_t set_interval;
|
||||||
|
|
||||||
|
retro_location_lifetime_status_t initialized;
|
||||||
|
retro_location_lifetime_status_t deinitialized;
|
||||||
|
};
|
||||||
|
|
||||||
enum retro_rumble_effect
|
enum retro_rumble_effect
|
||||||
{
|
{
|
||||||
RETRO_RUMBLE_STRONG = 0,
|
RETRO_RUMBLE_STRONG = 0,
|
||||||
@@ -802,7 +990,6 @@ typedef void (*retro_hw_context_reset_t)(void);
|
|||||||
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
|
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
|
||||||
|
|
||||||
// Get a symbol from HW context.
|
// Get a symbol from HW context.
|
||||||
typedef void (*retro_proc_address_t)(void);
|
|
||||||
typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
|
typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
|
||||||
|
|
||||||
enum retro_hw_context_type
|
enum retro_hw_context_type
|
||||||
@@ -1063,6 +1250,8 @@ void retro_get_system_info(struct retro_system_info *info);
|
|||||||
void retro_get_system_av_info(struct retro_system_av_info *info);
|
void retro_get_system_av_info(struct retro_system_av_info *info);
|
||||||
|
|
||||||
// Sets device to be used for player 'port'.
|
// Sets device to be used for player 'port'.
|
||||||
|
// By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all available ports.
|
||||||
|
// Setting a particular device type is not a guarantee that libretro cores will only poll input based on that particular device type. It is only a hint to the libretro core when a core cannot automatically detect the appropriate input device type on its own. It is also relevant when a core can change its behavior depending on device type.
|
||||||
void retro_set_controller_port_device(unsigned port, unsigned device);
|
void retro_set_controller_port_device(unsigned port, unsigned device);
|
||||||
|
|
||||||
// Resets the current game.
|
// Resets the current game.
|
||||||
|
|||||||
Reference in New Issue
Block a user