Initial commit
This commit is contained in:
commit
e4cc7bbf30
|
@ -0,0 +1,71 @@
|
|||
# Main Makefile for FB Alpha, execute an appropriate system-specific makefile
|
||||
|
||||
export
|
||||
|
||||
#
|
||||
# Declare variables
|
||||
#
|
||||
|
||||
# Make a special build, pass the quoted text as comment (use FORCE_UPDATE declaration below to force recompilation of resources)
|
||||
# SPECIALBUILD = "This text will appear in the property sheet of the .exe file"
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Flags. Uncomment any of these declarations to enable their function.
|
||||
#
|
||||
|
||||
# Inluclude Unicode support
|
||||
UNICODE = 1
|
||||
|
||||
# Build A68K ASM 68000 core
|
||||
BUILD_A68K = 1
|
||||
|
||||
# Include x86 Assembly routines
|
||||
BUILD_X86_ASM = 1
|
||||
|
||||
# Build for x64 targets (MinGW64 and MSVC only, this will undefine BUILD_A68K and BUILD_X86_ASM)
|
||||
#BUILD_X64_EXE = 1
|
||||
|
||||
# Include symbols and other debug information in the executable
|
||||
#SYMBOL = 1
|
||||
|
||||
# Include features for debugging drivers
|
||||
#DEBUG = 1
|
||||
|
||||
# Include rom set verifying features (comment this for release builds)
|
||||
#ROM_VERIFY = 1
|
||||
|
||||
# Force recompilation of files that need it (i.e. use __TIME__, __DATE__, SPECIALBUILD).
|
||||
FORCE_UPDATE = 1
|
||||
|
||||
# Use the __fastcall calling convention when interfacing with A68K/Musashi/Doze
|
||||
FASTCALL = 1
|
||||
|
||||
# Compress executable with upx (the DEBUG option ignores this)
|
||||
# COMPRESS = 1
|
||||
|
||||
# Perl is available
|
||||
PERL = 1
|
||||
|
||||
|
||||
#
|
||||
# execute an appropriate system-specific makefile
|
||||
#
|
||||
|
||||
mingw345: FORCE
|
||||
@$(MAKE) -s -f makefile.mingw GCC345=1
|
||||
|
||||
mingw452: FORCE
|
||||
@$(MAKE) -s -f makefile.mingw GCC452=1
|
||||
|
||||
mingw461: FORCE
|
||||
@$(MAKE) -s -f makefile.mingw GCC461=1
|
||||
|
||||
sdl: FORCE
|
||||
@$(MAKE) -s -f makefile.sdl
|
||||
|
||||
vc: FORCE
|
||||
@$(MAKE) -s -f makefile.vc
|
||||
|
||||
FORCE:
|
|
@ -0,0 +1,695 @@
|
|||
# Makefile for FBA, for use with GNU make & GCC (MinGW)
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
# Flags. Uncomment any of these declarations to enable their function.
|
||||
#
|
||||
|
||||
# Check for changes in header files
|
||||
DEPEND = 1
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Declare variables
|
||||
#
|
||||
|
||||
# Specify the name of the executable file, without ".exe"
|
||||
NAME = fba
|
||||
|
||||
ifdef BUILD_X64_EXE
|
||||
ifdef BUILD_A68K
|
||||
undefine BUILD_A68K
|
||||
endif
|
||||
ifdef BUILD_X86_ASM
|
||||
undefine BUILD_X86_ASM
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef CPUTYPE
|
||||
CPUTYPE = i686
|
||||
endif
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
MMX = 1
|
||||
else
|
||||
MMX = 0
|
||||
endif
|
||||
|
||||
ifndef BUILD_X86_ASM
|
||||
NAME := $(NAME)n
|
||||
endif
|
||||
ifdef BUILD_X64_EXE
|
||||
NAME = fba64
|
||||
endif
|
||||
ifdef DEBUG
|
||||
NAME := $(NAME)d
|
||||
endif
|
||||
ifdef SYMBOL
|
||||
NAME := $(NAME)s
|
||||
endif
|
||||
ifndef UNICODE
|
||||
NAME := $(NAME)a
|
||||
endif
|
||||
|
||||
ifeq ($(CPUTYPE),i686)
|
||||
ppro = ppro
|
||||
else
|
||||
NAME := $(NAME)$(CPUTYPE)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Specify paths/files
|
||||
#
|
||||
|
||||
ifdef GCC345
|
||||
objdir = obj/GNU345_WIN32/$(NAME)/
|
||||
endif
|
||||
ifdef GCC452
|
||||
objdir = obj/GNU452_WIN32/$(NAME)/
|
||||
endif
|
||||
ifdef GCC461
|
||||
objdir = obj/GNU461_WIN32/$(NAME)/
|
||||
endif
|
||||
|
||||
srcdir = src/
|
||||
|
||||
include makefile.rules
|
||||
|
||||
ifdef GCC345
|
||||
incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)depend/generated -I$(srcdir)depend/mingw/include -I- -I$(srcdir)depend/mingw/include/directx9 -I$(srcdir)depend/mingw/include/xaudio2
|
||||
endif
|
||||
ifdef GCC452
|
||||
incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)depend/generated -I$(srcdir)depend/mingw/include -I$(srcdir)depend/mingw/include/directx9 -I$(srcdir)depend/mingw/include/xaudio2
|
||||
endif
|
||||
ifdef GCC461
|
||||
incdir = $(foreach dir,$(alldir),-I$(srcdir)$(dir)) -I$(objdir)depend/generated -I$(srcdir)depend/mingw/include -I$(srcdir)depend/mingw/include/directx9 -I$(srcdir)depend/mingw/include/xaudio2
|
||||
endif
|
||||
|
||||
ifdef UNICODE
|
||||
# lib = -lunicows
|
||||
endif
|
||||
|
||||
# lib += `sdl-config --libs`
|
||||
lib += -luser32 -lgdi32 -lcomdlg32 -lcomctl32 -lshell32 -lwinmm -lshlwapi \
|
||||
-ladvapi32 -lsetupapi -lole32 -luuid
|
||||
|
||||
|
||||
depobj += resource.o \
|
||||
|
||||
autdep = $(depobj:.o=.d)
|
||||
|
||||
ifdef BUILD_A68K
|
||||
a68k.o = $(objdir)cpu/a68k/a68k.o
|
||||
endif
|
||||
|
||||
app_gnuc.rc = $(srcdir)depend/generated/app_gnuc.rc
|
||||
license.rtf = $(srcdir)depend/generated/license.rtf
|
||||
driverlist.h = $(srcdir)depend/generated/driverlist.h
|
||||
ctv.h = $(srcdir)depend/generated/ctv.h
|
||||
toa_gp9001_func.h = $(srcdir)depend/generated/toa_gp9001_func.h
|
||||
neo_sprite_func.h = $(srcdir)depend/generated/neo_sprite_func.h
|
||||
cave_tile_func.h = $(srcdir)depend/generated/cave_tile_func.h
|
||||
cave_sprite_func.h = $(srcdir)depend/generated/cave_sprite_func.h
|
||||
psikyo_tile_func.h = $(srcdir)depend/generated/psikyo_tile_func.h
|
||||
build_details.h = $(srcdir)depend/generated/build_details.h
|
||||
|
||||
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.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)))))))
|
||||
|
||||
#
|
||||
#
|
||||
# Specify compiler/linker/assembler
|
||||
#
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
LD = $(CXX)
|
||||
AS = nasm
|
||||
|
||||
LDFLAGS = -static
|
||||
|
||||
ifdef GCC345
|
||||
CFLAGS = -pipe \
|
||||
-std=gnu99 -march=$(CPUTYPE) -O1 \
|
||||
-mno-cygwin -mwindows \
|
||||
-fforce-mem -fforce-addr -finline-limit=1200 -fthread-jumps \
|
||||
-freduce-all-givs -fmove-all-movables -fexpensive-optimizations \
|
||||
-Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \
|
||||
$(DEF) $(incdir) # `sdl-config --cflags`
|
||||
|
||||
CXXFLAGS = -pipe \
|
||||
-march=$(CPUTYPE) -O3 \
|
||||
-mno-cygwin -mwindows \
|
||||
-fforce-mem -fforce-addr -finline-limit=1200 -fthread-jumps \
|
||||
-freduce-all-givs -fmove-all-movables -fexpensive-optimizations \
|
||||
-fcheck-new \
|
||||
-Wall -W -pedantic -Wno-long-long \
|
||||
-Wunknown-pragmas -Wundef -Wconversion -Wno-missing-braces \
|
||||
-Wuninitialized -Wpointer-arith -Winline -Wno-multichar \
|
||||
$(DEF) $(incdir) # `sdl-config --cflags`
|
||||
endif
|
||||
ifdef GCC452
|
||||
CFLAGS = -pipe \
|
||||
-std=gnu99 -march=$(CPUTYPE) -O1 \
|
||||
-mno-cygwin -mwindows \
|
||||
-fforce-addr -finline-limit=1200 -fthread-jumps \
|
||||
-fexpensive-optimizations \
|
||||
-Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \
|
||||
-Wno-sequence-point \
|
||||
$(DEF) $(incdir) # `sdl-config --cflags`
|
||||
|
||||
CXXFLAGS = -pipe \
|
||||
-march=$(CPUTYPE) -O1 \
|
||||
-mno-cygwin -mwindows \
|
||||
-fforce-addr -finline-limit=1200 -fthread-jumps \
|
||||
-fexpensive-optimizations -fcheck-new \
|
||||
-Wall -W -pedantic -Wshadow -Wno-long-long -Wno-write-strings \
|
||||
-Wunknown-pragmas -Wundef -Wno-conversion -Wno-missing-braces -Wno-multichar \
|
||||
-Wuninitialized -Wpointer-arith -Wno-inline -Wno-address -Wno-unused-value \
|
||||
-Wno-sequence-point \
|
||||
$(DEF) $(incdir) # `sdl-config --cflags`
|
||||
endif
|
||||
ifdef GCC461
|
||||
CFLAGS = -pipe \
|
||||
-std=gnu99 -O1 \
|
||||
-mwindows \
|
||||
-fforce-addr -finline-limit=1200 -fthread-jumps \
|
||||
-fexpensive-optimizations \
|
||||
-Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \
|
||||
-Wno-sequence-point \
|
||||
$(DEF) $(incdir) # `sdl-config --cflags`
|
||||
|
||||
CXXFLAGS = -pipe \
|
||||
-O1 \
|
||||
-mwindows \
|
||||
-fforce-addr -finline-limit=1200 -fthread-jumps \
|
||||
-fexpensive-optimizations -fcheck-new \
|
||||
-Wall -W -pedantic -Wshadow -Wno-long-long -Wno-write-strings \
|
||||
-Wunknown-pragmas -Wundef -Wno-conversion -Wno-missing-braces -Wno-multichar \
|
||||
-Wuninitialized -Wpointer-arith -Wno-inline -Wno-address -Wno-unused-value \
|
||||
-Wno-unused-but-set-variable -Wno-sequence-point \
|
||||
$(DEF) $(incdir) # `sdl-config --cflags`
|
||||
|
||||
ifdef BUILD_X64_EXE
|
||||
CFLAGS += -m64
|
||||
CXXFLAGS += -m64
|
||||
LDFLAGS += -m64
|
||||
else
|
||||
CFLAGS += -m32
|
||||
CXXFLAGS += -m32
|
||||
LDFLAGS += -m32
|
||||
endif
|
||||
endif
|
||||
|
||||
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
|
||||
|
||||
DEF := -DBUILD_WIN32 -DUSE_SPEEDHACKS -DFILENAME=$(NAME) -DMMX=$(MMX)
|
||||
|
||||
ifdef UNICODE
|
||||
DEF := $(DEF) -D_UNICODE
|
||||
endif
|
||||
|
||||
ifdef SPECIALBUILD
|
||||
DEF := $(DEF) -DSPECIALBUILD=$(SPECIALBUILD)
|
||||
endif
|
||||
|
||||
ifdef FASTCALL
|
||||
DEF := $(DEF) -DFASTCALL
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
ifdef GCC345
|
||||
CFLAGS += -mconsole
|
||||
endif
|
||||
ifdef GCC452
|
||||
CFLAGS += -mconsole
|
||||
endif
|
||||
DEF := $(DEF) -DFBA_DEBUG
|
||||
endif
|
||||
|
||||
ifdef ROM_VERIFY
|
||||
DEF := $(DEF) -DROM_VERIFY
|
||||
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 SYMBOL
|
||||
|
||||
CFLAGS += -ggdb3
|
||||
ASFLAGS += -g
|
||||
DEF := $(DEF) -D_DEBUG
|
||||
|
||||
ifdef PROFILE
|
||||
CFLAGS += -pg
|
||||
CXXFLAGS += -pg
|
||||
else
|
||||
CFLAGS += -fomit-frame-pointer
|
||||
CXXFLAGS += -fomit-frame-pointer
|
||||
endif
|
||||
|
||||
else
|
||||
LDFLAGS += -s
|
||||
endif
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
CFLAGS += -mmmx
|
||||
CXXFLAGS += -mmmx
|
||||
endif
|
||||
|
||||
# For zlib
|
||||
DEF := $(DEF) -DNO_VIZ -D_LARGEFILE64_SOURCE=0 -D_FILE_OFFSET_BITS=32
|
||||
|
||||
#
|
||||
#
|
||||
# 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 $(autdep) $(autobj)
|
||||
ifdef GCC345
|
||||
@$(MAKE) -f makefile.mingw -s GCC345=1
|
||||
endif
|
||||
ifdef GCC452
|
||||
@$(MAKE) -f makefile.mingw -s GCC452=1
|
||||
endif
|
||||
ifdef GCC461
|
||||
@$(MAKE) -f makefile.mingw -s GCC461=1
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
all: init $(autobj)
|
||||
ifdef GCC345
|
||||
@$(MAKE) -f makefile.mingw -s GCC345=1
|
||||
endif
|
||||
ifdef GCC452
|
||||
@$(MAKE) -f makefile.mingw -s GCC452=1
|
||||
endif
|
||||
ifdef GCC461
|
||||
@$(MAKE) -f makefile.mingw -s GCC461=1
|
||||
endif
|
||||
|
||||
endif
|
||||
else
|
||||
|
||||
all: $(NAME).exe
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
#
|
||||
# Rule for linking the executable
|
||||
#
|
||||
#
|
||||
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
|
||||
$(NAME).exe: $(allobj)
|
||||
@echo
|
||||
@echo Linking executable... $(NAME).exe
|
||||
@$(LD) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(lib)
|
||||
|
||||
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): $(drvobj) $(srcdir)depend/scripts/gamelist.pl
|
||||
ifdef PERL
|
||||
@$(srcdir)depend/scripts/gamelist.pl -o $@ -l gamelist.txt \
|
||||
$(filter %.cpp,$(foreach file,$(drvobj:.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
|
||||
|
||||
|
||||
#
|
||||
# Fix the .rc file
|
||||
#
|
||||
|
||||
resource.o resource.d: $(app_gnuc.rc) string.rc version.rc version.h $(build_details.h)
|
||||
|
||||
$(license.rtf): $(srcdir)license.txt $(srcdir)depend/scripts/license2rtf.pl
|
||||
|
||||
ifdef PERL
|
||||
@$(srcdir)depend/scripts/license2rtf.pl $< -o $(srcdir)depend/generated/$(@F:.rc=.rtf)
|
||||
else
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
@echo
|
||||
@echo Warning: Perl is not available on this system.
|
||||
@echo $@ cannot be updated or created!
|
||||
@echo
|
||||
endif
|
||||
endif
|
||||
|
||||
$(app_gnuc.rc): app.rc $(license.rc) $(license.rtf) $(srcdir)depend/scripts/fixrc.pl $(srcdir)burner/win32/resource/fba.ico $(srcdir)burner/win32/resource/about.bmp $(srcdir)burner/win32/resource/splash.bmp $(srcdir)burner/win32/resource/misc.bmp
|
||||
|
||||
ifdef PERL
|
||||
@$(srcdir)depend/scripts/fixrc.pl $< -o $@
|
||||
else
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
@echo
|
||||
@echo Warning: Perl is not available on this system.
|
||||
@echo $@ cannot be updated or created!
|
||||
@echo
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Generate some info on the build details
|
||||
#
|
||||
|
||||
about.o about.d: $(build_details.h)
|
||||
|
||||
$(build_details.h): $(srcdir)depend/scripts/build_details.cpp
|
||||
@$(CXX) -mconsole $(CXXFLAGS) $(LDFLAGS) $< -o $(objdir)depend/generated/build_details.exe
|
||||
@$(objdir)depend/generated/build_details.exe >$@
|
||||
|
||||
#
|
||||
# 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)depend/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.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kops.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo Compiling Musashi MC680x0 core \(m68kops.c\)...
|
||||
@$(CC) $(CFLAGS) -c $(objdir)depend/generated/m68kops.c -o $(objdir)cpu/m68k/m68kops.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kopac.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kopac.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo Compiling Musashi MC680x0 core \(m68kopac.c\)...
|
||||
@$(CC) $(CFLAGS) -c $(objdir)depend/generated/m68kopac.c -o $(objdir)cpu/m68k/m68kopac.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kopdm.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kopdm.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo Compiling Musashi MC680x0 core \(m68kopdm.c\)...
|
||||
@$(CC) $(CFLAGS) -c $(objdir)depend/generated/m68kopdm.c -o $(objdir)cpu/m68k/m68kopdm.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kopnz.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kopnz.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo Compiling Musashi MC680x0 core \(m68kopnz.c\)...
|
||||
@$(CC) $(CFLAGS) -c $(objdir)depend/generated/m68kopnz.c -o $(objdir)cpu/m68k/m68kopnz.o
|
||||
|
||||
$(objdir)depend/generated/m68kops.h: $(objdir)cpu/m68k/m68kmake.exe $(srcdir)cpu/m68k/m68k_in.c
|
||||
$(objdir)/cpu/m68k/m68kmake $(objdir)depend/generated/ $(srcdir)cpu/m68k/m68k_in.c
|
||||
|
||||
$(objdir)cpu/m68k/m68kmake.exe: $(srcdir)cpu/m68k/m68kmake.c
|
||||
@echo Compiling Musashi MC680x0 core \(m68kmake.c\)...
|
||||
@$(CC) $(CFLAGS) $(srcdir)cpu/m68k/m68kmake.c -o $(objdir)cpu/m68k/m68kmake.exe
|
||||
|
||||
|
||||
#
|
||||
# Extra rules for generated header file cvt.h, needed by ctv.cpp
|
||||
#
|
||||
|
||||
ctv.d ctv.o: $(ctv.h)
|
||||
|
||||
$(ctv.h): ctv_make.cpp
|
||||
@echo Generating $(srcdir)depend/generated/$(@F)...
|
||||
@$(CC) -mconsole $(CXXFLAGS) $(LDFLAGS) $< \
|
||||
-o $(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe)
|
||||
@$(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)depend/scripts/toa_gp9001_func.pl
|
||||
@$(srcdir)depend/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)depend/scripts/neo_sprite_func.pl
|
||||
@$(srcdir)depend/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)depend/scripts/cave_tile_func.pl
|
||||
@$(srcdir)depend/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)depend/scripts/cave_sprite_func.pl
|
||||
@$(srcdir)depend/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)depend/scripts/psikyo_tile_func.pl
|
||||
$(srcdir)depend/scripts/psikyo_tile_func.pl -o $(psikyo_tile_func.h)
|
||||
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
ifdef DEPEND
|
||||
|
||||
include $(alldep)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Generic rule for resource files
|
||||
#
|
||||
|
||||
%.o: %.rc
|
||||
@echo Compiling resource file $(<F)...
|
||||
ifdef GCC345
|
||||
@windres $(DEF) $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F) $(foreach dir,$(alldir),--include-dir $(srcdir)$(dir))
|
||||
endif
|
||||
ifdef GCC452
|
||||
@windres $(DEF) $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F) $(foreach dir,$(alldir),--include-dir $(srcdir)$(dir))
|
||||
endif
|
||||
ifdef GCC461
|
||||
ifdef BUILD_X64_EXE
|
||||
@windres -F pe-x86-64 $(DEF) $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F) $(foreach dir,$(alldir),--include-dir $(srcdir)$(dir))
|
||||
else
|
||||
@windres -F pe-i386 $(DEF) $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F) $(foreach dir,$(alldir),--include-dir $(srcdir)$(dir))
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Generic rules for C/C++ files
|
||||
#
|
||||
|
||||
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
|
||||
@echo Assembling $<...
|
||||
@$(AS) $(ASFLAGS) $< -o $(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
else
|
||||
|
||||
%.o: %.c
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.o: %.asm
|
||||
@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)depend/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)/depend/generated/*
|
||||
-@for dir in $(alldir); do touch -c -r $(NAME).exe $(objdir)$$dir/*; done
|
||||
|
||||
clean:
|
||||
@echo Removing all files from $(objdir)...
|
||||
-@rm -f -r $(objdir)
|
||||
-@rm -f -r $(ctv.h)
|
||||
|
||||
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:
|
|
@ -0,0 +1,148 @@
|
|||
alldir = burn burn/devices burn/sound burn/drivers burn/drivers/capcom burn/drivers/cave burn/drivers/cps3 \
|
||||
burn/drivers/galaxian burn/drivers/irem burn/drivers/konami burn/drivers/megadrive burn/drivers/misc_post90s \
|
||||
burn/drivers/misc_pre90s burn/drivers/neogeo burn/drivers/pgm burn/drivers/psikyo burn/drivers/sega \
|
||||
burn/drivers/taito burn/drivers/toaplan burner burner/win32 interface interface/scalers interface/win32 cpu \
|
||||
cpu/a68k cpu/arm cpu/arm7 cpu/h6280 cpu/hd6309 cpu/i8039 cpu/konami cpu/m68k cpu/m6502 cpu/m6800 cpu/m6805 \
|
||||
cpu/m6809 cpu/nec cpu/s2650 cpu/sh2 cpu/z80 depend/kaillera/client depend/libs/libpng depend/libs/zlib \
|
||||
depend/generated
|
||||
|
||||
drvobj = d_dodonpachi.o d_donpachi.o d_esprade.o d_feversos.o d_gaia.o d_guwange.o d_hotdogst.o d_korokoro.o d_mazinger.o \
|
||||
d_metmqstr.o d_pwrinst2.o d_sailormn.o d_tjumpman.o d_uopoko.o \
|
||||
\
|
||||
d_cps1.o \
|
||||
\
|
||||
d_cps2.o \
|
||||
\
|
||||
d_cps3.o \
|
||||
\
|
||||
d_galaxian.o \
|
||||
\
|
||||
d_m62.o d_m63.o d_m72.o d_m90.o d_m92.o \
|
||||
\
|
||||
d_88games.o d_ajax.o d_aliens.o d_blockhl.o d_bottom9.o d_contra.o d_crimfght.o d_gbusters.o d_gradius3.o d_hcastle.o \
|
||||
d_hexion.o d_mainevt.o d_parodius.o d_rollerg.o d_simpsons.o d_spy.o d_surpratk.o d_thunderx.o d_tmnt.o d_twin16.o \
|
||||
d_ultraman.o d_vendetta.o d_xmen.o \
|
||||
\
|
||||
d_neogeo.o \
|
||||
\
|
||||
d_pacman.o d_pac2650.o \
|
||||
\
|
||||
d_pgm.o \
|
||||
\
|
||||
d_psikyo.o d_psikyosh.o \
|
||||
\
|
||||
d_hangon.o d_outrun.o d_sys1.o d_sys16a.o d_sys16b.o d_sys18.o d_xbrd.o d_ybrd.o \
|
||||
\
|
||||
d_taitob.o d_taitof2.o d_taitox.o d_taitoz.o d_taitomisc.o d_asuka.o d_bublbobl.o d_darius2.o d_othunder.o \
|
||||
d_slapshot.o d_superchs.o \
|
||||
\
|
||||
d_batrider.o d_batsugun.o d_battleg.o d_bbakraid.o d_demonwld.o d_dogyuun.o d_fixeight.o d_ghox.o d_hellfire.o \
|
||||
d_kbash.o d_kbash2.o d_mahoudai.o d_outzone.o d_pipibibs.o d_rallybik.o d_samesame.o d_shippumd.o d_snowbro2.o \
|
||||
d_tekipaki.o d_truxton.o d_truxton2.o d_vfive.o d_vimana.o d_zerowing.o \
|
||||
\
|
||||
d_4enraya.o d_1942.o d_1943.o d_ambush.o d_angelkds.o d_arabian.o d_arkanoid.o d_armedf.o d_aztarac.o d_bankp.o \
|
||||
d_baraduke.o d_bionicc.o d_blktiger.o d_blockout.o d_blueprnt.o d_bombjack.o d_chaknpop.o d_commando.o d_dec0.o \
|
||||
d_dec8.o d_ddragon.o d_dotrikun.o d_dynduke.o d_epos.o d_exedexes.o d_flstory.o d_funkybee.o d_galaga.o d_gauntlet.o \
|
||||
d_gberet.o d_ginganin.o d_gng.o d_gunsmoke.o d_gyruss.o d_higemaru.o d_ikki.o d_jack.o d_kangaroo.o d_karnov.o \
|
||||
d_kyugo.o d_ladybug.o d_lkage.o d_lwings.o d_madgear.o d_markham.o d_marineb.o d_meijinsn.o d_minivdr.o d_mitchell.o \
|
||||
d_mole.o d_mrdo.o d_mrflea.o d_mystston.o d_pkunwar.o d_pooyan.o d_prehisle.o d_quizo.o d_rallyx.o d_renegade.o \
|
||||
d_retofinv.o d_route16.o d_scotrsht.o d_scregg.o d_sf.o d_skyfox.o d_skykid.o d_snk68.o d_solomon.o d_sonson.o \
|
||||
d_srumbler.o d_tecmo.o d_tigerheli.o d_tigeroad.o d_toki.o d_tnzs.o d_vaportra.o d_vigilant.o d_vulgus.o d_wallc.o \
|
||||
d_wc90.o d_wc90b.o d_wwfsstar.o \
|
||||
\
|
||||
d_1945kiii.o d_aerofgt.o d_airbustr.o d_aquarium.o d_ashnojoe.o d_backfire.o d_bloodbro.o d_boogwing.o d_cbuster.o \
|
||||
d_cninja.o d_crospang.o d_crshrace.o d_darkseal.o d_dassault.o d_dcon.o d_deniam.o d_ddragon3.o d_dietgogo.o \
|
||||
d_diverboy.o d_drtomy.o d_egghunt.o d_esd16.o d_f1gp.o d_fstarfrc.o d_funkyjet.o d_funybubl.o d_fuukifg3.o d_gaelco.o \
|
||||
d_gaiden.o d_galpanic.o d_gotcha.o d_gumbo.o d_hyperpac.o d_kaneko16.o d_lordgun.o d_mcatadv.o d_midas.o d_mogura.o \
|
||||
d_mugsmash.o d_news.o d_nmg5.o d_nmk16.o d_ohmygod.o d_pass.o d_pirates.o d_pktgaldx.o d_powerins.o d_pushman.o \
|
||||
d_raiden.o d_rohga.o d_seta.o d_seta2.o d_shadfrce.o d_silkroad.o d_simpl156.o d_speedspn.o d_suna16.o d_supbtime.o \
|
||||
d_taotaido.o d_tecmosys.o d_tumbleb.o d_tumblep.o d_unico.o d_vmetal.o d_welltris.o d_wwfwfest.o d_xorworld.o \
|
||||
d_yunsun16.o d_zerozone.o \
|
||||
\
|
||||
d_parent.o \
|
||||
\
|
||||
d_megadrive.o
|
||||
|
||||
depobj := about.o bzip.o cona.o debugger.o drv.o dwmapi_core.o dynhuff.o fba_kaillera.o image_win32.o inpc.o inpcheat.o inpd.o \
|
||||
inpdipsw.o inps.o ips_manager.o localise.o main.o mdi.o media.o memcard.o menu.o misc_win32.o neocdlist.o neocdsel.o \
|
||||
numdial.o numpluscommas.o paletteviewer.o popup_win32.o progress.o replay.o res.o roms.o run.o scrn.o sel.o sfactd.o \
|
||||
splash.o stated.o support_paths.o systeminfo.o wave.o \
|
||||
\
|
||||
conc.o cong.o dat.o gamc.o gami.o image.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 \
|
||||
\
|
||||
png.o pngerror.o pngget.o pngmem.o pngpread.o pngread.o pngrio.o pngrtran.o pngrutil.o pngset.o pngtrans.o pngwio.o \
|
||||
pngwrite.o pngwtran.o pngwutil.o \
|
||||
\
|
||||
net.o \
|
||||
\
|
||||
$(drvobj) \
|
||||
\
|
||||
burn.o burn_gun.o burn_led.o burn_memory.o burn_sound.o burn_sound_c.o cheat.o hiscore.o load.o tiles_generic.o \
|
||||
timer.o vector.o \
|
||||
\
|
||||
8255ppi.o eeprom.o pandora.o seibusnd.o timekpr.o \
|
||||
\
|
||||
ay8910.o burn_y8950.o burn_ym2151.o burn_ym2203.o burn_ym2413.o burn_ym2608.o burn_ym2610.o burn_ym2612.o \
|
||||
burn_ym3526.o burn_ym3812.o burn_ymf278b.o dac.o es5506.o es8712.o fm.o fmopl.o ics2115.o iremga20.o k007232.o \
|
||||
k051649.o k053260.o k054539.o msm5205.o msm6295.o namco_snd.o rf5c68.o saa1099.o samples.o segapcm.o sn76496.o \
|
||||
upd7759.o x1010.o ym2151.o ym2413.o ymdeltat.o ymf278b.o ymz280b.o \
|
||||
\
|
||||
arm7_intf.o arm_intf.o h6280_intf.o hd6309_intf.o konami_intf.o m6502_intf.o m6800_intf.o m6805_intf.o m6809_intf.o \
|
||||
s2650_intf.o sek.o vez.o zet.o \
|
||||
\
|
||||
arm.o arm7.o h6280.o hd6309.o i8039.o konami.o m6502.o m6800.o m6805.o m6809.o nec.o s2650.o sh2.o v25.o z80.o \
|
||||
z80daisy.o \
|
||||
\
|
||||
aud_dsp.o aud_interface.o cd_interface.o inp_interface.o interface.o lowpass2.o prf_interface.o vid_interface.o \
|
||||
vid_softfx.o vid_support.o \
|
||||
\
|
||||
2xpm.o 2xsai.o epx.o hq2xs.o hq2xs_16.o \
|
||||
\
|
||||
aud_dsound3.o aud_xaudio2.o cd_isowav.o cdsound.o ddraw_core.o dinput_core.o directx9_core.o dsound_core.o \
|
||||
inp_dinput.o prf_performance_counter.o vid_d3d.o vid_ddraw.o vid_ddrawfx.o vid_directx9.o vid_directx_support.o \
|
||||
\
|
||||
cave.o cave_palette.o cave_sprite.o cave_tile.o \
|
||||
\
|
||||
cps2_crpt.o cps.o cps_config.o cps_draw.o cps_mem.o cps_obj.o cps_pal.o cps_run.o cps_rw.o cps_scr.o cpsr.o cpsrd.o \
|
||||
cpst.o ctv.o kabuki.o ps.o ps_m.o ps_z.o qs.o qs_c.o qs_z.o \
|
||||
\
|
||||
cps3run.o cps3snd.o \
|
||||
\
|
||||
gal_gfx.o gal_run.o gal_sound.o gal_stars.o \
|
||||
\
|
||||
irem_cpu.o \
|
||||
\
|
||||
k051316.o k051733.o k051960.o k052109.o k053245.o k053247.o k053251.o k053936.o k054000.o konamiic.o \
|
||||
\
|
||||
neo_decrypt.o neo_palette.o neo_run.o neo_sprite.o neo_text.o neo_upd4990a.o neogeo.o \
|
||||
\
|
||||
pgm_crypt.o pgm_draw.o pgm_prot.o pgm_run.o \
|
||||
\
|
||||
psikyo_palette.o psikyo_sprite.o psikyo_tile.o psikyosh_render.o \
|
||||
\
|
||||
fd1089.o fd1094.o genesis_vid.o mc8123.o sys16_fd1094.o sys16_gfx.o sys16_run.o \
|
||||
\
|
||||
cchip.o pc080sn.o pc090oj.o taito.o taito_ic.o taito_m68705.o tc0100scn.o tc0110pcr.o tc0140syt.o tc0150rod.o \
|
||||
tc0180vcu.o tc0220ioc.o tc0280grd.o tc0360pri.o tc0480scp.o tc0510nio.o tc0640fio.o \
|
||||
\
|
||||
toa_bcu2.o toa_extratext.o toa_gp9001.o toa_palette.o toaplan1.o toaplan.o \
|
||||
\
|
||||
tnzs_prot.o \
|
||||
\
|
||||
deco16ic.o nmk004.o \
|
||||
\
|
||||
megadrive.o \
|
||||
\
|
||||
|
||||
ifdef DEBUG
|
||||
depobj += m68kdasm.o
|
||||
endif
|
||||
|
||||
autobj += $(depobj)
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
autobj += burn_sound_a.o eagle_fm.o 2xsaimmx.o hq2x32.o hq3x32.o hq4x32.o superscale.o
|
||||
endif
|
|
@ -0,0 +1,544 @@
|
|||
# Makefile for FBA, for use with GNU make & Microsoft Visual C++ 2010
|
||||
#
|
||||
# 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.
|
||||
|
||||
MAKEOS = cygwin
|
||||
ifeq ($(MAKEOS),)
|
||||
MAKEOS = $(OSTYPE)
|
||||
endif
|
||||
|
||||
unexport
|
||||
|
||||
#
|
||||
# Declare variables
|
||||
#
|
||||
|
||||
# Specify the name of the executable file, without ".exe"
|
||||
NAME = fba
|
||||
|
||||
ifdef BUILD_X64_EXE
|
||||
ifdef BUILD_A68K
|
||||
undefine BUILD_A68K
|
||||
endif
|
||||
ifdef BUILD_X86_ASM
|
||||
undefine BUILD_X86_ASM
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef CPUTYPE
|
||||
CPUTYPE = i686
|
||||
endif
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
MMX = 1
|
||||
else
|
||||
MMX = 0
|
||||
endif
|
||||
|
||||
ifndef BUILD_X86_ASM
|
||||
NAME := $(NAME)n
|
||||
endif
|
||||
ifdef BUILD_X64_EXE
|
||||
NAME = fba64
|
||||
endif
|
||||
ifdef DEBUG
|
||||
NAME := $(NAME)d
|
||||
endif
|
||||
ifdef SYMBOL
|
||||
NAME := $(NAME)s
|
||||
endif
|
||||
ifndef UNICODE
|
||||
NAME := $(NAME)a
|
||||
endif
|
||||
|
||||
cpulevel = 6
|
||||
ifeq ($(CPUTYPE),i586)
|
||||
cpulevel = 5
|
||||
endif
|
||||
ifeq ($(CPUTYPE),pentium)
|
||||
cpulevel = 5
|
||||
endif
|
||||
ifeq ($(CPUTYPE),k6)
|
||||
cpulevel = 5
|
||||
endif
|
||||
ifeq ($(CPUTYPE),i786)
|
||||
cpulevel = 7
|
||||
endif
|
||||
ifeq ($(CPUTYPE),pentium4)
|
||||
cpulevel = 7
|
||||
endif
|
||||
ifeq ($(CPUTYPE),athlon)
|
||||
cpulevel = 7
|
||||
endif
|
||||
|
||||
ifeq ($(cpulevel),6)
|
||||
ppro = ppro
|
||||
else
|
||||
NAME := $(NAME)$(CPUTYPE)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Specify paths/files
|
||||
#
|
||||
|
||||
objdir = obj/VC_WIN32/$(NAME)/
|
||||
srcdir = src/
|
||||
|
||||
include makefile.rules
|
||||
|
||||
incdir = $(foreach dir,$(alldir),/I$(srcdir)$(dir)) /I$(objdir)depend/generated
|
||||
|
||||
ifdef UNICODE
|
||||
# lib = unicows.lib
|
||||
endif
|
||||
|
||||
lib += user32.lib gdi32.lib comdlg32.lib comctl32.lib shell32.lib winmm.lib ole32.lib shlwapi.lib \
|
||||
advapi32.lib setupapi.lib
|
||||
|
||||
ifdef BUILD_X86_ASM
|
||||
autobj += hq3xs.o hq_shared32.o
|
||||
endif
|
||||
|
||||
ifdef BUILD_A68K
|
||||
a68k.o = $(objdir)cpu/a68k/a68k.o
|
||||
endif
|
||||
|
||||
license.rtf = $(srcdir)depend/generated/license.rtf
|
||||
driverlist.h = $(srcdir)depend/generated/driverlist.h
|
||||
ctv.h = $(srcdir)depend/generated/ctv.h
|
||||
toa_gp9001_func.h = $(srcdir)depend/generated/toa_gp9001_func.h
|
||||
neo_sprite_func.h = $(srcdir)depend/generated/neo_sprite_func.h
|
||||
cave_tile_func.h = $(srcdir)depend/generated/cave_tile_func.h
|
||||
cave_sprite_func.h = $(srcdir)depend/generated/cave_sprite_func.h
|
||||
psikyo_tile_func.h = $(srcdir)depend/generated/psikyo_tile_func.h
|
||||
# psikyo_sprite_func.h = $(srcdir)depend/generated/psikyo_sprite_func.h
|
||||
build_details.h = $(srcdir)depend/generated/build_details.h
|
||||
|
||||
allobj = $(objdir)cpu/m68k/m68kcpu.o $(objdir)cpu/m68k/m68kopnz.o $(objdir)cpu/m68k/m68kopdm.o $(objdir)cpu/m68k/m68kopac.o $(objdir)cpu/m68k/m68kops.o $(objdir)burner/win32/resource.res \
|
||||
$(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)))))))
|
||||
|
||||
ifdef BUILD_A68K
|
||||
allobj += $(a68k.o)
|
||||
endif
|
||||
|
||||
#
|
||||
#
|
||||
# Specify compiler/linker/assembler
|
||||
#
|
||||
#
|
||||
|
||||
CC = cl
|
||||
CXX = cl
|
||||
LD = link
|
||||
AS = nasm
|
||||
|
||||
incdir += /Isrc\depend\VC\include
|
||||
|
||||
ifndef BUILD_X64_EXE
|
||||
LDFLAGS = /NOLOGO /INCREMENTAL:NO /MACHINE:X86 /LIBPATH:src\VC\lib /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcd.lib # /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:libcp.lib /NODEFAULTLIB:libcpd.lib /NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:libcpmtd.lib
|
||||
else
|
||||
LDFLAGS = /NOLOGO /INCREMENTAL:NO /MACHINE:X64 /LIBPATH:src\VC\lib /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcd.lib # /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:libcp.lib /NODEFAULTLIB:libcpd.lib /NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:libcpmtd.lib
|
||||
endif
|
||||
|
||||
ASFLAGS = -O1 -f coff -w-orphan-labels
|
||||
|
||||
DEF = /DBUILD_WIN32 /DUSE_SPEEDHACKS /DFILENAME=$(NAME) /DMMX=$(MMX) /DZLIB_WINAPI /DDECL_SPEC=__cdecl
|
||||
|
||||
ifdef UNICODE
|
||||
DEF := $(DEF) /D_UNICODE
|
||||
endif
|
||||
|
||||
ifdef SPECIALBUILD
|
||||
DEF := $(DEF) /DSPECIALBUILD=$(SPECIALBUILD)
|
||||
endif
|
||||
|
||||
ifdef FASTCALL
|
||||
DEF := $(DEF) /DFASTCALL
|
||||
endif
|
||||
|
||||
ifdef DEBUG
|
||||
DEF := $(DEF) /DFBA_DEBUG
|
||||
endif
|
||||
|
||||
ifdef ROM_VERIFY
|
||||
DEF := $(DEF) /DROM_VERIFY
|
||||
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 SYMBOL
|
||||
CFLAGS = /nologo /Od /GF /GS /RTC1 /Zi /Zc:forScope /MTd /EHsc /Fp$(objdir)/depend/generated/ # /Wall
|
||||
ASFLAGS += -g
|
||||
LDFLAGS += /DEBUG
|
||||
DEF := $(DEF) /D_DEBUG
|
||||
|
||||
ifdef PROFILE
|
||||
CFLAGS += /Oy
|
||||
else
|
||||
CFLAGS += /Oy-
|
||||
endif
|
||||
|
||||
else
|
||||
CFLAGS = /nologo /w /O2 /Ox /Oi /Ot /Oy /Ob2 /GF /Gs /Gy /GL /Gr /Zc:forScope /MT /EHsc
|
||||
LDFLAGS += /LTCG:STATUS
|
||||
endif
|
||||
|
||||
# Change the priority of some warnings so they are only shown at warning level 4. They are:
|
||||
# lvl4 C4127: conditional expression is constant
|
||||
# lvl4 C4201: nonstandard extension used : nameless struct/union
|
||||
# lvl1 C4244: 'variable' : conversion from 'type' to 'type', possible loss of data
|
||||
# 3 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
# lvl4 C4505: 'function' : unreferenced local function has been removed
|
||||
# lvl4 C4514: 'function' : unreferenced inline function has been removed
|
||||
# lvl4 C4611: interaction between 'function' and C++ object destruction is non-portable
|
||||
# lvl4 C4710: 'function' : function not inlined
|
||||
# lvl1 C4799: No EMMS at end of function 'function'
|
||||
# lvl3 C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
CFLAGS += /w44201 /w44127 /w44244 /w44505 /w44514 /w44611 /w44710 /w44799 /w44800 $(DEF) $(incdir)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
#
|
||||
#
|
||||
# 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 %.res $(foreach dir,$(alldir),$(srcdir)$(dir)/ )
|
||||
|
||||
#
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
#
|
||||
|
||||
.PHONY: all init cleandep touch clean
|
||||
|
||||
ifeq ($(MAKELEVEL),1)
|
||||
|
||||
all: init $(autobj) resource.res
|
||||
$(MAKE) -f makefile.vc
|
||||
|
||||
else
|
||||
|
||||
all: $(NAME).exe
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
#
|
||||
# Rule for linking the executable
|
||||
#
|
||||
#
|
||||
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
|
||||
$(NAME).exe: $(allobj)
|
||||
@echo
|
||||
@echo Linking executable $(NAME).exe...
|
||||
$(LD) $(LDFLAGS) /OUT:$@ $^ $(lib)
|
||||
|
||||
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): $(drvobj) $(srcdir)depend/scripts/gamelist.pl
|
||||
ifdef PERL
|
||||
@$(srcdir)depend/scripts/gamelist.pl -o $@ -l gamelist.txt \
|
||||
$(filter %.cpp,$(foreach file,$(drvobj:.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
|
||||
|
||||
|
||||
#
|
||||
# Fix the .rc file
|
||||
#
|
||||
|
||||
resource.res resource.d: app.rc version.rc version.h $(build_details.h) $(license.rtf)
|
||||
|
||||
$(license.rtf): $(srcdir)license.txt $(srcdir)depend/scripts/license2rtf.pl
|
||||
|
||||
ifdef PERL
|
||||
$(srcdir)depend/scripts/license2rtf.pl $< -o $(srcdir)depend/generated/$(@F:.rc=.rtf)
|
||||
else
|
||||
ifeq ($(MAKELEVEL),2)
|
||||
@echo
|
||||
@echo Warning: Perl is not available on this system.
|
||||
@echo $@ cannot be updated or created!
|
||||
@echo
|
||||
endif
|
||||
endif
|
||||
|
||||
resource.rc: app.rc $(license.rc) $(srcdir)burner/win32/resource/fba.ico $(srcdir)burner/win32/resource/about.bmp $(srcdir)burner/win32/resource/splash.bmp $(srcdir)burner/win32/resource/misc.bmp
|
||||
|
||||
#
|
||||
# Generate some info on the build details
|
||||
#
|
||||
|
||||
about.o about.d systeminfo.o systeminfo.d: $(build_details.h)
|
||||
|
||||
$(build_details.h): $(srcdir)depend/scripts/build_details.cpp
|
||||
$(CC) $(CFLAGS) $< /Fo$(objdir)depend/generated/ /Fe$(objdir)depend/generated/build_details.exe
|
||||
$(objdir)depend/generated/build_details.exe >$@
|
||||
|
||||
#
|
||||
# Compile 68000 cores
|
||||
#
|
||||
|
||||
# A68K
|
||||
|
||||
ifdef BUILD_A68K
|
||||
$(a68k.o): fba_make68k.c
|
||||
echo "Compiling A68K MC68000 core... "
|
||||
$(CC) $(CFLAGS) -DWIN32 $< /Fo$(subst $(srcdir),$(objdir),$(<D))/ /Fe$(subst $(srcdir),$(objdir),$(<D))/$(<F:.c=.exe) /link $(LDFLAGS) /SUBSYSTEM:CONSOLE
|
||||
$(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)depend/generated/m68kops.h $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo "Compiling Musashi MC680x0 core... "
|
||||
$(CC) $(CFLAGS) /DINLINE="__inline static" /c $(srcdir)cpu/m68k/m68kcpu.c /Fo$(objdir)cpu/m68k/m68kcpu.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kops.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kops.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo "Compiling Musashi MC680x0 core... "
|
||||
$(CC) $(CFLAGS) /DINLINE="__inline static" /c $(objdir)depend/generated/m68kops.c /Fo$(objdir)cpu/m68k/m68kops.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kopac.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kopac.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo "Compiling Musashi MC680x0 core... "
|
||||
$(CC) $(CFLAGS) /DINLINE="__inline static" /c $(objdir)depend/generated/m68kopac.c /Fo$(objdir)cpu/m68k/m68kopac.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kopdm.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kopdm.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo "Compiling Musashi MC680x0 core... "
|
||||
$(CC) $(CFLAGS) /DINLINE="__inline static" /c $(objdir)depend/generated/m68kopdm.c /Fo$(objdir)cpu/m68k/m68kopdm.o
|
||||
|
||||
$(objdir)cpu/m68k/m68kopnz.o: $(objdir)cpu/m68k/m68kmake.exe $(objdir)depend/generated/m68kops.h $(objdir)depend/generated/m68kopnz.c $(srcdir)cpu/m68k/m68k.h $(srcdir)cpu/m68k/m68kconf.h
|
||||
@echo "Compiling Musashi MC680x0 core... "
|
||||
$(CC) $(CFLAGS) /DINLINE="__inline static" /c $(objdir)depend/generated/m68kopnz.c /Fo$(objdir)cpu/m68k/m68kopnz.o
|
||||
|
||||
$(objdir)depend/generated/m68kops.h: $(objdir)cpu/m68k/m68kmake.exe $(srcdir)cpu/m68k/m68k_in.c
|
||||
$(objdir)/cpu/m68k/m68kmake $(objdir)depend/generated/ $(srcdir)cpu/m68k/m68k_in.c
|
||||
|
||||
$(objdir)cpu/m68k/m68kmake.exe: $(srcdir)cpu/m68k/m68kmake.c
|
||||
@echo "Compiling Musashi MC680x0 core... "
|
||||
$(CC) $(CFLAGS) /DINLINE="__inline static" $(srcdir)cpu/m68k/m68kmake.c /Fo$(objdir)cpu/m68k/ /Fe$(objdir)cpu/m68k/m68kmake.exe /link $(LDFLAGS) /SUBSYSTEM:CONSOLE
|
||||
|
||||
|
||||
#
|
||||
# Extra rules for generated header file cvt.h, needed by ctv.cpp
|
||||
#
|
||||
|
||||
ctv.o: $(ctv.h)
|
||||
|
||||
$(ctv.h): ctv_make.cpp
|
||||
@echo Generating... $(srcdir)depend/generated/$(@F)
|
||||
$(CC) $(CXXFLAGS) $< /Fo$(subst $(srcdir),$(objdir),$(<D))/ /Fe$(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe) /link $(LDFLAGS) /SUBSYSTEM:CONSOLE
|
||||
$(subst $(srcdir),$(objdir),$(<D))/$(<F:.cpp=.exe) >$@
|
||||
|
||||
#
|
||||
# Extra rules for generated header file toa_gp9001_func.h, needed by toa_gp9001.cpp
|
||||
#
|
||||
|
||||
toa_bcu2.o toa_gp9001.o: $(toa_gp9001_func.h)
|
||||
|
||||
$(toa_gp9001_func.h): $(srcdir)depend/scripts/toa_gp9001_func.pl
|
||||
$(srcdir)depend/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.o: $(neo_sprite_func.h)
|
||||
|
||||
$(neo_sprite_func.h): $(srcdir)depend/scripts/neo_sprite_func.pl
|
||||
$(srcdir)depend/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.o: $(cave_tile_func.h)
|
||||
|
||||
$(cave_tile_func.h): $(srcdir)depend/scripts/cave_tile_func.pl
|
||||
$(srcdir)depend/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.o: $(cave_sprite_func.h)
|
||||
|
||||
$(cave_sprite_func.h): $(srcdir)depend/scripts/cave_sprite_func.pl
|
||||
$(srcdir)depend/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.o psikyo_sprite.o: $(psikyo_tile_func.h)
|
||||
|
||||
$(psikyo_tile_func.h): $(srcdir)depend/scripts/psikyo_tile_func.pl
|
||||
$(srcdir)depend/scripts/psikyo_tile_func.pl -o $(psikyo_tile_func.h)
|
||||
|
||||
#
|
||||
# Generic rule for resource files
|
||||
#
|
||||
|
||||
%.res: %.rc
|
||||
@echo Compiling resource file... $(<F)
|
||||
rc $(DEF) /n /Fo $(subst $(srcdir),$(objdir),$(<D))/$(@F) $(incdir) $<
|
||||
|
||||
#
|
||||
# Generic rules for C/C++ files
|
||||
#
|
||||
|
||||
ifeq ($(MAKELEVEL),1)
|
||||
|
||||
%.o: %.cpp
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CXXFLAGS) /c $< /Fo$(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
%.o: %.c
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CFLAGS) /c /Dinline=__inline $< /Fo$(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
%.o: %.asm
|
||||
@echo Assembling $<...
|
||||
@$(AS) $(ASFLAGS) $< -o$(subst $(srcdir),$(objdir),$(<D))/$(@F)
|
||||
|
||||
else
|
||||
|
||||
%.o: %.c
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CFLAGS) /c /Dinline=__inline $< /Fo $@
|
||||
|
||||
%.o: %.asm
|
||||
@echo Assembling $<...
|
||||
@$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
%.o:
|
||||
@echo Compiling $<...
|
||||
@$(CC) $(CXXFLAGS) /c $< /Fo $@
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# Phony targets
|
||||
#
|
||||
|
||||
init:
|
||||
|
||||
ifdef DEBUG
|
||||
@echo Making debug build...
|
||||
else
|
||||
@echo Making normal build...
|
||||
endif
|
||||
@echo
|
||||
ifeq ($(MAKEOS),cygwin)
|
||||
@mkdir -p $(foreach dir, $(alldir),$(objdir)$(dir))
|
||||
@mkdir -p $(srcdir)depend/generated
|
||||
else
|
||||
@echo nt
|
||||
@mkdir $(foreach dir, $(alldir),$(objdir)$(dir))
|
||||
@mkdir $(srcdir)depend/generated
|
||||
endif
|
||||
|
||||
touch:
|
||||
@echo Marking all targets for $(NAME) as uptodate...
|
||||
-@touch $(NAME).exe
|
||||
-@touch -c -r $(NAME).exe $(srcdir)/depend/generated/*
|
||||
-@for dir in $(alldir); do touch -c -r $(NAME).exe $(objdir)$$dir/*; done
|
||||
|
||||
clean:
|
||||
@echo Removing all files from $(objdir)...
|
||||
ifeq ($(MAKEOS),cygwin)
|
||||
-@rm -f -r $(objdir)
|
||||
-@rm -f -r $(ctv.h)
|
||||
else
|
||||
-@del -f -s $(objdir)
|
||||
-@del -f -s $(ctv.h)
|
||||
endif
|
||||
|
||||
ifdef PERL
|
||||
@echo Removing all files generated with perl scripts...
|
||||
ifeq ($(MAKEOS),cygwin)
|
||||
-@rm -f -r $(driverlist)
|
||||
else
|
||||
-@del -f -s $(driverlist)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# Rule to force recompilation of any target that depends on it
|
||||
#
|
||||
|
||||
FORCE:
|
Binary file not shown.
|
@ -0,0 +1,100 @@
|
|||
#define BITSWAP32(n, \
|
||||
bit31, bit30, bit29, bit28, bit27, bit26, bit25, bit24, \
|
||||
bit23, bit22, bit21, bit20, bit19, bit18, bit17, bit16, \
|
||||
bit15, bit14, bit13, bit12, bit11, bit10, bit09, bit08, \
|
||||
bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \
|
||||
(((((n) >> (bit31)) & 1) << 31) | \
|
||||
((((n) >> (bit30)) & 1) << 30) | \
|
||||
((((n) >> (bit29)) & 1) << 29) | \
|
||||
((((n) >> (bit28)) & 1) << 28) | \
|
||||
((((n) >> (bit27)) & 1) << 27) | \
|
||||
((((n) >> (bit26)) & 1) << 26) | \
|
||||
((((n) >> (bit25)) & 1) << 25) | \
|
||||
((((n) >> (bit24)) & 1) << 24) | \
|
||||
((((n) >> (bit23)) & 1) << 23) | \
|
||||
((((n) >> (bit22)) & 1) << 22) | \
|
||||
((((n) >> (bit21)) & 1) << 21) | \
|
||||
((((n) >> (bit20)) & 1) << 20) | \
|
||||
((((n) >> (bit19)) & 1) << 19) | \
|
||||
((((n) >> (bit18)) & 1) << 18) | \
|
||||
((((n) >> (bit17)) & 1) << 17) | \
|
||||
((((n) >> (bit16)) & 1) << 16) | \
|
||||
((((n) >> (bit15)) & 1) << 15) | \
|
||||
((((n) >> (bit14)) & 1) << 14) | \
|
||||
((((n) >> (bit13)) & 1) << 13) | \
|
||||
((((n) >> (bit12)) & 1) << 12) | \
|
||||
((((n) >> (bit11)) & 1) << 11) | \
|
||||
((((n) >> (bit10)) & 1) << 10) | \
|
||||
((((n) >> (bit09)) & 1) << 9) | \
|
||||
((((n) >> (bit08)) & 1) << 8) | \
|
||||
((((n) >> (bit07)) & 1) << 7) | \
|
||||
((((n) >> (bit06)) & 1) << 6) | \
|
||||
((((n) >> (bit05)) & 1) << 5) | \
|
||||
((((n) >> (bit04)) & 1) << 4) | \
|
||||
((((n) >> (bit03)) & 1) << 3) | \
|
||||
((((n) >> (bit02)) & 1) << 2) | \
|
||||
((((n) >> (bit01)) & 1) << 1) | \
|
||||
((((n) >> (bit00)) & 1) << 0))
|
||||
|
||||
#define BITSWAP24(n, \
|
||||
bit23, bit22, bit21, bit20, bit19, bit18, bit17, bit16, \
|
||||
bit15, bit14, bit13, bit12, bit11, bit10, bit09, bit08, \
|
||||
bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \
|
||||
(((((n) >> (bit23)) & 1) << 23) | \
|
||||
((((n) >> (bit22)) & 1) << 22) | \
|
||||
((((n) >> (bit21)) & 1) << 21) | \
|
||||
((((n) >> (bit20)) & 1) << 20) | \
|
||||
((((n) >> (bit19)) & 1) << 19) | \
|
||||
((((n) >> (bit18)) & 1) << 18) | \
|
||||
((((n) >> (bit17)) & 1) << 17) | \
|
||||
((((n) >> (bit16)) & 1) << 16) | \
|
||||
((((n) >> (bit15)) & 1) << 15) | \
|
||||
((((n) >> (bit14)) & 1) << 14) | \
|
||||
((((n) >> (bit13)) & 1) << 13) | \
|
||||
((((n) >> (bit12)) & 1) << 12) | \
|
||||
((((n) >> (bit11)) & 1) << 11) | \
|
||||
((((n) >> (bit10)) & 1) << 10) | \
|
||||
((((n) >> (bit09)) & 1) << 9) | \
|
||||
((((n) >> (bit08)) & 1) << 8) | \
|
||||
((((n) >> (bit07)) & 1) << 7) | \
|
||||
((((n) >> (bit06)) & 1) << 6) | \
|
||||
((((n) >> (bit05)) & 1) << 5) | \
|
||||
((((n) >> (bit04)) & 1) << 4) | \
|
||||
((((n) >> (bit03)) & 1) << 3) | \
|
||||
((((n) >> (bit02)) & 1) << 2) | \
|
||||
((((n) >> (bit01)) & 1) << 1) | \
|
||||
((((n) >> (bit00)) & 1) << 0))
|
||||
|
||||
#define BITSWAP16(n, \
|
||||
bit15, bit14, bit13, bit12, bit11, bit10, bit09, bit08, \
|
||||
bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \
|
||||
(((((n) >> (bit15)) & 1) << 15) | \
|
||||
((((n) >> (bit14)) & 1) << 14) | \
|
||||
((((n) >> (bit13)) & 1) << 13) | \
|
||||
((((n) >> (bit12)) & 1) << 12) | \
|
||||
((((n) >> (bit11)) & 1) << 11) | \
|
||||
((((n) >> (bit10)) & 1) << 10) | \
|
||||
((((n) >> (bit09)) & 1) << 9) | \
|
||||
((((n) >> (bit08)) & 1) << 8) | \
|
||||
((((n) >> (bit07)) & 1) << 7) | \
|
||||
((((n) >> (bit06)) & 1) << 6) | \
|
||||
((((n) >> (bit05)) & 1) << 5) | \
|
||||
((((n) >> (bit04)) & 1) << 4) | \
|
||||
((((n) >> (bit03)) & 1) << 3) | \
|
||||
((((n) >> (bit02)) & 1) << 2) | \
|
||||
((((n) >> (bit01)) & 1) << 1) | \
|
||||
((((n) >> (bit00)) & 1) << 0))
|
||||
|
||||
#define BITSWAP08(n, \
|
||||
bit07, bit06, bit05, bit04, bit03, bit02, bit01, bit00) \
|
||||
(((((n) >> (bit07)) & 1) << 7) | \
|
||||
((((n) >> (bit06)) & 1) << 6) | \
|
||||
((((n) >> (bit05)) & 1) << 5) | \
|
||||
((((n) >> (bit04)) & 1) << 4) | \
|
||||
((((n) >> (bit03)) & 1) << 3) | \
|
||||
((((n) >> (bit02)) & 1) << 2) | \
|
||||
((((n) >> (bit01)) & 1) << 1) | \
|
||||
((((n) >> (bit00)) & 1) << 0))
|
||||
|
||||
#define BYTE_XOR_LE(a) ((a))
|
||||
#define BIT(x,n) (((x)>>(n))&1)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,507 @@
|
|||
// FB Alpha - Emulator for MC68000/Z80 based arcade games
|
||||
// Refer to the "license.txt" file for more info
|
||||
|
||||
// Burner emulation library
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined (_WIN32)
|
||||
#define __cdecl
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH (260)
|
||||
#endif
|
||||
|
||||
extern TCHAR szAppHiscorePath[MAX_PATH];
|
||||
extern TCHAR szAppSamplesPath[MAX_PATH];
|
||||
|
||||
// Enable the MAME logerror() function in debug builds
|
||||
// #define MAME_USE_LOGERROR
|
||||
|
||||
// Give access to the CPUID function for various compilers
|
||||
#if defined (__GNUC__)
|
||||
#define CPUID(f,ra,rb,rc,rd) __asm__ __volatile__ ("cpuid" \
|
||||
: "=a" (ra), "=b" (rb), "=c" (rc), "=d" (rd) \
|
||||
: "a" (f) \
|
||||
);
|
||||
#elif defined (_MSC_VER)
|
||||
#define CPUID(f,ra,rb,rc,rd) __asm { __asm mov eax, f \
|
||||
__asm cpuid \
|
||||
__asm mov ra, eax \
|
||||
__asm mov rb, ebx \
|
||||
__asm mov rc, ecx \
|
||||
__asm mov rd, edx }
|
||||
#else
|
||||
#define CPUID(f,ra,rb,rc,rd)
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_X86_ASM
|
||||
#undef CPUID
|
||||
#define CPUID(f,ra,rb,rc,rd)
|
||||
#endif
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define SEPERATOR_1 " \u2022 "
|
||||
#define SEPERATOR_2 " \u25E6 "
|
||||
#else
|
||||
#define SEPERATOR_1 " ~ "
|
||||
#define SEPERATOR_2 " ~ "
|
||||
#endif
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define WRITE_UNICODE_BOM(file) { UINT16 BOM[] = { 0xFEFF }; fwrite(BOM, 2, 1, file); }
|
||||
#else
|
||||
#define WRITE_UNICODE_BOM(file)
|
||||
#endif
|
||||
|
||||
typedef unsigned char UINT8;
|
||||
typedef signed char INT8;
|
||||
typedef unsigned short UINT16;
|
||||
typedef signed short INT16;
|
||||
typedef unsigned int UINT32;
|
||||
typedef signed int INT32;
|
||||
#ifdef _MSC_VER
|
||||
typedef signed __int64 INT64;
|
||||
typedef unsigned __int64 UINT64;
|
||||
#else
|
||||
__extension__ typedef unsigned long long UINT64;
|
||||
__extension__ typedef long long INT64;
|
||||
#endif
|
||||
|
||||
#include "state.h"
|
||||
#include "cheat.h"
|
||||
#include "hiscore.h"
|
||||
|
||||
extern INT32 nBurnVer; // Version number of the library
|
||||
|
||||
enum BurnCartrigeCommand { CART_INIT_START, CART_INIT_END, CART_EXIT };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Callbacks
|
||||
|
||||
// Application-defined rom loading function
|
||||
extern INT32 (__cdecl *BurnExtLoadRom)(UINT8* Dest, INT32* pnWrote, INT32 i);
|
||||
|
||||
// Application-defined progress indicator functions
|
||||
extern INT32 (__cdecl *BurnExtProgressRangeCallback)(double dProgressRange);
|
||||
extern INT32 (__cdecl *BurnExtProgressUpdateCallback)(double dProgress, const TCHAR* pszText, bool bAbs);
|
||||
|
||||
// Application-defined catridge initialisation function
|
||||
extern INT32 (__cdecl *BurnExtCartridgeSetupCallback)(BurnCartrigeCommand nCommand);
|
||||
|
||||
// Application-defined colour conversion function
|
||||
extern UINT32 (__cdecl *BurnHighCol) (INT32 r, INT32 g, INT32 b, INT32 i);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
extern UINT32 nCurrentFrame;
|
||||
|
||||
inline static INT32 GetCurrentFrame() {
|
||||
return nCurrentFrame;
|
||||
}
|
||||
|
||||
inline static void SetCurrentFrame(const UINT32 n) {
|
||||
nCurrentFrame = n;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Driver info structures
|
||||
|
||||
// ROMs
|
||||
|
||||
#define BRF_PRG (1 << 20)
|
||||
#define BRF_GRA (1 << 21)
|
||||
#define BRF_SND (1 << 22)
|
||||
|
||||
#define BRF_ESS (1 << 24)
|
||||
#define BRF_BIOS (1 << 25)
|
||||
#define BRF_SELECT (1 << 26)
|
||||
#define BRF_OPT (1 << 27)
|
||||
#define BRF_NODUMP (1 << 28)
|
||||
|
||||
struct BurnRomInfo {
|
||||
char szName[100];
|
||||
UINT32 nLen;
|
||||
UINT32 nCrc;
|
||||
UINT32 nType;
|
||||
};
|
||||
|
||||
struct BurnSampleInfo {
|
||||
char szName[100];
|
||||
UINT32 nFlags;
|
||||
};
|
||||
|
||||
// Inputs
|
||||
|
||||
#define BIT_DIGITAL (1)
|
||||
|
||||
#define BIT_GROUP_ANALOG (4)
|
||||
#define BIT_ANALOG_REL (4)
|
||||
#define BIT_ANALOG_ABS (5)
|
||||
|
||||
#define BIT_GROUP_CONSTANT (8)
|
||||
#define BIT_CONSTANT (8)
|
||||
#define BIT_DIPSWITCH (9)
|
||||
|
||||
struct BurnInputInfo {
|
||||
char* szName;
|
||||
UINT8 nType;
|
||||
union {
|
||||
UINT8* pVal; // Most inputs use a char*
|
||||
UINT16* pShortVal; // All analog inputs use a short*
|
||||
};
|
||||
char* szInfo;
|
||||
};
|
||||
|
||||
// DIPs
|
||||
|
||||
struct BurnDIPInfo {
|
||||
INT32 nInput;
|
||||
UINT8 nFlags;
|
||||
UINT8 nMask;
|
||||
UINT8 nSetting;
|
||||
char* szText;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
extern bool bBurnUseMMX;
|
||||
extern bool bBurnUseASMCPUEmulation;
|
||||
|
||||
extern UINT32 nFramesEmulated;
|
||||
extern UINT32 nFramesRendered;
|
||||
extern clock_t starttime; // system time when emulation started and after roms loaded
|
||||
|
||||
extern bool bForce60Hz;
|
||||
|
||||
extern INT32 nBurnFPS;
|
||||
extern INT32 nBurnCPUSpeedAdjust;
|
||||
|
||||
extern UINT32 nBurnDrvCount; // Count of game drivers
|
||||
extern UINT32 nBurnDrvActive; // Which game driver is selected
|
||||
extern UINT32 nBurnDrvSelect[8]; // Which games are selected (i.e. loaded but not necessarily active)
|
||||
|
||||
extern INT32 nMaxPlayers;
|
||||
|
||||
extern UINT8 *pBurnDraw; // Pointer to correctly sized bitmap
|
||||
extern INT32 nBurnPitch; // Pitch between each line
|
||||
extern INT32 nBurnBpp; // Bytes per pixel (2, 3, or 4)
|
||||
|
||||
extern UINT8 nBurnLayer; // Can be used externally to select which layers to show
|
||||
extern UINT8 nSpriteEnable; // Can be used externally to select which Sprites to show
|
||||
|
||||
extern INT32 nBurnSoundRate; // Samplerate of sound
|
||||
extern INT32 nBurnSoundLen; // Length in samples per frame
|
||||
extern INT16* pBurnSoundOut; // Pointer to output buffer
|
||||
|
||||
extern INT32 nInterpolation; // Desired interpolation level for ADPCM/PCM sound
|
||||
extern INT32 nFMInterpolation; // Desired interpolation level for FM sound
|
||||
|
||||
extern UINT32 *pBurnDrvPalette;
|
||||
|
||||
#define PRINT_NORMAL (0)
|
||||
#define PRINT_UI (1)
|
||||
#define PRINT_IMPORTANT (2)
|
||||
#define PRINT_ERROR (3)
|
||||
|
||||
extern INT32 (__cdecl *bprintf) (INT32 nStatus, TCHAR* szFormat, ...);
|
||||
|
||||
INT32 BurnLibInit();
|
||||
INT32 BurnLibExit();
|
||||
|
||||
INT32 BurnDrvInit();
|
||||
INT32 BurnDrvExit();
|
||||
|
||||
INT32 BurnDrvCartridgeSetup(BurnCartrigeCommand nCommand);
|
||||
|
||||
INT32 BurnDrvFrame();
|
||||
INT32 BurnDrvRedraw();
|
||||
INT32 BurnRecalcPal();
|
||||
INT32 BurnDrvGetPaletteEntries();
|
||||
|
||||
INT32 BurnSetProgressRange(double dProgressRange);
|
||||
INT32 BurnUpdateProgress(double dProgressStep, const TCHAR* pszText, bool bAbs);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Retrieve driver information
|
||||
|
||||
#define DRV_NAME (0)
|
||||
#define DRV_DATE (1)
|
||||
#define DRV_FULLNAME (2)
|
||||
//#define DRV_MEDIUMNAME (3)
|
||||
#define DRV_COMMENT (4)
|
||||
#define DRV_MANUFACTURER (5)
|
||||
#define DRV_SYSTEM (6)
|
||||
#define DRV_PARENT (7)
|
||||
#define DRV_BOARDROM (8)
|
||||
#define DRV_SAMPLENAME (9)
|
||||
|
||||
#define DRV_NEXTNAME (1 << 8)
|
||||
#define DRV_ASCIIONLY (1 << 12)
|
||||
#define DRV_UNICODEONLY (1 << 13)
|
||||
|
||||
TCHAR* BurnDrvGetText(UINT32 i);
|
||||
char* BurnDrvGetTextA(UINT32 i);
|
||||
|
||||
INT32 BurnDrvGetZipName(char** pszName, UINT32 i);
|
||||
INT32 BurnDrvGetRomInfo(struct BurnRomInfo *pri, UINT32 i);
|
||||
INT32 BurnDrvGetRomName(char** pszName, UINT32 i, INT32 nAka);
|
||||
INT32 BurnDrvGetInputInfo(struct BurnInputInfo* pii, UINT32 i);
|
||||
INT32 BurnDrvGetDIPInfo(struct BurnDIPInfo* pdi, UINT32 i);
|
||||
INT32 BurnDrvGetVisibleSize(INT32* pnWidth, INT32* pnHeight);
|
||||
INT32 BurnDrvGetVisibleOffs(INT32* pnLeft, INT32* pnTop);
|
||||
INT32 BurnDrvGetFullSize(INT32* pnWidth, INT32* pnHeight);
|
||||
INT32 BurnDrvGetAspect(INT32* pnXAspect, INT32* pnYAspect);
|
||||
INT32 BurnDrvGetHardwareCode();
|
||||
INT32 BurnDrvGetFlags();
|
||||
bool BurnDrvIsWorking();
|
||||
INT32 BurnDrvGetMaxPlayers();
|
||||
INT32 BurnDrvSetVisibleSize(INT32 pnWidth, INT32 pnHeight);
|
||||
INT32 BurnDrvSetAspect(INT32 pnXAspect, INT32 pnYAspect);
|
||||
INT32 BurnDrvGetGenreFlags();
|
||||
INT32 BurnDrvGetFamilyFlags();
|
||||
INT32 BurnDrvGetSampleInfo(struct BurnSampleInfo *pri, UINT32 i);
|
||||
INT32 BurnDrvGetSampleName(char** pszName, UINT32 i, INT32 nAka);
|
||||
|
||||
void Reinitialise();
|
||||
|
||||
extern bool bDoIpsPatch;
|
||||
void IpsApplyPatches(UINT8* base, char* rom_name);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Flags used with the Burndriver structure
|
||||
|
||||
// Flags for the flags member
|
||||
#define BDF_GAME_WORKING (1 << 0)
|
||||
#define BDF_ORIENTATION_FLIPPED (1 << 1)
|
||||
#define BDF_ORIENTATION_VERTICAL (1 << 2)
|
||||
#define BDF_BOARDROM (1 << 3)
|
||||
#define BDF_CLONE (1 << 4)
|
||||
#define BDF_BOOTLEG (1 << 5)
|
||||
#define BDF_PROTOTYPE (1 << 6)
|
||||
#define BDF_16BIT_ONLY (1 << 7)
|
||||
#define BDF_HACK (1 << 8)
|
||||
#define BDF_HOMEBREW (1 << 9)
|
||||
#define BDF_DEMO (1 << 10)
|
||||
#define BDF_HISCORE_SUPPORTED (1 << 11)
|
||||
|
||||
// Flags for the hardware member
|
||||
// Format: 0xDDEEFFFF, where EE: Manufacturer, DD: Hardware platform, FFFF: Flags (used by driver)
|
||||
|
||||
#define HARDWARE_PUBLIC_MASK (0xFFFF0000)
|
||||
|
||||
#define HARDWARE_PREFIX_CARTRIDGE (0x80000000)
|
||||
|
||||
#define HARDWARE_PREFIX_MISC_PRE90S (0x00000000)
|
||||
#define HARDWARE_PREFIX_CAPCOM (0x01000000)
|
||||
#define HARDWARE_PREFIX_SEGA (0x02000000)
|
||||
#define HARDWARE_PREFIX_KONAMI (0x03000000)
|
||||
#define HARDWARE_PREFIX_TOAPLAN (0x04000000)
|
||||
#define HARDWARE_PREFIX_SNK (0x05000000)
|
||||
#define HARDWARE_PREFIX_CAVE (0x06000000)
|
||||
#define HARDWARE_PREFIX_CPS2 (0x07000000)
|
||||
#define HARDWARE_PREFIX_IGS_PGM (0x08000000)
|
||||
#define HARDWARE_PREFIX_CPS3 (0x09000000)
|
||||
#define HARDWARE_PREFIX_MISC_POST90S (0x0a000000)
|
||||
#define HARDWARE_PREFIX_TAITO (0x0b000000)
|
||||
#define HARDWARE_PREFIX_SEGA_MEGADRIVE (0x0c000000)
|
||||
#define HARDWARE_PREFIX_PSIKYO (0x0d000000)
|
||||
//#define HARDWARE_PREFIX_KANEKO16 (0x0e000000) // spare
|
||||
#define HARDWARE_PREFIX_PACMAN (0x0f000000)
|
||||
#define HARDWARE_PREFIX_GALAXIAN (0x10000000)
|
||||
#define HARDWARE_PREFIX_IREM (0x20000000)
|
||||
|
||||
#define HARDWARE_MISC_PRE90S (HARDWARE_PREFIX_MISC_PRE90S)
|
||||
#define HARDWARE_MISC_POST90S (HARDWARE_PREFIX_MISC_POST90S)
|
||||
|
||||
#define HARDWARE_CAPCOM_CPS1 (HARDWARE_PREFIX_CAPCOM | 0x00010000)
|
||||
#define HARDWARE_CAPCOM_CPS1_QSOUND (HARDWARE_PREFIX_CAPCOM | 0x00020000)
|
||||
#define HARDWARE_CAPCOM_CPS1_GENERIC (HARDWARE_PREFIX_CAPCOM | 0x00030000)
|
||||
#define HARDWARE_CAPCOM_CPSCHANGER (HARDWARE_PREFIX_CAPCOM | 0x00040000)
|
||||
#define HARDWARE_CAPCOM_CPS2 (HARDWARE_PREFIX_CPS2 | 0x00010000)
|
||||
#define HARDWARE_CAPCOM_CPS2_SIMM (0x0002)
|
||||
|
||||
#define HARDWARE_SEGA_SYSTEMX (HARDWARE_PREFIX_SEGA | 0x00010000)
|
||||
#define HARDWARE_SEGA_SYSTEMY (HARDWARE_PREFIX_SEGA | 0x00020000)
|
||||
#define HARDWARE_SEGA_SYSTEM16A (HARDWARE_PREFIX_SEGA | 0x00030000)
|
||||
#define HARDWARE_SEGA_SYSTEM16B (HARDWARE_PREFIX_SEGA | 0x00040000)
|
||||
#define HARDWARE_SEGA_SYSTEM16M (HARDWARE_PREFIX_SEGA | 0x00050000)
|
||||
#define HARDWARE_SEGA_SYSTEM18 (HARDWARE_PREFIX_SEGA | 0x00060000)
|
||||
#define HARDWARE_SEGA_HANGON (HARDWARE_PREFIX_SEGA | 0x00070000)
|
||||
#define HARDWARE_SEGA_OUTRUN (HARDWARE_PREFIX_SEGA | 0x00080000)
|
||||
#define HARDWARE_SEGA_SYSTEM1 (HARDWARE_PREFIX_SEGA | 0x00090000)
|
||||
|
||||
#define HARDWARE_SEGA_FD1089A_ENC (0x0001)
|
||||
#define HARDWARE_SEGA_FD1089B_ENC (0x0002)
|
||||
#define HARDWARE_SEGA_5358 (0x0004)
|
||||
#define HARDWARE_SEGA_MC8123_ENC (0x0008)
|
||||
#define HARDWARE_SEGA_BAYROUTE_MEMMAP (0x0010)
|
||||
#define HARDWARE_SEGA_ALT_MEMMAP (0x0020)
|
||||
#define HARDWARE_SEGA_FD1094_ENC (0x0040)
|
||||
#define HARDWARE_SEGA_SPRITE_LOAD32 (0x0080)
|
||||
#define HARDWARE_SEGA_YM2203 (0x0100)
|
||||
#define HARDWARE_SEGA_INVERT_TILES (0x0200)
|
||||
#define HARDWARE_SEGA_5521 (0x0400)
|
||||
#define HARDWARE_SEGA_5797 (0x0800)
|
||||
#define HARDWARE_SEGA_YM2413 (0x1000)
|
||||
#define HARDWARE_SEGA_FD1094_ENC_CPU2 (0x2000)
|
||||
#define HARDWARE_SEGA_ISGSM (0x4000)
|
||||
#define HARDWARE_SEGA_5704_PS2 (0x8000)
|
||||
|
||||
#define HARDWARE_KONAMI_68K_Z80 (HARDWARE_PREFIX_KONAMI | 0x00010000)
|
||||
#define HARDWARE_KONAMI_68K_ONLY (HARDWARE_PREFIX_KONAMI | 0x00020000)
|
||||
|
||||
#define HARDWARE_TOAPLAN_RAIZING (HARDWARE_PREFIX_TOAPLAN | 0x00010000)
|
||||
#define HARDWARE_TOAPLAN_68K_Zx80 (HARDWARE_PREFIX_TOAPLAN | 0x00020000)
|
||||
#define HARDWARE_TOAPLAN_68K_ONLY (HARDWARE_PREFIX_TOAPLAN | 0x00030000)
|
||||
|
||||
#define HARDWARE_SNK_NEOGEO (HARDWARE_PREFIX_SNK | 0x00010000)
|
||||
#define HARDWARE_SNK_SWAPP (0x0001) // Swap code roms
|
||||
#define HARDWARE_SNK_SWAPV (0x0002) // Swap sound roms
|
||||
#define HARDWARE_SNK_SWAPC (0x0004) // Swap sprite roms
|
||||
#define HARDWARE_SNK_CMC42 (0x0008) // CMC42 encryption chip
|
||||
#define HARDWARE_SNK_CMC50 (0x0010) // CMC50 encryption chip
|
||||
#define HARDWARE_SNK_ALTERNATE_TEXT (0x0020) // KOF2000 text layer banks
|
||||
#define HARDWARE_SNK_SMA_PROTECTION (0x0040) // SMA protection
|
||||
#define HARDWARE_SNK_KOF2K3 (0x0080) // KOF2K3 hardware
|
||||
#define HARDWARE_SNK_ENCRYPTED_M1 (0x0100) // M1 encryption
|
||||
#define HARDWARE_SNK_P32 (0x0200) // SWAP32 P ROMs
|
||||
#define HARDWARE_SNK_SPRITE32 (0x0400)
|
||||
|
||||
#define HARDWARE_SNK_CONTROLMASK (0xF000)
|
||||
#define HARDWARE_SNK_JOYSTICK (0x0000) // Uses joysticks
|
||||
#define HARDWARE_SNK_PADDLE (0x1000) // Uses joysticks or paddles
|
||||
#define HARDWARE_SNK_TRACKBALL (0x2000) // Uses a trackball
|
||||
#define HARDWARE_SNK_4_JOYSTICKS (0x3000) // Uses 4 joysticks
|
||||
#define HARDWARE_SNK_MAHJONG (0x4000) // Uses a special mahjong controller
|
||||
#define HARDWARE_SNK_GAMBLING (0x5000) // Uses gambling controls
|
||||
|
||||
#define HARDWARE_SNK_MVS (HARDWARE_PREFIX_SNK | 0x00020000)
|
||||
#define HARDWARE_SNK_NEOCD (HARDWARE_PREFIX_SNK | 0x00030000)
|
||||
#define HARDWARE_SNK_DEDICATED_PCB (HARDWARE_PREFIX_SNK | 0x00040000)
|
||||
|
||||
#define HARDWARE_CAVE_68K_ONLY (HARDWARE_PREFIX_CAVE)
|
||||
#define HARDWARE_CAVE_68K_Z80 (HARDWARE_PREFIX_CAVE | 0x0001)
|
||||
#define HARDWARE_CAVE_M6295 (0x0002)
|
||||
#define HARDWARE_CAVE_YM2151 (0x0004)
|
||||
|
||||
#define HARDWARE_IGS_PGM (HARDWARE_PREFIX_IGS_PGM)
|
||||
#define HARDWARE_IGS_USE_ARM_CPU (0x0001)
|
||||
|
||||
#define HARDWARE_CAPCOM_CPS3 (HARDWARE_PREFIX_CPS3)
|
||||
#define HARDWARE_CAPCOM_CPS3_NO_CD (0x0001)
|
||||
|
||||
#define HARDWARE_TAITO_TAITOZ (HARDWARE_PREFIX_TAITO | 0x00010000)
|
||||
#define HARDWARE_TAITO_TAITOF2 (HARDWARE_PREFIX_TAITO | 0x00020000)
|
||||
#define HARDWARE_TAITO_MISC (HARDWARE_PREFIX_TAITO | 0x00030000)
|
||||
#define HARDWARE_TAITO_TAITOX (HARDWARE_PREFIX_TAITO | 0x00040000)
|
||||
#define HARDWARE_TAITO_TAITOB (HARDWARE_PREFIX_TAITO | 0x00050000)
|
||||
|
||||
#define HARDWARE_IREM_M62 (HARDWARE_PREFIX_IREM | 0x00010000)
|
||||
#define HARDWARE_IREM_M63 (HARDWARE_PREFIX_IREM | 0x00020000)
|
||||
#define HARDWARE_IREM_M72 (HARDWARE_PREFIX_IREM | 0x00030000)
|
||||
#define HARDWARE_IREM_M90 (HARDWARE_PREFIX_IREM | 0x00040000)
|
||||
#define HARDWARE_IREM_M92 (HARDWARE_PREFIX_IREM | 0x00050000)
|
||||
|
||||
#define HARDWARE_SEGA_MEGADRIVE (HARDWARE_PREFIX_SEGA_MEGADRIVE)
|
||||
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_EEPROM (1)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_SRAM (2)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SEGA_FRAM (3)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART (4)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_CM_JCART_SEPROM (5)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_CODE_MASTERS (6)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SSF2 (7)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_GAME_KANDUME (8)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_BEGGAR (9)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM (10)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_NBA_JAM_TE (11)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_NFL_QB_96 (12)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_C_SLAM (13)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_EA_NHLPA (14)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_LIONK3 (15)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SDK99 (16)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SKINGKONG (17)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_REDCL_EN (18)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_RADICA (19)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_KOF98 (20)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_KOF99 (21)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SOULBLAD (22)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_MJLOVER (23)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SQUIRRELK (24)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SMOUSE (25)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SMB (26)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SMB2 (27)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_KAIJU (28)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_CHINFIGHT3 (29)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_LIONK2 (30)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_BUGSLIFE (31)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_ELFWOR (32)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_ROCKMANX3 (33)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_SBUBBOB (34)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_REALTEC (35)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP19IN1 (36)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_MC_SUP15IN1 (37)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_12IN1 (38)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_TOPFIGHTER (39)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_POKEMON (40)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_PCB_MULAN (41)
|
||||
|
||||
#define HARDWARE_SEGA_MEGADRIVE_SRAM_00400 (0x0100)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_SRAM_00800 (0x0200)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_SRAM_01000 (0x0400)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_SRAM_04000 (0x0800)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_SRAM_10000 (0x1000)
|
||||
#define HARDWARE_SEGA_MEGADRIVE_FRAM_00400 (0x2000)
|
||||
|
||||
|
||||
#define HARDWARE_PSIKYO (HARDWARE_PREFIX_PSIKYO)
|
||||
|
||||
#define HARDWARE_KANEKO16 (HARDWARE_PREFIX_KANEKO16)
|
||||
|
||||
#define HARDWARE_PACMAN (HARDWARE_PREFIX_PACMAN)
|
||||
|
||||
#define HARDWARE_GALAXIAN (HARDWARE_PREFIX_GALAXIAN)
|
||||
|
||||
// flags for the genre member
|
||||
#define GBF_HORSHOOT (1 << 0)
|
||||
#define GBF_VERSHOOT (1 << 1)
|
||||
#define GBF_SCRFIGHT (1 << 2)
|
||||
#define GBF_VSFIGHT (1 << 3)
|
||||
#define GBF_BIOS (1 << 4)
|
||||
#define GBF_BREAKOUT (1 << 5)
|
||||
#define GBF_CASINO (1 << 6)
|
||||
#define GBF_BALLPADDLE (1 << 7)
|
||||
#define GBF_MAZE (1 << 8)
|
||||
#define GBF_MINIGAMES (1 << 9)
|
||||
#define GBF_PINBALL (1 << 10)
|
||||
#define GBF_PLATFORM (1 << 11)
|
||||
#define GBF_PUZZLE (1 << 12)
|
||||
#define GBF_QUIZ (1 << 13)
|
||||
#define GBF_SPORTSMISC (1 << 14)
|
||||
#define GBF_SPORTSFOOTBALL (1 << 15)
|
||||
#define GBF_MISC (1 << 16)
|
||||
#define GBF_MAHJONG (1 << 17)
|
||||
#define GBF_RACING (1 << 18)
|
||||
#define GBF_SHOOT (1 << 19)
|
||||
|
||||
// flags for the family member
|
||||
#define FBF_MSLUG (1 << 0)
|
||||
#define FBF_SF (1 << 1)
|
||||
#define FBF_KOF (1 << 2)
|
||||
#define FBF_DSTLK (1 << 3)
|
||||
#define FBF_FATFURY (1 << 4)
|
||||
#define FBF_SAMSHO (1 << 5)
|
||||
#define FBF_19XX (1 << 6)
|
||||
#define FBF_SONICWI (1 << 7)
|
||||
#define FBF_PWRINST (1 << 8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // End of extern "C"
|
||||
#endif
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
#include "burnint.h"
|
||||
#include "burn_gun.h"
|
||||
|
||||
// Generic Light Gun support for FBA
|
||||
// written by Barry Harris (Treble Winner) based on the code in Kev's opwolf driver
|
||||
|
||||
INT32 nBurnGunNumPlayers = 0;
|
||||
static bool bBurnGunDrawTargets = true;
|
||||
|
||||
static INT32 nBurnGunMaxX = 0;
|
||||
static INT32 nBurnGunMaxY = 0;
|
||||
|
||||
INT32 BurnGunX[MAX_GUNS];
|
||||
INT32 BurnGunY[MAX_GUNS];
|
||||
|
||||
#define P1Colour 0xfc, 0x12, 0xee
|
||||
#define P2Colour 0x1c, 0xfc, 0x1c
|
||||
#define P3Colour 0x15, 0x93, 0xfd
|
||||
#define P4Colour 0xf7, 0xfa, 0x0e
|
||||
|
||||
#define a 0,
|
||||
#define b 1,
|
||||
|
||||
UINT8 BurnGunTargetData[18][18] = {
|
||||
{ a a a a a a a a b a a a a a a a a a },
|
||||
{ a a a a a a b b b b b a a a a a a a },
|
||||
{ a a a a b b a a b a a b b a a a a a },
|
||||
{ a a a b a a a a b a a a a b a a a a },
|
||||
{ a a b a a a a a b a a a a a b a a a },
|
||||
{ a a b a a a a b b b a a a a b a a a },
|
||||
{ a b a a a a b b b b b a a a a b a a },
|
||||
{ a b a a a b b a a a a b a a a b a a },
|
||||
{ b b b b b b b a a a b b b b b b b a },
|
||||
{ a b a a a b b a a a a b b a a b a a },
|
||||
{ a b a a a a b a b a b b a a a b a a },
|
||||
{ a a b a a a a b b b b a a a b a a a },
|
||||
{ a a b a a a a a b b a a a a b a a a },
|
||||
{ a a a b a a a a b a a a a b a a a a },
|
||||
{ a a a a b b a a b a a b b a a a a a },
|
||||
{ a a a a a a b b b b b a a a a a a a },
|
||||
{ a a a a a a a a b a a a a a a a a a },
|
||||
{ a a a a a a a a a a a a a a a a a a },
|
||||
};
|
||||
#undef b
|
||||
#undef a
|
||||
|
||||
UINT8 BurnGunReturnX(INT32 num)
|
||||
{
|
||||
if (num > MAX_GUNS - 1) return 0xff;
|
||||
|
||||
float temp = (float)((BurnGunX[num] >> 8) + 8) / nBurnGunMaxX * 0xff;
|
||||
return (UINT8)temp;
|
||||
}
|
||||
|
||||
UINT8 BurnGunReturnY(INT32 num)
|
||||
{
|
||||
if (num > MAX_GUNS - 1) return 0xff;
|
||||
|
||||
float temp = (float)((BurnGunY[num] >> 8) + 8) / nBurnGunMaxY * 0xff;
|
||||
return (UINT8)temp;
|
||||
}
|
||||
|
||||
void BurnGunMakeInputs(INT32 num, INT16 x, INT16 y)
|
||||
{
|
||||
if (num > MAX_GUNS - 1) return;
|
||||
|
||||
const INT32 MinX = -8 * 0x100;
|
||||
const INT32 MinY = -8 * 0x100;
|
||||
|
||||
BurnGunX[num] += x;
|
||||
BurnGunY[num] += y;
|
||||
|
||||
if (BurnGunX[num] < MinX) BurnGunX[num] = MinX;
|
||||
if (BurnGunX[num] > MinX + nBurnGunMaxX * 0x100) BurnGunX[num] = MinX + nBurnGunMaxX * 0x100;
|
||||
if (BurnGunY[num] < MinY) BurnGunY[num] = MinY;
|
||||
if (BurnGunY[num] > MinY + nBurnGunMaxY * 0x100) BurnGunY[num] = MinY + nBurnGunMaxY * 0x100;
|
||||
}
|
||||
|
||||
void BurnGunInit(INT32 nNumPlayers, bool bDrawTargets)
|
||||
{
|
||||
if (nNumPlayers > MAX_GUNS) nNumPlayers = MAX_GUNS;
|
||||
nBurnGunNumPlayers = nNumPlayers;
|
||||
bBurnGunDrawTargets = bDrawTargets;
|
||||
|
||||
if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
|
||||
BurnDrvGetVisibleSize(&nBurnGunMaxY, &nBurnGunMaxX);
|
||||
} else {
|
||||
BurnDrvGetVisibleSize(&nBurnGunMaxX, &nBurnGunMaxY);
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < MAX_GUNS; i++) {
|
||||
BurnGunX[i] = ((nBurnGunMaxX / 2) - 7) << 8;
|
||||
BurnGunY[i] = ((nBurnGunMaxY / 2) - 8) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
void BurnGunExit()
|
||||
{
|
||||
nBurnGunNumPlayers = 0;
|
||||
bBurnGunDrawTargets = true;
|
||||
|
||||
nBurnGunMaxX = 0;
|
||||
nBurnGunMaxY = 0;
|
||||
|
||||
for (INT32 i = 0; i < MAX_GUNS; i++) {
|
||||
BurnGunX[i] = 0;
|
||||
BurnGunY[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BurnGunScan()
|
||||
{
|
||||
SCAN_VAR(BurnGunX);
|
||||
SCAN_VAR(BurnGunY);
|
||||
}
|
||||
|
||||
void BurnGunDrawTarget(INT32 num, INT32 x, INT32 y)
|
||||
{
|
||||
if (bBurnGunDrawTargets == false) return;
|
||||
|
||||
if (num > MAX_GUNS - 1) return;
|
||||
|
||||
UINT8* pTile = pBurnDraw + nBurnGunMaxX * nBurnBpp * (y - 1) + nBurnBpp * x;
|
||||
|
||||
UINT32 nTargetCol = 0;
|
||||
if (num == 0) nTargetCol = BurnHighCol(P1Colour, 0);
|
||||
if (num == 1) nTargetCol = BurnHighCol(P2Colour, 0);
|
||||
if (num == 2) nTargetCol = BurnHighCol(P3Colour, 0);
|
||||
if (num == 3) nTargetCol = BurnHighCol(P4Colour, 0);
|
||||
|
||||
for (INT32 y2 = 0; y2 < 17; y2++) {
|
||||
|
||||
pTile += nBurnGunMaxX * nBurnBpp;
|
||||
|
||||
if ((y + y2) < 0 || (y + y2) > nBurnGunMaxY - 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (INT32 x2 = 0; x2 < 17; x2++) {
|
||||
|
||||
if ((x + x2) < 0 || (x + x2) > nBurnGunMaxX - 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BurnGunTargetData[y2][x2]) {
|
||||
if (nBurnBpp == 2) {
|
||||
((UINT16*)pTile)[x2] = (UINT16)nTargetCol;
|
||||
} else {
|
||||
((UINT32*)pTile)[x2] = nTargetCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef P1Colour
|
||||
#undef P2Colour
|
||||
#undef P3Colour
|
||||
#undef P4Colour
|
|
@ -0,0 +1,15 @@
|
|||
#define MAX_GUNS 4
|
||||
|
||||
extern INT32 nBurnGunNumPlayers;
|
||||
|
||||
extern INT32 BurnGunX[MAX_GUNS];
|
||||
extern INT32 BurnGunY[MAX_GUNS];
|
||||
|
||||
UINT8 BurnGunReturnX(INT32 num);
|
||||
UINT8 BurnGunReturnY(INT32 num);
|
||||
|
||||
extern void BurnGunInit(INT32 nNumPlayers, bool bDrawTargets);
|
||||
void BurnGunExit();
|
||||
void BurnGunScan();
|
||||
extern void BurnGunDrawTarget(INT32 num, INT32 x, INT32 y);
|
||||
extern void BurnGunMakeInputs(INT32 num, INT16 x, INT16 y);
|
|
@ -0,0 +1,235 @@
|
|||
#include "burnint.h"
|
||||
#include "burn_led.h"
|
||||
|
||||
#define MAX_LED 8
|
||||
|
||||
static INT32 led_status[MAX_LED];
|
||||
|
||||
static INT32 led_count;
|
||||
static INT32 led_alpha_level;
|
||||
static INT32 led_alpha_level2;
|
||||
static INT32 led_color;
|
||||
static INT32 led_size;
|
||||
static INT32 led_position0;
|
||||
static INT32 led_position;
|
||||
static INT32 led_xpos;
|
||||
static INT32 led_ypos;
|
||||
static INT32 led_xadv;
|
||||
static INT32 led_yadv;
|
||||
|
||||
static INT32 nScreenWidth, nScreenHeight;
|
||||
static INT32 screen_flipped;
|
||||
static INT32 flipscreen = -1;
|
||||
|
||||
static inline UINT32 alpha_blend32(UINT32 d)
|
||||
{
|
||||
return (((((led_color & 0xff00ff) * led_alpha_level) + ((d & 0xff00ff) * led_alpha_level2)) & 0xff00ff00) |
|
||||
((((led_color & 0x00ff00) * led_alpha_level) + ((d & 0x00ff00) * led_alpha_level2)) & 0x00ff0000)) >> 8;
|
||||
}
|
||||
|
||||
static void set_led_draw_position()
|
||||
{
|
||||
led_position = led_position0;
|
||||
|
||||
if (screen_flipped ^ flipscreen) {
|
||||
switch (led_position & 3) {
|
||||
case LED_POSITION_TOP_LEFT: led_position = LED_POSITION_BOTTOM_RIGHT; break;
|
||||
case LED_POSITION_TOP_RIGHT: led_position = LED_POSITION_BOTTOM_LEFT; break;
|
||||
case LED_POSITION_BOTTOM_LEFT: led_position = LED_POSITION_TOP_RIGHT; break;
|
||||
case LED_POSITION_BOTTOM_RIGHT: led_position = LED_POSITION_TOP_LEFT; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
|
||||
BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth);
|
||||
|
||||
led_xadv = 0;
|
||||
led_yadv = led_size + 1;
|
||||
|
||||
switch (led_position & 3)
|
||||
{
|
||||
case LED_POSITION_TOP_LEFT:
|
||||
led_xpos = (nScreenWidth - 1) - led_size;
|
||||
led_ypos = 1;
|
||||
break;
|
||||
|
||||
case LED_POSITION_BOTTOM_RIGHT:
|
||||
led_xpos = 1;
|
||||
led_ypos = (nScreenHeight - 1) - (led_yadv * led_count);
|
||||
break;
|
||||
|
||||
case LED_POSITION_BOTTOM_LEFT:
|
||||
led_xpos = 1;
|
||||
led_ypos = 1;
|
||||
break;
|
||||
|
||||
case LED_POSITION_TOP_RIGHT:
|
||||
default:
|
||||
led_xpos = (nScreenWidth - 1) - led_size;
|
||||
led_ypos = (nScreenHeight - 1) - (led_yadv * led_count);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight);
|
||||
|
||||
led_xadv = led_size + 1;
|
||||
led_yadv = 0;
|
||||
|
||||
switch (led_position & 3)
|
||||
{
|
||||
case LED_POSITION_BOTTOM_LEFT:
|
||||
led_xpos = 1;
|
||||
led_ypos = (nScreenHeight - 1) - led_size;
|
||||
// led_ypos;
|
||||
break;
|
||||
|
||||
case LED_POSITION_TOP_RIGHT:
|
||||
led_xpos = (nScreenWidth - 1) - (led_xadv * led_count);
|
||||
led_ypos = 1;
|
||||
break;
|
||||
|
||||
case LED_POSITION_TOP_LEFT:
|
||||
led_xpos = 1;
|
||||
led_ypos = 1;
|
||||
break;
|
||||
|
||||
case LED_POSITION_BOTTOM_RIGHT:
|
||||
default:
|
||||
led_xpos = (nScreenWidth - 1) - (led_xadv * led_count);
|
||||
led_ypos = (nScreenHeight - 1) - led_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BurnLEDSetFlipscreen(INT32 flip)
|
||||
{
|
||||
flip = flip ? 1 : 0;
|
||||
|
||||
if (flipscreen != flip) {
|
||||
flipscreen = flip;
|
||||
set_led_draw_position();
|
||||
}
|
||||
}
|
||||
|
||||
void BurnLEDReset()
|
||||
{
|
||||
memset (led_status, 0, MAX_LED * sizeof(INT32));
|
||||
|
||||
BurnLEDSetFlipscreen(0);
|
||||
}
|
||||
|
||||
void BurnLEDInit(INT32 num, INT32 position, INT32 size, INT32 color, INT32 transparency)
|
||||
{
|
||||
if (num >= MAX_LED) num = MAX_LED - 1;
|
||||
|
||||
led_count = num;
|
||||
led_color = color;
|
||||
led_size = size;
|
||||
led_position0 = position;
|
||||
|
||||
led_alpha_level = (255 * transparency) / 100;
|
||||
led_alpha_level2 = 256 - led_alpha_level;
|
||||
|
||||
screen_flipped = (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) ? 1 : 0;
|
||||
|
||||
BurnLEDReset();
|
||||
}
|
||||
|
||||
void BurnLEDSetStatus(INT32 led, UINT32 status)
|
||||
{
|
||||
if (led >= led_count) return;
|
||||
|
||||
if (screen_flipped ^ flipscreen) {
|
||||
led = (led_count - 1) - led;
|
||||
}
|
||||
|
||||
led_status[led] = status ? 1 : 0;
|
||||
}
|
||||
|
||||
void BurnLEDExit()
|
||||
{
|
||||
BurnLEDReset();
|
||||
|
||||
led_count = 0;
|
||||
|
||||
led_alpha_level = 0;
|
||||
led_alpha_level2 = 0;
|
||||
led_color = 0;
|
||||
led_size = 0;
|
||||
led_position = 0;
|
||||
led_position0 = 0;
|
||||
|
||||
led_xpos = 0;
|
||||
led_ypos = 0;
|
||||
|
||||
screen_flipped = 0;
|
||||
nScreenWidth = 0;
|
||||
nScreenHeight = 0;
|
||||
|
||||
flipscreen = -1;
|
||||
}
|
||||
|
||||
void BurnLEDRender()
|
||||
{
|
||||
INT32 xpos = led_xpos;
|
||||
INT32 ypos = led_ypos;
|
||||
int color = BurnHighCol((led_color >> 16) & 0xff, (led_color >> 8) & 0xff, (led_color >> 0) & 0xff, 0);
|
||||
|
||||
for (INT32 i = 0; i < led_count; i++)
|
||||
{
|
||||
if (xpos < 0 || xpos > (nScreenWidth - led_size)) break;
|
||||
|
||||
if (led_status[i])
|
||||
{
|
||||
for (INT32 y = 0; y < led_size; y++)
|
||||
{
|
||||
UINT8 *ptr = pBurnDraw + (((ypos + y) * nScreenWidth) + xpos) * nBurnBpp;
|
||||
|
||||
for (INT32 x = 0; x < led_size; x++)
|
||||
{
|
||||
if (nBurnBpp >= 4)
|
||||
{
|
||||
*((UINT32*)ptr) = alpha_blend32(*((UINT32*)ptr));
|
||||
}
|
||||
else if (nBurnBpp == 3)
|
||||
{
|
||||
UINT32 t = alpha_blend32((ptr[2] << 16) | (ptr[1] << 8) | ptr[0]);
|
||||
|
||||
ptr[2] = t >> 16;
|
||||
ptr[1] = t >> 8;
|
||||
ptr[0] = t >> 0;
|
||||
}
|
||||
else if (nBurnBpp == 2) // alpha blend not supported for 16-bit
|
||||
{
|
||||
*((UINT16*)ptr) = color;
|
||||
}
|
||||
|
||||
ptr += nBurnBpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xpos += led_xadv;
|
||||
ypos += led_yadv;
|
||||
}
|
||||
}
|
||||
|
||||
INT32 BurnLEDScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin != NULL) {
|
||||
*pnMin = 0x029707;
|
||||
}
|
||||
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
ba.Data = &led_status;
|
||||
ba.nLen = led_count * sizeof(INT32);
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "Led status";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
#define LED_COLOR_RED 0xff0000
|
||||
#define LED_COLOR_GREEN 0x00ff00
|
||||
#define LED_COLOR_BLUE 0x0000ff
|
||||
#define LED_COLOR_WHITE 0xffffff
|
||||
#define LED_COLOR_YELLOW 0xffff00
|
||||
|
||||
#define LED_SIZE_2x2 2
|
||||
#define LED_SIZE_3x3 3
|
||||
#define LED_SIZE_4x4 4
|
||||
#define LED_SIZE_5x5 5
|
||||
#define LED_SIZE_6x6 6
|
||||
#define LED_SIZE_7x7 7
|
||||
#define LED_SIZE_8x8 8
|
||||
|
||||
#define LED_POSITION_TOP_LEFT 0
|
||||
#define LED_POSITION_TOP_RIGHT 1
|
||||
#define LED_POSITION_BOTTOM_LEFT 2
|
||||
#define LED_POSITION_BOTTOM_RIGHT 3
|
||||
|
||||
// transparency is a percentage 0 - 100
|
||||
void BurnLEDInit(INT32 num, INT32 position, INT32 size, INT32 color, INT32 transparency);
|
||||
|
||||
void BurnLEDReset();
|
||||
void BurnLEDSetStatus(INT32 led, UINT32 status);
|
||||
void BurnLEDSetFlipscreen(INT32 flip);
|
||||
void BurnLEDRender();
|
||||
void BurnLEDExit();
|
||||
|
||||
INT32 BurnLEDScan(INT32 nAction, INT32 *pnMin);
|
|
@ -0,0 +1,74 @@
|
|||
// FB Alpha memory management module
|
||||
|
||||
// The purpose of this module is to offer replacement functions for standard C/C++ ones
|
||||
// that allocate and free memory. This should help deal with the problem of memory
|
||||
// leaks and non-null pointers on game exit.
|
||||
|
||||
#include "burnint.h"
|
||||
|
||||
#define MAX_MEM_PTR 0x400 // more than 1024 malloc calls should be insane...
|
||||
|
||||
static UINT8 *memptr[MAX_MEM_PTR]; // pointer to allocated memory
|
||||
|
||||
// this should be called early on... BurnDrvInit?
|
||||
|
||||
void BurnInitMemoryManager()
|
||||
{
|
||||
memset (memptr, 0, MAX_MEM_PTR * sizeof(UINT8 **));
|
||||
}
|
||||
|
||||
// should we pass the pointer as a variable here so that we can save a pointer to it
|
||||
// and then ensure it is NULL'd in BurnFree or BurnExitMemoryManager?
|
||||
|
||||
// call instead of 'malloc'
|
||||
UINT8 *BurnMalloc(INT32 size)
|
||||
{
|
||||
for (INT32 i = 0; i < MAX_MEM_PTR; i++)
|
||||
{
|
||||
if (memptr[i] == NULL) {
|
||||
memptr[i] = (UINT8*)malloc(size);
|
||||
|
||||
if (memptr[i] == NULL) {
|
||||
bprintf (0, _T("BurnMalloc failed to allocate %d bytes of memory!\n"), size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (memptr[i], 0, size); // set contents to 0
|
||||
|
||||
return memptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
bprintf (0, _T("BurnMalloc called too many times!\n"));
|
||||
|
||||
return NULL; // Freak out!
|
||||
}
|
||||
|
||||
// call instead of "free"
|
||||
void _BurnFree(void *ptr)
|
||||
{
|
||||
UINT8 *mptr = (UINT8*)ptr;
|
||||
|
||||
for (INT32 i = 0; i < MAX_MEM_PTR; i++)
|
||||
{
|
||||
if (memptr[i] == mptr) {
|
||||
free (memptr[i]);
|
||||
memptr[i] = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// call in BurnDrvExit?
|
||||
|
||||
void BurnExitMemoryManager()
|
||||
{
|
||||
for (INT32 i = 0; i < MAX_MEM_PTR; i++)
|
||||
{
|
||||
if (memptr[i] != NULL) {
|
||||
free (memptr[i]);
|
||||
memptr[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#include "burnint.h"
|
||||
#include "burn_sound.h"
|
||||
|
||||
INT16 Precalc[4096 *4];
|
||||
|
||||
// Routine used to precalculate the table used for interpolation
|
||||
INT32 cmc_4p_Precalc()
|
||||
{
|
||||
INT32 a, x, x2, x3;
|
||||
|
||||
for (a = 0; a < 4096; a++) {
|
||||
x = a * 4; // x = 0..16384
|
||||
x2 = x * x / 16384; // pow(x, 2);
|
||||
x3 = x2 * x / 16384; // pow(x, 3);
|
||||
|
||||
Precalc[a * 4 + 0] = (INT16)(-x / 3 + x2 / 2 - x3 / 6);
|
||||
Precalc[a * 4 + 1] = (INT16)(-x / 2 - x2 + x3 / 2 + 16384);
|
||||
Precalc[a * 4 + 2] = (INT16)( x + x2 / 2 - x3 / 2);
|
||||
Precalc[a * 4 + 3] = (INT16)(-x / 6 + x3 / 6);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// burn_sound.h - General sound support functions
|
||||
// based on code by Daniel Moreno (ComaC) < comac2k@teleline.es >
|
||||
|
||||
#if defined BUILD_X86_ASM
|
||||
extern "C" {
|
||||
int __cdecl ChannelMix_QS_A(int* Dest, int nLen,
|
||||
char* Sample, int LoopEnd,
|
||||
int* Pos,
|
||||
int VolL, int VolR,
|
||||
int LoopLen,
|
||||
int IncPos,
|
||||
char* EndBuff);
|
||||
|
||||
void __cdecl BurnSoundCopyClamp_A(int* Src, short* Dest, int Len);
|
||||
void __cdecl BurnSoundCopyClamp_Add_A(int* Src, short* Dest, int Len);
|
||||
|
||||
void __cdecl BurnSoundCopyClamp_Mono_A(int* Src, short* Dest, int Len);
|
||||
void __cdecl BurnSoundCopyClamp_Mono_Add_A(int* Src, short* Dest, int Len);
|
||||
|
||||
void __cdecl BurnSoundCopy_FM_A(short* SrcL, short* SrcR, short* Dest, int Len, int VolL, int VolR);
|
||||
void __cdecl BurnSoundCopy_FM_Add_A(short* SrcL, short* SrcR, short* Dest, int Len, int VolL, int VolR);
|
||||
|
||||
/* SrcOPN should have left channel data at SrcOPN, right channel at SrcOPN + 4096, SrcPSG should have all summed channels */
|
||||
void __cdecl BurnSoundCopy_FM_OPN_A(short* SrcOPN, int* SrcPSG, short* Dest, int Len, int VolPSGL, int VolPSGR);
|
||||
void __cdecl BurnSoundCopy_FM_OPN_Add_A(short* SrcOPN, int* SrcPSG, short* Dest, int Len, int VolPSGL, int VolPSGR);
|
||||
}
|
||||
#endif
|
||||
|
||||
void BurnSoundCopyClamp_C(INT32* Src, INT16* Dest, INT32 Len);
|
||||
void BurnSoundCopyClamp_Add_C(INT32* Src, INT16* Dest, INT32 Len);
|
||||
void BurnSoundCopyClamp_Mono_C(INT32* Src, INT16* Dest, INT32 Len);
|
||||
void BurnSoundCopyClamp_Mono_Add_C(INT32* Src, INT16* Dest, INT32 Len);
|
||||
|
||||
extern INT32 cmc_4p_Precalc();
|
||||
|
||||
#ifdef __ELF__
|
||||
#define Precalc _Precalc
|
||||
#endif
|
||||
|
||||
extern "C" INT16 Precalc[];
|
||||
|
||||
#define INTERPOLATE4PS_8BIT(fp, sN, s0, s1, s2) (((INT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (INT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (INT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (INT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 64)
|
||||
#define INTERPOLATE4PS_16BIT(fp, sN, s0, s1, s2) (((INT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (INT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (INT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (INT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 16384)
|
||||
#define INTERPOLATE4PS_CUSTOM(fp, sN, s0, s1, s2, v) (((INT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (INT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (INT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (INT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / (INT32)(v))
|
||||
|
||||
#define INTERPOLATE4PU_8BIT(fp, sN, s0, s1, s2) (((UINT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (UINT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (UINT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (UINT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 64)
|
||||
#define INTERPOLATE4PU_16BIT(fp, sN, s0, s1, s2) (((UINT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (UINT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (UINT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (UINT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / 16384)
|
||||
#define INTERPOLATE4PU_CUSTOM(fp, sN, s0, s1, s2, v) (((UINT32)((sN) * Precalc[(INT32)(fp) * 4 + 0]) + (UINT32)((s0) * Precalc[(INT32)(fp) * 4 + 1]) + (UINT32)((s1) * Precalc[(INT32)(fp) * 4 + 2]) + (UINT32)((s2) * Precalc[(INT32)(fp) * 4 + 3])) / (UINT32)(v))
|
|
@ -0,0 +1,751 @@
|
|||
; MMX general sound support + PCM channel mixing
|
||||
; based on code by Daniel Moreno (ComaC) - 2001 < comac2k@teleline.es >
|
||||
|
||||
; ChannelMix_QS mixes one channel using 4 point, 3rd order interpolation.
|
||||
; The volume of the resulting audio is 64 times louder, to have extra precision
|
||||
; when mixing the channels.
|
||||
;
|
||||
; The BurnSoundCopy* functions convert a 32-bit (interleaved stereo or mono) buffer
|
||||
; to interleaved 16-bit stereo, clamping and dividing volume by 256 on the fly.
|
||||
;
|
||||
; BurnSoundCopy_FM interleaves 2 16-bit buffers into a single interleaved stereo buffer,
|
||||
; correcting volume (variable) on the fly
|
||||
;
|
||||
; BurnSoundCopy_FM interleaves 2 16-bit buffers into a single interleaved stereo buffer,
|
||||
; adding a 3rd 32-bit buffer correcting volume on the 3rd buffer (variable) on the fly
|
||||
|
||||
[BITS 32]
|
||||
|
||||
global ChannelMix_QS_A
|
||||
global _ChannelMix_QS_A
|
||||
|
||||
global ChannelMix_8U_A
|
||||
global _ChannelMix_8U_A
|
||||
|
||||
global BurnSoundCopyClamp_A
|
||||
global _BurnSoundCopyClamp_A
|
||||
global BurnSoundCopyClamp_Add_A
|
||||
global _BurnSoundCopyClamp_Add_A
|
||||
|
||||
global _BurnSoundCopyClamp_Mono_A
|
||||
global BurnSoundCopyClamp_Mono_A
|
||||
global _BurnSoundCopyClamp_Mono_Add_A
|
||||
global BurnSoundCopyClamp_Mono_Add_A
|
||||
|
||||
global BurnSoundCopy_FM_A
|
||||
global _BurnSoundCopy_FM_A
|
||||
global BurnSoundCopy_FM_Add_A
|
||||
global _BurnSoundCopy_FM_Add_A
|
||||
|
||||
global _BurnSoundCopy_FM_OPN_A
|
||||
global BurnSoundCopy_FM_OPN_A
|
||||
global _BurnSoundCopy_FM_OPN_Add_A
|
||||
global BurnSoundCopy_FM_OPN_Add_A
|
||||
|
||||
extern _Precalc
|
||||
|
||||
|
||||
|
||||
section .text
|
||||
|
||||
; This macro is used from other functions. It contains the main mixing
|
||||
; loop for 8 bit samples. At its input it expects:
|
||||
;
|
||||
; EAX -> pointer to sample buffer
|
||||
; EBX -> index inside sample (current position)
|
||||
; ECX -> index of the first sample that does NOT have to play (LoopEnd)
|
||||
; ESI -> pointer to destination buffer
|
||||
; mm3 -> Volumes Low = Left, High = Right
|
||||
;
|
||||
; Param 1 -> dword containing position increment
|
||||
; Param 2 -> dword containing loop length
|
||||
; Param 3 -> dword containing size of out buffer in samples
|
||||
; Param 4 -> pointer to enf buffer
|
||||
; Param 5 -> instructions to do to unpacked samples, or text NONE if none
|
||||
;
|
||||
; At exit:
|
||||
;
|
||||
; EBX -> next position to play
|
||||
; EDX -> destroyed
|
||||
; [Param 2] -> updated acordingly
|
||||
; [Param 4] -> zero
|
||||
; mm0 -> destroyed
|
||||
; mm1 -> destroyed
|
||||
|
||||
%macro Mix_Loop 5
|
||||
|
||||
%define INCR %1
|
||||
%define LOOP %2
|
||||
%define BUFLEN %3
|
||||
%define ENDBUF %4
|
||||
|
||||
cmp EBX, ECX ; Past the end?
|
||||
jl %%Sigue ; No? -> Continue
|
||||
|
||||
%%PassedEnd:
|
||||
mov EDX, ECX ; We are at or near the end of the sample
|
||||
add EDX, 0x3000 ; We need to either stop, set the pointer
|
||||
and EDX, (0xFFFF << 12) ; to the loop point, or render a few samples
|
||||
cmp EBX, EDX ; from the end buffer
|
||||
jge %%LoopCheck ;
|
||||
|
||||
; We need to render samples from the end buffer
|
||||
|
||||
push EBX ; We need to copy EBX to EDX (!!!)
|
||||
pxor mm0, mm0 ; Zero mm0 (to do zero extension of sample)
|
||||
|
||||
add EBX, 0x4000 ; load end buffer in EDX, index in EBX
|
||||
sub EBX, EDX ;
|
||||
mov EDX, ENDBUF ;
|
||||
shr EBX, 12 ;
|
||||
|
||||
punpcklbw mm0, [EDX + EBX] ; Load & unpack samples (from the end buffer) to 16 bit
|
||||
|
||||
pop EDX ; !!!
|
||||
jmp %%Interpolate
|
||||
|
||||
%%LoopCheck:
|
||||
cmp LOOP, 0x1000 ; > 0x1000
|
||||
jg %%SetLoopPoint ; Yes -> Loop Sample
|
||||
cmp LOOP, 0
|
||||
je %%EndSample
|
||||
|
||||
mov EBX, ECX ; Kludge to work around some situations
|
||||
add EBX, 0x2000 ; where the QSound hardware is left in
|
||||
jmp %%End_StayOn ; a non-standard state (e.g. DDTOD, DDSOM)
|
||||
|
||||
%%EndSample:
|
||||
xor EBX, EBX
|
||||
xor EAX, EAX ; set bKey to zero
|
||||
jmp %%End ; exit function
|
||||
|
||||
%%SetLoopPoint:
|
||||
sub EBX, LOOP ; Set EBX to the loop point
|
||||
|
||||
%%NextSample:
|
||||
cmp EBX, ECX ; Passed the end?
|
||||
jge %%PassedEnd
|
||||
|
||||
%%Sigue:
|
||||
mov EDX, EBX
|
||||
and EBX, (0xFFFF << 12) ; QSound banks are 0x10000 bytes
|
||||
shr EBX, 12 ; EBX = Integer(nPos)
|
||||
|
||||
pxor mm0, mm0 ; Zero mm0 (to do zero extension of sample)
|
||||
punpcklbw mm0, [EAX + EBX] ; Load & unpack samples to 16 bit
|
||||
|
||||
%%Interpolate:
|
||||
mov EBX, EDX
|
||||
and EDX, 0x0FFF ; EDX = Decimal(nPos)
|
||||
|
||||
; Execute sign adaptation instructions if necessary:
|
||||
|
||||
%ifnidni %5, NONE
|
||||
pxor mm0, %5
|
||||
%endif
|
||||
|
||||
; Interpolate sample
|
||||
|
||||
pmaddwd mm0, [_Precalc + EDX*8] ; Get multipliers
|
||||
movq mm1, mm0 ; We need High(mm0) + Low(mm0)
|
||||
psrlq mm0, 32 ; mm0 = High(mm0)
|
||||
paddd mm0, mm1 ; mm0 = Sample interpolated * 16384
|
||||
psrad mm0, 16 ; Shift samples right
|
||||
packssdw mm0, mm0 ; Hi(mm0) = sample, Low(mm0) = sample
|
||||
|
||||
add EBX, INCR ; Advance counters
|
||||
pmaddwd mm0, mm3 ; Multiply samples with volume
|
||||
dec BUFLEN ; 1 sample less left
|
||||
|
||||
paddd mm0, [ESI] ; Add to buffer
|
||||
movq [ESI], mm0 ; Store result on buffer
|
||||
|
||||
lea ESI, [ESI + 8]
|
||||
jnz %%NextSample ; Continue if there are more samples
|
||||
|
||||
%%End_StayOn:
|
||||
mov EAX, 1 ; leave bKey at 1
|
||||
%%End:
|
||||
|
||||
%endmacro
|
||||
|
||||
; Parameters to ChannelMix_QS/8U:
|
||||
|
||||
%define BuffDest dword [EBP + 8]
|
||||
%define BuffLen dword [EBP + 12]
|
||||
%define SampleBuff dword [EBP + 16]
|
||||
%define LoopEnd dword [EBP + 20]
|
||||
%define PosPtr dword [EBP + 24]
|
||||
%define Volumes qword [EBP + 28]
|
||||
%define LoopLen dword [EBP + 36]
|
||||
%define IncrPos dword [EBP + 40]
|
||||
%define EndBuff dword [EBP + 44]
|
||||
|
||||
_ChannelMix_QS_A:
|
||||
ChannelMix_QS_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
|
||||
push EBX
|
||||
push ESI
|
||||
push EDI
|
||||
|
||||
mov EAX, SampleBuff ; EAX = Sample Buffer
|
||||
mov EBX, PosPtr
|
||||
|
||||
movq mm3, Volumes ; mm3 = Volumes
|
||||
|
||||
mov EBX, [EBX] ; EBX = Sample Position
|
||||
mov ECX, LoopEnd ; ECX = LoopEnd
|
||||
sub ECX, 0x3000
|
||||
mov ESI, BuffDest ; ESI = destionation buffer
|
||||
mov EDI, IncrPos ; EDI = IncrPos
|
||||
|
||||
Mix_Loop EDI, LoopLen, BuffLen, EndBuff, NONE
|
||||
|
||||
mov ECX, PosPtr
|
||||
pop EDI
|
||||
pop ESI
|
||||
mov [ECX], EBX ; Save position
|
||||
|
||||
; emms
|
||||
pop EBX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
|
||||
_ChannelMix_8U_A:
|
||||
ChannelMix_8U_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
|
||||
push EBX
|
||||
push ESI
|
||||
push EDI
|
||||
|
||||
mov EAX, SampleBuff ; EAX = Sample Buffer
|
||||
mov EBX, PosPtr
|
||||
|
||||
movq mm3, Volumes ; mm3 = Volumes
|
||||
movq mm4, [XorSign] ; mm4 = Value to xor to adapt sign
|
||||
|
||||
dec EAX
|
||||
mov EBX, [EBX] ; EBX = Sample Position
|
||||
mov ECX, LoopEnd ; ECX = LoopEnd
|
||||
mov ESI, BuffDest ; ESI = destionation buffer
|
||||
mov EDI, IncrPos ; EDI = IncrPos
|
||||
|
||||
Mix_Loop EDI, LoopLen, BuffLen, EndBuff, mm4
|
||||
|
||||
mov ECX, PosPtr
|
||||
pop EDI
|
||||
pop ESI
|
||||
mov [ECX], EBX ; Save position
|
||||
|
||||
; emms
|
||||
pop EBX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
|
||||
; Parameters to BurnSoundCopyClamp* functions
|
||||
|
||||
%define BufSrc [EBP + 8]
|
||||
%define BufDest [EBP + 12]
|
||||
%define Len [EBP + 16]
|
||||
|
||||
_BurnSoundCopyClamp_A:
|
||||
BurnSoundCopyClamp_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
|
||||
mov ECX, BufSrc ; ECX = Buff Src
|
||||
mov EDX, BufDest ; EDX = Buff Dest
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movq mm0, [ECX] ; Hi(mm0) = SampleR*256, Low(mm0) = SampleL*256
|
||||
movq mm1, [ECX + 8] ; Load next sample too
|
||||
psrad mm0, 8 ; Hi(mm0) = Sample1R, Low(mm0) = Sample1L
|
||||
psrad mm1, 8 ; Hi(mm1) = Sample2R, Low(mm1) = Sample2L
|
||||
add ECX, byte 16 ; ECX -> next samples
|
||||
|
||||
packssdw mm0, mm1 ; We have both samples packed here
|
||||
dec EAX ; 2 samples less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next sample
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of sample pairs.
|
||||
; Handle the last sample pair here
|
||||
|
||||
movq mm0, [ECX]
|
||||
psrad mm0, 8
|
||||
packssdw mm0, mm0
|
||||
movd [EDX], mm0
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
_BurnSoundCopyClamp_Add_A:
|
||||
BurnSoundCopyClamp_Add_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
|
||||
mov ECX, BufSrc ; ECX = Buff Src
|
||||
mov EDX, BufDest ; EDX = Buff Dest
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movq mm0, [ECX] ; Hi(mm0) = SampleR*256, Low(mm0) = SampleL*256
|
||||
movq mm1, [ECX + 8] ; Load next sample too
|
||||
psrad mm0, 8 ; Hi(mm0) = Sample1R, Low(mm0) = Sample1L
|
||||
psrad mm1, 8 ; Hi(mm1) = Sample2R, Low(mm1) = Sample2L
|
||||
add ECX, byte 16 ; ECX -> next samples
|
||||
|
||||
packssdw mm0, mm1 ; Here we have the 2 samples packed
|
||||
|
||||
paddsw mm0, [EDX] ; Add to the contents of the buffer
|
||||
dec EAX ; 2 samples less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next 2 samples
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of sample pairs.
|
||||
; Handle the last sample pair here
|
||||
|
||||
movq mm0, [ECX]
|
||||
psrad mm0, 8
|
||||
packssdw mm0, mm0
|
||||
movd mm1, [EDX]
|
||||
paddsw mm0, mm1
|
||||
movd [EDX], mm0
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
_BurnSoundCopyClamp_Mono_A:
|
||||
BurnSoundCopyClamp_Mono_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
|
||||
mov ECX, BufSrc ; ECX = Buff Src
|
||||
mov EDX, BufDest ; EDX = Buff Dest
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movq mm0, [ECX] ; Hi(mm0) = Sample2*256, Low(mm0) = Sample1*256
|
||||
psrad mm0, 8 ; Hi(mm0) = Sample2, Low(mm0) = Sample1
|
||||
add ECX, byte 8 ; ECX -> next samples
|
||||
packssdw mm0, mm0 ; We have both samples packed here
|
||||
punpcklwd mm0, mm0
|
||||
|
||||
dec EAX ; 2 samples less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next sample
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of samples.
|
||||
; Handle the last sample here
|
||||
|
||||
movd mm0, [ECX]
|
||||
psrad mm0, 8
|
||||
packssdw mm0, mm0
|
||||
punpcklwd mm0, mm0
|
||||
movd [EDX], mm0
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
_BurnSoundCopyClamp_Mono_Add_A:
|
||||
BurnSoundCopyClamp_Mono_Add_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
|
||||
mov ECX, BufSrc ; ECX = Buff Src
|
||||
mov EDX, BufDest ; EDX = Buff Dest
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movq mm0, [ECX] ; Hi(mm0) = Sample2*256, Low(mm0) = Sample1*256
|
||||
psrad mm0, 8 ; Hi(mm0) = Sample2, Low(mm0) = Sample1
|
||||
add ECX, byte 8 ; ECX -> next samples
|
||||
packssdw mm0, mm0 ; We have both samples packed here
|
||||
punpcklwd mm0, mm0
|
||||
|
||||
paddsw mm0, [EDX] ; Add to the contents of the buffer
|
||||
dec EAX ; 2 samples less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next 2 samples
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of samples.
|
||||
; Handle the last sample here
|
||||
|
||||
movd mm0, [ECX]
|
||||
psrad mm0, 8
|
||||
packssdw mm0, mm0
|
||||
punpcklwd mm0, mm0
|
||||
movd mm1, [EDX]
|
||||
paddsw mm0, mm1
|
||||
movd [EDX], mm0
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
; Parameters to BurnSoundCopy_FM
|
||||
|
||||
%define BufSrcL dword [EBP + 8]
|
||||
%define BufSrcR dword [EBP + 12]
|
||||
%define BufDest dword [EBP + 16]
|
||||
%define Len dword [EBP + 20]
|
||||
%define Volumes qword [EBP + 24]
|
||||
|
||||
_BurnSoundCopy_FM_A:
|
||||
BurnSoundCopy_FM_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
push EBX
|
||||
|
||||
movq mm1, Volumes
|
||||
packssdw mm1, Volumes
|
||||
|
||||
; mm1 now holds the volumes as packed words
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
|
||||
mov EDX, BufDest ; EDX = BufDest
|
||||
mov ECX, BufSrcR ; ECX = BufSrcR
|
||||
mov EBX, BufSrcL ; EBX = BufSrcL
|
||||
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movd mm0, [EBX]
|
||||
punpcklwd mm0, [ECX]
|
||||
|
||||
; mm0 now has SrcR2 - SrcL2 - SrcR1 - SrcL1
|
||||
|
||||
pmulhw mm0, mm1 ; Multiply mm0 with volumes
|
||||
|
||||
add EBX, byte 4 ; EBX -> next samples
|
||||
add ECX, byte 4 ; ECX -> next samples
|
||||
|
||||
dec EAX ; 2 sample less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next sample
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of sample pairs.
|
||||
; Handle the last sample pair here
|
||||
|
||||
movd mm0, [EBX]
|
||||
punpcklwd mm0, [ECX]
|
||||
|
||||
; mm0 now has ? - ? - SrcR1 - SrcL1
|
||||
|
||||
pmulhw mm0, mm1 ; Multiply mm0 with volumes
|
||||
|
||||
movd [EDX], mm0 ; Save the result
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
_BurnSoundCopy_FM_Add_A:
|
||||
BurnSoundCopy_FM_Add_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
push EBX
|
||||
|
||||
movq mm1, Volumes
|
||||
packssdw mm1, Volumes
|
||||
|
||||
; mm1 now holds the volumes as packed words
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
|
||||
mov EDX, BufDest ; EDX = BufDest
|
||||
mov ECX, BufSrcR ; ECX = BufSrcR
|
||||
mov EBX, BufSrcL ; EBX = BufSrcL
|
||||
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movd mm0, [EBX]
|
||||
punpcklwd mm0, [ECX]
|
||||
|
||||
; mm0 now has SrcR2 - SrcL2 - SrcR1 - SrcL1
|
||||
|
||||
pmulhw mm0, mm1 ; Multiply mm0 with volumes
|
||||
|
||||
add EBX, byte 4 ; EBX -> next samples
|
||||
add ECX, byte 4 ; ECX -> next samples
|
||||
|
||||
paddsw mm0, [EDX] ; Add to the contents of the buffer
|
||||
dec EAX ; 2 sample less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next sample
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of sample pairs.
|
||||
; Handle the last sample pair here
|
||||
|
||||
movd mm0, [EBX]
|
||||
punpcklwd mm0, [ECX]
|
||||
|
||||
; mm0 now has ? - ? - SrcR1 - SrcL1
|
||||
|
||||
pmulhw mm0, mm1 ; Multiply mm0 with volumes
|
||||
|
||||
movd mm1, [EDX]
|
||||
paddsw mm0, mm1 ; Add to the contents of the buffer
|
||||
movd [EDX], mm0 ; Save the result
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
; Parameters to BurnSoundCopyFM_OPN_A
|
||||
|
||||
%define BufSrcOPN dword [EBP + 8]
|
||||
%define BufSrcPSG dword [EBP + 12]
|
||||
%define BufDest dword [EBP + 16]
|
||||
%define Len dword [EBP + 20]
|
||||
%define Volumes qword [EBP + 24]
|
||||
|
||||
_BurnSoundCopy_FM_OPN_A:
|
||||
BurnSoundCopy_FM_OPN_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
push EBX
|
||||
|
||||
movq mm4, Volumes
|
||||
packssdw mm4, Volumes
|
||||
|
||||
mov EBX, BufSrcOPN ; EBX = Buff Src (OPN)
|
||||
mov ECX, BufSrcPSG ; ECX = Buff Src (PSG)
|
||||
mov EDX, BufDest ; EDX = Buff Dest
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movq mm0, [ECX] ; Hi(mm0) = Sample2, Low(mm0) = Sample1
|
||||
add ECX, byte 8 ; ECX -> next samples
|
||||
|
||||
packssdw mm0, mm0
|
||||
|
||||
movd mm1, [EBX] ; OPN sample left
|
||||
|
||||
punpcklwd mm0, mm0
|
||||
|
||||
; mm0 now has SrcPSGR2 - SrcPSGL2 - SrcPSGR1 - SrcPSGL1
|
||||
|
||||
punpcklwd mm1, [EBX + 8192] ; OPN sample right
|
||||
|
||||
; mm1 now has SrcOPNR2 - SrcOPNL2 - SrcOPNR1 - SrcOPNL1
|
||||
|
||||
pmulhw mm0, mm4 ; Multiply mm0 with volumes
|
||||
|
||||
add EBX, byte 4 ; EBX -> next samples
|
||||
|
||||
paddsw mm0, mm1
|
||||
|
||||
dec EAX ; 2 samples less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next sample
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of samples.
|
||||
; Handle the last sample here
|
||||
|
||||
movd mm0, [ECX]
|
||||
packssdw mm0, mm0
|
||||
movd mm1, [EBX]
|
||||
punpcklwd mm0, mm0
|
||||
punpcklwd mm1, [EBX + 8192]
|
||||
pmulhw mm0, mm4
|
||||
paddsw mm0, mm1
|
||||
|
||||
movd [EDX], mm0
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
_BurnSoundCopy_FM_OPN_Add_A:
|
||||
BurnSoundCopy_FM_OPN_Add_A:
|
||||
|
||||
push EBP
|
||||
mov EBP, ESP
|
||||
push EBX
|
||||
|
||||
movq mm4, Volumes
|
||||
packssdw mm4, Volumes
|
||||
|
||||
mov EBX, BufSrcOPN ; EBX = Buff Src (OPN)
|
||||
mov ECX, BufSrcPSG ; ECX = Buff Src (PSG)
|
||||
mov EDX, BufDest ; EDX = Buff Dest
|
||||
|
||||
mov EAX, Len ; EAX = Length
|
||||
shr EAX, 1
|
||||
je .LastSample
|
||||
|
||||
.Loop:
|
||||
movq mm0, [ECX] ; Hi(mm0) = Sample2, Low(mm0) = Sample1
|
||||
add ECX, byte 8 ; ECX -> next samples
|
||||
|
||||
packssdw mm0, mm0
|
||||
|
||||
movd mm1, [EBX] ; OPN sample left
|
||||
|
||||
punpcklwd mm0, mm0
|
||||
|
||||
; mm0 now has SrcPSGR2 - SrcPSGL2 - SrcPSGR1 - SrcPSGL1
|
||||
|
||||
punpcklwd mm1, [EBX + 8192] ; OPN sample right
|
||||
|
||||
; mm1 now has SrcOPNR2 - SrcOPNL2 - SrcOPNR1 - SrcOPNL1
|
||||
|
||||
pmulhw mm0, mm4 ; Multiply mm0 with volumes
|
||||
|
||||
add EBX, byte 4 ; EBX -> next samples
|
||||
|
||||
paddsw mm0, mm1
|
||||
|
||||
paddsw mm0, [EDX] ; Add to the contents of the buffer
|
||||
|
||||
dec EAX ; 2 samples less left
|
||||
|
||||
movq [EDX], mm0 ; Save the result
|
||||
|
||||
lea EDX, [EDX + 8] ; EDX -> next sample
|
||||
jnz .Loop ; Continue if there are more samples
|
||||
|
||||
.LastSample:
|
||||
mov EAX, Len ; EAX = Length
|
||||
test EAX, 1
|
||||
je .End
|
||||
|
||||
; We need to handle an odd amount of samples.
|
||||
; Handle the last sample here
|
||||
|
||||
movd mm0, [ECX]
|
||||
packssdw mm0, mm0
|
||||
movd mm1, [EBX]
|
||||
punpcklwd mm0, mm0
|
||||
punpcklwd mm1, [EBX + 8192]
|
||||
pmulhw mm0, mm4
|
||||
paddsw mm0, mm1
|
||||
|
||||
movd mm1, [EDX]
|
||||
paddsw mm0, mm1 ; Add to the contents of the buffer
|
||||
|
||||
movd [EDX], mm0
|
||||
|
||||
.End:
|
||||
emms ; Done with MMX
|
||||
pop EBX
|
||||
pop EBP
|
||||
ret
|
||||
|
||||
|
||||
section .data
|
||||
|
||||
; Used to xor with the unpacked samples to change sign:
|
||||
XorSign: dw 0x8000, 0x8000, 0x8000, 0x8000
|
||||
|
||||
|
||||
|
||||
section .bss
|
||||
|
||||
VolMMX: resd 2
|
||||
ActiveFlag: resb 1
|
|
@ -0,0 +1,46 @@
|
|||
#include "burnint.h"
|
||||
#include "burn_sound.h"
|
||||
|
||||
#define CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A))
|
||||
|
||||
void BurnSoundCopyClamp_C(INT32 *Src, INT16 *Dest, INT32 Len)
|
||||
{
|
||||
Len *= 2;
|
||||
while (Len--) {
|
||||
*Dest = CLIP((*Src >> 8));
|
||||
Src++;
|
||||
Dest++;
|
||||
}
|
||||
}
|
||||
|
||||
void BurnSoundCopyClamp_Add_C(INT32 *Src, INT16 *Dest, INT32 Len)
|
||||
{
|
||||
Len *= 2;
|
||||
while (Len--) {
|
||||
*Dest = CLIP((*Src >> 8) + *Dest);
|
||||
Src++;
|
||||
Dest++;
|
||||
}
|
||||
}
|
||||
|
||||
void BurnSoundCopyClamp_Mono_C(INT32 *Src, INT16 *Dest, INT32 Len)
|
||||
{
|
||||
while (Len--) {
|
||||
Dest[0] = CLIP((*Src >> 8));
|
||||
Dest[1] = CLIP((*Src >> 8));
|
||||
Src++;
|
||||
Dest += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void BurnSoundCopyClamp_Mono_Add_C(INT32 *Src, INT16 *Dest, INT32 Len)
|
||||
{
|
||||
while (Len--) {
|
||||
Dest[0] = CLIP((*Src >> 8) + Dest[0]);
|
||||
Dest[1] = CLIP((*Src >> 8) + Dest[1]);
|
||||
Src++;
|
||||
Dest += 2;
|
||||
}
|
||||
}
|
||||
|
||||
#undef CLIP
|
|
@ -0,0 +1,121 @@
|
|||
// Burn - Arcade emulator library - internal code
|
||||
|
||||
// Standard headers
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tchar.h"
|
||||
#include "burn.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CPU emulation interfaces
|
||||
|
||||
// sek.cpp
|
||||
#include "sek.h"
|
||||
|
||||
// zet.cpp
|
||||
#include "zet.h"
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct { UINT8 l,h,h2,h3; } b;
|
||||
struct { UINT16 l,h; } w;
|
||||
UINT32 d;
|
||||
} PAIR;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Driver information
|
||||
|
||||
struct BurnDriver {
|
||||
char* szShortName; // The filename of the zip file (without extension)
|
||||
char* szParent; // The filename of the parent (without extension, NULL if not applicable)
|
||||
char* szBoardROM; // The filename of the board ROMs (without extension, NULL if not applicable)
|
||||
char* szSampleName; // The filename of the samples zip file (without extension, NULL if not applicable)
|
||||
char* szDate;
|
||||
|
||||
// szFullNameA, szCommentA, szManufacturerA and szSystemA should always contain valid info
|
||||
// szFullNameW, szCommentW, szManufacturerW and szSystemW should be used only if characters or scripts are needed that ASCII can't handle
|
||||
char* szFullNameA; char* szCommentA; char* szManufacturerA; char* szSystemA;
|
||||
wchar_t* szFullNameW; wchar_t* szCommentW; wchar_t* szManufacturerW; wchar_t* szSystemW;
|
||||
|
||||
INT32 Flags; // See burn.h
|
||||
INT32 Players; // Max number of players a game supports (so we can remove single player games from netplay)
|
||||
INT32 Hardware; // Which type of hardware the game runs on
|
||||
INT32 Genre;
|
||||
INT32 Family;
|
||||
INT32 (*GetZipName)(char** pszName, UINT32 i); // Function to get possible zip names
|
||||
INT32 (*GetRomInfo)(struct BurnRomInfo* pri, UINT32 i); // Function to get the length and crc of each rom
|
||||
INT32 (*GetRomName)(char** pszName, UINT32 i, INT32 nAka); // Function to get the possible names for each rom
|
||||
INT32 (*GetSampleInfo)(struct BurnSampleInfo* pri, UINT32 i); // Function to get the sample flags
|
||||
INT32 (*GetSampleName)(char** pszName, UINT32 i, INT32 nAka); // Function to get the possible names for each sample
|
||||
INT32 (*GetInputInfo)(struct BurnInputInfo* pii, UINT32 i); // Function to get the input info for the game
|
||||
INT32 (*GetDIPInfo)(struct BurnDIPInfo* pdi, UINT32 i); // Function to get the input info for the game
|
||||
INT32 (*Init)(); INT32 (*Exit)(); INT32 (*Frame)(); INT32 (*Redraw)(); INT32 (*AreaScan)(INT32 nAction, INT32* pnMin);
|
||||
UINT8* pRecalcPal; UINT32 nPaletteEntries; // Set to 1 if the palette needs to be fully re-calculated
|
||||
INT32 nWidth, nHeight; INT32 nXAspect, nYAspect; // Screen width, height, x/y aspect
|
||||
};
|
||||
|
||||
#define BurnDriverD BurnDriver // Debug status
|
||||
#define BurnDriverX BurnDriver // Exclude from build
|
||||
|
||||
// Standard functions for dealing with ROM and input info structures
|
||||
#include "stdfunc.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// burn.cpp
|
||||
INT32 BurnSetRefreshRate(double dRefreshRate);
|
||||
INT32 BurnByteswap(UINT8* pm,INT32 nLen);
|
||||
INT32 BurnClearScreen();
|
||||
|
||||
// load.cpp
|
||||
INT32 BurnLoadRom(UINT8* Dest, INT32 i, INT32 nGap);
|
||||
INT32 BurnXorRom(UINT8* Dest, INT32 i, INT32 nGap);
|
||||
INT32 BurnLoadBitField(UINT8* pDest, UINT8* pSrc, INT32 nField, INT32 nSrcLen);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Colour-depth independant image transfer
|
||||
|
||||
extern UINT16* pTransDraw;
|
||||
|
||||
void BurnTransferClear();
|
||||
INT32 BurnTransferCopy(UINT32* pPalette);
|
||||
void BurnTransferExit();
|
||||
INT32 BurnTransferInit();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Plotting pixels
|
||||
|
||||
inline static void PutPix(UINT8* pPix, UINT32 c)
|
||||
{
|
||||
if (nBurnBpp >= 4) {
|
||||
*((UINT32*)pPix) = c;
|
||||
} else {
|
||||
if (nBurnBpp == 2) {
|
||||
*((UINT16*)pPix) = (UINT16)c;
|
||||
} else {
|
||||
pPix[0] = (UINT8)(c >> 0);
|
||||
pPix[1] = (UINT8)(c >> 8);
|
||||
pPix[2] = (UINT8)(c >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Setting up cpus for cheats
|
||||
|
||||
void CpuCheatRegister(INT32 type, INT32 num);
|
||||
|
||||
// burn_memory.cpp
|
||||
void BurnInitMemoryManager();
|
||||
UINT8 *BurnMalloc(INT32 size);
|
||||
void _BurnFree(void *ptr);
|
||||
#define BurnFree(x) _BurnFree(x); x = NULL;
|
||||
void BurnExitMemoryManager();
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sound clipping macro
|
||||
#define BURN_SND_CLIP(A) ((A) < -0x8000 ? -0x8000 : (A) > 0x7fff ? 0x7fff : (A))
|
|
@ -0,0 +1,664 @@
|
|||
// Cheat module
|
||||
|
||||
#include "burnint.h"
|
||||
#include "vez.h"
|
||||
#include "sh2.h"
|
||||
#include "m6502_intf.h"
|
||||
#include "m6809_intf.h"
|
||||
#include "hd6309_intf.h"
|
||||
#include "m6800_intf.h"
|
||||
#include "s2650_intf.h"
|
||||
#include "konami_intf.h"
|
||||
#include "arm7_intf.h"
|
||||
|
||||
bool bCheatsAllowed;
|
||||
CheatInfo* pCheatInfo = NULL;
|
||||
|
||||
static bool bCheatsEnabled = false;
|
||||
|
||||
//----------------------------------------------------
|
||||
// Cpu interface for cheat application
|
||||
|
||||
#define MAX_CHEAT_CPU 8 // enough?
|
||||
|
||||
static INT32 nActiveCheatCpus;
|
||||
|
||||
struct cheat_subs {
|
||||
INT32 nCpu; // Which cpu is this? (SekOpen(#), ZetOpen(#))
|
||||
void (*cpu_open)(INT32);
|
||||
void (*write)(UINT32, UINT8);
|
||||
UINT8 (*read)(UINT32);
|
||||
void (*cpu_close)();
|
||||
INT32 (*active_cpu)();
|
||||
UINT32 nMemorySize;
|
||||
};
|
||||
|
||||
struct cheat_subs cheat_sub_block[MAX_CHEAT_CPU];
|
||||
struct cheat_subs *cheat_subptr;
|
||||
|
||||
//---------------------------------------------------
|
||||
// Dummy handlers
|
||||
|
||||
static INT32 CheatDummyGetActive() { return -1; }
|
||||
static void CheatDummyOpen(INT32) {}
|
||||
static void CheatDummyClose() {}
|
||||
static void CheatDummyWriteByte(UINT32, UINT8) {}
|
||||
static UINT8 CheatDummyReadByte(UINT32) { return 0; }
|
||||
|
||||
// -----------------------------------------------
|
||||
// Set up handlers for cpu cores that aren't totally compatible
|
||||
|
||||
#define CHEAT_READ(name,funct) \
|
||||
static UINT8 name##ReadByteCheat(UINT32 a) { \
|
||||
return funct; \
|
||||
}
|
||||
|
||||
#define CHEAT_WRITE(name,funct) \
|
||||
static void name##WriteByteCheat(UINT32 a, UINT8 d) { \
|
||||
funct; \
|
||||
}
|
||||
|
||||
CHEAT_READ(Sek, SekReadByte(a))
|
||||
CHEAT_READ(Sh2, Sh2ReadByte(a))
|
||||
CHEAT_WRITE(Sh2, Sh2WriteByte(a,d))
|
||||
CHEAT_READ(Zet, ZetReadByte(a))
|
||||
CHEAT_WRITE(Zet, ZetWriteRom(a,d))
|
||||
CHEAT_READ(M6800, M6800ReadByte(a))
|
||||
CHEAT_WRITE(M6800, M6800WriteRom(a,d))
|
||||
CHEAT_READ(M6809, M6809ReadByte(a))
|
||||
CHEAT_WRITE(M6809, M6809WriteRom(a,d))
|
||||
CHEAT_READ(HD6309, HD6309ReadByte(a))
|
||||
CHEAT_WRITE(HD6309, HD6309WriteRom(a,d))
|
||||
CHEAT_READ(m6502, M6502ReadByte(a))
|
||||
CHEAT_WRITE(m6502, M6502WriteRom(a,d))
|
||||
CHEAT_READ(s2650, s2650_read(a))
|
||||
CHEAT_WRITE(s2650, s2650_write_rom(a,d))
|
||||
CHEAT_READ(konami, konami_read(a))
|
||||
CHEAT_WRITE(konami, konami_write_rom(a,d))
|
||||
|
||||
//------------------------------------------------
|
||||
// Central cpu registry for functions necessary for cheats
|
||||
|
||||
void CpuCheatRegister(INT32 type, INT32 nNum)
|
||||
{
|
||||
cheat_subptr = &cheat_sub_block[nActiveCheatCpus];
|
||||
nActiveCheatCpus++;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0x0000: // m68k
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = SekOpen;
|
||||
cheat_subptr->cpu_close = SekClose;
|
||||
cheat_subptr->active_cpu = SekGetActive;
|
||||
cheat_subptr->write = SekWriteByteROM;
|
||||
cheat_subptr->read = SekReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x01000000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0001: // NEC V30 / V33
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = VezOpen;
|
||||
cheat_subptr->cpu_close = VezClose;
|
||||
cheat_subptr->active_cpu = VezGetActive;
|
||||
cheat_subptr->write = cpu_writemem20;
|
||||
cheat_subptr->read = cpu_readmem20;
|
||||
cheat_subptr->nMemorySize = 0x00100000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0002: // SH2
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = Sh2Open;
|
||||
cheat_subptr->cpu_close = Sh2Close;
|
||||
cheat_subptr->active_cpu = Sh2GetActive;
|
||||
cheat_subptr->write = Sh2WriteByteCheat;
|
||||
cheat_subptr->read = Sh2ReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x02080000; // Good enough for CPS3
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0003: // M6502
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = M6502Open;
|
||||
cheat_subptr->cpu_close = M6502Close;
|
||||
cheat_subptr->active_cpu = M6502GetActive;
|
||||
cheat_subptr->write = m6502WriteByteCheat;
|
||||
cheat_subptr->read = m6502ReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0004: // Z80
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = ZetOpen;
|
||||
cheat_subptr->cpu_close = ZetClose;
|
||||
cheat_subptr->active_cpu = ZetGetActive;
|
||||
cheat_subptr->write = ZetWriteByteCheat;
|
||||
cheat_subptr->read = ZetReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0005: // M6809
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = M6809Open;
|
||||
cheat_subptr->cpu_close = M6809Close;
|
||||
cheat_subptr->active_cpu = M6809GetActive;
|
||||
cheat_subptr->write = M6809WriteByteCheat;
|
||||
cheat_subptr->read = M6809ReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0006: // HD6309
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = HD6309Open;
|
||||
cheat_subptr->cpu_close = HD6309Close;
|
||||
cheat_subptr->active_cpu = HD6309GetActive;
|
||||
cheat_subptr->write = HD6309WriteByteCheat;
|
||||
cheat_subptr->read = HD6309ReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0007: // M6800
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = CheatDummyOpen;
|
||||
cheat_subptr->cpu_close = CheatDummyClose;
|
||||
cheat_subptr->active_cpu = CheatDummyGetActive;
|
||||
cheat_subptr->write = M6800WriteByteCheat;
|
||||
cheat_subptr->read = M6800ReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0008: // S2650
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = s2650Open;
|
||||
cheat_subptr->cpu_close = s2650Close;
|
||||
cheat_subptr->active_cpu = s2650GetActive;
|
||||
cheat_subptr->write = s2650WriteByteCheat;
|
||||
cheat_subptr->read = s2650ReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0009: // Konami Custom
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = konamiOpen;
|
||||
cheat_subptr->cpu_close = konamiClose;
|
||||
cheat_subptr->active_cpu = konamiGetActive;
|
||||
cheat_subptr->write = konamiWriteByteCheat;
|
||||
cheat_subptr->read = konamiReadByteCheat;
|
||||
cheat_subptr->nMemorySize = 0x00010000;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x000a: // ARM7
|
||||
{
|
||||
cheat_subptr->nCpu = nNum;
|
||||
cheat_subptr->cpu_open = Arm7Open;
|
||||
cheat_subptr->cpu_close = Arm7Close;
|
||||
cheat_subptr->active_cpu = CheatDummyGetActive;
|
||||
cheat_subptr->write = Arm7_write_rom_byte;
|
||||
cheat_subptr->read = Arm7_program_read_byte_32le;
|
||||
cheat_subptr->nMemorySize = 0x80000000; // enough for PGM...
|
||||
}
|
||||
break;
|
||||
|
||||
// Just in case the called cpu isn't supported and so MinGW
|
||||
// doesn't complain about unused functions...
|
||||
default:
|
||||
{
|
||||
cheat_subptr->nCpu = 0;
|
||||
cheat_subptr->cpu_open = CheatDummyOpen;
|
||||
cheat_subptr->cpu_close = CheatDummyClose;
|
||||
cheat_subptr->active_cpu = CheatDummyGetActive;
|
||||
cheat_subptr->write = CheatDummyWriteByte;
|
||||
cheat_subptr->read = CheatDummyReadByte;
|
||||
cheat_subptr->nMemorySize = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INT32 CheatUpdate()
|
||||
{
|
||||
bCheatsEnabled = false;
|
||||
|
||||
if (bCheatsAllowed) {
|
||||
CheatInfo* pCurrentCheat = pCheatInfo;
|
||||
CheatAddressInfo* pAddressInfo;
|
||||
|
||||
while (pCurrentCheat) {
|
||||
if (pCurrentCheat->nStatus > 1) {
|
||||
pAddressInfo = pCurrentCheat->pOption[pCurrentCheat->nCurrent]->AddressInfo;
|
||||
if (pAddressInfo->nAddress) {
|
||||
bCheatsEnabled = true;
|
||||
}
|
||||
}
|
||||
pCurrentCheat = pCurrentCheat->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CheatEnable(INT32 nCheat, INT32 nOption)
|
||||
{
|
||||
INT32 nCurrentCheat = 0;
|
||||
CheatInfo* pCurrentCheat = pCheatInfo;
|
||||
CheatAddressInfo* pAddressInfo;
|
||||
INT32 nOpenCPU = -1;
|
||||
|
||||
if (!bCheatsAllowed) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nOption >= CHEAT_MAX_OPTIONS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
cheat_subptr = &cheat_sub_block[0]; // first cpu...
|
||||
|
||||
while (pCurrentCheat && nCurrentCheat <= nCheat) {
|
||||
if (nCurrentCheat == nCheat) {
|
||||
|
||||
if (nOption == -1) {
|
||||
nOption = pCurrentCheat->nDefault;
|
||||
}
|
||||
|
||||
if (pCurrentCheat->nType != 1) {
|
||||
|
||||
// Return OK if the cheat is already active with the same option
|
||||
if (pCurrentCheat->nCurrent == nOption) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Deactivate old option (if any)
|
||||
pAddressInfo = pCurrentCheat->pOption[nOption]->AddressInfo;
|
||||
while (pAddressInfo->nAddress) {
|
||||
|
||||
if (pAddressInfo->nCPU != nOpenCPU) {
|
||||
|
||||
if (nOpenCPU != -1) {
|
||||
cheat_subptr->cpu_close();
|
||||
}
|
||||
|
||||
nOpenCPU = pAddressInfo->nCPU;
|
||||
cheat_subptr = &cheat_sub_block[nOpenCPU];
|
||||
cheat_subptr->cpu_open(cheat_subptr->nCpu);
|
||||
}
|
||||
|
||||
// Write back original values to memory
|
||||
cheat_subptr->write(pAddressInfo->nAddress, pAddressInfo->nOriginalValue);
|
||||
pAddressInfo++;
|
||||
}
|
||||
}
|
||||
|
||||
// Activate new option
|
||||
pAddressInfo = pCurrentCheat->pOption[nOption]->AddressInfo;
|
||||
while (pAddressInfo->nAddress) {
|
||||
|
||||
if (pAddressInfo->nCPU != nOpenCPU) {
|
||||
if (nOpenCPU != -1) {
|
||||
cheat_subptr->cpu_close();
|
||||
}
|
||||
|
||||
nOpenCPU = pAddressInfo->nCPU;
|
||||
cheat_subptr = &cheat_sub_block[nOpenCPU];
|
||||
cheat_subptr->cpu_open(cheat_subptr->nCpu);
|
||||
}
|
||||
|
||||
// Copy the original values
|
||||
pAddressInfo->nOriginalValue = cheat_subptr->read(pAddressInfo->nAddress);
|
||||
|
||||
if (pCurrentCheat->nType != 0) {
|
||||
if (pAddressInfo->nCPU != nOpenCPU) {
|
||||
if (nOpenCPU != -1) {
|
||||
cheat_subptr->cpu_close();
|
||||
}
|
||||
|
||||
nOpenCPU = pAddressInfo->nCPU;
|
||||
cheat_subptr = &cheat_sub_block[nOpenCPU];
|
||||
cheat_subptr->cpu_open(cheat_subptr->nCpu);
|
||||
}
|
||||
|
||||
// Activate the cheat
|
||||
cheat_subptr->write(pAddressInfo->nAddress, pAddressInfo->nValue);
|
||||
}
|
||||
|
||||
pAddressInfo++;
|
||||
}
|
||||
|
||||
// Set cheat status and active option
|
||||
if (pCurrentCheat->nType != 1) {
|
||||
pCurrentCheat->nCurrent = nOption;
|
||||
}
|
||||
if (pCurrentCheat->nType == 0) {
|
||||
pCurrentCheat->nStatus = 2;
|
||||
}
|
||||
if (pCurrentCheat->nType == 2) {
|
||||
pCurrentCheat->nStatus = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
pCurrentCheat = pCurrentCheat->pNext;
|
||||
nCurrentCheat++;
|
||||
}
|
||||
|
||||
if (nOpenCPU != -1) {
|
||||
cheat_subptr->cpu_close();
|
||||
}
|
||||
|
||||
CheatUpdate();
|
||||
|
||||
if (nCurrentCheat == nCheat && pCurrentCheat) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
INT32 CheatApply()
|
||||
{
|
||||
if (!bCheatsEnabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 nOpenCPU = -1;
|
||||
|
||||
CheatInfo* pCurrentCheat = pCheatInfo;
|
||||
CheatAddressInfo* pAddressInfo;
|
||||
while (pCurrentCheat) {
|
||||
if (pCurrentCheat->nStatus > 1) {
|
||||
pAddressInfo = pCurrentCheat->pOption[pCurrentCheat->nCurrent]->AddressInfo;
|
||||
while (pAddressInfo->nAddress) {
|
||||
|
||||
if (pAddressInfo->nCPU != nOpenCPU) {
|
||||
if (nOpenCPU != -1) {
|
||||
cheat_subptr->cpu_close();
|
||||
}
|
||||
|
||||
nOpenCPU = pAddressInfo->nCPU;
|
||||
cheat_subptr = &cheat_sub_block[nOpenCPU];
|
||||
cheat_subptr->cpu_open(cheat_subptr->nCpu);
|
||||
}
|
||||
|
||||
cheat_subptr->write(pAddressInfo->nAddress, pAddressInfo->nValue);
|
||||
pAddressInfo++;
|
||||
}
|
||||
}
|
||||
pCurrentCheat = pCurrentCheat->pNext;
|
||||
}
|
||||
|
||||
if (nOpenCPU != -1) {
|
||||
cheat_subptr->cpu_close();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CheatInit()
|
||||
{
|
||||
CheatExit();
|
||||
|
||||
bCheatsEnabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CheatExit()
|
||||
{
|
||||
if (pCheatInfo) {
|
||||
CheatInfo* pCurrentCheat = pCheatInfo;
|
||||
CheatInfo* pNextCheat;
|
||||
|
||||
do {
|
||||
pNextCheat = pCurrentCheat->pNext;
|
||||
for (INT32 i = 0; i < CHEAT_MAX_OPTIONS; i++) {
|
||||
if (pCurrentCheat->pOption[i]) {
|
||||
free(pCurrentCheat->pOption[i]);
|
||||
}
|
||||
}
|
||||
if (pCurrentCheat) {
|
||||
free(pCurrentCheat);
|
||||
}
|
||||
} while ((pCurrentCheat = pNextCheat) != 0);
|
||||
}
|
||||
|
||||
nActiveCheatCpus = 0;
|
||||
for (INT32 i = 0; i < MAX_CHEAT_CPU; i++) {
|
||||
CpuCheatRegister(-1, i); // set them all to dummy...
|
||||
}
|
||||
nActiveCheatCpus = 0;
|
||||
|
||||
pCheatInfo = NULL;
|
||||
}
|
||||
|
||||
// Cheat search
|
||||
|
||||
static UINT8 *MemoryValues = NULL;
|
||||
static UINT8 *MemoryStatus = NULL;
|
||||
static UINT32 nMemorySize = 0;
|
||||
|
||||
#define NOT_IN_RESULTS 0
|
||||
#define IN_RESULTS 1
|
||||
|
||||
UINT32 CheatSearchShowResultAddresses[CHEATSEARCH_SHOWRESULTS];
|
||||
UINT32 CheatSearchShowResultValues[CHEATSEARCH_SHOWRESULTS];
|
||||
|
||||
INT32 CheatSearchInit()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CheatSearchExit()
|
||||
{
|
||||
if (MemoryValues) {
|
||||
free(MemoryValues);
|
||||
MemoryValues = NULL;
|
||||
}
|
||||
if (MemoryStatus) {
|
||||
free(MemoryStatus);
|
||||
MemoryStatus = NULL;
|
||||
}
|
||||
|
||||
nMemorySize = 0;
|
||||
|
||||
memset(CheatSearchShowResultAddresses, 0, CHEATSEARCH_SHOWRESULTS);
|
||||
memset(CheatSearchShowResultValues, 0, CHEATSEARCH_SHOWRESULTS);
|
||||
}
|
||||
|
||||
void CheatSearchStart()
|
||||
{
|
||||
UINT32 nAddress;
|
||||
|
||||
INT32 nActiveCPU = 0;
|
||||
cheat_subptr = &cheat_sub_block[nActiveCPU]; // first cpu only (ok?)
|
||||
|
||||
nActiveCPU = cheat_subptr->active_cpu();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_close();
|
||||
cheat_subptr->cpu_open(cheat_subptr->nCpu);
|
||||
nMemorySize = cheat_subptr->nMemorySize;
|
||||
|
||||
MemoryValues = (UINT8*)malloc(nMemorySize);
|
||||
MemoryStatus = (UINT8*)malloc(nMemorySize);
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
MemoryValues[nAddress] = cheat_subptr->read(nAddress);
|
||||
}
|
||||
|
||||
cheat_subptr->cpu_close();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU);
|
||||
|
||||
memset(MemoryStatus, IN_RESULTS, nMemorySize);
|
||||
}
|
||||
|
||||
static void CheatSearchGetResults()
|
||||
{
|
||||
UINT32 nAddress;
|
||||
UINT32 nResultsPos = 0;
|
||||
|
||||
memset(CheatSearchShowResultAddresses, 0, CHEATSEARCH_SHOWRESULTS);
|
||||
memset(CheatSearchShowResultValues, 0, CHEATSEARCH_SHOWRESULTS);
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
if (MemoryStatus[nAddress] == IN_RESULTS) {
|
||||
CheatSearchShowResultAddresses[nResultsPos] = nAddress;
|
||||
CheatSearchShowResultValues[nResultsPos] = MemoryValues[nAddress];
|
||||
nResultsPos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 CheatSearchValueNoChange()
|
||||
{
|
||||
UINT32 nMatchedAddresses = 0;
|
||||
UINT32 nAddress;
|
||||
|
||||
INT32 nActiveCPU = 0;
|
||||
|
||||
nActiveCPU = cheat_subptr->active_cpu();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_close();
|
||||
cheat_subptr->cpu_open(0);
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue;
|
||||
if (cheat_subptr->read(nAddress) == MemoryValues[nAddress]) {
|
||||
MemoryValues[nAddress] = cheat_subptr->read(nAddress);
|
||||
nMatchedAddresses++;
|
||||
} else {
|
||||
MemoryStatus[nAddress] = NOT_IN_RESULTS;
|
||||
}
|
||||
}
|
||||
|
||||
cheat_subptr->cpu_close();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU);
|
||||
|
||||
if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults();
|
||||
|
||||
return nMatchedAddresses;
|
||||
}
|
||||
|
||||
UINT32 CheatSearchValueChange()
|
||||
{
|
||||
UINT32 nMatchedAddresses = 0;
|
||||
UINT32 nAddress;
|
||||
|
||||
INT32 nActiveCPU = 0;
|
||||
|
||||
nActiveCPU = cheat_subptr->active_cpu();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_close();
|
||||
cheat_subptr->cpu_open(0);
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue;
|
||||
if (cheat_subptr->read(nAddress) != MemoryValues[nAddress]) {
|
||||
MemoryValues[nAddress] = cheat_subptr->read(nAddress);
|
||||
nMatchedAddresses++;
|
||||
} else {
|
||||
MemoryStatus[nAddress] = NOT_IN_RESULTS;
|
||||
}
|
||||
}
|
||||
|
||||
cheat_subptr->cpu_close();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU);
|
||||
|
||||
if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults();
|
||||
|
||||
return nMatchedAddresses;
|
||||
}
|
||||
|
||||
UINT32 CheatSearchValueDecreased()
|
||||
{
|
||||
UINT32 nMatchedAddresses = 0;
|
||||
UINT32 nAddress;
|
||||
|
||||
INT32 nActiveCPU = 0;
|
||||
|
||||
nActiveCPU = cheat_subptr->active_cpu();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_close();
|
||||
cheat_subptr->cpu_open(0);
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue;
|
||||
if (cheat_subptr->read(nAddress) < MemoryValues[nAddress]) {
|
||||
MemoryValues[nAddress] = cheat_subptr->read(nAddress);
|
||||
nMatchedAddresses++;
|
||||
} else {
|
||||
MemoryStatus[nAddress] = NOT_IN_RESULTS;
|
||||
}
|
||||
}
|
||||
|
||||
cheat_subptr->cpu_close();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU);
|
||||
|
||||
if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults();
|
||||
|
||||
return nMatchedAddresses;
|
||||
}
|
||||
|
||||
UINT32 CheatSearchValueIncreased()
|
||||
{
|
||||
UINT32 nMatchedAddresses = 0;
|
||||
UINT32 nAddress;
|
||||
|
||||
INT32 nActiveCPU = 0;
|
||||
|
||||
nActiveCPU = cheat_subptr->active_cpu();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_close();
|
||||
cheat_subptr->cpu_open(0);
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
if (MemoryStatus[nAddress] == NOT_IN_RESULTS) continue;
|
||||
if (cheat_subptr->read(nAddress) > MemoryValues[nAddress]) {
|
||||
MemoryValues[nAddress] = cheat_subptr->read(nAddress);
|
||||
nMatchedAddresses++;
|
||||
} else {
|
||||
MemoryStatus[nAddress] = NOT_IN_RESULTS;
|
||||
}
|
||||
}
|
||||
|
||||
cheat_subptr->cpu_close();
|
||||
if (nActiveCPU >= 0) cheat_subptr->cpu_open(nActiveCPU);
|
||||
|
||||
if (nMatchedAddresses <= CHEATSEARCH_SHOWRESULTS) CheatSearchGetResults();
|
||||
|
||||
return nMatchedAddresses;
|
||||
}
|
||||
|
||||
void CheatSearchDumptoFile()
|
||||
{
|
||||
FILE *fp = fopen("cheatsearchdump.txt", "wt");
|
||||
UINT32 nAddress;
|
||||
|
||||
if (fp) {
|
||||
char Temp[256];
|
||||
|
||||
for (nAddress = 0; nAddress < nMemorySize; nAddress++) {
|
||||
if (MemoryStatus[nAddress] == IN_RESULTS) {
|
||||
sprintf(Temp, "Address %08X Value %02X\n", nAddress, MemoryValues[nAddress]);
|
||||
fwrite(Temp, 1, strlen(Temp), fp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
#undef NOT_IN_RESULTS
|
||||
#undef IN_RESULTS
|
|
@ -0,0 +1,49 @@
|
|||
#define CHEAT_MAX_ADDRESS ( 64)
|
||||
#define CHEAT_MAX_OPTIONS (192)
|
||||
#define CHEAT_MAX_NAME (128)
|
||||
|
||||
extern bool bCheatsAllowed;
|
||||
|
||||
struct CheatAddressInfo {
|
||||
INT32 nCPU;
|
||||
INT32 nAddress;
|
||||
UINT32 nValue;
|
||||
UINT32 nOriginalValue;
|
||||
};
|
||||
|
||||
struct CheatOption {
|
||||
TCHAR szOptionName[CHEAT_MAX_NAME];
|
||||
struct CheatAddressInfo AddressInfo[CHEAT_MAX_ADDRESS + 1];
|
||||
};
|
||||
|
||||
struct CheatInfo {
|
||||
struct CheatInfo* pNext;
|
||||
struct CheatInfo* pPrevious;
|
||||
INT32 nType; // Cheat type
|
||||
INT32 nStatus; // 0 = Inactive
|
||||
INT32 nCurrent; // Currently selected option
|
||||
INT32 nDefault; // Default option
|
||||
TCHAR szCheatName[CHEAT_MAX_NAME];
|
||||
struct CheatOption* pOption[CHEAT_MAX_OPTIONS];
|
||||
};
|
||||
|
||||
extern CheatInfo* pCheatInfo;
|
||||
|
||||
INT32 CheatUpdate();
|
||||
INT32 CheatEnable(INT32 nCheat, INT32 nOption);
|
||||
INT32 CheatApply();
|
||||
INT32 CheatInit();
|
||||
void CheatExit();
|
||||
|
||||
#define CHEATSEARCH_SHOWRESULTS 3
|
||||
extern UINT32 CheatSearchShowResultAddresses[CHEATSEARCH_SHOWRESULTS];
|
||||
extern UINT32 CheatSearchShowResultValues[CHEATSEARCH_SHOWRESULTS];
|
||||
|
||||
INT32 CheatSearchInit();
|
||||
void CheatSearchExit();
|
||||
void CheatSearchStart();
|
||||
UINT32 CheatSearchValueNoChange();
|
||||
UINT32 CheatSearchValueChange();
|
||||
UINT32 CheatSearchValueDecreased();
|
||||
UINT32 CheatSearchValueIncreased();
|
||||
void CheatSearchDumptoFile();
|
|
@ -0,0 +1,450 @@
|
|||
#include "burnint.h"
|
||||
#include "8255ppi.h"
|
||||
|
||||
#define MAX_PPIS 3
|
||||
|
||||
PPIPortRead PPI0PortReadA;
|
||||
PPIPortRead PPI0PortReadB;
|
||||
PPIPortRead PPI0PortReadC;
|
||||
PPIPortWrite PPI0PortWriteA;
|
||||
PPIPortWrite PPI0PortWriteB;
|
||||
PPIPortWrite PPI0PortWriteC;
|
||||
PPIPortRead PPI1PortReadA;
|
||||
PPIPortRead PPI1PortReadB;
|
||||
PPIPortRead PPI1PortReadC;
|
||||
PPIPortWrite PPI1PortWriteA;
|
||||
PPIPortWrite PPI1PortWriteB;
|
||||
PPIPortWrite PPI1PortWriteC;
|
||||
PPIPortRead PPI2PortReadA;
|
||||
PPIPortRead PPI2PortReadB;
|
||||
PPIPortRead PPI2PortReadC;
|
||||
PPIPortWrite PPI2PortWriteA;
|
||||
PPIPortWrite PPI2PortWriteB;
|
||||
PPIPortWrite PPI2PortWriteC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* mode flags */
|
||||
UINT8 groupA_mode;
|
||||
UINT8 groupB_mode;
|
||||
UINT8 portA_dir;
|
||||
UINT8 portB_dir;
|
||||
UINT8 portCH_dir;
|
||||
UINT8 portCL_dir;
|
||||
|
||||
/* handshake signals (1=asserted; 0=non-asserted) */
|
||||
UINT8 obf_a;
|
||||
UINT8 obf_b;
|
||||
UINT8 ibf_a;
|
||||
UINT8 ibf_b;
|
||||
UINT8 inte_a;
|
||||
UINT8 inte_b;
|
||||
|
||||
UINT8 in_mask[3]; /* input mask */
|
||||
UINT8 out_mask[3]; /* output mask */
|
||||
UINT8 read[3]; /* data read from ports */
|
||||
UINT8 latch[3]; /* data written to ports */
|
||||
UINT8 output[3]; /* actual output data */
|
||||
} ppi8255;
|
||||
|
||||
static ppi8255 chips[MAX_PPIS];
|
||||
|
||||
static void ppi8255_get_handshake_signals(ppi8255 *chip, UINT8 *result)
|
||||
{
|
||||
UINT8 handshake = 0x00;
|
||||
UINT8 mask = 0x00;
|
||||
|
||||
/* group A */
|
||||
if (chip->groupA_mode == 1)
|
||||
{
|
||||
if (chip->portA_dir)
|
||||
{
|
||||
handshake |= chip->ibf_a ? 0x20 : 0x00;
|
||||
handshake |= (chip->ibf_a && chip->inte_a) ? 0x08 : 0x00;
|
||||
mask |= 0x28;
|
||||
}
|
||||
else
|
||||
{
|
||||
handshake |= chip->obf_a ? 0x00 : 0x80;
|
||||
handshake |= (chip->obf_a && chip->inte_a) ? 0x08 : 0x00;
|
||||
mask |= 0x88;
|
||||
}
|
||||
}
|
||||
else if (chip->groupA_mode == 2)
|
||||
{
|
||||
handshake |= chip->inte_a ? 0x08 : 0x00;
|
||||
handshake |= chip->obf_a ? 0x00 : 0x80;
|
||||
handshake |= chip->ibf_a ? 0x20 : 0x00;
|
||||
mask |= 0xA8;
|
||||
}
|
||||
|
||||
/* group B */
|
||||
if (chip->groupB_mode == 1)
|
||||
{
|
||||
if (chip->portA_dir)
|
||||
{
|
||||
handshake |= chip->ibf_b ? 0x02 : 0x00;
|
||||
handshake |= (chip->ibf_b && chip->inte_b) ? 0x01 : 0x00;
|
||||
mask |= 0x03;
|
||||
}
|
||||
else
|
||||
{
|
||||
handshake |= chip->obf_b ? 0x00 : 0x02;
|
||||
handshake |= (chip->obf_b && chip->inte_b) ? 0x01 : 0x00;
|
||||
mask |= 0x03;
|
||||
}
|
||||
}
|
||||
|
||||
*result &= ~mask;
|
||||
*result |= handshake & mask;
|
||||
}
|
||||
|
||||
static void ppi8255_write_port(ppi8255 *chip, INT32 port, INT32 chipnum)
|
||||
{
|
||||
UINT8 write_data;
|
||||
|
||||
write_data = chip->latch[port] & chip->out_mask[port];
|
||||
write_data |= 0xFF & ~chip->out_mask[port];
|
||||
|
||||
/* write out special port 2 signals */
|
||||
if (port == 2)
|
||||
ppi8255_get_handshake_signals(chip, &write_data);
|
||||
|
||||
chip->output[port] = write_data;
|
||||
|
||||
if (chipnum == 0 && port == 0) {
|
||||
if (PPI0PortWriteA) PPI0PortWriteA(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 0 && port == 1) {
|
||||
if (PPI0PortWriteB) PPI0PortWriteB(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 0 && port == 2) {
|
||||
if (PPI0PortWriteC) PPI0PortWriteC(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 1 && port == 0) {
|
||||
if (PPI1PortWriteA) PPI1PortWriteA(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 1 && port == 1) {
|
||||
if (PPI1PortWriteB) PPI1PortWriteB(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 1 && port == 2) {
|
||||
if (PPI1PortWriteC) PPI1PortWriteC(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 2 && port == 0) {
|
||||
if (PPI2PortWriteA) PPI2PortWriteA(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 2 && port == 1) {
|
||||
if (PPI2PortWriteB) PPI2PortWriteB(write_data);
|
||||
}
|
||||
|
||||
if (chipnum == 2 && port == 2) {
|
||||
if (PPI2PortWriteC) PPI2PortWriteC(write_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ppi8255_input(ppi8255 *chip, INT32 port, UINT8 data, INT32 which)
|
||||
{
|
||||
INT32 changed = 0;
|
||||
|
||||
chip->read[port] = data;
|
||||
|
||||
/* port C is special */
|
||||
if (port == 2)
|
||||
{
|
||||
if (((chip->groupA_mode == 1) && (chip->portA_dir == 0)) || (chip->groupA_mode == 2))
|
||||
{
|
||||
/* is !ACKA asserted? */
|
||||
if (chip->obf_a && !(data & 0x40))
|
||||
{
|
||||
chip->obf_a = 0;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((chip->groupB_mode == 1) && (chip->portB_dir == 0))
|
||||
{
|
||||
/* is !ACKB asserted? */
|
||||
if (chip->obf_b && !(data & 0x04))
|
||||
{
|
||||
chip->obf_b = 0;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
ppi8255_write_port(chip, 2, which);
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 ppi8255_read_port(ppi8255 *chip, INT32 port, INT32 chipnum)
|
||||
{
|
||||
UINT8 result = 0x00;
|
||||
|
||||
if (chip->in_mask[port])
|
||||
{
|
||||
if (chipnum == 0 && port == 0) {
|
||||
ppi8255_input(chip, port, (PPI0PortReadA) ? PPI0PortReadA() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 0 && port == 1) {
|
||||
ppi8255_input(chip, port, (PPI0PortReadB) ? PPI0PortReadB() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 0 && port == 2) {
|
||||
ppi8255_input(chip, port, (PPI0PortReadC) ? PPI0PortReadC() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 1 && port == 0) {
|
||||
ppi8255_input(chip, port, (PPI1PortReadA) ? PPI1PortReadA() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 1 && port == 1) {
|
||||
ppi8255_input(chip, port, (PPI1PortReadB) ? PPI1PortReadB() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 1 && port == 2) {
|
||||
ppi8255_input(chip, port, (PPI1PortReadC) ? PPI1PortReadC() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 2 && port == 0) {
|
||||
ppi8255_input(chip, port, (PPI2PortReadA) ? PPI2PortReadA() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 2 && port == 1) {
|
||||
ppi8255_input(chip, port, (PPI2PortReadB) ? PPI2PortReadB() : 0, chipnum);
|
||||
}
|
||||
|
||||
if (chipnum == 2 && port == 2) {
|
||||
ppi8255_input(chip, port, (PPI2PortReadC) ? PPI2PortReadC() : 0, chipnum);
|
||||
}
|
||||
|
||||
result |= chip->read[port] & chip->in_mask[port];
|
||||
}
|
||||
result |= chip->latch[port] & chip->out_mask[port];
|
||||
|
||||
/* read special port 2 signals */
|
||||
if (port == 2)
|
||||
ppi8255_get_handshake_signals(chip, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
UINT8 ppi8255_r(INT32 which, INT32 offset)
|
||||
{
|
||||
ppi8255 *chip = &chips[which];
|
||||
UINT8 result = 0;
|
||||
|
||||
offset %= 4;
|
||||
|
||||
switch(offset)
|
||||
{
|
||||
case 0: /* Port A read */
|
||||
case 1: /* Port B read */
|
||||
case 2: /* Port C read */
|
||||
result = ppi8255_read_port(chip, offset, which);
|
||||
break;
|
||||
|
||||
case 3: /* Control word */
|
||||
result = 0xFF;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void set_mode(INT32 which, INT32 data, INT32 call_handlers)
|
||||
{
|
||||
ppi8255 *chip = &chips[which];
|
||||
INT32 i;
|
||||
|
||||
/* parse out mode */
|
||||
chip->groupA_mode = (data >> 5) & 3;
|
||||
chip->groupB_mode = (data >> 2) & 1;
|
||||
chip->portA_dir = (data >> 4) & 1;
|
||||
chip->portB_dir = (data >> 1) & 1;
|
||||
chip->portCH_dir = (data >> 3) & 1;
|
||||
chip->portCL_dir = (data >> 0) & 1;
|
||||
|
||||
/* normalize groupA_mode */
|
||||
if (chip->groupA_mode == 3)
|
||||
chip->groupA_mode = 2;
|
||||
|
||||
/* Port A direction */
|
||||
if (chip->portA_dir)
|
||||
chip->in_mask[0] = 0xFF, chip->out_mask[0] = 0x00; /* input */
|
||||
else
|
||||
chip->in_mask[0] = 0x00, chip->out_mask[0] = 0xFF; /* output */
|
||||
|
||||
/* Port B direction */
|
||||
if (chip->portB_dir)
|
||||
chip->in_mask[1] = 0xFF, chip->out_mask[1] = 0x00; /* input */
|
||||
else
|
||||
chip->in_mask[1] = 0x00, chip->out_mask[1] = 0xFF; /* output */
|
||||
|
||||
/* Port C upper direction */
|
||||
if (chip->portCH_dir)
|
||||
chip->in_mask[2] = 0xF0, chip->out_mask[2] = 0x00; /* input */
|
||||
else
|
||||
chip->in_mask[2] = 0x00, chip->out_mask[2] = 0xF0; /* output */
|
||||
|
||||
/* Port C lower direction */
|
||||
if (chip->portCL_dir)
|
||||
chip->in_mask[2] |= 0x0F; /* input */
|
||||
else
|
||||
chip->out_mask[2] |= 0x0F; /* output */
|
||||
|
||||
/* now depending on the group modes, certain Port C lines may be replaced
|
||||
* with varying control signals */
|
||||
switch(chip->groupA_mode)
|
||||
{
|
||||
case 0: /* Group A mode 0 */
|
||||
/* no changes */
|
||||
break;
|
||||
|
||||
case 1: /* Group A mode 1 */
|
||||
/* bits 5-3 are reserved by Group A mode 1 */
|
||||
chip->in_mask[2] &= ~0x38;
|
||||
chip->out_mask[2] &= ~0x38;
|
||||
break;
|
||||
|
||||
case 2: /* Group A mode 2 */
|
||||
/* bits 7-3 are reserved by Group A mode 2 */
|
||||
chip->in_mask[2] &= ~0xF8;
|
||||
chip->out_mask[2] &= ~0xF8;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(chip->groupB_mode)
|
||||
{
|
||||
case 0: /* Group B mode 0 */
|
||||
/* no changes */
|
||||
break;
|
||||
|
||||
case 1: /* Group B mode 1 */
|
||||
/* bits 2-0 are reserved by Group B mode 1 */
|
||||
chip->in_mask[2] &= ~0x07;
|
||||
chip->out_mask[2] &= ~0x07;
|
||||
break;
|
||||
}
|
||||
|
||||
/* KT: 25-Dec-99 - 8255 resets latches when mode set */
|
||||
chip->latch[0] = chip->latch[1] = chip->latch[2] = 0;
|
||||
|
||||
if (call_handlers)
|
||||
{
|
||||
for (i = 0; i < 3; i++)
|
||||
ppi8255_write_port(chip, i, which);
|
||||
}
|
||||
}
|
||||
|
||||
void ppi8255_w(INT32 which, INT32 offset, UINT8 data)
|
||||
{
|
||||
ppi8255 *chip = &chips[which];
|
||||
|
||||
offset %= 4;
|
||||
|
||||
switch( offset )
|
||||
{
|
||||
case 0: /* Port A write */
|
||||
case 1: /* Port B write */
|
||||
case 2: /* Port C write */
|
||||
chip->latch[offset] = data;
|
||||
ppi8255_write_port(chip, offset, which);
|
||||
|
||||
switch(offset)
|
||||
{
|
||||
case 0:
|
||||
if (!chip->portA_dir && (chip->groupA_mode != 0))
|
||||
{
|
||||
chip->obf_a = 1;
|
||||
ppi8255_write_port(chip, 2, which);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (!chip->portB_dir && (chip->groupB_mode != 0))
|
||||
{
|
||||
chip->obf_b = 1;
|
||||
ppi8255_write_port(chip, 2, which);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* Control word */
|
||||
if (data & 0x80)
|
||||
{
|
||||
set_mode(which, data & 0x7f, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bit set/reset */
|
||||
INT32 bit;
|
||||
|
||||
bit = (data >> 1) & 0x07;
|
||||
|
||||
if (data & 1)
|
||||
chip->latch[2] |= (1<<bit); /* set bit */
|
||||
else
|
||||
chip->latch[2] &= ~(1<<bit); /* reset bit */
|
||||
|
||||
ppi8255_write_port(chip, 2, which);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ppi8255_init(INT32 num)
|
||||
{
|
||||
for (INT32 i = 0; i < num; i++) {
|
||||
ppi8255 *chip = &chips[i];
|
||||
|
||||
memset(chip, 0, sizeof(*chip));
|
||||
|
||||
set_mode(i, 0x1b, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ppi8255_exit()
|
||||
{
|
||||
for (INT32 i = 0; i < MAX_PPIS; i++) {
|
||||
ppi8255 *chip = &chips[i];
|
||||
|
||||
memset(chip, 0, sizeof(*chip));
|
||||
}
|
||||
|
||||
PPI0PortReadA = NULL;
|
||||
PPI0PortReadB = NULL;
|
||||
PPI0PortReadC = NULL;
|
||||
PPI0PortWriteA = NULL;
|
||||
PPI0PortWriteB = NULL;
|
||||
PPI0PortWriteC = NULL;
|
||||
PPI1PortReadA = NULL;
|
||||
PPI1PortReadB = NULL;
|
||||
PPI1PortReadC = NULL;
|
||||
PPI1PortWriteA = NULL;
|
||||
PPI1PortWriteB = NULL;
|
||||
PPI1PortWriteC = NULL;
|
||||
PPI2PortReadA = NULL;
|
||||
PPI2PortReadB = NULL;
|
||||
PPI2PortReadC = NULL;
|
||||
PPI2PortWriteA = NULL;
|
||||
PPI2PortWriteB = NULL;
|
||||
PPI2PortWriteC = NULL;
|
||||
}
|
||||
|
||||
void ppi8255_scan()
|
||||
{
|
||||
SCAN_VAR(chips);
|
||||
}
|
||||
|
||||
void ppi8255_set_portC( INT32 which, UINT8 data ) { ppi8255_input(&chips[which], 2, data, which); }
|
||||
|
||||
#undef MAX_PPIS
|
|
@ -0,0 +1,27 @@
|
|||
typedef UINT8 (*PPIPortRead)();
|
||||
typedef void (*PPIPortWrite)(UINT8 data);
|
||||
extern PPIPortRead PPI0PortReadA;
|
||||
extern PPIPortRead PPI0PortReadB;
|
||||
extern PPIPortRead PPI0PortReadC;
|
||||
extern PPIPortWrite PPI0PortWriteA;
|
||||
extern PPIPortWrite PPI0PortWriteB;
|
||||
extern PPIPortWrite PPI0PortWriteC;
|
||||
extern PPIPortRead PPI1PortReadA;
|
||||
extern PPIPortRead PPI1PortReadB;
|
||||
extern PPIPortRead PPI1PortReadC;
|
||||
extern PPIPortWrite PPI1PortWriteA;
|
||||
extern PPIPortWrite PPI1PortWriteB;
|
||||
extern PPIPortWrite PPI1PortWriteC;
|
||||
extern PPIPortRead PPI2PortReadA;
|
||||
extern PPIPortRead PPI2PortReadB;
|
||||
extern PPIPortRead PPI2PortReadC;
|
||||
extern PPIPortWrite PPI2PortWriteA;
|
||||
extern PPIPortWrite PPI2PortWriteB;
|
||||
extern PPIPortWrite PPI2PortWriteC;
|
||||
|
||||
void ppi8255_init(INT32 num);
|
||||
void ppi8255_exit();
|
||||
void ppi8255_scan();
|
||||
UINT8 ppi8255_r(INT32 which, INT32 offset);
|
||||
void ppi8255_w(INT32 which, INT32 offset, UINT8 data);
|
||||
void ppi8255_set_portC( INT32 which, UINT8 data );
|
|
@ -0,0 +1,328 @@
|
|||
#include "burnint.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
#define SERIAL_BUFFER_LENGTH 40
|
||||
#define MEMORY_SIZE 1024
|
||||
|
||||
static const eeprom_interface *intf;
|
||||
|
||||
static INT32 serial_count;
|
||||
static UINT8 serial_buffer[SERIAL_BUFFER_LENGTH];
|
||||
static UINT8 eeprom_data[MEMORY_SIZE];
|
||||
static INT32 eeprom_data_bits;
|
||||
static INT32 eeprom_read_address;
|
||||
static INT32 eeprom_clock_count;
|
||||
static INT32 latch, reset_line, clock_line, sending;
|
||||
static INT32 locked;
|
||||
static INT32 reset_delay;
|
||||
|
||||
static INT32 neeprom_available = 0;
|
||||
|
||||
static INT32 eeprom_command_match(const char *buf, const char *cmd, INT32 len)
|
||||
{
|
||||
if ( cmd == 0 ) return 0;
|
||||
if ( len == 0 ) return 0;
|
||||
|
||||
for (;len>0;)
|
||||
{
|
||||
char b = *buf;
|
||||
char c = *cmd;
|
||||
|
||||
if ((b==0) || (c==0))
|
||||
return (b==c);
|
||||
|
||||
switch ( c )
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
if (b != c) return 0;
|
||||
case 'X':
|
||||
case 'x':
|
||||
buf++;
|
||||
len--;
|
||||
cmd++;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
c = cmd[1];
|
||||
switch( c )
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
if (b == c) { cmd++; }
|
||||
else { buf++; len--; }
|
||||
break;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (*cmd==0);
|
||||
}
|
||||
|
||||
INT32 EEPROMAvailable()
|
||||
{
|
||||
return neeprom_available;
|
||||
}
|
||||
|
||||
void EEPROMInit(const eeprom_interface *interface)
|
||||
{
|
||||
intf = interface;
|
||||
|
||||
if ((1 << intf->address_bits) * intf->data_bits / 8 > MEMORY_SIZE)
|
||||
{
|
||||
bprintf(0, _T("EEPROM larger than eeprom allows"));
|
||||
}
|
||||
|
||||
memset(eeprom_data,0xff,(1 << intf->address_bits) * intf->data_bits / 8);
|
||||
serial_count = 0;
|
||||
latch = 0;
|
||||
reset_line = EEPROM_ASSERT_LINE;
|
||||
clock_line = EEPROM_ASSERT_LINE;
|
||||
eeprom_read_address = 0;
|
||||
sending = 0;
|
||||
if (intf->cmd_unlock) locked = 1;
|
||||
else locked = 0;
|
||||
|
||||
char output[128];
|
||||
sprintf (output, "config\\games\\%s.nv", BurnDrvGetTextA(DRV_NAME));
|
||||
|
||||
neeprom_available = 0;
|
||||
|
||||
INT32 len = ((1 << intf->address_bits) * (intf->data_bits >> 3)) & (MEMORY_SIZE-1);
|
||||
|
||||
FILE *fz = fopen(output, "rb");
|
||||
if (fz != NULL) {
|
||||
neeprom_available = 1;
|
||||
fread (eeprom_data, len, 1, fz);
|
||||
fclose (fz);
|
||||
}
|
||||
}
|
||||
|
||||
void EEPROMExit()
|
||||
{
|
||||
char output[128];
|
||||
sprintf (output, "config\\games\\%s.nv", BurnDrvGetTextA(DRV_NAME));
|
||||
|
||||
neeprom_available = 0;
|
||||
|
||||
INT32 len = ((1 << intf->address_bits) * (intf->data_bits >> 3)) & (MEMORY_SIZE-1);
|
||||
|
||||
FILE *fz = fopen(output, "wb");
|
||||
fwrite (eeprom_data, len, 1, fz);
|
||||
fclose (fz);
|
||||
}
|
||||
|
||||
static void eeprom_write(INT32 bit)
|
||||
{
|
||||
if (serial_count >= SERIAL_BUFFER_LENGTH-1)
|
||||
{
|
||||
bprintf(0, _T("error: EEPROM serial buffer overflow\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
serial_buffer[serial_count++] = (bit ? '1' : '0');
|
||||
serial_buffer[serial_count] = 0;
|
||||
|
||||
if ( (serial_count > intf->address_bits) &&
|
||||
eeprom_command_match((char*)serial_buffer,intf->cmd_read,strlen((char*)serial_buffer)-intf->address_bits) )
|
||||
{
|
||||
INT32 i,address;
|
||||
|
||||
address = 0;
|
||||
for (i = serial_count-intf->address_bits;i < serial_count;i++)
|
||||
{
|
||||
address <<= 1;
|
||||
if (serial_buffer[i] == '1') address |= 1;
|
||||
}
|
||||
if (intf->data_bits == 16)
|
||||
eeprom_data_bits = (eeprom_data[2*address+0] << 8) + eeprom_data[2*address+1];
|
||||
else
|
||||
eeprom_data_bits = eeprom_data[address];
|
||||
eeprom_read_address = address;
|
||||
eeprom_clock_count = 0;
|
||||
sending = 1;
|
||||
serial_count = 0;
|
||||
}
|
||||
else if ( (serial_count > intf->address_bits) &&
|
||||
eeprom_command_match((char*)serial_buffer,intf->cmd_erase,strlen((char*)serial_buffer)-intf->address_bits) )
|
||||
{
|
||||
INT32 i,address;
|
||||
|
||||
address = 0;
|
||||
for (i = serial_count-intf->address_bits;i < serial_count;i++)
|
||||
{
|
||||
address <<= 1;
|
||||
if (serial_buffer[i] == '1') address |= 1;
|
||||
}
|
||||
|
||||
if (locked == 0)
|
||||
{
|
||||
if (intf->data_bits == 16)
|
||||
{
|
||||
eeprom_data[2*address+0] = 0xff;
|
||||
eeprom_data[2*address+1] = 0xff;
|
||||
}
|
||||
else
|
||||
eeprom_data[address] = 0xff;
|
||||
}
|
||||
else
|
||||
serial_count = 0;
|
||||
}
|
||||
else if ( (serial_count > (intf->address_bits + intf->data_bits)) &&
|
||||
eeprom_command_match((char*)serial_buffer,intf->cmd_write,strlen((char*)serial_buffer)-(intf->address_bits + intf->data_bits)) )
|
||||
{
|
||||
INT32 i,address,data;
|
||||
|
||||
address = 0;
|
||||
for (i = serial_count-intf->data_bits-intf->address_bits;i < (serial_count-intf->data_bits);i++)
|
||||
{
|
||||
address <<= 1;
|
||||
if (serial_buffer[i] == '1') address |= 1;
|
||||
}
|
||||
data = 0;
|
||||
for (i = serial_count-intf->data_bits;i < serial_count;i++)
|
||||
{
|
||||
data <<= 1;
|
||||
if (serial_buffer[i] == '1') data |= 1;
|
||||
}
|
||||
|
||||
if (locked == 0)
|
||||
{
|
||||
if (intf->data_bits == 16)
|
||||
{
|
||||
eeprom_data[2*address+0] = data >> 8;
|
||||
eeprom_data[2*address+1] = data & 0xff;
|
||||
}
|
||||
else
|
||||
eeprom_data[address] = data;
|
||||
}
|
||||
else
|
||||
serial_count = 0;
|
||||
}
|
||||
else if ( eeprom_command_match((char*)serial_buffer,intf->cmd_lock,strlen((char*)serial_buffer)) )
|
||||
{
|
||||
locked = 1;
|
||||
serial_count = 0;
|
||||
}
|
||||
else if ( eeprom_command_match((char*)serial_buffer,intf->cmd_unlock,strlen((char*)serial_buffer)) )
|
||||
{
|
||||
locked = 0;
|
||||
serial_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EEPROMReset()
|
||||
{
|
||||
serial_count = 0;
|
||||
sending = 0;
|
||||
reset_delay = intf->reset_delay;
|
||||
}
|
||||
|
||||
void EEPROMWriteBit(INT32 bit)
|
||||
{
|
||||
latch = bit;
|
||||
}
|
||||
|
||||
INT32 EEPROMRead()
|
||||
{
|
||||
INT32 res;
|
||||
|
||||
if (sending)
|
||||
res = (eeprom_data_bits >> intf->data_bits) & 1;
|
||||
else
|
||||
{
|
||||
if (reset_delay > 0)
|
||||
{
|
||||
/* this is needed by wbeachvl */
|
||||
reset_delay--;
|
||||
res = 0;
|
||||
}
|
||||
else
|
||||
res = 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void EEPROMSetCSLine(INT32 state)
|
||||
{
|
||||
reset_line = state;
|
||||
|
||||
if (reset_line != EEPROM_CLEAR_LINE)
|
||||
EEPROMReset();
|
||||
}
|
||||
|
||||
void EEPROMSetClockLine(INT32 state)
|
||||
{
|
||||
if (state == EEPROM_PULSE_LINE || (clock_line == EEPROM_CLEAR_LINE && state != EEPROM_CLEAR_LINE))
|
||||
{
|
||||
if (reset_line == EEPROM_CLEAR_LINE)
|
||||
{
|
||||
if (sending)
|
||||
{
|
||||
if (eeprom_clock_count == intf->data_bits && intf->enable_multi_read)
|
||||
{
|
||||
eeprom_read_address = (eeprom_read_address + 1) & ((1 << intf->address_bits) - 1);
|
||||
if (intf->data_bits == 16)
|
||||
eeprom_data_bits = (eeprom_data[2*eeprom_read_address+0] << 8) + eeprom_data[2*eeprom_read_address+1];
|
||||
else
|
||||
eeprom_data_bits = eeprom_data[eeprom_read_address];
|
||||
eeprom_clock_count = 0;
|
||||
}
|
||||
eeprom_data_bits = (eeprom_data_bits << 1) | 1;
|
||||
eeprom_clock_count++;
|
||||
}
|
||||
else
|
||||
eeprom_write(latch);
|
||||
}
|
||||
}
|
||||
|
||||
clock_line = state;
|
||||
}
|
||||
|
||||
void EEPROMFill(const UINT8 *data, INT32 offset, INT32 length)
|
||||
{
|
||||
memcpy(eeprom_data + offset, data, length);
|
||||
}
|
||||
|
||||
void EEPROMScan(INT32 nAction, INT32* pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
|
||||
if (pnMin && *pnMin < 0x020902) {
|
||||
*pnMin = 0x029705;
|
||||
}
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = serial_buffer;
|
||||
ba.nLen = SERIAL_BUFFER_LENGTH;
|
||||
ba.szName = "Serial Buffer";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SCAN_VAR(serial_count);
|
||||
SCAN_VAR(eeprom_data_bits);
|
||||
SCAN_VAR(eeprom_read_address);
|
||||
SCAN_VAR(eeprom_clock_count);
|
||||
SCAN_VAR(latch);
|
||||
SCAN_VAR(reset_line);
|
||||
SCAN_VAR(clock_line);
|
||||
SCAN_VAR(sending);
|
||||
SCAN_VAR(locked);
|
||||
SCAN_VAR(reset_delay);
|
||||
}
|
||||
|
||||
// if (nAction & ACB_NVRAM) {
|
||||
//
|
||||
// if (pnMin && (nAction & ACB_TYPEMASK) == ACB_NVRAM) {
|
||||
// *pnMin = 0x02705;
|
||||
// }
|
||||
//
|
||||
// memset(&ba, 0, sizeof(ba));
|
||||
// ba.Data = eeprom_data;
|
||||
// ba.nLen = MEMORY_SIZE;
|
||||
// ba.szName = "EEPROM memory";
|
||||
// BurnAcb(&ba);
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
typedef struct _eeprom_interface eeprom_interface;
|
||||
struct _eeprom_interface
|
||||
{
|
||||
INT32 address_bits; /* EEPROM has 2^address_bits cells */
|
||||
INT32 data_bits; /* every cell has this many bits (8 or 16) */
|
||||
const char *cmd_read; /* read command string, e.g. "0110" */
|
||||
const char *cmd_write; /* write command string, e.g. "0111" */
|
||||
const char *cmd_erase; /* erase command string, or 0 if n/a */
|
||||
const char *cmd_lock; /* lock command string, or 0 if n/a */
|
||||
const char *cmd_unlock; /* unlock command string, or 0 if n/a */
|
||||
INT32 enable_multi_read; /* set to 1 to enable multiple values to be read from one read command */
|
||||
INT32 reset_delay; /* number of times eeprom_read_bit() should return 0 after a reset, */
|
||||
/* before starting to return 1. */
|
||||
};
|
||||
|
||||
// default for most in fba
|
||||
const eeprom_interface eeprom_interface_93C46 =
|
||||
{
|
||||
6, // address bits 6
|
||||
16, // data bits 16
|
||||
"*110", // read 1 10 aaaaaa
|
||||
"*101", // write 1 01 aaaaaa dddddddddddddddd
|
||||
"*111", // erase 1 11 aaaaaa
|
||||
"*10000xxxx", // lock 1 00 00xxxx
|
||||
"*10011xxxx", // unlock 1 00 11xxxx
|
||||
1,
|
||||
0
|
||||
};
|
||||
|
||||
#define EEPROM_CLEAR_LINE 0
|
||||
#define EEPROM_ASSERT_LINE 1
|
||||
#define EEPROM_PULSE_LINE 2
|
||||
|
||||
void EEPROMInit(const eeprom_interface *interface);
|
||||
void EEPROMReset();
|
||||
void EEPROMExit();
|
||||
|
||||
INT32 EEPROMAvailable(); // are we loading an eeprom file?
|
||||
|
||||
INT32 EEPROMRead();
|
||||
|
||||
// Write each individually
|
||||
void EEPROMWriteBit(INT32 bit);
|
||||
void EEPROMSetCSLine(INT32 state);
|
||||
void EEPROMSetClockLine(INT32 state);
|
||||
|
||||
// Or all at once
|
||||
#define EEPROMWrite(clock, cs, bit) \
|
||||
EEPROMWriteBit(bit); \
|
||||
EEPROMSetCSLine(cs ? EEPROM_CLEAR_LINE : EEPROM_ASSERT_LINE); \
|
||||
EEPROMSetClockLine(clock ? EEPROM_ASSERT_LINE : EEPROM_CLEAR_LINE)
|
||||
|
||||
void EEPROMFill(const UINT8 *data, INT32 offset, INT32 length);
|
||||
|
||||
void EEPROMScan(INT32 nAction, INT32* pnMin);
|
|
@ -0,0 +1,122 @@
|
|||
// Kaneko Pandora module
|
||||
|
||||
#include "tiles_generic.h"
|
||||
|
||||
static UINT16 *pandora_temp = NULL;
|
||||
static UINT8 *pandora_ram = NULL;
|
||||
static UINT8 *pandora_gfx = NULL;
|
||||
static INT32 pandora_clear;
|
||||
static INT32 pandora_xoffset;
|
||||
static INT32 pandora_yoffset;
|
||||
static INT32 pandora_color_offset;
|
||||
INT32 pandora_flipscreen;
|
||||
|
||||
void pandora_set_clear(INT32 clear)
|
||||
{
|
||||
pandora_clear = clear;
|
||||
}
|
||||
|
||||
void pandora_update(UINT16 *dest)
|
||||
{
|
||||
for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) {
|
||||
if (pandora_temp[i]) {
|
||||
dest[i] = pandora_temp[i] & 0x3ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pandora_buffer_sprites()
|
||||
{
|
||||
INT32 sx=0, sy=0, x=0, y=0;
|
||||
|
||||
if (pandora_clear) memset (pandora_temp, 0, nScreenWidth * nScreenHeight * sizeof(UINT16));
|
||||
|
||||
for (INT32 offs = 0; offs < 0x1000; offs += 8)
|
||||
{
|
||||
INT32 attr = pandora_ram[offs+7];
|
||||
INT32 code = pandora_ram[offs+6] + ((attr & 0x3f) << 8);
|
||||
INT32 dy = pandora_ram[offs+5];
|
||||
INT32 dx = pandora_ram[offs+4];
|
||||
INT32 color = pandora_ram[offs+3];
|
||||
INT32 flipy = attr & 0x40;
|
||||
INT32 flipx = attr & 0x80;
|
||||
|
||||
if (color & 1) dx |= 0x100;
|
||||
if (color & 2) dy |= 0x100;
|
||||
|
||||
if (color & 4)
|
||||
{
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = dx;
|
||||
y = dy;
|
||||
}
|
||||
|
||||
if (pandora_flipscreen)
|
||||
{
|
||||
sx = 240 - x;
|
||||
sy = 240 - y;
|
||||
flipx = !flipx;
|
||||
flipy = !flipy;
|
||||
}
|
||||
else
|
||||
{
|
||||
sx = x;
|
||||
sy = y;
|
||||
}
|
||||
|
||||
sx = (sx + pandora_xoffset) & 0x1ff;
|
||||
sy = (sy + pandora_yoffset) & 0x1ff;
|
||||
if (sx & 0x100) sx -= 0x200;
|
||||
if (sy & 0x100) sy -= 0x200;
|
||||
|
||||
if (sx >= nScreenWidth || sx < -15) continue;
|
||||
if (sy >= nScreenHeight || sy < -15) continue;
|
||||
|
||||
if (flipy) {
|
||||
if (flipx) {
|
||||
Render16x16Tile_Mask_FlipXY_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx);
|
||||
} else {
|
||||
Render16x16Tile_Mask_FlipY_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx);
|
||||
}
|
||||
} else {
|
||||
if (flipx) {
|
||||
Render16x16Tile_Mask_FlipX_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx);
|
||||
} else {
|
||||
Render16x16Tile_Mask_Clip(pandora_temp, code, sx, sy, color >> 4, 4, 0, pandora_color_offset, pandora_gfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// must be called after GenericTilesInit()
|
||||
void pandora_init(UINT8 *ram, UINT8 *gfx, INT32 color_offset, INT32 x, INT32 y)
|
||||
{
|
||||
pandora_ram = ram;
|
||||
pandora_xoffset = x;
|
||||
pandora_yoffset = y;
|
||||
pandora_gfx = gfx;
|
||||
pandora_color_offset = color_offset;
|
||||
|
||||
if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
|
||||
BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth);
|
||||
} else {
|
||||
BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight);
|
||||
}
|
||||
|
||||
pandora_temp = (UINT16*)malloc(nScreenWidth * nScreenHeight * sizeof(UINT16));
|
||||
pandora_clear = 1;
|
||||
}
|
||||
|
||||
void pandora_exit()
|
||||
{
|
||||
if (pandora_temp) {
|
||||
free (pandora_temp);
|
||||
pandora_temp = NULL;
|
||||
}
|
||||
|
||||
pandora_ram = pandora_gfx = NULL;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
extern INT32 pandora_flipscreen;
|
||||
|
||||
void pandora_set_clear(INT32 clear);
|
||||
void pandora_update(UINT16 *dest);
|
||||
void pandora_buffer_sprites();
|
||||
void pandora_init(UINT8 *ram, UINT8 *gfx, INT32 color_offset, INT32 x, INT32 y);
|
||||
void pandora_exit();
|
|
@ -0,0 +1,525 @@
|
|||
//
|
||||
// FB Alpha Seibu sound hardware module
|
||||
//
|
||||
// Games using this hardware:
|
||||
//
|
||||
// Dead Angle 2x YM2203 + adpcm -- not implemented
|
||||
//
|
||||
// Dynamite Duke 1x YM3812 + 1x M6295
|
||||
// Toki 1x YM3812 + 1x M6295
|
||||
// Raiden 1x YM3812 + 1x M6295
|
||||
// Blood Brothers 1x YM3812 + 1x M6295
|
||||
// D-Con 1x YM3812 + 1x M6295
|
||||
// Legionnaire 1x YM3812 + 1x M6295
|
||||
//
|
||||
// SD Gundam PSK 1x YM2151 + 1x M6295
|
||||
// Raiden II 1x YM2151 + 2x M6295
|
||||
// Raiden DX 1x YM2151 + 2x M6295
|
||||
// Zero Team 1x YM2151 + 2x M6295
|
||||
//
|
||||
// Cross Shooter 1x YM2151 + ?
|
||||
// Cabal 1x YM2151 + adpcm -- not implemented
|
||||
//
|
||||
|
||||
#include "burnint.h"
|
||||
#include "burn_ym3812.h"
|
||||
#include "burn_ym2151.h"
|
||||
#include "burn_ym2203.h"
|
||||
#include "msm6295.h"
|
||||
#include "bitswap.h"
|
||||
|
||||
static UINT8 main2sub[2];
|
||||
static UINT8 sub2main[2];
|
||||
static INT32 main2sub_pending;
|
||||
static INT32 sub2main_pending;
|
||||
static INT32 SeibuSoundBank;
|
||||
|
||||
UINT8 *SeibuZ80DecROM;
|
||||
UINT8 *SeibuZ80ROM;
|
||||
UINT8 *SeibuZ80RAM;
|
||||
INT32 seibu_coin_input;
|
||||
|
||||
static INT32 seibu_sndcpu_frequency;
|
||||
static INT32 seibu_snd_type;
|
||||
static INT32 is_sdgndmps = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
VECTOR_INIT,
|
||||
RST10_ASSERT,
|
||||
RST10_CLEAR,
|
||||
RST18_ASSERT,
|
||||
RST18_CLEAR
|
||||
};
|
||||
|
||||
static void update_irq_lines(INT32 param)
|
||||
{
|
||||
static INT32 irq1,irq2;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case VECTOR_INIT:
|
||||
irq1 = irq2 = 0xff;
|
||||
break;
|
||||
|
||||
case RST10_ASSERT:
|
||||
irq1 = 0xd7;
|
||||
break;
|
||||
|
||||
case RST10_CLEAR:
|
||||
irq1 = 0xff;
|
||||
break;
|
||||
|
||||
case RST18_ASSERT:
|
||||
irq2 = 0xdf;
|
||||
break;
|
||||
|
||||
case RST18_CLEAR:
|
||||
irq2 = 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((irq1 & irq2) == 0xff) {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
} else {
|
||||
if (irq2 == 0xdf) {
|
||||
ZetSetVector(irq1 & irq2);
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 seibu_main_word_read(INT32 offset)
|
||||
{
|
||||
offset = (offset >> 1) & 7;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
return sub2main[offset-2];
|
||||
case 5:
|
||||
return main2sub_pending ? 1 : 0;
|
||||
default:
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void seibu_main_word_write(INT32 offset, UINT8 data)
|
||||
{
|
||||
offset = (offset >> 1) & 7;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
main2sub[offset] = data;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (is_sdgndmps) update_irq_lines(RST10_ASSERT);
|
||||
update_irq_lines(RST18_ASSERT);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
sub2main_pending = 0;
|
||||
main2sub_pending = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void seibu_sound_mustb_write_word(INT32 /*offset*/, UINT8 data)
|
||||
{
|
||||
main2sub[0] = data & 0xff;
|
||||
main2sub[1] = data >> 8;
|
||||
|
||||
update_irq_lines(RST18_ASSERT);
|
||||
}
|
||||
|
||||
static void seibu_z80_bank(INT32 data)
|
||||
{
|
||||
SeibuSoundBank = data & 1;
|
||||
|
||||
ZetMapArea(0x8000, 0xffff, 0, SeibuZ80ROM + 0x10000 + (data & 1) * 0x8000);
|
||||
ZetMapArea(0x8000, 0xffff, 2, SeibuZ80ROM + 0x10000 + (data & 1) * 0x8000);
|
||||
}
|
||||
|
||||
void __fastcall seibu_sound_write(UINT16 address, UINT8 data)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x4000:
|
||||
main2sub_pending = 0;
|
||||
sub2main_pending = 1;
|
||||
return;
|
||||
|
||||
case 0x4001:
|
||||
update_irq_lines(VECTOR_INIT);
|
||||
return;
|
||||
|
||||
case 0x4002:
|
||||
// rst10 ack (unused)
|
||||
return;
|
||||
|
||||
case 0x4003:
|
||||
update_irq_lines(RST18_CLEAR);
|
||||
return;
|
||||
|
||||
case 0x4007:
|
||||
seibu_z80_bank(data);
|
||||
return;
|
||||
|
||||
case 0x4008:
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Write(0, data);
|
||||
return;
|
||||
|
||||
case 1:
|
||||
BurnYM2151SelectRegister(data);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
BurnYM2203Write(0, 0, data);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x4009:
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Write(1, data);
|
||||
return;
|
||||
|
||||
case 1:
|
||||
BurnYM2151WriteRegister(data);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
BurnYM2203Write(0, 1, data);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x4018:
|
||||
case 0x4019:
|
||||
sub2main[address & 1] = data;
|
||||
return;
|
||||
|
||||
case 0x401b:
|
||||
// coin counters
|
||||
return;
|
||||
|
||||
case 0x6000:
|
||||
MSM6295Command(0, data);
|
||||
return;
|
||||
|
||||
case 0x6002:
|
||||
if (seibu_snd_type & 4) MSM6295Command(1, data);
|
||||
return;
|
||||
|
||||
// type 2
|
||||
case 0x6008:
|
||||
case 0x6009:
|
||||
if (seibu_snd_type == 2) BurnYM2203Write(1, address & 1, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall seibu_sound_read(UINT16 address)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x4008:
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
return BurnYM3812Read(0);
|
||||
|
||||
case 1:
|
||||
return BurnYM2151ReadStatus();
|
||||
|
||||
case 2:
|
||||
return BurnYM2203Read(0, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0x4009: {
|
||||
if (seibu_snd_type < 2) return 0;
|
||||
return BurnYM2203Read(0, 1);
|
||||
}
|
||||
|
||||
case 0x4010:
|
||||
case 0x4011:
|
||||
return main2sub[address & 1];
|
||||
|
||||
case 0x4012:
|
||||
return sub2main_pending ? 1 : 0;
|
||||
|
||||
case 0x4013:
|
||||
return seibu_coin_input;
|
||||
|
||||
case 0x6000:
|
||||
return MSM6295ReadStatus(0);
|
||||
|
||||
case 0x6002:
|
||||
if (seibu_snd_type & 4) return MSM6295ReadStatus(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT8 decrypt_data(INT32 a,INT32 src)
|
||||
{
|
||||
if ( BIT(a,9) & BIT(a,8)) src ^= 0x80;
|
||||
if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40;
|
||||
if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04;
|
||||
if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02;
|
||||
if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01;
|
||||
|
||||
if (BIT(a,13) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,3,2,0,1);
|
||||
if (BIT(a, 8) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,2,3,1,0);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static UINT8 decrypt_opcode(INT32 a,INT32 src)
|
||||
{
|
||||
if ( BIT(a,9) & BIT(a,8)) src ^= 0x80;
|
||||
if ( BIT(a,11) & BIT(a,4) & BIT(a,1)) src ^= 0x40;
|
||||
if (~BIT(a,13) & BIT(a,12)) src ^= 0x20;
|
||||
if (~BIT(a,6) & BIT(a,1)) src ^= 0x10;
|
||||
if (~BIT(a,12) & BIT(a,2)) src ^= 0x08;
|
||||
if ( BIT(a,11) & ~BIT(a,8) & BIT(a,1)) src ^= 0x04;
|
||||
if ( BIT(a,13) & ~BIT(a,6) & BIT(a,4)) src ^= 0x02;
|
||||
if (~BIT(a,11) & BIT(a,9) & BIT(a,2)) src ^= 0x01;
|
||||
|
||||
if (BIT(a,13) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,3,2,0,1);
|
||||
if (BIT(a, 8) & BIT(a,4)) src = BITSWAP08(src,7,6,5,4,2,3,1,0);
|
||||
if (BIT(a,12) & BIT(a,9)) src = BITSWAP08(src,7,6,4,5,3,2,1,0);
|
||||
if (BIT(a,11) & ~BIT(a,6)) src = BITSWAP08(src,6,7,5,4,3,2,1,0);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static void seibu_sound_decrypt(INT32 length)
|
||||
{
|
||||
for (INT32 i = 0; i < length; i++)
|
||||
{
|
||||
UINT8 src = SeibuZ80ROM[i];
|
||||
|
||||
SeibuZ80ROM[i] = decrypt_data(i,src);
|
||||
SeibuZ80DecROM[i] = decrypt_opcode(i,src);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvSynchroniseStream(INT32 nSoundRate)
|
||||
{
|
||||
return (INT64)ZetTotalCycles() * nSoundRate / seibu_sndcpu_frequency;
|
||||
}
|
||||
|
||||
static void DrvFMIRQHandler(INT32, INT32 nStatus)
|
||||
{
|
||||
if (nStatus) {
|
||||
update_irq_lines(RST10_ASSERT);
|
||||
} else {
|
||||
update_irq_lines(RST10_CLEAR);
|
||||
}
|
||||
}
|
||||
|
||||
static void Drv2151FMIRQHandler(INT32 nStatus)
|
||||
{
|
||||
DrvFMIRQHandler(0, nStatus);
|
||||
}
|
||||
|
||||
static double Drv2203GetTime()
|
||||
{
|
||||
return (double)ZetTotalCycles() / seibu_sndcpu_frequency;
|
||||
}
|
||||
|
||||
void seibu_sound_reset()
|
||||
{
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
update_irq_lines(VECTOR_INIT);
|
||||
ZetClose();
|
||||
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Reset();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
BurnYM2151Reset();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
BurnYM2203Reset();
|
||||
break;
|
||||
}
|
||||
|
||||
MSM6295Reset(0);
|
||||
if (seibu_snd_type & 4) MSM6295Reset(1);
|
||||
|
||||
memset (main2sub, 0, 2);
|
||||
memset (sub2main, 0, 2);
|
||||
main2sub_pending = 0;
|
||||
sub2main_pending = 0;
|
||||
|
||||
seibu_coin_input = 0;
|
||||
SeibuSoundBank = 0;
|
||||
}
|
||||
|
||||
void seibu_sound_init(INT32 type, INT32 len, INT32 freq0 /*cpu*/, INT32 freq1 /*ym*/, INT32 freq2 /*oki*/)
|
||||
{
|
||||
seibu_snd_type = type;
|
||||
|
||||
if (len && SeibuZ80DecROM != NULL) {
|
||||
seibu_sound_decrypt(len);
|
||||
} else {
|
||||
SeibuZ80DecROM = SeibuZ80ROM;
|
||||
}
|
||||
|
||||
seibu_sndcpu_frequency = freq0;
|
||||
|
||||
ZetInit(1);
|
||||
ZetOpen(0);
|
||||
ZetMapArea(0x0000, 0x1fff, 0, SeibuZ80ROM);
|
||||
ZetMapArea(0x0000, 0x1fff, 2, SeibuZ80DecROM, SeibuZ80ROM);
|
||||
ZetMapArea(0x2000, 0x27ff, 0, SeibuZ80RAM);
|
||||
ZetMapArea(0x2000, 0x27ff, 1, SeibuZ80RAM);
|
||||
ZetMapArea(0x2000, 0x27ff, 2, SeibuZ80RAM);
|
||||
ZetSetWriteHandler(seibu_sound_write);
|
||||
ZetSetReadHandler(seibu_sound_read);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Init(freq1, &DrvFMIRQHandler, &DrvSynchroniseStream, 0);
|
||||
BurnTimerAttachZetYM3812(freq0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
BurnYM2151Init(freq1, 100.0);
|
||||
BurnYM2151SetIrqHandler(&Drv2151FMIRQHandler);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
BurnYM2203Init(2, freq1, DrvFMIRQHandler, DrvSynchroniseStream, Drv2203GetTime, 0);
|
||||
BurnTimerAttachZet(freq0);
|
||||
break;
|
||||
}
|
||||
|
||||
MSM6295Init(0, freq2, 100.0, 1);
|
||||
if (seibu_snd_type & 4) MSM6295Init(1, freq2, 100.0, 1);
|
||||
|
||||
// init kludge for sdgndmps
|
||||
if (!strcmp(BurnDrvGetTextA(DRV_NAME), "sdgndmps")) {
|
||||
is_sdgndmps = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void seibu_sound_exit()
|
||||
{
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Exit();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
BurnYM2151Exit();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
BurnYM2203Exit();
|
||||
break;
|
||||
}
|
||||
|
||||
MSM6295Exit(0);
|
||||
if (seibu_snd_type & 4) MSM6295Exit(1);
|
||||
|
||||
ZetExit();
|
||||
|
||||
MSM6295ROM = NULL;
|
||||
|
||||
SeibuZ80DecROM = NULL;
|
||||
SeibuZ80ROM = NULL;
|
||||
SeibuZ80RAM = NULL;
|
||||
seibu_sndcpu_frequency = 0;
|
||||
is_sdgndmps = 0;
|
||||
}
|
||||
|
||||
void seibu_sound_update(INT16 *pbuf, INT32 nLen)
|
||||
{
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Update(pbuf, nLen);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
BurnYM2151Render(pbuf, nLen);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
BurnYM2203Update(pbuf, nLen);
|
||||
break;
|
||||
}
|
||||
|
||||
if (seibu_snd_type & 4)
|
||||
MSM6295Render(1, pbuf, nLen);
|
||||
MSM6295Render(0, pbuf, nLen);
|
||||
}
|
||||
|
||||
void seibu_sound_scan(INT32 *pnMin, INT32 nAction)
|
||||
{
|
||||
if (nAction & ACB_VOLATILE)
|
||||
{
|
||||
ZetScan(nAction);
|
||||
|
||||
switch (seibu_snd_type & 3)
|
||||
{
|
||||
case 0:
|
||||
BurnYM3812Scan(nAction, pnMin);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
BurnYM2203Scan(nAction, pnMin);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
BurnYM2151Scan(nAction);
|
||||
break;
|
||||
}
|
||||
|
||||
MSM6295Scan(0, nAction);
|
||||
if (seibu_snd_type & 4) {
|
||||
MSM6295Scan(1, nAction);
|
||||
}
|
||||
|
||||
SCAN_VAR(main2sub[0]);
|
||||
SCAN_VAR(main2sub[1]);
|
||||
SCAN_VAR(sub2main[0]);
|
||||
SCAN_VAR(sub2main[1]);
|
||||
SCAN_VAR(main2sub_pending);
|
||||
SCAN_VAR(sub2main_pending);
|
||||
SCAN_VAR(SeibuSoundBank);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE)
|
||||
{
|
||||
ZetOpen(0);
|
||||
seibu_z80_bank(SeibuSoundBank);
|
||||
ZetClose();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include "burn_ym3812.h"
|
||||
#include "burn_ym2151.h"
|
||||
#include "burn_ym2203.h"
|
||||
#include "msm6295.h"
|
||||
|
||||
extern UINT8 *SeibuZ80DecROM;
|
||||
extern UINT8 *SeibuZ80ROM;
|
||||
extern UINT8 *SeibuZ80RAM;
|
||||
|
||||
extern INT32 seibu_coin_input;
|
||||
|
||||
unsigned char seibu_main_word_read(INT32 offset);
|
||||
void seibu_main_word_write(INT32 offset, UINT8 data);
|
||||
void seibu_sound_mustb_write_word(INT32 offset, UINT8 data);
|
||||
|
||||
void seibu_sound_reset();
|
||||
|
||||
void seibu_sound_update(INT16 *pbuf, INT32 nLen);
|
||||
|
||||
/*
|
||||
Type 0 - YM3812
|
||||
Type 1 - YM2151
|
||||
Type 2 - YM2203
|
||||
|
||||
all init a single oki6295
|
||||
add 4 to init a second oki6295
|
||||
*/
|
||||
|
||||
void seibu_sound_init(INT32 type, INT32 encrypted_len, INT32 freq0 /*cpu*/, INT32 freq1 /*ym*/, INT32 freq2 /*oki*/);
|
||||
void seibu_sound_exit();
|
||||
|
||||
void seibu_sound_scan(INT32 *pnMin, INT32 nAction);
|
|
@ -0,0 +1,331 @@
|
|||
#include "burnint.h"
|
||||
#include "time.h"
|
||||
#include "timekpr.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 control;
|
||||
UINT8 seconds;
|
||||
UINT8 minutes;
|
||||
UINT8 hours;
|
||||
UINT8 day;
|
||||
UINT8 date;
|
||||
UINT8 month;
|
||||
UINT8 year;
|
||||
UINT8 century;
|
||||
UINT8 *data;
|
||||
INT32 type;
|
||||
INT32 size;
|
||||
INT32 offset_control;
|
||||
INT32 offset_seconds;
|
||||
INT32 offset_minutes;
|
||||
INT32 offset_hours;
|
||||
INT32 offset_day;
|
||||
INT32 offset_date;
|
||||
INT32 offset_month;
|
||||
INT32 offset_year;
|
||||
INT32 offset_century;
|
||||
INT32 offset_flags;
|
||||
} timekeeper_chip;
|
||||
|
||||
static timekeeper_chip Chip;
|
||||
|
||||
static INT32 AllocatedOwnDataArea = 0;
|
||||
|
||||
#define MASK_SECONDS ( 0x7f )
|
||||
#define MASK_MINUTES ( 0x7f )
|
||||
#define MASK_HOURS ( 0x3f )
|
||||
#define MASK_DAY ( 0x07 )
|
||||
#define MASK_DATE ( 0x3f )
|
||||
#define MASK_MONTH ( 0x1f )
|
||||
#define MASK_YEAR ( 0xff )
|
||||
#define MASK_CENTURY ( 0xff )
|
||||
|
||||
#define CONTROL_W ( 0x80 )
|
||||
#define CONTROL_R ( 0x40 )
|
||||
#define CONTROL_S ( 0x20 ) /* not emulated */
|
||||
#define CONTROL_CALIBRATION ( 0x1f ) /* not emulated */
|
||||
|
||||
#define SECONDS_ST ( 0x80 )
|
||||
|
||||
#define DAY_FT ( 0x40 ) /* not emulated */
|
||||
#define DAY_CEB ( 0x20 ) /* M48T58 */
|
||||
#define DAY_CB ( 0x10 ) /* M48T58 */
|
||||
|
||||
#define DATE_BLE ( 0x80 ) /* M48T58: not emulated */
|
||||
#define DATE_BL ( 0x40 ) /* M48T58: not emulated */
|
||||
|
||||
#define FLAGS_BL ( 0x10 ) /* MK48T08: not emulated */
|
||||
|
||||
static inline UINT8 make_bcd(UINT8 data)
|
||||
{
|
||||
return ( ( ( data / 10 ) % 10 ) << 4 ) + ( data % 10 );
|
||||
}
|
||||
|
||||
static inline UINT8 from_bcd(UINT8 data)
|
||||
{
|
||||
return ( ( ( data >> 4 ) & 15 ) * 10 ) + ( data & 15 );
|
||||
}
|
||||
|
||||
static INT32 inc_bcd( UINT8 *data, INT32 mask, INT32 min, INT32 max )
|
||||
{
|
||||
INT32 bcd;
|
||||
INT32 carry;
|
||||
|
||||
bcd = ( *( data ) + 1 ) & mask;
|
||||
carry = 0;
|
||||
|
||||
if( ( bcd & 0x0f ) > 9 )
|
||||
{
|
||||
bcd &= 0xf0;
|
||||
bcd += 0x10;
|
||||
if( bcd > max )
|
||||
{
|
||||
bcd = min;
|
||||
carry = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*( data ) = ( *( data ) & ~mask ) | ( bcd & mask );
|
||||
return carry;
|
||||
}
|
||||
|
||||
static void counter_to_ram(UINT8 *data, INT32 offset, INT32 counter)
|
||||
{
|
||||
if( offset >= 0 )
|
||||
{
|
||||
data[ offset ] = counter;
|
||||
}
|
||||
}
|
||||
|
||||
static void counters_to_ram()
|
||||
{
|
||||
counter_to_ram( Chip.data, Chip.offset_control, Chip.control );
|
||||
counter_to_ram( Chip.data, Chip.offset_seconds, Chip.seconds );
|
||||
counter_to_ram( Chip.data, Chip.offset_minutes, Chip.minutes );
|
||||
counter_to_ram( Chip.data, Chip.offset_hours, Chip.hours );
|
||||
counter_to_ram( Chip.data, Chip.offset_day, Chip.day );
|
||||
counter_to_ram( Chip.data, Chip.offset_date, Chip.date );
|
||||
counter_to_ram( Chip.data, Chip.offset_month, Chip.month );
|
||||
counter_to_ram( Chip.data, Chip.offset_year, Chip.year );
|
||||
counter_to_ram( Chip.data, Chip.offset_century, Chip.century );
|
||||
}
|
||||
|
||||
static INT32 counter_from_ram(UINT8 *data, INT32 offset)
|
||||
{
|
||||
if( offset >= 0 )
|
||||
{
|
||||
return data[ offset ];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void counters_from_ram()
|
||||
{
|
||||
Chip.control = counter_from_ram( Chip.data, Chip.offset_control );
|
||||
Chip.seconds = counter_from_ram( Chip.data, Chip.offset_seconds );
|
||||
Chip.minutes = counter_from_ram( Chip.data, Chip.offset_minutes );
|
||||
Chip.hours = counter_from_ram( Chip.data, Chip.offset_hours );
|
||||
Chip.day = counter_from_ram( Chip.data, Chip.offset_day );
|
||||
Chip.date = counter_from_ram( Chip.data, Chip.offset_date );
|
||||
Chip.month = counter_from_ram( Chip.data, Chip.offset_month );
|
||||
Chip.year = counter_from_ram( Chip.data, Chip.offset_year );
|
||||
Chip.century = counter_from_ram( Chip.data, Chip.offset_century );
|
||||
}
|
||||
|
||||
UINT8 TimeKeeperRead(UINT32 offset)
|
||||
{
|
||||
return Chip.data[offset];
|
||||
}
|
||||
|
||||
void TimeKeeperWrite(INT32 offset, UINT8 data)
|
||||
{
|
||||
if( offset == Chip.offset_control )
|
||||
{
|
||||
if( ( Chip.control & CONTROL_W ) != 0 &&
|
||||
( data & CONTROL_W ) == 0 )
|
||||
{
|
||||
counters_from_ram();
|
||||
}
|
||||
Chip.control = data;
|
||||
}
|
||||
else if( Chip.type == TIMEKEEPER_M48T58 && offset == Chip.offset_day )
|
||||
{
|
||||
Chip.day = ( Chip.day & ~DAY_CEB ) | ( data & DAY_CEB );
|
||||
}
|
||||
else if( Chip.type == TIMEKEEPER_M48T58 && offset == Chip.offset_date )
|
||||
{
|
||||
data &= ~DATE_BL;
|
||||
}
|
||||
else if( Chip.type == TIMEKEEPER_MK48T08 && offset == Chip.offset_flags )
|
||||
{
|
||||
data &= ~FLAGS_BL;
|
||||
}
|
||||
|
||||
Chip.data[ offset ] = data;
|
||||
}
|
||||
|
||||
void TimeKeeperTick()
|
||||
{
|
||||
INT32 carry;
|
||||
|
||||
if( ( Chip.seconds & SECONDS_ST ) != 0 ||
|
||||
( Chip.control & CONTROL_W ) != 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
carry = inc_bcd( &Chip.seconds, MASK_SECONDS, 0x00, 0x59 );
|
||||
if( carry )
|
||||
{
|
||||
carry = inc_bcd( &Chip.minutes, MASK_MINUTES, 0x00, 0x59 );
|
||||
}
|
||||
if( carry )
|
||||
{
|
||||
carry = inc_bcd( &Chip.hours, MASK_HOURS, 0x00, 0x23 );
|
||||
}
|
||||
|
||||
if( carry )
|
||||
{
|
||||
UINT8 month;
|
||||
UINT8 year;
|
||||
UINT8 maxdays;
|
||||
static const UINT8 daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
|
||||
|
||||
inc_bcd( &Chip.day, MASK_DAY, 0x01, 0x07 );
|
||||
|
||||
month = from_bcd( Chip.month );
|
||||
year = from_bcd( Chip.year );
|
||||
|
||||
if( month == 2 && ( year % 4 ) == 0 )
|
||||
{
|
||||
maxdays = 0x29;
|
||||
}
|
||||
else if( month >= 1 && month <= 12 )
|
||||
{
|
||||
maxdays = daysinmonth[ month - 1 ];
|
||||
}
|
||||
else
|
||||
{
|
||||
maxdays = 0x31;
|
||||
}
|
||||
|
||||
carry = inc_bcd( &Chip.date, MASK_DATE, 0x01, maxdays );
|
||||
}
|
||||
if( carry )
|
||||
{
|
||||
carry = inc_bcd( &Chip.month, MASK_MONTH, 0x01, 0x12 );
|
||||
}
|
||||
if( carry )
|
||||
{
|
||||
carry = inc_bcd( &Chip.year, MASK_YEAR, 0x00, 0x99 );
|
||||
}
|
||||
if( carry )
|
||||
{
|
||||
carry = inc_bcd( &Chip.century, MASK_CENTURY, 0x00, 0x99 );
|
||||
if( Chip.type == TIMEKEEPER_M48T58 && ( Chip.day & DAY_CEB ) != 0 )
|
||||
{
|
||||
Chip.day ^= DAY_CB;
|
||||
}
|
||||
}
|
||||
|
||||
if( ( Chip.control & CONTROL_R ) == 0 )
|
||||
{
|
||||
counters_to_ram();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeKeeperInit(INT32 type, UINT8 *data)
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
Chip.type = type;
|
||||
|
||||
switch( Chip.type )
|
||||
{
|
||||
case TIMEKEEPER_M48T02:
|
||||
Chip.offset_control = 0x7f8;
|
||||
Chip.offset_seconds = 0x7f9;
|
||||
Chip.offset_minutes = 0x7fa;
|
||||
Chip.offset_hours = 0x7fb;
|
||||
Chip.offset_day = 0x7fc;
|
||||
Chip.offset_date = 0x7fd;
|
||||
Chip.offset_month = 0x7fe;
|
||||
Chip.offset_year = 0x7ff;
|
||||
Chip.offset_century = -1;
|
||||
Chip.offset_flags = -1;
|
||||
Chip.size = 0x800;
|
||||
break;
|
||||
case TIMEKEEPER_M48T58:
|
||||
Chip.offset_control = 0x1ff8;
|
||||
Chip.offset_seconds = 0x1ff9;
|
||||
Chip.offset_minutes = 0x1ffa;
|
||||
Chip.offset_hours = 0x1ffb;
|
||||
Chip.offset_day = 0x1ffc;
|
||||
Chip.offset_date = 0x1ffd;
|
||||
Chip.offset_month = 0x1ffe;
|
||||
Chip.offset_year = 0x1fff;
|
||||
Chip.offset_century = -1;
|
||||
Chip.offset_flags = -1;
|
||||
Chip.size = 0x2000;
|
||||
break;
|
||||
case TIMEKEEPER_MK48T08:
|
||||
Chip.offset_control = 0x1ff8;
|
||||
Chip.offset_seconds = 0x1ff9;
|
||||
Chip.offset_minutes = 0x1ffa;
|
||||
Chip.offset_hours = 0x1ffb;
|
||||
Chip.offset_day = 0x1ffc;
|
||||
Chip.offset_date = 0x1ffd;
|
||||
Chip.offset_month = 0x1ffe;
|
||||
Chip.offset_year = 0x1fff;
|
||||
Chip.offset_century = 0x1ff1;
|
||||
Chip.offset_flags = 0x1ff0;
|
||||
Chip.size = 0x2000;
|
||||
break;
|
||||
}
|
||||
|
||||
if( data == NULL )
|
||||
{
|
||||
data = (UINT8*)malloc(Chip.size);
|
||||
memset(data, 0xff, Chip.size );
|
||||
AllocatedOwnDataArea = 1;
|
||||
}
|
||||
Chip.data = data;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
Chip.control = 0;
|
||||
Chip.seconds = make_bcd(timeinfo->tm_sec);
|
||||
Chip.minutes = make_bcd(timeinfo->tm_min);
|
||||
Chip.hours = make_bcd(timeinfo->tm_hour);
|
||||
Chip.day = make_bcd(timeinfo->tm_wday + 1 );
|
||||
Chip.date = make_bcd(timeinfo->tm_mday );
|
||||
Chip.month = make_bcd(timeinfo->tm_mon + 1 );
|
||||
Chip.year = make_bcd(timeinfo->tm_year % 100 );
|
||||
Chip.century = make_bcd(timeinfo->tm_year / 100 );
|
||||
}
|
||||
|
||||
void TimeKeeperExit()
|
||||
{
|
||||
if (AllocatedOwnDataArea) {
|
||||
free (Chip.data);
|
||||
Chip.data = NULL;
|
||||
}
|
||||
AllocatedOwnDataArea = 0;
|
||||
memset(&Chip, 0, sizeof(Chip));
|
||||
}
|
||||
|
||||
void TimeKeeperScan(INT32 nAction)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (nAction & ACB_NVRAM) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = Chip.data;
|
||||
ba.nLen = Chip.size;
|
||||
ba.szName = "Time Keeper RAM";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#define TIMEKEEPER_M48T58 ( 1 )
|
||||
#define TIMEKEEPER_M48T02 ( 2 )
|
||||
#define TIMEKEEPER_MK48T08 ( 3 )
|
||||
|
||||
UINT8 TimeKeeperRead(UINT32 offset);
|
||||
void TimeKeeperWrite(INT32 offset, UINT8 data);
|
||||
void TimeKeeperTick();
|
||||
void TimeKeeperInit(INT32 type, UINT8 *data);
|
||||
void TimeKeeperExit();
|
||||
void TimeKeeperScan(INT32 nAction);
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* For the MAME sound cores
|
||||
*/
|
||||
|
||||
#ifndef DRIVER_H
|
||||
#define DRIVER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#if !defined (_WIN32)
|
||||
#define __cdecl
|
||||
#endif
|
||||
|
||||
#ifndef INLINE
|
||||
#define INLINE __inline static
|
||||
#endif
|
||||
|
||||
#define FBA
|
||||
|
||||
typedef unsigned char UINT8;
|
||||
typedef signed char INT8;
|
||||
typedef unsigned short UINT16;
|
||||
typedef signed short INT16;
|
||||
typedef unsigned int UINT32;
|
||||
typedef signed int INT32;
|
||||
#ifdef _MSC_VER
|
||||
typedef signed __int64 INT64;
|
||||
typedef unsigned __int64 UINT64;
|
||||
#else
|
||||
__extension__ typedef unsigned long long UINT64;
|
||||
__extension__ typedef long long INT64;
|
||||
#endif
|
||||
#define OSD_CPU_H
|
||||
|
||||
/* OPN */
|
||||
#define HAS_YM2203 1
|
||||
#define HAS_YM2608 1
|
||||
#define HAS_YM2610 1
|
||||
#define HAS_YM2610B 1
|
||||
#define HAS_YM2612 1
|
||||
#define HAS_YM3438 1
|
||||
/* OPL */
|
||||
#define HAS_YM3812 1
|
||||
#define HAS_YM3526 1
|
||||
#define HAS_Y8950 1
|
||||
|
||||
enum {
|
||||
CLEAR_LINE = 0,
|
||||
ASSERT_LINE,
|
||||
HOLD_LINE,
|
||||
PULSE_LINE
|
||||
};
|
||||
|
||||
#define timer_get_time() BurnTimerGetTime()
|
||||
|
||||
#define READ8_HANDLER(name) UINT8 name(void)
|
||||
#define WRITE8_HANDLER(name) void name(UINT8 data)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
double BurnTimerGetTime(void);
|
||||
|
||||
typedef UINT8 (*read8_handler)(UINT32 offset);
|
||||
typedef void (*write8_handler)(UINT32 offset, UINT32 data);
|
||||
|
||||
#ifdef MAME_USE_LOGERROR
|
||||
void __cdecl logerror(char* szFormat, ...);
|
||||
#else
|
||||
#define logerror
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVER_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,385 @@
|
|||
// CPS ----------------------------------
|
||||
#include "burnint.h"
|
||||
|
||||
#include "msm6295.h"
|
||||
#include "eeprom.h"
|
||||
#include "timer.h"
|
||||
|
||||
// Maximum number of beam-synchronized interrupts to check
|
||||
#define MAX_RASTER 10
|
||||
|
||||
extern UINT32 CpsMProt[4]; // Mprot changes
|
||||
extern UINT32 CpsBID[3]; // Board ID changes
|
||||
|
||||
// cps.cpp
|
||||
extern INT32 Cps; // 1 = CPS1, 2 = CPS2, 3 = CPS CHanger
|
||||
extern INT32 Cps1Qs;
|
||||
extern INT32 Cps1Pic;
|
||||
extern INT32 nCPS68KClockspeed;
|
||||
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 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 UINT8 *CpsAd; extern UINT32 nCpsAdLen; // ADPCM Data
|
||||
extern UINT32 nCpsGfxScroll[4]; // Offset to Scroll tiles
|
||||
extern UINT32 nCpsGfxMask; // Address mask
|
||||
extern UINT8* CpsStar;
|
||||
INT32 CpsInit();
|
||||
INT32 Cps2Init();
|
||||
INT32 CpsExit();
|
||||
INT32 CpsLoadTiles(UINT8 *Tile,INT32 nStart);
|
||||
INT32 CpsLoadTilesByte(UINT8 *Tile,INT32 nStart);
|
||||
INT32 CpsLoadTilesForgottn(INT32 nStart);
|
||||
INT32 CpsLoadTilesForgottnu(INT32 nStart);
|
||||
INT32 CpsLoadTilesPang(UINT8 *Tile,INT32 nStart);
|
||||
INT32 CpsLoadTilesHack160(UINT8 *Tile,INT32 nStart);
|
||||
INT32 CpsLoadTilesBootleg(UINT8 *Tile, INT32 nStart);
|
||||
INT32 CpsLoadTilesCaptcomb(UINT8 *Tile, INT32 nStart);
|
||||
INT32 CpsLoadTilesPunipic2(UINT8 *Tile, INT32 nStart);
|
||||
INT32 CpsLoadTilesSf2ebbl(UINT8 *Tile, INT32 nStart);
|
||||
INT32 CpsLoadStars(UINT8 *pStar, INT32 nStart);
|
||||
INT32 CpsLoadStarsByte(UINT8 *pStar, INT32 nStart);
|
||||
INT32 CpsLoadStarsForgottnAlt(UINT8 *pStar, INT32 nStart);
|
||||
INT32 Cps2LoadTiles(UINT8 *Tile,INT32 nStart);
|
||||
INT32 Cps2LoadTilesSIM(UINT8 *Tile,INT32 nStart);
|
||||
|
||||
// cps_config.h
|
||||
#define CPS_B_01 0
|
||||
#define CPS_B_02 1
|
||||
#define CPS_B_03 2
|
||||
#define CPS_B_04 3
|
||||
#define CPS_B_05 4
|
||||
#define CPS_B_11 5
|
||||
#define CPS_B_12 6
|
||||
#define CPS_B_13 7
|
||||
#define CPS_B_14 8
|
||||
#define CPS_B_15 9
|
||||
#define CPS_B_16 10
|
||||
#define CPS_B_17 11
|
||||
#define CPS_B_18 12
|
||||
#define CPS_B_21_DEF 13
|
||||
#define CPS_B_21_BT1 14
|
||||
#define CPS_B_21_BT2 15
|
||||
#define CPS_B_21_BT3 16
|
||||
#define CPS_B_21_BT4 17
|
||||
#define CPS_B_21_BT5 18
|
||||
#define CPS_B_21_BT6 19
|
||||
#define CPS_B_21_BT7 20
|
||||
#define CPS_B_21_QS1 21
|
||||
#define CPS_B_21_QS2 22
|
||||
#define CPS_B_21_QS3 23
|
||||
#define CPS_B_21_QS4 24
|
||||
#define CPS_B_21_QS5 25
|
||||
#define HACK_B_1 26
|
||||
#define HACK_B_2 27
|
||||
#define HACK_B_3 28
|
||||
#define HACK_B_4 29
|
||||
|
||||
#define GFXTYPE_SPRITES (1<<0)
|
||||
#define GFXTYPE_SCROLL1 (1<<1)
|
||||
#define GFXTYPE_SCROLL2 (1<<2)
|
||||
#define GFXTYPE_SCROLL3 (1<<3)
|
||||
#define GFXTYPE_STARS (1<<4)
|
||||
|
||||
#define mapper_LWCHR 0
|
||||
#define mapper_LW621 1
|
||||
#define mapper_DM620 2
|
||||
#define mapper_ST24M1 3
|
||||
#define mapper_DM22A 4
|
||||
#define mapper_DAM63B 5
|
||||
#define mapper_ST22B 6
|
||||
#define mapper_TK22B 7
|
||||
#define mapper_WL24B 8
|
||||
#define mapper_S224B 9
|
||||
#define mapper_YI24B 10
|
||||
#define mapper_AR24B 11
|
||||
#define mapper_AR22B 12
|
||||
#define mapper_O224B 13
|
||||
#define mapper_MS24B 14
|
||||
#define mapper_CK24B 15
|
||||
#define mapper_NM24B 16
|
||||
#define mapper_CA24B 17
|
||||
#define mapper_CA22B 18
|
||||
#define mapper_STF29 19
|
||||
#define mapper_RT24B 20
|
||||
#define mapper_RT22B 21
|
||||
#define mapper_KD29B 22
|
||||
#define mapper_CC63B 23
|
||||
#define mapper_KR63B 24
|
||||
#define mapper_S9263B 25
|
||||
#define mapper_VA63B 26
|
||||
#define mapper_VA22B 27
|
||||
#define mapper_Q522B 28
|
||||
#define mapper_TK263B 29
|
||||
#define mapper_CD63B 30
|
||||
#define mapper_PS63B 31
|
||||
#define mapper_MB63B 32
|
||||
#define mapper_QD22B 33
|
||||
#define mapper_QD63B 34
|
||||
#define mapper_qtono2 35
|
||||
#define mapper_RCM63B 36
|
||||
#define mapper_PKB10B 37
|
||||
#define mapper_pang3 38
|
||||
#define mapper_sfzch 39
|
||||
#define mapper_cps2 40
|
||||
#define mapper_frog 41
|
||||
extern void SetGfxMapper(INT32 MapperId);
|
||||
extern INT32 GfxRomBankMapper(INT32 Type, INT32 Code);
|
||||
extern void SetCpsBId(INT32 CpsBId, INT32 bStars);
|
||||
|
||||
// cps_pal.cpp
|
||||
extern UINT32* CpsPal; // Hicolor version of palette
|
||||
extern UINT32* CpsObjPal; // Pointer to lagged obj palette
|
||||
extern INT32 nLagObjectPalettes; // Lag object palettes by one frame if non-zero
|
||||
INT32 CpsPalInit();
|
||||
INT32 CpsPalExit();
|
||||
INT32 CpsPalUpdate(UINT8 *pNewPal,INT32 bRecalcAll);
|
||||
INT32 CpsStarPalUpdate(UINT8* pNewPal, INT32 nLayer, INT32 bRecalcAll);
|
||||
|
||||
// cps_mem.cpp
|
||||
extern UINT8 *CpsRam90;
|
||||
extern UINT8 *CpsZRamC0,*CpsZRamF0;
|
||||
extern UINT8 *CpsSavePal;
|
||||
extern UINT8 *CpsRam708,*CpsReg,*CpsFrg;
|
||||
extern UINT8 *CpsSaveReg[MAX_RASTER + 1];
|
||||
extern UINT8 *CpsSaveFrg[MAX_RASTER + 1];
|
||||
extern UINT8 *CpsRamFF;
|
||||
void CpsMapObjectBanks(INT32 nBank);
|
||||
INT32 CpsMemInit();
|
||||
INT32 CpsMemExit();
|
||||
INT32 CpsAreaScan(INT32 nAction,INT32 *pnMin);
|
||||
|
||||
// cps_run.cpp
|
||||
extern UINT8 CpsReset;
|
||||
extern UINT8 Cpi01A, Cpi01C, Cpi01E;
|
||||
extern INT32 nIrqLine50, nIrqLine52; // The scanlines at which the interrupts are triggered
|
||||
extern INT32 CpsDrawSpritesInReverse;
|
||||
INT32 CpsRunInit();
|
||||
INT32 CpsRunExit();
|
||||
INT32 Cps1Frame();
|
||||
INT32 Cps2Frame();
|
||||
|
||||
inline static UINT8* CpsFindGfxRam(INT32 nAddr,INT32 nLen)
|
||||
{
|
||||
nAddr&=0xffffff; // 24-bit bus
|
||||
if (nAddr>=0x900000 && nAddr+nLen<=0x930000) return CpsRam90+nAddr-0x900000;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// cps_rw.cpp
|
||||
// Treble Winner - Added INP(1FD) for sf2ue
|
||||
#define CPSINPSET INP(000) INP(001) INP(006) INP(007) INP(008) INP(010) INP(011) INP(012) INP(018) INP(019) INP(020) INP(021) INP(029) INP(176) INP(177) INP(179) INP(186) INP(1fd)
|
||||
|
||||
// prototype for input bits
|
||||
#define INP(nnn) extern UINT8 CpsInp##nnn[8];
|
||||
CPSINPSET
|
||||
#undef INP
|
||||
|
||||
#define INP(nnn) extern UINT8 Inp##nnn;
|
||||
CPSINPSET
|
||||
#undef INP
|
||||
|
||||
#define CPSINPEX INP(c000) INP(c001) INP(c002) INP(c003)
|
||||
|
||||
#define INP(nnnn) extern UINT8 CpsInp##nnnn[8];
|
||||
CPSINPEX
|
||||
#undef INP
|
||||
|
||||
// For the Forgotten Worlds analog controls
|
||||
extern UINT16 CpsInp055, CpsInp05d;
|
||||
extern UINT16 CpsInpPaddle1, CpsInpPaddle2;
|
||||
|
||||
extern INT32 PangEEP;
|
||||
extern INT32 Forgottn;
|
||||
extern INT32 Cps1QsHack;
|
||||
extern INT32 Kodh;
|
||||
extern INT32 Cawingb;
|
||||
extern INT32 Wofh;
|
||||
extern INT32 Sf2thndr;
|
||||
extern INT32 Pzloop2;
|
||||
extern INT32 Ssf2tb;
|
||||
extern INT32 Dinopic;
|
||||
extern INT32 Dinohunt;
|
||||
extern INT32 Port6SoundWrite;
|
||||
|
||||
extern UINT8* CpsEncZRom;
|
||||
|
||||
INT32 CpsRwInit();
|
||||
INT32 CpsRwExit();
|
||||
INT32 CpsRwGetInp();
|
||||
UINT8 __fastcall CpsReadByte(UINT32 a);
|
||||
void __fastcall CpsWriteByte(UINT32 a, UINT8 d);
|
||||
UINT16 __fastcall CpsReadWord(UINT32 a);
|
||||
void __fastcall CpsWriteWord(UINT32 a, UINT16 d);
|
||||
|
||||
// cps_draw.cpp
|
||||
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
|
||||
extern INT32 nStartline, nEndline; // specify the vertical slice of the screen to render
|
||||
extern INT32 nRasterline[MAX_RASTER + 2]; // The lines at which an interrupt occurs
|
||||
extern INT32 MaskAddr[4];
|
||||
extern INT32 CpsLayer1XOffs;
|
||||
extern INT32 CpsLayer2XOffs;
|
||||
extern INT32 CpsLayer3XOffs;
|
||||
extern INT32 CpsLayer1YOffs;
|
||||
extern INT32 CpsLayer2YOffs;
|
||||
extern INT32 CpsLayer3YOffs;
|
||||
void DrawFnInit();
|
||||
INT32 CpsDraw();
|
||||
INT32 CpsRedraw();
|
||||
|
||||
INT32 QsndInit();
|
||||
void QsndExit();
|
||||
void QsndReset();
|
||||
void QsndNewFrame();
|
||||
void QsndEndFrame();
|
||||
void QsndSyncZ80();
|
||||
INT32 QsndScan(INT32 nAction);
|
||||
|
||||
// qs_z.cpp
|
||||
INT32 QsndZInit();
|
||||
INT32 QsndZExit();
|
||||
INT32 QsndZScan(INT32 nAction);
|
||||
|
||||
// qs_c.cpp
|
||||
INT32 QscInit(INT32 nRate, INT32 nVolumeShift);
|
||||
void QscReset();
|
||||
void QscExit();
|
||||
INT32 QscScan(INT32 nAction);
|
||||
void QscNewFrame();
|
||||
void QscWrite(INT32 a, INT32 d);
|
||||
INT32 QscUpdate(INT32 nEnd);
|
||||
|
||||
// cps_tile.cpp
|
||||
extern UINT32* CpstPal;
|
||||
extern UINT32 nCpstType; extern INT32 nCpstX,nCpstY;
|
||||
extern UINT32 nCpstTile; extern INT32 nCpstFlip;
|
||||
extern short* CpstRowShift;
|
||||
extern UINT32 CpstPmsk; // Pixel mask
|
||||
|
||||
inline static void CpstSetPal(INT32 nPal)
|
||||
{
|
||||
nPal <<= 4;
|
||||
nPal &= 0x7F0;
|
||||
CpstPal= CpsPal + nPal;
|
||||
}
|
||||
|
||||
// ctv.cpp
|
||||
extern INT32 nBgHi;
|
||||
extern UINT16 ZValue;
|
||||
extern UINT16 *ZBuf;
|
||||
extern UINT16 *pZVal;
|
||||
extern UINT32 nCtvRollX,nCtvRollY;
|
||||
extern UINT8 *pCtvTile; // Pointer to tile data
|
||||
extern INT32 nCtvTileAdd; // Amount to add after each tile line
|
||||
extern UINT8 *pCtvLine; // Pointer to output bitmap
|
||||
typedef INT32 (*CtvDoFn)();
|
||||
typedef INT32 (*CpstOneDoFn)();
|
||||
extern CtvDoFn CtvDoX[0x20];
|
||||
extern CtvDoFn CtvDoXM[0x20];
|
||||
extern CtvDoFn CtvDoXB[0x20];
|
||||
extern CpstOneDoFn CpstOneDoX[3];
|
||||
extern CpstOneDoFn CpstOneObjDoX[2];
|
||||
INT32 CtvReady();
|
||||
|
||||
// nCpstType constants
|
||||
// To get size do (nCpstType & 24) + 8
|
||||
#define CTT_FLIPX ( 1)
|
||||
#define CTT_CARE ( 2)
|
||||
#define CTT_ROWS ( 4)
|
||||
#define CTT_8X8 ( 0)
|
||||
#define CTT_16X16 ( 8)
|
||||
#define CTT_32X32 (24)
|
||||
|
||||
// cps_obj.cpp
|
||||
extern INT32 nCpsObjectBank;
|
||||
|
||||
extern UINT8 *BootlegSpriteRam;
|
||||
|
||||
extern INT32 Sf2Hack;
|
||||
|
||||
INT32 CpsObjInit();
|
||||
INT32 CpsObjExit();
|
||||
INT32 CpsObjGet();
|
||||
void CpsObjDrawInit();
|
||||
INT32 Cps1ObjDraw(INT32 nLevelFrom,INT32 nLevelTo);
|
||||
INT32 Cps2ObjDraw(INT32 nLevelFrom,INT32 nLevelTo);
|
||||
|
||||
// cps_scr.cpp
|
||||
#define SCROLL_2 0
|
||||
#define SCROLL_3 1
|
||||
extern INT32 Ghouls;
|
||||
extern INT32 Mercs;
|
||||
extern INT32 Sf2jc;
|
||||
extern INT32 Ssf2t;
|
||||
extern INT32 Qad;
|
||||
extern INT32 Xmcota;
|
||||
|
||||
extern INT32 Scroll1TileMask;
|
||||
extern INT32 Scroll2TileMask;
|
||||
extern INT32 Scroll3TileMask;
|
||||
INT32 Cps1Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
INT32 Cps1Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
INT32 Cps2Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
INT32 Cps2Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy);
|
||||
|
||||
// cpsr.cpp
|
||||
extern UINT8 *CpsrBase; // Tile data base
|
||||
extern INT32 nCpsrScrX,nCpsrScrY; // Basic scroll info
|
||||
extern UINT16 *CpsrRows; // Row scroll table, 0x400 words long
|
||||
extern INT32 nCpsrRowStart; // Start of row scroll (can wrap?)
|
||||
|
||||
// Information needed to draw a line
|
||||
struct CpsrLineInfo {
|
||||
INT32 nStart; // 0-0x3ff - where to start drawing tiles from
|
||||
INT32 nWidth; // 0-0x400 - width of scroll shifts
|
||||
// e.g. for no rowscroll at all, nWidth=0
|
||||
INT32 nTileStart; // Range of tiles which are visible onscreen
|
||||
INT32 nTileEnd; // (e.g. 0x20 -> 0x50 , wraps around to 0x10)
|
||||
INT16 Rows[16]; // 16 row scroll values for this line
|
||||
INT32 nMaxLeft, nMaxRight; // Maximum row shifts left and right
|
||||
};
|
||||
extern struct CpsrLineInfo CpsrLineInfo[15];
|
||||
INT32 Cps1rPrepare();
|
||||
INT32 Cps2rPrepare();
|
||||
|
||||
// cpsrd.cpp
|
||||
INT32 Cps1rRender();
|
||||
INT32 Cps2rRender();
|
||||
|
||||
// dc_input.cpp
|
||||
extern struct BurnInputInfo CpsFsi[0x1B];
|
||||
|
||||
// ps.cpp
|
||||
extern UINT8 PsndCode, PsndFade; // Sound code/fade sent to the z80 program
|
||||
INT32 PsndInit();
|
||||
INT32 PsndExit();
|
||||
void PsndNewFrame();
|
||||
INT32 PsndSyncZ80(INT32 nCycles);
|
||||
INT32 PsndScan(INT32 nAction);
|
||||
|
||||
// ps_z.cpp
|
||||
INT32 PsndZInit();
|
||||
INT32 PsndZExit();
|
||||
INT32 PsndZScan(INT32 nAction);
|
||||
extern INT32 Kodb;
|
||||
|
||||
// ps_m.cpp
|
||||
extern INT32 bPsmOkay; // 1 if the module is okay
|
||||
INT32 PsmInit();
|
||||
INT32 PsmExit();
|
||||
void PsmNewFrame();
|
||||
INT32 PsmUpdate(INT32 nEnd);
|
||||
|
||||
// kabuki.cpp
|
||||
void wof_decode();
|
||||
void dino_decode();
|
||||
void punisher_decode();
|
||||
void slammast_decode();
|
||||
|
||||
// cps2_crypt.cpp
|
||||
void cps2_decrypt_game_data();
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,490 @@
|
|||
#include "cps.h"
|
||||
// CPS - Draw
|
||||
|
||||
UINT8 CpsRecalcPal = 0; // Flag - If it is 1, recalc the whole palette
|
||||
|
||||
static INT32 LayerCont;
|
||||
INT32 nStartline, nEndline;
|
||||
INT32 nRasterline[MAX_RASTER + 2];
|
||||
|
||||
INT32 nCpsLcReg = 0; // Address of layer controller register
|
||||
INT32 CpsLayEn[6] = {0, 0, 0, 0, 0, 0}; // bits for layer enable
|
||||
INT32 MaskAddr[4] = {0, 0, 0, 0};
|
||||
|
||||
INT32 CpsLayer1XOffs = 0;
|
||||
INT32 CpsLayer2XOffs = 0;
|
||||
INT32 CpsLayer3XOffs = 0;
|
||||
INT32 CpsLayer1YOffs = 0;
|
||||
INT32 CpsLayer2YOffs = 0;
|
||||
INT32 CpsLayer3YOffs = 0;
|
||||
|
||||
static void Cps1Layers();
|
||||
static void Cps2Layers();
|
||||
|
||||
typedef INT32 (*CpsObjDrawDoFn)(INT32,INT32);
|
||||
typedef INT32 (*CpsScrXDrawDoFn)(UINT8 *,INT32,INT32);
|
||||
typedef void (*CpsLayersDoFn)();
|
||||
typedef INT32 (*CpsrPrepareDoFn)();
|
||||
typedef INT32 (*CpsrRenderDoFn)();
|
||||
|
||||
CpsObjDrawDoFn CpsObjDrawDoX;
|
||||
CpsScrXDrawDoFn CpsScr1DrawDoX;
|
||||
CpsScrXDrawDoFn CpsScr3DrawDoX;
|
||||
CpsLayersDoFn CpsLayersDoX;
|
||||
CpsrPrepareDoFn CpsrPrepareDoX;
|
||||
CpsrRenderDoFn CpsrRenderDoX;
|
||||
|
||||
void DrawFnInit()
|
||||
{
|
||||
if(Cps == 2) {
|
||||
CpsLayersDoX = Cps2Layers;
|
||||
CpsScr1DrawDoX = Cps2Scr1Draw;
|
||||
CpsScr3DrawDoX = Cps2Scr3Draw;
|
||||
CpsObjDrawDoX = Cps2ObjDraw;
|
||||
CpsrPrepareDoX = Cps2rPrepare;
|
||||
CpsrRenderDoX = Cps2rRender;
|
||||
} else {
|
||||
CpsLayersDoX = Cps1Layers;
|
||||
CpsScr1DrawDoX = Cps1Scr1Draw;
|
||||
CpsScr3DrawDoX = Cps1Scr3Draw;
|
||||
CpsObjDrawDoX = Cps1ObjDraw;
|
||||
CpsrPrepareDoX = Cps1rPrepare;
|
||||
CpsrRenderDoX = Cps1rRender;
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrawScroll1(INT32 i)
|
||||
{
|
||||
// Draw Scroll 1
|
||||
INT32 nOff, nScrX, nScrY;
|
||||
UINT8 *Find;
|
||||
|
||||
nOff = *((UINT16 *)(CpsSaveReg[i] + 0x02));
|
||||
|
||||
// Get scroll coordinates
|
||||
nScrX = *((UINT16 *)(CpsSaveReg[i] + 0x0c)); // Scroll 1 X
|
||||
nScrY = *((UINT16 *)(CpsSaveReg[i] + 0x0e)); // Scroll 1 Y
|
||||
|
||||
nScrX += 0x40;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("1 %x, %x, %x\n"), nOff, nScrX, nScrY);
|
||||
|
||||
nScrX += CpsLayer1XOffs;
|
||||
nScrY += 0x10;
|
||||
nScrY += CpsLayer1YOffs;
|
||||
nOff <<= 8;
|
||||
nOff &= 0xffc000;
|
||||
Find = CpsFindGfxRam(nOff, 0x4000);
|
||||
if (Find == NULL) {
|
||||
return 1;
|
||||
}
|
||||
CpsScr1DrawDoX(Find, nScrX, nScrY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrawScroll2Init(INT32 i)
|
||||
{
|
||||
// Draw Scroll 2
|
||||
INT32 nScr2Off; INT32 n;
|
||||
|
||||
nScr2Off = *((UINT16 *)(CpsSaveReg[i] + 0x04));
|
||||
|
||||
// Get scroll coordinates
|
||||
nCpsrScrX= *((UINT16 *)(CpsSaveReg[i] + 0x10)); // Scroll 2 X
|
||||
nCpsrScrY= *((UINT16 *)(CpsSaveReg[i] + 0x12)); // Scroll 2 Ytess
|
||||
|
||||
// Get row scroll information
|
||||
n = *((UINT16 *)(CpsSaveReg[i] + 0x22));
|
||||
|
||||
nScr2Off <<= 8;
|
||||
|
||||
nCpsrScrX += 0x40;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("2 %x, %x, %x\n"), nScr2Off, nCpsrScrX, nCpsrScrY);
|
||||
|
||||
nCpsrScrX += CpsLayer2XOffs;
|
||||
nCpsrScrX &= 0x03FF;
|
||||
|
||||
nCpsrScrY += 0x10;
|
||||
nCpsrScrY += CpsLayer2YOffs;
|
||||
nCpsrScrY &= 0x03FF;
|
||||
|
||||
nScr2Off &= 0xFFC000;
|
||||
CpsrBase = CpsFindGfxRam(nScr2Off, 0x4000);
|
||||
if (CpsrBase == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CpsrRows = NULL;
|
||||
|
||||
if (n & 1) {
|
||||
INT32 nTab, nStart;
|
||||
// Find row scroll table:
|
||||
|
||||
nTab = *((UINT16 *)(CpsSaveReg[i] + 0x08));
|
||||
nStart = *((UINT16 *)(CpsSaveReg[i] + 0x20));
|
||||
|
||||
nTab <<= 8;
|
||||
nTab &= 0xFFF800; // Vampire - Row scroll effect in VS screen background
|
||||
|
||||
CpsrRows = (UINT16 *)CpsFindGfxRam(nTab, 0x0800);
|
||||
|
||||
// Find start offset
|
||||
nCpsrRowStart = nStart + 16;
|
||||
}
|
||||
|
||||
CpsrPrepareDoX();
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 DrawScroll2Exit()
|
||||
{
|
||||
CpsrBase = NULL;
|
||||
nCpsrScrX = 0;
|
||||
nCpsrScrY = 0;
|
||||
CpsrRows = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 DrawScroll2Do()
|
||||
{
|
||||
if (CpsrBase == NULL) {
|
||||
return 1;
|
||||
}
|
||||
CpsrRenderDoX();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrawScroll3(INT32 i)
|
||||
{
|
||||
// Draw Scroll 3
|
||||
INT32 nOff, nScrX, nScrY;
|
||||
UINT8 *Find;
|
||||
|
||||
nOff = *((UINT16 *)(CpsSaveReg[i] + 0x06));
|
||||
|
||||
// Get scroll coordinates
|
||||
nScrX = *((UINT16 *)(CpsSaveReg[i] + 0x14)); // Scroll 3 X
|
||||
nScrY = *((UINT16 *)(CpsSaveReg[i] + 0x16)); // Scroll 3 Y
|
||||
|
||||
nScrX += 0x40;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("3 %x, %x, %x\n"), nOff, nScrX, nScrY);
|
||||
|
||||
nScrX += CpsLayer3XOffs;
|
||||
nScrY += 0x10;
|
||||
nScrY += CpsLayer3YOffs;
|
||||
|
||||
nOff <<= 8;
|
||||
nOff &= 0xffc000;
|
||||
Find=CpsFindGfxRam(nOff, 0x4000);
|
||||
if (Find == NULL) {
|
||||
return 1;
|
||||
}
|
||||
CpsScr3DrawDoX(Find, nScrX, nScrY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrawStar(INT32 nLayer)
|
||||
{
|
||||
INT32 nStar, nStarXPos, nStarYPos, nStarColour;
|
||||
UINT8* pStar = CpsStar + (nLayer << 12);
|
||||
|
||||
for (nStar = 0; nStar < 0x1000; nStar++) {
|
||||
nStarColour = pStar[nStar];
|
||||
|
||||
if (nStarColour != 0x0F) {
|
||||
nStarXPos = (((nStar >> 8) << 5) - *((INT16*)(CpsSaveReg[0] + 0x18 + (nLayer << 2))) + (nStarColour & 0x1F) - 64) & 0x01FF;
|
||||
nStarYPos = ((nStar & 0xFF) - *((INT16*)(CpsSaveReg[0] + 0x1A + (nLayer << 2))) - 16) & 0xFF;
|
||||
|
||||
if (nStarXPos < 384 && nStarYPos < 224) {
|
||||
nStarColour = ((nStarColour & 0xE0) >> 1) + ((GetCurrentFrame() >> 4) & 0x0F);
|
||||
PutPix(pBurnDraw + (nBurnPitch * nStarYPos) + (nBurnBpp * nStarXPos), CpsPal[0x0800 + (nLayer << 9) + nStarColour]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Cps1Layers()
|
||||
{
|
||||
INT32 Draw[4]={-1,-1,-1,-1};
|
||||
INT32 nDrawMask=0;
|
||||
INT32 i=0;
|
||||
|
||||
nDrawMask=1; // Sprites always on
|
||||
LayerCont = *((UINT16 *)(CpsSaveReg[0] + nCpsLcReg));
|
||||
// Get correct bits from Layer Controller
|
||||
if (LayerCont & CpsLayEn[1]) nDrawMask|=2;
|
||||
if (LayerCont & CpsLayEn[2]) nDrawMask|=4;
|
||||
if (LayerCont & CpsLayEn[3]) nDrawMask|=8;
|
||||
nDrawMask&=nBurnLayer; // User choice of layers to display
|
||||
|
||||
// Layer control:
|
||||
Draw[0]=(LayerCont>>12)&3; // top layer
|
||||
Draw[1]=(LayerCont>>10)&3;
|
||||
Draw[2]=(LayerCont>> 8)&3;
|
||||
Draw[3]=(LayerCont>> 6)&3; // bottom layer (most covered up)
|
||||
|
||||
// Check for repeated layers and if there are any, the lower layer is omitted
|
||||
#define CRP(a,b) if (Draw[a]==Draw[b]) Draw[b]=-1;
|
||||
CRP(0,1) CRP(0,2) CRP(0,3) CRP(1,2) CRP(1,3) CRP(2,3)
|
||||
#undef CRP
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (LayerCont & CpsLayEn[4 + i]) {
|
||||
CpsStarPalUpdate(CpsSavePal, i, CpsRecalcPal);
|
||||
DrawStar(i);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare layer 2
|
||||
DrawScroll2Init(0);
|
||||
|
||||
// draw layers, bottom -> top
|
||||
for (i=3;i>=0;i--)
|
||||
{
|
||||
INT32 n=Draw[i]; // Find out which layer to draw
|
||||
|
||||
if (n==0) {
|
||||
if (nDrawMask & 1) CpsObjDrawDoX(0,7);
|
||||
|
||||
if (!Mercs && !Sf2jc && !Qad) {
|
||||
nBgHi=1;
|
||||
switch (Draw[i+1]) {
|
||||
case 1:
|
||||
if (nDrawMask & 2) DrawScroll1(0);
|
||||
break;
|
||||
case 2:
|
||||
if (nDrawMask & 4) DrawScroll2Do();
|
||||
break;
|
||||
case 3:
|
||||
if (nDrawMask & 8) DrawScroll3(0);
|
||||
break;
|
||||
}
|
||||
nBgHi=0;
|
||||
}
|
||||
}
|
||||
|
||||
// Then Draw the scroll layer on top
|
||||
switch (n) {
|
||||
case 1:
|
||||
if (nDrawMask & 2) DrawScroll1(0);
|
||||
break;
|
||||
case 2:
|
||||
if (nDrawMask & 4) DrawScroll2Do();
|
||||
break;
|
||||
case 3:
|
||||
if (nDrawMask & 8) DrawScroll3(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DrawScroll2Exit();
|
||||
}
|
||||
|
||||
static void Cps2Layers()
|
||||
{
|
||||
INT32 Draw[MAX_RASTER][4];
|
||||
INT32 Prio[MAX_RASTER][4];
|
||||
INT32 nDrawMask[MAX_RASTER];
|
||||
|
||||
CpsObjDrawInit();
|
||||
|
||||
INT32 nSlice = 0;
|
||||
do {
|
||||
LayerCont = *((UINT16 *)(CpsSaveReg[nSlice] + nCpsLcReg));
|
||||
|
||||
// Determine which layers are enabled
|
||||
nDrawMask[nSlice] = 1; // Sprites always on
|
||||
if (LayerCont & CpsLayEn[1]) nDrawMask[nSlice] |= 2;
|
||||
if (LayerCont & CpsLayEn[2]) nDrawMask[nSlice] |= 4;
|
||||
if (LayerCont & CpsLayEn[3]) nDrawMask[nSlice] |= 8;
|
||||
nDrawMask[nSlice] &= nBurnLayer; // User choice of layers to display
|
||||
|
||||
// Determine layerö priority:
|
||||
Draw[nSlice][3] = (LayerCont >> 12) & 3; // top layer
|
||||
Draw[nSlice][2] = (LayerCont >> 10) & 3;
|
||||
Draw[nSlice][1] = (LayerCont >> 8) & 3;
|
||||
Draw[nSlice][0] = (LayerCont >> 6) & 3; // bottom layer (most covered up)
|
||||
|
||||
// Determine layer-sprite priority (layer >= sprites -> layer on top)
|
||||
INT32 nLayPri = (CpsSaveFrg[nSlice][4] << 8) | CpsSaveFrg[nSlice][5]; // Layer priority register at word (400004)
|
||||
Prio[nSlice][3] = (nLayPri >> 12) & 7;
|
||||
Prio[nSlice][2] = (nLayPri >> 8) & 7;
|
||||
Prio[nSlice][1] = (nLayPri >> 4) & 7;
|
||||
Prio[nSlice][0] = 0;
|
||||
|
||||
// Check for repeated layers (if found, discard the lower layer)
|
||||
#define CRP(a, b) if (Draw[nSlice][a] == Draw[nSlice][b]) Draw[nSlice][b] = -1;
|
||||
CRP(3, 2) CRP(3, 1) CRP(2, 1) CRP(3, 0) CRP(2, 0) CRP(1, 0)
|
||||
#undef CRP
|
||||
|
||||
// Pre-process priorities
|
||||
// Higher priority layers must have higher layer-sprite priorities
|
||||
// N.B. If this is not the case, masking effects may occur (not emulated)
|
||||
#if 0
|
||||
// Raise sprite priorities of top layers if needed
|
||||
INT32 nHighPrio = 0;
|
||||
for (INT32 i = 0; i < 4; i++) {
|
||||
if (Draw[nSlice][i] > 0) {
|
||||
if (Prio[nSlice][Draw[nSlice][i]] < nHighPrio) {
|
||||
Prio[nSlice][Draw[nSlice][i]] = nHighPrio;
|
||||
} else {
|
||||
nHighPrio = Prio[nSlice][Draw[nSlice][i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Lower sprite priorities of bottom layers if needed
|
||||
INT32 nHighPrio = 9999;
|
||||
for (INT32 i = 3; i >= 0; i--) {
|
||||
if (Draw[nSlice][i] > 0) {
|
||||
if (Prio[nSlice][Draw[nSlice][i]] > nHighPrio) {
|
||||
Prio[nSlice][Draw[nSlice][i]] = nHighPrio;
|
||||
} else {
|
||||
nHighPrio = Prio[nSlice][Draw[nSlice][i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nSlice++;
|
||||
} while (nSlice < MAX_RASTER && nRasterline[nSlice]);
|
||||
|
||||
INT32 nPrevPrio = -1;
|
||||
for (INT32 nCurrPrio = 0; nCurrPrio < 8; nCurrPrio++) {
|
||||
|
||||
nSlice = 0;
|
||||
do {
|
||||
for (INT32 i = 0; i < 4; i++) {
|
||||
|
||||
if (Prio[nSlice][Draw[nSlice][i]] == nCurrPrio) {
|
||||
|
||||
// Render sprites between the previous layer and this one
|
||||
if ((nDrawMask[0] & 1) && (nPrevPrio < nCurrPrio)) {
|
||||
CpsObjDrawDoX(nPrevPrio + 1, nCurrPrio);
|
||||
nPrevPrio = nCurrPrio;
|
||||
}
|
||||
|
||||
nStartline = nRasterline[nSlice];
|
||||
nEndline = nRasterline[nSlice + 1];
|
||||
if (!nEndline) {
|
||||
nEndline = 224;
|
||||
}
|
||||
|
||||
// Render layer
|
||||
switch (Draw[nSlice][i]) {
|
||||
case 1:
|
||||
if (nDrawMask[nSlice] & 2) {
|
||||
DrawScroll1(nSlice);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (nDrawMask[nSlice] & 4) {
|
||||
DrawScroll2Init(nSlice);
|
||||
DrawScroll2Do();
|
||||
DrawScroll2Exit();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (nDrawMask[nSlice] & 8) {
|
||||
DrawScroll3(nSlice);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
nSlice++;
|
||||
} while (nSlice < MAX_RASTER && nRasterline[nSlice]);
|
||||
}
|
||||
|
||||
// Render highest priority sprites
|
||||
if ((nDrawMask[0] & 1) && (nPrevPrio < 7)) {
|
||||
CpsObjDrawDoX(nPrevPrio + 1, 7);
|
||||
}
|
||||
}
|
||||
|
||||
void CpsClearScreen()
|
||||
{
|
||||
if (Cps == 1) {
|
||||
switch (nBurnBpp) {
|
||||
case 4: {
|
||||
UINT32* pClear = (UINT32*)pBurnDraw;
|
||||
UINT32 nColour = CpsPal[0xbff ^ 15];
|
||||
for (INT32 i = 0; i < 384 * 224 / 8; i++) {
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
UINT8* pClear = pBurnDraw;
|
||||
UINT8 r = CpsPal[0xbff ^ 15];
|
||||
UINT8 g = (r >> 8) & 0xFF;
|
||||
UINT8 b = (r >> 16) & 0xFF;
|
||||
r &= 0xFF;
|
||||
for (INT32 i = 0; i < 384 * 224; i++) {
|
||||
*pClear++ = r;
|
||||
*pClear++ = g;
|
||||
*pClear++ = b;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
UINT32* pClear = (UINT32*)pBurnDraw;
|
||||
UINT32 nColour = CpsPal[0xbff ^ 15] | CpsPal[0xbff ^ 15] << 16;
|
||||
for (INT32 i = 0; i < 384 * 224 / 16; i++) {
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset(pBurnDraw, 0, 384 * 224 * nBurnBpp);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoDraw(INT32 Recalc)
|
||||
{
|
||||
CtvReady(); // Point to correct tile drawing functions
|
||||
|
||||
// Update Palette
|
||||
CpsPalUpdate(CpsSavePal, Recalc); // recalc whole palette if needed
|
||||
|
||||
CpsClearScreen();
|
||||
|
||||
CpsLayersDoX();
|
||||
}
|
||||
|
||||
INT32 CpsDraw()
|
||||
{
|
||||
DoDraw(CpsRecalcPal);
|
||||
|
||||
CpsRecalcPal = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsRedraw()
|
||||
{
|
||||
DoDraw(1);
|
||||
|
||||
CpsRecalcPal = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,427 @@
|
|||
#include "cps.h"
|
||||
// CPS - Memory
|
||||
|
||||
UINT32 CpsMProt[4];
|
||||
UINT32 CpsBID[3];
|
||||
|
||||
static UINT8 *CpsMem=NULL,*CpsMemEnd=NULL;
|
||||
UINT8 *CpsRam90=NULL;
|
||||
UINT8 *CpsZRamC0=NULL,*CpsZRamF0=NULL,*CpsEncZRom=NULL;
|
||||
UINT8 *CpsSavePal=NULL;
|
||||
UINT8 *CpsSaveReg[MAX_RASTER + 1];
|
||||
UINT8 *CpsSaveFrg[MAX_RASTER + 1];
|
||||
static UINT8 *CpsSaveRegData = NULL;
|
||||
static UINT8 *CpsSaveFrgData = NULL;
|
||||
UINT8 *CpsRam660=NULL,*CpsRam708=NULL,*CpsReg=NULL,*CpsFrg=NULL;
|
||||
UINT8 *CpsRamFF=NULL;
|
||||
|
||||
// This routine is called first to determine how much memory is needed
|
||||
// and then to set up all the pointers.
|
||||
static INT32 CpsMemIndex()
|
||||
{
|
||||
UINT8* Next; Next = CpsMem;
|
||||
|
||||
CpsRam90 = Next; Next += 0x030000; // Video Ram
|
||||
CpsRamFF = Next; Next += 0x010000; // Work Ram
|
||||
CpsReg = Next; Next += 0x000100; // Registers
|
||||
|
||||
CpsSavePal = Next; Next += 0x002000; // Draw Copy of Correct Palette
|
||||
|
||||
if (Cps == 2 || Cps1Qs == 1) {
|
||||
CpsZRamC0 = Next; Next += 0x001000; // Z80 c000-cfff
|
||||
CpsZRamF0 = Next; Next += 0x001000; // Z80 f000-ffff
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
CpsRam660 = Next; Next += 0x004000; // Extra Memory
|
||||
CpsRam708 = Next; Next += 0x010000; // Obj Ram
|
||||
CpsFrg = Next; Next += 0x000010; // 'Four' Registers (Registers at 0x400000)
|
||||
|
||||
ZBuf = (UINT16*)Next; Next += 384 * 224 * 2; // Sprite Masking Z buffer
|
||||
|
||||
CpsSaveRegData = Next; Next += 0x0100 * (MAX_RASTER + 1); // Draw Copy of registers
|
||||
CpsSaveFrgData = Next; Next += 0x0010 * (MAX_RASTER + 1); // Draw Copy of 'Four' Registers
|
||||
|
||||
for (INT32 i = 0; i < MAX_RASTER + 1; i++) {
|
||||
CpsSaveReg[i] = CpsSaveRegData + i * 0x0100;
|
||||
CpsSaveFrg[i] = CpsSaveFrgData + i * 0x0010;
|
||||
}
|
||||
|
||||
} else {
|
||||
CpsSaveRegData = Next; Next += 0x0100; // Draw Copy of registers
|
||||
CpsSaveFrgData = Next; Next += 0x0010; // Draw Copy of 'Four' Registers
|
||||
|
||||
CpsSaveReg[0] = CpsSaveRegData;
|
||||
CpsSaveFrg[0] = CpsSaveFrgData;
|
||||
}
|
||||
|
||||
CpsMemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 AllocateMemory()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
CpsMem = NULL; // Find out how much memory is needed
|
||||
CpsMemIndex();
|
||||
nLen = CpsMemEnd - (UINT8*)0;
|
||||
|
||||
if ((CpsMem = (UINT8*)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(CpsMem, 0, nLen); // blank all memory
|
||||
CpsMemIndex(); // Index the allocated memory
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Map the correct bank of obj memory to the 68000 address space (including mirrors).
|
||||
void CpsMapObjectBanks(INT32 nBank)
|
||||
{
|
||||
if (nBank != nCpsObjectBank) {
|
||||
nCpsObjectBank = nBank;
|
||||
|
||||
if (nCpsObjectBank) {
|
||||
SekMapMemory(CpsRam708 + 0x8000, 0x708000, 0x709FFF, SM_RAM);
|
||||
SekMapMemory(CpsRam708 + 0x8000, 0x70A000, 0x70BFFF, SM_RAM);
|
||||
SekMapMemory(CpsRam708 + 0x8000, 0x70C000, 0x70DFFF, SM_RAM);
|
||||
SekMapMemory(CpsRam708 + 0x8000, 0x70E000, 0x70FFFF, SM_RAM);
|
||||
} else {
|
||||
SekMapMemory(CpsRam708, 0x708000, 0x709FFF, SM_RAM);
|
||||
SekMapMemory(CpsRam708, 0x70A000, 0x70BFFF, SM_RAM);
|
||||
SekMapMemory(CpsRam708, 0x70C000, 0x70DFFF, SM_RAM);
|
||||
SekMapMemory(CpsRam708, 0x70E000, 0x70FFFF, SM_RAM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT32 __fastcall CPSResetCallback()
|
||||
{
|
||||
// Reset instruction on 68000
|
||||
if (!Cps1Pic) ZetReset(); // Reset Z80 (CPU #1)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
UINT8 __fastcall CPSQSoundC0ReadByte(UINT32 sekAddress)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" QS %06X read\n"), sekAddress);
|
||||
|
||||
if (!(sekAddress & 1)) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
QsndSyncZ80();
|
||||
|
||||
sekAddress &= 0x1FFF;
|
||||
return CpsZRamC0[sekAddress >> 1];
|
||||
}
|
||||
|
||||
void __fastcall CPSQSoundC0WriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" QS %06X -> %02X\n"), sekAddress, byteValue);
|
||||
|
||||
if (!(sekAddress & 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sekAddress &= 0x1FFF;
|
||||
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
// Sync only when the last byte of the sound command is written
|
||||
if (sekAddress == 0x001F) {
|
||||
QsndSyncZ80();
|
||||
}
|
||||
#else
|
||||
QsndSyncZ80();
|
||||
#endif
|
||||
|
||||
CpsZRamC0[sekAddress >> 1] = byteValue;
|
||||
}
|
||||
|
||||
UINT8 __fastcall CPSQSoundF0ReadByte(UINT32 sekAddress)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" QS %06X read\n"), sekAddress);
|
||||
|
||||
if (!(sekAddress & 1)) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
QsndSyncZ80();
|
||||
|
||||
sekAddress &= 0x1FFF;
|
||||
return CpsZRamF0[sekAddress >> 1];
|
||||
}
|
||||
|
||||
void __fastcall CPSQSoundF0WriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" QS %06X -> %02X\n"), sekAddress, byteValue);
|
||||
|
||||
if (!(sekAddress & 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sekAddress &= 0x1FFF;
|
||||
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
// Sync only when the last byte of the sound command is written
|
||||
if (sekAddress == 0x001F) {
|
||||
QsndSyncZ80();
|
||||
}
|
||||
#else
|
||||
QsndSyncZ80();
|
||||
#endif
|
||||
|
||||
CpsZRamF0[sekAddress >> 1] = byteValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
UINT8 __fastcall CPSExtraNVRAMReadByte(UINT32 sekAddress)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" - 0x%06X read.\n"), sekAddress);
|
||||
|
||||
sekAddress &= 0x3FFF;
|
||||
return CpsRam660[sekAddress];
|
||||
}
|
||||
|
||||
void __fastcall CPSExtraNVRAMWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" - 0x%06X -> %02X\n"), sekAddress, byteValue);
|
||||
|
||||
sekAddress &= 0x3FFF;
|
||||
CpsRam660[sekAddress] = byteValue;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
INT32 prevline;
|
||||
|
||||
void __fastcall CpsWriteSpriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
if (prevline != SekCurrentScanline()) {
|
||||
prevline = SekCurrentScanline();
|
||||
// bprintf(PRINT_NORMAL, _T(" - sb (%3i)\n"), prevline);
|
||||
}
|
||||
|
||||
sekAddress &= 0x1FFF;
|
||||
CpsRam708[sekAddress + nCpsObjectBank * 0x8000] = byteValue;
|
||||
}
|
||||
|
||||
void __fastcall CpsWriteSpriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
if (prevline != SekCurrentScanline()) {
|
||||
prevline = SekCurrentScanline();
|
||||
// bprintf(PRINT_NORMAL, _T(" - sw (%3i)\n"), prevline);
|
||||
}
|
||||
|
||||
sekAddress &= 0x1FFE;
|
||||
CpsRam708[sekAddress + nCpsObjectBank * 0x8000 + 1] = wordValue >> 8;
|
||||
CpsRam708[sekAddress + nCpsObjectBank * 0x8000 + 0] = wordValue & 255;
|
||||
}
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
UINT8 __fastcall haxx0rReadByte(UINT32 sekAddress)
|
||||
{
|
||||
sekAddress &= 0xFFFF;
|
||||
bprintf(PRINT_NORMAL, _T(" QS %06X read (%02X)\n"), sekAddress, CpsEncZRom[sekAddress]);
|
||||
return CpsEncZRom[sekAddress];
|
||||
}
|
||||
|
||||
INT32 CpsMemInit()
|
||||
{
|
||||
if (AllocateMemory()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
SekSetResetCallback(CPSResetCallback);
|
||||
|
||||
// Map in memory:
|
||||
// 68000 Rom (as seen as is, through read)
|
||||
SekMapMemory(CpsRom, 0, nCpsRomLen - 1, SM_READ);
|
||||
|
||||
// 68000 Rom (as seen decrypted, through fetch)
|
||||
if (nCpsCodeLen > 0) {
|
||||
// Decoded part (up to nCpsCodeLen)
|
||||
SekMapMemory(CpsCode, 0, nCpsCodeLen - 1, SM_FETCH);
|
||||
}
|
||||
if (nCpsRomLen > nCpsCodeLen) {
|
||||
// The rest (up to nCpsRomLen)
|
||||
SekMapMemory(CpsRom + nCpsCodeLen, nCpsCodeLen, nCpsRomLen - 1, SM_FETCH);
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
nCpsObjectBank = -1;
|
||||
CpsMapObjectBanks(0);
|
||||
|
||||
#if 0
|
||||
SekMapHandler(3, 0x660000, 0x663FFF, SM_RAM);
|
||||
SekSetReadByteHandler(3, CPSExtraNVRAMReadByte);
|
||||
SekSetWriteByteHandler(3, CPSExtraNVRAMWriteByte);
|
||||
#else
|
||||
SekMapMemory(CpsRam660, 0x660000, 0x663FFF, SM_RAM);
|
||||
#endif
|
||||
|
||||
// SekMapHandler(4, 0x708000, 0x709FFF, SM_WRITE);
|
||||
// SekMapHandler(4, 0x70A000, 0x70BFFF, SM_WRITE);
|
||||
// SekMapHandler(4, 0x70C000, 0x70DFFF, SM_WRITE);
|
||||
// SekMapHandler(4, 0x70E000, 0x70FFFF, SM_WRITE);
|
||||
|
||||
// SekSetWriteByteHandler(4, CpsWriteSpriteByte);
|
||||
// SekSetWriteWordHandler(4, CpsWriteSpriteWord);
|
||||
}
|
||||
|
||||
SekMapMemory(CpsRam90, 0x900000, 0x92FFFF, SM_RAM); // Gfx Ram
|
||||
SekMapMemory(CpsRamFF, 0xFF0000, 0xFFFFFF, SM_RAM); // Work Ram
|
||||
|
||||
SekSetReadByteHandler(0, CpsReadByte);
|
||||
SekSetWriteByteHandler(0, CpsWriteByte);
|
||||
SekSetReadWordHandler(0, CpsReadWord);
|
||||
SekSetWriteWordHandler(0, CpsWriteWord);
|
||||
|
||||
// QSound
|
||||
if (Cps == 2) {
|
||||
SekMapHandler(1, 0x618000, 0x619FFF, SM_RAM);
|
||||
|
||||
SekSetReadByteHandler(1, CPSQSoundC0ReadByte);
|
||||
SekSetWriteByteHandler(1, CPSQSoundC0WriteByte);
|
||||
}
|
||||
|
||||
if (Cps1Qs == 1) {
|
||||
// Map the 1st 32KB of the QSound ROM into the 68K address space
|
||||
for (INT32 i = 0x7FFF; i >= 0; i--) {
|
||||
CpsEncZRom[(i << 1) + 0] = CpsEncZRom[i];
|
||||
CpsEncZRom[(i << 1) + 1] = 0xFF;
|
||||
}
|
||||
SekMapMemory(CpsEncZRom, 0xF00000, 0xF0FFFF, SM_ROM);
|
||||
|
||||
// QSound shared RAM
|
||||
SekMapHandler(1, 0xF18000, 0xF19FFF, SM_RAM);
|
||||
SekMapHandler(2, 0xF1E000, 0xF1FFFF, SM_RAM);
|
||||
|
||||
SekSetReadByteHandler(1, CPSQSoundC0ReadByte);
|
||||
SekSetWriteByteHandler(1, CPSQSoundC0WriteByte);
|
||||
SekSetReadByteHandler(2, CPSQSoundF0ReadByte);
|
||||
SekSetWriteByteHandler(2, CPSQSoundF0WriteByte);
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsMemExit()
|
||||
{
|
||||
#if 0
|
||||
FILE* fp = fopen("mem.raw", "wb");
|
||||
if (fp) {
|
||||
fwrite(CpsRam660, 1, 0x4000, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Deallocate all used memory
|
||||
if (CpsMem) {
|
||||
free(CpsMem);
|
||||
CpsMem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 ScanRam()
|
||||
{
|
||||
// scan ram:
|
||||
struct BurnArea ba;
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
|
||||
ba.Data = CpsRam90; ba.nLen = 0x030000; ba.szName = "CpsRam90"; BurnAcb(&ba);
|
||||
ba.Data = CpsRamFF; ba.nLen = 0x010000; ba.szName = "CpsRamFF"; BurnAcb(&ba);
|
||||
ba.Data = CpsReg; ba.nLen = 0x000100; ba.szName = "CpsReg"; BurnAcb(&ba);
|
||||
|
||||
if (Cps == 2 || Cps1Qs == 1) {
|
||||
ba.Data = CpsZRamC0; ba.nLen = 0x001000; ba.szName = "CpsZRamC0"; BurnAcb(&ba);
|
||||
ba.Data = CpsZRamF0; ba.nLen = 0x001000; ba.szName = "CpsZRamF0"; BurnAcb(&ba);
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
ba.Data = CpsRam708; ba.nLen = 0x010000; ba.szName = "CpsRam708"; BurnAcb(&ba);
|
||||
ba.Data = CpsFrg; ba.nLen = 0x000010; ba.szName = "CpsFrg"; BurnAcb(&ba);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan the current state of the CPS1/2 machine
|
||||
INT32 CpsAreaScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (CpsMem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x029521;
|
||||
}
|
||||
|
||||
if (nAction & ACB_MEMORY_ROM) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = CpsRom;
|
||||
ba.nLen = nCpsRomLen;
|
||||
ba.szName = "CpsRom";
|
||||
BurnAcb(&ba);
|
||||
|
||||
ba.Data = CpsZRom;
|
||||
ba.nLen = nCpsZRomLen;
|
||||
ba.szName = "CpsZRom";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
|
||||
if (Cps == 2 || Cps1Qs == 1 || PangEEP == 1) { // Scan EEPROM
|
||||
EEPROMScan(nAction, pnMin);
|
||||
}
|
||||
|
||||
if (nAction & ACB_MEMORY_RAM) {
|
||||
|
||||
ScanRam();
|
||||
|
||||
if (Cps == 2) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = CpsRam660;
|
||||
ba.nLen = 0x004000;
|
||||
ba.szName = "CpsRam660";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (nAction & ACB_DRIVER_DATA) { // Scan volatile variables/registers/RAM
|
||||
|
||||
SekScan(nAction); // Scan 68000 state
|
||||
|
||||
if (nAction & ACB_WRITE) { // Palette could have changed
|
||||
CpsRecalcPal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Cps == 2 || Cps1Qs == 1) { // Scan QSound chips
|
||||
QsndScan(nAction);
|
||||
} else { // Scan PSound chips
|
||||
PsndScan(nAction);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,401 @@
|
|||
#include "cps.h"
|
||||
// CPS Objs (sprites)
|
||||
|
||||
INT32 nCpsObjectBank;
|
||||
|
||||
UINT8 *BootlegSpriteRam = NULL;
|
||||
|
||||
INT32 Sf2Hack = 0;
|
||||
|
||||
// Our copy of the sprite table
|
||||
static UINT8 *ObjMem = NULL;
|
||||
|
||||
static INT32 nMax = 0;
|
||||
static INT32 nGetNext = 0;
|
||||
|
||||
static INT32 nMaxZValue;
|
||||
static INT32 nMaxZMask;
|
||||
|
||||
static INT32 nZOffset;
|
||||
|
||||
// Object frames, so you can lag the Objs by nFrameCount-1 frames
|
||||
struct ObjFrame {
|
||||
INT32 nShiftX, nShiftY;
|
||||
UINT8* Obj;
|
||||
INT32 nCount;
|
||||
};
|
||||
|
||||
static INT32 nFrameCount = 0;
|
||||
static struct ObjFrame of[3];
|
||||
|
||||
INT32 CpsObjInit()
|
||||
{
|
||||
nMax = 0x100; // CPS1 has 256 sprites
|
||||
|
||||
if (Cps == 2) { // CPS2 has 1024 sprites
|
||||
nMax = 0x400;
|
||||
}
|
||||
|
||||
nFrameCount = 2; // CPS2 sprites lagged by 1 frame and double buffered
|
||||
// CPS1 sprites lagged by 1 frame
|
||||
|
||||
ObjMem = (UINT8*)malloc((nMax << 3) * nFrameCount);
|
||||
if (ObjMem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set up the frame buffers
|
||||
for (INT32 i = 0; i < nFrameCount; i++) {
|
||||
of[i].Obj = ObjMem + (nMax << 3) * i;
|
||||
of[i].nCount = 0;
|
||||
}
|
||||
|
||||
nGetNext=0;
|
||||
|
||||
if (Cps == 2) {
|
||||
memset(ZBuf, 0, 384 * 224 * 2);
|
||||
nMaxZMask = nZOffset = 0;
|
||||
nMaxZValue = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsObjExit()
|
||||
{
|
||||
for (INT32 i = 0; i < nFrameCount; i++) {
|
||||
of[i].Obj = NULL;
|
||||
of[i].nCount = 0;
|
||||
}
|
||||
|
||||
if (ObjMem) {
|
||||
free(ObjMem);
|
||||
ObjMem = NULL;
|
||||
}
|
||||
|
||||
nFrameCount = 0;
|
||||
nMax = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get CPS sprites into Obj
|
||||
INT32 CpsObjGet()
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 *pg, *po;
|
||||
struct ObjFrame* pof;
|
||||
UINT8* Get = NULL;
|
||||
|
||||
pof = of + nGetNext;
|
||||
|
||||
pof->nCount = 0;
|
||||
|
||||
po = pof->Obj;
|
||||
pof->nShiftX = -0x40;
|
||||
pof->nShiftY = -0x10;
|
||||
|
||||
if (Cps == 2) {
|
||||
Get = CpsRam708 + ((nCpsObjectBank ^ 1) << 15); // Select CPS2 sprite buffer
|
||||
// Get = CpsRam708 + ((GetCurrentFrame() & 1) << 15); // Select CPS2 sprite buffer
|
||||
|
||||
pof->nShiftX = -CpsSaveFrg[0][0x9];
|
||||
pof->nShiftY = -CpsSaveFrg[0][0xB];
|
||||
} else {
|
||||
INT32 nOff = *((UINT16*)(CpsReg + 0x00)) << 8;
|
||||
nOff &= 0xfff800;
|
||||
Get = CpsFindGfxRam(nOff, 0x800);
|
||||
|
||||
if (Sf2Hack) {
|
||||
Get = CpsFindGfxRam(0x910000, 0x800);
|
||||
} else {
|
||||
if (Dinopic) {
|
||||
Get = BootlegSpriteRam + 0x1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Get==NULL) return 1;
|
||||
|
||||
// Make a copy of all active sprites in the list
|
||||
for (pg = Get, i = 0; i < nMax; pg += 8, i++) {
|
||||
UINT16* ps = (UINT16*)pg;
|
||||
|
||||
if (Cps == 2) {
|
||||
if (ps[1] & 0x8000) { // end of sprite list?
|
||||
break;
|
||||
}
|
||||
if (ps[0] == 0 && ps[1] == 0x0100 && ps[2] == 0 && ps[3] == 0xff00) { // Slammasters end of sprite list?
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (Dinopic) {
|
||||
if (ps[1] == 0x8000) { // end of sprite list
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (ps[3] == 0xff00) { // end of sprite list
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Dinopic) {
|
||||
if (((ps[2] - 461) | ps[1]) == 0) { // sprite blank
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ((ps[0] | ps[3]) == 0) { // sprite blank
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Okay - this sprite is active:
|
||||
memcpy(po, pg, 8); // copy it over
|
||||
|
||||
pof->nCount++;
|
||||
po += 8;
|
||||
}
|
||||
|
||||
nGetNext++;
|
||||
if (nGetNext >= nFrameCount) {
|
||||
nGetNext = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CpsObjDrawInit()
|
||||
{
|
||||
nZOffset = nMaxZMask;
|
||||
|
||||
if (nZOffset >= 0xFC00) {
|
||||
// The Z buffer might moverflow the next fram, so initialise it
|
||||
memset(ZBuf, 0, 384 * 224 * 2);
|
||||
nZOffset = 0;
|
||||
}
|
||||
|
||||
nMaxZValue = nZOffset + 1;
|
||||
nMaxZMask = nZOffset;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
INT32 Cps1ObjDraw(INT32 nLevelFrom,INT32 nLevelTo)
|
||||
{
|
||||
INT32 i; UINT16 *ps; INT32 nPsAdd;
|
||||
struct ObjFrame *pof;
|
||||
(void)nLevelFrom; (void)nLevelTo;
|
||||
|
||||
// Draw the earliest frame we have in history
|
||||
pof=of+nGetNext;
|
||||
|
||||
// Point to Obj list
|
||||
ps=(UINT16 *)pof->Obj;
|
||||
|
||||
if (!CpsDrawSpritesInReverse) {
|
||||
ps+=(pof->nCount-1)<<2; nPsAdd=-4; // CPS1 is reversed
|
||||
} else {
|
||||
nPsAdd=4;
|
||||
}
|
||||
|
||||
// Go through all the Objs
|
||||
for (i=0; i<pof->nCount; i++,ps+=nPsAdd) {
|
||||
INT32 x,y,n,a,bx,by,dx,dy; INT32 nFlip;
|
||||
|
||||
if (Dinopic) {
|
||||
n = ps[0]; a = ps[1]; x = ps[2] - 461; y = 0x2f0 - ps[3];
|
||||
bx = 1;
|
||||
by = 1;
|
||||
} else {
|
||||
x = ps[0]; y = ps[1]; n = ps[2]; a = ps[3];
|
||||
|
||||
// Find out sprite size
|
||||
bx=((a>> 8)&15)+1;
|
||||
by=((a>>12)&15)+1;
|
||||
}
|
||||
|
||||
n = GfxRomBankMapper(GFXTYPE_SPRITES, n);
|
||||
if (n == -1) continue;
|
||||
|
||||
n |= (y & 0x6000) << 3; // high bits of address
|
||||
|
||||
// CPS1 coords are 9 bit signed?
|
||||
x&=0x01ff; if (x>=0x1c0) x-=0x200;
|
||||
y&=0x01ff; y^=0x100; y-=0x100;
|
||||
|
||||
x+=pof->nShiftX;
|
||||
y+=pof->nShiftY;
|
||||
|
||||
// Find the palette for the tiles on this sprite
|
||||
CpstPal = CpsObjPal + ((a & 0x1F) << 4);
|
||||
|
||||
nFlip=(a>>5)&3;
|
||||
|
||||
// Take care with tiles if the sprite goes off the screen
|
||||
if (x<0 || y<0 || x+(bx<<4)>384 || y+(by<<4)>224) {
|
||||
nCpstType=CTT_16X16 | CTT_CARE;
|
||||
} else {
|
||||
nCpstType=CTT_16X16;
|
||||
}
|
||||
|
||||
nCpstFlip=nFlip;
|
||||
for (dy=0;dy<by;dy++) {
|
||||
for (dx=0;dx<bx;dx++) {
|
||||
INT32 ex,ey;
|
||||
if (nFlip&1) ex=(bx-dx-1);
|
||||
else ex=dx;
|
||||
if (nFlip&2) ey=(by-dy-1);
|
||||
else ey=dy;
|
||||
|
||||
nCpstX=x+(ex<<4);
|
||||
nCpstY=y+(ey<<4);
|
||||
nCpstTile = (n & ~0x0F) + (dy << 4) + ((n + dx) & 0x0F);
|
||||
nCpstTile <<= 7;
|
||||
CpstOneObjDoX[0]();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Delay sprite drawing by one frame
|
||||
INT32 Cps2ObjDraw(INT32 nLevelFrom, INT32 nLevelTo)
|
||||
{
|
||||
const INT32 nPsAdd = 4;
|
||||
|
||||
UINT16 *ps;
|
||||
struct ObjFrame *pof;
|
||||
CpstOneDoFn pCpstOne;
|
||||
INT32 nCount;
|
||||
|
||||
bool bMask = 0;
|
||||
|
||||
// Draw the earliest frame we have in history
|
||||
pof = of + nGetNext;
|
||||
|
||||
// Point to Obj list
|
||||
ps = (UINT16*)pof->Obj + nPsAdd * (nMaxZValue - nZOffset - 1);
|
||||
nCount = nZOffset + pof->nCount;
|
||||
|
||||
// Go through all the Objs
|
||||
for (ZValue = (UINT16)nMaxZValue; ZValue <= nCount; ZValue++, ps += nPsAdd) {
|
||||
INT32 x, y, n, a, bx, by, dx, dy;
|
||||
INT32 nFlip;
|
||||
INT32 v = ps[0] >> 13;
|
||||
|
||||
if ((nSpriteEnable & (1 << v)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if sprite is between these levels
|
||||
if (v > nLevelTo) {
|
||||
bMask = 1;
|
||||
continue;
|
||||
}
|
||||
if (v < nLevelFrom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bMask) {
|
||||
nMaxZMask = ZValue;
|
||||
} else {
|
||||
nMaxZValue = ZValue;
|
||||
}
|
||||
|
||||
// Select CpstOne function;
|
||||
if (bMask || nMaxZMask > nMaxZValue) {
|
||||
pCpstOne = CpstOneObjDoX[1];
|
||||
} else {
|
||||
pCpstOne = CpstOneObjDoX[0];
|
||||
}
|
||||
|
||||
x = ps[0];
|
||||
y = ps[1];
|
||||
n = ps[2];
|
||||
a = ps[3];
|
||||
|
||||
if (a & 0x80) { // marvel vs capcom ending sprite off-set
|
||||
x += CpsSaveFrg[0][0x9];
|
||||
}
|
||||
|
||||
// CPS2 coords are 10 bit signed (-512 to 511)
|
||||
x &= 0x03FF; x ^= 0x200; x -= 0x200;
|
||||
y &= 0x03FF; y ^= 0x200; y -= 0x200;
|
||||
|
||||
#if 0
|
||||
// This *MAY* be needed to get correct sprite positions when raster interrups are used.
|
||||
if (nRasterline[1]) {
|
||||
for (INT32 i = 1; i < MAX_RASTER; i++) {
|
||||
if ((y < nRasterline[i]) || (nRasterline[i] == 0)) {
|
||||
x -= CpsSaveFrg[i - 1][0x09];
|
||||
y -= CpsSaveFrg[i - 1][0x0B];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
x -= CpsSaveFrg[0][0x9];
|
||||
y -= CpsSaveFrg[0][0xB];
|
||||
}
|
||||
#else
|
||||
// Ignore sprite offsets when raster interrupts are used (seems to work for all games).
|
||||
x += pof->nShiftX;
|
||||
y += pof->nShiftY;
|
||||
|
||||
// x -= CpsSaveFrg[0][0x9];
|
||||
// y -= CpsSaveFrg[0][0xB];
|
||||
|
||||
#endif
|
||||
n |= (ps[1] & 0x6000) << 3; // high bits of address
|
||||
|
||||
// Find the palette for the tiles on this sprite
|
||||
CpstPal = CpsObjPal + ((a & 0x1F) << 4);
|
||||
|
||||
nFlip = (a >> 5) & 3;
|
||||
// Find out sprite size
|
||||
bx = ((a >> 8) & 15) + 1;
|
||||
by = ((a >> 12) & 15) + 1;
|
||||
|
||||
// Take care with tiles if the sprite goes off the screen
|
||||
if (x < 0 || y < 0 || x + (bx << 4) > 383 || y + (by << 4) > 223) {
|
||||
nCpstType = CTT_16X16 | CTT_CARE;
|
||||
} else {
|
||||
nCpstType = CTT_16X16;
|
||||
}
|
||||
|
||||
// if (v == 0) {
|
||||
// bprintf(PRINT_IMPORTANT, _T(" - %4i: 0x%04X 0x%04X 0x%04X 0x%04X\n"), ZValue - (UINT16)nMaxZValue, ps[0], ps[1], ps[2], ps[3]);
|
||||
// }
|
||||
|
||||
nCpstFlip = nFlip;
|
||||
for (dy = 0; dy < by; dy++) {
|
||||
for (dx = 0; dx < bx; dx++) {
|
||||
INT32 ex, ey;
|
||||
|
||||
if (nFlip & 1) {
|
||||
ex = (bx - dx - 1);
|
||||
} else {
|
||||
ex = dx;
|
||||
}
|
||||
|
||||
if (nFlip & 2) {
|
||||
ey = (by - dy - 1);
|
||||
} else {
|
||||
ey = dy;
|
||||
}
|
||||
|
||||
nCpstX = x + (ex << 4);
|
||||
nCpstY = y + (ey << 4);
|
||||
|
||||
// nCpstTile = n + (dy << 4) + dx; // normal version
|
||||
nCpstTile = (n & ~0x0F) + (dy << 4) + ((n + dx) & 0x0F); // pgear fix
|
||||
nCpstTile <<= 7; // Find real tile address
|
||||
|
||||
pCpstOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
#include "cps.h"
|
||||
// CPS (palette)
|
||||
|
||||
static UINT8* CpsPalSrc = NULL; // Copy of current input palette
|
||||
|
||||
UINT32* CpsPal = NULL; // Hicolor version of palette
|
||||
UINT32* CpsObjPal = NULL;
|
||||
|
||||
INT32 nLagObjectPalettes;
|
||||
|
||||
inline static UINT32 CalcColCPS1(UINT16 a)
|
||||
{
|
||||
INT32 r, g, b, f;
|
||||
const INT32 F_OFFSET = 0x0F;
|
||||
|
||||
// Format is FFFF RRRR GGGG BBBB
|
||||
f = (a & 0xF000) >> 12;
|
||||
|
||||
r = (a & 0x0F00) >> 4; // Red
|
||||
r |= r >> 4;
|
||||
g = (a & 0x00F0); // Green
|
||||
g |= g >> 4;
|
||||
b = (a & 0x000F); // Blue
|
||||
b |= b << 4;
|
||||
|
||||
f += F_OFFSET;
|
||||
r *= f; r /= F_OFFSET + 0x0F;
|
||||
g *= f; g /= F_OFFSET + 0x0F;
|
||||
b *= f; b /= F_OFFSET + 0x0F;
|
||||
|
||||
return BurnHighCol(r, g, b, 0);
|
||||
}
|
||||
|
||||
static UINT32 CalcColCPS2(UINT16 a)
|
||||
{
|
||||
INT32 r, g, b, f;
|
||||
const INT32 F_OFFSET = 0x0F;
|
||||
|
||||
// Format is FFFF RRRR GGGG BBBB
|
||||
f = (a & 0xF000) >> 12;
|
||||
|
||||
r = (a & 0x0F00) >> 4; // Red
|
||||
r |= r >> 4;
|
||||
g = (a & 0x00F0); // Green
|
||||
g |= g >> 4;
|
||||
b = (a & 0x000F); // Blue
|
||||
b |= b << 4;
|
||||
|
||||
f += F_OFFSET;
|
||||
r *= f; r /= F_OFFSET + 0x0F;
|
||||
g *= f; g /= F_OFFSET + 0x0F;
|
||||
b *= f; b /= F_OFFSET + 0x0F;
|
||||
|
||||
return BurnHighCol(r, g, b, 0);
|
||||
}
|
||||
|
||||
static INT32 CalcAll()
|
||||
{
|
||||
UINT16* ps;
|
||||
|
||||
if (Cps == 2) {
|
||||
if (nLagObjectPalettes) {
|
||||
ps = (UINT16*)CpsPalSrc + 0x0C00;
|
||||
for (INT32 i = 0x0C00; i < 0x0E00; i++, ps++) {
|
||||
CpsPal[i ^ 15] = CalcColCPS2(*ps);
|
||||
}
|
||||
ps = (UINT16*)CpsPalSrc + 0x0200;
|
||||
for (INT32 i = 0x0200; i < 0x0800; i++, ps++) {
|
||||
CpsPal[i ^ 15] = CalcColCPS2(*ps);
|
||||
}
|
||||
|
||||
memcpy(CpsPal + 0x0E00, CpsPal + 0x0C00, 0x0200 << 2);
|
||||
} else {
|
||||
ps = (UINT16*)CpsPalSrc;
|
||||
for (INT32 i = 0x0000; i < 0x0800; i++, ps++) {
|
||||
CpsPal[i ^ 15] = CalcColCPS2(*ps);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ps = (UINT16*)CpsPalSrc;
|
||||
for (INT32 i = 0x0000; i < 0x0c00; i++, ps++) {
|
||||
CpsPal[i ^ 15] = CalcColCPS1(*ps);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CalcAllStar(INT32 nLayer)
|
||||
{
|
||||
UINT16* ps = (UINT16*)CpsPalSrc;
|
||||
INT32 nOffset = 0x0800 + (nLayer << 9);
|
||||
|
||||
for (INT32 i = 0; i < 128; i++, ps++) {
|
||||
CpsPal[(i + nOffset) ^ 15] = CalcColCPS1(*(ps + nOffset));
|
||||
}
|
||||
}
|
||||
|
||||
INT32 CpsPalInit()
|
||||
{
|
||||
INT32 nLen = 0;
|
||||
|
||||
nLen = 0x1000 * sizeof(UINT16);
|
||||
CpsPalSrc = (UINT8*)malloc(nLen);
|
||||
if (CpsPalSrc == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(CpsPalSrc, 0, nLen);
|
||||
|
||||
// The star layer palettes are at the end of the normal palette, so double the size
|
||||
nLen = 0x1000 * sizeof(UINT32);
|
||||
CpsPal = (UINT32*)malloc(nLen);
|
||||
if (CpsPal == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set CpsPal to initial values
|
||||
CalcAll();
|
||||
if (CpsStar) {
|
||||
CalcAllStar(0);
|
||||
CalcAllStar(1);
|
||||
}
|
||||
|
||||
if (nLagObjectPalettes) {
|
||||
CpsObjPal = CpsPal + 0x0C00;
|
||||
} else {
|
||||
CpsObjPal = CpsPal;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsPalExit()
|
||||
{
|
||||
if (CpsPal) {
|
||||
free(CpsPal);
|
||||
CpsPal = NULL;
|
||||
}
|
||||
if (CpsPalSrc) {
|
||||
free(CpsPalSrc);
|
||||
CpsPalSrc = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Update CpsPal with the new palette at pNewPal (length 0x1000 bytes)
|
||||
INT32 CpsPalUpdate(UINT8* pNewPal, INT32 bRecalcAll)
|
||||
{
|
||||
INT32 i;
|
||||
UINT16 *ps, *pn;
|
||||
|
||||
// If we are recalculating the whole palette, just copy to CpsPalSrc
|
||||
// and recalculate it all
|
||||
if (bRecalcAll) {
|
||||
ps = (UINT16*)CpsPalSrc;
|
||||
pn = (UINT16*)pNewPal;
|
||||
|
||||
if (nLagObjectPalettes) {
|
||||
INT32 nBuffer = 0x0C00 + ((GetCurrentFrame() & 1) << 9);
|
||||
|
||||
memcpy(ps + 0x0200, pn + 0x0200, 0x0600 << 1);
|
||||
memcpy(ps + nBuffer, pn, 0x0200 << 1);
|
||||
memcpy(ps + 0x0E00, pn, 0x0200 << 1);
|
||||
|
||||
CpsObjPal = CpsPal + nBuffer;
|
||||
} else {
|
||||
memcpy(ps, pn, 0x0c00 << 1);
|
||||
}
|
||||
|
||||
CalcAll();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
if (nLagObjectPalettes) {
|
||||
INT32 nBuffer = 0x0C00 + ((GetCurrentFrame() & 1) << 9);
|
||||
|
||||
ps = (UINT16*)CpsPalSrc + (nBuffer ^ 0x0200);
|
||||
pn = (UINT16*)pNewPal;
|
||||
CpsObjPal = CpsPal + (nBuffer ^ 0x0200);
|
||||
|
||||
for (i = 0; i < 0x0200; i++, ps++, pn++) {
|
||||
UINT16 n;
|
||||
n = *pn;
|
||||
if (*ps == n) {
|
||||
continue; // Colour hasn't changed - great!
|
||||
}
|
||||
|
||||
*ps = n; // Update our copy of the palette
|
||||
|
||||
CpsObjPal[i ^ 15] = CalcColCPS2(n);
|
||||
}
|
||||
|
||||
ps = (UINT16*)CpsPalSrc + 0x0200;
|
||||
pn = (UINT16*)pNewPal + 0x0200;
|
||||
|
||||
for (i = 0x0200; i < 0x0800; i++, ps++, pn++) {
|
||||
UINT16 n;
|
||||
n = *pn;
|
||||
if (*ps == n) {
|
||||
continue; // Colour hasn't changed - great!
|
||||
}
|
||||
|
||||
*ps = n; // Update our copy of the palette
|
||||
|
||||
CpsPal[i ^ 15] = CalcColCPS2(n);
|
||||
}
|
||||
|
||||
CpsObjPal = CpsPal + nBuffer;
|
||||
} else {
|
||||
ps = (UINT16*)CpsPalSrc;
|
||||
pn = (UINT16*)pNewPal;
|
||||
|
||||
for (i = 0x0000; i < 0x0800; i++, ps++, pn++) {
|
||||
UINT16 n = *pn;
|
||||
if (*ps == n) {
|
||||
continue; // Colour hasn't changed - great!
|
||||
}
|
||||
|
||||
*ps = n; // Update our copy of the palette
|
||||
|
||||
CpsPal[i ^ 15] = CalcColCPS2(n);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ps = (UINT16*)CpsPalSrc;
|
||||
pn = (UINT16*)pNewPal;
|
||||
|
||||
for (i = 0x0000; i < 0x0c00; i++, ps++, pn++) {
|
||||
UINT16 n = *pn;
|
||||
if (*ps == n) {
|
||||
continue; // Colour hasn't changed - great!
|
||||
}
|
||||
|
||||
*ps = n; // Update our copy of the palette
|
||||
|
||||
CpsPal[i ^ 15] = CalcColCPS1(n);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsStarPalUpdate(UINT8* pNewPal, INT32 nLayer, INT32 bRecalcAll)
|
||||
{
|
||||
INT32 i;
|
||||
UINT16 *ps, *pn;
|
||||
|
||||
if (nLayer == 0) {
|
||||
ps = (UINT16*)CpsPalSrc + 0x0800;
|
||||
pn = (UINT16*)pNewPal + 0x0800;
|
||||
|
||||
if (bRecalcAll) {
|
||||
memcpy(ps, pn, 256);
|
||||
CalcAllStar(nLayer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Star layer 0
|
||||
for (i = 0x0800; i < 0x0880; i++, ps++, pn++) {
|
||||
UINT16 n = *pn;
|
||||
if (*ps == n) {
|
||||
continue; // Colour hasn't changed - great!
|
||||
}
|
||||
|
||||
*ps = n; // Update our copy of the palette
|
||||
|
||||
CpsPal[i ^ 15] = CalcColCPS1(n);
|
||||
}
|
||||
} else {
|
||||
ps = (UINT16*)CpsPalSrc + 0x0A00;
|
||||
pn = (UINT16*)pNewPal + 0x0A00;
|
||||
|
||||
if (bRecalcAll) {
|
||||
memcpy(ps, pn, 256);
|
||||
CalcAllStar(nLayer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Star layer 1
|
||||
for (i = 0x0A00; i < 0x0A80; i++, ps++, pn++) {
|
||||
UINT16 n = *pn;
|
||||
if (*ps == n) {
|
||||
continue; // Colour hasn't changed - great!
|
||||
}
|
||||
|
||||
*ps = n; // Update our copy of the palette
|
||||
|
||||
CpsPal[i ^ 15] = CalcColCPS1(n);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,497 @@
|
|||
// CPS - Run
|
||||
#include "cps.h"
|
||||
|
||||
// Inputs:
|
||||
UINT8 CpsReset = 0;
|
||||
UINT8 Cpi01A = 0, Cpi01C = 0, Cpi01E = 0;
|
||||
|
||||
static INT32 nInterrupt;
|
||||
static INT32 nIrqLine, nIrqCycles;
|
||||
static bool bEnableAutoIrq50, bEnableAutoIrq52; // Trigger an interrupt every 32 scanlines
|
||||
|
||||
static const INT32 nFirstLine = 0x0C; // The first scanline of the display
|
||||
static const INT32 nVBlank = 0x0106 - 0x0C; // The scanline at which the vblank interrupt is triggered
|
||||
|
||||
static INT32 nCpsCyclesExtra;
|
||||
|
||||
INT32 CpsDrawSpritesInReverse = 0;
|
||||
|
||||
INT32 nIrqLine50, nIrqLine52;
|
||||
|
||||
static INT32 DrvReset()
|
||||
{
|
||||
// Reset machine
|
||||
if (Cps == 2 || PangEEP || Cps1Qs == 1) EEPROMReset();
|
||||
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
if (!Cps1Pic) {
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
ZetClose();
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
// Disable beam-synchronized interrupts
|
||||
*((UINT16*)(CpsReg + 0x4E)) = 0x0200;
|
||||
*((UINT16*)(CpsReg + 0x50)) = 0x0106;
|
||||
*((UINT16*)(CpsReg + 0x52)) = 0x0106;
|
||||
}
|
||||
|
||||
CpsMapObjectBanks(0);
|
||||
|
||||
nCpsCyclesExtra = 0;
|
||||
|
||||
if (Cps == 2 || Cps1Qs == 1) { // Sound init (QSound)
|
||||
QsndReset();
|
||||
}
|
||||
|
||||
HiscoreReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const eeprom_interface qsound_eeprom_interface =
|
||||
{
|
||||
7, /* address bits */
|
||||
8, /* data bits */
|
||||
"0110", /* read command */
|
||||
"0101", /* write command */
|
||||
"0111", /* erase command */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
static const eeprom_interface cps2_eeprom_interface =
|
||||
{
|
||||
6, /* address bits */
|
||||
16, /* data bits */
|
||||
"0110", /* read command */
|
||||
"0101", /* write command */
|
||||
"0111", /* erase command */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
INT32 CpsRunInit()
|
||||
{
|
||||
nLagObjectPalettes = 0;
|
||||
|
||||
if (Cps == 2) nLagObjectPalettes = 1;
|
||||
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
|
||||
if (CpsMemInit()) { // Memory init
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Cps == 2 || PangEEP) {
|
||||
EEPROMInit(&cps2_eeprom_interface);
|
||||
} else {
|
||||
if (Cps1Qs == 1) {
|
||||
EEPROMInit(&qsound_eeprom_interface);
|
||||
}
|
||||
}
|
||||
|
||||
CpsRwInit(); // Registers setup
|
||||
|
||||
if (CpsPalInit()) { // Palette init
|
||||
return 1;
|
||||
}
|
||||
if (CpsObjInit()) { // Sprite init
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((Cps & 1) && Cps1Qs == 0 && Cps1Pic == 0) { // Sound init (MSM6295 + YM2151)
|
||||
if (PsndInit()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Cps == 2 || Cps1Qs == 1) { // Sound init (QSound)
|
||||
if (QsndInit()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Cps == 2 || PangEEP || Cps1Qs == 1) EEPROMReset();
|
||||
DrvReset();
|
||||
|
||||
//Init Draw Function
|
||||
DrawFnInit();
|
||||
|
||||
pBurnDrvPalette = CpsPal;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsRunExit()
|
||||
{
|
||||
if (Cps == 2 || PangEEP || Cps1Qs == 1) EEPROMExit();
|
||||
|
||||
// Sound exit
|
||||
if (Cps == 2 || Cps1Qs == 1) QsndExit();
|
||||
if (Cps != 2 && Cps1Qs == 0) PsndExit();
|
||||
|
||||
// Graphics exit
|
||||
CpsObjExit();
|
||||
CpsPalExit();
|
||||
|
||||
// Sprite Masking exit
|
||||
ZBuf = NULL;
|
||||
|
||||
// Memory exit
|
||||
CpsRwExit();
|
||||
CpsMemExit();
|
||||
|
||||
SekExit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// nStart = 0-3, nCount=1-4
|
||||
inline static void GetPalette(INT32 nStart, INT32 nCount)
|
||||
{
|
||||
// Update Palette (Ghouls points to the wrong place on boot up I think)
|
||||
INT32 nPal = (*((UINT16*)(CpsReg + 0x0A)) << 8) & 0xFFF800;
|
||||
|
||||
UINT8* Find = CpsFindGfxRam(nPal, 0x1000);
|
||||
if (Find) {
|
||||
memcpy(CpsSavePal + (nStart << 10), Find + (nStart << 10), nCount << 10);
|
||||
}
|
||||
}
|
||||
|
||||
static void GetStarPalette()
|
||||
{
|
||||
INT32 nPal = (*((UINT16*)(CpsReg + 0x0A)) << 8) & 0xFFF800;
|
||||
|
||||
UINT8* Find = CpsFindGfxRam(nPal, 256);
|
||||
if (Find) {
|
||||
memcpy(CpsSavePal + 4096, Find + 4096, 256);
|
||||
memcpy(CpsSavePal + 5120, Find + 5120, 256);
|
||||
}
|
||||
}
|
||||
|
||||
inline static void CopyCpsReg(INT32 i)
|
||||
{
|
||||
memcpy(CpsSaveReg[i], CpsReg, 0x0100);
|
||||
}
|
||||
|
||||
inline static void CopyCpsFrg(INT32 i)
|
||||
{
|
||||
memcpy(CpsSaveFrg[i], CpsFrg, 0x0010);
|
||||
}
|
||||
|
||||
// Schedule a beam-synchronized interrupt
|
||||
static void ScheduleIRQ()
|
||||
{
|
||||
INT32 nLine = 0x0106;
|
||||
|
||||
if (nIrqLine50 <= nLine) {
|
||||
nLine = nIrqLine50;
|
||||
}
|
||||
if (nIrqLine52 < nLine) {
|
||||
nLine = nIrqLine52;
|
||||
}
|
||||
|
||||
if (nLine < 0x0106) {
|
||||
nIrqLine = nLine;
|
||||
nIrqCycles = (nLine * nCpsCycles / 0x0106) + 1;
|
||||
} else {
|
||||
nIrqCycles = nCpsCycles + 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute a beam-synchronised interrupt and schedule the next one
|
||||
static void DoIRQ()
|
||||
{
|
||||
// 0x4E - bit 9 = 1: Beam Synchronized interrupts disabled
|
||||
// 0x50 - Beam synchronized interrupt #1 occurs at raster line.
|
||||
// 0x52 - Beam synchronized interrupt #2 occurs at raster line.
|
||||
|
||||
// Trigger IRQ and copy registers.
|
||||
if (nIrqLine >= nFirstLine) {
|
||||
|
||||
nInterrupt++;
|
||||
nRasterline[nInterrupt] = nIrqLine - nFirstLine;
|
||||
}
|
||||
|
||||
SekSetIRQLine(4, SEK_IRQSTATUS_AUTO);
|
||||
SekRun(nCpsCycles * 0x01 / 0x0106);
|
||||
if (nRasterline[nInterrupt] < 224) {
|
||||
CopyCpsReg(nInterrupt);
|
||||
CopyCpsFrg(nInterrupt);
|
||||
} else {
|
||||
nRasterline[nInterrupt] = 0;
|
||||
}
|
||||
|
||||
// Schedule next interrupt
|
||||
if (!bEnableAutoIrq50) {
|
||||
if (nIrqLine >= nIrqLine50) {
|
||||
nIrqLine50 = 0x0106;
|
||||
}
|
||||
} else {
|
||||
if (bEnableAutoIrq50 && nIrqLine == nIrqLine50) {
|
||||
nIrqLine50 += 32;
|
||||
}
|
||||
}
|
||||
if (!bEnableAutoIrq52 && nIrqLine >= nIrqLine52) {
|
||||
nIrqLine52 = 0x0106;
|
||||
} else {
|
||||
if (bEnableAutoIrq52 && nIrqLine == nIrqLine52) {
|
||||
nIrqLine52 += 32;
|
||||
}
|
||||
}
|
||||
ScheduleIRQ();
|
||||
if (nIrqCycles < SekTotalCycles()) {
|
||||
nIrqCycles = SekTotalCycles() + 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
INT32 Cps1Frame()
|
||||
{
|
||||
INT32 nDisplayEnd, nNext, i;
|
||||
|
||||
if (CpsReset) {
|
||||
DrvReset();
|
||||
}
|
||||
|
||||
SekNewFrame();
|
||||
if (Cps1Qs == 1) {
|
||||
QsndNewFrame();
|
||||
} else {
|
||||
if (!Cps1Pic) {
|
||||
ZetOpen(0);
|
||||
PsndNewFrame();
|
||||
}
|
||||
}
|
||||
|
||||
nCpsCycles = (INT32)((INT64)nCPS68KClockspeed * nBurnCPUSpeedAdjust >> 8);
|
||||
|
||||
CpsRwGetInp(); // Update the input port values
|
||||
|
||||
nDisplayEnd = (nCpsCycles * (nFirstLine + 224)) / 0x0106; // Account for VBlank
|
||||
|
||||
SekOpen(0);
|
||||
SekIdle(nCpsCyclesExtra);
|
||||
|
||||
SekRun(nCpsCycles * nFirstLine / 0x0106); // run 68K for the first few lines
|
||||
|
||||
if (!CpsDrawSpritesInReverse) {
|
||||
CpsObjGet(); // Get objects
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
nNext = ((i + 1) * nCpsCycles) >> 2; // find out next cycle count to run to
|
||||
|
||||
if (SekTotalCycles() < nDisplayEnd && nNext > nDisplayEnd) {
|
||||
|
||||
SekRun(nNext - nDisplayEnd); // run 68K
|
||||
|
||||
memcpy(CpsSaveReg[0], CpsReg, 0x100); // Registers correct now
|
||||
|
||||
GetPalette(0, 6); // Get palette
|
||||
if (CpsStar) {
|
||||
GetStarPalette();
|
||||
}
|
||||
|
||||
if (CpsDrawSpritesInReverse) {
|
||||
if (i == 3) CpsObjGet(); // Get objects
|
||||
}
|
||||
|
||||
SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // Trigger VBlank interrupt
|
||||
}
|
||||
|
||||
SekRun(nNext - SekTotalCycles()); // run 68K
|
||||
|
||||
// if (pBurnDraw) {
|
||||
// CpsDraw(); // Draw frame
|
||||
// }
|
||||
}
|
||||
|
||||
if (pBurnDraw) {
|
||||
CpsDraw(); // Draw frame
|
||||
}
|
||||
|
||||
if (Cps1Qs == 1) {
|
||||
QsndEndFrame();
|
||||
} else {
|
||||
if (!Cps1Pic) {
|
||||
PsndSyncZ80(nCpsZ80Cycles);
|
||||
PsmUpdate(nBurnSoundLen);
|
||||
ZetClose();
|
||||
}
|
||||
}
|
||||
|
||||
nCpsCyclesExtra = SekTotalCycles() - nCpsCycles;
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps2Frame()
|
||||
{
|
||||
INT32 nDisplayEnd, nNext; // variables to keep track of executed 68K cyles
|
||||
INT32 i;
|
||||
|
||||
if (CpsReset) {
|
||||
DrvReset();
|
||||
}
|
||||
|
||||
// extern INT32 prevline;
|
||||
// prevline = -1;
|
||||
|
||||
SekNewFrame();
|
||||
QsndNewFrame();
|
||||
|
||||
nCpsCycles = (INT32)(((INT64)nCPS68KClockspeed * nBurnCPUSpeedAdjust) / 0x0100);
|
||||
SekSetCyclesScanline(nCpsCycles / 262);
|
||||
|
||||
CpsRwGetInp(); // Update the input port values
|
||||
|
||||
nDisplayEnd = nCpsCycles * (nFirstLine + 224) / 0x0106; // Account for VBlank
|
||||
|
||||
nInterrupt = 0;
|
||||
for (i = 0; i < MAX_RASTER + 2; i++) {
|
||||
nRasterline[i] = 0;
|
||||
}
|
||||
|
||||
// Determine which (if any) of the line counters generates the first IRQ
|
||||
bEnableAutoIrq50 = bEnableAutoIrq52 = false;
|
||||
nIrqLine50 = nIrqLine52 = 0x0106;
|
||||
if (*((UINT16*)(CpsReg + 0x50)) & 0x8000) {
|
||||
bEnableAutoIrq50 = true;
|
||||
}
|
||||
if (bEnableAutoIrq50 || (*((UINT16*)(CpsReg + 0x4E)) & 0x0200) == 0) {
|
||||
nIrqLine50 = (*((UINT16*)(CpsReg + 0x50)) & 0x01FF);
|
||||
}
|
||||
if (*((UINT16*)(CpsReg + 0x52)) & 0x8000) {
|
||||
bEnableAutoIrq52 = true;
|
||||
}
|
||||
if (bEnableAutoIrq52 || (*((UINT16*)(CpsReg + 0x4E)) & 0x0200) == 0) {
|
||||
nIrqLine52 = (*((UINT16*)(CpsReg + 0x52)) & 0x01FF);
|
||||
}
|
||||
ScheduleIRQ();
|
||||
|
||||
SekOpen(0);
|
||||
SekIdle(nCpsCyclesExtra);
|
||||
|
||||
if (nIrqCycles < nCpsCycles * nFirstLine / 0x0106) {
|
||||
SekRun(nIrqCycles);
|
||||
DoIRQ();
|
||||
}
|
||||
nNext = nCpsCycles * nFirstLine / 0x0106;
|
||||
if (SekTotalCycles() < nNext) {
|
||||
SekRun(nNext - SekTotalCycles());
|
||||
}
|
||||
|
||||
CopyCpsReg(0); // Get inititial copy of registers
|
||||
CopyCpsFrg(0); //
|
||||
|
||||
if (nIrqLine >= 0x0106 && (*((UINT16*)(CpsReg + 0x4E)) & 0x0200) == 0) {
|
||||
nIrqLine50 = *((UINT16*)(CpsReg + 0x50)) & 0x01FF;
|
||||
nIrqLine52 = *((UINT16*)(CpsReg + 0x52)) & 0x01FF;
|
||||
ScheduleIRQ();
|
||||
}
|
||||
|
||||
GetPalette(0, 4); // Get palettes
|
||||
CpsObjGet(); // Get objects
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
nNext = ((i + 1) * nDisplayEnd) / 3; // find out next cycle count to run to
|
||||
|
||||
while (nNext > nIrqCycles && nInterrupt < MAX_RASTER) {
|
||||
SekRun(nIrqCycles - SekTotalCycles());
|
||||
DoIRQ();
|
||||
}
|
||||
SekRun(nNext - SekTotalCycles()); // run cpu
|
||||
}
|
||||
|
||||
// nCpsCyclesSegment[0] = (nCpsCycles * nVBlank) / 0x0106;
|
||||
// nDone += SekRun(nCpsCyclesSegment[0] - nDone);
|
||||
|
||||
SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); // VBlank
|
||||
SekRun(nCpsCycles - SekTotalCycles());
|
||||
|
||||
if (pBurnDraw) {
|
||||
CpsDraw();
|
||||
}
|
||||
|
||||
nCpsCyclesExtra = SekTotalCycles() - nCpsCycles;
|
||||
|
||||
QsndEndFrame();
|
||||
|
||||
SekClose();
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" -\n"));
|
||||
|
||||
#if 0 && defined FBA_DEBUG
|
||||
if (nInterrupt) {
|
||||
bprintf(PRINT_IMPORTANT, _T("Beam synchronized interrupt at line %2X.\r"), nRasterline[nInterrupt]);
|
||||
} else {
|
||||
bprintf(PRINT_NORMAL, _T("Beam synchronized interrupt disabled. \r"));
|
||||
}
|
||||
|
||||
extern INT32 counter;
|
||||
if (counter) {
|
||||
bprintf(PRINT_NORMAL, _T("\n\nSlices start at: "));
|
||||
for (i = 0; i < MAX_RASTER + 2; i++) {
|
||||
bprintf(PRINT_NORMAL, _T("%2X "), nRasterline[i]);
|
||||
}
|
||||
bprintf(PRINT_NORMAL, _T("\n"));
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
if (*((UINT16*)(CpsSaveReg[0] + i * 2)) != *((UINT16*)(CpsSaveReg[nInterrupt] + i * 2))) {
|
||||
bprintf(PRINT_NORMAL, _T("Register %2X: %4X -> %4X\n"), i * 2, *((UINT16*)(CpsSaveReg[0] + i * 2)), *((UINT16*)(CpsSaveReg[nInterrupt] + i * 2)));
|
||||
}
|
||||
}
|
||||
bprintf(PRINT_NORMAL, _T("\n"));
|
||||
for (i = 0; i < 0x010; i++) {
|
||||
if (CpsSaveFrg[0][i] != CpsSaveFrg[nInterrupt][i]) {
|
||||
bprintf(PRINT_NORMAL, _T("FRG %X: %02X -> %02X\n"), i, CpsSaveFrg[0][i], CpsSaveFrg[nInterrupt][i]);
|
||||
}
|
||||
}
|
||||
bprintf(PRINT_NORMAL, _T("\n"));
|
||||
if (((CpsSaveFrg[0][4] << 8) | CpsSaveFrg[0][5]) != ((CpsSaveFrg[nInterrupt][4] << 8) | CpsSaveFrg[nInterrupt][5])) {
|
||||
bprintf(PRINT_NORMAL, _T("Layer-sprite priority: %04X -> %04X\n"), ((CpsSaveFrg[0][4] << 8) | CpsSaveFrg[0][5]), ((CpsSaveFrg[nInterrupt][4] << 8) | CpsSaveFrg[nInterrupt][5]));
|
||||
}
|
||||
|
||||
bprintf(PRINT_NORMAL, _T("\n"));
|
||||
for (INT32 j = 0; j <= nInterrupt; j++) {
|
||||
if (j) {
|
||||
bprintf(PRINT_NORMAL, _T("IRQ : %i (triggered at line %3i)\n\n"), j, nRasterline[j]);
|
||||
} else {
|
||||
bprintf(PRINT_NORMAL, _T("Initial register status\n\n"));
|
||||
}
|
||||
|
||||
for (i = 0; i < 0x080; i+= 8) {
|
||||
bprintf(PRINT_NORMAL, _T("%2X: %4X %4X %4X %4X %4X %4X %4X %4X\n"), i * 2, *((UINT16*)(CpsSaveReg[j] + 0 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 2 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 4 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 6 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 8 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 10 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 12 + i * 2)), *((UINT16*)(CpsSaveReg[j] + 14 + i * 2)));
|
||||
}
|
||||
|
||||
bprintf(PRINT_NORMAL, _T("\nFRG: "));
|
||||
for (i = 0; i < 0x010; i++) {
|
||||
bprintf(PRINT_NORMAL, _T("%02X "), CpsSaveFrg[j][i]);
|
||||
}
|
||||
bprintf(PRINT_NORMAL, _T("\n\n"));
|
||||
|
||||
}
|
||||
|
||||
extern INT32 bRunPause;
|
||||
bRunPause = 1;
|
||||
counter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,589 @@
|
|||
#include "cps.h"
|
||||
// CPS - Read/Write
|
||||
|
||||
// Input bits
|
||||
#define INP(nnn) UINT8 CpsInp##nnn[8];
|
||||
CPSINPSET
|
||||
#undef INP
|
||||
|
||||
// Bytes to return from ports
|
||||
#define INP(nnn) UINT8 Inp##nnn;
|
||||
CPSINPSET
|
||||
#undef INP
|
||||
|
||||
UINT16 CpsInp055 = 0;
|
||||
UINT16 CpsInp05d = 0;
|
||||
UINT16 CpsInpPaddle1 = 0;
|
||||
UINT16 CpsInpPaddle2 = 0;
|
||||
static INT32 ReadPaddle = 0;
|
||||
INT32 CpsPaddle1Value = 0;
|
||||
INT32 CpsPaddle2Value = 0;
|
||||
INT32 CpsPaddle1 = 0;
|
||||
INT32 CpsPaddle2 = 0;
|
||||
static INT32 nDial055, nDial05d;
|
||||
|
||||
INT32 PangEEP = 0;
|
||||
INT32 Forgottn = 0;
|
||||
INT32 Cps1QsHack = 0;
|
||||
INT32 Kodh = 0;
|
||||
INT32 Cawingb = 0;
|
||||
INT32 Wofh = 0;
|
||||
INT32 Sf2thndr = 0;
|
||||
INT32 Pzloop2 = 0;
|
||||
INT32 Ssf2tb = 0;
|
||||
INT32 Dinopic = 0;
|
||||
INT32 Dinohunt = 0;
|
||||
INT32 Port6SoundWrite = 0;
|
||||
|
||||
static INT32 nCalc[2] = {0, 0};
|
||||
|
||||
static const bool nCPSExtraNVRAM = false;
|
||||
static INT32 n664001;
|
||||
|
||||
#define INP(nnnn) UINT8 CpsInp##nnnn[8];
|
||||
CPSINPEX
|
||||
#undef INP
|
||||
|
||||
#define INP(nnnn) static UINT8 Inp##nnnn;
|
||||
CPSINPEX
|
||||
#undef INP
|
||||
|
||||
|
||||
// Read input port 0x000-0x1ff
|
||||
static UINT8 CpsReadPort(const UINT32 ia)
|
||||
{
|
||||
UINT8 d = 0xFF;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("Read Port %x\n"), ia);
|
||||
|
||||
if (ia == 0x000) {
|
||||
d = (UINT8)~Inp000;
|
||||
if (Pzloop2) {
|
||||
if (ReadPaddle) {
|
||||
d -= CpsPaddle2Value;
|
||||
} else {
|
||||
d = CpsPaddle2;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x001) {
|
||||
d = (UINT8)~Inp001;
|
||||
if (Pzloop2) {
|
||||
if (ReadPaddle) {
|
||||
d -= CpsPaddle1Value;
|
||||
} else {
|
||||
d = CpsPaddle1;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x010) {
|
||||
d = (UINT8)~Inp010;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x011) {
|
||||
d = (UINT8)~Inp011;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x012) {
|
||||
d = (UINT8)~Inp012;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x018) {
|
||||
d = (UINT8)~Inp018;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x019) {
|
||||
d = (UINT8)~Inp019;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x01A) {
|
||||
d = (UINT8)~Cpi01A;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x01C) {
|
||||
d = (UINT8)~Cpi01C;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x01E) {
|
||||
d = (UINT8)~Cpi01E;
|
||||
return d;
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
// Used on CPS2 only I think
|
||||
if (ia == 0x020) {
|
||||
d = (UINT8)~Inp020;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x021) {
|
||||
d = (UINT8)~Inp021;
|
||||
d &= 0xFE;
|
||||
d |= EEPROMRead();
|
||||
return d;
|
||||
}
|
||||
|
||||
// CPS2 Volume control
|
||||
if (ia == 0x030) {
|
||||
if (Ssf2tb) {
|
||||
d = 0x20;
|
||||
} else {
|
||||
d = 0xe0;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x031) {
|
||||
d = 0x21;
|
||||
return d;
|
||||
}
|
||||
|
||||
if (ia >= 0x0100 && ia < 0x0200) {
|
||||
static INT32 nRasterLine;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T(" - port 0x%02X (%3i)\n"), ia & 255, SekCurrentScanline());
|
||||
|
||||
// The linecounters seem to return the line at which the last IRQ triggered by this counter is scheduled minus the current line
|
||||
if ((ia & 0x0FE) == 0x50) {
|
||||
if ((ia & 1) == 0) {
|
||||
nRasterLine = nIrqLine50 - SekCurrentScanline();
|
||||
return nRasterLine >> 8;
|
||||
} else {
|
||||
return nRasterLine & 0xFF;
|
||||
}
|
||||
}
|
||||
if ((ia & 0x0FE) == 0x52) {
|
||||
if ((ia & 1) == 0) {
|
||||
nRasterLine = nIrqLine52 - SekCurrentScanline();
|
||||
return nRasterLine >> 8;
|
||||
} else {
|
||||
return nRasterLine & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// Board ID
|
||||
if (ia == 0x100 + CpsBID[0]) {
|
||||
d = (UINT8)CpsBID[1];
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x100 + (CpsBID[0] + 1)) {
|
||||
d = (UINT8)CpsBID[2];
|
||||
return d;
|
||||
}
|
||||
|
||||
if (Sf2thndr) {
|
||||
// this reads the B-ID from here on startup as well as the normal location in-game
|
||||
if (ia == 0x1c8) {
|
||||
d = (UINT8)CpsBID[1];
|
||||
return d;
|
||||
}
|
||||
|
||||
if (ia == 0x1c9) {
|
||||
d = (UINT8)CpsBID[2];
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
// CPS1 EEPROM read
|
||||
if (ia == 0xC007) {
|
||||
return EEPROMRead();
|
||||
}
|
||||
|
||||
// Pang3 EEPROM
|
||||
if (PangEEP == 1) {
|
||||
if (ia == 0x17B) {
|
||||
return EEPROMRead();
|
||||
}
|
||||
}
|
||||
|
||||
// Extra Input ports (move from game-to-game)
|
||||
if (ia == 0x006) {
|
||||
d = (UINT8)~Inp006;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x007) {
|
||||
d = (UINT8)~Inp007;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x008) {
|
||||
d = (UINT8)~Inp008;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x029) {
|
||||
d = (UINT8)~Inp029;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x176) {
|
||||
d = (UINT8)~Inp176;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x177) {
|
||||
d = (UINT8)~Inp177;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x179) {
|
||||
d = (UINT8)~Inp179;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x186) {
|
||||
d = (UINT8)~Inp186;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0x1fd) {
|
||||
d = (UINT8)~Inp1fd;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0xC000) {
|
||||
d = (UINT8)~Inpc000;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0xC001) {
|
||||
d = (UINT8)~Inpc001;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0xC002) {
|
||||
d = (UINT8)~Inpc002;
|
||||
return d;
|
||||
}
|
||||
if (ia == 0xC003) {
|
||||
d = (UINT8)~Inpc003;
|
||||
return d;
|
||||
}
|
||||
|
||||
// Forgotten Worlds Dial
|
||||
if (Forgottn) {
|
||||
if (ia == 0x053) {
|
||||
return (nDial055 >> 8) & 0xFF;
|
||||
}
|
||||
if (ia == 0x055) {
|
||||
return (nDial055 >> 16) & 0xFF;
|
||||
}
|
||||
if (ia == 0x05B) {
|
||||
return (nDial05d >> 8) & 0xFF;
|
||||
}
|
||||
if (ia == 0x05D) {
|
||||
return (nDial05d >> 16) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
// Write output port 0x000-0x1ff
|
||||
static void CpsWritePort(const UINT32 ia, UINT8 d)
|
||||
{
|
||||
if ((Cps & 1) && Cps1Qs == 0) {
|
||||
// CPS1 sound code
|
||||
if (ia == 0x181 || (Port6SoundWrite && (ia == 0x006 || ia == 0x007))) {
|
||||
PsndSyncZ80((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles);
|
||||
|
||||
PsndCode = d;
|
||||
return;
|
||||
}
|
||||
|
||||
// CPS1 sound fade
|
||||
if (ia == 0x189) {
|
||||
PsndSyncZ80((INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles);
|
||||
|
||||
PsndFade = d;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ia == 0x041) {
|
||||
nDial055 = 0;
|
||||
}
|
||||
if (ia == 0x049) {
|
||||
nDial05d = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (Cps == 1 && Cps1QsHack == 1) {
|
||||
if (ia == 0x181) {
|
||||
// Pass the Sound Code to the Q-Sound Shared Ram
|
||||
CpsZRamC0[0x001] = d;
|
||||
}
|
||||
}
|
||||
|
||||
// CPS registers
|
||||
if (ia >= 0x100 && ia < 0x200) {
|
||||
//Pang3 EEPROM
|
||||
if (PangEEP == 1 && ia == 0x17B) {
|
||||
EEPROMWrite(d & 0x40, d & 0x80, d & 0x01);
|
||||
return;
|
||||
}
|
||||
CpsReg[(ia ^ 1) & 0xFF] = d;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
if (ia == 0x40) {
|
||||
EEPROMWrite(d & 0x20, d& 0x40, d & 0x10);
|
||||
return;
|
||||
}
|
||||
|
||||
// CPS2 object bank select
|
||||
if ((ia & 0x1FF) == 0x0E1) {
|
||||
// bprintf(PRINT_NORMAL, _T(" - %2i (%3i)\n"), d & 1, SekCurrentScanline());
|
||||
// CpsObjGet();
|
||||
CpsMapObjectBanks(d & 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ia == 0x41 && Pzloop2) {
|
||||
ReadPaddle = d & 0x02;
|
||||
}
|
||||
}
|
||||
|
||||
if (Cps1Qs == 1) {
|
||||
//CPS1 EEPROM write
|
||||
if (ia == 0xc007) {
|
||||
EEPROMWrite(d & 0x40, d & 0x80, d & 0x01);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall CpsReadByte(UINT32 a)
|
||||
{
|
||||
// Input ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8000) == 0x800000) {
|
||||
return CpsReadPort(a & 0x1FF);
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
if ((a & 0xFF8000) == 0x660000) {
|
||||
if (a == 0x664001) {
|
||||
return n664001;
|
||||
}
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
if (a >= 0xF1C000 && a <= 0xF1C007) {
|
||||
return CpsReadPort(a & 0xC00F);
|
||||
}
|
||||
|
||||
if (Dinohunt && a == 0xfc0001) return (UINT8)~Inpc001;
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("Read Byte %x\n"), a);
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void __fastcall CpsWriteByte(UINT32 a,UINT8 d)
|
||||
{
|
||||
// Output ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8000) == 0x800000) {
|
||||
CpsWritePort(a & 0x1FF, d);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cps == 2) {
|
||||
// 0x400000 registers
|
||||
if ((a & 0xFFFFF0) == 0x400000) {
|
||||
CpsFrg[a & 0x0F] = d;
|
||||
return;
|
||||
}
|
||||
if ((a & 0xFF8000) == 0x660000) {
|
||||
if (a == 0x664001) {
|
||||
// bit 1 toggled on/off each frame
|
||||
n664001 = d;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cps1Qs == 1) {
|
||||
// CPS1 EEPROM
|
||||
if (a == 0xf1c007) {
|
||||
CpsWritePort(a & 0xC00F, d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("Write Byte %x, %x\n"), a, d);
|
||||
}
|
||||
|
||||
UINT16 __fastcall CpsReadWord(UINT32 a)
|
||||
{
|
||||
if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[3]) {
|
||||
return (UINT16)((nCalc[0] * nCalc[1]) >> 16);
|
||||
}
|
||||
// ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[2]) {
|
||||
return (UINT16)((nCalc[0] * nCalc[1]));
|
||||
}
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("Read Word %x\n"), a);
|
||||
|
||||
SEK_DEF_READ_WORD(0, a);
|
||||
}
|
||||
|
||||
void __fastcall CpsWriteWord(UINT32 a, UINT16 d)
|
||||
{
|
||||
// ports mirrored between 0x800000 and 0x807fff
|
||||
if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[0])
|
||||
nCalc[0] = d;
|
||||
if ((a & 0xFF8FFF) == 0x800100 + CpsMProt[1])
|
||||
nCalc[1] = d;
|
||||
|
||||
if (a == 0x804040) {
|
||||
if ((d & 0x0008) == 0) {
|
||||
ZetReset();
|
||||
}
|
||||
}
|
||||
|
||||
if (Dinopic && a == 0x800222) {
|
||||
CpsReg[6] = d & 0xff;
|
||||
CpsReg[7] = d >> 8;
|
||||
return;
|
||||
}
|
||||
|
||||
// bprintf(PRINT_NORMAL, _T("Write Word %x, %x\n"), a, d);
|
||||
|
||||
SEK_DEF_WRITE_WORD(0, a, d);
|
||||
}
|
||||
|
||||
// Reset all inputs to zero
|
||||
static INT32 InpBlank()
|
||||
{
|
||||
#define INP(nnn) Inp##nnn = 0; memset(CpsInp##nnn, 0, sizeof(CpsInp##nnn));
|
||||
CPSINPSET
|
||||
#undef INP
|
||||
|
||||
#define INP(nnnn) Inp##nnnn = 0; memset(CpsInp##nnnn, 0, sizeof(CpsInp##nnnn));
|
||||
CPSINPEX
|
||||
#undef INP
|
||||
|
||||
CpsInp055 = CpsInp05d = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsRwInit()
|
||||
{
|
||||
InpBlank();
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CpsRwExit()
|
||||
{
|
||||
InpBlank();
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static void StopOpposite(UINT8* pInput)
|
||||
{
|
||||
if ((*pInput & 0x03) == 0x03) {
|
||||
*pInput &= ~0x03;
|
||||
}
|
||||
if ((*pInput & 0x0C) == 0x0C) {
|
||||
*pInput &= ~0x0C;
|
||||
}
|
||||
}
|
||||
|
||||
INT32 CpsRwGetInp()
|
||||
{
|
||||
// Compile separate buttons into Inpxxx
|
||||
#define INP(nnn) \
|
||||
{ INT32 i = 0; Inp##nnn = 0; \
|
||||
for (i = 0; i < 8; i++) { Inp##nnn |= (CpsInp##nnn[i] & 1) << i; } }
|
||||
CPSINPSET
|
||||
#undef INP
|
||||
|
||||
|
||||
#define INP(nnnn) \
|
||||
{ INT32 i = 0; Inp##nnnn = 0; \
|
||||
for (i = 0; i < 8; i++) { Inp##nnnn |= (CpsInp##nnnn[i] & 1) << i; } }
|
||||
CPSINPEX
|
||||
#undef INP
|
||||
|
||||
if (Forgottn) {
|
||||
// Handle analog controls
|
||||
nDial055 += (INT32)((INT16)CpsInp055);
|
||||
nDial05d += (INT32)((INT16)CpsInp05d);
|
||||
}
|
||||
|
||||
if (Pzloop2) {
|
||||
if (ReadPaddle) {
|
||||
CpsPaddle1Value = 0;
|
||||
CpsPaddle2Value = 0;
|
||||
if (CpsInpPaddle1) {
|
||||
if (CpsInpPaddle1 > 0x8000) {
|
||||
CpsPaddle1Value = 2;
|
||||
}
|
||||
|
||||
if (CpsInpPaddle1 < 0x7fff) {
|
||||
CpsPaddle1Value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (CpsInpPaddle2) {
|
||||
if (CpsInpPaddle2 > 0x8000) {
|
||||
CpsPaddle2Value = 2;
|
||||
}
|
||||
|
||||
if (CpsInpPaddle2 < 0x7fff) {
|
||||
CpsPaddle2Value = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CpsPaddle1 += (CpsInpPaddle1 >> 8) & 0xff;
|
||||
CpsPaddle2 += (CpsInpPaddle2 >> 8) & 0xff;
|
||||
}
|
||||
|
||||
StopOpposite(&Inp000);
|
||||
StopOpposite(&Inp001);
|
||||
|
||||
// Ghouls uses a 4-way stick
|
||||
if (Ghouls) {
|
||||
static UINT8 nPrevInp000, nPrevInp001;
|
||||
|
||||
if ((Inp000 & 0x03) && (Inp000 & 0x0C)) {
|
||||
Inp000 ^= (nPrevInp000 & 0x0F);
|
||||
} else {
|
||||
nPrevInp000 = Inp000;
|
||||
}
|
||||
|
||||
if ((Inp001 & 0x03) && (Inp001 & 0x0C)) {
|
||||
Inp001 ^= (nPrevInp001 & 0x0F);
|
||||
} else {
|
||||
nPrevInp001 = Inp001;
|
||||
}
|
||||
}
|
||||
|
||||
if (nMaxPlayers > 2) {
|
||||
if (Cps == 2) {
|
||||
StopOpposite(&Inp011);
|
||||
if (nMaxPlayers == 4) {
|
||||
StopOpposite(&Inp010);
|
||||
}
|
||||
} else {
|
||||
StopOpposite(&Inp177);
|
||||
if (nMaxPlayers == 4) {
|
||||
StopOpposite(&Inp179);
|
||||
}
|
||||
if (Cps1Qs) {
|
||||
StopOpposite(&Inpc001);
|
||||
if (nMaxPlayers == 4) {
|
||||
StopOpposite(&Inpc003);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CpsSoundCmd(UINT16 sound_code) {
|
||||
// CpsWritePort(0x181, sound_code);
|
||||
PsndCode = sound_code;
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
#include "cps.h"
|
||||
|
||||
// CPS Scroll (Background Layers)
|
||||
|
||||
// Base = 0x4000 long tile map
|
||||
// sx=Scroll X value, sy=Scroll Y value,
|
||||
INT32 Ghouls=0;
|
||||
INT32 Mercs=0;
|
||||
INT32 Sf2jc=0;
|
||||
INT32 Ssf2t=0;
|
||||
INT32 Qad=0;
|
||||
INT32 Xmcota=0;
|
||||
|
||||
INT32 Scroll1TileMask = 0;
|
||||
INT32 Scroll2TileMask = 0;
|
||||
INT32 Scroll3TileMask = 0;
|
||||
|
||||
INT32 Cps1Scr1Draw(UINT8 *Base,INT32 sx,INT32 sy)
|
||||
{
|
||||
INT32 x,y;
|
||||
INT32 ix,iy;
|
||||
INT32 nKnowBlank=-1; // The tile we know is blank
|
||||
|
||||
ix=(sx>>3)+1; iy=(sy>>3)+1;
|
||||
sx&=7; sy&=7; sx=8-sx; sy=8-sy;
|
||||
|
||||
for (y=-1; y<28; y++)
|
||||
{
|
||||
for (x=-1; x<48; x++)
|
||||
{
|
||||
INT32 t,a;
|
||||
UINT16 *pst;
|
||||
INT32 fx,fy,p;
|
||||
fx=ix+x; fy=iy+y; // fx/fy= 0 to 63
|
||||
|
||||
// Find tile address
|
||||
p=((fy&0x20)<<8) | ((fx&0x3f)<<7) | ((fy&0x1f)<<2);
|
||||
p&=0x3fff;
|
||||
pst=(UINT16 *)(Base + p);
|
||||
|
||||
t=pst[0];
|
||||
|
||||
if (Scroll1TileMask) t &= Scroll1TileMask;
|
||||
|
||||
t = GfxRomBankMapper(GFXTYPE_SCROLL1, t);
|
||||
if (t == -1) continue;
|
||||
|
||||
t<<=6; // Get real tile address
|
||||
|
||||
t+=nCpsGfxScroll[1]; // add on offset to scroll tiles
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
|
||||
a=pst[1];
|
||||
|
||||
CpstSetPal(0x20 | (a&0x1f));
|
||||
|
||||
// Don't need to clip except around the border
|
||||
if (x<0 || x>=48-1 || y<0 || y>=28-1)
|
||||
nCpstType=CTT_8X8 | CTT_CARE;
|
||||
else
|
||||
nCpstType=CTT_8X8;
|
||||
|
||||
nCpstX=sx+(x<<3); nCpstY=sy+(y<<3);
|
||||
nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
|
||||
if (nBgHi) {
|
||||
CpstPmsk = *(UINT16*)(CpsSaveReg[0] + MaskAddr[(a & 0x180) >> 7]);
|
||||
}
|
||||
|
||||
if(CpstOneDoX[nBgHi]()) nKnowBlank=t;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps2Scr1Draw(UINT8 *Base, INT32 sx, INT32 sy)
|
||||
{
|
||||
INT32 x, y;
|
||||
INT32 ix, iy;
|
||||
INT32 nFirstY, nLastY;
|
||||
INT32 nKnowBlank = -1; // The tile we know is blank
|
||||
|
||||
ix = (sx >> 3) + 1;
|
||||
sx &= 7;
|
||||
sx = 8 - sx;
|
||||
|
||||
iy = (sy >> 3) + 1;
|
||||
sy &= 7;
|
||||
|
||||
nLastY = (nEndline + sy) >> 3;
|
||||
nFirstY = (nStartline + sy) >> 3;
|
||||
|
||||
sy = 8 - sy;
|
||||
|
||||
for (y = nFirstY - 1; y < nLastY; y++) {
|
||||
INT32 nClipY = ((y << 3) < nStartline) | (((y << 3) + 8) >= nEndline);
|
||||
for (x = -1; x < 48; x++) {
|
||||
INT32 t, a;
|
||||
UINT16 *pst;
|
||||
INT32 fx, fy, p;
|
||||
fx = ix + x;
|
||||
fy = iy + y; // 0 <= fx/fy <= 63
|
||||
|
||||
// Find tile address
|
||||
p = ((fy & 0x20) << 8) | ((fx & 0x3F) << 7) | ((fy & 0x1F) << 2);
|
||||
p &= 0x3FFF;
|
||||
pst = (UINT16 *)(Base + p);
|
||||
|
||||
t = pst[0];
|
||||
t <<= 6; // Get real tile address
|
||||
|
||||
t += nCpsGfxScroll[1]; // add on offset to scroll tiles
|
||||
|
||||
if (t != nKnowBlank) { // Draw tile
|
||||
a = pst[1];
|
||||
|
||||
CpstSetPal(0x20 | (a & 0x1F));
|
||||
|
||||
nCpstX = sx + (x << 3);
|
||||
nCpstY = sy + (y << 3);
|
||||
nCpstTile = t;
|
||||
nCpstFlip = (a >> 5) & 3;
|
||||
|
||||
// Don't need to clip except around the border
|
||||
if (x < 0 || x >= 48 - 1 || nClipY) {
|
||||
nCpstType = CTT_8X8 | CTT_CARE;
|
||||
} else {
|
||||
nCpstType = CTT_8X8;
|
||||
}
|
||||
|
||||
if (CpstOneDoX[2]()) {
|
||||
nKnowBlank = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps1Scr3Draw(UINT8 *Base,INT32 sx,INT32 sy)
|
||||
{
|
||||
INT32 x,y;
|
||||
INT32 ix,iy;
|
||||
INT32 nKnowBlank=-1; // The tile we know is blank
|
||||
ix=(sx>>5)+1; iy=(sy>>5)+1;
|
||||
sx&=31; sy&=31; sx=32-sx; sy=32-sy;
|
||||
|
||||
for (y=-1; y<7; y++)
|
||||
{
|
||||
for (x=-1; x<12; x++)
|
||||
{
|
||||
INT32 t,a;
|
||||
UINT16 *pst;
|
||||
INT32 fx,fy,p;
|
||||
fx=ix+x; fy=iy+y; // fx/fy= 0 to 63
|
||||
|
||||
// Find tile address
|
||||
p=((fy&0x38)<<8) | ((fx&0x3f)<<5) | ((fy&0x07)<<2);
|
||||
p&=0x3fff;
|
||||
pst=(UINT16 *)(Base + p);
|
||||
|
||||
t=pst[0];
|
||||
|
||||
if (Scroll3TileMask) t &= Scroll3TileMask;
|
||||
|
||||
t = GfxRomBankMapper(GFXTYPE_SCROLL3, t);
|
||||
if (t == -1) continue;
|
||||
|
||||
t<<=9; // Get real tile address
|
||||
t+=nCpsGfxScroll[3]; // add on offset to scroll tiles
|
||||
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
|
||||
a=pst[1];
|
||||
|
||||
CpstSetPal(0x60 | (a&0x1f));
|
||||
|
||||
// Don't need to clip except around the border
|
||||
if (x<0 || x>=12-1 || y<0 || y>=7-1)
|
||||
nCpstType=CTT_32X32 | CTT_CARE;
|
||||
else
|
||||
nCpstType=CTT_32X32;
|
||||
|
||||
nCpstX=sx+(x<<5); nCpstY=sy+(y<<5);
|
||||
nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
|
||||
if (nBgHi) {
|
||||
CpstPmsk = *(UINT16*)(CpsSaveReg[0] + MaskAddr[(a & 0x180) >> 7]);
|
||||
}
|
||||
|
||||
if(CpstOneDoX[nBgHi]()) nKnowBlank=t;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps2Scr3Draw(UINT8 *Base, INT32 sx, INT32 sy)
|
||||
{
|
||||
INT32 x, y;
|
||||
INT32 ix, iy;
|
||||
INT32 nFirstY, nLastY;
|
||||
INT32 nKnowBlank = -1; // The tile we know is blank
|
||||
|
||||
ix = (sx >> 5) + 1;
|
||||
sx &= 31;
|
||||
sx = 32 - sx;
|
||||
|
||||
iy = (sy >> 5) + 1;
|
||||
sy &= 31;
|
||||
|
||||
nLastY = (nEndline + sy) >> 5;
|
||||
nFirstY = (nStartline + sy) >> 5;
|
||||
|
||||
sy = 32 - sy;
|
||||
|
||||
for (y = nFirstY - 1; y < nLastY; y++) {
|
||||
INT32 nClipY = ((y << 5) < nStartline) | (((y << 5) + 32) >= nEndline);
|
||||
for (x = -1; x < 12; x++) {
|
||||
INT32 t, a;
|
||||
UINT16 *pst;
|
||||
INT32 fx, fy, p;
|
||||
fx = ix + x;
|
||||
fy = iy + y; // 0 <= fx/fy <= 63
|
||||
|
||||
// Find tile address
|
||||
p = ((fy & 0x38) << 8) | ((fx & 0x3F) << 5) | ((fy & 0x07) << 2);
|
||||
p &= 0x3FFF;
|
||||
pst = (UINT16 *)(Base + p);
|
||||
|
||||
t = pst[0];
|
||||
|
||||
if(Xmcota && t>=0x5800) t-=0x4000;
|
||||
else if(Ssf2t && t<0x5600) t+=0x4000;
|
||||
t <<= 9; // Get real tile address
|
||||
t += nCpsGfxScroll[3]; // add on offset to scroll tiles
|
||||
|
||||
if (t != nKnowBlank) { // Draw tile
|
||||
a = pst[1];
|
||||
|
||||
CpstSetPal(0x60 | (a & 0x1F));
|
||||
|
||||
nCpstX = sx + (x << 5);
|
||||
nCpstY = sy + (y << 5);
|
||||
nCpstTile = t;
|
||||
nCpstFlip = (a >> 5) & 3;
|
||||
|
||||
// Don't need to clip except around the border
|
||||
if (x < 0 || x >= 12 - 1 || nClipY) {
|
||||
nCpstType = CTT_32X32 | CTT_CARE;
|
||||
} else {
|
||||
nCpstType = CTT_32X32;
|
||||
}
|
||||
|
||||
if (CpstOneDoX[2]()) {
|
||||
nKnowBlank = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
#include "cps.h"
|
||||
|
||||
// CPS Scroll2 with Row scroll support
|
||||
|
||||
UINT8 *CpsrBase=NULL; // Tile data base
|
||||
INT32 nCpsrScrX=0,nCpsrScrY=0; // Basic scroll info
|
||||
UINT16 *CpsrRows=NULL; // Row scroll table, 0x400 words long
|
||||
int nCpsrRowStart=0; // Start of row scroll (can wrap?)
|
||||
static INT32 nShiftY=0;
|
||||
static INT32 EndLineInfo=0;
|
||||
|
||||
struct CpsrLineInfo CpsrLineInfo[15];
|
||||
|
||||
static void GetRowsRange(INT32 *pnStart,INT32 *pnWidth,INT32 nRowFrom,INT32 nRowTo)
|
||||
{
|
||||
INT32 i,nStart,nWidth;
|
||||
|
||||
// Get the range of scroll values within nRowCount rows
|
||||
// Start with zero range
|
||||
nStart=CpsrRows[nRowFrom&0x3ff]; nStart&=0x3ff; nWidth=0;
|
||||
for (i=nRowFrom;i<nRowTo;i++)
|
||||
{
|
||||
INT32 nViz; INT32 nDiff;
|
||||
nViz=CpsrRows[i&0x3ff]; nViz&=0x3ff;
|
||||
// Work out if this is on the left or the right of our
|
||||
// start point.
|
||||
nDiff=nViz-nStart;
|
||||
// clip to 10-bit signed
|
||||
nDiff=((nDiff+0x200)&0x3ff)-0x200;
|
||||
if (nDiff>=0)
|
||||
{
|
||||
// On the right
|
||||
if (nDiff>=nWidth) nWidth=nDiff; // expand width to cover it
|
||||
}
|
||||
else
|
||||
{
|
||||
// On the left
|
||||
nStart+=nDiff; nStart&=0x3ff;
|
||||
nWidth-=nDiff; // expand width to cover it
|
||||
}
|
||||
}
|
||||
|
||||
if (nWidth>0x400) nWidth=0x400;
|
||||
|
||||
*pnStart=nStart;
|
||||
*pnWidth=nWidth;
|
||||
}
|
||||
|
||||
|
||||
static INT32 PrepareRows()
|
||||
{
|
||||
INT32 y; INT32 r;
|
||||
struct CpsrLineInfo *pli;
|
||||
// Calculate the amount of pixels to shift each
|
||||
// row of the tile lines, assuming we draw tile x at
|
||||
// (x-pli->nTileStart)<<4 - i.e. 0, 16, ...
|
||||
|
||||
r=nShiftY-16;
|
||||
for (y = -1, pli = CpsrLineInfo; y < EndLineInfo; y++, pli++)
|
||||
{
|
||||
// Maximum row scroll left and right on this line
|
||||
INT32 nMaxLeft=0,nMaxRight=0;
|
||||
INT32 ty; INT16 *pr;
|
||||
|
||||
if (CpsrRows==NULL)
|
||||
{
|
||||
// No row shift - all the same
|
||||
INT32 v;
|
||||
v =(pli->nTileStart<<4)-nCpsrScrX;
|
||||
nMaxLeft=v; nMaxRight=v;
|
||||
for (ty=0,pr=pli->Rows; ty<16; ty++,pr++)
|
||||
{
|
||||
*pr=(INT16)v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ty=0,pr=pli->Rows; ty<16; ty++,pr++,r++)
|
||||
{
|
||||
// Get the row offset, if it's in range
|
||||
if (r>=0 && r<nEndline)
|
||||
{
|
||||
INT32 v;
|
||||
v =(pli->nTileStart<<4)-nCpsrScrX;
|
||||
v-=CpsrRows[(nCpsrRowStart+r)&0x3ff];
|
||||
// clip to 10-bit signed
|
||||
v+=0x200; v&=0x3ff; v-=0x200;
|
||||
*pr=(INT16)v;
|
||||
if (v<nMaxLeft) nMaxLeft=v;
|
||||
else if (v>nMaxRight) nMaxRight=v;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pr=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pli->nMaxLeft =nMaxLeft;
|
||||
pli->nMaxRight=nMaxRight;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Prepare to draw Scroll 2 with rows, by seeing how much
|
||||
// row scroll each tile line uses (pli->nStart/nWidth),
|
||||
// and finding which tiles are visible onscreen (pli->nTileStart/End).
|
||||
|
||||
INT32 Cps1rPrepare()
|
||||
{
|
||||
INT32 y; struct CpsrLineInfo *pli;
|
||||
if (CpsrBase==NULL) return 1;
|
||||
|
||||
nEndline = 224;
|
||||
EndLineInfo = 14;
|
||||
nShiftY=16-(nCpsrScrY&15);
|
||||
|
||||
for (y=-1,pli=CpsrLineInfo; y<EndLineInfo; y++,pli++)
|
||||
{
|
||||
INT32 nStart=0,nWidth=0;
|
||||
|
||||
if (CpsrRows!=NULL)
|
||||
{
|
||||
INT32 nRowFrom,nRowTo;
|
||||
// Find out which rows we need to check
|
||||
nRowFrom=(y<<4)+nShiftY;
|
||||
nRowTo=nRowFrom+16;
|
||||
if (nRowFrom<0) nRowFrom=0;
|
||||
if (nRowTo>224) nRowTo=224;
|
||||
|
||||
// Shift by row table start offset
|
||||
nRowFrom+=nCpsrRowStart;
|
||||
nRowTo +=nCpsrRowStart;
|
||||
|
||||
// Find out what range of scroll values there are for this line
|
||||
GetRowsRange(&nStart,&nWidth,nRowFrom,nRowTo);
|
||||
}
|
||||
|
||||
nStart+=nCpsrScrX;
|
||||
nStart&=0x3ff;
|
||||
|
||||
// Save info in CpsrLineInfo table
|
||||
pli->nStart=nStart;
|
||||
pli->nWidth=nWidth;
|
||||
// Find range of tiles to draw to see whole width:
|
||||
pli->nTileStart=nStart>>4;
|
||||
pli->nTileEnd=(nStart+nWidth+0x18f)>>4;
|
||||
}
|
||||
|
||||
PrepareRows();
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps2rPrepare()
|
||||
{
|
||||
INT32 y;
|
||||
struct CpsrLineInfo *pli;
|
||||
if (CpsrBase==NULL) return 1;
|
||||
|
||||
EndLineInfo = ((nEndline + 15) >> 4);
|
||||
|
||||
nShiftY=16-(nCpsrScrY&15);
|
||||
for (y = -1, pli = CpsrLineInfo; y < EndLineInfo; y++, pli++)
|
||||
{
|
||||
INT32 nStart=0,nWidth=0;
|
||||
|
||||
if (CpsrRows!=NULL)
|
||||
{
|
||||
INT32 nRowFrom,nRowTo;
|
||||
// Find out which rows we need to check
|
||||
nRowFrom=(y<<4)+nShiftY;
|
||||
nRowTo=nRowFrom+16;
|
||||
if (nRowFrom < 0) nRowFrom = 0;
|
||||
if (nRowTo > nEndline) nRowTo = nEndline;
|
||||
|
||||
// Shift by row table start offset
|
||||
nRowFrom+=nCpsrRowStart;
|
||||
nRowTo +=nCpsrRowStart;
|
||||
|
||||
// Find out what range of scroll values there are for this line
|
||||
GetRowsRange(&nStart,&nWidth,nRowFrom,nRowTo);
|
||||
}
|
||||
|
||||
nStart+=nCpsrScrX;
|
||||
nStart&=0x3ff;
|
||||
|
||||
// Save info in CpsrLineInfo table
|
||||
pli->nStart=nStart;
|
||||
pli->nWidth=nWidth;
|
||||
// Find range of tiles to draw to see whole width:
|
||||
pli->nTileStart=nStart>>4;
|
||||
pli->nTileEnd=(nStart+nWidth+0x18f)>>4;
|
||||
}
|
||||
|
||||
PrepareRows();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
#include "cps.h"
|
||||
|
||||
// CPS Scroll2 with Row scroll - Draw
|
||||
static INT32 nKnowBlank=-1; // The tile we know is blank
|
||||
static INT32 nFirstY, nLastY;
|
||||
static INT32 bVCare;
|
||||
|
||||
inline static UINT16 *FindTile(INT32 fx,INT32 fy)
|
||||
{
|
||||
INT32 p; UINT16 *pst;
|
||||
// Find tile address
|
||||
p=((fy&0x30)<<8) | ((fx&0x3f)<<6) | ((fy&0x0f)<<2);
|
||||
pst=(UINT16 *)(CpsrBase + p);
|
||||
return pst;
|
||||
}
|
||||
|
||||
// Draw a tile line without Row Shift
|
||||
static void Cps1TileLine(INT32 y,INT32 sx)
|
||||
{
|
||||
INT32 x,ix,iy,sy;
|
||||
|
||||
bVCare=0;
|
||||
if (y<0 || y>=14-1) bVCare=1; // Take care on the edges
|
||||
|
||||
ix=(sx>>4)+1; sx&=15; sx=16-sx;
|
||||
sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1;
|
||||
nCpstY=sy+(y<<4);
|
||||
|
||||
for (x=-1; x<24; x++)
|
||||
{
|
||||
UINT16 *pst; INT32 t,a;
|
||||
// Don't need to clip except around the border
|
||||
if (bVCare || x<0 || x>=24-1) nCpstType=CTT_16X16 | CTT_CARE;
|
||||
else nCpstType=CTT_16X16;
|
||||
|
||||
pst=FindTile(ix+x,iy+y);
|
||||
t=pst[0];
|
||||
|
||||
if (Scroll2TileMask) t &= Scroll2TileMask;
|
||||
|
||||
t = GfxRomBankMapper(GFXTYPE_SCROLL2, t);
|
||||
if (t == -1) continue;
|
||||
|
||||
t<<=7; // Get real tile address
|
||||
t+=nCpsGfxScroll[2]; // add on offset to scroll tile
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
|
||||
a=pst[1];
|
||||
|
||||
CpstSetPal(0x40 | (a&0x1f));
|
||||
nCpstX=sx+(x<<4); nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
|
||||
if(nBgHi) CpstPmsk=*(UINT16 *)(CpsSaveReg[0] + MaskAddr[(a&0x180)>>7]);
|
||||
if(CpstOneDoX[nBgHi]()) nKnowBlank=t;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cps2TileLine(INT32 y,INT32 sx)
|
||||
{
|
||||
INT32 x,ix,iy,sy;
|
||||
|
||||
ix=(sx>>4)+1; sx&=15; sx=16-sx;
|
||||
sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1;
|
||||
nCpstY=sy+(y<<4);
|
||||
|
||||
for (x=-1; x<24; x++)
|
||||
{
|
||||
UINT16 *pst; INT32 t,a;
|
||||
// Don't need to clip except around the border
|
||||
if (bVCare || x<0 || x>=24-1) nCpstType=CTT_16X16 | CTT_CARE;
|
||||
else nCpstType=CTT_16X16;
|
||||
|
||||
pst=FindTile(ix+x,iy+y);
|
||||
t=pst[0];
|
||||
t<<=7; // Get real tile address
|
||||
t+=nCpsGfxScroll[2]; // add on offset to scroll tiles
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
a=pst[1];
|
||||
|
||||
CpstSetPal(0x40 | (a&0x1f));
|
||||
nCpstX=sx+(x<<4); nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
if(CpstOneDoX[2]()) nKnowBlank=t;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a tile line with Row Shift
|
||||
static void Cps1TileLineRows(INT32 y,struct CpsrLineInfo *pli)
|
||||
{
|
||||
INT32 sy,iy,x;
|
||||
INT32 nTileCount;
|
||||
INT32 nLimLeft,nLimRight;
|
||||
|
||||
bVCare=0;
|
||||
if (y<0 || y>=14-1) bVCare=1; // Take care on the edges
|
||||
|
||||
nTileCount=pli->nTileEnd-pli->nTileStart;
|
||||
|
||||
sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1;
|
||||
nCpstY=sy+(y<<4);
|
||||
CpstRowShift=pli->Rows;
|
||||
|
||||
// If these rowshift limits go off the edges, we should take
|
||||
// care drawing the tile.
|
||||
nLimLeft =pli->nMaxLeft;
|
||||
nLimRight=pli->nMaxRight;
|
||||
for (x=0; x<nTileCount; x++,
|
||||
nLimLeft+=16, nLimRight+=16)
|
||||
{
|
||||
UINT16 *pst; INT32 t,a; INT32 tx; INT32 bCare;
|
||||
tx=pli->nTileStart+x;
|
||||
|
||||
// See if we have to clip vertically anyway
|
||||
bCare=bVCare;
|
||||
if (bCare==0) // If we don't...
|
||||
{
|
||||
// Check screen limits of this tile
|
||||
if (nLimLeft < 0) bCare=1; // Will cross left egde
|
||||
if (nLimRight> 384-16) bCare=1; // Will cross right edge
|
||||
}
|
||||
if (bCare) nCpstType=CTT_16X16 | CTT_ROWS | CTT_CARE;
|
||||
else nCpstType=CTT_16X16 | CTT_ROWS;
|
||||
|
||||
pst=FindTile(tx,iy+y);
|
||||
t=pst[0];
|
||||
|
||||
if (Scroll2TileMask) t &= Scroll2TileMask;
|
||||
|
||||
t = GfxRomBankMapper(GFXTYPE_SCROLL2, t);
|
||||
if (t == -1) continue;
|
||||
|
||||
t<<=7; // Get real tile address
|
||||
t+=nCpsGfxScroll[2]; // add on offset to scroll tiles
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
|
||||
a=pst[1];
|
||||
|
||||
CpstSetPal(0x40 | (a&0x1f));
|
||||
|
||||
nCpstX=x<<4; nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
|
||||
if (nBgHi) {
|
||||
CpstPmsk = *(UINT16*)(CpsSaveReg[0] + MaskAddr[(a & 0x180) >> 7]);
|
||||
}
|
||||
|
||||
if(CpstOneDoX[nBgHi]()) nKnowBlank=t;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cps2TileLineRows(INT32 y,struct CpsrLineInfo *pli)
|
||||
{
|
||||
INT32 sy,iy,x;
|
||||
INT32 nTileCount;
|
||||
INT32 nLimLeft,nLimRight;
|
||||
|
||||
nTileCount=pli->nTileEnd-pli->nTileStart;
|
||||
|
||||
sy=16-(nCpsrScrY&15); iy=(nCpsrScrY>>4)+1;
|
||||
nCpstY=sy+(y<<4);
|
||||
CpstRowShift=pli->Rows;
|
||||
|
||||
// If these rowshift limits go off the edges, we should take
|
||||
// care drawing the tile.
|
||||
nLimLeft =pli->nMaxLeft;
|
||||
nLimRight=pli->nMaxRight;
|
||||
for (x=0; x<nTileCount; x++,
|
||||
nLimLeft+=16, nLimRight+=16)
|
||||
{
|
||||
UINT16 *pst; INT32 t,a; INT32 tx; INT32 bCare;
|
||||
tx=pli->nTileStart+x;
|
||||
|
||||
// See if we have to clip vertically anyway
|
||||
bCare=bVCare;
|
||||
if (bCare==0) // If we don't...
|
||||
{
|
||||
// Check screen limits of this tile
|
||||
if (nLimLeft < 0) bCare=1; // Will cross left egde
|
||||
if (nLimRight> 384-16) bCare=1; // Will cross right edge
|
||||
}
|
||||
if (bCare) nCpstType=CTT_16X16 | CTT_ROWS | CTT_CARE;
|
||||
else nCpstType=CTT_16X16 | CTT_ROWS;
|
||||
|
||||
pst=FindTile(tx,iy+y);
|
||||
t=pst[0];
|
||||
t<<=7; // Get real tile address
|
||||
t+=nCpsGfxScroll[2]; // add on offset to scroll tiles
|
||||
|
||||
if (t==nKnowBlank) continue; // Don't draw: we know it's blank
|
||||
a=pst[1];
|
||||
|
||||
CpstSetPal(0x40 | (a&0x1f));
|
||||
|
||||
nCpstX=x<<4; nCpstTile=t; nCpstFlip=(a>>5)&3;
|
||||
if(CpstOneDoX[2]()) nKnowBlank=t;
|
||||
}
|
||||
}
|
||||
|
||||
INT32 Cps1rRender()
|
||||
{
|
||||
INT32 y; struct CpsrLineInfo *pli;
|
||||
if (CpsrBase==NULL) return 1;
|
||||
|
||||
nKnowBlank=-1; // We don't know which tile is blank yet
|
||||
|
||||
for (y=-1,pli=CpsrLineInfo; y<14; y++,pli++)
|
||||
{
|
||||
if (pli->nWidth==0)
|
||||
Cps1TileLine(y,pli->nStart); // no rowscroll needed
|
||||
else
|
||||
Cps1TileLineRows(y,pli); // row scroll
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 Cps2rRender()
|
||||
{
|
||||
INT32 y;
|
||||
struct CpsrLineInfo *pli;
|
||||
if (CpsrBase==NULL) return 1;
|
||||
|
||||
nKnowBlank = -1; // We don't know which tile is blank yet
|
||||
|
||||
nLastY = (nEndline + (nCpsrScrY & 15)) >> 4;
|
||||
nFirstY = (nStartline + (nCpsrScrY & 15)) >> 4;
|
||||
for (y = nFirstY - 1, pli = CpsrLineInfo + nFirstY; y < nLastY; y++, pli++) {
|
||||
|
||||
bVCare = ((y << 4) < nStartline) | (((y << 4) + 16) >= nEndline);
|
||||
|
||||
if (pli->nWidth==0) {
|
||||
Cps2TileLine(y,pli->nStart); // no rowscroll needed
|
||||
} else {
|
||||
Cps2TileLineRows(y,pli); // row scroll
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
#include "cps.h"
|
||||
|
||||
// CPS Tiles
|
||||
UINT32 *CpstPal=NULL;
|
||||
|
||||
// Arguments for the tile draw function
|
||||
UINT32 nCpstType = 0;
|
||||
INT32 nCpstX = 0, nCpstY = 0;
|
||||
UINT32 nCpstTile = 0;
|
||||
INT32 nCpstFlip = 0;
|
||||
INT16 *CpstRowShift = NULL;
|
||||
UINT32 CpstPmsk = 0; // Pixel mask
|
||||
|
||||
INT32 nBgHi = 0;
|
||||
UINT16 ZValue = 1;
|
||||
UINT16* ZBuf = NULL;
|
||||
UINT16* pZVal = NULL;
|
||||
|
||||
static INT32 CpstOne();
|
||||
static INT32 Cps2tOne();
|
||||
static INT32 CpstOneBgHi();
|
||||
static INT32 CpstOneObjZ();
|
||||
CpstOneDoFn CpstOneDoX[3] = { CpstOne, CpstOneBgHi, Cps2tOne};
|
||||
CpstOneDoFn CpstOneObjDoX[2] = { CpstOne, CpstOneObjZ};
|
||||
|
||||
static INT32 CpstOne()
|
||||
{
|
||||
INT32 nFun; INT32 nSize;
|
||||
nSize=(nCpstType&24)+8;
|
||||
|
||||
if (nCpstType&CTT_CARE)
|
||||
{
|
||||
if ((nCpstType&CTT_ROWS)==0)
|
||||
{
|
||||
// Return if not visible at all
|
||||
if (nCpstX <= -nSize) return 0;
|
||||
if (nCpstX >= 384) return 0;
|
||||
if (nCpstY <= -nSize) return 0;
|
||||
if (nCpstY >= 224) return 0;
|
||||
}
|
||||
nCtvRollX=0x4000017f + nCpstX * 0x7fff;
|
||||
nCtvRollY=0x400000df + nCpstY * 0x7fff;
|
||||
}
|
||||
|
||||
// Clip to loaded graphics data (we have a gap of 0x200 at the end)
|
||||
nCpstTile&=nCpsGfxMask; if (nCpstTile>=nCpsGfxLen) return 1;
|
||||
pCtvTile=CpsGfx+nCpstTile;
|
||||
|
||||
// Find pLine (pointer to first pixel)
|
||||
pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp;
|
||||
|
||||
if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8;
|
||||
|
||||
if (nCpstFlip&2)
|
||||
{
|
||||
// Flip vertically
|
||||
if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; }
|
||||
else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; }
|
||||
else { nCtvTileAdd= -8; pCtvTile+= 7* 8; }
|
||||
}
|
||||
|
||||
nFun =nCpstType&0x1e;
|
||||
nFun|=nCpstFlip&1;
|
||||
return CtvDoX[nFun]();
|
||||
}
|
||||
|
||||
static INT32 CpstOneBgHi()
|
||||
{
|
||||
INT32 nFun; INT32 nSize;
|
||||
nSize=(nCpstType&24)+8;
|
||||
|
||||
if (nCpstType&CTT_CARE)
|
||||
{
|
||||
if ((nCpstType&CTT_ROWS)==0)
|
||||
{
|
||||
// Return if not visible at all
|
||||
if (nCpstX<=-nSize) return 0;
|
||||
if (nCpstX>=384) return 0;
|
||||
if (nCpstY<=-nSize) return 0;
|
||||
if (nCpstY>=224) return 0;
|
||||
}
|
||||
nCtvRollX=0x4000017f + nCpstX * 0x7fff;
|
||||
nCtvRollY=0x400000df + nCpstY * 0x7fff;
|
||||
}
|
||||
|
||||
// Clip to loaded graphics data (we have a gap of 0x200 at the end)
|
||||
nCpstTile&=nCpsGfxMask;
|
||||
if (nCpstTile>=nCpsGfxLen) return 1;
|
||||
pCtvTile=CpsGfx+nCpstTile;
|
||||
|
||||
// Find pLine (pointer to first pixel)
|
||||
pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp;
|
||||
|
||||
if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8;
|
||||
|
||||
if (nCpstFlip&2)
|
||||
{
|
||||
// Flip vertically
|
||||
if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; }
|
||||
else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; }
|
||||
else { nCtvTileAdd= -8; pCtvTile+= 7* 8; }
|
||||
}
|
||||
|
||||
nFun =nCpstType&0x1e;
|
||||
nFun|=nCpstFlip&1;
|
||||
return CtvDoXB[nFun]();
|
||||
}
|
||||
|
||||
static INT32 Cps2tOne()
|
||||
{
|
||||
INT32 nFun; INT32 nSize;
|
||||
nSize=(nCpstType&24)+8;
|
||||
|
||||
if (nCpstType&CTT_CARE)
|
||||
{
|
||||
if ((nCpstType&CTT_ROWS)==0)
|
||||
{
|
||||
// Return if not visible at all
|
||||
if (nCpstX <= -nSize) return 0;
|
||||
if (nCpstX >= 384) return 0;
|
||||
if (nCpstY <= -nStartline - nSize) return 0;
|
||||
if (nCpstY >= nEndline) return 0;
|
||||
}
|
||||
nCtvRollX=0x4000017f + nCpstX * 0x7fff;
|
||||
nCtvRollY=0x40000000 + nEndline - nStartline - 1 + (nCpstY - nStartline) * 0x7fff;
|
||||
}
|
||||
|
||||
// Clip to loaded graphics data (we have a gap of 0x200 at the end)
|
||||
nCpstTile&=nCpsGfxMask; if (nCpstTile>=nCpsGfxLen) return 0;
|
||||
pCtvTile=CpsGfx+nCpstTile;
|
||||
|
||||
// Find pLine (pointer to first pixel)
|
||||
pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp;
|
||||
|
||||
if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8;
|
||||
|
||||
if (nCpstFlip&2)
|
||||
{
|
||||
// Flip vertically
|
||||
if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; }
|
||||
else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; }
|
||||
else { nCtvTileAdd= -8; pCtvTile+= 7* 8; }
|
||||
}
|
||||
|
||||
nFun =nCpstType&0x1e;
|
||||
nFun|=nCpstFlip&1;
|
||||
return CtvDoX[nFun]();
|
||||
}
|
||||
|
||||
static INT32 CpstOneObjZ()
|
||||
{
|
||||
INT32 nFun; INT32 nSize;
|
||||
nSize=(nCpstType&24)+8;
|
||||
|
||||
|
||||
if (nCpstType&CTT_CARE)
|
||||
{
|
||||
if ((nCpstType&CTT_ROWS)==0)
|
||||
{
|
||||
// Return if not visible at all
|
||||
if (nCpstX <= -nSize) return 0;
|
||||
if (nCpstX >= 384) return 0;
|
||||
if (nCpstY <= -nSize) return 0;
|
||||
if (nCpstY >= 224) return 0;
|
||||
}
|
||||
nCtvRollX=0x4000017f + nCpstX * 0x7fff;
|
||||
nCtvRollY=0x400000df + nCpstY * 0x7fff;
|
||||
}
|
||||
|
||||
|
||||
// Clip to loaded graphics data (we have a gap of 0x200 at the end)
|
||||
nCpstTile&=nCpsGfxMask; if (nCpstTile>=nCpsGfxLen) return 1;
|
||||
pCtvTile=CpsGfx+nCpstTile;
|
||||
|
||||
// Find pLine (pointer to first pixel)
|
||||
pCtvLine=pBurnDraw + nCpstY*nBurnPitch + nCpstX*nBurnBpp;
|
||||
pZVal=ZBuf + nCpstY*384 + nCpstX;
|
||||
|
||||
if (nSize==32) nCtvTileAdd=16; else nCtvTileAdd=8;
|
||||
|
||||
if (nCpstFlip&2)
|
||||
{
|
||||
// Flip vertically
|
||||
if (nSize==16) { nCtvTileAdd= -8; pCtvTile+=15* 8; }
|
||||
else if (nSize==32) { nCtvTileAdd=-16; pCtvTile+=31*16; }
|
||||
else { nCtvTileAdd= -8; pCtvTile+= 7* 8; }
|
||||
}
|
||||
|
||||
nFun =nCpstType&0x1e;
|
||||
nFun|=nCpstFlip&1;
|
||||
return CtvDoXM[nFun]();
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#include "cps.h"
|
||||
|
||||
// CPS Tile Variants
|
||||
// horizontal/vertical clip rolls
|
||||
UINT32 nCtvRollX=0,nCtvRollY=0;
|
||||
// Add 0x7fff after each pixel/line
|
||||
// If nRollX/Y&0x20004000 both == 0, you can draw the pixel
|
||||
|
||||
UINT8 *pCtvTile=NULL; // Pointer to tile data
|
||||
INT32 nCtvTileAdd=0; // Amount to add after each tile line
|
||||
UINT8 *pCtvLine=NULL; // Pointer to output bitmap
|
||||
|
||||
// Include all tile variants:
|
||||
#include "ctv.h"
|
||||
|
||||
static INT32 nLastBpp=0;
|
||||
INT32 CtvReady()
|
||||
{
|
||||
// Set up the CtvDoX functions to point to the correct bpp functions.
|
||||
// Must be called before calling CpstOne
|
||||
if (nBurnBpp!=nLastBpp)
|
||||
{
|
||||
if (nBurnBpp==2) {
|
||||
memcpy(CtvDoX,CtvDo2,sizeof(CtvDoX));
|
||||
memcpy(CtvDoXM,CtvDo2m,sizeof(CtvDoXM));
|
||||
memcpy(CtvDoXB,CtvDo2b,sizeof(CtvDoXB));
|
||||
}
|
||||
else if (nBurnBpp==3) {
|
||||
memcpy(CtvDoX,CtvDo3,sizeof(CtvDoX));
|
||||
memcpy(CtvDoXM,CtvDo3m,sizeof(CtvDoXM));
|
||||
memcpy(CtvDoXB,CtvDo3b,sizeof(CtvDoXB));
|
||||
}
|
||||
else if (nBurnBpp==4) {
|
||||
memcpy(CtvDoX,CtvDo4,sizeof(CtvDoX));
|
||||
memcpy(CtvDoXM,CtvDo4m,sizeof(CtvDoXM));
|
||||
memcpy(CtvDoXB,CtvDo4b,sizeof(CtvDoXB));
|
||||
}
|
||||
}
|
||||
nLastBpp=nBurnBpp;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
// CPS Tiles (header)
|
||||
|
||||
// Draw a nxn tile
|
||||
// pCtvLine, pTile, nTileAdd are defined
|
||||
// CU_FLIPX is 1 to flip the tile horizontally
|
||||
// CU_CARE is 1 to clip output based on nCtvRollX/Y
|
||||
// CU_ROWS is 1 to shift output based on CpstRowShift
|
||||
// CU_SIZE is 8, 16 or 32
|
||||
// CU_BPP is 1 2 3 4 bytes per pixel
|
||||
// CU_MASK CPS1 BgHi CPS2 Sprite Masking
|
||||
|
||||
#ifndef CU_FLIPX
|
||||
#error "CU_FLIPX wasn\'t defined"
|
||||
#endif
|
||||
|
||||
#ifndef CU_CARE
|
||||
#error "CU_CARE wasn\'t defined"
|
||||
#endif
|
||||
|
||||
#ifndef CU_ROWS
|
||||
#error "CU_ROWS wasn\'t defined"
|
||||
#endif
|
||||
|
||||
#ifndef CU_SIZE
|
||||
#error "CU_SIZE wasn\'t defined"
|
||||
#endif
|
||||
|
||||
#ifndef CU_BPP
|
||||
#error "CU_BPP wasn\'t defined"
|
||||
#endif
|
||||
|
||||
#ifndef CU_MASK
|
||||
#error "CU_MASK wasn\'t defined"
|
||||
#endif
|
||||
|
||||
{
|
||||
INT32 y;
|
||||
UINT32 *ctp;
|
||||
UINT32 nBlank = 0;
|
||||
|
||||
UINT32 b; // Eight bit-packed pixels (msb) AAAABBBB CCCCDDDD EEEEFFFF GGGGHHHH (lsb)
|
||||
UINT32 c; // 32-bit colour value
|
||||
UINT8 *pPix; // Pointer to output bitmap
|
||||
|
||||
#if CU_ROWS == 1
|
||||
INT16 *Rows = CpstRowShift;
|
||||
#endif
|
||||
|
||||
ctp = CpstPal;
|
||||
|
||||
for (y = 0; y < CU_SIZE; y++, pCtvLine += nBurnPitch, pCtvTile += nCtvTileAdd
|
||||
|
||||
#if CU_ROWS==1
|
||||
,Rows++
|
||||
#endif
|
||||
|
||||
#if CU_MASK==1
|
||||
,pZVal += 384
|
||||
#endif
|
||||
|
||||
)
|
||||
{
|
||||
#if CU_CARE==1
|
||||
UINT32 rx = nCtvRollX; // Copy of nCtvRollX
|
||||
#endif
|
||||
|
||||
#if CU_MASK==1
|
||||
UINT16 *pPixZ;
|
||||
#endif
|
||||
|
||||
#if CU_CARE==1
|
||||
if (nCtvRollY & 0x20004000) { nCtvRollY += 0x7fff; continue; } else nCtvRollY += 0x7fff; // okay to plot line
|
||||
#endif
|
||||
|
||||
// Point to the line to draw
|
||||
pPix = pCtvLine;
|
||||
#if CU_MASK==1
|
||||
pPixZ = pZVal;
|
||||
#endif
|
||||
|
||||
#if CU_ROWS==1
|
||||
#if CU_MASK==1
|
||||
pPixZ += Rows[0];
|
||||
#endif
|
||||
pPix += Rows[0] * nBurnBpp;
|
||||
#if CU_CARE==1
|
||||
rx += Rows[0] * 0x7fff;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Make macros for plotting c and advancing pPix by one pixel
|
||||
#if CU_BPP==2
|
||||
#if CU_MASK==1
|
||||
#define PLOT { if(*pPixZ < ZValue) { *((UINT16 *)pPix)=(UINT16)c; *pPixZ=ZValue; } }
|
||||
#define ADV { pPix+=2; pPixZ++; }
|
||||
#else
|
||||
#define PLOT { *((UINT16 *)pPix)=(UINT16)c; }
|
||||
#define ADV pPix+=2
|
||||
#endif
|
||||
#elif CU_BPP==3
|
||||
#if CU_MASK==1
|
||||
#define PLOT { if(*pPixZ < ZValue) { pPix[0]=(UINT8)c; pPix[1]=(UINT8)(c>>8); pPix[2]=(UINT8)(c>>16); } }
|
||||
#define ADV { pPix+=3; pPixZ++; }
|
||||
#else
|
||||
#define PLOT { pPix[0]=(UINT8)c; pPix[1]=(UINT8)(c>>8); pPix[2]=(UINT8)(c>>16); }
|
||||
#define ADV pPix+=3
|
||||
#endif
|
||||
#elif CU_BPP==4
|
||||
#if CU_MASK==1
|
||||
#define PLOT { if(*pPixZ < ZValue) { *((UINT32 *)pPix)=c; *pPixZ=ZValue; } }
|
||||
#define ADV { pPix+=4; pPixZ++; }
|
||||
#else
|
||||
#define PLOT { *((UINT32 *)pPix)=c; }
|
||||
#define ADV pPix+=4
|
||||
#endif
|
||||
#else
|
||||
#error Unsupported CU_BPP
|
||||
#endif
|
||||
|
||||
// Make macros for plotting the next pixel from 'b' (= 8 packed pixels)
|
||||
// or skipping the pixel.
|
||||
#if CU_FLIPX==0
|
||||
#define NEXTPIXEL ADV; b <<= 4;
|
||||
#if CU_MASK==2
|
||||
#define DRAWPIXEL { c = (b >> 28); if (c && CpstPmsk & (1 << (c ^ 15))) { c = ctp[c]; PLOT } }
|
||||
#else
|
||||
#define DRAWPIXEL { if (b & 0xf0000000) { c = ctp[b >> 28]; PLOT } }
|
||||
#endif
|
||||
#else
|
||||
#define NEXTPIXEL ADV; b >>= 4;
|
||||
#if CU_MASK==2
|
||||
#define DRAWPIXEL { c = (b & 15); if (c && CpstPmsk & (1 << (c ^ 15))) { c = ctp[c]; PLOT } }
|
||||
#else
|
||||
#define DRAWPIXEL { if (b & 0x0000000f) { c = ctp[b & 15]; PLOT } }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define EIGHT(x) x x x x x x x x
|
||||
|
||||
#if CU_CARE==1
|
||||
// If we need to clip left or right, check nCtvRollX before plotting
|
||||
#define DO_PIX if ((rx & 0x20004000) == 0) DRAWPIXEL NEXTPIXEL rx += 0x7fff;
|
||||
#else
|
||||
// Always plot
|
||||
#define DO_PIX DRAWPIXEL NEXTPIXEL
|
||||
#endif
|
||||
|
||||
#define DRAW_8 nBlank |= b; EIGHT(DO_PIX)
|
||||
|
||||
#if CU_SIZE==8
|
||||
// 8x8 tiles
|
||||
b=*((UINT32 *)(pCtvTile+0)); DRAW_8
|
||||
#elif CU_SIZE==16
|
||||
// 16x16 tiles
|
||||
#if CU_FLIPX==0
|
||||
b=*((UINT32 *)(pCtvTile+0)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+4)); DRAW_8
|
||||
#else
|
||||
b=*((UINT32 *)(pCtvTile+4)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+0)); DRAW_8
|
||||
#endif
|
||||
|
||||
#elif CU_SIZE==32
|
||||
// 32x32 tiles
|
||||
#if CU_FLIPX==0
|
||||
b=*((UINT32 *)(pCtvTile+ 0)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+ 4)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+ 8)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+12)); DRAW_8
|
||||
#else
|
||||
b=*((UINT32 *)(pCtvTile+12)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+ 8)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+ 4)); DRAW_8
|
||||
b=*((UINT32 *)(pCtvTile+ 0)); DRAW_8
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error Unsupported CU_SIZE
|
||||
#endif
|
||||
|
||||
#undef DRAW_8
|
||||
#undef DO_PIX
|
||||
#undef EIGHT
|
||||
#undef DRAWPIXEL
|
||||
#undef NEXTPIXEL
|
||||
|
||||
#undef ADV
|
||||
#undef PLOT
|
||||
}
|
||||
|
||||
return nBlank == 0;
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
#include <stdio.h>
|
||||
|
||||
// Create the ctv.h header file
|
||||
// which includes all combinations of the cps tile drawing functions
|
||||
|
||||
int main()
|
||||
{
|
||||
int nCuMask=0;
|
||||
int nCuBpp=0;
|
||||
int nCuSize=0;
|
||||
int nCuRows=0;
|
||||
int nCuCare=0;
|
||||
int nCuFlipX=0;
|
||||
|
||||
for (nCuMask=0; nCuMask<=2; nCuMask++)
|
||||
{
|
||||
printf ("#define CU_MASK (%d)\n\n",nCuMask);
|
||||
for (nCuBpp=2; nCuBpp<=4; nCuBpp++)
|
||||
{
|
||||
printf ("#define CU_BPP (%d)\n\n",nCuBpp);
|
||||
for (nCuSize=8; nCuSize<=32; nCuSize<<=1)
|
||||
{
|
||||
printf ("#define CU_SIZE (%d)\n\n",nCuSize);
|
||||
for (nCuRows=0; nCuRows<2; nCuRows++)
|
||||
{
|
||||
printf ("#define CU_ROWS (%d)\n\n",nCuRows);
|
||||
for (nCuCare=0; nCuCare<2; nCuCare++)
|
||||
{
|
||||
printf ("#define CU_CARE (%d)\n",nCuCare);
|
||||
for (nCuFlipX=0; nCuFlipX<2; nCuFlipX++)
|
||||
{
|
||||
printf ("#define CU_FLIPX (%d)\n",nCuFlipX);
|
||||
|
||||
if ((nCuRows && (nCuSize != 16) || (nCuRows && nCuMask))) {
|
||||
printf("// Invalid combination of capabilities.\n");
|
||||
} else {
|
||||
printf ("static INT32 ");
|
||||
printf ("CtvDo");
|
||||
printf ("%d",nCuBpp);
|
||||
printf ("%.2d",nCuSize);
|
||||
if (nCuRows) printf ("r"); else printf ("_");
|
||||
if (nCuCare) printf ("c"); else printf ("_");
|
||||
if (nCuFlipX) printf ("f"); else printf ("_");
|
||||
if (nCuMask==1) printf ("m()\n#include \"ctv_do.h\"\n");
|
||||
else if (nCuMask==2) printf ("b()\n#include \"ctv_do.h\"\n");
|
||||
else printf ("_()\n#include \"ctv_do.h\"\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
printf ("#undef CU_FLIPX\n");
|
||||
}
|
||||
printf ("#undef CU_CARE\n\n");
|
||||
}
|
||||
printf ("#undef CU_ROWS\n\n");
|
||||
}
|
||||
printf ("#undef CU_SIZE\n\n");
|
||||
}
|
||||
printf ("#undef CU_BPP\n\n");
|
||||
}
|
||||
printf ("#undef CU_MASK\n\n");
|
||||
}
|
||||
|
||||
printf ("\n\n");
|
||||
|
||||
printf ("// Filler function\n");
|
||||
printf ("static INT32 CtvDo_______() { return 0; }\n\n\n\n");
|
||||
|
||||
for (nCuMask=0; nCuMask<=2; nCuMask++)
|
||||
{
|
||||
for (nCuBpp=2; nCuBpp<=4; nCuBpp++)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
if (nCuMask==1)
|
||||
{
|
||||
printf ("// Lookup table for %d bpp with Sprite Masking\n",nCuBpp);
|
||||
printf ("static CtvDoFn CtvDo%dm[0x20]={\n",nCuBpp);
|
||||
}
|
||||
else if (nCuMask==2)
|
||||
{
|
||||
printf ("// Lookup table for %d bpp with BgHi\n",nCuBpp);
|
||||
printf ("static CtvDoFn CtvDo%db[0x20]={\n",nCuBpp);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("// Lookup table for %d bpp\n",nCuBpp);
|
||||
printf ("static CtvDoFn CtvDo%d[0x20]={\n",nCuBpp);
|
||||
}
|
||||
|
||||
for (i=0;i<0x20;i++)
|
||||
{
|
||||
int s;
|
||||
printf ("CtvDo");
|
||||
|
||||
s=(i&24)+8;
|
||||
if (s!=8 && s!=16 && s!=32) { printf ("_______"); goto End; }
|
||||
if ((i&4) && (s!=16)) { printf ("_______"); goto End; }
|
||||
if ((i&4) && nCuMask) { printf ("_______"); goto End; }
|
||||
printf ("%d",nCuBpp);
|
||||
printf ("%.2d",s);
|
||||
if (i&4) printf ("r"); else printf ("_");
|
||||
if (i&2) printf ("c"); else printf ("_");
|
||||
if (i&1) printf ("f"); else printf ("_");
|
||||
if (nCuMask==1) printf ("m");
|
||||
else if (nCuMask==2) printf ("b");
|
||||
else printf ("_");
|
||||
|
||||
End:
|
||||
printf (",");
|
||||
if (((i+1)&3)==0) printf("\n");
|
||||
}
|
||||
printf ("};\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf ("\n\n");
|
||||
printf ("// Current BPP:\n");
|
||||
printf ("CtvDoFn CtvDoX[0x20];\n");
|
||||
printf ("CtvDoFn CtvDoXM[0x20];\n");
|
||||
printf ("CtvDoFn CtvDoXB[0x20];\n");
|
||||
printf ("\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,167 @@
|
|||
// This file is based on the MAME source code (see http://www.mame.net/)
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
"Kabuki" Z80 encryption
|
||||
|
||||
|
||||
The "Kabuki" is a custom Z80 module which runs encrypted code. The encryption
|
||||
key is stored in some battery-backed RAM, therefore the chip has the annoying
|
||||
habit of stopping working every few years, when the battery dies.
|
||||
Check at the bottom of this text to see a list of all the known games which
|
||||
use this chip.
|
||||
|
||||
|
||||
How it works:
|
||||
The base operation is a bit swap which affects couples of adjacent bits.
|
||||
Each of the 4 couples may or may not be swapped, depending on the address of
|
||||
the byte and on whether it is an opcode or data.
|
||||
The decryption consists of these steps:
|
||||
- bitswap
|
||||
- ROL
|
||||
- bitswap
|
||||
- XOR with a key
|
||||
- ROL
|
||||
- bitswap
|
||||
- ROL
|
||||
- bitswap
|
||||
|
||||
To know how to apply the bit swap, take the address of the byte to decode and:
|
||||
- if the byte is an opcode, add addr_key to the address
|
||||
- if the byte is data, XOR the address with 1FC0, add 1, and then add addr_key
|
||||
You'll get a 16-bit word. The first two bitswaps depend on bits 0-7 of that
|
||||
word, while the second two on bits 8-15. When a bit in the word is 1, swap the
|
||||
two bits, oherwise don't. The exact couple of bits affected depends on the
|
||||
game and is identified in this file with two keys: swap_key1 and swap_key2
|
||||
(which are just permutations of the numbers 0-7, not full 32-bit integers).
|
||||
|
||||
|
||||
Key space size:
|
||||
- swap_key1 8! = 40320
|
||||
- swap_key2 8! = 40320
|
||||
- addr_key 2^16 = 65536
|
||||
- xor_key 2^8 = 256
|
||||
- total 2.7274 * 10^16
|
||||
|
||||
|
||||
Weaknesses:
|
||||
- 0x00 and 0xff, having all the bits set to the same value, are not affected
|
||||
by bit permutations after the XOR. Therefore, their encryption is the same
|
||||
regardless of the high 8 bits of the address, and of the value of
|
||||
swap_key2. If there is a long stream of 0x00 or 0xff in the original data,
|
||||
this can be used to find by brute force all the candidates for swap_key1,
|
||||
xor_key, and for the low 8 bits of addr_key. This is a serious weakness
|
||||
which dramatically reduces the security of the encryption.
|
||||
- A 0x00 is always encrypted as a byte with as many 1s as xor_key; a 0xff is
|
||||
always encrypted as a byte with as many 0s as xor_key has 1s. So you just
|
||||
need to know one 0x00 or 0xff in the unencrypted data to know how many 1s
|
||||
there are in xor_key.
|
||||
- Once you have restricted the range for swap_key1 and you know the number of
|
||||
1s in the xor_key, you can easily use known plaintext attacks and brute
|
||||
force to find the remaining keys. Long strings like THIS GAME IS FOR USE IN
|
||||
and ABCDEFGHIJKLMNOPQRSTUVWXYZ can be found by comparing the number of 1s
|
||||
in the clear and encrypted data, taking xor_key into account. When you have
|
||||
found where the string is, use brute force to reduce the key space.
|
||||
|
||||
|
||||
Known games:
|
||||
swap_key1 swap_key2 addr_key xor_key
|
||||
Mahjong Gakuen 2 Gakuen-chou no Fukushuu 76543210 01234567 aa55 a5
|
||||
Poker Ladies " " " " "" ""
|
||||
Dokaben " " " " "" ""
|
||||
Dokaben 2 unknown
|
||||
Pang / Buster Bros / Pomping World 01234567 76543210 6548 24
|
||||
Capcom Baseball " " " " "" ""
|
||||
Capcom World 04152637 40516273 5751 43
|
||||
Adventure Quiz 2 Hatena ? no Dai-Bouken 45670123 45670123 5751 43
|
||||
Super Pang 45670123 45670123 5852 43
|
||||
Super Buster Bros 45670123 45670123 2130 12
|
||||
Super Marukin-Ban 54321076 54321076 4854 4f
|
||||
Quiz Tonosama no Yabou 12345670 12345670 1111 11
|
||||
Ashita Tenki ni Naare unknown
|
||||
Quiz Sangokushi 23456701 23456701 1828 18
|
||||
Block Block 02461357 64207531 0002 01
|
||||
|
||||
Warriors of Fate 01234567 54163072 5151 51
|
||||
Cadillacs and Dinosaurs 76543210 24601357 4343 43
|
||||
Punisher 67452103 75316024 2222 22
|
||||
Slam Masters 54321076 65432107 3131 19
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
// #include "driver.h"
|
||||
#include "cps.h"
|
||||
|
||||
|
||||
static INT32 bitswap1(INT32 src,INT32 key,INT32 select)
|
||||
{
|
||||
if (select & (1 << ((key >> 0) & 7)))
|
||||
src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
|
||||
if (select & (1 << ((key >> 4) & 7)))
|
||||
src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
|
||||
if (select & (1 << ((key >> 8) & 7)))
|
||||
src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
|
||||
if (select & (1 << ((key >>12) & 7)))
|
||||
src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static INT32 bitswap2(INT32 src,INT32 key,INT32 select)
|
||||
{
|
||||
if (select & (1 << ((key >>12) & 7)))
|
||||
src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
|
||||
if (select & (1 << ((key >> 8) & 7)))
|
||||
src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
|
||||
if (select & (1 << ((key >> 4) & 7)))
|
||||
src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
|
||||
if (select & (1 << ((key >> 0) & 7)))
|
||||
src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static INT32 bytedecode(INT32 src,INT32 swap_key1,INT32 swap_key2,INT32 xor_key,INT32 select)
|
||||
{
|
||||
src = bitswap1(src,swap_key1 & 0xffff,select & 0xff);
|
||||
src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
|
||||
src = bitswap2(src,swap_key1 >> 16,select & 0xff);
|
||||
src ^= xor_key;
|
||||
src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
|
||||
src = bitswap2(src,swap_key2 & 0xffff,select >> 8);
|
||||
src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
|
||||
src = bitswap1(src,swap_key2 >> 16,select >> 8);
|
||||
return src;
|
||||
}
|
||||
|
||||
void kabuki_decode(UINT8 *src,UINT8 *dest_op,UINT8 *dest_data,
|
||||
INT32 base_addr,INT32 length,INT32 swap_key1,INT32 swap_key2,INT32 addr_key,INT32 xor_key)
|
||||
{
|
||||
INT32 A;
|
||||
INT32 select;
|
||||
|
||||
for (A = 0;A < length;A++)
|
||||
{
|
||||
/* decode opcodes */
|
||||
select = (A + base_addr) + addr_key;
|
||||
dest_op[A] = (UINT8)bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
|
||||
|
||||
/* decode data */
|
||||
select = ((A + base_addr) ^ 0x1fc0) + addr_key + 1;
|
||||
dest_data[A] = (UINT8)bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
|
||||
}
|
||||
}
|
||||
|
||||
static void cps1_decode(INT32 swap_key1,INT32 swap_key2,INT32 addr_key,INT32 xor_key)
|
||||
{
|
||||
UINT8 *rom = CpsZRom;
|
||||
INT32 diff = nCpsZRomLen / 2;
|
||||
|
||||
CpsZRom=rom+diff;
|
||||
kabuki_decode(rom,rom+diff,rom,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key);
|
||||
}
|
||||
|
||||
void wof_decode(void) { cps1_decode(0x01234567,0x54163072,0x5151,0x51); }
|
||||
void dino_decode(void) { cps1_decode(0x76543210,0x24601357,0x4343,0x43); }
|
||||
void punisher_decode(void) { cps1_decode(0x67452103,0x75316024,0x2222,0x22); }
|
||||
void slammast_decode(void) { cps1_decode(0x54321076,0x65432107,0x3131,0x19); }
|
|
@ -0,0 +1,86 @@
|
|||
// PSound (CPS1 sound)
|
||||
#include "cps.h"
|
||||
#include "driver.h"
|
||||
extern "C" {
|
||||
#include "ym2151.h"
|
||||
}
|
||||
|
||||
UINT8 PsndCode, PsndFade; // Sound code/fade sent to the z80 program
|
||||
|
||||
static INT32 nSyncPeriod;
|
||||
static INT32 nSyncNext;
|
||||
|
||||
static INT32 nCyclesDone;
|
||||
|
||||
static void drvYM2151IRQHandler(INT32 nStatus)
|
||||
{
|
||||
if (nStatus) {
|
||||
ZetSetIRQLine(0xFF, ZET_IRQSTATUS_ACK);
|
||||
ZetRun(0x0800);
|
||||
} else {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
INT32 PsndInit()
|
||||
{
|
||||
nCpsZ80Cycles = 4000000 * 100 / nBurnFPS;
|
||||
nSyncPeriod = nCpsZ80Cycles / 32;
|
||||
|
||||
// Init PSound z80
|
||||
if (PsndZInit()!= 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Init PSound mixing (not critical if it fails)
|
||||
PsmInit();
|
||||
|
||||
YM2151SetIrqHandler(0, &drvYM2151IRQHandler);
|
||||
|
||||
PsndCode = 0; PsndFade = 0;
|
||||
|
||||
nCyclesDone = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 PsndExit()
|
||||
{
|
||||
PsmExit();
|
||||
PsndZExit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 PsndScan(INT32 nAction)
|
||||
{
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
SCAN_VAR(nCyclesDone); SCAN_VAR(nSyncNext);
|
||||
PsndZScan(nAction); // Scan Z80
|
||||
SCAN_VAR(PsndCode); SCAN_VAR(PsndFade); // Scan sound info
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PsndNewFrame()
|
||||
{
|
||||
ZetNewFrame();
|
||||
PsmNewFrame();
|
||||
nSyncNext = nSyncPeriod;
|
||||
|
||||
ZetIdle(nCyclesDone % nCpsZ80Cycles);
|
||||
nCyclesDone = 0;
|
||||
}
|
||||
|
||||
INT32 PsndSyncZ80(INT32 nCycles)
|
||||
{
|
||||
while (nSyncNext < nCycles) {
|
||||
PsmUpdate(nSyncNext * nBurnSoundLen / nCpsZ80Cycles);
|
||||
ZetRun(nSyncNext - ZetTotalCycles());
|
||||
nSyncNext += nSyncPeriod;
|
||||
}
|
||||
|
||||
nCyclesDone = ZetRun(nCycles - ZetTotalCycles());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
#include "cps.h"
|
||||
#include "burn_ym2151.h"
|
||||
|
||||
// CPS1 sound Mixing
|
||||
|
||||
INT32 bPsmOkay = 0; // 1 if the module is okay
|
||||
static INT16* WaveBuf = NULL;
|
||||
|
||||
static INT32 nPos;
|
||||
|
||||
INT32 PsmInit()
|
||||
{
|
||||
INT32 nMemLen, nRate, nRet;
|
||||
bPsmOkay = 0; // not OK yet
|
||||
|
||||
if (nBurnSoundRate > 0) {
|
||||
nRate = nBurnSoundRate;
|
||||
} else {
|
||||
nRate = 11025;
|
||||
}
|
||||
|
||||
if (BurnYM2151Init(3579540, 50.0)) { // Init FM sound chip
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Allocate a buffer for the intermediate sound (between YM2151 and pBurnSoundOut)
|
||||
nMemLen = nBurnSoundLen * 2 * sizeof(INT16);
|
||||
WaveBuf = (INT16*)malloc(nMemLen);
|
||||
if (WaveBuf == NULL) {
|
||||
PsmExit();
|
||||
return 1;
|
||||
}
|
||||
memset(WaveBuf, 0, nMemLen); // Init to silence
|
||||
|
||||
// Init ADPCM
|
||||
MSM6295ROM = CpsAd;
|
||||
if (Forgottn) {
|
||||
nRet = MSM6295Init(0, 6061, 21.5, 1);
|
||||
} else {
|
||||
nRet = MSM6295Init(0, 7576, 21.5, 1);
|
||||
}
|
||||
|
||||
if (nRet!=0) {
|
||||
PsmExit(); return 1;
|
||||
}
|
||||
|
||||
bPsmOkay = 1; // OK
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 PsmExit()
|
||||
{
|
||||
bPsmOkay = 0;
|
||||
|
||||
MSM6295Exit(0);
|
||||
|
||||
if (WaveBuf) {
|
||||
free(WaveBuf);
|
||||
WaveBuf = NULL;
|
||||
}
|
||||
|
||||
BurnYM2151Exit(); // Exit FM sound chip
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PsmNewFrame()
|
||||
{
|
||||
nPos = 0;
|
||||
}
|
||||
|
||||
INT32 PsmUpdate(INT32 nEnd)
|
||||
{
|
||||
if (bPsmOkay == 0 || pBurnSoundOut == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nEnd <= nPos) {
|
||||
return 0;
|
||||
}
|
||||
if (nEnd > nBurnSoundLen) {
|
||||
nEnd = nBurnSoundLen;
|
||||
}
|
||||
|
||||
// Render FM
|
||||
BurnYM2151Render(pBurnSoundOut + (nPos << 1), nEnd - nPos);
|
||||
|
||||
// Render ADPCM
|
||||
MSM6295Render(0, pBurnSoundOut + (nPos << 1), nEnd - nPos);
|
||||
|
||||
nPos = nEnd;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
#include "cps.h"
|
||||
#include "burn_ym2151.h"
|
||||
|
||||
// PSound - Z80
|
||||
static INT32 nPsndZBank = 0;
|
||||
static UINT8 *PsndZRam = NULL;
|
||||
|
||||
INT32 Kodb = 0;
|
||||
|
||||
// Map in the memory for the current 0x8000-0xc000 bank
|
||||
static INT32 PsndZBankMap()
|
||||
{
|
||||
UINT8 *Bank;
|
||||
UINT32 nOff = (nPsndZBank << 14) + 0x8000;
|
||||
|
||||
if (nOff + 0x4000 > nCpsZRomLen) { // End of bank in out of range
|
||||
nOff = 0;
|
||||
}
|
||||
|
||||
Bank = CpsZRom + nOff;
|
||||
|
||||
// Read and fetch the bank
|
||||
ZetMapArea(0x8000, 0xBFFF, 0, Bank);
|
||||
ZetMapArea(0x8000, 0xBFFF, 2, Bank);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// PSound Z80 memory write
|
||||
void __fastcall PsndZWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
switch (a) {
|
||||
case 0xF000:
|
||||
BurnYM2151SelectRegister(d);
|
||||
// bprintf(PRINT_NORMAL, "YM2151 select -> %02X\n", d);
|
||||
break;
|
||||
case 0xF001:
|
||||
BurnYM2151WriteRegister(d);
|
||||
// bprintf(PRINT_NORMAL, "YM2151 write -> %02X\n", d);
|
||||
break;
|
||||
case 0xF002:
|
||||
MSM6295Command(0, d);
|
||||
break;
|
||||
case 0xF004: {
|
||||
INT32 nNewBank = d & 0x0f;
|
||||
if (nPsndZBank != nNewBank) {
|
||||
nPsndZBank = nNewBank;
|
||||
PsndZBankMap();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0xF006: // ??? Enable interrupt ???
|
||||
break;
|
||||
|
||||
#ifdef FBA_DEBUG
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, _T("Z80 address %04X -> %02X.\n"), a, d);
|
||||
#endif
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void __fastcall kodbZWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
switch (a) {
|
||||
case 0xE000:
|
||||
BurnYM2151SelectRegister(d);
|
||||
break;
|
||||
case 0xE001:
|
||||
BurnYM2151WriteRegister(d);
|
||||
break;
|
||||
case 0xE400:
|
||||
MSM6295Command(0, d);
|
||||
break;
|
||||
|
||||
#ifdef FBA_DEBUG
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, _T("Z80 address %04X -> %02X.\n"), a, d);
|
||||
#endif
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// PSound Z80 memory read
|
||||
UINT8 __fastcall PsndZRead(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
case 0xF001:
|
||||
return BurnYM2151ReadStatus();
|
||||
case 0xF002:
|
||||
return MSM6295ReadStatus(0);
|
||||
case 0xF008:
|
||||
// bprintf(PRINT_NORMAL, " -- Sound latch read (%i).\n", PsndCode);
|
||||
return PsndCode;
|
||||
case 0xF00A:
|
||||
return PsndFade;
|
||||
|
||||
#ifdef FBA_DEBUG
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, _T("Z80 address %04X read.\n"), a);
|
||||
#endif
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT8 __fastcall kodbZRead(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
case 0xE001:
|
||||
return BurnYM2151ReadStatus();
|
||||
case 0xE400:
|
||||
return MSM6295ReadStatus(0);
|
||||
case 0xE800:
|
||||
return PsndCode;
|
||||
|
||||
#ifdef FBA_DEBUG
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, _T("Z80 address %04X read.\n"), a);
|
||||
#endif
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 PsndZInit()
|
||||
{
|
||||
if (nCpsZRomLen < 0x8000) { // Not enough Z80 Data
|
||||
return 1;
|
||||
}
|
||||
if (CpsZRom == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
PsndZRam = (UINT8 *)malloc(0x800);
|
||||
if (PsndZRam == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ZetInit(1);
|
||||
|
||||
if (Kodb) {
|
||||
ZetSetReadHandler(kodbZRead);
|
||||
ZetSetWriteHandler(kodbZWrite);
|
||||
} else {
|
||||
ZetSetReadHandler(PsndZRead);
|
||||
ZetSetWriteHandler(PsndZWrite);
|
||||
}
|
||||
|
||||
// Read and fetch first 0x8000 of Rom
|
||||
ZetMapArea(0x0000,0x7fff,0,CpsZRom);
|
||||
ZetMapArea(0x0000,0x7fff,2,CpsZRom);
|
||||
|
||||
// Map first Bank of Rom to 0x8000-0xc000
|
||||
nPsndZBank=0;
|
||||
PsndZBankMap();
|
||||
|
||||
// Ram
|
||||
ZetMapArea(0xd000,0xd7ff,0,PsndZRam);
|
||||
ZetMapArea(0xd000,0xd7ff,1,PsndZRam);
|
||||
ZetMapArea(0xd000,0xd7ff,2,PsndZRam);
|
||||
|
||||
// Sound chip interfaces
|
||||
ZetMemCallback(0xf000,0xffff,0);
|
||||
ZetMemCallback(0xf000,0xffff,1);
|
||||
|
||||
// In case it tries to fetch other areas
|
||||
ZetMapArea(0xc000,0xcfff,2,CpsZRom);
|
||||
ZetMapArea(0xd800,0xffff,2,CpsZRom);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 PsndZExit()
|
||||
{
|
||||
if (PsndZRam) {
|
||||
free(PsndZRam);
|
||||
PsndZRam = NULL;
|
||||
}
|
||||
|
||||
ZetExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan the current PSound z80 state
|
||||
INT32 PsndZScan(INT32 nAction)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
ZetScan(nAction);
|
||||
|
||||
MSM6295Scan(0, nAction);
|
||||
BurnYM2151Scan(nAction);
|
||||
|
||||
SCAN_VAR(nPsndZBank);
|
||||
|
||||
// Scan Ram
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.szName = "Z80 RAM";
|
||||
ba.Data = PsndZRam;
|
||||
ba.nLen = 0x800;
|
||||
BurnAcb(&ba);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
#include "cps.h"
|
||||
// QSound
|
||||
|
||||
static INT32 nQsndCyclesExtra;
|
||||
|
||||
static INT32 qsndTimerOver(INT32, INT32)
|
||||
{
|
||||
// bprintf(PRINT_NORMAL, _T(" - IRQ -> 1.\n"));
|
||||
ZetSetIRQLine(0xFF, ZET_IRQSTATUS_AUTO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 QsndInit()
|
||||
{
|
||||
INT32 nVolumeShift;
|
||||
INT32 nRate;
|
||||
|
||||
// Init QSound z80
|
||||
if (QsndZInit()) {
|
||||
return 1;
|
||||
}
|
||||
BurnTimerInit(qsndTimerOver, NULL);
|
||||
|
||||
if (Cps1Qs == 1) {
|
||||
nCpsZ80Cycles = 6000000 * 100 / nBurnFPS;
|
||||
BurnTimerAttachZet(6000000);
|
||||
} else {
|
||||
nCpsZ80Cycles = 8000000 * 100 / nBurnFPS;
|
||||
BurnTimerAttachZet(8000000);
|
||||
}
|
||||
|
||||
if (nBurnSoundRate >= 0) {
|
||||
nRate = nBurnSoundRate;
|
||||
} else {
|
||||
nRate = 11025;
|
||||
}
|
||||
|
||||
nVolumeShift = 0;
|
||||
|
||||
// These games are too soft at normal volumes
|
||||
if (strncmp(BurnDrvGetTextA(DRV_NAME), "csclub", 6) == 0) {
|
||||
nVolumeShift = -1;
|
||||
}
|
||||
#if 0
|
||||
// These games are loud at normal volumes (no clipping)
|
||||
if (strncmp(BurnDrvGetTextA(DRV_NAME), "1944", 4) == 0 ||
|
||||
strcmp( BurnDrvGetTextA(DRV_NAME), "dimahoo" ) == 0 ||
|
||||
strcmp( BurnDrvGetTextA(DRV_NAME), "gmahoo" ) == 0)
|
||||
{
|
||||
nVolumeShift = 1;
|
||||
}
|
||||
#endif
|
||||
// These games are too loud at normal volumes (no clipping)
|
||||
if (strncmp(BurnDrvGetTextA(DRV_NAME), "sgemf", 5) == 0 ||
|
||||
strncmp(BurnDrvGetTextA(DRV_NAME), "pfght", 5) == 0 ||
|
||||
strncmp(BurnDrvGetTextA(DRV_NAME), "mpang", 5) == 0 ||
|
||||
strncmp(BurnDrvGetTextA(DRV_NAME), "spf2", 4) == 0 ||
|
||||
strncmp(BurnDrvGetTextA(DRV_NAME), "sfa2", 4) == 0 ||
|
||||
strncmp(BurnDrvGetTextA(DRV_NAME), "sfa2", 4) == 0)
|
||||
{
|
||||
nVolumeShift = 1;
|
||||
}
|
||||
// These games are too loud at normal volumes (clipping)
|
||||
if (strncmp(BurnDrvGetTextA(DRV_NAME), "19xx", 4) == 0 ||
|
||||
strncmp(BurnDrvGetTextA(DRV_NAME), "ddtod", 5) == 0)
|
||||
{
|
||||
nVolumeShift = 2;
|
||||
}
|
||||
|
||||
QscInit(nRate, nVolumeShift); // Init QSound chip
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QsndReset()
|
||||
{
|
||||
BurnTimerReset();
|
||||
BurnTimerSetRetrig(0, 1.0 / 252.0);
|
||||
|
||||
nQsndCyclesExtra = 0;
|
||||
}
|
||||
|
||||
void QsndExit()
|
||||
{
|
||||
QscExit(); // Exit QSound chip
|
||||
QsndZExit();
|
||||
}
|
||||
|
||||
INT32 QsndScan(INT32 nAction)
|
||||
{
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
QsndZScan(nAction); // Scan Z80
|
||||
QscScan(nAction); // Scan QSound Chip
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QsndNewFrame()
|
||||
{
|
||||
ZetNewFrame();
|
||||
|
||||
ZetOpen(0);
|
||||
ZetIdle(nQsndCyclesExtra);
|
||||
|
||||
QscNewFrame();
|
||||
}
|
||||
|
||||
void QsndEndFrame()
|
||||
{
|
||||
BurnTimerEndFrame(nCpsZ80Cycles);
|
||||
if (pBurnSoundOut) QscUpdate(nBurnSoundLen);
|
||||
|
||||
nQsndCyclesExtra = ZetTotalCycles() - nCpsZ80Cycles;
|
||||
ZetClose();
|
||||
}
|
||||
|
||||
void QsndSyncZ80()
|
||||
{
|
||||
int nCycles = (INT64)SekTotalCycles() * nCpsZ80Cycles / nCpsCycles;
|
||||
|
||||
if (nCycles <= ZetTotalCycles()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BurnTimerUpdate(nCycles);
|
||||
}
|
|
@ -0,0 +1,454 @@
|
|||
// QSound - emulator for the QSound Chip
|
||||
|
||||
#include <math.h>
|
||||
#include "cps.h"
|
||||
#include "burn_sound.h"
|
||||
|
||||
static const INT32 nQscClock = 4000000;
|
||||
static const INT32 nQscClockDivider = 166;
|
||||
|
||||
static INT32 nQscRate = 0;
|
||||
static INT32 nQscVolumeShift;
|
||||
|
||||
static INT32 Tams = -1;
|
||||
static INT32* Qs_s = NULL;
|
||||
|
||||
static INT32 nPos;
|
||||
|
||||
struct QChan {
|
||||
UINT8 bKey; // 1 if channel is playing
|
||||
INT8 nBank; // Bank we are currently playing a sample from
|
||||
|
||||
INT8* PlayBank; // Pointer to current bank
|
||||
|
||||
INT32 nPlayStart; // Start of being played
|
||||
INT32 nStart; // Start of sample 16.12
|
||||
INT32 nEnd; // End of sample 16.12
|
||||
INT32 nLoop; // Loop offset from end
|
||||
INT32 nPos; // Current position within the bank 16.12
|
||||
INT32 nAdvance; // Sample size
|
||||
|
||||
INT32 nMasterVolume; // Master volume for the channel
|
||||
INT32 nVolume[2]; // Left & right side volumes (panning)
|
||||
|
||||
INT32 nPitch; // Playback frequency
|
||||
|
||||
INT8 nEndBuffer[8]; // Buffer to enable correct cubic interpolation
|
||||
};
|
||||
|
||||
static struct QChan QChan[16];
|
||||
|
||||
static INT32 PanningVolumes[33];
|
||||
|
||||
static void MapBank(struct QChan* pc)
|
||||
{
|
||||
UINT32 nBank;
|
||||
|
||||
nBank = (pc->nBank & 0x7F) << 16; // Banks are 0x10000 samples long
|
||||
|
||||
// Confirm whole bank is in range:
|
||||
// If bank is out of range use bank 0 instead
|
||||
if ((nBank + 0x10000) > nCpsQSamLen) {
|
||||
nBank = 0;
|
||||
}
|
||||
pc->PlayBank = (INT8*)CpsQSam + nBank;
|
||||
}
|
||||
|
||||
static void UpdateEndBuffer(struct QChan* pc)
|
||||
{
|
||||
if (pc->bKey) {
|
||||
// prepare a buffer to correctly interpolate the last 4 samples
|
||||
if (nInterpolation >= 3) {
|
||||
for (INT32 i = 0; i < 4; i++) {
|
||||
pc->nEndBuffer[i] = pc->PlayBank[(pc->nEnd >> 12) - 4 + i];
|
||||
}
|
||||
|
||||
if (pc->nLoop) {
|
||||
for (INT32 i = 0, j = 0; i < 4; i++, j++) {
|
||||
if (j >= (pc->nLoop >> 12)) {
|
||||
j = 0;
|
||||
}
|
||||
pc->nEndBuffer[i + 4] = pc->PlayBank[((pc->nEnd - pc->nLoop) >> 12) + j];
|
||||
}
|
||||
} else {
|
||||
for (INT32 i = 0; i < 4; i++) {
|
||||
pc->nEndBuffer[i + 4] = pc->nEndBuffer[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcAdvance(struct QChan* pc)
|
||||
{
|
||||
if (nQscRate) {
|
||||
pc->nAdvance = (INT64)pc->nPitch * nQscClock / nQscClockDivider / nQscRate;
|
||||
}
|
||||
}
|
||||
|
||||
void QscReset()
|
||||
{
|
||||
memset(QChan, 0, sizeof(QChan));
|
||||
|
||||
// Point all to bank 0
|
||||
for (INT32 i = 0; i < 16; i++) {
|
||||
QChan[i].PlayBank = (INT8*)CpsQSam;
|
||||
}
|
||||
}
|
||||
|
||||
void QscExit()
|
||||
{
|
||||
nQscRate = 0;
|
||||
|
||||
if (Qs_s) {
|
||||
free(Qs_s);
|
||||
Qs_s = NULL;
|
||||
}
|
||||
Tams = -1;
|
||||
}
|
||||
|
||||
INT32 QscInit(INT32 nRate, INT32 nVolumeShift)
|
||||
{
|
||||
nQscRate = nRate;
|
||||
|
||||
nQscVolumeShift = 10 + nVolumeShift;
|
||||
|
||||
for (INT32 i = 0; i < 33; i++) {
|
||||
PanningVolumes[i] = (INT32)((256.0 / sqrt(32.0)) * sqrt((double)i));
|
||||
}
|
||||
|
||||
QscReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 QscScan(INT32 nAction)
|
||||
{
|
||||
SCAN_VAR(QChan);
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
// Update bank pointers with new banks, and recalc nAdvance
|
||||
for (INT32 i = 0; i < 16; i++) {
|
||||
MapBank(QChan + i);
|
||||
CalcAdvance(QChan + i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QscNewFrame()
|
||||
{
|
||||
nPos = 0;
|
||||
}
|
||||
|
||||
static inline void QscSyncQsnd()
|
||||
{
|
||||
if (pBurnSoundOut) QscUpdate(ZetTotalCycles() * nBurnSoundLen / nCpsZ80Cycles);
|
||||
}
|
||||
|
||||
void QscWrite(INT32 a, INT32 d)
|
||||
{
|
||||
struct QChan* pc;
|
||||
INT32 nChanNum, r;
|
||||
|
||||
// unknown
|
||||
if (a >= 0x90) {
|
||||
// bprintf(PRINT_NORMAL, "QSound: reg 0x%02X -> 0x%02X.\n", a, d);
|
||||
return;
|
||||
}
|
||||
|
||||
QscSyncQsnd();
|
||||
|
||||
if (a >= 0x80) { // Set panning for channel
|
||||
INT32 nPan;
|
||||
|
||||
nChanNum = a & 15;
|
||||
|
||||
pc = QChan + nChanNum; // Find channel
|
||||
nPan = (d - 0x10) & 0x3F; // nPan = 0x00 to 0x20 now
|
||||
if (nPan > 0x20) {
|
||||
nPan = 0x20;
|
||||
}
|
||||
|
||||
// bprintf(PRINT_NORMAL, "QSound: ch#%i pan -> 0x%04X\n", nChanNum, d);
|
||||
|
||||
pc->nVolume[0] = PanningVolumes[0x20 - nPan];
|
||||
pc->nVolume[1] = PanningVolumes[0x00 + nPan];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get channel and register number
|
||||
nChanNum = (a >> 3) & 15;
|
||||
r = a & 7;
|
||||
|
||||
// Pointer to channel info
|
||||
pc = QChan + nChanNum;
|
||||
|
||||
switch (r) {
|
||||
case 0: { // Set bank
|
||||
// Strange but true
|
||||
pc = QChan + ((nChanNum + 1) & 15);
|
||||
pc->nBank = d;
|
||||
MapBank(pc);
|
||||
UpdateEndBuffer(pc);
|
||||
break;
|
||||
}
|
||||
case 1: { // Set sample start offset
|
||||
pc->nStart = d << 12;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
pc->nPitch = d;
|
||||
CalcAdvance(pc);
|
||||
|
||||
if (d == 0) { // Key off; stop playing
|
||||
pc->bKey = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case 3: {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case 4: { // Set sample loop offset
|
||||
pc->nLoop = d << 12;
|
||||
UpdateEndBuffer(pc);
|
||||
break;
|
||||
}
|
||||
case 5: { // Set sample end offset
|
||||
pc->nEnd = d << 12;
|
||||
UpdateEndBuffer(pc);
|
||||
break;
|
||||
}
|
||||
case 6: { // Set volume
|
||||
pc->nMasterVolume = d;
|
||||
|
||||
if (d == 0) {
|
||||
pc->bKey = 0;
|
||||
} else {
|
||||
if (pc->bKey == 0) { // Key on; play sample
|
||||
pc->nPlayStart = pc->nStart;
|
||||
|
||||
pc->nPos = 0;
|
||||
pc->bKey = 3;
|
||||
UpdateEndBuffer(pc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case 7: {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
INT32 QscUpdate(INT32 nEnd)
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
if (nEnd > nBurnSoundLen) {
|
||||
nEnd = nBurnSoundLen;
|
||||
}
|
||||
|
||||
nLen = nEnd - nPos;
|
||||
|
||||
if (nLen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Tams < nLen) {
|
||||
if (Qs_s) {
|
||||
free(Qs_s);
|
||||
Qs_s = NULL;
|
||||
}
|
||||
Tams = nLen;
|
||||
Qs_s = (INT32*)malloc(sizeof(INT32) * 2 * Tams);
|
||||
}
|
||||
|
||||
memset(Qs_s, 0, nLen * 2 * sizeof(INT32));
|
||||
|
||||
if (nInterpolation < 3) {
|
||||
|
||||
// Go through all channels
|
||||
for (INT32 c = 0; c < 16; c++) {
|
||||
|
||||
// If the channel is playing, add the samples to the buffer
|
||||
if (QChan[c].bKey) {
|
||||
INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> nQscVolumeShift;
|
||||
INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> nQscVolumeShift;
|
||||
INT32* pTemp = Qs_s;
|
||||
INT32 i = nLen;
|
||||
INT32 s, p;
|
||||
|
||||
if (QChan[c].bKey & 2) {
|
||||
QChan[c].bKey &= ~2;
|
||||
QChan[c].nPos = QChan[c].nPlayStart;
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
|
||||
p = (QChan[c].nPos >> 12) & 0xFFFF;
|
||||
|
||||
// Check for end of sample
|
||||
if (QChan[c].nPos >= (QChan[c].nEnd - 0x01000)) {
|
||||
if (QChan[c].nLoop) { // Loop sample
|
||||
if (QChan[c].nPos < QChan[c].nEnd) {
|
||||
QChan[c].nEndBuffer[0] = QChan[c].PlayBank[(QChan[c].nEnd - QChan[c].nLoop) >> 12];
|
||||
} else {
|
||||
QChan[c].nPos = QChan[c].nEnd - QChan[c].nLoop + (QChan[c].nPos & 0x0FFF);
|
||||
p = (QChan[c].nPos >> 12) & 0xFFFF;
|
||||
}
|
||||
} else {
|
||||
if (QChan[c].nPos < QChan[c].nEnd) {
|
||||
QChan[c].nEndBuffer[0] = QChan[c].PlayBank[p];
|
||||
} else {
|
||||
QChan[c].bKey = 0; // Quit playing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QChan[c].nEndBuffer[0] = QChan[c].PlayBank[p + 1];
|
||||
}
|
||||
|
||||
// Interpolate sample
|
||||
s = QChan[c].PlayBank[p] * (1 << 6) + ((QChan[c].nPos) & ((1 << 12) - 1)) * (QChan[c].nEndBuffer[0] - QChan[c].PlayBank[p]) / (1 << 6);
|
||||
|
||||
// Add to the sound currently in the buffer
|
||||
pTemp[0] += s * VolL;
|
||||
pTemp[1] += s * VolR;
|
||||
|
||||
pTemp += 2;
|
||||
|
||||
QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bBurnUseMMX) {
|
||||
#if defined BUILD_X86_ASM
|
||||
BurnSoundCopyClamp_A(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
|
||||
#endif
|
||||
} else {
|
||||
BurnSoundCopyClamp_C(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
|
||||
}
|
||||
nPos = nEnd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Go through all channels
|
||||
for (INT32 c = 0; c < 16; c++) {
|
||||
|
||||
// If the channel is playing, add the samples to the buffer
|
||||
if (QChan[c].bKey) {
|
||||
INT32 VolL = (QChan[c].nMasterVolume * QChan[c].nVolume[0]) >> nQscVolumeShift;
|
||||
INT32 VolR = (QChan[c].nMasterVolume * QChan[c].nVolume[1]) >> nQscVolumeShift;
|
||||
INT32* pTemp = Qs_s;
|
||||
INT32 i = nLen;
|
||||
|
||||
// handle 1st sample
|
||||
if (QChan[c].bKey & 2) {
|
||||
while (QChan[c].nPos < 0x1000 && i) {
|
||||
INT32 p = QChan[c].nPlayStart >> 12;
|
||||
INT32 s = INTERPOLATE4PS_CUSTOM(QChan[c].nPos,
|
||||
0,
|
||||
QChan[c].PlayBank[p + 0],
|
||||
QChan[c].PlayBank[p + 1],
|
||||
QChan[c].PlayBank[p + 2],
|
||||
256);
|
||||
|
||||
pTemp[0] += s * VolL;
|
||||
pTemp[1] += s * VolR;
|
||||
|
||||
QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch
|
||||
|
||||
pTemp += 2;
|
||||
i--;
|
||||
}
|
||||
if (i > 0) {
|
||||
QChan[c].bKey &= ~2;
|
||||
QChan[c].nPos = (QChan[c].nPos & 0x0FFF) + QChan[c].nPlayStart;
|
||||
}
|
||||
}
|
||||
|
||||
if (bBurnUseMMX && i > 0) {
|
||||
#if defined BUILD_X86_ASM
|
||||
QChan[c].bKey = (UINT8)ChannelMix_QS_A(pTemp, i,
|
||||
(char*)QChan[c].PlayBank,
|
||||
QChan[c].nEnd,
|
||||
&(QChan[c].nPos),
|
||||
VolL,
|
||||
VolR,
|
||||
QChan[c].nLoop,
|
||||
QChan[c].nAdvance,
|
||||
(char*)QChan[c].nEndBuffer);
|
||||
#endif
|
||||
} else {
|
||||
while (i > 0) {
|
||||
INT32 s, p;
|
||||
|
||||
// Check for end of sample
|
||||
if (QChan[c].nPos >= (QChan[c].nEnd - 0x3000)) {
|
||||
if (QChan[c].nPos < QChan[c].nEnd) {
|
||||
INT32 nIndex = 4 - ((QChan[c].nEnd - QChan[c].nPos) >> 12);
|
||||
s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1),
|
||||
QChan[c].nEndBuffer[nIndex + 0],
|
||||
QChan[c].nEndBuffer[nIndex + 1],
|
||||
QChan[c].nEndBuffer[nIndex + 2],
|
||||
QChan[c].nEndBuffer[nIndex + 3],
|
||||
256);
|
||||
} else {
|
||||
if (QChan[c].nLoop) { // Loop sample
|
||||
if (QChan[c].nLoop <= 0x1000) { // Don't play, but leave bKey on
|
||||
QChan[c].nPos = QChan[c].nEnd - 0x1000;
|
||||
break;
|
||||
}
|
||||
QChan[c].nPos -= QChan[c].nLoop;
|
||||
continue;
|
||||
} else {
|
||||
QChan[c].bKey = 0; // Stop playing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p = (QChan[c].nPos >> 12) & 0xFFFF;
|
||||
s = INTERPOLATE4PS_CUSTOM((QChan[c].nPos) & ((1 << 12) - 1),
|
||||
QChan[c].PlayBank[p + 0],
|
||||
QChan[c].PlayBank[p + 1],
|
||||
QChan[c].PlayBank[p + 2],
|
||||
QChan[c].PlayBank[p + 3],
|
||||
256);
|
||||
}
|
||||
|
||||
// Add to the sound currently in the buffer
|
||||
pTemp[0] += s * VolL;
|
||||
pTemp[1] += s * VolR;
|
||||
|
||||
pTemp += 2;
|
||||
|
||||
QChan[c].nPos += QChan[c].nAdvance; // increment sample position based on pitch
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bBurnUseMMX) {
|
||||
#if defined BUILD_X86_ASM
|
||||
BurnSoundCopyClamp_A(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
|
||||
#endif
|
||||
} else {
|
||||
BurnSoundCopyClamp_C(Qs_s, pBurnSoundOut + (nPos << 1), nLen);
|
||||
}
|
||||
nPos = nEnd;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
#include "cps.h"
|
||||
// QSound - Z80
|
||||
|
||||
static INT32 nQsndZBank = 0;
|
||||
|
||||
// Map in the memory for the current 0x8000-0xc000 music bank
|
||||
static INT32 QsndZBankMap()
|
||||
{
|
||||
UINT32 nOff;
|
||||
UINT8* Bank;
|
||||
nOff = nQsndZBank << 14;
|
||||
nOff += 0x8000;
|
||||
|
||||
if (Cps1Qs == 0) {
|
||||
if (nOff + 0x4000 > nCpsZRomLen) { // End of bank is out of range
|
||||
nOff = 0;
|
||||
}
|
||||
Bank = CpsZRom + nOff;
|
||||
} else {
|
||||
if (nOff + 0x4000 > (nCpsZRomLen / 2)) {
|
||||
nOff = 0;
|
||||
}
|
||||
Bank = CpsZRom - (nCpsZRomLen / 2) + nOff;
|
||||
}
|
||||
|
||||
// Read and fetch the bank
|
||||
ZetMapArea(0x8000, 0xbfff, 0, Bank);
|
||||
if (Cps1Qs == 0) {
|
||||
ZetMapArea(0x8000, 0xbfff, 2, Bank, CpsZRom + nOff);
|
||||
} else {
|
||||
ZetMapArea(0x8000, 0xbfff, 2, Bank);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT8 QscCmd[2] = {0, 0};
|
||||
|
||||
void __fastcall QsndZWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
if (a == 0xd000) {
|
||||
QscCmd[0] = d;
|
||||
return;
|
||||
}
|
||||
if (a == 0xd001) {
|
||||
QscCmd[1] = d;
|
||||
return;
|
||||
}
|
||||
if (a == 0xd002) {
|
||||
QscWrite(d, (QscCmd[0] << 8) | QscCmd[1]);
|
||||
// bprintf(PRINT_NORMAL, _T("QSound command %02X %04X sent.\n"), d, (QscCmd[0] << 8) | QscCmd[1]);
|
||||
return;
|
||||
}
|
||||
if (a == 0xd003) {
|
||||
INT32 nNewBank = d & 0x0f;
|
||||
if (nQsndZBank != nNewBank) {
|
||||
nQsndZBank = nNewBank;
|
||||
QsndZBankMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall QsndZRead(UINT16 a)
|
||||
{
|
||||
if (a == 0xd007) { // return ready all the time
|
||||
return 0x80;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 QsndZInit()
|
||||
{
|
||||
if (nCpsZRomLen < 0x8000) { // Not enough Z80 Data
|
||||
return 1;
|
||||
}
|
||||
if (CpsZRom == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ZetInit(1);
|
||||
|
||||
ZetSetReadHandler(QsndZRead);
|
||||
ZetSetWriteHandler(QsndZWrite);
|
||||
|
||||
// Read and fetch first 0x8000 of Rom
|
||||
if (Cps1Qs) {
|
||||
ZetMapArea(0x0000, 0x7FFF, 0, CpsZRom - (nCpsZRomLen / 2));
|
||||
ZetMapArea(0x0000, 0x7FFF, 2, CpsZRom, CpsZRom - (nCpsZRomLen / 2)); // If it tries to fetch this area
|
||||
} else {
|
||||
ZetMapArea(0x0000, 0x7FFF, 0 ,CpsZRom);
|
||||
ZetMapArea(0x0000, 0x7FFF, 2, CpsZRom);
|
||||
}
|
||||
|
||||
// Map first Bank of Rom
|
||||
nQsndZBank = 0;
|
||||
QsndZBankMap();
|
||||
|
||||
ZetMapArea(0xC000, 0xCFFF, 0, CpsZRamC0);
|
||||
ZetMapArea(0xC000, 0xCFFF, 1, CpsZRamC0);
|
||||
ZetMapArea(0xC000, 0xCFFF, 2, CpsZRamC0);
|
||||
|
||||
ZetMemCallback(0xD000, 0xEFFF, 0);
|
||||
ZetMemCallback(0xD000, 0xEFFF, 1);
|
||||
|
||||
if (Cps1Qs) {
|
||||
ZetMapArea(0xD000, 0xEFFF, 2, CpsZRom, CpsZRom - (nCpsZRomLen / 2)); // If it tries to fetch this area
|
||||
} else {
|
||||
ZetMapArea(0xD000, 0xEFFF, 2, CpsZRom);
|
||||
}
|
||||
|
||||
ZetMapArea(0xF000, 0xFFFF, 0, CpsZRamF0);
|
||||
ZetMapArea(0xF000, 0xFFFF, 1, CpsZRamF0);
|
||||
ZetMapArea(0xF000, 0xFFFF, 2, CpsZRamF0);
|
||||
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 QsndZExit()
|
||||
{
|
||||
ZetExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan the current QSound z80 state
|
||||
INT32 QsndZScan(INT32 nAction)
|
||||
{
|
||||
ZetScan(nAction); // Scan Z80
|
||||
SCAN_VAR(nQsndZBank);
|
||||
|
||||
if (nAction & ACB_WRITE) { // If write, bank could have changed
|
||||
QsndZBankMap();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#include "cave.h"
|
||||
|
||||
INT32 nCaveXSize = 0, nCaveYSize = 0;
|
||||
INT32 nCaveXOffset = 0, nCaveYOffset = 0;
|
||||
INT32 nCaveExtraXOffset = 0, nCaveExtraYOffset = 0;
|
||||
INT32 nCaveRowModeOffset = 0;
|
||||
|
||||
INT32 CaveScanGraphics()
|
||||
{
|
||||
SCAN_VAR(nCaveXOffset);
|
||||
SCAN_VAR(nCaveYOffset);
|
||||
|
||||
SCAN_VAR(nCaveTileBank);
|
||||
|
||||
SCAN_VAR(nCaveSpriteBank);
|
||||
SCAN_VAR(nCaveSpriteBankDelay);
|
||||
|
||||
for (INT32 i = 0; i < 4; i++) {
|
||||
SCAN_VAR(CaveTileReg[i][0]);
|
||||
SCAN_VAR(CaveTileReg[i][1]);
|
||||
SCAN_VAR(CaveTileReg[i][2]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function fills the screen with the background colour
|
||||
void CaveClearScreen(UINT32 nColour)
|
||||
{
|
||||
if (nColour) {
|
||||
UINT32* pClear = (UINT32*)pBurnDraw;
|
||||
nColour = nColour | (nColour << 16);
|
||||
for (INT32 i = nCaveXSize * nCaveYSize / 16; i > 0 ; i--) {
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
*pClear++ = nColour;
|
||||
}
|
||||
} else {
|
||||
memset(pBurnDraw, 0, nCaveXSize * nCaveYSize * sizeof(INT16));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include "burnint.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
#define CAVE_REFRESHRATE (15625.0 / 271.5)
|
||||
|
||||
inline static void CaveClearOpposites(UINT16* nJoystickInputs)
|
||||
{
|
||||
if ((*nJoystickInputs & 0x0003) == 0x0003) {
|
||||
*nJoystickInputs &= ~0x0003;
|
||||
}
|
||||
if ((*nJoystickInputs & 0x000C) == 0x000C) {
|
||||
*nJoystickInputs &= ~0x000C;
|
||||
}
|
||||
}
|
||||
|
||||
// cave.cpp
|
||||
extern INT32 nCaveXSize, nCaveYSize;
|
||||
extern INT32 nCaveXOffset, nCaveYOffset;
|
||||
extern INT32 nCaveExtraXOffset, nCaveExtraYOffset;
|
||||
extern INT32 nCaveRowModeOffset;
|
||||
|
||||
INT32 CaveScanGraphics();
|
||||
void CaveClearScreen(UINT32 nColour);
|
||||
|
||||
// cave_palette.cpp
|
||||
extern UINT32* CavePalette;
|
||||
|
||||
extern UINT8* CavePalSrc;
|
||||
extern UINT8 CaveRecalcPalette;
|
||||
|
||||
INT32 CavePalInit(INT32 nPalSize);
|
||||
INT32 CavePalExit();
|
||||
INT32 CavePalUpdate4Bit(INT32 nOffset, INT32 nNumPalettes);
|
||||
INT32 CavePalUpdate8Bit(INT32 nOffset, INT32 nNumPalettes);
|
||||
|
||||
void CavePalWriteByte(UINT32 nAddress, UINT8 byteValue);
|
||||
void CavePalWriteWord(UINT32 nAddress, UINT16 wordValue);
|
||||
|
||||
// cave_tiles.cpp
|
||||
extern UINT8* CaveTileROM[4];
|
||||
extern UINT8* CaveTileRAM[4];
|
||||
|
||||
extern UINT32 CaveTileReg[4][3];
|
||||
extern INT32 nCaveTileBank;
|
||||
|
||||
INT32 CaveTileRender(INT32 nMode);
|
||||
void CaveTileExit();
|
||||
INT32 CaveTileInit();
|
||||
INT32 CaveTileInitLayer(INT32 nLayer, INT32 nROMSize, INT32 nBitdepth, INT32 nOffset);
|
||||
|
||||
// cave_sprite.cpp
|
||||
extern INT32 CaveSpriteVisibleXOffset;
|
||||
|
||||
extern UINT8* CaveSpriteROM;
|
||||
extern UINT8* CaveSpriteRAM;
|
||||
|
||||
extern INT32 nCaveSpriteBank;
|
||||
extern INT32 nCaveSpriteBankDelay;
|
||||
|
||||
extern INT32 (*CaveSpriteBuffer)();
|
||||
extern INT32 CaveSpriteRender(INT32 nLowPriority, INT32 nHighPriority);
|
||||
void CaveSpriteExit();
|
||||
INT32 CaveSpriteInit(INT32 nType, INT32 nROMSize);
|
|
@ -0,0 +1,154 @@
|
|||
#include "cave.h"
|
||||
|
||||
UINT8* CavePalSrc;
|
||||
UINT8 CaveRecalcPalette; // Set to 1 to force recalculation of the entire palette
|
||||
|
||||
UINT32* CavePalette = NULL;
|
||||
static UINT16* CavePalCopy = NULL;
|
||||
|
||||
INT32 CavePalInit(INT32 nPalSize)
|
||||
{
|
||||
CavePalette = (UINT32*)malloc(nPalSize * sizeof(UINT32));
|
||||
memset(CavePalette, 0, nPalSize * sizeof(UINT32));
|
||||
|
||||
CavePalCopy = (UINT16*)malloc(nPalSize * sizeof(UINT16));
|
||||
memset(CavePalCopy, 0, nPalSize * sizeof(UINT16));
|
||||
|
||||
pBurnDrvPalette = CavePalette;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CavePalExit()
|
||||
{
|
||||
if (CavePalette) {
|
||||
free(CavePalette);
|
||||
CavePalette = NULL;
|
||||
}
|
||||
if (CavePalCopy) {
|
||||
free(CavePalCopy);
|
||||
CavePalCopy = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static UINT32 CalcCol(UINT16 nColour)
|
||||
{
|
||||
INT32 r, g, b;
|
||||
|
||||
r = (nColour & 0x03E0) >> 2; // Red
|
||||
r |= r >> 5;
|
||||
g = (nColour & 0x7C00) >> 7; // Green
|
||||
g |= g >> 5;
|
||||
b = (nColour & 0x001F) << 3; // Blue
|
||||
b |= b >> 5;
|
||||
|
||||
return BurnHighCol(r, g, b, 0);
|
||||
}
|
||||
|
||||
INT32 CavePalUpdate4Bit(INT32 nOffset, INT32 nNumPalettes)
|
||||
{
|
||||
INT32 i, j;
|
||||
|
||||
UINT16* ps = (UINT16*)CavePalSrc + nOffset;
|
||||
UINT16* pc;
|
||||
UINT32* pd;
|
||||
|
||||
UINT16 c;
|
||||
|
||||
if (CaveRecalcPalette) {
|
||||
|
||||
for (i = 0; i < 0 + nNumPalettes; i++) {
|
||||
|
||||
pc = CavePalCopy + (i << 8);
|
||||
pd = CavePalette + (i << 8);
|
||||
|
||||
for (j = 0; j < 16; j++, ps++, pc++, pd++) {
|
||||
|
||||
c = *ps;
|
||||
*pc = c;
|
||||
*pd = CalcCol(c);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CaveRecalcPalette = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 0 + nNumPalettes; i++) {
|
||||
|
||||
pc = CavePalCopy + (i << 8);
|
||||
pd = CavePalette + (i << 8);
|
||||
|
||||
for (j = 0; j < 16; j++, ps++, pc++, pd++) {
|
||||
|
||||
c = *ps;
|
||||
if (*pc != c) {
|
||||
*pc = c;
|
||||
*pd = CalcCol(c);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CavePalUpdate8Bit(INT32 nOffset, INT32 nNumPalettes)
|
||||
{
|
||||
if (CaveRecalcPalette) {
|
||||
INT32 i, j;
|
||||
|
||||
UINT16* ps = (UINT16*)CavePalSrc + nOffset;
|
||||
UINT16* pc;
|
||||
UINT32* pd;
|
||||
|
||||
UINT16 c;
|
||||
|
||||
for (i = 0; i < nNumPalettes; i++) {
|
||||
|
||||
pc = CavePalCopy + nOffset + (i << 8);
|
||||
pd = CavePalette + nOffset + (i << 8);
|
||||
|
||||
for (j = 0; j < 256; j++, ps++, pc++, pd++) {
|
||||
|
||||
c = *ps;
|
||||
*pc = c;
|
||||
*pd = CalcCol(c);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CaveRecalcPalette = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Update the PC copy of the palette on writes to the palette memory
|
||||
void CavePalWriteByte(UINT32 nAddress, UINT8 byteValue)
|
||||
{
|
||||
nAddress ^= 1;
|
||||
CavePalSrc[nAddress] = byteValue; // write byte
|
||||
|
||||
if (*((UINT8*)(CavePalCopy + nAddress)) != byteValue) {
|
||||
*((UINT8*)(CavePalCopy + nAddress)) = byteValue;
|
||||
CavePalette[nAddress >> 1] = CalcCol(*(UINT16*)(CavePalSrc + (nAddress & ~0x01)));
|
||||
}
|
||||
}
|
||||
|
||||
void CavePalWriteWord(UINT32 nAddress, UINT16 wordValue)
|
||||
{
|
||||
nAddress >>= 1;
|
||||
|
||||
((UINT16*)CavePalSrc)[nAddress] = wordValue; // write word
|
||||
|
||||
if (CavePalCopy[nAddress] != wordValue) {
|
||||
CavePalCopy[nAddress] = wordValue;
|
||||
CavePalette[nAddress] = CalcCol(wordValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,742 @@
|
|||
// Cave hardware sprites
|
||||
#include "cave.h"
|
||||
|
||||
INT32 CaveSpriteVisibleXOffset;
|
||||
|
||||
UINT8* CaveSpriteROM = NULL;
|
||||
UINT8* CaveSpriteRAM = NULL;
|
||||
|
||||
INT32 nCaveSpriteBank;
|
||||
INT32 nCaveSpriteBankDelay;
|
||||
|
||||
static INT32 nSpriteAddressMask;
|
||||
|
||||
struct CaveSprite {
|
||||
INT8 flip;
|
||||
INT8 priority;
|
||||
INT16 palette;
|
||||
INT32 x; INT32 y;
|
||||
INT32 xsize; INT32 ysize;
|
||||
INT32 xzoom; INT32 yzoom;
|
||||
INT32 address;
|
||||
};
|
||||
|
||||
static CaveSprite* pSpriteList = NULL;
|
||||
|
||||
INT32 (*CaveSpriteBuffer)();
|
||||
|
||||
static UINT8* pRow;
|
||||
static UINT8* pPixel;
|
||||
static UINT32* pSpriteData;
|
||||
static UINT32* pSpritePalette;
|
||||
|
||||
static UINT16* pZBuffer = NULL;
|
||||
static UINT16* pZRow;
|
||||
static UINT16* pZPixel;
|
||||
|
||||
static INT32 nSpriteRow, nSpriteRowSize;
|
||||
static INT32 nXPos, nYPos, nZPos;
|
||||
static INT32 nXSize, nYSize;
|
||||
static INT32 nSpriteXZoomSize, nSpriteYZoomSize;
|
||||
static INT32 nSpriteXOffset, nSpriteYOffset;
|
||||
|
||||
static INT32 nFirstSprite[4], nLastSprite[4];
|
||||
|
||||
static INT32 nTopSprite;
|
||||
static INT32 nZOffset;
|
||||
|
||||
typedef void (*RenderSpriteFunction)();
|
||||
static RenderSpriteFunction* RenderSprite;
|
||||
|
||||
// Include the sprite rendering functions
|
||||
#include "cave_sprite_func.h"
|
||||
|
||||
INT32 CaveSpriteRender(INT32 nLowPriority, INT32 nHighPriority)
|
||||
{
|
||||
static INT32 nMaskLeft, nMaskRight, nMaskTop, nMaskBottom;
|
||||
CaveSprite* pBuffer;
|
||||
|
||||
INT32 nPriorityMask = 0;
|
||||
INT32 nMaxZPos = -1;
|
||||
INT32 nCurrentZPos = 0x00010000;
|
||||
INT32 nUseBuffer = 0x00010000;
|
||||
INT32 nFunction;
|
||||
|
||||
if (nLowPriority == 0) {
|
||||
nZPos = -1;
|
||||
nTopSprite = -1;
|
||||
|
||||
nMaskLeft = nMaskTop = 9999;
|
||||
nMaskRight = nMaskBottom = -1;
|
||||
}
|
||||
|
||||
if ((nBurnLayer & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nHighPriority < 3) {
|
||||
for (INT32 i = nHighPriority + 1; i < 4; i++) {
|
||||
if (nUseBuffer > nFirstSprite[i]) {
|
||||
nUseBuffer = nFirstSprite[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (INT32 i = nLowPriority; i <= nHighPriority; i++) {
|
||||
if (nCurrentZPos > nFirstSprite[i]) {
|
||||
nCurrentZPos = nFirstSprite[i];
|
||||
}
|
||||
if (nMaxZPos < nLastSprite[i]) {
|
||||
nMaxZPos = nLastSprite[i];
|
||||
}
|
||||
nPriorityMask |= 8 >> i;
|
||||
}
|
||||
|
||||
nPriorityMask &= nSpriteEnable;
|
||||
if (nPriorityMask == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (pBuffer = pSpriteList + nCurrentZPos; nCurrentZPos <= nMaxZPos; pBuffer++, nCurrentZPos++) {
|
||||
|
||||
if ((pBuffer->priority & nPriorityMask) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nXPos = pBuffer->x;
|
||||
nYPos = pBuffer->y;
|
||||
|
||||
pSpriteData = (UINT32*)(CaveSpriteROM + ((pBuffer->address << 8) & nSpriteAddressMask));
|
||||
pSpritePalette = CavePalette + pBuffer->palette;
|
||||
|
||||
nXSize = pBuffer->xsize;
|
||||
nYSize = pBuffer->ysize;
|
||||
|
||||
if (pBuffer->xzoom == 0x0100 && pBuffer->yzoom == 0x0100) { // This sprite doesn't use zooming
|
||||
|
||||
nSpriteRowSize = pBuffer->xsize >> 2;
|
||||
|
||||
if (pBuffer->flip & 1) { // Y Flip
|
||||
pSpriteData += nSpriteRowSize * (nYSize - 1);
|
||||
nSpriteRowSize = -nSpriteRowSize;
|
||||
}
|
||||
|
||||
if (nYPos >= 0x0200) {
|
||||
nYPos -= 0x0400;
|
||||
}
|
||||
|
||||
if (nYPos < 0) {
|
||||
pSpriteData += nSpriteRowSize * -nYPos;
|
||||
nYSize += nYPos;
|
||||
nYPos = 0;
|
||||
}
|
||||
|
||||
if ((nYPos + nYSize) > nCaveYSize) {
|
||||
nYSize -= (nYPos + nYSize) - nCaveYSize;
|
||||
}
|
||||
|
||||
if (nXPos >= 0x0200) {
|
||||
nXPos -= 0x0400;
|
||||
}
|
||||
|
||||
if (nXPos < 0) {
|
||||
if ((pBuffer->flip & 2) == 0) {
|
||||
pSpriteData += (-nXPos >> 4) << 2;
|
||||
}
|
||||
nXSize -= -nXPos & 0xFFF0;
|
||||
nXPos += -nXPos & 0xFFF0;
|
||||
}
|
||||
|
||||
if (nXPos + nXSize >= nCaveXSize) {
|
||||
if (pBuffer->flip & 2) {
|
||||
pSpriteData += ((nXPos + nXSize - nCaveXSize) >> 4) << 2;
|
||||
}
|
||||
nXSize -= (nXPos + nXSize - nCaveXSize) & 0xFFF0;
|
||||
}
|
||||
|
||||
pRow = pBurnDraw + (nYPos * nBurnPitch) + (nXPos * nBurnBpp);
|
||||
|
||||
nFunction = (pBuffer->flip & 2) << 1; // X Flip
|
||||
|
||||
if (nTopSprite > nCurrentZPos) { // Test ZBuffer
|
||||
if (nXPos < nMaskRight && (nXPos + nXSize) >= nMaskLeft && nYPos < nMaskBottom && (nYPos + nYSize) >= nMaskTop) {
|
||||
nFunction |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nUseBuffer < nCurrentZPos) { // Write ZBuffer
|
||||
nFunction |= 2;
|
||||
|
||||
if (nXPos < nMaskLeft) {
|
||||
nMaskLeft = nXPos;
|
||||
}
|
||||
if ((nXPos + nXSize) > nMaskRight) {
|
||||
nMaskRight = nXPos + nXSize;
|
||||
}
|
||||
if (nYPos < nMaskTop) {
|
||||
nMaskTop = nYPos;
|
||||
}
|
||||
if ((nYPos + nYSize) > nMaskBottom) {
|
||||
nMaskBottom = nYPos + nYSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (nFunction & 3) {
|
||||
pZRow = pZBuffer + (nYPos * 320) + nXPos;
|
||||
nZPos = nCurrentZPos + nZOffset;
|
||||
}
|
||||
|
||||
nXSize = nXSize >> 2;
|
||||
|
||||
RenderSprite[nFunction]();
|
||||
} else { // This sprite uses zooming
|
||||
nSpriteXZoomSize = 0x01000000; // * zoom factor = size of each screen pixel
|
||||
|
||||
nXSize *= pBuffer->xzoom;
|
||||
nXSize >>= 8; // Round to multiple of whole pixel
|
||||
if (nXSize < 1) { // Make sure the sprite is at least one pixel wide
|
||||
nXSize = 1;
|
||||
} else {
|
||||
nSpriteXZoomSize /= pBuffer->xzoom;
|
||||
}
|
||||
if (nSpriteXZoomSize > (pBuffer->xsize << 16)) {
|
||||
nSpriteXZoomSize = pBuffer->xsize << 16;
|
||||
}
|
||||
nSpriteXOffset = nSpriteXZoomSize >> 1; // Make certain the pixels displayed are centered
|
||||
|
||||
if (pBuffer->flip & 2) { // X Flip
|
||||
nXPos += pBuffer->xsize - nXSize;
|
||||
|
||||
nSpriteXOffset = (pBuffer->xsize << 16) - nSpriteXOffset;
|
||||
nSpriteXZoomSize = -nSpriteXZoomSize;
|
||||
}
|
||||
|
||||
if (nXPos >= 0x0200) {
|
||||
nXPos -= 0x0400;
|
||||
}
|
||||
|
||||
if (nXPos < 0) {
|
||||
if (nXPos + nXSize <= 0) {
|
||||
continue;
|
||||
}
|
||||
nXPos = -nXPos;
|
||||
nSpriteXOffset += nXPos * nSpriteXZoomSize;
|
||||
nXSize -= nXPos;
|
||||
nXPos = 0;
|
||||
}
|
||||
|
||||
if (nXPos + nXSize >= nCaveXSize) {
|
||||
if (nXPos >= nCaveXSize) {
|
||||
continue;
|
||||
}
|
||||
nXSize = nCaveXSize - nXPos;
|
||||
}
|
||||
|
||||
nSpriteRowSize = pBuffer->xsize; // Size of each sprite row in memory
|
||||
nSpriteYZoomSize = 0x01000000; // * zoom factor = size of each screen pixel
|
||||
|
||||
nYSize *= pBuffer->yzoom;
|
||||
nYSize >>= 8; // Round to multiple of whole pixel
|
||||
if (nYSize < 1) { // Make certain the sprite is at least one pixel high
|
||||
nYSize = 1;
|
||||
} else {
|
||||
nSpriteYZoomSize /= pBuffer->yzoom;
|
||||
}
|
||||
if (nSpriteYZoomSize > (pBuffer->ysize << 16)) {
|
||||
nSpriteYZoomSize = pBuffer->ysize << 16;
|
||||
}
|
||||
nSpriteYOffset = nSpriteYZoomSize >> 1; // Make certain the pixels displayed are centered
|
||||
|
||||
if (pBuffer->flip & 1) { // Y Flip
|
||||
nYPos += pBuffer->ysize - nYSize;
|
||||
|
||||
nSpriteYOffset = (pBuffer->ysize << 16) - nSpriteYOffset;
|
||||
nSpriteYZoomSize = -nSpriteYZoomSize;
|
||||
}
|
||||
|
||||
if (nYPos >= 0x0200) {
|
||||
nYPos -= 0x0400;
|
||||
}
|
||||
|
||||
if (nYPos < 0) {
|
||||
if (nYPos + nYSize <= 0) {
|
||||
continue;
|
||||
}
|
||||
nYPos = -nYPos;
|
||||
nSpriteYOffset += nYPos * nSpriteYZoomSize;
|
||||
nYSize -= nYPos;
|
||||
nYPos = 0;
|
||||
}
|
||||
|
||||
if (nYPos + nYSize >= nCaveYSize) {
|
||||
if (nYPos >= nCaveYSize) {
|
||||
continue;
|
||||
}
|
||||
nYSize = nCaveYSize - nYPos;
|
||||
}
|
||||
|
||||
pRow = pBurnDraw + (nYPos * nBurnPitch) + (nXPos * nBurnBpp);
|
||||
|
||||
nFunction = 8;
|
||||
|
||||
if (pBuffer->xzoom > 0x0100 || pBuffer->yzoom > 0x0100) {
|
||||
nFunction |= 4;
|
||||
}
|
||||
|
||||
if (nTopSprite > nCurrentZPos) { // Test ZBuffer
|
||||
if (nXPos < nMaskRight && nXPos + nXSize >= nMaskLeft && nYPos < nMaskBottom && nYPos + nYSize >= nMaskTop) {
|
||||
nFunction |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nUseBuffer < nCurrentZPos) { // Write ZBuffer
|
||||
nFunction |= 2;
|
||||
|
||||
if (nXPos < nMaskLeft) {
|
||||
nMaskLeft = nXPos;
|
||||
}
|
||||
if (nXPos + nXSize > nMaskRight) {
|
||||
nMaskRight = nXPos + nXSize;
|
||||
}
|
||||
if (nYPos < nMaskTop) {
|
||||
nMaskTop = nYPos;
|
||||
}
|
||||
if (nYPos + nYSize > nMaskBottom) {
|
||||
nMaskBottom = nYPos + nYSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (nFunction & 3) {
|
||||
pZRow = pZBuffer + (nYPos * nCaveXSize) + nXPos;
|
||||
nZPos = nCurrentZPos + nZOffset;
|
||||
}
|
||||
|
||||
nXSize <<= 16;
|
||||
nYSize <<= 16;
|
||||
|
||||
RenderSprite[nFunction]();
|
||||
}
|
||||
}
|
||||
|
||||
if (nMaxZPos > nTopSprite) {
|
||||
nTopSprite = nMaxZPos;
|
||||
}
|
||||
|
||||
if (nHighPriority == 3) {
|
||||
if (nZPos >= 0) {
|
||||
nZOffset += nTopSprite;
|
||||
if (nZOffset > 0xFC00) {
|
||||
memset(pZBuffer, 0, nCaveXSize * nCaveYSize * sizeof(UINT16));
|
||||
nZOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Donpachi/DoDonpachi sprite format (no zooming)
|
||||
static INT32 CaveSpriteBuffer_NoZoom()
|
||||
{
|
||||
UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14));
|
||||
CaveSprite* pBuffer = pSpriteList;
|
||||
INT32 nPriority;
|
||||
|
||||
nFirstSprite[0] = 0x00010000;
|
||||
nFirstSprite[1] = 0x00010000;
|
||||
nFirstSprite[2] = 0x00010000;
|
||||
nFirstSprite[3] = 0x00010000;
|
||||
|
||||
nLastSprite[0] = -1;
|
||||
nLastSprite[1] = -1;
|
||||
nLastSprite[2] = -1;
|
||||
nLastSprite[3] = -1;
|
||||
|
||||
INT16 word;
|
||||
INT32 x, y, xs, ys;
|
||||
|
||||
for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) {
|
||||
|
||||
word = pSprite[4];
|
||||
|
||||
xs = (word >> 4) & 0x01F0;
|
||||
ys = (word << 4) & 0x01F0;
|
||||
if (ys == 0 || xs == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
x = (pSprite[2] + nCaveExtraXOffset) & 0x03FF;
|
||||
#else
|
||||
x = (pSprite[2] + CaveSpriteVisibleXOffset) & 0x03FF;
|
||||
#endif
|
||||
if (x >= 320) {
|
||||
if (x + xs <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
y = (pSprite[3] + nCaveExtraYOffset) & 0x03FF;
|
||||
#else
|
||||
y = pSprite[3] & 0x03FF;
|
||||
#endif
|
||||
if (y >= 240) {
|
||||
if (y + ys <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite is both active and onscreen, so add it to the buffer
|
||||
|
||||
word = pSprite[0];
|
||||
|
||||
nPriority = (word >> 4) & 0x03;
|
||||
if (nLastSprite[nPriority] == -1) {
|
||||
nFirstSprite[nPriority] = z;
|
||||
}
|
||||
nLastSprite[nPriority] = z;
|
||||
|
||||
pBuffer->priority = 8 >> nPriority;
|
||||
|
||||
pBuffer->flip = (word >> 2) & 0x03;
|
||||
pBuffer->palette = word & 0x3F00;
|
||||
|
||||
pBuffer->address = pSprite[1] | ((word & 3) << 16);
|
||||
|
||||
pBuffer->x = x;
|
||||
pBuffer->y = y;
|
||||
|
||||
pBuffer->xsize = xs;
|
||||
pBuffer->ysize = ys;
|
||||
|
||||
pBuffer++;
|
||||
z++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Normal sprite format (zooming)
|
||||
static INT32 CaveSpriteBuffer_ZoomA()
|
||||
{
|
||||
UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14));
|
||||
CaveSprite* pBuffer = pSpriteList;
|
||||
INT32 nPriority;
|
||||
|
||||
nFirstSprite[0] = 0x00010000;
|
||||
nFirstSprite[1] = 0x00010000;
|
||||
nFirstSprite[2] = 0x00010000;
|
||||
nFirstSprite[3] = 0x00010000;
|
||||
|
||||
nLastSprite[0] = -1;
|
||||
nLastSprite[1] = -1;
|
||||
nLastSprite[2] = -1;
|
||||
nLastSprite[3] = -1;
|
||||
|
||||
INT16 word;
|
||||
INT32 x, y, xs, ys;
|
||||
|
||||
for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) {
|
||||
|
||||
word = pSprite[6];
|
||||
|
||||
xs = (word >> 4) & 0x01F0;
|
||||
ys = (word << 4) & 0x01F0;
|
||||
if (ys == 0 || xs == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
word = pSprite[2];
|
||||
|
||||
nPriority = (word >> 4) & 0x03;
|
||||
|
||||
x = ((pSprite[0] >> 6) + CaveSpriteVisibleXOffset) & 0x03FF;
|
||||
#if 0
|
||||
y = ((pSprite[1] >> 6) + nCaveExtraYOffset) & 0x03FF;
|
||||
#else
|
||||
y = (pSprite[1] >> 6) & 0x03FF;
|
||||
#endif
|
||||
|
||||
if (pSprite[4] <= 0x0100 && pSprite[5] <= 0x0100) {
|
||||
if (x >= 320) {
|
||||
if (x + xs <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (y >= 240) {
|
||||
if (y + ys <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite is active and most likely on screen, so add it to the buffer
|
||||
|
||||
if (nLastSprite[nPriority] == -1) {
|
||||
nFirstSprite[nPriority] = z;
|
||||
}
|
||||
nLastSprite[nPriority] = z;
|
||||
|
||||
pBuffer->priority = 8 >> nPriority;
|
||||
|
||||
pBuffer->xzoom = pSprite[4];
|
||||
pBuffer->yzoom = pSprite[5];
|
||||
|
||||
pBuffer->xsize = xs;
|
||||
pBuffer->ysize = ys;
|
||||
|
||||
pBuffer->x = x;
|
||||
pBuffer->y = y;
|
||||
|
||||
pBuffer->flip = (word >> 2) & 0x03;
|
||||
pBuffer->palette = word & 0x3F00;
|
||||
|
||||
pBuffer->address = pSprite[3] | ((word & 3) << 16);
|
||||
|
||||
pBuffer++;
|
||||
z++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Normal sprite format (zooming, alternate position handling)
|
||||
static INT32 CaveSpriteBuffer_ZoomB()
|
||||
{
|
||||
UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14));
|
||||
CaveSprite* pBuffer = pSpriteList;
|
||||
INT32 nPriority;
|
||||
|
||||
nFirstSprite[0] = 0x00010000;
|
||||
nFirstSprite[1] = 0x00010000;
|
||||
nFirstSprite[2] = 0x00010000;
|
||||
nFirstSprite[3] = 0x00010000;
|
||||
|
||||
nLastSprite[0] = -1;
|
||||
nLastSprite[1] = -1;
|
||||
nLastSprite[2] = -1;
|
||||
nLastSprite[3] = -1;
|
||||
|
||||
INT16 word;
|
||||
INT32 x, y, xs, ys;
|
||||
|
||||
for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) {
|
||||
|
||||
word = pSprite[6];
|
||||
|
||||
xs = (word >> 4) & 0x01F0;
|
||||
ys = (word << 4) & 0x01F0;
|
||||
if (ys == 0 || xs == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
word = pSprite[2];
|
||||
|
||||
nPriority = (word >> 4) & 0x03;
|
||||
|
||||
#if 0
|
||||
x = (pSprite[0] + nCaveExtraXOffset) & 0x03FF;
|
||||
# else
|
||||
x = (pSprite[0] + CaveSpriteVisibleXOffset) & 0x03FF;
|
||||
#endif
|
||||
#if 0
|
||||
y = (pSprite[1] + nCaveExtraYOffset) & 0x03FF;
|
||||
#else
|
||||
y = pSprite[1] & 0x03FF;
|
||||
#endif
|
||||
|
||||
if (pSprite[4] <= 0x0100 && pSprite[5] <= 0x0100) {
|
||||
if (x >= nCaveXSize) {
|
||||
if (x + xs <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (y >= nCaveYSize) {
|
||||
if (y + ys <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite is active and most likely on screen, so add it to the buffer
|
||||
|
||||
if (nLastSprite[nPriority] == -1) {
|
||||
nFirstSprite[nPriority] = z;
|
||||
}
|
||||
nLastSprite[nPriority] = z;
|
||||
|
||||
pBuffer->priority = 8 >> nPriority;
|
||||
|
||||
pBuffer->xzoom = pSprite[4];
|
||||
pBuffer->yzoom = pSprite[5];
|
||||
|
||||
pBuffer->xsize = xs;
|
||||
pBuffer->ysize = ys;
|
||||
|
||||
pBuffer->x = x;
|
||||
pBuffer->y = y;
|
||||
|
||||
pBuffer->flip = (word >> 2) & 0x03;
|
||||
pBuffer->palette = word & 0x3F00;
|
||||
|
||||
pBuffer->address = pSprite[3] | ((word & 3) << 16);
|
||||
|
||||
pBuffer++;
|
||||
z++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Power Instinct 2 sprite format (no zooming)
|
||||
static INT32 CaveSpriteBuffer_PowerInstinct()
|
||||
{
|
||||
UINT16* pSprite = (UINT16*)(CaveSpriteRAM + (nCaveSpriteBank << 14));
|
||||
CaveSprite* pBuffer = pSpriteList;
|
||||
INT32 nPriority;
|
||||
|
||||
nFirstSprite[0] = 0x00010000;
|
||||
nFirstSprite[1] = 0x00010000;
|
||||
nFirstSprite[2] = 0x00010000;
|
||||
nFirstSprite[3] = 0x00010000;
|
||||
|
||||
nLastSprite[0] = -1;
|
||||
nLastSprite[1] = -1;
|
||||
nLastSprite[2] = -1;
|
||||
nLastSprite[3] = -1;
|
||||
|
||||
INT16 word;
|
||||
INT32 x, y, xs, ys;
|
||||
|
||||
for (INT32 i = 0, z = 0; i < 0x0400; i++, pSprite += 8) {
|
||||
|
||||
word = pSprite[4];
|
||||
|
||||
xs = (word >> 4) & 0x01F0;
|
||||
ys = (word << 4) & 0x01F0;
|
||||
if (ys == 0 || xs == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
x = (pSprite[2] + nCaveExtraXOffset) & 0x03FF;
|
||||
if (x >= 320) {
|
||||
if (x + xs <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
y = (pSprite[3] + nCaveExtraYOffset) & 0x03FF;
|
||||
if (y >= 240) {
|
||||
if (y + ys <= 0x0400) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite is both active and onscreen, so add it to the buffer
|
||||
|
||||
word = pSprite[0];
|
||||
|
||||
nPriority = ((word >> 4) & 0x01) | 2;
|
||||
if (nLastSprite[nPriority] == -1) {
|
||||
nFirstSprite[nPriority] = z;
|
||||
}
|
||||
nLastSprite[nPriority] = z;
|
||||
|
||||
pBuffer->priority = 8 >> nPriority;
|
||||
|
||||
pBuffer->flip = (word >> 2) & 0x03;
|
||||
pBuffer->palette = ((word >> 4) & 0x03F0) + ((word << 5) & 0xC00);
|
||||
|
||||
pBuffer->address = pSprite[1] | ((word & 3) << 16);
|
||||
|
||||
pBuffer->x = x;
|
||||
pBuffer->y = y;
|
||||
|
||||
pBuffer->xsize = xs;
|
||||
pBuffer->ysize = ys;
|
||||
|
||||
pBuffer++;
|
||||
z++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CaveSpriteExit()
|
||||
{
|
||||
if (pSpriteList) {
|
||||
free(pSpriteList);
|
||||
pSpriteList = NULL;
|
||||
}
|
||||
|
||||
if (pZBuffer) {
|
||||
free(pZBuffer);
|
||||
pZBuffer = NULL;
|
||||
}
|
||||
|
||||
CaveSpriteVisibleXOffset = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
INT32 CaveSpriteInit(INT32 nType, INT32 nROMSize)
|
||||
{
|
||||
if (pSpriteList) {
|
||||
free(pSpriteList);
|
||||
}
|
||||
pSpriteList = (CaveSprite*)malloc(0x0401 * sizeof(CaveSprite));
|
||||
if (pSpriteList == NULL) {
|
||||
CaveSpriteExit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < 0x0400; i++) {
|
||||
pSpriteList[i].xzoom = 0x0100;
|
||||
pSpriteList[i].yzoom = 0x0100;
|
||||
}
|
||||
for (INT32 i = 0; i < 4; i++) {
|
||||
nFirstSprite[i] = 0x00010000;
|
||||
nLastSprite[i] = -1;
|
||||
}
|
||||
|
||||
if (pZBuffer) {
|
||||
free(pZBuffer);
|
||||
}
|
||||
pZBuffer = (UINT16*)malloc(nCaveXSize * nCaveYSize * sizeof(UINT16));
|
||||
if (pZBuffer == NULL) {
|
||||
CaveSpriteExit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(pZBuffer, 0, nCaveXSize * nCaveYSize * sizeof(UINT16));
|
||||
nZOffset = 0;
|
||||
|
||||
for (nSpriteAddressMask = 1; nSpriteAddressMask < nROMSize; nSpriteAddressMask <<= 1) {}
|
||||
nSpriteAddressMask--;
|
||||
|
||||
switch (nType) {
|
||||
case 0:
|
||||
CaveSpriteBuffer = &CaveSpriteBuffer_NoZoom;
|
||||
break;
|
||||
case 1:
|
||||
CaveSpriteBuffer = &CaveSpriteBuffer_ZoomA;
|
||||
break;
|
||||
case 2:
|
||||
CaveSpriteBuffer = &CaveSpriteBuffer_ZoomB;
|
||||
break;
|
||||
case 3:
|
||||
CaveSpriteBuffer = &CaveSpriteBuffer_PowerInstinct;
|
||||
break;
|
||||
default:
|
||||
CaveSpriteExit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
nCaveSpriteBank = 0;
|
||||
nCaveSpriteBankDelay = 0;
|
||||
|
||||
RenderSprite = RenderSprite_ROT0[(nCaveXSize == 320) ? 0 : 1];
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
// Create a unique name for each of the functions
|
||||
#define FN(a,b,c,d,e,f,g) RenderSprite ## a ## _ ## b ## _ROT ## c ## d ## e ## _CLIPX ## f ## g
|
||||
#define FUNCTIONNAME(a,b,c,d,e,f,g) FN(a,b,c,d,e,f,g)
|
||||
|
||||
#if ROT == 0
|
||||
#define ADVANCEWORD pPixel += ((BPP >> 3) * 16)
|
||||
#define ADVANCEROW pRow += ((BPP >> 3) * XSIZE)
|
||||
#else
|
||||
#error unsupported rotation angle specified
|
||||
#endif
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
#define DEPTH _16
|
||||
#elif EIGHTBIT == 1
|
||||
#define DEPTH _256
|
||||
#else
|
||||
#error illegal eightbit value
|
||||
#endif
|
||||
|
||||
#define TESTCOLOUR(x) x
|
||||
|
||||
#if ZBUFFER == 0
|
||||
#define ZBUF _NOZBUFFER
|
||||
#define ADVANCEZWORD
|
||||
#define ADVANCEZROW
|
||||
#define TESTZBUF(a) 1
|
||||
#define WRITEZBUF(a)
|
||||
#elif ZBUFFER == 1
|
||||
#define ZBUF _RZBUFFER
|
||||
#define ADVANCEZWORD pZPixel += 16
|
||||
#define ADVANCEZROW pZRow += XSIZE
|
||||
#define TESTZBUF(a) (pZPixel[a] <= nZPos)
|
||||
#define WRITEZBUF(a)
|
||||
#elif ZBUFFER == 2
|
||||
#define ZBUF _WZBUFFER
|
||||
#define ADVANCEZWORD pZPixel += 16
|
||||
#define ADVANCEZROW pZRow += XSIZE
|
||||
#define TESTZBUF(a) 1
|
||||
#define WRITEZBUF(a) pZPixel[a] = nZPos
|
||||
#elif ZBUFFER == 3
|
||||
#define ZBUF _RWZBUFFER
|
||||
#define ADVANCEZWORD pZPixel += 16
|
||||
#define ADVANCEZROW pZRow += XSIZE
|
||||
#define TESTZBUF(a) (pZPixel[a] <= nZPos)
|
||||
#define WRITEZBUF(a) pZPixel[a] = nZPos
|
||||
#else
|
||||
#error unsupported zbuffer mode specified.
|
||||
#endif
|
||||
|
||||
#if BPP == 16
|
||||
#define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \
|
||||
WRITEZBUF(a); \
|
||||
*((UINT16*)(pPixel + a * 2)) = (UINT16)pSpritePalette[b]; \
|
||||
}
|
||||
#elif BPP == 24
|
||||
#define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \
|
||||
WRITEZBUF(a); \
|
||||
UINT32 nRGB = pSpritePalette[b]; \
|
||||
pPixel[a * 3 + 0] = (UINT8)nRGB; \
|
||||
pPixel[a * 3 + 1] = (UINT8)(nRGB >> 8); \
|
||||
pPixel[a * 3 + 2] = (UINT8)(nRGB >> 16); \
|
||||
}
|
||||
#elif BPP == 32
|
||||
#define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \
|
||||
WRITEZBUF(a); \
|
||||
*((UINT32*)(pPixel + a * 4)) = (UINT32)pSpritePalette[b]; \
|
||||
}
|
||||
#else
|
||||
#error unsupported bitdepth specified.
|
||||
#endif
|
||||
|
||||
#if XFLIP == 0
|
||||
#define FLIP _NOFLIP
|
||||
#elif XFLIP == 1
|
||||
#define FLIP _FLIPX
|
||||
#else
|
||||
#error illegal XFLIP value
|
||||
#endif
|
||||
|
||||
#if ZOOM == 0
|
||||
#define ZOOMMODE _NOZOOM
|
||||
#elif ZOOM == 1
|
||||
#define ZOOMMODE _ZOOMXY
|
||||
#else
|
||||
#error unsupported rowscroll mode specified.
|
||||
#endif
|
||||
|
||||
#if XFLIP == 0
|
||||
#define OFFSET(a) a
|
||||
#define CLIP(a,b) if (nColumn >= (XSIZE - a)) { continue; } \
|
||||
if (nXPos >= (0 - a)) { b }
|
||||
#else
|
||||
#define OFFSET(a) (15 - a)
|
||||
#define CLIP(a,b) if (nColumn >= (0 - a) && nColumn < (XSIZE - a)) { b }
|
||||
#endif
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
#define PLOT8_CLIP(x) \
|
||||
CLIP(OFFSET((x + 0)), PLOTPIXEL(OFFSET((x + 0)), nColour & 0x0F)); \
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 1)), PLOTPIXEL(OFFSET((x + 1)), nColour & 0x0F)); \
|
||||
\
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 2)), PLOTPIXEL(OFFSET((x + 2)), nColour & 0x0F)); \
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 3)), PLOTPIXEL(OFFSET((x + 3)), nColour & 0x0F)); \
|
||||
\
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 4)), PLOTPIXEL(OFFSET((x + 4)), nColour & 0x0F)); \
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 5)), PLOTPIXEL(OFFSET((x + 5)), nColour & 0x0F)); \
|
||||
\
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 6)), PLOTPIXEL(OFFSET((x + 6)), nColour & 0x0F)); \
|
||||
nColour >>= 4; \
|
||||
CLIP(OFFSET((x + 7)), PLOTPIXEL(OFFSET((x + 7)), nColour & 0x0F));
|
||||
|
||||
#define PLOT8_NOCLIP(x) \
|
||||
PLOTPIXEL(OFFSET((x + 0)), nColour & 0x0F); \
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 1)), nColour & 0x0F); \
|
||||
\
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 2)), nColour & 0x0F); \
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 3)), nColour & 0x0F); \
|
||||
\
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 4)), nColour & 0x0F); \
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 5)), nColour & 0x0F); \
|
||||
\
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 6)), nColour & 0x0F); \
|
||||
nColour >>= 4; \
|
||||
PLOTPIXEL(OFFSET((x + 7)), nColour & 0x0F);
|
||||
#else
|
||||
#define PLOT4_CLIP(x) \
|
||||
CLIP(OFFSET((x + 0)), PLOTPIXEL(OFFSET((x + 0)), nColour & 0xFF)); \
|
||||
nColour >>= 8; \
|
||||
CLIP(OFFSET((x + 1)), PLOTPIXEL(OFFSET((x + 1)), nColour & 0xFF)); \
|
||||
nColour >>= 8; \
|
||||
\
|
||||
CLIP(OFFSET((x + 2)), PLOTPIXEL(OFFSET((x + 2)), nColour & 0xFF)); \
|
||||
nColour >>= 8; \
|
||||
CLIP(OFFSET((x + 3)), PLOTPIXEL(OFFSET((x + 3)), nColour & 0xFF));
|
||||
|
||||
#define PLOT4_NOCLIP(x) \
|
||||
PLOTPIXEL(OFFSET((x + 0)), nColour & 0xFF); \
|
||||
nColour >>= 8; \
|
||||
PLOTPIXEL(OFFSET((x + 1)), nColour & 0xFF); \
|
||||
nColour >>= 8; \
|
||||
\
|
||||
PLOTPIXEL(OFFSET((x + 2)), nColour & 0xFF); \
|
||||
nColour >>= 8; \
|
||||
PLOTPIXEL(OFFSET((x + 3)), nColour & 0xFF);
|
||||
#endif
|
||||
|
||||
static void FUNCTIONNAME(BPP,XSIZE,ROT,FLIP,ZOOMMODE,ZBUF,DEPTH)()
|
||||
{
|
||||
// Create an empty function if unsupported features are requested
|
||||
#if ROT == 0
|
||||
|
||||
INT32 x, nColumn;
|
||||
INT32 nColour;
|
||||
|
||||
#if ZBUFFER == 0
|
||||
for (nSpriteRow = 0; nSpriteRow < nYSize; ADVANCEROW, nSpriteRow++, pSpriteData += nSpriteRowSize) {
|
||||
#else
|
||||
for (nSpriteRow = 0; nSpriteRow < nYSize; ADVANCEROW, ADVANCEZROW, nSpriteRow++, pSpriteData += nSpriteRowSize) {
|
||||
#endif
|
||||
nColumn = nXPos;
|
||||
|
||||
#if ZBUFFER == 0
|
||||
#if XFLIP == 0
|
||||
for (x = (0 << EIGHTBIT), pPixel = pRow; x < nXSize; x += (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD) {
|
||||
#else
|
||||
for (x = nXSize - (2 << EIGHTBIT), pPixel = pRow; x >= 0; x -= (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD) {
|
||||
#endif
|
||||
#else
|
||||
#if XFLIP == 0
|
||||
for (x = 0, pPixel = pRow, pZPixel = pZRow; x < nXSize; x += (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD, ADVANCEZWORD) {
|
||||
#else
|
||||
for (x = nXSize - (2 << EIGHTBIT), pPixel = pRow, pZPixel = pZRow; x >= 0; x -= (2 << EIGHTBIT), nColumn += 16, ADVANCEWORD, ADVANCEZWORD) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
if (nColumn >= 0 && nColumn < (XSIZE - 16)) {
|
||||
#if XFLIP == 0
|
||||
nColour = pSpriteData[x];
|
||||
PLOT8_NOCLIP(0);
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT8_NOCLIP(8);
|
||||
#else
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT8_NOCLIP(8);
|
||||
nColour = pSpriteData[x];
|
||||
PLOT8_NOCLIP(0);
|
||||
#endif
|
||||
} else {
|
||||
#if XFLIP == 0
|
||||
nColour = pSpriteData[x];
|
||||
PLOT8_CLIP(0);
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT8_CLIP(8);
|
||||
#else
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT8_CLIP(8);
|
||||
nColour = pSpriteData[x];
|
||||
PLOT8_CLIP(0);
|
||||
#endif
|
||||
#else
|
||||
if (nColumn >= 0 && nColumn < (XSIZE - 16)) {
|
||||
#if XFLIP == 0
|
||||
nColour = pSpriteData[x];
|
||||
PLOT4_NOCLIP(0);
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT4_NOCLIP(4);
|
||||
nColour = pSpriteData[x + 2];
|
||||
PLOT4_NOCLIP(8);
|
||||
nColour = pSpriteData[x + 3];
|
||||
PLOT4_NOCLIP(12);
|
||||
#else
|
||||
nColour = pSpriteData[x + 3];
|
||||
PLOT4_NOCLIP(12);
|
||||
nColour = pSpriteData[x + 2];
|
||||
PLOT4_NOCLIP(8);
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT4_NOCLIP(4);
|
||||
nColour = pSpriteData[x];
|
||||
PLOT4_NOCLIP(0);
|
||||
#endif
|
||||
} else {
|
||||
#if XFLIP == 0
|
||||
nColour = pSpriteData[x];
|
||||
PLOT4_CLIP(0);
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT4_CLIP(4);
|
||||
nColour = pSpriteData[x + 2];
|
||||
PLOT4_CLIP(8);
|
||||
nColour = pSpriteData[x + 3];
|
||||
PLOT4_CLIP(12);
|
||||
#else
|
||||
nColour = pSpriteData[x + 3];
|
||||
PLOT4_CLIP(12);
|
||||
nColour = pSpriteData[x + 2];
|
||||
PLOT4_CLIP(8);
|
||||
nColour = pSpriteData[x + 1];
|
||||
PLOT4_CLIP(4);
|
||||
nColour = pSpriteData[x];
|
||||
PLOT4_CLIP(0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef PLOT4_CLIP
|
||||
#undef PLOT4_NOCLIP
|
||||
#undef PLOT8_CLIP
|
||||
#undef PLOT8_NOCLIP
|
||||
#undef OFFSET
|
||||
#undef FLIP
|
||||
#undef PLOTPIXEL
|
||||
#undef CLIP
|
||||
#undef TESTCOLOUR
|
||||
#undef ADVANCEZROW
|
||||
#undef ADVANCEZWORD
|
||||
#undef ADVANCEROW
|
||||
#undef ADVANCEWORD
|
||||
#undef TESTZBUF
|
||||
#undef WRITEZBUF
|
||||
#undef ZBUF
|
||||
#undef ZOOMMODE
|
||||
#undef DEPTH
|
||||
#undef FUNCTIONNAME
|
||||
#undef FN
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
// Create a unique name for each of the functions
|
||||
#define FN(a,b,c,d,e,f,g) RenderSprite ## a ## _ ## b ## _ROT ## c ## d ## e ## _NOCLIP ## f ## g
|
||||
#define FUNCTIONNAME(a,b,c,d,e,f,g) FN(a,b,c,d,e,f,g)
|
||||
|
||||
#if ROT == 0
|
||||
#define ADVANCECOLUMN pPixel += (BPP >> 3)
|
||||
#define ADVANCEROW pRow += ((BPP >> 3) * XSIZE)
|
||||
#else
|
||||
#error unsupported rotation angle specified
|
||||
#endif
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
#define DEPTH _16
|
||||
#elif EIGHTBIT == 1
|
||||
#define DEPTH _256
|
||||
#else
|
||||
#error illegal eightbit value
|
||||
#endif
|
||||
|
||||
#define TESTCOLOUR(x) x
|
||||
|
||||
#if ZBUFFER == 0
|
||||
#define ZBUF _NOZBUFFER
|
||||
#define ADVANCEZCOLUMN
|
||||
#define ADVANCEZROW
|
||||
#define TESTZBUF(a) 1
|
||||
#define WRITEZBUF(a)
|
||||
#elif ZBUFFER == 1
|
||||
#define ZBUF _RZBUFFER
|
||||
#define ADVANCEZCOLUMN pZPixel += 1
|
||||
#define ADVANCEZROW pZRow += XSIZE
|
||||
#define TESTZBUF(a) (pZPixel[a] <= nZPos)
|
||||
#define WRITEZBUF(a)
|
||||
#elif ZBUFFER == 2
|
||||
#define ZBUF _WZBUFFER
|
||||
#define ADVANCEZCOLUMN pZPixel += 1
|
||||
#define ADVANCEZROW pZRow += XSIZE
|
||||
#define TESTZBUF(a) 1
|
||||
#define WRITEZBUF(a) pZPixel[a] = nZPos
|
||||
#elif ZBUFFER == 3
|
||||
#define ZBUF _RWZBUFFER
|
||||
#define ADVANCEZCOLUMN pZPixel += 1
|
||||
#define ADVANCEZROW pZRow += XSIZE
|
||||
#define TESTZBUF(a) (pZPixel[a] <= nZPos)
|
||||
#define WRITEZBUF(a) pZPixel[a] = nZPos
|
||||
#else
|
||||
#error unsupported zbuffer mode specified.
|
||||
#endif
|
||||
|
||||
#if BPP == 16
|
||||
#define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \
|
||||
WRITEZBUF(a); \
|
||||
*((UINT16*)(pPixel + a * 2)) = (UINT16)pSpritePalette[b]; \
|
||||
}
|
||||
#elif BPP == 24
|
||||
#define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \
|
||||
WRITEZBUF(a); \
|
||||
UINT32 nRGB = pSpritePalette[b]; \
|
||||
pPixel[a * 3 + 0] = (UINT8)nRGB; \
|
||||
pPixel[a * 3 + 1] = (UINT8)(nRGB >> 8); \
|
||||
pPixel[a * 3 + 2] = (UINT8)(nRGB >> 16); \
|
||||
}
|
||||
#elif BPP == 32
|
||||
#define PLOTPIXEL(a,b) if (TESTCOLOUR(b) && TESTZBUF(a)) { \
|
||||
WRITEZBUF(a); \
|
||||
*((UINT32*)(pPixel + a * 4)) = (UINT32)pSpritePalette[b]; \
|
||||
}
|
||||
#else
|
||||
#error unsupported bitdepth specified.
|
||||
#endif
|
||||
|
||||
#if XFLIP == 0
|
||||
#define FLIP _NOFLIP
|
||||
#elif XFLIP == 1
|
||||
#define FLIP _FLIPX
|
||||
#else
|
||||
#error illegal XFLIP value
|
||||
#endif
|
||||
|
||||
#if ZOOM == 0
|
||||
#define ZOOMMODE _NOZOOM
|
||||
#elif ZOOM == 1
|
||||
#define ZOOMMODE _ZOOMOUT
|
||||
#elif ZOOM == 2
|
||||
#define ZOOMMODE _ZOOMIN
|
||||
#else
|
||||
#error unsupported zoom mode specified.
|
||||
#endif
|
||||
|
||||
static void FUNCTIONNAME(BPP,XSIZE,ROT,FLIP,ZOOMMODE,ZBUF,DEPTH)()
|
||||
{
|
||||
// Create an empty function if unsupported features are requested
|
||||
#if ROT == 0 && XFLIP == 0 && EIGHTBIT == 1
|
||||
|
||||
INT32 nSpriteColumn;
|
||||
|
||||
INT32 nSpriteXOffset2;
|
||||
|
||||
#if ZOOM == 2
|
||||
INT32 nPrevSpriteXOffset;
|
||||
INT32 nPrevSpriteXOffsetStart = nSpriteXOffset & 0xFFFF0000;
|
||||
INT32 nPrevSpriteYOffset = nSpriteYOffset & 0xFFFF0000;
|
||||
|
||||
if (nPrevSpriteXOffsetStart == 0) {
|
||||
nPrevSpriteXOffsetStart = 0xFEDC1234;
|
||||
}
|
||||
|
||||
if (nPrevSpriteYOffset == 0) {
|
||||
nPrevSpriteYOffset = 0xFEDC1234;
|
||||
}
|
||||
#endif
|
||||
|
||||
UINT8* pSpriteRowData = (UINT8*)pSpriteData;
|
||||
|
||||
for (nSpriteRow = nYSize; nSpriteRow > 0; nSpriteRow -= 0x00010000, nSpriteYOffset += nSpriteYZoomSize) {
|
||||
|
||||
#if ZOOM == 2
|
||||
if ((nSpriteYOffset & 0xFFFF0000) == (nPrevSpriteYOffset & 0xFFFF0000)) {
|
||||
|
||||
ADVANCEROW;
|
||||
#if ZBUFFER != 0
|
||||
ADVANCEZROW;
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
nPrevSpriteYOffset = nSpriteYOffset;
|
||||
nPrevSpriteXOffset = nPrevSpriteXOffsetStart;
|
||||
#endif
|
||||
pSpriteRowData = ((UINT8*)pSpriteData) + (nSpriteYOffset >> 16) * nSpriteRowSize;
|
||||
|
||||
nSpriteXOffset2 = nSpriteXOffset;
|
||||
|
||||
#if ZBUFFER != 0
|
||||
pZPixel = pZRow;
|
||||
#endif
|
||||
|
||||
for (nSpriteColumn = nXSize, pPixel = pRow; nSpriteColumn > 0; nSpriteColumn -= 0x00010000, nSpriteXOffset2 += nSpriteXZoomSize) {
|
||||
|
||||
#if ZOOM == 2
|
||||
if ((nSpriteXOffset2 & 0xFFFF0000) != (nPrevSpriteXOffset & 0xFFFF0000)) {
|
||||
|
||||
nPrevSpriteXOffset = nSpriteXOffset2;
|
||||
#endif
|
||||
PLOTPIXEL(0, pSpriteRowData[nSpriteXOffset2 >> 16]);
|
||||
|
||||
#if ZOOM == 2
|
||||
}
|
||||
#endif
|
||||
|
||||
ADVANCECOLUMN;
|
||||
#if ZBUFFER != 0
|
||||
ADVANCEZCOLUMN;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ADVANCEROW;
|
||||
#if ZBUFFER != 0
|
||||
ADVANCEZROW;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef OFFSET
|
||||
#undef FLIP
|
||||
#undef PLOTPIXEL
|
||||
#undef TESTCOLOUR
|
||||
#undef ADVANCEZROW
|
||||
#undef ADVANCEZCOLUMN
|
||||
#undef ADVANCEROW
|
||||
#undef ADVANCECOLUMN
|
||||
#undef TESTZBUF
|
||||
#undef WRITEZBUF
|
||||
#undef ZBUF
|
||||
#undef ZOOMMODE
|
||||
#undef DEPTH
|
||||
#undef FUNCTIONNAME
|
||||
#undef FN
|
||||
|
|
@ -0,0 +1,981 @@
|
|||
// Cave hardware tilemaps
|
||||
|
||||
#include "cave.h"
|
||||
|
||||
struct CaveTile { INT16 x; INT16 y; UINT32 tile; };
|
||||
|
||||
static CaveTile* CaveTileQueueMemory[4] = { NULL, };
|
||||
static CaveTile* CaveTileQueue[4][4];
|
||||
|
||||
UINT32 CaveTileReg[4][3];
|
||||
|
||||
UINT8* CaveTileROM[4] = { NULL, };
|
||||
UINT8* CaveTileRAM[4] = { NULL, };
|
||||
|
||||
static INT8* CaveTileAttrib[4] = { NULL, };
|
||||
|
||||
INT32 nCaveTileBank = 0;
|
||||
|
||||
// Used when row-select mode is enabled
|
||||
static INT32* pRowScroll[4] = { NULL, };
|
||||
static INT32* pRowSelect[4] = { NULL, };
|
||||
|
||||
static INT32 nLayerXOffset[4];
|
||||
static INT32 nLayerYOffset;
|
||||
static INT32 nPaletteOffset[4];
|
||||
static INT32 nPaletteSize[4];
|
||||
|
||||
static INT32 CaveTileCount[4];
|
||||
static INT32 CaveTileMax[4];
|
||||
static INT32 nTileMask[4];
|
||||
|
||||
static UINT8* pTile;
|
||||
static UINT32* pTileData;
|
||||
static UINT32* pTilePalette;
|
||||
static INT32* pTileRowInfo;
|
||||
|
||||
typedef void (*RenderTileFunction)();
|
||||
static RenderTileFunction* RenderTile;
|
||||
|
||||
static INT32 nTileXPos, nTileYPos, nRowOffset;
|
||||
|
||||
static INT32 nClipX8, nClipX16;
|
||||
static INT32 nClipY8, nClipY16;
|
||||
|
||||
// Include the tile rendering functions
|
||||
#include "cave_tile_func.h"
|
||||
|
||||
static void CaveQueue8x8Layer_Normal(INT32 nLayer)
|
||||
{
|
||||
INT32 x, y;
|
||||
INT32 bx, by, cx, cy, mx;
|
||||
INT32 nTileColumn, nTileRow;
|
||||
UINT32 nTileNumber;
|
||||
|
||||
UINT8* pTileRAM = CaveTileRAM[nLayer];
|
||||
|
||||
UINT32 nTileOffset = 0;
|
||||
if (nCaveTileBank) {
|
||||
nTileOffset = 0x040000;
|
||||
}
|
||||
|
||||
mx = (nCaveXSize >> 3) << 2;
|
||||
|
||||
bx = CaveTileReg[nLayer][0] - 0x0A + nLayerXOffset[nLayer];
|
||||
bx &= 0x01FF;
|
||||
cx = (bx >> 3) << 2;
|
||||
bx &= 0x0007;
|
||||
|
||||
by = CaveTileReg[nLayer][1] + nLayerYOffset;
|
||||
by &= 0x01FF;
|
||||
cy = (by >> 3) << 8;
|
||||
by &= 0x0007;
|
||||
|
||||
for (y = 0; y < (31 << 8); y += (1 << 8)) {
|
||||
nTileRow = (cy + y) & (0x3F << 8);
|
||||
nTileYPos = (y >> 5) - by;
|
||||
|
||||
if (nTileYPos <= -8 || nTileYPos >= nCaveYSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (x = mx; x >= 0; x -= (1 << 2)) {
|
||||
nTileColumn = (cx + x) & (0x3F << 2);
|
||||
nTileNumber = *((UINT16*)(pTileRAM + 0x4000 + nTileRow + nTileColumn)) << 16;
|
||||
nTileNumber |= *((UINT16*)(pTileRAM + 0x4002 + nTileRow + nTileColumn));
|
||||
|
||||
nTileNumber |= nTileOffset;
|
||||
|
||||
if (CaveTileAttrib[nLayer][nTileNumber & nTileMask[nLayer]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nTileXPos = (x << 1) - bx;
|
||||
|
||||
if (nTileXPos <= -8 || nTileXPos >= nCaveXSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]->x = nTileXPos;
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]->y = nTileYPos;
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]->tile = nTileNumber;
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]++;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave8x8Layer_Normal(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
UINT32 nTileNumber;
|
||||
|
||||
UINT32* pPalette = CavePalette + nPaletteOffset[nLayer];
|
||||
UINT32 nPaletteMask = 0x3F000000;
|
||||
if (nPaletteSize[nLayer] == 6) {
|
||||
nPaletteMask = 0x0F000000;
|
||||
}
|
||||
INT32 nPaletteShift = 24 - nPaletteSize[nLayer];
|
||||
|
||||
CaveTile* TileQueue = CaveTileQueue[nLayer][nPriority];
|
||||
|
||||
while ((nTileXPos = TileQueue->x) < 9999) {
|
||||
nTileYPos = TileQueue->y;
|
||||
nTileNumber = TileQueue->tile;
|
||||
pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift);
|
||||
nTileNumber &= nTileMask[nLayer];
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp);
|
||||
|
||||
pTileData = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6));
|
||||
|
||||
if (nTileYPos < 0 || nTileYPos > nClipY8 || nTileXPos < 0 || nTileXPos > nClipX8) {
|
||||
RenderTile[1]();
|
||||
} else {
|
||||
RenderTile[0]();
|
||||
}
|
||||
|
||||
TileQueue++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave8x8Layer_RowScroll(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
INT32 x, y;
|
||||
INT32 bx, by, cy;
|
||||
INT32 nTileColumn, nTileRow;
|
||||
UINT32 nTileNumber;
|
||||
|
||||
UINT8* pTileRAM = CaveTileRAM[nLayer];
|
||||
UINT32* pPalette = CavePalette + nPaletteOffset[nLayer];
|
||||
INT32 nPaletteShift = 24 - nPaletteSize[nLayer];
|
||||
|
||||
INT32* rowscroll = pRowScroll[nLayer];
|
||||
|
||||
INT32 count = CaveTileCount[nLayer];
|
||||
|
||||
if (count >= (64 * 31)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UINT32 nTileOffset = 0;
|
||||
if (nCaveTileBank) {
|
||||
nTileOffset = 0x040000;
|
||||
}
|
||||
|
||||
bx = CaveTileReg[nLayer][0] - 0x0A + nLayerXOffset[nLayer];
|
||||
bx &= 0x01FF;
|
||||
|
||||
by = CaveTileReg[nLayer][1] + nLayerYOffset;
|
||||
by &= 0x01FF;
|
||||
cy = (by >> 3) << 8;
|
||||
by &= 0x0007;
|
||||
|
||||
if (nPriority == 0) {
|
||||
INT32 dy = CaveTileReg[nLayer][1] + 0x12 - nCaveRowModeOffset;
|
||||
|
||||
for (y = 0; y < nCaveYSize; y++) {
|
||||
rowscroll[y] = *((UINT16*)(pTileRAM + 0x1000 + (((dy + y) & 0x01FF) << 2))) + bx;
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < (31 << 8); y += (1 << 8)) {
|
||||
nTileYPos = (y >> 5) - by;
|
||||
|
||||
nTileRow = (cy + y) & (0x3F << 8);
|
||||
pTileRowInfo = rowscroll + nTileYPos;
|
||||
|
||||
for (x = 0; x < (64 << 2); x += (1 << 2)) {
|
||||
nTileColumn = x & (0x3F << 2);
|
||||
nTileNumber = *((UINT16*)(pTileRAM + 0x4000 + nTileRow + nTileColumn)) << 16;
|
||||
if ((nTileNumber >> 30) != nPriority) {
|
||||
continue;
|
||||
}
|
||||
nTileNumber |= *((UINT16*)(pTileRAM + 0x4002 + nTileRow + nTileColumn));
|
||||
pTilePalette = pPalette + ((nTileNumber & 0x3F000000) >> nPaletteShift);
|
||||
|
||||
nTileNumber |= nTileOffset;
|
||||
nTileNumber &= nTileMask[nLayer];
|
||||
|
||||
count++;
|
||||
|
||||
if (nTileYPos <= -8 || nTileYPos >= nCaveYSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*((UINT32*)(CaveTileAttrib[nLayer] + nTileNumber))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nTileXPos = (x << 1);
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch);
|
||||
|
||||
pTileData = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6));
|
||||
|
||||
if (nTileYPos < 0 || nTileYPos > nClipY8 || nTileXPos < 0 || nTileXPos > nClipX8) {
|
||||
RenderTile[3]();
|
||||
} else {
|
||||
RenderTile[2]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= (64 * 31)) {
|
||||
CaveTileMax[0] -= 0x0123;
|
||||
CaveTileMax[1] -= 0x0123;
|
||||
CaveTileMax[2] -= 0x0123;
|
||||
CaveTileMax[3] -= 0x0123;
|
||||
}
|
||||
CaveTileCount[nLayer] = count;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void CaveQueue16x16Layer_Normal(INT32 nLayer)
|
||||
{
|
||||
INT32 x, y;
|
||||
INT32 bx, by, cx, cy, mx;
|
||||
INT32 nTileColumn, nTileRow;
|
||||
UINT32 nTileNumber;
|
||||
|
||||
UINT8* pTileRAM = CaveTileRAM[nLayer];
|
||||
|
||||
mx = (nCaveXSize >> 4) << 2;
|
||||
|
||||
bx = CaveTileReg[nLayer][0] - 0x12 + nLayerXOffset[nLayer];
|
||||
bx &= 0x01FF;
|
||||
cx = (bx >> 4) << 2;
|
||||
bx &= 0x000F;
|
||||
|
||||
by = CaveTileReg[nLayer][1] + nLayerYOffset;
|
||||
by &= 0x01FF;
|
||||
cy = (by >> 4) << 7;
|
||||
by &= 0x000F;
|
||||
|
||||
for (y = 0; y < (16 << 7); y += (1 << 7)) {
|
||||
nTileRow = (cy + y) & (0x1F << 7);
|
||||
nTileYPos = (y >> 3) - by;
|
||||
|
||||
if (nTileYPos <= -16 || nTileYPos >= nCaveYSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (x = mx; x >= 0; x -= (1 << 2)) {
|
||||
nTileColumn = (cx + x) & (0x1F << 2);
|
||||
nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16;
|
||||
nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn));
|
||||
|
||||
if (*((UINT32*)(CaveTileAttrib[nLayer] + ((nTileNumber << 2) & nTileMask[nLayer]))) == 0x01010101) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nTileXPos = (x << 2) - bx;
|
||||
|
||||
if (nTileXPos <= -16 || nTileXPos >= nCaveXSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]->x = nTileXPos;
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]->y = nTileYPos;
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]->tile = nTileNumber;
|
||||
CaveTileQueue[nLayer][nTileNumber >> 30]++;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave16x16Layer_Normal(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
UINT32 nTileNumber, nAttrib;
|
||||
UINT32* pTileStart;
|
||||
|
||||
UINT32* pPalette = CavePalette + nPaletteOffset[nLayer];
|
||||
INT32 nPaletteShift = 24 - nPaletteSize[nLayer];
|
||||
UINT32 nPaletteMask = 0x3F000000;
|
||||
if (nPaletteSize[nLayer] == 6) {
|
||||
nPaletteMask = 0x0F000000;
|
||||
}
|
||||
|
||||
CaveTile* TileQueue = CaveTileQueue[nLayer][nPriority];
|
||||
|
||||
while ((nTileXPos = TileQueue->x) < 9999) {
|
||||
nTileYPos = TileQueue->y;
|
||||
nTileNumber = TileQueue->tile;
|
||||
pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift);
|
||||
nTileNumber <<= 2;
|
||||
nTileNumber &= nTileMask[nLayer];
|
||||
|
||||
nAttrib = *((UINT32*)(CaveTileAttrib[nLayer] + nTileNumber));
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp);
|
||||
|
||||
pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6));
|
||||
|
||||
if (nTileXPos < 0 || nTileXPos > nClipX16 || nTileYPos < 0 || nTileYPos > nClipY16) {
|
||||
|
||||
if ((nAttrib & 0x000000FF) == 0) {
|
||||
pTileData = pTileStart;
|
||||
if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[0]();
|
||||
} else {
|
||||
RenderTile[1]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nTileXPos += 8;
|
||||
pTile += 8 * nBurnBpp;
|
||||
if ((nAttrib & 0x0000FF00) == 0) {
|
||||
if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
pTileData = pTileStart + 16;
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[0]();
|
||||
} else{
|
||||
RenderTile[1]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nTileXPos -= 8;
|
||||
nTileYPos += 8;
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp);
|
||||
if ((nAttrib & 0x00FF0000) == 0) {
|
||||
if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
pTileData = pTileStart + 32;
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[0]();
|
||||
} else {
|
||||
RenderTile[1]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nTileXPos += 8;
|
||||
pTile += 8 * nBurnBpp;
|
||||
if ((nAttrib & 0xFF000000) == 0) {
|
||||
if (nTileXPos > -8 && nTileXPos < nCaveXSize && nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
pTileData = pTileStart + 48;
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8 && nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[0]();
|
||||
} else {
|
||||
RenderTile[1]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((nAttrib & 0x000000FF) == 0) {
|
||||
pTileData = pTileStart;
|
||||
RenderTile[0]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
pTile += 8 * nBurnBpp;
|
||||
if ((nAttrib & 0x0000FF00) == 0) {
|
||||
pTileData = pTileStart + 16;
|
||||
RenderTile[0]();
|
||||
}
|
||||
nTileXPos -= 8;
|
||||
nTileYPos += 8;
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp);
|
||||
if ((nAttrib & 0x00FF0000) == 0) {
|
||||
pTileData = pTileStart + 32;
|
||||
RenderTile[0]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
pTile += 8 * nBurnBpp;
|
||||
if ((nAttrib & 0xFF000000) == 0) {
|
||||
pTileData = pTileStart + 48;
|
||||
RenderTile[0]();
|
||||
}
|
||||
}
|
||||
|
||||
TileQueue++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave16x16Layer_RowScroll(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
INT32 x, y;
|
||||
INT32 bx, by, cy;
|
||||
INT32 nTileColumn, nTileRow;
|
||||
UINT32 nTileNumber, nAttrib;
|
||||
UINT32* pTileStart;
|
||||
|
||||
UINT8* pTileRAM = CaveTileRAM[nLayer];
|
||||
UINT32* pPalette = CavePalette + nPaletteOffset[nLayer];
|
||||
INT32 nPaletteShift = 24 - nPaletteSize[nLayer];
|
||||
UINT32 nPaletteMask = 0x3F000000;
|
||||
if (nPaletteSize[nLayer] == 6) {
|
||||
nPaletteMask = 0x0F000000;
|
||||
}
|
||||
|
||||
INT32* rowscroll = pRowScroll[nLayer];
|
||||
|
||||
INT32 count = CaveTileCount[nLayer];
|
||||
|
||||
if (count >= (32 * 16)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bx = CaveTileReg[nLayer][0] - 0x12 + nLayerXOffset[nLayer];
|
||||
bx &= 0x01FF;
|
||||
|
||||
by = CaveTileReg[nLayer][1] + nLayerYOffset;
|
||||
by &= 0x01FF;
|
||||
cy = (by >> 4) << 7;
|
||||
by &= 0x000F;
|
||||
|
||||
if (nPriority == 0) {
|
||||
INT32 dy = CaveTileReg[nLayer][1] + 0x12 - nCaveRowModeOffset;
|
||||
|
||||
for (y = 0; y < nCaveYSize; y++) {
|
||||
rowscroll[y] = *((UINT16*)(pTileRAM + 0x1000 + (((dy + y) & 0x01FF) << 2))) + bx;
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < (16 << 7); y += (1 << 7)) {
|
||||
nTileRow = (cy + y) & (0x1F << 7);
|
||||
nTileYPos = (y >> 3) - by;
|
||||
|
||||
pTileRowInfo = rowscroll + nTileYPos;
|
||||
|
||||
for (x = 0; x < (32 << 2); x += (1 << 2)) {
|
||||
nTileColumn = x & (0x1F << 2);
|
||||
nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16;
|
||||
if ((nTileNumber >> 30) != nPriority) {
|
||||
continue;
|
||||
}
|
||||
nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn));
|
||||
pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift);
|
||||
nTileNumber <<= 2;
|
||||
nTileNumber &= nTileMask[nLayer];
|
||||
|
||||
count++;
|
||||
|
||||
nAttrib = *((UINT32*)(CaveTileAttrib[nLayer] + nTileNumber));
|
||||
if (nAttrib == 0x01010101) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nTileXPos = (x << 2);
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch);
|
||||
|
||||
pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 6));
|
||||
|
||||
if (nTileYPos < 0 || nTileYPos > nClipY16) {
|
||||
if ((nAttrib & 0x000000FF) == 0) {
|
||||
pTileData = pTileStart;
|
||||
if (nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
if (nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[2]();
|
||||
} else {
|
||||
RenderTile[3]();
|
||||
}
|
||||
}
|
||||
}
|
||||
nTileXPos += 8;
|
||||
if ((nAttrib & 0x0000FF00) == 0) {
|
||||
if (nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
pTileData = pTileStart + 16;
|
||||
if (nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[2]();
|
||||
} else {
|
||||
RenderTile[3]();
|
||||
}
|
||||
}
|
||||
}
|
||||
nTileXPos -= 8;
|
||||
nTileYPos += 8;
|
||||
|
||||
pTileRowInfo += 8;
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch);
|
||||
if ((nAttrib & 0x00FF0000) == 0) {
|
||||
if (nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
pTileData = pTileStart + 32;
|
||||
if (nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[2]();
|
||||
} else {
|
||||
RenderTile[3]();
|
||||
}
|
||||
}
|
||||
}
|
||||
nTileXPos += 8;
|
||||
if ((nAttrib & 0xFF000000) == 0) {
|
||||
if (nTileYPos > -8 && nTileYPos < nCaveYSize) {
|
||||
pTileData = pTileStart + 48;
|
||||
if (nTileYPos >= 0 && nTileYPos <= nClipY8) {
|
||||
RenderTile[2]();
|
||||
} else {
|
||||
RenderTile[3]();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((nAttrib & 0x000000FF) == 0) {
|
||||
pTileData = pTileStart;
|
||||
RenderTile[2]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
if ((nAttrib & 0x0000FF00) == 0) {
|
||||
pTileData = pTileStart + 16;
|
||||
RenderTile[2]();
|
||||
}
|
||||
nTileXPos -= 8;
|
||||
nTileYPos += 8;
|
||||
|
||||
pTileRowInfo += 8;
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch);
|
||||
if ((nAttrib & 0x00FF0000) == 0) {
|
||||
pTileData = pTileStart + 32;
|
||||
RenderTile[2]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
if ((nAttrib & 0xFF000000) == 0) {
|
||||
pTileData = pTileStart + 48;
|
||||
RenderTile[2]();
|
||||
}
|
||||
}
|
||||
nTileYPos -= 8;
|
||||
|
||||
pTileRowInfo -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= (32 * 16)) {
|
||||
CaveTileMax[0] -= 0x0123;
|
||||
CaveTileMax[1] -= 0x0123;
|
||||
CaveTileMax[2] -= 0x0123;
|
||||
CaveTileMax[3] -= 0x0123;
|
||||
}
|
||||
CaveTileCount[nLayer] = count;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave16x16Layer_RowSelect(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
INT32 x, y, ry, rx;
|
||||
INT32 bx, by, mx;
|
||||
INT32 nTileColumn, nTileRow;
|
||||
UINT32 nTileNumber;
|
||||
UINT32* pTileStart;
|
||||
|
||||
UINT8* pTileRAM = CaveTileRAM[nLayer];
|
||||
UINT32* pPalette = CavePalette + nPaletteOffset[nLayer];
|
||||
INT32 nPaletteShift = 24 - nPaletteSize[nLayer];
|
||||
UINT32 nPaletteMask = 0x3F000000;
|
||||
if (nPaletteSize[nLayer] == 6) {
|
||||
nPaletteMask = 0x0F000000;
|
||||
}
|
||||
|
||||
INT32* rowselect = pRowSelect[nLayer];
|
||||
INT32* rowscroll = pRowScroll[nLayer];
|
||||
|
||||
INT32 count = CaveTileCount[nLayer];
|
||||
|
||||
mx = nCaveXSize >> 4;
|
||||
|
||||
if (count >= nCaveYSize * (mx + 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bx = CaveTileReg[nLayer][0] - 0x12 + nLayerXOffset[nLayer];
|
||||
bx &= 0x01FF;
|
||||
|
||||
by = CaveTileReg[nLayer][1] + nLayerYOffset;
|
||||
by &= 0x01FF;
|
||||
|
||||
if (nPriority == 0) {
|
||||
INT32 cy = CaveTileReg[nLayer][1] + 0x12 - nCaveRowModeOffset;
|
||||
|
||||
if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode
|
||||
for (y = 0; y < nCaveYSize; y++) {
|
||||
rowselect[y] = *((UINT16*)(pTileRAM + 0x1002 + (((cy + y) & 0x01FF) << 2)));
|
||||
rowscroll[y] = *((UINT16*)(pTileRAM + 0x1000 + (((cy + y) & 0x01FF) << 2))) + bx;
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < nCaveYSize; y++) {
|
||||
rowselect[y] = *((UINT16*)(pTileRAM + 0x1002 + (((cy + y) & 0x01FF) << 2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < nCaveYSize; y++) {
|
||||
ry = rowselect[y];
|
||||
nTileRow = ((ry >> 4) & 0x1F) << 7;
|
||||
nTileYPos = y;
|
||||
|
||||
if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode
|
||||
rx = rowscroll[y];
|
||||
ry = (((ry & 8) << 1) + (ry & 7)) << 1;
|
||||
|
||||
for (x = 0; x <= mx; x++) {
|
||||
|
||||
nTileColumn = (((rx >> 4) + x) & 0x1F) << 2;
|
||||
nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16;
|
||||
if ((nTileNumber >> 30) != nPriority) {
|
||||
continue;
|
||||
}
|
||||
nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn));
|
||||
pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift);
|
||||
nTileNumber &= nTileMask[nLayer];
|
||||
|
||||
count++;
|
||||
|
||||
if (((UINT32*)CaveTileAttrib[nLayer])[nTileNumber] == 0x01010101) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nTileXPos = (x << 4) - (rx & 15);
|
||||
|
||||
if (nTileXPos <= -16 || nTileXPos >= nCaveXSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch) + (nTileXPos * nBurnBpp);
|
||||
|
||||
pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 8));
|
||||
pTileStart += ry;
|
||||
|
||||
pTileData = pTileStart;
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8) {
|
||||
RenderTile[4]();
|
||||
} else {
|
||||
RenderTile[5]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
pTile += (nBurnBpp << 3);
|
||||
pTileData = pTileStart + 16;
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX16) {
|
||||
RenderTile[4]();
|
||||
} else {
|
||||
RenderTile[5]();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nTileXPos = - (bx & 15);
|
||||
pTile = pBurnDraw + (nTileYPos * nBurnPitch) - ((bx & 15) * nBurnBpp);
|
||||
|
||||
ry = (((ry & 8) << 1) + (ry & 7)) << 1;
|
||||
|
||||
for (x = 0; x <= mx; x++) {
|
||||
nTileColumn = (((bx >> 4) + x) & 0x1F) << 2;
|
||||
nTileNumber = *((UINT16*)(pTileRAM + 0x0000 + nTileRow + nTileColumn)) << 16;
|
||||
if ((nTileNumber >> 30) != nPriority) {
|
||||
nTileXPos += 16;
|
||||
pTile += (nBurnBpp << 4);
|
||||
continue;
|
||||
}
|
||||
nTileNumber |= *((UINT16*)(pTileRAM + 0x0002 + nTileRow + nTileColumn));
|
||||
pTilePalette = pPalette + ((nTileNumber & nPaletteMask) >> nPaletteShift);
|
||||
nTileNumber &= nTileMask[nLayer];
|
||||
|
||||
count++;
|
||||
|
||||
if (((UINT32*)CaveTileAttrib[nLayer])[nTileNumber] == 0x01010101) {
|
||||
nTileXPos += 16;
|
||||
pTile += (nBurnBpp << 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
pTileStart = (UINT32*)(CaveTileROM[nLayer] + (nTileNumber << 8));
|
||||
pTileStart += ry;
|
||||
|
||||
pTileData = pTileStart;
|
||||
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8) {
|
||||
RenderTile[4]();
|
||||
} else {
|
||||
RenderTile[5]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
pTile += (nBurnBpp << 3);
|
||||
|
||||
pTileData = pTileStart + 16;
|
||||
if (nTileXPos >= 0 && nTileXPos <= nClipX8) {
|
||||
RenderTile[4]();
|
||||
} else {
|
||||
RenderTile[5]();
|
||||
}
|
||||
nTileXPos += 8;
|
||||
pTile += (nBurnBpp << 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= nCaveYSize * (mx + 1)) {
|
||||
CaveTileMax[0] -= 0x0123;
|
||||
CaveTileMax[1] -= 0x0123;
|
||||
CaveTileMax[2] -= 0x0123;
|
||||
CaveTileMax[3] -= 0x0123;
|
||||
}
|
||||
CaveTileCount[nLayer] = count;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave16x16Layer(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
if (CaveTileReg[nLayer][1] & 0x4000) { // Row-select mode
|
||||
Cave16x16Layer_RowSelect(nLayer, nPriority);
|
||||
// bprintf(PRINT_NORMAL, " Layer %d row-select mode enabled (16x16)\n", nLayer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode
|
||||
Cave16x16Layer_RowScroll(nLayer, nPriority);
|
||||
// bprintf(PRINT_NORMAL, " Layer %d row-scroll mode enabled (16x16)\n", nLayer);
|
||||
return;
|
||||
}
|
||||
|
||||
Cave16x16Layer_Normal(nLayer, nPriority);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Cave8x8Layer(INT32 nLayer, UINT32 nPriority)
|
||||
{
|
||||
#if 0
|
||||
if (CaveTileReg[nLayer][1] & 0x4000) { // Row-select mode
|
||||
Cave8x8Layer_RowSelect(nLayer, nPriority);
|
||||
// bprintf(PRINT_NORMAL, " Layer %d row-select mode enabled ( 8x 8)\n", nLayer);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (CaveTileReg[nLayer][1] & 0x4000) {
|
||||
// bprintf(PRINT_ERROR, " Layer %d row-select mode enabled ( 8x 8, UNSUPPORTED!)\n", nLayer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CaveTileReg[nLayer][0] & 0x4000) { // Row-scroll mode
|
||||
Cave8x8Layer_RowScroll(nLayer, nPriority);
|
||||
// bprintf(PRINT_NORMAL, " Layer %d row-scroll mode enabled ( 8x 8)\n", nLayer);
|
||||
return;
|
||||
}
|
||||
|
||||
Cave8x8Layer_Normal(nLayer, nPriority);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
INT32 CaveTileRender(INT32 nMode)
|
||||
{
|
||||
UINT32 nPriority;
|
||||
INT32 nLowPriority;
|
||||
INT32 nLayer;
|
||||
INT32 nOffset = 0;
|
||||
|
||||
CaveTileCount[0] = CaveTileCount[1] = CaveTileCount[2] = CaveTileCount[3] = 0;
|
||||
CaveTileMax[0] = CaveTileMax[1] = CaveTileMax[2] = CaveTileMax[3] = 0;
|
||||
|
||||
nLayerYOffset = 0x12 - nCaveYOffset - nCaveExtraYOffset;
|
||||
|
||||
for (nLayer = 0; nLayer < 4; nLayer++) {
|
||||
|
||||
nLayerXOffset[nLayer] = nLayer + nOffset - nCaveXOffset - nCaveExtraXOffset;
|
||||
|
||||
if ((CaveTileReg[nLayer][2] & 0x0010) == 0) {
|
||||
|
||||
for (nPriority = 0; nPriority < 4; nPriority++) {
|
||||
CaveTileQueue[nLayer][nPriority] = &CaveTileQueueMemory[nLayer][nPriority * 1536];
|
||||
}
|
||||
if (nBurnLayer & (8 >> nLayer)) {
|
||||
if (CaveTileReg[nLayer][1] & 0x2000) {
|
||||
if (nMode && ((CaveTileReg[nLayer][0] | CaveTileReg[nLayer][1]) & 0x4000)) {
|
||||
CaveTileMax[0] += 0x0123;
|
||||
CaveTileMax[1] += 0x0123;
|
||||
CaveTileMax[2] += 0x0123;
|
||||
CaveTileMax[3] += 0x0123;
|
||||
} else {
|
||||
CaveQueue16x16Layer_Normal(nLayer);
|
||||
}
|
||||
} else {
|
||||
if (nMode && (CaveTileReg[nLayer][0] & 0x4000)) {
|
||||
CaveTileMax[0] += 0x0123;
|
||||
CaveTileMax[1] += 0x0123;
|
||||
CaveTileMax[2] += 0x0123;
|
||||
CaveTileMax[3] += 0x0123;
|
||||
} else {
|
||||
CaveQueue8x8Layer_Normal(nLayer);
|
||||
}
|
||||
|
||||
// nOffset += 8;
|
||||
}
|
||||
}
|
||||
|
||||
for (nPriority = 0; nPriority < 4; nPriority++) {
|
||||
CaveTileQueue[nLayer][nPriority]->x = 9999;
|
||||
CaveTileQueue[nLayer][nPriority] = &CaveTileQueueMemory[nLayer][nPriority * 1536];
|
||||
if (CaveTileQueue[nLayer][nPriority]->x < 9999) {
|
||||
CaveTileMax[nPriority] += 0x123;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nLowPriority = 0;
|
||||
|
||||
for (nPriority = 0; nPriority < 4; nPriority++) {
|
||||
|
||||
if (CaveTileMax[nPriority] || nPriority == 3) {
|
||||
CaveSpriteRender(nLowPriority, nPriority);
|
||||
nLowPriority = nPriority + 1;
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < 4; i++) {
|
||||
for (nLayer = 0; nLayer < 4; nLayer++) {
|
||||
if ((CaveTileReg[nLayer][2] & 0x0003) == i) {
|
||||
if ((CaveTileReg[nLayer][2] & 0x0010) || (nBurnLayer & (8 >> nLayer)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CaveTileReg[nLayer][1] & 0x2000) {
|
||||
if (nMode) {
|
||||
Cave16x16Layer(nLayer, nPriority);
|
||||
} else {
|
||||
Cave16x16Layer_Normal(nLayer, nPriority);
|
||||
}
|
||||
} else {
|
||||
if (nMode) {
|
||||
Cave8x8Layer(nLayer, nPriority);
|
||||
} else {
|
||||
Cave8x8Layer_Normal(nLayer, nPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CaveTileExit()
|
||||
{
|
||||
for (INT32 nLayer = 0; nLayer < 4; nLayer++) {
|
||||
if (CaveTileAttrib[nLayer]) {
|
||||
free(CaveTileAttrib[nLayer]);
|
||||
CaveTileAttrib[nLayer] = NULL;
|
||||
}
|
||||
|
||||
if (CaveTileQueueMemory[nLayer]) {
|
||||
free(CaveTileQueueMemory[nLayer]);
|
||||
CaveTileQueueMemory[nLayer] = NULL;
|
||||
}
|
||||
|
||||
if (pRowScroll[nLayer]) {
|
||||
free(pRowScroll[nLayer]);
|
||||
pRowScroll[nLayer] = NULL;
|
||||
}
|
||||
|
||||
if (pRowSelect[nLayer]) {
|
||||
free(pRowSelect[nLayer]);
|
||||
pRowSelect[nLayer] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nCaveXOffset = nCaveYOffset = 0;
|
||||
nCaveRowModeOffset = 0;
|
||||
nCaveExtraXOffset = nCaveExtraYOffset = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
INT32 CaveTileInit()
|
||||
{
|
||||
for (INT32 nLayer = 0; nLayer < 4; nLayer++) {
|
||||
CaveTileReg[nLayer][0] = 0x0000;
|
||||
CaveTileReg[nLayer][1] = 0x0000;
|
||||
CaveTileReg[nLayer][2] = 0x0010; // Disable layer
|
||||
}
|
||||
|
||||
nCaveTileBank = 0;
|
||||
|
||||
BurnDrvGetFullSize(&nCaveXSize, &nCaveYSize);
|
||||
|
||||
nClipX8 = nCaveXSize - 8;
|
||||
nClipX16 = nCaveXSize - 16;
|
||||
nClipY8 = nCaveYSize - 8;
|
||||
nClipY16 = nCaveYSize - 16;
|
||||
|
||||
RenderTile = RenderTile_ROT0[(nCaveXSize == 320) ? 0 : 1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 CaveTileInitLayer(INT32 nLayer, INT32 nROMSize, INT32 nBitdepth, INT32 nOffset)
|
||||
{
|
||||
INT32 nTileSize = (8 << 3);
|
||||
INT32 nNumTiles = nROMSize / nTileSize;
|
||||
|
||||
for (nTileMask[nLayer] = 1; nTileMask[nLayer] < nNumTiles; nTileMask[nLayer] <<= 1) { }
|
||||
nTileMask[nLayer]--;
|
||||
|
||||
if (CaveTileAttrib[nLayer]) {
|
||||
free(CaveTileAttrib[nLayer]);
|
||||
}
|
||||
CaveTileAttrib[nLayer] = (INT8*)malloc(nTileMask[nLayer] + 1);
|
||||
if (CaveTileAttrib[nLayer] == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < nNumTiles; i++) {
|
||||
bool bTransparent = true;
|
||||
for (INT32 j = i * nTileSize; j < (i + 1) * nTileSize; j++) {
|
||||
if (CaveTileROM[nLayer][j]) {
|
||||
bTransparent = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bTransparent) {
|
||||
CaveTileAttrib[nLayer][i] = 1;
|
||||
} else {
|
||||
CaveTileAttrib[nLayer][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (INT32 i = nNumTiles; i <= nTileMask[nLayer]; i++) {
|
||||
CaveTileAttrib[nLayer][i] = 1;
|
||||
}
|
||||
|
||||
if (CaveTileQueueMemory[nLayer]) {
|
||||
free(CaveTileQueueMemory[nLayer]);
|
||||
}
|
||||
CaveTileQueueMemory[nLayer] = (CaveTile*)malloc(4 * 1536 * sizeof(CaveTile));
|
||||
if (CaveTileQueueMemory[nLayer] == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pRowScroll[nLayer]) {
|
||||
free(pRowScroll[nLayer]);
|
||||
}
|
||||
pRowScroll[nLayer] = (INT32*)malloc(nCaveYSize * sizeof(INT32));
|
||||
if (pRowScroll[nLayer] == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pRowSelect[nLayer]) {
|
||||
free(pRowSelect[nLayer]);
|
||||
}
|
||||
pRowSelect[nLayer] = (INT32*)malloc(nCaveYSize * sizeof(INT32));
|
||||
if (pRowSelect[nLayer] == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
nPaletteSize[nLayer] = nBitdepth;
|
||||
nPaletteOffset[nLayer] = nOffset;
|
||||
|
||||
CaveTileReg[nLayer][2] = 0x0000; // Enable layer
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,370 @@
|
|||
// Graphics format: 8 × 8 pixel tiles, 4/8 bits/pixel.
|
||||
|
||||
// Create a unique name for each of the functions
|
||||
#define FN(a,b,c,d,e,f,g,h) RenderTile ## a ## _ ## b ## _ROT ## c ## d ## e ## f ## g ## h
|
||||
#define FUNCTIONNAME(a,b,c,d,e,f,g,h) FN(a,b,c,d,e,f,g,h)
|
||||
|
||||
#if ROT == 0
|
||||
|
||||
#if XFLIP == 0
|
||||
#define ADVANCECOLUMN pPixel += (BPP >> 3)
|
||||
#else
|
||||
#error illegal XFLIP value
|
||||
#endif
|
||||
|
||||
#if YFLIP == 0
|
||||
#define ADVANCEROW pTileRow += ((BPP >> 3) * XSIZE)
|
||||
#else
|
||||
#error illegal YFLIP value
|
||||
#endif
|
||||
|
||||
#else
|
||||
#error unsupported rotation angle specified
|
||||
#endif
|
||||
|
||||
#if DOCLIP == 0
|
||||
#define CLIP _NOCLIP
|
||||
#elif DOCLIP == 1
|
||||
#define CLIP _CLIP
|
||||
#else
|
||||
#error illegal doclip value.
|
||||
#endif
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
#define DEPTH _16
|
||||
#elif EIGHTBIT == 1
|
||||
#define DEPTH _256
|
||||
#else
|
||||
#error illegal eightbit value
|
||||
#endif
|
||||
|
||||
#define TESTCOLOUR(x) x
|
||||
|
||||
#if BPP == 16
|
||||
#define PLOTPIXEL(a) if (TESTCOLOUR(a)) { \
|
||||
*((UINT16*)pPixel) = (UINT16)pTilePalette[a]; \
|
||||
}
|
||||
#elif BPP == 24
|
||||
#define PLOTPIXEL(a) if (TESTCOLOUR(a)) { \
|
||||
UINT32 nRGB = pTilePalette[a]; \
|
||||
pPixel[0] = (UINT8)nRGB; \
|
||||
pPixel[1] = (UINT8)(nRGB >> 8); \
|
||||
pPixel[2] = (UINT8)(nRGB >> 16); \
|
||||
}
|
||||
#elif BPP == 32
|
||||
#define PLOTPIXEL(a) if (TESTCOLOUR(a)) { \
|
||||
*((UINT32*)pPixel) = (UINT32)pTilePalette[a]; \
|
||||
}
|
||||
#else
|
||||
#error unsupported bitdepth specified.
|
||||
#endif
|
||||
|
||||
// For decorating the function name
|
||||
#if XFLIP == 1
|
||||
#if YFLIP == 1
|
||||
#define FLIP _FLIPXY
|
||||
#else
|
||||
#define FLIP _FLIPX
|
||||
#endif
|
||||
#elif YFLIP == 1
|
||||
#define FLIP _FLIPY
|
||||
#else
|
||||
#define FLIP _NOFLIP
|
||||
#endif
|
||||
|
||||
#if ROWSELECT == 0
|
||||
#define SELECT _NOROWSELECT
|
||||
#elif ROWSELECT == 1
|
||||
#define SELECT _ROWSELECT
|
||||
#else
|
||||
#error unsupported rowselect mode specified.
|
||||
#endif
|
||||
|
||||
#if ROWSCROLL == 0
|
||||
#define SCROLL _NOROWSCROLL
|
||||
#elif ROWSCROLL == 1
|
||||
#define SCROLL _ROWSCROLL
|
||||
#else
|
||||
#error unsupported rowscroll mode specified.
|
||||
#endif
|
||||
|
||||
static void FUNCTIONNAME(BPP,XSIZE,ROT,FLIP,SCROLL,SELECT,CLIP,DEPTH)()
|
||||
{
|
||||
// Create an empty function if unsupported features are requested
|
||||
#if ROT == 0 && XFLIP == 0 && YFLIP == 0 && !(ROWSCROLL == 1 && ROWSELECT == 1) && EIGHTBIT == 1
|
||||
|
||||
UINT8 *pTileRow, *pPixel;
|
||||
INT32 nColour;
|
||||
|
||||
#if ROWSELECT == 0
|
||||
INT32 y;
|
||||
#endif
|
||||
|
||||
#if ROWSELECT == 0
|
||||
for (y = 0, pTileRow = pTile; y < 8; y++, ADVANCEROW) {
|
||||
|
||||
#if DOCLIP == 1
|
||||
if (nTileYPos + y < 0) {
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
pTileData++;
|
||||
#else
|
||||
pTileData += 2;
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nTileYPos + y >= nCaveYSize) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
pTileRow = pTile;
|
||||
#endif
|
||||
|
||||
pPixel = pTileRow;
|
||||
|
||||
#if ROWSCROLL == 1
|
||||
nRowOffset = (nTileXPos - pTileRowInfo[y]) & 0x01FF;
|
||||
if (nRowOffset >= 0x01F8) {
|
||||
nRowOffset -= 0x0200;
|
||||
}
|
||||
if (nRowOffset >= XSIZE) {
|
||||
#if EIGHTBIT == 0
|
||||
pTileData++;
|
||||
#else
|
||||
pTileData += 2;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
pPixel += (BPP >> 3) * nRowOffset;
|
||||
#endif
|
||||
|
||||
#if ROWSCROLL == 1
|
||||
#define XPOS nRowOffset
|
||||
#else
|
||||
#define XPOS nTileXPos
|
||||
#endif
|
||||
|
||||
#if EIGHTBIT == 0
|
||||
#if DOCLIP == 1 || ROWSCROLL == 1
|
||||
nColour = *pTileData++;
|
||||
|
||||
if (XPOS <= (XSIZE - 8)) {
|
||||
if (XPOS < 0) {
|
||||
nColour >>= -XPOS * 4;
|
||||
pPixel += -XPOS * (BPP >> 3);
|
||||
}
|
||||
|
||||
switch (XPOS < 0 ? -XPOS : 0) {
|
||||
case 0:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 1:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 2:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 3:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 4:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 5:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 6:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
case 7:
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
}
|
||||
} else {
|
||||
|
||||
#define CLIPPIXEL(a,b) if (XPOS < XSIZE - (a)) { b; }
|
||||
CLIPPIXEL(0, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(1, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(2, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(3, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(4, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(5, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(6, PLOTPIXEL(nColour & 0xFF));
|
||||
#undef CLIPPIXEL
|
||||
|
||||
}
|
||||
#else
|
||||
nColour = *pTileData++;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 4;
|
||||
PLOTPIXEL(nColour & 0x0F);
|
||||
#endif
|
||||
#else
|
||||
#if DOCLIP == 1 || ROWSCROLL == 1
|
||||
nColour = pTileData[0];
|
||||
|
||||
if (XPOS <= (XSIZE - 8)) {
|
||||
if (XPOS < 0) {
|
||||
if (XPOS < -3) {
|
||||
nColour = pTileData[1];
|
||||
}
|
||||
nColour >>= (-XPOS & 3) * 8;
|
||||
pPixel += -XPOS * (BPP >> 3);
|
||||
}
|
||||
|
||||
switch (XPOS < 0 ? -XPOS : 0) {
|
||||
case 0:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
case 1:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
case 2:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
case 3:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour = pTileData[1];
|
||||
case 4:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
case 5:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
case 6:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
case 7:
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
}
|
||||
} else {
|
||||
|
||||
#define CLIPPIXEL(a,b) if (XPOS < XSIZE - (a)) { b; }
|
||||
CLIPPIXEL(0, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(1, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(2, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(3, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour = pTileData[1];
|
||||
CLIPPIXEL(4, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(5, PLOTPIXEL(nColour & 0xFF));
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
CLIPPIXEL(6, PLOTPIXEL(nColour & 0xFF));
|
||||
#undef CLIPPIXEL
|
||||
|
||||
}
|
||||
|
||||
pTileData += 2;
|
||||
|
||||
#else
|
||||
nColour = *pTileData++;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
|
||||
nColour >>= 8;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
|
||||
nColour = *pTileData++;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
|
||||
nColour >>= 8;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
ADVANCECOLUMN;
|
||||
nColour >>= 8;
|
||||
PLOTPIXEL(nColour & 0xFF);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef XPOS
|
||||
|
||||
#if ROWSELECT == 0
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef FLIP
|
||||
#undef CLIP
|
||||
#undef PLOTPIXEL
|
||||
#undef TESTCLIP
|
||||
#undef TESTCOLOUR
|
||||
#undef ADVANCEROW
|
||||
#undef ADVANCECOLUMN
|
||||
#undef SCROLL
|
||||
#undef SELECT
|
||||
#undef DEPTH
|
||||
#undef FUNCTIONNAME
|
||||
#undef FN
|
||||
|
|
@ -0,0 +1,676 @@
|
|||
// DoDonpachi
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT32 nSpeedhack;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static struct BurnInputInfo ddonpachInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(ddonpach)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall ddonpachReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300002:
|
||||
case 0x300003: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x800000:
|
||||
case 0x800001: {
|
||||
UINT8 nRet = 6 | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800002:
|
||||
case 0x800003:
|
||||
case 0x800004:
|
||||
case 0x800005:
|
||||
case 0x800006:
|
||||
case 0x800007: {
|
||||
UINT8 nRet = 6 | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00000:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0xD00001:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0xD00002:
|
||||
return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3);
|
||||
case 0xD00003:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall ddonpachReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300002: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x800000: {
|
||||
UINT16 nRet = 6 | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x800002:
|
||||
case 0x800004:
|
||||
case 0x800006: {
|
||||
UINT16 nRet = 6 | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xD00002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall ddonpachWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
return;
|
||||
case 0x300003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
return;
|
||||
|
||||
case 0xE00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
return;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall ddonpachWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
YMZ280BSelectRegister(wordValue);
|
||||
return;
|
||||
case 0x300002:
|
||||
YMZ280BWriteRegister(wordValue);
|
||||
return;
|
||||
|
||||
case 0x800000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x800002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x800008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x900000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
return;
|
||||
case 0x900002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
return;
|
||||
case 0x900004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
return;
|
||||
|
||||
case 0xA00000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
return;
|
||||
case 0xA00002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
return;
|
||||
case 0xA00004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
return;
|
||||
|
||||
case 0xB00000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
return;
|
||||
case 0xB00002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
return;
|
||||
case 0xB00004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
return;
|
||||
|
||||
case 0xE00000:
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
return;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall ddonpachWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xFFFF, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall ddonpachWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xFFFF, wordValue);
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
YMZ280BExit();
|
||||
|
||||
EEPROMExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate8Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x7F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
INT32 nCurrentPC = SekGetPC(-1) - nSpeedhack;
|
||||
|
||||
if (!nIRQPending && nCurrentPC >= 0 && nCurrentPC <= 12) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// bprintf(PRINT_NORMAL, "\n");
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
// Make sure the buffer is entirely filled.
|
||||
{
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x1000000;
|
||||
CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x200000; // Tile layer 2
|
||||
YMZ280BROM = Next; Next += 0x400000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveTileRAM[2] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x200000, 3, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x400000, 4, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x600000, 5, 1);
|
||||
BurnByteswap(CaveSpriteROM, 0x800000);
|
||||
NibbleSwap2(CaveSpriteROM, 0x800000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0], 6, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x200000);
|
||||
BurnLoadRom(CaveTileROM[1], 7, 1);
|
||||
NibbleSwap2(CaveTileROM[1], 0x200000);
|
||||
|
||||
UINT8* pTemp = (UINT8*)malloc(0x200000);
|
||||
BurnLoadRom(pTemp, 8, 1);
|
||||
for (INT32 i = 0; i < 0x0100000; i++) {
|
||||
CaveTileROM[2][(i << 1) + 1] = (pTemp[(i << 1) + 0] & 15) | ((pTemp[(i << 1) + 1] & 15) << 4);
|
||||
CaveTileROM[2][(i << 1) + 0] = (pTemp[(i << 1) + 0] >> 4) | (pTemp[(i << 1) + 1] & 240);
|
||||
}
|
||||
if (pTemp) {
|
||||
free(pTemp);
|
||||
pTemp = NULL;
|
||||
}
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM + 0x000000, 9, 1);
|
||||
BurnLoadRom(YMZ280BROM + 0x200000, 10, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0x00,0x0C,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2] + 0x4000, 0x700000, 0x703FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2] + 0x4000, 0x704000, 0x707FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2] + 0x4000, 0x708000, 0x70BFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2] + 0x4000, 0x70C000, 0x70FFFF, SM_RAM);
|
||||
|
||||
SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler)
|
||||
SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); //
|
||||
|
||||
SekSetReadWordHandler(0, ddonpachReadWord);
|
||||
SekSetReadByteHandler(0, ddonpachReadByte);
|
||||
SekSetWriteWordHandler(0, ddonpachWriteWord);
|
||||
SekSetWriteByteHandler(0, ddonpachWriteByte);
|
||||
|
||||
SekSetWriteWordHandler(1, ddonpachWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, ddonpachWriteBytePalette);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 1;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(0, 0x1000000);
|
||||
CaveTileInitLayer(0, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(2, 0x200000, 8, 0x4000);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
// US version: 0x0571AC - 0x0571B8
|
||||
// Japan version: 0x056DF4 - 0x056E00
|
||||
|
||||
nSpeedhack = (strcmp(BurnDrvGetTextA(DRV_NAME), "ddonpach") == 0) ? 0x0571AC : 0x056DF4;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo ddonpachRomDesc[] = {
|
||||
{ "b1.u27", 0x080000, 0xB5CDC8D3, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "b2.u26", 0x080000, 0x6BBB063A, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "u50.bin", 0x200000, 0x14B260EC, BRF_GRA }, // 2 Sprite data
|
||||
{ "u51.bin", 0x200000, 0xE7BA8CCE, BRF_GRA }, // 3
|
||||
{ "u52.bin", 0x200000, 0x02492EE0, BRF_GRA }, // 4
|
||||
{ "u53.bin", 0x200000, 0xCB4C10F0, BRF_GRA }, // 5
|
||||
|
||||
{ "u60.bin", 0x200000, 0x903096A7, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "u61.bin", 0x200000, 0xD89B7631, BRF_GRA }, // 7 Layer 1 Tile data
|
||||
{ "u62.bin", 0x200000, 0x292BFB6B, BRF_GRA }, // 8 Layer 2 Tile data
|
||||
|
||||
{ "u6.bin", 0x200000, 0x9DFDAFAF, BRF_SND }, // 9 YMZ280B (AD)PCM data
|
||||
{ "u7.bin", 0x200000, 0x795B17D5, BRF_SND }, // 10
|
||||
|
||||
{ "eeprom-ddonpach.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(ddonpach)
|
||||
STD_ROM_FN(ddonpach)
|
||||
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo ddonpachjRomDesc[] = {
|
||||
{ "u27.bin", 0x080000, 0x2432FF9B, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "u26.bin", 0x080000, 0x4F3A914A, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "u50.bin", 0x200000, 0x14B260EC, BRF_GRA }, // 2 Sprite data
|
||||
{ "u51.bin", 0x200000, 0xE7BA8CCE, BRF_GRA }, // 3
|
||||
{ "u52.bin", 0x200000, 0x02492EE0, BRF_GRA }, // 4
|
||||
{ "u53.bin", 0x200000, 0xCB4C10F0, BRF_GRA }, // 5
|
||||
|
||||
{ "u60.bin", 0x200000, 0x903096A7, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "u61.bin", 0x200000, 0xD89B7631, BRF_GRA }, // 7 Layer 1 Tile data
|
||||
{ "u62.bin", 0x200000, 0x292BFB6B, BRF_GRA }, // 8 Layer 2 Tile data
|
||||
|
||||
{ "u6.bin", 0x200000, 0x9DFDAFAF, BRF_SND }, // 9 YMZ280B (AD)PCM data
|
||||
{ "u7.bin", 0x200000, 0x795B17D5, BRF_SND }, // 10
|
||||
|
||||
{ "eeprom-ddonpach.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(ddonpachj)
|
||||
STD_ROM_FN(ddonpachj)
|
||||
|
||||
|
||||
struct BurnDriver BurnDrvDoDonpachi = {
|
||||
"ddonpach", NULL, NULL, NULL, "1997",
|
||||
"DoDonPachi (International, master ver. 97/02/05)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u6012\u9996\u9818\u8702 DoDonPachi (International, master ver. 97/02/05)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, ddonpachRomInfo, ddonpachRomName, NULL, NULL, ddonpachInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvDoDonpachiJ = {
|
||||
"ddonpachj", "ddonpach", NULL, NULL, "1997",
|
||||
"DoDonPachi (Japan, master ver. 97/02/05)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u6012\u9996\u9818\u8702 DoDonPachi (Japan, master ver. 97/02/05)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, ddonpachjRomInfo, ddonpachjRomName, NULL, NULL, ddonpachInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,783 @@
|
|||
// Donpachi
|
||||
#include "cave.h"
|
||||
#include "msm6295.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT32 nBankSize[2] = {0x200000, 0x300000};
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static struct BurnInputInfo donpachiInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(donpachi)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall donpachiReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
|
||||
case 0x900000:
|
||||
case 0x900001:
|
||||
case 0x900002:
|
||||
case 0x900003: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x900004:
|
||||
case 0x900005: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x900006:
|
||||
case 0x900007: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xB00001:
|
||||
return MSM6295ReadStatus(0);
|
||||
case 0xB00011:
|
||||
return MSM6295ReadStatus(1);
|
||||
|
||||
case 0xC00000:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0xC00001:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0xC00002:
|
||||
return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3);
|
||||
case 0xC00003:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall donpachiReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x900000:
|
||||
case 0x900002: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x900004: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x900006: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xB00000:
|
||||
return MSM6295ReadStatus(0);
|
||||
case 0xB00010:
|
||||
return MSM6295ReadStatus(1);
|
||||
|
||||
case 0xC00000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xC00002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall donpachiWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
|
||||
case 0xB00000:
|
||||
case 0xB00001:
|
||||
case 0xB00002:
|
||||
case 0xB00003:
|
||||
MSM6295Command(0, byteValue);
|
||||
break;
|
||||
case 0xB00010:
|
||||
case 0xB00011:
|
||||
case 0xB00012:
|
||||
case 0xB00013:
|
||||
MSM6295Command(1, byteValue);
|
||||
break;
|
||||
|
||||
case 0xB00020:
|
||||
case 0xB00021:
|
||||
case 0xB00022:
|
||||
case 0xB00023:
|
||||
case 0xB00024:
|
||||
case 0xB00025:
|
||||
case 0xB00026:
|
||||
case 0xB00027:
|
||||
case 0xB00028:
|
||||
case 0xB00029:
|
||||
case 0xB0002A:
|
||||
case 0xB0002B:
|
||||
case 0xB0002C:
|
||||
case 0xB0002D:
|
||||
case 0xB0002E:
|
||||
case 0xB0002F: {
|
||||
INT32 nBank = (sekAddress >> 1) & 3;
|
||||
INT32 nChip = (sekAddress >> 3) & 1;
|
||||
INT32 nAddress = byteValue << 16;
|
||||
while (nAddress > nBankSize[nChip]) {
|
||||
nAddress -= nBankSize[nChip];
|
||||
}
|
||||
|
||||
if (nChip == 1) {
|
||||
MSM6295SampleData[1][nBank] = MSM6295ROM + nAddress;
|
||||
MSM6295SampleInfo[1][nBank] = MSM6295ROM + nAddress + (nBank << 8);
|
||||
} else {
|
||||
MSM6295SampleData[0][nBank] = MSM6295ROM + 0x100000 + nAddress;
|
||||
if (nBank == 0) {
|
||||
MSM6295SampleInfo[0][0] = MSM6295ROM + 0x100000 + nAddress + 0x0000;
|
||||
MSM6295SampleInfo[0][1] = MSM6295ROM + 0x100000 + nAddress + 0x0100;
|
||||
MSM6295SampleInfo[0][2] = MSM6295ROM + 0x100000 + nAddress + 0x0200;
|
||||
MSM6295SampleInfo[0][3] = MSM6295ROM + 0x100000 + nAddress + 0x0300;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xD00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall donpachiWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x600000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0x600002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0x600004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x700000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x700002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x700004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x800000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
break;
|
||||
case 0x800002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
break;
|
||||
case 0x800004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x900000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x900002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x900008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0xB00000:
|
||||
case 0xB00002:
|
||||
MSM6295Command(0, wordValue);
|
||||
break;
|
||||
case 0xB00010:
|
||||
case 0xB00012:
|
||||
MSM6295Command(1, wordValue);
|
||||
break;
|
||||
|
||||
case 0xB00020:
|
||||
case 0xB00021:
|
||||
case 0xB00022:
|
||||
case 0xB00023:
|
||||
case 0xB00024:
|
||||
case 0xB00025:
|
||||
case 0xB00026:
|
||||
case 0xB00027:
|
||||
case 0xB00028:
|
||||
case 0xB00029:
|
||||
case 0xB0002A:
|
||||
case 0xB0002B:
|
||||
case 0xB0002C:
|
||||
case 0xB0002D:
|
||||
case 0xB0002E:
|
||||
case 0xB0002F: {
|
||||
INT32 nBank = (sekAddress >> 1) & 3;
|
||||
INT32 nChip = (sekAddress >> 3) & 1;
|
||||
INT32 nAddress = wordValue << 16;
|
||||
while (nAddress > nBankSize[nChip]) {
|
||||
nAddress -= nBankSize[nChip];
|
||||
}
|
||||
|
||||
if (nChip == 1) {
|
||||
MSM6295SampleData[1][nBank] = MSM6295ROM + nAddress;
|
||||
MSM6295SampleInfo[1][nBank] = MSM6295ROM + nAddress + (nBank << 8);
|
||||
} else {
|
||||
MSM6295SampleData[0][nBank] = MSM6295ROM + 0x100000 + nAddress;
|
||||
if (nBank == 0) {
|
||||
MSM6295SampleInfo[0][0] = MSM6295ROM + 0x100000 + nAddress + 0x0000;
|
||||
MSM6295SampleInfo[0][1] = MSM6295ROM + 0x100000 + nAddress + 0x0100;
|
||||
MSM6295SampleInfo[0][2] = MSM6295ROM + 0x100000 + nAddress + 0x0200;
|
||||
MSM6295SampleInfo[0][3] = MSM6295ROM + 0x100000 + nAddress + 0x0300;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xD00000:
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
EEPROMExit();
|
||||
|
||||
MSM6295Exit(1);
|
||||
MSM6295Exit(0);
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
MSM6295Reset(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate4Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x7F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
INT32 nCurrentPC = SekGetPC(-1);
|
||||
|
||||
// All versions are the same
|
||||
if (!nIRQPending && nCurrentPC >= 0x002ED6 && nCurrentPC <= 0x002EE2) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
INT32 nCyclesTotal[2];
|
||||
INT32 nCyclesDone[2];
|
||||
|
||||
INT32 nCyclesSegment;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nCurrentCPU = 0;
|
||||
INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// Run 68000
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the buffer is entirely filled.
|
||||
{
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(1, pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x080000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x800000;
|
||||
CaveTileROM[0] = Next; Next += 0x200000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x200000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x080000; // Tile layer 2
|
||||
MSM6295ROM = Next; Next += 0x300000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveTileRAM[2] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x001000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01, 0, 1);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 1, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x200000, 2, 1);
|
||||
BurnByteswap(CaveSpriteROM, 0x400000);
|
||||
NibbleSwap2(CaveSpriteROM, 0x400000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0], 3, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x100000);
|
||||
BurnLoadRom(CaveTileROM[1], 4, 1);
|
||||
NibbleSwap2(CaveTileROM[1], 0x100000);
|
||||
BurnLoadRom(CaveTileROM[2], 5, 1);
|
||||
NibbleSwap2(CaveTileROM[2], 0x040000);
|
||||
|
||||
// Load MSM6295 ADPCM data
|
||||
BurnLoadRom(MSM6295ROM, 6, 1);
|
||||
BurnLoadRom(MSM6295ROM + 0x100000, 7, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
MSM6295Scan(0, nAction);
|
||||
MSM6295Scan(1, nAction);
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0x00,0x0C,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x200000, 0x207FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x300000, 0x307FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2] + 0x4000, 0x400000, 0x403FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2] + 0x4000, 0x404000, 0x407FFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x500000, 0x50FFFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0xA08000, 0xA08FFF, SM_RAM); // Palette RAM
|
||||
|
||||
SekSetReadWordHandler(0, donpachiReadWord);
|
||||
SekSetReadByteHandler(0, donpachiReadByte);
|
||||
SekSetWriteWordHandler(0, donpachiWriteWord);
|
||||
SekSetWriteByteHandler(0, donpachiWriteByte);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(0, 0x0800000);
|
||||
CaveTileInitLayer(0, 0x200000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x200000, 8, 0x4000);
|
||||
CaveTileInitLayer(2, 0x080000, 8, 0x4000);
|
||||
|
||||
MSM6295Init(0, 8000, 50.0, 0);
|
||||
MSM6295Init(1, 16000, 50.0, 0);
|
||||
|
||||
MSM6295SampleData[0][0] = MSM6295ROM + 0x100000;
|
||||
MSM6295SampleInfo[0][0] = MSM6295ROM + 0x100000 + 0x0000;
|
||||
MSM6295SampleData[0][1] = MSM6295ROM + 0x100000;
|
||||
MSM6295SampleInfo[0][1] = MSM6295ROM + 0x100000 + 0x0100;
|
||||
MSM6295SampleData[0][2] = MSM6295ROM + 0x100000;
|
||||
MSM6295SampleInfo[0][2] = MSM6295ROM + 0x100000 + 0x0200;
|
||||
MSM6295SampleData[0][3] = MSM6295ROM + 0x100000;
|
||||
MSM6295SampleInfo[0][3] = MSM6295ROM + 0x100000 + 0x0300;
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo donpachiRomDesc[] = {
|
||||
{ "prgu.u29", 0x080000, 0x89C36802, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data
|
||||
{ "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2
|
||||
|
||||
{ "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
{ "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data
|
||||
{ "text.u58", 0x040000, 0x5DBA06E7, BRF_GRA }, // 5 Layer 2 Tile data
|
||||
|
||||
{ "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data
|
||||
{ "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data
|
||||
|
||||
{ "eeprom-donpachi.u10", 0x0080, 0x315fb546, BRF_OPT },
|
||||
|
||||
{ "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(donpachi)
|
||||
STD_ROM_FN(donpachi)
|
||||
|
||||
static struct BurnRomInfo donpachijRomDesc[] = {
|
||||
{ "prg.u29", 0x080000, 0x6BE14AF6, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data
|
||||
{ "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2
|
||||
|
||||
{ "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
{ "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data
|
||||
{ "u58.bin", 0x040000, 0x285379FF, BRF_GRA }, // 5 Layer 2 Tile data
|
||||
|
||||
{ "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data
|
||||
{ "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data
|
||||
|
||||
{ "eeprom-donpachi.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
|
||||
{ "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(donpachij)
|
||||
STD_ROM_FN(donpachij)
|
||||
|
||||
static struct BurnRomInfo donpachikrRomDesc[] = {
|
||||
{ "prgk.u26", 0x080000, 0xBBAF4C8B, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data
|
||||
{ "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2
|
||||
|
||||
{ "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
{ "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data
|
||||
{ "u58.bin", 0x040000, 0x285379FF, BRF_GRA }, // 5 Layer 2 Tile data
|
||||
|
||||
{ "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data
|
||||
{ "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data
|
||||
|
||||
{ "eeprom-donpachi.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
|
||||
{ "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(donpachikr)
|
||||
STD_ROM_FN(donpachikr)
|
||||
|
||||
static struct BurnRomInfo donpachihkRomDesc[] = {
|
||||
{ "37.u29", 0x080000, 0x71f39f30, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "atdp.u44", 0x200000, 0x7189E953, BRF_GRA }, // 1 Sprite data
|
||||
{ "atdp.u45", 0x200000, 0x6984173F, BRF_GRA }, // 2
|
||||
|
||||
{ "atdp.u54", 0x100000, 0x6BDA6B66, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
{ "atdp.u57", 0x100000, 0x0A0E72B9, BRF_GRA }, // 4 Layer 1 Tile data
|
||||
{ "u58.bin", 0x040000, 0x285379ff, BRF_GRA }, // 5 Layer 2 Tile data
|
||||
|
||||
{ "atdp.u32", 0x100000, 0x0D89FCCA, BRF_SND }, // 6 MSM6295 #1 ADPCM data
|
||||
{ "atdp.u33", 0x200000, 0xD749DE00, BRF_SND }, // 7 MSM6295 #0/1 ADPCM data
|
||||
|
||||
{ "eeprom-donpachi.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
|
||||
{ "peel18cv8p-15.u18", 0x0155, 0x3f4787e9, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(donpachihk)
|
||||
STD_ROM_FN(donpachihk)
|
||||
|
||||
|
||||
struct BurnDriver BurnDrvDonpachi = {
|
||||
"donpachi", NULL, NULL, NULL, "1995",
|
||||
"DonPachi (USA, ver. 1.12, 95/05/2x)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u9996\u9818\u8702 DonPachi (USA, ver. 1.12, 95/05/2x)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0,
|
||||
NULL, donpachiRomInfo, donpachiRomName, NULL, NULL, donpachiInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvDonpachij = {
|
||||
"donpachij", "donpachi", NULL, NULL, "1995",
|
||||
"DonPachi (Japan, ver. 1.01, 95/05/11)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u9996\u9818\u8702 DonPachi (Japan, ver. 1.01, 95/05/11)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0,
|
||||
NULL, donpachijRomInfo, donpachijRomName, NULL, NULL, donpachiInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvDonpachikr = {
|
||||
"donpachikr", "donpachi", NULL, NULL, "1995",
|
||||
"DonPachi (Korea, ver. 1.12, 95/05/2x)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u9996\u9818\u8702 DonPachi (Korea, ver. 1.12, 95/05/2x)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0,
|
||||
NULL, donpachikrRomInfo, donpachikrRomName, NULL, NULL, donpachiInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvDonpachihk = {
|
||||
"donpachihk", "donpachi", NULL, NULL, "1995",
|
||||
"DonPachi (Hong Kong, ver. 1.10, 95/05/17)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u9996\u9818\u8702 DonPachi (Hong Kong, ver. 1.10, 95/05/17)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_VERSHOOT, 0,
|
||||
NULL, donpachihkRomInfo, donpachihkRomName, NULL, NULL, donpachiInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
|
@ -0,0 +1,723 @@
|
|||
// E.S.P. Ra De
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT32 nSpeedhack;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static struct BurnInputInfo espradeInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(esprade)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall espradeReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300003: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x800000:
|
||||
case 0x800001:
|
||||
case 0x800002:
|
||||
case 0x800003: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x800004:
|
||||
case 0x800005: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800006:
|
||||
case 0x800007: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00000:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0xD00001:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0xD00002:
|
||||
return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3);
|
||||
case 0xD00003:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall espradeReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300002: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x800000:
|
||||
case 0x800002: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x800004: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800006: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xD00002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall espradeWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
break;
|
||||
case 0x300003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
break;
|
||||
|
||||
case 0xE00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall espradeWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
YMZ280BSelectRegister(wordValue);
|
||||
break;
|
||||
case 0x300002:
|
||||
YMZ280BWriteRegister(wordValue);
|
||||
break;
|
||||
|
||||
case 0x800000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x800002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x800008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x900000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x900002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x900004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xA00000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0xA00002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0xA00004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xB00000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
break;
|
||||
case 0xB00002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
break;
|
||||
case 0xB00004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xE00000:
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall espradeWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xFFFF, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall espradeWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xFFFF, wordValue);
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
YMZ280BExit();
|
||||
|
||||
EEPROMExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate8Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x0000]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
INT32 nCurrentPC = SekGetPC(-1) - nSpeedhack;
|
||||
|
||||
if (!nIRQPending && nCurrentPC >= 0 && nCurrentPC <= 12) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure the buffer is entirely filled.
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x1000000;
|
||||
CaveTileROM[0] = Next; Next += 0x800000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x800000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2
|
||||
YMZ280BROM = Next; Next += 0x400000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveTileRAM[2] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap3(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[0] = (n1 << 4) | (n2 & 0x0F);
|
||||
pData[1] = (n1 & 0xF0) | (n2 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap4(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[1] = (n2 << 4) | (n1 & 0x0F);
|
||||
pData[0] = (n2 & 0xF0) | (n1 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 2, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x000001, 3, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x800000, 4, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x800001, 5, 2);
|
||||
NibbleSwap3(CaveSpriteROM, 0x800000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x000000, 6, 1);
|
||||
BurnLoadRom(CaveTileROM[0] + 0x400000, 7, 1);
|
||||
NibbleSwap4(CaveTileROM[0], 0x400000);
|
||||
BurnLoadRom(CaveTileROM[1] + 0x000000, 8, 1);
|
||||
BurnLoadRom(CaveTileROM[1] + 0x400000, 9, 1);
|
||||
NibbleSwap4(CaveTileROM[1], 0x400000);
|
||||
BurnLoadRom(CaveTileROM[2] + 0x000000, 10, 1);
|
||||
NibbleSwap4(CaveTileROM[2], 0x200000);
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM, 11, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0x00,0x0C,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2], 0x700000, 0x707FFF, SM_RAM);
|
||||
|
||||
SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler)
|
||||
SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); //
|
||||
|
||||
SekSetReadWordHandler(0, espradeReadWord);
|
||||
SekSetReadByteHandler(0, espradeReadByte);
|
||||
SekSetWriteWordHandler(0, espradeWriteWord);
|
||||
SekSetWriteByteHandler(0, espradeWriteByte);
|
||||
|
||||
SekSetWriteWordHandler(1, espradeWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, espradeWriteBytePalette);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(1, 0x1000000);
|
||||
CaveTileInitLayer(0, 0x800000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x800000, 8, 0x4000);
|
||||
CaveTileInitLayer(2, 0x400000, 8, 0x4000);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
// 4/22 version: 0x04F37C - 0x04F388
|
||||
// 4/21 version: 0x04F150 - 0x04F15C
|
||||
// 4/14 version: 0x04F152 - 0x04F15E
|
||||
|
||||
if (strcmp(BurnDrvGetTextA(DRV_NAME), "esprade") == 0) {
|
||||
nSpeedhack = 0x04F37C;
|
||||
} else {
|
||||
if (strcmp(BurnDrvGetTextA(DRV_NAME), "espradej") == 0) {
|
||||
nSpeedhack = 0x04F152;
|
||||
} else {
|
||||
nSpeedhack = 0x04F150;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo espradeRomDesc[] = {
|
||||
{ "u42.int", 0x080000, 0x3B510A73, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "u41.int", 0x080000, 0x97C1B649, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "esp_u63.u63", 0x400000, 0x2F2FE92C, BRF_GRA }, // 2 Sprite data
|
||||
{ "esp_u64.u64", 0x400000, 0x491A3DA4, BRF_GRA }, // 3
|
||||
{ "esp_u65.u65", 0x400000, 0x06563EFE, BRF_GRA }, // 4
|
||||
{ "esp_u66.u66", 0x400000, 0x7BBE4CFC, BRF_GRA }, // 5
|
||||
|
||||
{ "esp_u54.u54", 0x400000, 0xE7CA6936, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "esp_u55.u55", 0x400000, 0xF53BD94F, BRF_GRA }, // 7
|
||||
{ "esp_u52.u52", 0x400000, 0xE7ABE7B4, BRF_GRA }, // 8 Layer 1 Tile data
|
||||
{ "esp_u53.u53", 0x400000, 0x51A0F391, BRF_GRA }, // 9
|
||||
{ "esp_u51.u51", 0x400000, 0x0B9B875C, BRF_GRA }, // 10 Layer 2 Tile data
|
||||
|
||||
{ "esp_u19.u19", 0x400000, 0xF54B1CAB, BRF_SND }, // 11 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-esprade.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(esprade)
|
||||
STD_ROM_FN(esprade)
|
||||
|
||||
static struct BurnRomInfo espradejRomDesc[] = {
|
||||
{ "u42_ver.2", 0x080000, 0x75D03C42, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "u41_ver.2", 0x080000, 0x734B3EF0, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "esp_u63.u63", 0x400000, 0x2F2FE92C, BRF_GRA }, // 2 Sprite data
|
||||
{ "esp_u64.u64", 0x400000, 0x491A3DA4, BRF_GRA }, // 3
|
||||
{ "esp_u65.u65", 0x400000, 0x06563EFE, BRF_GRA }, // 4
|
||||
{ "esp_u66.u66", 0x400000, 0x7BBE4CFC, BRF_GRA }, // 5
|
||||
|
||||
{ "esp_u54.u54", 0x400000, 0xE7CA6936, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "esp_u55.u55", 0x400000, 0xF53BD94F, BRF_GRA }, // 7
|
||||
{ "esp_u52.u52", 0x400000, 0xE7ABE7B4, BRF_GRA }, // 8 Layer 1 Tile data
|
||||
{ "esp_u53.u53", 0x400000, 0x51A0F391, BRF_GRA }, // 9
|
||||
{ "esp_u51.u51", 0x400000, 0x0B9B875C, BRF_GRA }, // 10 Layer 2 Tile data
|
||||
|
||||
{ "esp_u19.u19", 0x400000, 0xF54B1CAB, BRF_SND }, // 11 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-esprade.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(espradej)
|
||||
STD_ROM_FN(espradej)
|
||||
|
||||
static struct BurnRomInfo espradejoRomDesc[] = {
|
||||
{ "u42.bin", 0x080000, 0x0718C7E5, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "u41.bin", 0x080000, 0xDEF30539, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "esp_u63.u63", 0x400000, 0x2F2FE92C, BRF_GRA }, // 2 Sprite data
|
||||
{ "esp_u64.u64", 0x400000, 0x491A3DA4, BRF_GRA }, // 3
|
||||
{ "esp_u65.u65", 0x400000, 0x06563EFE, BRF_GRA }, // 4
|
||||
{ "esp_u66.u66", 0x400000, 0x7BBE4CFC, BRF_GRA }, // 5
|
||||
|
||||
{ "esp_u54.u54", 0x400000, 0xE7CA6936, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "esp_u55.u55", 0x400000, 0xF53BD94F, BRF_GRA }, // 7
|
||||
{ "esp_u52.u52", 0x400000, 0xE7ABE7B4, BRF_GRA }, // 8 Layer 1 Tile data
|
||||
{ "esp_u53.u53", 0x400000, 0x51A0F391, BRF_GRA }, // 9
|
||||
{ "esp_u51.u51", 0x400000, 0x0B9B875C, BRF_GRA }, // 10 Layer 2 Tile data
|
||||
|
||||
{ "esp_u19.u19", 0x400000, 0xF54B1CAB, BRF_SND }, // 11 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-esprade.bin", 0x0080, 0x315fb546, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(espradejo)
|
||||
STD_ROM_FN(espradejo)
|
||||
|
||||
struct BurnDriver BurnDrvEsprade = {
|
||||
"esprade", NULL, NULL, NULL, "1998",
|
||||
"ESP Ra.De. - A.D.2018 Tokyo (International, ver. 98/04/22)\0", NULL, "Atlus / Cave", "Cave",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, espradeRomInfo, espradeRomName, NULL, NULL, espradeInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvEspradej = {
|
||||
"espradej", "esprade", NULL, NULL, "1998",
|
||||
"ESP Ra.De. (Japan, ver. 98/04/21)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"ESP Ra.De. \u30A8\u30B9\u30D7\u30EC\u30A4\u30C9 (Japan, ver. 98/04/21)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, espradejRomInfo, espradejRomName, NULL, NULL, espradeInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvEspradejo = {
|
||||
"espradejo", "esprade", NULL, NULL, "1998",
|
||||
"ESP Ra.De. (Japan, ver. 98/04/14)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"ESP Ra.De. \u30A8\u30B9\u30D7\u30EC\u30A4\u30C9 (Japan, ver. 98/04/14)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, espradejoRomInfo, espradejoRomName, NULL, NULL, espradeInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
|
@ -0,0 +1,645 @@
|
|||
// Fever SOS / Dangun Feveron
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01, *Ram02;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT32 nSpeedhack;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static struct BurnInputInfo feversosInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(feversos)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall feversosReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300003: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x800000:
|
||||
case 0x800001:
|
||||
case 0x800002:
|
||||
case 0x800003: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x800004:
|
||||
case 0x800005: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800006:
|
||||
case 0x800007: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xB00000:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0xB00001:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0xB00002:
|
||||
return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3);
|
||||
case 0xB00003:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall feversosReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300002: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x800000:
|
||||
case 0x800002: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x800004: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800006: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xB00000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xB00002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall feversosWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
break;
|
||||
case 0x300003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
break;
|
||||
|
||||
case 0xC00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall feversosWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
YMZ280BSelectRegister(wordValue);
|
||||
break;
|
||||
case 0x300002:
|
||||
YMZ280BWriteRegister(wordValue);
|
||||
break;
|
||||
|
||||
case 0x800000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x800002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x800008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x900000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x900002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x900004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xA00000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0xA00002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0xA00004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xC00000:
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
EEPROMExit();
|
||||
|
||||
YMZ280BExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate4Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x3F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
#if 0 && defined USE_SPEEDHACKS
|
||||
UINT32 nCurrentPC = SekGetPC(-1);
|
||||
|
||||
if (!nIRQPending && nCurrentPC >= nSpeedhack && nCurrentPC <= nSpeedhack + 0x18) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure the buffer is entirely filled.
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x1000000;
|
||||
CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1
|
||||
YMZ280BROM = Next; Next += 0x400000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
Ram02 = Next; Next += 0x001000;
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x001000; // palette
|
||||
// CaveVideoRegisters= Next; Next += 0x000080;
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x400000, 3, 1);
|
||||
NibbleSwap1(CaveSpriteROM, 0x800000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0], 4, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x200000);
|
||||
BurnLoadRom(CaveTileROM[1], 5, 1);
|
||||
NibbleSwap2(CaveTileROM[1], 0x200000);
|
||||
|
||||
BurnLoadRom(YMZ280BROM, 6, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0x00,0x0C,0x11,0x0D,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x11,0x11,0xFF,0xFF,0xFF,0xFF};
|
||||
static const UINT8 default_eeprom_feversos[18] = {0x00,0x0C,0x16,0x27,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x11,0x11,0xFF,0xFF,0xFF,0xFF,0x05,0x19}; /* Fever SOS (code checks for the 0x0519 or it won't boot) */
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
|
||||
if (!strcmp(BurnDrvGetTextA(DRV_NAME), "dfeveron")) {
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
}
|
||||
if (!strcmp(BurnDrvGetTextA(DRV_NAME), "feversos")) {
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom_feversos,0, sizeof(default_eeprom_feversos));
|
||||
}
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0x708000, 0x708FFF, SM_RAM); // Palette RAM
|
||||
SekMapMemory(Ram02, 0x710000, 0x710BFF, SM_ROM);
|
||||
SekMapMemory(Ram02, 0x710C00, 0x710FFF, SM_RAM);
|
||||
|
||||
SekSetReadWordHandler(0, feversosReadWord);
|
||||
SekSetReadByteHandler(0, feversosReadByte);
|
||||
SekSetWriteWordHandler(0, feversosWriteWord);
|
||||
SekSetWriteByteHandler(0, feversosWriteByte);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 1;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(1, 0x1000000);
|
||||
CaveTileInitLayer(0, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x400000, 8, 0x4000);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
// Fever SOS: 0x07766C - 0x077684
|
||||
// Dangun Feveron: 0x0772F2 - 0x07730A
|
||||
|
||||
nSpeedhack = (strcmp(BurnDrvGetTextA(DRV_NAME), "feversos") == 0) ? 0x07766C : 0x0772F2;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo feversosRomDesc[] = {
|
||||
{ "cv01-u34.sos", 0x080000, 0x24EF3CE6, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "cv01-u33.sos", 0x080000, 0x64FF73FD, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "cv01-u25.bin", 0x400000, 0xA6F6A95D, BRF_GRA }, // 2 Sprite data
|
||||
{ "cv01-u26.bin", 0x400000, 0x32EDB62A, BRF_GRA }, // 3
|
||||
|
||||
{ "cv01-u50.bin", 0x200000, 0x7A344417, BRF_GRA }, // 4 Layer 0 Tile data
|
||||
{ "cv01-u49.bin", 0x200000, 0xD21CDDA7, BRF_GRA }, // 5 Layer 1 Tile data
|
||||
|
||||
{ "cv01-u19.bin", 0x400000, 0x5F5514DA, BRF_SND }, // 6 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-feversos.bin", 0x0080, 0xd80303aa, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(feversos)
|
||||
STD_ROM_FN(feversos)
|
||||
|
||||
static struct BurnRomInfo dfeveronRomDesc[] = {
|
||||
{ "cv01-u34.bin", 0x080000, 0xBE87F19D, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "cv01-u33.bin", 0x080000, 0xE53A7DB3, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "cv01-u25.bin", 0x400000, 0xA6F6A95D, BRF_GRA }, // 2 Sprite data
|
||||
{ "cv01-u26.bin", 0x400000, 0x32EDB62A, BRF_GRA }, // 3
|
||||
|
||||
{ "cv01-u50.bin", 0x200000, 0x7A344417, BRF_GRA }, // 4 Layer 0 Tile data
|
||||
{ "cv01-u49.bin", 0x200000, 0xD21CDDA7, BRF_GRA }, // 5 Layer 1 Tile data
|
||||
|
||||
{ "cv01-u19.bin", 0x400000, 0x5F5514DA, BRF_SND }, // 6 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-dfeveron.bin", 0x0080, 0xc3174959, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(dfeveron)
|
||||
STD_ROM_FN(dfeveron)
|
||||
|
||||
struct BurnDriver BurnDrvFeverSOS = {
|
||||
"feversos", NULL, NULL, NULL, "1998",
|
||||
"Fever SOS (International, ver. 98/09/25)\0", NULL, "Cave / Nihon System inc.", "Cave",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, feversosRomInfo, feversosRomName, NULL, NULL, feversosInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvDFeveron = {
|
||||
"dfeveron", "feversos", NULL, NULL, "1998",
|
||||
"Dangun Feveron (Japan, ver. 98/09/17)\0", NULL, "Cave / Nihon System inc.", "Cave",
|
||||
L"\u5F3E\u9283 Feveron \u3060\u3093\u304C\u3093\u30D5\u30A3\u30FC\u30D0\u30ED\u30F3 (Japan, ver. 98/09/17)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, dfeveronRomInfo, dfeveronRomName, NULL, NULL, feversosInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
|
@ -0,0 +1,887 @@
|
|||
// Gaia Crusaders
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[16] = {0, };
|
||||
static UINT8 DrvJoy2[16] = {0, };
|
||||
static UINT16 DrvInput[3] = {0, };
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static INT8 nVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static struct BurnInputInfo gaiaInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy2 + 4, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
{"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 4"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 5, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy1 + 8, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy1 + 9, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy1 + 10, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy1 + 11, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 12, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 3"},
|
||||
{"P2 Button 4", BIT_DIGITAL, DrvJoy1 + 15, "p2 fire 4"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy2 + 2, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 3, "service"},
|
||||
|
||||
{"DIP A", BIT_DIPSWITCH, (UINT8*)(DrvInput + 2) + 0, "dip"},
|
||||
{"DIP B", BIT_DIPSWITCH, (UINT8*)(DrvInput + 2) + 1, "dip"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(gaia)
|
||||
|
||||
static struct BurnDIPInfo gaiaDIPList[] = {
|
||||
// Defaults
|
||||
{0x17, 0xFF, 0xFF, 0x04, NULL},
|
||||
{0x18, 0xFF, 0xFF, 0x00, NULL},
|
||||
|
||||
// DIP 1
|
||||
{0, 0xFE, 0, 2, "V reverse"},
|
||||
{0x17, 0x01, 0x01, 0x00, "Off"},
|
||||
{0x17, 0x01, 0x01, 0x01, "On"},
|
||||
{0, 0xFE, 0, 2, "Demo sound"},
|
||||
{0x17, 0x01, 0x02, 0x02, "Off"},
|
||||
{0x17, 0x01, 0x02, 0x00, "On"},
|
||||
{0, 0xFE, 0, 2, "Language"},
|
||||
{0x17, 0x01, 0x04, 0x00, "Japanese"},
|
||||
{0x17, 0x01, 0x04, 0x04, "English"},
|
||||
{0, 0xFE, 0, 9, "Coin"},
|
||||
{0x17, 0x01, 0x78, 0x00, "1 coin 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x08, "1 coin 2 credits"},
|
||||
{0x17, 0x01, 0x78, 0x10, "1 coin 3 credits"},
|
||||
{0x17, 0x01, 0x78, 0x18, "2 coins 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x20, "2 coins 3 credits"},
|
||||
{0x17, 0x01, 0x78, 0x28, "3 coins 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x30, "4 coins 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x38, "2 coins 1 credit 1 continue"},
|
||||
{0x17, 0x01, 0x78, 0x40, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x48, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x50, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x58, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x60, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x68, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x70, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x78, "Free play"},
|
||||
{0, 0xFE, 0, 2, "Continue"},
|
||||
{0x17, 0x01, 0x80, 0x80, "Off"},
|
||||
{0x17, 0x01, 0x80, 0x00, "On"},
|
||||
|
||||
// DIP 2
|
||||
{0, 0xFE, 0, 8, "Level"},
|
||||
{0x18, 0x01, 0xE0, 0x20, "Very easy"},
|
||||
{0x18, 0x01, 0xE0, 0x40, "Easy"},
|
||||
{0x18, 0x01, 0xE0, 0x00, "Medium"},
|
||||
{0x18, 0x01, 0xE0, 0x80, "Medium hard"},
|
||||
{0x18, 0x01, 0xE0, 0x60, "Hard 1"},
|
||||
{0x18, 0x01, 0xE0, 0xC0, "Hard 2"},
|
||||
{0x18, 0x01, 0xE0, 0xA0, "Very hard"},
|
||||
{0x18, 0x01, 0xE0, 0xE0, "Hardest"},
|
||||
|
||||
// Extend condition
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0x00, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/350,000"},
|
||||
{0x18, 0x00, 0xE0, 0x00, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0x20, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/300,000"},
|
||||
{0x18, 0x00, 0xE0, 0x20, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0x40, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/350,000"},
|
||||
{0x18, 0x00, 0xE0, 0x40, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0x60, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/400,000"},
|
||||
{0x18, 0x00, 0xE0, 0x60, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0x80, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/400,000"},
|
||||
{0x18, 0x00, 0xE0, 0x80, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0xA0, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "200,000/500,000"},
|
||||
{0x18, 0x00, 0xE0, 0xA0, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0xC0, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/400,000"},
|
||||
{0x18, 0x00, 0xE0, 0xC0, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xE0, 0xE0, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "200,000/500,000"},
|
||||
{0x18, 0x00, 0xE0, 0xE0, NULL},
|
||||
|
||||
{0, 0xFE, 0, 4, "Life"},
|
||||
{0x18, 0x01, 0x03, 0x02, "1 player"},
|
||||
{0x18, 0x01, 0x03, 0x03, "2 players"},
|
||||
{0x18, 0x01, 0x03, 0x00, "3 players"},
|
||||
{0x18, 0x01, 0x03, 0x01, "4 players"},
|
||||
{0, 0xFE, 0, 4, "Damage"},
|
||||
{0x18, 0x01, 0x18, 0x00, "+0"},
|
||||
{0x18, 0x01, 0x18, 0x08, "+1"},
|
||||
{0x18, 0x01, 0x18, 0x10, "+2"},
|
||||
{0x18, 0x01, 0x18, 0x18, "+3"},
|
||||
};
|
||||
|
||||
STDDIPINFO(gaia)
|
||||
|
||||
static struct BurnDIPInfo theroesDIPList[] = {
|
||||
// Defaults
|
||||
{0x17, 0xFF, 0xFF, 0x04, NULL},
|
||||
{0x18, 0xFF, 0xFF, 0x00, NULL},
|
||||
|
||||
// DIP 1
|
||||
{0, 0xFE, 0, 2, "V reverse"},
|
||||
{0x17, 0x01, 0x01, 0x00, "Off"},
|
||||
{0x17, 0x01, 0x01, 0x01, "On"},
|
||||
{0, 0xFE, 0, 2, "Demo sound"},
|
||||
{0x17, 0x01, 0x02, 0x02, "Off"},
|
||||
{0x17, 0x01, 0x02, 0x00, "On"},
|
||||
{0, 0xFE, 0, 2, "Language"},
|
||||
{0x17, 0x01, 0x04, 0x00, "Chinese"},
|
||||
{0x17, 0x01, 0x04, 0x04, "English"},
|
||||
{0, 0xFE, 0, 9, "Coin"},
|
||||
{0x17, 0x01, 0x78, 0x00, "1 coin 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x08, "1 coin 2 credits"},
|
||||
{0x17, 0x01, 0x78, 0x10, "1 coin 3 credits"},
|
||||
{0x17, 0x01, 0x78, 0x18, "2 coins 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x20, "2 coins 3 credits"},
|
||||
{0x17, 0x01, 0x78, 0x28, "3 coins 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x30, "4 coins 1 credit"},
|
||||
{0x17, 0x01, 0x78, 0x38, "2 coins 1 credit 1 continue"},
|
||||
{0x17, 0x01, 0x78, 0x40, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x48, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x50, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x58, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x60, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x68, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x70, "Free play"},
|
||||
{0x17, 0x01, 0x78, 0x78, "Free play"},
|
||||
{0, 0xFE, 0, 2, "Continue"},
|
||||
{0x17, 0x01, 0x80, 0x80, "Off"},
|
||||
{0x17, 0x01, 0x80, 0x00, "On"},
|
||||
|
||||
// DIP 2
|
||||
{0, 0xFE, 0, 4, "Level"},
|
||||
{0x18, 0x01, 0xC0, 0x40, "Very easy"},
|
||||
{0x18, 0x01, 0xC0, 0x00, "Medium"},
|
||||
{0x18, 0x01, 0xC0, 0x80, "Medium hard"},
|
||||
{0x18, 0x01, 0xC0, 0xC0, "Hardest"},
|
||||
|
||||
// Extend condition
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xC0, 0x00, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/350,000"},
|
||||
{0x18, 0x00, 0xC0, 0x00, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xC0, 0x40, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/300,000"},
|
||||
{0x18, 0x00, 0xC0, 0x40, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xC0, 0x80, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "150,000/400,000"},
|
||||
{0x18, 0x00, 0xC0, 0x80, NULL},
|
||||
{0, 0xFE, 0, 2, "Extend"},
|
||||
{0x18, 0x02, 0x04, 0x04, "Nothing"},
|
||||
{0x18, 0x00, 0xC0, 0xC0, NULL},
|
||||
{0x18, 0x02, 0x04, 0x00, "200,000/500,000"},
|
||||
{0x18, 0x00, 0xC0, 0xC0, NULL},
|
||||
|
||||
{0, 0xFE, 0, 4, "Life"},
|
||||
{0x18, 0x01, 0x03, 0x02, "1 player"},
|
||||
{0x18, 0x01, 0x03, 0x03, "2 players"},
|
||||
{0x18, 0x01, 0x03, 0x00, "3 players"},
|
||||
{0x18, 0x01, 0x03, 0x01, "4 players"},
|
||||
{0, 0xFE, 0, 4, "Damage"},
|
||||
{0x18, 0x01, 0x18, 0x00, "+0"},
|
||||
{0x18, 0x01, 0x18, 0x08, "+1"},
|
||||
{0x18, 0x01, 0x18, 0x10, "+2"},
|
||||
{0x18, 0x01, 0x18, 0x18, "+3"},
|
||||
};
|
||||
|
||||
STDDIPINFO(theroes)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall gaiaReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300003: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
#if 0
|
||||
case 0x800000:
|
||||
case 0x800001: {
|
||||
UINT16 nRet = ((nVBlank ^ 1) << 2) | (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
#else
|
||||
case 0x800000:
|
||||
case 0x800001:
|
||||
#endif
|
||||
case 0x800002:
|
||||
case 0x800003: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x800004:
|
||||
case 0x800005: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800006:
|
||||
case 0x800007: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00010:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0xD00011:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0xD00012:
|
||||
return (DrvInput[1] >> 8) ^ 0xFF;
|
||||
case 0xD00013:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
case 0xD00014:
|
||||
return (DrvInput[2] >> 8) ^ 0xFF;
|
||||
case 0xD00015:
|
||||
return (DrvInput[2] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall gaiaReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300002: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
#if 0
|
||||
case 0x800000: {
|
||||
UINT16 nRet = ((nVBlank ^ 1) << 2) | (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
#else
|
||||
case 0x800000:
|
||||
#endif
|
||||
case 0x800002: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x800004: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x800006: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00010:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xD00012:
|
||||
return DrvInput[1] ^ 0xFFFF;
|
||||
case 0xD00014:
|
||||
return DrvInput[2] ^ 0xFFFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall gaiaWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
break;
|
||||
case 0x300003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall gaiaWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
YMZ280BSelectRegister(wordValue);
|
||||
break;
|
||||
case 0x300002:
|
||||
YMZ280BWriteRegister(wordValue);
|
||||
break;
|
||||
|
||||
case 0x800000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x800002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x800008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x900000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x900002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x900004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xA00000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0xA00002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0xA00004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xB00000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
break;
|
||||
case 0xB00002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
break;
|
||||
case 0xB00004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall gaiaWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xFFFF, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall gaiaWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xFFFF, wordValue);
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
YMZ280BExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate8Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x0000]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static void gaiaClearOpposites(UINT8* nJoystickInputs)
|
||||
{
|
||||
if ((*nJoystickInputs & 0x03) == 0x03) {
|
||||
*nJoystickInputs &= ~0x03;
|
||||
}
|
||||
if ((*nJoystickInputs & 0x0C) == 0x0C) {
|
||||
*nJoystickInputs &= ~0xC;
|
||||
}
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 16; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
gaiaClearOpposites(((UINT8*)DrvInput) + 0);
|
||||
gaiaClearOpposites(((UINT8*)DrvInput) + 1);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * 58));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 265.5);
|
||||
nVBlank = 0;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!nVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
nVBlank = 1;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure the buffer is entirely filled.
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x1000000;
|
||||
CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2
|
||||
YMZ280BROM = Next; Next += 0xC00000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x010000;
|
||||
CaveTileRAM[1] = Next; Next += 0x010000;
|
||||
CaveTileRAM[2] = Next; Next += 0x010000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap4(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[1] = (n2 << 4) | (n1 & 0x0F);
|
||||
pData[0] = (n2 & 0xF0) | (n1 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 2, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x400000, 3, 1);
|
||||
NibbleSwap1(CaveSpriteROM, 0x800000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x000000, 4, 1);
|
||||
NibbleSwap4(CaveTileROM[0], 0x400000);
|
||||
BurnLoadRom(CaveTileROM[1] + 0x000000, 5, 1);
|
||||
NibbleSwap4(CaveTileROM[1], 0x400000);
|
||||
BurnLoadRom(CaveTileROM[2] + 0x000000, 6, 1);
|
||||
NibbleSwap4(CaveTileROM[2], 0x400000);
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM + 0x000000, 7, 1);
|
||||
BurnLoadRom(YMZ280BROM + 0x400000, 8, 1);
|
||||
BurnLoadRom(YMZ280BROM + 0x800000, 9, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
if (nAction & ACB_MEMORY_ROM) { // Scan all memory, devices & variables
|
||||
ba.Data = Rom01;
|
||||
ba.nLen = 0x00100000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "68K ROM";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
|
||||
if (nAction & ACB_MEMORY_RAM) { // Scan all memory, devices & variables
|
||||
ba.Data = Ram01;
|
||||
ba.nLen = 0x00010000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "68K RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
ba.Data = CaveTileRAM[0];
|
||||
ba.nLen = 0x00010000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "Tilemap 0";
|
||||
BurnAcb(&ba);
|
||||
|
||||
ba.Data = CaveTileRAM[1];
|
||||
ba.nLen = 0x00010000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "Tilemap 1";
|
||||
BurnAcb(&ba);
|
||||
|
||||
ba.Data = CaveTileRAM[2];
|
||||
ba.nLen = 0x00010000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "Tile layer 2";
|
||||
BurnAcb(&ba);
|
||||
|
||||
ba.Data = CaveSpriteRAM;
|
||||
ba.nLen = 0x00010000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "Sprite tables";
|
||||
BurnAcb(&ba);
|
||||
|
||||
ba.Data = CavePalSrc;
|
||||
ba.nLen = 0x00010000;
|
||||
ba.nAddress = 0;
|
||||
ba.szName = "Palette";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(nVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(58.0);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x500000, 0x50FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x600000, 0x60FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2], 0x700000, 0x70FFFF, SM_RAM);
|
||||
|
||||
SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler)
|
||||
SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); //
|
||||
|
||||
SekSetReadWordHandler(0, gaiaReadWord);
|
||||
SekSetReadByteHandler(0, gaiaReadByte);
|
||||
SekSetWriteWordHandler(0, gaiaWriteWord);
|
||||
SekSetWriteByteHandler(0, gaiaWriteByte);
|
||||
|
||||
SekSetWriteWordHandler(1, gaiaWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, gaiaWriteBytePalette);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 0;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(2, 0x1000000);
|
||||
CaveTileInitLayer(0, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(2, 0x400000, 8, 0x4000);
|
||||
|
||||
YMZ280BInit(16000000, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo gaiaRomDesc[] = {
|
||||
{ "prg1.127", 0x080000, 0x47B904B2, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "prg2.128", 0x080000, 0x469B7794, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "obj1.736", 0x400000, 0xF4F84E5D, BRF_GRA }, // 2 Sprite data
|
||||
{ "obj2.738", 0x400000, 0x15C2A9CE, BRF_GRA }, // 3
|
||||
|
||||
{ "bg1.989", 0x400000, 0x013A693D, BRF_GRA }, // 4 Layer 0 Tile data
|
||||
{ "bg2.995", 0x400000, 0x783CC62F, BRF_GRA }, // 5 Layer 1 Tile data
|
||||
{ "bg3.998", 0x400000, 0xbcd61d1c, BRF_GRA }, // 6 Layer 2 Tile data
|
||||
|
||||
{ "snd1.447", 0x400000, 0x92770A52, BRF_SND }, // 7 YMZ280B (AD)PCM data
|
||||
{ "snd2.454", 0x400000, 0x329AE1CF, BRF_SND }, // 8
|
||||
{ "snd3.455", 0x400000, 0x4048D64E, BRF_SND }, // 9
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(gaia)
|
||||
STD_ROM_FN(gaia)
|
||||
|
||||
struct BurnDriver BurnDrvGaia = {
|
||||
"gaia", NULL, NULL, NULL, "1999",
|
||||
"Gaia Crusaders\0", NULL, "Noise Factory", "Cave",
|
||||
L"Gaia Crusaders \u5F81\u6226\u8005\0Gaia Crusaders \u30AC\u30A4\u30A2\u30AF\u30EB\u30BB\u30A4\u30C0\u30FC\u30BA\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_SCRFIGHT, 0,
|
||||
NULL, gaiaRomInfo, gaiaRomName, NULL, NULL, gaiaInputInfo, gaiaDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 224, 4, 3
|
||||
};
|
||||
|
||||
static struct BurnRomInfo theroesRomDesc[] = {
|
||||
{ "t-hero-epm1.u0127", 0x080000, 0x09db7195, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "t-hero-epm0.u0129", 0x080000, 0x2d4e3310, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "t-hero-obj1.u0736", 0x400000, 0x35090f7c, BRF_GRA }, // 2 Sprite data
|
||||
{ "t-hero-obj2.u0738", 0x400000, 0x71605108, BRF_GRA }, // 3
|
||||
|
||||
{ "t-hero-bg1.u0999", 0x400000, 0x47b0fb40, BRF_GRA }, // 4 Layer 0 Tile data
|
||||
{ "t-hero-bg2.u0995", 0x400000, 0xb16237a1, BRF_GRA }, // 5 Layer 1 Tile data
|
||||
{ "t-hero-bg3.u0998", 0x400000, 0x08eb5604, BRF_GRA }, // 6 Layer 2 Tile data
|
||||
|
||||
{ "crvsaders-snd1.u0447", 0x400000, 0x92770A52, BRF_SND }, // 7 YMZ280B (AD)PCM data
|
||||
{ "crvsaders-snd2.u0454", 0x400000, 0x329AE1CF, BRF_SND }, // 8
|
||||
{ "t-hero-snd3.u0455", 0x400000, 0x52b0b2c0, BRF_SND }, // 9
|
||||
};
|
||||
|
||||
STD_ROM_PICK(theroes)
|
||||
STD_ROM_FN(theroes)
|
||||
|
||||
struct BurnDriver BurnDrvTheroes = {
|
||||
"theroes", NULL, NULL, NULL, "2001",
|
||||
"Thunder Heroes\0", NULL, "Primetec Investments", "Cave",
|
||||
L"\u9739\u96F3\u82F1\u96C4 Thunder Heroes\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_SCRFIGHT, 0,
|
||||
NULL, theroesRomInfo, theroesRomName, NULL, NULL, gaiaInputInfo, theroesDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 224, 4, 3
|
||||
};
|
|
@ -0,0 +1,714 @@
|
|||
// Guwange
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[16] = {0, };
|
||||
static UINT8 DrvJoy2[16] = {0, };
|
||||
static UINT16 DrvInput[2] = {0, };
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static struct BurnInputInfo guwangeInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 7, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 1, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy1 + 8, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy1 + 9, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy1 + 10, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy1 + 11, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy1 + 12, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy1 + 13, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy1 + 14, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy1 + 15, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy2 + 2, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 3, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(guwange)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall guwangeReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x800002:
|
||||
case 0x800003: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x300000:
|
||||
case 0x300001:
|
||||
case 0x300002:
|
||||
case 0x300003: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x300004:
|
||||
case 0x300005: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x300006:
|
||||
case 0x300007: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00010:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0xD00011:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0xD00012:
|
||||
return (DrvInput[1] >> 8) ^ 0xFF;
|
||||
case 0xD00013:
|
||||
return ((DrvInput[1] & 0x7F) ^ 0x7F) | (EEPROMRead() << 7);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall guwangeReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x800002: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x300000:
|
||||
case 0x300002: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x300004: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x300006: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xD00010:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xD00012:
|
||||
return (DrvInput[1] ^ 0xFF7F) | (EEPROMRead() << 7);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall guwangeWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x800000:
|
||||
case 0x800001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
break;
|
||||
case 0x800002:
|
||||
case 0x800003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
break;
|
||||
|
||||
case 0xD00011:
|
||||
EEPROMWrite(byteValue & 0x40, byteValue & 0x20, byteValue & 0x80);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall guwangeWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
|
||||
case 0x300000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x300002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x300008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x800000:
|
||||
YMZ280BSelectRegister(wordValue & 0xFF);
|
||||
break;
|
||||
case 0x800002:
|
||||
YMZ280BWriteRegister(wordValue & 0xFF);
|
||||
break;
|
||||
|
||||
case 0x900000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x900002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x900004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xA00000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0xA00002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0xA00004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xB00000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
break;
|
||||
case 0xB00002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
break;
|
||||
case 0xB00004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xD00010:
|
||||
EEPROMWrite(wordValue & 0x40, wordValue & 0x20, wordValue & 0x80);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall guwangeWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xFFFF, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall guwangeWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xFFFF, wordValue);
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
YMZ280BExit();
|
||||
|
||||
EEPROMExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate8Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x7F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static void guwangeClearOpposites(UINT8* nJoystickInputs)
|
||||
{
|
||||
if ((*nJoystickInputs & 0x06) == 0x06) {
|
||||
*nJoystickInputs &= ~0x06;
|
||||
}
|
||||
if ((*nJoystickInputs & 0x18) == 0x18) {
|
||||
*nJoystickInputs &= ~0x18;
|
||||
}
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
#if 1 && defined USE_SPEEDHACKS
|
||||
INT32 nCurrentPC = SekGetPC(-1);
|
||||
|
||||
if (!nIRQPending && nCurrentPC >= 0x06D6DE && nCurrentPC <= 0x06D6F4) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Joysticks
|
||||
DrvInput[1] = 0x0000; // Other controls
|
||||
for (INT32 i = 0; i < 16; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
guwangeClearOpposites(((UINT8*)DrvInput) + 0);
|
||||
guwangeClearOpposites(((UINT8*)DrvInput) + 1);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
// Make sure the buffer is entirely filled.
|
||||
{
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x2000000;
|
||||
CaveTileROM[0] = Next; Next += 0x800000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2
|
||||
YMZ280BROM = Next; Next += 0x400000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveTileRAM[2] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap3(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[0] = (n1 << 4) | (n2 & 0x0F);
|
||||
pData[1] = (n1 & 0xF0) | (n2 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap4(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[1] = (n2 << 4) | (n1 & 0x0F);
|
||||
pData[0] = (n2 & 0xF0) | (n1 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x0000000, 2, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x0000001, 3, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x1000000, 4, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x1000001, 5, 2);
|
||||
NibbleSwap3(CaveSpriteROM, 0xC00000);
|
||||
|
||||
#if 1
|
||||
for (INT32 i = 0; i < 0x100000; i++) {
|
||||
UINT16 nValue = rand() & 0x0101;
|
||||
if (nValue & 0x0001) {
|
||||
nValue |= 0x00FF;
|
||||
}
|
||||
if (nValue & 0x0100) {
|
||||
nValue |= 0xFF00;
|
||||
}
|
||||
((UINT16*)(CaveSpriteROM + 0x1800000))[i] = nValue;
|
||||
((UINT16*)(CaveSpriteROM + 0x1A00000))[i] = nValue;
|
||||
((UINT16*)(CaveSpriteROM + 0x1C00000))[i] = nValue;
|
||||
((UINT16*)(CaveSpriteROM + 0x1E00000))[i] = nValue;
|
||||
}
|
||||
#else
|
||||
memcpy(CaveSpriteROM + 0x1800000, CaveSpriteROM + 0x1000000, 0x800000);
|
||||
#endif
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x000000, 6, 1);
|
||||
NibbleSwap4(CaveTileROM[0], 0x400000);
|
||||
BurnLoadRom(CaveTileROM[1] + 0x000000, 7, 1);
|
||||
NibbleSwap4(CaveTileROM[1], 0x200000);
|
||||
BurnLoadRom(CaveTileROM[2] + 0x000000, 8, 1);
|
||||
NibbleSwap4(CaveTileROM[2], 0x200000);
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM, 9, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0x00,0x0C,0x11,0x0D,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x11,0x11,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x200000, 0x20FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x600000, 0x607FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2], 0x700000, 0x707FFF, SM_RAM);
|
||||
|
||||
SekMapMemory(CavePalSrc, 0xC00000, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler)
|
||||
SekMapHandler(1, 0xC00000, 0xC0FFFF, SM_WRITE); //
|
||||
|
||||
SekSetReadWordHandler(0, guwangeReadWord);
|
||||
SekSetReadByteHandler(0, guwangeReadByte);
|
||||
SekSetWriteWordHandler(0, guwangeWriteWord);
|
||||
SekSetWriteByteHandler(0, guwangeWriteByte);
|
||||
|
||||
SekSetWriteWordHandler(1, guwangeWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, guwangeWriteBytePalette);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 2;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(1, 0x2000000);
|
||||
CaveTileInitLayer(0, 0x800000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(2, 0x400000, 8, 0x4000);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo guwangeRomDesc[] = {
|
||||
{ "gu-u0127.bin", 0x080000, 0xF86B5293, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "gu-u0129.bin", 0x080000, 0x6C0E3B93, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "u083.bin", 0x800000, 0xADC4B9C4, BRF_GRA }, // 2 Sprite data
|
||||
{ "u082.bin", 0x800000, 0x3D75876C, BRF_GRA }, // 3
|
||||
{ "u086.bin", 0x400000, 0x188E4F81, BRF_GRA }, // 4
|
||||
{ "u085.bin", 0x400000, 0xA7D5659E, BRF_GRA }, // 5
|
||||
|
||||
{ "u101.bin", 0x800000, 0x0369491F, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "u10102.bin", 0x400000, 0xE28D6855, BRF_GRA }, // 7 Layer 1 Tile data
|
||||
{ "u10103.bin", 0x400000, 0x0FE91B8E, BRF_GRA }, // 8 Layer 2 Tile data
|
||||
|
||||
{ "u0462.bin", 0x400000, 0xB3D75691, BRF_SND }, // 9 YMZ280B (AD)PCM data
|
||||
|
||||
{ "atc05-1.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
{ "u0259.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
{ "u084.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
{ "u108.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
|
||||
{ "eeprom-guwange.bin", 0x0080, 0xc3174959, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(guwange)
|
||||
STD_ROM_FN(guwange)
|
||||
|
||||
|
||||
struct BurnDriver BurnDrvGuwange = {
|
||||
"guwange", NULL, NULL, NULL, "1999",
|
||||
"Guwange (Japan, master ver. 99/06/24)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u3050\u308F\u3093\u3052 (Japan, master ver. 99/06/24)\0Guwange\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, guwangeRomInfo, guwangeRomName, NULL, NULL, guwangeInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
||||
|
||||
|
||||
static struct BurnRomInfo guwangesRomDesc[] = {
|
||||
{ "gu-u0127b.bin",0x080000, 0x64667d2e, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "gu-u0129b.bin",0x080000, 0xa99C6b6c, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "u083.bin", 0x800000, 0xADC4B9C4, BRF_GRA }, // 2 Sprite data
|
||||
{ "u082.bin", 0x800000, 0x3D75876C, BRF_GRA }, // 3
|
||||
{ "u086.bin", 0x400000, 0x188E4F81, BRF_GRA }, // 4
|
||||
{ "u085.bin", 0x400000, 0xA7D5659E, BRF_GRA }, // 5
|
||||
|
||||
{ "u101.bin", 0x800000, 0x0369491F, BRF_GRA }, // 6 Layer 0 Tile data
|
||||
{ "u10102.bin", 0x400000, 0xE28D6855, BRF_GRA }, // 7 Layer 1 Tile data
|
||||
{ "u10103.bin", 0x400000, 0x0FE91B8E, BRF_GRA }, // 8 Layer 2 Tile data
|
||||
|
||||
{ "u0462.bin", 0x400000, 0xB3D75691, BRF_SND }, // 9 YMZ280B (AD)PCM data
|
||||
|
||||
{ "atc05-1.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
{ "u0259.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
{ "u084.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
{ "u108.bin", 0x000001, 0x00000000, BRF_NODUMP },
|
||||
|
||||
{ "eeprom-guwange.bin", 0x0080, 0xc3174959, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(guwanges)
|
||||
STD_ROM_FN(guwanges)
|
||||
|
||||
|
||||
struct BurnDriver BurnDrvGuwanges = {
|
||||
"guwanges", "guwange", NULL, NULL, "1999",
|
||||
"Guwange (Japan, special ver. 00/01/01)\0", NULL, "Atlus / Cave", "Cave",
|
||||
L"\u3050\u308F\u3093\u3052 (Japan, special ver. 00/01/01)\0Guwange\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_VERSHOOT, 0,
|
||||
NULL, guwangesRomInfo, guwangesRomName, NULL, NULL, guwangeInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 320, 3, 4
|
||||
};
|
|
@ -0,0 +1,757 @@
|
|||
// hotdogst
|
||||
#include "cave.h"
|
||||
#include "msm6295.h"
|
||||
#include "burn_ym2203.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01, *RomZ80;
|
||||
static UINT8 *Ram01, *RamZ80;
|
||||
static UINT8 *MSM6295ROMSrc;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesDone[2];
|
||||
|
||||
static UINT16 DrvSoundLatch;
|
||||
static UINT8 DrvZ80Bank;
|
||||
static UINT8 DrvOkiBank1;
|
||||
static UINT8 DrvOkiBank2;
|
||||
|
||||
static struct BurnInputInfo hotdogstInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(hotdogst)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall hotdogstReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0xc80002:
|
||||
return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3);
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall hotdogstWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
if (~byteValue & 0x0100) {
|
||||
case 0xd00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 __fastcall hotdogstReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0xa80000:
|
||||
case 0xa80002: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0xa80004: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0xa80006: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
// case 0xa8006e: {
|
||||
// return 0xff;
|
||||
// }
|
||||
|
||||
case 0xc80000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xC80002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall hotdogstWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0xa80000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0xa80002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
|
||||
case 0xa80008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0xa8006e: {
|
||||
DrvSoundLatch = wordValue;
|
||||
ZetNmi();
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xb00000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0xb00002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0xb00004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xb80000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0xb80002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0xb80004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xc00000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
break;
|
||||
case 0xc00002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
break;
|
||||
case 0xc00004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xd00000:
|
||||
if (~wordValue & 0x0100) {
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
}
|
||||
case 0xd00002: {
|
||||
//nop
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall hotdogstZIn(UINT16 nAddress)
|
||||
{
|
||||
nAddress &= 0xFF;
|
||||
|
||||
switch (nAddress) {
|
||||
case 0x30: {
|
||||
return DrvSoundLatch & 0xff;
|
||||
}
|
||||
|
||||
case 0x40: {
|
||||
return (DrvSoundLatch & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
case 0x50: {
|
||||
return BurnYM2203Read(0, 0);
|
||||
}
|
||||
|
||||
case 0x60: {
|
||||
return MSM6295ReadStatus(0);
|
||||
}
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall hotdogstZOut(UINT16 nAddress, UINT8 nValue)
|
||||
{
|
||||
nAddress &= 0xFF;
|
||||
|
||||
switch (nAddress) {
|
||||
case 0x00: {
|
||||
DrvZ80Bank = nValue & 0x0f;
|
||||
|
||||
ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x50: {
|
||||
BurnYM2203Write(0, 0, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x51: {
|
||||
BurnYM2203Write(0, 1, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x60: {
|
||||
MSM6295Command(0, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x70: {
|
||||
DrvOkiBank1 = (nValue >> 0) & 0x03;
|
||||
DrvOkiBank2 = (nValue >> 4) & 0x03;
|
||||
|
||||
memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall hotdogstZRead(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall hotdogstZWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
EEPROMExit();
|
||||
|
||||
MSM6295Exit(0);
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
ZetExit();
|
||||
|
||||
BurnYM2203Exit();
|
||||
|
||||
DrvSoundLatch = 0;
|
||||
DrvZ80Bank = 0;
|
||||
DrvOkiBank1 = 0;
|
||||
DrvOkiBank2 = 0;
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2203Reset();
|
||||
MSM6295Reset(0);
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
DrvSoundLatch = 0;
|
||||
DrvZ80Bank = 0;
|
||||
DrvOkiBank1 = 0;
|
||||
DrvOkiBank2 = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate4Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x3F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 80;
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
INT32 nCyclesSegment;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
ZetNewFrame();
|
||||
|
||||
SekOpen(0);
|
||||
ZetOpen(0);
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesTotal[1] = (INT32)(4000000 / CAVE_REFRESHRATE);
|
||||
nCyclesDone[0] = nCyclesDone[1] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nCurrentCPU = 0;
|
||||
INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// Run 68000
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
CaveSpriteBuffer();
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave));
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2203Update(pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
nSoundBufferPos += nSegmentLength;
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
BurnTimerEndFrame(nCyclesTotal[1]);
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
BurnYM2203Update(pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
RomZ80 = Next; Next += 0x040000;
|
||||
CaveSpriteROM = Next; Next += 0x800000;
|
||||
CaveTileROM[0] = Next; Next += 0x100000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x100000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x100000; // Tile layer 2
|
||||
MSM6295ROM = Next; Next += 0x040000;
|
||||
MSM6295ROMSrc = Next; Next += 0x080000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
RamZ80 = Next; Next += 0x002000;
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveTileRAM[2] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x001000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
|
||||
BurnLoadRom(RomZ80, 2, 1);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 3, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x200000, 4, 1);
|
||||
NibbleSwap1(CaveSpriteROM, 0x400000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0], 5, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x080000);
|
||||
BurnLoadRom(CaveTileROM[1], 6, 1);
|
||||
NibbleSwap2(CaveTileROM[1], 0x080000);
|
||||
BurnLoadRom(CaveTileROM[2], 7, 1);
|
||||
NibbleSwap2(CaveTileROM[2], 0x080000);
|
||||
|
||||
// Load MSM6295 ADPCM data
|
||||
BurnLoadRom(MSM6295ROMSrc, 8, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction);
|
||||
ZetScan(nAction);
|
||||
|
||||
BurnYM2203Scan(nAction, pnMin);
|
||||
MSM6295Scan(0, nAction);
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
SCAN_VAR(DrvSoundLatch);
|
||||
SCAN_VAR(DrvZ80Bank);
|
||||
SCAN_VAR(DrvOkiBank1);
|
||||
SCAN_VAR(DrvOkiBank2);
|
||||
}
|
||||
if (nAction & ACB_WRITE) {
|
||||
ZetOpen(0);
|
||||
ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetClose();
|
||||
|
||||
memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000);
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DrvFMIRQHandler(INT32, INT32 nStatus)
|
||||
{
|
||||
if (nStatus & 1) {
|
||||
ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK);
|
||||
} else {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvSynchroniseStream(INT32 nSoundRate)
|
||||
{
|
||||
return (INT64)ZetTotalCycles() * nSoundRate / 4000000;
|
||||
}
|
||||
|
||||
static double DrvGetTime()
|
||||
{
|
||||
return (double)ZetTotalCycles() / 4000000;
|
||||
}
|
||||
|
||||
static INT32 drvZInit()
|
||||
{
|
||||
ZetInit(1);
|
||||
|
||||
ZetOpen(0);
|
||||
|
||||
ZetSetInHandler(hotdogstZIn);
|
||||
ZetSetOutHandler(hotdogstZOut);
|
||||
ZetSetReadHandler(hotdogstZRead);
|
||||
ZetSetWriteHandler(hotdogstZWrite);
|
||||
|
||||
// ROM bank 1
|
||||
ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM
|
||||
ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM
|
||||
// ROM bank 2
|
||||
ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x4000); // Direct Read from ROM
|
||||
ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x4000); //
|
||||
// RAM
|
||||
ZetMapArea (0xE000, 0xFFFF, 0, RamZ80); // Direct Read from RAM
|
||||
ZetMapArea (0xE000, 0xFFFF, 1, RamZ80); // Direct Write to RAM
|
||||
ZetMapArea (0xE000, 0xFFFF, 2, RamZ80); //
|
||||
|
||||
ZetMemEnd();
|
||||
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0xF3,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x300000, 0x30FFFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0x408000, 0x408FFF, SM_RAM); // Palette RAM
|
||||
SekMapMemory(CaveTileRAM[0], 0x880000, 0x887FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x900000, 0x907FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[2], 0x980000, 0x987FFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0xf00000, 0xf0fFFF, SM_RAM);
|
||||
|
||||
SekSetReadByteHandler(0, hotdogstReadByte);
|
||||
SekSetWriteByteHandler(0, hotdogstWriteByte);
|
||||
SekSetReadWordHandler(0, hotdogstReadWord);
|
||||
SekSetWriteWordHandler(0, hotdogstWriteWord);
|
||||
SekClose();
|
||||
}
|
||||
|
||||
drvZInit();
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(2, 0x0800000);
|
||||
CaveTileInitLayer(0, 0x100000, 8, 0);
|
||||
CaveTileInitLayer(1, 0x100000, 8, 0);
|
||||
CaveTileInitLayer(2, 0x100000, 8, 0);
|
||||
|
||||
nCaveExtraXOffset = -32;
|
||||
nCaveExtraYOffset = 32;
|
||||
|
||||
BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0);
|
||||
BurnTimerAttachZet(4000000);
|
||||
|
||||
memcpy(MSM6295ROM, MSM6295ROMSrc, 0x40000);
|
||||
MSM6295Init(0, 1056000 / 132, 50.0, 1);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo hotdogstRomDesc[] = {
|
||||
{ "mp3.u29", 0x080000, 0x1f4e5479, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "mp4.u28", 0x080000, 0x6f1c3c4b, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "mp2.u19", 0x040000, 0xff979ebe, BRF_ESS | BRF_PRG }, // 2 Z80 Code
|
||||
|
||||
{ "mp9.u55", 0x200000, 0x258d49ec, BRF_GRA }, // 3 Sprite data
|
||||
{ "mp8.u54", 0x200000, 0xbdb4d7b8, BRF_GRA }, // 4
|
||||
|
||||
{ "mp7.u56", 0x080000, 0x87c21c50, BRF_GRA }, // 5 Layer 0 Tile data
|
||||
{ "mp6.u61", 0x080000, 0x4dafb288, BRF_GRA }, // 6 Layer 1 Tile data
|
||||
{ "mp5.u64", 0x080000, 0x9b26458c, BRF_GRA }, // 7 Layer 2 Tile data
|
||||
|
||||
{ "mp1.u65", 0x080000, 0x4868be1b, BRF_SND }, // 8 MSM6295 #1 ADPCM data
|
||||
|
||||
{ "eeprom-hotdogst.bin", 0x0080, 0x12b4f934, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(hotdogst)
|
||||
STD_ROM_FN(hotdogst)
|
||||
|
||||
struct BurnDriver BurnDrvhotdogst = {
|
||||
"hotdogst", NULL, NULL, NULL, "1996",
|
||||
"Hotdog Storm - The First Supersonics (International)\0", NULL, "Marble / ACE International", "Cave",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0,
|
||||
NULL, hotdogstRomInfo, hotdogstRomName, NULL, NULL, hotdogstInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 384, 3, 4
|
||||
};
|
|
@ -0,0 +1,734 @@
|
|||
// Koro Koro Quest & Crusher Makochan
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvDip[1];
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT32 korokoro_hopper = 0;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static const eeprom_interface eeprom_interface_93C46_8bit =
|
||||
{
|
||||
7, // address bits 7
|
||||
8, // data bits 8
|
||||
"*110", // read 1 10 aaaaaa
|
||||
"*101", // write 1 01 aaaaaa dddddddddddddddd
|
||||
"*111", // erase 1 11 aaaaaa
|
||||
"*10000xxxx", // lock 1 00 00xxxx
|
||||
"*10011xxxx", // unlock 1 00 11xxxx
|
||||
1,
|
||||
0
|
||||
};
|
||||
|
||||
static struct BurnInputInfo KorokoroInputList[] = {
|
||||
{"Coin 1", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" },
|
||||
{"Coin 2", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" },
|
||||
{"Coin 3", BIT_DIGITAL, DrvJoy1 + 2, "p3 coin" },
|
||||
{"Button 1", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 1" },
|
||||
{"Button 2", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 2" },
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
|
||||
{"Service", BIT_DIGITAL, DrvJoy1 + 14, "service" },
|
||||
{"Service", BIT_DIGITAL, DrvJoy1 + 12, "service" },
|
||||
{"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" },
|
||||
};
|
||||
|
||||
STDINPUTINFO(Korokoro)
|
||||
|
||||
static struct BurnDIPInfo KorokoroDIPList[]=
|
||||
{
|
||||
{0x08, 0xff, 0xff, 0x20, NULL },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Service Mode" },
|
||||
{0x08, 0x01, 0x20, 0x00, "On" },
|
||||
{0x08, 0x01, 0x20, 0x20, "Off" },
|
||||
};
|
||||
|
||||
STDDIPINFO(Korokoro)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
|
||||
SekSetIRQLine(2, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall korokoroReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress)
|
||||
{
|
||||
case 0x1c0000:
|
||||
case 0x1c0001:
|
||||
case 0x300000:
|
||||
case 0x300001:
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 0 : 4);
|
||||
|
||||
case 0x1c0002:
|
||||
case 0x1c0003:
|
||||
case 0x300002:
|
||||
case 0x300003:
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
|
||||
case 0x1c0004:
|
||||
case 0x1c0005:
|
||||
case 0x300004:
|
||||
case 0x300005:
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
|
||||
case 0x1c0006:
|
||||
case 0x1c0007:
|
||||
case 0x300006:
|
||||
case 0x300007:
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
|
||||
case 0x280000:
|
||||
return ((DrvInput[0] >> 8) & 0x5F) | (korokoro_hopper ? 0x00 : 0x80) | (DrvDip[0] & 0x20);
|
||||
|
||||
case 0x280001:
|
||||
return DrvInput[0] & 0xFF;
|
||||
|
||||
case 0x280002:
|
||||
return ((DrvInput[1] >> 8) & 0xEF) | (EEPROMRead() ? 0x10 : 0x00);
|
||||
|
||||
case 0x280003:
|
||||
return DrvInput[1] & 0xFF;
|
||||
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall korokoroReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x1c0000:
|
||||
case 0x300000:
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 4 : 0);
|
||||
|
||||
case 0x1c0002:
|
||||
case 0x300002:
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
|
||||
case 0x1c0004:
|
||||
case 0x300004:
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
|
||||
case 0x1c0006:
|
||||
case 0x300006:
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
|
||||
case 0x280000:
|
||||
return (DrvInput[0] & 0x5FFF) | (korokoro_hopper ? 0x0000 : 0x8000) | ((DrvDip[0] & 0x20) << 8);
|
||||
|
||||
case 0x280002:
|
||||
return (DrvInput[1] & 0xEFFF) | ((EEPROMRead() & 1) ? 0x1000 : 0x0000);
|
||||
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall korokoroWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x240001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
break;
|
||||
|
||||
case 0x240003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
break;
|
||||
|
||||
case 0x280008:
|
||||
case 0x280009:
|
||||
// leds
|
||||
break;
|
||||
|
||||
case 0x28000a:
|
||||
korokoro_hopper = byteValue & 0x01;
|
||||
EEPROMWrite(byteValue & 0x20, byteValue & 0x10, byteValue & 0x40);
|
||||
break;
|
||||
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall korokoroWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x140000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x140002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x140004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x1c0000:
|
||||
case 0x300000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
|
||||
case 0x1c0002:
|
||||
case 0x300002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
|
||||
case 0x1c0008:
|
||||
case 0x300008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x240000:
|
||||
YMZ280BSelectRegister(wordValue & 0xff);
|
||||
break;
|
||||
|
||||
case 0x240002:
|
||||
YMZ280BWriteRegister(wordValue & 0xff);
|
||||
break;
|
||||
|
||||
case 0x280008:
|
||||
return;
|
||||
|
||||
case 0x28000a: {
|
||||
wordValue >>= 8;
|
||||
korokoro_hopper = wordValue & 0x01;
|
||||
EEPROMWrite(wordValue & 0x20, wordValue & 0x10, wordValue & 0x40);
|
||||
break;
|
||||
}
|
||||
|
||||
// default:
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
}
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
YMZ280BExit();
|
||||
|
||||
EEPROMExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
BurnFree(Mem);
|
||||
Mem = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static UINT32 CalcCol(UINT16 nColour)
|
||||
{
|
||||
INT32 r, g, b;
|
||||
|
||||
r = (nColour & 0x03E0) >> 2; // Red
|
||||
r |= r >> 5;
|
||||
g = (nColour & 0x7C00) >> 7; // Green
|
||||
g |= g >> 5;
|
||||
b = (nColour & 0x001F) << 3; // Blue
|
||||
b |= b >> 5;
|
||||
|
||||
return BurnHighCol(r, g, b, 0);
|
||||
}
|
||||
|
||||
static void KorokoroPaletteUpdate()
|
||||
{
|
||||
for (INT32 color = 0; color < 0x40; color++) {
|
||||
for (INT32 pen = 0; pen < 0x10; pen++) {
|
||||
CavePalette[(color << 8) | pen] = CalcCol(*(UINT16*)(CavePalSrc + ((0x3c00 | (color << 4) | pen)*2)));
|
||||
}
|
||||
|
||||
for (INT32 pen = 0x10; pen < 0x100; pen++) {
|
||||
CavePalette[(color << 8) | pen] = CalcCol(*(UINT16*)(CavePalSrc + ((0x0000 | (color << 8) | pen)*2)));
|
||||
}
|
||||
}
|
||||
|
||||
for (INT32 color = 0; color < 0x4000; color++) {
|
||||
CavePalette[color+0x4000] = CalcCol(*(UINT16*)(CavePalSrc + color*2));
|
||||
}
|
||||
|
||||
pBurnDrvPalette = CavePalette;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
KorokoroPaletteUpdate(); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x3F00]);
|
||||
|
||||
CaveSpriteBuffer();
|
||||
|
||||
if (bDrawScreen) {
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0; // Player 1
|
||||
DrvInput[1] = 0; // Player 2
|
||||
for (INT32 i = 0; i < 16; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
DrvInput[0] ^= 0xffff;
|
||||
DrvInput[1] ^= 0xffff;
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure the buffer is entirely filled.
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
SCAN_VAR(korokoro_hopper);
|
||||
|
||||
CaveScanGraphics();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
|
||||
Rom01 = Next; Next += 0x080000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x400000;
|
||||
CaveTileROM[0] = Next; Next += 0x200000; // Tile layer 0
|
||||
YMZ280BROM = Next; Next += 0x200000;
|
||||
|
||||
RamStart = Next;
|
||||
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
|
||||
RamEnd = Next;
|
||||
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 0, 1);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x0000000, 1, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x0100000, 2, 1);
|
||||
NibbleSwap1(CaveSpriteROM + 0x0000000, 0x180000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x000000, 3, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x100000);
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM, 4, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46_8bit);
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(CaveTileRAM[0], 0x100000, 0x107FFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x180000, 0x187FFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0x200000, 0x207FFF, SM_RAM);
|
||||
SekMapMemory(Ram01, 0x300000, 0x30FFFF, SM_RAM);
|
||||
|
||||
SekSetReadWordHandler(0, korokoroReadWord);
|
||||
SekSetReadByteHandler(0, korokoroReadByte);
|
||||
SekSetWriteWordHandler(0, korokoroWriteWord);
|
||||
SekSetWriteByteHandler(0, korokoroWriteByte);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 1;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(1, 0x300000);
|
||||
CaveTileInitLayer(0, 0x200000, 4, 0x4400);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 crushermLoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 0, 1);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x0000000, 1, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x0100000, 2, 1);
|
||||
NibbleSwap1(CaveSpriteROM + 0x0000000, 0x200000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x000000, 3, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x100000);
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM + 0x000000, 4, 1);
|
||||
BurnLoadRom(YMZ280BROM + 0x100000, 5, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 crushermInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46_8bit);
|
||||
|
||||
// Load the roms into memory
|
||||
if (crushermLoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(CaveTileRAM[0], 0x100000, 0x107FFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x180000, 0x187FFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0x200000, 0x207FFF, SM_RAM);
|
||||
SekMapMemory(Ram01, 0x340000, 0x34FFFF, SM_RAM);
|
||||
|
||||
SekSetReadWordHandler(0, korokoroReadWord);
|
||||
SekSetReadByteHandler(0, korokoroReadByte);
|
||||
SekSetWriteWordHandler(0, korokoroWriteWord);
|
||||
SekSetWriteByteHandler(0, korokoroWriteByte);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 1;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(1, 0x400000);
|
||||
CaveTileInitLayer(0, 0x200000, 4, 0x4400);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Koro Koro Quest (Japan)
|
||||
|
||||
static struct BurnRomInfo korokoroRomDesc[] = {
|
||||
{ "mp-001_ver07.u0130", 0x080000, 0x86c7241f, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "mp-001_ver01.u1066", 0x100000, 0xc5c6af7e, BRF_GRA }, // 1 Sprite data
|
||||
{ "mp-001_ver01.u1051", 0x080000, 0xfe5e28e8, BRF_GRA }, // 2
|
||||
|
||||
{ "mp-001_ver01.u1060", 0x100000, 0xec9cf9d8, BRF_GRA }, // 3 layer 0 Tile data
|
||||
|
||||
{ "mp-001_ver01.u1186", 0x100000, 0xd16e7c5d, BRF_SND }, // 4 YMZ280B (AD)PCM data
|
||||
};
|
||||
|
||||
STD_ROM_PICK(korokoro)
|
||||
STD_ROM_FN(korokoro)
|
||||
|
||||
struct BurnDriver BurnDrvKorokoro = {
|
||||
"korokoro", NULL, NULL, NULL, "1999",
|
||||
"Koro Koro Quest (Japan)\0", NULL, "Takumi", "Cave",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_MISC, 0,
|
||||
NULL, korokoroRomInfo, korokoroRomName, NULL, NULL, KorokoroInputInfo, KorokoroDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 240, 4, 3
|
||||
};
|
||||
|
||||
|
||||
// Crusher Makochan (Japan)
|
||||
|
||||
static struct BurnRomInfo crushermRomDesc[] = {
|
||||
{ "mp-003ver01.u0130", 0x080000, 0xa4f56e6b, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "mp-003ver01.u1067", 0x100000, 0x268a4921, BRF_GRA }, // 1 Sprite data
|
||||
{ "mp-003ver01.u1066", 0x100000, 0x79e77a6e, BRF_GRA }, // 2
|
||||
|
||||
{ "mp-003ver01.u1060", 0x100000, 0x7661893e, BRF_GRA }, // 3 layer 0 Tile data
|
||||
|
||||
{ "mp-003ver01.u1186", 0x100000, 0xc3aeb745, BRF_SND }, // 4 YMZ280B (AD)PCM data
|
||||
{ "mp-003ver01.u1187", 0x100000, 0xd9312497, BRF_SND }, // 5
|
||||
};
|
||||
|
||||
STD_ROM_PICK(crusherm)
|
||||
STD_ROM_FN(crusherm)
|
||||
|
||||
struct BurnDriver BurnDrvCrusherm = {
|
||||
"crusherm", NULL, NULL, NULL, "1999",
|
||||
"Crusher Makochan (Japan)\0", NULL, "Takumi", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_MISC, 0,
|
||||
NULL, crushermRomInfo, crushermRomName, NULL, NULL, KorokoroInputInfo, KorokoroDIPInfo,
|
||||
crushermInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 240, 4, 3
|
||||
};
|
|
@ -0,0 +1,846 @@
|
|||
// mazinger
|
||||
#include "cave.h"
|
||||
#include "msm6295.h"
|
||||
#include "burn_ym2203.h"
|
||||
#include "bitswap.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01, *RomZ80;
|
||||
static UINT8 *Ram01, *RamZ80;
|
||||
static UINT8 *MSM6295ROMSrc;
|
||||
static UINT8 *DefEEPROM = NULL;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesDone[2];
|
||||
|
||||
static INT32 SoundLatch;
|
||||
static INT32 SoundLatchReply[48];
|
||||
static INT32 SoundLatchStatus;
|
||||
|
||||
static INT32 SoundLatchReplyIndex;
|
||||
static INT32 SoundLatchReplyMax;
|
||||
|
||||
static UINT8 DrvZ80Bank;
|
||||
static UINT8 DrvOkiBank1;
|
||||
static UINT8 DrvOkiBank2;
|
||||
|
||||
static struct BurnInputInfo mazingerInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(mazinger)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall mazingerReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x800002:
|
||||
return (DrvInput[1] ^ 0xF7) | (EEPROMRead() << 3);
|
||||
case 0x800003:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall mazingerWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
|
||||
case 0x900000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 __fastcall mazingerReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
case 0x300002: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x300004: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x300006: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x30006E:
|
||||
if (SoundLatchReplyIndex > SoundLatchReplyMax) {
|
||||
SoundLatchReplyIndex = 0;
|
||||
SoundLatchReplyMax = -1;
|
||||
return 0;
|
||||
}
|
||||
return SoundLatchReply[SoundLatchReplyIndex++];
|
||||
|
||||
case 0x800000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0x800002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall mazingerWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
if (sekAddress >= 0x30000a && sekAddress <= 0x300066) return;
|
||||
if (sekAddress >= 0x30006a && sekAddress <= 0x30006c) return;
|
||||
if (sekAddress >= 0x300004 && sekAddress <= 0x300006) return;
|
||||
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x300002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
|
||||
case 0x300008:
|
||||
// CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x30006e:
|
||||
SoundLatch = wordValue;
|
||||
SoundLatchStatus |= 0x0C;
|
||||
|
||||
ZetNmi();
|
||||
nCyclesDone[1] += ZetRun(0x0400);
|
||||
return;
|
||||
|
||||
case 0x600000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0x600002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0x600004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x700000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x700002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x700004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x900000:
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall mazingerWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xffff, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall mazingerWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xffff, wordValue);
|
||||
}
|
||||
|
||||
UINT8 __fastcall mazingerZIn(UINT16 nAddress)
|
||||
{
|
||||
nAddress &= 0xFF;
|
||||
|
||||
switch (nAddress) {
|
||||
case 0x30: {
|
||||
SoundLatchStatus |= 0x04;
|
||||
return SoundLatch & 0xFF;
|
||||
}
|
||||
|
||||
case 0x52: {
|
||||
return BurnYM2203Read(0, 0);
|
||||
}
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall mazingerZOut(UINT16 nAddress, UINT8 nValue)
|
||||
{
|
||||
nAddress &= 0xFF;
|
||||
|
||||
switch (nAddress) {
|
||||
case 0x00: {
|
||||
DrvZ80Bank = nValue & 0x07;
|
||||
|
||||
ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x10:
|
||||
if (SoundLatchReplyIndex > SoundLatchReplyMax) {
|
||||
SoundLatchReplyMax = -1;
|
||||
SoundLatchReplyIndex = 0;
|
||||
}
|
||||
SoundLatchReplyMax++;
|
||||
SoundLatchReply[SoundLatchReplyMax] = nValue;
|
||||
break;
|
||||
|
||||
case 0x50: {
|
||||
BurnYM2203Write(0, 0, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x51: {
|
||||
BurnYM2203Write(0, 1, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x70: {
|
||||
MSM6295Command(0, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x74: {
|
||||
DrvOkiBank1 = (nValue >> 0) & 0x03;
|
||||
DrvOkiBank2 = (nValue >> 4) & 0x03;
|
||||
|
||||
memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall mazingerZRead(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall mazingerZWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
EEPROMExit();
|
||||
|
||||
MSM6295Exit(0);
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
ZetExit();
|
||||
|
||||
BurnYM2203Exit();
|
||||
|
||||
SoundLatch = 0;
|
||||
DrvZ80Bank = 0;
|
||||
DrvOkiBank1 = 0;
|
||||
DrvOkiBank2 = 0;
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekRun(10000); // Need to run for a bit and reset to make it start - Watchdog would force reset?
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2203Reset();
|
||||
MSM6295Reset(0);
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
SoundLatch = 0;
|
||||
DrvZ80Bank = 0;
|
||||
DrvOkiBank1 = 0;
|
||||
DrvOkiBank2 = 0;
|
||||
|
||||
SoundLatch = 0;
|
||||
SoundLatchStatus = 0x0C;
|
||||
|
||||
memset(SoundLatchReply, 0, sizeof(SoundLatchReply));
|
||||
SoundLatchReplyIndex = 0;
|
||||
SoundLatchReplyMax = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
if (CaveRecalcPalette) {
|
||||
CavePalUpdate8Bit(0x4400, 12);
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
CavePalUpdate4Bit(0, 64);
|
||||
|
||||
CaveClearScreen(CavePalette[0x3F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
|
||||
INT32 nInterleave = 80;
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
INT32 nCyclesSegment;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
ZetNewFrame();
|
||||
|
||||
SekOpen(0);
|
||||
ZetOpen(0);
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesTotal[1] = (INT32)(4000000 / CAVE_REFRESHRATE);
|
||||
nCyclesDone[0] = nCyclesDone[1] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nCurrentCPU = 0;
|
||||
INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// Run 68000
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
CaveSpriteBuffer();
|
||||
UINT8 Temp = nCaveSpriteBank;
|
||||
nCaveSpriteBank = nCaveSpriteBankDelay;
|
||||
nCaveSpriteBankDelay = Temp;
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
nUnknownIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
BurnTimerUpdate(i * (nCyclesTotal[1] / nInterleave));
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2203Update(pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
nSoundBufferPos += nSegmentLength;
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
BurnTimerEndFrame(nCyclesTotal[1]);
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
BurnYM2203Update(pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
RomZ80 = Next; Next += 0x020000;
|
||||
CaveSpriteROM = Next; Next += 0x800000;
|
||||
CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1
|
||||
MSM6295ROM = Next; Next += 0x040000;
|
||||
MSM6295ROMSrc = Next; Next += 0x080000;
|
||||
DefEEPROM = Next; Next += 0x000080;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
RamZ80 = Next; Next += 0x001000;
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
BurnLoadRom(Rom01 + 0x00000, 0, 1);
|
||||
BurnLoadRom(Rom01 + 0x80000, 1, 1);
|
||||
|
||||
BurnLoadRom(RomZ80, 2, 1);
|
||||
|
||||
UINT8 *pTemp = (UINT8*)malloc(0x400000);
|
||||
BurnLoadRom(pTemp + 0x000000, 3, 1);
|
||||
BurnLoadRom(pTemp + 0x200000, 4, 1);
|
||||
for (INT32 i = 0; i < 0x400000; i++) {
|
||||
CaveSpriteROM[i ^ 0xdf88] = pTemp[BITSWAP24(i,23,22,21,20,19,9,7,3,15,4,17,14,18,2,16,5,11,8,6,13,1,10,12,0)];
|
||||
}
|
||||
if (pTemp) {
|
||||
free(pTemp);
|
||||
pTemp = NULL;
|
||||
}
|
||||
NibbleSwap1(CaveSpriteROM, 0x400000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0], 5, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x200000);
|
||||
|
||||
pTemp = (UINT8*)malloc(0x200000);
|
||||
BurnLoadRom(pTemp, 6, 1);
|
||||
for (INT32 i = 0; i < 0x0100000; i++) {
|
||||
CaveTileROM[1][(i << 1) + 1] = (pTemp[(i << 1) + 0] & 15) | ((pTemp[(i << 1) + 1] & 15) << 4);
|
||||
CaveTileROM[1][(i << 1) + 0] = (pTemp[(i << 1) + 0] >> 4) | (pTemp[(i << 1) + 1] & 240);
|
||||
}
|
||||
if (pTemp) {
|
||||
free(pTemp);
|
||||
pTemp = NULL;
|
||||
}
|
||||
|
||||
// Load MSM6295 ADPCM data
|
||||
BurnLoadRom(MSM6295ROMSrc, 7, 1);
|
||||
|
||||
BurnLoadRom(DefEEPROM, 8, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction);
|
||||
ZetScan(nAction);
|
||||
|
||||
BurnYM2203Scan(nAction, pnMin);
|
||||
MSM6295Scan(0, nAction);
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
SCAN_VAR(SoundLatch);
|
||||
SCAN_VAR(DrvZ80Bank);
|
||||
SCAN_VAR(DrvOkiBank1);
|
||||
SCAN_VAR(DrvOkiBank2);
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
ZetOpen(0);
|
||||
ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetClose();
|
||||
|
||||
memcpy(MSM6295ROM + 0x00000, MSM6295ROMSrc + 0x20000 * DrvOkiBank1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x20000, MSM6295ROMSrc + 0x20000 * DrvOkiBank2, 0x20000);
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DrvFMIRQHandler(INT32, INT32 nStatus)
|
||||
{
|
||||
if (nStatus & 1) {
|
||||
ZetSetIRQLine(0xff, ZET_IRQSTATUS_ACK);
|
||||
} else {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvSynchroniseStream(INT32 nSoundRate)
|
||||
{
|
||||
return (INT64)ZetTotalCycles() * nSoundRate / 4000000;
|
||||
}
|
||||
|
||||
static double DrvGetTime()
|
||||
{
|
||||
return (double)ZetTotalCycles() / 4000000;
|
||||
}
|
||||
|
||||
static INT32 drvZInit()
|
||||
{
|
||||
ZetInit(1);
|
||||
|
||||
ZetOpen(0);
|
||||
|
||||
ZetSetInHandler(mazingerZIn);
|
||||
ZetSetOutHandler(mazingerZOut);
|
||||
ZetSetReadHandler(mazingerZRead);
|
||||
ZetSetWriteHandler(mazingerZWrite);
|
||||
|
||||
// ROM bank 1
|
||||
ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM
|
||||
ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM
|
||||
// ROM bank 2
|
||||
ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x4000); // Direct Read from ROM
|
||||
ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x4000); //
|
||||
// RAM
|
||||
ZetMapArea (0xc000, 0xc7FF, 0, RamZ80 + 0x0000); // Direct Read from RAM
|
||||
ZetMapArea (0xc000, 0xc7FF, 1, RamZ80 + 0x0000); // Direct Write to RAM
|
||||
ZetMapArea (0xc000, 0xc7FF, 2, RamZ80 + 0x0000); //
|
||||
|
||||
ZetMapArea (0xf800, 0xffFF, 0, RamZ80 + 0x0800); // Direct Read from RAM
|
||||
ZetMapArea (0xf800, 0xffFF, 1, RamZ80 + 0x0800); // Direct Write to RAM
|
||||
ZetMapArea (0xf800, 0xffFF, 2, RamZ80 + 0x0800); //
|
||||
|
||||
ZetMemEnd();
|
||||
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0xED,0xFF,0x00,0x00,0x12,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x200000, 0x20FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1] + 0x4000, 0x400000, 0x403FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1] + 0x4000, 0x404000, 0x407FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0] + 0x4000, 0x500000, 0x503FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0] + 0x4000, 0x504000, 0x507FFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0xC08000, 0xc087FF, SM_RAM); // Palette RAM
|
||||
SekMapMemory(CavePalSrc + 0x8800, 0xC08800, 0xC0FFFF, SM_ROM); // Palette RAM (write goes through handler)
|
||||
SekMapHandler(1, 0xC08800, 0xC0FFFF, SM_WRITE); //
|
||||
|
||||
SekMapMemory(Rom01 + 0x80000, 0xD00000, 0xD7FFFF, SM_ROM); // CPU 0 ROM
|
||||
|
||||
SekSetReadByteHandler(0, mazingerReadByte);
|
||||
SekSetWriteByteHandler(0, mazingerWriteByte);
|
||||
SekSetReadWordHandler(0, mazingerReadWord);
|
||||
SekSetWriteWordHandler(0, mazingerWriteWord);
|
||||
|
||||
SekSetWriteWordHandler(1, mazingerWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, mazingerWriteBytePalette);
|
||||
SekClose();
|
||||
}
|
||||
|
||||
drvZInit();
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(2, 0x0800000);
|
||||
CaveTileInitLayer(0, 0x400000, 8, 0x0000);
|
||||
CaveTileInitLayer(1, 0x400000, 6, 0x4400);
|
||||
|
||||
BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, DrvSynchroniseStream, DrvGetTime, 0);
|
||||
BurnTimerAttachZet(4000000);
|
||||
|
||||
memcpy(MSM6295ROM, MSM6295ROMSrc, 0x40000);
|
||||
MSM6295Init(0, 1056000 / 132, 100.0, 1);
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(DefEEPROM,0, 0x80);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo mazingerRomDesc[] = {
|
||||
{ "mzp-0.u24", 0x080000, 0x43a4279f, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "mzp-1.924", 0x080000, 0xdb40acba, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "mzs.u21", 0x020000, 0xc5b4f7ed, BRF_ESS | BRF_PRG }, // 2 Z80 Code
|
||||
|
||||
{ "bp943a-2.u56", 0x200000, 0x97e13959, BRF_GRA }, // 3 Sprite data
|
||||
{ "bp943a-3.u55", 0x080000, 0x9c4957dd, BRF_GRA }, // 4
|
||||
|
||||
{ "bp943a-1.u60", 0x200000, 0x46327415, BRF_GRA }, // 5 Layer 0 Tile data
|
||||
{ "bp943a-0.u63", 0x200000, 0xc1fed98a, BRF_GRA }, // 6 Layer 1 Tile data
|
||||
|
||||
{ "bp943a-4.u64", 0x080000, 0x3fc7f29a, BRF_SND }, // 7 MSM6295 #1 ADPCM data
|
||||
|
||||
{ "mazinger_world.nv", 0x0080, 0x4f6225c6, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(mazinger)
|
||||
STD_ROM_FN(mazinger)
|
||||
|
||||
static struct BurnRomInfo mazingerjRomDesc[] = {
|
||||
{ "mzp-0.u24", 0x080000, 0x43a4279f, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "mzp-1.924", 0x080000, 0xdb40acba, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "mzs.u21", 0x020000, 0xc5b4f7ed, BRF_ESS | BRF_PRG }, // 2 Z80 Code
|
||||
|
||||
{ "bp943a-2.u56", 0x200000, 0x97e13959, BRF_GRA }, // 3 Sprite data
|
||||
{ "bp943a-3.u55", 0x080000, 0x9c4957dd, BRF_GRA }, // 4
|
||||
|
||||
{ "bp943a-1.u60", 0x200000, 0x46327415, BRF_GRA }, // 5 Layer 0 Tile data
|
||||
{ "bp943a-0.u63", 0x200000, 0xc1fed98a, BRF_GRA }, // 6 Layer 1 Tile data
|
||||
|
||||
{ "bp943a-4.u64", 0x080000, 0x3fc7f29a, BRF_SND }, // 7 MSM6295 #1 ADPCM data
|
||||
|
||||
{ "mazinger_japan.nv", 0x0080, 0xf84a2a45, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(mazingerj)
|
||||
STD_ROM_FN(mazingerj)
|
||||
|
||||
struct BurnDriver BurnDrvmazinger = {
|
||||
"mazinger", NULL, NULL, NULL, "1994",
|
||||
"Mazinger Z (World, ver. 94/06/27)\0", NULL, "Banpresto / Dynamic Pl. Toei Animation", "Cave",
|
||||
L"Mazinger Z\0\u30DE\u30B8\u30F3\u30AC\u30FC \uFF3A (World, ver. 94/06/27)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL |BDF_ORIENTATION_FLIPPED | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0,
|
||||
NULL, mazingerRomInfo, mazingerRomName, NULL, NULL, mazingerInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 384, 3, 4
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvmazingerj = {
|
||||
"mazingerj", "mazinger", NULL, NULL, "1994",
|
||||
"Mazinger Z (Japan, ver. 94/06/27)\0", NULL, "Banpresto / Dynamic Pl. Toei Animation", "Cave",
|
||||
L"Mazinger Z\0\u30DE\u30B8\u30F3\u30AC\u30FC \uFF3A (Japan, ver. 94/06/27)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL |BDF_ORIENTATION_FLIPPED | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VERSHOOT, 0,
|
||||
NULL, mazingerjRomInfo, mazingerjRomName, NULL, NULL, mazingerInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 240, 384, 3, 4
|
||||
};
|
|
@ -0,0 +1,852 @@
|
|||
// metmqstr
|
||||
#include "cave.h"
|
||||
#include "burn_ym2151.h"
|
||||
#include "msm6295.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01, *RomZ80;
|
||||
static UINT8 *Ram01, *RamZ80;
|
||||
static UINT8 *MSM6295ROMSrc1, *MSM6295ROMSrc2;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesDone[2];
|
||||
|
||||
static INT32 SoundLatch;
|
||||
static INT32 SoundLatchReply[48];
|
||||
static INT32 SoundLatchStatus;
|
||||
|
||||
static INT32 SoundLatchReplyIndex;
|
||||
static INT32 SoundLatchReplyMax;
|
||||
|
||||
static UINT8 DrvZ80Bank;
|
||||
static UINT8 DrvOkiBank1_1;
|
||||
static UINT8 DrvOkiBank1_2;
|
||||
static UINT8 DrvOkiBank2_1;
|
||||
static UINT8 DrvOkiBank2_2;
|
||||
|
||||
static struct BurnInputInfo metmqstrInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
{"P1 Button 4", BIT_DIGITAL, DrvJoy1 + 10, "p1 fire 4"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
{"P2 Button 4", BIT_DIGITAL, DrvJoy2 + 10, "p2 fire 4"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(metmqstr)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall metmqstrReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall metmqstrWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
if (~byteValue & 0x0100) {
|
||||
case 0xd00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 __fastcall metmqstrReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0xa80000:
|
||||
case 0xa80002: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0xa80004: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0xa80006: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0xa8006C:
|
||||
if (SoundLatchReplyIndex > SoundLatchReplyMax) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0xa8006E:
|
||||
if (SoundLatchReplyIndex > SoundLatchReplyMax) {
|
||||
SoundLatchReplyIndex = 0;
|
||||
SoundLatchReplyMax = -1;
|
||||
return 0;
|
||||
}
|
||||
return SoundLatchReply[SoundLatchReplyIndex++];
|
||||
|
||||
case 0xc80000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0xc80002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall metmqstrWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
if (sekAddress >= 0xa8000a && sekAddress <= 0xa80068) return;
|
||||
if (sekAddress >= 0xa8006a && sekAddress <= 0xa8006c) return;
|
||||
if (sekAddress >= 0xa80004 && sekAddress <= 0xa80006) return;
|
||||
|
||||
switch (sekAddress) {
|
||||
case 0xa80000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0xa80002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
|
||||
case 0xa80008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0xa8006E:
|
||||
SoundLatch = wordValue;
|
||||
SoundLatchStatus |= 0x0C;
|
||||
|
||||
ZetNmi();
|
||||
nCyclesDone[1] += ZetRun(0x0400);
|
||||
return;
|
||||
|
||||
case 0xb00000:
|
||||
CaveTileReg[2][0] = wordValue;
|
||||
break;
|
||||
case 0xb00002:
|
||||
CaveTileReg[2][1] = wordValue;
|
||||
break;
|
||||
case 0xb00004:
|
||||
CaveTileReg[2][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xb80000:
|
||||
CaveTileReg[1][0] = wordValue;
|
||||
break;
|
||||
case 0xb80002:
|
||||
CaveTileReg[1][1] = wordValue;
|
||||
break;
|
||||
case 0xb80004:
|
||||
CaveTileReg[1][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xc00000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0xc00002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0xc00004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xd00000:
|
||||
if (~wordValue & 0x0100) {
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall metmqstrZIn(UINT16 nAddress)
|
||||
{
|
||||
nAddress &= 0xFF;
|
||||
|
||||
switch (nAddress) {
|
||||
case 0x20: {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 0x30:
|
||||
SoundLatchStatus |= 0x04;
|
||||
return SoundLatch & 0xFF;
|
||||
|
||||
case 0x40:
|
||||
SoundLatchStatus |= 0x08;
|
||||
return SoundLatch >> 8;
|
||||
|
||||
case 0x51:
|
||||
return BurnYM2151ReadStatus();
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Port Read %x\n"), nAddress);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall metmqstrZOut(UINT16 nAddress, UINT8 nValue)
|
||||
{
|
||||
nAddress &= 0xFF;
|
||||
|
||||
switch (nAddress) {
|
||||
case 0x00: {
|
||||
DrvZ80Bank = nValue & 0x0f;
|
||||
|
||||
ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x50:
|
||||
BurnYM2151SelectRegister(nValue);
|
||||
break;
|
||||
case 0x51:
|
||||
BurnYM2151WriteRegister(nValue);
|
||||
break;
|
||||
|
||||
case 0x60: {
|
||||
MSM6295Command(0, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x70: {
|
||||
DrvOkiBank1_1 = (nValue >> 0) & 0x07;
|
||||
DrvOkiBank1_2 = (nValue >> 4) & 0x07;
|
||||
|
||||
memcpy(MSM6295ROM + 0x000000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x020000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_2, 0x20000);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x80: {
|
||||
MSM6295Command(1, nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90: {
|
||||
DrvOkiBank2_1 = (nValue >> 0) & 0x07;
|
||||
DrvOkiBank2_2 = (nValue >> 4) & 0x07;
|
||||
|
||||
memcpy(MSM6295ROM + 0x100000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x120000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_2, 0x20000);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Port Write %x, %x\n"), nAddress, nValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall metmqstrZRead(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Read => %04X\n"), a);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall metmqstrZWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 Write => %04X, %02X\n"), a, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
EEPROMExit();
|
||||
|
||||
BurnYM2151Exit();
|
||||
MSM6295Exit(0);
|
||||
MSM6295Exit(1);
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
ZetExit();
|
||||
|
||||
SoundLatch = 0;
|
||||
DrvZ80Bank = 0;
|
||||
DrvOkiBank1_1 = 0;
|
||||
DrvOkiBank1_2 = 0;
|
||||
DrvOkiBank2_1 = 0;
|
||||
DrvOkiBank2_2 = 0;
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekRun(10000); // Need to run for a bit and reset to make it start - Watchdog would force reset?
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2151Reset();
|
||||
MSM6295Reset(0);
|
||||
MSM6295Reset(1);
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
SoundLatch = 0;
|
||||
DrvZ80Bank = 0;
|
||||
DrvOkiBank1_1 = 0;
|
||||
DrvOkiBank1_2 = 0;
|
||||
DrvOkiBank2_1 = 0;
|
||||
DrvOkiBank2_2 = 0;
|
||||
|
||||
SoundLatch = 0;
|
||||
SoundLatchStatus = 0x0C;
|
||||
|
||||
memset(SoundLatchReply, 0, sizeof(SoundLatchReply));
|
||||
SoundLatchReplyIndex = 0;
|
||||
SoundLatchReplyMax = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate4Bit(0, 128);
|
||||
|
||||
CaveClearScreen(CavePalette[0x7F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
INT32 nCyclesSegment;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 11; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
ZetNewFrame();
|
||||
|
||||
SekOpen(0);
|
||||
ZetOpen(0);
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesTotal[1] = (INT32)(8000000 / CAVE_REFRESHRATE);
|
||||
nCyclesDone[0] = nCyclesDone[1] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nCurrentCPU = 0;
|
||||
INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// Run 68000
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
UINT8 Temp = nCaveSpriteBank;
|
||||
nCaveSpriteBank = nCaveSpriteBankDelay;
|
||||
nCaveSpriteBankDelay = Temp;
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
nUnknownIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
SekSetIRQLine(1, SEK_IRQSTATUS_AUTO);
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = 1;
|
||||
nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
nCyclesSegment = ZetRun(nCyclesSegment);
|
||||
nCyclesDone[nCurrentCPU] += nCyclesSegment;
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2151Render(pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(1, pSoundBuf, nSegmentLength);
|
||||
nSoundBufferPos += nSegmentLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the buffer is entirely filled.
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
|
||||
if (nSegmentLength) {
|
||||
BurnYM2151Render(pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(0, pSoundBuf, nSegmentLength);
|
||||
MSM6295Render(1, pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x180000; // 68K program
|
||||
RomZ80 = Next; Next += 0x040000;
|
||||
CaveSpriteROM = Next; Next += 0x1000000;
|
||||
CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0
|
||||
CaveTileROM[1] = Next; Next += 0x400000; // Tile layer 1
|
||||
CaveTileROM[2] = Next; Next += 0x400000; // Tile layer 2
|
||||
MSM6295ROM = Next; Next += 0x140000;
|
||||
MSM6295ROMSrc1 = Next; Next += 0x200000;
|
||||
MSM6295ROMSrc2 = Next; Next += 0x200000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x018000; // CPU #0 work RAM
|
||||
RamZ80 = Next; Next += 0x002000;
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveTileRAM[1] = Next; Next += 0x008000;
|
||||
CaveTileRAM[2] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap2(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[1] = *pOrg & 15;
|
||||
pDest[0] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
BurnLoadRom(Rom01 + 0x000000, 0, 1);
|
||||
BurnLoadRom(Rom01 + 0x080000, 1, 1);
|
||||
BurnLoadRom(Rom01 + 0x100000, 2, 1);
|
||||
|
||||
BurnLoadRom(RomZ80, 3, 1);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 4, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x200000, 5, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x400000, 6, 1);
|
||||
BurnLoadRom(CaveSpriteROM + 0x600000, 7, 1);
|
||||
NibbleSwap1(CaveSpriteROM, 0x800000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0], 8, 1);
|
||||
NibbleSwap2(CaveTileROM[0], 0x200000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[1], 9, 1);
|
||||
NibbleSwap2(CaveTileROM[1], 0x200000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[2], 10, 1);
|
||||
NibbleSwap2(CaveTileROM[2], 0x200000);
|
||||
|
||||
// Load MSM6295 ADPCM data
|
||||
BurnLoadRom(MSM6295ROMSrc1, 11, 1);
|
||||
BurnLoadRom(MSM6295ROMSrc2, 12, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction);
|
||||
ZetScan(nAction);
|
||||
|
||||
BurnYM2151Scan(nAction);
|
||||
MSM6295Scan(0, nAction);
|
||||
MSM6295Scan(1, nAction);
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
SCAN_VAR(SoundLatch);
|
||||
SCAN_VAR(DrvZ80Bank);
|
||||
SCAN_VAR(DrvOkiBank1_1);
|
||||
SCAN_VAR(DrvOkiBank1_2);
|
||||
SCAN_VAR(DrvOkiBank2_1);
|
||||
SCAN_VAR(DrvOkiBank2_2);
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
ZetOpen(0);
|
||||
ZetMapArea(0x4000, 0x7FFF, 0, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetMapArea(0x4000, 0x7FFF, 2, RomZ80 + (DrvZ80Bank * 0x4000));
|
||||
ZetClose();
|
||||
|
||||
memcpy(MSM6295ROM + 0x000000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x020000, MSM6295ROMSrc1 + 0x20000 * DrvOkiBank1_2, 0x20000);
|
||||
|
||||
memcpy(MSM6295ROM + 0x100000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_1, 0x20000);
|
||||
memcpy(MSM6295ROM + 0x120000, MSM6295ROMSrc2 + 0x20000 * DrvOkiBank2_2, 0x20000);
|
||||
|
||||
CaveRecalcPalette = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 drvZInit()
|
||||
{
|
||||
ZetInit(1);
|
||||
|
||||
ZetOpen(0);
|
||||
|
||||
ZetSetInHandler(metmqstrZIn);
|
||||
ZetSetOutHandler(metmqstrZOut);
|
||||
ZetSetReadHandler(metmqstrZRead);
|
||||
ZetSetWriteHandler(metmqstrZWrite);
|
||||
|
||||
// ROM bank 1
|
||||
ZetMapArea (0x0000, 0x3FFF, 0, RomZ80 + 0x0000); // Direct Read from ROM
|
||||
ZetMapArea (0x0000, 0x3FFF, 2, RomZ80 + 0x0000); // Direct Fetch from ROM
|
||||
// ROM bank 2
|
||||
ZetMapArea (0x4000, 0x7FFF, 0, RomZ80 + 0x4000); // Direct Read from ROM
|
||||
ZetMapArea (0x4000, 0x7FFF, 2, RomZ80 + 0x4000); //
|
||||
// RAM
|
||||
ZetMapArea (0xe000, 0xFFFF, 0, RamZ80 + 0x0000); // Direct Read from RAM
|
||||
ZetMapArea (0xe000, 0xFFFF, 1, RamZ80 + 0x0000); // Direct Write to RAM
|
||||
ZetMapArea (0xe000, 0xFFFF, 2, RamZ80 + 0x0000); //
|
||||
|
||||
ZetMemEnd();
|
||||
|
||||
ZetClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DrvYM2151IrqHandler(INT32 Irq)
|
||||
{
|
||||
if (Irq) {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
} else {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Rom01 + 0x080000, 0x100000, 0x17FFFF, SM_ROM);
|
||||
SekMapMemory(Rom01 + 0x100000, 0x200000, 0x27FFFF, SM_ROM);
|
||||
SekMapMemory(CaveTileRAM[2], 0x880000, 0x887FFF, SM_RAM);
|
||||
SekMapMemory(Ram01 + 0x00000, 0x888000, 0x88FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[1], 0x900000, 0x907FFF, SM_RAM);
|
||||
SekMapMemory(Ram01 + 0x08000, 0x908000, 0x90FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x980000, 0x987FFF, SM_RAM);
|
||||
SekMapMemory(Ram01 + 0x10000, 0x988000, 0x98FFFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0x408000, 0x408FFF, SM_RAM); // Palette RAM
|
||||
SekMapMemory(CaveSpriteRAM, 0xF00000, 0xF0FFFF, SM_RAM);
|
||||
SekSetReadByteHandler(0, metmqstrReadByte);
|
||||
SekSetWriteByteHandler(0, metmqstrWriteByte);
|
||||
SekSetReadWordHandler(0, metmqstrReadWord);
|
||||
SekSetWriteWordHandler(0, metmqstrWriteWord);
|
||||
SekClose();
|
||||
}
|
||||
|
||||
drvZInit();
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(2, 0x1000000);
|
||||
CaveTileInitLayer(0, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(1, 0x400000, 8, 0x4000);
|
||||
CaveTileInitLayer(2, 0x400000, 8, 0x4000);
|
||||
|
||||
nCaveExtraXOffset = -126;
|
||||
CaveSpriteVisibleXOffset = -126;
|
||||
|
||||
BurnYM2151Init(4000000, 25.0);
|
||||
BurnYM2151SetIrqHandler(&DrvYM2151IrqHandler);
|
||||
|
||||
memcpy(MSM6295ROM, MSM6295ROMSrc1, 0x40000);
|
||||
memcpy(MSM6295ROM + 0x100000, MSM6295ROMSrc2, 0x40000);
|
||||
MSM6295Init(0, 2000000 / 132, 100.0, 1);
|
||||
MSM6295Init(1, 2000000 / 132, 100.0, 1);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
#if defined FBA_DEBUG && defined USE_SPEEDHACKS
|
||||
bprintf(PRINT_IMPORTANT, _T(" * Using speed-hacks (detecting idle loops).\n"));
|
||||
#endif
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo metmqstrRomDesc[] = {
|
||||
{ "bp947a.u25", 0x080000, 0x0a5c3442, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "bp947a.u28", 0x080000, 0x8c55decf, BRF_ESS | BRF_PRG }, // 1
|
||||
{ "bp947a.u29", 0x080000, 0xcf0f3f3b, BRF_ESS | BRF_PRG }, // 2
|
||||
|
||||
{ "bp947a.u20", 0x040000, 0xa4a36170, BRF_ESS | BRF_PRG }, // 3 Z80 Code
|
||||
|
||||
{ "bp947a.u49", 0x200000, 0x09749531, BRF_GRA }, // 4 Sprite data
|
||||
{ "bp947a.u50", 0x200000, 0x19cea8b2, BRF_GRA }, // 5
|
||||
{ "bp947a.u51", 0x200000, 0xc19bed67, BRF_GRA }, // 6
|
||||
{ "bp947a.u52", 0x200000, 0x70c64875, BRF_GRA }, // 7
|
||||
|
||||
{ "bp947a.u48", 0x200000, 0x04ff6a3d, BRF_GRA }, // 8 Layer 0 Tile data
|
||||
{ "bp947a.u47", 0x200000, 0x0de42827, BRF_GRA }, // 9 Layer 2 Tile data
|
||||
{ "bp947a.u46", 0x200000, 0x0f9c906e, BRF_GRA }, // 10 Layer 2 Tile data
|
||||
|
||||
{ "bp947a.u42", 0x200000, 0x2ce8ff2a, BRF_SND }, // 11 MSM6295 #1 ADPCM data
|
||||
{ "bp947a.u37", 0x200000, 0xc3077c8f, BRF_SND }, // 12 MSM6295 #2 ADPCM data
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(metmqstr)
|
||||
STD_ROM_FN(metmqstr)
|
||||
|
||||
static struct BurnRomInfo nmasterRomDesc[] = {
|
||||
{ "bp947a_n.u25", 0x080000, 0x748cc514, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "bp947a.u28", 0x080000, 0x8c55decf, BRF_ESS | BRF_PRG }, // 1
|
||||
{ "bp947a.u29", 0x080000, 0xcf0f3f3b, BRF_ESS | BRF_PRG }, // 2
|
||||
|
||||
{ "bp947a.u20", 0x040000, 0xa4a36170, BRF_ESS | BRF_PRG }, // 3 Z80 Code
|
||||
|
||||
{ "bp947a.u49", 0x200000, 0x09749531, BRF_GRA }, // 4 Sprite data
|
||||
{ "bp947a.u50", 0x200000, 0x19cea8b2, BRF_GRA }, // 5
|
||||
{ "bp947a.u51", 0x200000, 0xc19bed67, BRF_GRA }, // 6
|
||||
{ "bp947a.u52", 0x200000, 0x70c64875, BRF_GRA }, // 7
|
||||
|
||||
{ "bp947a.u48", 0x200000, 0x04ff6a3d, BRF_GRA }, // 8 Layer 0 Tile data
|
||||
{ "bp947a.u47", 0x200000, 0x0de42827, BRF_GRA }, // 9 Layer 2 Tile data
|
||||
{ "bp947a.u46", 0x200000, 0x0f9c906e, BRF_GRA }, // 10 Layer 2 Tile data
|
||||
|
||||
{ "bp947a.u42", 0x200000, 0x2ce8ff2a, BRF_SND }, // 11 MSM6295 #1 ADPCM data
|
||||
{ "bp947a.u37", 0x200000, 0xc3077c8f, BRF_SND }, // 12 MSM6295 #2 ADPCM data
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(nmaster)
|
||||
STD_ROM_FN(nmaster)
|
||||
|
||||
struct BurnDriver BurnDrvmetmqstr = {
|
||||
"metmqstr", NULL, NULL, NULL, "1995",
|
||||
"Metamoqester (International)\0", NULL, "Banpresto / Pandorabox", "Cave",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, 0,
|
||||
NULL, metmqstrRomInfo, metmqstrRomName, NULL, NULL, metmqstrInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 384, 240, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvnmaster = {
|
||||
"nmaster", "metmqstr", NULL, NULL, "1995",
|
||||
"Oni - The Ninja Master (Japan)\0", NULL, "Banpresto / Pandorabox", "Cave",
|
||||
L"\u7A4F\u5FCD - The Ninja Master (Japan)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY | BDF_CLONE, 2, HARDWARE_CAVE_68K_Z80, GBF_VSFIGHT, 0,
|
||||
NULL, nmasterRomInfo, nmasterRomName, NULL, NULL, metmqstrInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 384, 240, 4, 3
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,583 @@
|
|||
// Tobikose! Jumpman
|
||||
#include "cave.h"
|
||||
#include "msm6295.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0, 0};
|
||||
static UINT8 DrvDip[2] = { 0, 0 };
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nPrevCoinHack = 0;
|
||||
static INT32 watchdog;
|
||||
static INT32 tjumpman_hopper;
|
||||
|
||||
static struct BurnInputInfo TjumpmanInputList[] = {
|
||||
{"Coin", BIT_DIGITAL, DrvJoy2 + 6, "p1 coin" },
|
||||
{"1 Bet", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1" },
|
||||
{"3 Bet", BIT_DIGITAL, DrvJoy2 + 7, "p1 fire 2" },
|
||||
{"No (not)", BIT_DIGITAL, DrvJoy2 + 4, "p1 start" },
|
||||
{"Yes (do)", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 4" },
|
||||
{"Pay Out", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 5" },
|
||||
{"Go", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 3" },
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
|
||||
{"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" },
|
||||
{"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" },
|
||||
};
|
||||
|
||||
STDINPUTINFO(Tjumpman)
|
||||
|
||||
static struct BurnDIPInfo TjumpmanDIPList[]=
|
||||
{
|
||||
{0x08, 0xff, 0xff, 0x01, NULL },
|
||||
{0x09, 0xff, 0xff, 0x08, NULL },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Service Mode" },
|
||||
{0x08, 0x01, 0x01, 0x01, "Off" },
|
||||
{0x08, 0x01, 0x01, 0x00, "On" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Self Test" },
|
||||
{0x09, 0x01, 0x08, 0x08, "Off" },
|
||||
{0x09, 0x01, 0x08, 0x00, "On" },
|
||||
};
|
||||
|
||||
STDDIPINFO(Tjumpman)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
static INT32 tjumpman_hopper_read()
|
||||
{
|
||||
return (tjumpman_hopper && !(nCurrentFrame % 10)) ? 0 : 1;
|
||||
}
|
||||
|
||||
UINT8 __fastcall tjumpmanReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress)
|
||||
{
|
||||
case 0x600000:
|
||||
return 0xff;
|
||||
|
||||
case 0x600001:
|
||||
return ((DrvInput[0] & 0x76) ^ 0x76) | (DrvDip[0] & 1) | ((EEPROMRead() & 1) << 3) | (tjumpman_hopper_read() << 7);
|
||||
|
||||
case 0x600002:
|
||||
return 0xff;
|
||||
|
||||
case 0x600003:
|
||||
return ((DrvInput[1] & 0xF7) ^ 0xF7) | (DrvDip[1] & 8);
|
||||
|
||||
case 0x700000:
|
||||
case 0x700001: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 4 : 0);
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x700002:
|
||||
case 0x700003: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x700004:
|
||||
case 0x700005: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x700006:
|
||||
case 0x700007: {
|
||||
UINT8 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x800001:
|
||||
return MSM6295ReadStatus(0);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall tjumpmanReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress)
|
||||
{
|
||||
case 0x600000:
|
||||
return (DrvInput[0] ^ 0xFF76) | (DrvDip[0] & 1) | ((EEPROMRead() & 1) << 3) | (tjumpman_hopper_read() << 7);
|
||||
|
||||
case 0x600002:
|
||||
return (DrvInput[1] ^ 0xFFF7) | (DrvDip[1] & 8);
|
||||
|
||||
case 0x700000: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ | (bVBlank ? 4 : 0);
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x700002: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x700004: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x700006: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x800000:
|
||||
return MSM6295ReadStatus(0);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall tjumpmanWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress)
|
||||
{
|
||||
case 0x800001:
|
||||
MSM6295Command(0, byteValue);
|
||||
break;
|
||||
|
||||
case 0xc00000:
|
||||
break;
|
||||
|
||||
case 0xc00001:
|
||||
tjumpman_hopper = byteValue & 0x40;
|
||||
break;
|
||||
|
||||
case 0xe00001:
|
||||
EEPROMWrite(byteValue & 0x10, byteValue & 0x08, byteValue & 0x20);
|
||||
break;
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall tjumpmanWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress)
|
||||
{
|
||||
case 0x400000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x400002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x400004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0x700000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x700002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x700008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x700068:
|
||||
watchdog = 0;
|
||||
break;
|
||||
|
||||
case 0x800000:
|
||||
MSM6295Command(0, wordValue);
|
||||
break;
|
||||
|
||||
case 0xc00000:
|
||||
tjumpman_hopper = wordValue & 0x40;
|
||||
break;
|
||||
|
||||
case 0xe00000:
|
||||
EEPROMWrite(wordValue & 0x10, wordValue & 0x08, wordValue & 0x20);
|
||||
break;
|
||||
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall tjumpmanWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xFFFF, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall tjumpmanWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xFFFF, wordValue);
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
EEPROMExit();
|
||||
|
||||
MSM6295Exit(0);
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit();
|
||||
|
||||
BurnFree(Mem);
|
||||
Mem = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
MSM6295Reset(0);
|
||||
|
||||
tjumpman_hopper = 0;
|
||||
watchdog = 0;
|
||||
// nPrevCoinHack = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CaveSpriteBuffer();
|
||||
CavePalUpdate8Bit(0, 128);
|
||||
CaveClearScreen(CavePalette[0x7F00]);
|
||||
|
||||
CaveTileRender(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
INT32 nCyclesTotal[1];
|
||||
INT32 nCyclesDone[1];
|
||||
|
||||
INT32 nCyclesSegment;
|
||||
|
||||
watchdog++;
|
||||
if (DrvReset || (watchdog > 180)) {
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
DrvInput[0] = 0;
|
||||
DrvInput[1] = 0;
|
||||
for (INT32 i = 0; i < 8; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
|
||||
//if ((nPrevCoinHack != (DrvInput[1] & 0x0040)) && (DrvInput[1] & 0x0040)) {
|
||||
// Ram01[0x24]++;
|
||||
// if (Ram01[0x24] > 9) Ram01[0x24] = 9; // ?
|
||||
//}
|
||||
|
||||
nPrevCoinHack = DrvInput[1] & 0x0040;
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)14000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nCurrentCPU = 0;
|
||||
INT32 nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
}
|
||||
|
||||
if (pBurnDraw) {
|
||||
DrvDraw();
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
|
||||
// end of vblank
|
||||
if (i == nInterleave) {
|
||||
bVBlank = false;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
MSM6295Render(0, pBurnSoundOut, nBurnSoundLen);
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next;
|
||||
|
||||
Next = Mem;
|
||||
|
||||
Rom01 = Next; Next += 0x080000;
|
||||
CaveSpriteROM = Next; Next += 0x200000;
|
||||
CaveTileROM[0] = Next; Next += 0x100000;
|
||||
|
||||
MSM6295ROM = Next; Next += 0x040000;
|
||||
|
||||
Ram01 = Next; Next += 0x010000; // work RAM (NV!)
|
||||
|
||||
RamStart = Next;
|
||||
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000;
|
||||
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap4(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[1] = (n2 << 4) | (n1 & 0x0F);
|
||||
pData[0] = (n2 & 0xF0) | (n1 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
BurnLoadRom(Rom01, 0, 1);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x000000, 1, 2);
|
||||
BurnLoadRom(CaveSpriteROM + 0x000001, 2, 2);
|
||||
NibbleSwap1(CaveSpriteROM, 0x100000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x00000, 3, 2);
|
||||
BurnLoadRom(CaveTileROM[0] + 0x00001, 4, 2);
|
||||
NibbleSwap4(CaveTileROM[0], 0x80000);
|
||||
|
||||
BurnLoadRom(MSM6295ROM, 5, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) {
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin);
|
||||
|
||||
if (nAction & ACB_VOLATILE) {
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction);
|
||||
|
||||
MSM6295Scan(0, nAction);
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
|
||||
SCAN_VAR(tjumpman_hopper);
|
||||
|
||||
CaveScanGraphics();
|
||||
}
|
||||
|
||||
if (nAction & ACB_NVRAM) {
|
||||
ba.Data = Ram01;
|
||||
ba.nLen = 0x010000;
|
||||
ba.nAddress = 0x100000;
|
||||
ba.szName = "NV RAM";
|
||||
BurnAcb(&ba);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen);
|
||||
MemIndex();
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000);
|
||||
SekOpen(0);
|
||||
SekMapMemory(Rom01, 0x000000, 0x07FFFF, SM_ROM);
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x300000, 0x303FFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x304000, 0x307FFF, SM_RAM); // mirror
|
||||
SekMapMemory(CaveSpriteRAM, 0x200000, 0x20FFFF, SM_RAM);
|
||||
SekMapMemory(CavePalSrc, 0x500000, 0x50FFFF, SM_ROM);
|
||||
SekSetReadWordHandler(0, tjumpmanReadWord);
|
||||
SekSetReadByteHandler(0, tjumpmanReadByte);
|
||||
SekSetWriteWordHandler(0, tjumpmanWriteWord);
|
||||
SekSetWriteByteHandler(0, tjumpmanWriteByte);
|
||||
|
||||
SekMapHandler(1, 0x500000, 0x50FFFF, SM_WRITE);
|
||||
SekSetWriteWordHandler(1, tjumpmanWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, tjumpmanWriteBytePalette);
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveExtraXOffset = -128; // bg
|
||||
CaveSpriteVisibleXOffset = -128; // sprite
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(2, 0x0200000);
|
||||
CaveTileInitLayer(0, 0x100000, 8, 0x4000);
|
||||
|
||||
MSM6295Init(0, 7575, 100.0, 0);
|
||||
|
||||
DrvDoReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Tobikose! Jumpman
|
||||
|
||||
static struct BurnRomInfo tjumpmanRomDesc[] = {
|
||||
{ "tj1_mpr-0c.u41", 0x80000, 0xde3030b8, BRF_PRG | BRF_PRG }, // 0 CPU #0 code
|
||||
|
||||
{ "tj1_obj-0a.u52", 0x80000, 0xb42cf8e8, BRF_GRA }, // 1 Sprite data
|
||||
{ "tj1_obj-1a.u53", 0x80000, 0x5f0124d7, BRF_GRA }, // 2
|
||||
|
||||
{ "tj1_cha-0a.u60", 0x40000, 0x8aa08a38, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
{ "tj1_cha-1a.u61", 0x40000, 0x50072c82, BRF_GRA }, // 4
|
||||
|
||||
{ "tj1_voi-0a.u27", 0x40000, 0xb5693aae, BRF_SND }, // 5 MSM6295 #0 ADPCM data
|
||||
|
||||
{ "n44u3b.u3", 0x00117, 0x4cd79750, BRF_OPT }, // 6 PLDs
|
||||
{ "n44u1g.u1", 0x00117, 0xe226ec18, BRF_OPT }, // 7
|
||||
};
|
||||
|
||||
STD_ROM_PICK(tjumpman)
|
||||
STD_ROM_FN(tjumpman)
|
||||
|
||||
struct BurnDriverD BurnDrvTjumpman = {
|
||||
"tjumpman", NULL, NULL, NULL, "1999",
|
||||
"Tobikose! Jumpman\0", "Coin input not working?", "Namco", "Cave",
|
||||
L"\u30E1\u30B0\u30EB\u3092\u3044\u308C\u3066\u306D!\0Tobikose! Jumpman\0", NULL, NULL, NULL,
|
||||
BDF_16BIT_ONLY, 1, HARDWARE_CAVE_68K_ONLY | HARDWARE_CAVE_M6295, GBF_MISC, 0,
|
||||
NULL, tjumpmanRomInfo, tjumpmanRomName, NULL, NULL, TjumpmanInputInfo, TjumpmanDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 240, 4, 3
|
||||
};
|
|
@ -0,0 +1,610 @@
|
|||
// Uo Poko
|
||||
#include "cave.h"
|
||||
#include "ymz280b.h"
|
||||
|
||||
#define CAVE_VBLANK_LINES 12
|
||||
|
||||
static UINT8 DrvJoy1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT8 DrvJoy2[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static UINT16 DrvInput[2] = {0x0000, 0x0000};
|
||||
|
||||
static UINT8 *Mem = NULL, *MemEnd = NULL;
|
||||
static UINT8 *RamStart, *RamEnd;
|
||||
static UINT8 *Rom01;
|
||||
static UINT8 *Ram01;
|
||||
|
||||
static UINT8 DrvReset = 0;
|
||||
static UINT8 bDrawScreen;
|
||||
static bool bVBlank;
|
||||
|
||||
static INT8 nVideoIRQ;
|
||||
static INT8 nSoundIRQ;
|
||||
static INT8 nUnknownIRQ;
|
||||
|
||||
static INT8 nIRQPending;
|
||||
|
||||
static INT32 nCurrentCPU;
|
||||
static INT32 nCyclesDone[2];
|
||||
static INT32 nCyclesTotal[2];
|
||||
static INT32 nCyclesSegment;
|
||||
|
||||
static struct BurnInputInfo uopokoInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 8, "p1 coin"},
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start"},
|
||||
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy1 + 0, "p1 up"},
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy1 + 1, "p1 down"},
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 2, "p1 left"},
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 3, "p1 right"},
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1"},
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2"},
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3"},
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy2 + 8, "p2 coin"},
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start"},
|
||||
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy2 + 0, "p2 up"},
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy2 + 1, "p2 down"},
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy2 + 2, "p2 left"},
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy2 + 3, "p2 right"},
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1"},
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2"},
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3"},
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Diagnostics", BIT_DIGITAL, DrvJoy1 + 9, "diag"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy2 + 9, "service"},
|
||||
};
|
||||
|
||||
STDINPUTINFO(uopoko)
|
||||
|
||||
static void UpdateIRQStatus()
|
||||
{
|
||||
nIRQPending = (nVideoIRQ == 0 || nSoundIRQ == 0 || nUnknownIRQ == 0);
|
||||
SekSetIRQLine(1, nIRQPending ? SEK_IRQSTATUS_ACK : SEK_IRQSTATUS_NONE);
|
||||
}
|
||||
|
||||
UINT8 __fastcall uopokoReadByte(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300003: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x600000:
|
||||
case 0x600001:
|
||||
case 0x600002:
|
||||
case 0x600003: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x600004:
|
||||
case 0x600005: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x600006:
|
||||
case 0x600007: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x900000:
|
||||
return (DrvInput[0] >> 8) ^ 0xFF;
|
||||
case 0x900001:
|
||||
return (DrvInput[0] & 0xFF) ^ 0xFF;
|
||||
case 0x900002:
|
||||
return ((DrvInput[1] >> 8) ^ 0xF7) | (EEPROMRead() << 3);
|
||||
case 0x900003:
|
||||
return (DrvInput[1] & 0xFF) ^ 0xFF;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read byte value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall uopokoReadWord(UINT32 sekAddress)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300002: {
|
||||
return YMZ280BReadStatus();
|
||||
}
|
||||
|
||||
case 0x600000:
|
||||
case 0x600002: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
return nRet;
|
||||
}
|
||||
case 0x600004: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nVideoIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
case 0x600006: {
|
||||
UINT16 nRet = (nUnknownIRQ << 1) | nVideoIRQ;
|
||||
nUnknownIRQ = 1;
|
||||
UpdateIRQStatus();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
case 0x900000:
|
||||
return DrvInput[0] ^ 0xFFFF;
|
||||
case 0x900002:
|
||||
return (DrvInput[1] ^ 0xF7FF) | (EEPROMRead() << 11);
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to read word value of location %x\n", sekAddress);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall uopokoWriteByte(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300001:
|
||||
YMZ280BSelectRegister(byteValue);
|
||||
break;
|
||||
case 0x300003:
|
||||
YMZ280BWriteRegister(byteValue);
|
||||
break;
|
||||
|
||||
case 0xA00000:
|
||||
EEPROMWrite(byteValue & 0x04, byteValue & 0x02, byteValue & 0x08);
|
||||
break;
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write byte value %x to location %x\n", byteValue, sekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall uopokoWriteWord(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
switch (sekAddress) {
|
||||
case 0x300000:
|
||||
YMZ280BSelectRegister(wordValue);
|
||||
break;
|
||||
case 0x300002:
|
||||
YMZ280BWriteRegister(wordValue);
|
||||
break;
|
||||
|
||||
case 0x600000:
|
||||
nCaveXOffset = wordValue;
|
||||
return;
|
||||
case 0x600002:
|
||||
nCaveYOffset = wordValue;
|
||||
return;
|
||||
case 0x600008:
|
||||
CaveSpriteBuffer();
|
||||
nCaveSpriteBank = wordValue;
|
||||
return;
|
||||
|
||||
case 0x700000:
|
||||
CaveTileReg[0][0] = wordValue;
|
||||
break;
|
||||
case 0x700002:
|
||||
CaveTileReg[0][1] = wordValue;
|
||||
break;
|
||||
case 0x700004:
|
||||
CaveTileReg[0][2] = wordValue;
|
||||
break;
|
||||
|
||||
case 0xA00000: {
|
||||
wordValue >>= 8;
|
||||
EEPROMWrite(wordValue & 0x04, wordValue & 0x02, wordValue & 0x08);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// bprintf(PRINT_NORMAL, "Attempt to write word value %x to location %x\n", wordValue, sekAddress);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall uopokoWriteBytePalette(UINT32 sekAddress, UINT8 byteValue)
|
||||
{
|
||||
CavePalWriteByte(sekAddress & 0xFFFF, byteValue);
|
||||
}
|
||||
|
||||
void __fastcall uopokoWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
|
||||
{
|
||||
CavePalWriteWord(sekAddress & 0xFFFF, wordValue);
|
||||
}
|
||||
|
||||
static void TriggerSoundIRQ(INT32 nStatus)
|
||||
{
|
||||
nSoundIRQ = nStatus ^ 1;
|
||||
UpdateIRQStatus();
|
||||
|
||||
if (nIRQPending && nCurrentCPU != 0) {
|
||||
nCyclesDone[0] += SekRun(0x0400);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
YMZ280BExit();
|
||||
|
||||
EEPROMExit();
|
||||
|
||||
CaveTileExit();
|
||||
CaveSpriteExit();
|
||||
CavePalExit();
|
||||
|
||||
SekExit(); // Deallocate 68000s
|
||||
|
||||
// Deallocate all used memory
|
||||
if (Mem) {
|
||||
free(Mem);
|
||||
Mem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
SekOpen(0);
|
||||
SekReset();
|
||||
SekClose();
|
||||
|
||||
EEPROMReset();
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
nVideoIRQ = 1;
|
||||
nSoundIRQ = 1;
|
||||
nUnknownIRQ = 1;
|
||||
|
||||
nIRQPending = 0;
|
||||
|
||||
YMZ280BReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
CavePalUpdate8Bit(0, 128); // Update the palette
|
||||
CaveClearScreen(CavePalette[0x7F00]);
|
||||
|
||||
if (bDrawScreen) {
|
||||
// CaveGetBitmap();
|
||||
|
||||
CaveTileRender(1); // Render tiles
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline static INT32 CheckSleep(INT32)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
INT32 nCyclesVBlank;
|
||||
INT32 nInterleave = 8;
|
||||
|
||||
if (DrvReset) { // Reset machine
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
// Compile digital inputs
|
||||
DrvInput[0] = 0x0000; // Player 1
|
||||
DrvInput[1] = 0x0000; // Player 2
|
||||
for (INT32 i = 0; i < 16; i++) {
|
||||
DrvInput[0] |= (DrvJoy1[i] & 1) << i;
|
||||
DrvInput[1] |= (DrvJoy2[i] & 1) << i;
|
||||
}
|
||||
CaveClearOpposites(&DrvInput[0]);
|
||||
CaveClearOpposites(&DrvInput[1]);
|
||||
|
||||
SekNewFrame();
|
||||
|
||||
nCyclesTotal[0] = (INT32)((INT64)16000000 * nBurnCPUSpeedAdjust / (0x0100 * CAVE_REFRESHRATE));
|
||||
nCyclesDone[0] = 0;
|
||||
|
||||
nCyclesVBlank = nCyclesTotal[0] - (INT32)((nCyclesTotal[0] * CAVE_VBLANK_LINES) / 271.5);
|
||||
bVBlank = false;
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
|
||||
SekOpen(0);
|
||||
|
||||
for (INT32 i = 1; i <= nInterleave; i++) {
|
||||
INT32 nNext;
|
||||
|
||||
// Render sound segment
|
||||
if ((i & 1) == 0) {
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentEnd = nBurnSoundLen * i / nInterleave;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
YMZ280BRender(pSoundBuf, nSegmentEnd - nSoundBufferPos);
|
||||
nSoundBufferPos = nSegmentEnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Run 68000
|
||||
nCurrentCPU = 0;
|
||||
nNext = i * nCyclesTotal[nCurrentCPU] / nInterleave;
|
||||
|
||||
// See if we need to trigger the VBlank interrupt
|
||||
if (!bVBlank && nNext > nCyclesVBlank) {
|
||||
if (nCyclesDone[nCurrentCPU] < nCyclesVBlank) {
|
||||
nCyclesSegment = nCyclesVBlank - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBurnDraw != NULL) {
|
||||
DrvDraw(); // Draw screen if needed
|
||||
}
|
||||
|
||||
bVBlank = true;
|
||||
nVideoIRQ = 0;
|
||||
UpdateIRQStatus();
|
||||
}
|
||||
|
||||
nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
|
||||
if (!CheckSleep(nCurrentCPU)) { // See if this CPU is busywaiting
|
||||
nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
|
||||
} else {
|
||||
nCyclesDone[nCurrentCPU] += SekIdle(nCyclesSegment);
|
||||
}
|
||||
|
||||
nCurrentCPU = -1;
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure the buffer is entirely filled.
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
if (nSegmentLength) {
|
||||
YMZ280BRender(pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SekClose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
|
||||
// and then afterwards to set up all the pointers
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8* Next; Next = Mem;
|
||||
Rom01 = Next; Next += 0x100000; // 68K program
|
||||
CaveSpriteROM = Next; Next += 0x800000;
|
||||
CaveTileROM[0] = Next; Next += 0x400000; // Tile layer 0
|
||||
YMZ280BROM = Next; Next += 0x200000;
|
||||
RamStart = Next;
|
||||
Ram01 = Next; Next += 0x010000; // CPU #0 work RAM
|
||||
CaveTileRAM[0] = Next; Next += 0x008000;
|
||||
CaveSpriteRAM = Next; Next += 0x010000;
|
||||
CavePalSrc = Next; Next += 0x010000; // palette
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NibbleSwap1(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
UINT8* pOrg = pData + nLen - 1;
|
||||
UINT8* pDest = pData + ((nLen - 1) << 1);
|
||||
|
||||
for (INT32 i = 0; i < nLen; i++, pOrg--, pDest -= 2) {
|
||||
pDest[0] = *pOrg & 15;
|
||||
pDest[1] = *pOrg >> 4;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void NibbleSwap4(UINT8* pData, INT32 nLen)
|
||||
{
|
||||
for (INT32 i = 0; i < nLen; i++, pData += 2) {
|
||||
UINT8 n1 = pData[0];
|
||||
UINT8 n2 = pData[1];
|
||||
|
||||
pData[1] = (n2 << 4) | (n1 & 0x0F);
|
||||
pData[0] = (n2 & 0xF0) | (n1 >> 4);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static INT32 LoadRoms()
|
||||
{
|
||||
// Load 68000 ROM
|
||||
BurnLoadRom(Rom01 + 0, 1, 2);
|
||||
BurnLoadRom(Rom01 + 1, 0, 2);
|
||||
|
||||
BurnLoadRom(CaveSpriteROM + 0x0000000, 2, 1);
|
||||
NibbleSwap1(CaveSpriteROM, 0x400000);
|
||||
|
||||
BurnLoadRom(CaveTileROM[0] + 0x000000, 3, 1);
|
||||
NibbleSwap4(CaveTileROM[0], 0x200000);
|
||||
|
||||
// Load YMZ280B data
|
||||
BurnLoadRom(YMZ280BROM, 4, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scan ram
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) { // Return minimum compatible version
|
||||
*pnMin = 0x020902;
|
||||
}
|
||||
|
||||
EEPROMScan(nAction, pnMin); // Scan EEPROM
|
||||
|
||||
if (nAction & ACB_VOLATILE) { // Scan volatile ram
|
||||
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
ba.Data = RamStart;
|
||||
ba.nLen = RamEnd - RamStart;
|
||||
ba.szName = "RAM";
|
||||
BurnAcb(&ba);
|
||||
|
||||
SekScan(nAction); // scan 68000 states
|
||||
|
||||
YMZ280BScan();
|
||||
|
||||
SCAN_VAR(nVideoIRQ);
|
||||
SCAN_VAR(nSoundIRQ);
|
||||
SCAN_VAR(nUnknownIRQ);
|
||||
SCAN_VAR(bVBlank);
|
||||
|
||||
CaveScanGraphics();
|
||||
|
||||
SCAN_VAR(DrvInput);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT8 default_eeprom[16] = {0x00,0x03,0x08,0x00,0xFF,0xFF,0xFF,0xFF,0x08,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
INT32 nLen;
|
||||
|
||||
BurnSetRefreshRate(CAVE_REFRESHRATE);
|
||||
|
||||
// Find out how much memory is needed
|
||||
Mem = NULL;
|
||||
MemIndex();
|
||||
nLen = MemEnd - (UINT8 *)0;
|
||||
if ((Mem = (UINT8 *)malloc(nLen)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
memset(Mem, 0, nLen); // blank all memory
|
||||
MemIndex(); // Index the allocated memory
|
||||
|
||||
EEPROMInit(&eeprom_interface_93C46);
|
||||
if (!EEPROMAvailable()) EEPROMFill(default_eeprom,0, sizeof(default_eeprom));
|
||||
|
||||
// Load the roms into memory
|
||||
if (LoadRoms()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
SekInit(0, 0x68000); // Allocate 68000
|
||||
SekOpen(0);
|
||||
|
||||
// Map 68000 memory:
|
||||
SekMapMemory(Rom01, 0x000000, 0x0FFFFF, SM_ROM); // CPU 0 ROM
|
||||
SekMapMemory(Ram01, 0x100000, 0x10FFFF, SM_RAM);
|
||||
SekMapMemory(CaveSpriteRAM, 0x400000, 0x40FFFF, SM_RAM);
|
||||
SekMapMemory(CaveTileRAM[0], 0x500000, 0x507FFF, SM_RAM);
|
||||
|
||||
SekMapMemory(CavePalSrc, 0x800000, 0x80FFFF, SM_ROM); // Palette RAM (write goes through handler)
|
||||
SekMapHandler(1, 0x800000, 0x80FFFF, SM_WRITE); //
|
||||
|
||||
SekSetReadWordHandler(0, uopokoReadWord);
|
||||
SekSetReadByteHandler(0, uopokoReadByte);
|
||||
SekSetWriteWordHandler(0, uopokoWriteWord);
|
||||
SekSetWriteByteHandler(0, uopokoWriteByte);
|
||||
|
||||
SekSetWriteWordHandler(1,uopokoWriteWordPalette);
|
||||
SekSetWriteByteHandler(1, uopokoWriteBytePalette);
|
||||
|
||||
SekClose();
|
||||
}
|
||||
|
||||
nCaveRowModeOffset = 1;
|
||||
|
||||
CavePalInit(0x8000);
|
||||
CaveTileInit();
|
||||
CaveSpriteInit(1, 0x800000);
|
||||
CaveTileInitLayer(0, 0x400000, 8, 0x4000);
|
||||
|
||||
YMZ280BInit(16934400, &TriggerSoundIRQ, 3);
|
||||
|
||||
bDrawScreen = true;
|
||||
|
||||
DrvDoReset(); // Reset machine
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rom information
|
||||
static struct BurnRomInfo uopokoRomDesc[] = {
|
||||
{ "u26.int", 0x080000, 0xb445c9ac, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "u25.int", 0x080000, 0xa1258482, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "u33.bin", 0x400000, 0x5D142Ad2, BRF_GRA }, // 2 Sprite data
|
||||
|
||||
{ "u49.bin", 0x400000, 0x12FB11BB, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
|
||||
{ "u4.bin", 0x200000, 0xA2D0D755, BRF_SND }, // 4 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-uopoko.bin", 0x0080, 0xf4a24b95, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(uopoko)
|
||||
STD_ROM_FN(uopoko)
|
||||
|
||||
static struct BurnRomInfo uopokojRomDesc[] = {
|
||||
{ "u26.bin", 0x080000, 0xE7EEC050, BRF_ESS | BRF_PRG }, // 0 CPU #0 code
|
||||
{ "u25.bin", 0x080000, 0x68CB6211, BRF_ESS | BRF_PRG }, // 1
|
||||
|
||||
{ "u33.bin", 0x400000, 0x5D142Ad2, BRF_GRA }, // 2 Sprite data
|
||||
|
||||
{ "u49.bin", 0x400000, 0x12FB11BB, BRF_GRA }, // 3 Layer 0 Tile data
|
||||
|
||||
{ "u4.bin", 0x200000, 0xA2D0D755, BRF_SND }, // 4 YMZ280B (AD)PCM data
|
||||
|
||||
{ "eeprom-uopoko.bin", 0x0080, 0xf4a24b95, BRF_OPT },
|
||||
};
|
||||
|
||||
|
||||
STD_ROM_PICK(uopokoj)
|
||||
STD_ROM_FN(uopokoj)
|
||||
|
||||
struct BurnDriver BurnDrvUoPoko = {
|
||||
"uopoko", NULL, NULL, NULL, "1999",
|
||||
"Puzzle Uo Poko (International, ver. 98/02/06)\0", NULL, "Cave / Jaleco", "Cave",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_PUZZLE, 0,
|
||||
NULL, uopokoRomInfo, uopokoRomName, NULL, NULL, uopokoInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 240, 4, 3
|
||||
};
|
||||
|
||||
struct BurnDriver BurnDrvUoPokoj = {
|
||||
"uopokoj", "uopoko", NULL, NULL, "1999",
|
||||
"Puzzle Uo Poko (Japan, ver. 98/02/06)\0", NULL, "Cave / Jaleco", "Cave",
|
||||
L"\u30D1\u30BA\u30EB \u9B5A\u30DD\u30B3 \u3046\u304A\u307D\u3053 (Japan, ver. 98/02/06)\0Puzzle Uo Poko\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_16BIT_ONLY, 2, HARDWARE_CAVE_68K_ONLY, GBF_PUZZLE, 0,
|
||||
NULL, uopokojRomInfo, uopokojRomName, NULL, NULL, uopokoInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
|
||||
&CaveRecalcPalette, 0x8000, 320, 240, 4, 3
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include "burnint.h"
|
||||
|
||||
#ifndef HARDWARE_CAPCOM_CPS3
|
||||
#define HARDWARE_CAPCOM_CPS3 HARDWARE_MISC_MISC
|
||||
#endif
|
||||
|
||||
#ifndef HARDWARE_CAPCOM_CPS3_NO_CD
|
||||
#define HARDWARE_CAPCOM_CPS3_NO_CD HARDWARE_CAPCOM_CPS3
|
||||
#endif
|
||||
|
||||
extern UINT8 cps3_reset;
|
||||
extern UINT8 cps3_palette_change;
|
||||
|
||||
extern UINT16 *Cps3CurPal;
|
||||
|
||||
extern UINT32 cps3_key1, cps3_key2, cps3_isSpecial;
|
||||
extern UINT32 cps3_bios_test_hack, cps3_game_test_hack;
|
||||
extern UINT32 cps3_speedup_ram_address, cps3_speedup_code_address;
|
||||
extern UINT8 cps3_dip;
|
||||
extern UINT32 cps3_region_address, cps3_ncd_address;
|
||||
|
||||
extern UINT8 Cps3But1[16];
|
||||
extern UINT8 Cps3But2[16];
|
||||
extern UINT8 Cps3But3[16];
|
||||
|
||||
INT32 cps3Init();
|
||||
INT32 cps3Exit();
|
||||
INT32 cps3Frame();
|
||||
INT32 cps3Scan(INT32 nAction,INT32 *pnMin);
|
||||
|
||||
// sound
|
||||
|
||||
UINT8 __fastcall cps3SndReadByte(UINT32 addr);
|
||||
UINT16 __fastcall cps3SndReadWord(UINT32 addr);
|
||||
UINT32 __fastcall cps3SndReadLong(UINT32 addr);
|
||||
|
||||
void __fastcall cps3SndWriteByte(UINT32 addr, UINT8 data);
|
||||
void __fastcall cps3SndWriteWord(UINT32 addr, UINT16 data);
|
||||
void __fastcall cps3SndWriteLong(UINT32 addr, UINT32 data);
|
||||
|
||||
INT32 cps3SndInit(UINT8 *);
|
||||
void cps3SndReset();
|
||||
void cps3SndExit();
|
||||
void cps3SndUpdate();
|
||||
|
||||
INT32 cps3SndScan(INT32);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,215 @@
|
|||
#include "cps3.h"
|
||||
|
||||
#define CPS3_VOICES 16
|
||||
|
||||
#define CPS3_SND_INT_RATE (nBurnFPS / 100)
|
||||
#define CPS3_SND_RATE (42954500 / 3 / 384)
|
||||
#define CPS3_SND_BUFFER_SIZE (CPS3_SND_RATE / CPS3_SND_INT_RATE)
|
||||
#define CPS3_SND_LINEAR_SHIFT 12
|
||||
|
||||
typedef struct {
|
||||
UINT16 regs[16];
|
||||
UINT32 pos;
|
||||
UINT16 frac;
|
||||
} cps3_voice;
|
||||
|
||||
typedef struct {
|
||||
cps3_voice voice[CPS3_VOICES];
|
||||
UINT16 key;
|
||||
|
||||
UINT8 * rombase;
|
||||
UINT32 delta;
|
||||
|
||||
} cps3snd_chip;
|
||||
|
||||
static cps3snd_chip * chip;
|
||||
|
||||
UINT8 __fastcall cps3SndReadByte(UINT32 addr)
|
||||
{
|
||||
addr &= 0x000003ff;
|
||||
bprintf(PRINT_NORMAL, _T("SND Attempt to read byte value of location %8x\n"), addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 __fastcall cps3SndReadWord(UINT32 addr)
|
||||
{
|
||||
addr &= 0x000003ff;
|
||||
|
||||
if (addr < 0x200) {
|
||||
return chip->voice[addr >> 5].regs[(addr>>1) & 0xf];
|
||||
} else
|
||||
if (addr == 0x200) {
|
||||
return chip->key;
|
||||
} else
|
||||
|
||||
bprintf(PRINT_NORMAL, _T("SND Attempt to read word value of location %8x\n"), addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 __fastcall cps3SndReadLong(UINT32 addr)
|
||||
{
|
||||
addr &= 0x000003ff;
|
||||
|
||||
bprintf(PRINT_NORMAL, _T("SND Attempt to read long value of location %8x\n"), addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall cps3SndWriteByte(UINT32 addr, UINT8 data)
|
||||
{
|
||||
addr &= 0x000003ff;
|
||||
bprintf(PRINT_NORMAL, _T("SND Attempt to write byte value %2x to location %8x\n"), data, addr);
|
||||
}
|
||||
|
||||
void __fastcall cps3SndWriteWord(UINT32 addr, UINT16 data)
|
||||
{
|
||||
addr &= 0x000003ff;
|
||||
|
||||
if (addr < 0x200) {
|
||||
chip->voice[addr >> 5].regs[(addr>>1) & 0xf] = data;
|
||||
//bprintf(PRINT_NORMAL, _T("SND Attempt to write word value %4x to Chip[%02d][%02d] %s\n"), data, addr >> 5, (addr>>2) & 7, (addr & 0x02) ? "lo" : "hi" );
|
||||
} else
|
||||
if (addr == 0x200) {
|
||||
UINT16 key = data;
|
||||
for (INT32 i = 0; i < CPS3_VOICES; i++) {
|
||||
// Key off -> Key on
|
||||
if ((key & (1 << i)) && !(chip->key & (1 << i))) {
|
||||
chip->voice[i].frac = 0;
|
||||
chip->voice[i].pos = 0;
|
||||
}
|
||||
}
|
||||
chip->key = key;
|
||||
} else
|
||||
bprintf(PRINT_NORMAL, _T("SND Attempt to write word value %4x to location %8x\n"), data, addr);
|
||||
|
||||
}
|
||||
|
||||
void __fastcall cps3SndWriteLong(UINT32 addr, UINT32 data)
|
||||
{
|
||||
//addr &= 0x000003ff;
|
||||
bprintf(PRINT_NORMAL, _T("SND Attempt to write long value %8x to location %8x\n"), data, addr);
|
||||
}
|
||||
|
||||
INT32 cps3SndInit(UINT8 * sndrom)
|
||||
{
|
||||
chip = (cps3snd_chip *) malloc( sizeof(cps3snd_chip) );
|
||||
if ( chip ) {
|
||||
memset( chip, 0, sizeof(cps3snd_chip) );
|
||||
chip->rombase = sndrom;
|
||||
|
||||
/*
|
||||
* CPS-3 Sound chip clock: 42954500 / 3 / 384 = 37286.89
|
||||
* Sound interupt 80Hz
|
||||
*/
|
||||
|
||||
if (nBurnSoundRate) {
|
||||
//chip->delta = 37286.9 / nBurnSoundRate;
|
||||
chip->delta = (CPS3_SND_BUFFER_SIZE << CPS3_SND_LINEAR_SHIFT) / nBurnSoundLen;
|
||||
//bprintf(0, _T("BurnSnd %08x, %d, %d\n"), chip->delta, chip->burnlen, nBurnSoundLen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cps3SndReset()
|
||||
{
|
||||
}
|
||||
|
||||
void cps3SndExit()
|
||||
{
|
||||
if (chip) {
|
||||
free( chip );
|
||||
chip = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void cps3SndUpdate()
|
||||
{
|
||||
if (!pBurnSoundOut) {
|
||||
// TODO: ???
|
||||
// chip->key = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(pBurnSoundOut, 0, nBurnSoundLen * 2 * 2 );
|
||||
INT8 * base = (INT8 *)chip->rombase;
|
||||
cps3_voice *vptr = &chip->voice[0];
|
||||
|
||||
for(INT32 i=0; i<CPS3_VOICES; i++, vptr++) {
|
||||
if (chip->key & (1 << i)) {
|
||||
|
||||
UINT32 start = ((vptr->regs[ 3] << 16) | vptr->regs[ 2]) - 0x400000;
|
||||
UINT32 end = ((vptr->regs[11] << 16) | vptr->regs[10]) - 0x400000;
|
||||
UINT32 loop = ((vptr->regs[ 9] << 16) | vptr->regs[ 7]) - 0x400000;
|
||||
UINT32 step = ( vptr->regs[ 6] * chip->delta ) >> CPS3_SND_LINEAR_SHIFT;
|
||||
|
||||
//INT32 vol_l = ((signed short)vptr->regs[15] * 12) >> 4;
|
||||
//INT32 vol_r = ((signed short)vptr->regs[14] * 12) >> 4;
|
||||
INT32 vol_l = (INT16)vptr->regs[15];
|
||||
INT32 vol_r = (INT16)vptr->regs[14];
|
||||
|
||||
UINT32 pos = vptr->pos;
|
||||
UINT32 frac = vptr->frac;
|
||||
|
||||
/* Go through the buffer and add voice contributions */
|
||||
INT16 * buffer = (INT16 *)pBurnSoundOut;
|
||||
|
||||
for (INT32 j=0; j<nBurnSoundLen; j++) {
|
||||
INT32 sample;
|
||||
|
||||
pos += (frac >> 12);
|
||||
frac &= 0xfff;
|
||||
|
||||
if (start + pos >= end) {
|
||||
if (vptr->regs[5]) {
|
||||
pos = loop - start;
|
||||
} else {
|
||||
chip->key &= ~(1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 8bit sample store with 16bit bigend ???
|
||||
sample = base[(start + pos) ^ 1];
|
||||
frac += step;
|
||||
|
||||
#if 1
|
||||
INT32 sample_l;
|
||||
|
||||
sample_l = ((sample * vol_r) >> 8) + buffer[0];
|
||||
if (sample_l > 32767) buffer[0] = 32767;
|
||||
else if (sample_l < -32768) buffer[0] = -32768;
|
||||
else buffer[0] = sample_l;
|
||||
|
||||
sample_l = ((sample * vol_l) >> 8) + buffer[1];
|
||||
if (sample_l > 32767) buffer[1] = 32767;
|
||||
else if (sample_l < -32768) buffer[1] = -32768;
|
||||
else buffer[1] = sample_l;
|
||||
#else
|
||||
buffer[0] += (sample * (vol_l >> 8));
|
||||
buffer[1] += (sample * (vol_r >> 8));
|
||||
#endif
|
||||
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
|
||||
vptr->pos = pos;
|
||||
vptr->frac = frac;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
INT32 cps3SndScan(INT32 nAction)
|
||||
{
|
||||
if (nAction & ACB_DRIVER_DATA) {
|
||||
|
||||
SCAN_VAR( chip->voice );
|
||||
SCAN_VAR( chip->key );
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,343 @@
|
|||
// A module for keeping parents who have no driver in FBA
|
||||
|
||||
#include "burnint.h"
|
||||
|
||||
static UINT8 ParentReset = 0;
|
||||
|
||||
static struct BurnInputInfo ParentInputList[] = {
|
||||
{"Reset" , BIT_DIGITAL , &ParentReset , "reset" },
|
||||
};
|
||||
|
||||
STDINPUTINFO(Parent)
|
||||
|
||||
static INT32 ParentInit()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static INT32 ParentExit()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct BurnRomInfo BagmanRomDesc[] = {
|
||||
{ "e9_b05.bin", 0x01000, 0xe0156191, BRF_ESS | BRF_PRG },
|
||||
{ "f9_b06.bin", 0x01000, 0x7b758982, BRF_ESS | BRF_PRG },
|
||||
{ "f9_b07.bin", 0x01000, 0x302a077b, BRF_ESS | BRF_PRG },
|
||||
{ "k9_b08.bin", 0x01000, 0xf04293cb, BRF_ESS | BRF_PRG },
|
||||
{ "m9_b09s.bin", 0x01000, 0x68e83e4f, BRF_ESS | BRF_PRG },
|
||||
{ "n9_b10.bin", 0x01000, 0x1d6579f7, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "e1_b02.bin", 0x01000, 0x4a0a6b55, BRF_ESS | BRF_PRG },
|
||||
{ "j1_b04.bin", 0x01000, 0xc680ef04, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "c1_b01.bin", 0x01000, 0x705193b2, BRF_ESS | BRF_PRG },
|
||||
{ "f1_b03s.bin", 0x01000, 0xdba1eda7, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "p3.bin", 0x00020, 0x2a855523, BRF_GRA },
|
||||
{ "r3.bin", 0x00020, 0xae6f1019, BRF_GRA },
|
||||
{ "r6.bin", 0x00020, 0xc58a4f6a, BRF_GRA },
|
||||
|
||||
{ "r9_b11.bin", 0x01000, 0x2e0057ff, BRF_SND },
|
||||
{ "t9_b12.bin", 0x01000, 0xb2120edd, BRF_SND },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Bagman)
|
||||
STD_ROM_FN(Bagman)
|
||||
|
||||
struct BurnDriver BurnDrvBagman = {
|
||||
"bagman", NULL, NULL, NULL, "1982",
|
||||
"Bagman\0", "Parent set for working drivers", "Valadon Automation", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0,
|
||||
NULL, BagmanRomInfo, BagmanRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 224, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo CkongRomDesc[] = {
|
||||
{ "falcon7", 0x01000, 0x2171cac3, BRF_ESS | BRF_PRG },
|
||||
{ "falcon8", 0x01000, 0x88b83ff7, BRF_ESS | BRF_PRG },
|
||||
{ "falcon9", 0x01000, 0xcff2af47, BRF_ESS | BRF_PRG },
|
||||
{ "falcon10", 0x01000, 0x6b2ecf23, BRF_ESS | BRF_PRG },
|
||||
{ "falcon11", 0x01000, 0x327dcadf, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "falcon6", 0x01000, 0xa8916dc8, BRF_GRA },
|
||||
{ "falcon5", 0x01000, 0xcd3b5dde, BRF_GRA },
|
||||
{ "falcon4", 0x01000, 0xb62a0367, BRF_GRA },
|
||||
{ "falcon3", 0x01000, 0x61122c5e, BRF_GRA },
|
||||
|
||||
{ "falcon2", 0x00800, 0xf67c80f1, BRF_GRA },
|
||||
{ "falcon1", 0x00800, 0x80eb517d, BRF_GRA },
|
||||
|
||||
{ "ck6v.bin", 0x00020, 0x751c3325, BRF_GRA },
|
||||
{ "ck6u.bin", 0x00020, 0xab1940fa, BRF_GRA },
|
||||
{ "ck6t.bin", 0x00020, 0xb4e827a5, BRF_GRA },
|
||||
|
||||
{ "falcon13", 0x01000, 0x5f0bcdfb, BRF_SND },
|
||||
{ "falcon12", 0x01000, 0x9003ffbd, BRF_SND },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Ckong)
|
||||
STD_ROM_FN(Ckong)
|
||||
|
||||
struct BurnDriver BurnDrvCkong = {
|
||||
"ckong", NULL, NULL, NULL, "1981",
|
||||
"Crazy Kong Part II (set 1)\0", "Parent set for working drivers", "Falcon", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0,
|
||||
NULL, CkongRomInfo, CkongRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 224, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo DkongjrRomDesc[] = {
|
||||
{ "dkj.5b", 0x02000, 0xdea28158, BRF_ESS | BRF_PRG },
|
||||
{ "dkj.5c", 0x02000, 0x6fb5faf6, BRF_ESS | BRF_PRG },
|
||||
{ "dkj.5e", 0x02000, 0xd042b6a8, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "c_3h.bin", 0x01000, 0x715da5f8, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "dkj.3n", 0x01000, 0x8d51aca9, BRF_ESS | BRF_PRG },
|
||||
{ "dkj.3p", 0x01000, 0x4ef64ba5, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "v_7c.bin", 0x00800, 0xdc7f4164, BRF_ESS | BRF_PRG },
|
||||
{ "v_7d.bin", 0x00800, 0x0ce7dcf6, BRF_ESS | BRF_PRG },
|
||||
{ "v_7e.bin", 0x00800, 0x24d1ff17, BRF_ESS | BRF_PRG },
|
||||
{ "v_7f.bin", 0x00800, 0x0f8c083f, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "c-2e.bpr", 0x00100, 0x463dc7ad, BRF_GRA },
|
||||
{ "c-2f.bpr", 0x00100, 0x47ba0042, BRF_GRA },
|
||||
{ "v-2n.bpr", 0x00100, 0xdbf185bf, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Dkongjr)
|
||||
STD_ROM_FN(Dkongjr)
|
||||
|
||||
struct BurnDriver BurnDrvDkongjr = {
|
||||
"dkongjr", NULL, NULL, NULL, "1982",
|
||||
"Donkey Kong Junior (US)\0", "Parent set for working drivers", "Nintendo of America", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0,
|
||||
NULL, DkongjrRomInfo, DkongjrRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 224, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo DockmanRomDesc[] = {
|
||||
{ "pe1.19", 0x01000, 0xeef2ec54, BRF_ESS | BRF_PRG },
|
||||
{ "pe2.18", 0x01000, 0xbc48d16b, BRF_ESS | BRF_PRG },
|
||||
{ "pe3.17", 0x01000, 0x1c923057, BRF_ESS | BRF_PRG },
|
||||
{ "pe4.16", 0x01000, 0x23af1cba, BRF_ESS | BRF_PRG },
|
||||
{ "pe5.15", 0x01000, 0x39dbe429, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "pe7.22", 0x00800, 0xd2094e4a, BRF_ESS | BRF_PRG },
|
||||
{ "pe6.23", 0x00800, 0x1cf447f4, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "pe8.9", 0x01000, 0x4d8c2974, BRF_GRA },
|
||||
{ "pe9.8", 0x01000, 0x4e4ea162, BRF_GRA },
|
||||
|
||||
{ "mb7051.3", 0x00020, 0x6440dc61, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Dockman)
|
||||
STD_ROM_FN(Dockman)
|
||||
|
||||
struct BurnDriver BurnDrvDockman = {
|
||||
"dockman", NULL, NULL, NULL, "1982",
|
||||
"Dock Man\0", "Parent set for working drivers", "Taito Corporation", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0,
|
||||
NULL, DockmanRomInfo, DockmanRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 224, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo EightballactRomDesc[] = {
|
||||
{ "8b-dk.5e", 0x01000, 0x166c1c9b, BRF_ESS | BRF_PRG },
|
||||
{ "8b-dk.5c", 0x01000, 0x9ec87baa, BRF_ESS | BRF_PRG },
|
||||
{ "8b-dk.5b", 0x01000, 0xf836a962, BRF_ESS | BRF_PRG },
|
||||
{ "8b-dk.5a", 0x01000, 0xd45866d4, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "8b-dk.3h", 0x00800, 0xa8752c60, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "8b-dk.3n", 0x00800, 0x44830867, BRF_GRA },
|
||||
{ "8b-dk.3p", 0x00800, 0x6148c6f2, BRF_GRA },
|
||||
|
||||
{ "8b-dk.7c", 0x00800, 0xe34409f5, BRF_GRA },
|
||||
{ "8b-dk.7d", 0x00800, 0xb4dc37ca, BRF_GRA },
|
||||
{ "8b-dk.7e", 0x00800, 0x655af8a8, BRF_GRA },
|
||||
{ "8b-dk.7f", 0x00800, 0xa29b2763, BRF_GRA },
|
||||
|
||||
{ "8b.2e", 0x00100, 0xc7379a12, BRF_GRA },
|
||||
{ "8b.2f", 0x00100, 0x116612b4, BRF_GRA },
|
||||
{ "8b.2n", 0x00100, 0x30586988, BRF_GRA },
|
||||
|
||||
{ "82s147.prm", 0x00200, 0x46e5bc92, BRF_GRA },
|
||||
|
||||
{ "pls153h.bin", 0x000eb, 0x00000000, BRF_NODUMP },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Eightballact)
|
||||
STD_ROM_FN(Eightballact)
|
||||
|
||||
struct BurnDriver BurnDrvEightballact = {
|
||||
"8ballact", NULL, NULL, NULL, "1984",
|
||||
"Eight Ball Action (DK conversion)\0", "Parent set for working drivers", "Seatongrove Ltd (Magic Eletronics USA licence)", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0,
|
||||
NULL, EightballactRomInfo, EightballactRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 256, 224, 4, 3
|
||||
};
|
||||
|
||||
static struct BurnRomInfo HunchbakRomDesc[] = {
|
||||
{ "hb-gp1.bin", 0x01000, 0xaf801d54, BRF_ESS | BRF_PRG },
|
||||
{ "hb-gp2.bin", 0x01000, 0xb448cc8e, BRF_ESS | BRF_PRG },
|
||||
{ "hb-gp3.bin", 0x01000, 0x57c6ea7b, BRF_ESS | BRF_PRG },
|
||||
{ "hb-gp4.bin", 0x01000, 0x7f91287b, BRF_ESS | BRF_PRG },
|
||||
{ "hb-gp5.bin", 0x01000, 0x1dd5755c, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "6c.sdp1", 0x01000, 0xf9ba2854, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "8a.sp1", 0x00800, 0xed1cd201, BRF_SND },
|
||||
|
||||
{ "11a.cp1", 0x00800, 0xf256b047, BRF_GRA },
|
||||
{ "10a.cp2", 0x00800, 0xb870c64f, BRF_GRA },
|
||||
{ "9a.cp3", 0x00800, 0x9a7dab88, BRF_GRA },
|
||||
|
||||
{ "5b.bin", 0x00800, 0xf055a624, BRF_SND },
|
||||
|
||||
{ "82s185.10h", 0x00800, 0xc205bca6, BRF_GRA },
|
||||
{ "82s123.10k", 0x00020, 0xb5221cec, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Hunchbak)
|
||||
STD_ROM_FN(Hunchbak)
|
||||
|
||||
struct BurnDriver BurnDrvHunchbak = {
|
||||
"hunchbak", NULL, NULL, NULL, "1983",
|
||||
"Hunchback (set 1)\0", "Parent set for working drivers", "Century Electronics", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0,
|
||||
NULL, HunchbakRomInfo, HunchbakRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 224, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo HuncholyRomDesc[] = {
|
||||
{ "ho-gp1.bin", 0x01000, 0x4f17cda7, BRF_ESS | BRF_PRG },
|
||||
{ "ho-gp2.bin", 0x01000, 0x70fa52c7, BRF_ESS | BRF_PRG },
|
||||
{ "ho-gp3.bin", 0x01000, 0x931934b1, BRF_ESS | BRF_PRG },
|
||||
{ "ho-gp4.bin", 0x01000, 0xaf5cd501, BRF_ESS | BRF_PRG },
|
||||
{ "ho-gp5.bin", 0x01000, 0x658e8974, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "ho-sdp1.bin", 0x01000, 0x3efb3ffd, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "ho-sp1.bin", 0x01000, 0x3fd39b1e, BRF_SND },
|
||||
|
||||
{ "ho-cp1.bin", 0x00800, 0xc6c73d46, BRF_GRA },
|
||||
{ "ho-cp2.bin", 0x00800, 0xe596371c, BRF_GRA },
|
||||
{ "ho-cp3.bin", 0x00800, 0x11fae1cf, BRF_GRA },
|
||||
|
||||
{ "5b.bin", 0x00800, 0xf055a624, BRF_SND },
|
||||
|
||||
{ "82s185.10h", 0x00800, 0xc205bca6, BRF_GRA },
|
||||
{ "82s123.10k", 0x00020, 0xb5221cec, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Huncholy)
|
||||
STD_ROM_FN(Huncholy)
|
||||
|
||||
struct BurnDriver BurnDrvHuncholy = {
|
||||
"huncholy", NULL, NULL, NULL, "1984",
|
||||
"Hunchback Olympic\0", "Parent set for working drivers", "Seatongrove Ltd", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0,
|
||||
NULL, HuncholyRomInfo, HuncholyRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 224, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo ManiacsqRomDesc[] = {
|
||||
{ "d8-d15.1m", 0x20000, 0x9121d1b6, BRF_ESS | BRF_PRG },
|
||||
{ "d0-d7.1m", 0x20000, 0xa95cfd2a, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "d0-d7.4m", 0x80000, 0xd8551b2f, BRF_GRA },
|
||||
{ "d8-d15.4m", 0x80000, 0xb269c427, BRF_GRA },
|
||||
{ "d16-d23.1m", 0x20000, 0xaf4ea5e7, BRF_GRA },
|
||||
{ "d24-d31.1m", 0x20000, 0x578c3588, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Maniacsq)
|
||||
STD_ROM_FN(Maniacsq)
|
||||
|
||||
struct BurnDriver BurnDrvManiacsq = {
|
||||
"maniacsq", NULL, NULL, NULL, "1996",
|
||||
"Maniac Square (unprotected)\0", "Parent set for working drivers", "Gaelco", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0,
|
||||
NULL, ManiacsqRomInfo, ManiacsqRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 256, 224, 4, 3
|
||||
};
|
||||
|
||||
static struct BurnRomInfo PhoenixRomDesc[] = {
|
||||
{ "ic45", 0x00800, 0x9f68086b, BRF_ESS | BRF_PRG },
|
||||
{ "ic46", 0x00800, 0x273a4a82, BRF_ESS | BRF_PRG },
|
||||
{ "ic47", 0x00800, 0x3d4284b9, BRF_ESS | BRF_PRG },
|
||||
{ "ic48", 0x00800, 0xcb5d9915, BRF_ESS | BRF_PRG },
|
||||
{ "h5-ic49.5a", 0x00800, 0xa105e4e7, BRF_ESS | BRF_PRG },
|
||||
{ "h6-ic50.6a", 0x00800, 0xac5e9ec1, BRF_ESS | BRF_PRG },
|
||||
{ "h7-ic51.7a", 0x00800, 0x2eab35b4, BRF_ESS | BRF_PRG },
|
||||
{ "h8-ic52.8a", 0x00800, 0xaff8e9c5, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "ic23.3d", 0x00800, 0x3c7e623f, BRF_GRA },
|
||||
{ "ic24.4d", 0x00800, 0x59916d3b, BRF_GRA },
|
||||
{ "b1-ic39.3b", 0x00800, 0x53413e8f, BRF_GRA },
|
||||
{ "b2-ic40.4b", 0x00800, 0x0be2ba91, BRF_GRA },
|
||||
|
||||
{ "mmi6301.ic40", 0x00100, 0x79350b25, BRF_GRA },
|
||||
{ "mmi6301.ic41", 0x00100, 0xe176b768, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Phoenix)
|
||||
STD_ROM_FN(Phoenix)
|
||||
|
||||
struct BurnDriver BurnDrvPhoenix = {
|
||||
"phoenix", NULL, NULL, NULL, "1980",
|
||||
"Phoenix (Amstar)\0", "Parent set for working drivers", "Amstar", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0,
|
||||
NULL, PhoenixRomInfo, PhoenixRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 208, 256, 3, 4
|
||||
};
|
||||
|
||||
static struct BurnRomInfo ThepitRomDesc[] = {
|
||||
{ "pit1.bin", 0x01000, 0x71affecc, BRF_ESS | BRF_PRG },
|
||||
{ "pit2.bin", 0x01000, 0x894063cd, BRF_ESS | BRF_PRG },
|
||||
{ "pit3.bin", 0x01000, 0x1b488543, BRF_ESS | BRF_PRG },
|
||||
{ "pit4.bin", 0x01000, 0xe941e848, BRF_ESS | BRF_PRG },
|
||||
{ "pit5.bin", 0x01000, 0xe0643c95, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "pit6.bin", 0x00800, 0x1b79dfb6, BRF_ESS | BRF_PRG },
|
||||
|
||||
{ "pit8.bin", 0x00800, 0x69502afc, BRF_GRA },
|
||||
{ "pit7.bin", 0x00800, 0xd901b353, BRF_GRA },
|
||||
|
||||
{ "82s123.ic4", 0x00020, 0xa758b567, BRF_GRA },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(Thepit)
|
||||
STD_ROM_FN(Thepit)
|
||||
|
||||
struct BurnDriver BurnDrvThepit = {
|
||||
"thepit", NULL, NULL, NULL, "1992",
|
||||
"The Pit\0", "Parent set for working drivers", "Taito", "Miscellaneous",
|
||||
NULL, NULL, NULL, NULL,
|
||||
0, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0,
|
||||
NULL, ThepitRomInfo, ThepitRomName, NULL, NULL, ParentInputInfo, NULL,
|
||||
ParentInit, ParentExit, NULL, NULL, NULL,
|
||||
NULL, 0, 256, 224, 4, 3
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,316 @@
|
|||
#include "tiles_generic.h"
|
||||
#include "dac.h"
|
||||
#include "8255ppi.h"
|
||||
#include "bitswap.h"
|
||||
#include "s2650_intf.h"
|
||||
#include "sn76496.h"
|
||||
|
||||
#include "driver.h"
|
||||
extern "C" {
|
||||
#include "ay8910.h"
|
||||
}
|
||||
|
||||
// ROM types
|
||||
#define GAL_ROM_Z80_PROG1 1
|
||||
#define GAL_ROM_Z80_PROG2 2
|
||||
#define GAL_ROM_Z80_PROG3 3
|
||||
#define GAL_ROM_TILES_SHARED 4
|
||||
#define GAL_ROM_TILES_CHARS 5
|
||||
#define GAL_ROM_TILES_SPRITES 6
|
||||
#define GAL_ROM_PROM 7
|
||||
#define GAL_ROM_S2650_PROG1 8
|
||||
|
||||
#define GAL_ROM_OFFSET_Z80_PROG2 GalZ80Rom1Num
|
||||
#define GAL_ROM_OFFSET_Z80_PROG3 GalZ80Rom1Num + GalZ80Rom2Num
|
||||
#define GAL_ROM_OFFSET_TILES_SHARED GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num
|
||||
#define GAL_ROM_OFFSET_TILES_CHARS GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum
|
||||
#define GAL_ROM_OFFSET_TILES_SPRITES GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum + GalTilesCharRomNum
|
||||
#define GAL_ROM_OFFSET_PROM GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum + GalTilesCharRomNum + GalTilesSpriteRomNum
|
||||
#define GAL_ROM_OFFSET_S2650_PROG1 GalZ80Rom1Num + GalZ80Rom2Num + GalZ80Rom3Num + GalTilesSharedRomNum + GalTilesCharRomNum + GalTilesSpriteRomNum + GalPromRomNum
|
||||
|
||||
// IRQ types
|
||||
#define GAL_IRQ_TYPE_NMI 1
|
||||
#define GAL_IRQ_TYPE_IRQ0 2
|
||||
|
||||
// Sound hardware types
|
||||
#define GAL_SOUND_HARDWARE_TYPE_GALAXIAN 1
|
||||
#define GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 2
|
||||
#define GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 3
|
||||
#define GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 4
|
||||
#define GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 5
|
||||
#define GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 6
|
||||
#define GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC 7
|
||||
#define GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 8
|
||||
#define GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 9
|
||||
#define GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 10
|
||||
#define GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 11
|
||||
#define GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC 12
|
||||
#define GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 13
|
||||
#define GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 14
|
||||
#define GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496 15
|
||||
#define GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496 16
|
||||
#define GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910 17
|
||||
|
||||
// Palette Numbers
|
||||
#define GAL_PALETTE_NUM_COLOURS_PROM 64
|
||||
#define GAL_PALETTE_NUM_COLOURS_STARS 64
|
||||
#define GAL_PALETTE_NUM_COLOURS_BULLETS 8
|
||||
#define GAL_PALETTE_NUM_COLOURS_BACKGROUND 256
|
||||
#define GAL_PALETTE_STARS_OFFSET GAL_PALETTE_NUM_COLOURS_PROM
|
||||
#define GAL_PALETTE_BULLETS_OFFSET GAL_PALETTE_NUM_COLOURS_PROM + GAL_PALETTE_NUM_COLOURS_STARS
|
||||
#define GAL_PALETTE_BACKGROUND_OFFSET GAL_PALETTE_NUM_COLOURS_PROM + GAL_PALETTE_NUM_COLOURS_STARS + GAL_PALETTE_NUM_COLOURS_BULLETS
|
||||
|
||||
// gal_gfx.cpp
|
||||
extern UINT8 GalFlipScreenX;
|
||||
extern UINT8 GalFlipScreenY;
|
||||
extern UINT8 *GalGfxBank;
|
||||
extern UINT8 GalPaletteBank;
|
||||
extern UINT8 GalSpriteClipStart;
|
||||
extern UINT8 GalSpriteClipEnd;
|
||||
extern UINT8 FroggerAdjust;
|
||||
extern UINT8 GalBackgroundRed;
|
||||
extern UINT8 GalBackgroundGreen;
|
||||
extern UINT8 GalBackgroundBlue;
|
||||
extern UINT8 GalBackgroundEnable;
|
||||
extern UINT8 SfxTilemap;
|
||||
extern UINT8 GalOrientationFlipX;
|
||||
extern UINT8 GalColourDepth;
|
||||
extern UINT8 DarkplntBulletColour;
|
||||
extern UINT8 DambustrBgColour1;
|
||||
extern UINT8 DambustrBgColour2;
|
||||
extern UINT8 DambustrBgPriority;
|
||||
extern UINT8 DambustrBgSplitLine;
|
||||
extern UINT8 *RockclimTiles;
|
||||
extern UINT16 RockclimScrollX;
|
||||
extern UINT16 RockclimScrollY;
|
||||
extern INT32 CharPlaneOffsets[2];
|
||||
extern INT32 CharXOffsets[8];
|
||||
extern INT32 CharYOffsets[8];
|
||||
extern INT32 SpritePlaneOffsets[2];
|
||||
extern INT32 SpriteXOffsets[16];
|
||||
extern INT32 SpriteYOffsets[16];
|
||||
|
||||
typedef void (*GalRenderBackground)();
|
||||
extern GalRenderBackground GalRenderBackgroundFunction;
|
||||
typedef void (*GalCalcPalette)();
|
||||
extern GalCalcPalette GalCalcPaletteFunction;
|
||||
typedef void (*GalDrawBullet)(INT32, INT32, INT32);
|
||||
extern GalDrawBullet GalDrawBulletsFunction;
|
||||
typedef void (*GalExtendTileInfo)(UINT16*, INT32*, INT32, INT32);
|
||||
extern GalExtendTileInfo GalExtendTileInfoFunction;
|
||||
typedef void (*GalExtendSpriteInfo)(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16*, UINT8*);
|
||||
extern GalExtendSpriteInfo GalExtendSpriteInfoFunction;
|
||||
typedef void (*GalRenderFrame)();
|
||||
extern GalRenderFrame GalRenderFrameFunction;
|
||||
|
||||
void UpperExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void UpperExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void PiscesExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void PiscesExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void Batman2ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void GmgalaxExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void GmgalaxExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void MooncrstExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void MooncrstExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void MoonqsrExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32);
|
||||
void MoonqsrExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void SkybaseExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void SkybaseExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void RockclimExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void JumpbugExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void JumpbugExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void FroggerExtendTileInfo(UINT16*, INT32 *Colour, INT32, INT32);
|
||||
void FroggerExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16*, UINT8 *Colour);
|
||||
void CalipsoExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8 *yFlip, UINT16 *Code, UINT8*);
|
||||
void MshuttleExtendTileInfo(UINT16 *Code, INT32*, INT32 Attr, INT32);
|
||||
void MshuttleExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void Fourin1ExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void Fourin1ExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void DkongjrmExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*);
|
||||
void MarinerExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x);
|
||||
void MimonkeyExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32);
|
||||
void MimonkeyExtendSpriteInfo(const UINT8*, INT32*, INT32*, UINT8*, UINT8*, UINT16 *Code, UINT8*);
|
||||
void DambustrExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x);
|
||||
void Ad2083ExtendTileInfo(UINT16 *Code, INT32 *Colour, INT32 Attr, INT32);
|
||||
void Ad2083ExtendSpriteInfo(const UINT8 *Base, INT32*, INT32*, UINT8 *xFlip, UINT8*, UINT16 *Code, UINT8*);
|
||||
void RacknrolExtendTileInfo(UINT16 *Code, INT32*, INT32, INT32 x);
|
||||
void HardCodeGalaxianPROM();
|
||||
void HardCodeMooncrstPROM();
|
||||
void GalaxianCalcPalette();
|
||||
void RockclimCalcPalette();
|
||||
void MarinerCalcPalette();
|
||||
void StratgyxCalcPalette();
|
||||
void RescueCalcPalette();
|
||||
void MinefldCalcPalette();
|
||||
void DarkplntCalcPalette();
|
||||
void DambustrCalcPalette();
|
||||
void GalaxianDrawBackground();
|
||||
void RockclimDrawBackground();
|
||||
void JumpbugDrawBackground();
|
||||
void FroggerDrawBackground();
|
||||
void TurtlesDrawBackground();
|
||||
void ScrambleDrawBackground();
|
||||
void AnteaterDrawBackground();
|
||||
void MarinerDrawBackground();
|
||||
void StratgyxDrawBackground();
|
||||
void RescueDrawBackground();
|
||||
void MinefldDrawBackground();
|
||||
void DambustrDrawBackground();
|
||||
void GalaxianDrawBullets(INT32 Offs, INT32 x, INT32 y);
|
||||
void TheendDrawBullets(INT32 Offs, INT32 x, INT32 y);
|
||||
void ScrambleDrawBullets(INT32, INT32 x, INT32 y);
|
||||
void MoonwarDrawBullets(INT32, INT32 x, INT32 y);
|
||||
void MshuttleDrawBullets(INT32, INT32 x, INT32 y);
|
||||
void DarkplntDrawBullets(INT32, INT32 x, INT32 y);
|
||||
void DambustrDrawBullets(INT32 Offs, INT32 x, INT32 y);
|
||||
void GalDraw();
|
||||
void DkongjrmRenderFrame();
|
||||
void DambustrRenderFrame();
|
||||
|
||||
// gal_run.cpp
|
||||
extern UINT8 GalInputPort0[8];
|
||||
extern UINT8 GalInputPort1[8];
|
||||
extern UINT8 GalInputPort2[8];
|
||||
extern UINT8 GalInputPort3[8];
|
||||
extern UINT8 GalDip[7];
|
||||
extern UINT8 GalInput[4];
|
||||
extern UINT8 GalReset;
|
||||
extern UINT8 GalFakeDip;
|
||||
extern INT32 GalAnalogPort0;
|
||||
extern INT32 GalAnalogPort1;
|
||||
|
||||
extern UINT8 *GalMem;
|
||||
extern UINT8 *GalMemEnd;
|
||||
extern UINT8 *GalRamStart;
|
||||
extern UINT8 *GalRamEnd;
|
||||
extern UINT8 *GalZ80Rom1;
|
||||
extern UINT8 *GalZ80Rom1Op;
|
||||
extern UINT8 *GalZ80Rom2;
|
||||
extern UINT8 *GalZ80Rom3;
|
||||
extern UINT8 *GalS2650Rom1;
|
||||
extern UINT8 *GalZ80Ram1;
|
||||
extern UINT8 *GalZ80Ram2;
|
||||
extern UINT8 *GalVideoRam;
|
||||
extern UINT8 *GalVideoRam2;
|
||||
extern UINT8 *GalSpriteRam;
|
||||
extern UINT8 *GalScrollVals;
|
||||
extern UINT8 *GalProm;
|
||||
extern UINT8 *GalChars;
|
||||
extern UINT8 *GalSprites;
|
||||
extern UINT8 *GalTempRom;
|
||||
extern UINT32 *GalPalette;
|
||||
extern UINT32 GalZ80Rom1Size;
|
||||
extern UINT32 GalZ80Rom1Num;
|
||||
extern UINT32 GalZ80Rom2Size;
|
||||
extern UINT32 GalZ80Rom2Num;
|
||||
extern UINT32 GalZ80Rom3Size;
|
||||
extern UINT32 GalZ80Rom3Num;
|
||||
extern UINT32 GalS2650Rom1Size;
|
||||
extern UINT32 GalS2650Rom1Num;
|
||||
extern UINT32 GalTilesSharedRomSize;
|
||||
extern UINT32 GalTilesSharedRomNum;
|
||||
extern UINT32 GalTilesCharRomSize;
|
||||
extern UINT32 GalTilesCharRomNum;
|
||||
extern UINT32 GalNumChars;
|
||||
extern UINT32 GalTilesSpriteRomSize;
|
||||
extern UINT32 GalTilesSpriteRomNum;
|
||||
extern UINT32 GalNumSprites;
|
||||
extern UINT32 GalPromRomSize;
|
||||
extern UINT32 GalPromRomNum;
|
||||
|
||||
typedef void (*GalPostLoadCallback)();
|
||||
extern GalPostLoadCallback GalPostLoadCallbackFunction;
|
||||
|
||||
extern UINT8 GalIrqType;
|
||||
extern UINT8 GalIrqFire;
|
||||
extern INT32 nGalCyclesDone[3], nGalCyclesTotal[3];
|
||||
|
||||
extern UINT8 ZigzagAYLatch;
|
||||
extern UINT8 GalSoundLatch;
|
||||
extern UINT8 GalSoundLatch2;
|
||||
extern UINT8 KingballSound;
|
||||
extern UINT8 KonamiSoundControl;
|
||||
extern UINT8 SfxSampleControl;
|
||||
extern UINT8 KingballSpeechDip;
|
||||
extern UINT16 ScrambleProtectionState;
|
||||
extern UINT8 ScrambleProtectionResult;
|
||||
extern UINT8 MoonwarPortSelect;
|
||||
extern UINT8 MshuttleAY8910CS;
|
||||
extern UINT8 GmgalaxSelectedGame;
|
||||
extern UINT8 Fourin1Bank;
|
||||
extern UINT8 GameIsGmgalax;
|
||||
extern UINT8 CavelonBankSwitch;
|
||||
extern UINT8 GalVBlank;
|
||||
|
||||
UINT8 KonamiPPIReadIN0();
|
||||
UINT8 KonamiPPIReadIN1();
|
||||
UINT8 KonamiPPIReadIN2();
|
||||
UINT8 KonamiPPIReadIN3();
|
||||
INT32 GalInit();
|
||||
void MapMooncrst();
|
||||
void MapJumpbug();
|
||||
void MapFrogger();
|
||||
void KonamiPPIInit();
|
||||
void MapTheend();
|
||||
void MapTurtles();
|
||||
void MapScobra();
|
||||
INT32 GalExit();
|
||||
INT32 KonamiExit();
|
||||
INT32 GalFrame();
|
||||
INT32 GalScan(INT32 nAction, INT32 *pnMin);
|
||||
|
||||
// gal_sound.cpp
|
||||
extern INT16* pFMBuffer;
|
||||
extern INT16* pAY8910Buffer[9];
|
||||
extern UINT8 GalSoundType;
|
||||
extern UINT8 GalSoundVolumeShift;
|
||||
extern UINT8 HunchbksSoundIrqFire;
|
||||
extern UINT8 GalLastPort2;
|
||||
extern UINT8 GalShootEnable;
|
||||
extern UINT8 GalNoiseEnable;
|
||||
extern INT32 GalNoiseVolume;
|
||||
extern double GalShootWavePos;
|
||||
extern double GalNoiseWavePos;
|
||||
extern INT32 GalPitch;
|
||||
extern INT32 GalVol;
|
||||
extern INT32 GalLfoVolume[3];
|
||||
extern double GalLfoFreq;
|
||||
extern double GalLfoFreqFrameVar;
|
||||
extern INT32 GalLfoBit[4];
|
||||
|
||||
void GalSoundReset();
|
||||
void GalSoundInit();
|
||||
void GalSoundExit();
|
||||
void GalSoundScan(INT32 nAction, INT32 *pnMin);
|
||||
UINT8 CheckmajPortARead(UINT32);
|
||||
UINT8 BongoDipSwitchRead(UINT32);
|
||||
UINT8 KonamiSoundLatchRead(UINT32);
|
||||
UINT8 KonamiSoundTimerRead(UINT32);
|
||||
UINT8 FroggerSoundTimerRead(UINT32);
|
||||
UINT8 HunchbksSoundTimerRead(UINT32);
|
||||
void KonamiSoundLatchWrite(UINT8 d);
|
||||
void KonamiSoundControlWrite(UINT8 d);
|
||||
void HunchbksSoundControlWrite(UINT8 d);
|
||||
void SfxSoundLatch2Write(UINT32, UINT32 d);
|
||||
void SfxSampleControlWrite(UINT32, UINT32 d);
|
||||
void FroggerSoundInit();
|
||||
void FroggerSoundNoEncryptionInit();
|
||||
void KonamiSoundInit();
|
||||
void HunchbksSoundInit();
|
||||
void GalRenderSoundSamples(INT16 *pSoundBuf, INT32 nLength);
|
||||
void GalaxianSoundWrite(UINT32 Offset, UINT8 d);
|
||||
void GalaxianLfoFreqWrite(UINT32 Offset, UINT8 d);
|
||||
void GalaxianSoundUpdateTimers();
|
||||
|
||||
// gal_stars.cpp
|
||||
extern INT32 GalStarsEnable;
|
||||
extern INT32 GalStarsScrollPos;
|
||||
extern INT32 GalStarsBlinkState;
|
||||
extern INT32 GalBlinkTimerStartFrame;
|
||||
|
||||
void GalInitStars();
|
||||
void GalaxianRenderStarLayer();
|
||||
void JumpbugRenderStarLayer();
|
||||
void ScrambleRenderStarLayer();
|
||||
void MarinerRenderStarLayer();
|
||||
void RescueRenderStarLayer();
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,943 @@
|
|||
#include "gal.h"
|
||||
|
||||
INT16* pFMBuffer;
|
||||
INT16* pAY8910Buffer[9];
|
||||
|
||||
UINT8 GalSoundType;
|
||||
UINT8 GalSoundVolumeShift;
|
||||
UINT8 HunchbksSoundIrqFire;
|
||||
|
||||
#define XTAL 18432000
|
||||
#define RNG_RATE (XTAL / 3)
|
||||
#define NOISE_RATE (XTAL / 3 / 192 / 2 / 2)
|
||||
#define NOISE_LENGTH (NOISE_RATE * 4)
|
||||
#define NOISE_AMPLITUDE (70 * 256)
|
||||
#define SHOOT_VOLUME 0.50f
|
||||
#define SHOOT_SEC 2
|
||||
#define R41__ 100000
|
||||
#define R44__ 10000
|
||||
#define R45__ 22000
|
||||
#define R46__ 10000
|
||||
#define R47__ 2200
|
||||
#define R48__ 2200
|
||||
#define C25__ 0.000001
|
||||
#define C27__ 0.00000001
|
||||
#define C28__ 0.000047
|
||||
#define C29__ 0.00000001
|
||||
#define IC8L3_L 0.2
|
||||
#define IC8L3_H 4.5
|
||||
#define NOISE_L 0.2
|
||||
#define NOISE_H 4.5
|
||||
#define SHOOT_KEYON_TIME 0.1
|
||||
#define NE555_FM_ADJUST_RATE 0.80
|
||||
#define TOOTHSAW_LENGTH 16
|
||||
#define TOOTHSAW_VOLUME 0.36f
|
||||
#define TOOTHSAW_AMPLITUDE (64*256)
|
||||
#define V(r0,r1) 2 * TOOTHSAW_AMPLITUDE * (r0) / (r0 + r1) - TOOTHSAW_AMPLITUDE
|
||||
#define STEPS 16
|
||||
#define LFO_VOLUME 0.06f
|
||||
#define MINFREQ (139 - 139 / 3)
|
||||
#define MAXFREQ (139 + 139 / 3)
|
||||
|
||||
static INT16 *GalNoiseWave;
|
||||
static INT16 *GalShootWave;
|
||||
static UINT32 GalShootLength;
|
||||
static UINT32 GalShootRate;
|
||||
UINT8 GalLastPort2 = 0;
|
||||
UINT8 GalShootEnable;
|
||||
UINT8 GalNoiseEnable;
|
||||
INT32 GalNoiseVolume;
|
||||
double GalShootWavePos;
|
||||
double GalNoiseWavePos;
|
||||
double GalLfoWavePos[3];
|
||||
INT32 GalPitch;
|
||||
INT32 GalVol;
|
||||
static double GalCounter;
|
||||
static INT32 GalCountDown;
|
||||
INT32 GalLfoVolume[3];
|
||||
double GalLfoFreq;
|
||||
double GalLfoFreqFrameVar;
|
||||
INT32 GalLfoBit[4];
|
||||
|
||||
static INT16 GalToneWave[4][TOOTHSAW_LENGTH];
|
||||
|
||||
static const INT16 GalBackgroundWave[32] =
|
||||
{
|
||||
0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
|
||||
0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
|
||||
-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,
|
||||
-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,-0x4000,
|
||||
};
|
||||
|
||||
void GalSoundReset()
|
||||
{
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) {
|
||||
AY8910Reset(0);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
AY8910Reset(0);
|
||||
AY8910Reset(1);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) {
|
||||
AY8910Reset(0);
|
||||
AY8910Reset(1);
|
||||
AY8910Reset(2);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) {
|
||||
DACReset();
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) {
|
||||
GalLastPort2 = 0;
|
||||
GalShootEnable = 0;
|
||||
GalNoiseEnable = 0;
|
||||
GalNoiseVolume = 0;
|
||||
GalShootWavePos = 0;
|
||||
GalNoiseWavePos = 0;
|
||||
GalLfoWavePos[0] = GalLfoWavePos[1] = GalLfoWavePos[2] = 0;
|
||||
GalPitch = 0xff;
|
||||
GalVol = 0;
|
||||
GalCounter = 0;
|
||||
GalCountDown = 0;
|
||||
GalLfoVolume[0] = GalLfoVolume[1] = GalLfoVolume[2] = 0;
|
||||
GalLfoFreq = MAXFREQ;
|
||||
GalLfoFreqFrameVar = 0;
|
||||
GalLfoBit[0] = GalLfoBit[1] = GalLfoBit[2] = GalLfoBit[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GalSoundInit()
|
||||
{
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) {
|
||||
pFMBuffer = (INT16*)malloc(nBurnSoundLen * 3 * sizeof(INT16));
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
pFMBuffer = (INT16*)malloc(nBurnSoundLen * 6 * sizeof(INT16));
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) {
|
||||
pFMBuffer = (INT16*)malloc(nBurnSoundLen * 9 * sizeof(INT16));
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
pAY8910Buffer[0] = pFMBuffer + nBurnSoundLen * 0;
|
||||
pAY8910Buffer[1] = pFMBuffer + nBurnSoundLen * 1;
|
||||
pAY8910Buffer[2] = pFMBuffer + nBurnSoundLen * 2;
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
pAY8910Buffer[3] = pFMBuffer + nBurnSoundLen * 3;
|
||||
pAY8910Buffer[4] = pFMBuffer + nBurnSoundLen * 4;
|
||||
pAY8910Buffer[5] = pFMBuffer + nBurnSoundLen * 5;
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) {
|
||||
pAY8910Buffer[6] = pFMBuffer + nBurnSoundLen * 6;
|
||||
pAY8910Buffer[7] = pFMBuffer + nBurnSoundLen * 7;
|
||||
pAY8910Buffer[8] = pFMBuffer + nBurnSoundLen * 8;
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910) {
|
||||
AY8910Init(0, 1789750, nBurnSoundRate, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) {
|
||||
AY8910Init(0, 1789750, nBurnSoundRate, &BongoDipSwitchRead, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910) {
|
||||
AY8910Init(0, 1620000, nBurnSoundRate, &CheckmajPortARead, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_MSHUTTLEAY8910) {
|
||||
// Port A Write - cclimber_sample_select_w
|
||||
AY8910Init(0, 18432000 / 3 / 4, nBurnSoundRate, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &FroggerSoundTimerRead, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL);
|
||||
AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &KonamiSoundTimerRead, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, &KonamiSoundTimerRead, NULL, NULL, NULL);
|
||||
AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL);
|
||||
AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &KonamiSoundTimerRead, NULL, NULL);
|
||||
AY8910Init(2, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, &KonamiSoundTimerRead, NULL, NULL, NULL);
|
||||
AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, &SfxSoundLatch2Write, &SfxSampleControlWrite);
|
||||
AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &KonamiSoundTimerRead, NULL, NULL);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) {
|
||||
DACInit(0, 0, 1);
|
||||
DACSetVolShift(0, 2);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496) {
|
||||
SN76496Init(0, 18432000 / 3 / 2, 0);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496) {
|
||||
SN76496Init(0, 18432000 / 3 / 2, 0);
|
||||
SN76496Init(1, 18432000 / 3 / 2, 1);
|
||||
SN76496Init(2, 18432000 / 3 / 2, 1);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
AY8910Init(0, 14318000 / 8, nBurnSoundRate, NULL, NULL, NULL, NULL);
|
||||
AY8910Init(1, 14318000 / 8, nBurnSoundRate, &KonamiSoundLatchRead, &HunchbksSoundTimerRead, NULL, NULL);
|
||||
}
|
||||
|
||||
GalSoundVolumeShift = 1;
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) {
|
||||
GalShootEnable = 0;
|
||||
GalShootWavePos = 0;
|
||||
INT32 CountDown, Generator, Bit1, Bit2;
|
||||
|
||||
GalNoiseWave = (INT16*)malloc(NOISE_LENGTH * sizeof(INT16));
|
||||
|
||||
GalShootRate = 22050;
|
||||
GalShootLength = SHOOT_SEC * GalShootRate;
|
||||
GalShootWave = (INT16*)malloc(GalShootLength * sizeof(INT16));
|
||||
|
||||
Generator = 0;
|
||||
CountDown = NOISE_RATE / 2;
|
||||
for (INT32 i = 0; i < NOISE_LENGTH; i++) {
|
||||
CountDown -= RNG_RATE;
|
||||
while (CountDown < 0) {
|
||||
Generator <<= 1;
|
||||
Bit1 = (~Generator >> 17) & 1;
|
||||
Bit2 = (Generator >> 5) & 1;
|
||||
if (Bit1 ^ Bit2) Generator |= 1;
|
||||
CountDown += NOISE_RATE;
|
||||
}
|
||||
GalNoiseWave[i] = ((Generator >> 17) & 1) ? NOISE_AMPLITUDE : -NOISE_AMPLITUDE;
|
||||
}
|
||||
|
||||
double v = 5.0;
|
||||
double vK = (GalShootRate) ? exp(-1 / (R41__ * C25__) / GalShootRate) : 0;
|
||||
double IC8L3 = IC8L3_L;
|
||||
INT32 IC8Lcnt = (INT32)(SHOOT_KEYON_TIME * GalShootRate);
|
||||
double c28v = IC8L3_H - (IC8L3_H - (NOISE_H + NOISE_L) / 2) / (R46__ + R47__ + R48__) * R47__;
|
||||
double c28K = (GalShootRate) ? exp(-1 / (22000 * 0.000047 ) / GalShootRate) : 0;
|
||||
double c29v = IC8L3_H - (IC8L3_H - (NOISE_H + NOISE_L) / 2) / (R46__ + R47__ + R48__) * (R47__ + R48__);
|
||||
double c29K1 = (GalShootRate) ? exp(-1 / (22000 * 0.00000001 ) / GalShootRate) : 0;
|
||||
double c29K2 = (GalShootRate) ? exp(-1 / (100000 * 0.00000001 ) / GalShootRate) : 0;
|
||||
double ne555cnt = 0;
|
||||
double ne555step = (GalShootRate) ? ((1.44 / ((R44__ + R45__ * 2) * C27__)) / GalShootRate) : 0;
|
||||
double ne555duty = (double)(R44__ + R45__) / (R44__ + R45__ * 2);
|
||||
double ne555sr;
|
||||
double ncnt = 0.0;
|
||||
double nstep = (GalShootRate) ? ((double)NOISE_RATE / GalShootRate) : 0;
|
||||
double noise_sh2;
|
||||
|
||||
for (UINT32 i = 0; i < GalShootLength; i++) {
|
||||
noise_sh2 = GalNoiseWave[(INT32)ncnt % NOISE_LENGTH] == NOISE_AMPLITUDE ? NOISE_H : NOISE_L;
|
||||
ncnt += nstep;
|
||||
ne555sr = c29v * NE555_FM_ADJUST_RATE / (5.0 * 2 / 3);
|
||||
ne555cnt += ne555step;
|
||||
if (ne555cnt >= ne555sr) ne555cnt -= ne555sr;
|
||||
if (ne555cnt < ne555sr * ne555duty) {
|
||||
GalShootWave[i] = (INT16)(v / 5 * 0x7fff);
|
||||
if(IC8L3 == IC8L3_H) v *= vK;
|
||||
} else {
|
||||
GalShootWave[i] = 0;
|
||||
}
|
||||
c28v += (IC8L3 - c28v) - (IC8L3 - c28v) * c28K;
|
||||
c28v += (c29v - c28v) - (c29v - c28v) * c28K;
|
||||
c29v += (c28v - c29v) - (c28v - c29v) * c29K1;
|
||||
c29v += (noise_sh2 - c29v) - (noise_sh2 - c29v) * c29K2;
|
||||
if(IC8L3 == IC8L3_L && --IC8Lcnt == 0) IC8L3 = IC8L3_H;
|
||||
}
|
||||
|
||||
memset(GalToneWave, 0, sizeof(GalToneWave));
|
||||
|
||||
for (UINT32 i = 0; i < TOOTHSAW_LENGTH; i++ ) {
|
||||
double r0a = 1.0 / 1e12, r1a = 1.0 / 1e12;
|
||||
double r0b = 1.0 / 1e12, r1b = 1.0 / 1e12;
|
||||
|
||||
if (i & 1) {
|
||||
r1a += 1.0 / 33000;
|
||||
r1b += 1.0 / 33000;
|
||||
} else {
|
||||
r0a += 1.0 / 33000;
|
||||
r0b += 1.0 / 33000;
|
||||
}
|
||||
if (i & 4) {
|
||||
r1a += 1.0 / 22000;
|
||||
r1b += 1.0 / 22000;
|
||||
} else {
|
||||
r0a += 1.0 / 22000;
|
||||
r0b += 1.0 / 22000;
|
||||
}
|
||||
GalToneWave[0][i] = (INT16)(V(1.0 / r0a, 1.0 / r1a));
|
||||
|
||||
if (i & 4) {
|
||||
r1a += 1.0 / 10000;
|
||||
} else {
|
||||
r0a += 1.0 / 10000;
|
||||
}
|
||||
GalToneWave[1][i] = (INT16)(V(1.0 / r0a, 1.0 / r1a));
|
||||
|
||||
if (i & 8) {
|
||||
r1b += 1.0 / 15000;
|
||||
} else {
|
||||
r0b += 1.0 / 15000;
|
||||
}
|
||||
GalToneWave[2][i] = (INT16)(V(1.0 / r0b, 1.0 / r1b));
|
||||
|
||||
if (i & 4) {
|
||||
r0b += 1.0 / 10000;
|
||||
} else {
|
||||
r1b += 1.0 / 10000;
|
||||
}
|
||||
GalToneWave[3][i] = (INT16)(V(1.0 / r0b, 1.0 / r1b));
|
||||
}
|
||||
|
||||
GalPitch = 0xff;
|
||||
GalVol = 0;
|
||||
|
||||
GalLfoFreq = MAXFREQ;
|
||||
GalLfoFreqFrameVar = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GalSoundExit()
|
||||
{
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910) {
|
||||
AY8910Exit(0);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
AY8910Exit(0);
|
||||
AY8910Exit(1);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910) {
|
||||
AY8910Exit(0);
|
||||
AY8910Exit(1);
|
||||
AY8910Exit(2);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) {
|
||||
DACExit();
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HEXPOOLASN76496) {
|
||||
SN76496Exit();
|
||||
}
|
||||
|
||||
if (pFMBuffer) {
|
||||
free(pFMBuffer);
|
||||
pFMBuffer = NULL;
|
||||
for (INT32 i = 0; i < 9; i++) pAY8910Buffer[i] = NULL;
|
||||
}
|
||||
|
||||
if (GalNoiseWave) {
|
||||
free(GalNoiseWave);
|
||||
GalNoiseWave = NULL;
|
||||
}
|
||||
|
||||
if (GalShootWave) {
|
||||
free(GalShootWave);
|
||||
GalShootWave = NULL;
|
||||
}
|
||||
|
||||
HunchbksSoundIrqFire = 0;
|
||||
GalShootLength = 0;
|
||||
GalShootRate = 0;
|
||||
GalLastPort2 = 0;
|
||||
GalShootEnable = 0;
|
||||
GalNoiseEnable = 0;
|
||||
GalNoiseVolume = 0;
|
||||
GalShootWavePos = 0;
|
||||
GalNoiseWavePos = 0;
|
||||
GalLfoWavePos[0] = GalLfoWavePos[1] = GalLfoWavePos[2] = 0;
|
||||
GalPitch = 0;
|
||||
GalVol = 0;
|
||||
GalCounter = 0;
|
||||
GalCountDown = 0;
|
||||
GalLfoVolume[0] = GalLfoVolume[1] = GalLfoVolume[2] = 0;
|
||||
GalLfoFreq = 0;
|
||||
GalLfoFreqFrameVar = 0;
|
||||
GalLfoBit[0] = GalLfoBit[1] = GalLfoBit[2] = GalLfoBit[3] = 0;
|
||||
memset(GalToneWave, 0, sizeof(GalToneWave));
|
||||
}
|
||||
|
||||
void GalSoundScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_GALAXIAN || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC) {
|
||||
SCAN_VAR(GalLastPort2);
|
||||
SCAN_VAR(GalShootEnable);
|
||||
SCAN_VAR(GalNoiseEnable);
|
||||
SCAN_VAR(GalNoiseVolume);
|
||||
SCAN_VAR(GalShootWavePos);
|
||||
SCAN_VAR(GalNoiseWavePos);
|
||||
SCAN_VAR(GalLfoWavePos);
|
||||
SCAN_VAR(GalPitch);
|
||||
SCAN_VAR(GalVol);
|
||||
SCAN_VAR(GalCounter);
|
||||
SCAN_VAR(GalCountDown);
|
||||
SCAN_VAR(GalLfoVolume);
|
||||
SCAN_VAR(GalLfoFreq);
|
||||
SCAN_VAR(GalLfoFreqFrameVar);
|
||||
SCAN_VAR(GalLfoBit);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_ZIGZAGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_JUMPBUGAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMANAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_CHECKMAJAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_FROGGERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_BONGOAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_KONAMIAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_EXPLORERAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_AD2083AY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SCORPIONAY8910 || GalSoundType == GAL_SOUND_HARDWARE_TYPE_HUNCHBACKAY8910) {
|
||||
AY8910Scan(nAction, pnMin);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_KINGBALLDAC || GalSoundType == GAL_SOUND_HARDWARE_TYPE_SFXAY8910DAC) {
|
||||
DACScan(nAction, pnMin);
|
||||
}
|
||||
|
||||
if (GalSoundType == GAL_SOUND_HARDWARE_TYPE_RACKNROLSN76496) {
|
||||
SN76496Scan(nAction, pnMin);
|
||||
}
|
||||
}
|
||||
|
||||
// AY8910 Port Handlers
|
||||
UINT8 CheckmajPortARead(UINT32)
|
||||
{
|
||||
return GalSoundLatch;
|
||||
}
|
||||
|
||||
UINT8 BongoDipSwitchRead(UINT32)
|
||||
{
|
||||
return GalInput[3] | GalDip[3];
|
||||
}
|
||||
|
||||
UINT8 KonamiSoundLatchRead(UINT32)
|
||||
{
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
return GalSoundLatch;
|
||||
}
|
||||
|
||||
UINT8 KonamiSoundTimerRead(UINT32)
|
||||
{
|
||||
INT32 nActiveCPU = ZetGetActive();
|
||||
UINT32 Cycles;
|
||||
|
||||
if (nActiveCPU == 1) {
|
||||
Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2);
|
||||
} else {
|
||||
ZetClose();
|
||||
ZetOpen(1);
|
||||
Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2);
|
||||
ZetClose();
|
||||
ZetOpen(nActiveCPU);
|
||||
}
|
||||
|
||||
UINT8 HiBit = 0;
|
||||
|
||||
if (Cycles >= 16 * 16 * 2 * 8 * 5) {
|
||||
HiBit = 1;
|
||||
Cycles -= 16 * 16 * 2 * 8 * 5;
|
||||
}
|
||||
|
||||
return (HiBit << 7) | (BIT(Cycles, 14) << 6) | (BIT(Cycles, 13) << 5) | (BIT(Cycles, 11) << 4) | 0x0e;
|
||||
}
|
||||
|
||||
UINT8 FroggerSoundTimerRead(UINT32)
|
||||
{
|
||||
UINT8 KonamiValue = KonamiSoundTimerRead(0);
|
||||
return BITSWAP08(KonamiValue, 7, 6, 3, 4, 5, 2, 1, 0);
|
||||
}
|
||||
|
||||
UINT8 HunchbksSoundTimerRead(UINT32)
|
||||
{
|
||||
INT32 nActiveCPU = ZetGetActive();
|
||||
UINT32 Cycles;
|
||||
|
||||
if (nActiveCPU == 0) {
|
||||
Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2);
|
||||
} else {
|
||||
ZetOpen(0);
|
||||
Cycles = (ZetTotalCycles() * 8) % (UINT64)(16 * 16 * 2 * 8 * 5 * 2);
|
||||
ZetClose();
|
||||
}
|
||||
|
||||
UINT8 HiBit = 0;
|
||||
|
||||
if (Cycles >= 16 * 16 * 2 * 8 * 5) {
|
||||
HiBit = 1;
|
||||
Cycles -= 16 * 16 * 2 * 8 * 5;
|
||||
}
|
||||
|
||||
return (HiBit << 7) | (BIT(Cycles, 14) << 6) | (BIT(Cycles, 13) << 5) | (BIT(Cycles, 11) << 4) | 0x0e;
|
||||
}
|
||||
|
||||
void KonamiSoundLatchWrite(UINT8 d)
|
||||
{
|
||||
GalSoundLatch = d;
|
||||
}
|
||||
|
||||
void KonamiSoundControlWrite(UINT8 d)
|
||||
{
|
||||
UINT8 Old = KonamiSoundControl;
|
||||
KonamiSoundControl = d;
|
||||
|
||||
if ((Old & 0x08) && !(d & 0x08)) {
|
||||
INT32 nActiveCPU = ZetGetActive();
|
||||
|
||||
if (nActiveCPU == 1) {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
} else {
|
||||
ZetClose();
|
||||
ZetOpen(1);
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
ZetClose();
|
||||
ZetOpen(nActiveCPU);
|
||||
}
|
||||
}
|
||||
|
||||
/* bit 4 is sound disable */
|
||||
// sound_global_enable(~data & 0x10);
|
||||
}
|
||||
|
||||
void HunchbksSoundControlWrite(UINT8 d)
|
||||
{
|
||||
UINT8 Old = KonamiSoundControl;
|
||||
KonamiSoundControl = d;
|
||||
|
||||
HunchbksSoundIrqFire = 0;
|
||||
|
||||
if ((Old & 0x08) && !(d & 0x08)) {
|
||||
HunchbksSoundIrqFire = 1;
|
||||
}
|
||||
|
||||
/* bit 4 is sound disable */
|
||||
// sound_global_enable(~data & 0x10);
|
||||
}
|
||||
|
||||
void SfxSoundLatch2Write(UINT32, UINT32 d)
|
||||
{
|
||||
GalSoundLatch2 = d & 0xff;
|
||||
}
|
||||
|
||||
void SfxSampleControlWrite(UINT32, UINT32 d)
|
||||
{
|
||||
UINT8 Old = SfxSampleControl;
|
||||
|
||||
d &= 0xff;
|
||||
SfxSampleControl = d;
|
||||
|
||||
if ((Old & 0x01) && !(d & 0x01)) {
|
||||
INT32 nActiveCPU = ZetGetActive();
|
||||
|
||||
if (nActiveCPU == 1) {
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
} else {
|
||||
ZetClose();
|
||||
ZetOpen(1);
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
ZetClose();
|
||||
ZetOpen(nActiveCPU);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Frogger Sound CPU Memory Map
|
||||
UINT8 __fastcall FroggerSoundZ80Read(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a);
|
||||
}
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void __fastcall FroggerSoundZ80Write(UINT16 a, UINT8 d)
|
||||
{
|
||||
if (a >= 0x6000 && a <= 0x6fff) {
|
||||
// konami_sound_filter_w
|
||||
return;
|
||||
}
|
||||
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall FroggerSoundZ80PortRead(UINT16 a)
|
||||
{
|
||||
a &= 0xff;
|
||||
|
||||
UINT8 Result = 0xff;
|
||||
if (a & 0x40) Result &= AY8910Read(0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
void __fastcall FroggerSoundZ80PortWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
a &= 0xff;
|
||||
|
||||
if (a & 0x40) {
|
||||
AY8910Write(0, 1, d);
|
||||
} else {
|
||||
if (a & 0x80) {
|
||||
AY8910Write(0, 0, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FroggerSoundNoEncryptionInit()
|
||||
{
|
||||
ZetOpen(1);
|
||||
ZetSetReadHandler(FroggerSoundZ80Read);
|
||||
ZetSetWriteHandler(FroggerSoundZ80Write);
|
||||
ZetSetInHandler(FroggerSoundZ80PortRead);
|
||||
ZetSetOutHandler(FroggerSoundZ80PortWrite);
|
||||
ZetMapArea(0x0000, GalZ80Rom2Size - 1, 0, GalZ80Rom2);
|
||||
ZetMapArea(0x0000, GalZ80Rom2Size - 1, 2, GalZ80Rom2);
|
||||
ZetMapArea(0x4000, 0x43ff, 0, GalZ80Ram2);
|
||||
ZetMapArea(0x4000, 0x43ff, 1, GalZ80Ram2);
|
||||
ZetMapArea(0x4000, 0x43ff, 2, GalZ80Ram2);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
nGalCyclesTotal[1] = (14318000 / 8) / 60;
|
||||
}
|
||||
|
||||
void FroggerSoundInit()
|
||||
{
|
||||
FroggerSoundNoEncryptionInit();
|
||||
|
||||
for (UINT32 Offset = 0; Offset < 0x0800; Offset++) GalZ80Rom2[Offset] = BITSWAP08(GalZ80Rom2[Offset], 7, 6, 5, 4, 3, 2, 0, 1);
|
||||
}
|
||||
|
||||
// Konami Sound CPU Memory Map
|
||||
UINT8 __fastcall KonamiSoundZ80Read(UINT16 a)
|
||||
{
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 #2 Read => %04X\n"), a);
|
||||
}
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void __fastcall KonamiSoundZ80Write(UINT16 a, UINT8 d)
|
||||
{
|
||||
if (a >= 0x9000 && a <= 0x9fff) {
|
||||
// konami_sound_filter_w
|
||||
return;
|
||||
}
|
||||
|
||||
switch (a) {
|
||||
default: {
|
||||
bprintf(PRINT_NORMAL, _T("Z80 #2 Write => %04X, %02X\n"), a, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall KonamiSoundZ80PortRead(UINT16 a)
|
||||
{
|
||||
a &= 0xff;
|
||||
|
||||
UINT8 Result = 0xff;
|
||||
if (a & 0x20) Result &= AY8910Read(0);
|
||||
if (a & 0x80) Result &= AY8910Read(1);
|
||||
return Result;
|
||||
}
|
||||
|
||||
void __fastcall KonamiSoundZ80PortWrite(UINT16 a, UINT8 d)
|
||||
{
|
||||
a &= 0xff;
|
||||
|
||||
if (a & 0x10) {
|
||||
AY8910Write(0, 0, d);
|
||||
} else {
|
||||
if (a & 0x20) {
|
||||
AY8910Write(0, 1, d);
|
||||
}
|
||||
}
|
||||
|
||||
if (a & 0x40) {
|
||||
AY8910Write(1, 0, d);
|
||||
} else {
|
||||
if (a & 0x80) {
|
||||
AY8910Write(1, 1, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KonamiSoundInit()
|
||||
{
|
||||
ZetOpen(1);
|
||||
ZetSetReadHandler(KonamiSoundZ80Read);
|
||||
ZetSetWriteHandler(KonamiSoundZ80Write);
|
||||
ZetSetInHandler(KonamiSoundZ80PortRead);
|
||||
ZetSetOutHandler(KonamiSoundZ80PortWrite);
|
||||
ZetMapArea(0x0000, GalZ80Rom2Size - 1, 0, GalZ80Rom2);
|
||||
ZetMapArea(0x0000, GalZ80Rom2Size - 1, 2, GalZ80Rom2);
|
||||
ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram2);
|
||||
ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram2);
|
||||
ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram2);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
nGalCyclesTotal[1] = (14318000 / 8) / 60;
|
||||
}
|
||||
|
||||
void HunchbksSoundInit()
|
||||
{
|
||||
ZetOpen(0);
|
||||
ZetSetReadHandler(KonamiSoundZ80Read);
|
||||
ZetSetWriteHandler(KonamiSoundZ80Write);
|
||||
ZetSetInHandler(KonamiSoundZ80PortRead);
|
||||
ZetSetOutHandler(KonamiSoundZ80PortWrite);
|
||||
ZetMapArea(0x0000, GalZ80Rom1Size - 1, 0, GalZ80Rom1);
|
||||
ZetMapArea(0x0000, GalZ80Rom1Size - 1, 2, GalZ80Rom1);
|
||||
ZetMapArea(0x8000, 0x83ff, 0, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8000, 0x83ff, 1, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8000, 0x83ff, 2, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8400, 0x87ff, 0, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8400, 0x87ff, 1, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8400, 0x87ff, 2, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8800, 0x8bff, 0, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8800, 0x8bff, 1, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8800, 0x8bff, 2, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8c00, 0x8fff, 0, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8c00, 0x8fff, 1, GalZ80Ram1 + 0x400);
|
||||
ZetMapArea(0x8c00, 0x8fff, 2, GalZ80Ram1 + 0x400);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
nGalCyclesTotal[1] = (14318000 / 8) / 60;
|
||||
}
|
||||
|
||||
// Galaxian samples
|
||||
static void GalRenderShootSample(INT16 *pSoundBuf, INT32 nLength)
|
||||
{
|
||||
double Addr = GalShootWavePos;
|
||||
double Step = (double)GalShootRate / nBurnSoundRate;
|
||||
|
||||
for (INT32 i = 0; i < nLength; i += 2) {
|
||||
INT16 Sample = (INT16)(GalShootWave[(INT32)Addr] * SHOOT_VOLUME);
|
||||
Sample >>= 4;
|
||||
|
||||
pSoundBuf[i + 0] += Sample;
|
||||
pSoundBuf[i + 1] += Sample;
|
||||
|
||||
Addr += Step;
|
||||
}
|
||||
|
||||
GalShootWavePos = Addr;
|
||||
if (GalShootWavePos > GalShootLength) {
|
||||
GalShootWavePos = 0;
|
||||
GalShootEnable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void GalRenderNoiseSample(INT16 *pSoundBuf, INT32 nLength)
|
||||
{
|
||||
double Addr = GalNoiseWavePos;
|
||||
double Step = (double)NOISE_RATE / nBurnSoundRate;
|
||||
|
||||
for (INT32 i = 0; i < nLength; i += 2) {
|
||||
INT16 Sample = (INT16)(GalNoiseWave[(INT32)Addr] * (GalNoiseVolume / 100));
|
||||
Sample >>= 4;
|
||||
|
||||
pSoundBuf[i + 0] += Sample;
|
||||
pSoundBuf[i + 1] += Sample;
|
||||
|
||||
Addr += Step;
|
||||
}
|
||||
|
||||
GalNoiseWavePos = Addr;
|
||||
if (GalNoiseWavePos > NOISE_LENGTH) {
|
||||
GalNoiseWavePos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void GalRenderToneWave(INT16 *pSoundBuf, INT32 nLength)
|
||||
{
|
||||
INT32 i,j;
|
||||
INT16 *w = GalToneWave[GalVol];
|
||||
|
||||
if (GalPitch != 0xff) {
|
||||
for (i = 0; i < nLength; i += 2) {
|
||||
INT32 mix = 0;
|
||||
|
||||
for (j = 0; j < STEPS; j++) {
|
||||
if (GalCountDown >= 256) {
|
||||
GalCounter = GalCounter + ((double)96000 / nBurnSoundRate);
|
||||
if (GalCounter > TOOTHSAW_LENGTH) GalCounter = 0;
|
||||
GalCountDown = GalPitch;
|
||||
}
|
||||
GalCountDown++;
|
||||
|
||||
mix += w[(INT32)GalCounter];
|
||||
}
|
||||
|
||||
INT16 Sample = mix / STEPS;
|
||||
Sample >>= 4;
|
||||
|
||||
pSoundBuf[i + 0] = Sample;
|
||||
pSoundBuf[i + 1] = Sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GalRenderLfoWaveSample(INT32 nLfoWave, INT16 *pSoundBuf, INT32 nLength)
|
||||
{
|
||||
double Addr = GalLfoWavePos[nLfoWave];
|
||||
double Step = (double)(sizeof(GalBackgroundWave) * GalLfoFreq * (100 + 2 * 470) / (100 + 2 * 470)) / nBurnSoundRate;
|
||||
|
||||
for (INT32 i = 0; i < nLength; i += 2) {
|
||||
INT16 Sample = (INT16)(GalBackgroundWave[(INT32)Addr] * (GalLfoVolume[nLfoWave] ? LFO_VOLUME : 0));
|
||||
Sample >>= 4;
|
||||
|
||||
pSoundBuf[i + 0] += Sample;
|
||||
pSoundBuf[i + 1] += Sample;
|
||||
|
||||
Addr += Step;
|
||||
}
|
||||
|
||||
GalLfoWavePos[nLfoWave] = Addr;
|
||||
if (GalLfoWavePos[nLfoWave] > 32) {
|
||||
GalLfoWavePos[nLfoWave] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GalRenderSoundSamples(INT16 *pSoundBuf, INT32 nLength)
|
||||
{
|
||||
memset(pSoundBuf, 0, nLength * 2 * sizeof(INT16));
|
||||
|
||||
GalRenderToneWave(pSoundBuf, nLength);
|
||||
GalRenderNoiseSample(pSoundBuf, nLength);
|
||||
if (GalShootEnable) GalRenderShootSample(pSoundBuf, nLength);
|
||||
GalRenderLfoWaveSample(0, pSoundBuf, nLength);
|
||||
GalRenderLfoWaveSample(1, pSoundBuf, nLength);
|
||||
GalRenderLfoWaveSample(2, pSoundBuf, nLength);
|
||||
}
|
||||
|
||||
void GalaxianSoundWrite(UINT32 Offset, UINT8 d)
|
||||
{
|
||||
d &= 0x01;
|
||||
|
||||
switch (Offset & 0x07) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02: {
|
||||
GalLfoVolume[Offset] = d;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x03: {
|
||||
GalNoiseEnable = d & 1;
|
||||
if (GalNoiseEnable) {
|
||||
GalNoiseVolume = 100;
|
||||
GalNoiseWavePos = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x04: {
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x05: {
|
||||
if (d & 1 && !(GalLastPort2 & 1) ) {
|
||||
GalShootEnable = 1;
|
||||
GalShootWavePos = 0;
|
||||
}
|
||||
GalLastPort2 = d;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x06:
|
||||
case 0x07: {
|
||||
GalVol = (GalVol & ~(1 << (Offset & 0x01))) | ((d & 1) << (Offset & 0x01));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GalaxianLfoFreqWrite(UINT32 Offset, UINT8 d)
|
||||
{
|
||||
double r0, r1, rx = 100000.0;
|
||||
|
||||
if ((d & 0x01) == GalLfoBit[Offset]) return;
|
||||
|
||||
GalLfoBit[Offset] = d & 0x01;
|
||||
|
||||
r0 = 1.0 / 330000;
|
||||
r1 = 1.0 / 1e12;
|
||||
|
||||
if (GalLfoBit[0]) {
|
||||
r1 += 1.0 / 1000000;
|
||||
} else {
|
||||
r0 += 1.0 / 1000000;
|
||||
}
|
||||
|
||||
if (GalLfoBit[1]) {
|
||||
r1 += 1.0 / 470000;
|
||||
} else {
|
||||
r0 += 1.0 / 470000;
|
||||
}
|
||||
|
||||
if (GalLfoBit[2]) {
|
||||
r1 += 1.0 / 220000;
|
||||
} else {
|
||||
r0 += 1.0 / 220000;
|
||||
}
|
||||
|
||||
if (GalLfoBit[3]) {
|
||||
r1 += 1.0 / 100000;
|
||||
} else {
|
||||
r0 += 1.0 / 100000;
|
||||
}
|
||||
|
||||
r0 = 1.0 / r0;
|
||||
r1 = 1.0 / r1;
|
||||
|
||||
rx = rx + 2000000.0 * r0 / (r0 + r1);
|
||||
|
||||
GalLfoFreqFrameVar = (1000000000 / ((MAXFREQ - MINFREQ) * 639 * rx)) * 100;
|
||||
|
||||
bprintf(PRINT_NORMAL, _T("Offset %x, rx %f, %f\n"), Offset, (MAXFREQ - MINFREQ) * 639 * rx, GalLfoFreqFrameVar);
|
||||
}
|
||||
|
||||
void GalaxianSoundUpdateTimers()
|
||||
{
|
||||
if (GetCurrentFrame() % 3) {
|
||||
if (!GalNoiseEnable && GalNoiseVolume > 0) {
|
||||
GalNoiseVolume -= (GalNoiseVolume / 10) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (GalLfoFreq > MINFREQ) {
|
||||
GalLfoFreq -= GalLfoFreqFrameVar;
|
||||
} else {
|
||||
GalLfoFreq = MAXFREQ;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
#include "gal.h"
|
||||
|
||||
// This module is not accurate to the arcade hardware - it is ported from my previous Galaxian driver for FBA,
|
||||
// which was based on an old version of MAME. It is considered "good enough" for the purpose of giving the impression
|
||||
// of the star layers without being totally accurate
|
||||
|
||||
struct Star
|
||||
{
|
||||
INT32 x, y, Colour;
|
||||
};
|
||||
|
||||
static struct Star Stars[252];
|
||||
|
||||
INT32 GalStarsEnable = 0;
|
||||
INT32 GalStarsScrollPos = 0;
|
||||
INT32 GalStarsBlinkState = 0;
|
||||
INT32 GalBlinkTimerStartFrame = 0;
|
||||
static double GalBlinkEveryFrames = (0.693 * (100000 + 2.0 + 10000) * 0.00001) * (16000.0 / 132 / 2);
|
||||
|
||||
void GalInitStars()
|
||||
{
|
||||
INT32 nStars, Generator, x, y;
|
||||
|
||||
GalStarsEnable = 0;
|
||||
GalStarsScrollPos = -1;
|
||||
GalStarsBlinkState = 0;
|
||||
|
||||
nStars = 0;
|
||||
Generator = 0;
|
||||
|
||||
for (y = 255; y >= 0; y--) {
|
||||
for (x = 511; x >= 0; x--) {
|
||||
INT32 Bit0;
|
||||
|
||||
Bit0 = ((~Generator >> 16) & 0x01) ^ ((Generator >> 4) & 0x01);
|
||||
|
||||
Generator = (Generator << 1) | Bit0;
|
||||
|
||||
if (((~Generator >> 16) & 0x01) && (Generator & 0xff) == 0xff) {
|
||||
INT32 Colour;
|
||||
|
||||
Colour = (~(Generator >> 8)) & 0x3f;
|
||||
|
||||
if (Colour) {
|
||||
Stars[nStars].x = x;
|
||||
Stars[nStars].y = y;
|
||||
Stars[nStars].Colour = Colour;
|
||||
|
||||
nStars++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 GalCheckStarsBlinkState()
|
||||
{
|
||||
INT32 CurrentFrame = GetCurrentFrame();
|
||||
|
||||
if ((CurrentFrame - GalBlinkTimerStartFrame) >= (INT32)GalBlinkEveryFrames) {
|
||||
GalBlinkTimerStartFrame = CurrentFrame;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void GalPlotStar(INT32 x, INT32 y, INT32 Colour)
|
||||
{
|
||||
if (y >= 0 && y < nScreenHeight && x >= 0 && x < nScreenWidth) {
|
||||
pTransDraw[(y * nScreenWidth) + x] = Colour + GAL_PALETTE_STARS_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
void GalaxianRenderStarLayer()
|
||||
{
|
||||
GalStarsScrollPos++;
|
||||
|
||||
for (INT32 Offs = 0; Offs < 252; Offs++) {
|
||||
INT32 x, y;
|
||||
|
||||
x = ((Stars[Offs].x + GalStarsScrollPos) & 0x01ff) >>1;
|
||||
y = (Stars[Offs].y + ((GalStarsScrollPos + Stars[Offs].x) >> 9)) & 0xff;
|
||||
|
||||
if ((y & 0x01) ^ ((x >> 3) & 0x01)) {
|
||||
if (GalFlipScreenX) x = 255 - x;
|
||||
if (GalFlipScreenY) y = 255 - y;
|
||||
y -= 16;
|
||||
GalPlotStar(x, y, Stars[Offs].Colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JumpbugRenderStarLayer()
|
||||
{
|
||||
if (GalCheckStarsBlinkState()) GalStarsBlinkState++;
|
||||
|
||||
for (INT32 Offs = 0; Offs < 252; Offs++) {
|
||||
INT32 x, y;
|
||||
|
||||
x = Stars[Offs].x >> 1;
|
||||
y = Stars[Offs].y >> 1;
|
||||
|
||||
if ((y & 0x01) ^ ((x >> 3) & 0x01)) {
|
||||
switch (GalStarsBlinkState & 0x03) {
|
||||
case 0: {
|
||||
if (!(Stars[Offs].Colour & 0x01)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
if (!(Stars[Offs].Colour & 0x04)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
if (!(Stars[Offs].y & 0x02)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
x = Stars[Offs].x >> 1;
|
||||
y = Stars[Offs].y & 0xff;
|
||||
|
||||
if (x >= 240) continue;
|
||||
|
||||
if (GalFlipScreenX) x = 255 - x;
|
||||
if (GalFlipScreenY) y = 255 - y;
|
||||
y -= 16;
|
||||
GalPlotStar(x, y, Stars[Offs].Colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScrambleRenderStarLayer()
|
||||
{
|
||||
if (GalCheckStarsBlinkState()) GalStarsBlinkState++;
|
||||
|
||||
for (INT32 Offs = 0; Offs < 252; Offs++) {
|
||||
INT32 x, y;
|
||||
|
||||
x = Stars[Offs].x >> 1;
|
||||
y = Stars[Offs].y;
|
||||
|
||||
if ((y & 0x01) ^ ((x >> 3) & 0x01)) {
|
||||
switch (GalStarsBlinkState & 0x03) {
|
||||
case 0: {
|
||||
if (!(Stars[Offs].Colour & 0x01)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
if (!(Stars[Offs].Colour & 0x04)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
if (!(Stars[Offs].y & 0x02)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GalFlipScreenX) x = 255 - x;
|
||||
if (GalFlipScreenY) y = 255 - y;
|
||||
y -= 16;
|
||||
GalPlotStar(x, y, Stars[Offs].Colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MarinerRenderStarLayer()
|
||||
{
|
||||
UINT8 *Prom = GalProm + 0x120;
|
||||
|
||||
GalStarsScrollPos++;
|
||||
|
||||
for (INT32 Offs = 0; Offs < 252; Offs++) {
|
||||
INT32 x, y;
|
||||
|
||||
x = ((Stars[Offs].x + GalStarsScrollPos) & 0x01ff) >>1;
|
||||
y = (Stars[Offs].y + ((GalStarsScrollPos + Stars[Offs].x) >> 9)) & 0xff;
|
||||
|
||||
if ((y & 0x01) ^ ((x >> 3) & 0x01)) {
|
||||
if (GalFlipScreenX) x = 255 - x;
|
||||
if (GalFlipScreenY) y = 255 - y;
|
||||
y -= 16;
|
||||
|
||||
if (Prom[((x / 8) + 1) & 0x1f] & 0x04) {
|
||||
GalPlotStar(x, y, Stars[Offs].Colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RescueRenderStarLayer()
|
||||
{
|
||||
if (GalCheckStarsBlinkState()) GalStarsBlinkState++;
|
||||
|
||||
for (INT32 Offs = 0; Offs < 252; Offs++) {
|
||||
INT32 x, y;
|
||||
|
||||
x = Stars[Offs].x >> 1;
|
||||
y = Stars[Offs].y;
|
||||
|
||||
if (x < 128 && ((y & 0x01) ^ ((x >> 3) & 0x01))) {
|
||||
switch (GalStarsBlinkState & 0x03) {
|
||||
case 0: {
|
||||
if (!(Stars[Offs].Colour & 0x01)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
if (!(Stars[Offs].Colour & 0x04)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
if (!(Stars[Offs].y & 0x02)) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GalFlipScreenX) x = 255 - x;
|
||||
if (GalFlipScreenY) y = 255 - y;
|
||||
y -= 16;
|
||||
GalPlotStar(x, y, Stars[Offs].Colour);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,657 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Irem Custom V35+ CPU
|
||||
-- has internal 256 byte lookup table, handled in realtime. Bomberman
|
||||
World runs encrypted code from RAM, Risky Challenge expects to be able
|
||||
to run code in emulation (non-encrypted) mode for some subroutines..
|
||||
|
||||
Hasamu Nanao 08J27261A1 011 9102KK700
|
||||
Gunforce Nanao 08J27261A1 011 9106KK701
|
||||
Ken-Go Nanao 08J27261A1 011 9102KK701
|
||||
Bomberman Nanao 08J27261A1 012 9123KK200
|
||||
Atomic Punk Nanao 08J27291A1 012 9128KK440
|
||||
Blade Master / Cross Blades! Nanao 08J27291A1 012 9123KK740
|
||||
Quiz F-1 1,2 Finish Nanao 08J27291A4 014 9147KK700
|
||||
Gunforce 2 Nanao 08J27291A4 014 9247KK700
|
||||
Lethal Thunder Nanao 08J27291A4 014 9147KK700
|
||||
Bomberman World / New Atomic Punk Nanao 08J27291A5 015 9219KK700
|
||||
Undercover Cops Nanao 08J27291A5 015 9219KK700
|
||||
Gun Hohki Nanao 08J27291A6 016 9217NK700
|
||||
Skins Game Nanao 08J27291A7 017
|
||||
Hook Nanao 08J27291A8 018 9237NK700
|
||||
|
||||
R-Type Leo Irem D8000021A1 019 9242NK700
|
||||
Fire Barrel Irem D8000010A1 019 9243NK700
|
||||
In The Hunt Irem D8000011A1 020
|
||||
Risky Challenge/Gussun Oyoyo Irem D8000019A1 022 9331NK700
|
||||
Match It II/Shisensho II Irem D8000020A1 023 9320NK700
|
||||
World PK Soccer/Kick for the Goal Irem D8000021A1 024 9335NK701
|
||||
Ninja Baseball Batman Irem D8000021A1 024 9335NK700
|
||||
Perfect Soldiers Irem D8000022A1
|
||||
Dream Soccer '94 Irem D8000023A1 026
|
||||
|
||||
Please let me know if you can fill in any of the blanks.
|
||||
|
||||
Emulation by Bryan McPhail, mish@tendril.co.uk, thanks to Chris Hardy too!
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "burnint.h"
|
||||
#include "irem_cpu.h"
|
||||
|
||||
|
||||
// CAVEATS:
|
||||
// 0x80 and 0x82 pre- opcodes can easily be confused. They perform exactly the same
|
||||
// function when operating on memory, but when working with registers one affects
|
||||
// byte registers and the other word registers. Gunforce, Blade Master and
|
||||
// Lethal Thunder had this error.
|
||||
|
||||
//double check 0x00 0x22 0x28 0x4a 0x34 in these tables
|
||||
|
||||
#define xxxx 0x90/* Unknown */
|
||||
|
||||
const UINT8 gunforce_decryption_table[256] = {
|
||||
0xff,xxxx,xxxx,0x2c,xxxx,xxxx,0x43,0x88, xxxx,0x13,0x0a,0xbd,0xba,0x60,0xea,xxxx, /* 00 */
|
||||
xxxx,xxxx,0xf2,0x29,0xb3,0x22,xxxx,0x0c, 0xa9,0x5f,0x9d,0x07,xxxx,xxxx,0x0b,0xbb, /* 10 */
|
||||
0x8a,xxxx,xxxx,xxxx,0x3a,0x3c,0x5a,0x38, 0x99,xxxx,0xf8,0x89,xxxx,0x91,xxxx,0x55, /* 20 */
|
||||
0xac,0x40,0x73,xxxx,0x59,xxxx,0xfc,xxxx, 0x50,0xfa,xxxx,0x25,xxxx,0x34,0x47,0xb7, /* 30 */
|
||||
xxxx,xxxx,xxxx,0x49,xxxx,0x0f,0x8b,0x05, 0xc3,0xa5,0xbf,0x83,0x86,0xc5,xxxx,xxxx, /* 40 */
|
||||
0x28,0x77,0x24,0xb4,xxxx,0x92,xxxx,0x3b, 0x5e,0xb6,0x80,0x0d,0x2e,0xab,0xe7,xxxx, /* 50 */
|
||||
0x48,xxxx,0xad,0xc0,xxxx,0x1b,0xc6,0xa3, 0x04,xxxx,xxxx,xxxx,0x16,0xb0,0x7d,0x98, /* 60 */
|
||||
0x87,0x46,0x8c,xxxx,xxxx,0xfe,xxxx,0xcf, xxxx,0x68,0x84,xxxx,0xd2,xxxx,0x18,0x51, /* 70 */
|
||||
0x76,0xa4,0x36,0x52,0xfb,xxxx,0xb9,xxxx, xxxx,0xb1,0x1c,0x21,0xe6,0xb5,0x17,0x27, /* 80 */
|
||||
0x3d,0x45,0xbe,0xae,xxxx,0x4a,0x0e,0xe5, xxxx,0x58,0x1f,0x61,0xf3,0x02,xxxx,0xe8, /* 90 */
|
||||
xxxx,xxxx,xxxx,0xf7,0x56,0x96,xxxx,0xbc, 0x4f,xxxx,xxxx,0x79,0xd0,xxxx,0x2a,0x12, /* A0 */
|
||||
0x4e,0xb8,xxxx,0x41,xxxx,0x90,0xd3,xxxx, 0x2d,0x33,0xf6,xxxx,xxxx,0x14,xxxx,0x32, /* B0 */
|
||||
0x5d,0xa8,0x53,0x26,0x2b,0x20,0x81,0x75, 0x7f,0x3e,xxxx,xxxx,0x00,0x93,xxxx,0xb2, /* C0 */
|
||||
0x57,xxxx,0xa0,xxxx,0x39,xxxx,xxxx,0x72, xxxx,0x01,0x42,0x74,0x9c,0x1e,xxxx,0x5b, /* D0 */
|
||||
xxxx,0xf9,xxxx,0x2f,0x85,xxxx,0xeb,0xa2, xxxx,0xe2,0x11,xxxx,0x4b,0x7e,xxxx,0x78, /* E0 */
|
||||
xxxx,xxxx,0x09,0xa1,0x03,xxxx,0x23,0xc1, 0x8e,0xe9,0xd1,0x7c,xxxx,xxxx,0xc7,0x06, /* F0 */
|
||||
};
|
||||
// 0x13 (0x29) guess
|
||||
// 0x18 (0xa9) guess
|
||||
// 0x50 (0x28) guess
|
||||
// 0x63 (0xc0) guess
|
||||
// 0x7e (0x18) opcode is right but arguments could be swapped
|
||||
// 0xcc (0x00) guess
|
||||
// 0xea (0x11) guess
|
||||
// 0x51 (0x77) guess (kengo)
|
||||
// 0x96 (0x0e) complete guess (kengo), maybe wrong but I don't see what it could be
|
||||
|
||||
|
||||
//double check 22 (boot bomb at 2a000)
|
||||
//47a7 (46e0 in boot) - hmm
|
||||
|
||||
// 0x00 is NOT 0x20 (no context in bomberman)
|
||||
|
||||
const UINT8 bomberman_decryption_table[256] = {
|
||||
xxxx,xxxx,0x79,xxxx,0x9d,0x48,xxxx,xxxx, xxxx,xxxx,0x2e,xxxx,xxxx,0xa5,0x72,xxxx, /* 00 */
|
||||
0x46,0x5b,0xb1,0x3a,0xc3,xxxx,0x35,xxxx, xxxx,0x23,xxxx,0x99,xxxx,0x05,xxxx,0x3c, /* 10 */
|
||||
0x3b,0x76,0x11,xxxx,xxxx,0x4b,xxxx,0x92, xxxx,0x32,0x5d,xxxx,0xf7,0x5a,0x9c,xxxx, /* 20 */
|
||||
0x26,0x40,0x89,xxxx,xxxx,xxxx,xxxx,0x57, xxxx,xxxx,xxxx,xxxx,xxxx,0xba,0x53,0xbb, /* 30 */
|
||||
0x42,0x59,0x2f,xxxx,0x77,xxxx,xxxx,0x4f, 0xbf,0x4a,0xcb,0x86,0x62,0x7d,xxxx,0xb8, /* 40 */
|
||||
xxxx,0x34,xxxx,0x5f,xxxx,0x7f,0xf8,0x80, 0xa0,0x84,0x12,0x52,xxxx,xxxx,xxxx,0x47, /* 50 */
|
||||
xxxx,0x2b,0x88,0xf9,xxxx,0xa3,0x83,xxxx, 0x75,0x87,xxxx,0xab,0xeb,xxxx,0xfe,xxxx, /* 60 */
|
||||
xxxx,0xaf,0xd0,0x2c,0xd1,0xe6,0x90,0x43, 0xa2,0xe7,0x85,0xe2,0x49,0x22,0x29,xxxx, /* 70 */
|
||||
0x7c,xxxx,xxxx,0x9a,xxxx,xxxx,0xb9,xxxx, 0x14,0xcf,0x33,0x02,xxxx,xxxx,xxxx,0x73, /* 80 */
|
||||
xxxx,0xc5,xxxx,xxxx,xxxx,0xf3,0xf6,0x24, xxxx,0x56,0xd3,xxxx,0x09,0x01,xxxx,xxxx, /* 90 */
|
||||
0x03,0x2d,0x1b,xxxx,0xf5,0xbe,xxxx,xxxx, 0xfb,0x8e,0x21,0x8d,0x0b,xxxx,xxxx,0xb2, /* A0 */
|
||||
0xfc,0xfa,0xc6,xxxx,0xe8,0xd2,xxxx,0x08, 0x0a,0xa8,0x78,0xff,xxxx,0xb5,xxxx,xxxx, /* B0 */
|
||||
0xc7,0x06,0x18,xxxx,xxxx,0x1e,0x7e,0xb0, 0x0e,0x0f,xxxx,xxxx,0x0c,0xaa,0x55,xxxx, /* C0 */
|
||||
xxxx,0x74,0x3d,xxxx,xxxx,0x38,0x27,0x50, xxxx,0xb6,0x5e,0x8b,0x07,0xe5,0x39,0xea, /* D0 */
|
||||
0xbd,xxxx,0x81,0xb7,xxxx,0x8a,0x0d,xxxx, 0x58,0xa1,0xa9,0x36,xxxx,0xc4,xxxx,0x8f, /* E0 */
|
||||
0x8c,0x1f,0x51,0x04,0xf2,xxxx,0xb3,0xb4, 0xe9,0x2a,xxxx,xxxx,xxxx,0x25,xxxx,0xbc, /* F0 */
|
||||
};
|
||||
// 49 -> 4a (verified in a bombrman PCB)
|
||||
|
||||
const UINT8 lethalth_decryption_table[256] = {
|
||||
0x7f,0x26,0x5d,xxxx,0xba,xxxx,0x1e,0x5e, 0xb8,xxxx,0xbc,0xe8,0x01,xxxx,0x4a,0x25, /* 00 */
|
||||
// ssss !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||
xxxx,0xbd,xxxx,0x22,0x10,xxxx,0x02,0x57, 0x70,xxxx,0x7e,xxxx,0xe7,0x52,xxxx,0xa9, /* 10 */
|
||||
// !!!! !!!! !!!! ???? !!!! !!!! gggg
|
||||
xxxx,xxxx,0xc6,0x06,0xa0,0xfe,0xcf,0x8e, 0x43,0x8f,0x2d,xxxx,0xd4,0x85,0x75,0xa2, /* 20 */
|
||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||
0x3d,xxxx,xxxx,0x38,0x7c,0x89,0xd1,0x80, 0x3b,0x72,0x07,xxxx,0x42,0x37,0x0a,0x18, /* 30 */
|
||||
// gggg !!!! ???? !!!! !!!! !!!! !!!! !!!! !!!! ssss !!!!
|
||||
0x88,0xb4,0x98,0x8b,0xb9,0x9c,0xad,0x0e, 0x2b,xxxx,0xbf,xxxx,0x55,xxxx,0x56,0xb0, /* 40 */
|
||||
// !!!! pppp !!!! !!!! !!!! !!!! gggg !!!! !!!! !!!! !!!!
|
||||
0x93,0x91,xxxx,0xeb,xxxx,0x50,0x41,0x29, 0x47,xxxx,xxxx,0x60,xxxx,0xab,xxxx,xxxx, /* 50 */
|
||||
// pppp !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||
0xc3,0xe2,0xd0,0xb2,0x11,0x79,xxxx,0x08, xxxx,0xfb,xxxx,0x2c,0x23,xxxx,0x28,0x0d, /* 60 */
|
||||
// !!!! !!!! !!!! !!!! ???? !!!! !!!!
|
||||
xxxx,xxxx,xxxx,0x83,0x3c,xxxx,0x1b,0x34, 0x5b,xxxx,0x40,xxxx,xxxx,0x04,0xfc,0xcd, /* 70 */
|
||||
// !!!! !!!! !!!! !!!! !!!! ssss
|
||||
0xb1,0xf3,0x8a,xxxx,xxxx,0x87,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0xbe,0x84,0x1f,0xe6, /* 80 */
|
||||
// !!!! !!!! !!!! !!!! !!!!
|
||||
0xff,xxxx,0x12,xxxx,0xb5,0x36,xxxx,0xb3, xxxx,xxxx,xxxx,0xd2,0x4e,xxxx,xxxx,xxxx, /* 90 */
|
||||
// !!!! !!!! !!!!
|
||||
0xa5,xxxx,xxxx,0xc7,xxxx,0x27,0x0b,xxxx, 0x20,xxxx,xxxx,xxxx,xxxx,xxxx,0x61,0x7d, /* A0 */
|
||||
// !!!! !!!! !!!! !!!! ????
|
||||
xxxx,xxxx,0x86,0x0f,xxxx,0xb7,xxxx,0x4f, xxxx,xxxx,0xc0,0xfd,xxxx,0x39,xxxx,0x77, /* B0 */
|
||||
// !!!! !!!! !!!! !!!! !!!!
|
||||
0x05,0x3a,xxxx,0x48,0x92,0x76,0x3e,0x03, xxxx,0xf8,xxxx,0x59,0xa8,0x5f,0xf9,0xbb, /* C0 */
|
||||
// !!!! !!!! pppp !!!! !!!! !!!! !!!! !!!!
|
||||
0x81,0xfa,0x9d,0xe9,0x2e,0xa1,0xc1,0x33, xxxx,0x78,xxxx,0x0c,xxxx,0x24,0xaa,0xac, /* D0 */
|
||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! ???? !!!! !!!!
|
||||
xxxx,0xb6,xxxx,0xea,xxxx,0x73,0xe5,0x58, 0x00,0xf7,xxxx,0x74,xxxx,0x76,xxxx,0xa3, /* E0 */
|
||||
// !!!! gggg !!!! !!!! !!!! !!!! ???? !!!!
|
||||
xxxx,0x5a,0xf6,0x32,0x46,0x2a,xxxx,xxxx, 0x53,0x4b,0x90,0x0d,0x51,0x68,0x99,0x13, /* F0 */
|
||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! ???? !!!! !!!!
|
||||
};
|
||||
/*
|
||||
missing opcode:
|
||||
|
||||
"!!!!" -> checked against gussun
|
||||
"gggg" -> very probably
|
||||
"pppp" -> probably
|
||||
"ssss" -> sure
|
||||
"????" -> missing
|
||||
|
||||
|
||||
1a -> (78,7c,7e) ->
|
||||
34 -> (78,7c,7e) -> 78
|
||||
|
||||
65 -> (79,
|
||||
af -> (79,7d) (strange 71) ->
|
||||
d9 -> (11e07 from 11de6) (70,78 -> to handle a01ce=000-7d0 -> 0x78
|
||||
ed -> (p76,78,7c,7e) ->
|
||||
fb ->
|
||||
|
||||
probably:
|
||||
42 -> 0x98 (083a3)
|
||||
50 -> 0x93 (083a7)
|
||||
c5 -> (18d56 - from 1844f) (71,73,76,79,7a,7d,7e) -> to handle level number (a008d=00-0f) -> 0x76
|
||||
|
||||
very probably:
|
||||
48 -> 0x2b
|
||||
e5 -> 0x73
|
||||
|
||||
sure:
|
||||
00 -> 0x7f
|
||||
3d -> 0x37
|
||||
7f -> 0xcd (little machine in the game - 16058)
|
||||
|
||||
*/
|
||||
// 0x2c (0xd4) complete guess
|
||||
// 0x2d (0x85) complete guess
|
||||
// 0xc4 (0x92) guess
|
||||
// 0xbb (0xfd) guess
|
||||
// 0x46 (0xad) guess - risky challenge use same code
|
||||
// 0x6e (0x28) guess
|
||||
// 0x76 (0x1b) guess
|
||||
// 0x8d (0x84) guess
|
||||
// 0xa6 (0x0b) guess - risky challenge use same code
|
||||
// 0xa8 (0x20) guess
|
||||
// 0xbd (0x39) guess - risky challenge use same code
|
||||
// 0xc3 (0x48) guess
|
||||
// and our collection of conditional branches:
|
||||
// 0xbf (0x7d) >= (monitor test)
|
||||
// 0x34 (0x7c) < or <= (seems more like <) | these two are used toghether
|
||||
// 0xaf (0x7f) > or >= (seems more like >) |
|
||||
// 0xed (0x7e) <= or < (seems more like <=)
|
||||
// 0x00 (0x7f) > ? | these two are used toghether
|
||||
// 0x1a (0x7c) < ? | (rowscroll on pink screen on startup)
|
||||
// 0xc5 (0x7a) completely in the dark (game start after car seelction)
|
||||
|
||||
|
||||
const UINT8 dynablaster_decryption_table[256] = {
|
||||
0x1f,0x51,0x84,xxxx,0x3d,0x09,0x0d,xxxx, xxxx,0x57,xxxx,xxxx,xxxx,0x32,0x11,xxxx, /* 00 */
|
||||
xxxx,0x9c,xxxx,xxxx,0x4b,xxxx,xxxx,0x03, xxxx,xxxx,xxxx,0x89,0xb0,xxxx,xxxx,xxxx, /* 10 */
|
||||
xxxx,0xbb,0x18,0xbe,0x53,0x21,0x55,0x7c, xxxx,xxxx,0x47,0x58,0xf6,xxxx,xxxx,0xb2, /* 20 */
|
||||
0x06,xxxx,0x2b,xxxx,0x2f,0x0b,0xfc, 0x91 , xxxx,xxxx,0xfa,0x81,0x83,0x40,0x38,xxxx, /* 30 */
|
||||
xxxx,xxxx,0x49,0x85,0xd1,0xf5,0x07,0xe2, 0x5e,0x1e,xxxx,0x04,xxxx,xxxx,xxxx,0xb1, /* 40 */
|
||||
0xc7,xxxx,0x96, 0xf2 /*0xaf*/, 0xb6,0xd2,0xc3,xxxx, 0x87,0xba,0xcb,0x88,xxxx,0xb9,0xd0,0xb5, /* 50 */
|
||||
0x9a,0x80,0xa2,0x72,xxxx,0xb4,xxxx,0xaa, 0x26,0x7d,0x52,0x33,0x2e,0xbc,0x08,0x79, /* 60 */
|
||||
0x48,xxxx,0x76,0x36,0x02,xxxx,0x5b,0x12, 0x8b,0xe7,xxxx,xxxx,xxxx,0xab,xxxx,0x4f, /* 70 */
|
||||
xxxx,xxxx,0xa8,0xe5,0x39,0x0e,0xa9,xxxx, xxxx,0x14,xxxx,0xff, 0x7f/*0x75*/ ,xxxx,xxxx,0x27, /* 80 */
|
||||
xxxx,0x01,xxxx,xxxx,0xe6,0x8a,0xd3,xxxx, xxxx,0x8e,0x56,0xa5,0x92,xxxx,xxxx,0xf9, /* 90 */
|
||||
0x22,xxxx,0x5f,xxxx,xxxx,0xa1,xxxx,0x74, 0xb8,xxxx,0x46,0x05,0xeb,0xcf,0xbf,0x5d, /* a0 */
|
||||
0x24,xxxx,0x9d,xxxx,xxxx,xxxx,xxxx,xxxx, 0x59,0x8d,0x3c,0xf8,0xc5,xxxx,0xf3,0x4e, /* b0 */
|
||||
xxxx,xxxx,0x50,0xc6,0xe9,0xfe,0x0a,xxxx, 0x99,0x86,xxxx,xxxx,0xaf ,0x8c/*0x8e*/,0x42,0xf7, /* c0 */
|
||||
xxxx,0x41,xxxx,0xa3,xxxx,0x3a,0x2a,0x43, xxxx,0xb3,0xe8,xxxx,0xc4,0x35,0x78,0x25, /* d0 */
|
||||
0x75,xxxx,0xb7,xxxx,0x23,xxxx, xxxx/*0xe2*/,0x8f, xxxx,xxxx,0x2c,xxxx,0x77,0x7e,xxxx,0x0f, /* e0 */
|
||||
0x0c,0xa0,0xbd,xxxx,xxxx,0x2d,0x29,0xea, xxxx,0x3b,0x73,xxxx,0xfb,0x20,xxxx,0x5a /* f0 */
|
||||
};
|
||||
//double check 0x00/0xa0 AND.
|
||||
//double check 0x8c (0x7d jg)
|
||||
//double check 0xfd (0x20 AND) - 9d2 in code
|
||||
//double check 0xd1 (0x41 INC cw) used in uccops and dynablaster (LOOKS GOOD)
|
||||
|
||||
//AND fd (0x20)
|
||||
//0x37 (91) guess from dynablaster title screen
|
||||
|
||||
// BM - 0x61 NOT 82, but instead 0x80 verified in both Atomic Punk and UCCops
|
||||
// 0x22 is 0x18 (SBB) verified from Gunforce
|
||||
// 0x5b seems confirmed (previous commented out as 0x36)
|
||||
// NS I expected 0x32 to be 0x1b (SBB) like in gunforce, but startup tests fail in bbmanw.
|
||||
// therefore it seems to be 0x2b (SUB)
|
||||
// NS010718 0xa0 was 0x00 (ADDB), verified to be 0x22 (ANDB)
|
||||
|
||||
|
||||
const UINT8 mysticri_decryption_table[256] = {
|
||||
xxxx,0x57,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0xbf,0x43,xxxx,xxxx,xxxx,xxxx,0xfc,xxxx, /* 00 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,0x52,0xa3,0x26, xxxx,0xc7,xxxx,0x0f,xxxx,0x0c,xxxx,xxxx, /* 10 */
|
||||
xxxx,xxxx,0xff,xxxx,xxxx,0x02,xxxx,xxxx, 0x2e,xxxx,0x5f,xxxx,xxxx,xxxx,0x73,0x50, /* 20 */
|
||||
0xb2,0x3a,xxxx,xxxx,0xbb,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
|
||||
xxxx,xxxx,0x8e,0x3c,0x42,xxxx,xxxx,0xb9, xxxx,xxxx,0x2a,xxxx,0x47,0xa0,0x2b,0x03, /* 40 */
|
||||
0xb5,0x1f,xxxx,0xaa,xxxx,0xfb,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0x38,xxxx,xxxx,xxxx, /* 50 */
|
||||
0x2c,xxxx,xxxx,0xc6,xxxx,xxxx,0xb1,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xa2,xxxx, /* 60 */
|
||||
0xe9,0xe8,xxxx,xxxx,0x86,xxxx,0x8b,xxxx, xxxx,xxxx,xxxx,xxxx,0x5b,0x72,xxxx,xxxx, /* 70 */
|
||||
xxxx,xxxx,0x5d,0x0a,xxxx,xxxx,0x89,xxxx, 0xb0,0x88,xxxx,xxxx,xxxx,0x87,0x75,0xbd, /* 80 */
|
||||
xxxx,0x51,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,0x5a,0x58,xxxx,xxxx,0x56, /* 90 */
|
||||
xxxx,0x8a,xxxx,0x55,xxxx,xxxx,xxxx,0xb4, 0x08,xxxx,0xf6,xxxx,xxxx,0x9d,xxxx,0xbc, /* A0 */
|
||||
0x0b,xxxx,xxxx,0x5e,xxxx,xxxx,xxxx,0x22, 0x36,xxxx,0x1e,xxxx,0xb6,0xba,0x23,xxxx, /* B0 */
|
||||
0x20,xxxx,xxxx,xxxx,0x59,0x53,xxxx,0x04, 0x81,xxxx,xxxx,0xf3,xxxx,xxxx,0x3b,0x06, /* C0 */
|
||||
xxxx,0x79,0x83,0x9c,xxxx,0x18,0x80,xxxx, 0xc3,xxxx,xxxx,xxxx,0x32,xxxx,0xcf,xxxx, /* D0 */
|
||||
0xeb,xxxx,xxxx,0x33,xxxx,0xfa,xxxx,xxxx, 0xd2,xxxx,0x24,xxxx,0x74,0x41,0xb8,xxxx, /* E0 */
|
||||
xxxx,xxxx,0xd0,0x07,xxxx,xxxx,xxxx,xxxx, xxxx,0x46,xxxx,0xea,0xfe,0x78,xxxx,xxxx, /* F0 */
|
||||
};
|
||||
// 0xd5 (0x18) opcode is right but arguments could be swapped
|
||||
// 0x4e (0x2b) not sure, could be 0x1b
|
||||
|
||||
|
||||
const UINT8 majtitl2_decryption_table[256] = {
|
||||
0x87,xxxx,0x78,0xaa,xxxx,xxxx,xxxx,0x2c, 0x32,0x0a,0x0f,xxxx,0x5e,xxxx,0xc6,0x8a, /* 00 */
|
||||
0x33,xxxx,xxxx,xxxx,xxxx,0xea,xxxx,0x72, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x24,0x55, /* 10 */
|
||||
xxxx,xxxx,xxxx,0x89,0xfb,xxxx,0x59,0x02, xxxx,xxxx,0x5d,xxxx,xxxx,xxxx,0x36,xxxx, /* 20 */
|
||||
xxxx,0x06,0x79,xxxx,xxxx,0x1e,0x07,xxxx, xxxx,xxxx,0x83,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
|
||||
0x9d,xxxx,xxxx,0x74,xxxx,xxxx,xxxx,0x0c, 0x58,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 40 */
|
||||
0x3c,xxxx,0x03,xxxx,xxxx,0xfa,0x43,xxxx, 0xbf,xxxx,xxxx,0x75,xxxx,0x88,xxxx,0x80, /* 50 */
|
||||
xxxx,0xa3,xxxx,0xfe,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0x3a,xxxx,xxxx,xxxx, /* 60 */
|
||||
0x2b,xxxx,xxxx,xxxx,xxxx,0xe9,0x5f,xxxx, 0x46,xxxx,0x41,xxxx,0x18,0xb8,xxxx,xxxx, /* 70 */
|
||||
0xb4,0x5a,0xb1,xxxx,xxxx,0x50,0xe8,0x20, xxxx,0xb2,xxxx,xxxx,xxxx,xxxx,xxxx,0x51, /* 80 */
|
||||
xxxx,xxxx,xxxx,0x56,xxxx,xxxx,xxxx,xxxx, xxxx,0xcf,xxxx,xxxx,xxxx,0xc3,xxxx,xxxx, /* 90 */
|
||||
xxxx,xxxx,xxxx,xxxx,0x0b,xxxx,xxxx,0xb5, 0x57,xxxx,xxxx,0xc7,0x3b,xxxx,xxxx,xxxx, /* A0 */
|
||||
xxxx,xxxx,xxxx,xxxx,0xb6,xxxx,0xeb,xxxx, 0x38,xxxx,0xa0,0x08,xxxx,0x86,0xb0,xxxx, /* B0 */
|
||||
0x42,0x1f,0x73,xxxx,0xf6,xxxx,xxxx,xxxx, 0x53,xxxx,0x52,xxxx,0x04,0xbd,xxxx,xxxx, /* C0 */
|
||||
0x26,0xff,0x2e,xxxx,0x81,xxxx,0x47,xxxx, xxxx,xxxx,xxxx,0xd0,0x22,xxxx,xxxx,0xb9, /* D0 */
|
||||
0x23,xxxx,0xf3,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0xd2,0x8b,0xba,xxxx,xxxx,xxxx,0x5b, /* E0 */
|
||||
xxxx,xxxx,0x9c,xxxx,xxxx,xxxx,xxxx,0xfc, 0xbc,0xa2,0x2a,xxxx,xxxx,0x8e,0xbb,xxxx, /* F0 */
|
||||
};
|
||||
// 0x7c (0x18) opcode is right but arguments could be swapped
|
||||
// 0x70 (0x2b) not sure, could be 0x1b
|
||||
|
||||
|
||||
const UINT8 hook_decryption_table[256] = {
|
||||
0xb6,0x20,0x22,xxxx,0x0f,0x57,0x59,0xc6, 0xeb,xxxx,0xb0,0xbb,0x3b,xxxx,xxxx,xxxx, /* 00 */
|
||||
0x36,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0xfe,xxxx,xxxx,xxxx,xxxx,xxxx,0xa0, /* 10 */
|
||||
0x2e,xxxx,0x0b,xxxx,xxxx,0x58,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,0x80,xxxx,xxxx, /* 20 */
|
||||
0x33,xxxx,xxxx,0xbf,0x55,xxxx,xxxx,xxxx, 0x53,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
|
||||
0x47,0x74,xxxx,0xb1,0xb4,xxxx,xxxx,0x88, xxxx,xxxx,0x38,0xcf,xxxx,0x8e,xxxx,xxxx, /* 40 */
|
||||
xxxx,0xc7,xxxx,0x32,xxxx,0x52,0x3c,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,0x72, /* 50 */
|
||||
xxxx,0x73,xxxx,0x5a,xxxx,0x43,xxxx,xxxx, xxxx,xxxx,0x41,0xe9,0xbd,xxxx,0xb2,0xd2, /* 60 */
|
||||
xxxx,0xaa,0xa2,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,0x26,xxxx,xxxx,0x8a,xxxx, /* 70 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x18, xxxx,0x9d,xxxx,xxxx,xxxx,0x5d,xxxx,0x46, /* 80 */
|
||||
xxxx,xxxx,xxxx,0xf6,0xc3,0xa3,0x1e,0x07, 0x5f,0x81,xxxx,0x0c,xxxx,0xb8,xxxx,0x75, /* 90 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x79, /* A0 */
|
||||
xxxx,0x5e,xxxx,xxxx,0x06,xxxx,0xff,xxxx, 0x5b,0x24,xxxx,0x2b,xxxx,xxxx,xxxx,0x02, /* B0 */
|
||||
0x86,xxxx,xxxx,0xfb,xxxx,xxxx,0x50,0xfc, 0x08,xxxx,xxxx,xxxx,0x03,xxxx,0xb9,xxxx, /* C0 */
|
||||
xxxx,0xbc,0xe8,0x1f,0xfa,0x42,xxxx,xxxx, 0x89,xxxx,0x23,0x87,xxxx,0x2a,xxxx,xxxx, /* D0 */
|
||||
0x8b,xxxx,0xf3,0xea,0x04,0x2c,0xb5,xxxx, 0x0a,xxxx,0x51,xxxx,xxxx,0x3a,xxxx,0x9c, /* E0 */
|
||||
xxxx,xxxx,0x78,xxxx,0xba,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0xd0,0x56,xxxx,xxxx, /* F0 */
|
||||
};
|
||||
// 0x87 (0x18) opcode is right but arguments could be swapped
|
||||
// 0xbb (0x2b) not sure, could be 0x1b
|
||||
|
||||
|
||||
const UINT8 rtypeleo_decryption_table[256] = {
|
||||
0x5d,xxxx,0xc6,xxxx,xxxx,xxxx,0x2a,0x3a,xxxx,xxxx,xxxx,0x86,xxxx,0x22,xxxx,0xf3, /* 00 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,0x38,0xf7,0x42,0x04,xxxx,xxxx,0x1f,0x4b,xxxx,xxxx,0x58, /* 10 */
|
||||
0x57,0x2e,xxxx,xxxx,0x53,xxxx,0xb9,xxxx,xxxx,xxxx,xxxx,xxxx,0x20,0x55,xxxx,0x3d, /* 20 */
|
||||
0xa0,xxxx,xxxx,0x0c,0x03,xxxx,0x83,xxxx,xxxx,xxxx,0x8a,0x00,xxxx,0xaa,xxxx,xxxx, /* 30 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x41,0x0a,0x26,0x8b,0x56,0x5e,xxxx, /* 40 */
|
||||
xxxx,0x74,xxxx,xxxx,xxxx,xxxx,0x06,xxxx,xxxx,0x89,0x5b,0xc7,0x43,xxxx,xxxx,xxxx, /* 50 */
|
||||
xxxx,0xb6,xxxx,0x3b,xxxx,xxxx,xxxx,xxxx,xxxx,0x36,0xea,0x80,xxxx,xxxx,xxxx,0x5f, /* 60 */
|
||||
xxxx,0x0f,xxxx,xxxx,xxxx,0x46,xxxx,xxxx,0x3c,0x8e,xxxx,0xa3,0x87,xxxx,xxxx,xxxx, /* 70 */
|
||||
0x2b,0xfb,0x47,0x0b,xxxx,0xfc,0x02,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x72,0x2c, /* 80 */
|
||||
0x33,xxxx,xxxx,xxxx,xxxx,xxxx,0x9d,0xbd,xxxx,0xb2,xxxx,0x78,0x75,0xb8,xxxx,xxxx, /* 90 */
|
||||
xxxx,xxxx,xxxx,xxxx,0xcf,0x5a,0x88,xxxx,xxxx,xxxx,0xc3,xxxx,0xeb,0xfa,xxxx,0x32, /* A0 */
|
||||
xxxx,xxxx,xxxx,0x52,0xb4,xxxx,xxxx,xxxx,xxxx,0xbc,xxxx,xxxx,xxxx,0xb1,0x59,0x50, /* B0 */
|
||||
xxxx,xxxx,0xb5,xxxx,0x08,0xa2,0xbf,0xbb,0x1e,0x9c,xxxx,0x73,xxxx,0xd0,xxxx,xxxx, /* C0 */
|
||||
xxxx,xxxx,xxxx,xxxx,0x81,xxxx,0x79,xxxx,xxxx,0x24,0x23,xxxx,xxxx,0xb0,0x07,0xff, /* D0 */
|
||||
xxxx,0xba,0xf6,0x51,xxxx,xxxx,xxxx,0xfe,xxxx,0x92,xxxx,xxxx,xxxx,xxxx,0xe9,xxxx, /* E0 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xe8,0xd2,xxxx,0x18,xxxx,xxxx,xxxx,0xd1,xxxx,xxxx, /* F0 */
|
||||
// ^^^^
|
||||
};
|
||||
// 0xf9 (0x18) opcode is right but arguments could be swapped
|
||||
// 0x80 (0x2b) not sure, could be 0x1b
|
||||
// 0x16 (0x01) guess (wrong?)
|
||||
// fixed 0x16 = 0xf7 mapping
|
||||
// 3d = correct
|
||||
|
||||
const UINT8 inthunt_decryption_table[256] = {
|
||||
0x1f,xxxx,0xbb,0x50,xxxx,0x58,0x42,0x57, xxxx,xxxx,0xe9,xxxx,xxxx,xxxx,xxxx,0x0b, /* 00 */
|
||||
xxxx,xxxx,0x9d,0x9c,xxxx,xxxx,0x1e,xxxx, xxxx,0xb4,0x5b,xxxx,xxxx,xxxx,xxxx,xxxx, /* 10 */
|
||||
xxxx,xxxx,0x78,0xc7,xxxx,xxxx,0x83,xxxx, xxxx,0x0c,0xb0,0x04,xxxx,xxxx,xxxx,xxxx, /* 20 */
|
||||
xxxx,xxxx,xxxx,xxxx,0x3b,0xc3,0xb5,0x47, xxxx,xxxx,xxxx,xxxx,0x59,xxxx,xxxx,xxxx, /* 30 */
|
||||
xxxx,xxxx,xxxx,0x38,xxxx,xxxx,xxxx,xxxx, 0x5f,0xa3,0xfa,xxxx,0xe8,0x36,0x75,xxxx, /* 40 */
|
||||
0x88,0x33,xxxx,xxxx,xxxx,xxxx,0x43,xxxx, xxxx,0x87,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */
|
||||
xxxx,xxxx,xxxx,xxxx,0x8e,0xf3,0x56,xxxx, xxxx,xxxx,xxxx,0x26,0xff,xxxx,xxxx,xxxx, /* 60 */
|
||||
xxxx,xxxx,xxxx,0x2a,xxxx,0x8a,xxxx,0x18, xxxx,xxxx,0x03,0x89,0x24,xxxx,xxxx,xxxx, /* 70 */
|
||||
0x0a,xxxx,0xeb,xxxx,0x86,xxxx,xxxx,xxxx, 0x79,0x3a,xxxx,xxxx,xxxx,xxxx,0xa0,xxxx, /* 80 */
|
||||
0xea,xxxx,xxxx,xxxx,xxxx,xxxx,0x2c,xxxx, 0xc6,xxxx,xxxx,0x46,xxxx,0xaa,0xb6,0x5e, /* 90 */
|
||||
xxxx,xxxx,xxxx,xxxx,0x8b,xxxx,xxxx,xxxx, xxxx,xxxx,0xba,xxxx,0xb9,0x53,0xa2,xxxx, /* A0 */
|
||||
xxxx,0x07,xxxx,xxxx,xxxx,0x3c,0x32,xxxx, 0x2b,xxxx,0xb8,xxxx,xxxx,xxxx,xxxx,xxxx, /* B0 */
|
||||
0xbd,xxxx,xxxx,xxxx,xxxx,0x81,xxxx,0xd0, 0x08,xxxx,0x55,0x06,0xcf,xxxx,xxxx,0xfc, /* C0 */
|
||||
xxxx,xxxx,xxxx,0xb1,0xbf,xxxx,xxxx,0x51, 0x52,xxxx,0x5d,xxxx,0x5a,xxxx,0xb2,xxxx, /* D0 */
|
||||
0xfe,xxxx,xxxx,0x22,0x20,0x72,0xf6,0x80, 0x02,0x2e,xxxx,0x74,0x0f,xxxx,xxxx,xxxx, /* E0 */
|
||||
xxxx,xxxx,xxxx,xxxx,0xbc,0x41,xxxx,0xfb, 0x73,xxxx,xxxx,xxxx,0x23,0xd2,xxxx,xxxx, /* F0 */
|
||||
};
|
||||
// 0x77 (0x18) opcode is right but arguments could be swapped
|
||||
// 0xb8 (0x2b) not sure, could be 0x1b
|
||||
|
||||
const UINT8 gussun_decryption_table[256] = {
|
||||
0x63,xxxx,xxxx,0x36,xxxx,0x52,0xb1,0x5b, 0x68,0xcd,xxxx,xxxx,xxxx,0xa8,xxxx,xxxx, /* 00 */
|
||||
// gggg gggg gggg gggg
|
||||
xxxx,xxxx,0x75,0x24,0x08,0x83,0x32,0xe9, xxxx,0x79,xxxx,0x8f,0x22,xxxx,0xac,xxxx, /* 10 */
|
||||
// pppp pppp gggg
|
||||
0x5d,0xa5,0x11,0x51,0x0a,0x29,xxxx,xxxx ,0xf8,0x98,0x91,0x40,0x28,0x00,0x03,0x5f, /* 20 */
|
||||
// gggg gggg gggg gggg gggg gggg pppp
|
||||
0x26,xxxx,xxxx,0x8b,0x2f,0x02,xxxx,xxxx, 0x8e,0xab,xxxx,xxxx,0xbc,0x90,0xb3,xxxx, /* 30 */
|
||||
// gggg
|
||||
0x09,xxxx,0xc6,xxxx,xxxx,0x3a,xxxx,xxxx, xxxx,0x74,0x61,xxxx,0x33,xxxx,xxxx,xxxx, /* 40 */
|
||||
// gggg
|
||||
xxxx,0x53,0xa0,0xc0,0xc3,0x41,0xfc,0xe7, xxxx,0x2c,0x7c,0x2b,xxxx,0x4f,0xba,0x2a, /* 50 */
|
||||
// gggg gggg gggg pppp gggg gggg
|
||||
0xb0,xxxx,0x21,0x7d,xxxx,xxxx,0xb5,0x07, 0xb9,xxxx,0x27,0x46,0xf9,xxxx,xxxx,xxxx, /* 60 */
|
||||
// pppp pppp gggg gggg
|
||||
xxxx,0xea,0x72,0x73,0xad,0xd1,0x3b,0x5e, 0xe5,0x57,xxxx,0x0d,0xfd,xxxx,0x92,0x3c, /* 70 */
|
||||
// gggg pppp gggg gggg
|
||||
xxxx,0x86,0x78,0x7f,0x30,0x25,0x2d,xxxx, 0x9a,0xeb,0x04,0x0b,0xa2,0xb8,0xf6,xxxx, /* 80 */
|
||||
// pppp gggg gggg pppp gggg
|
||||
xxxx,xxxx,0x9d,xxxx,0xbb,xxxx,xxxx,0xcb, 0xa9,0xcf,xxxx,0x60,0x43,0x56,xxxx,xxxx, /* 90 */
|
||||
// gggg gggg
|
||||
xxxx,0xa3,xxxx,xxxx,0x12,xxxx,0xfa,0xb4, xxxx,0x81,0xe6,0x48,0x80,0x8c,0xd4,xxxx, /* a0 */
|
||||
// gggg gggg pppp gggg gggg
|
||||
0x42,xxxx,0x84,0xb6,0x77,0x3d,0x3e,xxxx, xxxx,0x0c,0x4b,xxxx,0xa4,xxxx,xxxx,xxxx, /* b0 */
|
||||
// gggg gggg pppp gggg gggg pppp pppp gggg
|
||||
xxxx,0xff,0x47,xxxx,0x55,0x1e,xxxx,0x59, 0x93,xxxx,xxxx,xxxx,0x88,0xc1,0x01,0xb2, /* c0 */
|
||||
// gggg
|
||||
0x85,0x2e,0x06,0xc7,0x05,xxxx,0x8a,0x5a, 0x58,0xbe,xxxx,0x4e,xxxx,0x1f,0x23,xxxx, /* d0 */
|
||||
// gggg gggg
|
||||
0xe8,xxxx,0x89,0xa1,0xd0,xxxx,xxxx,0xe2, 0x38,0xfe,0x50,0x9c,xxxx,xxxx,xxxx,0x49, /* e0 */
|
||||
// gggg gggg
|
||||
0xfb,0x20,0xf3,xxxx,xxxx,0x0f,xxxx,xxxx, xxxx,0x76,0xf7,0xbd,0x39,0x7e,0xbf,xxxx, /* f0 */
|
||||
// pppp gggg gggg gggg
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
missing opcode:
|
||||
|
||||
" " -> checked against hasamu (i.e. you can compare gussun from 2002a and hasamu from 54a0)
|
||||
"gggg" -> very probably
|
||||
"pppp" -> probably
|
||||
"????" -> missing
|
||||
|
||||
rz probably:
|
||||
14 -> 08 (2097b 20980 - routine from 2097a) (08 30) to handle the player number -> 08
|
||||
19 -> 79 (1df45 routine from 1df27 / 2282f - routine from 2281f to 22871) no 70,78,7a,7b,7c,7e,7f(ok) ok 79,7d
|
||||
5a -> 7c (195eb - (222fc - routine from 222ed to ) (7x j...) no 70,71,79,7a,7b ok (78,7c) -> 7c
|
||||
63 -> 7d (1df7f, 1df8c, 1df95, 21f08 - routine from 1df27 to ) no 70,78,7a,7b,7c,7e,7f(ok) ok 79,7d
|
||||
7b -> 0d
|
||||
82 -> 78 (78,7c) -> 78
|
||||
86 -> 2d
|
||||
ab -> 48 (1956f - routine from 194e1 to 19619 - bp 19567) (when the water go up) -> 48
|
||||
b3 -> b6 (216b6 - 216cf - 16663 (when you rotate a piece) - 175f1 - 17d2a - 17d36) -> b6
|
||||
b9 -> 0c (21210 - routine from 2117e to ) 2 bytes -> to handle messages in level 0 (learning level)
|
||||
ba -> 4b (1094d, 10b28 - routine from 10948 to 10b73) one byte -> probably 4b
|
||||
f1 -> 20 to handle the player number
|
||||
|
||||
rz guess:
|
||||
06 -> b1 (22872 - routine from 22872 to 2289d)
|
||||
09 -> cd (22a17 - routine from 229ed to 22a1a)
|
||||
0d -> a8 (
|
||||
1b -> 8f (1d8f9 - routine from 1d8c7 to 1d8fc) - three bytes (pop instruction for the push in 1d8e6)
|
||||
22 -> 11 (1deff - routine from 1dee8 to 1df26) -> 11 - to handle sprite animation
|
||||
25 -> 29 (195a0 - routine from 194e1 to ) (19,29)
|
||||
28 -> f8 (
|
||||
29 -> 98 (1df22 - routine from 1dee8 to 1df26) -> 98 - to handle sprite animation
|
||||
2b -> 40 (1d4d2 1db81 1dba9 - routine from 1d4b2 to 1d4de) -> 40
|
||||
2c -> 28 (20333 - routine from 2032a to 20366) (18,28)
|
||||
2d -> 00 (1df1d - routine from 1dee8 to 1df26) -> 00 - to handle sprite animation
|
||||
34 -> 2f (20381 - routine from 2037b to 20391) - used to handle number of lives and game over
|
||||
40 -> 09
|
||||
52 -> a0
|
||||
55 -> 41
|
||||
59 -> 2c (220cf - 2037f - routine from 2202f to ) 2bytes (2c,
|
||||
5b -> 2b (used in "Service Mode" / "CHARACTER menu")
|
||||
5d -> 4f
|
||||
62 -> 21 (1cf86 1cfa3 - routine from 1cf61 to 1cff4) (water in level 1) (01 11 19 29)
|
||||
66 -> b5 (1daaf - routine from 1da61 to 1daca) - two bytes (colors effect)
|
||||
6a -> 27 (20368 - routine from 20368 to 2037a) - used to limit the max lives number
|
||||
73 -> 73 (1d4f7 - routine from 1d4df to 1d539) -> (no 70,71,72,74,75,76,77,78,79,7a,7b,7c,7d,7e,7f) - ok 73
|
||||
7c -> fd
|
||||
7e -> 92 (1e095 - routine from 1e073 to 1e0cf)
|
||||
83 -> 7f (194cd - routine from) no 70,78,79,7a,7b,7c,7d,7e ok 77(no) ok 7f
|
||||
84 -> 08 (1d8f1 - routine from 1d8c7 to 1d8fc) - three bytes (ok 30) (sprite animation) -> 30
|
||||
88 -> 9a
|
||||
92 -> 9d
|
||||
97 -> cb
|
||||
a4 -> 12 (02,12) - routine from 1d392 -> 12
|
||||
a7 -> b4 (2029a - routine from 20290 to
|
||||
ad -> 8c (1d559, 1d8d4 - routine from 1d547 - ; routine from 1d8b8 to 1d8fc) ..............................
|
||||
ae -> d4 (20215 - ) used when you insert a coin to handle the "coin number" in decimal
|
||||
b0 -> 42 (routine from 128db)
|
||||
b2 -> 84 (20a8b - 20acc) 20,21,84,85 (scroll down the object) - to handle the player number
|
||||
b4 -> 77 (1d03a, 1d57a - routine from 1d4df ) no 70,71,76,78,79,7a,7b,7c,7d,7e,7f ok 77
|
||||
b6 -> 3e
|
||||
bc -> a4
|
||||
c2 -> 47 (22881, 220ff - routine from 22872 to 22885)
|
||||
d0 -> 85 (routine from 16a3e) (when you rotate a piece)
|
||||
db -> 4e (18b1a)
|
||||
eb -> 9c
|
||||
ef -> 49 (dec CW) (used in "Service Mode" / "CHARACTER menu")
|
||||
f9 -> 76 (16d02(f 16cfa)-16598-165a1-18de7(f 18dc4) no 71(no),77(no),(icons? 70,76,78,7a,7c,7e),79,7d,7f(no) maybe 76
|
||||
fb -> bd
|
||||
fd -> 7e (1d659 - routine from 1d63c to 1d65e) no 70,76,77,78,79,7a,7b, 7c,7d,7e,7f ok 7e
|
||||
|
||||
missing V35+ core:
|
||||
0f 92 -> of 92 not supported (1011d before STI instruction) (for now no effects)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
AS notes:
|
||||
0x1e is lodsb not lds,noted from 2344f
|
||||
0x16 is xor r8,r8 not xor r16,r16
|
||||
0xc8 not inc aw but xch bw,aw
|
||||
0xcd is 0xc1 not 0xbd(palette at startup)
|
||||
0x97 guess,but seems right(228c1),known to *not* be ret %Iw.
|
||||
0x00 wrong(for sure it needs a one byte operand due to push es called at one point...)
|
||||
0x19 guess (0x82 PRE)
|
||||
0xc2 guess,it could be dec iy...
|
||||
|
||||
above - c8 (inc aw) guess from stos code
|
||||
0xc5 -> 1e (push ds) guess (pop ds soon after) right?
|
||||
0xa9 -> 81 (not 0x82 PRE) guess from 237df
|
||||
0xcd -> c1 total guess (wrong but 3 bytes)
|
||||
*/
|
||||
|
||||
/*
|
||||
e0100 palette sub-routine:
|
||||
12485: 23 push es
|
||||
12486: 27 C2 mov es,dw
|
||||
12488: D7 C0 xor aw,aw
|
||||
1248A: D7 FF xor iy,iy
|
||||
1248C: 44 00 01 mov cw,$0100
|
||||
1248F: 81 5D repe stosw
|
||||
12491: 95 22 06 97 39 mov byte ss:[$3997],$FF
|
||||
12497: 3A pop es
|
||||
12498: 60 ret
|
||||
|
||||
d1a86
|
||||
|
||||
unk
|
||||
add bw,bw [d8]
|
||||
add ix,sp [e6]
|
||||
add iy,sp [e7]
|
||||
clc
|
||||
ret
|
||||
*/
|
||||
|
||||
const UINT8 leagueman_decryption_table[256] = {
|
||||
xxxx,xxxx,xxxx,0x55,0xbb,xxxx,0x23,0x79, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x38,xxxx, /* 00 */
|
||||
0x01,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0x3d,xxxx,xxxx,xxxx,0xba,xxxx,0x1e,xxxx, /* 10 */
|
||||
0x2c,0x46,xxxx,0xb5,xxxx,0x4b,xxxx,0xfe, xxxx,xxxx,0xfb,0x2e,xxxx,xxxx,0x36,0x04, /* 20 */
|
||||
0xcf,xxxx,0xf3,0x5a,0x8a,0x0c,0x9c,xxxx, xxxx,xxxx,0xb2,0x50,xxxx,xxxx,xxxx,0x5f, /* 30 */
|
||||
xxxx,xxxx,0x24,xxxx,xxxx,0x41,0x2b,xxxx, 0xe9,xxxx,0x08,0x3b,xxxx,xxxx,xxxx,xxxx, /* 40 */
|
||||
xxxx,0xd2,0x51,xxxx,xxxx,xxxx,0x22,xxxx, 0xeb,0x3a,0x5b,0xa2,0xb1,0x80,xxxx,xxxx, /* 50 */
|
||||
xxxx,xxxx,xxxx,xxxx,0x59,0xb4,0x88,xxxx, xxxx,0xbf,0xd1,xxxx,0xb9,0x57,xxxx,xxxx, /* 60 */
|
||||
0x72,xxxx,0x73,xxxx,xxxx,xxxx,xxxx,0x0f, xxxx,xxxx,xxxx,xxxx,0x56,xxxx,xxxx,0xc6, /* 70 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,0x2a,0x8e,xxxx, 0x81,0xa3,0x58,xxxx,0xaa,0x78,0x89,xxxx, /* 80 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xbd,xxxx, xxxx,xxxx,0xff,xxxx,xxxx,xxxx,0x07,0x53, /* 90 */
|
||||
0xa0,xxxx,xxxx,0x5e,0xb0,xxxx,0x83,0xf6, xxxx,0x26,0x32,xxxx,xxxx,xxxx,0x74,0x0a, /* A0 */
|
||||
0x18,xxxx,xxxx,xxxx,0x75,0x03,xxxx,xxxx, 0xb6,0x02,xxxx,xxxx,0x43,xxxx,0xb8,xxxx, /* B0 */
|
||||
0xe8,xxxx,0xfc,xxxx,0x20,0xc3,xxxx,0x06, xxxx,0x1f,0x86,0x00,xxxx,xxxx,xxxx,0xd0, /* C0 */
|
||||
0x47,xxxx,0x87,xxxx,xxxx,0x9d,0x3c,0xc7, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* D0 */
|
||||
xxxx,xxxx,xxxx,0x8b,xxxx,xxxx,0x33,xxxx, xxxx,xxxx,xxxx,xxxx,0xfa,0x42,xxxx,xxxx, /* E0 */
|
||||
xxxx,xxxx,xxxx,0xea,xxxx,0x52,xxxx,0x5d, xxxx,xxxx,xxxx,xxxx,0xbc,xxxx,xxxx,xxxx, /* F0 */
|
||||
};
|
||||
// 0x25 (0x4b) guess
|
||||
// 0x10 (0x01) guess (wrong?)
|
||||
|
||||
|
||||
const UINT8 psoldier_decryption_table[256] = {
|
||||
xxxx,xxxx,xxxx,0x8a,xxxx,0xaa,xxxx,xxxx, xxxx,0x20,0x23,0x55,xxxx,0xb5,0x0a,xxxx, /* 00 */
|
||||
xxxx,0x46,xxxx,0xb6,xxxx,0x74,0x8b,xxxx, xxxx,0xba,0x01,xxxx,xxxx,0x5a,0x86,0xfb, /* 10 */
|
||||
0xb2,xxxx,0xb0,xxxx,0x42,0x06,0x1e,0x08, 0x22,0x9d,xxxx,xxxx,xxxx,xxxx,xxxx,0x73, /* 20 */
|
||||
xxxx,xxxx,0x5f,xxxx,xxxx,0xd0,xxxx,0xff, xxxx,xxxx,0xbd,xxxx,0x03,xxxx,0xb9,xxxx, /* 30 */
|
||||
xxxx,xxxx,xxxx,0x51,0x5e,0x24,xxxx,xxxx, xxxx,xxxx,xxxx,0x58,0x59,xxxx,xxxx,xxxx, /* 40 */
|
||||
0x52,xxxx,xxxx,xxxx,0xa0,xxxx,xxxx,0x02, 0xd2,xxxx,0x79,0x26,0x3a,0x0f,0xcf,0xb4, /* 50 */
|
||||
0xf3,xxxx,xxxx,0x50,xxxx,0x75,0xb1,xxxx, 0xd1,0x47,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 60 */
|
||||
0xc6,xxxx,xxxx,xxxx,xxxx,xxxx,0xbc,xxxx, xxxx,xxxx,xxxx,xxxx,0x53,0x41,xxxx,xxxx, /* 70 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x04,xxxx, xxxx,xxxx,xxxx,0x2c,xxxx,0xbf,xxxx,xxxx, /* 80 */
|
||||
xxxx,xxxx,0xe8,xxxx,xxxx,0x78,xxxx,0xbb, xxxx,xxxx,0x1f,0x2b,0x87,xxxx,0x4b,0x56, /* 90 */
|
||||
0x36,0x33,xxxx,xxxx,xxxx,0x9c,0xc3,xxxx, xxxx,0x81,xxxx,0xe9,xxxx,0xfa,xxxx,xxxx, /* A0 */
|
||||
xxxx,0x72,xxxx,0xa2,xxxx,xxxx,0xc7,xxxx, xxxx,0x92,xxxx,xxxx,0x88,xxxx,xxxx,xxxx, /* B0 */
|
||||
0x3b,xxxx,0x0c,xxxx,0x80,xxxx,xxxx,xxxx, xxxx,0x2e,xxxx,xxxx,xxxx,0x57,xxxx,0x8e, /* C0 */
|
||||
0x07,xxxx,0xa3,xxxx,xxxx,xxxx,0x3d,xxxx, 0xfe,xxxx,xxxx,0xfc,0xea,xxxx,0x38,xxxx, /* D0 */
|
||||
0x3c,0xf6,xxxx,xxxx,xxxx,0x18,xxxx,xxxx, 0xb8,xxxx,xxxx,xxxx,0x2a,0x5d,0x5b,xxxx, /* E0 */
|
||||
xxxx,0x43,0x32,xxxx,xxxx,xxxx,0xeb,xxxx, xxxx,xxxx,xxxx,xxxx,0x83,0x89,xxxx,xxxx, /* F0 */
|
||||
};
|
||||
// 0x9e (0x4b) guess
|
||||
// 0x1a (0x01) guess (wrong?)
|
||||
|
||||
|
||||
const UINT8 dsoccr94_decryption_table[256] = {
|
||||
xxxx,0xd1,xxxx,xxxx,xxxx,0x79,0x2e,xxxx, xxxx,xxxx,0x5a,0x0f,xxxx,xxxx,0x43,xxxx, /* 00 */
|
||||
xxxx,xxxx,0xe8,0x50,xxxx,xxxx,xxxx,0xa0, 0x5d,0x22,xxxx,xxxx,0xb2,0x3a,xxxx,xxxx, /* 10 */
|
||||
0xf6,0x8a,0x41,xxxx,xxxx,0x81,xxxx,xxxx, xxxx,xxxx,0x2b,0x58,xxxx,xxxx,xxxx,0xc6, /* 20 */
|
||||
xxxx,xxxx,0xb9,xxxx,xxxx,0x2a,xxxx,0x3c, xxxx,0x80,0x26,xxxx,0xb0,xxxx,0x47,xxxx, /* 30 */
|
||||
xxxx,xxxx,0x0a,0x55,xxxx,xxxx,xxxx,0x88, xxxx,xxxx,0x87,xxxx,xxxx,0xb4,0x0c,xxxx, /* 40 */
|
||||
0x73,0x53,xxxx,xxxx,0x3b,0x1f,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */
|
||||
0x01,xxxx,xxxx,xxxx,xxxx,0x1e,xxxx,xxxx, 0xc3,xxxx,0xa3,0x74,xxxx,0x32,0x42,0x75, /* 60 */
|
||||
0xfc,xxxx,0xb8,xxxx,0x33,xxxx,0x5e,xxxx, xxxx,0xaa,xxxx,xxxx,0x04,xxxx,0x9c,0xba, /* 70 */
|
||||
xxxx,xxxx,0x24,0x89,xxxx,xxxx,0xea,xxxx, 0x23,xxxx,xxxx,xxxx,0xbb,xxxx,xxxx,0xc7, /* 80 */
|
||||
xxxx,0x8e,xxxx,0x52,xxxx,0x18,xxxx,0x72, xxxx,xxxx,xxxx,xxxx,0xb6,xxxx,xxxx,xxxx, /* 90 */
|
||||
0xfa,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0xb1,xxxx,xxxx,xxxx,xxxx,0x57,0x78,0xa2, /* A0 */
|
||||
xxxx,0x3d,0x51,xxxx,xxxx,0xbf,0x46,0x2c, xxxx,xxxx,0xfb,xxxx,xxxx,xxxx,xxxx,0x38, /* B0 */
|
||||
0x56,xxxx,0xcf,xxxx,0x08,xxxx,xxxx,xxxx, 0x5b,0x07,xxxx,xxxx,xxxx,0x20,0x9d,xxxx, /* C0 */
|
||||
0x03,xxxx,xxxx,xxxx,xxxx,xxxx,0xbc,0x86, 0x59,xxxx,0x02,xxxx,0xff,0xd2,0x8b,xxxx, /* D0 */
|
||||
xxxx,0xd0,xxxx,xxxx,xxxx,xxxx,xxxx,0xe9, 0x06,xxxx,0x5f,0xf3,xxxx,0xb5,xxxx,xxxx, /* E0 */
|
||||
0xeb,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,xxxx, 0x36,xxxx,xxxx,xxxx,xxxx,0xbd,0xfe,xxxx, /* F0 */
|
||||
};
|
||||
|
||||
// 0x95 (0x18) opcode is right but arguments could be swapped
|
||||
// 0x2a (0x2b) not sure, could be 0x1b
|
||||
// 0x60 (0x01) guess (wrong?)
|
||||
|
||||
|
||||
/* preliminary table by Pierpaolo Prazzoli */
|
||||
const UINT8 matchit2_decryption_table[256] = {
|
||||
xxxx,0x86,0x0a,xxxx,0x32,0x01,0x81,0xbe, 0xea,xxxx,0xbb,xxxx,xxxx,xxxx,0xa5,0xf6, /* 00 */
|
||||
// new new new new new new new new new
|
||||
0x5d,0x8c,0xf3,0xc4,0x42,0x5a,0x22,0x26, xxxx,0x58,xxxx,0xfd,0x59,0x53,0x80,0x09, /* 10 */
|
||||
// new new new new !!!! new !!!! new !!!! new new new !!!!
|
||||
xxxx,0x1e,0x48,0xe2,0x50,xxxx,0xc3,0x23, xxxx,xxxx,0xe9,xxxx,0x40,0x83,0xa3,0x46, /* 20 */
|
||||
// new new new new new new new new new new
|
||||
0x49,0xb4,0xa9,xxxx,0xd3,0x8b,0xe8,0xb8, 0xa0,xxxx,xxxx,xxxx,0x84,xxxx,xxxx,xxxx, /* 30 */
|
||||
// !!!! ???? new !!!! new new new new
|
||||
xxxx,xxxx,xxxx,xxxx,0x14,xxxx,0x25,xxxx, xxxx,0x5e,xxxx,0x87,0x56,0xb9,0x4a,0x39, /* 40 */
|
||||
// new new new new new new new new
|
||||
0x89,xxxx,xxxx,xxxx,xxxx,0x1f,0xa4,xxxx, 0xf8,0x5f,0x21,0xb3,0x5b,xxxx,0x8d,xxxx, /* 50 */
|
||||
// new new !!!! new new !!!! new new
|
||||
xxxx,0xc5,0x7c,0x07,xxxx,0x88,0xba,0x47, 0x35,0xfb,xxxx,0x7f,xxxx,xxxx,0xc6,0xeb, /* 60 */
|
||||
// new !!!! new new new new new new !!!! new
|
||||
xxxx,0xc7,xxxx,xxxx,0xd2,0xa1,0x72,0x79, 0xfe,0x24,0xab,0x2a,0xbc,0x0d,0x8f,0x7e, /* 70 */
|
||||
// !!!! new new new new new new new new new !!!!
|
||||
xxxx,0x7d,xxxx,0xe7,0x2d,xxxx,xxxx,0x57, 0x0b,0xa2,xxxx,0x9d,xxxx,xxxx,0x74,0x85, /* 80 */
|
||||
// !!!! new new new new new new new new
|
||||
0xaf,0x2f,0x8a,0xe6,0x08,xxxx,0xff,xxxx, xxxx,0x1c,xxxx,xxxx,0x02,xxxx,xxxx,xxxx, /* 90 */
|
||||
// new !!!! new new new new !!!! new
|
||||
0x43,0x04,xxxx,xxxx,0xbf,0x3b,0x93,0x38, xxxx,xxxx,xxxx,0x77,xxxx,0xb0,xxxx,0x3a, /* A0 */
|
||||
// new new new new new new new new new
|
||||
0xfc,xxxx,0xb5,xxxx,xxxx,xxxx,xxxx,0x05, 0x52,0x76,0x2b,0xe5,0xbd,xxxx,0x0e,0xb1, /* B0 */
|
||||
// new new new new new new new new new !!!!
|
||||
0x73,xxxx,xxxx,0x45,0x92,0x99,xxxx,0xf7, 0x3d,0xd0,0xb6,0x36,0xf9,0xfa,0x0f,xxxx, /* C0 */
|
||||
// new new new new new new new !!!! new new
|
||||
0x75,xxxx,0xaa,0x9c,xxxx,0x11,xxxx,xxxx, 0x27,0x4b,xxxx,0x2c,0x51,0x2e,0x4d,xxxx, /* D0 */
|
||||
// new !!!! new new new new new new new !!!!
|
||||
0x55,0x3c,xxxx,0xb7,xxxx,0xd1,0x8e,xxxx, 0xb2,xxxx,0x78,xxxx,0x12,xxxx,0x29,0x0c, /* E0 */
|
||||
// new new new ???? new new new new new new new
|
||||
0x33,xxxx,0xf2,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0x03,0x06,0xa8,xxxx,xxxx,0xcf,xxxx, /* F0 */
|
||||
// new new new new new new
|
||||
};
|
||||
/*
|
||||
Unknown (marked "????")
|
||||
|
||||
from shisen 2:
|
||||
E4 -> pc: b08; f458, 1920 (99% 1 byte at boot and sometimes when a piece is selected)
|
||||
b65c (after one match is finished with the girl on the background or when you finish some levels in the other modes)
|
||||
|
||||
Found (marked "!!!!")
|
||||
14 -> pc: 8b2a -> 42
|
||||
16 -> pc: 1714, 1804, 1a70, 1cc3 (00 10 13 1C 20 21 22 34 D4 D5 after a match) -> 22
|
||||
1B -> pc: 630e (it's used to update the high score) -> FD
|
||||
1F -> pc: f30, f35, af74, 153a, 6dd8, 674f -> 09
|
||||
30 -> pc: 19af, 1986 -> 49
|
||||
31 -> pc: c804, c813, c822, 1358, c303, c312, c321, 1315, 1338 (2 bytes opcode) -> B4
|
||||
34 -> pc: 42cd -> D3
|
||||
4E -> pc: 7ac3, 7ae8 (after a 2 players match and in a 2 players match in "stalemate") -> 4a
|
||||
56 -> pc: 6587 (can be 6C, 6D, 6E, 6F, A4, A6, A7, AA, AC, AD, AE at boot) -> A4
|
||||
5A -> pc: ae83 (after an item is selected) (00 10 13 15 1B -1C already used- 1D 21 28) -> 21 (it's used to evidence tiles similar to the one selected)
|
||||
62 -> pc: 5b3f (jump 71, 7C) -> 7C
|
||||
6B -> pc: 1810, 1936 (jump) -> 7F
|
||||
74 -> pc: ca75 -> D2
|
||||
7F -> pc: 6b7e, 51d7, 5a8c, 5a9a, 5996 (jump: 7C, 7E) -> 7E
|
||||
81 -> pc: 599d (jump: 7D, 7F) -> 7D
|
||||
91 -> pc: 6e0c, 96ef, 96d0 (1 byte opcode) -> 2F
|
||||
99 -> pc: 96f7, 9702 (after undo button is pressed) -> 1C (it's used to update the score when the you undo the moves)
|
||||
BF -> pc: 6af3, 6b01, ca73, ab39 (2 bytes opcode) -> B1
|
||||
C4 -> pc: deb4 -> 92 from bbmanw
|
||||
EC -> pc: 966e, 9679 -> 12 from bbmanw
|
||||
D2 -> pc: 631c (it's used to update the high score) (6C, 6E, A6, AA, AE) -> AA
|
||||
|
||||
the ones marked with "new" are checked against dynablst and bomberman tables
|
||||
*/
|
||||
|
||||
|
||||
const UINT8 test_decryption_table[256] = {
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 00 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 10 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 20 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 40 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 60 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 70 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 80 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 90 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* A0 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* B0 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* C0 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* D0 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* E0 */
|
||||
xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* F0 */
|
||||
};
|
||||
|
||||
|
||||
void irem_cpu_decrypt(INT32 /*cpu*/,const UINT8 *decryption_table, UINT8 *src, UINT8 *dest, INT32 size)
|
||||
{
|
||||
for (INT32 A = 0;A < size;A++)
|
||||
{
|
||||
dest[A] = decryption_table[src[A]];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
extern const UINT8 gunforce_decryption_table[];
|
||||
extern const UINT8 bomberman_decryption_table[];
|
||||
extern const UINT8 lethalth_decryption_table[];
|
||||
extern const UINT8 dynablaster_decryption_table[];
|
||||
extern const UINT8 mysticri_decryption_table[];
|
||||
extern const UINT8 majtitl2_decryption_table[];
|
||||
extern const UINT8 hook_decryption_table[];
|
||||
extern const UINT8 rtypeleo_decryption_table[];
|
||||
extern const UINT8 inthunt_decryption_table[];
|
||||
extern const UINT8 gussun_decryption_table[];
|
||||
extern const UINT8 leagueman_decryption_table[];
|
||||
extern const UINT8 psoldier_decryption_table[];
|
||||
extern const UINT8 dsoccr94_decryption_table[];
|
||||
extern const UINT8 matchit2_decryption_table[];
|
||||
|
||||
extern const UINT8 test_decryption_table[];
|
||||
|
||||
extern void irem_cpu_decrypt(INT32 cpu,const UINT8 *decryption_table, UINT8 *src,UINT8 *dest, INT32 size);
|
|
@ -0,0 +1,846 @@
|
|||
// FB Alpha '88 Games driver module
|
||||
// Based on MAME driver by Nicola Salmoria
|
||||
|
||||
#include "tiles_generic.h"
|
||||
#include "konami_intf.h"
|
||||
#include "konamiic.h"
|
||||
#include "burn_ym2151.h"
|
||||
#include "UPD7759.h"
|
||||
|
||||
static UINT8 *AllMem;
|
||||
static UINT8 *MemEnd;
|
||||
static UINT8 *AllRam;
|
||||
static UINT8 *RamEnd;
|
||||
static UINT8 *DrvKonROM;
|
||||
static UINT8 *DrvZ80ROM;
|
||||
static UINT8 *DrvGfxROM0;
|
||||
static UINT8 *DrvGfxROM1;
|
||||
static UINT8 *DrvGfxROM2;
|
||||
static UINT8 *DrvGfxROMExp0;
|
||||
static UINT8 *DrvGfxROMExp1;
|
||||
static UINT8 *DrvGfxROMExp2;
|
||||
static UINT8 *DrvSndROM0;
|
||||
static UINT8 *DrvSndROM1;
|
||||
static UINT8 *DrvBankRAM;
|
||||
static UINT8 *DrvKonRAM;
|
||||
static UINT8 *DrvPalRAM;
|
||||
static UINT8 *DrvZ80RAM;
|
||||
static UINT8 *DrvNVRAM;
|
||||
|
||||
static UINT32 *DrvPalette;
|
||||
static UINT8 DrvRecalc;
|
||||
|
||||
static UINT8 *soundlatch;
|
||||
static UINT8 *nDrvBank;
|
||||
|
||||
static INT32 videobank;
|
||||
static INT32 zoomreadroms;
|
||||
static INT32 k88games_priority;
|
||||
static INT32 UPD7759Device;
|
||||
|
||||
static UINT8 DrvJoy1[8];
|
||||
static UINT8 DrvJoy2[8];
|
||||
static UINT8 DrvJoy3[8];
|
||||
static UINT8 DrvDips[3];
|
||||
static UINT8 DrvInputs[3];
|
||||
static UINT8 DrvReset;
|
||||
|
||||
static struct BurnInputInfo games88InputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" },
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start" },
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 0, "p1 fire 1" },
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 1, "p1 fire 2" },
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 2, "p1 fire 3" },
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" },
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" },
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" },
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" },
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" },
|
||||
|
||||
{"P3 Start", BIT_DIGITAL, DrvJoy3 + 3, "p3 start" },
|
||||
{"P3 Button 1", BIT_DIGITAL, DrvJoy3 + 0, "p3 fire 1" },
|
||||
{"P3 Button 2", BIT_DIGITAL, DrvJoy3 + 1, "p3 fire 2" },
|
||||
{"P3 Button 3", BIT_DIGITAL, DrvJoy3 + 2, "p3 fire 3" },
|
||||
|
||||
{"P4 Start", BIT_DIGITAL, DrvJoy3 + 7, "p4 start" },
|
||||
{"P4 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p4 fire 1" },
|
||||
{"P4 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p4 fire 2" },
|
||||
{"P4 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p4 fire 3" },
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
|
||||
{"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" },
|
||||
{"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
|
||||
{"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
|
||||
{"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" },
|
||||
};
|
||||
|
||||
STDINPUTINFO(games88)
|
||||
|
||||
static struct BurnDIPInfo games88DIPList[]=
|
||||
{
|
||||
{0x14, 0xff, 0xff, 0xf0, NULL },
|
||||
{0x15, 0xff, 0xff, 0xff, NULL },
|
||||
{0x16, 0xff, 0xff, 0x7b, NULL },
|
||||
|
||||
// {0 , 0xfe, 0 , 2, "Flip Screen" },
|
||||
// {0x14, 0x01, 0x10, 0x10, "Off" },
|
||||
// {0x14, 0x01, 0x10, 0x00, "On" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "World Records" },
|
||||
{0x14, 0x01, 0x20, 0x20, "Don't Erase" },
|
||||
{0x14, 0x01, 0x20, 0x00, "Erase on Reset" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Service Mode" },
|
||||
{0x14, 0x01, 0x40, 0x40, "Off" },
|
||||
{0x14, 0x01, 0x40, 0x00, "On" },
|
||||
|
||||
{0 , 0xfe, 0 , 16, "Coin A" },
|
||||
{0x15, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" },
|
||||
{0x15, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" },
|
||||
{0x15, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" },
|
||||
{0x15, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" },
|
||||
{0x15, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" },
|
||||
{0x15, 0x01, 0x0f, 0x00, "Free Play" },
|
||||
|
||||
{0 , 0xfe, 0 , 16, "Coin B" },
|
||||
{0x15, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" },
|
||||
{0x15, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" },
|
||||
{0x15, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" },
|
||||
{0x15, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" },
|
||||
{0x15, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" },
|
||||
{0x15, 0x01, 0xf0, 0x00, "No Coin B" },
|
||||
|
||||
// {0 , 0xfe, 0 , 4, "Cabinet" },
|
||||
// {0x16, 0x01, 0x06, 0x06, "Cocktail" },
|
||||
// {0x16, 0x01, 0x06, 0x04, "Cocktail (A)" },
|
||||
// {0x16, 0x01, 0x06, 0x02, "Upright" },
|
||||
// {0x16, 0x01, 0x06, 0x00, "Upright (D)" },
|
||||
|
||||
{0 , 0xfe, 0 , 4, "Difficulty" },
|
||||
{0x16, 0x01, 0x60, 0x60, "Easy" },
|
||||
{0x16, 0x01, 0x60, 0x40, "Normal" },
|
||||
{0x16, 0x01, 0x60, 0x20, "Hard" },
|
||||
{0x16, 0x01, 0x60, 0x00, "Hardest" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Demo Sounds" },
|
||||
{0x16, 0x01, 0x80, 0x80, "Off" },
|
||||
{0x16, 0x01, 0x80, 0x00, "On" },
|
||||
};
|
||||
|
||||
STDDIPINFO(games88)
|
||||
|
||||
void games88_main_write(UINT16 address, UINT8 data)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x5f84:
|
||||
zoomreadroms = data & 0x04;
|
||||
return;
|
||||
|
||||
case 0x5f88:
|
||||
// watchdog
|
||||
return;
|
||||
|
||||
case 0x5f8c:
|
||||
*soundlatch = data;
|
||||
return;
|
||||
|
||||
case 0x5f90:
|
||||
ZetSetVector(0xff);
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xf800) == 0x3800)
|
||||
{
|
||||
if (videobank)
|
||||
DrvBankRAM[address & 0x7ff] = data;
|
||||
else
|
||||
K051316Write(0, address & 0x7ff, data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xfff0) == 0x5fc0) {
|
||||
K051316WriteCtrl(0, address & 0x0f, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xc000) == 0x4000) {
|
||||
K052109_051960_w(address & 0x3fff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 games88_main_read(UINT16 address)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x5f94:
|
||||
return (DrvInputs[0] & 0x0f) | (DrvDips[0] & 0xf0);
|
||||
|
||||
case 0x5f95:
|
||||
return DrvInputs[1];
|
||||
|
||||
case 0x5f96:
|
||||
return DrvInputs[2];
|
||||
|
||||
case 0x5f97:
|
||||
return DrvDips[1];
|
||||
|
||||
case 0x5f9b:
|
||||
return DrvDips[2];
|
||||
}
|
||||
|
||||
if ((address & 0xf800) == 0x3800)
|
||||
{
|
||||
if (videobank) {
|
||||
return DrvBankRAM[address & 0x7ff];
|
||||
} else {
|
||||
if (zoomreadroms) {
|
||||
return K051316ReadRom(0, address & 0x7ff); // k051316_rom_0
|
||||
} else {
|
||||
return K051316Read(0, address & 0x7ff); // k051316_0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((address & 0xc000) == 0x4000) {
|
||||
return K052109_051960_r(address & 0x3fff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall games88_sound_write(UINT16 address, UINT8 data)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0x9000:
|
||||
UPD7759PortWrite(UPD7759Device, data);
|
||||
return;
|
||||
|
||||
case 0xc000:
|
||||
BurnYM2151SelectRegister(data);
|
||||
return;
|
||||
|
||||
case 0xc001:
|
||||
BurnYM2151WriteRegister(data);
|
||||
return;
|
||||
|
||||
case 0xe000:
|
||||
UPD7759Device = (data & 4) >> 2;
|
||||
UPD7759ResetWrite(UPD7759Device, data & 2);
|
||||
UPD7759StartWrite(UPD7759Device, data & 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall games88_sound_read(UINT16 address)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0xa000:
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
return *soundlatch;
|
||||
|
||||
case 0xc000:
|
||||
case 0xc001:
|
||||
return BurnYM2151ReadStatus();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void games88_set_lines(INT32 lines)
|
||||
{
|
||||
nDrvBank[0] = lines;
|
||||
|
||||
INT32 nBank = 0x10000 + (lines & 0x07) * 0x2000;
|
||||
|
||||
konamiMapMemory(DrvKonROM + nBank, 0x0000, 0x0fff, KON_ROM);
|
||||
|
||||
if (lines & 8) {
|
||||
konamiMapMemory(DrvPalRAM, 0x1000, 0x1fff, KON_RAM);
|
||||
} else {
|
||||
konamiMapMemory(DrvKonROM + nBank + 0x1000, 0x1000, 0x1fff, KON_ROM);
|
||||
konamiMapMemory(DrvKonROM + 0x0000, 0x1000, 0x1fff, KON_WRITE); // unmap writes
|
||||
}
|
||||
|
||||
videobank = lines & 0x10;
|
||||
K052109RMRDLine = lines & 0x20;
|
||||
k88games_priority = lines & 0x80;
|
||||
}
|
||||
|
||||
static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *)
|
||||
{
|
||||
INT32 layer_colorbase[3] = { 64, 0, 16 };
|
||||
|
||||
*code |= ((*color & 0x0f) << 8) | (bank << 12);
|
||||
*color = layer_colorbase[layer] + ((*color & 0xf0) >> 4);
|
||||
}
|
||||
|
||||
static void K051960Callback(INT32 */*code*/, INT32 *color, INT32 *priority, INT32 *)
|
||||
{
|
||||
*priority = (*color & 0x20) >> 5;
|
||||
*color = 32 + (*color & 0x0f);
|
||||
}
|
||||
|
||||
static void K051316Callback(INT32 *code,INT32 *color,INT32 *flags)
|
||||
{
|
||||
*flags = *color & 0x40;
|
||||
*code |= ((*color & 0x07) << 8);
|
||||
*color = 48 + ((*color & 0x38) >> 3) + ((*color & 0x80) >> 4);
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
DrvReset = 0;
|
||||
|
||||
memset (AllRam, 0, RamEnd - AllRam);
|
||||
|
||||
konamiOpen(0);
|
||||
konamiReset();
|
||||
konamiClose();
|
||||
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2151Reset();
|
||||
|
||||
KonamiICReset();
|
||||
|
||||
UPD7759Reset();
|
||||
|
||||
videobank = 0;
|
||||
zoomreadroms = 0;
|
||||
k88games_priority = 0;
|
||||
UPD7759Device = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8 *Next; Next = AllMem;
|
||||
|
||||
DrvKonROM = Next; Next += 0x020000;
|
||||
DrvZ80ROM = Next; Next += 0x010000;
|
||||
|
||||
DrvGfxROM0 = Next; Next += 0x080000;
|
||||
DrvGfxROM1 = Next; Next += 0x100000;
|
||||
DrvGfxROM2 = Next; Next += 0x040000;
|
||||
DrvGfxROMExp0 = Next; Next += 0x100000;
|
||||
DrvGfxROMExp1 = Next; Next += 0x200000;
|
||||
DrvGfxROMExp2 = Next; Next += 0x080000;
|
||||
|
||||
DrvSndROM0 = Next; Next += 0x020000;
|
||||
DrvSndROM1 = Next; Next += 0x020000;
|
||||
|
||||
DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32);
|
||||
|
||||
AllRam = Next;
|
||||
|
||||
DrvBankRAM = Next; Next += 0x000800;
|
||||
DrvKonRAM = Next; Next += 0x001000;
|
||||
DrvPalRAM = Next; Next += 0x001000;
|
||||
DrvNVRAM = Next; Next += 0x000800;
|
||||
|
||||
DrvZ80RAM = Next; Next += 0x000800;
|
||||
|
||||
soundlatch = Next; Next += 0x000001;
|
||||
nDrvBank = Next; Next += 0x000002;
|
||||
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvGfxDecode()
|
||||
{
|
||||
INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 };
|
||||
INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 };
|
||||
INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
|
||||
0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 };
|
||||
INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0,
|
||||
0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 };
|
||||
|
||||
konami_rom_deinterleave_2(DrvGfxROM0, 0x080000);
|
||||
konami_rom_deinterleave_2(DrvGfxROM1, 0x100000);
|
||||
|
||||
GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x100, DrvGfxROM0, DrvGfxROMExp0);
|
||||
GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x400, DrvGfxROM1, DrvGfxROMExp1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
AllMem = NULL;
|
||||
MemIndex();
|
||||
INT32 nLen = MemEnd - (UINT8 *)0;
|
||||
if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1;
|
||||
memset(AllMem, 0, nLen);
|
||||
MemIndex();
|
||||
|
||||
{
|
||||
if (BurnLoadRom(DrvKonROM + 0x008000, 0, 1)) return 1;
|
||||
if (BurnLoadRom(DrvKonROM + 0x010000, 1, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1;
|
||||
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x000001, 4, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x020000, 5, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x020001, 6, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x040000, 7, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x040001, 8, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x060000, 9, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x060001, 10, 2)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x000000, 11, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x000001, 12, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x020000, 13, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x020001, 14, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x040000, 15, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x040001, 16, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x060000, 17, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x060001, 18, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x080000, 19, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x080001, 20, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 21, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0a0001, 22, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 23, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 24, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 25, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0e0001, 26, 2)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x000000, 27, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x010000, 28, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x020000, 29, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x030000, 30, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x000000, 31, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x010000, 32, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x000000, 33, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x010000, 34, 1)) return 1;
|
||||
|
||||
DrvGfxDecode();
|
||||
}
|
||||
|
||||
konamiInit(1);
|
||||
konamiOpen(0);
|
||||
konamiMapMemory(DrvPalRAM + 0x0000, 0x1000, 0x1fff, KON_RAM);
|
||||
konamiMapMemory(DrvKonRAM, 0x2000, 0x2fff, KON_RAM);
|
||||
konamiMapMemory(DrvNVRAM, 0x3000, 0x37ff, KON_RAM);
|
||||
konamiMapMemory(DrvKonROM + 0x8000, 0x8000, 0xffff, KON_ROM);
|
||||
konamiSetWriteHandler(games88_main_write);
|
||||
konamiSetReadHandler(games88_main_read);
|
||||
konamiSetlinesCallback(games88_set_lines);
|
||||
konamiClose();
|
||||
|
||||
ZetInit(1);
|
||||
ZetOpen(0);
|
||||
ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM);
|
||||
ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM);
|
||||
ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM);
|
||||
ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM);
|
||||
ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM);
|
||||
ZetSetWriteHandler(games88_sound_write);
|
||||
ZetSetReadHandler(games88_sound_read);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2151Init(3579545, 75.0);
|
||||
|
||||
UPD7759Init(0, UPD7759_STANDARD_CLOCK, DrvSndROM0);
|
||||
UPD7759Init(1, UPD7759_STANDARD_CLOCK, DrvSndROM1);
|
||||
|
||||
K052109Init(DrvGfxROM0, 0x7ffff);
|
||||
K052109SetCallback(K052109Callback);
|
||||
K052109AdjustScroll(0, 0);
|
||||
|
||||
K051960Init(DrvGfxROM1, 0xfffff);
|
||||
K051960SetCallback(K051960Callback);
|
||||
K051960SetSpriteOffset(0, 0);
|
||||
|
||||
K051316Init(0, DrvGfxROM2, DrvGfxROMExp2, 0x3ffff, K051316Callback, 4, 0);
|
||||
K051316SetOffset(0, -104, -16);
|
||||
|
||||
GenericTilesInit();
|
||||
|
||||
DrvDoReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
GenericTilesExit();
|
||||
|
||||
KonamiICExit();
|
||||
|
||||
konamiExit();
|
||||
ZetExit();
|
||||
|
||||
BurnYM2151Exit();
|
||||
UPD7759Exit();
|
||||
|
||||
if (AllMem) {
|
||||
free (AllMem);
|
||||
AllMem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
if (DrvRecalc) {
|
||||
KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x1000);
|
||||
}
|
||||
|
||||
K052109UpdateScroll();
|
||||
|
||||
if (k88games_priority)
|
||||
{
|
||||
K052109RenderLayer(0, 1, DrvGfxROMExp0);
|
||||
K051960SpritesRender(DrvGfxROMExp1, 1);
|
||||
K052109RenderLayer(2, 0, DrvGfxROMExp0);
|
||||
K052109RenderLayer(1, 0, DrvGfxROMExp0);
|
||||
K051960SpritesRender(DrvGfxROMExp1, 0);
|
||||
K051316_zoom_draw(0, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
K052109RenderLayer(2, 1, DrvGfxROMExp0);
|
||||
K051316_zoom_draw(0, 4);
|
||||
K051960SpritesRender(DrvGfxROMExp1, 0);
|
||||
K052109RenderLayer(1, 0, DrvGfxROMExp0);
|
||||
K051960SpritesRender(DrvGfxROMExp1, 1);
|
||||
K052109RenderLayer(0, 0, DrvGfxROMExp0);
|
||||
}
|
||||
|
||||
BurnTransferCopy(DrvPalette);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
if (DrvReset) {
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
{
|
||||
memset (DrvInputs, 0xff, 3);
|
||||
for (INT32 i = 0; i < 8; i++) {
|
||||
DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
|
||||
DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
|
||||
DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
|
||||
}
|
||||
}
|
||||
|
||||
konamiNewFrame();
|
||||
ZetNewFrame();
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
INT32 nInterleave = 100;
|
||||
INT32 nCyclesTotal[2] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3579545 / 60 };
|
||||
INT32 nCyclesDone[2] = { 0, 0 };
|
||||
|
||||
ZetOpen(0);
|
||||
konamiOpen(0);
|
||||
|
||||
for (INT32 i = 0; i < nInterleave; i++)
|
||||
{
|
||||
INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1);
|
||||
|
||||
nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]);
|
||||
|
||||
nSegment = (nCyclesTotal[1] / nInterleave) * (i + 1);
|
||||
|
||||
nCyclesDone[1] += ZetRun(nSegment - nCyclesDone[1]);
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2151Render(pSoundBuf, nSegmentLength);
|
||||
UPD7759Update(0, pSoundBuf, nSegmentLength);
|
||||
UPD7759Update(1, pSoundBuf, nSegmentLength);
|
||||
nSoundBufferPos += nSegmentLength;
|
||||
}
|
||||
}
|
||||
|
||||
if (K052109_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE);
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
if (nSegmentLength) {
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2151Render(pSoundBuf, nSegmentLength);
|
||||
UPD7759Update(0, pSoundBuf, nSegmentLength);
|
||||
UPD7759Update(1, pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
konamiClose();
|
||||
ZetClose();
|
||||
|
||||
if (pBurnDraw) {
|
||||
DrvDraw();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvScan(INT32 nAction,INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) {
|
||||
*pnMin = 0x029705;
|
||||
}
|
||||
|
||||
if (nAction & ACB_VOLATILE) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
|
||||
ba.Data = AllRam;
|
||||
ba.nLen = RamEnd - AllRam;
|
||||
ba.szName = "All Ram";
|
||||
BurnAcb(&ba);
|
||||
|
||||
konamiCpuScan(nAction, pnMin);
|
||||
ZetScan(nAction);
|
||||
|
||||
BurnYM2151Scan(nAction);
|
||||
UPD7759Scan(0, nAction, pnMin);
|
||||
UPD7759Scan(0, nAction, pnMin);
|
||||
|
||||
KonamiICScan(nAction);
|
||||
|
||||
SCAN_VAR(videobank);
|
||||
SCAN_VAR(zoomreadroms);
|
||||
SCAN_VAR(k88games_priority);
|
||||
SCAN_VAR(UPD7759Device);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
konamiOpen(0);
|
||||
games88_set_lines(nDrvBank[0]);
|
||||
konamiClose();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// '88 Games
|
||||
|
||||
static struct BurnRomInfo games88RomDesc[] = {
|
||||
{ "861m01.k18", 0x08000, 0x4a4e2959, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Cpu
|
||||
{ "861m02.k16", 0x10000, 0xe19f15f6, 1 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "861d01.d9", 0x08000, 0x0ff1dec0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code
|
||||
|
||||
{ "861a08.a", 0x10000, 0x77a00dd6, 3 | BRF_GRA }, // 3 K052109 Tiles
|
||||
{ "861a08.c", 0x10000, 0xb422edfc, 3 | BRF_GRA }, // 4
|
||||
{ "861a08.b", 0x10000, 0x28a8304f, 3 | BRF_GRA }, // 5
|
||||
{ "861a08.d", 0x10000, 0xe01a3802, 3 | BRF_GRA }, // 6
|
||||
{ "861a09.a", 0x10000, 0xdf8917b6, 3 | BRF_GRA }, // 7
|
||||
{ "861a09.c", 0x10000, 0xf577b88f, 3 | BRF_GRA }, // 8
|
||||
{ "861a09.b", 0x10000, 0x4917158d, 3 | BRF_GRA }, // 9
|
||||
{ "861a09.d", 0x10000, 0x2bb3282c, 3 | BRF_GRA }, // 10
|
||||
|
||||
{ "861a05.a", 0x10000, 0xcedc19d0, 4 | BRF_GRA }, // 11 K051960 Tiles
|
||||
{ "861a05.e", 0x10000, 0x725af3fc, 4 | BRF_GRA }, // 12
|
||||
{ "861a05.b", 0x10000, 0xdb2a8808, 4 | BRF_GRA }, // 13
|
||||
{ "861a05.f", 0x10000, 0x32d830ca, 4 | BRF_GRA }, // 14
|
||||
{ "861a05.c", 0x10000, 0xcf03c449, 4 | BRF_GRA }, // 15
|
||||
{ "861a05.g", 0x10000, 0xfd51c4ea, 4 | BRF_GRA }, // 16
|
||||
{ "861a05.d", 0x10000, 0x97d78c77, 4 | BRF_GRA }, // 17
|
||||
{ "861a05.h", 0x10000, 0x60d0c8a5, 4 | BRF_GRA }, // 18
|
||||
{ "861a06.a", 0x10000, 0x85e2e30e, 4 | BRF_GRA }, // 19
|
||||
{ "861a06.e", 0x10000, 0x6f96651c, 4 | BRF_GRA }, // 20
|
||||
{ "861a06.b", 0x10000, 0xce17eaf0, 4 | BRF_GRA }, // 21
|
||||
{ "861a06.f", 0x10000, 0x88310bf3, 4 | BRF_GRA }, // 22
|
||||
{ "861a06.c", 0x10000, 0xa568b34e, 4 | BRF_GRA }, // 23
|
||||
{ "861a06.g", 0x10000, 0x4a55beb3, 4 | BRF_GRA }, // 24
|
||||
{ "861a06.d", 0x10000, 0xbc70ab39, 4 | BRF_GRA }, // 25
|
||||
{ "861a06.h", 0x10000, 0xd906b79b, 4 | BRF_GRA }, // 26
|
||||
|
||||
{ "861a04.a", 0x10000, 0x092a8b15, 5 | BRF_GRA }, // 27 K051316 Tiles
|
||||
{ "861a04.b", 0x10000, 0x75744b56, 5 | BRF_GRA }, // 28
|
||||
{ "861a04.c", 0x10000, 0xa00021c5, 5 | BRF_GRA }, // 29
|
||||
{ "861a04.d", 0x10000, 0xd208304c, 5 | BRF_GRA }, // 30
|
||||
|
||||
{ "861a07.a", 0x10000, 0x5d035d69, 6 | BRF_SND }, // 31 UPD7759 #0 Samples
|
||||
{ "861a07.b", 0x10000, 0x6337dd91, 6 | BRF_SND }, // 32
|
||||
|
||||
{ "861a07.c", 0x10000, 0x5067a38b, 7 | BRF_SND }, // 33 UPD7759 #1 Samples
|
||||
{ "861a07.d", 0x10000, 0x86731451, 7 | BRF_SND }, // 34
|
||||
|
||||
{ "861.g3", 0x00100, 0x429785db, 0 | BRF_OPT }, // 31 Priority Prom
|
||||
};
|
||||
|
||||
STD_ROM_PICK(games88)
|
||||
STD_ROM_FN(games88)
|
||||
|
||||
struct BurnDriver BurnDrvgames88 = {
|
||||
"88games", NULL, NULL, NULL, "1988",
|
||||
"'88 Games\0", NULL, "Konami", "GX861",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0,
|
||||
NULL, games88RomInfo, games88RomName, NULL, NULL, games88InputInfo, games88DIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
|
||||
304, 224, 4, 3
|
||||
};
|
||||
|
||||
|
||||
// Konami '88
|
||||
|
||||
static struct BurnRomInfo konami88RomDesc[] = {
|
||||
{ "861.e03", 0x08000, 0x55979bd9, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Cpu
|
||||
{ "861.e02", 0x10000, 0x5b7e98a6, 1 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "861d01.d9", 0x08000, 0x0ff1dec0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code
|
||||
|
||||
{ "861a08.a", 0x10000, 0x77a00dd6, 3 | BRF_GRA }, // 3 K052109 Tiles
|
||||
{ "861a08.c", 0x10000, 0xb422edfc, 3 | BRF_GRA }, // 4
|
||||
{ "861a08.b", 0x10000, 0x28a8304f, 3 | BRF_GRA }, // 5
|
||||
{ "861a08.d", 0x10000, 0xe01a3802, 3 | BRF_GRA }, // 6
|
||||
{ "861a09.a", 0x10000, 0xdf8917b6, 3 | BRF_GRA }, // 7
|
||||
{ "861a09.c", 0x10000, 0xf577b88f, 3 | BRF_GRA }, // 8
|
||||
{ "861a09.b", 0x10000, 0x4917158d, 3 | BRF_GRA }, // 9
|
||||
{ "861a09.d", 0x10000, 0x2bb3282c, 3 | BRF_GRA }, // 10
|
||||
|
||||
{ "861a05.a", 0x10000, 0xcedc19d0, 4 | BRF_GRA }, // 11 K051960 Tiles
|
||||
{ "861a05.e", 0x10000, 0x725af3fc, 4 | BRF_GRA }, // 12
|
||||
{ "861a05.b", 0x10000, 0xdb2a8808, 4 | BRF_GRA }, // 13
|
||||
{ "861a05.f", 0x10000, 0x32d830ca, 4 | BRF_GRA }, // 14
|
||||
{ "861a05.c", 0x10000, 0xcf03c449, 4 | BRF_GRA }, // 15
|
||||
{ "861a05.g", 0x10000, 0xfd51c4ea, 4 | BRF_GRA }, // 16
|
||||
{ "861a05.d", 0x10000, 0x97d78c77, 4 | BRF_GRA }, // 17
|
||||
{ "861a05.h", 0x10000, 0x60d0c8a5, 4 | BRF_GRA }, // 18
|
||||
{ "861a06.a", 0x10000, 0x85e2e30e, 4 | BRF_GRA }, // 19
|
||||
{ "861a06.e", 0x10000, 0x6f96651c, 4 | BRF_GRA }, // 20
|
||||
{ "861a06.b", 0x10000, 0xce17eaf0, 4 | BRF_GRA }, // 21
|
||||
{ "861a06.f", 0x10000, 0x88310bf3, 4 | BRF_GRA }, // 22
|
||||
{ "861a06.c", 0x10000, 0xa568b34e, 4 | BRF_GRA }, // 23
|
||||
{ "861a06.g", 0x10000, 0x4a55beb3, 4 | BRF_GRA }, // 24
|
||||
{ "861a06.d", 0x10000, 0xbc70ab39, 4 | BRF_GRA }, // 25
|
||||
{ "861a06.h", 0x10000, 0xd906b79b, 4 | BRF_GRA }, // 26
|
||||
|
||||
{ "861a04.a", 0x10000, 0x092a8b15, 5 | BRF_GRA }, // 27 K051316 Tiles
|
||||
{ "861a04.b", 0x10000, 0x75744b56, 5 | BRF_GRA }, // 28
|
||||
{ "861a04.c", 0x10000, 0xa00021c5, 5 | BRF_GRA }, // 29
|
||||
{ "861a04.d", 0x10000, 0xd208304c, 5 | BRF_GRA }, // 30
|
||||
|
||||
{ "861a07.a", 0x10000, 0x5d035d69, 6 | BRF_SND }, // 31 UPD7759 #0 Samples
|
||||
{ "861a07.b", 0x10000, 0x6337dd91, 6 | BRF_SND }, // 32
|
||||
|
||||
{ "861a07.c", 0x10000, 0x5067a38b, 7 | BRF_SND }, // 33 UPD7759 #1 Samples
|
||||
{ "861a07.d", 0x10000, 0x86731451, 7 | BRF_SND }, // 34
|
||||
|
||||
{ "861.g3", 0x00100, 0x429785db, 0 | BRF_OPT }, // 31 Priority Prom
|
||||
};
|
||||
|
||||
STD_ROM_PICK(konami88)
|
||||
STD_ROM_FN(konami88)
|
||||
|
||||
struct BurnDriver BurnDrvKonami88 = {
|
||||
"konami88", "88games", NULL, NULL, "1988",
|
||||
"Konami '88\0", NULL, "Konami", "GX861",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0,
|
||||
NULL, konami88RomInfo, konami88RomName, NULL, NULL, games88InputInfo, games88DIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
|
||||
304, 224, 4, 3
|
||||
};
|
||||
|
||||
|
||||
// Hyper Sports Special (Japan)
|
||||
|
||||
static struct BurnRomInfo hypsptspRomDesc[] = {
|
||||
{ "861f03.k18", 0x08000, 0x8c61aebd, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Cpu
|
||||
{ "861f02.k16", 0x10000, 0xd2460c28, 1 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "861d01.d9", 0x08000, 0x0ff1dec0, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code
|
||||
|
||||
{ "861a08.a", 0x10000, 0x77a00dd6, 3 | BRF_GRA }, // 3 K052109 Tiles
|
||||
{ "861a08.c", 0x10000, 0xb422edfc, 3 | BRF_GRA }, // 4
|
||||
{ "861a08.b", 0x10000, 0x28a8304f, 3 | BRF_GRA }, // 5
|
||||
{ "861a08.d", 0x10000, 0xe01a3802, 3 | BRF_GRA }, // 6
|
||||
{ "861a09.a", 0x10000, 0xdf8917b6, 3 | BRF_GRA }, // 7
|
||||
{ "861a09.c", 0x10000, 0xf577b88f, 3 | BRF_GRA }, // 8
|
||||
{ "861a09.b", 0x10000, 0x4917158d, 3 | BRF_GRA }, // 9
|
||||
{ "861a09.d", 0x10000, 0x2bb3282c, 3 | BRF_GRA }, // 10
|
||||
|
||||
{ "861a05.a", 0x10000, 0xcedc19d0, 4 | BRF_GRA }, // 11 K051960 Tiles
|
||||
{ "861a05.e", 0x10000, 0x725af3fc, 4 | BRF_GRA }, // 12
|
||||
{ "861a05.b", 0x10000, 0xdb2a8808, 4 | BRF_GRA }, // 13
|
||||
{ "861a05.f", 0x10000, 0x32d830ca, 4 | BRF_GRA }, // 14
|
||||
{ "861a05.c", 0x10000, 0xcf03c449, 4 | BRF_GRA }, // 15
|
||||
{ "861a05.g", 0x10000, 0xfd51c4ea, 4 | BRF_GRA }, // 16
|
||||
{ "861a05.d", 0x10000, 0x97d78c77, 4 | BRF_GRA }, // 17
|
||||
{ "861a05.h", 0x10000, 0x60d0c8a5, 4 | BRF_GRA }, // 18
|
||||
{ "861a06.a", 0x10000, 0x85e2e30e, 4 | BRF_GRA }, // 19
|
||||
{ "861a06.e", 0x10000, 0x6f96651c, 4 | BRF_GRA }, // 20
|
||||
{ "861a06.b", 0x10000, 0xce17eaf0, 4 | BRF_GRA }, // 21
|
||||
{ "861a06.f", 0x10000, 0x88310bf3, 4 | BRF_GRA }, // 22
|
||||
{ "861a06.c", 0x10000, 0xa568b34e, 4 | BRF_GRA }, // 23
|
||||
{ "861a06.g", 0x10000, 0x4a55beb3, 4 | BRF_GRA }, // 24
|
||||
{ "861a06.d", 0x10000, 0xbc70ab39, 4 | BRF_GRA }, // 25
|
||||
{ "861a06.h", 0x10000, 0xd906b79b, 4 | BRF_GRA }, // 26
|
||||
|
||||
{ "861a04.a", 0x10000, 0x092a8b15, 5 | BRF_GRA }, // 27 K051316 Tiles
|
||||
{ "861a04.b", 0x10000, 0x75744b56, 5 | BRF_GRA }, // 28
|
||||
{ "861a04.c", 0x10000, 0xa00021c5, 5 | BRF_GRA }, // 29
|
||||
{ "861a04.d", 0x10000, 0xd208304c, 5 | BRF_GRA }, // 30
|
||||
|
||||
{ "861a07.a", 0x10000, 0x5d035d69, 6 | BRF_SND }, // 31 UPD7759 #0 Samples
|
||||
{ "861a07.b", 0x10000, 0x6337dd91, 6 | BRF_SND }, // 32
|
||||
|
||||
{ "861a07.c", 0x10000, 0x5067a38b, 7 | BRF_SND }, // 33 UPD7759 #1 Samples
|
||||
{ "861a07.d", 0x10000, 0x86731451, 7 | BRF_SND }, // 34
|
||||
|
||||
{ "861.g3", 0x00100, 0x429785db, 8 | BRF_OPT }, // 31 Priority Prom
|
||||
};
|
||||
|
||||
STD_ROM_PICK(hypsptsp)
|
||||
STD_ROM_FN(hypsptsp)
|
||||
|
||||
struct BurnDriver BurnDrvHypsptsp = {
|
||||
"hypsptsp", "88games", NULL, NULL, "1988",
|
||||
"Hyper Sports Special (Japan)\0", NULL, "Konami", "GX861",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_PREFIX_KONAMI, GBF_SPORTSMISC, 0,
|
||||
NULL, hypsptspRomInfo, hypsptspRomName, NULL, NULL, games88InputInfo, games88DIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
|
||||
304, 224, 4, 3
|
||||
};
|
|
@ -0,0 +1,940 @@
|
|||
// FB Alpha Ajax driver module
|
||||
// Based on MAME driver by Manuel Abadia
|
||||
|
||||
#include "tiles_generic.h"
|
||||
#include "konami_intf.h"
|
||||
#include "konamiic.h"
|
||||
#include "burn_ym2151.h"
|
||||
#include "k007232.h"
|
||||
#include "m6809_intf.h"
|
||||
|
||||
static UINT8 *AllMem;
|
||||
static UINT8 *MemEnd;
|
||||
static UINT8 *AllRam;
|
||||
static UINT8 *RamEnd;
|
||||
static UINT8 *DrvKonROM;
|
||||
static UINT8 *DrvM6809ROM;
|
||||
static UINT8 *DrvZ80ROM;
|
||||
static UINT8 *DrvGfxROM0;
|
||||
static UINT8 *DrvGfxROM1;
|
||||
static UINT8 *DrvGfxROM2;
|
||||
static UINT8 *DrvGfxROMExp0;
|
||||
static UINT8 *DrvGfxROMExp1;
|
||||
static UINT8 *DrvSndROM0;
|
||||
static UINT8 *DrvSndROM1;
|
||||
static UINT8 *DrvShareRAM;
|
||||
static UINT8 *DrvKonRAM;
|
||||
static UINT8 *DrvPalRAM;
|
||||
static UINT8 *DrvZ80RAM;
|
||||
static UINT32 *DrvPalette;
|
||||
static UINT8 DrvRecalc;
|
||||
|
||||
static UINT8 *soundlatch;
|
||||
static UINT8 *nDrvBankRom;
|
||||
|
||||
static UINT8 DrvInputs[3];
|
||||
static UINT8 DrvJoy1[8];
|
||||
static UINT8 DrvJoy2[8];
|
||||
static UINT8 DrvJoy3[8];
|
||||
static UINT8 DrvDips[3];
|
||||
static UINT8 DrvReset;
|
||||
|
||||
static INT32 firq_enable;
|
||||
static INT32 ajax_priority;
|
||||
|
||||
static struct BurnInputInfo AjaxInputList[] = {
|
||||
{"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" },
|
||||
{"P1 Start", BIT_DIGITAL, DrvJoy1 + 3, "p1 start" },
|
||||
{"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" },
|
||||
{"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" },
|
||||
{"P1 Left", BIT_DIGITAL, DrvJoy2 + 0, "p1 left" },
|
||||
{"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" },
|
||||
{"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" },
|
||||
{"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" },
|
||||
{"P1 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p1 fire 3" },
|
||||
|
||||
{"P2 Coin", BIT_DIGITAL, DrvJoy1 + 1, "p2 coin" },
|
||||
{"P2 Start", BIT_DIGITAL, DrvJoy1 + 4, "p2 start" },
|
||||
{"P2 Up", BIT_DIGITAL, DrvJoy3 + 2, "p2 up" },
|
||||
{"P2 Down", BIT_DIGITAL, DrvJoy3 + 3, "p2 down" },
|
||||
{"P2 Left", BIT_DIGITAL, DrvJoy3 + 0, "p2 left" },
|
||||
{"P2 Right", BIT_DIGITAL, DrvJoy3 + 1, "p2 right" },
|
||||
{"P2 Button 1", BIT_DIGITAL, DrvJoy3 + 4, "p2 fire 1" },
|
||||
{"P2 Button 2", BIT_DIGITAL, DrvJoy3 + 5, "p2 fire 2" },
|
||||
{"P2 Button 3", BIT_DIGITAL, DrvJoy3 + 6, "p2 fire 3" },
|
||||
|
||||
{"Reset", BIT_DIGITAL, &DrvReset, "reset"},
|
||||
{"Service", BIT_DIGITAL, DrvJoy1 + 2, "service" },
|
||||
{"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
|
||||
{"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
|
||||
{"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" },
|
||||
};
|
||||
|
||||
STDINPUTINFO(Ajax)
|
||||
|
||||
static struct BurnDIPInfo AjaxDIPList[]=
|
||||
{
|
||||
{0x14, 0xff, 0xff, 0xff, NULL },
|
||||
{0x15, 0xff, 0xff, 0x52, NULL },
|
||||
{0x16, 0xff, 0xff, 0xff, NULL },
|
||||
|
||||
{0 , 0xfe, 0 , 16, "Coin A" },
|
||||
{0x14, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" },
|
||||
{0x14, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" },
|
||||
{0x14, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" },
|
||||
{0x14, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" },
|
||||
{0x14, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" },
|
||||
{0x14, 0x01, 0x0f, 0x00, "Free Play" },
|
||||
|
||||
{0 , 0xfe, 0 , 15, "Coin B" },
|
||||
{0x14, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" },
|
||||
{0x14, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" },
|
||||
{0x14, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" },
|
||||
{0x14, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" },
|
||||
{0x14, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" },
|
||||
{0x14, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" },
|
||||
|
||||
{0 , 0xfe, 0 , 4, "Lives" },
|
||||
{0x15, 0x01, 0x03, 0x03, "2" },
|
||||
{0x15, 0x01, 0x03, 0x02, "3" },
|
||||
{0x15, 0x01, 0x03, 0x01, "5" },
|
||||
{0x15, 0x01, 0x03, 0x00, "7" },
|
||||
|
||||
// {0 , 0xfe, 0 , 2, "Cabinet" },
|
||||
// {0x15, 0x01, 0x04, 0x00, "Upright" },
|
||||
// {0x15, 0x01, 0x04, 0x04, "Cocktail" },
|
||||
|
||||
{0 , 0xfe, 0 , 4, "Bonus Life" },
|
||||
{0x15, 0x01, 0x18, 0x18, "30000 150000" },
|
||||
{0x15, 0x01, 0x18, 0x10, "50000 200000" },
|
||||
{0x15, 0x01, 0x18, 0x08, "30000" },
|
||||
{0x15, 0x01, 0x18, 0x00, "50000" },
|
||||
|
||||
{0 , 0xfe, 0 , 4, "Difficulty" },
|
||||
{0x15, 0x01, 0x60, 0x60, "Easy" },
|
||||
{0x15, 0x01, 0x60, 0x40, "Normal" },
|
||||
{0x15, 0x01, 0x60, 0x20, "Difficult" },
|
||||
{0x15, 0x01, 0x60, 0x00, "Very Difficult" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Demo Sounds" },
|
||||
{0x15, 0x01, 0x80, 0x80, "Off" },
|
||||
{0x15, 0x01, 0x80, 0x00, "On" },
|
||||
|
||||
// {0 , 0xfe, 0 , 2, "Flip Screen" },
|
||||
// {0x16, 0x01, 0x01, 0x01, "Off" },
|
||||
// {0x16, 0x01, 0x01, 0x00, "On" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Upright Controls" },
|
||||
{0x16, 0x01, 0x02, 0x02, "Single" },
|
||||
{0x16, 0x01, 0x02, 0x00, "Dual" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Service Mode" },
|
||||
{0x16, 0x01, 0x04, 0x04, "Off" },
|
||||
{0x16, 0x01, 0x04, 0x00, "On" },
|
||||
|
||||
{0 , 0xfe, 0 , 2, "Control in 3D Stages" },
|
||||
{0x16, 0x01, 0x08, 0x08, "Normal" },
|
||||
{0x16, 0x01, 0x08, 0x00, "Inverted" },
|
||||
};
|
||||
|
||||
STDDIPINFO(Ajax)
|
||||
|
||||
static void ajax_main_bankswitch(INT32 data)
|
||||
{
|
||||
nDrvBankRom[0] = data;
|
||||
|
||||
INT32 nBank = 0x10000 + ((data & 0x80) << 9) + ((data & 7) << 13);
|
||||
|
||||
ajax_priority = data & 0x08;
|
||||
|
||||
konamiMapMemory(DrvKonROM + nBank, 0x6000, 0x7fff, KON_ROM);
|
||||
}
|
||||
|
||||
void ajax_main_write(UINT16 address, UINT8 data)
|
||||
{
|
||||
if (address <= 0x1c0)
|
||||
{
|
||||
switch ((address & 0x01c0) >> 6)
|
||||
{
|
||||
case 0x0000:
|
||||
if (address == 0 && firq_enable) {
|
||||
M6809SetIRQ(1, M6809_IRQSTATUS_AUTO);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0001:
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_ACK);
|
||||
break;
|
||||
|
||||
case 0x0002:
|
||||
*soundlatch = data;
|
||||
break;
|
||||
|
||||
case 0x0003:
|
||||
ajax_main_bankswitch(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((address & 0xfff8) == 0x0800) {
|
||||
K051937Write(address & 7, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xfc00) == 0x0c00) {
|
||||
K051960Write(address & 0x3ff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 ajax_main_read(UINT16 address)
|
||||
{
|
||||
if (address <= 0x01c0) {
|
||||
switch ((address & 0x1c0) >> 6)
|
||||
{
|
||||
case 0x0000:
|
||||
return konamiTotalCycles() & 0xff; // rand
|
||||
|
||||
case 0x0004:
|
||||
return DrvInputs[2];
|
||||
|
||||
case 0x0006:
|
||||
switch (address & 3) {
|
||||
case 0:
|
||||
return DrvInputs[0];
|
||||
|
||||
case 1:
|
||||
return DrvInputs[1];
|
||||
|
||||
case 2:
|
||||
return DrvDips[0];
|
||||
|
||||
case 3:
|
||||
return DrvDips[1];
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0x0007:
|
||||
return DrvDips[2];
|
||||
}
|
||||
}
|
||||
|
||||
if ((address & 0xfff8) == 0x0800) {
|
||||
return K051937Read(address & 7);
|
||||
}
|
||||
|
||||
if ((address & 0xfc00) == 0x0c00) {
|
||||
return K051960Read(address & 0x3ff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ajax_sub_bankswitch(UINT8 data)
|
||||
{
|
||||
nDrvBankRom[1] = data;
|
||||
|
||||
K052109RMRDLine = data & 0x40;
|
||||
|
||||
K051316WrapEnable(0, data & 0x20);
|
||||
|
||||
firq_enable = data & 0x10;
|
||||
|
||||
INT32 nBank = ((data & 0x0f) << 13) + 0x10000;
|
||||
M6809MapMemory(DrvM6809ROM + nBank, 0x8000, 0x9fff, M6809_ROM);
|
||||
}
|
||||
|
||||
void ajax_sub_write(UINT16 address, UINT8 data)
|
||||
{
|
||||
if ((address & 0xf800) == 0x0000) {
|
||||
K051316Write(0, address & 0x7ff, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xfff0) == 0x0800) {
|
||||
K051316WriteCtrl(0, address & 0x0f, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (address == 0x1800) {
|
||||
ajax_sub_bankswitch(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xc000) == 0x4000) {
|
||||
K052109Write(address & 0x3fff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 ajax_sub_read(UINT16 address)
|
||||
{
|
||||
if ((address & 0xf800) == 0x0000) {
|
||||
return K051316Read(0, address & 0x7ff);
|
||||
}
|
||||
|
||||
if ((address & 0xf800) == 0x1000) {
|
||||
return K051316ReadRom(0, address & 0x7ff);
|
||||
}
|
||||
|
||||
if ((address & 0xc000) == 0x4000) {
|
||||
return K052109Read(address & 0x3fff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __fastcall ajax_sound_write(UINT16 address, UINT8 data)
|
||||
{
|
||||
if ((address & 0xfff0) == 0xa000) {
|
||||
K007232WriteReg(0, address & 0x0f, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((address & 0xfff0) == 0xb000) {
|
||||
K007232WriteReg(1, address & 0x0f, data);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case 0x9000:
|
||||
k007232_set_bank(0, (data >> 1) & 1, (data >> 0) & 1 );
|
||||
k007232_set_bank(1, (data >> 4) & 3, (data >> 2) & 3 );
|
||||
return;
|
||||
|
||||
case 0xb80c:
|
||||
K007232SetVolume(1, 0, (data & 0x0f) * 0x11/2, (data & 0x0f) * 0x11/2);
|
||||
return;
|
||||
|
||||
case 0xc000:
|
||||
BurnYM2151SelectRegister(data);
|
||||
return;
|
||||
|
||||
case 0xc001:
|
||||
BurnYM2151WriteRegister(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 __fastcall ajax_sound_read(UINT16 address)
|
||||
{
|
||||
if ((address & 0xfff0) == 0xa000) {
|
||||
return K007232ReadReg(0, address & 0x0f);
|
||||
}
|
||||
|
||||
if ((address & 0xfff0) == 0xb000) {
|
||||
return K007232ReadReg(1, address & 0x0f);
|
||||
}
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case 0xc000:
|
||||
case 0xc001:
|
||||
return BurnYM2151ReadStatus();
|
||||
|
||||
case 0xe000:
|
||||
ZetSetIRQLine(0, ZET_IRQSTATUS_NONE);
|
||||
return *soundlatch;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *, INT32 *)
|
||||
{
|
||||
INT32 layer_colorbase[3] = { 64, 0, 32 };
|
||||
|
||||
*code |= ((*color & 0x0f) << 8) | (bank << 12);
|
||||
*code &= 0x3fff;
|
||||
*color = layer_colorbase[layer] + ((*color & 0xf0) >> 4);
|
||||
}
|
||||
|
||||
static void K051960Callback(INT32 *code, INT32 *color,INT32 *priority, INT32 *)
|
||||
{
|
||||
*priority = 0;
|
||||
if ( *color & 0x10) *priority = 1;
|
||||
if (~*color & 0x40) *priority = 2;
|
||||
if ( *color & 0x20) *priority = 3;
|
||||
*color = 16 + (*color & 0x0f);
|
||||
*code &= 0x1fff;
|
||||
}
|
||||
|
||||
static void K051316Callback(INT32 *code,INT32 *color,INT32 *)
|
||||
{
|
||||
*code |= ((*color & 0x07) << 8);
|
||||
*code &= 0x7ff;
|
||||
*color = 6 + ((*color & 0x08) >> 3);
|
||||
}
|
||||
|
||||
static void DrvK007232VolCallback0(INT32 v)
|
||||
{
|
||||
K007232SetVolume(0, 0, (v >> 0x4) * 0x11, 0);
|
||||
K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11);
|
||||
}
|
||||
|
||||
static void DrvK007232VolCallback1(INT32 v)
|
||||
{
|
||||
K007232SetVolume(1, 0, (v & 0x0f) * 0x11/2, (v & 0x0f) * 0x11/2);
|
||||
}
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
DrvReset = 0;
|
||||
|
||||
memset (AllRam, 0, RamEnd - AllRam);
|
||||
|
||||
konamiOpen(0);
|
||||
konamiReset();
|
||||
konamiClose();
|
||||
|
||||
M6809Open(0);
|
||||
M6809Reset();
|
||||
M6809Close();
|
||||
|
||||
ZetOpen(0);
|
||||
ZetReset();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2151Reset();
|
||||
|
||||
KonamiICReset();
|
||||
|
||||
firq_enable = 0;
|
||||
ajax_priority = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 MemIndex()
|
||||
{
|
||||
UINT8 *Next; Next = AllMem;
|
||||
|
||||
DrvKonROM = Next; Next += 0x030000;
|
||||
DrvM6809ROM = Next; Next += 0x030000;
|
||||
DrvZ80ROM = Next; Next += 0x010000;
|
||||
|
||||
DrvGfxROM0 = Next; Next += 0x080000;
|
||||
DrvGfxROM1 = Next; Next += 0x100000;
|
||||
DrvGfxROM2 = Next; Next += 0x080000;
|
||||
DrvGfxROMExp0 = Next; Next += 0x100000;
|
||||
DrvGfxROMExp1 = Next; Next += 0x200000;
|
||||
|
||||
DrvSndROM0 = Next; Next += 0x040000;
|
||||
DrvSndROM1 = Next; Next += 0x080000;
|
||||
|
||||
DrvPalette = (UINT32*)Next; Next += 0x800 * sizeof(UINT32);
|
||||
|
||||
AllRam = Next;
|
||||
|
||||
DrvShareRAM = Next; Next += 0x002000;
|
||||
DrvKonRAM = Next; Next += 0x002000;
|
||||
DrvPalRAM = Next; Next += 0x001000 + 0x1000;
|
||||
|
||||
DrvZ80RAM = Next; Next += 0x000800;
|
||||
|
||||
soundlatch = Next; Next += 0x000001;
|
||||
nDrvBankRom = Next; Next += 0x000002;
|
||||
|
||||
RamEnd = Next;
|
||||
MemEnd = Next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvGfxDecode()
|
||||
{
|
||||
INT32 Plane0[4] = { 0x018, 0x010, 0x008, 0x000 };
|
||||
INT32 Plane1[4] = { 0x000, 0x008, 0x010, 0x018 };
|
||||
INT32 XOffs0[16] = { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
|
||||
0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107 };
|
||||
INT32 YOffs0[16] = { 0x000, 0x020, 0x040, 0x060, 0x080, 0x0a0, 0x0c0, 0x0e0,
|
||||
0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0 };
|
||||
|
||||
konami_rom_deinterleave_2(DrvGfxROM0, 0x080000);
|
||||
konami_rom_deinterleave_2(DrvGfxROM1, 0x100000);
|
||||
|
||||
GfxDecode(0x04000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x100, DrvGfxROM0, DrvGfxROMExp0);
|
||||
GfxDecode(0x02000, 4, 16, 16, Plane1, XOffs0, YOffs0, 0x400, DrvGfxROM1, DrvGfxROMExp1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
AllMem = NULL;
|
||||
MemIndex();
|
||||
INT32 nLen = MemEnd - (UINT8 *)0;
|
||||
if ((AllMem = (UINT8 *)malloc(nLen)) == NULL) return 1;
|
||||
memset(AllMem, 0, nLen);
|
||||
MemIndex();
|
||||
|
||||
{
|
||||
if (BurnLoadRom(DrvKonROM + 0x020000, 0, 1)) return 1;
|
||||
if (BurnLoadRom(DrvKonROM + 0x010000, 1, 1)) return 1;
|
||||
memcpy (DrvKonROM + 0x08000, DrvKonROM + 0x28000, 0x8000);
|
||||
|
||||
if (BurnLoadRom(DrvM6809ROM + 0x20000, 2, 1)) return 1;
|
||||
memcpy (DrvM6809ROM + 0xa000, DrvM6809ROM + 0x22000, 0x6000);
|
||||
if (BurnLoadRom(DrvM6809ROM + 0x10000, 3, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvZ80ROM + 0x000000, 4, 1)) return 1;
|
||||
|
||||
if (strcmp(BurnDrvGetTextA(DRV_NAME), "ajax") == 0) {
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x000001, 6, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x020000, 7, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x020001, 8, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x040000, 9, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x040001, 10, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x060000, 11, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x060001, 12, 2)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x000000, 13, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x000001, 14, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x020000, 15, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x020001, 16, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x040000, 17, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x040001, 18, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x060000, 19, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x060001, 20, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x080000, 21, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x080001, 22, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0a0000, 23, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0a0001, 24, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0c0000, 25, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0c0001, 26, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0e0000, 27, 2)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x0e0001, 28, 2)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x000000, 29, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x040000, 30, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x000000, 31, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x010000, 32, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x020000, 33, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x030000, 34, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x000000, 35, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x010000, 36, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x020000, 37, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x030000, 38, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x040000, 39, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x050000, 40, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x060000, 41, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x070000, 42, 1)) return 1;
|
||||
} else {
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x000000, 5, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM0 + 0x040000, 6, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x000000, 7, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x000000, 9, 1)) return 1;
|
||||
if (BurnLoadRom(DrvGfxROM2 + 0x040000, 10, 1)) return 1;
|
||||
|
||||
if (BurnLoadRom(DrvSndROM0 + 0x000000, 11, 1)) return 1;
|
||||
if (BurnLoadRom(DrvSndROM1 + 0x000000, 12, 1)) return 1;
|
||||
}
|
||||
|
||||
DrvGfxDecode();
|
||||
}
|
||||
|
||||
konamiInit(1);
|
||||
konamiOpen(0);
|
||||
konamiMapMemory(DrvPalRAM, 0x1000, 0x1fff, KON_RAM);
|
||||
konamiMapMemory(DrvShareRAM, 0x2000, 0x3fff, KON_RAM);
|
||||
konamiMapMemory(DrvKonRAM, 0x4000, 0x5fff, KON_RAM);
|
||||
konamiMapMemory(DrvKonROM + 0x10000, 0x6000, 0x7fff, KON_ROM);
|
||||
konamiMapMemory(DrvKonROM + 0x08000, 0x8000, 0xffff, KON_ROM);
|
||||
konamiSetWriteHandler(ajax_main_write);
|
||||
konamiSetReadHandler(ajax_main_read);
|
||||
konamiClose();
|
||||
|
||||
M6809Init(1);
|
||||
M6809Open(0);
|
||||
M6809MapMemory(DrvShareRAM, 0x2000, 0x3fff, M6809_RAM);
|
||||
M6809MapMemory(DrvM6809ROM + 0x10000, 0x8000, 0x9fff, M6809_ROM);
|
||||
M6809MapMemory(DrvM6809ROM + 0x0a000, 0xa000, 0xffff, M6809_ROM);
|
||||
M6809SetWriteByteHandler(ajax_sub_write);
|
||||
M6809SetReadByteHandler(ajax_sub_read);
|
||||
M6809Close();
|
||||
|
||||
ZetInit(1);
|
||||
ZetOpen(0);
|
||||
ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM);
|
||||
ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM);
|
||||
ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM);
|
||||
ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM);
|
||||
ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM);
|
||||
ZetSetWriteHandler(ajax_sound_write);
|
||||
ZetSetReadHandler(ajax_sound_read);
|
||||
ZetMemEnd();
|
||||
ZetClose();
|
||||
|
||||
BurnYM2151Init(3579545, 25.0);
|
||||
|
||||
K007232Init(0, 3579545, DrvSndROM0, 0x40000);
|
||||
K007232SetPortWriteHandler(0, DrvK007232VolCallback0);
|
||||
|
||||
K007232Init(1, 3579545, DrvSndROM1, 0x80000);
|
||||
K007232SetPortWriteHandler(1, DrvK007232VolCallback1);
|
||||
|
||||
K052109Init(DrvGfxROM0, 0x7ffff);
|
||||
K052109SetCallback(K052109Callback);
|
||||
K052109AdjustScroll(8, 0);
|
||||
|
||||
K051960Init(DrvGfxROM1, 0xfffff);
|
||||
K051960SetCallback(K051960Callback);
|
||||
K051960SetSpriteOffset(8, 0);
|
||||
|
||||
K051316Init(0, DrvGfxROM2, DrvGfxROM2, 0x7ffff, K051316Callback, 7, 0);
|
||||
K051316SetOffset(0, -112, -16);
|
||||
|
||||
GenericTilesInit();
|
||||
|
||||
DrvDoReset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
GenericTilesExit();
|
||||
|
||||
KonamiICExit();
|
||||
|
||||
M6809Exit();
|
||||
konamiExit();
|
||||
ZetExit();
|
||||
|
||||
K007232Exit();
|
||||
BurnYM2151Exit();
|
||||
|
||||
if (AllMem) {
|
||||
free (AllMem);
|
||||
AllMem = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
if (DrvRecalc) {
|
||||
KonamiRecalcPal(DrvPalRAM, DrvPalette, 0x1000);
|
||||
}
|
||||
|
||||
K052109UpdateScroll();
|
||||
|
||||
BurnTransferClear();
|
||||
|
||||
if (nBurnLayer & 1) K052109RenderLayer(2, 0, DrvGfxROMExp0);
|
||||
|
||||
if (ajax_priority)
|
||||
{
|
||||
if (nBurnLayer & 2) K051316_zoom_draw(0, 4);
|
||||
if (nBurnLayer & 4) K052109RenderLayer(1, 0, DrvGfxROMExp0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nBurnLayer & 4) K052109RenderLayer(1, 0, DrvGfxROMExp0);
|
||||
if (nBurnLayer & 2) K051316_zoom_draw(0, 4);
|
||||
}
|
||||
|
||||
// needs work...
|
||||
if (nSpriteEnable & 1) K051960SpritesRender(DrvGfxROMExp1, 3);
|
||||
if (nSpriteEnable & 2) K051960SpritesRender(DrvGfxROMExp1, 2);
|
||||
if (nSpriteEnable & 4) K051960SpritesRender(DrvGfxROMExp1, 1);
|
||||
if (nSpriteEnable & 8) K051960SpritesRender(DrvGfxROMExp1, 0);
|
||||
|
||||
if (nBurnLayer & 8) K052109RenderLayer(0, 0, DrvGfxROMExp0);
|
||||
|
||||
BurnTransferCopy(DrvPalette);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
if (DrvReset) {
|
||||
DrvDoReset();
|
||||
}
|
||||
|
||||
{
|
||||
memset (DrvInputs, 0xff, 3);
|
||||
for (INT32 i = 0; i < 8; i++) {
|
||||
DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
|
||||
DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
|
||||
DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
|
||||
}
|
||||
|
||||
// Clear opposites
|
||||
if ((DrvInputs[1] & 0x03) == 0) DrvInputs[1] |= 0x03;
|
||||
if ((DrvInputs[1] & 0x0c) == 0) DrvInputs[1] |= 0x0c;
|
||||
if ((DrvInputs[2] & 0x03) == 0) DrvInputs[2] |= 0x03;
|
||||
if ((DrvInputs[2] & 0x0c) == 0) DrvInputs[2] |= 0x0c;
|
||||
}
|
||||
|
||||
INT32 nSoundBufferPos = 0;
|
||||
INT32 nInterleave = 100;
|
||||
INT32 nCyclesTotal[3] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3000000 / 60, 3579545 / 60 };
|
||||
INT32 nCyclesDone[3] = { 0, 0, 0 };
|
||||
|
||||
ZetOpen(0);
|
||||
M6809Open(0);
|
||||
konamiOpen(0);
|
||||
|
||||
for (INT32 i = 0; i < nInterleave; i++)
|
||||
{
|
||||
INT32 nSegment = (nCyclesTotal[0] / nInterleave) * (i + 1);
|
||||
nCyclesDone[0] += konamiRun(nSegment - nCyclesDone[0]);
|
||||
|
||||
nCyclesDone[1] += M6809Run(nSegment - nCyclesDone[1]);
|
||||
nSegment = (nCyclesTotal[2] / nInterleave) * (i + 1);
|
||||
|
||||
nCyclesDone[2] += ZetRun(nSegment - nCyclesDone[2]);
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2151Render(pSoundBuf, nSegmentLength);
|
||||
K007232Update(0, pSoundBuf, nSegmentLength);
|
||||
K007232Update(1, pSoundBuf, nSegmentLength);
|
||||
nSoundBufferPos += nSegmentLength;
|
||||
}
|
||||
}
|
||||
|
||||
if (K051960_irq_enabled) konamiSetIrqLine(KONAMI_IRQ_LINE, KONAMI_HOLD_LINE);
|
||||
|
||||
if (pBurnSoundOut) {
|
||||
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
|
||||
if (nSegmentLength) {
|
||||
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
|
||||
BurnYM2151Render(pSoundBuf, nSegmentLength);
|
||||
K007232Update(0, pSoundBuf, nSegmentLength);
|
||||
K007232Update(1, pSoundBuf, nSegmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
konamiClose();
|
||||
M6809Close();
|
||||
ZetClose();
|
||||
|
||||
if (pBurnDraw) {
|
||||
DrvDraw();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvScan(INT32 nAction,INT32 *pnMin)
|
||||
{
|
||||
struct BurnArea ba;
|
||||
|
||||
if (pnMin) {
|
||||
*pnMin = 0x029705;
|
||||
}
|
||||
|
||||
if (nAction & ACB_VOLATILE) {
|
||||
memset(&ba, 0, sizeof(ba));
|
||||
|
||||
ba.Data = AllRam;
|
||||
ba.nLen = RamEnd - AllRam;
|
||||
ba.szName = "All Ram";
|
||||
BurnAcb(&ba);
|
||||
|
||||
konamiCpuScan(nAction, pnMin);
|
||||
M6809Scan(nAction);
|
||||
ZetScan(nAction);
|
||||
|
||||
BurnYM2151Scan(nAction);
|
||||
K007232Scan(nAction, pnMin);
|
||||
|
||||
KonamiICScan(nAction);
|
||||
}
|
||||
|
||||
if (nAction & ACB_WRITE) {
|
||||
konamiOpen(0);
|
||||
ajax_main_bankswitch(nDrvBankRom[0]);
|
||||
konamiClose();
|
||||
|
||||
M6809Open(0);
|
||||
ajax_sub_bankswitch(nDrvBankRom[1]);
|
||||
M6809Close();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Ajax
|
||||
|
||||
static struct BurnRomInfo ajaxRomDesc[] = {
|
||||
{ "770_m01.n11", 0x10000, 0x4a64e53a, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code
|
||||
{ "770_l02.n12", 0x10000, 0xad7d592b, 1 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "770_l05.i16", 0x08000, 0xed64fbb2, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 Code
|
||||
{ "770_f04.g16", 0x10000, 0xe0e4ec9c, 2 | BRF_PRG | BRF_ESS }, // 3
|
||||
|
||||
{ "770_h03.f16", 0x08000, 0x2ffd2afc, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code
|
||||
|
||||
{ "770c13-a.f3", 0x10000, 0x4ef6fff2, 4 | BRF_GRA }, // 5 K052109 Tiles
|
||||
{ "770c13-c.f4", 0x10000, 0x97ffbab6, 4 | BRF_GRA }, // 6
|
||||
{ "770c13-b.e3", 0x10000, 0x86fdd706, 4 | BRF_GRA }, // 7
|
||||
{ "770c13-d.e4", 0x10000, 0x7d7acb2d, 4 | BRF_GRA }, // 8
|
||||
{ "770c12-a.f5", 0x10000, 0x6c0ade68, 4 | BRF_GRA }, // 9
|
||||
{ "770c12-c.f6", 0x10000, 0x61fc39cc, 4 | BRF_GRA }, // 10
|
||||
{ "770c12-b.e5", 0x10000, 0x5f221cc6, 4 | BRF_GRA }, // 11
|
||||
{ "770c12-d.e6", 0x10000, 0xf1edb2f4, 4 | BRF_GRA }, // 12
|
||||
|
||||
{ "770c09-a.f8", 0x10000, 0x76690fb8, 5 | BRF_GRA }, // 13 K051960 Tiles
|
||||
{ "770c09-e.f9", 0x10000, 0x17b482c9, 5 | BRF_GRA }, // 14
|
||||
{ "770c09-b.e8", 0x10000, 0xcd1709d1, 5 | BRF_GRA }, // 15
|
||||
{ "770c09-f.e9", 0x10000, 0xcba4b47e, 5 | BRF_GRA }, // 16
|
||||
{ "770c09-c.d8", 0x10000, 0xbfd080b8, 5 | BRF_GRA }, // 17
|
||||
{ "770c09-g.d9", 0x10000, 0x77d58ea0, 5 | BRF_GRA }, // 18
|
||||
{ "770c09-d.c8", 0x10000, 0x6f955600, 5 | BRF_GRA }, // 19
|
||||
{ "770c09-h.c9", 0x10000, 0x494a9090, 5 | BRF_GRA }, // 20
|
||||
{ "770c08-a.f10", 0x10000, 0xefd29a56, 5 | BRF_GRA }, // 21
|
||||
{ "770c08-e.f11", 0x10000, 0x6d43afde, 5 | BRF_GRA }, // 22
|
||||
{ "770c08-b.e10", 0x10000, 0xf3374014, 5 | BRF_GRA }, // 23
|
||||
{ "770c08-f.e11", 0x10000, 0xf5ba59aa, 5 | BRF_GRA }, // 24
|
||||
{ "770c08-c.d10", 0x10000, 0x28e7088f, 5 | BRF_GRA }, // 25
|
||||
{ "770c08-g.d11", 0x10000, 0x17da8f6d, 5 | BRF_GRA }, // 26
|
||||
{ "770c08-d.c10", 0x10000, 0x91591777, 5 | BRF_GRA }, // 27
|
||||
{ "770c08-h.c11", 0x10000, 0xd97d4b15, 5 | BRF_GRA }, // 28
|
||||
|
||||
{ "770c06", 0x40000, 0xd0c592ee, 6 | BRF_GRA }, // 29 K051960 Tiles
|
||||
{ "770c07", 0x40000, 0x0b399fb1, 6 | BRF_GRA }, // 30
|
||||
|
||||
{ "770c10-a.a7", 0x10000, 0xe45ec094, 7 | BRF_SND }, // 31 K007232 #0 Samples
|
||||
{ "770c10-b.a6", 0x10000, 0x349db7d3, 7 | BRF_SND }, // 32
|
||||
{ "770c10-c.a5", 0x10000, 0x71cb1f05, 7 | BRF_SND }, // 33
|
||||
{ "770c10-d.a4", 0x10000, 0xe8ab1844, 7 | BRF_SND }, // 34
|
||||
|
||||
{ "770c11-a.c6", 0x10000, 0x8cccd9e0, 8 | BRF_SND }, // 35 K007232 #1 Samples
|
||||
{ "770c11-b.c5", 0x10000, 0x0af2fedd, 8 | BRF_SND }, // 36
|
||||
{ "770c11-c.c4", 0x10000, 0x7471f24a, 8 | BRF_SND }, // 37
|
||||
{ "770c11-d.c3", 0x10000, 0xa58be323, 8 | BRF_SND }, // 38
|
||||
{ "770c11-e.b7", 0x10000, 0xdd553541, 8 | BRF_SND }, // 39
|
||||
{ "770c11-f.b6", 0x10000, 0x3f78bd0f, 8 | BRF_SND }, // 40
|
||||
{ "770c11-g.b5", 0x10000, 0x078c51b2, 8 | BRF_SND }, // 41
|
||||
{ "770c11-h.b4", 0x10000, 0x7300c2e1, 8 | BRF_SND }, // 42
|
||||
|
||||
{ "63s241.j11", 0x00200, 0x9bdd719f, 9 | BRF_OPT }, // 43 Timing Prom (unused)
|
||||
};
|
||||
|
||||
STD_ROM_PICK(ajax)
|
||||
STD_ROM_FN(ajax)
|
||||
|
||||
struct BurnDriver BurnDrvAjax = {
|
||||
"ajax", NULL, NULL, NULL, "1987",
|
||||
"Ajax\0", NULL, "Konami", "GX770",
|
||||
L"Ajax\0\u30A8\u30FC\u30B8\u30E3\u30C3\u30AF\u30B9\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_VERSHOOT, 0,
|
||||
NULL, ajaxRomInfo, ajaxRomName, NULL, NULL, AjaxInputInfo, AjaxDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
|
||||
224, 288, 3, 4
|
||||
};
|
||||
|
||||
|
||||
// Typhoon
|
||||
|
||||
static struct BurnRomInfo typhoonRomDesc[] = {
|
||||
{ "770_k01.n11", 0x10000, 0x5ba74a22, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code
|
||||
{ "770_k02.n12", 0x10000, 0x3bcf782a, 1 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "770_k05.i16", 0x08000, 0x0f1bebbb, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 Code
|
||||
{ "770_f04.g16", 0x10000, 0xe0e4ec9c, 2 | BRF_PRG | BRF_ESS }, // 3
|
||||
|
||||
{ "770_h03.f16", 0x08000, 0x2ffd2afc, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code
|
||||
|
||||
{ "770c13", 0x40000, 0xb859ca4e, 4 | BRF_GRA }, // 5 K052109 Tiles
|
||||
{ "770c12", 0x40000, 0x50d14b72, 4 | BRF_GRA }, // 6
|
||||
|
||||
{ "770c09", 0x80000, 0x1ab4a7ff, 5 | BRF_GRA }, // 7 K051960 Tiles
|
||||
{ "770c08", 0x80000, 0xa8e80586, 5 | BRF_GRA }, // 8
|
||||
|
||||
{ "770c06", 0x40000, 0xd0c592ee, 6 | BRF_GRA }, // 9 K051960 Tiles
|
||||
{ "770c07", 0x40000, 0x0b399fb1, 6 | BRF_GRA }, // 10
|
||||
|
||||
{ "770c10", 0x40000, 0x7fac825f, 7 | BRF_SND }, // 11 K007232 #0 Samples
|
||||
|
||||
{ "770c11", 0x80000, 0x299a615a, 8 | BRF_SND }, // 12 K007232 #1 Samples
|
||||
|
||||
{ "63s241.j11", 0x00200, 0x9bdd719f, 9 | BRF_OPT }, // 13 Timing Prom (unused)
|
||||
};
|
||||
|
||||
STD_ROM_PICK(typhoon)
|
||||
STD_ROM_FN(typhoon)
|
||||
|
||||
struct BurnDriver BurnDrvTyphoon = {
|
||||
"typhoon", "ajax", NULL, NULL, "1987",
|
||||
"Typhoon\0", NULL, "Konami", "GX770",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_VERSHOOT, 0,
|
||||
NULL, typhoonRomInfo, typhoonRomName, NULL, NULL, AjaxInputInfo, AjaxDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
|
||||
224, 288, 3, 4
|
||||
};
|
||||
|
||||
|
||||
// Ajax (Japan)
|
||||
|
||||
static struct BurnRomInfo ajaxjRomDesc[] = {
|
||||
{ "770_l01.n11", 0x10000, 0x7cea5274, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code
|
||||
{ "770_l02.n12", 0x10000, 0xad7d592b, 1 | BRF_PRG | BRF_ESS }, // 1
|
||||
|
||||
{ "770_l05.i16", 0x08000, 0xed64fbb2, 2 | BRF_PRG | BRF_ESS }, // 2 M6809 code
|
||||
{ "770_f04.g16", 0x10000, 0xe0e4ec9c, 2 | BRF_PRG | BRF_ESS }, // 3
|
||||
|
||||
{ "770_f03.f16", 0x08000, 0x3fe914fd, 3 | BRF_PRG | BRF_ESS }, // 4 Z80 Code
|
||||
|
||||
{ "770c13", 0x40000, 0xb859ca4e, 4 | BRF_GRA }, // 5 K052109 Tiles
|
||||
{ "770c12", 0x40000, 0x50d14b72, 4 | BRF_GRA }, // 6
|
||||
|
||||
{ "770c09", 0x80000, 0x1ab4a7ff, 5 | BRF_GRA }, // 7 K051960 Tiles
|
||||
{ "770c08", 0x80000, 0xa8e80586, 5 | BRF_GRA }, // 8
|
||||
|
||||
{ "770c06", 0x40000, 0xd0c592ee, 6 | BRF_GRA }, // 9 K051960 Tiles
|
||||
{ "770c07", 0x40000, 0x0b399fb1, 6 | BRF_GRA }, // 10
|
||||
|
||||
{ "770c10", 0x40000, 0x7fac825f, 7 | BRF_SND }, // 11 K007232 #0 Samples
|
||||
|
||||
{ "770c11", 0x80000, 0x299a615a, 8 | BRF_SND }, // 12 K007232 #1 Samples
|
||||
|
||||
{ "63s241.j11", 0x00200, 0x9bdd719f, 9 | BRF_OPT }, // 13 Timing Prom (unused)
|
||||
};
|
||||
|
||||
STD_ROM_PICK(ajaxj)
|
||||
STD_ROM_FN(ajaxj)
|
||||
|
||||
struct BurnDriver BurnDrvAjaxj = {
|
||||
"ajaxj", "ajax", NULL, NULL, "1987",
|
||||
"Ajax (Japan)\0", NULL, "Konami", "GX770",
|
||||
L"Ajax\0\u30A8\u30FC\u30B8\u30E3\u30C3\u30AF\u30B9 (Japan)\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_PREFIX_KONAMI, GBF_VERSHOOT, 0,
|
||||
NULL, ajaxjRomInfo, ajaxjRomName, NULL, NULL, AjaxInputInfo, AjaxDIPInfo,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
|
||||
224, 288, 3, 4
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue