1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
@@ -3,11 +3,7 @@ INCFLAGS := -I$(CORE_DIR)/drivers/libretro -I$(LIBRETRO_COMM_DIR)/include -
|
||||
COREDEFINES = -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DFCEU_VERSION_NUMERIC=9813 -DFRONTEND_SUPPORTS_RGB565
|
||||
|
||||
INCLUDE_STDINT = 0
|
||||
ifneq (,$(findstring msvc2003,$(platform)))
|
||||
INCLUDE_STDINT = 1
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring msvc2005,$(platform)))
|
||||
ifneq (,$(findstring msvc200,$(platform)))
|
||||
INCLUDE_STDINT = 1
|
||||
endif
|
||||
|
||||
@@ -17,8 +13,6 @@ endif
|
||||
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
COREDEFINES += -DINLINE=_inline
|
||||
else
|
||||
COREDEFINES += -DINLINE=inline
|
||||
endif
|
||||
|
||||
ifeq ($(PSS_STYLE),2)
|
||||
|
||||
@@ -4,6 +4,7 @@ EXTERNAL_ZLIB=0
|
||||
HAVE_GRIFFIN=1
|
||||
STATIC_LINKING=0
|
||||
ENDIANNESS_DEFINES=
|
||||
SIGNED_CHAR=0
|
||||
|
||||
SPACE :=
|
||||
SPACE := $(SPACE) $(SPACE)
|
||||
@@ -13,6 +14,7 @@ filter_out1 = $(filter-out $(firstword $1),$1)
|
||||
filter_out2 = $(call filter_out1,$(call filter_out1,$1))
|
||||
unixpath = $(subst \,/,$1)
|
||||
unixcygpath = /$(subst :,,$(call unixpath,$1))
|
||||
RETROARCH_OBJECTS :=
|
||||
|
||||
ifeq ($(platform),)
|
||||
platform = unix
|
||||
@@ -154,6 +156,21 @@ else ifeq ($(platform), sncps3)
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
|
||||
# PS2
|
||||
else ifeq ($(platform), ps2)
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
CC = ee-gcc$(EXE_EXT)
|
||||
AR = ee-ar$(EXE_EXT)
|
||||
FCEU_DEFINES := -DPATH_MAX=1024 -DINLINE=inline -DPSS_STYLE=1 -DFCEU_VERSION_NUMERIC=9813 -DHAVE_ASPRINTF
|
||||
ENDIANNESS_DEFINES := -DLSB_FIRST -DLOCAL_LE=1
|
||||
PLATFORM_DEFINES := -DPS2 -G0 -DFRONTEND_SUPPORTS_ABGR1555 -DRENDER_GSKIT_PS2
|
||||
PLATFORM_DEFINES += -Dmemcpy=mips_memcpy -Dmemset=mips_memset
|
||||
PLATFORM_DEFINES += -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -Ips2/ -I$(PS2DEV)/gsKit/include
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
|
||||
RETROARCH_OBJECTS += ps2/SMS_Utils.o
|
||||
|
||||
# PSP
|
||||
else ifeq ($(platform), psp1)
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||
@@ -255,6 +272,7 @@ else ifeq ($(platform), wii)
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
SIGNED_CHAR=1
|
||||
|
||||
# Nintendo WiiU
|
||||
else ifeq ($(platform), wiiu)
|
||||
@@ -266,6 +284,7 @@ else ifeq ($(platform), wiiu)
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
STATIC_LINKING=1
|
||||
EXTERNAL_ZLIB=1
|
||||
SIGNED_CHAR=1
|
||||
|
||||
# Nintendo Switch (libtransistor)
|
||||
else ifeq ($(platform), switch)
|
||||
@@ -366,9 +385,21 @@ else ifeq ($(platform), gcw0)
|
||||
SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined
|
||||
PLATFORM_DEFINES += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float
|
||||
EXTERNAL_ZLIB = 1
|
||||
|
||||
|
||||
# Genode
|
||||
else ifeq ($(platform), genode)
|
||||
TARGET := $(TARGET_NAME)_libretro.lib.so
|
||||
CC := $(shell pkg-config genode-base --variable=cc)
|
||||
LD := $(shell pkg-config genode-base --variable=ld)
|
||||
CFLAGS += $(shell pkg-config --cflags genode-libc)
|
||||
LDFLAGS += -shared --version-script=src/drivers/libretro/link.T
|
||||
LDFLAGS += $(shell pkg-config --libs genode-lib genode-libc)
|
||||
LIBM =
|
||||
|
||||
# Windows MSVC 2017 all architectures
|
||||
else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
CC = cl.exe
|
||||
CXX = cl.exe
|
||||
|
||||
PlatformSuffix = $(subst windows_msvc2017_,,$(platform))
|
||||
ifneq (,$(findstring desktop,$(PlatformSuffix)))
|
||||
@@ -388,8 +419,6 @@ else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
|
||||
TargetArchMoniker = $(subst $(WinPartition)_,,$(PlatformSuffix))
|
||||
|
||||
CC = cl.exe
|
||||
CXX = cl.exe
|
||||
LD = link.exe
|
||||
|
||||
reg_query = $(call filter_out2,$(subst $2,,$(shell reg query "$2" -v "$1" 2>nul)))
|
||||
@@ -530,6 +559,26 @@ CXXFLAGS += -D_XBOX -D_XBOX360
|
||||
ENDIANNESS_DEFINES += -DMSB_FIRST
|
||||
STATIC_LINKING=1
|
||||
|
||||
# Windows MSVC 2008 x86
|
||||
else ifeq ($(platform), windows_msvc2008_x86)
|
||||
CC = cl.exe
|
||||
CXX = cl.exe
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/include")
|
||||
LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS90COMNTOOLS)../../VC/lib")
|
||||
BIN := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin")
|
||||
|
||||
WindowsSdkDir := $(INETSDK)
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
CFLAGS += -D_CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
# Windows MSVC 2005 x86
|
||||
else ifeq ($(platform), windows_msvc2005_x86)
|
||||
CC = cl.exe
|
||||
@@ -543,7 +592,7 @@ BIN := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin")
|
||||
|
||||
WindowsSdkDir := $(INETSDK)
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include;src/drivers/libretro/msvc/msvc-2005
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
@@ -563,7 +612,7 @@ BIN := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin")
|
||||
|
||||
WindowsSdkDir := $(INETSDK)
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include;src/drivers/libretro/msvc/msvc-2005
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
@@ -616,6 +665,10 @@ ifeq ($(EXTERNAL_ZLIB), 1)
|
||||
CFLAGS += -DHAVE_EXTERNAL_ZLIB
|
||||
endif
|
||||
|
||||
ifeq ($(SIGNED_CHAR), 1)
|
||||
CFLAGS += -fsigned-char
|
||||
endif
|
||||
|
||||
CORE_DIR := src
|
||||
|
||||
include Makefile.common
|
||||
@@ -623,6 +676,7 @@ include Makefile.common
|
||||
CFLAGS += -DWANT_GRIFFIN
|
||||
|
||||
OBJECTS := $(SOURCES_C:.c=.o)
|
||||
OBJECTS += $(RETROARCH_OBJECTS)
|
||||
|
||||
DEFINES := $(COREDEFINES) $(PLATFORM_DEFINES)
|
||||
|
||||
@@ -660,6 +714,9 @@ else ifeq ($(platform), switch)
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
# libtransistor.mk sets LD for us
|
||||
else ifeq ($(platform), genode)
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
else
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
@@ -674,7 +731,6 @@ include $(THEOS_MAKE_PATH)/library.mk
|
||||
else
|
||||
all: $(TARGET)
|
||||
$(TARGET): $(OBJECTS)
|
||||
@echo "** BUILDING $(TARGET) FOR PLATFORM $(platform) **"
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
$(LD) $(LINKOUT)$@ $(OBJECTS)
|
||||
@@ -684,11 +740,15 @@ endif
|
||||
else
|
||||
$(LD) $(LINKOUT)$@ $(SHARED) $(OBJECTS) $(LDFLAGS) $(LIBS)
|
||||
endif
|
||||
@echo "** BUILD SUCCESSFUL! GG NO RE **"
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(OBJOUT)$@ $< $(CFLAGS) $(INCFLAGS)
|
||||
|
||||
ifeq ($(platform), ps2)
|
||||
%.o: %.s
|
||||
ee-as -G0 $< -o $@
|
||||
endif
|
||||
|
||||
clean-objs:
|
||||
rm -f $(OBJECTS)
|
||||
|
||||
|
||||
202
ps2/SMS_Utils.s
Normal file
202
ps2/SMS_Utils.s
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
# ___ _ _ ___
|
||||
# | | | | |
|
||||
# ___| | | ___| PS2DEV Open Source Project.
|
||||
#----------------------------------------------------------
|
||||
# MUL64 is pulled from some binary library (I don't remember which one).
|
||||
# mips_memcpy routine is pulled from 'sde' library from MIPS.
|
||||
#
|
||||
*/
|
||||
.set noat
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
|
||||
.globl MUL64
|
||||
.globl mips_memcpy
|
||||
.globl mips_memset
|
||||
|
||||
.text
|
||||
|
||||
MUL64:
|
||||
pmultuw $v0, $a0, $a1
|
||||
dsra32 $a2, $a0, 0
|
||||
dsra32 $v1, $a1, 0
|
||||
mult $v1, $a0, $v1
|
||||
mult1 $a2, $a2, $a1
|
||||
addu $v1, $v1, $a2
|
||||
dsll32 $v1, $v1, 0
|
||||
jr $ra
|
||||
daddu $v0, $v0, $v1
|
||||
|
||||
mips_memcpy:
|
||||
addu $v0, $a0, $zero
|
||||
beqz $a2, 1f
|
||||
sltiu $t2, $a2, 12
|
||||
bnez $t2, 2f
|
||||
xor $v1, $a1, $a0
|
||||
andi $v1, $v1, 7
|
||||
negu $a3, $a0
|
||||
beqz $v1, 3f
|
||||
andi $a3, $a3, 7
|
||||
beqz $a3, 4f
|
||||
subu $a2, $a2, $a3
|
||||
ldr $v1, 0($a1)
|
||||
ldl $v1, 7($a1)
|
||||
addu $a1, $a1, $a3
|
||||
sdr $v1, 0($a0)
|
||||
addu $a0, $a0, $a3
|
||||
4:
|
||||
andi $v1, $a2, 31
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 5f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
6:
|
||||
ldr $v1, 0($a1)
|
||||
ldl $v1, 7($a1)
|
||||
ldr $t0, 8($a1)
|
||||
ldl $t0, 15($a1)
|
||||
ldr $t1, 16($a1)
|
||||
ldl $t1, 23($a1)
|
||||
ldr $t2, 24($a1)
|
||||
ldl $t2, 31($a1)
|
||||
sd $v1, 0($a0)
|
||||
sd $t0, 8($a0)
|
||||
sd $t1, 16($a0)
|
||||
addiu $a1, $a1, 32
|
||||
addiu $a0, $a0, 32
|
||||
bne $a1, $a3, 6b
|
||||
sd $t2, -8($a0)
|
||||
5:
|
||||
andi $v1, $a2, 7
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 2f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
7:
|
||||
ldr $v1, 0($a1)
|
||||
ldl $v1, 7($a1)
|
||||
addiu $a1, $a1, 8
|
||||
addiu $a0, $a0, 8
|
||||
nop
|
||||
bne $a1, $a3, 7b
|
||||
sd $v1, -8($a0)
|
||||
beq $zero, $zero, 2f
|
||||
nop
|
||||
3:
|
||||
beqz $a3, 8f
|
||||
subu $a2, $a2, $a3
|
||||
ldr $v1, 0($a1)
|
||||
addu $a1, $a1, $a3
|
||||
sdr $v1, 0($a0)
|
||||
addu $a0, $a0, $a3
|
||||
8:
|
||||
andi $v1, $a2, 31
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 9f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
10:
|
||||
ld $v1, 0($a1)
|
||||
ld $t0, 8($a1)
|
||||
ld $t1, 16($a1)
|
||||
ld $t2, 24($a1)
|
||||
sd $v1, 0($a0)
|
||||
sd $t0, 8($a0)
|
||||
sd $t1, 16($a0)
|
||||
addiu $a1, $a1, 32
|
||||
addiu $a0, $a0, 32
|
||||
bne $a1, $a3, 10b
|
||||
sd $t2, -8($a0)
|
||||
9:
|
||||
andi $v1, $a2, 7
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 2f
|
||||
addu $a2, $v1, $zero
|
||||
addu $a3, $a3, $a1
|
||||
11:
|
||||
ld $v1, 0($a1)
|
||||
addiu $a1, $a1, 8
|
||||
addiu $a0, $a0, 8
|
||||
nop
|
||||
nop
|
||||
bne $a1, $a3, 11b
|
||||
sd $v1, -8($a0)
|
||||
2:
|
||||
beqz $a2, 1f
|
||||
addu $a3, $a2, $a1
|
||||
12:
|
||||
lbu $v1, 0($a1)
|
||||
addiu $a1, $a1, 1
|
||||
addiu $a0, $a0, 1
|
||||
nop
|
||||
nop
|
||||
bne $a1, $a3, 12b
|
||||
sb $v1, -1($a0)
|
||||
1:
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
mips_memset:
|
||||
beqz $a2, 1f
|
||||
sltiu $at, $a2, 16
|
||||
bnez $at, 2f
|
||||
andi $a1, $a1, 0xFF
|
||||
dsll $at, $a1, 0x8
|
||||
or $a1, $a1, $at
|
||||
dsll $at, $a1, 0x10
|
||||
or $a1, $a1, $at
|
||||
dsll32 $at, $a1, 0x0
|
||||
or $a1, $a1, $at
|
||||
andi $v1, $a0, 0x7
|
||||
beqz $v1, 3f
|
||||
li $a3, 8
|
||||
subu $a3, $a3, $v1
|
||||
subu $a2, $a2, $a3
|
||||
sdr $a1, 0($a0)
|
||||
addu $a0, $a0, $a3
|
||||
3:
|
||||
andi $v1, $a2, 0x1f
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 4f
|
||||
move $a2, $v1
|
||||
addu $a3, $a3, $a0
|
||||
5:
|
||||
sd $a1, 0($a0)
|
||||
sd $a1, 8($a0)
|
||||
sd $a1, 16($a0)
|
||||
addiu $a0, $a0, 32
|
||||
sd $a1, -8($a0)
|
||||
bne $a0, $a3, 5b
|
||||
4:
|
||||
andi $v1, $a2, 0x7
|
||||
subu $a3, $a2, $v1
|
||||
beqz $a3, 2f
|
||||
move $a2, $v1
|
||||
addu $a3, $a3, $a0
|
||||
6:
|
||||
addiu $a0, $a0, 8
|
||||
beq $a0, $a3, 2f
|
||||
sd $a1, -8($a0)
|
||||
addiu $a0, $a0, 8
|
||||
beq $a0, $a3, 2f
|
||||
sd $a1, -8($a0)
|
||||
addiu $a0, $a0, 8
|
||||
bne $a0, $a3, 6b
|
||||
sd $a1, -8($a0)
|
||||
2:
|
||||
beqz $a2, 1f
|
||||
addu $a3, $a2, $a0
|
||||
7:
|
||||
addiu $a0, $a0, 1
|
||||
beq $a0, $a3, 1f
|
||||
sb $a1, -1($a0)
|
||||
addiu $a0, $a0, 1
|
||||
beq $a0, $a3, 1f
|
||||
sb $a1, -1($a0)
|
||||
addiu $a0, $a0, 1
|
||||
bne $a0, $a3, 7b
|
||||
sb $a1, -1($a0)
|
||||
1:
|
||||
jr $ra
|
||||
nop
|
||||
8
ps2/inttypes.h
Normal file
8
ps2/inttypes.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef INTTYPES_H
|
||||
#define INTTYPES_H
|
||||
|
||||
#define PRId64 "ld"
|
||||
#define PRIu64 "lu"
|
||||
#define PRIuPTR "lu"
|
||||
|
||||
#endif //INTTYPES_H
|
||||
33
ps2/stdint.h
Normal file
33
ps2/stdint.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef STDINT_H
|
||||
#define STDINT_H
|
||||
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef signed long intptr_t;
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long uint64_t;
|
||||
|
||||
typedef unsigned long uint_least32_t;
|
||||
typedef unsigned short uint_least16_t;
|
||||
|
||||
#define STDIN_FILENO 0 /* standard input file descriptor */
|
||||
#define STDOUT_FILENO 1 /* standard output file descriptor */
|
||||
#define STDERR_FILENO 2 /* standard error file descriptor */
|
||||
|
||||
#define INT8_C(val) val##c
|
||||
#define INT16_C(val) val##h
|
||||
#define INT32_C(val) val##i
|
||||
#define INT64_C(val) val##l
|
||||
|
||||
#define UINT8_C(val) val##uc
|
||||
#define UINT16_C(val) val##uh
|
||||
#define UINT32_C(val) val##ui
|
||||
#define UINT64_C(val) val##ul
|
||||
|
||||
#endif //STDINT_H
|
||||
102
src/boards/69.c
102
src/boards/69.c
@@ -27,6 +27,8 @@ static int32 IRQCount;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
static void(*sfun[3]) (void);
|
||||
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ &cmdreg, 1, "CMDR" },
|
||||
@@ -41,7 +43,7 @@ static SFORMAT StateRegs[] =
|
||||
static void Sync(void) {
|
||||
uint8 i;
|
||||
if ((preg[3] & 0xC0) == 0xC0)
|
||||
setprg8r(0x10, 0x6000, 0);
|
||||
setprg8r(0x10, 0x6000, preg[3] & 0x3F);
|
||||
else
|
||||
setprg8(0x6000, preg[3] & 0x3F);
|
||||
setprg8(0x8000, preg[0]);
|
||||
@@ -89,9 +91,6 @@ static DECLFW(M69Write1) {
|
||||
case 0xA: preg[1] = V; Sync(); break;
|
||||
case 0xB: preg[2] = V; Sync(); break;
|
||||
case 0xC: mirr = V & 3; Sync();break;
|
||||
/* 17/10/17- reg $0D should awknowledge IRQ and no other
|
||||
* http://forums.nesdev.com/viewtopic.php?f=2&t=12436&start=15
|
||||
*/
|
||||
case 0xD: IRQa = V; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xE: IRQCount &= 0xFF00; IRQCount |= V; break;
|
||||
case 0xF: IRQCount &= 0x00FF; IRQCount |= V << 8; break;
|
||||
@@ -114,6 +113,20 @@ static SFORMAT SStateRegs[] =
|
||||
{
|
||||
{ &sndcmd, 1, "SCMD" },
|
||||
{ sreg, 14, "SREG" },
|
||||
|
||||
/* Ignoring these sound state files for Wii since it causes states unable to load */
|
||||
#ifndef GEKKO
|
||||
{ &dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" },
|
||||
{ &dcount[1], 4 | FCEUSTATE_RLSB, "DCT1" },
|
||||
{ &dcount[2], 4 | FCEUSTATE_RLSB, "DCT2" },
|
||||
{ &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" },
|
||||
{ &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" },
|
||||
{ &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" },
|
||||
{ &CAYBC[0], 4 | FCEUSTATE_RLSB, "BC00" },
|
||||
{ &CAYBC[1], 4 | FCEUSTATE_RLSB, "BC01" },
|
||||
{ &CAYBC[2], 4 | FCEUSTATE_RLSB, "BC02" },
|
||||
#endif
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -125,22 +138,21 @@ static DECLFW(M69SWrite1) {
|
||||
int x;
|
||||
GameExpSound.Fill = AYSound;
|
||||
GameExpSound.HiFill = AYSoundHQ;
|
||||
if (FSettings.SndRate)
|
||||
switch (sndcmd) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 8: if (FSettings.soundq >= 1) DoAYSQHQ(0); else DoAYSQ(0); break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 9: if (FSettings.soundq >= 1) DoAYSQHQ(1); else DoAYSQ(1); break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 10: if (FSettings.soundq >= 1) DoAYSQHQ(2); else DoAYSQ(2); break;
|
||||
case 7:
|
||||
for (x = 0; x < 2; x++)
|
||||
if (FSettings.soundq >= 1) DoAYSQHQ(x); else DoAYSQ(x);
|
||||
break;
|
||||
}
|
||||
switch (sndcmd) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 8: if (sfun[0]) sfun[0](); break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 9: if (sfun[1]) sfun[1](); break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 10: if (sfun[2]) sfun[2](); break;
|
||||
case 7:
|
||||
if (sfun[0]) sfun[0]();
|
||||
if (sfun[1]) sfun[1]();
|
||||
break;
|
||||
}
|
||||
sreg[sndcmd] = V;
|
||||
}
|
||||
|
||||
@@ -190,19 +202,43 @@ static void DoAYSQHQ(int x) {
|
||||
CAYBC[x] = SOUNDTS;
|
||||
}
|
||||
|
||||
static void DoAYSQ1(void) {
|
||||
DoAYSQ(0);
|
||||
}
|
||||
|
||||
static void DoAYSQ2(void) {
|
||||
DoAYSQ(1);
|
||||
}
|
||||
|
||||
static void DoAYSQ3(void) {
|
||||
DoAYSQ(2);
|
||||
}
|
||||
|
||||
static void DoAYSQ1HQ(void) {
|
||||
DoAYSQHQ(0);
|
||||
}
|
||||
|
||||
static void DoAYSQ2HQ(void) {
|
||||
DoAYSQHQ(1);
|
||||
}
|
||||
|
||||
static void DoAYSQ3HQ(void) {
|
||||
DoAYSQHQ(2);
|
||||
}
|
||||
|
||||
static void AYSound(int Count) {
|
||||
int x;
|
||||
DoAYSQ(0);
|
||||
DoAYSQ(1);
|
||||
DoAYSQ(2);
|
||||
DoAYSQ1();
|
||||
DoAYSQ2();
|
||||
DoAYSQ3();
|
||||
for (x = 0; x < 3; x++)
|
||||
CAYBC[x] = Count;
|
||||
}
|
||||
|
||||
static void AYSoundHQ(void) {
|
||||
DoAYSQHQ(0);
|
||||
DoAYSQHQ(1);
|
||||
DoAYSQHQ(2);
|
||||
DoAYSQ1HQ();
|
||||
DoAYSQ2HQ();
|
||||
DoAYSQ3HQ();
|
||||
}
|
||||
|
||||
static void AYHiSync(int32 ts) {
|
||||
@@ -218,6 +254,18 @@ void Mapper69_ESI(void) {
|
||||
memset(dcount, 0, sizeof(dcount));
|
||||
memset(vcount, 0, sizeof(vcount));
|
||||
memset(CAYBC, 0, sizeof(CAYBC));
|
||||
if (FSettings.SndRate) {
|
||||
if (FSettings.soundq >= 1) {
|
||||
sfun[0] = DoAYSQ1HQ;
|
||||
sfun[1] = DoAYSQ2HQ;
|
||||
sfun[2] = DoAYSQ3HQ;
|
||||
} else {
|
||||
sfun[0] = DoAYSQ1;
|
||||
sfun[1] = DoAYSQ2;
|
||||
sfun[2] = DoAYSQ3;
|
||||
}
|
||||
} else
|
||||
memset(sfun, 0, sizeof(sfun));
|
||||
}
|
||||
|
||||
/* SUNSOFT-5/FME-7 Sound */
|
||||
@@ -270,8 +318,8 @@ void Mapper69_Init(CartInfo *info) {
|
||||
}
|
||||
GameStateRestore = StateRestore;
|
||||
Mapper69_ESI();
|
||||
AddExState(&SStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
AddExState(&SStateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void NSFAY_Init(void) {
|
||||
|
||||
@@ -31,12 +31,29 @@ static int16 IRQCount, IRQLatch;
|
||||
static uint8 *WRAM = NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
|
||||
/* TODO: Clean this up. State variables are expanded for
|
||||
* big-endian compatibility when saving and loading states */
|
||||
static SFORMAT StateRegs[] =
|
||||
{
|
||||
{ reg, 16, "REGS" },
|
||||
{ ®[0], 1, "REG0" },
|
||||
{ ®[1], 1, "REG1" },
|
||||
{ ®[2], 1, "REG2" },
|
||||
{ ®[3], 1, "REG3" },
|
||||
{ ®[4], 1, "REG4" },
|
||||
{ ®[5], 1, "REG5" },
|
||||
{ ®[6], 1, "REG6" },
|
||||
{ ®[7], 1, "REG7" },
|
||||
{ ®[8], 1, "REG8" },
|
||||
{ ®[9], 1, "REG9" },
|
||||
{ ®[10], 1, "REGA" },
|
||||
{ ®[11], 1, "REGB" },
|
||||
{ ®[12], 1, "REGC" },
|
||||
{ ®[13], 1, "REGD" },
|
||||
{ ®[14], 1, "REGE" },
|
||||
{ ®[15], 1, "REGF" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
{ &IRQCount, 2, "IRQC" },
|
||||
{ &IRQLatch, 2, "IRQL" }, /* need for Famicom Jump II - Saikyou no 7 Nin (J) [!] */
|
||||
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
|
||||
{ &IRQLatch, 2 | FCEUSTATE_RLSB, "IRQL" }, /* need for Famicom Jump II - Saikyou no 7 Nin (J) [!] */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -7,20 +7,6 @@
|
||||
#include <math.h>
|
||||
#include "../fceu-types.h"
|
||||
|
||||
#ifndef INLINE
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#elif defined(_MWERKS_)
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -75,7 +75,6 @@ static void SSSNROMPower(void) {
|
||||
regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0;
|
||||
regs[7] = 0xff;
|
||||
Sync();
|
||||
memset(WRAM, 0x00, WRAMSIZE);
|
||||
/* SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite); */
|
||||
SetReadHandler(0x0800, 0x1FFF, CartBR);
|
||||
SetWriteHandler(0x0800, 0x1FFF, CartBW);
|
||||
|
||||
@@ -751,12 +751,31 @@ static void GenMMC5Reset(void) {
|
||||
FCEU_CheatAddRAM(1, 0x5c00, ExRAM);
|
||||
}
|
||||
|
||||
/* TODO: Clean this up. State variables are expanded for
|
||||
* big-endian compatibility when saving and loading states */
|
||||
static SFORMAT MMC5_StateRegs[] = {
|
||||
{ PRGBanks, 4, "PRGB" },
|
||||
{ CHRBanksA, 16, "CHRA" },
|
||||
{ CHRBanksB, 8, "CHRB" },
|
||||
{ &PRGBanks[0], 1, "PRG1" },
|
||||
{ &PRGBanks[1], 1, "PRG2" },
|
||||
{ &PRGBanks[2], 1, "PRG3" },
|
||||
{ &PRGBanks[3], 1, "PRG4" },
|
||||
|
||||
{ &CHRBanksA[0], 2 | FCEUSTATE_RLSB, "CRA1" },
|
||||
{ &CHRBanksA[1], 2 | FCEUSTATE_RLSB, "CRA2" },
|
||||
{ &CHRBanksA[2], 2 | FCEUSTATE_RLSB, "CRA3" },
|
||||
{ &CHRBanksA[3], 2 | FCEUSTATE_RLSB, "CRA4" },
|
||||
{ &CHRBanksA[4], 2 | FCEUSTATE_RLSB, "CRA5" },
|
||||
{ &CHRBanksA[5], 2 | FCEUSTATE_RLSB, "CRA6" },
|
||||
{ &CHRBanksA[6], 2 | FCEUSTATE_RLSB, "CRA7" },
|
||||
{ &CHRBanksA[7], 2 | FCEUSTATE_RLSB, "CRA8" },
|
||||
|
||||
{ &CHRBanksB[0], 2 | FCEUSTATE_RLSB, "CRB1" },
|
||||
{ &CHRBanksB[1], 2 | FCEUSTATE_RLSB, "CRB2" },
|
||||
{ &CHRBanksB[2], 2 | FCEUSTATE_RLSB, "CRB3" },
|
||||
{ &CHRBanksB[3], 2 | FCEUSTATE_RLSB, "CRB4" },
|
||||
|
||||
{ &WRAMPage, 1, "WRMP" },
|
||||
{ WRAMMaskEnable, 2, "WRME" },
|
||||
{ &WRAMMaskEnable[0], 1, "WRM1" },
|
||||
{ &WRAMMaskEnable[1], 1, "WRM2" },
|
||||
{ &mmc5ABMode, 1, "ABMD" },
|
||||
{ &IRQScanline, 1, "IRQS" },
|
||||
{ &IRQEnable, 1, "IRQE" },
|
||||
@@ -770,13 +789,25 @@ static SFORMAT MMC5_StateRegs[] = {
|
||||
{ &MMC5LineCounter, 1, "LCTR" },
|
||||
{ &mmc5psize, 1, "PSIZ" },
|
||||
{ &mmc5vsize, 1, "VSIZ" },
|
||||
{ mul, 2, "MUL2" },
|
||||
{ MMC5ROMWrProtect, 4, "WRPR" },
|
||||
{ MMC5MemIn, 5, "MEMI" },
|
||||
|
||||
{ &mul[0], 1, "MUL1" },
|
||||
{ &mul[1], 1, "MUL2" },
|
||||
|
||||
{ &MMC5ROMWrProtect[0], 1, "WRP1" },
|
||||
{ &MMC5ROMWrProtect[1], 1, "WRP2" },
|
||||
{ &MMC5ROMWrProtect[2], 1, "WRP3" },
|
||||
{ &MMC5ROMWrProtect[3], 1, "WRP4" },
|
||||
|
||||
{ &MMC5MemIn[0], 1, "MMI1" },
|
||||
{ &MMC5MemIn[1], 1, "MMI2" },
|
||||
{ &MMC5MemIn[2], 1, "MMI3" },
|
||||
{ &MMC5MemIn[3], 1, "MMI4" },
|
||||
{ &MMC5MemIn[4], 1, "MMI5" },
|
||||
|
||||
{ &MMC5Sound.wl[0], 2 | FCEUSTATE_RLSB, "SDW0" },
|
||||
{ &MMC5Sound.wl[1], 2 | FCEUSTATE_RLSB, "SDW1" },
|
||||
{ MMC5Sound.env, 2, "SDEV" },
|
||||
{ &MMC5Sound.env[0], 1, "SEV1" },
|
||||
{ &MMC5Sound.env[1], 1, "SEV2" },
|
||||
{ &MMC5Sound.enable, 1, "SDEN" },
|
||||
{ &MMC5Sound.running, 1, "SDRU" },
|
||||
{ &MMC5Sound.raw, 1, "SDRW" },
|
||||
@@ -790,6 +821,7 @@ static SFORMAT MMC5_StateRegs[] = {
|
||||
{ &MMC5Sound.BC[2], 4 | FCEUSTATE_RLSB, "BC02" },
|
||||
{ &MMC5Sound.vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" },
|
||||
{ &MMC5Sound.vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" },
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -53,10 +53,34 @@ static int is210; /* Lesser mapper. */
|
||||
static uint8 PRG[3];
|
||||
static uint8 CHR[8];
|
||||
|
||||
/* TODO: Clean this up. State variables are expanded for
|
||||
* big-endian compatibility when saving and loading states */
|
||||
static SFORMAT N106_StateRegs[] = {
|
||||
{ PRG, 3, "PRG" },
|
||||
{ CHR, 8, "CHR" },
|
||||
{ NTAPage, 4, "NTA" },
|
||||
{ &PRG[0], 1, "PRG1" },
|
||||
{ &PRG[1], 1, "PRG2" },
|
||||
{ &PRG[2], 1, "PRG3" },
|
||||
|
||||
{ &CHR[0], 1, "CHR1" },
|
||||
{ &CHR[1], 1, "CHR2" },
|
||||
{ &CHR[2], 1, "CHR3" },
|
||||
{ &CHR[3], 1, "CHR4" },
|
||||
{ &CHR[4], 1, "CHR5" },
|
||||
{ &CHR[5], 1, "CHR6" },
|
||||
{ &CHR[6], 1, "CHR7" },
|
||||
{ &CHR[7], 1, "CHR8" },
|
||||
|
||||
{ &NTAPage[0], 1, "NTA1" },
|
||||
{ &NTAPage[1], 1, "NTA2" },
|
||||
{ &NTAPage[2], 1, "NTA3" },
|
||||
{ &NTAPage[3], 1, "NTA4" },
|
||||
|
||||
{ &IRQCount, 2 | FCEUSTATE_RLSB, "IRQC" },
|
||||
{ &IRQa, 1, "IRQA" },
|
||||
|
||||
{ &dopol, 1, "GORF" },
|
||||
{ &gorfus, 1, "DOPO" },
|
||||
{ &gorko, 1, "GORK" },
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -224,6 +248,28 @@ static int32 CVBC;
|
||||
|
||||
#define TOINDEX (16 + 1)
|
||||
|
||||
static SFORMAT N106_SStateRegs[] =
|
||||
{
|
||||
{ &PlayIndex[0], 4 | FCEUSTATE_RLSB, "IDX0" },
|
||||
{ &PlayIndex[1], 4 | FCEUSTATE_RLSB, "IDX1" },
|
||||
{ &PlayIndex[2], 4 | FCEUSTATE_RLSB, "IDX2" },
|
||||
{ &PlayIndex[3], 4 | FCEUSTATE_RLSB, "IDX3" },
|
||||
{ &PlayIndex[4], 4 | FCEUSTATE_RLSB, "IDX4" },
|
||||
{ &PlayIndex[5], 4 | FCEUSTATE_RLSB, "IDX5" },
|
||||
{ &PlayIndex[6], 4 | FCEUSTATE_RLSB, "IDX6" },
|
||||
{ &PlayIndex[7], 4 | FCEUSTATE_RLSB, "IDX7" },
|
||||
{ &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" },
|
||||
{ &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" },
|
||||
{ &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" },
|
||||
{ &vcount[3], 4 | FCEUSTATE_RLSB, "VCT3" },
|
||||
{ &vcount[4], 4 | FCEUSTATE_RLSB, "VCT4" },
|
||||
{ &vcount[5], 4 | FCEUSTATE_RLSB, "VCT5" },
|
||||
{ &vcount[6], 4 | FCEUSTATE_RLSB, "VCT6" },
|
||||
{ &vcount[7], 4 | FCEUSTATE_RLSB, "VCT7" },
|
||||
{ &CVBC, 4 | FCEUSTATE_RLSB, "BC00" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* 16:15 */
|
||||
static void SyncHQ(int32 ts) {
|
||||
CVBC = ts;
|
||||
@@ -404,6 +450,7 @@ void Mapper19_Init(CartInfo *info) {
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(IRAM, 128, 0, "IRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
AddExState(N106_SStateRegs, ~0, 0, 0);
|
||||
|
||||
if (info->battery) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
|
||||
@@ -226,16 +226,16 @@ void UNROM512_Init(CartInfo *info) {
|
||||
|
||||
mirror = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2);
|
||||
switch (mirror) {
|
||||
case 0: // hard horizontal, internal
|
||||
case 0: /* hard horizontal, internal */
|
||||
SetupCartMirroring(MI_H, 1, NULL);
|
||||
break;
|
||||
case 1: // hard vertical, internal
|
||||
case 1: /* hard vertical, internal */
|
||||
SetupCartMirroring(MI_V, 1, NULL);
|
||||
break;
|
||||
case 2: // switchable 1-screen, internal (flags: 4-screen + horizontal)
|
||||
case 2: /* switchable 1-screen, internal (flags: 4-screen + horizontal) */
|
||||
SetupCartMirroring(MI_0, 0, NULL);
|
||||
break;
|
||||
case 3: // hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical)
|
||||
case 3: /* hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) */
|
||||
SetupCartMirroring(4, 1, VROM + (info->vram_size - 8192));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -44,16 +44,33 @@ static SFORMAT StateRegs[] =
|
||||
};
|
||||
|
||||
static void(*sfun[3]) (void);
|
||||
|
||||
static uint8 vpsg1[8];
|
||||
static uint8 vpsg2[4];
|
||||
static int32 cvbc[3];
|
||||
static int32 vcount[3];
|
||||
static int32 dcount[2];
|
||||
static int32 dcount[3];
|
||||
static int32 phaseacc;
|
||||
|
||||
static SFORMAT SStateRegs[] =
|
||||
{
|
||||
{ vpsg1, 8, "PSG1" },
|
||||
{ vpsg2, 4, "PSG2" },
|
||||
|
||||
/* Ignoring these sound state files for Wii since it causes states unable to load */
|
||||
#ifndef GEKKO
|
||||
/* rw - 2018-11-28 Added */
|
||||
{ &cvbc[0], 4 | FCEUSTATE_RLSB, "BC01" },
|
||||
{ &cvbc[1], 4 | FCEUSTATE_RLSB, "BC02" },
|
||||
{ &cvbc[2], 4 | FCEUSTATE_RLSB, "BC03" },
|
||||
{ &dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" },
|
||||
{ &dcount[1], 4 | FCEUSTATE_RLSB, "DCT1" },
|
||||
{ &dcount[2], 4 | FCEUSTATE_RLSB, "DCT2" },
|
||||
{ &vcount[0], 4 | FCEUSTATE_RLSB, "VCT0" },
|
||||
{ &vcount[1], 4 | FCEUSTATE_RLSB, "VCT1" },
|
||||
{ &vcount[2], 4 | FCEUSTATE_RLSB, "VCT2" },
|
||||
{ &phaseacc, 4 | FCEUSTATE_RLSB, "ACCU" },
|
||||
#endif
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -177,15 +194,20 @@ static INLINE void DoSQV(int x) {
|
||||
} else {
|
||||
int32 thresh = (vpsg1[x << 2] >> 4) & 7;
|
||||
int32 freq = ((vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1) << 17;
|
||||
int32 dc = dcount[x];
|
||||
int32 vc = vcount[x];
|
||||
|
||||
for (V = start; V < end; V++) {
|
||||
if (dcount[x] > thresh)
|
||||
if (dc > thresh)
|
||||
Wave[V >> 4] += amp;
|
||||
vcount[x] -= nesincsize;
|
||||
while (vcount[x] <= 0) {
|
||||
vcount[x] += freq;
|
||||
dcount[x] = (dcount[x] + 1) & 15;
|
||||
vc -= nesincsize;
|
||||
while (vc <= 0) {
|
||||
vc += freq;
|
||||
dc = (dc + 1) & 15;
|
||||
}
|
||||
}
|
||||
vcount[x] = vc;
|
||||
dcount[x] = dc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,29 +230,26 @@ static void DoSawV(void) {
|
||||
cvbc[2] = end;
|
||||
|
||||
if (vpsg2[2] & 0x80) {
|
||||
static int32 saw1phaseacc = 0;
|
||||
uint32 freq3;
|
||||
static uint8 b3 = 0;
|
||||
static int32 phaseacc = 0;
|
||||
static uint32 duff = 0;
|
||||
|
||||
freq3 = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1);
|
||||
|
||||
for (V = start; V < end; V++) {
|
||||
saw1phaseacc -= nesincsize;
|
||||
if (saw1phaseacc <= 0) {
|
||||
vcount[2] -= nesincsize;
|
||||
if (vcount[2] <= 0) {
|
||||
int32 t;
|
||||
rea:
|
||||
t = freq3;
|
||||
t <<= 18;
|
||||
saw1phaseacc += t;
|
||||
vcount[2] += t;
|
||||
phaseacc += vpsg2[0] & 0x3f;
|
||||
b3++;
|
||||
if (b3 == 7) {
|
||||
b3 = 0;
|
||||
dcount[2]++;
|
||||
if (dcount[2] == 7) {
|
||||
dcount[2] = 0;
|
||||
phaseacc = 0;
|
||||
}
|
||||
if (saw1phaseacc <= 0)
|
||||
if (vcount[2] <= 0)
|
||||
goto rea;
|
||||
duff = (((phaseacc >> 3) & 0x1f) << 4) * 6 / 8;
|
||||
}
|
||||
@@ -249,15 +268,20 @@ static INLINE void DoSQVHQ(int x) {
|
||||
WaveHi[V] += amp;
|
||||
} else {
|
||||
int32 thresh = (vpsg1[x << 2] >> 4) & 7;
|
||||
int32 dc = dcount[x];
|
||||
int32 vc = vcount[x];
|
||||
|
||||
for (V = cvbc[x]; V < (int)SOUNDTS; V++) {
|
||||
if (dcount[x] > thresh)
|
||||
if (dc > thresh)
|
||||
WaveHi[V] += amp;
|
||||
vcount[x]--;
|
||||
if (vcount[x] <= 0) {
|
||||
vcount[x] = (vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1;
|
||||
dcount[x] = (dcount[x] + 1) & 15;
|
||||
vc--;
|
||||
if (vc <= 0) {
|
||||
vc = (vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1;
|
||||
dc = (dc + 1) & 15;
|
||||
}
|
||||
}
|
||||
dcount[x] = dc;
|
||||
vcount[x] = vc;
|
||||
}
|
||||
}
|
||||
cvbc[x] = SOUNDTS;
|
||||
@@ -272,8 +296,6 @@ static void DoSQV2HQ(void) {
|
||||
}
|
||||
|
||||
static void DoSawVHQ(void) {
|
||||
static uint8 b3 = 0;
|
||||
static int32 phaseacc = 0;
|
||||
int32 V;
|
||||
|
||||
if (vpsg2[2] & 0x80) {
|
||||
@@ -283,9 +305,9 @@ static void DoSawVHQ(void) {
|
||||
if (vcount[2] <= 0) {
|
||||
vcount[2] = (vpsg2[1] + ((vpsg2[2] & 15) << 8) + 1) << 1;
|
||||
phaseacc += vpsg2[0] & 0x3f;
|
||||
b3++;
|
||||
if (b3 == 7) {
|
||||
b3 = 0;
|
||||
dcount[2]++;
|
||||
if (dcount[2] == 7) {
|
||||
dcount[2] = 0;
|
||||
phaseacc = 0;
|
||||
}
|
||||
}
|
||||
@@ -294,7 +316,6 @@ static void DoSawVHQ(void) {
|
||||
cvbc[2] = SOUNDTS;
|
||||
}
|
||||
|
||||
|
||||
void VRC6Sound(int Count) {
|
||||
int x;
|
||||
|
||||
@@ -322,6 +343,7 @@ static void VRC6_ESI(void) {
|
||||
GameExpSound.HiFill = VRC6SoundHQ;
|
||||
GameExpSound.HiSync = VRC6SyncHQ;
|
||||
|
||||
phaseacc = 0;
|
||||
memset(cvbc, 0, sizeof(cvbc));
|
||||
memset(vcount, 0, sizeof(vcount));
|
||||
memset(dcount, 0, sizeof(dcount));
|
||||
@@ -347,8 +369,8 @@ void Mapper24_Init(CartInfo *info) {
|
||||
MapIRQHook = VRC6IRQHook;
|
||||
VRC6_ESI();
|
||||
GameStateRestore = StateRestore;
|
||||
AddExState(&SStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
AddExState(&SStateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper26_Init(CartInfo *info) {
|
||||
@@ -367,8 +389,8 @@ void Mapper26_Init(CartInfo *info) {
|
||||
info->SaveGame[0] = WRAM;
|
||||
info->SaveGameLen[0] = WRAMSIZE;
|
||||
}
|
||||
AddExState(&SStateRegs, ~0, 0, 0);
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
AddExState(&SStateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void NSFVRC6_Init(void) {
|
||||
|
||||
@@ -174,6 +174,10 @@ static void VRC7IRQHook(int a) {
|
||||
|
||||
static void StateRestore(int version) {
|
||||
Sync();
|
||||
|
||||
#ifndef GEKKO
|
||||
OPLL_forceRefresh(VRC7Sound);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mapper85_Init(CartInfo *info) {
|
||||
@@ -191,6 +195,31 @@ void Mapper85_Init(CartInfo *info) {
|
||||
GameStateRestore = StateRestore;
|
||||
VRC7_ESI();
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
|
||||
/* Ignoring these sound state files for Wii since it causes states unable to load */
|
||||
#ifndef GEKKO
|
||||
/* Sound states */
|
||||
AddExState(&VRC7Sound->adr, sizeof(VRC7Sound->adr), 0, "ADDR");
|
||||
AddExState(&VRC7Sound->out, sizeof(VRC7Sound->out), 0, "OUT0");
|
||||
AddExState(&VRC7Sound->realstep, sizeof(VRC7Sound->realstep), 0, "RTIM");
|
||||
AddExState(&VRC7Sound->oplltime, sizeof(VRC7Sound->oplltime), 0, "TIME");
|
||||
AddExState(&VRC7Sound->opllstep, sizeof(VRC7Sound->opllstep), 0, "STEP");
|
||||
AddExState(&VRC7Sound->prev, sizeof(VRC7Sound->prev), 0, "PREV");
|
||||
AddExState(&VRC7Sound->next, sizeof(VRC7Sound->next), 0, "NEXT");
|
||||
AddExState(&VRC7Sound->LowFreq, sizeof(VRC7Sound->LowFreq), 0, "LFQ0");
|
||||
AddExState(&VRC7Sound->HiFreq, sizeof(VRC7Sound->HiFreq), 0, "HFQ0");
|
||||
AddExState(&VRC7Sound->InstVol, sizeof(VRC7Sound->InstVol), 0, "VOLI");
|
||||
AddExState(&VRC7Sound->CustInst, sizeof(VRC7Sound->CustInst), 0, "CUSI");
|
||||
AddExState(&VRC7Sound->slot_on_flag, sizeof(VRC7Sound->slot_on_flag), 0, "FLAG");
|
||||
AddExState(&VRC7Sound->pm_phase, sizeof(VRC7Sound->pm_phase), 0, "PMPH");
|
||||
AddExState(&VRC7Sound->lfo_pm, sizeof(VRC7Sound->lfo_pm), 0, "PLFO");
|
||||
AddExState(&VRC7Sound->am_phase, sizeof(VRC7Sound->am_phase), 0, "AMPH");
|
||||
AddExState(&VRC7Sound->lfo_am, sizeof(VRC7Sound->lfo_am), 0, "ALFO");
|
||||
AddExState(&VRC7Sound->patch_number, sizeof(VRC7Sound->patch_number), 0, "PNUM");
|
||||
AddExState(&VRC7Sound->key_status, sizeof(VRC7Sound->key_status), 0, "KET");
|
||||
AddExState(&VRC7Sound->mask, sizeof(VRC7Sound->mask), 0, "MASK");
|
||||
AddExState((uint8 *)VRC7Sound->slot, sizeof(VRC7Sound->slot), 0, "SLOT");
|
||||
#endif
|
||||
}
|
||||
|
||||
void NSFVRC7_Init(void) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2017 The RetroArch team
|
||||
/* Copyright (C) 2010-2018 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this libretro API header (libretro.h).
|
||||
@@ -128,7 +128,8 @@ extern "C" {
|
||||
|
||||
/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2.
|
||||
* It reports X/Y coordinates in screen space (similar to the pointer)
|
||||
* in the range [-0x8000, 0x7fff] in both axes, with zero being center.
|
||||
* in the range [-0x8000, 0x7fff] in both axes, with zero being center and
|
||||
* -0x8000 being out of bounds.
|
||||
* As well as reporting on/off screen state. It features a trigger,
|
||||
* start/select buttons, auxiliary action buttons and a
|
||||
* directional pad. A forced off-screen shot can be requested for
|
||||
@@ -139,7 +140,8 @@ extern "C" {
|
||||
/* The ANALOG device is an extension to JOYPAD (RetroPad).
|
||||
* Similar to DualShock2 it adds two analog sticks and all buttons can
|
||||
* be analog. This is treated as a separate device type as it returns
|
||||
* axis values in the full analog range of [-0x8000, 0x7fff].
|
||||
* axis values in the full analog range of [-0x7fff, 0x7fff],
|
||||
* although some devices may return -0x8000.
|
||||
* Positive X axis is right. Positive Y axis is down.
|
||||
* Buttons are returned in the range [0, 0x7fff].
|
||||
* Only use ANALOG type when polling for analog values.
|
||||
@@ -271,6 +273,7 @@ enum retro_language
|
||||
RETRO_LANGUAGE_POLISH = 14,
|
||||
RETRO_LANGUAGE_VIETNAMESE = 15,
|
||||
RETRO_LANGUAGE_ARABIC = 16,
|
||||
RETRO_LANGUAGE_GREEK = 17,
|
||||
RETRO_LANGUAGE_LAST,
|
||||
|
||||
/* Ensure sizeof(enum) == sizeof(int) */
|
||||
@@ -450,6 +453,7 @@ enum retro_key
|
||||
RETROK_POWER = 320,
|
||||
RETROK_EURO = 321,
|
||||
RETROK_UNDO = 322,
|
||||
RETROK_OEM_102 = 323,
|
||||
|
||||
RETROK_LAST,
|
||||
|
||||
@@ -599,9 +603,12 @@ enum retro_mod
|
||||
* GET_VARIABLE.
|
||||
* This allows the frontend to present these variables to
|
||||
* a user dynamically.
|
||||
* This should be called as early as possible (ideally in
|
||||
* retro_set_environment).
|
||||
*
|
||||
* This should be called the first time as early as
|
||||
* possible (ideally in retro_set_environment).
|
||||
* Afterward it may be called again for the core to communicate
|
||||
* updated options to the frontend, but the number of core
|
||||
* options must not change from the number in the initial call.
|
||||
*
|
||||
* 'data' points to an array of retro_variable structs
|
||||
* terminated by a { NULL, NULL } element.
|
||||
* retro_variable::key should be namespaced to not collide
|
||||
@@ -654,6 +661,15 @@ enum retro_mod
|
||||
/* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK.
|
||||
* It was not used by any known core at the time,
|
||||
* and was removed from the API. */
|
||||
#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21
|
||||
/* const struct retro_frame_time_callback * --
|
||||
* Lets the core know how much time has passed since last
|
||||
* invocation of retro_run().
|
||||
* The frontend can tamper with the timing to fake fast-forward,
|
||||
* slow-motion, frame stepping, etc.
|
||||
* In this case the delta time will use the reference value
|
||||
* in frame_time_callback..
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22
|
||||
/* const struct retro_audio_callback * --
|
||||
* Sets an interface which is used to notify a libretro core about audio
|
||||
@@ -680,15 +696,6 @@ enum retro_mod
|
||||
* A libretro core using SET_AUDIO_CALLBACK should also make use of
|
||||
* SET_FRAME_TIME_CALLBACK.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21
|
||||
/* const struct retro_frame_time_callback * --
|
||||
* Lets the core know how much time has passed since last
|
||||
* invocation of retro_run().
|
||||
* The frontend can tamper with the timing to fake fast-forward,
|
||||
* slow-motion, frame stepping, etc.
|
||||
* In this case the delta time will use the reference value
|
||||
* in frame_time_callback..
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23
|
||||
/* struct retro_rumble_interface * --
|
||||
* Gets an interface which is used by a libretro core to set
|
||||
@@ -775,17 +782,18 @@ enum retro_mod
|
||||
*/
|
||||
#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
|
||||
* Returns the "save" directory of the frontend, unless there is no
|
||||
* save directory available. The save directory should 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.
|
||||
* If the frontend cannot designate a save directory, it will return
|
||||
* NULL to indicate that the core should attempt to operate without a
|
||||
* save directory set.
|
||||
*
|
||||
* NOTE: early libretro cores used the system directory for save
|
||||
* files. Cores that need to be backwards-compatible can still check
|
||||
* GET_SYSTEM_DIRECTORY.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32
|
||||
/* const struct retro_system_av_info * --
|
||||
@@ -853,26 +861,39 @@ enum retro_mod
|
||||
#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
|
||||
* which controller subclasses 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.
|
||||
* 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 specifcally
|
||||
* provided by the Libretro 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.
|
||||
* In order for a frontend to understand the workings of those devices,
|
||||
* they must be defined as a specialized subclass 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,
|
||||
* is terminated with a blanked out struct. Each element of the
|
||||
* retro_controller_info struct corresponds to the ascending port index
|
||||
* that is passed to retro_set_controller_port_device() when that function
|
||||
* is called to indicate to the core that the frontend has changed the
|
||||
* active device subclass. SEE ALSO: retro_set_controller_port_device()
|
||||
*
|
||||
* The ascending input port indexes provided by the core in the struct
|
||||
* are generally presented by frontends as ascending User # or Player #,
|
||||
* such as Player 1, Player 2, Player 3, etc. Which device subclasses are
|
||||
* supported can vary per input port.
|
||||
*
|
||||
* The first inner element of each entry in the retro_controller_info array
|
||||
* is a retro_controller_description struct that specifies the names and
|
||||
* codes of all device subclasses that are available for the corresponding
|
||||
* User or Player, beginning with the generic Libretro device that the
|
||||
* subclasses are derived from. The second inner element of each entry is the
|
||||
* total number of subclasses that are listed in the retro_controller_description.
|
||||
*
|
||||
* NOTE: Even if special device types are set in the libretro core,
|
||||
* libretro should only poll input based on the base input device types.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
@@ -951,7 +972,37 @@ enum retro_mod
|
||||
* A frontend must make sure that the pointer obtained from this function is
|
||||
* writeable (and readable).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const struct retro_hw_render_interface ** --
|
||||
* Returns an API specific rendering interface for accessing API specific data.
|
||||
* Not all HW rendering APIs support or need this.
|
||||
* The contents of the returned pointer is specific to the rendering API
|
||||
* being used. See the various headers like libretro_vulkan.h, etc.
|
||||
*
|
||||
* GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
|
||||
* Similarly, after context_destroyed callback returns,
|
||||
* the contents of the HW_RENDER_INTERFACE are invalidated.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const bool * --
|
||||
* If true, the libretro implementation supports achievements
|
||||
* either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
|
||||
* or via retro_get_memory_data/retro_get_memory_size.
|
||||
*
|
||||
* This must be called before the first call to retro_run.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const struct retro_hw_render_context_negotiation_interface * --
|
||||
* Sets an interface which lets the libretro core negotiate with frontend how a context is created.
|
||||
* The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
|
||||
* This interface will be used when the frontend is trying to create a HW rendering context,
|
||||
* so it will be used after SET_HW_RENDER, but before the context_reset callback.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
|
||||
/* uint64_t * --
|
||||
* Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
|
||||
* recognize or support. Should be set in either retro_init or retro_load_game, but not both.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* N/A (null) * --
|
||||
* The frontend will try to use a 'shared' hardware context (mostly applicable
|
||||
@@ -963,14 +1014,70 @@ enum retro_mod
|
||||
* This will do nothing on its own until SET_HW_RENDER env callbacks are
|
||||
* being used.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* struct retro_vfs_interface_info * --
|
||||
* Gets access to the VFS interface.
|
||||
* VFS presence needs to be queried prior to load_game or any
|
||||
* get_system/save/other_directory being called to let front end know
|
||||
* core supports VFS before it starts handing out paths.
|
||||
* It is recomended to do so in retro_set_environment */
|
||||
* It is recomended to do so in retro_set_environment
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* struct retro_led_interface * --
|
||||
* Gets an interface which is used by a libretro core to set
|
||||
* state of LEDs.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* int * --
|
||||
* Tells the core if the frontend wants audio or video.
|
||||
* If disabled, the frontend will discard the audio or video,
|
||||
* so the core may decide to skip generating a frame or generating audio.
|
||||
* This is mainly used for increasing performance.
|
||||
* Bit 0 (value 1): Enable Video
|
||||
* Bit 1 (value 2): Enable Audio
|
||||
* Bit 2 (value 4): Use Fast Savestates.
|
||||
* Bit 3 (value 8): Hard Disable Audio
|
||||
* Other bits are reserved for future use and will default to zero.
|
||||
* If video is disabled:
|
||||
* * The frontend wants the core to not generate any video,
|
||||
* including presenting frames via hardware acceleration.
|
||||
* * The frontend's video frame callback will do nothing.
|
||||
* * After running the frame, the video output of the next frame should be
|
||||
* no different than if video was enabled, and saving and loading state
|
||||
* should have no issues.
|
||||
* If audio is disabled:
|
||||
* * The frontend wants the core to not generate any audio.
|
||||
* * The frontend's audio callbacks will do nothing.
|
||||
* * After running the frame, the audio output of the next frame should be
|
||||
* no different than if audio was enabled, and saving and loading state
|
||||
* should have no issues.
|
||||
* Fast Savestates:
|
||||
* * Guaranteed to be created by the same binary that will load them.
|
||||
* * Will not be written to or read from the disk.
|
||||
* * Suggest that the core assumes loading state will succeed.
|
||||
* * Suggest that the core updates its memory buffers in-place if possible.
|
||||
* * Suggest that the core skips clearing memory.
|
||||
* * Suggest that the core skips resetting the system.
|
||||
* * Suggest that the core may skip validation steps.
|
||||
* Hard Disable Audio:
|
||||
* * Used for a secondary core when running ahead.
|
||||
* * Indicates that the frontend will never need audio from the core.
|
||||
* * Suggests that the core may stop synthesizing audio, but this should not
|
||||
* compromise emulation accuracy.
|
||||
* * Audio output for the next frame does not matter, and the frontend will
|
||||
* never need an accurate audio state in the future.
|
||||
* * State will never be saved when using Hard Disable Audio.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* struct retro_midi_interface ** --
|
||||
* Returns a MIDI interface that can be used for raw data I/O.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* bool * --
|
||||
* Boolean value that indicates whether or not the frontend is in
|
||||
* fastforwarding mode.
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
@@ -1030,6 +1137,10 @@ typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *st
|
||||
* Introduced in VFS API v1 */
|
||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream);
|
||||
|
||||
/* Truncate file to specified size. Returns 0 on success or -1 on error
|
||||
* Introduced in VFS API v2 */
|
||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length);
|
||||
|
||||
/* Get the current read / write position for the file. Returns - 1 for error.
|
||||
* Introduced in VFS API v1 */
|
||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream);
|
||||
@@ -1060,6 +1171,7 @@ typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const cha
|
||||
|
||||
struct retro_vfs_interface
|
||||
{
|
||||
/* VFS API v1 */
|
||||
retro_vfs_get_path_t get_path;
|
||||
retro_vfs_open_t open;
|
||||
retro_vfs_close_t close;
|
||||
@@ -1071,6 +1183,8 @@ struct retro_vfs_interface
|
||||
retro_vfs_flush_t flush;
|
||||
retro_vfs_remove_t remove;
|
||||
retro_vfs_rename_t rename;
|
||||
/* VFS API v2 */
|
||||
retro_vfs_truncate_t truncate;
|
||||
};
|
||||
|
||||
struct retro_vfs_interface_info
|
||||
@@ -1104,81 +1218,41 @@ struct retro_hw_render_interface
|
||||
unsigned interface_version;
|
||||
};
|
||||
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* struct retro_led_interface * --
|
||||
* Gets an interface which is used by a libretro core to set
|
||||
* state of LEDs.
|
||||
*/
|
||||
|
||||
typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state);
|
||||
struct retro_led_interface
|
||||
{
|
||||
retro_set_led_state_t set_led_state;
|
||||
};
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* int * --
|
||||
* Tells the core if the frontend wants audio or video.
|
||||
* If disabled, the frontend will discard the audio or video,
|
||||
* so the core may decide to skip generating a frame or generating audio.
|
||||
* This is mainly used for increasing performance.
|
||||
* Bit 0 (value 1): Enable Video
|
||||
* Bit 1 (value 2): Enable Audio
|
||||
* Bit 2 (value 4): Use Fast Savestates.
|
||||
* Bit 3 (value 8): Hard Disable Audio
|
||||
* Other bits are reserved for future use and will default to zero.
|
||||
* If video is disabled:
|
||||
* * The frontend wants the core to not generate any video,
|
||||
* including presenting frames via hardware acceleration.
|
||||
* * The frontend's video frame callback will do nothing.
|
||||
* * After running the frame, the video output of the next frame should be
|
||||
* no different than if video was enabled, and saving and loading state
|
||||
* should have no issues.
|
||||
* If audio is disabled:
|
||||
* * The frontend wants the core to not generate any audio.
|
||||
* * The frontend's audio callbacks will do nothing.
|
||||
* * After running the frame, the audio output of the next frame should be
|
||||
* no different than if audio was enabled, and saving and loading state
|
||||
* should have no issues.
|
||||
* Fast Savestates:
|
||||
* * Guaranteed to be created by the same binary that will load them.
|
||||
* * Will not be written to or read from the disk.
|
||||
* * Suggest that the core assumes loading state will succeed.
|
||||
* * Suggest that the core updates its memory buffers in-place if possible.
|
||||
* * Suggest that the core skips clearing memory.
|
||||
* * Suggest that the core skips resetting the system.
|
||||
* * Suggest that the core may skip validation steps.
|
||||
* Hard Disable Audio:
|
||||
* * Used for a secondary core when running ahead.
|
||||
* * Indicates that the frontend will never need audio from the core.
|
||||
* * Suggests that the core may stop synthesizing audio, but this should not
|
||||
* compromise emulation accuracy.
|
||||
* * Audio output for the next frame does not matter, and the frontend will
|
||||
* never need an accurate audio state in the future.
|
||||
* * State will never be saved when using Hard Disable Audio.
|
||||
*/
|
||||
/* Retrieves the current state of the MIDI input.
|
||||
* Returns true if it's enabled, false otherwise. */
|
||||
typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void);
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const struct retro_hw_render_interface ** --
|
||||
* Returns an API specific rendering interface for accessing API specific data.
|
||||
* Not all HW rendering APIs support or need this.
|
||||
* The contents of the returned pointer is specific to the rendering API
|
||||
* being used. See the various headers like libretro_vulkan.h, etc.
|
||||
*
|
||||
* GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
|
||||
* Similarly, after context_destroyed callback returns,
|
||||
* the contents of the HW_RENDER_INTERFACE are invalidated.
|
||||
*/
|
||||
/* Retrieves the current state of the MIDI output.
|
||||
* Returns true if it's enabled, false otherwise */
|
||||
typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void);
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const bool * --
|
||||
* If true, the libretro implementation supports achievements
|
||||
* either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
|
||||
* or via retro_get_memory_data/retro_get_memory_size.
|
||||
*
|
||||
* This must be called before the first call to retro_run.
|
||||
*/
|
||||
/* Reads next byte from the input stream.
|
||||
* Returns true if byte is read, false otherwise. */
|
||||
typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte);
|
||||
|
||||
/* Writes byte to the output stream.
|
||||
* 'delta_time' is in microseconds and represent time elapsed since previous write.
|
||||
* Returns true if byte is written, false otherwise. */
|
||||
typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time);
|
||||
|
||||
/* Flushes previously written data.
|
||||
* Returns true if successful, false otherwise. */
|
||||
typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void);
|
||||
|
||||
struct retro_midi_interface
|
||||
{
|
||||
retro_midi_input_enabled_t input_enabled;
|
||||
retro_midi_output_enabled_t output_enabled;
|
||||
retro_midi_read_t read;
|
||||
retro_midi_write_t write;
|
||||
retro_midi_flush_t flush;
|
||||
};
|
||||
|
||||
enum retro_hw_render_context_negotiation_interface_type
|
||||
{
|
||||
@@ -1193,13 +1267,6 @@ struct retro_hw_render_context_negotiation_interface
|
||||
enum retro_hw_render_context_negotiation_interface_type interface_type;
|
||||
unsigned interface_version;
|
||||
};
|
||||
#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* const struct retro_hw_render_context_negotiation_interface * --
|
||||
* Sets an interface which lets the libretro core negotiate with frontend how a context is created.
|
||||
* The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
|
||||
* This interface will be used when the frontend is trying to create a HW rendering context,
|
||||
* so it will be used after SET_HW_RENDER, but before the context_reset callback.
|
||||
*/
|
||||
|
||||
/* Serialized state is incomplete in some way. Set if serialization is
|
||||
* usable in typical end-user cases but should not be relied upon to
|
||||
@@ -1225,20 +1292,17 @@ struct retro_hw_render_context_negotiation_interface
|
||||
* dependence */
|
||||
#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6)
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
|
||||
/* uint64_t * --
|
||||
* Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
|
||||
* recognize or support. Should be set in either retro_init or retro_load_game, but not both.
|
||||
*/
|
||||
|
||||
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
|
||||
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
|
||||
#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
|
||||
#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
|
||||
#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
|
||||
#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */
|
||||
#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
|
||||
#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
|
||||
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
|
||||
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
|
||||
#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */
|
||||
#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */
|
||||
#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */
|
||||
#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
|
||||
#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
|
||||
#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
|
||||
#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */
|
||||
#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
|
||||
#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
|
||||
struct retro_memory_descriptor
|
||||
{
|
||||
uint64_t flags;
|
||||
@@ -2138,17 +2202,26 @@ struct retro_system_info
|
||||
* Typically used for a GUI to filter
|
||||
* out extensions. */
|
||||
|
||||
/* If true, retro_load_game() is guaranteed to provide a valid pathname
|
||||
* in retro_game_info::path.
|
||||
* ::data and ::size are both invalid.
|
||||
/* Libretro cores that need to have direct access to their content
|
||||
* files, including cores which use the path of the content files to
|
||||
* determine the paths of other files, should set need_fullpath to true.
|
||||
*
|
||||
* If false, ::data and ::size are guaranteed to be valid, but ::path
|
||||
* might not be valid.
|
||||
* Cores should strive for setting need_fullpath to false,
|
||||
* as it allows the frontend to perform patching, etc.
|
||||
*
|
||||
* This is typically set to true for libretro implementations that must
|
||||
* load from file.
|
||||
* Implementations should strive for setting this to false, as it allows
|
||||
* the frontend to perform patching, etc. */
|
||||
* If need_fullpath is true and retro_load_game() is called:
|
||||
* - retro_game_info::path is guaranteed to have a valid path
|
||||
* - retro_game_info::data and retro_game_info::size are invalid
|
||||
*
|
||||
* If need_fullpath is false and retro_load_game() is called:
|
||||
* - retro_game_info::path may be NULL
|
||||
* - retro_game_info::data and retro_game_info::size are guaranteed
|
||||
* to be valid
|
||||
*
|
||||
* See also:
|
||||
* - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY
|
||||
* - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY
|
||||
*/
|
||||
bool need_fullpath;
|
||||
|
||||
/* If true, the frontend is not allowed to extract any archives before
|
||||
@@ -2333,7 +2406,13 @@ RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info);
|
||||
* 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. */
|
||||
* core can change its behavior depending on device type.
|
||||
*
|
||||
* As part of the core's implementation of retro_set_controller_port_device,
|
||||
* the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the
|
||||
* frontend if the descriptions for any controls have changed as a
|
||||
* result of changing the device type.
|
||||
*/
|
||||
RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device);
|
||||
|
||||
/* Resets the current game. */
|
||||
@@ -2365,7 +2444,9 @@ RETRO_API bool retro_unserialize(const void *data, size_t size);
|
||||
RETRO_API void retro_cheat_reset(void);
|
||||
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
|
||||
|
||||
/* Loads a game. */
|
||||
/* Loads a game.
|
||||
* Return true to indicate successful loading and false to indicate load failure.
|
||||
*/
|
||||
RETRO_API bool retro_load_game(const struct retro_game_info *game);
|
||||
|
||||
/* Loads a "special" kind of game. Should not be used,
|
||||
@@ -2375,7 +2456,7 @@ RETRO_API bool retro_load_game_special(
|
||||
const struct retro_game_info *info, size_t num_info
|
||||
);
|
||||
|
||||
/* Unloads a currently loaded game. */
|
||||
/* Unloads the currently loaded game. Called before retro_deinit(void). */
|
||||
RETRO_API void retro_unload_game(void);
|
||||
|
||||
/* Gets region of game. */
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/* Copyright (C) 2010-2018 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this libretro API header (libretro_d3d.h)
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the
|
||||
* "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBRETRO_GSKIT_PS2_H_
|
||||
#define LIBRETRO_GSKIT_PS2_H_
|
||||
|
||||
#include "libretro.h"
|
||||
|
||||
#if defined(PS2)
|
||||
|
||||
#include <gsKit.h>
|
||||
|
||||
#define RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION 1
|
||||
|
||||
struct retro_hw_ps2_insets
|
||||
{
|
||||
float top;
|
||||
float left;
|
||||
float bottom;
|
||||
float right;
|
||||
};
|
||||
|
||||
#define empty_ps2_insets (struct retro_hw_ps2_insets){0.f, 0.f, 0.f, 0.f}
|
||||
|
||||
struct retro_hw_render_interface_gskit_ps2
|
||||
{
|
||||
/* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2. */
|
||||
enum retro_hw_render_interface_type interface_type;
|
||||
/* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION. */
|
||||
unsigned interface_version;
|
||||
|
||||
/* Opaque handle to the GSKit_PS2 backend in the frontend
|
||||
* which must be passed along to all function pointers
|
||||
* in this interface.
|
||||
*/
|
||||
GSTEXTURE *coreTexture;
|
||||
bool clearTexture;
|
||||
bool updatedPalette;
|
||||
struct retro_hw_ps2_insets padding;
|
||||
};
|
||||
typedef struct retro_hw_render_interface_gskit_ps2 RETRO_HW_RENDER_INTEFACE_GSKIT_PS2;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* LIBRETRO_GSKIT_PS2_H_ */
|
||||
@@ -24,19 +24,29 @@
|
||||
#include "../../vsuni.h"
|
||||
#include "../../video.h"
|
||||
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
#include "libretro-common/include/libretro_gskit_ps2.h"
|
||||
#endif
|
||||
|
||||
#include "libretro-common/include/streams/memory_stream.h"
|
||||
|
||||
#define MAX_PLAYERS 4 /* max supported players */
|
||||
#define MAX_PORTS 2 /* max controller ports,
|
||||
* port 0 for player 1/3, port 1 for player 2/4 */
|
||||
|
||||
#define RETRO_DEVICE_GAMEPAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0)
|
||||
#define RETRO_DEVICE_AUTO RETRO_DEVICE_JOYPAD
|
||||
#define RETRO_DEVICE_GAMEPAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1)
|
||||
#define RETRO_DEVICE_ZAPPER RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 0)
|
||||
#define RETRO_DEVICE_ARKANOID RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 1)
|
||||
|
||||
#define RETRO_DEVICE_FC_ARKANOID RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 2)
|
||||
#define RETRO_DEVICE_FC_OEKAKIDS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 3)
|
||||
#define RETRO_DEVICE_FC_SHADOW RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 4)
|
||||
#define RETRO_DEVICE_FC_4PLAYERS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 2)
|
||||
#define RETRO_DEVICE_FC_AUTO RETRO_DEVICE_JOYPAD
|
||||
|
||||
#define NES_WIDTH 256
|
||||
#define NES_HEIGHT 240
|
||||
#define NES_8_7_PAR ((width * (8.0 / 7.0)) / height)
|
||||
#define NES_4_3 ((width / (height * (256.0 / 240.0))) * 4.0 / 3.0)
|
||||
|
||||
@@ -45,6 +55,10 @@ void* linearMemAlign(size_t size, size_t alignment);
|
||||
void linearFree(void* mem);
|
||||
#endif
|
||||
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
RETRO_HW_RENDER_INTEFACE_GSKIT_PS2 *ps2 = NULL;
|
||||
#endif
|
||||
|
||||
static retro_video_refresh_t video_cb = NULL;
|
||||
static retro_input_poll_t poll_cb = NULL;
|
||||
static retro_input_state_t input_cb = NULL;
|
||||
@@ -89,20 +103,27 @@ static __attribute__((aligned(16))) uint16_t retro_palette[256];
|
||||
#else
|
||||
static uint16_t retro_palette[256];
|
||||
#endif
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
static uint8_t* fceu_video_out;
|
||||
#else
|
||||
static uint16_t* fceu_video_out;
|
||||
#endif
|
||||
|
||||
/* Some timing-related variables. */
|
||||
unsigned sndsamplerate = 48000;
|
||||
unsigned sndquality = 0;
|
||||
unsigned sndvolume = 150;
|
||||
unsigned swapDuty = 0;
|
||||
static unsigned sndsamplerate;
|
||||
static unsigned sndquality;
|
||||
static unsigned sndvolume;
|
||||
unsigned swapDuty;
|
||||
|
||||
static int32_t *sound = 0;
|
||||
static uint32_t JSReturn = 0;
|
||||
static uint32_t Dummy = 0;
|
||||
static uint32_t MouseData[MAX_PORTS][3] = { {0} };
|
||||
static uint32_t fc_MouseData[3] = {0};
|
||||
static uint32_t current_palette = 0;
|
||||
|
||||
static unsigned serialize_size;
|
||||
|
||||
int PPUViewScanline=0;
|
||||
int PPUViewer=0;
|
||||
|
||||
@@ -136,6 +157,16 @@ int FCEUD_SendData(void *data, uint32 len)
|
||||
#define RED_EXPAND 3
|
||||
#define GREEN_EXPAND 2
|
||||
#define BLUE_EXPAND 3
|
||||
#elif defined (FRONTEND_SUPPORTS_ABGR1555)
|
||||
#define RED_SHIFT 0
|
||||
#define GREEN_SHIFT 5
|
||||
#define BLUE_SHIFT 10
|
||||
#define RED_EXPAND 3
|
||||
#define GREEN_EXPAND 3
|
||||
#define BLUE_EXPAND 3
|
||||
#define RED_MASK 0x1F
|
||||
#define GREEN_MASK 0x3E0
|
||||
#define BLUE_MASK 0x7C00
|
||||
#elif defined (FRONTEND_SUPPORTS_RGB565)
|
||||
#define RED_SHIFT 11
|
||||
#define GREEN_SHIFT 5
|
||||
@@ -155,12 +186,23 @@ int FCEUD_SendData(void *data, uint32 len)
|
||||
#define BLUE_EXPAND 3
|
||||
#endif
|
||||
|
||||
void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b)
|
||||
void FCEUD_SetPalette(uint8_t index, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
unsigned char index_to_write = index;
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
/* Index correction for PS2 GS */
|
||||
int modi = index & 63;
|
||||
if ((modi >= 8 && modi < 16) || (modi >= 40 && modi < 48)) {
|
||||
index_to_write += 8;
|
||||
} else if ((modi >= 16 && modi < 24) || (modi >= 48 && modi < 56)) {
|
||||
index_to_write -= 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FRONTEND_SUPPORTS_RGB565
|
||||
retro_palette[index] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND);
|
||||
retro_palette[index_to_write] = BUILD_PIXEL_RGB565(r >> RED_EXPAND, g >> GREEN_EXPAND, b >> BLUE_EXPAND);
|
||||
#else
|
||||
retro_palette[index] =
|
||||
retro_palette[index_to_write] =
|
||||
((r >> RED_EXPAND) << RED_SHIFT) | ((g >> GREEN_EXPAND) << GREEN_SHIFT) | ((b >> BLUE_EXPAND) << BLUE_SHIFT);
|
||||
#endif
|
||||
}
|
||||
@@ -214,10 +256,11 @@ FILE *FCEUD_UTF8fopen(const char *n, const char *m)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MAX_PATH 1024
|
||||
|
||||
/*palette for FCEU*/
|
||||
#define MAXPAL 17 /* raw palette # */
|
||||
#define PAL_TOTAL 16 /* total no. of palettes in palettes[] */
|
||||
#define PAL_DEFAULT (PAL_TOTAL + 1)
|
||||
#define PAL_RAW (PAL_TOTAL + 2)
|
||||
#define PAL_CUSTOM (PAL_TOTAL + 3)
|
||||
static int external_palette_exist = 0;
|
||||
extern int ipalette;
|
||||
|
||||
@@ -546,31 +589,150 @@ void retro_set_input_state(retro_input_state_t cb)
|
||||
input_cb = cb;
|
||||
}
|
||||
|
||||
void set_input_nes_controller(unsigned port, int x);
|
||||
void set_input_famicom_controller(int x);
|
||||
static void update_nes_controllers(unsigned port, unsigned device)
|
||||
{
|
||||
input_type[port] = device;
|
||||
|
||||
if (port < 4)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_NONE:
|
||||
FCEUI_SetInput(port, SI_NONE, &Dummy, 0);
|
||||
FCEU_printf(" Player %u: None Connected\n", port + 1);
|
||||
break;
|
||||
case RETRO_DEVICE_ZAPPER:
|
||||
FCEUI_SetInput(port, SI_ZAPPER, MouseData[port], 1);
|
||||
FCEU_printf(" Player %u: Zapper\n", port + 1);
|
||||
break;
|
||||
case RETRO_DEVICE_ARKANOID:
|
||||
FCEUI_SetInput(port, SI_ARKANOID, MouseData[port], 0);
|
||||
FCEU_printf(" Player %u: Arkanoid\n", port + 1);
|
||||
break;
|
||||
case RETRO_DEVICE_GAMEPAD:
|
||||
default:
|
||||
input_type[port] = RETRO_DEVICE_GAMEPAD;
|
||||
FCEUI_SetInput(port, SI_GAMEPAD, &JSReturn, 0);
|
||||
FCEU_printf(" Player %u: Gamepad\n", port + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (port == 4)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_FC_ARKANOID:
|
||||
FCEUI_SetInputFC(SIFC_ARKANOID, fc_MouseData, 0);
|
||||
FCEU_printf(" Famicom Expansion: Arkanoid\n");
|
||||
break;
|
||||
case RETRO_DEVICE_FC_SHADOW:
|
||||
FCEUI_SetInputFC(SIFC_SHADOW, fc_MouseData, 1);
|
||||
FCEU_printf(" Famicom Expansion: (Bandai) Hyper Shot\n");
|
||||
break;
|
||||
case RETRO_DEVICE_FC_OEKAKIDS:
|
||||
FCEUI_SetInputFC(SIFC_OEKAKIDS, fc_MouseData, 1);
|
||||
FCEU_printf(" Famicom Expansion: Oeka Kids Tablet\n");
|
||||
break;
|
||||
case RETRO_DEVICE_FC_4PLAYERS:
|
||||
FCEUI_SetInputFC(SIFC_4PLAYER, &JSReturn, 0);
|
||||
FCEU_printf(" Famicom Expansion: Famicom 4-Player Adapter\n");
|
||||
break;
|
||||
case RETRO_DEVICE_NONE:
|
||||
default:
|
||||
FCEUI_SetInputFC(SIFC_NONE, &Dummy, 0);
|
||||
FCEU_printf(" Famicom Expansion: None Connected\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned nes_to_libretro(int d)
|
||||
{
|
||||
switch(d)
|
||||
{
|
||||
case SI_UNSET:
|
||||
case SI_GAMEPAD:
|
||||
return RETRO_DEVICE_GAMEPAD;
|
||||
case SI_NONE:
|
||||
return RETRO_DEVICE_NONE;
|
||||
case SI_ZAPPER:
|
||||
return RETRO_DEVICE_ZAPPER;
|
||||
case SI_ARKANOID:
|
||||
return RETRO_DEVICE_ARKANOID;
|
||||
}
|
||||
|
||||
return (RETRO_DEVICE_GAMEPAD);
|
||||
}
|
||||
|
||||
static unsigned fc_to_libretro(int d)
|
||||
{
|
||||
switch(d)
|
||||
{
|
||||
case SIFC_UNSET:
|
||||
case SIFC_NONE:
|
||||
return RETRO_DEVICE_NONE;
|
||||
case SIFC_ARKANOID:
|
||||
return RETRO_DEVICE_FC_ARKANOID;
|
||||
case SIFC_SHADOW:
|
||||
return RETRO_DEVICE_FC_SHADOW;
|
||||
case SIFC_OEKAKIDS:
|
||||
return RETRO_DEVICE_FC_OEKAKIDS;
|
||||
case SIFC_4PLAYER:
|
||||
return RETRO_DEVICE_FC_4PLAYERS;
|
||||
}
|
||||
|
||||
return (RETRO_DEVICE_NONE);
|
||||
}
|
||||
|
||||
void retro_set_controller_port_device(unsigned port, unsigned device)
|
||||
{
|
||||
if (port < MAX_PORTS) /* port #0 = player1/player3, port #1 = player2/player4 */
|
||||
if ((port < 5) && (input_type[port] != device))
|
||||
{
|
||||
switch(device)
|
||||
if (port < 2) /* player 1-2 */
|
||||
{
|
||||
case RETRO_DEVICE_NONE:
|
||||
set_input_nes_controller(port, SI_NONE);
|
||||
break;
|
||||
case RETRO_DEVICE_GAMEPAD:
|
||||
set_input_nes_controller(port, SI_GAMEPAD);
|
||||
break;
|
||||
case RETRO_DEVICE_ZAPPER:
|
||||
set_input_nes_controller(port, SI_ZAPPER);
|
||||
break;
|
||||
case RETRO_DEVICE_ARKANOID:
|
||||
set_input_nes_controller(port, SI_ARKANOID);
|
||||
break;
|
||||
case RETRO_DEVICE_JOYPAD: /* Assigned to auto configure devices */
|
||||
default: /* based on database */
|
||||
set_input_nes_controller(port, GameInfo->input[port]);
|
||||
break;
|
||||
if (device != RETRO_DEVICE_AUTO)
|
||||
update_nes_controllers(port, device);
|
||||
else
|
||||
update_nes_controllers(port, nes_to_libretro(GameInfo->input[port]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (port < 4) /* player 3-4 */
|
||||
{
|
||||
/* This section automatically enables 4players support
|
||||
* when player 3 or 4 used */
|
||||
|
||||
input_type[port] = RETRO_DEVICE_NONE;
|
||||
|
||||
if (device == RETRO_DEVICE_AUTO)
|
||||
{
|
||||
if (enable_4player)
|
||||
input_type[port] = RETRO_DEVICE_GAMEPAD;
|
||||
}
|
||||
else if (device == RETRO_DEVICE_GAMEPAD)
|
||||
input_type[port] = RETRO_DEVICE_GAMEPAD;
|
||||
|
||||
FCEU_printf(" Player %u: %s\n", port + 1,
|
||||
(input_type[port] == RETRO_DEVICE_NONE) ? "None Connected" : "Gamepad");
|
||||
}
|
||||
else /* do famicom controllers here */
|
||||
{
|
||||
if (device != RETRO_DEVICE_FC_AUTO)
|
||||
update_nes_controllers(4, device);
|
||||
else
|
||||
update_nes_controllers(4, fc_to_libretro(GameInfo->inputfc));
|
||||
}
|
||||
|
||||
if (input_type[2] == RETRO_DEVICE_GAMEPAD
|
||||
|| input_type[3] == RETRO_DEVICE_GAMEPAD)
|
||||
FCEUI_DisableFourScore(0);
|
||||
else
|
||||
FCEUI_DisableFourScore(1);
|
||||
|
||||
/* check if famicom 4player adapter is used */
|
||||
if (input_type[4] == RETRO_DEVICE_FC_4PLAYERS)
|
||||
FCEUI_DisableFourScore(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -592,33 +754,65 @@ void retro_set_environment(retro_environment_t cb)
|
||||
{ "fceumm_sndvolume", "Sound Volume; 150|160|170|180|190|200|210|220|230|240|250|0|10|20|30|40|50|60|70|80|90|100|110|120|130|140" },
|
||||
{ "fceumm_sndquality", "Sound Quality; Low|High|Very High" },
|
||||
{ "fceumm_swapduty", "Swap Duty Cycles; disabled|enabled" },
|
||||
#ifdef DEBUG
|
||||
{ "fceumm_apu_1", "Enable Sound Channel 1 (Square 1); enabled|disabled" },
|
||||
{ "fceumm_apu_2", "Enable Sound Channel 2 (Square 2); enabled|disabled" },
|
||||
{ "fceumm_apu_3", "Enable Sound Channel 3 (Triangle); enabled|disabled" },
|
||||
{ "fceumm_apu_4", "Enable Sound Channel 4 (Noise); enabled|disabled" },
|
||||
{ "fceumm_apu_5", "Enable Sound Channel 5 (PCM); enabled|disabled" },
|
||||
#endif
|
||||
{ "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" },
|
||||
{ "fceumm_turbo_delay", "Turbo Delay (in frames); 3|5|10|15|30|60|1|2" },
|
||||
{ "fceumm_zapper_mode", "Zapper Mode; lightgun|mouse" },
|
||||
{ "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" },
|
||||
{ "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" },
|
||||
{ "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads1[] = {
|
||||
{ "Auto", RETRO_DEVICE_JOYPAD },
|
||||
{ "Auto", RETRO_DEVICE_AUTO },
|
||||
{ "Gamepad", RETRO_DEVICE_GAMEPAD },
|
||||
{ "Zapper", RETRO_DEVICE_ZAPPER },
|
||||
{ NULL, 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads2[] = {
|
||||
{ "Auto", RETRO_DEVICE_JOYPAD },
|
||||
{ "Auto", RETRO_DEVICE_AUTO },
|
||||
{ "Gamepad", RETRO_DEVICE_GAMEPAD },
|
||||
{ "Arkanoid", RETRO_DEVICE_ARKANOID },
|
||||
{ "Zapper", RETRO_DEVICE_ZAPPER },
|
||||
{ NULL, 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads3[] = {
|
||||
{ "Auto", RETRO_DEVICE_AUTO },
|
||||
{ "Gamepad", RETRO_DEVICE_GAMEPAD },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads4[] = {
|
||||
{ "Auto", RETRO_DEVICE_AUTO },
|
||||
{ "Gamepad", RETRO_DEVICE_GAMEPAD },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads5[] = {
|
||||
{ "Auto", RETRO_DEVICE_FC_AUTO },
|
||||
{ "Arkanoid", RETRO_DEVICE_FC_ARKANOID },
|
||||
{ "(Bandai) Hyper Shot", RETRO_DEVICE_FC_SHADOW },
|
||||
{ "Oeka Kids Tablet", RETRO_DEVICE_FC_OEKAKIDS },
|
||||
{ "4-Player Adapter", RETRO_DEVICE_FC_4PLAYERS },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_info ports[] = {
|
||||
{ pads1, 3 },
|
||||
{ pads2, 4 },
|
||||
{ 0 },
|
||||
{ pads3, 2 },
|
||||
{ pads4, 2 },
|
||||
{ pads5, 5 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
environ_cb = cb;
|
||||
@@ -642,16 +836,16 @@ void retro_get_system_info(struct retro_system_info *info)
|
||||
void retro_get_system_av_info(struct retro_system_av_info *info)
|
||||
{
|
||||
#ifdef PSP
|
||||
unsigned width = use_overscan ? 256 : (256 - 16);
|
||||
unsigned height = use_overscan ? 240 : (240 - 16);
|
||||
unsigned width = NES_WIDTH - (use_overscan ? 16 : 0);
|
||||
unsigned height = NES_HEIGHT - (use_overscan ? 16 : 0);
|
||||
#else
|
||||
unsigned width = 256 - (overscan_h ? 16 : 0);
|
||||
unsigned height = 240 - (overscan_v ? 16 : 0);
|
||||
unsigned width = NES_WIDTH - (overscan_h ? 16 : 0);
|
||||
unsigned height = NES_HEIGHT - (overscan_v ? 16 : 0);
|
||||
#endif
|
||||
info->geometry.base_width = width;
|
||||
info->geometry.base_height = height;
|
||||
info->geometry.max_width = width;
|
||||
info->geometry.max_height = height;
|
||||
info->geometry.max_width = NES_WIDTH;
|
||||
info->geometry.max_height = NES_HEIGHT;
|
||||
info->geometry.aspect_ratio = (float)(use_par ? NES_8_7_PAR : NES_4_3);
|
||||
info->timing.sample_rate = (float)sndsamplerate;
|
||||
if (FSettings.PAL || dendy)
|
||||
@@ -681,6 +875,20 @@ void retro_init(void)
|
||||
if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565))
|
||||
log_cb.log(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
|
||||
#endif
|
||||
|
||||
/* initialize some of the default variables */
|
||||
#ifdef GEKKO
|
||||
sndsamplerate = 32000;
|
||||
#else
|
||||
sndsamplerate = 48000;
|
||||
#endif
|
||||
sndquality = 0;
|
||||
sndvolume = 150;
|
||||
swapDuty = 0;
|
||||
|
||||
/* Wii: initialize this or else last variable is passed through
|
||||
* when loading another rom causing save state size change. */
|
||||
serialize_size = 0;
|
||||
}
|
||||
|
||||
static void retro_set_custom_palette(void)
|
||||
@@ -690,27 +898,24 @@ static void retro_set_custom_palette(void)
|
||||
ipalette = 0;
|
||||
use_raw_palette = false;
|
||||
|
||||
if (!current_palette || current_palette > MAXPAL || (GameInfo->type == GIT_VSUNI))
|
||||
if (current_palette == PAL_DEFAULT || current_palette == PAL_CUSTOM
|
||||
|| (GameInfo->type == GIT_VSUNI))
|
||||
{
|
||||
if (current_palette > MAXPAL && GameInfo->type != GIT_VSUNI)
|
||||
if (current_palette == PAL_CUSTOM)
|
||||
{
|
||||
if (external_palette_exist)
|
||||
{
|
||||
ipalette = 1;
|
||||
}
|
||||
if (external_palette_exist && (GameInfo->type != GIT_VSUNI))
|
||||
ipalette = 1;
|
||||
}
|
||||
|
||||
FCEU_ResetPalette(); /* Do palette reset. Priority will be:
|
||||
* -ipalette : sets external palette
|
||||
* -ntsccol : sets ntsc to default palette.
|
||||
* If none of the above are true, then
|
||||
* default palette will be used.
|
||||
* VS Uniystem should always use default palette.
|
||||
FCEU_ResetPalette(); /* if ipalette is set to 1, external palette
|
||||
* is loaded when FCEU_ResetPalette is called,
|
||||
* else it will load default NES palette.
|
||||
* VS Unisystem should always use default palette.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_palette == MAXPAL) /* raw palette */
|
||||
if (current_palette == PAL_RAW) /* raw palette */
|
||||
{
|
||||
use_raw_palette = true;
|
||||
for (i = 0; i < 64; i++)
|
||||
@@ -726,14 +931,21 @@ static void retro_set_custom_palette(void)
|
||||
|
||||
for ( i = 0; i < 64; i++ )
|
||||
{
|
||||
r = palettes[current_palette-1].data[i] >> 16;
|
||||
g = ( palettes[current_palette-1].data[i] & 0xff00 ) >> 8;
|
||||
b = ( palettes[current_palette-1].data[i] & 0xff );
|
||||
unsigned palette_data = palettes[current_palette].data[i];
|
||||
r = ( palette_data >> 16 ) & 0xff;
|
||||
g = ( ( palette_data & 0xff00 ) >> 8 ) & 0xff;
|
||||
b = ( palette_data & 0xff );
|
||||
FCEUD_SetPalette( i, r, g, b);
|
||||
FCEUD_SetPalette( i+64, r, g, b);
|
||||
FCEUD_SetPalette( i+128, r, g, b);
|
||||
FCEUD_SetPalette( i+192, r, g, b);
|
||||
FCEUD_SetPalette( i + 64, r, g, b);
|
||||
FCEUD_SetPalette( i + 128, r, g, b);
|
||||
FCEUD_SetPalette( i + 192, r, g, b);
|
||||
}
|
||||
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
if (ps2) {
|
||||
ps2->updatedPalette = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set variables for NTSC(1) / PAL(2) / Dendy(3)
|
||||
@@ -787,6 +999,10 @@ void retro_deinit (void)
|
||||
free(fceu_video_out);
|
||||
fceu_video_out = NULL;
|
||||
#endif
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
ps2 = NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void retro_reset(void)
|
||||
@@ -809,71 +1025,20 @@ static const keymap bindmap[] = {
|
||||
{ RETRO_DEVICE_ID_JOYPAD_DOWN, JOY_DOWN },
|
||||
{ RETRO_DEVICE_ID_JOYPAD_LEFT, JOY_LEFT },
|
||||
{ RETRO_DEVICE_ID_JOYPAD_RIGHT, JOY_RIGHT },
|
||||
};
|
||||
|
||||
static const keymap turbomap[] = {
|
||||
{ RETRO_DEVICE_ID_JOYPAD_X, JOY_A },
|
||||
{ RETRO_DEVICE_ID_JOYPAD_Y, JOY_B },
|
||||
};
|
||||
|
||||
/* Set NES controllers */
|
||||
void set_input_nes_controller(unsigned port, int x)
|
||||
static void set_apu_channels(int chan)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case SI_NONE:
|
||||
input_type[port] = RETRO_DEVICE_NONE;
|
||||
FCEUI_SetInput(port, SI_NONE, NULL, 0);
|
||||
FCEU_printf(" Player %u: None\n", port + 1);
|
||||
break;
|
||||
case SI_ZAPPER:
|
||||
input_type[port] = RETRO_DEVICE_ZAPPER;
|
||||
FCEUI_SetInput(port, SI_ZAPPER, MouseData[port], 1);
|
||||
FCEU_printf(" Player %u: Zapper\n", port + 1);
|
||||
break;
|
||||
case SI_ARKANOID:
|
||||
input_type[port] = RETRO_DEVICE_ARKANOID;
|
||||
FCEUI_SetInput(port, SI_ARKANOID, MouseData[port], 0);
|
||||
FCEU_printf(" Player %u: Arkanoid\n", port + 1);
|
||||
break;
|
||||
case SI_GAMEPAD: /* Set gamepad as default when an unsupported device */
|
||||
default: /* is used */
|
||||
input_type[port] = RETRO_DEVICE_GAMEPAD;
|
||||
FCEUI_SetInput(port, SI_GAMEPAD, &JSReturn, 0);
|
||||
FCEU_printf(" Player %u: Gamepad\n", port + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable_4player) // check if 4-player mode is enabled
|
||||
input_type[2] = input_type[3] = RETRO_DEVICE_GAMEPAD;
|
||||
}
|
||||
|
||||
/* Set Famicom controllers */
|
||||
void set_input_famicom_controller(int x)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case SIFC_ARKANOID:
|
||||
input_type[4] = RETRO_DEVICE_FC_ARKANOID;
|
||||
FCEUI_SetInputFC(SIFC_ARKANOID, fc_MouseData, 0);
|
||||
FCEU_printf("Famicom Expansion: Arkanoid\n");
|
||||
break;
|
||||
case SIFC_SHADOW:
|
||||
input_type[4] = RETRO_DEVICE_FC_SHADOW;
|
||||
FCEUI_SetInputFC(SIFC_SHADOW, fc_MouseData, 1);
|
||||
FCEU_printf("Famicom Expansion: (Bandai) Hyper Shot\n");
|
||||
break;
|
||||
case SIFC_OEKAKIDS:
|
||||
input_type[4] = RETRO_DEVICE_FC_OEKAKIDS;
|
||||
FCEUI_SetInputFC(SIFC_OEKAKIDS, fc_MouseData, 1);
|
||||
FCEU_printf("Famicom Expansion: Oeka Kids Tablet\n");
|
||||
break;
|
||||
default:
|
||||
/* Do not disable port if a 4-player adaptor is used */
|
||||
if (!enable_4player)
|
||||
{
|
||||
input_type[4] = 0;
|
||||
FCEUI_SetInputFC(SIFC_NONE, NULL, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
FSettings.SquareVolume[1] = 256 * ((chan >> 0) & 1);
|
||||
FSettings.SquareVolume[0] = 256 * ((chan >> 1) & 1);
|
||||
FSettings.TriangleVolume = 256 * ((chan >> 2) & 1);
|
||||
FSettings.NoiseVolume = 256 * ((chan >> 3) & 1);
|
||||
FSettings.PCMVolume = 256 * ((chan >> 4) & 1);
|
||||
}
|
||||
|
||||
static void check_variables(bool startup)
|
||||
@@ -881,6 +1046,8 @@ static void check_variables(bool startup)
|
||||
struct retro_variable var = {0};
|
||||
struct retro_system_av_info av_info;
|
||||
bool geometry_update = false;
|
||||
char key[256];
|
||||
int i, enable_apu;
|
||||
|
||||
var.key = "fceumm_palette";
|
||||
|
||||
@@ -889,43 +1056,43 @@ static void check_variables(bool startup)
|
||||
unsigned orig_value = current_palette;
|
||||
|
||||
if (!strcmp(var.value, "default"))
|
||||
current_palette = 0;
|
||||
else if (!strcmp(var.value, "asqrealc"))
|
||||
current_palette = 1;
|
||||
else if (!strcmp(var.value, "nintendo-vc"))
|
||||
current_palette = 2;
|
||||
else if (!strcmp(var.value, "rgb"))
|
||||
current_palette = 3;
|
||||
else if (!strcmp(var.value, "yuv-v3"))
|
||||
current_palette = 4;
|
||||
else if (!strcmp(var.value, "unsaturated-final"))
|
||||
current_palette = 5;
|
||||
else if (!strcmp(var.value, "sony-cxa2025as-us"))
|
||||
current_palette = 6;
|
||||
else if (!strcmp(var.value, "pal"))
|
||||
current_palette = 7;
|
||||
else if (!strcmp(var.value, "bmf-final2"))
|
||||
current_palette = 8;
|
||||
else if (!strcmp(var.value, "bmf-final3"))
|
||||
current_palette = 9;
|
||||
else if (!strcmp(var.value, "smooth-fbx"))
|
||||
current_palette = 10;
|
||||
else if (!strcmp(var.value, "composite-direct-fbx"))
|
||||
current_palette = 11;
|
||||
else if (!strcmp(var.value, "pvm-style-d93-fbx"))
|
||||
current_palette = 12;
|
||||
else if (!strcmp(var.value, "ntsc-hardware-fbx"))
|
||||
current_palette = 13;
|
||||
else if (!strcmp(var.value, "nes-classic-fbx-fs"))
|
||||
current_palette = 14;
|
||||
else if (!strcmp(var.value, "nescap"))
|
||||
current_palette = 15;
|
||||
else if (!strcmp(var.value, "wavebeam"))
|
||||
current_palette = 16;
|
||||
current_palette = PAL_DEFAULT;
|
||||
else if (!strcmp(var.value, "raw"))
|
||||
current_palette = MAXPAL;
|
||||
current_palette = PAL_RAW;
|
||||
else if (!strcmp(var.value, "custom"))
|
||||
current_palette = MAXPAL+1;
|
||||
current_palette = PAL_CUSTOM;
|
||||
else if (!strcmp(var.value, "asqrealc"))
|
||||
current_palette = 0;
|
||||
else if (!strcmp(var.value, "nintendo-vc"))
|
||||
current_palette = 1;
|
||||
else if (!strcmp(var.value, "rgb"))
|
||||
current_palette = 2;
|
||||
else if (!strcmp(var.value, "yuv-v3"))
|
||||
current_palette = 3;
|
||||
else if (!strcmp(var.value, "unsaturated-final"))
|
||||
current_palette = 4;
|
||||
else if (!strcmp(var.value, "sony-cxa2025as-us"))
|
||||
current_palette = 5;
|
||||
else if (!strcmp(var.value, "pal"))
|
||||
current_palette = 6;
|
||||
else if (!strcmp(var.value, "bmf-final2"))
|
||||
current_palette = 7;
|
||||
else if (!strcmp(var.value, "bmf-final3"))
|
||||
current_palette = 8;
|
||||
else if (!strcmp(var.value, "smooth-fbx"))
|
||||
current_palette = 9;
|
||||
else if (!strcmp(var.value, "composite-direct-fbx"))
|
||||
current_palette = 10;
|
||||
else if (!strcmp(var.value, "pvm-style-d93-fbx"))
|
||||
current_palette = 11;
|
||||
else if (!strcmp(var.value, "ntsc-hardware-fbx"))
|
||||
current_palette = 12;
|
||||
else if (!strcmp(var.value, "nes-classic-fbx-fs"))
|
||||
current_palette = 13;
|
||||
else if (!strcmp(var.value, "nescap"))
|
||||
current_palette = 14;
|
||||
else if (!strcmp(var.value, "wavebeam"))
|
||||
current_palette = 15;
|
||||
|
||||
if (current_palette != orig_value)
|
||||
retro_set_custom_palette();
|
||||
@@ -1051,13 +1218,19 @@ static void check_variables(bool startup)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
turbo_enabler[i] = 0;
|
||||
turbo_enabler[0] = 0;
|
||||
turbo_enabler[1] = 0;
|
||||
|
||||
if (!strcmp(var.value, "Player 1"))
|
||||
{
|
||||
turbo_enabler[0] = 1;
|
||||
turbo_enabler[1] = 0;
|
||||
}
|
||||
else if (!strcmp(var.value, "Player 2"))
|
||||
{
|
||||
turbo_enabler[0] = 0;
|
||||
turbo_enabler[1] = 1;
|
||||
}
|
||||
else if (!strcmp(var.value, "Both"))
|
||||
{
|
||||
turbo_enabler[0] = 1;
|
||||
@@ -1088,7 +1261,6 @@ static void check_variables(bool startup)
|
||||
FCEUD_RegionOverride(setregion);
|
||||
}
|
||||
|
||||
|
||||
var.key = "fceumm_aspect";
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
@@ -1140,6 +1312,27 @@ static void check_variables(bool startup)
|
||||
swapDuty = newval;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
var.key = key;
|
||||
|
||||
enable_apu = 0;
|
||||
|
||||
strcpy(key, "fceumm_apu_x");
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
key[strlen("fceumm_apu_")] = '1' + i;
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && !strcmp(var.value, "disabled"))
|
||||
{
|
||||
enable_apu |= (1 << i);
|
||||
}
|
||||
}
|
||||
set_apu_channels(enable_apu ^ 0xff);
|
||||
#else
|
||||
set_apu_channels(0xff);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static int mzx = 0, mzy = 0;
|
||||
@@ -1226,55 +1419,58 @@ void get_mouse_input(unsigned port, uint32_t *zapdata)
|
||||
* each player
|
||||
*/
|
||||
|
||||
#define MAX_BUTTONS 8
|
||||
#define TURBO_BUTTONS 2
|
||||
unsigned char turbo_button_toggle[MAX_PLAYERS][TURBO_BUTTONS] = { {0} };
|
||||
|
||||
static void FCEUD_UpdateInput(void)
|
||||
{
|
||||
unsigned player, port, i;
|
||||
unsigned player, port;
|
||||
|
||||
poll_cb();
|
||||
|
||||
JSReturn = 0;
|
||||
|
||||
// nes gamepad
|
||||
/* nes gamepad */
|
||||
for (player = 0; player < MAX_PLAYERS; player++)
|
||||
{
|
||||
uint8_t input_buf = 0;
|
||||
bool player_enabled = (input_type[player] == RETRO_DEVICE_GAMEPAD);
|
||||
int i = 0;
|
||||
uint8_t input_buf = 0;
|
||||
int player_enabled = (input_type[player] == RETRO_DEVICE_GAMEPAD) || (input_type[player] == RETRO_DEVICE_JOYPAD);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
input_buf |= (player_enabled && input_cb(player, RETRO_DEVICE_JOYPAD, 0,
|
||||
bindmap[i].retro)) ? bindmap[i].nes : 0;
|
||||
|
||||
/* Turbo A and Turbo B buttons are
|
||||
* mapped to Joypad X and Joypad Y
|
||||
* in RetroArch joypad.
|
||||
*
|
||||
* We achieve this by keeping track of
|
||||
* the number of times it increments
|
||||
* the toggle counter and fire or not fire
|
||||
* depending on whether the delay value has
|
||||
* been reached.
|
||||
*/
|
||||
|
||||
if (turbo_enabler[player] == 1 && player_enabled)
|
||||
if (player_enabled)
|
||||
{
|
||||
/* Handle Turbo A & B buttons */
|
||||
for (i = 8; i < 10; i++)
|
||||
for (i = 0; i < MAX_BUTTONS; i++)
|
||||
input_buf |= input_cb(player, RETRO_DEVICE_JOYPAD, 0,
|
||||
bindmap[i].retro) ? bindmap[i].nes : 0;
|
||||
|
||||
/* Turbo A and Turbo B buttons are
|
||||
* mapped to Joypad X and Joypad Y
|
||||
* in RetroArch joypad.
|
||||
*
|
||||
* We achieve this by keeping track of
|
||||
* the number of times it increments
|
||||
* the toggle counter and fire or not fire
|
||||
* depending on whether the delay value has
|
||||
* been reached.
|
||||
*/
|
||||
|
||||
if (turbo_enabler[player])
|
||||
{
|
||||
if (input_cb(player, RETRO_DEVICE_JOYPAD, 0, bindmap[i].retro))
|
||||
/* Handle Turbo A & B buttons */
|
||||
for (i = 0; i < TURBO_BUTTONS; i++)
|
||||
{
|
||||
if (turbo_button_toggle[player][i-8] == 0)
|
||||
input_buf |= bindmap[i].nes;
|
||||
turbo_button_toggle[player][i-8]++;
|
||||
if (turbo_button_toggle[player][i-8] > turbo_delay)
|
||||
/* Reset the toggle if delay value is reached */
|
||||
turbo_button_toggle[player][i-8] = 0;
|
||||
if (input_cb(player, RETRO_DEVICE_JOYPAD, 0, turbomap[i].retro))
|
||||
{
|
||||
if (!turbo_button_toggle[player][i])
|
||||
input_buf |= turbomap[i].nes;
|
||||
turbo_button_toggle[player][i]++;
|
||||
turbo_button_toggle[player][i] %= turbo_delay + 1;
|
||||
}
|
||||
else
|
||||
/* If the button is not pressed, just reset the toggle */
|
||||
turbo_button_toggle[player][i] = 0;
|
||||
}
|
||||
else
|
||||
/* If the button is not pressed, just reset the toggle */
|
||||
turbo_button_toggle[player][i-8] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1289,7 +1485,6 @@ static void FCEUD_UpdateInput(void)
|
||||
}
|
||||
|
||||
JSReturn |= (input_buf & 0xff) << (player << 3);
|
||||
|
||||
}
|
||||
|
||||
/* other inputs*/
|
||||
@@ -1382,6 +1577,37 @@ static void retro_run_blit(uint8_t *gfx)
|
||||
sceGuFinish();
|
||||
|
||||
video_cb(texture_vram_p, width, height, 256);
|
||||
#elif defined(RENDER_GSKIT_PS2)
|
||||
uint32_t *buf = (uint32_t *)RETRO_HW_FRAME_BUFFER_VALID;
|
||||
|
||||
if (!ps2) {
|
||||
if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&ps2) || !ps2) {
|
||||
printf("Failed to get HW rendering interface!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) {
|
||||
printf("HW render interface mismatch, expected %u, got %u!\n",
|
||||
RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION, ps2->interface_version);
|
||||
return;
|
||||
}
|
||||
|
||||
ps2->coreTexture->Width = width;
|
||||
ps2->coreTexture->Height = height;
|
||||
ps2->coreTexture->PSM = GS_PSM_T8;
|
||||
ps2->coreTexture->ClutPSM = GS_PSM_CT16;
|
||||
ps2->coreTexture->Filter = GS_FILTER_LINEAR;
|
||||
ps2->padding = (struct retro_hw_ps2_insets){ overscan_v ? 8.0f : 0.0f,
|
||||
overscan_h ? 8.0f : 0.0f,
|
||||
overscan_v ? 8.0f : 0.0f,
|
||||
overscan_h ? 8.0f : 0.0f};
|
||||
}
|
||||
|
||||
ps2->updatedPalette = true;
|
||||
ps2->coreTexture->Clut = (u32*)retro_palette;
|
||||
ps2->coreTexture->Mem = (u32*)gfx;
|
||||
|
||||
video_cb(buf, width, height, pitch);
|
||||
#else
|
||||
incr += (overscan_h ? 16 : 0);
|
||||
width -= (overscan_h ? 16 : 0);
|
||||
@@ -1408,8 +1634,6 @@ static void retro_run_blit(uint8_t *gfx)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool firstrun = true;
|
||||
|
||||
void retro_run(void)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -1417,13 +1641,6 @@ void retro_run(void)
|
||||
int32_t ssize = 0;
|
||||
bool updated = false;
|
||||
|
||||
if (firstrun)
|
||||
{
|
||||
/* setup famicom expansion devices */
|
||||
set_input_famicom_controller(GameInfo->inputfc);
|
||||
firstrun = false;
|
||||
}
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
|
||||
check_variables(false);
|
||||
|
||||
@@ -1438,8 +1655,6 @@ void retro_run(void)
|
||||
retro_run_blit(gfx);
|
||||
}
|
||||
|
||||
static unsigned serialize_size = 0;
|
||||
|
||||
size_t retro_serialize_size(void)
|
||||
{
|
||||
if (serialize_size == 0)
|
||||
@@ -1763,7 +1978,14 @@ static const struct cartridge_db famicom_4p_db_list[] =
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
static char slash = '\\';
|
||||
#else
|
||||
static char slash = '/';
|
||||
#endif
|
||||
|
||||
extern uint32_t iNESGameCRC32;
|
||||
extern int option_ramstate;
|
||||
|
||||
bool retro_load_game(const struct retro_game_info *game)
|
||||
{
|
||||
@@ -1826,10 +2048,25 @@ bool retro_load_game(const struct retro_game_info *game)
|
||||
|
||||
struct retro_memory_descriptor descs[64];
|
||||
struct retro_memory_map mmaps;
|
||||
struct retro_variable var = {0};
|
||||
|
||||
if (!game)
|
||||
return false;
|
||||
|
||||
var.value = 0;
|
||||
var.key = "fceumm_ramstate";
|
||||
|
||||
/* set this variable before calling PowerNES() */
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
{
|
||||
if (!strcmp(var.value, "random"))
|
||||
option_ramstate = 2;
|
||||
else if (!strcmp(var.value, "fill $00"))
|
||||
option_ramstate = 1;
|
||||
else
|
||||
option_ramstate = 0;
|
||||
}
|
||||
|
||||
PowerNES();
|
||||
check_system_specs();
|
||||
#if defined(_3DS)
|
||||
@@ -1864,17 +2101,14 @@ bool retro_load_game(const struct retro_game_info *game)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++)
|
||||
for (i = 0; i < MAX_PORTS; i++) {
|
||||
FCEUI_SetInput(i, SI_GAMEPAD, &JSReturn, 0);
|
||||
input_type[i] == RETRO_DEVICE_JOYPAD;
|
||||
}
|
||||
|
||||
external_palette_exist = ipalette;
|
||||
if (external_palette_exist)
|
||||
FCEU_printf("nes.pal loaded from system directory.\n");
|
||||
else
|
||||
FCEU_PrintError("Cannot find nes.pal from system directory.\n");
|
||||
|
||||
if (GameInfo->type == GIT_VSUNI)
|
||||
FCEU_PrintError("VS Unisystem rom loaded, will use default palette.\n");
|
||||
FCEU_printf(" Loading custom palette: %s%cnes.pal\n", dir, slash);
|
||||
|
||||
is_PAL = retro_get_region(); /* Save current loaded region info */
|
||||
|
||||
@@ -1899,6 +2133,7 @@ bool retro_load_game(const struct retro_game_info *game)
|
||||
{
|
||||
if (famicom_4p_db_list[i].crc == iNESGameCRC32)
|
||||
{
|
||||
GameInfo->inputfc = SIFC_4PLAYER;
|
||||
FCEUI_SetInputFC(SIFC_4PLAYER, &JSReturn, 0);
|
||||
enable_4player = true;
|
||||
break;
|
||||
@@ -1946,6 +2181,9 @@ void retro_unload_game(void)
|
||||
free(fceu_video_out);
|
||||
fceu_video_out = NULL;
|
||||
#endif
|
||||
#if defined(RENDER_GSKIT_PS2)
|
||||
ps2 = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned retro_get_region(void)
|
||||
@@ -1953,7 +2191,6 @@ unsigned retro_get_region(void)
|
||||
return FSettings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC;
|
||||
}
|
||||
|
||||
|
||||
void *retro_get_memory_data(unsigned type)
|
||||
{
|
||||
uint8_t* data;
|
||||
@@ -1961,10 +2198,12 @@ void *retro_get_memory_data(unsigned type)
|
||||
switch(type)
|
||||
{
|
||||
case RETRO_MEMORY_SAVE_RAM:
|
||||
if (iNESCart.battery)
|
||||
if (iNESCart.battery && iNESCart.SaveGame[0] && iNESCart.SaveGameLen[0])
|
||||
return iNESCart.SaveGame[0];
|
||||
else if (UNIFCart.battery)
|
||||
else if (UNIFCart.battery && UNIFCart.SaveGame[0] && UNIFCart.SaveGameLen[0])
|
||||
return UNIFCart.SaveGame[0];
|
||||
else if (GameInfo->type == GIT_FDS)
|
||||
return FDSROM_ptr();
|
||||
else
|
||||
data = NULL;
|
||||
break;
|
||||
@@ -1986,10 +2225,12 @@ size_t retro_get_memory_size(unsigned type)
|
||||
switch(type)
|
||||
{
|
||||
case RETRO_MEMORY_SAVE_RAM:
|
||||
if (iNESCart.battery)
|
||||
if (iNESCart.battery && iNESCart.SaveGame[0] && iNESCart.SaveGameLen[0])
|
||||
size = iNESCart.SaveGameLen[0];
|
||||
else if (UNIFCart.battery)
|
||||
else if (UNIFCart.battery && UNIFCart.SaveGame[0] && UNIFCart.SaveGameLen[0])
|
||||
size = UNIFCart.SaveGameLen[0];
|
||||
else if (GameInfo->type == GIT_FDS)
|
||||
size = FDSROM_size();
|
||||
else
|
||||
size = 0;
|
||||
break;
|
||||
|
||||
@@ -31,7 +31,10 @@ void FlipByteOrder(uint8 *src, uint32 count)
|
||||
uint8 *start = src;
|
||||
uint8 *end = src + count - 1;
|
||||
|
||||
while(start < end)
|
||||
if ((count & 1) || !count)
|
||||
return; /* This shouldn't happen. */
|
||||
|
||||
while (count--)
|
||||
{
|
||||
uint8 tmp;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fceu-types.h"
|
||||
#include "fceu.h"
|
||||
|
||||
@@ -53,6 +53,19 @@ typedef unsigned long long uint64;
|
||||
typedef long long int64;
|
||||
#endif
|
||||
|
||||
#ifndef INLINE
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#elif defined(_MWERKS_)
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PSS_STYLE == 2
|
||||
|
||||
#define PSS "\\"
|
||||
|
||||
11
src/fceu.c
11
src/fceu.c
@@ -381,6 +381,8 @@ void ResetNES(void)
|
||||
X6502_Reset();
|
||||
}
|
||||
|
||||
int option_ramstate = 0;
|
||||
|
||||
void FCEU_MemoryRand(uint8 *ptr, uint32 size)
|
||||
{
|
||||
int x = 0;
|
||||
@@ -394,7 +396,14 @@ void FCEU_MemoryRand(uint8 *ptr, uint32 size)
|
||||
*ptr = (x & 1) ? 0x55 : 0xAA; /* F-15 Sity War HISCORE is screwed... */
|
||||
/* 1942 SCORE/HISCORE is screwed... */
|
||||
#endif
|
||||
*ptr = 0xFF;
|
||||
uint8_t v;
|
||||
switch (option_ramstate)
|
||||
{
|
||||
case 0: v = 0xff; break;
|
||||
case 1: v = 0x00; break;
|
||||
case 2: v = (uint8_t)rand(); break;
|
||||
}
|
||||
*ptr = v;
|
||||
x++;
|
||||
size--;
|
||||
ptr++;
|
||||
|
||||
@@ -83,6 +83,10 @@ typedef struct {
|
||||
int PAL;
|
||||
int NetworkPlay;
|
||||
int SoundVolume;
|
||||
int TriangleVolume;
|
||||
int SquareVolume[2];
|
||||
int NoiseVolume;
|
||||
int PCMVolume;
|
||||
int GameGenie;
|
||||
|
||||
/* Current first and last rendered scanlines. */
|
||||
|
||||
320
src/fds.c
320
src/fds.c
@@ -62,6 +62,8 @@ static uint8 FDSRegs[6];
|
||||
static int32 IRQLatch, IRQCount;
|
||||
static uint8 IRQa;
|
||||
|
||||
static uint8 *FDSROM = NULL;
|
||||
static uint32 FDSROMSize = 0;
|
||||
static uint8 *FDSRAM = NULL;
|
||||
static uint32 FDSRAMSize;
|
||||
static uint8 *FDSBIOS = NULL;
|
||||
@@ -71,7 +73,6 @@ static uint32 CHRRAMSize;
|
||||
|
||||
/* Original disk data backup, to help in creating save states. */
|
||||
static uint8 *diskdatao[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static uint8 *diskdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static uint32 TotalSides;
|
||||
@@ -84,6 +85,15 @@ static uint8 SelectDisk, InDisk;
|
||||
uint32 lastDiskPtrRead, lastDiskPtrWrite;
|
||||
|
||||
#define DC_INC 1
|
||||
#define BYTES_PER_SIDE 65500
|
||||
|
||||
uint8 *FDSROM_ptr(void) {
|
||||
return (FDSROM);
|
||||
}
|
||||
|
||||
uint32 FDSROM_size(void) {
|
||||
return (FDSROMSize);
|
||||
}
|
||||
|
||||
void FDSGI(int h) {
|
||||
switch (h) {
|
||||
@@ -142,10 +152,12 @@ static void FDSInit(void) {
|
||||
|
||||
void FCEU_FDSInsert(int oride) {
|
||||
if (InDisk == 255) {
|
||||
FCEU_DispMessage("Disk %d Side %s Inserted", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
FCEU_DispMessage("Disk %d of %d Side %s Inserted",
|
||||
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
InDisk = SelectDisk;
|
||||
} else {
|
||||
FCEU_DispMessage("Disk %d Side %s Ejected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
FCEU_DispMessage("Disk %d of %d Side %s Ejected",
|
||||
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
InDisk = 255;
|
||||
}
|
||||
}
|
||||
@@ -160,21 +172,23 @@ void FCEU_FDSSelect(void) {
|
||||
return;
|
||||
}
|
||||
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
|
||||
FCEU_DispMessage("Disk %d Side %s Selected", SelectDisk >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
FCEU_DispMessage("Disk %d of %d Side %s Selected",
|
||||
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
|
||||
}
|
||||
|
||||
/* 2018/12/15 - update irq timings */
|
||||
static void FP_FASTAPASS(1) FDSFix(int a) {
|
||||
if ((IRQa & 2) && IRQCount) {
|
||||
IRQCount -= a;
|
||||
if ((IRQa & 2) && (FDSRegs[3] & 0x1)) {
|
||||
if (IRQCount <= 0) {
|
||||
if (!(IRQa & 1)) {
|
||||
IRQa &= ~2;
|
||||
IRQCount = IRQLatch = 0;
|
||||
} else
|
||||
IRQCount = IRQLatch;
|
||||
if (!(IRQa & 1))
|
||||
IRQa &= ~2; /* does not clear latch, fix Druid */
|
||||
IRQCount = IRQLatch;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
} else {
|
||||
IRQCount -= a;
|
||||
}
|
||||
}
|
||||
|
||||
if (DiskSeekIRQ > 0) {
|
||||
DiskSeekIRQ -= a;
|
||||
if (DiskSeekIRQ <= 0) {
|
||||
@@ -492,20 +506,29 @@ void FDSSoundReset(void) {
|
||||
static DECLFW(FDSWrite) {
|
||||
switch (A) {
|
||||
case 0x4020:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQLatch &= 0xFF00;
|
||||
IRQLatch |= V;
|
||||
break;
|
||||
case 0x4021:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQLatch &= 0xFF;
|
||||
IRQLatch |= V << 8;
|
||||
break;
|
||||
case 0x4022:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQCount = IRQLatch;
|
||||
IRQa = V & 3;
|
||||
if (FDSRegs[3] & 0x1) {
|
||||
IRQa = (V & 0x3);
|
||||
if (IRQa & 2) {
|
||||
IRQCount = IRQLatch;
|
||||
} else {
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x4023:
|
||||
if (!(V & 1)) {
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
}
|
||||
case 0x4024:
|
||||
if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) {
|
||||
if (DiskPtr >= 0 && DiskPtr < 65500) {
|
||||
@@ -541,14 +564,180 @@ static DECLFW(FDSWrite) {
|
||||
FDSRegs[A & 7] = V;
|
||||
}
|
||||
|
||||
static void FreeFDSMemory(void) {
|
||||
int x;
|
||||
struct codes_t {
|
||||
uint8 code;
|
||||
char *name;
|
||||
};
|
||||
|
||||
for (x = 0; x < TotalSides; x++)
|
||||
if (diskdata[x]) {
|
||||
free(diskdata[x]);
|
||||
diskdata[x] = 0;
|
||||
static const struct codes_t list[] = {
|
||||
{ 0x01, "Nintendo" },
|
||||
{ 0x02, "Rocket Games" },
|
||||
{ 0x08, "Capcom" },
|
||||
{ 0x09, "Hot B Co." },
|
||||
{ 0x0A, "Jaleco" },
|
||||
{ 0x0B, "Coconuts Japan" },
|
||||
{ 0x0C, "Coconuts Japan/G.X.Media" },
|
||||
{ 0x13, "Electronic Arts Japan" },
|
||||
{ 0x18, "Hudson Soft Japan" },
|
||||
{ 0x19, "S.C.P." },
|
||||
{ 0x1A, "Yonoman" },
|
||||
{ 0x20, "Destination Software" },
|
||||
{ 0x22, "VR 1 Japan" },
|
||||
{ 0x25, "San-X" },
|
||||
{ 0x28, "Kemco Japan" },
|
||||
{ 0x29, "Seta" },
|
||||
{ 0x36, "Codemasters" },
|
||||
{ 0x37, "GAGA Communications" },
|
||||
{ 0x38, "Laguna" },
|
||||
{ 0x39, "Telstar Fun and Games" },
|
||||
{ 0x41, "Ubi Soft Entertainment" },
|
||||
{ 0x42, "Sunsoft" },
|
||||
{ 0x47, "Spectrum Holobyte" },
|
||||
{ 0x49, "Irem" },
|
||||
{ 0x4A, "Gakken" },
|
||||
{ 0x4D, "Malibu Games" },
|
||||
{ 0x4F, "Eidos/U.S. Gold" },
|
||||
{ 0x50, "Absolute Entertainment" },
|
||||
{ 0x51, "Acclaim" },
|
||||
{ 0x52, "Activision" },
|
||||
{ 0x53, "American Sammy Corp." },
|
||||
{ 0x54, "Take 2 Interactive" },
|
||||
{ 0x55, "Hi Tech" },
|
||||
{ 0x56, "LJN LTD." },
|
||||
{ 0x58, "Mattel" },
|
||||
{ 0x5A, "Mindscape/Red Orb Ent." },
|
||||
{ 0x5C, "Taxan" },
|
||||
{ 0x5D, "Midway" },
|
||||
{ 0x5F, "American Softworks" },
|
||||
{ 0x60, "Titus Interactive Studios" },
|
||||
{ 0x61, "Virgin Interactive" },
|
||||
{ 0x62, "Maxis" },
|
||||
{ 0x64, "LucasArts Entertainment" },
|
||||
{ 0x67, "Ocean" },
|
||||
{ 0x69, "Electronic Arts" },
|
||||
{ 0x6E, "Elite Systems Ltd." },
|
||||
{ 0x6F, "Electro Brain" },
|
||||
{ 0x70, "Infogrames" },
|
||||
{ 0x71, "Interplay" },
|
||||
{ 0x72, "JVC Musical Industries Inc" },
|
||||
{ 0x73, "Parker Brothers" },
|
||||
{ 0x75, "SCI" },
|
||||
{ 0x78, "THQ" },
|
||||
{ 0x79, "Accolade" },
|
||||
{ 0x7A, "Triffix Ent. Inc." },
|
||||
{ 0x7C, "Microprose Software" },
|
||||
{ 0x7D, "Universal Interactive Studios" },
|
||||
{ 0x7F, "Kemco" },
|
||||
{ 0x80, "Misawa" },
|
||||
{ 0x83, "LOZC" },
|
||||
{ 0x8B, "Bulletproof Software" },
|
||||
{ 0x8C, "Vic Tokai Inc." },
|
||||
{ 0x91, "Chun Soft" },
|
||||
{ 0x92, "Video System" },
|
||||
{ 0x93, "BEC" },
|
||||
{ 0x96, "Yonezawa/S'pal" },
|
||||
{ 0x97, "Kaneko" },
|
||||
{ 0x99, "Victor Interactive Software" },
|
||||
{ 0x9A, "Nichibutsu/Nihon Bussan" },
|
||||
{ 0x9B, "Tecmo" },
|
||||
{ 0x9C, "Imagineer" },
|
||||
{ 0x9F, "Nova" },
|
||||
{ 0xA0, "Telenet" },
|
||||
{ 0xA1, "Hori" },
|
||||
{ 0xA2, "Scorpion Soft " },
|
||||
{ 0xA4, "Konami" },
|
||||
{ 0xA6, "Kawada" },
|
||||
{ 0xA7, "Takara" },
|
||||
{ 0xA8, "Royal Industries" },
|
||||
{ 0xA9, "Technos Japan Corp." },
|
||||
{ 0xAA, "JVC" },
|
||||
{ 0xAC, "Toei Animation" },
|
||||
{ 0xAD, "Toho" },
|
||||
{ 0xAF, "Namco" },
|
||||
{ 0xB0, "Acclaim Japan" },
|
||||
{ 0xB1, "ASCII" },
|
||||
{ 0xB2, "Bandai" },
|
||||
{ 0xB3, "Soft Pro Inc." },
|
||||
{ 0xB4, "Enix" },
|
||||
{ 0xB6, "HAL Laboratory" },
|
||||
{ 0xB7, "SNK" },
|
||||
{ 0xB9, "Pony Canyon Hanbai" },
|
||||
{ 0xBA, "Culture Brain" },
|
||||
{ 0xBB, "Sunsoft" },
|
||||
{ 0xBC, "Toshiba EMI" },
|
||||
{ 0xBD, "Sony Imagesoft" },
|
||||
{ 0xBF, "Sammy" },
|
||||
{ 0xC0, "Taito" },
|
||||
{ 0xC1, "Sunsoft / Ask Co., Ltd." },
|
||||
{ 0xC2, "Kemco" },
|
||||
{ 0xC3, "Square Soft" },
|
||||
{ 0xC4, "Tokuma Shoten " },
|
||||
{ 0xC5, "Data East" },
|
||||
{ 0xC6, "Tonkin House" },
|
||||
{ 0xC7, "East Cube" },
|
||||
{ 0xC8, "Koei" },
|
||||
{ 0xCA, "Konami/Palcom/Ultra" },
|
||||
{ 0xCB, "Vapinc/NTVIC" },
|
||||
{ 0xCC, "Use Co.,Ltd." },
|
||||
{ 0xCD, "Meldac" },
|
||||
{ 0xCE, "FCI/Pony Canyon" },
|
||||
{ 0xCF, "Angel" },
|
||||
{ 0xD1, "Sofel" },
|
||||
/*{ 0xD2, "Quest" },*/
|
||||
{ 0xD2, "Bothtec, Inc." },
|
||||
{ 0xD3, "Sigma Enterprises" },
|
||||
{ 0xD4, "Ask Kodansa" },
|
||||
{ 0xD6, "Naxat" },
|
||||
{ 0xD7, "Copya System" },
|
||||
{ 0xD9, "Banpresto" },
|
||||
{ 0xDA, "TOMY" },
|
||||
/*{ 0xDB, "LJN Japan" },*/
|
||||
{ 0xDB, "Hiro Co., Ltd." },
|
||||
{ 0xDD, "NCS" },
|
||||
{ 0xDF, "Altron Corporation" },
|
||||
{ 0xE2, "Yutaka" },
|
||||
{ 0xE3, "Varie" },
|
||||
{ 0xE5, "Epoch" },
|
||||
{ 0xE7, "Athena" },
|
||||
{ 0xE8, "Asmik Ace Entertainment Inc." },
|
||||
{ 0xE9, "Natsume" },
|
||||
{ 0xEA, "King Records" },
|
||||
{ 0xEB, "Atlus" },
|
||||
{ 0xEC, "Epic/Sony Records" },
|
||||
{ 0xEE, "IGS" },
|
||||
{ 0xF0, "A Wave" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const char *getManufacturer(uint8 code)
|
||||
{
|
||||
int x = 0;
|
||||
char *ret = "unlicensed";
|
||||
|
||||
while (list[x].code != 0) {
|
||||
if (list[x].code == code) {
|
||||
ret = list[x].name;
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void FreeFDSMemory(void) {
|
||||
if (FDSROM)
|
||||
free(FDSROM);
|
||||
FDSROM = NULL;
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
if (FDSRAM)
|
||||
free(FDSRAM);
|
||||
FDSRAM = NULL;
|
||||
if (CHRRAM)
|
||||
free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
static int SubLoad(FCEUFILE *fp) {
|
||||
@@ -571,19 +760,21 @@ static int SubLoad(FCEUFILE *fp) {
|
||||
} else
|
||||
TotalSides = header[4];
|
||||
|
||||
md5_starts(&md5);
|
||||
|
||||
if (TotalSides > 8) TotalSides = 8;
|
||||
if (TotalSides < 1) TotalSides = 1;
|
||||
|
||||
FDSROMSize = TotalSides * BYTES_PER_SIDE;
|
||||
FDSROM = (uint8*)FCEU_malloc(FDSROMSize);
|
||||
|
||||
if (!FDSROM)
|
||||
return (0);
|
||||
|
||||
for (x = 0; x < TotalSides; x++)
|
||||
diskdata[x] = &FDSROM[x * BYTES_PER_SIDE];
|
||||
|
||||
md5_starts(&md5);
|
||||
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
diskdata[x] = (uint8*)FCEU_malloc(65500);
|
||||
if (!diskdata[x]) {
|
||||
int zol;
|
||||
for (zol = 0; zol < x; zol++)
|
||||
free(diskdata[zol]);
|
||||
return 0;
|
||||
}
|
||||
FCEU_fread(diskdata[x], 1, 65500, fp);
|
||||
md5_update(&md5, diskdata[x], 65500);
|
||||
}
|
||||
@@ -623,17 +814,9 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
|
||||
free(fn);
|
||||
|
||||
ResetCartMapping();
|
||||
FreeFDSMemory();
|
||||
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
if (FDSRAM)
|
||||
free(FDSRAM);
|
||||
FDSRAM = NULL;
|
||||
if (CHRRAM)
|
||||
free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
ResetCartMapping();
|
||||
|
||||
FDSBIOSsize = 8192;
|
||||
FDSBIOS = (uint8*)FCEU_gmalloc(FDSBIOSsize);
|
||||
@@ -643,16 +826,17 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
free(zp->fp->data);
|
||||
FCEU_fclose(zp);
|
||||
FCEU_PrintError("Error reading FDS BIOS ROM image.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(zp->fp->data);
|
||||
FCEU_fclose(zp);
|
||||
|
||||
FCEU_fseek(fp, 0, SEEK_SET);
|
||||
|
||||
FreeFDSMemory();
|
||||
if (!SubLoad(fp)) {
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
@@ -660,6 +844,16 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
diskdatao[x] = (uint8*)FCEU_malloc(65500);
|
||||
memcpy(diskdatao[x], diskdata[x], 65500);
|
||||
}
|
||||
|
||||
DiskWritten = 1;
|
||||
|
||||
#if 0
|
||||
/* auxillary rom loading for save file is now handled
|
||||
* using retro_get_memory_size/data */
|
||||
{
|
||||
FCEUFILE *tp;
|
||||
char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0);
|
||||
@@ -686,6 +880,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
}
|
||||
free(fn);
|
||||
}
|
||||
#endif
|
||||
|
||||
GameInfo->type = GIT_FDS;
|
||||
GameInterface = FDSGI;
|
||||
@@ -702,7 +897,12 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
AddExState(diskdata[x], 65500, 0, temp);
|
||||
}
|
||||
|
||||
AddExState(FDSRegs, sizeof(FDSRegs), 0, "FREG");
|
||||
AddExState(&FDSRegs[0], 1, 0, "REG1");
|
||||
AddExState(&FDSRegs[1], 1, 0, "REG2");
|
||||
AddExState(&FDSRegs[2], 1, 0, "REG3");
|
||||
AddExState(&FDSRegs[3], 1, 0, "REG4");
|
||||
AddExState(&FDSRegs[4], 1, 0, "REG5");
|
||||
AddExState(&FDSRegs[5], 1, 0, "REG6");
|
||||
AddExState(&IRQCount, 4, 1, "IRQC");
|
||||
AddExState(&IRQLatch, 4, 1, "IQL1");
|
||||
AddExState(&IRQa, 1, 0, "IRQA");
|
||||
@@ -715,19 +915,20 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
|
||||
CHRRAMSize = 8192;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
|
||||
memset(CHRRAM, 0, CHRRAMSize);
|
||||
SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1);
|
||||
AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
|
||||
|
||||
FDSRAMSize = 32768;
|
||||
FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize);
|
||||
memset(FDSRAM, 0, FDSRAMSize);
|
||||
SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1);
|
||||
AddExState(FDSRAM, FDSRAMSize, 0, "FDSR");
|
||||
|
||||
SetupCartMirroring(0, 0, 0);
|
||||
|
||||
FCEU_printf(" Sides: %d\n\n", TotalSides);
|
||||
FCEU_printf(" Code : %02x\n", diskdata[0][0xf]);
|
||||
FCEU_printf(" Manufacturer : %s\n", getManufacturer(diskdata[0][0xf]));
|
||||
FCEU_printf(" # of Sides : %d\n", TotalSides);
|
||||
FCEU_printf(" ROM MD5 : 0x%s\n", md5_asciistr(GameInfo->MD5));
|
||||
|
||||
FCEUI_SetVidSystem(0);
|
||||
|
||||
@@ -735,27 +936,10 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
|
||||
}
|
||||
|
||||
void FDSClose(void) {
|
||||
FILE *fp;
|
||||
int x;
|
||||
char *fn = FCEU_MakeFName(FCEUMKF_FDS, 0, 0);
|
||||
|
||||
if (!DiskWritten) return;
|
||||
|
||||
if (!(fp = fopen(fn, "wb"))) {
|
||||
free(fn);
|
||||
return;
|
||||
}
|
||||
FCEU_printf("FDS Save \"%s\"\n", fn);
|
||||
free(fn);
|
||||
|
||||
for (x = 0; x < TotalSides; x++) {
|
||||
if (fwrite(diskdata[x], 1, 65500, fp) != 65500) {
|
||||
FCEU_PrintError("Error saving FDS image!\n");
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < TotalSides; x++)
|
||||
if (diskdatao[x]) {
|
||||
free(diskdatao[x]);
|
||||
@@ -763,14 +947,4 @@ void FDSClose(void) {
|
||||
}
|
||||
|
||||
FreeFDSMemory();
|
||||
if (FDSBIOS)
|
||||
free(FDSBIOS);
|
||||
FDSBIOS = NULL;
|
||||
if (FDSRAM)
|
||||
free(FDSRAM);
|
||||
FDSRAM = NULL;
|
||||
if (CHRRAM)
|
||||
free(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef _FCEU_FDS_H
|
||||
#define _FCEU_FDS_H
|
||||
|
||||
uint8 *FDSROM_ptr(void);
|
||||
uint32 FDSROM_size(void);
|
||||
|
||||
void FDSSoundReset(void);
|
||||
|
||||
void FCEU_FDSInsert(int oride);
|
||||
|
||||
@@ -58,8 +58,6 @@ static MEMWRAP *MakeMemWrap(void *tz, int type)
|
||||
fread(tmp->data, 1, tmp->size, (FILE*)tz);
|
||||
|
||||
doret:
|
||||
if (type == 0)
|
||||
fclose((FILE*)tz);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -97,6 +95,7 @@ FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn,
|
||||
|
||||
fseek((FILE*)t, 0, SEEK_SET);
|
||||
fceufp->fp = MakeMemWrap(t, 0);
|
||||
fclose((FILE*)t);
|
||||
}
|
||||
return fceufp;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) {
|
||||
#endif
|
||||
max = (inlen - 1) << 16;
|
||||
|
||||
if (FSettings.soundq == 2)
|
||||
if (FSettings.soundq == 2) {
|
||||
for (x = mrindex; x < max; x += mrratio) {
|
||||
int32 acc = 0, acc2 = 0;
|
||||
uint32 c;
|
||||
@@ -116,7 +116,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) {
|
||||
out++;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
for (x = mrindex; x < max; x += mrratio) {
|
||||
int32 acc = 0, acc2 = 0;
|
||||
uint32 c;
|
||||
@@ -132,6 +132,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) {
|
||||
out++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
mrindex = x - max;
|
||||
|
||||
|
||||
310
src/sound.c
310
src/sound.c
@@ -70,6 +70,7 @@ static int32 RectDutyCount[2];
|
||||
static uint8 sweepon[2];
|
||||
static int32 curfreq[2];
|
||||
static uint8 SweepCount[2];
|
||||
static uint8 sweepReload[2];
|
||||
|
||||
static uint16 nreg = 0;
|
||||
|
||||
@@ -84,6 +85,9 @@ int32 nesincsize = 0;
|
||||
uint32 soundtsinc = 0;
|
||||
uint32 soundtsi = 0;
|
||||
static int32 sqacc[2];
|
||||
static uint32 lq_tcout;
|
||||
static int32 lq_triacc;
|
||||
static int32 lq_noiseacc;
|
||||
/* LQ variables segment ends. */
|
||||
|
||||
static int32 lengthcount[4];
|
||||
@@ -125,9 +129,9 @@ static const uint32 PALDMCTable[0x10] =
|
||||
* $4013 - Size register: Size in bytes = (V+1)*64
|
||||
*/
|
||||
|
||||
/*static*/ int32 DMCacc = 1;
|
||||
static int32 DMCacc = 1;
|
||||
static int32 DMCPeriod = 0;
|
||||
/*static*/ uint8 DMCBitCount = 0;
|
||||
static uint8 DMCBitCount = 0;
|
||||
|
||||
static uint8 DMCAddressLatch = 0, DMCSizeLatch = 0; /* writes to 4012 and 4013 */
|
||||
static uint8 DMCFormat = 0; /* Write to $4010 */
|
||||
@@ -175,21 +179,12 @@ static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr) {
|
||||
}
|
||||
|
||||
static void SQReload(int x, uint8 V) {
|
||||
if (EnabledChannels & (1 << x)) {
|
||||
if (x)
|
||||
DoSQ2();
|
||||
else
|
||||
DoSQ1();
|
||||
if (EnabledChannels & (1 << x))
|
||||
lengthcount[x] = lengthtable[(V >> 3) & 0x1f];
|
||||
}
|
||||
|
||||
sweepon[x] = PSG[(x << 2) | 1] & 0x80;
|
||||
curfreq[x] = PSG[(x << 2) | 0x2] | ((V & 7) << 8);
|
||||
SweepCount[x] = ((PSG[(x << 2) | 0x1] >> 4) & 7) + 1;
|
||||
|
||||
curfreq[x] = (curfreq[x] & 0xff) | ((V & 7) << 8);
|
||||
RectDutyCount[x] = 7;
|
||||
EnvUnits[x].reloaddec = 1;
|
||||
/* reloadfreq[x]=1; */
|
||||
}
|
||||
|
||||
static DECLFW(Write_PSG) {
|
||||
@@ -200,11 +195,11 @@ static DECLFW(Write_PSG) {
|
||||
DoSQ1();
|
||||
EnvUnits[0].Mode = (V & 0x30) >> 4;
|
||||
EnvUnits[0].Speed = (V & 0xF);
|
||||
if (swapDuty)
|
||||
V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1);
|
||||
break;
|
||||
case 0x1:
|
||||
sweepon[0] = V & 0x80;
|
||||
DoSQ1();
|
||||
sweepReload[0] = 1;
|
||||
sweepon[0] = (V & 0x80);
|
||||
break;
|
||||
case 0x2:
|
||||
DoSQ1();
|
||||
@@ -212,17 +207,18 @@ static DECLFW(Write_PSG) {
|
||||
curfreq[0] |= V;
|
||||
break;
|
||||
case 0x3:
|
||||
DoSQ1();
|
||||
SQReload(0, V);
|
||||
break;
|
||||
case 0x4:
|
||||
DoSQ2();
|
||||
EnvUnits[1].Mode = (V & 0x30) >> 4;
|
||||
EnvUnits[1].Speed = (V & 0xF);
|
||||
if (swapDuty)
|
||||
V = (V & 0x3F) | ((V & 0x80) >> 1) | ((V & 0x40) << 1);
|
||||
break;
|
||||
case 0x5:
|
||||
sweepon[1] = V & 0x80;
|
||||
DoSQ2();
|
||||
sweepReload[1] = 1;
|
||||
sweepon[1] = (V & 0x80);
|
||||
break;
|
||||
case 0x6:
|
||||
DoSQ2();
|
||||
@@ -230,6 +226,7 @@ static DECLFW(Write_PSG) {
|
||||
curfreq[1] |= V;
|
||||
break;
|
||||
case 0x7:
|
||||
DoSQ2();
|
||||
SQReload(1, V);
|
||||
break;
|
||||
case 0xa:
|
||||
@@ -288,17 +285,17 @@ static DECLFW(Write_DMCRegs) {
|
||||
break;
|
||||
case 0x01: DoPCM();
|
||||
RawDALatch = V & 0x7F;
|
||||
if (RawDALatch)
|
||||
DMC_7bit = 1;
|
||||
if (RawDALatch)
|
||||
DMC_7bit = 1;
|
||||
break;
|
||||
case 0x02:
|
||||
DMCAddressLatch = V;
|
||||
if (V)
|
||||
DMCAddressLatch = V;
|
||||
if (V)
|
||||
DMC_7bit = 0;
|
||||
break;
|
||||
break;
|
||||
case 0x03:
|
||||
DMCSizeLatch = V;
|
||||
if (V)
|
||||
DMCSizeLatch = V;
|
||||
if (V)
|
||||
DMC_7bit = 0;
|
||||
break;
|
||||
}
|
||||
@@ -313,6 +310,7 @@ static DECLFW(StatusWrite) {
|
||||
DoTriangle();
|
||||
DoNoise();
|
||||
DoPCM();
|
||||
|
||||
for (x = 0; x < 4; x++)
|
||||
if (!(V & (1 << x))) lengthcount[x] = 0; /* Force length counters to 0. */
|
||||
|
||||
@@ -336,9 +334,9 @@ static DECLFR(StatusRead) {
|
||||
for (x = 0; x < 4; x++) ret |= lengthcount[x] ? (1 << x) : 0;
|
||||
if (DMCSize) ret |= 0x10;
|
||||
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
if (!fceuindbg)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
SIRQStat &= ~0x40;
|
||||
X6502_IRQEnd(FCEU_IQFCOUNT);
|
||||
@@ -371,34 +369,25 @@ static void FASTAPASS(1) FrameSoundStuff(int V) {
|
||||
/* Frequency Sweep Code Here */
|
||||
/* xxxx 0000 */
|
||||
/* xxxx = hz. 120/(x+1)*/
|
||||
if (sweepon[P]) {
|
||||
int32 mod = 0;
|
||||
|
||||
if (SweepCount[P] > 0) SweepCount[P]--;
|
||||
if (SweepCount[P] <= 0) {
|
||||
SweepCount[P] = ((PSG[(P << 2) + 0x1] >> 4) & 7) + 1; /* +1; */
|
||||
/* http://wiki.nesdev.com/w/index.php/APU_Sweep */
|
||||
if (SweepCount[P] > 0) SweepCount[P]--;
|
||||
if (SweepCount[P] <= 0) {
|
||||
uint32 sweepShift = (PSG[(P << 2) + 0x1] & 7);
|
||||
if (sweepon[P] && sweepShift && curfreq[P] >= 8) {
|
||||
int32 mod = (curfreq[P] >> sweepShift);
|
||||
if (PSG[(P << 2) + 0x1] & 0x8) {
|
||||
mod -= (P ^ 1) + ((curfreq[P]) >> (PSG[(P << 2) + 0x1] & 7));
|
||||
if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) {
|
||||
curfreq[P] += mod;
|
||||
}
|
||||
} else {
|
||||
mod = curfreq[P] >> (PSG[(P << 2) + 0x1] & 7);
|
||||
if ((mod + curfreq[P]) & 0x800) {
|
||||
sweepon[P] = 0;
|
||||
curfreq[P] = 0;
|
||||
} else {
|
||||
if (curfreq[P] && (PSG[(P << 2) + 0x1] & 7) /* && sweepon[P]&0x80*/) {
|
||||
curfreq[P] += mod;
|
||||
}
|
||||
}
|
||||
curfreq[P] -= (mod + (P ^ 1));
|
||||
} else if ((mod + curfreq[P]) < 0x800) {
|
||||
curfreq[P] += mod;
|
||||
}
|
||||
}
|
||||
} else {/* Sweeping is disabled: */
|
||||
#if 0
|
||||
curfreq[P]&=0xFF00;
|
||||
curfreq[P]|=PSG[(P<<2)|0x2]; /* |((PSG[(P<<2)|3]&7)<<8); */
|
||||
#endif
|
||||
|
||||
SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1);
|
||||
}
|
||||
|
||||
if (sweepReload[P]) {
|
||||
SweepCount[P] = (((PSG[(P << 2) + 0x1] >> 4) & 7) + 1);
|
||||
sweepReload[P] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -437,19 +426,21 @@ void FrameSoundUpdate(void) {
|
||||
* Length counter: Bit 4-7 of $4003, $4007, $400b, $400f
|
||||
*/
|
||||
|
||||
if (!fcnt && !(IRQFrameMode & 0x3)) {
|
||||
SIRQStat |= 0x40;
|
||||
X6502_IRQBegin(FCEU_IQFCOUNT);
|
||||
}
|
||||
|
||||
if (fcnt == 3) {
|
||||
if (IRQFrameMode & 0x2)
|
||||
fhcnt += fhinc;
|
||||
}
|
||||
|
||||
FrameSoundStuff(fcnt);
|
||||
fcnt = (fcnt + 1) & 3;
|
||||
}
|
||||
|
||||
/* has to be moved here to fix Dragon Warrior 4
|
||||
* after irq inhibit fix for $4017 */
|
||||
if (!fcnt && !(IRQFrameMode & 0x3)) {
|
||||
SIRQStat |= 0x40;
|
||||
X6502_IRQBegin(FCEU_IQFCOUNT);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void tester(void) {
|
||||
if (DMCBitCount == 0) {
|
||||
@@ -476,9 +467,10 @@ static INLINE void DMCDMA(void) {
|
||||
if (DMCFormat & 0x40)
|
||||
PrepDPCM();
|
||||
else {
|
||||
SIRQStat |= 0x80;
|
||||
if (DMCFormat & 0x80)
|
||||
if (DMCFormat & 0x80) {
|
||||
SIRQStat |= 0x80;
|
||||
X6502_IRQBegin(FCEU_IQDPCM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -520,7 +512,8 @@ void RDoPCM(void) {
|
||||
uint32 V;
|
||||
|
||||
for (V = ChannelBC[4]; V < SOUNDTS; V++)
|
||||
WaveHi[V] += RawDALatch << 16;
|
||||
/* TODO: get rid of floating calculations to binary. set log volume scaling. */
|
||||
WaveHi[V] += (((RawDALatch << 16) / 256) * FSettings.PCMVolume ) & (~0xFFFF);
|
||||
|
||||
ChannelBC[4] = SOUNDTS;
|
||||
}
|
||||
@@ -535,45 +528,61 @@ static INLINE void RDoSQ(int x) {
|
||||
int32 cf;
|
||||
int32 rc;
|
||||
|
||||
if (curfreq[x] < 8 || curfreq[x] > 0x7ff)
|
||||
goto endit;
|
||||
if (!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1]))
|
||||
goto endit;
|
||||
if (!lengthcount[x])
|
||||
goto endit;
|
||||
|
||||
if (EnvUnits[x].Mode & 0x1)
|
||||
amp = EnvUnits[x].Speed;
|
||||
else
|
||||
amp = EnvUnits[x].decvolume;
|
||||
/* printf("%d\n",amp); */
|
||||
amp <<= 24;
|
||||
|
||||
rthresh = RectDuties[(PSG[(x << 2)] & 0xC0) >> 6];
|
||||
|
||||
D = &WaveHi[ChannelBC[x]];
|
||||
V = SOUNDTS - ChannelBC[x];
|
||||
|
||||
currdc = RectDutyCount[x];
|
||||
cf = (curfreq[x] + 1) * 2;
|
||||
rc = wlcount[x];
|
||||
|
||||
while (V > 0) {
|
||||
if (currdc < rthresh)
|
||||
*D += amp;
|
||||
rc--;
|
||||
if (!rc) {
|
||||
rc = cf;
|
||||
currdc = (currdc + 1) & 7;
|
||||
/* added 2018/12/08 */
|
||||
/* when pulse channel is silenced, resets length counters but not
|
||||
* duty cycle, instead of resetting both */
|
||||
if ((curfreq[x] < 8 || curfreq[x] > 0x7ff) ||
|
||||
!CheckFreq(curfreq[x], PSG[(x << 2) | 0x1]) ||
|
||||
!lengthcount[x]) {
|
||||
rc -= V;
|
||||
if (rc <= 0) {
|
||||
rc = cf - (-rc % cf);
|
||||
}
|
||||
V--;
|
||||
D++;
|
||||
} else {
|
||||
int dutyCycle;
|
||||
|
||||
if (EnvUnits[x].Mode & 0x1)
|
||||
amp = EnvUnits[x].Speed;
|
||||
else
|
||||
amp = EnvUnits[x].decvolume;
|
||||
/* printf("%d\n",amp); */
|
||||
|
||||
/* Modify Square wave volume based on channel volume modifiers
|
||||
* Note: the formulat x = x * y /100 does not yield exact results,
|
||||
* but is "close enough" and avoids the need for using double values
|
||||
* or implicit cohersion which are slower (we need speed here) */
|
||||
/* TODO: Optimize this. */
|
||||
if (FSettings.SquareVolume[x] != 256)
|
||||
amp = (amp * FSettings.SquareVolume[x]) / 256;
|
||||
|
||||
amp <<= 24;
|
||||
dutyCycle = (PSG[(x << 2)] & 0xC0) >> 6;
|
||||
if (swapDuty)
|
||||
dutyCycle = ((dutyCycle & 2) >> 1) | ((dutyCycle & 1) << 1);
|
||||
rthresh = RectDuties[dutyCycle];
|
||||
currdc = RectDutyCount[x];
|
||||
D = &WaveHi[ChannelBC[x]];
|
||||
|
||||
while (V > 0) {
|
||||
if (currdc < rthresh)
|
||||
*D += amp;
|
||||
rc--;
|
||||
if (!rc) {
|
||||
rc = cf;
|
||||
currdc = (currdc + 1) & 7;
|
||||
}
|
||||
V--;
|
||||
D++;
|
||||
}
|
||||
|
||||
RectDutyCount[x] = currdc;
|
||||
}
|
||||
|
||||
RectDutyCount[x] = currdc;
|
||||
wlcount[x] = rc;
|
||||
|
||||
endit:
|
||||
ChannelBC[x] = SOUNDTS;
|
||||
}
|
||||
|
||||
@@ -604,6 +613,7 @@ static void RDoSQLQ(void) {
|
||||
|
||||
for (x = 0; x < 2; x++) {
|
||||
int y;
|
||||
int dutyCycle;
|
||||
|
||||
inie[x] = nesincsize;
|
||||
if (curfreq[x] < 8 || curfreq[x] > 0x7ff)
|
||||
@@ -618,9 +628,21 @@ static void RDoSQLQ(void) {
|
||||
else
|
||||
amp[x] = EnvUnits[x].decvolume;
|
||||
|
||||
/* Modify Square wave volume based on channel volume modifiers
|
||||
* Note: the formulat x = x * y /100 does not yield exact results,
|
||||
* but is "close enough" and avoids the need for using double vales
|
||||
* or implicit cohersion which are slower (we need speed here)
|
||||
* fixed - setting up maximum volume for square2 caused complete mute square2 channel.
|
||||
* TODO: Optimize this. */
|
||||
if (FSettings.SquareVolume[x] != 256)
|
||||
amp[x] = (amp[x] * FSettings.SquareVolume[x]) / 256;
|
||||
|
||||
if (!inie[x]) amp[x] = 0; /* Correct? Buzzing in MM2, others otherwise... */
|
||||
|
||||
rthresh[x] = RectDuties[(PSG[x * 4] & 0xC0) >> 6];
|
||||
dutyCycle = (PSG[(x << 2)] & 0xC0) >> 6;
|
||||
if (swapDuty)
|
||||
dutyCycle = ((dutyCycle & 2) >> 1) | ((dutyCycle & 1) << 1);
|
||||
rthresh[x] = RectDuties[dutyCycle];
|
||||
|
||||
for (y = 0; y < 8; y++) {
|
||||
if (y < rthresh[x])
|
||||
@@ -637,7 +659,7 @@ static void RDoSQLQ(void) {
|
||||
if (!inie[0] && !inie[1]) {
|
||||
for (V = start; V < end; V++)
|
||||
Wave[V >> 4] += totalout;
|
||||
} else
|
||||
} else {
|
||||
for (V = start; V < end; V++) {
|
||||
/* int tmpamp=0;
|
||||
if(RectDutyCount[0]<rthresh[0])
|
||||
@@ -669,11 +691,12 @@ static void RDoSQLQ(void) {
|
||||
totalout = wlookup1[ ttable[0][RectDutyCount[0]] + ttable[1][RectDutyCount[1]] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RDoTriangle(void) {
|
||||
int32 V;
|
||||
int32 tcout;
|
||||
int32 tcout, cout;
|
||||
|
||||
tcout = (tristep & 0xF);
|
||||
if (!(tristep & 0x10)) tcout ^= 0xF;
|
||||
@@ -683,16 +706,17 @@ static void RDoTriangle(void) {
|
||||
int32 *start = &WaveHi[ChannelBC[2]];
|
||||
int32 count = SOUNDTS - ChannelBC[2];
|
||||
while (count--) {
|
||||
*start += tcout;
|
||||
*start += (tcout / 256 * FSettings.TriangleVolume) & (~0xFFFF); /* TODO OPTIMIZE ME */
|
||||
start++;
|
||||
}
|
||||
#if 0
|
||||
|
||||
/* cout = (tcout / 256 * FSettings.TriangleVolume) & (~0xFFFF);
|
||||
for(V = ChannelBC[2]; V < SOUNDTS; V++)
|
||||
WaveHi[V] += tcout;
|
||||
#endif
|
||||
} else
|
||||
WaveHi[V] += cout; */
|
||||
|
||||
} else {
|
||||
for (V = ChannelBC[2]; V < SOUNDTS; V++) {
|
||||
WaveHi[V] += tcout;
|
||||
WaveHi[V] += (tcout / 256 * FSettings.TriangleVolume) & (~0xFFFF); /* TODO OPTIMIZE ME! */
|
||||
wlcount[2]--;
|
||||
if (!wlcount[2]) {
|
||||
wlcount[2] = (PSG[0xa] | ((PSG[0xb] & 7) << 8)) + 1;
|
||||
@@ -702,14 +726,11 @@ static void RDoTriangle(void) {
|
||||
tcout = (tcout * 3) << 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChannelBC[2] = SOUNDTS;
|
||||
}
|
||||
|
||||
uint32 lq_tcout = 0;
|
||||
int32 lq_triacc = 0;
|
||||
int32 lq_noiseacc = 0;
|
||||
|
||||
static void RDoTriangleNoisePCMLQ(void) {
|
||||
int32 V;
|
||||
int32 start, end;
|
||||
@@ -738,6 +759,15 @@ static void RDoTriangleNoisePCMLQ(void) {
|
||||
amptab[0] = EnvUnits[2].Speed;
|
||||
else
|
||||
amptab[0] = EnvUnits[2].decvolume;
|
||||
|
||||
/* Modify Triangle wave volume based on channel volume modifiers
|
||||
* Note: the formulat x = x * y /100 does not yield exact results,
|
||||
* but is "close enough" and avoids the need for using double vales
|
||||
* or implicit cohersion which are slower (we need speed here)
|
||||
* TODO: Optimize this. */
|
||||
if (FSettings.TriangleVolume != 256)
|
||||
amptab[0] = (amptab[0] * FSettings.TriangleVolume) / 256;
|
||||
|
||||
amptab[1] = 0;
|
||||
amptab[0] <<= 1;
|
||||
|
||||
@@ -751,7 +781,6 @@ static void RDoTriangleNoisePCMLQ(void) {
|
||||
else
|
||||
nshift = 13;
|
||||
|
||||
|
||||
totalout = wlookup2[lq_tcout + noiseout + RawDALatch];
|
||||
|
||||
if (inie[0] && inie[1]) {
|
||||
@@ -831,7 +860,6 @@ static void RDoTriangleNoisePCMLQ(void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void RDoNoise(void) {
|
||||
uint32 V;
|
||||
int32 outo;
|
||||
@@ -842,6 +870,14 @@ static void RDoNoise(void) {
|
||||
else
|
||||
amptab[0] = EnvUnits[2].decvolume;
|
||||
|
||||
/* Modify Noise wave volume based on channel volume modifiers
|
||||
* Note: the formulat x = x * y /100 does not yield exact results,
|
||||
* but is "close enough" and avoids the need for using double vales
|
||||
* or implicit cohersion which are slower (we need speed here)
|
||||
* TODO: Optimize this. */
|
||||
if (FSettings.NoiseVolume != 256)
|
||||
amptab[0] = (amptab[0] * FSettings.NoiseVolume) / 256;
|
||||
|
||||
amptab[0] <<= 16;
|
||||
amptab[1] = 0;
|
||||
|
||||
@@ -853,7 +889,7 @@ static void RDoNoise(void) {
|
||||
outo = amptab[0] = 0;
|
||||
}
|
||||
|
||||
if (PSG[0xE] & 0x80)/* "short" noise */
|
||||
if (PSG[0xE] & 0x80) {/* "short" noise */
|
||||
for (V = ChannelBC[3]; V < SOUNDTS; V++) {
|
||||
WaveHi[V] += outo;
|
||||
wlcount[3]--;
|
||||
@@ -869,7 +905,7 @@ static void RDoNoise(void) {
|
||||
outo = amptab[(nreg >> 0xe) & 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
for (V = ChannelBC[3]; V < SOUNDTS; V++) {
|
||||
WaveHi[V] += outo;
|
||||
wlcount[3]--;
|
||||
@@ -885,6 +921,7 @@ static void RDoNoise(void) {
|
||||
outo = amptab[(nreg >> 0xe) & 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
ChannelBC[3] = SOUNDTS;
|
||||
}
|
||||
|
||||
@@ -893,10 +930,12 @@ DECLFW(Write_IRQFM) {
|
||||
fcnt = 0;
|
||||
if (V & 2)
|
||||
FrameSoundUpdate();
|
||||
fcnt = 1;
|
||||
/* fcnt = 1; */
|
||||
fhcnt = fhinc;
|
||||
X6502_IRQEnd(FCEU_IQFCOUNT);
|
||||
SIRQStat &= ~0x40;
|
||||
if (V & 1) {
|
||||
X6502_IRQEnd(FCEU_IQFCOUNT);
|
||||
SIRQStat &= ~0x40;
|
||||
}
|
||||
IRQFrameMode = V;
|
||||
}
|
||||
|
||||
@@ -938,6 +977,7 @@ int FlushEmulateSound(void) {
|
||||
*tmpo = (b & 65535) + wlookup2[(b >> 16) & 255] + wlookup1[b >> 24];
|
||||
tmpo++;
|
||||
}
|
||||
|
||||
end = NeoFilterSound(WaveHi, WaveFinal, SOUNDTS, &left);
|
||||
|
||||
memmove(WaveHi, WaveHi + SOUNDTS - left, left * sizeof(uint32));
|
||||
@@ -953,10 +993,9 @@ int FlushEmulateSound(void) {
|
||||
|
||||
SexyFilter(Wave, WaveFinal, end >> 4);
|
||||
|
||||
#if 0
|
||||
if (FSettings.lowpass)
|
||||
SexyFilter2(WaveFinal, end >> 4);
|
||||
#endif
|
||||
/* if (FSettings.lowpass)
|
||||
SexyFilter2(WaveFinal, end >> 4); */
|
||||
|
||||
if (end & 0xF)
|
||||
Wave[0] = Wave[(end >> 4)];
|
||||
Wave[end >> 4] = 0;
|
||||
@@ -1023,6 +1062,8 @@ void FCEUSND_Reset(void) {
|
||||
DMCAddress = 0;
|
||||
DMCSize = 0;
|
||||
DMCShift = 0;
|
||||
DMCacc=1;
|
||||
DMCBitCount=0;
|
||||
}
|
||||
|
||||
void FCEUSND_Power(void) {
|
||||
@@ -1162,8 +1203,8 @@ SFORMAT FCEUSND_STATEINFO[] = {
|
||||
{ &DMCAddressLatch, 1, "5ADL" },
|
||||
{ &DMCFormat, 1, "5FMT" },
|
||||
{ &RawDALatch, 1, "RWDA" },
|
||||
|
||||
//these are important for smooth sound after loading state
|
||||
|
||||
/* these are important for smooth sound after loading state */
|
||||
{ &sqacc[0], sizeof(sqacc[0]) | FCEUSTATE_RLSB, "SAC1" },
|
||||
{ &sqacc[1], sizeof(sqacc[1]) | FCEUSTATE_RLSB, "SAC2" },
|
||||
{ &RectDutyCount[0], sizeof(RectDutyCount[0]) | FCEUSTATE_RLSB, "RCD1"},
|
||||
@@ -1171,8 +1212,8 @@ SFORMAT FCEUSND_STATEINFO[] = {
|
||||
{ &tristep, sizeof(tristep) | FCEUSTATE_RLSB, "TRIS"},
|
||||
{ &lq_triacc, sizeof(lq_triacc) | FCEUSTATE_RLSB, "TACC" },
|
||||
{ &lq_noiseacc, sizeof(lq_noiseacc) | FCEUSTATE_RLSB, "NACC" },
|
||||
|
||||
//less important but still necessary
|
||||
|
||||
/* less important but still necessary */
|
||||
{ &ChannelBC[0], sizeof(ChannelBC[0]) | FCEUSTATE_RLSB, "CBC1" },
|
||||
{ &ChannelBC[1], sizeof(ChannelBC[1]) | FCEUSTATE_RLSB, "CBC2" },
|
||||
{ &ChannelBC[2], sizeof(ChannelBC[2]) | FCEUSTATE_RLSB, "CBC3" },
|
||||
@@ -1187,10 +1228,17 @@ SFORMAT FCEUSND_STATEINFO[] = {
|
||||
{ &sexyfilter_acc1, sizeof(sexyfilter_acc1) | FCEUSTATE_RLSB, "FAC1" },
|
||||
{ &sexyfilter_acc2, sizeof(sexyfilter_acc2) | FCEUSTATE_RLSB, "FAC2" },
|
||||
{ &lq_tcout, sizeof(lq_tcout) | FCEUSTATE_RLSB, "TCOU"},
|
||||
|
||||
//wave buffer is used for filtering, only need first 17 values from it
|
||||
|
||||
/* 2018-12-14 - Wii and possibly other big-endian platforms are having
|
||||
* issues loading states with this. Increasing it only helps a few games.
|
||||
* Disabling this state variable for Wii/WiiU/GC for now. */
|
||||
/* TODO: fix this for better runahead feature for big-endian */
|
||||
#ifndef GEKKO
|
||||
/* wave buffer is used for filtering, only need first 17 values from it */
|
||||
{ &Wave, 32 * sizeof(int32), "WAVE"},
|
||||
{ 0 }
|
||||
#endif
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void FCEUSND_SaveState(void) {
|
||||
@@ -1202,10 +1250,20 @@ void FCEUSND_LoadState(int version) {
|
||||
RawDALatch &= 0x7F;
|
||||
DMCAddress &= 0x7FFF;
|
||||
|
||||
//minimal validation
|
||||
/* minimal validation */
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (ChannelBC[i] < 0 || ChannelBC[i] > 15)
|
||||
int BC_max = 15;
|
||||
|
||||
if (FSettings.soundq == 2)
|
||||
{
|
||||
BC_max = 1025;
|
||||
}
|
||||
else if (FSettings.soundq == 1)
|
||||
{
|
||||
BC_max = 485;
|
||||
}
|
||||
if (ChannelBC[i] < 0 || ChannelBC[i] > BC_max)
|
||||
{
|
||||
ChannelBC[i] = 0;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ static int SubWrite(memstream_t *mem, SFORMAT *sf)
|
||||
if(sf->s & RLSB)
|
||||
FlipByteOrder((uint8 *)sf->v, sf->s & (~RLSB));
|
||||
#endif
|
||||
memstream_write(mem, (uint8 *)sf->v, sf->s & (~RLSB));
|
||||
memstream_write(mem, (char *)sf->v, sf->s & (~RLSB));
|
||||
|
||||
/* Now restore the original byte order. */
|
||||
#ifdef MSB_FIRST
|
||||
@@ -176,7 +176,7 @@ static int ReadStateChunk(memstream_t *mem, SFORMAT *sf, int size)
|
||||
|
||||
if((tmp = CheckS(sf, tsize, toa)))
|
||||
{
|
||||
memstream_read(mem, (uint8 *)tmp->v, tmp->s & (~RLSB));
|
||||
memstream_read(mem, (char *)tmp->v, tmp->s & (~RLSB));
|
||||
|
||||
#ifdef MSB_FIRST
|
||||
if(tmp->s & RLSB)
|
||||
@@ -213,8 +213,8 @@ static int ReadStateChunks(memstream_t *st, int32 totalsize)
|
||||
case 2:
|
||||
if (!ReadStateChunk(st, SFCPUC, size))
|
||||
ret = 0;
|
||||
else
|
||||
X.mooPI = X.P; /* Quick and dirty hack. */
|
||||
/* else
|
||||
X.mooPI = X.P; */ /* Quick and dirty hack. */
|
||||
break;
|
||||
case 3:
|
||||
if (!ReadStateChunk(st, FCEUPPU_STATEINFO, size))
|
||||
@@ -320,6 +320,7 @@ void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
|
||||
SPreSave = PreSave;
|
||||
SPostSave = PostSave;
|
||||
SFEXINDEX = 0;
|
||||
SFMDATA[0].s = 0;
|
||||
}
|
||||
|
||||
void AddExState(void *v, uint32 s, int type, char *desc)
|
||||
|
||||
Reference in New Issue
Block a user