mirror of
https://github.com/libretro/FBNeo.git
synced 2026-11-07 02:55:59 -10:00
Merge branch 'master' of https://github.com/finalburnneo/FBNeo into finalburnneo-master
This commit is contained in:
commit
d4d81688d0
80 files changed
+7584
-1421
No files matched your search
@@ -24,6 +24,7 @@ nvram
|
||||
*.nvr
|
||||
config/*
|
||||
fbneo.dat
|
||||
fbneo_headless.dylib
|
||||
|
||||
# libretro
|
||||
/.github
|
||||
|
||||
@@ -120,6 +120,9 @@ sdl: FORCE
|
||||
sdl2: FORCE
|
||||
@$(MAKE) -s -f makefile.sdl2
|
||||
|
||||
headless: FORCE
|
||||
@$(MAKE) -s -f makefile.headless
|
||||
|
||||
vc: FORCE
|
||||
@$(MAKE) -s -f makefile.vc
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ drvsrc = d_akkaarrh.o d_arcadecl.o d_atarig1.o d_atarisy1.o d_atarisy2.o d_badl
|
||||
\
|
||||
d_cps1.o d_mitchell.o \
|
||||
\
|
||||
d_cps2.o \
|
||||
d_cps2.o d_cps2_custom.o \
|
||||
\
|
||||
d_cps3.o \
|
||||
\
|
||||
|
||||
@@ -27,7 +27,7 @@ depobj += about.o bzip.o choose_monitor.o cona.o d3d11shaderparams.o debugger.o
|
||||
\
|
||||
2xpm.o 2xsai.o crt.o ddt3x.o epx.o hq2xs.o hq2xs_16.o hq3xs.o hq_shared32.o xbr.o xbr32.o \
|
||||
\
|
||||
aud_dsound3.o aud_xaudio2.o cd_img.o ddraw_core.o dinput_core.o directx9_core.o dsound_core.o \
|
||||
aud_dsound3.o aud_xaudio2.o aud_wasapi.o cd_img.o ddraw_core.o dinput_core.o directx9_core.o dsound_core.o \
|
||||
inp_dinput.o inp_xinput.o prf_performance_counter.o vid_d3d.o vid_d3d11.o vid_d3d11_shader.o vid_ddraw.o vid_ddrawfx.o vid_effect.o vid_directx9.o vid_directx_support.o
|
||||
|
||||
ifdef INCLUDE_7Z_SUPPORT
|
||||
|
||||
@@ -0,0 +1,639 @@
|
||||
# Makefile for FBNeo, headless core (derived from makefile.sdl2)
|
||||
#
|
||||
# The first pass makes sure all intermediary targets are present. The second pass updates
|
||||
# any targets, if necessary. (Intermediary) targets which have their own unique rules
|
||||
# are generated as required.
|
||||
|
||||
unexport
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
DARWIN=1
|
||||
endif
|
||||
|
||||
ifdef DARWIN
|
||||
PLATFLAGS += -arch arm64 -mmacosx-version-min=11.0 -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
WINDOWS=1
|
||||
endif
|
||||
|
||||
#
|
||||
# Flags. Uncomment any of these declarations to enable their function.
|
||||
#
|
||||
|
||||
# Check for changes in header files
|
||||
ifndef SKIPDEPEND
|
||||
DEPEND = 1
|
||||
endif
|
||||
|
||||
# SANITIZE = 1
|
||||
|
||||
#
|
||||
# Declare variables
|
||||
#
|
||||
|
||||
# Specify the name of the executable file, without ".exe"
|
||||
NAME = fbneo
|
||||
|
||||
PERL = 1
|
||||
LSB_FIRST = 1
|
||||
INCLUDE_7Z_SUPPORT = 1
|
||||
|
||||
BUILD_X86_ASM=
|
||||
INCLUDE_AVI_RECORDING=
|
||||
BUILD_A68K=
|
||||
UNICODE=
|
||||
|
||||
|
||||
#
|
||||
# Specify paths/files
|
||||
#
|
||||
|
||||
objdir = obj/
|
||||
srcdir = src/
|
||||
|
||||
include makefile.burn_rules
|
||||
|
||||
# Platform stuff
|
||||
alldir += burner burner/headless burner/sdl dep/libs/libspng dep/libs/lib7z dep/libs/zlib intf intf/video \
|
||||
intf/video/scalers intf/video/headless intf/audio intf/audio/headless intf/input intf/input/headless intf/cd \
|
||||
dep/generated
|
||||
|
||||
depobj += cdlist.o \
|
||||
\
|
||||
conc.o cong.o dat.o gamc.o gami.o image.o ioapi.o misc.o sshot.o state.o statec.o unzip.o zipfn.o \
|
||||
\
|
||||
adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o gzwrite.o infback.o inffast.o inflate.o inftrees.o \
|
||||
trees.o uncompr.o zutil.o \
|
||||
\
|
||||
spng.o \
|
||||
\
|
||||
aud_dsp.o aud_interface.o cd_interface.o cd_chd.o inp_interface.o interface.o lowpass2.o vid_interface.o \
|
||||
vid_support.o \
|
||||
\
|
||||
inp_headless.o aud_headless.o vid_headless.o support_paths.o ips_manager.o scrn.o localise_gamelist.o romdata.o \
|
||||
cd_img.o stringset.o bzip.o media.o \
|
||||
inpdipsw.o inputbuf.o replay.o stated.o headless_main.o headless_drv.o headless_misc.o headless_input.o headless_memory.o
|
||||
|
||||
ifdef FORCE_PULSE_AUDIO
|
||||
alldir += intf/audio/linux
|
||||
|
||||
depobj += aud_pulse_simple.o
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_7Z_SUPPORT
|
||||
depobj += un7z.o \
|
||||
\
|
||||
7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o 7zFile.o 7zStream.o Alloc.o Bcj2.o Bra.o Bra86.o BraIA64.o CpuArch.o \
|
||||
Delta.o LzFindOpt.o LzmaDec.o Lzma2Dec.o MtDec.o Ppmd7.o Ppmd7Dec.o Ppmd7aDec.o Sha256.o Sha1Opt.o Sha256Opt.o Threads.o Xxh64.o Xz.o XzCrc64.o XzCrc64Opt.o XzDec.o ZstdDec.o
|
||||
endif
|
||||
|
||||
autobj += $(depobj)
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
autobj += eagle_fm.o 2xsaimmx.o hq2x32.o hq3x32.o hq4x32.o superscale.o
|
||||
endif
|
||||
|
||||
# End, platform stuff
|
||||
|
||||
incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)dep/generated
|
||||
|
||||
lib = -lstdc++ -lm -lpthread
|
||||
|
||||
ifdef FORCE_PULSE_AUDIO
|
||||
lib += -lpulse-simple
|
||||
endif
|
||||
|
||||
|
||||
ifdef INCLUDE_SWITCHRES
|
||||
incdir += `pkg-config --cflags switchres`
|
||||
lib += `pkg-config --libs switchres`
|
||||
endif
|
||||
|
||||
autdep = $(depobj:.o=.d)
|
||||
drvdep = $(drvsrc:.o=.d)
|
||||
|
||||
ifdef BUILD_A68K
|
||||
a68k.o = $(objdir)cpu/a68k/a68k.o
|
||||
endif
|
||||
|
||||
driverlist.h = $(srcdir)dep/generated/driverlist.h
|
||||
ctv.h = $(srcdir)dep/generated/ctv.h
|
||||
toa_gp9001_func.h = $(srcdir)dep/generated/toa_gp9001_func.h
|
||||
neo_sprite_func.h = $(srcdir)dep/generated/neo_sprite_func.h
|
||||
cave_tile_func.h = $(srcdir)dep/generated/cave_tile_func.h
|
||||
cave_sprite_func.h = $(srcdir)dep/generated/cave_sprite_func.h
|
||||
psikyo_tile_func.h = $(srcdir)dep/generated/psikyo_tile_func.h
|
||||
pgm_sprite.h = $(srcdir)dep/generated/pgm_sprite.h
|
||||
build_details.h = $(srcdir)dep/generated/build_details.h
|
||||
|
||||
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kops.o \
|
||||
$(foreach file,$(autobj:.o=.c), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .c,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \
|
||||
$(foreach file,$(autobj:.o=.cpp), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .cpp,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \
|
||||
$(foreach file,$(autobj:.o=.asm), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .asm,.o,$(wildcard $(srcdir)$(dir)/$(file))))))) \
|
||||
$(foreach file,$(autobj:.o=.rc), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .rc,.o,$(wildcard $(srcdir)$(dir)/$(file)))))))
|
||||
|
||||
ifdef BUILD_A68K
|
||||
allobj += $(a68k.o)
|
||||
endif
|
||||
|
||||
alldep = $(foreach file,$(autobj:.o=.c), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .c,.d,$(wildcard $(srcdir)$(dir)/$(file))))))) \
|
||||
$(foreach file,$(autobj:.o=.cpp), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .cpp,.d,$(wildcard $(srcdir)$(dir)/$(file))))))) \
|
||||
$(foreach file,$(autobj:.o=.rc), \
|
||||
$(foreach dir,$(alldir),$(subst $(srcdir),$(objdir), \
|
||||
$(firstword $(subst .rc,.d,$(wildcard $(srcdir)$(dir)/$(file)))))))
|
||||
|
||||
autdrv := $(drvsrc:.cpp=.o)
|
||||
|
||||
#
|
||||
#
|
||||
# Specify compiler/linker/assembler
|
||||
#
|
||||
#
|
||||
|
||||
ifdef DARWIN
|
||||
CC = gcc
|
||||
else
|
||||
CC = gcc
|
||||
endif
|
||||
|
||||
CXX = $(CC)
|
||||
LD = $(CC)
|
||||
AS = nasm
|
||||
|
||||
# While cross-compiling, tools need to be compiled for host so that they can be executed by host.
|
||||
# if HOST_CC is not set, then we aren't cross-compiling, so we'll use target compiler as host compiler
|
||||
ifeq ($(HOST_CC),)
|
||||
HOST_CC := $(CC)
|
||||
HOST_CXX := $(CXX)
|
||||
HOST_CFLAGS := $(CFLAGS)
|
||||
HOST_CXXFLAGS := $(CXXFLAGS)
|
||||
HOST_LDFLAGS := $(LDFLAGS)
|
||||
endif
|
||||
|
||||
#LDFLAGS = -static
|
||||
|
||||
CFLAGS = -O2 -fomit-frame-pointer -Wno-write-strings \
|
||||
-Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \
|
||||
-Wno-conversion -Wno-attributes \
|
||||
-Wno-unused-parameter -Wno-unused-value -std=c99 \
|
||||
$(PLATFLAGS) $(DEF) $(incdir)
|
||||
|
||||
CXXFLAGS = -O2 -fomit-frame-pointer -Wno-write-strings \
|
||||
-Wall -W -Wno-long-long -Wno-sign-compare \
|
||||
-Wunknown-pragmas -Wundef -Wconversion -Wno-missing-braces \
|
||||
-Wuninitialized -Wpointer-arith -Winline -Wno-multichar \
|
||||
-Wno-conversion -Wno-attributes \
|
||||
-Wno-unused-parameter -Wno-unused-value -Wno-narrowing \
|
||||
$(PLATFLAGS) $(DEF) $(incdir)
|
||||
|
||||
ASFLAGS = -O1 -f coff -w-orphan-labels
|
||||
|
||||
# D3DUtils & D3DMath need these
|
||||
# DEF = -Dsinf=\(float\)sin -Dcosf=\(float\)cos -Dasinf=\(float\)asin -Dacosf=\(float\)acos -Dsqrtf=\(float\)sqrt
|
||||
|
||||
# FIXME
|
||||
DEF := -DBUILD_HEADLESS -DINCLUDE_FLACMP3_SUPPORT -DUSE_SPEEDHACKS -DFILENAME=$(NAME) -DUSE_FILE32API -DHAVE_UNISTD_H
|
||||
|
||||
ifdef FORCE_PULSE_AUDIO
|
||||
DEF := $(DEF) -DFORCE_PULSE_AUDIO
|
||||
endif
|
||||
|
||||
ifdef WINDOWS
|
||||
DEF := $(DEF) -DSDL_WINDOWS
|
||||
endif
|
||||
|
||||
ifdef UNICODE
|
||||
DEF := $(DEF) -D_UNICODE
|
||||
endif
|
||||
|
||||
ifdef SPECIALBUILD
|
||||
DEF := $(DEF) -DSPECIALBUILD=$(SPECIALBUILD)
|
||||
endif
|
||||
|
||||
ifdef FASTCALL
|
||||
DEF := $(DEF) -DFASTCALL
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
DEF := $(DEF) -DFBNEO_DEBUG
|
||||
endif
|
||||
|
||||
ifdef ROM_VERIFY
|
||||
DEF := $(DEF) -DROM_VERIFY
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_7Z_SUPPORT
|
||||
DEF := $(DEF) -DINCLUDE_7Z_SUPPORT
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_AVI_RECORDING
|
||||
DEF := $(DEF) -DINCLUDE_AVI_RECORDING
|
||||
endif
|
||||
|
||||
ifdef LSB_FIRST
|
||||
DEF := $(DEF) -DLSB_FIRST
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_LIB_PNGH
|
||||
DEF := $(DEF) -DINCLUDE_LIB_PNGH
|
||||
endif
|
||||
|
||||
ifdef BUILD_A68K
|
||||
DEF := $(DEF) -DBUILD_A68K
|
||||
endif
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
DEF := $(DEF) -DBUILD_X86_ASM
|
||||
endif
|
||||
|
||||
ifdef BUILD_X64_EXE
|
||||
DEF := $(DEF) -DBUILD_X64_EXE
|
||||
endif
|
||||
|
||||
ifdef INCLUDE_SWITCHRES
|
||||
DEF := $(DEF) -DINCLUDE_SWITCHRES
|
||||
endif
|
||||
|
||||
ifdef SANITIZE
|
||||
ifndef SYMBOL
|
||||
SYMBOL =1
|
||||
endif
|
||||
CFLAGS += -fsanitize=address -fsanitize=undefined -fsanitize=bounds-strict
|
||||
CXXFLAGS += -fsanitize=address -fsanitize=undefined -fsanitize=bounds-strict
|
||||
endif
|
||||
|
||||
ifdef SYMBOL
|
||||
CFLAGS += -ggdb3 -fno-omit-frame-pointer
|
||||
CXXFLAGS += -ggdb3 -fno-omit-frame-pointer
|
||||
ASFLAGS += -g
|
||||
DEF := $(DEF) -D_DEBUG
|
||||
else
|
||||
LDFLAGS += -s
|
||||
endif
|
||||
|
||||
ifdef PROFILE
|
||||
CFLAGS += -pg
|
||||
CXXFLAGS += -pg
|
||||
endif
|
||||
|
||||
|
||||
ifdef BUILD_NATIVE
|
||||
CFLAGS += -march=native -mtune=native
|
||||
CXXFLAGS += -march=native -mtune=native
|
||||
endif
|
||||
|
||||
# For zlib
|
||||
DEF := $(DEF) -DNO_VIZ -D_LARGEFILE64_SOURCE=0 -D_FILE_OFFSET_BITS=64
|
||||
|
||||
# For libchdr
|
||||
DEF := $(DEF) -DCHDR_SYSTEM_ZLIB
|
||||
|
||||
# For lib7z
|
||||
ifdef INCLUDE_7Z_SUPPORT
|
||||
DEF := $(DEF) -D_7ZIP_PPMD_SUPPPORT -D_7ZIP_ST
|
||||
endif
|
||||
|
||||
#
|
||||
#
|
||||
# Specify paths
|
||||
#
|
||||
#
|
||||
|
||||
vpath %.asm $(foreach dir,$(alldir),$(srcdir)$(dir)/ )
|
||||
vpath %.cpp $(foreach dir,$(alldir),$(srcdir)$(dir)/ )
|
||||
vpath %.c $(foreach dir,$(alldir),$(srcdir)$(dir)/ )
|
||||
vpath %.h $(foreach dir,$(alldir),$(srcdir)$(dir)/ )
|
||||
vpath %.rc $(foreach dir,$(alldir),$(srcdir)$(dir)/ )
|
||||
|
||||
vpath %.o $(foreach dir,$(alldir),$(objdir)$(dir)/ )
|
||||
vpath %.d $(foreach dir,$(alldir),$(objdir)$(dir)/ )
|
||||
|
||||
#
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
#
|
||||
|
||||
.PHONY: all init cleandep touch clean
|
||||
|
||||
ifeq ($(MAKELEVEL),1)
|
||||
ifdef DEPEND
|
||||
|
||||
all: init $(drvdep) $(autdep) $(autobj) $(autdrv)
|
||||
@$(MAKE) -f makefile.headless -s
|
||||
|
||||
else
|
||||
|
||||
all: init $(autobj) $(autdrv)
|
||||
@$(MAKE) -f makefile.headless -s
|
||||
|
||||
endif
|
||||
else
|
||||
|
||||
all: fbneo_headless.dylib
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
#
|
||||
# Rule for linking the executable
|
||||
#
|
||||
#
|
||||
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
|
||||
$(objdir)drivers.o: $(autdrv)
|
||||
@echo Linking drivers...
|
||||
@$(LD) -r -nostdlib -o $@ $^
|
||||
|
||||
ifdef WINDOWS
|
||||
|
||||
$(NAME): $(allobj) $(objdir)drivers.o
|
||||
@echo
|
||||
@echo Linking executable... $(NAME)
|
||||
@$(LD) -Wl,--image-base -Wl,0x10000000 -mconsole $(CFLAGS) $(LDFLAGS) -o $@ $^ $(lib)
|
||||
|
||||
else
|
||||
|
||||
fbneo_headless.dylib: $(allobj) $(objdir)drivers.o
|
||||
@echo
|
||||
@echo Linking dylib... $@
|
||||
@$(LD) -dynamiclib -install_name @rpath/fbneo_headless.dylib $(CFLAGS) $(LDFLAGS) -o $@ $^ $(lib)
|
||||
endif
|
||||
|
||||
|
||||
ifdef DEBUG
|
||||
|
||||
# Don't compress when making a debug build
|
||||
|
||||
else
|
||||
ifdef COMPRESS
|
||||
@upx --best $@
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MAKELEVEL),1)
|
||||
ifdef FORCE_UPDATE
|
||||
$(build_details.h): FORCE
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Generate the gamelist
|
||||
#
|
||||
|
||||
burn.o burn.d: $(driverlist.h)
|
||||
|
||||
$(driverlist.h): $(drvsrc) $(srcdir)dep/scripts/gamelist.pl
|
||||
ifdef PERL
|
||||
@$(srcdir)dep/scripts/gamelist.pl -o $@ -l gamelist.txt \
|
||||
$(filter %.cpp,$(foreach file,$(drvsrc:.o=.cpp),$(foreach dir,$(alldir), \
|
||||
$(firstword $(wildcard $(srcdir)$(dir)/$(file))))))
|
||||
else
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
@echo
|
||||
@echo Warning: Perl is not available on this system.
|
||||
@echo $@ cannot be updated or created!
|
||||
@echo
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Verify if driverlist.h needs to be updated
|
||||
#
|
||||
|
||||
#ifeq ($(MAKELEVEL),1)
|
||||
#ifdef FORCE_UPDATE
|
||||
#$(driverlist.h): FORCE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#
|
||||
# Compile 68000 cores
|
||||
#
|
||||
|
||||
# A68K
|
||||
|
||||
ifdef BUILD_A68K
|
||||
$(a68k.o): fba_make68k.c
|
||||
@echo Compiling A68K MC68000 core...
|
||||
@$(CC) -mconsole $(CFLAGS) $(LDFLAGS) -DWIN32 -Wno-unused -Wno-conversion -Wno-missing-prototypes \
|
||||
-s $< -o $(subst $(srcdir),$(objdir),$(<D))/$(<F:.c=.exe)
|
||||
@$(subst $(srcdir),$(objdir),$(<D))/$(<F:.c=.exe) $(@:.o=.asm) \
|
||||
$(@D)/a68k_tab.asm 00 $(ppro)
|
||||
@echo Assembling A68K MC68000 core...
|
||||
@$(AS) $(ASFLAGS) $(@:.o=.asm) -o $@
|
||||
endif
|
||||
|
||||
# Musashi
|
||||
|
||||
$(objdir)cpu/m68k/m68kcpu.o: $(srcdir)cpu/m68k/m68kcpu.c $(objdir)dep/generated/m68kops.h $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo Compiling Musashi MC680x0 core \(m68kcpu.c\)...
|
||||
@$(CC) $(CFLAGS) -c $(srcdir)cpu/m68k/m68kcpu.c -o $(objdir)cpu/m68k/m68kcpu.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kops.o: $(objdir)cpu/m68k/m68kmake $(objdir)dep/generated/m68kops.h $(objdir)dep/generated/m68kops.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo Compiling Musashi MC680x0 core \(m68kops.c\)...
|
||||
@$(CC) $(CFLAGS) -c $(objdir)dep/generated/m68kops.c -o $(objdir)cpu/m68k/m68kops.o
|
||||
|
||||
$(objdir)dep/generated/m68kops.h $(objdir)dep/generated/m68kops.c: $(objdir)cpu/m68k/m68kmake $(srcdir)cpu/m68k/m68k_in.c
|
||||
$(objdir)cpu/m68k/m68kmake $(objdir)dep/generated/ $(srcdir)cpu/m68k/m68k_in.c
|
||||
|
||||
$(objdir)cpu/m68k/m68kmake: $(srcdir)cpu/m68k/m68kmake.c
|
||||
@echo Compiling Musashi MC680x0 core \(m68kmake.c\)...
|
||||
@$(HOST_CC) $(HOST_CFLAGS) $(srcdir)cpu/m68k/m68kmake.c -o $(objdir)cpu/m68k/m68kmake -Dmain=main
|
||||
|
||||
|
||||
#
|
||||
# Extra rules for generated header file ctv.h, needed by ctv.cpp
|
||||
#
|
||||
|
||||
ctv.d ctv.o: $(ctv.h)
|
||||
|
||||
$(ctv.h): ctv_make.cpp
|
||||
@echo Generating $(srcdir)dep/generated/$(@F)...
|
||||
@$(HOST_CC) $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $< \
|
||||
-o $(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe) -Dmain=main
|
||||
@$(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe) >$@
|
||||
|
||||
#
|
||||
# Extra rules for generated header file toa_gp9001_func.h, needed by toa_gp9001.cpp
|
||||
#
|
||||
|
||||
toa_bcu2.d toa_bcu2.o toa_gp9001.d toa_gp9001.o: $(toa_gp9001_func.h)
|
||||
|
||||
$(toa_gp9001_func.h): $(srcdir)dep/scripts/toa_gp9001_func.pl
|
||||
@$(srcdir)dep/scripts/toa_gp9001_func.pl -o $(toa_gp9001_func.h)
|
||||
|
||||
#
|
||||
# Extra rules for generated header file neo_sprite_func.h, needed by neo_sprite.cpp
|
||||
#
|
||||
|
||||
neo_sprite.d neo_sprite.o: $(neo_sprite_func.h)
|
||||
|
||||
$(neo_sprite_func.h): $(srcdir)dep/scripts/neo_sprite_func.pl
|
||||
@$(srcdir)dep/scripts/neo_sprite_func.pl -o $(neo_sprite_func.h)
|
||||
|
||||
#
|
||||
# Extra rules for generated header file cave_tile_func.h, needed by cave_tile.cpp
|
||||
#
|
||||
|
||||
cave_tile.d cave_tile.o: $(cave_tile_func.h)
|
||||
|
||||
$(cave_tile_func.h): $(srcdir)dep/scripts/cave_tile_func.pl
|
||||
@$(srcdir)dep/scripts/cave_tile_func.pl -o $(cave_tile_func.h)
|
||||
|
||||
#
|
||||
# Extra rules for generated header file cave_sprite_func.h, needed by cave_sprite.cpp
|
||||
#
|
||||
|
||||
cave_sprite.d cave_sprite.o: $(cave_sprite_func.h)
|
||||
|
||||
$(cave_sprite_func.h): $(srcdir)dep/scripts/cave_sprite_func.pl
|
||||
@$(srcdir)dep/scripts/cave_sprite_func.pl -o $(cave_sprite_func.h)
|
||||
|
||||
#
|
||||
# Extra rules for generated header file psikyo_tile_func.h / psikyo_sprite_func.h, needed by psikyo_tile.cpp / psikyo_sprite.cpp
|
||||
#
|
||||
|
||||
psikyo_tile.d psikyo_tile.o psikyosprite.d psikyo_sprite.o: $(psikyo_tile_func.h)
|
||||
|
||||
$(psikyo_tile_func.h): $(srcdir)dep/scripts/psikyo_tile_func.pl
|
||||
$(srcdir)dep/scripts/psikyo_tile_func.pl -o $(psikyo_tile_func.h)
|
||||
|
||||
#
|
||||
# Extra rules for generated header file pgm_sprite.h, needed by pgm_draw.cpp
|
||||
#
|
||||
|
||||
pgm_draw.d pgm_draw.o: $(pgm_sprite.h)
|
||||
|
||||
$(pgm_sprite.h): pgm_sprite_create.cpp
|
||||
@echo Generating $(srcdir)dep/generated/$(@F)...
|
||||
@$(HOST_CC) $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $< \
|
||||
-o $(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe) -Dmain=main
|
||||
@$(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe) >$@
|
||||
|
||||
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
ifdef DEPEND
|
||||
|
||||
include $(alldep)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# Generic rules for C/C++ files
|
||||
#
|
||||
# Note: require init to complete before assembling anything (see "| init" below)
|
||||
# to avoid parallization issues on fresh builds.
|
||||
#
|
||||
|
||||
ifeq ($(MAKELEVEL),1)
|
||||
|
||||
%.o: %.cpp
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CXXFLAGS) -c $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
%.o: %.c
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CFLAGS) -c $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
%.o: %.asm | init
|
||||
@echo Assembling $<...
|
||||
@$(AS) $(ASFLAGS) $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
else
|
||||
|
||||
%.o: %.c
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.asm | init
|
||||
@echo Assembling $<...
|
||||
@$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
%.o:
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# Generate dependencies for C/C++ files
|
||||
#
|
||||
|
||||
ifdef DEPEND
|
||||
|
||||
%.d: %.c
|
||||
@echo Generating depend file for $<...
|
||||
@$(CC) -MM -MT "$(subst $(srcdir),$(objdir),$(<D))/$(*F).o $(subst $(srcdir),$(objdir),$(<D))/$(@F)" -x c++ $(CXXFLAGS) $< >$(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
%.d: %.cpp
|
||||
@echo Generating depend file for $<...
|
||||
@$(CC) -MM -MT "$(subst $(srcdir),$(objdir),$(<D))/$(*F).o $(subst $(srcdir),$(objdir),$(<D))/$(@F)" -x c++ $(CXXFLAGS) $< >$(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
%.d: %.rc
|
||||
@echo Generating depend file for $<...
|
||||
@$(CC) -MM -MT "$(subst $(srcdir),$(objdir),$(<D))/$(*F).o $(subst $(srcdir),$(objdir),$(<D))/$(@F)" -x c++ $(CXXFLAGS) $< >$(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# Phony targets
|
||||
#
|
||||
|
||||
init:
|
||||
|
||||
ifdef DEBUG
|
||||
@echo Making debug build...
|
||||
else
|
||||
@echo Making normal build...
|
||||
endif
|
||||
@echo
|
||||
@mkdir -p $(foreach dir, $(alldir),$(objdir)$(dir))
|
||||
@mkdir -p $(srcdir)dep/generated
|
||||
|
||||
cleandep:
|
||||
@echo Removing depend files from $(objdir)...
|
||||
-@for dir in $(alldir); do rm -f $(objdir)$$dir/*.d; done
|
||||
|
||||
touch:
|
||||
@echo Marking all targets for $(NAME) as uptodate...
|
||||
-@touch $(NAME).exe
|
||||
-@touch -c -r $(NAME).exe $(srcdir)/dep/generated/*
|
||||
-@for dir in $(alldir); do touch -c -r $(NAME).exe $(objdir)$$dir/*; done
|
||||
|
||||
clean:
|
||||
@echo Removing build files...
|
||||
-@rm -fr $(objdir) $(ctv.h) $(dep)generated gamelist.txt $(NAME)
|
||||
|
||||
ifdef PERL
|
||||
@echo Removing all files generated with perl scripts...
|
||||
-@rm -f -r $(app_gnuc.rc) $(driverlist)
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# Rule to force recompilation of any target that depends on it
|
||||
#
|
||||
|
||||
FORCE:
|
||||
@@ -317,6 +317,7 @@ $$DRV_CAPCOM {
|
||||
../../src/burn/drv/capcom/ctv.cpp \
|
||||
../../src/burn/drv/capcom/d_cps1.cpp \
|
||||
../../src/burn/drv/capcom/d_cps2.cpp \
|
||||
../../src/burn/drv/capcom/d_cps2_custom.cpp \
|
||||
../../src/burn/drv/capcom/fcrash_snd.cpp \
|
||||
../../src/burn/drv/capcom/kabuki.cpp \
|
||||
../../src/burn/drv/capcom/ps_m.cpp \
|
||||
|
||||
@@ -363,6 +363,9 @@
|
||||
<File
|
||||
RelativePath="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\burn\drv\capcom\fcrash_snd.cpp">
|
||||
</File>
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps1.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\ps.cpp" />
|
||||
|
||||
@@ -206,6 +206,9 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
<Filter>Source Files\burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
<Filter>Source Files\burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp">
|
||||
<Filter>Source Files\burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -529,6 +529,7 @@ rm %(Filename).exe</Command>
|
||||
</CustomBuild>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps1.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\ps.cpp" />
|
||||
|
||||
@@ -1227,6 +1227,9 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
<Filter>Burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
<Filter>Burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp">
|
||||
<Filter>Burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -477,6 +477,7 @@ del %(Filename).exe</Command>
|
||||
</CustomBuild>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps1.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\ps.cpp" />
|
||||
|
||||
@@ -247,6 +247,9 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -477,6 +477,7 @@ del %(Filename).exe</Command>
|
||||
</CustomBuild>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps1.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\ps.cpp" />
|
||||
|
||||
@@ -247,6 +247,9 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -477,6 +477,7 @@ del %(Filename).exe</Command>
|
||||
</CustomBuild>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps1.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\ps.cpp" />
|
||||
|
||||
@@ -247,6 +247,9 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\ctv.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps1.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_mitchell.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\fcrash_snd.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\kabuki.cpp" />
|
||||
|
||||
@@ -391,6 +391,9 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_cps2_custom.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\capcom\d_mitchell.cpp">
|
||||
<Filter>burn\drv\capcom</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -614,6 +614,7 @@
|
||||
FE1B262B23561A770065200C /* d_psikyo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1B208823561A6C0065200C /* d_psikyo.cpp */; };
|
||||
FE1B262C23561A770065200C /* cpsrd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1B208A23561A6C0065200C /* cpsrd.cpp */; };
|
||||
FE1B262D23561A770065200C /* d_cps2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1B208B23561A6C0065200C /* d_cps2.cpp */; };
|
||||
A427B0010000000000000001 /* d_cps2_custom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A427B0010000000000000002 /* d_cps2_custom.cpp */; };
|
||||
FE1B262E23561A770065200C /* cpst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1B208C23561A6C0065200C /* cpst.cpp */; };
|
||||
FE1B262F23561A770065200C /* qs_z.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1B208D23561A6C0065200C /* qs_z.cpp */; };
|
||||
FE1B263023561A770065200C /* d_cps1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1B208E23561A6C0065200C /* d_cps1.cpp */; };
|
||||
@@ -2156,6 +2157,7 @@
|
||||
FE1B208823561A6C0065200C /* d_psikyo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_psikyo.cpp; sourceTree = "<group>"; };
|
||||
FE1B208A23561A6C0065200C /* cpsrd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpsrd.cpp; sourceTree = "<group>"; };
|
||||
FE1B208B23561A6C0065200C /* d_cps2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_cps2.cpp; sourceTree = "<group>"; };
|
||||
A427B0010000000000000002 /* d_cps2_custom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_cps2_custom.cpp; sourceTree = "<group>"; };
|
||||
FE1B208C23561A6C0065200C /* cpst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpst.cpp; sourceTree = "<group>"; };
|
||||
FE1B208D23561A6C0065200C /* qs_z.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = qs_z.cpp; sourceTree = "<group>"; };
|
||||
FE1B208E23561A6C0065200C /* d_cps1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_cps1.cpp; sourceTree = "<group>"; };
|
||||
@@ -4587,6 +4589,7 @@
|
||||
children = (
|
||||
FE1B208A23561A6C0065200C /* cpsrd.cpp */,
|
||||
FE1B208B23561A6C0065200C /* d_cps2.cpp */,
|
||||
A427B0010000000000000002 /* d_cps2_custom.cpp */,
|
||||
FE1B208C23561A6C0065200C /* cpst.cpp */,
|
||||
FE1B208D23561A6C0065200C /* qs_z.cpp */,
|
||||
FE1B208E23561A6C0065200C /* d_cps1.cpp */,
|
||||
@@ -5845,6 +5848,7 @@
|
||||
FE1B252523561A760065200C /* d_pkscram.cpp in Sources */,
|
||||
FE1B276423561A790065200C /* tilemap_generic.cpp in Sources */,
|
||||
FE1B262D23561A770065200C /* d_cps2.cpp in Sources */,
|
||||
A427B0010000000000000001 /* d_cps2_custom.cpp in Sources */,
|
||||
FE1B26E923561A780065200C /* d_alpha68k1.cpp in Sources */,
|
||||
FE1B244E23561A750065200C /* 7zBuf.c in Sources */,
|
||||
FE1B23DC23561A750065200C /* m6809_intf.cpp in Sources */,
|
||||
|
||||
+70
-53
@@ -90,8 +90,51 @@ bool bSaveCRoms = 0;
|
||||
|
||||
UINT32 *pBurnDrvPalette;
|
||||
|
||||
static char** pszShortName = NULL, ** pszFullNameA = NULL;
|
||||
static wchar_t** pszFullNameW = NULL;
|
||||
// Writable driver names, created only for drivers whose name is changed
|
||||
// (RomData, custom/sub-driver names, localisation). Copying all of them at
|
||||
// startup cost about 1.4 KiB per driver: about 39 MiB for 28,000 drivers.
|
||||
struct BurnNameCopy {
|
||||
UINT32 nDrv;
|
||||
char* szOrigShortName;
|
||||
char* szOrigFullNameA;
|
||||
wchar_t* szOrigFullNameW;
|
||||
char szShortName[100];
|
||||
char szFullNameA[MAX_PATH];
|
||||
#if defined (_UNICODE)
|
||||
wchar_t szFullNameW[MAX_PATH];
|
||||
#endif
|
||||
BurnNameCopy* pNext;
|
||||
};
|
||||
static BurnNameCopy* pBurnNameCopies = NULL;
|
||||
|
||||
static BurnNameCopy* BurnNameCopyGet(UINT32 i)
|
||||
{
|
||||
if (i >= nBurnDrvCount) return NULL;
|
||||
|
||||
for (BurnNameCopy* p = pBurnNameCopies; p; p = p->pNext) {
|
||||
if (p->nDrv == i) return p;
|
||||
}
|
||||
|
||||
BurnNameCopy* p = (BurnNameCopy*)calloc(1, sizeof(BurnNameCopy));
|
||||
if (NULL == p) return NULL;
|
||||
|
||||
p->nDrv = i;
|
||||
p->szOrigShortName = pDriver[i]->szShortName;
|
||||
p->szOrigFullNameA = pDriver[i]->szFullNameA;
|
||||
p->szOrigFullNameW = pDriver[i]->szFullNameW;
|
||||
if (pDriver[i]->szShortName) strncpy(p->szShortName, pDriver[i]->szShortName, sizeof(p->szShortName) - 1);
|
||||
if (pDriver[i]->szFullNameA) strncpy(p->szFullNameA, pDriver[i]->szFullNameA, MAX_PATH - 1);
|
||||
pDriver[i]->szShortName = p->szShortName;
|
||||
pDriver[i]->szFullNameA = p->szFullNameA;
|
||||
#if defined (_UNICODE)
|
||||
if (pDriver[i]->szFullNameW) wcsncpy(p->szFullNameW, pDriver[i]->szFullNameW, MAX_PATH - 1);
|
||||
pDriver[i]->szFullNameW = p->szFullNameW;
|
||||
#endif
|
||||
p->pNext = pBurnNameCopies;
|
||||
pBurnNameCopies = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
bool BurnCheckMMXSupport()
|
||||
{
|
||||
@@ -107,53 +150,20 @@ bool BurnCheckMMXSupport()
|
||||
}
|
||||
|
||||
static void BurnGameListInit()
|
||||
{ // Avoid broken references, RomData requires separate string storage
|
||||
if (0 == nBurnDrvCount) return;
|
||||
|
||||
pszShortName = (char** )malloc(nBurnDrvCount * sizeof(char*));
|
||||
pszFullNameA = (char** )malloc(nBurnDrvCount * sizeof(char*));
|
||||
pszFullNameW = (wchar_t**)malloc(nBurnDrvCount * sizeof(wchar_t*));
|
||||
|
||||
if ((NULL != pszShortName) && (NULL != pszFullNameA) && (NULL != pszFullNameW)) {
|
||||
for (UINT32 i = 0; i < nBurnDrvCount; i++) {
|
||||
pszShortName[i] = (char* )malloc(100 * sizeof(char));
|
||||
pszFullNameA[i] = (char* )malloc(MAX_PATH * sizeof(char));
|
||||
pszFullNameW[i] = (wchar_t*)malloc(MAX_PATH * sizeof(wchar_t));
|
||||
|
||||
memset(pszShortName[i], '\0', 100 * sizeof(char));
|
||||
memset(pszFullNameA[i], '\0', MAX_PATH * sizeof(char));
|
||||
memset(pszFullNameW[i], '\0', MAX_PATH * sizeof(wchar_t));
|
||||
|
||||
if (NULL != pszShortName[i]) {
|
||||
strcpy(pszShortName[i], pDriver[i]->szShortName);
|
||||
pDriver[i]->szShortName = pszShortName[i];
|
||||
}
|
||||
if (NULL != pszFullNameA[i]) {
|
||||
strcpy(pszFullNameA[i], pDriver[i]->szFullNameA);
|
||||
pDriver[i]->szFullNameA = pszFullNameA[i];
|
||||
}
|
||||
#if defined (_UNICODE)
|
||||
if (NULL != pDriver[i]->szFullNameW) {
|
||||
wmemcpy(pszFullNameW[i], pDriver[i]->szFullNameW, MAX_PATH); // Include '\0'
|
||||
}
|
||||
pDriver[i]->szFullNameW = pszFullNameW[i];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
{ // Names are copied on first change, see BurnNameCopyGet().
|
||||
}
|
||||
|
||||
static void BurnGameListExit()
|
||||
{
|
||||
// Release of storage space
|
||||
for (UINT32 i = 0; i < nBurnDrvCount; i++) {
|
||||
if ((NULL != pszShortName) && (NULL != pszShortName[i])) free(pszShortName[i]);
|
||||
if ((NULL != pszFullNameA) && (NULL != pszFullNameA[i])) free(pszFullNameA[i]);
|
||||
if ((NULL != pszFullNameW) && (NULL != pszFullNameW[i])) free(pszFullNameW[i]);
|
||||
// Point the drivers back at their built-in names, then release the copies.
|
||||
while (pBurnNameCopies) {
|
||||
BurnNameCopy* p = pBurnNameCopies;
|
||||
pDriver[p->nDrv]->szShortName = p->szOrigShortName;
|
||||
pDriver[p->nDrv]->szFullNameA = p->szOrigFullNameA;
|
||||
pDriver[p->nDrv]->szFullNameW = p->szOrigFullNameW;
|
||||
pBurnNameCopies = p->pNext;
|
||||
free(p);
|
||||
}
|
||||
if (NULL != pszShortName) free(pszShortName);
|
||||
if (NULL != pszFullNameA) free(pszFullNameA);
|
||||
if (NULL != pszFullNameW) free(pszFullNameW);
|
||||
}
|
||||
|
||||
extern "C" INT32 BurnLibInit()
|
||||
@@ -519,9 +529,10 @@ static INT32 BurnDrvSetFullNameA(char* szName, UINT32 i = nBurnDrvActive)
|
||||
{
|
||||
// Preventing the emergence of ~0U
|
||||
// If not NULL, then FullNameA is customized
|
||||
if ((i >= 0) && (NULL != szName)) {
|
||||
memset(pszFullNameA[i], '\0', MAX_PATH * sizeof(char));
|
||||
strcpy(pszFullNameA[i], szName);
|
||||
BurnNameCopy* p = (NULL != szName) ? BurnNameCopyGet(i) : NULL;
|
||||
if (NULL != p) {
|
||||
memset(p->szFullNameA, '\0', MAX_PATH * sizeof(char));
|
||||
strncpy(p->szFullNameA, szName, MAX_PATH - 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -534,8 +545,10 @@ INT32 BurnDrvSetFullNameW(TCHAR* szName, INT32 i = nBurnDrvActive)
|
||||
if ((-1 == i) || (NULL == szName)) return -1;
|
||||
|
||||
#if defined (_UNICODE)
|
||||
memset(pszFullNameW[i], '\0', MAX_PATH * sizeof(wchar_t));
|
||||
wcscpy(pszFullNameW[i], szName);
|
||||
BurnNameCopy* p = BurnNameCopyGet(i);
|
||||
if (NULL == p) return -1;
|
||||
memset(p->szFullNameW, '\0', MAX_PATH * sizeof(wchar_t));
|
||||
wcsncpy(p->szFullNameW, szName, MAX_PATH - 1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@@ -548,8 +561,10 @@ void BurnLocalisationSetName(char* szName, TCHAR* szLongName)
|
||||
nBurnDrvActive = i;
|
||||
if (!strcmp(szName, pDriver[i]->szShortName)) {
|
||||
// pDriver[i]->szFullNameW = szLongName;
|
||||
memset(pszFullNameW[i], '\0', MAX_PATH * sizeof(wchar_t));
|
||||
_tcscpy(pszFullNameW[i], szLongName);
|
||||
BurnNameCopy* p = BurnNameCopyGet(i);
|
||||
if (NULL == p) continue;
|
||||
memset(p->szFullNameW, '\0', MAX_PATH * sizeof(wchar_t));
|
||||
wcsncpy(p->szFullNameW, szLongName, MAX_PATH - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,7 +633,9 @@ extern "C" INT32 BurnDrvSetZipName(char* szName, INT32 i)
|
||||
{
|
||||
if ((NULL == szName) || (-1 == i)) return -1;
|
||||
|
||||
strcpy(pszShortName[i], szName);
|
||||
BurnNameCopy* p = BurnNameCopyGet((UINT32)i);
|
||||
if (NULL == p) return -1;
|
||||
strncpy(p->szShortName, szName, sizeof(p->szShortName) - 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1735,7 +1752,7 @@ struct MovieExtInfo
|
||||
UINT32 hour, minute, second;
|
||||
};
|
||||
|
||||
#if !defined(BUILD_SDL) && !defined(BUILD_SDL2) && !defined(BUILD_MACOS) && !defined(__LIBRETRO__)
|
||||
#if !defined(BUILD_SDL) && !defined(BUILD_SDL2) && !defined(BUILD_MACOS) && !defined(BUILD_HEADLESS) && !defined(__LIBRETRO__)
|
||||
extern struct MovieExtInfo MovieInfo; // from replay.cpp
|
||||
#else
|
||||
struct MovieExtInfo MovieInfo = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
@@ -845,3 +845,60 @@ bool WriteValueAtHardwareAddress(HWAddressType address, unsigned int value, unsi
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef BUILD_HEADLESS
|
||||
// Added for OpenEmu-Silicon headless: fast helpers for cheat search / achievements.
|
||||
// Author: Leonardo Kasperavičius
|
||||
|
||||
// Size (in bytes) of the main CPU (cpu 0) address space, 0 if no driver is loaded.
|
||||
unsigned int GetMainMemorySize()
|
||||
{
|
||||
if (!bDrvOkay)
|
||||
return 0;
|
||||
// cpu 0 still holds dummy_config (nMemorySize = ~0UL) when no CPU registered with
|
||||
// the cheat engine; report 0 so the host never tries to allocate a 4GB buffer.
|
||||
unsigned int size = (unsigned int)cpus[0].cpuconfig->nMemorySize;
|
||||
return (size == ~0U) ? 0 : size;
|
||||
}
|
||||
|
||||
// Bulk-read a contiguous range from the main CPU (cpu 0) address space, opening
|
||||
// the cpu once. Returns the number of bytes actually read (clamped to memory size).
|
||||
unsigned int ReadMemoryRange(HWAddressType address, unsigned char *buffer, unsigned int length)
|
||||
{
|
||||
if (!bDrvOkay || buffer == NULL)
|
||||
return 0;
|
||||
|
||||
cheat_ptr = &cpus[0];
|
||||
cpu_core_config *cfg = cheat_ptr->cpuconfig;
|
||||
unsigned int memSize = (unsigned int)cfg->nMemorySize;
|
||||
|
||||
INT32 nActiveCPU = cfg->active();
|
||||
if (nActiveCPU >= 0) cfg->close();
|
||||
cfg->open(cheat_ptr->nCPU);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
if (address + i >= memSize) break;
|
||||
buffer[i] = cfg->read(address + i);
|
||||
}
|
||||
|
||||
cfg->close();
|
||||
if (nActiveCPU >= 0) cfg->open(nActiveCPU);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Multi-byte order hint for the host's cheat search and cheat writes. This is
|
||||
// deliberately NOT derived from nAddressFlags: RetroAchievements sets and
|
||||
// libretro .cht cheats (the formats the host matches) are authored
|
||||
// little-endian for the 68K arcade boards -- every FBNeo libretro .cht is
|
||||
// big_endian="false" -- and the CPUs that set MB_CHEAT_ENDI_SWAP (TMS34010,
|
||||
// V60) are natively little-endian; the flag only exists because FBNeo's own
|
||||
// cheat engine stores values big-endian. Reporting 1 for those made the host
|
||||
// write "0000A260:00A1" in Mortal Kombat as bytes 00 A1, so the game read
|
||||
// P1 health as 0xA100. Every board is therefore reported little-endian.
|
||||
int GetMainMemoryBigEndian()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -81,3 +81,10 @@ bool WriteValueAtHardwareAddress(HWAddressType address, unsigned int value, unsi
|
||||
bool WriteValueAtHardwareAddress_audio(HWAddressType address, unsigned int value, unsigned int size, int isLittleEndian);
|
||||
|
||||
bool IsHardwareAddressValid(HWAddressType address);
|
||||
|
||||
#ifdef BUILD_HEADLESS
|
||||
// OpenEmu-Silicon headless helpers (see cheat.cpp).
|
||||
unsigned int GetMainMemorySize();
|
||||
unsigned int ReadMemoryRange(HWAddressType address, unsigned char *buffer, unsigned int length);
|
||||
int GetMainMemoryBigEndian(); // multibyte order for host cheats; always 0 (little-endian), see cheat.cpp
|
||||
#endif
|
||||
+26
-49
@@ -15,6 +15,8 @@ UINT8 *CpsRom =NULL; UINT32 nCpsRomLen =0; // Program Rom (as in rom)
|
||||
UINT8 *CpsCode=NULL; UINT32 nCpsCodeLen=0; // Program Rom (decrypted)
|
||||
UINT8 *CpsZRom=NULL; UINT32 nCpsZRomLen=0; // Z80 Roms
|
||||
INT8 *CpsQSam=NULL; UINT32 nCpsQSamLen=0; // QSound Sample Roms
|
||||
UINT32 nCpsQSamMask = 0;
|
||||
UINT32 nCpsRomMapLen = 0;
|
||||
UINT8 *CpsAd =NULL; UINT32 nCpsAdLen =0; // ADPCM Data
|
||||
UINT8 *CpsStar=NULL;
|
||||
UINT8 *CpsKey=NULL; UINT32 nCpsKeyLen = 0;
|
||||
@@ -1778,23 +1780,7 @@ INT32 Cps2LoadTiles(UINT8* Tile, INT32 nStart)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
"usual cps2":
|
||||
rom0 12
|
||||
rom1 34
|
||||
rom2 56
|
||||
rom3 78
|
||||
|
||||
"interleaved (zero800/cps2turbo)"
|
||||
rom 12345678
|
||||
|
||||
12 12 12 12
|
||||
34 34 34 34
|
||||
56 56 56 56
|
||||
78 78 78 78
|
||||
(visualization helper)
|
||||
#endif
|
||||
|
||||
// Four interleaved ROM lanes in one source image.
|
||||
#define BLOCK_MOD 4
|
||||
|
||||
inline static void Cps2LoadBlockInterleaved(UINT8* Tile, UINT8* Sect, INT32 nShift)
|
||||
@@ -1856,19 +1842,6 @@ INT32 Cps2LoadTilesInterleaved(UINT8 *Tile, UINT8 *pSrc, UINT32 nSize)
|
||||
|
||||
#undef BLOCK_MOD
|
||||
|
||||
INT32 Cps2LoadTilesTurbo(UINT8* Tile, INT32 nSize) // cps2turbo
|
||||
{
|
||||
UINT8 *Rom = (UINT8*)BurnMalloc(nSize);
|
||||
memcpy(Rom, Tile, nSize);
|
||||
memset(Tile, 0, nSize);
|
||||
|
||||
Cps2LoadTilesInterleaved(Tile, Rom, nSize);
|
||||
|
||||
BurnFree(Rom);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps2LoadTilesSplit4(UINT8* Tile, INT32 nStart)
|
||||
{
|
||||
// left side of 16x16 tiles
|
||||
@@ -1986,7 +1959,7 @@ INT32 Cps2LoadTilesGigaman2(UINT8 *Tile, UINT8 *pSrc)
|
||||
|
||||
static UINT32 nGfxMaxSize;
|
||||
|
||||
static INT32 CpsGetROMs(bool bLoad)
|
||||
static INT32 CpsGetROMs(bool bLoad, INT32 bLinear)
|
||||
{
|
||||
struct BurnRomInfo ri;
|
||||
|
||||
@@ -2023,7 +1996,7 @@ static INT32 CpsGetROMs(bool bLoad)
|
||||
if ((ri.nType & 0x0f) == CPS2_PRG_68K) {
|
||||
if (bLoad) {
|
||||
if (BurnLoadRom(CpsRomLoad, i, 1)) return 1;
|
||||
if (Cps2Turbo) BurnByteswap(CpsRomLoad, ri.nLen);
|
||||
if (bLinear) BurnByteswap(CpsRomLoad, ri.nLen);
|
||||
CpsRomLoad += ri.nLen;
|
||||
} else {
|
||||
nCpsRomLen += ri.nLen;
|
||||
@@ -2052,7 +2025,7 @@ static INT32 CpsGetROMs(bool bLoad)
|
||||
|
||||
if ((ri.nType & 0x0f) == CPS2_GFX) {
|
||||
if (bLoad) {
|
||||
if (Cps2Turbo) {
|
||||
if (bLinear) {
|
||||
BurnLoadRom(CpsGfxLoad, i, 1);
|
||||
|
||||
CpsGfxLoad += ri.nLen;
|
||||
@@ -2142,7 +2115,7 @@ static INT32 CpsGetROMs(bool bLoad)
|
||||
if ((ri.nType & 0x0f) == CPS2_QSND) {
|
||||
if (bLoad) {
|
||||
BurnLoadRom(CpsQSamLoad, i, 1);
|
||||
if (Cps2Turbo == 0) {
|
||||
if (!bLinear) {
|
||||
BurnByteswap(CpsQSamLoad, ri.nLen);
|
||||
}
|
||||
CpsQSamLoad += ri.nLen;
|
||||
@@ -2189,11 +2162,8 @@ static INT32 CpsGetROMs(bool bLoad)
|
||||
((UINT32*)CpsCode)[i] ^= ((UINT32*)CpsRom)[i];
|
||||
}
|
||||
#endif
|
||||
if (Cps2Turbo) {
|
||||
Cps2LoadTilesTurbo(CpsGfx, nCpsGfxLen);
|
||||
}
|
||||
|
||||
cps2_decrypt_game_data();
|
||||
if (nCpsCodeLen && CpsCode == NULL) return 1;
|
||||
|
||||
// if (!nCpsCodeLen) return 1;
|
||||
} else {
|
||||
@@ -2252,9 +2222,6 @@ INT32 CpsInit()
|
||||
nCPS68KClockspeed = 10000000;
|
||||
}
|
||||
}
|
||||
if (Cps2Turbo) {
|
||||
nCPS68KClockspeed = 32000000;
|
||||
}
|
||||
nCPS68KClockspeed = (INT64)nCPS68KClockspeed * 100 / nBurnFPS;
|
||||
|
||||
nMemLen = nCpsGfxLen + nCpsRomLen + nCpsCodeLen + nCpsZRomLen + nCpsQSamLen + nCpsAdLen + nCpsKeyLen;
|
||||
@@ -2318,15 +2285,24 @@ INT32 CpsInit()
|
||||
|
||||
INT32 Cps2Init()
|
||||
{
|
||||
Cps = 2;
|
||||
return Cps2Init(0, 0, 0);
|
||||
}
|
||||
|
||||
if (CpsGetROMs(false)) {
|
||||
INT32 Cps2Init(INT32 nMapLen, UINT32 nGfxSize, INT32 bLinear)
|
||||
{
|
||||
Cps = 2;
|
||||
nCpsRomMapLen = nMapLen;
|
||||
|
||||
if (CpsGetROMs(false, bLinear)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CpsInit();
|
||||
if (nGfxSize) nCpsGfxLen = nGfxSize;
|
||||
if (CpsInit()) return 1;
|
||||
|
||||
if (CpsGetROMs(true)) {
|
||||
if (CpsGetROMs(true, bLinear)) {
|
||||
// Before decryption, CpsCode aliases the shared ROM allocation.
|
||||
if (!nCpsCodeLen) CpsCode = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2351,6 +2327,7 @@ INT32 CpsExit()
|
||||
nCpsCodeLen = nCpsRomLen = nCpsGfxLen = nCpsZRomLen = nCpsQSamLen = nCpsAdLen = nCpsKeyLen = 0;
|
||||
CpsRom = CpsZRom = CpsAd = CpsStar = NULL;
|
||||
CpsQSam = NULL;
|
||||
nCpsQSamMask = 0;
|
||||
CpsKey = NULL;
|
||||
|
||||
// All Memory is allocated to this (this is the only one we can free)
|
||||
@@ -2369,10 +2346,10 @@ INT32 CpsExit()
|
||||
nCpsGlobalXOffset = 0;
|
||||
nCpsGlobalYOffset = 0;
|
||||
|
||||
if (Cps2Turbo) {
|
||||
BurnSampleExit();
|
||||
Cps2Turbo = 0;
|
||||
}
|
||||
nCpsRomMapLen = 0;
|
||||
CpsDrawPaletteCallbackFunction = NULL;
|
||||
Cps2ScrollCallbackFunction = NULL;
|
||||
Cps2Scroll1CallbackFunction = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
+53
-20
@@ -28,9 +28,11 @@ extern INT32 nCpsCycles; // Cycles per frame
|
||||
extern INT32 nCpsZ80Cycles;
|
||||
extern UINT8 *CpsGfx; extern UINT32 nCpsGfxLen; // All the graphics
|
||||
extern UINT8 *CpsRom; extern UINT32 nCpsRomLen; // Program Rom (as in rom)
|
||||
extern UINT32 nCpsRomMapLen; // Optional program mapping size; 0 uses the ROM size
|
||||
extern UINT8 *CpsCode; extern UINT32 nCpsCodeLen; // Program Rom (decrypted)
|
||||
extern UINT8 *CpsZRom; extern UINT32 nCpsZRomLen; // Z80 Roms
|
||||
extern INT8 *CpsQSam; extern UINT32 nCpsQSamLen; // QSound Sample Roms
|
||||
extern UINT32 nCpsQSamMask; // Optional sample decoder mask; 0 uses the ROM size
|
||||
extern UINT8 *CpsAd; extern UINT32 nCpsAdLen; // ADPCM Data
|
||||
extern UINT8 *CpsKey; extern UINT32 nCpsKeyLen;
|
||||
extern UINT32 nCpsGfxScroll[4]; // Offset to Scroll tiles
|
||||
@@ -38,6 +40,7 @@ extern UINT32 nCpsGfxMask; // Address mask
|
||||
extern UINT8* CpsStar;
|
||||
INT32 CpsInit();
|
||||
INT32 Cps2Init();
|
||||
INT32 Cps2Init(INT32 nMapLen, UINT32 nGfxSize, INT32 bLinear);
|
||||
INT32 CpsExit();
|
||||
INT32 CpsLoadTiles(UINT8 *Tile,INT32 nStart);
|
||||
INT32 CpsLoadTilesByte(UINT8 *Tile,INT32 nStart);
|
||||
@@ -82,6 +85,7 @@ INT32 CpsLoadStarsByte(UINT8 *pStar, INT32 nStart);
|
||||
INT32 CpsLoadStarsForgottnAlt(UINT8 *pStar, INT32 nStart);
|
||||
INT32 Cps2LoadTiles(UINT8 *Tile,INT32 nStart);
|
||||
INT32 Cps2LoadTilesSIM(UINT8 *Tile,INT32 nStart);
|
||||
INT32 Cps2LoadTilesInterleaved(UINT8 *Tile, UINT8 *pSrc, UINT32 nSize);
|
||||
INT32 Cps2LoadTilesGigaman2(UINT8 *Tile, UINT8 *pSrc);
|
||||
|
||||
// cps_config.h
|
||||
@@ -177,6 +181,8 @@ INT32 Cps2LoadTilesGigaman2(UINT8 *Tile, UINT8 *pSrc);
|
||||
#define mapper_pang3b4 48
|
||||
#define mapper_TKSGZB 49
|
||||
#define mapper_varthb2 50
|
||||
#define mapper_STRIDEREX 51
|
||||
#define mapper_FFIGHTEX 52
|
||||
extern void SetGfxMapper(INT32 MapperId);
|
||||
extern INT32 GfxRomBankMapper(INT32 Type, INT32 Code);
|
||||
extern void SetCpsBId(INT32 CpsBId, INT32 bStars);
|
||||
@@ -188,6 +194,9 @@ extern INT32 bCpsUpdatePalEveryFrame;
|
||||
INT32 CpsPalInit();
|
||||
INT32 CpsPalExit();
|
||||
INT32 CpsPalUpdate(UINT8 *pNewPal);
|
||||
typedef void (*CpsPalUpdateCallback)(INT32 nPage, const UINT16* pPalette);
|
||||
extern CpsPalUpdateCallback CpsPalUpdateCallbackFunction;
|
||||
void CpsPalRecalc(const UINT16* pRaw);
|
||||
|
||||
// cps_mem.cpp
|
||||
extern UINT8 *CpsRam90;
|
||||
@@ -204,6 +213,13 @@ INT32 CpsAreaScan(INT32 nAction,INT32 *pnMin);
|
||||
|
||||
typedef INT32 (*CpsMemScanCallback)(INT32, INT32*);
|
||||
extern CpsMemScanCallback CpsMemScanCallbackFunction;
|
||||
// Additional device state precedes sound state in the scan order.
|
||||
extern CpsMemScanCallback CpsMemScanExtraCallbackFunction;
|
||||
// Optional replacement for the QSound state scan.
|
||||
typedef void (*CpsSoundScanCallback)(INT32, INT32*);
|
||||
extern CpsSoundScanCallback CpsSoundScanCallbackFunction;
|
||||
|
||||
extern INT32 bCpsObjectBankHandlers;
|
||||
|
||||
// cps_run.cpp
|
||||
extern UINT8 CpsReset;
|
||||
@@ -287,7 +303,6 @@ extern INT32 Ssf2tb;
|
||||
extern INT32 Dinohunt;
|
||||
extern INT32 Port6SoundWrite;
|
||||
extern INT32 CpsBootlegEEPROM;
|
||||
extern INT32 Cps2Turbo;
|
||||
extern INT32 Jurassic99;
|
||||
extern INT32 Dinoh;
|
||||
extern INT32 Wofhfh;
|
||||
@@ -312,8 +327,14 @@ void __fastcall CpsWriteWord(UINT32 a, UINT16 d);
|
||||
|
||||
typedef void (*CpsRWSoundCommandCallback)(UINT16);
|
||||
extern CpsRWSoundCommandCallback CpsRWSoundCommandCallbackFunction;
|
||||
// Prepare inputs before port compilation; return the number of stock-port players.
|
||||
typedef INT32 (*CpsRwGetInpCallback)();
|
||||
extern CpsRwGetInpCallback CpsRwGetInpCallbackFunction;
|
||||
|
||||
// cps_draw.cpp
|
||||
typedef INT32 (*CpsDrawPaletteCallback)();
|
||||
// Return nonzero when the palette is already current for this draw.
|
||||
extern CpsDrawPaletteCallback CpsDrawPaletteCallbackFunction;
|
||||
extern UINT8 CpsRecalcPal; // Flag - If it is 1, recalc the whole palette
|
||||
extern INT32 nCpsLcReg; // Address of layer controller register
|
||||
extern INT32 CpsLayEn[6]; // bits for layer enable
|
||||
@@ -349,9 +370,15 @@ void QsndReset();
|
||||
void QsndNewFrame();
|
||||
void QsndEndFrame();
|
||||
void QsndSyncZ80();
|
||||
INT32 QsndScan(INT32 nAction);
|
||||
INT32 QsndScan(INT32 nAction, INT32 bScanHistory = 0);
|
||||
|
||||
// qs_z.cpp
|
||||
extern INT32 nQsndZ80Clock, nQsndZBankOffset;
|
||||
void QsndZReset();
|
||||
void QsndZSetBank(INT32 nBank);
|
||||
INT32 QsndZGetBank();
|
||||
UINT8 __fastcall QsndZRead(UINT16 a);
|
||||
void __fastcall QsndZWrite(UINT16 a, UINT8 d);
|
||||
INT32 QsndZInit();
|
||||
INT32 QsndZExit();
|
||||
INT32 QsndZScan(INT32 nAction);
|
||||
@@ -361,7 +388,7 @@ INT32 QscInit(INT32 nRate);
|
||||
void QscSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir);
|
||||
void QscReset();
|
||||
void QscExit();
|
||||
INT32 QscScan(INT32 nAction);
|
||||
INT32 QscScan(INT32 nAction, INT32 bScanHistory = 0);
|
||||
void QscNewFrame();
|
||||
void QscWrite(INT32 a, INT32 d);
|
||||
UINT8 QscRead();
|
||||
@@ -411,6 +438,7 @@ INT32 CtvReady();
|
||||
|
||||
// cps_obj.cpp
|
||||
extern INT32 nCpsObjectBank;
|
||||
extern INT32 nCpsObjExtraLen; // Optional extra data bytes per buffered sprite frame
|
||||
extern UINT8 *CpsBootlegSpriteRam;
|
||||
extern INT32 Cps1LockSpriteList910000;
|
||||
extern INT32 Cps1DetectEndSpriteList8000;
|
||||
@@ -419,7 +447,17 @@ typedef INT32 (*Cps1ObjGetCallback)();
|
||||
extern Cps1ObjGetCallback Cps1ObjGetCallbackFunction;
|
||||
typedef INT32 (*Cps1ObjDrawCallback)(INT32, INT32);
|
||||
extern Cps1ObjDrawCallback Cps1ObjDrawCallbackFunction;
|
||||
extern INT32 bCpsUseParentBlend;
|
||||
typedef void (*Cps2ObjGetCallback)(UINT8* pExtra, INT32 nEntry, INT32 nSource);
|
||||
extern Cps2ObjGetCallback Cps2ObjGetCallbackFunction;
|
||||
typedef INT32 (*Cps2ObjTileCallback)(UINT16* pObject, INT32 nTile, const UINT8* pExtra, INT32 nEntry);
|
||||
extern Cps2ObjTileCallback Cps2ObjTileCallbackFunction;
|
||||
// Negative skips the object, zero uses its palette, positive supplies 16 colors.
|
||||
typedef INT32 (*Cps2ObjPaletteCallback)(INT32, UINT16, UINT16, INT32, UINT32*);
|
||||
extern Cps2ObjPaletteCallback Cps2ObjPaletteCallbackFunction;
|
||||
|
||||
void CpsObjReset();
|
||||
INT32 CpsObjScan(INT32 nAction, char* szName);
|
||||
INT32 CpsObjInit();
|
||||
INT32 CpsObjExit();
|
||||
INT32 CpsObjGet();
|
||||
@@ -449,6 +487,18 @@ INT32 Cps1Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
INT32 Cps2Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
INT32 Cps2Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
|
||||
typedef INT32 (*Cps2ScrollCallback)(INT32, INT32, INT32);
|
||||
extern Cps2ScrollCallback Cps2ScrollCallbackFunction;
|
||||
typedef const UINT8* (*Cps2Scroll1Callback)();
|
||||
extern Cps2Scroll1Callback Cps2Scroll1CallbackFunction;
|
||||
|
||||
// Resolve a scroll tile address, including its layer's graphics offset.
|
||||
inline static INT32 Cps2ScrollAddress(INT32 nAddress, INT32 nAttributes, INT32 nLayer)
|
||||
{
|
||||
if (Cps2ScrollCallbackFunction) return Cps2ScrollCallbackFunction(nAddress, nAttributes, nLayer);
|
||||
return nAddress + nCpsGfxScroll[nLayer];
|
||||
}
|
||||
|
||||
// cpsr.cpp
|
||||
extern UINT8 *CpsrBase; // Tile data base
|
||||
extern INT32 nCpsrScrX,nCpsrScrY; // Basic scroll info
|
||||
@@ -560,21 +610,4 @@ extern UINT16 Cps2VolumeStates[40];
|
||||
extern INT32 Cps2DisableDigitalVolume;
|
||||
extern UINT8 Cps2VolUp;
|
||||
extern UINT8 Cps2VolDwn;
|
||||
extern UINT8 AspectDIP;
|
||||
|
||||
// cps_rw.cpp: X-Men Vs. Street Fighter 3v3 + DHC board additions (xmvsf3v3.h)
|
||||
extern UINT8 CpsXmvSixButtons[6][13];
|
||||
extern INT32 CpsXmvSixEnabled;
|
||||
extern INT32 CpsXmvWide;
|
||||
INT32 CpsXmvSixInit(INT32 bWide);
|
||||
void CpsXmvSixExit();
|
||||
INT32 CpsXmvSixReset();
|
||||
INT32 CpsXmvSixScan(INT32 nAction, INT32* pnMin);
|
||||
const UINT8* CpsXmvScroll1Extension();
|
||||
// ... and its exact save states (run-ahead, netplay): the display state other games rebuild after a load
|
||||
INT32 CpsXmvVisualScan(INT32 nAction); // cps_mem.cpp
|
||||
INT32 CpsObjVisualScan(INT32 nAction); // cps_obj.cpp
|
||||
INT32 CpsPalVisualScan(INT32 nAction); // cps_pal.cpp
|
||||
INT32 CpsPalConsumeRestoredCache();
|
||||
|
||||
#endif
|
||||
@@ -643,8 +643,10 @@ static void cps2_decrypt(const UINT32 *master_key, UINT32 lower_limit, UINT32 up
|
||||
UINT16 *rom = (UINT16 *)CpsRom;
|
||||
UINT32 length = (upper_limit > 0) ? (upper_limit * 2) : nCpsRomLen;
|
||||
if (length > nCpsRomLen) length = nCpsRomLen;
|
||||
CpsCode = (UINT8*)BurnMalloc(length);
|
||||
if (nCpsRomMapLen && length > nCpsRomMapLen) length = nCpsRomMapLen;
|
||||
nCpsCodeLen = length;
|
||||
CpsCode = (UINT8*)BurnMalloc(length);
|
||||
if (CpsCode == NULL) return;
|
||||
UINT16 *dec = (UINT16*)CpsCode;
|
||||
|
||||
INT32 i;
|
||||
|
||||
@@ -72,6 +72,19 @@ static const struct GfxRange mapper_ST24M1_table[] =
|
||||
{ 0 , 0, 0, 0 }
|
||||
};
|
||||
|
||||
// Strider EX: original ST24M1 ranges plus the native backport graphics bank.
|
||||
static const struct GfxRange mapper_STRIDEREX_table[] = {
|
||||
{ GFXTYPE_STARS, 0x00000, 0x003ff, 0 },
|
||||
{ GFXTYPE_SPRITES, 0x00000, 0x04fff, 0 },
|
||||
{ GFXTYPE_SCROLL2, 0x04000, 0x07fff, 0 },
|
||||
{ GFXTYPE_SCROLL3, 0x00000, 0x07fff, 1 },
|
||||
{ GFXTYPE_SCROLL1, 0x07000, 0x07fff, 1 },
|
||||
{ GFXTYPE_SPRITES | GFXTYPE_SCROLL2, 0x10000, 0x17fff, 2 },
|
||||
{ GFXTYPE_SCROLL1, 0x08000, 0x0bfff, 2 },
|
||||
{ GFXTYPE_SCROLL3, 0x1c000, 0x1ffff, 2 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct GfxRange mapper_ST22B_table[] = {
|
||||
{ GFXTYPE_STARS, 0x00000, 0x1ffff, 0 },
|
||||
{ GFXTYPE_SPRITES, 0x00000, 0x03fff, 0 },
|
||||
@@ -107,6 +120,17 @@ static const struct GfxRange mapper_WL24B_table[] = {
|
||||
{ 0 , 0, 0, 0 }
|
||||
};
|
||||
|
||||
// Final Fight EX: published 6 MiB (4+2) graphics mapper.
|
||||
static const struct GfxRange mapper_FFIGHTEX_table[] = {
|
||||
{ GFXTYPE_SPRITES, 0x00000, 0x043ff, 0 },
|
||||
{ GFXTYPE_SCROLL1, 0x04400, 0x04bff, 0 },
|
||||
{ GFXTYPE_SCROLL3, 0x04c00, 0x05fff, 0 },
|
||||
{ GFXTYPE_SCROLL2, 0x06000, 0x07fff, 0 },
|
||||
{ GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x08000, 0x0ffff, 0 },
|
||||
{ GFXTYPE_SPRITES | GFXTYPE_SCROLL1 | GFXTYPE_SCROLL2 | GFXTYPE_SCROLL3, 0x10000, 0x17fff, 1 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct GfxRange mapper_S224B_table[] = {
|
||||
{ GFXTYPE_SPRITES, 0x0000, 0x43ff, 0 },
|
||||
{ GFXTYPE_SCROLL1, 0x4400, 0x4bff, 0 },
|
||||
@@ -542,6 +566,24 @@ void SetGfxMapper(INT32 MapperId)
|
||||
return;
|
||||
}
|
||||
|
||||
case mapper_FFIGHTEX: {
|
||||
GfxBankSizes[0] = 0x10000;
|
||||
GfxBankSizes[1] = 0x08000;
|
||||
GfxBankSizes[2] = 0x00000;
|
||||
GfxBankSizes[3] = 0x00000;
|
||||
GfxBankMapper = mapper_FFIGHTEX_table;
|
||||
return;
|
||||
}
|
||||
|
||||
case mapper_STRIDEREX: {
|
||||
GfxBankSizes[0] = 0x08000;
|
||||
GfxBankSizes[1] = 0x08000;
|
||||
GfxBankSizes[2] = 0x10000;
|
||||
GfxBankSizes[3] = 0x00000;
|
||||
GfxBankMapper = mapper_STRIDEREX_table;
|
||||
return;
|
||||
}
|
||||
|
||||
case mapper_ST24M1: {
|
||||
GfxBankSizes[0] = 0x8000;
|
||||
GfxBankSizes[1] = 0x8000;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "cps.h"
|
||||
// CPS - Draw
|
||||
|
||||
CpsDrawPaletteCallback CpsDrawPaletteCallbackFunction = NULL;
|
||||
|
||||
UINT8 CpsRecalcPal = 0; // Flag - If it is 1, recalc the whole palette
|
||||
|
||||
static INT32 LayerCont;
|
||||
@@ -499,8 +501,7 @@ static void DoDraw(INT32 Recalc)
|
||||
{
|
||||
CtvReady(); // Point to correct tile drawing functions
|
||||
|
||||
// xmvsf3v3: a state load restores the effective palette itself; rereading palette RAM would lose it
|
||||
if (!CpsPalConsumeRestoredCache()) {
|
||||
if (!CpsDrawPaletteCallbackFunction || !CpsDrawPaletteCallbackFunction()) {
|
||||
if (CpsRecalcPal || bCpsUpdatePalEveryFrame) GetPalette(0, 6);
|
||||
if (Recalc || bCpsUpdatePalEveryFrame) CpsPalUpdate(CpsSavePal); // recalc whole palette if needed
|
||||
}
|
||||
|
||||
+17
-137
@@ -16,6 +16,9 @@ UINT8 *CpsRam660=NULL,*CpsRam708=NULL,*CpsReg=NULL,*CpsFrg=NULL;
|
||||
UINT8 *CpsRamFF=NULL;
|
||||
|
||||
CpsMemScanCallback CpsMemScanCallbackFunction = NULL;
|
||||
CpsMemScanCallback CpsMemScanExtraCallbackFunction = NULL;
|
||||
CpsSoundScanCallback CpsSoundScanCallbackFunction = NULL;
|
||||
INT32 bCpsObjectBankHandlers = 0;
|
||||
|
||||
// This routine is called first to determine how much memory is needed
|
||||
// and then to set up all the pointers.
|
||||
@@ -87,6 +90,8 @@ void CpsDoMapObjectBanks(INT32 nBank)
|
||||
{
|
||||
nCpsObjectBank = nBank;
|
||||
|
||||
if (bCpsObjectBankHandlers) return;
|
||||
|
||||
if (nCpsObjectBank) {
|
||||
SekMapMemory(CpsRam708 + 0x8000, 0x708000, 0x709FFF, MAP_RAM);
|
||||
SekMapMemory(CpsRam708 + 0x8000, 0x70A000, 0x70BFFF, MAP_RAM);
|
||||
@@ -117,106 +122,6 @@ INT32 __fastcall CPSResetCallback()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// samples:
|
||||
// empty + 0x3f L, channel 0, sample + 0x00
|
||||
// empty + 0x3f R, channel 1, sample + 0x40
|
||||
|
||||
static void samples_l_start(int channel, int sample, int loop)
|
||||
{
|
||||
BurnSampleChannelPlay(channel + 0x00, sample + 0x00, loop);
|
||||
}
|
||||
|
||||
static int samples_l_playing()
|
||||
{
|
||||
return BurnSampleGetChannelStatus(0x00) == SAMPLE_PLAYING;
|
||||
}
|
||||
static int samples_r_playing()
|
||||
{
|
||||
return BurnSampleGetChannelStatus(0x01) == SAMPLE_PLAYING;
|
||||
}
|
||||
|
||||
static void samples_r_start(int channel, int sample, int loop)
|
||||
{
|
||||
BurnSampleChannelPlay(channel + 0x01, sample + 0x40, loop);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static void qsound_cps2turbo_write(UINT32 offset, UINT8 data) //Zero800 allows you to write and signal when a new song is played
|
||||
{
|
||||
UINT8 *m_qsound_sharedram1 = CpsZRamC0;
|
||||
UINT8 *m_qsound_sharedram2 = CpsZRamF0;
|
||||
if (offset == 0x0001 && (data & 0xff) == 0x00 && m_qsound_sharedram1[0x00] == 0xff) //stop samples sound
|
||||
{
|
||||
samples_l_start(0, 0, 0);
|
||||
samples_r_start(0, 0, 0);
|
||||
bprintf(0, _T("Stop: %02x to %x\n"), offset, offset);
|
||||
}
|
||||
|
||||
if (offset == 0xffe)
|
||||
{
|
||||
if (m_qsound_sharedram1[0x80] == 0x77) //stop music condition in audiocpu = C080 (z80 hacked)
|
||||
{
|
||||
samples_l_start(0, 0, 0); //init L samples
|
||||
samples_r_start(0, 0, 0); //init R samples
|
||||
m_qsound_sharedram2[0x27] = 0xc9; //Enable Qsound Volume
|
||||
m_qsound_sharedram1[0x80] = 0xff; //Reset music id flag
|
||||
m_qsound_sharedram1[0x81] = 0xff; //Reset music id flag
|
||||
bprintf(0, _T("Clear: %02x to %x\n"), data, offset);
|
||||
}
|
||||
else
|
||||
if (m_qsound_sharedram1[0x81] > 0x00 && m_qsound_sharedram1[0x81] < 0x40) //play music condition in audiocpu = C081 (z80 hacked)
|
||||
{
|
||||
int data_byte = m_qsound_sharedram1[0x81];
|
||||
m_qsound_sharedram1[0x80] = 0xff; //Reset music id flag
|
||||
m_qsound_sharedram1[0x81] = 0xff; //Reset music id flag
|
||||
bprintf(0, _T("Music: %02x to %x\n"), data_byte, offset);
|
||||
samples_l_start(0, data_byte, 1);
|
||||
if (samples_l_playing() == 1)
|
||||
{
|
||||
m_qsound_sharedram2[0x27] = 0x00; //Qsound music volume = 0
|
||||
}
|
||||
else
|
||||
samples_l_start(0, 0, 0); //init L samples
|
||||
|
||||
samples_r_start(0, data_byte, 1);
|
||||
if (samples_r_playing() == 1)
|
||||
{
|
||||
m_qsound_sharedram2[0x27] = 0x00; //Qsound music volume = 0
|
||||
}
|
||||
else
|
||||
samples_r_start(0, 0, 0); //init R samples
|
||||
}
|
||||
else
|
||||
if (m_qsound_sharedram2[0x27] == 0x00 && samples_l_playing() != 1) //if loadstate and qsound volume = 0 && samples stopped
|
||||
{
|
||||
samples_l_start(0, 0, 0); //init L samples
|
||||
samples_r_start(0, 0, 0); //init R samples
|
||||
m_qsound_sharedram2[0x27] = 0xc9; //Enable Qsound Volume
|
||||
m_qsound_sharedram1[0x80] = 0xff; //Reset music id flag
|
||||
m_qsound_sharedram1[0x81] = 0xff; //Reset music id flag
|
||||
bprintf(0, _T("Volume0: %02x to %x\n"), data, offset);
|
||||
}
|
||||
else
|
||||
if (m_qsound_sharedram2[0x27] != 0x00 && samples_l_playing() == 1) //if loadstate and qsound volume != 0 && samples playing
|
||||
{
|
||||
samples_l_start(0, 0, 0); //init L samples
|
||||
samples_r_start(0, 0, 0); //init R samples
|
||||
m_qsound_sharedram2[0x27] = 0xc9; //Enable Qsound Volume
|
||||
m_qsound_sharedram1[0x80] = 0xff; //Reset music id flag
|
||||
m_qsound_sharedram1[0x81] = 0xff; //Reset music id flag
|
||||
bprintf(0, _T("Volume0: %02x to %x\n"), data, offset);
|
||||
}
|
||||
else
|
||||
if ((data & 0xff) == 0x55) //init samples in rom start
|
||||
{
|
||||
samples_l_start(0, 0, 0);
|
||||
samples_r_start(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_qsound_sharedram1[offset] = data; //Play data Qsound
|
||||
}
|
||||
|
||||
UINT8 __fastcall CPSQSoundC0ReadByte(UINT32 sekAddress)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" QS %06X read\n"), sekAddress);
|
||||
@@ -241,10 +146,6 @@ void __fastcall CPSQSoundC0WriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
|
||||
sekAddress &= 0x1FFF;
|
||||
|
||||
if (Cps2Turbo) {
|
||||
qsound_cps2turbo_write(sekAddress >> 1, byteValue);
|
||||
}
|
||||
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
// Sync only when the last byte of the sound command is written
|
||||
if (sekAddress == 0x001F) {
|
||||
@@ -361,25 +262,19 @@ INT32 CpsMemInit()
|
||||
|
||||
SekSetResetCallback(CPSResetCallback);
|
||||
|
||||
if (Cps2Turbo) {
|
||||
// hmmmmmm
|
||||
bprintf(0, _T("limit 68k to 0x400000\n"));
|
||||
nCpsRomLen = 0x400000;
|
||||
nCpsCodeLen = 0x400000;
|
||||
}
|
||||
|
||||
// Map in memory:
|
||||
// 68000 Rom (as seen as is, through read)
|
||||
SekMapMemory(CpsRom, 0, nCpsRomLen - 1, MAP_READ);
|
||||
UINT32 nRomMapLen = nCpsRomMapLen ? nCpsRomMapLen : nCpsRomLen;
|
||||
SekMapMemory(CpsRom, 0, nRomMapLen - 1, MAP_READ);
|
||||
|
||||
// 68000 Rom (as seen decrypted, through fetch)
|
||||
if (nCpsCodeLen > 0) {
|
||||
// Decoded part (up to nCpsCodeLen)
|
||||
SekMapMemory(CpsCode, 0, nCpsCodeLen - 1, MAP_FETCH);
|
||||
}
|
||||
if (nCpsRomLen > nCpsCodeLen) {
|
||||
// The rest (up to nCpsRomLen)
|
||||
SekMapMemory(CpsRom + nCpsCodeLen, nCpsCodeLen, nCpsRomLen - 1, MAP_FETCH);
|
||||
if (nRomMapLen > nCpsCodeLen) {
|
||||
// The remaining program data is fetched without decryption.
|
||||
SekMapMemory(CpsRom + nCpsCodeLen, nCpsCodeLen, nRomMapLen - 1, MAP_FETCH);
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
@@ -456,6 +351,9 @@ INT32 CpsMemExit()
|
||||
BurnFree(CpsMem);
|
||||
|
||||
CpsMemScanCallbackFunction = NULL;
|
||||
CpsMemScanExtraCallbackFunction = NULL;
|
||||
CpsSoundScanCallbackFunction = NULL;
|
||||
bCpsObjectBankHandlers = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -541,11 +439,9 @@ INT32 CpsAreaScan(INT32 nAction, INT32 *pnMin)
|
||||
SCAN_VAR(nCps1LayerOffs);
|
||||
}
|
||||
|
||||
CpsRwScan(); // scan cps_rw.cpp stuff
|
||||
if (CpsMemScanExtraCallbackFunction && CpsMemScanExtraCallbackFunction(nAction, pnMin)) return 1;
|
||||
|
||||
if (Cps2Turbo) {
|
||||
BurnSampleScan(nAction, pnMin);
|
||||
}
|
||||
CpsRwScan(); // scan cps_rw.cpp stuff
|
||||
|
||||
if (nAction & ACB_WRITE) { // Palette could have changed
|
||||
CpsRecalcPal = 1;
|
||||
@@ -559,7 +455,8 @@ INT32 CpsAreaScan(INT32 nAction, INT32 *pnMin)
|
||||
}
|
||||
|
||||
if (((Cps == 2) && !Cps2DisableQSnd) || Cps1Qs == 1) { // Scan QSound chips
|
||||
QsndScan(nAction);
|
||||
if (CpsSoundScanCallbackFunction) CpsSoundScanCallbackFunction(nAction, pnMin);
|
||||
else QsndScan(nAction);
|
||||
} else { // Scan PSound chips
|
||||
if ((Cps & 1) && !Cps1DisablePSnd) PsndScan(nAction, pnMin);
|
||||
}
|
||||
@@ -570,20 +467,3 @@ INT32 CpsAreaScan(INT32 nAction, INT32 *pnMin)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// xmvsf3v3: the display state other games rebuild after a load (latched palette, registers and
|
||||
// 'four' registers, sprite lag buffers), so its states restore exactly, a paused redraw included
|
||||
INT32 CpsXmvVisualScan(INT32 nAction)
|
||||
{
|
||||
if (!CpsXmvSixEnabled || !(nAction & ACB_DRIVER_DATA)) return 0;
|
||||
|
||||
struct BurnArea ba;
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = CpsSavePal; ba.nLen = 0x2000; ba.szName = "XMvsSF 3v3 latched palette"; BurnAcb(&ba);
|
||||
ba.Data = CpsSaveRegData; ba.nLen = 0x100 * (MAX_RASTER + 1); ba.szName = "XMvsSF 3v3 latched registers"; BurnAcb(&ba);
|
||||
ba.Data = CpsSaveFrgData; ba.nLen = 0x20; ba.szName = "XMvsSF 3v3 latched frg"; BurnAcb(&ba);
|
||||
|
||||
if (CpsObjVisualScan(nAction)) return 1;
|
||||
|
||||
return CpsPalVisualScan(nAction);
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "cps.h"
|
||||
#include "xmvsf3v3.h"
|
||||
// CPS Objs (sprites)
|
||||
|
||||
INT32 nCpsObjectBank;
|
||||
INT32 nCpsObjExtraLen = 0;
|
||||
INT32 Sfa2ObjHack = 0;
|
||||
|
||||
UINT8 *CpsBootlegSpriteRam = NULL;
|
||||
@@ -12,9 +12,14 @@ INT32 Cps1DetectEndSpriteList8000 = 0;
|
||||
|
||||
Cps1ObjGetCallback Cps1ObjGetCallbackFunction = NULL;
|
||||
Cps1ObjDrawCallback Cps1ObjDrawCallbackFunction = NULL;
|
||||
Cps2ObjGetCallback Cps2ObjGetCallbackFunction = NULL;
|
||||
Cps2ObjTileCallback Cps2ObjTileCallbackFunction = NULL;
|
||||
Cps2ObjPaletteCallback Cps2ObjPaletteCallbackFunction = NULL;
|
||||
INT32 bCpsUseParentBlend = 1;
|
||||
|
||||
// Our copy of the sprite table
|
||||
static UINT8 *ObjMem = NULL;
|
||||
static INT32 nObjMemLen;
|
||||
|
||||
static INT32 nMax = 0;
|
||||
static INT32 nGetNext = 0;
|
||||
@@ -28,6 +33,7 @@ static INT32 nZOffset;
|
||||
struct ObjFrame {
|
||||
INT32 nShiftX, nShiftY;
|
||||
UINT8* Obj;
|
||||
UINT8* Extra;
|
||||
INT32 nCount;
|
||||
};
|
||||
|
||||
@@ -35,10 +41,12 @@ static INT32 nFrameCount = 0;
|
||||
static struct ObjFrame of[3];
|
||||
|
||||
static UINT8 *blendtable;
|
||||
static UINT32 nBlendCount;
|
||||
|
||||
static void CpsBlendInit()
|
||||
{
|
||||
blendtable = NULL;
|
||||
nBlendCount = 0;
|
||||
|
||||
TCHAR filename[MAX_PATH];
|
||||
|
||||
@@ -46,12 +54,8 @@ static void CpsBlendInit()
|
||||
|
||||
FILE *fa = _tfopen(filename, _T("rt"));
|
||||
|
||||
INT32 is_sfz3mix = strstr("sfz3mix", BurnDrvGetTextA(DRV_NAME)) != NULL;
|
||||
|
||||
if (fa == NULL) {
|
||||
if (is_sfz3mix) {
|
||||
// for sfz3mix, don't use parent's blend table. sfz3mix uses different
|
||||
// sprite indexing
|
||||
if (!bCpsUseParentBlend) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,8 +70,15 @@ static void CpsBlendInit()
|
||||
|
||||
bprintf (PRINT_IMPORTANT, _T("Using sprite blending (.bld) table!\n"));
|
||||
|
||||
blendtable = (UINT8*)BurnMalloc(0x40000); // maximum number of sprites
|
||||
memset (blendtable, 0, 0x40000); // no blend
|
||||
// One entry per 16x16 tile; retain the native range for mirrored tile addresses.
|
||||
nBlendCount = (nCpsGfxMask + 1) >> 7;
|
||||
if (nBlendCount < 0x40000) nBlendCount = 0x40000;
|
||||
blendtable = (UINT8*)BurnMalloc(nBlendCount);
|
||||
if (blendtable == NULL) {
|
||||
fclose(fa);
|
||||
return;
|
||||
}
|
||||
memset(blendtable, 0, nBlendCount);
|
||||
|
||||
char szLine[64];
|
||||
|
||||
@@ -97,7 +108,7 @@ static void CpsBlendInit()
|
||||
}
|
||||
|
||||
for (k = min; k <= max; k++) {
|
||||
if (k < 0x40000)
|
||||
if (k < nBlendCount)
|
||||
blendtable[k] = table[type&3];
|
||||
}
|
||||
}
|
||||
@@ -118,19 +129,17 @@ INT32 CpsObjInit()
|
||||
nFrameCount = 2; // CPS2 sprites lagged by 1 frame and double buffered
|
||||
// CPS1 sprites lagged by 1 frame
|
||||
|
||||
ObjMem = (UINT8*)BurnMalloc((nMax << 3) * nFrameCount);
|
||||
nObjMemLen = ((nMax << 3) + nCpsObjExtraLen) * nFrameCount;
|
||||
ObjMem = (UINT8*)BurnMalloc(nObjMemLen);
|
||||
if (ObjMem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// xmvsf3v3: every buffer its states hold starts the same way
|
||||
if (CpsXmvSixEnabled) memset(ObjMem, 0, (nMax << 3) * nFrameCount);
|
||||
|
||||
// Set up the frame buffers
|
||||
for (INT32 i = 0; i < nFrameCount; i++) {
|
||||
of[i].Obj = ObjMem + (nMax << 3) * i;
|
||||
of[i].Extra = nCpsObjExtraLen ? ObjMem + (nMax << 3) * nFrameCount + nCpsObjExtraLen * i : NULL;
|
||||
of[i].nCount = 0;
|
||||
if (CpsXmvSixEnabled) of[i].nShiftX = of[i].nShiftY = 0;
|
||||
}
|
||||
|
||||
nGetNext=0;
|
||||
@@ -146,11 +155,18 @@ INT32 CpsObjInit()
|
||||
|
||||
INT32 CpsObjExit()
|
||||
{
|
||||
Cps2ObjGetCallbackFunction = NULL;
|
||||
Cps2ObjTileCallbackFunction = NULL;
|
||||
Cps2ObjPaletteCallbackFunction = NULL;
|
||||
bCpsUseParentBlend = 1;
|
||||
nCpsObjExtraLen = 0;
|
||||
|
||||
if (blendtable)
|
||||
BurnFree(blendtable);
|
||||
|
||||
for (INT32 i = 0; i < nFrameCount; i++) {
|
||||
of[i].Obj = NULL;
|
||||
of[i].Extra = NULL;
|
||||
of[i].nCount = 0;
|
||||
}
|
||||
|
||||
@@ -167,6 +183,17 @@ INT32 CpsObjExit()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CpsObjReset()
|
||||
{
|
||||
if (ObjMem == NULL) return;
|
||||
memset(ObjMem, 0, nObjMemLen);
|
||||
for (INT32 i = 0; i < nFrameCount; i++) {
|
||||
of[i].nCount = 0;
|
||||
of[i].nShiftX = of[i].nShiftY = 0;
|
||||
}
|
||||
nGetNext = 0;
|
||||
}
|
||||
|
||||
// Get CPS sprites into Obj
|
||||
INT32 CpsObjGet()
|
||||
{
|
||||
@@ -236,6 +263,7 @@ INT32 CpsObjGet()
|
||||
|
||||
// Okay - this sprite is active:
|
||||
memcpy(po, pg, 8); // copy it over
|
||||
if (Cps2ObjGetCallbackFunction) Cps2ObjGetCallbackFunction(pof->Extra, pof->nCount, i);
|
||||
|
||||
pof->nCount++;
|
||||
po += 8;
|
||||
@@ -431,30 +459,17 @@ INT32 Cps2ObjDraw(INT32 nLevelFrom, INT32 nLevelTo)
|
||||
// y -= CpsSaveFrg[0][0xB];
|
||||
|
||||
#endif
|
||||
if (Cps2Turbo) {
|
||||
if (BURN_ENDIAN_SWAP_INT16(ps[1]) & 0x1000) ps[1] |= BURN_ENDIAN_SWAP_INT16(0x8000);
|
||||
n |= (BURN_ENDIAN_SWAP_INT16(ps[1]) & 0xe000) << 3; // high bits of address
|
||||
} else {
|
||||
n |= (BURN_ENDIAN_SWAP_INT16(ps[1]) & 0x6000) << 3; // high bits of address
|
||||
}
|
||||
|
||||
n |= (BURN_ENDIAN_SWAP_INT16(ps[1]) & 0x6000) << 3;
|
||||
|
||||
// Find the palette for the tiles on this sprite
|
||||
CpstPal = CpsPal + ((a & 0x1F) << 4);
|
||||
|
||||
// xmvsf3v3: the HUD's mini portraits in each fighter's colour, decoded from the program ROM
|
||||
UINT32* pStockPal = CpstPal;
|
||||
UINT32 nPortraitPal[16];
|
||||
UINT32 nPortraitColor = 0;
|
||||
if (CpsXmvSixEnabled && XmvPortraitObject(n, BURN_ENDIAN_SWAP_INT16(ps[0]), BURN_ENDIAN_SWAP_INT16(ps[1]), a, CpsXmvWide != 0, &nPortraitColor)) {
|
||||
UINT16 nColors[16];
|
||||
if (!XmvPortraitColors(CpsRom, nCpsRomLen, n, nPortraitColor, nColors)) {
|
||||
continue; // the marker isn't a palette, so don't draw it with one
|
||||
}
|
||||
for (INT32 pen = 0; pen < 16; pen++) {
|
||||
UINT32 c = nColors[pen];
|
||||
nPortraitPal[pen] = BurnHighCol(((c >> 8) & 15) * 17, ((c >> 4) & 15) * 17, (c & 15) * 17, 0);
|
||||
}
|
||||
CpstPal = nPortraitPal;
|
||||
UINT32 nObjectPal[16];
|
||||
if (Cps2ObjPaletteCallbackFunction) {
|
||||
INT32 nResult = Cps2ObjPaletteCallbackFunction(n, BURN_ENDIAN_SWAP_INT16(ps[0]), BURN_ENDIAN_SWAP_INT16(ps[1]), a, nObjectPal);
|
||||
if (nResult < 0) continue;
|
||||
if (nResult) CpstPal = nObjectPal;
|
||||
}
|
||||
|
||||
nFlip = (a >> 5) & 3;
|
||||
@@ -494,7 +509,11 @@ INT32 Cps2ObjDraw(INT32 nLevelFrom, INT32 nLevelTo)
|
||||
nCpstY = y + (ey << 4);
|
||||
|
||||
// nCpstTile = n + (dy << 4) + dx; // normal version
|
||||
nCpstTile = (n & ~0x0F) + (dy << 4) + ((n + dx) & 0x0F); // pgear fix
|
||||
nCpstTile = (n & ~0x0F) + (dy << 4) + ((n + dx) & 0x0F); // pgear fix
|
||||
if (Cps2ObjTileCallbackFunction) {
|
||||
INT32 nEntry = ((UINT8*)ps - pof->Obj) >> 3;
|
||||
nCpstTile = Cps2ObjTileCallbackFunction(ps, nCpstTile, pof->Extra, nEntry);
|
||||
}
|
||||
|
||||
if (Sfa2ObjHack) {
|
||||
// hack to not render blue squares on high score screen after name entry - they should be hidden by priority from what I can see
|
||||
@@ -503,7 +522,7 @@ INT32 Cps2ObjDraw(INT32 nLevelFrom, INT32 nLevelTo)
|
||||
//if (ps[2] == 0xa410) bprintf(PRINT_NORMAL, _T("%x, %x, %x, %x, %x, %x, %x\n"), nCpstTile, a & 0x1f, nCpstX, nCpstY, v, nLevelFrom, nLevelTo);
|
||||
}
|
||||
|
||||
nCpsBlend = (blendtable) ? blendtable[nCpstTile] : 0;
|
||||
nCpsBlend = (blendtable && nCpstTile < nBlendCount) ? blendtable[nCpstTile] : 0;
|
||||
nCpstTile <<= 7; // Find real tile address
|
||||
|
||||
pCpstOne();
|
||||
@@ -511,7 +530,7 @@ INT32 Cps2ObjDraw(INT32 nLevelFrom, INT32 nLevelTo)
|
||||
}
|
||||
}
|
||||
|
||||
CpstPal = pStockPal; // never leave it pointing at nPortraitPal
|
||||
CpstPal = pStockPal; // never leave it pointing at nObjectPal
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -907,19 +926,18 @@ INT32 FcrashObjDraw(INT32 nLevelFrom,INT32 nLevelTo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// xmvsf3v3: the sprite lag buffers (the Obj pointers are rebuilt by CpsObjInit, never saved).
|
||||
// The Z buffer and its counters aren't saved: only drawing changes them, so they'd make a state
|
||||
// depend on which frames were drawn (netplay replays and run-ahead's hidden frames aren't), and
|
||||
// each frame's Z values start above what's already in the buffer
|
||||
INT32 CpsObjVisualScan(INT32 nAction)
|
||||
// Save the sprite lag buffers, but rebuild their pointers on initialization.
|
||||
// The Z buffer and counters are drawing scratch: saving them would make states
|
||||
// depend on which frames were drawn. Each frame starts above the old Z values.
|
||||
INT32 CpsObjScan(INT32 nAction, char* szName)
|
||||
{
|
||||
if (!CpsXmvSixEnabled || !(nAction & ACB_DRIVER_DATA)) return 0;
|
||||
if (!(nAction & ACB_DRIVER_DATA)) return 0;
|
||||
|
||||
struct BurnArea ba;
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = ObjMem;
|
||||
ba.nLen = (nMax << 3) * nFrameCount;
|
||||
ba.szName = "XMvsSF 3v3 sprite lag buffers";
|
||||
ba.nLen = nObjMemLen;
|
||||
ba.szName = szName;
|
||||
BurnAcb(&ba);
|
||||
|
||||
SCAN_VAR(nGetNext);
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
// CPS (palette)
|
||||
|
||||
static bool CpsXmvPaletteRestored = false; // xmvsf3v3: CpsPalVisualScan() restored CpsPal
|
||||
static UINT8* CpsPalSrc = NULL; // Copy of current input palette
|
||||
CpsPalUpdateCallback CpsPalUpdateCallbackFunction = NULL;
|
||||
UINT32* CpsPal = NULL; // Hicolor version of palette
|
||||
INT32 nCpsPalCtrlReg;
|
||||
INT32 bCpsUpdatePalEveryFrame = 0; // Some of the hacks need this as they don't write to CpsReg 0x0a
|
||||
@@ -25,8 +25,6 @@ INT32 CpsPalInit()
|
||||
if (CpsPal == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if (CpsXmvSixEnabled) memset(CpsPal, 0, nLen);
|
||||
CpsXmvPaletteRestored = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -35,10 +33,21 @@ INT32 CpsPalExit()
|
||||
{
|
||||
BurnFree(CpsPal);
|
||||
BurnFree(CpsPalSrc);
|
||||
CpsPalUpdateCallbackFunction = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Update CpsPal with the new palette at pNewPal (length 0xc00 bytes)
|
||||
static inline UINT32 CpsPalColor(UINT16 nRaw)
|
||||
{
|
||||
INT32 Palette = BURN_ENDIAN_SWAP_INT16(nRaw);
|
||||
INT32 Bright = 0x0f + ((Palette >> 12) << 1);
|
||||
INT32 r = ((Palette >> 8) & 0x0f) * 0x11 * Bright / 0x2d;
|
||||
INT32 g = ((Palette >> 4) & 0x0f) * 0x11 * Bright / 0x2d;
|
||||
INT32 b = ((Palette >> 0) & 0x0f) * 0x11 * Bright / 0x2d;
|
||||
return BurnHighCol(r, g, b, 0);
|
||||
}
|
||||
|
||||
// Update CpsPal with the new palette at pNewPal (length 0xc00 words)
|
||||
INT32 CpsPalUpdate(UINT8* pNewPal)
|
||||
{
|
||||
UINT16 *ps, *pn;
|
||||
@@ -47,23 +56,15 @@ INT32 CpsPalUpdate(UINT8* pNewPal)
|
||||
pn = (UINT16*)pNewPal;
|
||||
|
||||
memcpy(ps, pn, 0xc00 * sizeof(UINT16));
|
||||
|
||||
|
||||
INT32 nCtrl = CpsReg[nCpsPalCtrlReg];
|
||||
UINT16 *PaletteRAM = (UINT16*)CpsPalSrc;
|
||||
|
||||
|
||||
for (INT32 nPage = 0; nPage < 6; nPage++) {
|
||||
if (BIT(nCtrl, nPage)) {
|
||||
if (CpsPalUpdateCallbackFunction) CpsPalUpdateCallbackFunction(nPage, PaletteRAM);
|
||||
for (INT32 Offset = 0; Offset < 0x200; ++Offset) {
|
||||
INT32 Palette = BURN_ENDIAN_SWAP_INT16(*(PaletteRAM++));
|
||||
INT32 r, g, b, Bright;
|
||||
|
||||
Bright = 0x0f + ((Palette >> 12) << 1);
|
||||
|
||||
r = ((Palette >> 8) & 0x0f) * 0x11 * Bright / 0x2d;
|
||||
g = ((Palette >> 4) & 0x0f) * 0x11 * Bright / 0x2d;
|
||||
b = ((Palette >> 0) & 0x0f) * 0x11 * Bright / 0x2d;
|
||||
|
||||
CpsPal[(0x200 * nPage) + (Offset ^ 15)] = BurnHighCol(r, g, b, 0);
|
||||
CpsPal[(0x200 * nPage) + (Offset ^ 15)] = CpsPalColor(*PaletteRAM++);
|
||||
}
|
||||
} else {
|
||||
if (PaletteRAM != (UINT16*)CpsPalSrc) {
|
||||
@@ -75,28 +76,7 @@ INT32 CpsPalUpdate(UINT8* pNewPal)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// xmvsf3v3: the effective colours: a palette DMA converts only the pages enabled at the time, and
|
||||
// palette RAM may already hold the next DMA's colours, so rereading it after a load can't rebuild
|
||||
// them; the pixel format must not change in between. CpsPalSrc isn't saved: CpsPalUpdate()
|
||||
// overwrites it before reading it
|
||||
INT32 CpsPalVisualScan(INT32 nAction)
|
||||
void CpsPalRecalc(const UINT16* pRaw)
|
||||
{
|
||||
if (!CpsXmvSixEnabled || !(nAction & ACB_DRIVER_DATA)) return 0;
|
||||
|
||||
struct BurnArea ba;
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = CpsPal; ba.nLen = 0xc00 * sizeof(UINT32); ba.szName = "XMvsSF 3v3 effective palette"; BurnAcb(&ba);
|
||||
|
||||
if (nAction & ACB_WRITE) CpsXmvPaletteRestored = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsPalConsumeRestoredCache()
|
||||
{
|
||||
if (!CpsXmvSixEnabled || !CpsXmvPaletteRestored) return 0;
|
||||
|
||||
CpsXmvPaletteRestored = false;
|
||||
|
||||
return 1;
|
||||
for (INT32 i = 0; i < 0xc00; i++) CpsPal[i ^ 15] = CpsPalColor(pRaw[i]);
|
||||
}
|
||||
@@ -6,7 +6,6 @@ INT32 Cps2Volume = 39;
|
||||
INT32 Cps2DisableDigitalVolume = 0;
|
||||
UINT8 Cps2VolUp;
|
||||
UINT8 Cps2VolDwn;
|
||||
UINT8 AspectDIP; // only for Cps2Turbo == 1
|
||||
|
||||
UINT16 Cps2VolumeStates[40] = {
|
||||
0xf010, 0xf008, 0xf004, 0xf002, 0xf001, 0xe810, 0xe808, 0xe804, 0xe802, 0xe801,
|
||||
@@ -36,8 +35,6 @@ INT32 Cps1VBlankIRQLine = 2;
|
||||
|
||||
INT32 Cps1DrawAtVblank = 0;
|
||||
|
||||
static UINT8 AspectDIPLast = 0;
|
||||
|
||||
CpsRunInitCallback CpsRunInitCallbackFunction = NULL;
|
||||
CpsRunInitCallback CpsRunExitCallbackFunction = NULL;
|
||||
CpsRunResetCallback CpsRunResetCallbackFunction = NULL;
|
||||
@@ -59,23 +56,6 @@ static void CpsQSoundCheatSearchCallback()
|
||||
}
|
||||
}
|
||||
|
||||
static void check_aspect()
|
||||
{
|
||||
if (Cps2Turbo && (AspectDIP & 0x03) != AspectDIPLast) {
|
||||
INT32 aspects[3][2] = { { 16, 9 }, { 4, 3 }, { 112, 81 } };
|
||||
AspectDIPLast = AspectDIP & 0x03;
|
||||
|
||||
INT32 nAspectX, nAspectY;
|
||||
BurnDrvGetAspect(&nAspectX, &nAspectY);
|
||||
|
||||
if (nAspectX != aspects[AspectDIPLast][0] || nAspectY != aspects[AspectDIPLast][1]) {
|
||||
bprintf(0, _T("* CPS-2: Changing to %d:%d aspect\n"), aspects[AspectDIPLast][0], aspects[AspectDIPLast][1]);
|
||||
BurnDrvSetAspect(aspects[AspectDIPLast][0], aspects[AspectDIPLast][1]);
|
||||
Reinitialise();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvReset()
|
||||
{
|
||||
// Reset machine
|
||||
@@ -115,11 +95,6 @@ static INT32 DrvReset()
|
||||
CpsRunResetCallbackFunction();
|
||||
}
|
||||
|
||||
if (Cps2Turbo) {
|
||||
AspectDIPLast = 0xff;
|
||||
check_aspect();
|
||||
}
|
||||
|
||||
HiscoreReset();
|
||||
|
||||
return 0;
|
||||
@@ -433,10 +408,6 @@ INT32 Cps2Frame()
|
||||
DrvReset();
|
||||
}
|
||||
|
||||
if (Cps2Turbo) {
|
||||
check_aspect();
|
||||
}
|
||||
|
||||
// extern INT32 prevline;
|
||||
// prevline = -1;
|
||||
|
||||
|
||||
+11
-166
@@ -1,7 +1,8 @@
|
||||
#include "cps.h"
|
||||
#include "xmvsf3v3.h"
|
||||
// CPS - Read/Write
|
||||
|
||||
CpsRwGetInpCallback CpsRwGetInpCallbackFunction = NULL;
|
||||
|
||||
// Input bits
|
||||
#define INP(nnn) UINT8 CpsInp##nnn[8];
|
||||
CPSINPSET
|
||||
@@ -48,7 +49,6 @@ INT32 Ssf2tb = 0;
|
||||
INT32 Dinohunt = 0;
|
||||
INT32 Port6SoundWrite = 0;
|
||||
INT32 CpsBootlegEEPROM = 0;
|
||||
INT32 Cps2Turbo = 0;
|
||||
INT32 Jurassic99 = 0;
|
||||
INT32 Dinoh = 0;
|
||||
INT32 Wofhfh = 0;
|
||||
@@ -466,130 +466,8 @@ void CpsWritePort(const UINT32 ia, UINT8 d)
|
||||
// bprintf(PRINT_NORMAL, _T("Write Port %x, %x\n"), ia, d);
|
||||
}
|
||||
|
||||
// X-Men Vs. Street Fighter 3v3 + DHC board additions (see xmvsf3v3.h), enabled by its drivers only
|
||||
UINT8 CpsXmvSixButtons[XMV6_PLAYERS][13];
|
||||
INT32 CpsXmvSixEnabled = 0;
|
||||
INT32 CpsXmvWide = 0;
|
||||
static UINT16 CpsXmvSixCapabilities = 0;
|
||||
static XmvSixInputState CpsXmvSixState;
|
||||
static UINT8 *CpsXmvSixWorkRam = NULL;
|
||||
|
||||
INT32 CpsXmvSixInit(INT32 bWide)
|
||||
{
|
||||
CpsXmvSixWorkRam = (UINT8*)BurnMalloc(XMV6_WORK_RAM_BYTES);
|
||||
if (CpsXmvSixWorkRam == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CpsXmvWide = bWide ? 1 : 0;
|
||||
CpsXmvSixCapabilities = XMV6_CAP_WORK_RAM | XMV6_CAP_PORTRAITS | XMV6_CAP_PORTRAITS_6 | XMV6_CAP_PORTRAITS_12 | XMV6_CAP_PORTRAITS_18;
|
||||
if (bWide) {
|
||||
CpsXmvSixCapabilities |= XMV6_CAP_WIDE | XMV6_CAP_WIDE_SCROLL1;
|
||||
}
|
||||
CpsXmvSixEnabled = 1;
|
||||
|
||||
memset(CpsXmvSixButtons, 0, sizeof(CpsXmvSixButtons));
|
||||
CpsXmvSixReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CpsXmvSixExit()
|
||||
{
|
||||
CpsXmvSixEnabled = 0;
|
||||
CpsXmvWide = 0;
|
||||
BurnFree(CpsXmvSixWorkRam);
|
||||
}
|
||||
|
||||
INT32 CpsXmvSixReset()
|
||||
{
|
||||
if (!CpsXmvSixEnabled) return 0;
|
||||
|
||||
XmvSixReset(&CpsXmvSixState);
|
||||
memset(CpsXmvSixWorkRam, 0, XMV6_WORK_RAM_BYTES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsXmvSixScan(INT32 nAction, INT32* /*pnMin*/)
|
||||
{
|
||||
if (!CpsXmvSixEnabled) return 0;
|
||||
|
||||
if (nAction & ACB_MEMORY_RAM) {
|
||||
struct BurnArea ba;
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = CpsXmvSixWorkRam;
|
||||
ba.nLen = XMV6_WORK_RAM_BYTES;
|
||||
ba.nAddress = XMV6_WORK_RAM_BASE;
|
||||
ba.szName = "XMvsSF 3v3 work RAM";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
SCAN_VAR(CpsXmvSixState);
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
if (CpsXmvSixState.abi != XMV6_VERSION || CpsXmvSixState.count > XMV6_DEPTH) {
|
||||
// not a state of this board
|
||||
CpsXmvSixReset();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CpsXmvVisualScan(nAction);
|
||||
}
|
||||
|
||||
// Wide screen: while the ROM keeps 'XS1X' at 0x813ff8, scroll1 columns 64-127 come from 0x814000
|
||||
const UINT8* CpsXmvScroll1Extension()
|
||||
{
|
||||
if (!CpsXmvSixEnabled || !CpsXmvWide) return NULL;
|
||||
|
||||
const UINT8* tag = CpsXmvSixWorkRam + 0x3ff8;
|
||||
if (tag[0] != 'X' || tag[1] != 'S' || tag[2] != '1' || tag[3] != 'X') return NULL;
|
||||
|
||||
return CpsXmvSixWorkRam + 0x4000;
|
||||
}
|
||||
|
||||
// Once a frame, before the input ports are compiled
|
||||
static void CpsXmvSixSample()
|
||||
{
|
||||
UINT16 raw[XMV6_PLAYERS];
|
||||
for (INT32 p = 0; p < XMV6_PLAYERS; p++) {
|
||||
raw[p] = 0;
|
||||
for (INT32 bit = 0; bit < 13; bit++) {
|
||||
raw[p] |= (CpsXmvSixButtons[p][bit] & 1) << bit;
|
||||
}
|
||||
}
|
||||
XmvSixSample(&CpsXmvSixState, raw);
|
||||
|
||||
// P1 and P2 also reach the stock input ports, for the game's own menus
|
||||
for (INT32 bit = 0; bit < 7; bit++) {
|
||||
CpsInp001[bit] = (CpsXmvSixState.held[0] >> bit) & 1;
|
||||
CpsInp000[bit] = (CpsXmvSixState.held[1] >> bit) & 1;
|
||||
}
|
||||
for (INT32 p = 0; p < 2; p++) {
|
||||
UINT16 value = CpsXmvSixState.held[p];
|
||||
CpsInp011[p * 4 + 0] = (value >> 8) & 1; // weak kick
|
||||
CpsInp011[p * 4 + 1] = (value >> 9) & 1; // medium kick
|
||||
CpsInp020[p + 0] = (value >> 11) & 1; // start
|
||||
CpsInp020[p + 4] = (value >> 12) & 1; // coin
|
||||
}
|
||||
CpsInp011[2] = (CpsXmvSixState.held[0] >> 10) & 1; // P1 strong kick
|
||||
CpsInp020[6] = (CpsXmvSixState.held[1] >> 10) & 1; // P2 strong kick
|
||||
}
|
||||
|
||||
UINT8 __fastcall CpsReadByte(UINT32 a)
|
||||
{
|
||||
if (CpsXmvSixEnabled) {
|
||||
if (a >= XMV6_BASE && a < XMV6_BASE + XMV6_WINDOW_BYTES) {
|
||||
return XmvSixReadByte(&CpsXmvSixState, CpsXmvSixCapabilities, a - XMV6_BASE);
|
||||
}
|
||||
if (a >= XMV6_WORK_RAM_BASE && a < XMV6_WORK_RAM_BASE + XMV6_WORK_RAM_BYTES) {
|
||||
return CpsXmvSixWorkRam[a - XMV6_WORK_RAM_BASE];
|
||||
}
|
||||
}
|
||||
|
||||
// Input ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8000) == 0x800000) {
|
||||
return CpsReadPort(a & 0x1FF);
|
||||
@@ -618,11 +496,6 @@ UINT8 __fastcall CpsReadByte(UINT32 a)
|
||||
|
||||
void __fastcall CpsWriteByte(UINT32 a,UINT8 d)
|
||||
{
|
||||
if (CpsXmvSixEnabled && a >= XMV6_WORK_RAM_BASE && a < XMV6_WORK_RAM_BASE + XMV6_WORK_RAM_BYTES) {
|
||||
CpsXmvSixWorkRam[a - XMV6_WORK_RAM_BASE] = d;
|
||||
return;
|
||||
}
|
||||
|
||||
// Output ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8000) == 0x800000) {
|
||||
CpsWritePort(a & 0x1FF, d);
|
||||
@@ -631,20 +504,9 @@ void __fastcall CpsWriteByte(UINT32 a,UINT8 d)
|
||||
|
||||
if (Cps == 2) {
|
||||
// 0x400000 registers
|
||||
if (Cps2Turbo) {
|
||||
if ((a & 0xFFFFF0) == 0x665000) {
|
||||
CpsFrg[a & 0x0F] = d;
|
||||
return;
|
||||
}
|
||||
if ((a & 0xFFFFF0) == 0xfffff0) {
|
||||
CpsFrg[a & 0x0F] = d;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ((a & 0xFFFFF0) == 0x400000) {
|
||||
CpsFrg[a & 0x0F] = d;
|
||||
return;
|
||||
}
|
||||
if ((a & 0xFFFFF0) == 0x400000) {
|
||||
CpsFrg[a & 0x0F] = d;
|
||||
return;
|
||||
}
|
||||
if ((a & 0xFF8000) == 0x660000) {
|
||||
if (a == 0x664001) {
|
||||
@@ -671,15 +533,6 @@ void __fastcall CpsWriteByte(UINT32 a,UINT8 d)
|
||||
|
||||
UINT16 __fastcall CpsReadWord(UINT32 a)
|
||||
{
|
||||
if (CpsXmvSixEnabled) {
|
||||
if (a >= XMV6_BASE && a < XMV6_BASE + XMV6_WINDOW_BYTES) {
|
||||
return XmvSixReadWord(&CpsXmvSixState, CpsXmvSixCapabilities, a - XMV6_BASE);
|
||||
}
|
||||
if (a >= XMV6_WORK_RAM_BASE && a < XMV6_WORK_RAM_BASE + XMV6_WORK_RAM_BYTES) {
|
||||
return XmvSixRamReadWord(CpsXmvSixWorkRam, a - XMV6_WORK_RAM_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[3]) {
|
||||
return (UINT16)((nCalc[0] * nCalc[1]) >> 16);
|
||||
}
|
||||
@@ -695,11 +548,6 @@ UINT16 __fastcall CpsReadWord(UINT32 a)
|
||||
|
||||
void __fastcall CpsWriteWord(UINT32 a, UINT16 d)
|
||||
{
|
||||
if (CpsXmvSixEnabled && a >= XMV6_WORK_RAM_BASE && a < XMV6_WORK_RAM_BASE + XMV6_WORK_RAM_BYTES) {
|
||||
XmvSixRamWriteWord(CpsXmvSixWorkRam, a - XMV6_WORK_RAM_BASE, d);
|
||||
return;
|
||||
}
|
||||
|
||||
// ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[0])
|
||||
nCalc[0] = d;
|
||||
@@ -742,6 +590,7 @@ INT32 CpsRwInit()
|
||||
|
||||
INT32 CpsRwExit()
|
||||
{
|
||||
CpsRwGetInpCallbackFunction = NULL;
|
||||
InpBlank();
|
||||
CpsRWSoundCommandCallbackFunction = NULL;
|
||||
return 0;
|
||||
@@ -749,9 +598,7 @@ INT32 CpsRwExit()
|
||||
|
||||
INT32 CpsRwGetInp()
|
||||
{
|
||||
if (CpsXmvSixEnabled) {
|
||||
CpsXmvSixSample();
|
||||
}
|
||||
INT32 nPortPlayers = CpsRwGetInpCallbackFunction ? CpsRwGetInpCallbackFunction() : nMaxPlayers;
|
||||
|
||||
// Compile separate buttons into Inpxxx
|
||||
#define INP(nnn) \
|
||||
@@ -862,22 +709,20 @@ INT32 CpsRwGetInp()
|
||||
}
|
||||
}
|
||||
|
||||
// xmvsf3v3: players 3-6 never reach the stock ports (Inp011 is P1/P2's kicks there), and
|
||||
// CpsXmvSixSample() has already cleaned every player's opposite directions
|
||||
if (nMaxPlayers > 2 && !CpsXmvSixEnabled) {
|
||||
if (nPortPlayers > 2) {
|
||||
if (Cps == 2) {
|
||||
clear_opposite.check(2, Inp011, 0x08, 0x04, 0x02, 0x01, nSocd[2]);
|
||||
if (nMaxPlayers == 4) {
|
||||
if (nPortPlayers == 4) {
|
||||
clear_opposite.check(3, Inp010, 0x08, 0x04, 0x02, 0x01, nSocd[3]);
|
||||
}
|
||||
} else {
|
||||
clear_opposite.check(2, Inp177, 0x08, 0x04, 0x02, 0x01, nSocd[2]);
|
||||
if (nMaxPlayers == 4) {
|
||||
if (nPortPlayers == 4) {
|
||||
clear_opposite.check(3, Inp179, 0x08, 0x04, 0x02, 0x01, nSocd[3]);
|
||||
}
|
||||
if (Cps1Qs) {
|
||||
clear_opposite.check(2, Inpc001, 0x08, 0x04, 0x02, 0x01, nSocd[2]);
|
||||
if (nMaxPlayers == 4) {
|
||||
if (nPortPlayers == 4) {
|
||||
clear_opposite.check(3, Inpc003, 0x08, 0x04, 0x02, 0x01, nSocd[3]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "cps.h"
|
||||
|
||||
Cps2ScrollCallback Cps2ScrollCallbackFunction = NULL;
|
||||
Cps2Scroll1Callback Cps2Scroll1CallbackFunction = NULL;
|
||||
|
||||
// CPS Scroll (Background Layers)
|
||||
|
||||
// Base = 0x4000 long tile map
|
||||
@@ -82,8 +85,8 @@ INT32 Cps2Scr1Draw(UINT8 *Base, INT32 sx, INT32 sy)
|
||||
INT32 nKnowBlank = -1; // The tile we know is blank
|
||||
INT32 nXTile = nCpsScreenWidth>>3; // 8x8 tiles
|
||||
|
||||
// xmvsf3v3 wide screen: scroll1 columns 64-127 can come from the board's extra work RAM
|
||||
const UINT8* pExt = CpsXmvScroll1Extension();
|
||||
// A board may supply the upper half of the scroll1 tilemap.
|
||||
const UINT8* pExt = Cps2Scroll1CallbackFunction ? Cps2Scroll1CallbackFunction() : NULL;
|
||||
|
||||
ix = (sx >> 3) + 1;
|
||||
sx &= 7;
|
||||
@@ -115,10 +118,10 @@ INT32 Cps2Scr1Draw(UINT8 *Base, INT32 sx, INT32 sy)
|
||||
t = pe ? ((pe[0] << 8) | pe[1]) : BURN_ENDIAN_SWAP_INT16(pst[0]);
|
||||
t <<= 6; // Get real tile address
|
||||
|
||||
t += nCpsGfxScroll[1]; // add on offset to scroll tiles
|
||||
a = pe ? ((pe[2] << 8) | pe[3]) : BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
t = Cps2ScrollAddress(t, a, 1);
|
||||
|
||||
if (t != nKnowBlank) { // Draw tile
|
||||
a = pe ? ((pe[2] << 8) | pe[3]) : BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
|
||||
CpstSetPal(0x20 | (a & 0x1F));
|
||||
|
||||
@@ -242,11 +245,10 @@ INT32 Cps2Scr3Draw(UINT8 *Base, INT32 sx, INT32 sy)
|
||||
if(Xmcota && t>=0x5800) t-=0x4000;
|
||||
else if(Ssf2t && t<0x5600) t+=0x4000;
|
||||
t <<= 9; // Get real tile address
|
||||
if (Cps2Turbo) t &= ~nCpsGfxScroll[3]; // buggy hack
|
||||
t += nCpsGfxScroll[3]; // add on offset to scroll tiles
|
||||
a = BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
t = Cps2ScrollAddress(t, a, 3);
|
||||
|
||||
if (t != nKnowBlank) { // Draw tile
|
||||
a = BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
|
||||
CpstSetPal(0x60 | (a & 0x1F));
|
||||
|
||||
|
||||
@@ -76,9 +76,9 @@ static void Cps2TileLine(INT32 y,INT32 sx)
|
||||
pst=FindTile(ix+x,iy+y);
|
||||
t = BURN_ENDIAN_SWAP_INT16(pst[0]);
|
||||
t<<=7; // Get real tile address
|
||||
t+=nCpsGfxScroll[2]; // add on offset to scroll tiles
|
||||
a = BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
t = Cps2ScrollAddress(t, a, 2);
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
a = BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
|
||||
CpstSetPal(0x40 | (a&0x1f));
|
||||
nCpstX=sx+(x<<4); nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
@@ -185,10 +185,10 @@ static void Cps2TileLineRows(INT32 y,struct CpsrLineInfo *pli)
|
||||
pst=FindTile(tx,iy+y);
|
||||
t = BURN_ENDIAN_SWAP_INT16(pst[0]);
|
||||
t<<=7; // Get real tile address
|
||||
t+=nCpsGfxScroll[2]; // add on offset to scroll tiles
|
||||
a = BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
t = Cps2ScrollAddress(t, a, 2);
|
||||
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
a = BURN_ENDIAN_SWAP_INT16(pst[1]);
|
||||
|
||||
CpstSetPal(0x40 | (a&0x1f));
|
||||
|
||||
|
||||
@@ -7348,6 +7348,62 @@ static struct BurnRomInfo DynwarjrRomDesc[] = {
|
||||
STD_ROM_PICK(Dynwarjr)
|
||||
STD_ROM_FN(Dynwarjr)
|
||||
|
||||
// https://arcadepatches.com/projects/final-fight-ex/ (RC4)
|
||||
static struct BurnRomInfo Ffightus01RomDesc[] = {
|
||||
{ "c07.p1", 0x020000, 0x1bbe6639, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07.p2", 0x020000, 0x9a9fe4f3, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07.p3", 0x020000, 0xd3c9e580, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07u.p4", 0x020000, 0x55a29283, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07.p5", 0x080000, 0x1c9b1b36, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP },
|
||||
{ "c07us01.p7", 0x100000, 0xe6e4df5f, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP },
|
||||
{ "c07.c01", 0x080000, 0x7b4aad16, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.c03", 0x080000, 0x28192faf, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.c05", 0x080000, 0xdeff8c10, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.c07", 0x080000, 0x4b532b36, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c09", 0x080000, 0x3365bae7, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c11", 0x080000, 0x9f53c8e0, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c13", 0x080000, 0xcf35f998, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c15", 0x080000, 0xd65f25ed, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c17", 0x080000, 0xc9dbe31e, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c19", 0x080000, 0x30c802e6, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c21", 0x080000, 0x936c49c4, BRF_GRA | CPS1_TILES },
|
||||
{ "c07us01.c23", 0x080000, 0xce2427a3, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.m1", 0x010000, 0x87eca9ec, BRF_PRG | CPS1_Z80_PROGRAM },
|
||||
{ "c07.v1", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES },
|
||||
{ "c07.v2", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Ffightus01)
|
||||
STD_ROM_FN(Ffightus01)
|
||||
|
||||
// https://arcadepatches.com/projects/final-fight-ex/ (RC4)
|
||||
static struct BurnRomInfo Ffightjs01RomDesc[] = {
|
||||
{ "c07.p1", 0x020000, 0x4dcd780e, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07.p2", 0x020000, 0xfd0623ca, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07.p3", 0x020000, 0x4d30793c, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07j.p4", 0x020000, 0xdabe8850, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "c07.p5", 0x080000, 0xf9e7b052, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP },
|
||||
{ "c07js01.p7", 0x100000, 0x8bdfd316, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_NO_BYTESWAP },
|
||||
{ "c07.c01", 0x080000, 0x976bcfbb, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.c03", 0x080000, 0xcfeb60c6, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.c05", 0x080000, 0x32deeebd, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.c07", 0x080000, 0xaca1645f, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c09", 0x080000, 0x923bfeba, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c11", 0x080000, 0x2699067e, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c13", 0x080000, 0xed5833cb, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c15", 0x080000, 0xbed965c8, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c17", 0x080000, 0x7d0a63fa, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c19", 0x080000, 0xb61bca08, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c21", 0x080000, 0x8e33931b, BRF_GRA | CPS1_TILES },
|
||||
{ "c07js01.c23", 0x080000, 0xd60af261, BRF_GRA | CPS1_TILES },
|
||||
{ "c07.m1", 0x010000, 0x57a4cf41, BRF_PRG | CPS1_Z80_PROGRAM },
|
||||
{ "c07.v1", 0x020000, 0x375c66e7, BRF_SND | CPS1_OKIM6295_SAMPLES },
|
||||
{ "c07.v2", 0x020000, 0x1ef137f9, BRF_SND | CPS1_OKIM6295_SAMPLES },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Ffightjs01)
|
||||
STD_ROM_FN(Ffightjs01)
|
||||
|
||||
static struct BurnRomInfo FfightRomDesc[] = {
|
||||
{ "ff_36.11f", 0x020000, 0xf9a5ce83, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "ff_42.11h", 0x020000, 0x65f11215, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
@@ -16387,6 +16443,57 @@ static struct BurnRomInfo StriderfixRomDesc[] = {
|
||||
STD_ROM_PICK(Striderfix)
|
||||
STD_ROM_FN(Striderfix)
|
||||
|
||||
static struct BurnRomInfo Striderus01RomDesc[] = {
|
||||
{ "c03us01.p1", 0x020000, 0x457395b9, CPS1_68K_PROGRAM_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.p2", 0x020000, 0x118f8690, CPS1_68K_PROGRAM_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.p3", 0x020000, 0x3306fd0f, CPS1_68K_PROGRAM_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.p4", 0x020000, 0x1ac8cad9, CPS1_68K_PROGRAM_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.p5", 0x080000, 0x06edfbaf, CPS1_68K_PROGRAM_NO_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.p6", 0x100000, 0x075dfc39, CPS1_68K_PROGRAM_NO_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.c01", 0x080000, 0xf92cc010, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c03", 0x080000, 0x9abd7b1e, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c05", 0x080000, 0x085ec243, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c07", 0x080000, 0x2443df27, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c17", 0x080000, 0x005f000b, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c19", 0x080000, 0xb9441519, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c21", 0x080000, 0xb7d04e8b, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c23", 0x080000, 0x6b4713b4, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c25", 0x100000, 0xe8507e5b, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c27", 0x100000, 0x1120f48d, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c29", 0x100000, 0xf7a36cd4, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.c31", 0x100000, 0xb0ef929a, CPS1_TILES | BRF_GRA },
|
||||
{ "c03us01.m1", 0x010000, 0xa08e24b9, CPS1_Z80_PROGRAM | BRF_ESS | BRF_PRG },
|
||||
{ "c03us01.v1", 0x020000, 0x897269dd, CPS1_OKIM6295_SAMPLES | BRF_SND },
|
||||
{ "c03us01.v2", 0x020000, 0x3f56c8cc, CPS1_OKIM6295_SAMPLES | BRF_SND },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Striderus01)
|
||||
STD_ROM_FN(Striderus01)
|
||||
|
||||
static struct BurnRomInfo Striderjs01RomDesc[] = {
|
||||
{ "c03js01.p1", 0x080000, 0x39260f46, CPS1_68K_PROGRAM_NO_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03js01.p5", 0x080000, 0xabc6d8ff, CPS1_68K_PROGRAM_NO_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03js01.p6", 0x100000, 0x150e1549, CPS1_68K_PROGRAM_NO_BYTESWAP | BRF_ESS | BRF_PRG },
|
||||
{ "c03js01.c01", 0x080000, 0xf92cc010, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c03", 0x080000, 0x9abd7b1e, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c05", 0x080000, 0x085ec243, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c07", 0x080000, 0x2443df27, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c17", 0x080000, 0x005f000b, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c19", 0x080000, 0xb9441519, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c21", 0x080000, 0xb7d04e8b, CPS1_TILES | BRF_GRA },
|
||||
{ "c03.c23", 0x080000, 0x6b4713b4, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c25", 0x100000, 0xe8507e5b, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c27", 0x100000, 0x1120f48d, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c29", 0x100000, 0xf7a36cd4, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.c31", 0x100000, 0xb0ef929a, CPS1_TILES | BRF_GRA },
|
||||
{ "c03js01.m1", 0x010000, 0xa08e24b9, CPS1_Z80_PROGRAM | BRF_ESS | BRF_PRG },
|
||||
{ "c03js01.v1", 0x020000, 0x897269dd, CPS1_OKIM6295_SAMPLES | BRF_SND },
|
||||
{ "c03js01.v2", 0x020000, 0x3f56c8cc, CPS1_OKIM6295_SAMPLES | BRF_SND },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Striderjs01)
|
||||
STD_ROM_FN(Striderjs01)
|
||||
|
||||
static struct BurnRomInfo UnsquadRomDesc[] = {
|
||||
{ "aru_30.11f", 0x020000, 0x24d8f88d, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
{ "aru_35.11h", 0x020000, 0x8b954b59, BRF_ESS | BRF_PRG | CPS1_68K_PROGRAM_BYTESWAP },
|
||||
@@ -17647,6 +17754,8 @@ static const struct GameConfig ConfigTable[] =
|
||||
{ "ffightae" , CPS_B_21_DEF, mapper_S224B , 0, NULL },
|
||||
{ "ffightaemgc" , CPS_B_21_DEF, mapper_S224B , 0, NULL },
|
||||
{ "ffighta" , CPS_B_04 , mapper_S224B , 0, NULL },
|
||||
{ "ffightus01" , CPS_B_04 , mapper_FFIGHTEX, 0, NULL },
|
||||
{ "ffightjs01" , CPS_B_04 , mapper_FFIGHTEX, 0, NULL },
|
||||
{ "ffightu" , CPS_B_04 , mapper_S224B , 0, NULL },
|
||||
{ "ffightu1" , CPS_B_04 , mapper_S224B , 0, NULL },
|
||||
{ "ffightu2" , CPS_B_04 , mapper_S224B , 0, NULL },
|
||||
@@ -17908,6 +18017,8 @@ static const struct GameConfig ConfigTable[] =
|
||||
{ "slampic" , CPS_B_21_QS4, mapper_MB63B , 0, slammast_patch },
|
||||
{ "slampic2" , CPS_B_21_QS4, mapper_MB63B , 0, NULL },
|
||||
{ "strider" , CPS_B_01 , mapper_ST24M1, 1, NULL },
|
||||
{ "striderus01" , CPS_B_01 , mapper_STRIDEREX, 1, NULL },
|
||||
{ "striderjs01" , CPS_B_21_DEF, mapper_STRIDEREX, 1, NULL },
|
||||
{ "striderua" , CPS_B_01 , mapper_ST24M1, 1, NULL },
|
||||
{ "strideruc" , CPS_B_17 , mapper_ST24M1, 1, NULL },
|
||||
{ "striderjr" , CPS_B_21_DEF, mapper_ST24M1, 1, NULL },
|
||||
@@ -22087,6 +22198,29 @@ static INT32 StriderjrInit()
|
||||
return nRet;
|
||||
}
|
||||
|
||||
// EX adds a program ROM before the graphics; derive the star ROM index
|
||||
// from the loaded program inventory rather than the stock parent's index.
|
||||
static INT32 StriderusexInit()
|
||||
{
|
||||
INT32 nRet = Cps1RasterInit();
|
||||
if (!nRet) {
|
||||
CpsStar = CpsGfx + nCpsGfxLen - 0x2000;
|
||||
CpsLoadStars(CpsStar, nCps68KByteswapRomNum + nCps68KNoByteswapRomNum);
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static INT32 StriderjexInit()
|
||||
{
|
||||
INT32 nRet = TwelveMhzInit();
|
||||
if (!nRet) {
|
||||
CpsStar = CpsGfx + nCpsGfxLen - 0x2000;
|
||||
CpsLoadStars(CpsStar, nCps68KByteswapRomNum + nCps68KNoByteswapRomNum);
|
||||
Cps1DrawAtVblank = 1;
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static INT32 StriderjInit()
|
||||
{
|
||||
INT32 nRet = 0;
|
||||
@@ -23716,6 +23850,26 @@ struct BurnDriver BurnDrvCpsDynwarjr = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsFfightus01 = {
|
||||
"ffightus01", "ffight", NULL, NULL, "2026",
|
||||
"Final Fight EX (USA, Backport RC4)\0", NULL, "Strygo", "CPS1",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0,
|
||||
NULL, Ffightus01RomInfo, Ffightus01RomName, NULL, NULL, NULL, NULL, FfightInputInfo, FfightDIPInfo,
|
||||
DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsFfightjs01 = {
|
||||
"ffightjs01", "ffight", NULL, NULL, "2026",
|
||||
"Final Fight EX (Japan, Backport RC4)\0", NULL, "Strygo", "CPS1",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_SCRFIGHT, 0,
|
||||
NULL, Ffightjs01RomInfo, Ffightjs01RomName, NULL, NULL, NULL, NULL, FfightInputInfo, FfightDIPInfo,
|
||||
DrvInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsFfight = {
|
||||
"ffight", NULL, NULL, NULL, "1989",
|
||||
"Final Fight (World, set 1)\0", NULL, "Capcom", "CPS1",
|
||||
@@ -26336,6 +26490,26 @@ struct BurnDriver BurnDrvCpsStriderjr = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsStriderus01 = {
|
||||
"striderus01", "strider", NULL, NULL, "2026",
|
||||
"Strider EX (USA, Backport RC1)\0", NULL, "Strygo", "CPS1",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM | GBF_SCRFIGHT, 0,
|
||||
NULL, Striderus01RomInfo, Striderus01RomName, NULL, NULL, NULL, NULL, StriderInputInfo, StrideruaDIPInfo,
|
||||
StriderusexInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsStriderjs01 = {
|
||||
"striderjs01", "strider", NULL, NULL, "2026",
|
||||
"Strider Hiryu EX (Japan, Backport RC1)\0", NULL, "Strygo", "CPS1",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS1, GBF_PLATFORM | GBF_SCRFIGHT, 0,
|
||||
NULL, Striderjs01RomInfo, Striderjs01RomName, NULL, NULL, NULL, NULL, StriderInputInfo, StriderDIPInfo,
|
||||
StriderjexInit, DrvExit, Cps1Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsStriderj = {
|
||||
"striderj", "strider", NULL, NULL, "1989",
|
||||
"Strider Hiryu (Japan)\0", NULL, "Capcom", "CPS1",
|
||||
|
||||
+191
-642
@@ -40,57 +40,6 @@ static struct BurnInputInfo Cps2FightingInputList[] = {
|
||||
|
||||
STDINPUTINFO(Cps2Fighting)
|
||||
|
||||
static struct BurnInputInfo Sfz3mixInputList[] = {
|
||||
{"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" },
|
||||
{"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" },
|
||||
{"P1 Up" , BIT_DIGITAL , CpsInp001+3, "p1 up" },
|
||||
{"P1 Down" , BIT_DIGITAL , CpsInp001+2, "p1 down" },
|
||||
{"P1 Left" , BIT_DIGITAL , CpsInp001+1, "p1 left" },
|
||||
{"P1 Right" , BIT_DIGITAL , CpsInp001+0, "p1 right" },
|
||||
{"P1 Weak Punch" , BIT_DIGITAL , CpsInp001+4, "p1 fire 1" },
|
||||
{"P1 Medium Punch" , BIT_DIGITAL , CpsInp001+5, "p1 fire 2" },
|
||||
{"P1 Strong Punch" , BIT_DIGITAL , CpsInp001+6, "p1 fire 3" },
|
||||
{"P1 Weak Kick" , BIT_DIGITAL , CpsInp011+0, "p1 fire 4" },
|
||||
{"P1 Medium Kick" , BIT_DIGITAL , CpsInp011+1, "p1 fire 5" },
|
||||
{"P1 Strong Kick" , BIT_DIGITAL , CpsInp011+2, "p1 fire 6" },
|
||||
|
||||
{"P2 Coin" , BIT_DIGITAL , CpsInp020+5, "p2 coin" },
|
||||
{"P2 Start" , BIT_DIGITAL , CpsInp020+1, "p2 start" },
|
||||
{"P2 Up" , BIT_DIGITAL , CpsInp000+3, "p2 up" },
|
||||
{"P2 Down" , BIT_DIGITAL , CpsInp000+2, "p2 down" },
|
||||
{"P2 Left" , BIT_DIGITAL , CpsInp000+1, "p2 left" },
|
||||
{"P2 Right" , BIT_DIGITAL , CpsInp000+0, "p2 right" },
|
||||
{"P2 Weak Punch" , BIT_DIGITAL , CpsInp000+4, "p2 fire 1" },
|
||||
{"P2 Medium Punch" , BIT_DIGITAL , CpsInp000+5, "p2 fire 2" },
|
||||
{"P2 Strong Punch" , BIT_DIGITAL , CpsInp000+6, "p2 fire 3" },
|
||||
{"P2 Weak Kick" , BIT_DIGITAL , CpsInp011+4, "p2 fire 4" },
|
||||
{"P2 Medium Kick" , BIT_DIGITAL , CpsInp011+5, "p2 fire 5" },
|
||||
{"P2 Strong Kick" , BIT_DIGITAL , CpsInp020+6, "p2 fire 6" },
|
||||
|
||||
{"Reset" , BIT_DIGITAL , &CpsReset , "reset" },
|
||||
{"Diagnostic" , BIT_DIGITAL , CpsInp021+1, "diag" },
|
||||
{"Service" , BIT_DIGITAL , CpsInp021+2, "service" },
|
||||
{"Volume Up" , BIT_DIGITAL , &Cps2VolUp , "volumeup" },
|
||||
{"Volume Down" , BIT_DIGITAL , &Cps2VolDwn, "volumedown"},
|
||||
{"Dip A" , BIT_DIPSWITCH, &AspectDIP , "dip" },
|
||||
};
|
||||
|
||||
STDINPUTINFO(Sfz3mix)
|
||||
|
||||
// sfz3mix 0.20+ only!
|
||||
static struct BurnDIPInfo Sfz3mixDIPList[] =
|
||||
{
|
||||
DIP_OFFSET(0x1d)
|
||||
{0x00, 0xff, 0xff, 0x00, NULL },
|
||||
|
||||
{0 , 0xfe, 0 , 3, "Aspect Ratio" },
|
||||
{0x00, 0x01, 0x03, 0x00, "16:9" },
|
||||
{0x00, 0x01, 0x03, 0x01, "4:3" },
|
||||
{0x00, 0x01, 0x03, 0x02, "112:81" },
|
||||
};
|
||||
|
||||
STDDIPINFO(Sfz3mix)
|
||||
|
||||
static struct BurnInputInfo NineXXInputList[] = {
|
||||
{"P1 Coin" , BIT_DIGITAL , CpsInp020+4, "p1 coin" },
|
||||
{"P1 Start" , BIT_DIGITAL , CpsInp020+0, "p1 start" },
|
||||
@@ -9997,7 +9946,6 @@ static INT32 DrvExit()
|
||||
Ssf2tb = 0;
|
||||
Xmcota = 0;
|
||||
Ecofght = 0;
|
||||
CpsXmvSixExit();
|
||||
|
||||
Cps2Volume = 39;
|
||||
Cps2DisableDigitalVolume = 0;
|
||||
@@ -14146,160 +14094,6 @@ static struct BurnRomInfo Sfz3jr2dRomDesc[] = {
|
||||
STD_ROM_PICK(Sfz3jr2d)
|
||||
STD_ROM_FN(Sfz3jr2d)
|
||||
|
||||
// Street Fighter Zero 3 Mix v0.32 (hacked by Zero800)
|
||||
// https://sfz3mix.github.io/
|
||||
|
||||
static struct BurnSampleInfo Sfz3mixSampleDesc[] = {
|
||||
{ "empty", SAMPLE_NOLOOP },
|
||||
{ "L01", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L02", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L03", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L04", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L05", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L06", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L07", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L08", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L09", SAMPLE_NOLOOP },
|
||||
{ "L0A", SAMPLE_NOLOOP },
|
||||
{ "L0B", SAMPLE_NOLOOP },
|
||||
{ "L0C", SAMPLE_NOLOOP },
|
||||
{ "L0D", SAMPLE_NOLOOP },
|
||||
{ "L0E", SAMPLE_NOLOOP },
|
||||
{ "L0F", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L10", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L11", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L12", SAMPLE_NOLOOP },
|
||||
{ "L13", SAMPLE_NOLOOP },
|
||||
{ "L14", SAMPLE_NOLOOP },
|
||||
{ "L15", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L16", SAMPLE_NOLOOP },
|
||||
{ "L17", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L18", SAMPLE_NOLOOP },
|
||||
{ "L19", SAMPLE_NOLOOP },
|
||||
{ "L1A", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L1B", SAMPLE_NOLOOP },
|
||||
{ "L1C", SAMPLE_NOLOOP },
|
||||
{ "L1D", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L1E", SAMPLE_NOLOOP },
|
||||
{ "L1F", SAMPLE_NOLOOP },
|
||||
{ "L20", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L21", SAMPLE_NOLOOP },
|
||||
{ "L22", SAMPLE_NOLOOP },
|
||||
{ "L23", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L24", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L25", SAMPLE_NOLOOP },
|
||||
{ "L26", SAMPLE_NOLOOP },
|
||||
{ "L27", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L28", SAMPLE_NOLOOP },
|
||||
{ "L29", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L2A", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L2B", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L2C", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L2D", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L2E", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L2F", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L30", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L31", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L32", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L33", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L34", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L35", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L36", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L37", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L38", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L39", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L3A", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L3B", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L3C", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L3D", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L3E", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "L3F", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "empty", SAMPLE_NOLOOP },
|
||||
{ "R01", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R02", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R03", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R04", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R05", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R06", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R07", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R08", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R09", SAMPLE_NOLOOP },
|
||||
{ "R0A", SAMPLE_NOLOOP },
|
||||
{ "R0B", SAMPLE_NOLOOP },
|
||||
{ "R0C", SAMPLE_NOLOOP },
|
||||
{ "R0D", SAMPLE_NOLOOP },
|
||||
{ "R0E", SAMPLE_NOLOOP },
|
||||
{ "R0F", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R10", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R11", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R12", SAMPLE_NOLOOP },
|
||||
{ "R13", SAMPLE_NOLOOP },
|
||||
{ "R14", SAMPLE_NOLOOP },
|
||||
{ "R15", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R16", SAMPLE_NOLOOP },
|
||||
{ "R17", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R18", SAMPLE_NOLOOP },
|
||||
{ "R19", SAMPLE_NOLOOP },
|
||||
{ "R1A", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R1B", SAMPLE_NOLOOP },
|
||||
{ "R1C", SAMPLE_NOLOOP },
|
||||
{ "R1D", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R1E", SAMPLE_NOLOOP },
|
||||
{ "R1F", SAMPLE_NOLOOP },
|
||||
{ "R20", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R21", SAMPLE_NOLOOP },
|
||||
{ "R22", SAMPLE_NOLOOP },
|
||||
{ "R23", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R24", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R25", SAMPLE_NOLOOP },
|
||||
{ "R26", SAMPLE_NOLOOP },
|
||||
{ "R27", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R28", SAMPLE_NOLOOP },
|
||||
{ "R29", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R2A", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R2B", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R2C", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R2D", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R2E", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R2F", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R30", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R31", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R32", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R33", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R34", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R35", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R36", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R37", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R38", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R39", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R3A", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R3B", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R3C", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R3D", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R3E", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "R3F", SAMPLE_NOLOOP | SAMPLE_NODUMP },
|
||||
{ "", 0 }
|
||||
};
|
||||
|
||||
STD_SAMPLE_PICK(Sfz3mix)
|
||||
STD_SAMPLE_FN(Sfz3mix)
|
||||
|
||||
static struct BurnRomInfo Sfz3mixRomDesc[] = {
|
||||
{ "sz3mx.03", 0x0600000, 0x7a968da6, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3mx.13m", 0x2000000, 0x5389b651, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3mx.21m", 0x2000000, 0x914c7031, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sz3mx.01", 0x0080000, 0x52f98a5c, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3mx.11m", 0x1000000, 0x395edce2, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "phoenix.key", 0x0000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Sfz3mix)
|
||||
STD_ROM_FN(Sfz3mix)
|
||||
|
||||
// Street Fighter Zero 3 Mix v0.13 (hacked by Zero800)
|
||||
// https://sfz3mix.github.io/
|
||||
|
||||
@@ -15303,37 +15097,6 @@ struct BurnDriver BurnDrvCpsSfz3jr2d = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
static INT32 Cps2TurboInit()
|
||||
{
|
||||
Cps2Turbo = 1;
|
||||
|
||||
INT32 rc = PhoenixInit();
|
||||
|
||||
if (!rc) {
|
||||
BurnSampleInit(1);
|
||||
for (int i = 0; i < 0x40; i++) {
|
||||
// Left side
|
||||
BurnSampleSetRoute(i + 0x00, BURN_SND_SAMPLE_ROUTE_1, 0.10, BURN_SND_ROUTE_LEFT);
|
||||
BurnSampleSetRoute(i + 0x00, BURN_SND_SAMPLE_ROUTE_2, 0.10, BURN_SND_ROUTE_NONE);
|
||||
// Right side
|
||||
BurnSampleSetRoute(i + 0x40, BURN_SND_SAMPLE_ROUTE_1, 0.10, BURN_SND_ROUTE_RIGHT);
|
||||
BurnSampleSetRoute(i + 0x40, BURN_SND_SAMPLE_ROUTE_2, 0.10, BURN_SND_ROUTE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct BurnDriver BurnDrvCpsSfz3mix = {
|
||||
"sfz3mix", "sfa3", NULL, "sfz3mix", "2026",
|
||||
"Street Fighter Zero 3 Mix v0.32\0", NULL, "hack (zero800)", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, Sfz3mixRomInfo, Sfz3mixRomName, NULL, NULL, Sfz3mixSampleInfo, Sfz3mixSampleName, Sfz3mixInputInfo, Sfz3mixDIPInfo,
|
||||
Cps2TurboInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 416, 234, 16, 9
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsSfz3mix13 = {
|
||||
"sfz3mix13", "sfa3", NULL, NULL, "2022",
|
||||
"Street Fighter Zero 3 Mix v0.13\0", NULL, "hack", "CPS2",
|
||||
@@ -16618,325 +16381,6 @@ struct BurnDriver BurnDrvCpsXmvsfcph = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// X-Men Vs. Street Fighter 3v3 + DHC (Hack, v1.1.0)
|
||||
// Modified by Morphus56K
|
||||
// 2026-10-11
|
||||
// https://www.morphus56k.com/blog/xmvsf-three-on-three
|
||||
// Three characters a team, Delayed Hyper Combos, snapbacks and eighteen colours per character.
|
||||
// The 6 player sets put P1-P3 against P4-P6; the wide sets show a 512 pixel wide arena.
|
||||
// All four need the board additions in xmvsf3v3.h (inputs for six players, extra work RAM,
|
||||
// HUD portraits in the chosen colour).
|
||||
|
||||
static struct BurnInputInfo Xmvsf3v3InputList[] = {
|
||||
{"P1 Coin" , BIT_DIGITAL , CpsXmvSixButtons[0] + 12, "p1 coin" },
|
||||
{"P1 Start" , BIT_DIGITAL , CpsXmvSixButtons[0] + 11, "p1 start" },
|
||||
{"P1 Up" , BIT_DIGITAL , CpsXmvSixButtons[0] + 3 , "p1 up" },
|
||||
{"P1 Down" , BIT_DIGITAL , CpsXmvSixButtons[0] + 2 , "p1 down" },
|
||||
{"P1 Left" , BIT_DIGITAL , CpsXmvSixButtons[0] + 1 , "p1 left" },
|
||||
{"P1 Right" , BIT_DIGITAL , CpsXmvSixButtons[0] + 0 , "p1 right" },
|
||||
{"P1 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[0] + 4 , "p1 fire 1" },
|
||||
{"P1 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[0] + 5 , "p1 fire 2" },
|
||||
{"P1 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[0] + 6 , "p1 fire 3" },
|
||||
{"P1 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[0] + 8 , "p1 fire 4" },
|
||||
{"P1 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[0] + 9 , "p1 fire 5" },
|
||||
{"P1 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[0] + 10, "p1 fire 6" },
|
||||
|
||||
{"P2 Coin" , BIT_DIGITAL , CpsXmvSixButtons[1] + 12, "p2 coin" },
|
||||
{"P2 Start" , BIT_DIGITAL , CpsXmvSixButtons[1] + 11, "p2 start" },
|
||||
{"P2 Up" , BIT_DIGITAL , CpsXmvSixButtons[1] + 3 , "p2 up" },
|
||||
{"P2 Down" , BIT_DIGITAL , CpsXmvSixButtons[1] + 2 , "p2 down" },
|
||||
{"P2 Left" , BIT_DIGITAL , CpsXmvSixButtons[1] + 1 , "p2 left" },
|
||||
{"P2 Right" , BIT_DIGITAL , CpsXmvSixButtons[1] + 0 , "p2 right" },
|
||||
{"P2 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[1] + 4 , "p2 fire 1" },
|
||||
{"P2 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[1] + 5 , "p2 fire 2" },
|
||||
{"P2 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[1] + 6 , "p2 fire 3" },
|
||||
{"P2 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[1] + 8 , "p2 fire 4" },
|
||||
{"P2 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[1] + 9 , "p2 fire 5" },
|
||||
{"P2 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[1] + 10, "p2 fire 6" },
|
||||
|
||||
{"Reset" , BIT_DIGITAL , &CpsReset , "reset" },
|
||||
{"Diagnostic" , BIT_DIGITAL , CpsInp021+1 , "diag" },
|
||||
{"Service" , BIT_DIGITAL , CpsInp021+2 , "service" },
|
||||
{"Volume Up" , BIT_DIGITAL , &Cps2VolUp , "volumeup" },
|
||||
{"Volume Down" , BIT_DIGITAL , &Cps2VolDwn , "volumedown"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(Xmvsf3v3)
|
||||
|
||||
static struct BurnInputInfo Xmvsf6pInputList[] = {
|
||||
{"P1 Coin" , BIT_DIGITAL , CpsXmvSixButtons[0] + 12, "p1 coin" },
|
||||
{"P1 Start" , BIT_DIGITAL , CpsXmvSixButtons[0] + 11, "p1 start" },
|
||||
{"P1 Up" , BIT_DIGITAL , CpsXmvSixButtons[0] + 3 , "p1 up" },
|
||||
{"P1 Down" , BIT_DIGITAL , CpsXmvSixButtons[0] + 2 , "p1 down" },
|
||||
{"P1 Left" , BIT_DIGITAL , CpsXmvSixButtons[0] + 1 , "p1 left" },
|
||||
{"P1 Right" , BIT_DIGITAL , CpsXmvSixButtons[0] + 0 , "p1 right" },
|
||||
{"P1 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[0] + 4 , "p1 fire 1" },
|
||||
{"P1 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[0] + 5 , "p1 fire 2" },
|
||||
{"P1 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[0] + 6 , "p1 fire 3" },
|
||||
{"P1 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[0] + 8 , "p1 fire 4" },
|
||||
{"P1 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[0] + 9 , "p1 fire 5" },
|
||||
{"P1 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[0] + 10, "p1 fire 6" },
|
||||
|
||||
{"P2 Coin" , BIT_DIGITAL , CpsXmvSixButtons[1] + 12, "p2 coin" },
|
||||
{"P2 Start" , BIT_DIGITAL , CpsXmvSixButtons[1] + 11, "p2 start" },
|
||||
{"P2 Up" , BIT_DIGITAL , CpsXmvSixButtons[1] + 3 , "p2 up" },
|
||||
{"P2 Down" , BIT_DIGITAL , CpsXmvSixButtons[1] + 2 , "p2 down" },
|
||||
{"P2 Left" , BIT_DIGITAL , CpsXmvSixButtons[1] + 1 , "p2 left" },
|
||||
{"P2 Right" , BIT_DIGITAL , CpsXmvSixButtons[1] + 0 , "p2 right" },
|
||||
{"P2 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[1] + 4 , "p2 fire 1" },
|
||||
{"P2 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[1] + 5 , "p2 fire 2" },
|
||||
{"P2 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[1] + 6 , "p2 fire 3" },
|
||||
{"P2 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[1] + 8 , "p2 fire 4" },
|
||||
{"P2 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[1] + 9 , "p2 fire 5" },
|
||||
{"P2 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[1] + 10, "p2 fire 6" },
|
||||
|
||||
{"P3 Coin" , BIT_DIGITAL , CpsXmvSixButtons[2] + 12, "p3 coin" },
|
||||
{"P3 Start" , BIT_DIGITAL , CpsXmvSixButtons[2] + 11, "p3 start" },
|
||||
{"P3 Up" , BIT_DIGITAL , CpsXmvSixButtons[2] + 3 , "p3 up" },
|
||||
{"P3 Down" , BIT_DIGITAL , CpsXmvSixButtons[2] + 2 , "p3 down" },
|
||||
{"P3 Left" , BIT_DIGITAL , CpsXmvSixButtons[2] + 1 , "p3 left" },
|
||||
{"P3 Right" , BIT_DIGITAL , CpsXmvSixButtons[2] + 0 , "p3 right" },
|
||||
{"P3 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[2] + 4 , "p3 fire 1" },
|
||||
{"P3 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[2] + 5 , "p3 fire 2" },
|
||||
{"P3 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[2] + 6 , "p3 fire 3" },
|
||||
{"P3 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[2] + 8 , "p3 fire 4" },
|
||||
{"P3 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[2] + 9 , "p3 fire 5" },
|
||||
{"P3 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[2] + 10, "p3 fire 6" },
|
||||
|
||||
{"P4 Coin" , BIT_DIGITAL , CpsXmvSixButtons[3] + 12, "p4 coin" },
|
||||
{"P4 Start" , BIT_DIGITAL , CpsXmvSixButtons[3] + 11, "p4 start" },
|
||||
{"P4 Up" , BIT_DIGITAL , CpsXmvSixButtons[3] + 3 , "p4 up" },
|
||||
{"P4 Down" , BIT_DIGITAL , CpsXmvSixButtons[3] + 2 , "p4 down" },
|
||||
{"P4 Left" , BIT_DIGITAL , CpsXmvSixButtons[3] + 1 , "p4 left" },
|
||||
{"P4 Right" , BIT_DIGITAL , CpsXmvSixButtons[3] + 0 , "p4 right" },
|
||||
{"P4 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[3] + 4 , "p4 fire 1" },
|
||||
{"P4 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[3] + 5 , "p4 fire 2" },
|
||||
{"P4 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[3] + 6 , "p4 fire 3" },
|
||||
{"P4 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[3] + 8 , "p4 fire 4" },
|
||||
{"P4 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[3] + 9 , "p4 fire 5" },
|
||||
{"P4 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[3] + 10, "p4 fire 6" },
|
||||
|
||||
{"P5 Coin" , BIT_DIGITAL , CpsXmvSixButtons[4] + 12, "p5 coin" },
|
||||
{"P5 Start" , BIT_DIGITAL , CpsXmvSixButtons[4] + 11, "p5 start" },
|
||||
{"P5 Up" , BIT_DIGITAL , CpsXmvSixButtons[4] + 3 , "p5 up" },
|
||||
{"P5 Down" , BIT_DIGITAL , CpsXmvSixButtons[4] + 2 , "p5 down" },
|
||||
{"P5 Left" , BIT_DIGITAL , CpsXmvSixButtons[4] + 1 , "p5 left" },
|
||||
{"P5 Right" , BIT_DIGITAL , CpsXmvSixButtons[4] + 0 , "p5 right" },
|
||||
{"P5 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[4] + 4 , "p5 fire 1" },
|
||||
{"P5 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[4] + 5 , "p5 fire 2" },
|
||||
{"P5 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[4] + 6 , "p5 fire 3" },
|
||||
{"P5 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[4] + 8 , "p5 fire 4" },
|
||||
{"P5 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[4] + 9 , "p5 fire 5" },
|
||||
{"P5 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[4] + 10, "p5 fire 6" },
|
||||
|
||||
{"P6 Coin" , BIT_DIGITAL , CpsXmvSixButtons[5] + 12, "p6 coin" },
|
||||
{"P6 Start" , BIT_DIGITAL , CpsXmvSixButtons[5] + 11, "p6 start" },
|
||||
{"P6 Up" , BIT_DIGITAL , CpsXmvSixButtons[5] + 3 , "p6 up" },
|
||||
{"P6 Down" , BIT_DIGITAL , CpsXmvSixButtons[5] + 2 , "p6 down" },
|
||||
{"P6 Left" , BIT_DIGITAL , CpsXmvSixButtons[5] + 1 , "p6 left" },
|
||||
{"P6 Right" , BIT_DIGITAL , CpsXmvSixButtons[5] + 0 , "p6 right" },
|
||||
{"P6 Weak Punch" , BIT_DIGITAL , CpsXmvSixButtons[5] + 4 , "p6 fire 1" },
|
||||
{"P6 Medium Punch" , BIT_DIGITAL , CpsXmvSixButtons[5] + 5 , "p6 fire 2" },
|
||||
{"P6 Strong Punch" , BIT_DIGITAL , CpsXmvSixButtons[5] + 6 , "p6 fire 3" },
|
||||
{"P6 Weak Kick" , BIT_DIGITAL , CpsXmvSixButtons[5] + 8 , "p6 fire 4" },
|
||||
{"P6 Medium Kick" , BIT_DIGITAL , CpsXmvSixButtons[5] + 9 , "p6 fire 5" },
|
||||
{"P6 Strong Kick" , BIT_DIGITAL , CpsXmvSixButtons[5] + 10, "p6 fire 6" },
|
||||
|
||||
{"Reset" , BIT_DIGITAL , &CpsReset , "reset" },
|
||||
{"Diagnostic" , BIT_DIGITAL , CpsInp021+1 , "diag" },
|
||||
{"Service" , BIT_DIGITAL , CpsInp021+2 , "service" },
|
||||
{"Volume Up" , BIT_DIGITAL , &Cps2VolUp , "volumeup" },
|
||||
{"Volume Down" , BIT_DIGITAL , &Cps2VolDwn , "volumedown"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(Xmvsf6p)
|
||||
|
||||
static INT32 Xmvsf3v3CommonInit(INT32 bWide)
|
||||
{
|
||||
if (CpsXmvSixInit(bWide)) return 1;
|
||||
|
||||
INT32 nRet = Cps2Init();
|
||||
if (nRet) {
|
||||
CpsXmvSixExit();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
CpsRunResetCallbackFunction = CpsXmvSixReset;
|
||||
CpsMemScanCallbackFunction = CpsXmvSixScan;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 Xmvsf3v3Init()
|
||||
{
|
||||
return Xmvsf3v3CommonInit(0);
|
||||
}
|
||||
|
||||
static INT32 Xmvsf3v3WideInit()
|
||||
{
|
||||
return Xmvsf3v3CommonInit(1);
|
||||
}
|
||||
|
||||
static struct BurnRomInfo Xmvsf3v3RomDesc[] = {
|
||||
{ "xvs3v3.03f", 0x080000, 0x7b151acd, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvse.04f", 0x080000, 0xef015aef, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.05a", 0x080000, 0x7db6025d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.06a", 0x080000, 0xe8e2c75c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.07", 0x080000, 0x08f0abed, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs3v3.08", 0x080000, 0x477a3f86, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs3v3.09", 0x080000, 0x98e06515, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs3v3.13m", 0x400000, 0xc8b777f6, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.15m", 0x400000, 0x8143c2b0, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.17m", 0x400000, 0x10cceec9, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.19m", 0x400000, 0xf458a1f8, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.14m", 0x400000, 0xbcac2e41, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.16m", 0x400000, 0xea04a272, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.18m", 0x400000, 0xb0def86a, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.20m", 0x400000, 0x4b40ff9f, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "xvs.01", 0x020000, 0x3999e93a, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.02", 0x020000, 0x101bdee9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs.11m", 0x200000, 0x9cadcdbc, CPS2_QSND | BRF_SND },
|
||||
{ "xvs.12m", 0x200000, 0x7b11e460, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "xmvsf.key", 0x000014, 0xd5c07311, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Xmvsf3v3)
|
||||
STD_ROM_FN(Xmvsf3v3)
|
||||
|
||||
static struct BurnRomInfo Xmvsf3v3wRomDesc[] = {
|
||||
{ "xvs3v3w.03f", 0x080000, 0x54ed459e, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvse.04f", 0x080000, 0xef015aef, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.05a", 0x080000, 0x7db6025d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.06a", 0x080000, 0xe8e2c75c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.07", 0x080000, 0x08f0abed, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs3v3.08", 0x080000, 0x477a3f86, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs3v3w.09", 0x080000, 0x145e92b6, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs3v3.13m", 0x400000, 0xc8b777f6, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.15m", 0x400000, 0x8143c2b0, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.17m", 0x400000, 0x10cceec9, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.19m", 0x400000, 0xf458a1f8, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.14m", 0x400000, 0xbcac2e41, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.16m", 0x400000, 0xea04a272, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.18m", 0x400000, 0xb0def86a, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.20m", 0x400000, 0x4b40ff9f, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "xvs.01", 0x020000, 0x3999e93a, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.02", 0x020000, 0x101bdee9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs.11m", 0x200000, 0x9cadcdbc, CPS2_QSND | BRF_SND },
|
||||
{ "xvs.12m", 0x200000, 0x7b11e460, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "xmvsf.key", 0x000014, 0xd5c07311, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Xmvsf3v3w)
|
||||
STD_ROM_FN(Xmvsf3v3w)
|
||||
|
||||
static struct BurnRomInfo Xmvsf6pRomDesc[] = {
|
||||
{ "xvs6p.03f", 0x080000, 0x8940699a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvse.04f", 0x080000, 0xef015aef, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.05a", 0x080000, 0x7db6025d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.06a", 0x080000, 0xe8e2c75c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.07", 0x080000, 0x08f0abed, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs6p.08", 0x080000, 0x14b6a689, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs6p.09", 0x080000, 0x6ea8fdea, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs3v3.13m", 0x400000, 0xc8b777f6, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.15m", 0x400000, 0x8143c2b0, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.17m", 0x400000, 0x10cceec9, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.19m", 0x400000, 0xf458a1f8, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.14m", 0x400000, 0xbcac2e41, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.16m", 0x400000, 0xea04a272, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.18m", 0x400000, 0xb0def86a, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.20m", 0x400000, 0x4b40ff9f, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "xvs.01", 0x020000, 0x3999e93a, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.02", 0x020000, 0x101bdee9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs.11m", 0x200000, 0x9cadcdbc, CPS2_QSND | BRF_SND },
|
||||
{ "xvs.12m", 0x200000, 0x7b11e460, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "xmvsf.key", 0x000014, 0xd5c07311, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Xmvsf6p)
|
||||
STD_ROM_FN(Xmvsf6p)
|
||||
|
||||
static struct BurnRomInfo Xmvsf6pwRomDesc[] = {
|
||||
{ "xvs6pw.03f", 0x080000, 0xa6b836c9, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvse.04f", 0x080000, 0xef015aef, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.05a", 0x080000, 0x7db6025d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.06a", 0x080000, 0xe8e2c75c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.07", 0x080000, 0x08f0abed, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs6p.08", 0x080000, 0x14b6a689, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "xvs6pw.09", 0x080000, 0xe2160a49, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs3v3.13m", 0x400000, 0xc8b777f6, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.15m", 0x400000, 0x8143c2b0, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.17m", 0x400000, 0x10cceec9, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs3v3.19m", 0x400000, 0xf458a1f8, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.14m", 0x400000, 0xbcac2e41, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.16m", 0x400000, 0xea04a272, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.18m", 0x400000, 0xb0def86a, CPS2_GFX | BRF_GRA },
|
||||
{ "xvs.20m", 0x400000, 0x4b40ff9f, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "xvs.01", 0x020000, 0x3999e93a, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "xvs.02", 0x020000, 0x101bdee9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "xvs.11m", 0x200000, 0x9cadcdbc, CPS2_QSND | BRF_SND },
|
||||
{ "xvs.12m", 0x200000, 0x7b11e460, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "xmvsf.key", 0x000014, 0xd5c07311, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Xmvsf6pw)
|
||||
STD_ROM_FN(Xmvsf6pw)
|
||||
|
||||
struct BurnDriver BurnDrvCpsXmvsf3v3 = {
|
||||
"xmvsf3v3", "xmvsf", NULL, NULL, "2026",
|
||||
"X-Men Vs. Street Fighter 3v3 + DHC (Hack, v1.1.0)\0", NULL, "hack (Morphus56K)", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, Xmvsf3v3RomInfo, Xmvsf3v3RomName, NULL, NULL, NULL, NULL, Xmvsf3v3InputInfo, NULL,
|
||||
Xmvsf3v3Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsXmvsf3v3w = {
|
||||
"xmvsf3v3w", "xmvsf", NULL, NULL, "2026",
|
||||
"X-Men Vs. Street Fighter 3v3 + DHC (Hack, v1.1.0, wide)\0", NULL, "hack (Morphus56K)", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, Xmvsf3v3wRomInfo, Xmvsf3v3wRomName, NULL, NULL, NULL, NULL, Xmvsf3v3InputInfo, NULL,
|
||||
Xmvsf3v3WideInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 512, 224, 16, 9
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsXmvsf6p = {
|
||||
"xmvsf6p", "xmvsf", NULL, NULL, "2026",
|
||||
"X-Men Vs. Street Fighter 3v3 + DHC (Hack, v1.1.0, 6 players)\0", NULL, "hack (Morphus56K)", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 6, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, Xmvsf6pRomInfo, Xmvsf6pRomName, NULL, NULL, NULL, NULL, Xmvsf6pInputInfo, NULL,
|
||||
Xmvsf3v3Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvCpsXmvsf6pw = {
|
||||
"xmvsf6pw", "xmvsf", NULL, NULL, "2026",
|
||||
"X-Men Vs. Street Fighter 3v3 + DHC (Hack, v1.1.0, 6 players, wide)\0", NULL, "hack (Morphus56K)", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 6, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, Xmvsf6pwRomInfo, Xmvsf6pwRomName, NULL, NULL, NULL, NULL, Xmvsf6pInputInfo, NULL,
|
||||
Xmvsf3v3WideInit, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 512, 224, 16, 9
|
||||
};
|
||||
|
||||
// Mars Matrix: Hyper Solid Shooting (Hack, Improvement v1.0.0)
|
||||
// 20251204
|
||||
|
||||
@@ -17114,34 +16558,34 @@ struct BurnDriver BurnDrvCpsSsf2xdced = {
|
||||
// https://strygo.github.io/arcade-patches/
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Final Fight EX (Hack, CPS2 hardware, USA RC1)
|
||||
|
||||
// Final Fight EX (Hack, CPS2 hardware, USA RC2)
|
||||
// 2026-10-25
|
||||
static struct BurnRomInfo Ffex2uRomDesc[] = {
|
||||
{ "sz3ud.03c", 0x080000, 0xe022fd18, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3ud.04c", 0x080000, 0x9c228c18, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.05c", 0x080000, 0x787bb7f2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.06c", 0x080000, 0x5652684a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.07c", 0x080000, 0x6e430b5c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.08c", 0x080000, 0x0b37c61a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.09c", 0x080000, 0xc0a36b4d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.10b", 0x080000, 0x85f1c748, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexd.03c", 0x080000, 0x4f9873c4, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexd.04c", 0x080000, 0x4957978c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.05c", 0x080000, 0x787bb7f2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.06c", 0x080000, 0x5652684a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.07c", 0x080000, 0x6e430b5c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.08c", 0x080000, 0x0b37c61a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.09c", 0x080000, 0xc0a36b4d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.10b", 0x080000, 0x85f1c748, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3.13m", 0x400000, 0x48cbc129, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.15m", 0x400000, 0xfd20f3aa, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.17m", 0x400000, 0x5ea87831, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.19m", 0x400000, 0xda6a3e7e, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.14m", 0x400000, 0xeca6de34, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.16m", 0x400000, 0x17069cbd, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.18m", 0x400000, 0x0f560d8c, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.20m", 0x400000, 0xe96d3923, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.13m", 0x400000, 0x48cbc129, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.15m", 0x400000, 0xfd20f3aa, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.17m", 0x400000, 0x5ea87831, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.19m", 0x400000, 0xda6a3e7e, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.14m", 0x400000, 0xeca6de34, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.16m", 0x400000, 0x17069cbd, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.18m", 0x400000, 0x0f560d8c, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.20m", 0x400000, 0xe96d3923, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sz3.01", 0x020000, 0x03d74a70, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.02", 0x020000, 0x7ee8cdcd, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.01", 0x020000, 0x03d74a70, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.02", 0x020000, 0x7ee8cdcd, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3.11m", 0x400000, 0xbea96b44, CPS2_QSND | BRF_SND },
|
||||
{ "sz3.12m", 0x400000, 0xdf5e34c3, CPS2_QSND | BRF_SND },
|
||||
{ "ffex.11m", 0x400000, 0xbea96b44, CPS2_QSND | BRF_SND },
|
||||
{ "ffex.12m", 0x400000, 0xdf5e34c3, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "phoenix.key", 0x000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
{ "phoenix.key", 0x000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Ffex2u)
|
||||
@@ -17149,7 +16593,7 @@ STD_ROM_FN(Ffex2u)
|
||||
|
||||
struct BurnDriver BurnDrvCpsFfex2u = {
|
||||
"ffex2u", NULL, NULL, NULL, "2026",
|
||||
"Final Fight EX (Hack, CPS2 hardware, USA RC1)\0", NULL, "Strygo", "CPS2",
|
||||
"Final Fight EX (Hack, CPS2 hardware, USA RC2)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HACK, 2, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0,
|
||||
NULL, Ffex2uRomInfo, Ffex2uRomName, NULL, NULL, NULL, NULL, Ffex2InputInfo, NULL,
|
||||
@@ -17157,34 +16601,34 @@ struct BurnDriver BurnDrvCpsFfex2u = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Final Fight EX (Hack, CPS2 hardware, Japan RC1)
|
||||
|
||||
// Final Fight EX (Hack, CPS2 hardware, Japan RC2)
|
||||
// 2026-10-25
|
||||
static struct BurnRomInfo Ffex2jRomDesc[] = {
|
||||
{ "sz3ud.03c", 0x080000, 0x9eb92f51, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3ud.04c", 0x080000, 0x3a2393c0, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.05c", 0x080000, 0x787bb7f2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.06c", 0x080000, 0xa8d2d10b, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.07c", 0x080000, 0xbcf7297e, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.08c", 0x080000, 0x7afbcbad, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.09c", 0x080000, 0x0642626b, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.10b", 0x080000, 0xb4208a79, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexjd.03c", 0x080000, 0x789ff036, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexjd.04c", 0x080000, 0x613c6ecc, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.05c", 0x080000, 0x787bb7f2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexj.06c", 0x080000, 0xa8d2d10b, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexj.07c", 0x080000, 0xbcf7297e, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexj.08c", 0x080000, 0x7afbcbad, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexj.09c", 0x080000, 0x0642626b, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexj.10b", 0x080000, 0xb4208a79, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3.13m", 0x400000, 0xd24130e3, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.15m", 0x400000, 0xcef0a6b3, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.17m", 0x400000, 0x00464598, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.19m", 0x400000, 0x6f5379cc, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.14m", 0x400000, 0xae054c04, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.16m", 0x400000, 0x0e09c2ba, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.18m", 0x400000, 0x0f560d8c, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.20m", 0x400000, 0xe96d3923, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexj.13m", 0x400000, 0xd24130e3, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexj.15m", 0x400000, 0xcef0a6b3, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexj.17m", 0x400000, 0x00464598, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexj.19m", 0x400000, 0x6f5379cc, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexj.14m", 0x400000, 0xae054c04, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexj.16m", 0x400000, 0x0e09c2ba, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.18m", 0x400000, 0x0f560d8c, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.20m", 0x400000, 0xe96d3923, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sz3.01", 0x020000, 0x36ef522c, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.02", 0x020000, 0x7ee8cdcd, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "ffexj.01", 0x020000, 0x36ef522c, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.02", 0x020000, 0x7ee8cdcd, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3.11m", 0x400000, 0xbea96b44, CPS2_QSND | BRF_SND },
|
||||
{ "sz3.12m", 0x400000, 0xdf5e34c3, CPS2_QSND | BRF_SND },
|
||||
{ "ffex.11m", 0x400000, 0xbea96b44, CPS2_QSND | BRF_SND },
|
||||
{ "ffex.12m", 0x400000, 0xdf5e34c3, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "phoenix.key", 0x000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
{ "phoenix.key", 0x000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Ffex2j)
|
||||
@@ -17192,7 +16636,7 @@ STD_ROM_FN(Ffex2j)
|
||||
|
||||
struct BurnDriver BurnDrvCpsFfex2j = {
|
||||
"ffex2j", "ffex2u", NULL, NULL, "2026",
|
||||
"Final Fight EX (Hack, CPS2 hardware, Japan RC1)\0", NULL, "Strygo", "CPS2",
|
||||
"Final Fight EX (Hack, CPS2 hardware, Japan RC2)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0,
|
||||
NULL, Ffex2jRomInfo, Ffex2jRomName, NULL, NULL, NULL, NULL, Ffex2InputInfo, NULL,
|
||||
@@ -17200,34 +16644,34 @@ struct BurnDriver BurnDrvCpsFfex2j = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Final Fight EX (Hack, CPS2 hardware, English Restoration RC1)
|
||||
|
||||
// Final Fight EX (Hack, CPS2 hardware, English Restoration RC2)
|
||||
// 2026-10-25
|
||||
static struct BurnRomInfo Ffex2rRomDesc[] = {
|
||||
{ "sz3ud.03c", 0x080000, 0xd1129b95, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3ud.04c", 0x080000, 0x5d10506d, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.05c", 0x080000, 0x787bb7f2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.06c", 0x080000, 0x5652684a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.07c", 0x080000, 0x6e430b5c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.08c", 0x080000, 0x64f42ba9, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.09c", 0x080000, 0xbd69566a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.10b", 0x080000, 0x9539a4aa, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexrd.03c", 0x080000, 0xbce36dc0, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexrd.04c", 0x080000, 0x273ae5d9, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.05c", 0x080000, 0x787bb7f2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.06c", 0x080000, 0x5652684a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.07c", 0x080000, 0x6e430b5c, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexr.08c", 0x080000, 0x64f42ba9, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexr.09c", 0x080000, 0xbd69566a, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "ffexr.10b", 0x080000, 0x9539a4aa, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3.13m", 0x400000, 0x231f811f, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.15m", 0x400000, 0x26cea23a, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.17m", 0x400000, 0xf118f464, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.19m", 0x400000, 0x876d7d45, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.14m", 0x400000, 0xeca6de34, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.16m", 0x400000, 0x17069cbd, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.18m", 0x400000, 0x0f560d8c, CPS2_GFX | BRF_GRA },
|
||||
{ "sz3.20m", 0x400000, 0xe96d3923, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexr.13m", 0x400000, 0x231f811f, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexr.15m", 0x400000, 0x26cea23a, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexr.17m", 0x400000, 0xf118f464, CPS2_GFX | BRF_GRA },
|
||||
{ "ffexr.19m", 0x400000, 0x876d7d45, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.14m", 0x400000, 0xeca6de34, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.16m", 0x400000, 0x17069cbd, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.18m", 0x400000, 0x0f560d8c, CPS2_GFX | BRF_GRA },
|
||||
{ "ffex.20m", 0x400000, 0xe96d3923, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sz3.01", 0x020000, 0x3c1c4965, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sz3.02", 0x020000, 0x7ee8cdcd, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "ffexr.01", 0x020000, 0x3c1c4965, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "ffex.02", 0x020000, 0x7ee8cdcd, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sz3.11m", 0x400000, 0xbea96b44, CPS2_QSND | BRF_SND },
|
||||
{ "sz3.12m", 0x400000, 0xdf5e34c3, CPS2_QSND | BRF_SND },
|
||||
{ "ffex.11m", 0x400000, 0xbea96b44, CPS2_QSND | BRF_SND },
|
||||
{ "ffex.12m", 0x400000, 0xdf5e34c3, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "phoenix.key", 0x000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
{ "phoenix.key", 0x000014, 0x2cf772b0, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Ffex2r)
|
||||
@@ -17235,7 +16679,7 @@ STD_ROM_FN(Ffex2r)
|
||||
|
||||
struct BurnDriver BurnDrvCpsFfex2r = {
|
||||
"ffex2r", "ffex2u", NULL, NULL, "2026",
|
||||
"Final Fight EX (Hack, CPS2 hardware, English Restoration RC1)\0", NULL, "Strygo", "CPS2",
|
||||
"Final Fight EX (Hack, CPS2 hardware, English Restoration RC2)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_CAPCOM_CPS2, GBF_SCRFIGHT, 0,
|
||||
NULL, Ffex2rRomInfo, Ffex2rRomName, NULL, NULL, NULL, NULL, Ffex2InputInfo, NULL,
|
||||
@@ -17606,6 +17050,111 @@ struct BurnDriver BurnDrvCpsSfzrej = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Street Fighter Alpha EX: Warriors' Dreams (Hack, USA RC1)
|
||||
// 2026-10-26
|
||||
static struct BurnRomInfo SfaexRomDesc[] = {
|
||||
{ "sfzex.03c", 0x080000, 0xa0c070cb, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzre.04b", 0x080000, 0x8d9b2480, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzre.05a", 0x080000, 0x8cf0a98f, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzex.06", 0x080000, 0x9b5fc006, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfzex.14m", 0x200000, 0x5e90868c, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzex.16m", 0x200000, 0x97ac2170, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzex.18m", 0x200000, 0x5e414b4f, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzex.20m", 0x200000, 0xf29757b8, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sfzex.01", 0x020000, 0xe52887c9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sfz.02", 0x020000, 0x45f46a08, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfz.11m", 0x200000, 0xc4b093cd, CPS2_QSND | BRF_SND },
|
||||
{ "sfz.12m", 0x200000, 0x8bdbc4b4, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "sfzj.key", 0x000014, 0x355d85b8, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Sfaex)
|
||||
STD_ROM_FN(Sfaex)
|
||||
|
||||
struct BurnDriver BurnDrvCpsSfaex = {
|
||||
"sfaex", "sfa", NULL, NULL, "2026",
|
||||
"Street Fighter Alpha EX: Warriors' Dreams (Hack, USA RC1)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, SfaexRomInfo, SfaexRomName, NULL, NULL, NULL, NULL, Cps2FightingInputInfo, NULL,
|
||||
Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Street Fighter Zero EX (Hack, Asia RC1)
|
||||
// 2026-10-26
|
||||
static struct BurnRomInfo SfzexaRomDesc[] = {
|
||||
{ "sfzexa.03c", 0x080000, 0x14c3e640, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzre.04b", 0x080000, 0x8d9b2480, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzre.05a", 0x080000, 0x8cf0a98f, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzexa.06", 0x080000, 0x4185da04, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfzexa.14m", 0x200000, 0x31318783, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzexa.16m", 0x200000, 0xb905c57d, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzexa.18m", 0x200000, 0x0ed47cd2, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzexa.20m", 0x200000, 0x688f9434, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sfzex.01", 0x020000, 0xe52887c9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sfz.02", 0x020000, 0x45f46a08, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfz.11m", 0x200000, 0xc4b093cd, CPS2_QSND | BRF_SND },
|
||||
{ "sfz.12m", 0x200000, 0x8bdbc4b4, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "sfzj.key", 0x000014, 0x355d85b8, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Sfzexa)
|
||||
STD_ROM_FN(Sfzexa)
|
||||
|
||||
struct BurnDriver BurnDrvCpsSfzexa = {
|
||||
"sfzexa", "sfa", NULL, NULL, "2026",
|
||||
"Street Fighter Zero EX (Hack, Asia RC1)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, SfzexaRomInfo, SfzexaRomName, NULL, NULL, NULL, NULL, Cps2FightingInputInfo, NULL,
|
||||
Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Street Fighter Zero EX (Hack, Japan RC1)
|
||||
// 2026-10-26
|
||||
static struct BurnRomInfo SfzexjRomDesc[] = {
|
||||
{ "sfzexj.03c", 0x080000, 0x7eb7adce, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzex.04b", 0x080000, 0x8d9b2480, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzrej.05a", 0x080000, 0xfa9ceda6, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfzexj.06", 0x080000, 0x995752fb, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfzexj.14m", 0x200000, 0x0a7de3b8, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzexj.16m", 0x200000, 0xc1b36217, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzexj.18m", 0x200000, 0x8f468f11, CPS2_GFX | BRF_GRA },
|
||||
{ "sfzexj.20m", 0x200000, 0x37c3c380, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sfzex.01", 0x020000, 0xe52887c9, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sfz.02", 0x020000, 0x45f46a08, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfz.11m", 0x200000, 0xc4b093cd, CPS2_QSND | BRF_SND },
|
||||
{ "sfz.12m", 0x200000, 0x8bdbc4b4, CPS2_QSND | BRF_SND },
|
||||
|
||||
{ "sfzj.key", 0x000014, 0x355d85b8, CPS2_ENCRYPTION_KEY },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Sfzexj)
|
||||
STD_ROM_FN(Sfzexj)
|
||||
|
||||
struct BurnDriver BurnDrvCpsSfzexj = {
|
||||
"sfzexj", "sfa", NULL, NULL, "2026",
|
||||
"Street Fighter Zero EX (Hack, Japan RC1)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, SfzexjRomInfo, SfzexjRomName, NULL, NULL, NULL, NULL, Cps2FightingInputInfo, NULL,
|
||||
Cps2Init, DrvExit, Cps2Frame, CpsRedraw, CpsAreaScan,
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Street Fighter Alpha 2 Restoration (Hack, USA RC2)
|
||||
// 2026-10-13
|
||||
static struct BurnRomInfo Sfa2reRomDesc[] = {
|
||||
@@ -18102,29 +17651,29 @@ struct BurnDriver BurnDrvCpsSfz3rej = {
|
||||
&CpsRecalcPal, 0x1000, 384, 224, 4, 3
|
||||
};
|
||||
|
||||
// Super Street Fighter II Turbo: Grand Master Challenge (Hack, English Restoration RC3)
|
||||
// 2026-10-21
|
||||
// Super Street Fighter II Turbo: Grand Master Challenge (Hack, English Restoration RC4)
|
||||
// 2026-10-25
|
||||
static struct BurnRomInfo Ssf2tgmcRomDesc[] = {
|
||||
{ "sfxgmc.03d", 0x080000, 0xee8e9e9b, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxgmc.03d", 0x080000, 0xcfc87616, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxgmc.04a", 0x080000, 0xc9df66cd, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxj.05", 0x080000, 0xf4ff18f5, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxj.06b", 0x080000, 0x413477c2, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxj.07a", 0x080000, 0xa18b3d83, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxgmc.08", 0x080000, 0xea0d1d90, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxgmc.09", 0x080000, 0x95718f1e, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxgmc.08", 0x080000, 0xf7587a54, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
{ "sfxgmc.09", 0x080000, 0x9a6ae34e, CPS2_PRG_68K | BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "sfxgmc.13m", 0x200000, 0x75dac0eb, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.15m", 0x200000, 0x84dcc039, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.17m", 0x200000, 0xbfcaf206, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.19m", 0x200000, 0x13a55fd3, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.14m", 0x100000, 0x1f8dd3ca, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.16m", 0x100000, 0x8033c95d, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.18m", 0x100000, 0xdd6cdee2, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.20m", 0x100000, 0x4dacc976, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.21m", 0x100000, 0x34f361da, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.23m", 0x100000, 0x279f2671, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.25m", 0x100000, 0x1fbd5b9e, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.27m", 0x100000, 0x11725784, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.14m", 0x100000, 0xa821a895, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.16m", 0x100000, 0xf4dd5566, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.18m", 0x100000, 0x6ac0a5bd, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.20m", 0x100000, 0x3942554d, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.21m", 0x100000, 0xc507ee10, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.23m", 0x100000, 0xd0bd63db, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.25m", 0x100000, 0x2a8193c4, CPS2_GFX | BRF_GRA },
|
||||
{ "sfxgmc.27m", 0x100000, 0x3c6e0a1a, CPS2_GFX | BRF_GRA },
|
||||
|
||||
{ "sfx.01", 0x020000, 0xb47b8835, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
{ "sfx.02", 0x020000, 0x0022633f, CPS2_PRG_Z80 | BRF_ESS | BRF_PRG },
|
||||
@@ -18140,7 +17689,7 @@ STD_ROM_FN(Ssf2tgmc)
|
||||
|
||||
struct BurnDriver BurnDrvCpsSsf2tgmc = {
|
||||
"ssf2tgmc", "ssf2t", NULL, NULL, "2026",
|
||||
"Super Street Fighter II Turbo: Grand Master Challenge (Hack, English Restoration RC3)\0", NULL, "Strygo", "CPS2",
|
||||
"Super Street Fighter II Turbo: Grand Master Challenge (Hack, English Restoration RC4)\0", NULL, "Strygo", "CPS2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_CAPCOM_CPS2, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, Ssf2tgmcRomInfo, Ssf2tgmcRomName, NULL, NULL, NULL, NULL, Cps2FightingInputInfo, NULL,
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -33,5 +33,6 @@ group_srcs = [
|
||||
drivers = {
|
||||
'd_cps1.cpp': ['ay8910', 'eeprom', 'm68000', 'msm5205', 'msm6295', 'samples', 'timekpr', 'ym2151', 'ym2203', 'z80'],
|
||||
'd_cps2.cpp': ['ay8910', 'eeprom', 'm68000', 'msm5205', 'msm6295', 'samples', 'ym2151', 'ym2203', 'z80'],
|
||||
'd_cps2_custom.cpp': ['ay8910', 'eeprom', 'm68000', 'msm5205', 'msm6295', 'samples', 'ym2151', 'ym2203', 'z80'],
|
||||
'd_mitchell.cpp': ['ay8910', 'eeprom', 'm68000', 'msm5205', 'msm6295', 'samples', 'ym2151', 'ym2203', 'ym2413', 'z80'],
|
||||
}
|
||||
@@ -21,18 +21,9 @@ INT32 QsndInit()
|
||||
}
|
||||
BurnTimerInit(qsndTimerOver, NULL);
|
||||
|
||||
if (Cps1Qs == 1) {
|
||||
nCpsZ80Cycles = 8000000 * 100 / nBurnFPS;
|
||||
BurnTimerAttachZet(8000000);
|
||||
} else {
|
||||
if (Cps2Turbo) {
|
||||
nCpsZ80Cycles = 16000000 * 100 / nBurnFPS;
|
||||
BurnTimerAttachZet(16000000);
|
||||
} else {
|
||||
nCpsZ80Cycles = 8000000 * 100 / nBurnFPS;
|
||||
BurnTimerAttachZet(8000000);
|
||||
}
|
||||
}
|
||||
INT32 nClock = (Cps1Qs == 1) ? 8000000 : nQsndZ80Clock;
|
||||
nCpsZ80Cycles = nClock * 100 / nBurnFPS;
|
||||
BurnTimerAttachZet(nClock);
|
||||
|
||||
if (nBurnSoundRate >= 0) {
|
||||
nRate = nBurnSoundRate;
|
||||
@@ -66,11 +57,11 @@ void QsndExit()
|
||||
QsndZExit();
|
||||
}
|
||||
|
||||
INT32 QsndScan(INT32 nAction)
|
||||
INT32 QsndScan(INT32 nAction, INT32 bScanHistory)
|
||||
{
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
QsndZScan(nAction); // Scan Z80
|
||||
QscScan(nAction); // Scan QSound Chip
|
||||
QscScan(nAction, bScanHistory); // Scan QSound Chip
|
||||
|
||||
BurnTimerScan(nAction, NULL);
|
||||
SCAN_VAR(nQsndCyclesExtra);
|
||||
@@ -93,9 +84,6 @@ void QsndEndFrame()
|
||||
{
|
||||
BurnTimerEndFrame(nCpsZ80Cycles);
|
||||
if (pBurnSoundOut) QscUpdate(nBurnSoundLen);
|
||||
if (Cps2Turbo && pBurnSoundOut) {
|
||||
BurnSampleRender(pBurnSoundOut, nBurnSoundLen);
|
||||
}
|
||||
|
||||
nQsndCyclesExtra = ZetTotalCycles() - nCpsZ80Cycles;
|
||||
ZetClose();
|
||||
|
||||
@@ -310,7 +310,7 @@ inline INT16 get_sample(UINT16 bank, UINT16 address)
|
||||
UINT8 sample_data;
|
||||
|
||||
if(nCpsQSamLen)
|
||||
rom_mask = nCpsQSamLen - 1;
|
||||
rom_mask = nCpsQSamMask ? nCpsQSamMask : nCpsQSamLen - 1;
|
||||
|
||||
if (! rom_mask)
|
||||
return 0; // no ROM loaded
|
||||
@@ -765,7 +765,7 @@ void QscSetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
|
||||
QsndOutputDir[nIndex] = nRouteDir;
|
||||
}
|
||||
|
||||
INT32 QscScan(INT32 nAction)
|
||||
INT32 QscScan(INT32 nAction, INT32 bScanHistory)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
char szName[16];
|
||||
@@ -778,8 +778,8 @@ INT32 QscScan(INT32 nAction)
|
||||
ba.szName = szName;
|
||||
BurnAcb(&ba);
|
||||
|
||||
if (CpsXmvSixEnabled) {
|
||||
// xmvsf3v3: the resampler too, so its states replay exactly (other games' states keep their size)
|
||||
if (bScanHistory) {
|
||||
// Preserve resampler history when replaying a saved frame.
|
||||
SCAN_VAR(nDelta);
|
||||
SCAN_VAR(nPos);
|
||||
SCAN_VAR(interpolate_buffer);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "cps.h"
|
||||
// QSound - Z80
|
||||
|
||||
INT32 nQsndZ80Clock = 8000000;
|
||||
INT32 nQsndZBankOffset = 0x8000;
|
||||
|
||||
static INT32 nQsndZBank = 0;
|
||||
static UINT8 QscCmd[2] = {0, 0};
|
||||
|
||||
@@ -10,7 +13,7 @@ static INT32 QsndZBankMap()
|
||||
UINT32 nOff;
|
||||
UINT8* Bank;
|
||||
nOff = nQsndZBank << 14;
|
||||
nOff += (Cps2Turbo) ? 0x10000 : 0x8000; // sfz3mix .22 z80 rom stored in mame memmap format (banks start at 0x10000, instead of 0x8000 like fbneo)
|
||||
nOff += nQsndZBankOffset;
|
||||
|
||||
if (Cps1Qs == 0) {
|
||||
if (nOff + 0x4000 > nCpsZRomLen) { // End of bank is out of range
|
||||
@@ -52,10 +55,7 @@ void __fastcall QsndZWrite(UINT16 a, UINT8 d)
|
||||
}
|
||||
if (a == 0xd003) {
|
||||
INT32 nNewBank = d & 0x0f;
|
||||
if (nQsndZBank != nNewBank) {
|
||||
nQsndZBank = nNewBank;
|
||||
QsndZBankMap();
|
||||
}
|
||||
QsndZSetBank(nNewBank);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +119,30 @@ INT32 QsndZInit()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QsndZSetBank(INT32 nBank)
|
||||
{
|
||||
if (nQsndZBank != nBank) {
|
||||
nQsndZBank = nBank;
|
||||
QsndZBankMap();
|
||||
}
|
||||
}
|
||||
|
||||
INT32 QsndZGetBank()
|
||||
{
|
||||
return nQsndZBank;
|
||||
}
|
||||
|
||||
void QsndZReset()
|
||||
{
|
||||
nQsndZBank = 0;
|
||||
QsndZBankMap();
|
||||
QscCmd[0] = QscCmd[1] = 0;
|
||||
}
|
||||
|
||||
INT32 QsndZExit()
|
||||
{
|
||||
nQsndZ80Clock = 8000000;
|
||||
nQsndZBankOffset = 0x8000;
|
||||
ZetExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// 0x810000-0x81ffff 64KB of extra work RAM, each 68000 word stored high byte first
|
||||
// The ROMs also mark the mini portraits on the HUD so that this board can draw them in the
|
||||
// fighter's chosen colour (one of eighteen), decoded from the colour table in the program ROM.
|
||||
// Nothing here is used by any other game: cps_rw.cpp only enables it for the 3v3 drivers.
|
||||
// Enabled by the 3v3 drivers in d_cps2_custom.cpp.
|
||||
|
||||
#ifndef XMVSF3V3_H
|
||||
#define XMVSF3V3_H
|
||||
|
||||
@@ -512,6 +512,21 @@ static struct BurnRomInfo sfiii2hRomDesc[] = {
|
||||
STD_ROM_PICK(sfiii2h)
|
||||
STD_ROM_FN(sfiii2h)
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Street Fighter III 2nd Impact: Giant Attack (Asia 970930)
|
||||
// ---------------------------------------------------------
|
||||
static struct BurnRomInfo sfiii2aRomDesc[] = {
|
||||
|
||||
{ "sfiii2_asia.29f400.u2", 0x080000, 0x4518d589, BRF_ESS | BRF_BIOS }, // SH-2 Bios
|
||||
|
||||
#if !defined ROM_VERIFY
|
||||
SFIII2_970930_FLASH
|
||||
#endif
|
||||
};
|
||||
|
||||
STD_ROM_PICK(sfiii2a)
|
||||
STD_ROM_FN(sfiii2a)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Street Fighter III 2nd Impact: Giant Attack (Asia 970930, NO CD)
|
||||
// ----------------------------------------------------------------
|
||||
@@ -1718,6 +1733,16 @@ struct BurnDriver BurnDrvSfiii2h = {
|
||||
384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvSfiii2a = {
|
||||
"sfiii2a", "sfiii2", NULL, NULL, "1997",
|
||||
"Street Fighter III 2nd Impact: Giant Attack (Asia 970930)\0", NULL, "Capcom", "CPS-3",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE | BDF_HISCORE_SUPPORTED, 2, HARDWARE_CAPCOM_CPS3, GBF_VSFIGHT, FBF_SF,
|
||||
NULL, sfiii2aRomInfo, sfiii2aRomName, NULL, NULL, NULL, NULL, cps3InputInfo, sfiiiwideasiaDIPInfo,
|
||||
sfiii2Init, cps3Exit, cps3Frame, DrvCps3Draw, cps3Scan, &cps3_palette_change, 0x40000,
|
||||
384, 224, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvSfiii2n = {
|
||||
"sfiii2n", "sfiii2", NULL, NULL, "1997",
|
||||
"Street Fighter III 2nd Impact: Giant Attack (Asia 970930, NO CD)\0", NULL, "Capcom", "CPS-3",
|
||||
|
||||
@@ -36,6 +36,7 @@ static UINT8 *DrvSprBuf1;
|
||||
static UINT8 *DrvZ80RAM;
|
||||
|
||||
static UINT32 *DrvPalette;
|
||||
static UINT16 *DrvTmpDraw[3]; // mutantf alpha temp. mixing
|
||||
static UINT8 DrvRecalc;
|
||||
|
||||
static UINT8 *soundlatch;
|
||||
@@ -1057,6 +1058,10 @@ static INT32 MemIndex()
|
||||
|
||||
DrvPalette = (UINT32*)Next; Next += 0x0800 * sizeof(UINT32);
|
||||
|
||||
for (INT32 i = 0; i < 3; i++) {
|
||||
DrvTmpDraw[i] = (UINT16*)Next; Next += 512 * 256 * sizeof(UINT16);
|
||||
}
|
||||
|
||||
AllRam = Next;
|
||||
|
||||
Drv68KRAM = Next; Next += 0x008000;
|
||||
@@ -1915,7 +1920,7 @@ static void cninjabl_draw_sprites()
|
||||
}
|
||||
}
|
||||
|
||||
static void mutantf_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 colbank, INT32 gfxbank)
|
||||
static void mutantf_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 colbank, INT32 gfxbank, UINT16 *dest)
|
||||
{
|
||||
UINT16 *spriteptr = (UINT16*)ram;
|
||||
|
||||
@@ -1937,7 +1942,6 @@ static void mutantf_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 colbank, INT32 gf
|
||||
while (offs != end)
|
||||
{
|
||||
INT32 x, y, sprite, colour, fx, fy, w, h, sx, sy, x_mult, y_mult;
|
||||
INT32 alpha = 0xff;
|
||||
|
||||
sprite = BURN_ENDIAN_SWAP_INT16(spriteptr[offs + 3]);
|
||||
if (!sprite)
|
||||
@@ -1962,7 +1966,6 @@ static void mutantf_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 colbank, INT32 gf
|
||||
|
||||
if (gfxbank == 4)
|
||||
{
|
||||
alpha = 0x80;
|
||||
colour &= 0xf;
|
||||
}
|
||||
|
||||
@@ -2000,8 +2003,7 @@ static void mutantf_draw_sprites(UINT8 *ram, UINT8 *gfx, INT32 colbank, INT32 gf
|
||||
{
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
// needs alpha blending...
|
||||
deco16_draw_prio_sprite(pTransDraw, gfx, sprite + y + h * x, (colour << 4) + colbank, sx + x_mult * (w-x), sy + y_mult * (h-y), fx, fy, 0);
|
||||
deco16_draw_prio_sprite(dest, gfx, sprite + y + h * x, (colour << 4) + colbank, sx + x_mult * (w-x), sy + y_mult * (h-y), fx, fy, 0);
|
||||
}
|
||||
}
|
||||
offs += inc;
|
||||
@@ -2179,6 +2181,36 @@ static INT32 Robocop2Draw()
|
||||
}
|
||||
|
||||
|
||||
static inline UINT32 mutantf_alpha_blend(UINT32 d, UINT32 s, UINT32 p)
|
||||
{
|
||||
INT32 a = 256 - p;
|
||||
|
||||
return (((((s & 0xff00ff) * p) + ((d & 0xff00ff) * a)) & 0xff00ff00) +
|
||||
((((s & 0x00ff00) * p) + ((d & 0x00ff00) * a)) & 0x00ff0000)) / 256;
|
||||
}
|
||||
|
||||
// mix a 16-bit (palette index) layer onto the 32bpp output, 0 = transparent
|
||||
static void mutantf_mix_layer(UINT16 *src, INT32 alpha)
|
||||
{
|
||||
UINT8 *dst = pBurnDraw;
|
||||
|
||||
for (INT32 y = 0; y < nScreenHeight; y++, src += nScreenWidth, dst += nBurnPitch)
|
||||
{
|
||||
UINT32 *d = (UINT32*)dst;
|
||||
|
||||
for (INT32 x = 0; x < nScreenWidth; x++)
|
||||
{
|
||||
if (src[x] == 0) continue;
|
||||
|
||||
if (alpha == 0xff) {
|
||||
d[x] = DrvPalette[src[x]];
|
||||
} else {
|
||||
d[x] = mutantf_alpha_blend(d[x], DrvPalette[src[x]], alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 MutantfDraw()
|
||||
{
|
||||
// if (DrvRecalc) {
|
||||
@@ -2195,24 +2227,54 @@ static INT32 MutantfDraw()
|
||||
if (nSpriteEnable & 2) deco16_draw_layer(1, pTransDraw, 0);
|
||||
if (nSpriteEnable & 4) deco16_draw_layer(2, pTransDraw, 0);
|
||||
|
||||
if (nBurnBpp != 4)
|
||||
{
|
||||
// no alpha @ < 32bpp
|
||||
if (deco16_priority & 1)
|
||||
{
|
||||
deco16_clear_prio_map();
|
||||
if (nBurnLayer & 1) mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3, pTransDraw);
|
||||
deco16_clear_prio_map();
|
||||
if (nBurnLayer & 2) mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4, pTransDraw);
|
||||
}
|
||||
else
|
||||
{
|
||||
deco16_clear_prio_map();
|
||||
if (nBurnLayer & 2) mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4, pTransDraw);
|
||||
deco16_clear_prio_map();
|
||||
if (nBurnLayer & 1) mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3, pTransDraw);
|
||||
}
|
||||
|
||||
if (nSpriteEnable & 8) deco16_draw_layer(0, pTransDraw, 0);
|
||||
|
||||
BurnTransferCopy(DrvPalette);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < 3; i++) memset(DrvTmpDraw[i], 0, nScreenWidth * nScreenHeight * sizeof(UINT16));
|
||||
|
||||
deco16_clear_prio_map();
|
||||
if (nBurnLayer & 1) mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3, DrvTmpDraw[0]);
|
||||
deco16_clear_prio_map();
|
||||
if (nBurnLayer & 2) mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4, DrvTmpDraw[1]);
|
||||
|
||||
if (nSpriteEnable & 8) deco16_draw_layer(0, DrvTmpDraw[2], 0);
|
||||
|
||||
BurnTransferCopy(DrvPalette);
|
||||
|
||||
if (deco16_priority & 1)
|
||||
{
|
||||
deco16_clear_prio_map();
|
||||
mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3);
|
||||
deco16_clear_prio_map();
|
||||
mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4);
|
||||
mutantf_mix_layer(DrvTmpDraw[0], 0xff);
|
||||
mutantf_mix_layer(DrvTmpDraw[1], 0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
deco16_clear_prio_map();
|
||||
mutantf_draw_sprites(DrvSprBuf1, DrvGfxROM4, 0x700, 4);
|
||||
deco16_clear_prio_map();
|
||||
mutantf_draw_sprites(DrvSprBuf, DrvGfxROM3, 0x100, 3);
|
||||
mutantf_mix_layer(DrvTmpDraw[1], 0x80);
|
||||
mutantf_mix_layer(DrvTmpDraw[0], 0xff);
|
||||
}
|
||||
|
||||
if (nSpriteEnable & 8) deco16_draw_layer(0, pTransDraw, 0);
|
||||
|
||||
BurnTransferCopy(DrvPalette);
|
||||
mutantf_mix_layer(DrvTmpDraw[2], 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4590,7 +4590,10 @@ static void TmntDecodeTitleSample()
|
||||
val = (val >> 3) & (0x3ff);
|
||||
val -= 0x200;
|
||||
|
||||
val <<= (expo-3);
|
||||
// expo-3 can be negative; a negative left-shift is undefined behaviour
|
||||
// (produced garbage spikes on arm64). Shift right for the negative case.
|
||||
INT32 sh = expo - 3;
|
||||
if (sh >= 0) val <<= sh; else val >>= (-sh);
|
||||
|
||||
DrvTitleSample[i] = val;
|
||||
}
|
||||
@@ -5892,7 +5895,7 @@ static void RenderTitleSample(INT16 *pSoundBuf, INT32 nLength)
|
||||
{
|
||||
double Addr = TitleSamplePos;
|
||||
double Step = (double)20000 / nBurnSoundRate;
|
||||
|
||||
|
||||
for (INT32 i = 0; i < nLength; i += 2) {
|
||||
if (Addr > 0x3ffff) break;
|
||||
INT16 Sample = DrvTitleSample[(INT32)Addr];
|
||||
|
||||
@@ -38677,10 +38677,10 @@ struct BurnDriver BurnDrvmd_bioblade = {
|
||||
&bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
// Black Tiger (HB, v1.9.1)
|
||||
// Black Tiger (HB, v1.9.3)
|
||||
// https://rester159.itch.io/black-tiger-md
|
||||
static struct BurnRomInfo md_blacktigerRomDesc[] = {
|
||||
{ "Black Tiger v1.9.1 (2026)(rester159).bin", 4194304, 0xa1b19794, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
{ "Black Tiger v1.9.3 (2026)(rester159).bin", 4194304, 0xe5debe42, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(md_blacktiger)
|
||||
@@ -38688,7 +38688,7 @@ STD_ROM_FN(md_blacktiger)
|
||||
|
||||
struct BurnDriver BurnDrvmd_blacktiger = {
|
||||
"md_blacktiger", NULL, NULL, NULL, "2026",
|
||||
"Black Tiger (HB, v1.9.1)\0", NULL, "rester159", "Genesis / Mega Drive",
|
||||
"Black Tiger (HB, v1.9.3)\0", NULL, "rester159", "Genesis / Mega Drive",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HOMEBREW, 1, HARDWARE_SEGA_MEGADRIVE, GBF_PLATFORM | GBF_RUNGUN, 0,
|
||||
MegadriveGetZipName, md_blacktigerRomInfo, md_blacktigerRomName, NULL, NULL, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo,
|
||||
@@ -42625,10 +42625,10 @@ struct BurnDriver BurnDrvmd_pandajump = {
|
||||
&bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
// Pang (DavidGames) (HB, Beta v1.03)
|
||||
// Pang (DavidGames) (HB, v1.00)
|
||||
// https://davidsgame.itch.io/pang-md
|
||||
static struct BurnRomInfo md_pangRomDesc[] = {
|
||||
{ "Pang Beta v1.03 (2026)(DavidGames).bin", 1310720, 0xbdd4517a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
{ "Pang v1.00 (2026)(DavidGames).bin", 1310720, 0x2d816dcb, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(md_pang)
|
||||
@@ -42636,7 +42636,7 @@ STD_ROM_FN(md_pang)
|
||||
|
||||
struct BurnDriver BurnDrvmd_pang = {
|
||||
"md_pang", NULL, NULL, NULL, "2026",
|
||||
"Pang (DavidGames) (HB, Beta v1.03)\0", NULL, "DavidGames", "Genesis / Mega Drive",
|
||||
"Pang (DavidGames) (HB, v1.00)\0", NULL, "DavidGames", "Genesis / Mega Drive",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HOMEBREW, 2, HARDWARE_SEGA_MEGADRIVE, GBF_ACTION, 0,
|
||||
MegadriveGetZipName, md_pangRomInfo, md_pangRomName, NULL, NULL, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo,
|
||||
@@ -42644,10 +42644,10 @@ struct BurnDriver BurnDrvmd_pang = {
|
||||
&bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
// Pang (Oldschool Is Beautiful) (HB, Beta 3)
|
||||
// Pang (Oldschool Is Beautiful) (HB, v1.00)
|
||||
// https://mlouvet.itch.io/pang-megadrive
|
||||
static struct BurnRomInfo md_pangoibRomDesc[] = {
|
||||
{ "Pang Beta 3 (2026)(Oldschool Is Beautiful).bin", 3877096, 0xa789941b, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
{ "Pang v1.00 (2026)(Oldschool Is Beautiful).bin", 3909708, 0x2022a547, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(md_pangoib)
|
||||
@@ -42655,7 +42655,7 @@ STD_ROM_FN(md_pangoib)
|
||||
|
||||
struct BurnDriver BurnDrvmd_pangoib = {
|
||||
"md_pangoib", NULL, NULL, NULL, "2026",
|
||||
"Pang (Oldschool Is Beautiful) (HB, Beta 3)\0", NULL, "Oldschool Is Beautiful", "Genesis / Mega Drive",
|
||||
"Pang (Oldschool Is Beautiful) (HB, v1.00)\0", NULL, "Oldschool Is Beautiful", "Genesis / Mega Drive",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HOMEBREW, 2, HARDWARE_SEGA_MEGADRIVE, GBF_ACTION, 0,
|
||||
MegadriveGetZipName, md_pangoibRomInfo, md_pangoibRomName, NULL, NULL, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo,
|
||||
@@ -42952,10 +42952,10 @@ struct BurnDriver BurnDrvmd_papriumunlck = {
|
||||
&bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
// Parasol Stars (HB, v1.0 RC3)
|
||||
// Parasol Stars (HB, v1.0.2)
|
||||
// https://mlouvet.itch.io/parasol-stars-megadrive-genesis
|
||||
static struct BurnRomInfo md_parasolRomDesc[] = {
|
||||
{ "Parasol Stars v1.0 RC3 (2026)(Oldschool Is Beautiful).bin", 4194304, 0x181b816a, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
{ "Parasol Stars v1.0.2 (2026)(Oldschool Is Beautiful).bin", 4194304, 0x72fc1b17, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(md_parasol)
|
||||
@@ -42963,7 +42963,7 @@ STD_ROM_FN(md_parasol)
|
||||
|
||||
struct BurnDriver BurnDrvmd_parasol = {
|
||||
"md_parasol", NULL, NULL, NULL, "2026",
|
||||
"Parasol Stars (HB, v1.0 RC3)\0", NULL, "Oldschool Is Beautiful", "Genesis / Mega Drive",
|
||||
"Parasol Stars (HB, v1.0.2)\0", NULL, "Oldschool Is Beautiful", "Genesis / Mega Drive",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HOMEBREW, 2, HARDWARE_SEGA_MEGADRIVE, GBF_PLATFORM, 0,
|
||||
MegadriveGetZipName, md_parasolRomInfo, md_parasolRomName, NULL, NULL, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo,
|
||||
@@ -44619,10 +44619,10 @@ struct BurnDriver BurnDrvmd_threestooges = {
|
||||
&bMegadriveRecalcPalette, 0x100, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
// Tiger Road (hombreimaginario) (HB, 2026-10-23)
|
||||
// Tiger Road (hombreimaginario) (HB, 2026-10-26)
|
||||
// https://hombreimaginario.itch.io/tiger-road-md
|
||||
static struct BurnRomInfo md_tigeroadRomDesc[] = {
|
||||
{ "Tiger Road 2026-10-23 (2026)(hombreimaginario).bin", 2490368, 0x8db153ab, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
{ "Tiger Road 2026-10-26 (2026)(hombreimaginario).bin", 2490368, 0x98decaf0, BRF_PRG | SEGA_MD_ROM_LOAD16_WORD_SWAP | SEGA_MD_ROM_OFFS_000000 },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(md_tigeroad)
|
||||
@@ -44630,7 +44630,7 @@ STD_ROM_FN(md_tigeroad)
|
||||
|
||||
struct BurnDriver BurnDrvmd_tigeroad = {
|
||||
"md_tigeroad", NULL, NULL, NULL, "2026",
|
||||
"Tiger Road (hombreimaginario) (HB, 2026-10-23)\0", NULL, "hombreimaginario", "Genesis / Mega Drive",
|
||||
"Tiger Road (hombreimaginario) (HB, 2026-10-26)\0", NULL, "hombreimaginario", "Genesis / Mega Drive",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_HOMEBREW, 1, HARDWARE_SEGA_MEGADRIVE, GBF_PLATFORM | GBF_SCRFIGHT, 0,
|
||||
MegadriveGetZipName, md_tigeroadRomInfo, md_tigeroadRomName, NULL, NULL, NULL, NULL, MegadriveInputInfo, MegadriveDIPInfo,
|
||||
|
||||
@@ -12562,7 +12562,7 @@ struct BurnDriver BurnDrvPulstar = {
|
||||
};
|
||||
|
||||
|
||||
// Pulstar Aegis (Hack)
|
||||
// Pulstar Aegis (Hack, v1.0.0)
|
||||
// https://github.com/Boomchil/neo-geo-romhacks/tree/main/public/patches/pulstar
|
||||
static struct BurnRomInfo pulstaraeRomDesc[] = {
|
||||
{ "089-p1ae.p1", 0x100000, 0xdcb02236, 1 | BRF_ESS | BRF_PRG }, // 0 68K code / mask rom TC538200
|
||||
@@ -12590,7 +12590,7 @@ STD_ROM_FN(pulstarae)
|
||||
|
||||
struct BurnDriver BurnDrvPulstarae = {
|
||||
"pulstarae", "pulstar", "neogeo", NULL, "2026",
|
||||
"Pulstar Aegis (Hack)\0", NULL, "Boomchil", "Neo Geo MVS",
|
||||
"Pulstar Aegis (Hack, v1.0.0)\0", NULL, "Boomchil", "Neo Geo MVS",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_HORSHOOT, 0,
|
||||
NULL, pulstaraeRomInfo, pulstaraeRomName, NULL, NULL, NULL, NULL, neogeoInputInfo, neogeoDIPInfo,
|
||||
@@ -12745,7 +12745,7 @@ struct BurnDriver BurnDrvWjammers = {
|
||||
};
|
||||
|
||||
|
||||
// Windjammers / Flying Power Disc (Endless Breeze, Hack, v1.2.0)
|
||||
// Windjammers / Flying Power Disc - Endless Breeze (Hack, v1.2.0)
|
||||
// https://github.com/Boomchil/neo-geo-romhacks/tree/main/public/patches/wjammers
|
||||
|
||||
static struct BurnRomInfo wjammebRomDesc[] = {
|
||||
@@ -12771,7 +12771,7 @@ STD_ROM_FN(wjammeb)
|
||||
|
||||
struct BurnDriver BurnDrvWjammeb = {
|
||||
"wjammeb", "wjammers", "neogeo", NULL, "2025-26",
|
||||
"Windjammers / Flying Power Disc (Endless Breeze, Hack, v1.2.0)\0", NULL, "Boomchil", "Neo Geo MVS",
|
||||
"Windjammers / Flying Power Disc - Endless Breeze (Hack, v1.2.0)\0", NULL, "Boomchil", "Neo Geo MVS",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 2, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_SNK_NEOGEO, GBF_SPORTSMISC, 0,
|
||||
NULL, wjammebRomInfo, wjammebRomName, NULL, NULL, NULL, NULL, neogeoInputInfo, neogeoDIPInfo,
|
||||
@@ -28294,7 +28294,7 @@ struct BurnDriver BurnDrvRobocopi = {
|
||||
BDF_GAME_WORKING | BDF_DEMO, 1, HARDWARE_SNK_NEOGEO, GBF_MISC, 0,
|
||||
NULL, robocopiRomInfo, robocopiRomName, NULL, NULL, NULL, NULL, neogeoInputInfo, neogeouniDIPInfo,
|
||||
NeoInit, NeoExit, NeoFrame, NeoRender, NeoScan, &NeoRecalcPalette,
|
||||
0x1000, 304, 224, 4, 3
|
||||
0x1000, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
|
||||
@@ -30444,7 +30444,7 @@ struct BurnDriver BurnDrvKarnovng = {
|
||||
// Maiya: Super Nature Girl (HB, v4)
|
||||
|
||||
static struct BurnRomInfo maiyaRomDesc[] = {
|
||||
{ "maiya-p1.p1", 0x080000, 0x5fe28a51, 1 | BRF_ESS | BRF_PRG }, // 0 68K code
|
||||
{ "maiya-p1.p1", 0x080000, 0xecef6baa, 1 | BRF_ESS | BRF_PRG }, // 0 68K code
|
||||
|
||||
{ "maiya-s1.s1", 0x020000, 0x5c7951e1, 2 | BRF_GRA }, // 1 Text layer tiles
|
||||
|
||||
|
||||
@@ -14699,7 +14699,27 @@ struct BurnDriver BurnDrvnes_aliensmash = {
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
};
|
||||
|
||||
// All Hell Unleashed - Ultimate Edition (HB)
|
||||
// https://8bitslasher.itch.io/ahu
|
||||
static struct BurnRomInfo nes_allhellunlueRomDesc[] = {
|
||||
{ "All Hell Unleashed - Ultimate Edition (2025-26)(Fista Productions).nes", 524304, 0x205da9ad, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(nes_allhellunlue)
|
||||
STD_ROM_FN(nes_allhellunlue)
|
||||
|
||||
struct BurnDriver BurnDrvnes_allhellunlue = {
|
||||
"nes_allhellunlue", NULL, NULL, NULL, "2025-26",
|
||||
"All Hell Unleashed - Ultimate Edition (HB)\0", NULL, "Fista Productions", "NES / Famicom",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_NES, GBF_SCRFIGHT | GBF_VSFIGHT, 0,
|
||||
NESGetZipName, nes_allhellunlueRomInfo, nes_allhellunlueRomName, NULL, NULL, NULL, NULL, NESInputInfo, NESDIPInfo,
|
||||
NESInit, NESExit, NESFrame, NESDraw, NESScan, &NESRecalc, 0x40,
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
};
|
||||
|
||||
// All Hell Unleashed (HB, v6.66)
|
||||
// https://8bitslasher.itch.io/ahu
|
||||
static struct BurnRomInfo nes_allhellunl666RomDesc[] = {
|
||||
{ "All Hell Unleashed v6.66 (2025)(Fista Productions).nes", 524304, 0x4203e09a, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
@@ -14708,16 +14728,17 @@ STD_ROM_PICK(nes_allhellunl666)
|
||||
STD_ROM_FN(nes_allhellunl666)
|
||||
|
||||
struct BurnDriver BurnDrvnes_allhellunl666 = {
|
||||
"nes_allhellunl666", NULL, NULL, NULL, "2025",
|
||||
"nes_allhellunl666", "nes_allhellunlue", NULL, NULL, "2025",
|
||||
"All Hell Unleashed (HB, v6.66)\0", NULL, "Fista Productions", "NES / Famicom",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_NES, GBF_SCRFIGHT | GBF_VSFIGHT, 0,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HOMEBREW, 1, HARDWARE_NES, GBF_SCRFIGHT | GBF_VSFIGHT, 0,
|
||||
NESGetZipName, nes_allhellunl666RomInfo, nes_allhellunl666RomName, NULL, NULL, NULL, NULL, NESInputInfo, NESDIPInfo,
|
||||
NESInit, NESExit, NESFrame, NESDraw, NESScan, &NESRecalc, 0x40,
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
};
|
||||
|
||||
// All Hell Unleashed (HB)
|
||||
// https://8bitslasher.itch.io/ahu
|
||||
static struct BurnRomInfo nes_allhellunlRomDesc[] = {
|
||||
{ "All Hell Unleashed (2025)(Fista Productions).nes", 524304, 0x2f78164f, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
@@ -14726,7 +14747,7 @@ STD_ROM_PICK(nes_allhellunl)
|
||||
STD_ROM_FN(nes_allhellunl)
|
||||
|
||||
struct BurnDriver BurnDrvnes_allhellunl = {
|
||||
"nes_allhellunl", "nes_allhellunl666", NULL, NULL, "2025",
|
||||
"nes_allhellunl", "nes_allhellunlue", NULL, NULL, "2025",
|
||||
"All Hell Unleashed (HB)\0", NULL, "Fista Productions", "NES / Famicom",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HOMEBREW, 1, HARDWARE_NES, GBF_SCRFIGHT | GBF_VSFIGHT, 0,
|
||||
@@ -14898,6 +14919,24 @@ struct BurnDriver BurnDrvnes_ambersa = {
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
};
|
||||
|
||||
// Angry Video Game Nerd 8-bit, The (HB)
|
||||
static struct BurnRomInfo nes_angrynerdRomDesc[] = {
|
||||
{ "Angry Video Game Nerd 8-bit, The (2025)(Retroware - Mega Cat Studios).nes", 786448, 0xfd8ddfb7, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(nes_angrynerd)
|
||||
STD_ROM_FN(nes_angrynerd)
|
||||
|
||||
struct BurnDriver BurnDrvnes_angrynerd = {
|
||||
"nes_angrynerd", NULL, NULL, NULL, "2025",
|
||||
"Angry Video Game Nerd 8-bit, The (HB)\0", NULL, "Retroware - Mega Cat Studios", "NES / Famicom",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_NES, GBF_PLATFORM | GBF_RUNGUN, 0,
|
||||
NESGetZipName, nes_angrynerdRomInfo, nes_angrynerdRomName, NULL, NULL, NULL, NULL, NESInputInfo, NESDIPInfo,
|
||||
NESInit, NESExit, NESFrame, NESDraw, NESScan, &NESRecalc, 0x40,
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT
|
||||
};
|
||||
|
||||
// Anguna: Scourge of the Goblin King (HB)
|
||||
static struct BurnRomInfo nes_angunaRomDesc[] = {
|
||||
{ "Anguna - Scourge of the Goblin King (2021)(The 6502 Collective).nes", 524304, 0x1119efff, BRF_ESS | BRF_PRG },
|
||||
@@ -21542,7 +21581,7 @@ struct BurnDriver BurnDrvnes_machinecave = {
|
||||
// Mad Mix Game R (HB)
|
||||
// https://enriqueggalvez.itch.io/mad-mix-game-r
|
||||
static struct BurnRomInfo nes_madmixgrRomDesc[] = {
|
||||
{ "Mad Mix Game R (2026)(Magic Games).nes", 2097168, 0x58702f7d, BRF_ESS | BRF_PRG },
|
||||
{ "Mad Mix Game R (2026)(Magic Games).nes", 2097168, 0xbb5d8cc7, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(nes_madmixgr)
|
||||
|
||||
+1434
-92
File diff suppressed because it is too large.
Load diff
@@ -221,7 +221,7 @@ static struct BurnInputInfo GrainbowInputList[] = {
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2" },
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3" },
|
||||
|
||||
{"P3 Start", BIT_DIGITAL, DrvJoy1 + 8, "p3 start" },
|
||||
{"P3 Start", BIT_DIGITAL, DrvJoy3 + 8, "p3 start" },
|
||||
{"P3 Up", BIT_DIGITAL, DrvJoy2 + 0, "p3 up" },
|
||||
{"P3 Down", BIT_DIGITAL, DrvJoy2 + 1, "p3 down" },
|
||||
{"P3 Left", BIT_DIGITAL, DrvJoy2 + 2, "p3 left" },
|
||||
@@ -230,7 +230,7 @@ static struct BurnInputInfo GrainbowInputList[] = {
|
||||
{"P3 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p3 fire 2" },
|
||||
{"P3 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p3 fire 3" },
|
||||
|
||||
{"P4 Start", BIT_DIGITAL, DrvJoy1 + 9, "p4 start" },
|
||||
{"P4 Start", BIT_DIGITAL, DrvJoy3 + 9, "p4 start" },
|
||||
{"P4 Up", BIT_DIGITAL, DrvJoy2 + 8, "p4 up" },
|
||||
{"P4 Down", BIT_DIGITAL, DrvJoy2 + 9, "p4 down" },
|
||||
{"P4 Left", BIT_DIGITAL, DrvJoy2 + 10, "p4 left" },
|
||||
|
||||
@@ -4848,6 +4848,69 @@ struct BurnDriver BurnDrvValkyrie = {
|
||||
};
|
||||
|
||||
|
||||
// Valkyrie no Densetsu (Hack, English Translation from Namco Museum Vol. 5)
|
||||
// https://github.com/SpiralBrad/valkyrie-no-densetsu-english
|
||||
|
||||
static struct BurnRomInfo valkyrienmv5RomDesc[] = {
|
||||
{ "wd1mpr0.bin", 0x20000, 0xf6e93a8c, 0x01 | BRF_PRG | BRF_ESS }, // 0 Main 68K Code
|
||||
{ "wd1mpr1.bin", 0x20000, 0x0f496013, 0x01 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "wd1spr0.bin", 0x10000, 0xb2398321, 0x02 | BRF_PRG | BRF_ESS }, // 2 Sub 68K Code
|
||||
{ "wd1spr1.bin", 0x10000, 0x38dba897, 0x02 | BRF_PRG | BRF_ESS }, // 3
|
||||
|
||||
{ "wd1snd0.bin", 0x20000, 0xd0fbf58b, 0x03 | BRF_PRG | BRF_ESS }, // 4 M6809 Code
|
||||
|
||||
#if !defined ROM_VERIFY
|
||||
{ "sys2mcpu.bin", 0x02000, 0xa342a97e, 0x04 | BRF_PRG | BRF_ESS }, // 5 HD68705 Code
|
||||
#endif
|
||||
{ "sys2c65c.bin", 0x08000, 0xa5b2a4ff, 0x04 | BRF_PRG | BRF_ESS }, // 6
|
||||
|
||||
{ "wdobj0.bin", 0x40000, 0xe8089451, 0x05 | BRF_GRA }, // 7 Sprites
|
||||
{ "wdobj1.bin", 0x40000, 0x7ca65666, 0x05 | BRF_GRA }, // 8
|
||||
{ "wdobj2.bin", 0x40000, 0x7c159407, 0x05 | BRF_GRA }, // 9
|
||||
{ "wdobj3.bin", 0x40000, 0x649f8760, 0x05 | BRF_GRA }, // 10
|
||||
{ "wdobj4.bin", 0x40000, 0x7ca39ae7, 0x05 | BRF_GRA }, // 11
|
||||
{ "wdobj5.bin", 0x40000, 0x9ead2444, 0x05 | BRF_GRA }, // 12
|
||||
{ "wdobj6.bin", 0x40000, 0x9fa2ea21, 0x05 | BRF_GRA }, // 13
|
||||
{ "wdobj7.bin", 0x40000, 0x66e07a36, 0x05 | BRF_GRA }, // 14
|
||||
|
||||
{ "wdchr0.bin", 0x20000, 0xdebb0116, 0x06 | BRF_GRA }, // 15 Layer Tiles
|
||||
{ "wdchr1.bin", 0x20000, 0x8a1431e8, 0x06 | BRF_GRA }, // 16
|
||||
{ "wdchr2.bin", 0x20000, 0x62f75f69, 0x06 | BRF_GRA }, // 17
|
||||
{ "wdchr3.bin", 0x20000, 0xcc43bbe7, 0x06 | BRF_GRA }, // 18
|
||||
{ "wdchr4.bin", 0x20000, 0x2f73d05e, 0x06 | BRF_GRA }, // 19
|
||||
{ "wdchr5.bin", 0x20000, 0xb632b2ec, 0x06 | BRF_GRA }, // 20
|
||||
|
||||
{ "wdroz0.bin", 0x20000, 0xf776bf66, 0x07 | BRF_GRA }, // 21 Roz Layer Tiles
|
||||
{ "wdroz1.bin", 0x20000, 0xc1a345c3, 0x07 | BRF_GRA }, // 22
|
||||
{ "wdroz2.bin", 0x20000, 0x28ffb44a, 0x07 | BRF_GRA }, // 23
|
||||
{ "wdroz3.bin", 0x20000, 0x7e77b46d, 0x07 | BRF_GRA }, // 24
|
||||
|
||||
{ "wdshape.bin", 0x20000, 0x3b5e0249, 0x08 | BRF_GRA }, // 25 Layer Tiles Mask Data
|
||||
|
||||
{ "wd1dat0.13s", 0x20000, 0xea209f48, 0x09 | BRF_PRG | BRF_ESS }, // 26 Shared 68K Data
|
||||
{ "wd1dat1.13p", 0x20000, 0x04b48ada, 0x09 | BRF_PRG | BRF_ESS }, // 27
|
||||
|
||||
{ "wd1voi1.bin", 0x40000, 0xf1ace193, 0x0a | BRF_SND }, // 28 C140 Samples Samples
|
||||
{ "wd1voi2.bin", 0x20000, 0xe95c5cf3, 0x0a | BRF_SND }, // 29
|
||||
|
||||
{ "valkyrie.nv", 0x02000, 0xd5ce4069, 0x0b | BRF_PRG | BRF_ESS}, // 30 nvram
|
||||
};
|
||||
|
||||
STD_ROM_PICK(valkyrienmv5)
|
||||
STD_ROM_FN(valkyrienmv5)
|
||||
|
||||
struct BurnDriver BurnDrvValkyrienmv5 = {
|
||||
"valkyrienmv5", "valkyrie", NULL, NULL, "2026",
|
||||
"Valkyrie no Densetsu (Hack, English Translation from Namco Museum Vol. 5)\0", NULL, "hack (SpiralBrad)", "System 2",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0,
|
||||
NULL, valkyrienmv5RomInfo, valkyrienmv5RomName, NULL, NULL, NULL, NULL, DefaultInputInfo, DefaultDIPInfo,
|
||||
ValkyrieInit, Namcos2Exit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x4000,
|
||||
224, 288, 3, 4
|
||||
};
|
||||
|
||||
|
||||
// Rolling Thunder 2
|
||||
|
||||
static struct BurnRomInfo rthun2RomDesc[] = {
|
||||
|
||||
@@ -3635,6 +3635,24 @@ struct BurnDriver BurnDrvngpc_cavitm = {
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Civilisation (HB)
|
||||
static struct BurnRomInfo ngpc_civilisationRomDesc[] = {
|
||||
{ "Civilisation (2026)(Chris Ahchay).ngp", 2097152, 0x9392c0d0, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
};
|
||||
|
||||
STDROMPICKEXT(ngpc_civilisation, ngpc_civilisation, ngpc_ngp)
|
||||
STD_ROM_FN(ngpc_civilisation)
|
||||
|
||||
struct BurnDriver BurnDrvngpc_civilisation = {
|
||||
"ngp_civilisation", NULL, "ngp_ngp", NULL, "2026",
|
||||
"Civilisation (HB)\0", NULL, "Chris Ahchay", "NeoGeo Pocket Color",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SNK_NGPC, GBF_STRATEGY, 0,
|
||||
NgpGetZipName, ngpc_civilisationRomInfo, ngpc_civilisationRomName, NULL, NULL, NULL, NULL, NgpInputInfo, NgpDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, k1geDraw, DrvScan, &BurnRecalc, 0x1000,
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Columns (HB)
|
||||
static struct BurnRomInfo ngpc_columnsRomDesc[] = {
|
||||
{ "Columns (2007)(Thor).ngp", 196608, 0x7b628e3b, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
@@ -3815,9 +3833,9 @@ struct BurnDriver BurnDrvngpc_furry = {
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Gardenia (HB, v1.4)
|
||||
// Gardenia (HB, v1.5)
|
||||
static struct BurnRomInfo ngpc_gardeniaRomDesc[] = {
|
||||
{ "Gardenia v1.4 (2026)(Chris Ahchay).ngp", 2097152, 0x6bf8b0aa, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
{ "Gardenia v1.5 (2026)(Chris Ahchay).ngp", 2097152, 0x1e8081c2, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
};
|
||||
|
||||
STDROMPICKEXT(ngpc_gardenia, ngpc_gardenia, ngpc_ngp)
|
||||
@@ -3825,7 +3843,7 @@ STD_ROM_FN(ngpc_gardenia)
|
||||
|
||||
struct BurnDriver BurnDrvngpc_gardenia = {
|
||||
"ngp_gardenia", NULL, "ngp_ngp", NULL, "2026",
|
||||
"Gardenia (HB, v1.4)\0", NULL, "Chris Ahchay", "NeoGeo Pocket Color",
|
||||
"Gardenia (HB, v1.5)\0", NULL, "Chris Ahchay", "NeoGeo Pocket Color",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SNK_NGPC, GBF_VERSHOOT, 0,
|
||||
NgpGetZipName, ngpc_gardeniaRomInfo, ngpc_gardeniaRomName, NULL, NULL, NULL, NULL, NgpInputInfo, NgpDIPInfo,
|
||||
@@ -4175,9 +4193,9 @@ struct BurnDriver BurnDrvngpc_neurasm = {
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Neo Bowling (HB, v0.9)
|
||||
// Neo Bowling (HB, v1.0)
|
||||
static struct BurnRomInfo ngpc_neobowlingRomDesc[] = {
|
||||
{ "Neo Bowling v0.9 (2026)(Hardhat Warrior).ngp", 2097152, 0x90e9e1cb, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
{ "Neo Bowling v1.0 (2026)(Hardhat Warrior).ngp", 2097152, 0xc2eb225c, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
};
|
||||
|
||||
STDROMPICKEXT(ngpc_neobowling, ngpc_neobowling, ngpc_ngp)
|
||||
@@ -4185,7 +4203,7 @@ STD_ROM_FN(ngpc_neobowling)
|
||||
|
||||
struct BurnDriver BurnDrvngpc_neobowling = {
|
||||
"ngp_neobowling", NULL, "ngp_ngp", NULL, "2026",
|
||||
"Neo Bowling (HB, v0.9)\0", NULL, "Hardhat Warrior", "NeoGeo Pocket Color",
|
||||
"Neo Bowling (HB, v1.0)\0", NULL, "Hardhat Warrior", "NeoGeo Pocket Color",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NGPC, GBF_SPORTSMISC, 0,
|
||||
NgpGetZipName, ngpc_neobowlingRomInfo, ngpc_neobowlingRomName, NULL, NULL, NULL, NULL, NgpInputInfo, NgpDIPInfo,
|
||||
@@ -4247,9 +4265,9 @@ struct BurnDriver BurnDrvngpc_neotris = {
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Over Rev (HB, v2.0)
|
||||
// Over Rev (HB, v3.0)
|
||||
static struct BurnRomInfo ngpc_overrevRomDesc[] = {
|
||||
{ "Over Rev v2.0 (2026)(Tixul).ngp", 2097152, 0xbd6dcde5, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
{ "Over Rev v3.0 (2026)(Tixul).ngp", 2097152, 0x8539834d, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
};
|
||||
|
||||
STDROMPICKEXT(ngpc_overrev, ngpc_overrev, ngpc_ngp)
|
||||
@@ -4257,7 +4275,7 @@ STD_ROM_FN(ngpc_overrev)
|
||||
|
||||
struct BurnDriver BurnDrvngpc_overrev = {
|
||||
"ngp_overrev", NULL, "ngp_ngp", NULL, "2026",
|
||||
"Over Rev (HB, v2.0)\0", NULL, "Tixul", "NeoGeo Pocket Color",
|
||||
"Over Rev (HB, v3.0)\0", NULL, "Tixul", "NeoGeo Pocket Color",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NGPC, GBF_RACING, 0,
|
||||
NgpGetZipName, ngpc_overrevRomInfo, ngpc_overrevRomName, NULL, NULL, NULL, NULL, NgpInputInfo, NgpDIPInfo,
|
||||
@@ -4355,6 +4373,24 @@ struct BurnDriver BurnDrvngpc_robotron = {
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Rogue Aces (HB)
|
||||
static struct BurnRomInfo ngpc_rogueacesRomDesc[] = {
|
||||
{ "Rogue Aces (2026)(Chris Ahchay).ngp", 2097152, 0x6ea9eb85, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
};
|
||||
|
||||
STDROMPICKEXT(ngpc_rogueaces, ngpc_rogueaces, ngpc_ngp)
|
||||
STD_ROM_FN(ngpc_rogueaces)
|
||||
|
||||
struct BurnDriver BurnDrvngpc_rogueaces = {
|
||||
"ngp_rogueaces", NULL, "ngp_ngp", NULL, "2026",
|
||||
"Rogue Aces (HB)\0", NULL, "Chris Ahchay", "NeoGeo Pocket Color",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SNK_NGPC, GBF_MULTISHOOT, 0,
|
||||
NgpGetZipName, ngpc_rogueacesRomInfo, ngpc_rogueacesRomName, NULL, NULL, NULL, NULL, NgpInputInfo, NgpDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, k1geDraw, DrvScan, &BurnRecalc, 0x1000,
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Ruptus Mini (HB)
|
||||
static struct BurnRomInfo ngpc_ruptusmRomDesc[] = {
|
||||
{ "Ruptus Mini (2025)(Inufuto).ngp", 524288, 0x09f1b098, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
@@ -4391,6 +4427,24 @@ struct BurnDriver BurnDrvngpc_samegame = {
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Shut the Box (HB, v0.1)
|
||||
static struct BurnRomInfo ngpc_shutboxRomDesc[] = {
|
||||
{ "Shut the Box v0.1 (2026)(Hardhat Warrior).ngp", 2097152, 0xe89d2a9c, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
};
|
||||
|
||||
STDROMPICKEXT(ngpc_shutbox, ngpc_shutbox, ngpc_ngp)
|
||||
STD_ROM_FN(ngpc_shutbox)
|
||||
|
||||
struct BurnDriver BurnDrvngpc_shutbox = {
|
||||
"ngp_shutbox", NULL, "ngp_ngp", NULL, "2026",
|
||||
"Shut the Box (HB, v0.1)\0", NULL, "Hardhat Warrior", "NeoGeo Pocket Color",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SNK_NGPC, GBF_BOARD, 0,
|
||||
NgpGetZipName, ngpc_shutboxRomInfo, ngpc_shutboxRomName, NULL, NULL, NULL, NULL, NgpInputInfo, NgpDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, k1geDraw, DrvScan, &BurnRecalc, 0x1000,
|
||||
160, 152, 4, 3
|
||||
};
|
||||
|
||||
// Snake (HB, v1.2)
|
||||
static struct BurnRomInfo ngpc_snakeRomDesc[] = {
|
||||
{ "Snake v1.2 (2000)(Ivan Mackintosh).ngp", 524288, 0x82510aa9, 1 | BRF_PRG | BRF_ESS }, // Cartridge
|
||||
|
||||
@@ -3502,7 +3502,7 @@ struct BurnDriver BurnSpecbarbarn2 = {
|
||||
// Barmy Burgers (48K)
|
||||
|
||||
static struct BurnRomInfo SpecBarmyburgRomDesc[] = {
|
||||
{ "Barmy Burgers 48K (1983)(Blaby Computer Games).z80", 28248, 0x138faacd, BRF_ESS | BRF_PRG },
|
||||
{ "Barmy Burgers 48K (1983)(Blaby Computer Games).tzx", 31126, 0x70455c9d, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecBarmyburg, SpecBarmyburg, Spectrum)
|
||||
@@ -6121,6 +6121,25 @@ struct BurnDriver BurnSpecCasanova = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Casey Jones (48K)
|
||||
|
||||
static struct BurnRomInfo SpecCaseyjonesRomDesc[] = {
|
||||
{ "Casey Jones 48K (1984)(Blaby Computer Games).tzx", 36421, 0xde4b4598, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecCaseyjones, SpecCaseyjones, Spectrum)
|
||||
STD_ROM_FN(SpecCaseyjones)
|
||||
|
||||
struct BurnDriver BurnSpecCaseyjones = {
|
||||
"spec_caseyjones", NULL, "spec_spectrum", NULL, "1984",
|
||||
"Casey Jones (48K)\0", NULL, "Blaby Computer Games", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_SPECTRUM, GBF_ACTION | GBF_HORSHOOT, 0,
|
||||
SpectrumGetZipName, SpecCaseyjonesRomInfo, SpecCaseyjonesRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Cashdash (48K)
|
||||
|
||||
static struct BurnRomInfo SpeccashdashRomDesc[] = {
|
||||
@@ -19594,6 +19613,25 @@ struct BurnDriver BurnSpecMindtrap = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Mine Alert (48K)
|
||||
|
||||
static struct BurnRomInfo SpecMinealertRomDesc[] = {
|
||||
{ "Mine Alert 48K (1987)(Ramon Gallastegui).tzx", 31444, 0x8d6e6afa, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecMinealert, SpecMinealert, Spectrum)
|
||||
STD_ROM_FN(SpecMinealert)
|
||||
|
||||
struct BurnDriver BurnSpecMinealert = {
|
||||
"spec_minealert", NULL, "spec_spectrum", NULL, "1987",
|
||||
"Mine Alert (48K)\0", NULL, "Ramon Gallastegui", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_SPECTRUM, GBF_MAZE, 0,
|
||||
SpectrumGetZipName, SpecMinealertRomInfo, SpecMinealertRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecQAOPSpaceDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Mined Out (48K)
|
||||
|
||||
static struct BurnRomInfo SpecMinedoutRomDesc[] = {
|
||||
@@ -19911,7 +19949,7 @@ struct BurnDriver BurnSpecMoonpatrol = {
|
||||
"spec_moonpatrol", NULL, "spec_spectrum", NULL, "1984",
|
||||
"Moon Patrol (48K)\0", NULL, "Atarisoft", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 2, HARDWARE_SPECTRUM, GBF_ACTION, 0,
|
||||
BDF_GAME_WORKING, 2, HARDWARE_SPECTRUM, GBF_ACTION | GBF_HORSHOOT, 0,
|
||||
SpectrumGetZipName, SpecMoonpatrolRomInfo, SpecMoonpatrolRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
@@ -21380,6 +21418,25 @@ struct BurnDriver BurnSpecNubowls = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Nuke Lear (48K)
|
||||
|
||||
static struct BurnRomInfo SpecNukelearRomDesc[] = {
|
||||
{ "Nuke Lear 48K (1984)(CCS).tzx", 30334, 0xf3e65284, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecNukelear, SpecNukelear, Spectrum)
|
||||
STD_ROM_FN(SpecNukelear)
|
||||
|
||||
struct BurnDriver BurnSpecNukelear = {
|
||||
"spec_nukelear", NULL, "spec_spectrum", NULL, "1984",
|
||||
"Nuke Lear (48K)\0", NULL, "CCS", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_SPECTRUM, GBF_ACTION, 0,
|
||||
SpectrumGetZipName, SpecNukelearRomInfo, SpecNukelearRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Number Painter (48K)
|
||||
|
||||
static struct BurnRomInfo SpecNumbpaintRomDesc[] = {
|
||||
@@ -32248,6 +32305,44 @@ struct BurnDriver BurnSpecViz = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Vulcan ~ The Tunisian Campaign (128K)
|
||||
|
||||
static struct BurnRomInfo SpecVulcan128RomDesc[] = {
|
||||
{ "Vulcan 128K (1986)(CCS).tzx", 53740, 0xc1299a09, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecVulcan128, SpecVulcan128, Spec128)
|
||||
STD_ROM_FN(SpecVulcan128)
|
||||
|
||||
struct BurnDriver BurnSpecVulcan128 = {
|
||||
"spec_vulcan128", NULL, "spec_spec128", NULL, "1986",
|
||||
"Vulcan ~ The Tunisian Campaign (128K)\0", NULL, "CCS", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 2, HARDWARE_SPECTRUM, GBF_STRATEGY, 0,
|
||||
SpectrumGetZipName, SpecVulcan128RomInfo, SpecVulcan128RomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecCursorKeysDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Vulcan ~ The Tunisian Campaign (48K)
|
||||
|
||||
static struct BurnRomInfo SpecVulcan48RomDesc[] = {
|
||||
{ "Vulcan 48K (1986)(CCS).tzx", 49796, 0x378fc601, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecVulcan48, SpecVulcan48, Spectrum)
|
||||
STD_ROM_FN(SpecVulcan48)
|
||||
|
||||
struct BurnDriver BurnSpecVulcan48 = {
|
||||
"spec_vulcan48", "spec_vulcan128", "spec_spectrum", NULL, "1986",
|
||||
"Vulcan ~ The Tunisian Campaign (48K)\0", NULL, "CCS", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_SPECTRUM, GBF_STRATEGY, 0,
|
||||
SpectrumGetZipName, SpecVulcan48RomInfo, SpecVulcan48RomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecCursorKeysDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Wacky Darts (48K-128K)
|
||||
|
||||
static struct BurnRomInfo SpecWackydartsRomDesc[] = {
|
||||
@@ -32516,19 +32611,19 @@ struct BurnDriver BurnSpecWhiteheat = {
|
||||
|
||||
// Who Dares Wins II (48K)
|
||||
|
||||
static struct BurnRomInfo SpecWhodareswinsiiRomDesc[] = {
|
||||
{ "Who Dares Wins II 48K (1986)(Alligata).tap", 48631, 0x02dc6931, BRF_ESS | BRF_PRG },
|
||||
static struct BurnRomInfo SpecWdwiiRomDesc[] = {
|
||||
{ "Who Dares Wins II 48K (1986)(Alligata).tzx", 48692, 0xbf14f1aa, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecWhodareswinsii, SpecWhodareswinsii, Spectrum)
|
||||
STD_ROM_FN(SpecWhodareswinsii)
|
||||
STDROMPICKEXT(SpecWdwii, SpecWdwii, Spectrum)
|
||||
STD_ROM_FN(SpecWdwii)
|
||||
|
||||
struct BurnDriver BurnSpecWhodareswinsii = {
|
||||
"spec_whodareswinsii", NULL, "spec_spectrum", NULL, "1986",
|
||||
struct BurnDriver BurnSpecWdwii = {
|
||||
"spec_wdwii", NULL, "spec_spectrum", NULL, "1986",
|
||||
"Who Dares Wins II (48K)\0", NULL, "Alligata Software", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_SPECTRUM, GBF_RUNGUN, 0,
|
||||
SpectrumGetZipName, SpecWhodareswinsiiRomInfo, SpecWhodareswinsiiRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpectrumGetZipName, SpecWdwiiRomInfo, SpecWdwiiRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
@@ -52910,6 +53005,25 @@ struct BurnDriver BurnSpecModrains = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Mine Alert 2 (128K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecMinealert2RomDesc[] = {
|
||||
{ "Mine Alert 2 128K (2026)(namco-nexgen).tap", 85093, 0x2eca386a, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecMinealert2, SpecMinealert2, Spec128)
|
||||
STD_ROM_FN(SpecMinealert2)
|
||||
|
||||
struct BurnDriver BurnSpecMinealert2 = {
|
||||
"spec_minealert2", NULL, "spec_spec128", NULL, "2026",
|
||||
"Mine Alert 2 (128K) (HB)\0", NULL, "namco/nexgen", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_MAZE | GBF_MULTISHOOT, 0,
|
||||
SpectrumGetZipName, SpecMinealert2RomInfo, SpecMinealert2RomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Minesweeper (128K) (HB, v1.03)
|
||||
|
||||
static struct BurnRomInfo SpecMinesweeper128RomDesc[] = {
|
||||
@@ -53481,10 +53595,10 @@ struct BurnDriver BurnSpecMoonpirates = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Moon Ranger (128K) (HB)
|
||||
// Moon Ranger (48K-128K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecMoonrangerRomDesc[] = {
|
||||
{ "Moon Ranger 128K (2020)(Gabriele Amore).tap", 29940, 0xd33c199a, BRF_ESS | BRF_PRG },
|
||||
{ "Moon Ranger 48K-128K (2020)(Gabriele Amore).tap", 29940, 0xd33c199a, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecMoonranger, SpecMoonranger, Spec128)
|
||||
@@ -53492,18 +53606,18 @@ STD_ROM_FN(SpecMoonranger)
|
||||
|
||||
struct BurnDriver BurnSpecMoonranger = {
|
||||
"spec_moonranger", NULL, "spec_spec128", NULL, "2020",
|
||||
"Moon Ranger (128K) (HB)\0", NULL, "Gabriele Amore", "ZX Spectrum",
|
||||
"Moon Ranger (48K-128K) (HB)\0", NULL, "Gabriele Amore", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_ACTION, 0,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_ACTION | GBF_HORSHOOT, 0,
|
||||
SpectrumGetZipName, SpecMoonrangerRomInfo, SpecMoonrangerRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecQAOPMDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Moon Ranger (128K) (HB, v2)
|
||||
// Moon Ranger (48K-128K) (HB, v2)
|
||||
|
||||
static struct BurnRomInfo SpecMoonrangerv2RomDesc[] = {
|
||||
{ "Moon Ranger v2 128K (2021)(Gabriele Amore).tap", 45527, 0xebb5c2a1, BRF_ESS | BRF_PRG },
|
||||
{ "Moon Ranger v2 48K-128K (2021)(Gabriele Amore).tap", 45527, 0xebb5c2a1, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecMoonrangerv2, SpecMoonrangerv2, Spec128)
|
||||
@@ -53511,9 +53625,9 @@ STD_ROM_FN(SpecMoonrangerv2)
|
||||
|
||||
struct BurnDriver BurnSpecMoonrangerv2 = {
|
||||
"spec_moonrangerv2", NULL, "spec_spec128", NULL, "2021",
|
||||
"Moon Ranger (128K) (HB, v2)\0", NULL, "Gabriele Amore", "ZX Spectrum",
|
||||
"Moon Ranger (48K-128K) (HB, v2)\0", NULL, "Gabriele Amore", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_ACTION, 0,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_ACTION | GBF_HORSHOOT, 0,
|
||||
SpectrumGetZipName, SpecMoonrangerv2RomInfo, SpecMoonrangerv2RomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecQAOPMDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
@@ -55571,6 +55685,25 @@ struct BurnDriver BurnSpecOure = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Outpost (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecOutpostRomDesc[] = {
|
||||
{ "Outpost 48K (2026)(usebox.net).tap", 22114, 0x2ac59251, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecOutpost, SpecOutpost, Spectrum)
|
||||
STD_ROM_FN(SpecOutpost)
|
||||
|
||||
struct BurnDriver BurnSpecOutpost = {
|
||||
"spec_outpost", NULL, "spec_spectrum", NULL, "2026",
|
||||
"Outpost (48K) (HB)\0", NULL, "usebox.net", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_PLATFORM, 0,
|
||||
SpectrumGetZipName, SpecOutpostRomInfo, SpecOutpostRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// P-47 The Freedom Fighter (128K) (Hack)
|
||||
|
||||
static struct BurnRomInfo SpecP47freedomfRomDesc[] = {
|
||||
@@ -58801,10 +58934,10 @@ struct BurnDriver BurnSpecRiverrad = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// River Raid+ (48K) (Hack, v0.2)
|
||||
// River Raid+ (48K) (Hack, v0.7)
|
||||
|
||||
static struct BurnRomInfo SpecRiveraidplusRomDesc[] = {
|
||||
{ "River Raid+ v0.2 48K (2026)(theALFEST).tap", 22554, 0x2e917c63, BRF_ESS | BRF_PRG },
|
||||
{ "River Raid+ v0.7 48K-AY (2026)(theALFEST).tap", 26652, 0x53f67db2, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecRiveraidplus, SpecRiveraidplus, Spectrum)
|
||||
@@ -58812,7 +58945,7 @@ STD_ROM_FN(SpecRiveraidplus)
|
||||
|
||||
struct BurnDriver BurnSpecRiveraidplus = {
|
||||
"spec_riveraidplus", "spec_riveraid", "spec_spectrum", NULL, "2026",
|
||||
"River Raid+ (48K) (Hack, v0.2)\0", NULL, "theALFEST", "ZX Spectrum",
|
||||
"River Raid+ (48K) (Hack, v0.7)\0", "AY Sound supported", "theALFEST", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 1, HARDWARE_SPECTRUM, GBF_VERSHOOT, 0,
|
||||
SpectrumGetZipName, SpecRiveraidplusRomInfo, SpecRiveraidplusRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
@@ -60568,10 +60701,10 @@ struct BurnDriver BurnSpecShadowfields = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Shadows of Belial (English) (128K) (HB, v1.0.4)
|
||||
// Shadows of Belial (English) (128K) (HB, v1.0.5)
|
||||
|
||||
static struct BurnRomInfo SpecShabelialenRomDesc[] = {
|
||||
{ "Shadows of Belial EN v1.0.4 128K (2016)(RetroWorks).tap", 138736, 0xcaf1f445, BRF_ESS | BRF_PRG },
|
||||
{ "Shadows of Belial EN v1.0.5 128K (2026)(RetroWorks).tap", 138687, 0x4ac79734, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecShabelialen, SpecShabelialen, Spec128)
|
||||
@@ -60579,7 +60712,7 @@ STD_ROM_FN(SpecShabelialen)
|
||||
|
||||
struct BurnDriver BurnSpecShabelialen = {
|
||||
"spec_shabelialen", NULL, "spec_spec128", NULL, "RetroWorks",
|
||||
"Shadows of Belial (English) (128K) (HB, v1.0.4)\0", NULL, "2026", "ZX Spectrum",
|
||||
"Shadows of Belial (English) (128K) (HB, v1.0.5)\0", NULL, "2026", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_PLATFORM, 0,
|
||||
SpectrumGetZipName, SpecShabelialenRomInfo, SpecShabelialenRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
@@ -60587,10 +60720,10 @@ struct BurnDriver BurnSpecShabelialen = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Shadows of Belial (Spanish) (128K) (HB, v1.0.4)
|
||||
// Shadows of Belial (Spanish) (128K) (HB, v1.0.5)
|
||||
|
||||
static struct BurnRomInfo SpecShabelialesRomDesc[] = {
|
||||
{ "Shadows of Belial ES v1.0.4 128K (2026)(RetroWorks).tap", 139295, 0x07167c28, BRF_ESS | BRF_PRG },
|
||||
{ "Shadows of Belial ES v1.0.5 128K (2026)(RetroWorks).tap", 139297, 0x2faa2142, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecShabeliales, SpecShabeliales, Spec128)
|
||||
@@ -60598,7 +60731,7 @@ STD_ROM_FN(SpecShabeliales)
|
||||
|
||||
struct BurnDriver BurnSpecShabeliales = {
|
||||
"spec_shabeliales", "spec_shabelialen", "spec_spec128", NULL, "RetroWorks",
|
||||
"Shadows of Belial (Spanish) (128K) (HB, v1.0.4)\0", NULL, "2026", "ZX Spectrum",
|
||||
"Shadows of Belial (Spanish) (128K) (HB, v1.0.5)\0", NULL, "2026", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_PLATFORM, 0,
|
||||
SpectrumGetZipName, SpecShabelialesRomInfo, SpecShabelialesRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
@@ -60606,6 +60739,44 @@ struct BurnDriver BurnSpecShabeliales = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Shadows of Belial (Portuguese) (128K) (HB, v1.0.5)
|
||||
|
||||
static struct BurnRomInfo SpecShabelialptRomDesc[] = {
|
||||
{ "Shadows of Belial PT v1.0.5 128K (2026)(RetroWorks).tap", 139372, 0xb20c499b, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecShabelialpt, SpecShabelialpt, Spec128)
|
||||
STD_ROM_FN(SpecShabelialpt)
|
||||
|
||||
struct BurnDriver BurnSpecShabelialpt = {
|
||||
"spec_shabelialpt", "spec_shabelialen", "spec_spec128", NULL, "RetroWorks",
|
||||
"Shadows of Belial (Portuguese) (128K) (HB, v1.0.5)\0", NULL, "2026", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_PLATFORM, 0,
|
||||
SpectrumGetZipName, SpecShabelialptRomInfo, SpecShabelialptRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Shadows of Belial (Russian) (128K) (HB, v1.0.5)
|
||||
|
||||
static struct BurnRomInfo SpecShabelialruRomDesc[] = {
|
||||
{ "Shadows of Belial RU v1.0.5 128K (2026)(RetroWorks).tap", 139086, 0x719f3964, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecShabelialru, SpecShabelialru, Spec128)
|
||||
STD_ROM_FN(SpecShabelialru)
|
||||
|
||||
struct BurnDriver BurnSpecShabelialru = {
|
||||
"spec_shabelialru", "spec_shabelialen", "spec_spec128", NULL, "RetroWorks",
|
||||
"Shadows of Belial (Russian) (128K) (HB, v1.0.5)\0", NULL, "2026", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_PLATFORM, 0,
|
||||
SpectrumGetZipName, SpecShabelialruRomInfo, SpecShabelialruRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Shape Shifter (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecShapeshiftRomDesc[] = {
|
||||
@@ -66382,6 +66553,25 @@ struct BurnDriver BurnSpecWhitejaguarzx = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Who Dares Wins III (128K) (HB, v1.1)
|
||||
|
||||
static struct BurnRomInfo SpecWdwiiiRomDesc[] = {
|
||||
{ "Who Dares Wins III v1.1 128K (2026)(namco-nexgen).tap", 73967, 0xb8f9cc8b, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecWdwiii, SpecWdwiii, Spec128)
|
||||
STD_ROM_FN(SpecWdwiii)
|
||||
|
||||
struct BurnDriver BurnSpecWdwiii = {
|
||||
"spec_wdwiii", NULL, "spec_spec128", NULL, "2026",
|
||||
"Who Dares Wins III (128K) (HB, v1.1)\0", NULL, "namco/nexgen", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_RUNGUN, 0,
|
||||
SpectrumGetZipName, SpecWdwiiiRomInfo, SpecWdwiiiRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
Spec128KInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Wiking - Improved Version (Polish) (128K) (Hack)
|
||||
|
||||
static struct BurnRomInfo SpecWiking128RomDesc[] = {
|
||||
@@ -66858,6 +67048,25 @@ struct BurnDriver BurnSpecXenomaze = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// XPong48 (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecXpong48RomDesc[] = {
|
||||
{ "XPong48 48K-AY (2026)(CodeBiters).tap", 32548, 0xc563401a, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecXpong48, SpecXpong48, Spectrum)
|
||||
STD_ROM_FN(SpecXpong48)
|
||||
|
||||
struct BurnDriver BurnSpecXpong48 = {
|
||||
"spec_xpong48", NULL, "spec_spectrum", NULL, "2026",
|
||||
"XPong48 (48K) (HB)\0", "AY Sound supported", "CodeBiters", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 2, HARDWARE_SPECTRUM, GBF_BALLPADDLE, 0,
|
||||
SpectrumGetZipName, SpecXpong48RomInfo, SpecXpong48RomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// X=Y=Z (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecXyzRomDesc[] = {
|
||||
@@ -67428,21 +67637,40 @@ struct BurnDriver BurnSpecZlalox = {
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Zoinho (Spanish) (48K) (HB)
|
||||
// Zoinho: No Jardim dos Tolos (Spanish) (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecZoinhoRomDesc[] = {
|
||||
{ "Zoinho 48K (2021)(Bitnamic).tap", 29137, 0xa64d5e5a, BRF_ESS | BRF_PRG },
|
||||
{ "Zoinho - No Jardim dos Tolos 48K (2021)(Bitnamic).tap", 29137, 0xa64d5e5a, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecZoinho, SpecZoinho, Spectrum)
|
||||
STD_ROM_FN(SpecZoinho)
|
||||
|
||||
struct BurnDriver BurnSpecZoinho = {
|
||||
"spec_zoinho", NULL, "spec_spectrum", NULL, "2021",
|
||||
"Zoinho (Spanish) (48K) (HB)\0", NULL, "Bitnamic", "ZX Spectrum",
|
||||
"spec_zoinho", "spec_zoinho25", "spec_spectrum", NULL, "2021",
|
||||
"Zoinho: No Jardim dos Tolos (Spanish) (48K) (HB)\0", NULL, "Bitnamic", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_ACTION | GBF_ADV, 0,
|
||||
SpectrumGetZipName, SpecZoinhoRomInfo, SpecZoinhoRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecIntf2DIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
|
||||
// Zoinho: In the Garden of the Fools (English) (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpecZoinho25RomDesc[] = {
|
||||
{ "Zoinho - In the Garden of the Fools 48K (2025)(R.C. Nunes).tap", 42058, 0x7ec6faaa, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(SpecZoinho25, SpecZoinho25, Spectrum)
|
||||
STD_ROM_FN(SpecZoinho25)
|
||||
|
||||
struct BurnDriver BurnSpecZoinho25 = {
|
||||
"spec_zoinho25", NULL, "spec_spectrum", NULL, "2025",
|
||||
"Zoinho: In the Garden of the Fools (English) (48K) (HB)\0", "Set 'Cursor Keys' to use controller", "R.C. Nunes", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_ACTION | GBF_ADV, 0,
|
||||
SpectrumGetZipName, SpecZoinhoRomInfo, SpecZoinhoRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecIntf2DIPInfo,
|
||||
SpectrumGetZipName, SpecZoinho25RomInfo, SpecZoinho25RomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecCursorKeysDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
};
|
||||
@@ -67450,7 +67678,7 @@ struct BurnDriver BurnSpecZoinho = {
|
||||
// Zombie Calavera Prologue (48K) (HB)
|
||||
|
||||
static struct BurnRomInfo SpeczcalaveraRomDesc[] = {
|
||||
{ "Zombie Calavera Prologue 48K (2010)(Mojon Twins).tap", 37966, 0x9eaf2b79, BRF_ESS | BRF_PRG },
|
||||
{ "Zombie Calavera Prologue 48K (2010)(The Mojon Twins).tzx", 38000, 0xbb2c916b, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(Speczcalavera, Speczcalavera, Spectrum)
|
||||
@@ -67460,7 +67688,7 @@ struct BurnDriver BurnSpeczcalavera = {
|
||||
"spec_zcalavera", NULL, "spec_spectrum", NULL, "2010",
|
||||
"Zombie Calavera Prologue (48K) (HB)\0", NULL, "The Mojon Twins", "ZX Spectrum",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_RUNGUN | GBF_PLATFORM, 0,
|
||||
BDF_GAME_WORKING | BDF_HOMEBREW, 1, HARDWARE_SPECTRUM, GBF_PLATFORM | GBF_RUNGUN, 0,
|
||||
SpectrumGetZipName, SpeczcalaveraRomInfo, SpeczcalaveraRomName, NULL, NULL, NULL, NULL, SpecInputInfo, SpecDIPInfo,
|
||||
SpecInit, SpecExit, SpecFrame, SpecDraw, SpecScan,
|
||||
&SpecRecalc, 0x10, 288, 224, 4, 3
|
||||
|
||||
@@ -466,9 +466,40 @@ void MultiPCMExit()
|
||||
}
|
||||
}
|
||||
|
||||
// The slot pointers (sample, LFO tables) are only valid in the process that set
|
||||
// them, a state loaded in another one (netplay) would crash. They are kept out of
|
||||
// the state and rebuilt from the slot registers, as WriteSlot sets them: reg 1
|
||||
// selects the sample, regs 6 and 7 the LFO scales (an LFO is only stepped when
|
||||
// its depth, reg & 7, is not zero).
|
||||
static void ClearSlotPointers()
|
||||
{
|
||||
for (INT32 i = 0; i < 28; i++) {
|
||||
SLOT *slot = &chip.Slots[i];
|
||||
|
||||
slot->Sample = NULL;
|
||||
slot->PLFO.table = slot->PLFO.scale = NULL;
|
||||
slot->ALFO.table = slot->ALFO.scale = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void RebuildSlotPointers()
|
||||
{
|
||||
for (INT32 i = 0; i < 28; i++) {
|
||||
SLOT *slot = &chip.Slots[i];
|
||||
|
||||
slot->Sample = chip.Samples + slot->Regs[1];
|
||||
slot->PLFO.table = PLFO_TRI;
|
||||
slot->PLFO.scale = PSCALES[slot->Regs[6] & 7];
|
||||
slot->ALFO.table = ALFO_TRI;
|
||||
slot->ALFO.scale = ASCALES[slot->Regs[7] & 7];
|
||||
}
|
||||
}
|
||||
|
||||
void MultiPCMScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
ClearSlotPointers();
|
||||
SCAN_VAR(chip);
|
||||
RebuildSlotPointers();
|
||||
}
|
||||
|
||||
void MultiPCMReset()
|
||||
|
||||
@@ -45,6 +45,8 @@ typedef struct tagIMAGE {
|
||||
#include "burner_macos.h"
|
||||
#elif defined (BUILD_SDL) || defined (BUILD_SDL2)
|
||||
#include "burner_sdl.h"
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
#include "burner_headless.h"
|
||||
#elif defined (_XBOX) && !defined(__LIBRETRO__)
|
||||
#include "burner_xbox.h"
|
||||
#elif defined(__LIBRETRO__)
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
// Platform burner header for the headless FinalBurn Neo frontend.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Declares the types, globals and frontend prototypes the shared burner code
|
||||
// expects (the headless counterpart of burner_sdl.h / burner_macos.h), without
|
||||
// any SDL or GUI dependencies. Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#ifndef BURNER_HEADLESS_PLATFORM_H
|
||||
#define BURNER_HEADLESS_PLATFORM_H
|
||||
|
||||
// Win32 type aliases the shared code relies on.
|
||||
#ifndef _WIN32
|
||||
typedef struct tagRECT
|
||||
{
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
} RECT, * PRECT, * LPRECT;
|
||||
typedef const RECT* LPCRECT;
|
||||
typedef UINT32 DWORD;
|
||||
typedef UINT8 BYTE;
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 511
|
||||
#endif
|
||||
|
||||
#ifndef __cdecl
|
||||
#define __cdecl
|
||||
#endif
|
||||
|
||||
// misc.cpp
|
||||
int SetBurnHighCol(int nDepth);
|
||||
|
||||
extern int nAppVirtualFps;
|
||||
extern bool bRunPause;
|
||||
extern bool bAppDoFast;
|
||||
extern char fpsstring[20];
|
||||
extern bool bAppShowFPS;
|
||||
extern bool bAlwaysProcessKeyboardInput;
|
||||
extern TCHAR szAppBurnVer[16];
|
||||
extern bool bAppFullscreen;
|
||||
extern bool bIntegerScale;
|
||||
extern int nWindowScale;
|
||||
extern bool bAlwaysMenu;
|
||||
extern int nGameSelect;
|
||||
extern int nFilterSelect;
|
||||
extern bool bShowAvailableOnly;
|
||||
extern bool bShowClones;
|
||||
extern int gameSelectedFromFilter;
|
||||
extern TCHAR* GetIsoPath();
|
||||
|
||||
TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int nOutSize);
|
||||
char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int nOutSize);
|
||||
|
||||
#define _TtoA(a) TCHARToANSI(a, NULL, 0)
|
||||
#define _AtoT(a) ANSIToTCHAR(a, NULL, 0)
|
||||
|
||||
bool AppProcessKeyboardInput();
|
||||
|
||||
// config
|
||||
int ConfigAppLoad();
|
||||
int ConfigAppSave();
|
||||
|
||||
// drv.cpp (headless)
|
||||
extern int bDrvOkay;
|
||||
extern char szAppRomPaths[DIRS_MAX][MAX_PATH];
|
||||
int DrvInit(int nDrvNum, bool bRestore);
|
||||
int DrvInitCallback();
|
||||
int DrvExit();
|
||||
int ProgressUpdateBurner(double dProgress, const TCHAR* pszText, bool bAbs);
|
||||
int AppError(TCHAR* szText, int bWarning);
|
||||
|
||||
// run
|
||||
extern int RunMessageLoop();
|
||||
extern int RunReset();
|
||||
|
||||
#define MESSAGE_MAX_FRAMES 180
|
||||
#define MESSAGE_MAX_LENGTH 255
|
||||
|
||||
extern UINT32 messageFrames;
|
||||
extern char lastMessage[MESSAGE_MAX_LENGTH];
|
||||
|
||||
void UpdateMessage(char* message);
|
||||
int StatedAuto(int bSave);
|
||||
|
||||
// media.cpp
|
||||
int MediaInit();
|
||||
int MediaExit();
|
||||
|
||||
// inpdipsw.cpp
|
||||
#define DIP_MAX_NAME 64
|
||||
#define MAXDIPSWITCHES 32
|
||||
#define MAXDIPOPTIONS 32
|
||||
bool setDIPSwitchOption(int dipgroup, int dipoption);
|
||||
int InpDIPSWCreate();
|
||||
void InpDIPSWResetDIPs();
|
||||
|
||||
struct GroupOfDIPSwitches
|
||||
{
|
||||
BurnDIPInfo dipSwitch;
|
||||
UINT16 DefaultDIPOption;
|
||||
UINT16 SelectedDIPOption;
|
||||
char OptionsNamesWithCheckBoxes[MAXDIPOPTIONS][DIP_MAX_NAME];
|
||||
BurnDIPInfo dipSwitchesOptions[MAXDIPOPTIONS];
|
||||
};
|
||||
|
||||
// inp_interface.cpp
|
||||
int InputInit();
|
||||
int InputExit();
|
||||
int InputMake(bool bCopy);
|
||||
|
||||
// stated.cpp
|
||||
int QuickState(int bSave);
|
||||
extern int bDrvSaveAll;
|
||||
|
||||
// stringset.cpp
|
||||
class StringSet {
|
||||
public:
|
||||
TCHAR* szText;
|
||||
int nLen;
|
||||
int __cdecl Add(TCHAR* szFormat, ...);
|
||||
int Reset();
|
||||
|
||||
StringSet();
|
||||
~StringSet();
|
||||
};
|
||||
|
||||
// support_paths.cpp
|
||||
extern TCHAR szAppListsPath[MAX_PATH];
|
||||
extern TCHAR szAppDatListsPath[MAX_PATH];
|
||||
extern TCHAR szAppArchivesPath[MAX_PATH];
|
||||
|
||||
#endif // BURNER_HEADLESS_PLATFORM_H
|
||||
@@ -0,0 +1,101 @@
|
||||
// Headless C API for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Consumed by a thin host wrapper so the emulator-side glue stays in the fork.
|
||||
// Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#ifndef BURNER_HEADLESS_H
|
||||
#define BURNER_HEADLESS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Lifecycle
|
||||
int FBHeadlessInit(void);
|
||||
void FBHeadlessExit(void);
|
||||
void FBHeadlessSetRomPath(const char *path);
|
||||
int FBHeadlessLoadDriver(const char *shortName); // e.g. "mslug"; returns 0 on success
|
||||
void FBHeadlessRunFrame(int draw);
|
||||
|
||||
// Video (filled by intf/video/headless)
|
||||
const unsigned char *FBHeadlessGetVideoBuffer(void);
|
||||
int FBHeadlessGetVideoWidth(void);
|
||||
int FBHeadlessGetVideoHeight(void);
|
||||
int FBHeadlessGetVideoPitch(void);
|
||||
int FBHeadlessGetVideoBPP(void);
|
||||
|
||||
// Audio (filled each frame by the frontend)
|
||||
int FBHeadlessGetAudioSampleRate(void);
|
||||
const short *FBHeadlessGetAudioBuffer(void);
|
||||
int FBHeadlessGetAudioFrames(void); // stereo sample frames produced last RunFrame
|
||||
|
||||
// Input: value is non-zero when pressed. code is an FBNeo input switch code.
|
||||
void FBHeadlessSetInputState(int code, int value);
|
||||
|
||||
// Frame timing / geometry (valid after a driver is loaded).
|
||||
int FBHeadlessGetFrameRate(void); // frames per second * 100 (e.g. 6000 = 60fps)
|
||||
int FBHeadlessGetAspectX(void);
|
||||
int FBHeadlessGetAspectY(void);
|
||||
|
||||
// Reset the loaded driver.
|
||||
void FBHeadlessReset(void);
|
||||
|
||||
// Save/load a full machine state to/from a file. Returns 0 on success.
|
||||
int FBHeadlessSaveState(const char *path);
|
||||
int FBHeadlessLoadState(const char *path);
|
||||
|
||||
// Memory access for cheats, cheat search, and achievements. Addresses are in the
|
||||
// main CPU (cpu 0) hardware address space. size is 1..4 bytes; littleEndian
|
||||
// controls byte order for multi-byte values. A value found via a memory-range
|
||||
// snapshot can be written back at the same address with FBHeadlessWriteMemory.
|
||||
unsigned int FBHeadlessGetMainMemorySize(void); // 0 until a driver is loaded
|
||||
unsigned int FBHeadlessReadMemoryRange(unsigned int address, unsigned char *out, unsigned int length); // returns bytes read
|
||||
unsigned int FBHeadlessReadMemory(unsigned int address, int size, int littleEndian);
|
||||
int FBHeadlessWriteMemory(unsigned int address, unsigned int value, int size, int littleEndian); // 1 on success
|
||||
int FBHeadlessIsAddressValid(unsigned int address);
|
||||
|
||||
// Achievements memory. RetroAchievements sets are authored against FBNeo's flat
|
||||
// main-RAM exposure (per driver hardware type), not the CPU address space.
|
||||
// FBHeadlessCheevosInit rebuilds the map (call after load/reset); the read is
|
||||
// gated to the mapped regions. Returns bytes read (stops at the first unmapped byte).
|
||||
void FBHeadlessCheevosInit(void);
|
||||
unsigned int FBHeadlessReadAchievementMemory(unsigned int address, unsigned char *out, unsigned int length);
|
||||
|
||||
// Cheats: write into the achievement memory map (same flat RAM the search reads), and
|
||||
// enumerate the mapped regions so the host can present cheat search. bigEndian follows
|
||||
// the libretro/RetroAchievements convention the host matches: 0 (little-endian) for every
|
||||
// board, including the 68K ones. See GetMainMemoryBigEndian.
|
||||
int FBHeadlessWriteAchievementMemory(unsigned int address, unsigned int value, int size, int littleEndian);
|
||||
int FBHeadlessGetMemoryRegionCount(void);
|
||||
int FBHeadlessGetMemoryRegion(int index, unsigned int *start, unsigned int *length, int *bigEndian);
|
||||
|
||||
// High-level input. player is 0-based; button is an FBHeadlessButton value. The
|
||||
// fork maps it to the active driver's inputs (parsed from its input names).
|
||||
typedef enum {
|
||||
FBHeadlessButtonUp = 0,
|
||||
FBHeadlessButtonDown,
|
||||
FBHeadlessButtonLeft,
|
||||
FBHeadlessButtonRight,
|
||||
FBHeadlessButton1,
|
||||
FBHeadlessButton2,
|
||||
FBHeadlessButton3,
|
||||
FBHeadlessButton4,
|
||||
FBHeadlessButton5,
|
||||
FBHeadlessButton6,
|
||||
FBHeadlessButtonStart,
|
||||
FBHeadlessButtonCoin,
|
||||
FBHeadlessButtonService, // test switch (settings menu); "service" when there is none
|
||||
FBHeadlessButtonConfigure, // "service" input of drivers that also have a test switch
|
||||
FBHeadlessButtonCount
|
||||
} FBHeadlessButton;
|
||||
void FBHeadlessSetInput(int player, int button, int value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // BURNER_HEADLESS_H
|
||||
@@ -0,0 +1,134 @@
|
||||
// Headless driver glue for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// The headless counterpart of the SDL burner's drv.cpp: wraps BurnDrvInit in the
|
||||
// zip loader and provides the frontend callbacks the shared burner code calls.
|
||||
// CD systems (NeoGeo CD / PCE CD) are not wired yet. Subject to the FB Neo
|
||||
// license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
|
||||
int bDrvOkay = 0;
|
||||
char szAppRomPaths[DIRS_MAX][MAX_PATH] = { { "roms/" }, };
|
||||
|
||||
static bool bSaveRAM = false;
|
||||
|
||||
// Battery-backed RAM (ACB_NVRAM: Mortal Kombat's settings, Robotron's high
|
||||
// scores...) is not saved by the driver, unlike the EEPROM device. Like the
|
||||
// Windows burner's StatedAuto, keep it in <szAppEEPROMPath><set>.fs: loaded
|
||||
// after init and saved before exit. Drivers without NVRAM write no file.
|
||||
static void DrvNvramAuto(int bSave)
|
||||
{
|
||||
TCHAR szName[MAX_PATH];
|
||||
_stprintf(szName, _T("%s%s.fs"), szAppEEPROMPath, BurnDrvGetText(DRV_NAME));
|
||||
if (bSave)
|
||||
BurnStateSave(szName, 0);
|
||||
else
|
||||
BurnStateLoad(szName, 0, NULL);
|
||||
}
|
||||
|
||||
static int DoLibInit() // Init the Burn library's driver
|
||||
{
|
||||
BzipOpen(false);
|
||||
int nRet = BurnDrvInit();
|
||||
BzipClose();
|
||||
return nRet ? 1 : 0;
|
||||
}
|
||||
|
||||
// Catch BurnLoadRom() calls once emulation has started: open the zip module,
|
||||
// forward, then exit cleanly.
|
||||
static int DrvLoadRom(unsigned char* Dest, int* pnWrote, int i)
|
||||
{
|
||||
BzipOpen(false);
|
||||
int nRet = BurnExtLoadRom(Dest, pnWrote, i);
|
||||
BzipClose();
|
||||
|
||||
BurnExtLoadRom = DrvLoadRom;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int DrvInit(int nDrvNum, bool bRestore)
|
||||
{
|
||||
DrvExit(); // Make sure exited
|
||||
MediaExit();
|
||||
|
||||
nBurnDrvActive = nDrvNum;
|
||||
|
||||
{ // Init input and audio; defer blitter init.
|
||||
bVidOkay = 1;
|
||||
bAudOkay = 1;
|
||||
MediaInit();
|
||||
bVidOkay = 0;
|
||||
bAudOkay = 0;
|
||||
}
|
||||
|
||||
nMaxPlayers = BurnDrvGetMaxPlayers();
|
||||
GameInpInit();
|
||||
|
||||
bSaveInputs = ConfigGameLoad(true);
|
||||
if (bSaveInputs) ConfigGameLoadHardwareDefaults();
|
||||
|
||||
InputMake(true);
|
||||
GameInpDefault();
|
||||
|
||||
if (DoLibInit()) {
|
||||
BurnDrvExit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
BurnExtLoadRom = DrvLoadRom;
|
||||
|
||||
bDrvOkay = 1;
|
||||
bSaveRAM = false;
|
||||
nBurnLayer = 0xFF;
|
||||
ConfigCheatLoad();
|
||||
RunReset();
|
||||
if (bRestore) {
|
||||
DrvNvramAuto(0);
|
||||
bSaveRAM = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DrvInitCallback()
|
||||
{
|
||||
return DrvInit(nBurnDrvActive, false);
|
||||
}
|
||||
|
||||
int DrvExit()
|
||||
{
|
||||
if (bDrvOkay) {
|
||||
if (nBurnDrvActive < nBurnDrvCount) {
|
||||
if (bSaveRAM) {
|
||||
DrvNvramAuto(1);
|
||||
bSaveRAM = false;
|
||||
}
|
||||
ConfigGameSave(bSaveInputs);
|
||||
GameInpExit();
|
||||
BurnDrvExit();
|
||||
}
|
||||
}
|
||||
|
||||
BurnExtLoadRom = NULL;
|
||||
bDrvOkay = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ProgressUpdateBurner(double /* dProgress */, const TCHAR* /* pszText */, bool /* bAbs */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppError(TCHAR* /* szText */, int /* bWarning */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The host drives frame timing, so there is no throttle to reset.
|
||||
int RunReset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
// Headless input mapping for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Maps a (player, FBHeadlessButton) pair to the active driver's GameInp. FBNeo
|
||||
// exposes each input's canonical lowercase name via szInfo ("p1 up",
|
||||
// "p1 fire 1", "p1 coin", "p1 start"); each matched digital input is rebound to
|
||||
// a private switch code the headless input plugin reads from its state table.
|
||||
// Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
#include "fbheadless.h"
|
||||
|
||||
// Private switch-code space, chosen to avoid the driver's default key/joy codes.
|
||||
// code = HL_CODE_BASE + player*16 + button; unmatched digital inputs get a dead
|
||||
// code that is never set so they read as released.
|
||||
#define HL_CODE_BASE 0x100
|
||||
#define HL_CODE_DEAD 0x1FF
|
||||
|
||||
static int hl_code(int player, int button)
|
||||
{
|
||||
return HL_CODE_BASE + player * 16 + button;
|
||||
}
|
||||
|
||||
// Parse an FBNeo szInfo name into (player, FBHeadlessButton). Returns 1 on match.
|
||||
static int hl_classify(const char *szInfo, int *outPlayer, int *outButton)
|
||||
{
|
||||
if (szInfo == NULL)
|
||||
return 0;
|
||||
|
||||
// "pN <control>" form (the common case).
|
||||
if ((szInfo[0] == 'p' || szInfo[0] == 'P') &&
|
||||
szInfo[1] >= '1' && szInfo[1] <= '4' && szInfo[2] == ' ') {
|
||||
int player = szInfo[1] - '1';
|
||||
const char *r = szInfo + 3;
|
||||
int b = -1;
|
||||
|
||||
if (!strcmp(r, "up")) b = FBHeadlessButtonUp;
|
||||
else if (!strcmp(r, "down")) b = FBHeadlessButtonDown;
|
||||
else if (!strcmp(r, "left")) b = FBHeadlessButtonLeft;
|
||||
else if (!strcmp(r, "right")) b = FBHeadlessButtonRight;
|
||||
else if (!strcmp(r, "start")) b = FBHeadlessButtonStart;
|
||||
else if (!strcmp(r, "coin")) b = FBHeadlessButtonCoin;
|
||||
else if (!strcmp(r, "service")) b = FBHeadlessButtonService;
|
||||
else if (!strcmp(r, "diagnostic")) b = FBHeadlessButtonService;
|
||||
else if (!strncmp(r, "fire ", 5) && r[5] >= '1' && r[5] <= '6')
|
||||
b = FBHeadlessButton1 + (r[5] - '1');
|
||||
else if (!strncmp(r, "button ", 7) && r[7] >= '1' && r[7] <= '6')
|
||||
b = FBHeadlessButton1 + (r[7] - '1');
|
||||
|
||||
if (b >= 0) {
|
||||
*outPlayer = player;
|
||||
*outButton = b;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// System "coin N" / "start N" form.
|
||||
if (!strncmp(szInfo, "coin ", 5) && szInfo[5] >= '1' && szInfo[5] <= '4') {
|
||||
*outPlayer = szInfo[5] - '1';
|
||||
*outButton = FBHeadlessButtonCoin;
|
||||
return 1;
|
||||
}
|
||||
if (!strncmp(szInfo, "start ", 6) && szInfo[6] >= '1' && szInfo[6] <= '4') {
|
||||
*outPlayer = szInfo[6] - '1';
|
||||
*outButton = FBHeadlessButtonStart;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Cabinet-wide test switch ("diag" in most drivers), which opens the game's
|
||||
// settings menu.
|
||||
static int hl_is_test_switch(const char *szInfo)
|
||||
{
|
||||
return szInfo != NULL &&
|
||||
(!strcmp(szInfo, "diag") || !strcmp(szInfo, "diagnostic") ||
|
||||
!strcmp(szInfo, "diagnostics") || !strcmp(szInfo, "test"));
|
||||
}
|
||||
|
||||
// Cabinet-wide "service" input. Drivers with a separate test switch use it as a
|
||||
// service credit; older drivers without one use it as the test switch itself.
|
||||
static int hl_is_service_switch(const char *szInfo)
|
||||
{
|
||||
return szInfo != NULL && !strcmp(szInfo, "service");
|
||||
}
|
||||
|
||||
// Index of a direction word at the start of s (0 left, 1 up, 2 down, 3 right),
|
||||
// or -1. *len receives its length.
|
||||
static int hl_direction(const char *s, size_t *len)
|
||||
{
|
||||
static const char *const dirs[] = { "left", "up", "down", "right" };
|
||||
for (int d = 0; d < 4; d++) {
|
||||
size_t n = strlen(dirs[d]);
|
||||
if (!strncasecmp(s, dirs[d], n)) {
|
||||
*len = n;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Twin-stick games (Robotron, Smash TV, Angel Kids, Ikari Warriors...), mapped
|
||||
// the way the MAME core does: the left stick on the player's d-pad, the right
|
||||
// stick on buttons 1-4 (left, up, down, right), since OpenEmu's arcade
|
||||
// controller has one stick. Drivers name the sticks inconsistently: the second
|
||||
// stick may be "pN <dir> 2", or either stick may borrow another player's plain
|
||||
// d-pad ("p2 up" for Robotron's "Fire Up", "p3 up" for Angel Kids' "P1 Left
|
||||
// Stick Up"). The display name, when it names a stick, decides the stick and
|
||||
// the player; otherwise "pN <dir> 2" is player N's right stick.
|
||||
static int hl_twin_stick(const char *szName, const char *szInfo, int *outPlayer, int *outButton)
|
||||
{
|
||||
if (szName == NULL || szInfo == NULL)
|
||||
return 0;
|
||||
if (szInfo[0] != 'p' || szInfo[1] < '1' || szInfo[1] > '4' || szInfo[2] != ' ')
|
||||
return 0;
|
||||
|
||||
size_t len = 0;
|
||||
int dir = hl_direction(szInfo + 3, &len);
|
||||
if (dir < 0)
|
||||
return 0;
|
||||
const char *rest = szInfo + 3 + len;
|
||||
int secondStick = !strcmp(rest, " 2");
|
||||
if (!secondStick && *rest != '\0')
|
||||
return 0;
|
||||
|
||||
static const struct { const char *prefix; int right; } sticks[] = {
|
||||
{ "Left Stick ", 0 }, { "Lft Stick ", 0 }, { "L Stick ", 0 }, { "Left ", 0 },
|
||||
{ "Right Stick ", 1 }, { "Rght Stick ", 1 }, { "ight Stick ", 1 }, { "R Stick ", 1 },
|
||||
{ "Right ", 1 }, { "Fire ", 1 }, { "Shoot ", 1 }, { "Aim ", 1 },
|
||||
};
|
||||
static const int dpad[] = { FBHeadlessButtonLeft, FBHeadlessButtonUp, FBHeadlessButtonDown, FBHeadlessButtonRight };
|
||||
|
||||
const char *n = szName;
|
||||
int player = 0;
|
||||
if ((n[0] == 'P' || n[0] == 'p') && n[1] >= '1' && n[1] <= '4' && n[2] == ' ') {
|
||||
player = n[1] - '1';
|
||||
n += 3;
|
||||
}
|
||||
for (size_t s = 0; s < sizeof(sticks) / sizeof(sticks[0]); s++) {
|
||||
size_t sl = strlen(sticks[s].prefix);
|
||||
size_t nameDirLen = 0;
|
||||
if (strncasecmp(n, sticks[s].prefix, sl) != 0)
|
||||
continue;
|
||||
if (hl_direction(n + sl, &nameDirLen) != dir || n[sl + nameDirLen] != '\0')
|
||||
break;
|
||||
*outPlayer = player;
|
||||
*outButton = sticks[s].right ? FBHeadlessButton1 + dir : dpad[dir];
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (secondStick) {
|
||||
*outPlayer = szInfo[1] - '1';
|
||||
*outButton = FBHeadlessButton1 + dir;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rebind every digital input of the loaded driver to the headless code space.
|
||||
// Called after DrvInit (which runs GameInpInit/GameInpDefault).
|
||||
void headless_map_inputs(void)
|
||||
{
|
||||
struct BurnInputInfo bii;
|
||||
|
||||
// Service always opens the settings menu: it drives the test switch when the
|
||||
// driver has one (and Configure drives "service"), otherwise "service".
|
||||
int hasTestSwitch = 0;
|
||||
for (UINT32 i = 0; i < nGameInpCount; i++) {
|
||||
if (BurnDrvGetInputInfo(&bii, i) == 0 && bii.nType == BIT_DIGITAL && hl_is_test_switch(bii.szInfo)) {
|
||||
hasTestSwitch = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < nGameInpCount; i++) {
|
||||
if (BurnDrvGetInputInfo(&bii, i))
|
||||
continue;
|
||||
if (bii.nType != BIT_DIGITAL)
|
||||
continue;
|
||||
|
||||
GameInp[i].nInput = GIT_SWITCH;
|
||||
|
||||
int player = 0, button = 0;
|
||||
if (hl_is_test_switch(bii.szInfo))
|
||||
GameInp[i].Input.Switch.nCode = (UINT16)hl_code(0, FBHeadlessButtonService);
|
||||
else if (hl_is_service_switch(bii.szInfo))
|
||||
GameInp[i].Input.Switch.nCode = (UINT16)hl_code(0, hasTestSwitch ? FBHeadlessButtonConfigure : FBHeadlessButtonService);
|
||||
else if (hl_twin_stick(bii.szName, bii.szInfo, &player, &button))
|
||||
GameInp[i].Input.Switch.nCode = (UINT16)hl_code(player, button);
|
||||
else if (hl_classify(bii.szInfo, &player, &button) && player >= 0 && player < 4)
|
||||
GameInp[i].Input.Switch.nCode = (UINT16)hl_code(player, button);
|
||||
else
|
||||
GameInp[i].Input.Switch.nCode = HL_CODE_DEAD;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void FBHeadlessSetInput(int player, int button, int value)
|
||||
{
|
||||
if (player < 0 || player >= 4)
|
||||
return;
|
||||
if (button < 0 || button >= FBHeadlessButtonCount)
|
||||
return;
|
||||
FBHeadlessSetInputState(hl_code(player, button), value);
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
// Headless frontend for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Provides the burner-side globals the FBNeo library expects from a frontend and
|
||||
// a small C API the host drives. Video/audio/input are routed through the
|
||||
// intf/{video,audio,input}/headless plugins; driver init/exit lives in drv.cpp.
|
||||
//
|
||||
// Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
#include "fbheadless.h"
|
||||
|
||||
// Implemented in headless_input.cpp.
|
||||
void headless_map_inputs(void);
|
||||
|
||||
// Implemented in vid_headless.cpp (rotates the native frame to the display buffer).
|
||||
void headless_video_present(void);
|
||||
|
||||
// --- Burner globals expected by the FBNeo library / shared burner code ---
|
||||
int nAppVirtualFps = 6000; // app fps * 100
|
||||
bool bRunPause = 0;
|
||||
bool bAppDoFast = 0;
|
||||
char fpsstring[20] = "";
|
||||
bool bAppShowFPS = 0;
|
||||
bool bAlwaysProcessKeyboardInput = 0;
|
||||
bool bAppFullscreen = 0;
|
||||
bool bIntegerScale = false;
|
||||
int nWindowScale = 2;
|
||||
bool bAlwaysMenu = false;
|
||||
int nGameSelect = 0;
|
||||
int nFilterSelect = 0;
|
||||
bool bShowAvailableOnly = true;
|
||||
bool bShowClones = true;
|
||||
int gameSelectedFromFilter = -1;
|
||||
UINT32 messageFrames = 0;
|
||||
char lastMessage[MESSAGE_MAX_LENGTH] = "";
|
||||
int bDrvSaveAll = 0;
|
||||
TCHAR szAppBurnVer[16] = _T("");
|
||||
|
||||
// --- Frontend audio state ---
|
||||
static short *audBuffer = NULL;
|
||||
static int audFrames = 0; // stereo sample frames produced last frame
|
||||
static int audSampleRate = 48000;
|
||||
|
||||
static int allocAudio()
|
||||
{
|
||||
free(audBuffer);
|
||||
audBuffer = NULL;
|
||||
if (nBurnSoundLen <= 0)
|
||||
return 1;
|
||||
audBuffer = (short *)malloc((nBurnSoundLen * 2 + 16) * sizeof(short));
|
||||
if (audBuffer == NULL)
|
||||
return 1;
|
||||
memset(audBuffer, 0, (nBurnSoundLen * 2 + 16) * sizeof(short));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- C API ---
|
||||
|
||||
int FBHeadlessInit(void)
|
||||
{
|
||||
BurnLibInit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FBHeadlessExit(void)
|
||||
{
|
||||
DrvExit();
|
||||
VidExit();
|
||||
AudSoundExit();
|
||||
InputExit();
|
||||
free(audBuffer);
|
||||
audBuffer = NULL;
|
||||
BurnLibExit();
|
||||
}
|
||||
|
||||
void FBHeadlessSetRomPath(const char *path)
|
||||
{
|
||||
// BzipOpen builds zip paths as szAppRomPaths[d] + "<name>.zip" with no
|
||||
// separator, so the path must end with a slash.
|
||||
size_t n = strlen(path);
|
||||
if (n > 0 && path[n - 1] == '/')
|
||||
snprintf(szAppRomPaths[0], MAX_PATH, "%s", path);
|
||||
else
|
||||
snprintf(szAppRomPaths[0], MAX_PATH, "%s/", path);
|
||||
}
|
||||
|
||||
int FBHeadlessLoadDriver(const char *shortName)
|
||||
{
|
||||
UINT32 i;
|
||||
for (i = 0; i < nBurnDrvCount; i++) {
|
||||
nBurnDrvActive = i;
|
||||
if (strcmp(BurnDrvGetTextA(DRV_NAME), shortName) == 0)
|
||||
break;
|
||||
}
|
||||
if (i >= nBurnDrvCount)
|
||||
return 1;
|
||||
|
||||
nAudSampleRate[0] = audSampleRate;
|
||||
nBurnSoundRate = audSampleRate;
|
||||
|
||||
InputInit();
|
||||
AudSoundInit();
|
||||
|
||||
if (DrvInit(i, true)) // true: restore battery-backed RAM
|
||||
return 1;
|
||||
|
||||
VidInit(); // after DrvInit: the game's visible size is known
|
||||
headless_map_inputs();
|
||||
|
||||
nAppVirtualFps = nBurnFPS;
|
||||
if (nAppVirtualFps <= 0)
|
||||
nAppVirtualFps = 6000;
|
||||
nBurnSoundLen = (audSampleRate * 100 + (nAppVirtualFps >> 1)) / nAppVirtualFps;
|
||||
allocAudio();
|
||||
|
||||
FBHeadlessCheevosInit(); // build the achievement memory map
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FBHeadlessRunFrame(int draw)
|
||||
{
|
||||
if (!bDrvOkay)
|
||||
return;
|
||||
|
||||
InputMake(true);
|
||||
|
||||
pBurnDraw = draw ? pVidImage : NULL;
|
||||
pBurnSoundOut = audBuffer;
|
||||
|
||||
BurnDrvFrame();
|
||||
|
||||
if (draw)
|
||||
headless_video_present();
|
||||
|
||||
audFrames = nBurnSoundLen;
|
||||
}
|
||||
|
||||
// Audio accessors
|
||||
int FBHeadlessGetAudioSampleRate(void) { return audSampleRate; }
|
||||
const short *FBHeadlessGetAudioBuffer(void) { return audBuffer; }
|
||||
int FBHeadlessGetAudioFrames(void) { return audFrames; }
|
||||
|
||||
// Frame timing / geometry
|
||||
int FBHeadlessGetFrameRate(void) { return nBurnFPS; }
|
||||
|
||||
int FBHeadlessGetAspectX(void)
|
||||
{
|
||||
INT32 x = 0, y = 0;
|
||||
if (bDrvOkay)
|
||||
BurnDrvGetAspect(&x, &y);
|
||||
return x;
|
||||
}
|
||||
|
||||
int FBHeadlessGetAspectY(void)
|
||||
{
|
||||
INT32 x = 0, y = 0;
|
||||
if (bDrvOkay)
|
||||
BurnDrvGetAspect(&x, &y);
|
||||
return y;
|
||||
}
|
||||
|
||||
void FBHeadlessReset(void)
|
||||
{
|
||||
if (!bDrvOkay)
|
||||
return;
|
||||
DrvInit(nBurnDrvActive, true); // full re-init; DrvExit saves battery RAM, DrvInit restores it
|
||||
VidInit(); // DrvInit defers blitter init + frees buffers; recreate them
|
||||
headless_map_inputs();
|
||||
FBHeadlessCheevosInit(); // RAM buffers were reallocated; refresh the map
|
||||
}
|
||||
|
||||
int FBHeadlessSaveState(const char *path)
|
||||
{
|
||||
if (!bDrvOkay || path == NULL)
|
||||
return 1;
|
||||
TCHAR szName[1024];
|
||||
ANSIToTCHAR(path, szName, 1024);
|
||||
return BurnStateSave(szName, 1); // bAll=1: full state
|
||||
}
|
||||
|
||||
int FBHeadlessLoadState(const char *path)
|
||||
{
|
||||
if (!bDrvOkay || path == NULL)
|
||||
return 1;
|
||||
TCHAR szName[1024];
|
||||
ANSIToTCHAR(path, szName, 1024);
|
||||
return BurnStateLoad(szName, 1, NULL); // game already loaded, so no reload callback
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
// Memory access for cheats, cheat search, and achievements (FinalBurn Neo headless).
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Thin C wrappers over FBNeo's cheat-engine memory interface (src/burn/cheat.cpp).
|
||||
// All addresses are in the main CPU (cpu 0) hardware address space — the same
|
||||
// space FBNeo's own cheat and achievement support uses, so a value found by a
|
||||
// memory search can be written back by address.
|
||||
//
|
||||
// Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
#include "state.h" // BurnArea, BurnAreaScan, BurnAcb, ACB_FULLSCAN
|
||||
#include "fbheadless.h"
|
||||
|
||||
unsigned int FBHeadlessGetMainMemorySize(void)
|
||||
{
|
||||
return GetMainMemorySize();
|
||||
}
|
||||
|
||||
unsigned int FBHeadlessReadMemoryRange(unsigned int address, unsigned char *out, unsigned int length)
|
||||
{
|
||||
return ReadMemoryRange(address, out, length);
|
||||
}
|
||||
|
||||
// Standard byte order: byte i lives at address+i. littleEndian controls which end
|
||||
// is the least-significant byte. (FBNeo's own Read/WriteValueAtHardwareAddress use
|
||||
// an MSB-first, address-decrementing convention — not exposed here to avoid surprises.)
|
||||
unsigned int FBHeadlessReadMemory(unsigned int address, int size, int littleEndian)
|
||||
{
|
||||
if (!bDrvOkay || size < 1 || size > 4)
|
||||
return 0;
|
||||
unsigned char b[4] = { 0, 0, 0, 0 };
|
||||
ReadMemoryRange(address, b, (unsigned int)size);
|
||||
unsigned int value = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
int shift = littleEndian ? (8 * i) : (8 * (size - 1 - i));
|
||||
value |= (unsigned int)b[i] << shift;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int FBHeadlessWriteMemory(unsigned int address, unsigned int value, int size, int littleEndian)
|
||||
{
|
||||
if (!bDrvOkay || size < 1 || size > 4)
|
||||
return 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
int shift = littleEndian ? (8 * i) : (8 * (size - 1 - i));
|
||||
unsigned char byte = (value >> shift) & 0xFF;
|
||||
WriteValueAtHardwareAddress(address + i, byte, 1, 1); // single byte, no endian ambiguity
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FBHeadlessIsAddressValid(unsigned int address)
|
||||
{
|
||||
return IsHardwareAddressValid(address) ? 1 : 0;
|
||||
}
|
||||
|
||||
// --- Achievements memory map ---
|
||||
//
|
||||
// RetroAchievements sets are authored against the flat main-RAM buffer FBNeo's
|
||||
// libretro port exposes (see CheevosInit / StateGetMainRamAcb in retro_memory.cpp),
|
||||
// NOT the CPU hardware address space. Find the same RAM area(s) by driver hardware
|
||||
// type and expose them at the same RA base addresses the libretro port uses.
|
||||
|
||||
#define FBH_MAX_RA_REGIONS 10
|
||||
typedef struct { unsigned int start; unsigned int len; unsigned char *ptr; } FBHRaRegion;
|
||||
static FBHRaRegion s_raRegions[FBH_MAX_RA_REGIONS];
|
||||
static int s_raRegionCount = 0;
|
||||
static int s_raBigEndian = 0; // main CPU multibyte order (68K etc. = big-endian)
|
||||
|
||||
static void fbh_ra_add(unsigned int start, unsigned int len, void *ptr)
|
||||
{
|
||||
if (s_raRegionCount >= FBH_MAX_RA_REGIONS || ptr == NULL || len == 0)
|
||||
return;
|
||||
s_raRegions[s_raRegionCount].start = start;
|
||||
s_raRegions[s_raRegionCount].len = len;
|
||||
s_raRegions[s_raRegionCount].ptr = (unsigned char *)ptr;
|
||||
s_raRegionCount++;
|
||||
}
|
||||
|
||||
static INT32 __cdecl fbh_ra_acb(struct BurnArea *pba)
|
||||
{
|
||||
if (!pba->szName)
|
||||
return 0;
|
||||
|
||||
switch (BurnDrvGetHardwareCode() & HARDWARE_PUBLIC_MASK) {
|
||||
case HARDWARE_CAPCOM_CPS1:
|
||||
case HARDWARE_CAPCOM_CPS1_QSOUND:
|
||||
case HARDWARE_CAPCOM_CPS1_GENERIC:
|
||||
case HARDWARE_CAPCOM_CPSCHANGER:
|
||||
case HARDWARE_CAPCOM_CPS2:
|
||||
if (strcmp(pba->szName, "CpsRamFF") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_CAPCOM_CPS3:
|
||||
if (strcmp(pba->szName, "Main RAM") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_SNK_NEOCD:
|
||||
if (strcmp(pba->szName, "68K program RAM") == 0) fbh_ra_add(0x00000000, pba->nLen, pba->Data);
|
||||
if (strcmp(pba->szName, "Memory card") == 0) fbh_ra_add(0x00800000, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_SNK_NEOGEO:
|
||||
case HARDWARE_IGS_PGM:
|
||||
if (strcmp(pba->szName, "68K RAM") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_PSIKYO:
|
||||
if (strcmp(pba->szName, "All RAM") == 0 || strcmp(pba->szName, "68K RAM") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_CAVE_68K_Z80:
|
||||
case HARDWARE_CAVE_68K_ONLY:
|
||||
if (strcmp(pba->szName, "RAM") == 0 || strcmp(pba->szName, "68K RAM") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_SEGA_MEGADRIVE:
|
||||
if (strcmp(pba->szName, "RAM") == 0) fbh_ra_add(0x00FF0000, pba->nLen, pba->Data);
|
||||
if (strcmp(pba->szName, "NV RAM") == 0) fbh_ra_add(0x00000000, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_SEGA_MASTER_SYSTEM:
|
||||
case HARDWARE_SEGA_GAME_GEAR:
|
||||
if (strcmp(pba->szName, "sms") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_NES:
|
||||
case HARDWARE_FDS:
|
||||
case HARDWARE_NVS:
|
||||
if (strcmp(pba->szName, "CPU Ram") == 0) fbh_ra_add(0x00000000, pba->nLen, pba->Data);
|
||||
if (strcmp(pba->szName, "Work Ram") == 0) fbh_ra_add(0x00006000, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_SNK_NGP:
|
||||
case HARDWARE_SNK_NGPC:
|
||||
if (strcmp(pba->szName, "Main Ram") == 0) fbh_ra_add(0x00004000, pba->nLen, pba->Data);
|
||||
if (strcmp(pba->szName, "Shared Ram") == 0) fbh_ra_add(0x00007000, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
case HARDWARE_TOAPLAN_RAIZING:
|
||||
if (strcmp(pba->szName, "All Ram") == 0 || strcmp(pba->szName, "All RAM") == 0 || strcmp(pba->szName, "RAM") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
default:
|
||||
// Most other drivers expose main RAM as "All Ram" / "All RAM".
|
||||
if (strcmp(pba->szName, "All Ram") == 0 || strcmp(pba->szName, "All RAM") == 0) fbh_ra_add(0, pba->nLen, pba->Data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild the achievement memory map. Call after a driver loads or resets, since
|
||||
// DrvInit reallocates the RAM buffers (the cached pointers would otherwise dangle).
|
||||
void FBHeadlessCheevosInit(void)
|
||||
{
|
||||
INT32 nMin = 0;
|
||||
s_raRegionCount = 0;
|
||||
s_raBigEndian = 0;
|
||||
if (!bDrvOkay)
|
||||
return;
|
||||
s_raBigEndian = GetMainMemoryBigEndian();
|
||||
BurnAcb = fbh_ra_acb;
|
||||
BurnAreaScan(ACB_FULLSCAN, &nMin);
|
||||
}
|
||||
|
||||
unsigned int FBHeadlessReadAchievementMemory(unsigned int address, unsigned char *out, unsigned int length)
|
||||
{
|
||||
if (out == NULL)
|
||||
return 0;
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < length; i++) {
|
||||
unsigned int a = address + i;
|
||||
int found = 0;
|
||||
for (int r = 0; r < s_raRegionCount; r++) {
|
||||
if (a >= s_raRegions[r].start && a < s_raRegions[r].start + s_raRegions[r].len) {
|
||||
out[i] = s_raRegions[r].ptr[a - s_raRegions[r].start];
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return i; // stop at the first unmapped address
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
// Write a value into the achievement memory map (used to apply cheats). Bytes land
|
||||
// at address+i for littleEndian, or MSB-first for big-endian. Returns 1 if anything
|
||||
// was written. Direct buffer writes — the CPU sees them next frame (plain RAM).
|
||||
int FBHeadlessWriteAchievementMemory(unsigned int address, unsigned int value, int size, int littleEndian)
|
||||
{
|
||||
if (size < 1 || size > 4)
|
||||
return 0;
|
||||
int wrote = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
unsigned int a = littleEndian ? (address + i) : (address + (size - 1 - i));
|
||||
unsigned char byte = (value >> (8 * i)) & 0xFF;
|
||||
for (int r = 0; r < s_raRegionCount; r++) {
|
||||
if (a >= s_raRegions[r].start && a < s_raRegions[r].start + s_raRegions[r].len) {
|
||||
s_raRegions[r].ptr[a - s_raRegions[r].start] = byte;
|
||||
wrote = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return wrote;
|
||||
}
|
||||
|
||||
// Enumerate the mapped regions so the host can present cheat-search memory.
|
||||
int FBHeadlessGetMemoryRegionCount(void)
|
||||
{
|
||||
return s_raRegionCount;
|
||||
}
|
||||
|
||||
int FBHeadlessGetMemoryRegion(int index, unsigned int *start, unsigned int *length, int *bigEndian)
|
||||
{
|
||||
if (index < 0 || index >= s_raRegionCount)
|
||||
return 0;
|
||||
if (start) *start = s_raRegions[index].start;
|
||||
if (length) *length = s_raRegions[index].len;
|
||||
if (bigEndian) *bigEndian = s_raBigEndian;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Headless frontend helpers for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Small frontend functions/globals the shared burner code expects, provided by
|
||||
// each platform (the headless counterpart of burner/macos/misc.cpp). Subject to
|
||||
// the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
|
||||
// General-purpose debug global referenced by various drivers.
|
||||
int counter = 0;
|
||||
|
||||
TCHAR* ANSIToTCHAR(const char* pszInString, TCHAR* pszOutString, int /* nOutSize */)
|
||||
{
|
||||
if (pszOutString) {
|
||||
_tcscpy(pszOutString, pszInString);
|
||||
return pszOutString;
|
||||
}
|
||||
return (TCHAR*)pszInString;
|
||||
}
|
||||
|
||||
char* TCHARToANSI(const TCHAR* pszInString, char* pszOutString, int /* nOutSize */)
|
||||
{
|
||||
if (pszOutString) {
|
||||
_tcscpy(pszOutString, pszInString);
|
||||
return pszOutString;
|
||||
}
|
||||
return (char*)pszInString;
|
||||
}
|
||||
|
||||
TCHAR* AdaptiveEncodingReads(const TCHAR* /* pszFileName */)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool AppProcessKeyboardInput()
|
||||
{
|
||||
// Input is always live for the headless core (the host gates pause/focus),
|
||||
// and CinpState() zeroes keyboard-range codes (< 0x4000, which ours are)
|
||||
// unless this returns true.
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpdateMessage(char* /* message */)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef TCHAR_H
|
||||
#define TCHAR_H
|
||||
|
||||
// Always available so non-_UNICODE code that still handles wide buffers
|
||||
// (e.g. burn.cpp zip-name parsing) can call wcslen/wcscpy.
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef _UNICODE
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#define __TEXT(q) L##q
|
||||
|
||||
typedef wchar_t TCHAR;
|
||||
typedef wchar_t _TCHAR;
|
||||
|
||||
#else /* ifndef _UNICODE */
|
||||
|
||||
#define __TEXT(q) q
|
||||
|
||||
typedef char TCHAR;
|
||||
typedef char _TCHAR;
|
||||
|
||||
//#define wcslen(void)
|
||||
|
||||
#define _tcslen strlen
|
||||
#define _tcscpy strcpy
|
||||
#define _tcsncpy strncpy
|
||||
|
||||
#define _tprintf printf
|
||||
#define _vstprintf vsprintf
|
||||
#define _vsntprintf vsnprintf
|
||||
#define _stprintf sprintf
|
||||
#define _sntprintf snprintf
|
||||
#define _ftprintf fprintf
|
||||
#define _tsprintf sprintf
|
||||
|
||||
#define _tcscmp strcmp
|
||||
#define _tcsncmp strncmp
|
||||
#define _tcsicmp strcasecmp
|
||||
#define _tcsnicmp strncasecmp
|
||||
#define _tcstol strtol
|
||||
#define _tcsrchr strrchr
|
||||
#define _tcsstr strstr
|
||||
|
||||
#define _tcsstr strstr
|
||||
|
||||
#define _fgetts fgets
|
||||
#define _fputts fputs
|
||||
|
||||
#define _istspace isspace
|
||||
|
||||
#define _tfopen fopen
|
||||
|
||||
#define _stricmp strcmp
|
||||
#define _strnicmp strncmp
|
||||
|
||||
// Win32 string/char shims the shared code uses on POSIX builds.
|
||||
#include <ctype.h>
|
||||
#define stricmp strcasecmp
|
||||
#define strnicmp strncasecmp
|
||||
#define _totlower(c) tolower((unsigned char)(c))
|
||||
#define _totupper(c) toupper((unsigned char)(c))
|
||||
|
||||
#define dprintf(...) fprintf (stderr, __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
#define _TEXT(x) __TEXT(x)
|
||||
#define _T(x) __TEXT(x)
|
||||
|
||||
#endif
|
||||
@@ -1316,6 +1316,7 @@ BEGIN
|
||||
MENUITEM "Enable Windowed Fullscreen (DX9/DX11 Blitters)", MENU_WINFS
|
||||
MENUITEM "Enable VSync (Windowed)", MENU_VIDEOVSYNC
|
||||
MENUITEM "Enable DWM Sync (Windowed)", MENU_DWMFIX
|
||||
MENUITEM "Enable Variable Refresh Rate (DX11, Win10+)", MENU_VRR
|
||||
MENUITEM "Auto Frameskip", MENU_AUTOFRAMESKIP
|
||||
MENUITEM "Enable RunAhead", MENU_RUNAHEAD
|
||||
END
|
||||
@@ -1325,6 +1326,7 @@ BEGIN
|
||||
BEGIN
|
||||
MENUITEM "DirectSound", MENU_AUD_PLUGIN_1
|
||||
MENUITEM "XAudio2", MENU_AUD_PLUGIN_2
|
||||
MENUITEM "WASAPI", MENU_AUD_PLUGIN_3
|
||||
END
|
||||
MENUITEM "Plugin &options", MENU_AUDIO_OPTIONS, GRAYED
|
||||
POPUP "&Audio Volume"
|
||||
@@ -1992,6 +1994,18 @@ BEGIN
|
||||
END
|
||||
END
|
||||
|
||||
IDR_MENU_AUD_PLUGIN_3 MENU
|
||||
BEGIN
|
||||
POPUP "WASAPI plugin"
|
||||
BEGIN
|
||||
MENUITEM "Use Low-pass filter", MENU_WASAPI_BASS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Sound disabled", MENU_WASAPI_NOSOUND
|
||||
MENUITEM "44100Hz samplerate", MENU_WASAPI_44100
|
||||
MENUITEM "48000Hz samplerate", MENU_WASAPI_48000
|
||||
END
|
||||
END
|
||||
|
||||
IDR_MENU_GAMESEL MENU
|
||||
BEGIN
|
||||
POPUP "Game Selection Menu"
|
||||
|
||||
@@ -269,6 +269,7 @@ int RunFrame(int bDraw, int bPause);
|
||||
int RunMessageLoop();
|
||||
int RunReset();
|
||||
void ToggleLayer(unsigned char thisLayer);
|
||||
bool EmulatorAppIsFast();
|
||||
|
||||
// scrn.cpp
|
||||
extern HWND hScrnWnd; // Handle to the screen window
|
||||
|
||||
@@ -296,6 +296,7 @@ int ConfigAppLoad()
|
||||
VAR(bVidDX9WinFullscreen);
|
||||
VAR(bVidVSync);
|
||||
VAR(bVidDWMSync);
|
||||
VAR(bVidVRR);
|
||||
|
||||
VAR(bVidScanlines);
|
||||
VAR(nVidScanIntensity);
|
||||
@@ -376,6 +377,8 @@ int ConfigAppLoad()
|
||||
VAR(nAudDSPModule[0]);
|
||||
VAR(nAudSampleRate[1]);
|
||||
VAR(nAudDSPModule[1]);
|
||||
VAR(nAudSampleRate[2]);
|
||||
VAR(nAudDSPModule[2]);
|
||||
|
||||
// Other
|
||||
STR(szPlaceHolder);
|
||||
@@ -685,6 +688,8 @@ int ConfigAppSave()
|
||||
VAR(bVidVSync);
|
||||
_ftprintf(h, _T("\n// If non-zero, try to synchronise to DWM on Windows 7+, this fixes frame stuttering problems.\n"));
|
||||
VAR(bVidDWMSync);
|
||||
_ftprintf(h, _T("\n// If non-zero, use variable refresh rate (G-Sync/FreeSync) with the DX11 blitter on Windows 10+\n"));
|
||||
VAR(bVidVRR);
|
||||
_ftprintf(h, _T("\n// Transfer method: 0 = blit from system memory / use driver/DirectX texture management;\n"));
|
||||
_ftprintf(h, _T("// 1 = copy to a video memory surface, then use bltfast();\n"));
|
||||
_ftprintf(h, _T("// -1 = autodetect for DirectDraw, equals 1 for Direct3D\n"));
|
||||
@@ -784,7 +789,7 @@ int ConfigAppSave()
|
||||
VAR(nInputSelect);
|
||||
_ftprintf(h, _T("\n"));
|
||||
_ftprintf(h, _T("// --- Sound ------------------------------------------------------------------\n"));
|
||||
_ftprintf(h, _T("\n// The selected audio plugin\n"));
|
||||
_ftprintf(h, _T("\n// The selected audio plugin (0 = DirectSound, 1 = XAudio2, 2 = WASAPI)\n"));
|
||||
VAR(nAudSelect);
|
||||
_ftprintf(h, _T("\n// Audio Volume\n"));
|
||||
VAR(nAudVolume);
|
||||
@@ -806,6 +811,12 @@ int ConfigAppSave()
|
||||
VAR(nAudSampleRate[1]);
|
||||
_ftprintf(h, _T("\n// DSP module to use for sound enhancement: 0 = none, 1 = low-pass filter, 2 = reverb\n"));
|
||||
VAR(nAudDSPModule[1]);
|
||||
_ftprintf(h, _T("\n"));
|
||||
_ftprintf(h, _T("// --- WASAPI plugin settings -------------------------------------------------\n"));
|
||||
_ftprintf(h, _T("\n// Sample rate\n"));
|
||||
VAR(nAudSampleRate[2]);
|
||||
_ftprintf(h, _T("\n// DSP module to use for sound enhancement: 0 = none, 1 = low-pass filter\n"));
|
||||
VAR(nAudDSPModule[2]);
|
||||
|
||||
_ftprintf(h, _T("\n\n\n"));
|
||||
_ftprintf(h, _T("// --- UI ---------------------------------------------------------------------\n"));
|
||||
|
||||
@@ -140,6 +140,36 @@ static INT32 GetCurrentMonitorHigh() {
|
||||
return monitorInfo.rcMonitor.bottom;
|
||||
}
|
||||
|
||||
//In order to properly clean up the currentMenuInfo structs created to handle owner Drawn components it is necessary to iterate over all the menus and clean
|
||||
//the mii.dwItemData variable
|
||||
void CleanUpMenuInfos(HMENU hMenu)
|
||||
{
|
||||
MENUINFO mi = { sizeof(MENUINFO) };
|
||||
int count = GetMenuItemCount(hMenu);
|
||||
for (int i = 0; i < count; i++) {
|
||||
HMENU hSub = GetSubMenu(hMenu, i);
|
||||
if(hSub)
|
||||
{
|
||||
CleanUpMenuInfos(hSub);
|
||||
}
|
||||
|
||||
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
|
||||
|
||||
mii.fMask = MIIM_FTYPE | MIIM_DATA;
|
||||
if (!GetMenuItemInfo(hMenu, i, TRUE, &mii))
|
||||
continue;
|
||||
|
||||
if ((mii.fType & MFT_OWNERDRAW) && mii.dwItemData != 0)
|
||||
{
|
||||
delete (CurrentItemInfo*)mii.dwItemData;
|
||||
mii.fMask = MIIM_DATA;
|
||||
mii.dwItemData = 0;
|
||||
SetMenuItemInfo(hMenu, i, TRUE, &mii);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMenuBackground(HMENU hMenu, HBRUSH hbr)
|
||||
{
|
||||
MENUINFO mi = { sizeof(MENUINFO) };
|
||||
@@ -438,6 +468,11 @@ void DisplayPopupMenu(int nMenu)
|
||||
if (!bModelessMenu) {
|
||||
UnhookWindowsHookEx(hMenuHook);
|
||||
}
|
||||
|
||||
if (uiOwnerDrawActive) {
|
||||
CleanUpMenuInfos(hPopupMenu);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,6 +728,7 @@ int MenuCreate()
|
||||
|
||||
hAudioPluginMenu[0] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_AUD_PLUGIN_1));
|
||||
hAudioPluginMenu[1] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_AUD_PLUGIN_2));
|
||||
hAudioPluginMenu[2] = FBALoadMenu(hAppInst, MAKEINTRESOURCE(IDR_MENU_AUD_PLUGIN_3));
|
||||
}
|
||||
|
||||
if (hMenuPopup == NULL) {
|
||||
@@ -1036,6 +1072,7 @@ void MenuUpdate()
|
||||
CheckMenuItem(hMenu, MENU_WINFS, bVidDX9WinFullscreen ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
CheckMenuItem(hMenu, MENU_DWMFIX, bVidDWMSync ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hMenu, MENU_VRR, bVidVRR ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
var = nVidSelect + MENU_BLITTER_1;
|
||||
CheckMenuRadioItem(hMenu, MENU_BLITTER_1, MENU_BLITTER_8, var, MF_BYCOMMAND);
|
||||
@@ -1382,6 +1419,25 @@ void MenuUpdate()
|
||||
EnableMenuItem(hMenu, MENU_AUDIO_VOLUME_200, MF_ENABLED | MF_BYCOMMAND);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
var = MENU_WASAPI_NOSOUND;
|
||||
if (nAudSampleRate[2] > 0) {
|
||||
if (nAudSampleRate[2] <= 44100) {
|
||||
var = MENU_WASAPI_44100;
|
||||
nAudSampleRate[2] = 44100; // sanity
|
||||
} else {
|
||||
var = MENU_WASAPI_48000;
|
||||
nAudSampleRate[2] = 48000;
|
||||
}
|
||||
}
|
||||
CheckMenuRadioItem(hMenu, MENU_WASAPI_NOSOUND, MENU_WASAPI_48000, var, MF_BYCOMMAND);
|
||||
CheckMenuItem(hMenu, MENU_WASAPI_BASS, (nAudDSPModule[2] & 1) ? MF_CHECKED : MF_UNCHECKED);
|
||||
// WASAPI is able to amp volume above 0db, enable:
|
||||
EnableMenuItem(hMenu, MENU_AUDIO_VOLUME_150, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_AUDIO_VOLUME_200, MF_ENABLED | MF_BYCOMMAND);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var = MENU_INTERPOLATE_0 + nInterpolation;
|
||||
@@ -1654,7 +1710,7 @@ void MenuEnableItems()
|
||||
SetMenuItemInfo(GetSubMenu(hMenu, 1), 1, TRUE, &myMenuItemInfo);
|
||||
}
|
||||
|
||||
if (hBlitterMenu[nAudSelect]) {
|
||||
if (hAudioPluginMenu[nAudSelect]) {
|
||||
MENUITEMINFO myMenuItemInfo;
|
||||
myMenuItemInfo.cbSize = sizeof(MENUITEMINFO);
|
||||
myMenuItemInfo.fMask = MIIM_SUBMENU | MIIM_STATE;
|
||||
@@ -1731,6 +1787,9 @@ void MenuEnableItems()
|
||||
EnableMenuItem(hMenu, MENU_XAUDIO_NOSOUND, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_XAUDIO_44100, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_XAUDIO_48000, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WASAPI_NOSOUND, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WASAPI_44100, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WASAPI_48000, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_INTERPOLATE_FM_0, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_INTERPOLATE_FM_3, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_FRAMES, MF_GRAYED | MF_BYCOMMAND);
|
||||
@@ -1748,6 +1807,7 @@ void MenuEnableItems()
|
||||
|
||||
EnableMenuItem(hMenu, MENU_AUD_PLUGIN_1, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_AUD_PLUGIN_2, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_AUD_PLUGIN_3, MF_GRAYED | MF_BYCOMMAND);
|
||||
|
||||
EnableMenuItem(hMenu, MENU_INP_PLUGIN_1, MF_GRAYED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_INP_PLUGIN_2, MF_GRAYED | MF_BYCOMMAND);
|
||||
@@ -2045,6 +2105,9 @@ void MenuEnableItems()
|
||||
EnableMenuItem(hMenu, MENU_XAUDIO_NOSOUND, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_XAUDIO_44100, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_XAUDIO_48000, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WASAPI_NOSOUND, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WASAPI_44100, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WASAPI_48000, MF_ENABLED | MF_BYCOMMAND);
|
||||
// EnableMenuItem(hMenu, MENU_INTERPOLATE_1, MF_ENABLED | MF_BYCOMMAND);
|
||||
// EnableMenuItem(hMenu, MENU_INTERPOLATE_3, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_WLOGSTART, MF_GRAYED | MF_BYCOMMAND);
|
||||
@@ -2065,6 +2128,7 @@ void MenuEnableItems()
|
||||
|
||||
EnableMenuItem(hMenu, MENU_AUD_PLUGIN_1, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_AUD_PLUGIN_2, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_AUD_PLUGIN_3, MF_ENABLED | MF_BYCOMMAND);
|
||||
|
||||
EnableMenuItem(hMenu, MENU_INP_PLUGIN_1, MF_ENABLED | MF_BYCOMMAND);
|
||||
EnableMenuItem(hMenu, MENU_INP_PLUGIN_2, MF_ENABLED | MF_BYCOMMAND);
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#define IDR_MENU_BLITTER_6 115
|
||||
#define IDR_MENU_AUD_PLUGIN_1 130
|
||||
#define IDR_MENU_AUD_PLUGIN_2 131
|
||||
#define IDR_MENU_AUD_PLUGIN_3 132
|
||||
#define IDR_MENU_GAMESEL 140
|
||||
#define IDR_MENU_LUAWINDOW 150
|
||||
#define IDR_ACCELERATOR 160
|
||||
@@ -601,6 +602,7 @@
|
||||
#define MENU_WINFS 10101
|
||||
#define MENU_FULL 10102
|
||||
#define MENU_DWMFIX 10103
|
||||
#define MENU_VRR 10104
|
||||
#define MENU_NOSTRETCH 10110
|
||||
#define MENU_STRETCH 10111
|
||||
#define MENU_ASPECT 10112
|
||||
@@ -658,12 +660,16 @@
|
||||
#define MENU_DSOUND_BASS 10201
|
||||
#define MENU_XAUDIO_BASS 10202
|
||||
#define MENU_XAUDIO_REVERB 10203
|
||||
#define MENU_WASAPI_BASS 10204
|
||||
#define MENU_DSOUND_NOSOUND 10210
|
||||
#define MENU_DSOUND_44100 10213
|
||||
#define MENU_DSOUND_48000 10214
|
||||
#define MENU_XAUDIO_NOSOUND 10220
|
||||
#define MENU_XAUDIO_44100 10223
|
||||
#define MENU_XAUDIO_48000 10224
|
||||
#define MENU_WASAPI_NOSOUND 10225
|
||||
#define MENU_WASAPI_44100 10226
|
||||
#define MENU_WASAPI_48000 10227
|
||||
#define MENU_INTERPOLATE_0 10230
|
||||
#define MENU_INTERPOLATE_1 10231
|
||||
#define MENU_INTERPOLATE_3 10233
|
||||
|
||||
+106
-14
@@ -60,6 +60,10 @@ struct lua_hotkey_handler hotkey_debounces[] = {
|
||||
{ NULL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
bool EmulatorAppIsFast() {
|
||||
return bAppDoFast;
|
||||
}
|
||||
|
||||
void EmulatorAppDoFast(bool dofast) {
|
||||
bAppDoFast = dofast;
|
||||
bAppDoFasttoggled = 0;
|
||||
@@ -168,31 +172,59 @@ static int GetInput(bool bCopy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static time_t fpstimer;
|
||||
static unsigned int nPreviousFrames;
|
||||
static LARGE_INTEGER qpcFreq, qpcLast;
|
||||
static UINT32 nLastEmu;
|
||||
|
||||
static void DisplayFPSInit()
|
||||
{
|
||||
nDoFPS = 0;
|
||||
fpstimer = 0;
|
||||
nPreviousFrames = (bAppDoFast) ? nFramesEmulated : nFramesRendered;
|
||||
QueryPerformanceFrequency(&qpcFreq);
|
||||
QueryPerformanceCounter(&qpcLast);
|
||||
nLastEmu = nFramesEmulated;
|
||||
}
|
||||
|
||||
static void DisplayFPS()
|
||||
{
|
||||
const int nFPSTotal = (bAppDoFast) ? nFramesEmulated : nFramesRendered;
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
double dt = (double)(now.QuadPart - qpcLast.QuadPart) / qpcFreq.QuadPart;
|
||||
if (dt < 1.0) return; // update once per second
|
||||
|
||||
TCHAR fpsstring[20];
|
||||
time_t temptime = clock();
|
||||
double fps = (double)(nFPSTotal - nPreviousFrames) * CLOCKS_PER_SEC / (temptime - fpstimer);
|
||||
double fps = (nFramesEmulated - nLastEmu) / dt;
|
||||
|
||||
_sntprintf(fpsstring, 7, _T("%2.2lf"), fps);
|
||||
if (fpstimer && temptime - fpstimer>0) { // avoid strange fps values
|
||||
VidSNewShortMsg(fpsstring, 0xDFDFFF, 480, 0);
|
||||
TCHAR s[32];
|
||||
_sntprintf(s, 32, _T("%2.2lf"), fps);
|
||||
VidSNewShortMsg(s, 0xDFDFFF, 480, 0);
|
||||
|
||||
qpcLast = now;
|
||||
nLastEmu = nFramesEmulated;
|
||||
}
|
||||
|
||||
static void DisplayFPSCheckState()
|
||||
{
|
||||
static int bLastFast = -1, bLastPause = -1;
|
||||
static LONGLONG nLastCall = 0;
|
||||
static int timer = 0;
|
||||
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
|
||||
// frame normally runs every ~16.67ms (at 60hz)
|
||||
// a gap over 100ms means something blocked the loop: menu, window drag, dialog, loading...
|
||||
const bool bStalled = nLastCall && qpcFreq.QuadPart &&
|
||||
(now.QuadPart - nLastCall) > qpcFreq.QuadPart / 10;
|
||||
nLastCall = now.QuadPart;
|
||||
|
||||
if (bStalled || bAppDoFast != bLastFast || bRunPause != bLastPause) {
|
||||
timer = 30;
|
||||
bLastFast = bAppDoFast;
|
||||
bLastPause = bRunPause;
|
||||
}
|
||||
if (timer > 0) {
|
||||
// it takes a few frames to stabilize...
|
||||
timer--;
|
||||
DisplayFPSInit();
|
||||
}
|
||||
|
||||
fpstimer = temptime;
|
||||
nPreviousFrames = nFPSTotal;
|
||||
}
|
||||
|
||||
// define this function somewhere above RunMessageLoop()
|
||||
@@ -225,6 +257,62 @@ void do_shonky_profile()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Present pacing when no video sync is active.
|
||||
// Frames are produced when the audio engine signals a free segment, which happens on
|
||||
// its own period (~10ms on Vista+), so frame times alternate e.g. 20/20/10ms.
|
||||
// Presents are held back to a steady QPC schedule which follows the audio clock.
|
||||
static LARGE_INTEGER qpcPaceFreq;
|
||||
static LONGLONG nPaceNext = 0;
|
||||
|
||||
static bool RunPaceActive()
|
||||
{
|
||||
if (bVidVSync || (bVidDWMSync && !nVidFullscreen)) return false;
|
||||
if (bAppDoFast || kNetGame) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void RunPacePresent()
|
||||
{
|
||||
if (!RunPaceActive()) {
|
||||
nPaceNext = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (qpcPaceFreq.QuadPart == 0) {
|
||||
QueryPerformanceFrequency(&qpcPaceFreq);
|
||||
}
|
||||
|
||||
LONGLONG nPeriod;
|
||||
if (bAudPlaying && nBurnSoundRate > 0 && nBurnSoundLen > 0) {
|
||||
nPeriod = qpcPaceFreq.QuadPart * nBurnSoundLen / nBurnSoundRate;
|
||||
} else {
|
||||
nPeriod = qpcPaceFreq.QuadPart * 100 / nAppVirtualFps;
|
||||
}
|
||||
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
|
||||
LONGLONG nLead = nPaceNext - now.QuadPart;
|
||||
if (nPaceNext == 0 || nLead < 0) {
|
||||
// late (or first frame): present now, the schedule follows
|
||||
nPaceNext = now.QuadPart;
|
||||
} else if (nLead > nPeriod) {
|
||||
// schedule drifted ahead of the frame source, pull it back
|
||||
nPaceNext = now.QuadPart + nPeriod;
|
||||
}
|
||||
|
||||
const LONGLONG nSleepMargin = qpcPaceFreq.QuadPart * 2 / 1000;
|
||||
for (;;) {
|
||||
QueryPerformanceCounter(&now);
|
||||
LONGLONG nRemain = nPaceNext - now.QuadPart;
|
||||
if (nRemain <= 0) break;
|
||||
Sleep((bEnableHighResTimer && nRemain > nSleepMargin) ? 1 : 0);
|
||||
}
|
||||
|
||||
nPaceNext += nPeriod;
|
||||
}
|
||||
|
||||
// With or without sound, run one frame.
|
||||
// If bDraw is true, it's the last frame before we are up to date, and so we should draw the screen
|
||||
int RunFrame(int bDraw, int bPause)
|
||||
@@ -232,7 +320,10 @@ int RunFrame(int bDraw, int bPause)
|
||||
static int bPrevPause = 0;
|
||||
static int bPrevDraw = 0;
|
||||
|
||||
if (bShowFPS) DisplayFPSCheckState();
|
||||
|
||||
if (bPrevDraw && !bPause) {
|
||||
RunPacePresent();
|
||||
VidPaint(0); // paint the screen (no need to validate)
|
||||
|
||||
if (!nVidFullscreen && bVidDWMSync) // Sync to DWM (Win7+, windowed)
|
||||
@@ -489,6 +580,7 @@ int RunReset()
|
||||
{
|
||||
// Reset the speed throttling code
|
||||
nNormalLast = 0; nNormalFrac = 0;
|
||||
nPaceNext = 0;
|
||||
|
||||
// Reset FPS display
|
||||
DisplayFPSInit();
|
||||
|
||||
@@ -2295,6 +2295,8 @@ static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify)
|
||||
bVidDWMSync = !bVidDWMSync;
|
||||
if (bVidDWMSync && bVidVSync)
|
||||
bVidVSync = 0;
|
||||
if (bVidDWMSync)
|
||||
bVidVRR = 0;
|
||||
|
||||
POST_INITIALISE_MESSAGE;
|
||||
break;
|
||||
@@ -2909,6 +2911,18 @@ static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify)
|
||||
bVidVSync = !bVidVSync;
|
||||
if (bVidVSync && bVidDWMSync)
|
||||
bVidDWMSync = 0;
|
||||
if (bVidVSync)
|
||||
bVidVRR = 0;
|
||||
|
||||
POST_INITIALISE_MESSAGE;
|
||||
break;
|
||||
|
||||
case MENU_VRR:
|
||||
bVidVRR = !bVidVRR;
|
||||
if (bVidVRR) {
|
||||
bVidVSync = 0;
|
||||
bVidDWMSync = 0;
|
||||
}
|
||||
|
||||
POST_INITIALISE_MESSAGE;
|
||||
break;
|
||||
@@ -2932,6 +2946,11 @@ static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify)
|
||||
POST_INITIALISE_MESSAGE;
|
||||
break;
|
||||
|
||||
case MENU_AUD_PLUGIN_3:
|
||||
AudSelect(2);
|
||||
POST_INITIALISE_MESSAGE;
|
||||
break;
|
||||
|
||||
case MENU_DSOUND_NOSOUND:
|
||||
if (!bDrvOkay) {
|
||||
nAudSampleRate[0] = 0;
|
||||
@@ -2970,6 +2989,25 @@ static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify)
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_WASAPI_NOSOUND:
|
||||
if (!bDrvOkay) {
|
||||
nAudSampleRate[2] = 0;
|
||||
POST_INITIALISE_MESSAGE;
|
||||
}
|
||||
break;
|
||||
case MENU_WASAPI_44100:
|
||||
if (!bDrvOkay) {
|
||||
nAudSampleRate[2] = 44100;
|
||||
POST_INITIALISE_MESSAGE;
|
||||
}
|
||||
break;
|
||||
case MENU_WASAPI_48000:
|
||||
if (!bDrvOkay) {
|
||||
nAudSampleRate[2] = 48000;
|
||||
POST_INITIALISE_MESSAGE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_FRAMES:
|
||||
if (UseDialogs()) {
|
||||
if (!bDrvOkay) {
|
||||
@@ -3012,6 +3050,10 @@ static void OnCommand(HWND /*hDlg*/, int id, HWND /*hwndCtl*/, UINT codeNotify)
|
||||
nAudDSPModule[1] ^= 2;
|
||||
break;
|
||||
|
||||
case MENU_WASAPI_BASS:
|
||||
nAudDSPModule[2] ^= 1;
|
||||
break;
|
||||
|
||||
case MENU_WLOGSTART:
|
||||
AudBlankSound();
|
||||
WaveLogStart();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Audio Output
|
||||
#include "burner.h"
|
||||
|
||||
INT32 nAudSampleRate[8] = { 44100, 44100, 22050, 22050, 22050, 22050, 22050, 22050 }; // sample rate
|
||||
INT32 nAudSampleRate[8] = { 44100, 44100, 48000, 22050, 22050, 22050, 22050, 22050 }; // sample rate
|
||||
INT32 nAudVolume = 10000; // Sound volume (% * 100)
|
||||
INT32 nAudSegCount = 6; // Segs in the pdsbLoop buffer
|
||||
INT32 nAudSegLen = 0; // Seg length in samples (calculated from Rate/Fps)
|
||||
@@ -19,8 +19,11 @@ static UINT32 nAudActive = 0;
|
||||
#if defined (BUILD_WIN32)
|
||||
extern struct AudOut AudOutDx;
|
||||
extern struct AudOut AudOutXAudio2;
|
||||
extern struct AudOut AudOutWASAPI;
|
||||
#elif defined (BUILD_MACOS)
|
||||
extern struct AudOut AudOutMacOS;
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
extern struct AudOut AudOutHeadless;
|
||||
#elif defined (BUILD_SDL)
|
||||
extern struct AudOut AudOutSDL;
|
||||
#elif defined (BUILD_SDL2)
|
||||
@@ -43,8 +46,11 @@ static struct AudOut *pAudOut[]=
|
||||
#if defined (BUILD_WIN32)
|
||||
&AudOutDx,
|
||||
&AudOutXAudio2,
|
||||
&AudOutWASAPI,
|
||||
#elif defined (BUILD_MACOS)
|
||||
&AudOutMacOS,
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
&AudOutHeadless,
|
||||
#elif defined (BUILD_SDL)
|
||||
&AudOutSDL,
|
||||
#elif defined (BUILD_SDL2)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Headless audio output for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// The frontend drives sound directly (it points pBurnSoundOut at its own buffer
|
||||
// and reads it after BurnDrvFrame), so this plugin only satisfies the AudOut
|
||||
// interface. Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
|
||||
static int HeadlessSoundBlank() { return 0; }
|
||||
static int HeadlessSoundCheck() { return 0; }
|
||||
|
||||
static int HeadlessSoundInit()
|
||||
{
|
||||
if (nAudSampleRate[0] <= 0)
|
||||
return 1;
|
||||
bAudOkay = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessSetCallback(int (* /* pCallback */)(int)) { return 0; }
|
||||
static int HeadlessSoundPlay() { bAudPlaying = 1; return 0; }
|
||||
static int HeadlessSoundStop() { bAudPlaying = 0; return 0; }
|
||||
|
||||
static int HeadlessSoundExit()
|
||||
{
|
||||
bAudOkay = 0;
|
||||
bAudPlaying = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessSoundSetVolume() { return 0; }
|
||||
static int HeadlessSoundGetSettings(InterfaceInfo *) { return 0; }
|
||||
|
||||
struct AudOut AudOutHeadless = {
|
||||
HeadlessSoundBlank,
|
||||
HeadlessSoundCheck,
|
||||
HeadlessSoundInit,
|
||||
HeadlessSetCallback,
|
||||
HeadlessSoundPlay,
|
||||
HeadlessSoundStop,
|
||||
HeadlessSoundExit,
|
||||
HeadlessSoundSetVolume,
|
||||
HeadlessSoundGetSettings,
|
||||
_T("Headless audio output"),
|
||||
};
|
||||
@@ -0,0 +1,739 @@
|
||||
// WASAPI (Windows Audio Session API) audio output module for FBNeo
|
||||
// - dink 2026
|
||||
#include "burner.h"
|
||||
#include "aud_dsp.h"
|
||||
|
||||
#include <mmdeviceapi.h>
|
||||
#include <audioclient.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "ole32")
|
||||
#endif
|
||||
|
||||
// These flags are missing from some older SDK / MinGW headers
|
||||
#ifndef AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
|
||||
#define AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
|
||||
#endif
|
||||
#ifndef AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
|
||||
#define AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000
|
||||
#endif
|
||||
#ifndef AUDCLNT_E_DEVICE_INVALIDATED
|
||||
#define AUDCLNT_E_DEVICE_INVALIDATED ((HRESULT)0x88890004L)
|
||||
#endif
|
||||
#ifndef AUDCLNT_E_RESOURCES_INVALIDATED
|
||||
#define AUDCLNT_E_RESOURCES_INVALIDATED ((HRESULT)0x88890026L)
|
||||
#endif
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#endif
|
||||
#ifndef WAVE_FORMAT_EXTENSIBLE
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||
#endif
|
||||
|
||||
// GUIDs are defined locally so we don't depend on __uuidof() or the uuid/ksuser libs
|
||||
static const GUID FBN_CLSID_MMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c, { 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e } };
|
||||
static const GUID FBN_IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35, { 0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6 } };
|
||||
static const GUID FBN_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
|
||||
static const GUID FBN_IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483, { 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2 } };
|
||||
static const GUID FBN_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
static const GUID FBN_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
// PKEY_Device_FriendlyName
|
||||
static const PROPERTYKEY FBN_PKEY_Device_FriendlyName = { { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }, 14 };
|
||||
|
||||
#define WASAPI_PLUGIN 2 // our index in nAudSampleRate[] / nAudDSPModule[]
|
||||
#define REFTIMES_PER_SEC 10000000
|
||||
|
||||
static IMMDeviceEnumerator* pEnumerator = NULL;
|
||||
static IMMDevice* pDevice = NULL;
|
||||
static IAudioClient* pAudioClient = NULL;
|
||||
static IAudioRenderClient* pRenderClient = NULL;
|
||||
static HANDLE hWasapiEvent = NULL;
|
||||
|
||||
int (*WasapiGetNextSound)(int); // Callback used to request more sound
|
||||
static int WasapiSetVolume(); // forward
|
||||
|
||||
static int nWasapiFps = 0; // Application fps * 100
|
||||
static float fWasapiVol = 1.0f; // Software volume (allows > 100%)
|
||||
|
||||
static UINT32 nBufferFrames = 0; // Size of the WASAPI buffer (frames)
|
||||
static UINT32 nTargetFrames = 0; // How full we keep the buffer (frames) = latency
|
||||
|
||||
static bool bStreamStarted = false;
|
||||
static bool bEventDriven = false; // false: fall back to polling
|
||||
static bool bBlanked = false; // AudBlankSound() was called during SoundCheck
|
||||
|
||||
// Output format actually used by the stream
|
||||
enum { FMT_S16 = 0, FMT_S24, FMT_S32, FMT_F32 };
|
||||
static int nOutFormat = FMT_S16;
|
||||
static int nOutChannels = 2;
|
||||
static int nOutBlockAlign = 4;
|
||||
static bool bAutoConvert = false;
|
||||
|
||||
static TCHAR szDeviceName[128] = _T("");
|
||||
|
||||
// Device-lost handling
|
||||
static bool bDeviceLost = false;
|
||||
static DWORD nLastReopenTry = 0;
|
||||
static DWORD nLostLastFrame = 0;
|
||||
|
||||
static int WasapiGetNextSoundFiller(int)
|
||||
{
|
||||
if (nAudNextSound == NULL) {
|
||||
return 1;
|
||||
}
|
||||
AudWriteSilence();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WasapiSetCallback(int (*pCallback)(int))
|
||||
{
|
||||
if (pCallback == NULL) {
|
||||
WasapiGetNextSound = WasapiGetNextSoundFiller;
|
||||
} else {
|
||||
WasapiGetNextSound = pCallback;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sample conversion: 16-bit stereo -> device format, with software volume
|
||||
|
||||
static inline INT32 WasapiClip16(INT32 s)
|
||||
{
|
||||
if (s > 32767) return 32767;
|
||||
if (s < -32768) return -32768;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void WasapiConvert(BYTE* pDst, const INT16* pSrc, UINT32 nFrames)
|
||||
{
|
||||
const bool bFullVol = (fWasapiVol == 1.0f);
|
||||
const INT32 nVol = (INT32)(fWasapiVol * 65536.0f); // 16.16 fixed point
|
||||
|
||||
for (UINT32 i = 0; i < nFrames; i++) {
|
||||
INT32 l = pSrc[i * 2 + 0];
|
||||
INT32 r = pSrc[i * 2 + 1];
|
||||
|
||||
if (!bFullVol) {
|
||||
l = WasapiClip16((INT32)(((INT64)l * nVol) >> 16));
|
||||
r = WasapiClip16((INT32)(((INT64)r * nVol) >> 16));
|
||||
}
|
||||
|
||||
switch (nOutFormat) {
|
||||
case FMT_S16: {
|
||||
INT16* d = (INT16*)pDst;
|
||||
d[0] = (INT16)l;
|
||||
d[1] = (INT16)r;
|
||||
for (int c = 2; c < nOutChannels; c++) d[c] = 0;
|
||||
break;
|
||||
}
|
||||
case FMT_S24: {
|
||||
BYTE* d = pDst;
|
||||
INT32 v[2] = { l << 8, r << 8 };
|
||||
for (int c = 0; c < 2; c++) {
|
||||
d[c * 3 + 0] = (BYTE)(v[c] & 0xff);
|
||||
d[c * 3 + 1] = (BYTE)((v[c] >> 8) & 0xff);
|
||||
d[c * 3 + 2] = (BYTE)((v[c] >> 16) & 0xff);
|
||||
}
|
||||
memset(d + 6, 0, (nOutChannels - 2) * 3);
|
||||
break;
|
||||
}
|
||||
case FMT_S32: {
|
||||
INT32* d = (INT32*)pDst;
|
||||
d[0] = l << 16;
|
||||
d[1] = r << 16;
|
||||
for (int c = 2; c < nOutChannels; c++) d[c] = 0;
|
||||
break;
|
||||
}
|
||||
case FMT_F32: {
|
||||
float* d = (float*)pDst;
|
||||
d[0] = (float)l * (1.0f / 32768.0f);
|
||||
d[1] = (float)r * (1.0f / 32768.0f);
|
||||
for (int c = 2; c < nOutChannels; c++) d[c] = 0.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pDst += nOutBlockAlign;
|
||||
}
|
||||
}
|
||||
|
||||
// Device / stream setup
|
||||
|
||||
static void WasapiReleaseStream()
|
||||
{
|
||||
if (pAudioClient && bStreamStarted) {
|
||||
pAudioClient->Stop();
|
||||
}
|
||||
bStreamStarted = false;
|
||||
|
||||
RELEASE(pRenderClient);
|
||||
RELEASE(pAudioClient);
|
||||
RELEASE(pDevice);
|
||||
RELEASE(pEnumerator);
|
||||
}
|
||||
|
||||
static void WasapiGetDeviceName()
|
||||
{
|
||||
szDeviceName[0] = 0;
|
||||
|
||||
IPropertyStore* pProps = NULL;
|
||||
if (pDevice && SUCCEEDED(pDevice->OpenPropertyStore(STGM_READ, &pProps))) {
|
||||
PROPVARIANT varName;
|
||||
PropVariantInit(&varName);
|
||||
if (SUCCEEDED(pProps->GetValue(FBN_PKEY_Device_FriendlyName, &varName)) && varName.vt == VT_LPWSTR && varName.pwszVal) {
|
||||
#if defined (_UNICODE)
|
||||
wcsncpy(szDeviceName, varName.pwszVal, 127);
|
||||
#else
|
||||
WideCharToMultiByte(CP_ACP, 0, varName.pwszVal, -1, szDeviceName, 128, NULL, NULL);
|
||||
#endif
|
||||
szDeviceName[127] = 0;
|
||||
}
|
||||
PropVariantClear(&varName);
|
||||
pProps->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// Work out how to feed a given (mix) format; returns 0 if we can handle it
|
||||
static int WasapiParseFormat(const WAVEFORMATEX* pwfx)
|
||||
{
|
||||
if (pwfx->nChannels < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool bFloat = false;
|
||||
bool bPCM = false;
|
||||
|
||||
if (pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
|
||||
bFloat = true;
|
||||
} else if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
|
||||
bPCM = true;
|
||||
} else if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE && pwfx->cbSize >= 22) {
|
||||
const WAVEFORMATEXTENSIBLE* pwfxe = (const WAVEFORMATEXTENSIBLE*)pwfx;
|
||||
if (IsEqualGUID(pwfxe->SubFormat, FBN_SUBTYPE_IEEE_FLOAT)) bFloat = true;
|
||||
if (IsEqualGUID(pwfxe->SubFormat, FBN_SUBTYPE_PCM)) bPCM = true;
|
||||
}
|
||||
|
||||
if (bFloat && pwfx->wBitsPerSample == 32) {
|
||||
nOutFormat = FMT_F32;
|
||||
} else if (bPCM && pwfx->wBitsPerSample == 16) {
|
||||
nOutFormat = FMT_S16;
|
||||
} else if (bPCM && pwfx->wBitsPerSample == 24) {
|
||||
nOutFormat = FMT_S24;
|
||||
} else if (bPCM && pwfx->wBitsPerSample == 32) {
|
||||
nOutFormat = FMT_S32;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
nOutChannels = pwfx->nChannels;
|
||||
nOutBlockAlign = pwfx->nBlockAlign;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Activate a fresh IAudioClient on pDevice and initialise it. A client can only be
|
||||
// Initialize()d once, so every attempt gets its own instance.
|
||||
static HRESULT WasapiTryInit(const WAVEFORMATEX* pwfx, DWORD nFlags, REFERENCE_TIME hnsBuffer)
|
||||
{
|
||||
RELEASE(pAudioClient);
|
||||
|
||||
HRESULT hr = pDevice->Activate(FBN_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, nFlags, hnsBuffer, 0, pwfx, NULL);
|
||||
if (FAILED(hr)) {
|
||||
RELEASE(pAudioClient);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static int WasapiOpenStream()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = CoCreateInstance(FBN_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, FBN_IID_IMMDeviceEnumerator, (void**)&pEnumerator))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice))) {
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
|
||||
WasapiGetDeviceName();
|
||||
|
||||
// The buffer we ask for holds nAudSegCount frames of emulation - same latency as the other plugins.
|
||||
REFERENCE_TIME hnsBuffer = (REFERENCE_TIME)REFTIMES_PER_SEC * nAudSegLen * nAudSegCount / nAudSampleRate[WASAPI_PLUGIN];
|
||||
|
||||
// Our native format: 16-bit stereo PCM at the selected rate
|
||||
WAVEFORMATEX wfx;
|
||||
memset(&wfx, 0, sizeof(wfx));
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nChannels = 2;
|
||||
wfx.nSamplesPerSec = nAudSampleRate[WASAPI_PLUGIN];
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nBlockAlign = 4;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
wfx.cbSize = 0;
|
||||
|
||||
const DWORD nAutoConv = AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||
|
||||
bEventDriven = true;
|
||||
bAutoConvert = true;
|
||||
nOutFormat = FMT_S16; nOutChannels = 2; nOutBlockAlign = 4;
|
||||
|
||||
// 1) 16-bit stereo, let Windows resample/convert to the mix format (Win7+)
|
||||
hr = WasapiTryInit(&wfx, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | nAutoConv, hnsBuffer);
|
||||
|
||||
// 2) Device mix format, converted by us (only possible if the rate matches)
|
||||
if (FAILED(hr)) {
|
||||
WAVEFORMATEX* pMix = NULL;
|
||||
IAudioClient* pTmp = NULL;
|
||||
|
||||
bAutoConvert = false;
|
||||
|
||||
if (SUCCEEDED(pDevice->Activate(FBN_IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pTmp))) {
|
||||
if (SUCCEEDED(pTmp->GetMixFormat(&pMix)) && pMix) {
|
||||
if (pMix->nSamplesPerSec == (DWORD)nAudSampleRate[WASAPI_PLUGIN] && WasapiParseFormat(pMix) == 0) {
|
||||
hr = WasapiTryInit(pMix, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, hnsBuffer);
|
||||
if (FAILED(hr)) {
|
||||
bEventDriven = false;
|
||||
hr = WasapiTryInit(pMix, 0, hnsBuffer);
|
||||
}
|
||||
}
|
||||
CoTaskMemFree(pMix);
|
||||
}
|
||||
pTmp->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Last resort: auto-convert without event callback (polling)
|
||||
if (FAILED(hr)) {
|
||||
bEventDriven = false;
|
||||
bAutoConvert = true;
|
||||
nOutFormat = FMT_S16; nOutChannels = 2; nOutBlockAlign = 4;
|
||||
hr = WasapiTryInit(&wfx, nAutoConv, hnsBuffer);
|
||||
}
|
||||
|
||||
if (FAILED(hr) || pAudioClient == NULL) {
|
||||
#ifdef PRINT_DEBUG_INFO
|
||||
bprintf(0, _T("*** WASAPI: unable to initialise audio client (0x%08x).\n"), hr);
|
||||
#endif
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bEventDriven) {
|
||||
if (FAILED(pAudioClient->SetEventHandle(hWasapiEvent))) {
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(pAudioClient->GetBufferSize(&nBufferFrames))) {
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (FAILED(pAudioClient->GetService(FBN_IID_IAudioRenderClient, (void**)&pRenderClient))) {
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Keep the buffer filled up to nAudSegCount segs (or as much as fits)
|
||||
nTargetFrames = nAudSegLen * nAudSegCount;
|
||||
if (nTargetFrames > nBufferFrames) {
|
||||
nTargetFrames = nBufferFrames;
|
||||
}
|
||||
if (nTargetFrames < (UINT32)nAudSegLen) {
|
||||
// WASAPI gave us a buffer smaller than one frame of sound - can't work with that
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fill the buffer up to the target with silence
|
||||
static void WasapiPrefill()
|
||||
{
|
||||
UINT32 nPadding = 0;
|
||||
BYTE* pData = NULL;
|
||||
|
||||
if (pAudioClient == NULL || pRenderClient == NULL) {
|
||||
return;
|
||||
}
|
||||
if (FAILED(pAudioClient->GetCurrentPadding(&nPadding))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// leave room for one seg so the first SoundCheck can run a frame immediately
|
||||
INT32 nFill = (INT32)nTargetFrames - (INT32)nAudSegLen - (INT32)nPadding;
|
||||
if (nFill > 0 && SUCCEEDED(pRenderClient->GetBuffer(nFill, &pData))) {
|
||||
pRenderClient->ReleaseBuffer(nFill, AUDCLNT_BUFFERFLAGS_SILENT);
|
||||
}
|
||||
}
|
||||
|
||||
static int WasapiStartStream()
|
||||
{
|
||||
if (pAudioClient == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
WasapiPrefill();
|
||||
|
||||
if (FAILED(pAudioClient->Start())) {
|
||||
return 1;
|
||||
}
|
||||
bStreamStarted = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Default device changed / unplugged etc. Try to reopen on the (new) default device.
|
||||
static int WasapiReopen()
|
||||
{
|
||||
WasapiReleaseStream();
|
||||
ResetEvent(hWasapiEvent);
|
||||
|
||||
if (WasapiOpenStream()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bAudPlaying) {
|
||||
if (WasapiStartStream()) {
|
||||
WasapiReleaseStream();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WasapiDeviceLost()
|
||||
{
|
||||
#ifdef PRINT_DEBUG_INFO
|
||||
bprintf(0, _T("*** WASAPI: audio device lost, will try to reopen.\n"));
|
||||
#endif
|
||||
WasapiReleaseStream();
|
||||
bDeviceLost = true;
|
||||
nLastReopenTry = timeGetTime();
|
||||
nLostLastFrame = nLastReopenTry;
|
||||
}
|
||||
|
||||
// Plugin interface
|
||||
|
||||
static int WasapiBlankSound()
|
||||
{
|
||||
if (nAudNextSound) {
|
||||
AudWriteSilence();
|
||||
}
|
||||
|
||||
// Throw away whatever is queued in the device buffer and refill with silence
|
||||
if (pAudioClient && pRenderClient) {
|
||||
bBlanked = true;
|
||||
if (bStreamStarted) {
|
||||
pAudioClient->Stop();
|
||||
pAudioClient->Reset();
|
||||
WasapiPrefill();
|
||||
pAudioClient->Start();
|
||||
} else {
|
||||
pAudioClient->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write the seg in nAudNextSound to the device
|
||||
static HRESULT WasapiWriteSeg()
|
||||
{
|
||||
BYTE* pData = NULL;
|
||||
HRESULT hr = pRenderClient->GetBuffer(nAudSegLen, &pData);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
WasapiConvert(pData, nAudNextSound, nAudSegLen);
|
||||
|
||||
return pRenderClient->ReleaseBuffer(nAudSegLen, 0);
|
||||
}
|
||||
|
||||
// Called continuously by the run loop: blocks until there's room for at least one
|
||||
// seg of sound, then runs the emulation for each free seg (drawing only the last one,
|
||||
// unless bAlwaysDrawFrames) - same pacing model as the DirectSound plugin.
|
||||
static int WasapiSoundCheck()
|
||||
{
|
||||
if (nAudNextSound == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bDeviceLost) {
|
||||
DWORD nNow = timeGetTime();
|
||||
|
||||
if (nNow - nLastReopenTry >= 1000) {
|
||||
nLastReopenTry = nNow;
|
||||
if (WasapiReopen() == 0) {
|
||||
bDeviceLost = false;
|
||||
#ifdef PRINT_DEBUG_INFO
|
||||
bprintf(0, _T("*** WASAPI: audio device reopened.\n"));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// No device: keep the emulation running at roughly the right speed, without sound
|
||||
DWORD nFrameMs = 100000 / (nWasapiFps ? nWasapiFps : 6000);
|
||||
if (nNow - nLostLastFrame < nFrameMs) {
|
||||
Sleep(1);
|
||||
return 0;
|
||||
}
|
||||
nLostLastFrame += nFrameMs;
|
||||
if (nNow - nLostLastFrame > nFrameMs * 4) nLostLastFrame = nNow; // don't try to catch up forever
|
||||
|
||||
WasapiGetNextSound(true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pAudioClient == NULL || pRenderClient == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!bAudPlaying) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
UINT32 nPadding = 0;
|
||||
HRESULT hr = pAudioClient->GetCurrentPadding(&nPadding);
|
||||
if (FAILED(hr)) {
|
||||
if (hr == AUDCLNT_E_DEVICE_INVALIDATED || hr == AUDCLNT_E_RESOURCES_INVALIDATED) {
|
||||
WasapiDeviceLost();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
INT32 nFree = (INT32)nTargetFrames - (INT32)nPadding;
|
||||
|
||||
if (nFree < nAudSegLen) {
|
||||
// Buffer is full enough - wait for the device to consume some
|
||||
if (bEventDriven) {
|
||||
// Event fires once per device period (~10ms); bail out after a while so the UI stays responsive
|
||||
DWORD nWait = WaitForSingleObject(hWasapiEvent, 200);
|
||||
#ifdef PRINT_DEBUG_INFO
|
||||
if (nWait == WAIT_TIMEOUT) {
|
||||
bprintf(0, _T("*** WASAPI playback notification timeout.\n"));
|
||||
}
|
||||
#else
|
||||
(void)nWait;
|
||||
#endif
|
||||
} else {
|
||||
Sleep(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 nSegs = nFree / nAudSegLen;
|
||||
|
||||
bBlanked = false;
|
||||
|
||||
for (INT32 i = 0; i < nSegs; i++) {
|
||||
// get more sound into nAudNextSound
|
||||
WasapiGetNextSound((i == nSegs - 1) || bAlwaysDrawFrames); // If this is the last seg of sound, draw the graphics (frameskipping)
|
||||
|
||||
if (nAudNextSound == NULL || pRenderClient == NULL) {
|
||||
// sound was shut down from inside the callback
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nAudDSPModule[WASAPI_PLUGIN] & 1) {
|
||||
if (bRunPause)
|
||||
AudWriteSilence();
|
||||
else
|
||||
DspDo(nAudNextSound, nAudSegLen);
|
||||
}
|
||||
|
||||
hr = WasapiWriteSeg();
|
||||
if (FAILED(hr)) {
|
||||
if (hr == AUDCLNT_E_DEVICE_INVALIDATED || hr == AUDCLNT_E_RESOURCES_INVALIDATED) {
|
||||
WasapiDeviceLost();
|
||||
}
|
||||
// AUDCLNT_E_BUFFER_TOO_LARGE: the callback blanked/refilled the buffer, just drop this seg
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bBlanked) {
|
||||
// buffer was flushed & re-primed from inside the callback (frame step etc.), start over
|
||||
bBlanked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WasapiExit()
|
||||
{
|
||||
DspExit();
|
||||
|
||||
WasapiReleaseStream();
|
||||
|
||||
if (hWasapiEvent) {
|
||||
CloseHandle(hWasapiEvent);
|
||||
hWasapiEvent = NULL;
|
||||
}
|
||||
|
||||
if (nAudNextSound) {
|
||||
free(nAudNextSound);
|
||||
nAudNextSound = NULL;
|
||||
}
|
||||
|
||||
WasapiGetNextSound = NULL;
|
||||
|
||||
bDeviceLost = false;
|
||||
nBufferFrames = 0;
|
||||
nTargetFrames = 0;
|
||||
szDeviceName[0] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WasapiInit()
|
||||
{
|
||||
if (nAudSampleRate[WASAPI_PLUGIN] <= 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (FAILED(nCOMInit)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
nWasapiFps = nAppVirtualFps;
|
||||
|
||||
// Calculate the Seg Length (round to nearest sample)
|
||||
nAudSegLen = (nAudSampleRate[WASAPI_PLUGIN] * 100 + (nWasapiFps >> 1)) / nWasapiFps;
|
||||
nAudAllocSegLen = nAudSegLen << 2;
|
||||
|
||||
bDeviceLost = false;
|
||||
bStreamStarted = false;
|
||||
|
||||
hWasapiEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset
|
||||
if (hWasapiEvent == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (WasapiOpenStream()) {
|
||||
WasapiExit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Note: +2 is a hacky work-around for crashy Midway games (mk2, etc) via Kaillera (same as DirectSound)
|
||||
nAudNextSound = (INT16*)malloc(nAudSegLen << (2 + 2)); // The next sound block to put in the stream
|
||||
if (nAudNextSound == NULL) {
|
||||
WasapiExit();
|
||||
return 1;
|
||||
}
|
||||
AudWriteSilence();
|
||||
|
||||
WasapiSetCallback(NULL);
|
||||
|
||||
DspInit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WasapiPlay()
|
||||
{
|
||||
if (bDeviceLost) {
|
||||
// will be started when the device comes back
|
||||
WasapiSetVolume();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pAudioClient == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nAudNextSound) {
|
||||
AudWriteSilence();
|
||||
}
|
||||
|
||||
WasapiSetVolume();
|
||||
|
||||
if (bStreamStarted) {
|
||||
pAudioClient->Stop();
|
||||
bStreamStarted = false;
|
||||
}
|
||||
pAudioClient->Reset();
|
||||
|
||||
if (WasapiStartStream()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WasapiStop()
|
||||
{
|
||||
if (!bAudOkay) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pAudioClient && bStreamStarted) {
|
||||
pAudioClient->Stop();
|
||||
pAudioClient->Reset();
|
||||
}
|
||||
bStreamStarted = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WasapiSetVolume()
|
||||
{
|
||||
// Same curve as the XAudio2 plugin, volume > 100% is allowed (samples are clipped)
|
||||
if (nAudVolume == 10000) {
|
||||
fWasapiVol = 1.0f;
|
||||
} else if (nAudVolume <= 0) {
|
||||
fWasapiVol = 0.0f;
|
||||
} else {
|
||||
fWasapiVol = (float)(((double)nAudVolume / 10000) * ((double)nAudVolume / 10000));
|
||||
}
|
||||
|
||||
return 1; // 1 succeeds here (as XAudio2).
|
||||
}
|
||||
|
||||
static int WasapiGetSettings(InterfaceInfo* pInfo)
|
||||
{
|
||||
TCHAR szString[MAX_PATH] = _T("");
|
||||
|
||||
if (bDeviceLost) {
|
||||
_sntprintf(szString, MAX_PATH, _T("Audio device lost, waiting for it to return"));
|
||||
IntInfoAddStringModule(pInfo, szString);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (szDeviceName[0]) {
|
||||
_sntprintf(szString, MAX_PATH, _T("Device: %s"), szDeviceName);
|
||||
IntInfoAddStringModule(pInfo, szString);
|
||||
}
|
||||
|
||||
_sntprintf(szString, MAX_PATH, _T("Shared mode, %s, %s"),
|
||||
bEventDriven ? _T("event driven") : _T("polled"),
|
||||
bAutoConvert ? _T("converted by Windows") : _T("converted to device mix format"));
|
||||
IntInfoAddStringModule(pInfo, szString);
|
||||
|
||||
if (nAudSampleRate[WASAPI_PLUGIN] > 0) {
|
||||
_sntprintf(szString, MAX_PATH, _T("Audio is delayed by approx. %ims (device buffer %ims)"),
|
||||
(int)((INT64)nTargetFrames * 1000 / nAudSampleRate[WASAPI_PLUGIN]),
|
||||
(int)((INT64)nBufferFrames * 1000 / nAudSampleRate[WASAPI_PLUGIN]));
|
||||
IntInfoAddStringModule(pInfo, szString);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct AudOut AudOutWASAPI = { WasapiBlankSound, WasapiSoundCheck, WasapiInit, WasapiSetCallback, WasapiPlay, WasapiStop, WasapiExit, WasapiSetVolume, WasapiGetSettings, _T("WASAPI audio output") };
|
||||
@@ -0,0 +1,63 @@
|
||||
// Headless input for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// Reads a digital switch state table populated by the host via
|
||||
// FBHeadlessSetInputState(). InputMake() calls ReadSwitch() while building each
|
||||
// frame's GameInp. Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
#include "fbheadless.h"
|
||||
|
||||
// Indexed by FBNeo input switch code (masked); 0 = released, non-zero = pressed.
|
||||
#define HEADLESS_INPUT_TABLE_SIZE 0x200
|
||||
static unsigned char inputState[HEADLESS_INPUT_TABLE_SIZE];
|
||||
|
||||
static int HeadlessInpInit()
|
||||
{
|
||||
memset(inputState, 0, sizeof(inputState));
|
||||
bInputOkay = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessInpExit()
|
||||
{
|
||||
bInputOkay = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessInpSetCooperativeLevel(bool /* bExclusive */, bool /* bForeground */) { return 0; }
|
||||
static int HeadlessInpNewFrame() { return 0; }
|
||||
|
||||
static int HeadlessInpReadSwitch(int nCode)
|
||||
{
|
||||
return inputState[nCode & (HEADLESS_INPUT_TABLE_SIZE - 1)] ? 1 : 0;
|
||||
}
|
||||
|
||||
static int HeadlessInpReadJoyAxis(int /* i */, int /* nAxis */) { return 0; }
|
||||
static int HeadlessInpReadMouseAxis(int /* i */, int /* nAxis */) { return 0; }
|
||||
static int HeadlessInpFind(bool /* createBaseline */) { return -1; }
|
||||
|
||||
static int HeadlessInpGetControlName(int /* nCode */, TCHAR * /* dev */, TCHAR * /* ctrl */) { return 0; }
|
||||
static int HeadlessInpGetSettings(InterfaceInfo *) { return 0; }
|
||||
|
||||
struct InputInOut InputInOutHeadless = {
|
||||
HeadlessInpInit,
|
||||
HeadlessInpExit,
|
||||
HeadlessInpSetCooperativeLevel,
|
||||
HeadlessInpNewFrame,
|
||||
HeadlessInpReadSwitch,
|
||||
HeadlessInpReadJoyAxis,
|
||||
HeadlessInpReadMouseAxis,
|
||||
HeadlessInpFind,
|
||||
HeadlessInpGetControlName,
|
||||
HeadlessInpGetSettings,
|
||||
_T("Headless input"),
|
||||
};
|
||||
|
||||
extern "C" void FBHeadlessSetInputState(int code, int value)
|
||||
{
|
||||
inputState[code & (HEADLESS_INPUT_TABLE_SIZE - 1)] = value ? 1 : 0;
|
||||
}
|
||||
@@ -16,6 +16,8 @@ static bool bCinpOkay;
|
||||
extern struct InputInOut InputInOutXInput;
|
||||
#elif defined (BUILD_MACOS)
|
||||
extern struct InputInOut InputInOutMacOS;
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
extern struct InputInOut InputInOutHeadless;
|
||||
#elif defined (BUILD_SDL)
|
||||
extern struct InputInOut InputInOutSDL;
|
||||
#elif defined (BUILD_SDL2)
|
||||
@@ -33,6 +35,8 @@ static struct InputInOut *pInputInOut[]=
|
||||
&InputInOutXInput,
|
||||
#elif defined (BUILD_MACOS)
|
||||
&InputInOutMacOS,
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
&InputInOutHeadless,
|
||||
#elif defined (BUILD_SDL2)
|
||||
&InputInOutSDL2,
|
||||
#elif defined (BUILD_SDL)
|
||||
|
||||
@@ -241,6 +241,7 @@ extern INT64 nVidBlitterOpt[];
|
||||
extern INT32 bVidFullStretch;
|
||||
extern INT32 bVidTripleBuffer;
|
||||
extern INT32 bVidVSync;
|
||||
extern INT32 bVidVRR;
|
||||
extern double dVidCubicB;
|
||||
extern double dVidCubicC;
|
||||
extern INT32 bVidDX9Bilinear;
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
// Headless video output for FinalBurn Neo.
|
||||
// Author: Leonardo Kasperavičius
|
||||
//
|
||||
// Adapted from the macOS video interface by Akop Karapetyan
|
||||
// https://github.com/0xe1f/FinalBurn-X (Apache License 2.0)
|
||||
//
|
||||
// Built originally to support OpenEmu-Silicon
|
||||
// (https://github.com/OpenEmu-Silicon/OpenEmu-Silicon).
|
||||
//
|
||||
// FBNeo renders every game in its native orientation (vertical games come out
|
||||
// sideways), so this keeps a native render buffer for the emulator and presents
|
||||
// an upright, correctly-pitched buffer to the host, rotating when needed.
|
||||
// Subject to the FB Neo license (see src/license.txt).
|
||||
|
||||
#include "burner.h"
|
||||
#include "fbheadless.h"
|
||||
|
||||
static unsigned char *nativeBuffer = NULL; // FBNeo renders here (pBurnDraw), nativeBpp deep
|
||||
static unsigned char *displayBuffer = NULL; // exposed to the host, always 32bpp upright
|
||||
static int nativeW = 0, nativeH = 0;
|
||||
static int dispW = 0, dispH = 0;
|
||||
static int nativeBpp = 0; // FBNeo render depth in bytes: 2 (BDF_16BIT_ONLY) or 4
|
||||
static int rotate = 0; // 0 none, 1 CW90, 2 180, 3 CCW90
|
||||
|
||||
static void freeBuffers()
|
||||
{
|
||||
if (displayBuffer && displayBuffer != nativeBuffer)
|
||||
free(displayBuffer);
|
||||
free(nativeBuffer);
|
||||
nativeBuffer = NULL;
|
||||
displayBuffer = NULL;
|
||||
}
|
||||
|
||||
static int HeadlessVideoInit()
|
||||
{
|
||||
int vw = 0, vh = 0;
|
||||
int flags = BurnDrvGetFlags();
|
||||
BurnDrvGetVisibleSize(&vw, &vh);
|
||||
|
||||
// Some drivers (Cave, CPS3, Megadrive) are BDF_16BIT_ONLY: their blitters only
|
||||
// write RGB565, so render those at 16bpp and convert to 32bpp on present. All
|
||||
// others render straight 32bpp XRGB8888, which the host consumes directly.
|
||||
if (flags & BDF_16BIT_ONLY) {
|
||||
nativeBpp = 2;
|
||||
nVidImageDepth = 16;
|
||||
} else {
|
||||
nativeBpp = 4;
|
||||
nVidImageDepth = 32;
|
||||
}
|
||||
nVidImageBPP = nativeBpp;
|
||||
SetBurnHighCol(nVidImageDepth);
|
||||
|
||||
if (flags & BDF_ORIENTATION_VERTICAL) {
|
||||
// Visible size is the upright (display) size; FBNeo renders it sideways.
|
||||
nativeW = vh; nativeH = vw;
|
||||
dispW = vw; dispH = vh;
|
||||
rotate = (flags & BDF_ORIENTATION_FLIPPED) ? 1 : 3; // CW : CCW
|
||||
} else {
|
||||
nativeW = vw; nativeH = vh;
|
||||
dispW = vw; dispH = vh;
|
||||
rotate = (flags & BDF_ORIENTATION_FLIPPED) ? 2 : 0; // 180 : none
|
||||
}
|
||||
|
||||
freeBuffers();
|
||||
nativeBuffer = (unsigned char *)malloc(nativeW * nativeH * nativeBpp);
|
||||
if (nativeBuffer == NULL)
|
||||
return 1;
|
||||
memset(nativeBuffer, 0, nativeW * nativeH * nativeBpp);
|
||||
|
||||
// The host always receives 32bpp. Zero-copy only when FBNeo already renders
|
||||
// 32bpp AND upright; otherwise present() fills a dedicated 32bpp buffer
|
||||
// (converting 16->32 and/or rotating).
|
||||
if (nativeBpp == 4 && rotate == 0) {
|
||||
displayBuffer = nativeBuffer;
|
||||
} else {
|
||||
displayBuffer = (unsigned char *)malloc(dispW * dispH * 4);
|
||||
if (displayBuffer == NULL)
|
||||
return 1;
|
||||
memset(displayBuffer, 0, dispW * dispH * 4);
|
||||
}
|
||||
|
||||
// FBNeo draws into the native buffer, pitch = native width.
|
||||
nVidImageWidth = nativeW;
|
||||
nVidImageHeight = nativeH;
|
||||
nVidImagePitch = nativeW * nativeBpp;
|
||||
nBurnBpp = nativeBpp;
|
||||
nBurnPitch = nativeW * nativeBpp;
|
||||
pVidImage = nativeBuffer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessVideoExit()
|
||||
{
|
||||
freeBuffers();
|
||||
nativeW = nativeH = dispW = dispH = nativeBpp = rotate = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// RGB565 -> 0x00RRGGBB, matching SetBurnHighCol(32)'s component order.
|
||||
static inline uint32_t rgb565_to_xrgb8888(uint16_t p)
|
||||
{
|
||||
uint32_t r = (p >> 11) & 0x1F;
|
||||
uint32_t g = (p >> 5) & 0x3F;
|
||||
uint32_t b = p & 0x1F;
|
||||
r = (r << 3) | (r >> 2);
|
||||
g = (g << 2) | (g >> 4);
|
||||
b = (b << 3) | (b >> 2);
|
||||
return (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
// Map a display pixel (dx,dy) back to its native-buffer coordinate for the
|
||||
// current rotation. Native/display dims are swapped for the 90-degree cases.
|
||||
static inline void src_coord(int dx, int dy, int *sx, int *sy)
|
||||
{
|
||||
switch (rotate) {
|
||||
case 1: *sx = dy; *sy = nativeH - 1 - dx; break; // CW 90
|
||||
case 3: *sx = nativeW - 1 - dy; *sy = dx; break; // CCW 90
|
||||
case 2: *sx = dispW - 1 - dx; *sy = dispH - 1 - dy; break; // 180
|
||||
default: *sx = dx; *sy = dy; break; // none
|
||||
}
|
||||
}
|
||||
|
||||
// Present the freshly rendered native frame to the host: convert 16->32bpp for
|
||||
// BDF_16BIT_ONLY drivers and/or rotate vertical games upright. Called by the
|
||||
// frontend after BurnDrvFrame. The zero-copy case (32bpp, upright) is a no-op.
|
||||
void headless_video_present(void)
|
||||
{
|
||||
if (displayBuffer == nativeBuffer)
|
||||
return;
|
||||
|
||||
uint32_t *dst = (uint32_t *)displayBuffer;
|
||||
|
||||
if (nativeBpp == 2) {
|
||||
const uint16_t *src = (const uint16_t *)nativeBuffer;
|
||||
for (int dy = 0; dy < dispH; dy++)
|
||||
for (int dx = 0; dx < dispW; dx++) {
|
||||
int sx, sy;
|
||||
src_coord(dx, dy, &sx, &sy);
|
||||
dst[dy * dispW + dx] = rgb565_to_xrgb8888(src[sy * nativeW + sx]);
|
||||
}
|
||||
} else {
|
||||
const uint32_t *src = (const uint32_t *)nativeBuffer;
|
||||
for (int dy = 0; dy < dispH; dy++)
|
||||
for (int dx = 0; dx < dispW; dx++) {
|
||||
int sx, sy;
|
||||
src_coord(dx, dy, &sx, &sy);
|
||||
dst[dy * dispW + dx] = src[sy * nativeW + sx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int HeadlessVideoFrame(bool redraw)
|
||||
{
|
||||
if (pVidImage == NULL || bRunPause)
|
||||
return 0;
|
||||
VidFrameCallback(redraw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessVideoPaint(int /* validate */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessVideoScale(RECT *, int, int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HeadlessVideoGetSettings(InterfaceInfo *)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct VidOut VidOutHeadless = {
|
||||
HeadlessVideoInit,
|
||||
HeadlessVideoExit,
|
||||
HeadlessVideoFrame,
|
||||
HeadlessVideoPaint,
|
||||
HeadlessVideoScale,
|
||||
HeadlessVideoGetSettings,
|
||||
_T("Headless Video"),
|
||||
};
|
||||
|
||||
// --- C accessors for the host wrapper ---
|
||||
|
||||
extern "C" const unsigned char *FBHeadlessGetVideoBuffer(void) { return displayBuffer; }
|
||||
extern "C" int FBHeadlessGetVideoWidth(void) { return dispW; }
|
||||
extern "C" int FBHeadlessGetVideoHeight(void) { return dispH; }
|
||||
extern "C" int FBHeadlessGetVideoPitch(void) { return dispW * 4; }
|
||||
extern "C" int FBHeadlessGetVideoBPP(void) { return 4; }
|
||||
@@ -15,6 +15,8 @@
|
||||
extern struct VidOut VidOutD3D11;
|
||||
#elif defined (BUILD_MACOS)
|
||||
extern struct VidOut VidOutMacOS;
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
extern struct VidOut VidOutHeadless;
|
||||
#elif defined (BUILD_PI)
|
||||
extern struct VidOut VidOutPi;
|
||||
#elif defined (BUILD_SDL2)
|
||||
@@ -39,6 +41,8 @@ static struct VidOut *pVidOut[] = {
|
||||
&VidOutD3D11,
|
||||
#elif defined (BUILD_MACOS)
|
||||
&VidOutMacOS,
|
||||
#elif defined (BUILD_HEADLESS)
|
||||
&VidOutHeadless,
|
||||
#elif defined (BUILD_PI)
|
||||
&VidOutPi,
|
||||
#elif defined (BUILD_SDL2)
|
||||
@@ -86,6 +90,7 @@ INT32 bVidFullStretch = 0; // 1 = stretch to fill the entire window/screen
|
||||
INT32 bVidCorrectAspect = 1; // 1 = stretch to fill the window/screen while maintaining the correct aspect ratio
|
||||
INT32 bVidIntegerScale = 0; // Wants integer scaling
|
||||
INT32 bVidVSync = 0; // 1 = sync blits/pageflips/presents to the screen
|
||||
INT32 bVidVRR = 0; // 1 = variable refresh rate (G-Sync/FreeSync), DX11 blitter only
|
||||
INT32 bVidTripleBuffer = 0; // 1 = use triple buffering
|
||||
INT32 bVidBilinear = 1; // 1 = enable bi-linear filtering (D3D blitter)
|
||||
INT32 bVidScanlines = 0; // 1 = draw scanlines
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
static const GUID FBNEO_IID_IDXGIDevice = { 0x54ec77fa, 0x1377, 0x44e6, { 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c } };
|
||||
static const GUID FBNEO_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
|
||||
static const GUID FBNEO_IID_IDXGIFactory = { 0x7b7166ec, 0x21c7, 0x44ae, { 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69 } };
|
||||
static const GUID FBNEO_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
|
||||
static const GUID FBNEO_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
|
||||
// ID3D11ShaderReflection changed IID between d3dcompiler versions
|
||||
static const GUID FBNEO_IID_ID3D11ShaderReflection_47 = { 0x8d536ca1, 0x0cca, 0x4956, { 0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84 } };
|
||||
@@ -61,6 +62,9 @@ static const GUID FBNEO_IID_ID3D11ShaderReflection_43 = { 0x0a233719, 0x3960, 0x
|
||||
// DXGI values that older headers may not have
|
||||
#define FBNEO_DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ((DXGI_SWAP_EFFECT)3)
|
||||
#define FBNEO_DXGI_SWAP_EFFECT_FLIP_DISCARD ((DXGI_SWAP_EFFECT)4)
|
||||
#define FBNEO_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING 0x800
|
||||
#define FBNEO_DXGI_PRESENT_ALLOW_TEARING 0x200
|
||||
#define FBNEO_DXGI_FEATURE_PRESENT_ALLOW_TEARING 0
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Runtime-loaded DLLs
|
||||
@@ -165,6 +169,7 @@ static ID3D11RenderTargetView* pRenderTarget = NULL;
|
||||
static D3D_FEATURE_LEVEL nFeatureLevel = D3D_FEATURE_LEVEL_9_1;
|
||||
static bool bWarpDevice = false;
|
||||
static DXGI_SWAP_EFFECT nSwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
static UINT nSwapChainFlags = 0;
|
||||
static UINT nSwapChainWidth = 0, nSwapChainHeight = 0;
|
||||
static UINT nDeviceGeneration = 0; // bumped every time a device is created (OSD textures follow it)
|
||||
static bool bDeviceLost = false;
|
||||
@@ -2579,7 +2584,7 @@ static int d3d11ResizeSwapChain(UINT nWidth, UINT nHeight)
|
||||
pContext->OMSetRenderTargets(0, NULL, NULL);
|
||||
D3D11_RELEASE(pRenderTarget);
|
||||
|
||||
if (FAILED(pSwapChain->ResizeBuffers(0, nWidth, nHeight, DXGI_FORMAT_UNKNOWN, 0))) {
|
||||
if (FAILED(pSwapChain->ResizeBuffers(0, nWidth, nHeight, DXGI_FORMAT_UNKNOWN, nSwapChainFlags))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2589,6 +2594,27 @@ static int d3d11ResizeSwapChain(UINT nWidth, UINT nHeight)
|
||||
return d3d11CreateRenderTarget();
|
||||
}
|
||||
|
||||
// IDXGIFactory5::CheckFeatureSupport() is called through the vtable, so no DXGI 1.5 headers are needed
|
||||
static bool d3d11TearingSupported(IDXGIFactory* pFactory)
|
||||
{
|
||||
typedef HRESULT (STDMETHODCALLTYPE* pfnCheckFeatureSupport)(void*, UINT, void*, UINT);
|
||||
void* pFactory5 = NULL;
|
||||
BOOL bAllowTearing = FALSE;
|
||||
|
||||
if (FAILED(pFactory->QueryInterface(FBNEO_IID_IDXGIFactory5, &pFactory5))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pfnCheckFeatureSupport pCheckFeatureSupport = (pfnCheckFeatureSupport)((*(void***)pFactory5)[28]);
|
||||
if (FAILED(pCheckFeatureSupport(pFactory5, FBNEO_DXGI_FEATURE_PRESENT_ALLOW_TEARING, &bAllowTearing, sizeof(bAllowTearing)))) {
|
||||
bAllowTearing = FALSE;
|
||||
}
|
||||
|
||||
((IUnknown*)pFactory5)->Release();
|
||||
|
||||
return bAllowTearing != FALSE;
|
||||
}
|
||||
|
||||
static int d3d11CreateSwapChain()
|
||||
{
|
||||
IDXGIDevice* pDXGIDevice = NULL;
|
||||
@@ -2613,6 +2639,9 @@ static int d3d11CreateSwapChain()
|
||||
nSwapChainWidth = (rect.right > 0) ? rect.right : 1;
|
||||
nSwapChainHeight = (rect.bottom > 0) ? rect.bottom : 1;
|
||||
|
||||
bool bTearing = bVidVRR && d3d11TearingSupported(pFactory);
|
||||
nSwapChainFlags = 0;
|
||||
|
||||
// Prefer the flip model (Win10: FLIP_DISCARD, Win8: FLIP_SEQUENTIAL), fall back to the blt model (Win7)
|
||||
static const DXGI_SWAP_EFFECT SwapEffects[] = { FBNEO_DXGI_SWAP_EFFECT_FLIP_DISCARD, FBNEO_DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_SWAP_EFFECT_DISCARD };
|
||||
|
||||
@@ -2630,9 +2659,11 @@ static int d3d11CreateSwapChain()
|
||||
scd.OutputWindow = hD3D11View;
|
||||
scd.Windowed = TRUE;
|
||||
scd.SwapEffect = SwapEffects[i];
|
||||
scd.Flags = (bFlip && bTearing) ? FBNEO_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
|
||||
if (SUCCEEDED(pFactory->CreateSwapChain(pDevice, &scd, &pSwapChain))) {
|
||||
nSwapEffect = SwapEffects[i];
|
||||
nSwapChainFlags = scd.Flags;
|
||||
} else {
|
||||
pSwapChain = NULL;
|
||||
}
|
||||
@@ -3447,7 +3478,10 @@ static int d3d11Paint(int bValidate)
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT hr = pSwapChain->Present(bVidVSync ? 1 : 0, 0);
|
||||
UINT nSyncInterval = (bVidVSync && !EmulatorAppIsFast()) ? 1 : 0;
|
||||
// VRR: present immediately, the display follows our own frame pacing
|
||||
UINT nPresentFlags = (nSyncInterval == 0 && (nSwapChainFlags & FBNEO_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)) ? FBNEO_DXGI_PRESENT_ALLOW_TEARING : 0;
|
||||
HRESULT hr = pSwapChain->Present(nSyncInterval, nPresentFlags);
|
||||
|
||||
bInPaint = false;
|
||||
|
||||
@@ -3489,6 +3523,12 @@ static int d3d11GetSettings(InterfaceInfo* pInfo)
|
||||
IntInfoAddStringModule(pInfo, _T("Using a flip-model swap chain"));
|
||||
}
|
||||
|
||||
if (nSwapChainFlags & FBNEO_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) {
|
||||
IntInfoAddStringModule(pInfo, _T("Variable refresh rate (tearing) presents enabled"));
|
||||
} else if (bVidVRR) {
|
||||
IntInfoAddStringModule(pInfo, _T("Variable refresh rate requested, but not supported"));
|
||||
}
|
||||
|
||||
if (nVidFullscreen) {
|
||||
if (bChangedDisplayMode) {
|
||||
_sntprintf(szString, MAX_PATH, _T("Fullscreen (%i x %i, display mode changed)"), nVidScrnWidth, nVidScrnHeight);
|
||||
|
||||
Reference in new issue
Block a user